In [1]:
import complexism as cx

In [2]:
import numpy as np
import numpy.random as rd
from complexism.element import StepTicker, Event
from complexism.agentbased import ActiveBehaviour, PassiveBehaviour
import complexism.agentbased.statespace as ss
from complexism.agentbased.statespace.be import StateEnterTrigger, ActiveModBehaviour
import epidag.data as dat
import pandas as pd

In [3]:
mat = pd.read_csv('data/SimFM.csv')

ds = cx.DemographySex()
ds.load_birth_data(mat, i_year='Year', i_f='BirthF', i_m='BirthM')
ds.load_death_data(mat, i_year='Year', i_f='DeathF', i_m='DeathM')
ds.load_migration_data(mat, i_year='Year', i_f='MigrationF', i_m='MigrationM')
ds.load_population_data(mat, i_year='Year', i_f='PopF', i_m='PopM')
ds.complete_loading()
ds


Out[3]:
Sex-specific demography, [1990, 2050], Birth, Death, Migration

In [9]:
psc = """
PCore pSLIR {
    beta = 0.4
    lambda = 0.2
    gamma = 0.05
    Recov ~ exp(gamma)
    Die ~ exp(0.02)
}
"""

dsc = """
CTBN dIR {
    life[Alive | Dead]
    ir[I | R]

    Alive{life:Alive}
    Dead{life:Dead}
    Inf{life:Alive, ir:I}
    Rec{life:Alive, ir:R}

    Die -> Dead # from transition Die to state Dead by distribution Die
    Inf -- Recov -> Rec

    Alive -- Die # from state Alive to transition Die
}
"""

In [10]:
def SL_ODE(y, t, p, x):
    life = x['life']
    fs, ms, fl, ml = y

    brs = life.get_birth_rate(t)
    mrs = life.get_migration_rate(t)
    drs = life.get_death_rate(t)

    return [
        fs * (brs['Female'] - drs['Female'] + mrs['Female'] - p['lambda']),
        ms * (brs['Male'] - drs['Male'] + mrs['Male'] - p['lambda']),
        fl * (brs['Female'] - drs['Female'] + mrs['Female']) + fs * p['lambda'],
        ml * (brs['Male'] - drs['Male'] + mrs['Male']) + ms * p['lambda']

    ]


def measure(y, t, p, x):
    return {
        'Sus': y[0] + y[1],
        'Lat': y[2] + y[3]
    }

In [11]:
ctrl = cx.Director()

ctrl.read_bayes_net(psc)
ctrl.read_state_space_model(dsc)

In [12]:
bp = ctrl.new_sim_model('IR', 'StSpABM')
bp.set_agent('dIR')
bp.set_observations(states=['Inf', 'Rec', 'Dead'])
bp.add_behaviour('Life', 'Reincarnation', s_death='Dead', s_birth='Inf')

y0 = bp.get_y0_proto()
y0.define(n=1000, st='Inf')

lyo = ctrl.new_sim_model('MIR', 'MultiModel')
lyo.add_entry('M', 'IR', y0, fr=1, to=3)
lyo.add_summary('#M', 'Inf', 'Inf')
lyo.add_summary('#M', 'Rec', 'Rec')

bp = ctrl.new_sim_model('SL', 'ODEEBM')
bp.set_fn_ode(SL_ODE, ['FS', 'MS', 'FL', 'ML'])
bp.set_external_variables({'life': ds})

bp.set_dt(dt=0.1, odt=1)
bp.add_observing_function(measure)


lyo = ctrl.new_sim_model('SLIR', 'MultiModel')

y0 = bp.get_y0_proto()
ns = {k: v.sum()/100 for k, v in ds.get_population(1990).items()}
y0.define(st='FS', n=ns['Female'])
y0.define(st='MS', n=ns['Male'])


lyo.add_entry('mir', 'MIR')
lyo.add_entry('sl', 'SL', y0)
lyo.set_observations()

In [13]:
model = ctrl.generate_model('M1', 'SLIR', bn='pSLIR')

y0 = ctrl.get_y0s('SLIR')
cx.start_counting()
out = cx.simulate(model, y0, 1990, 2035, 1, log=False)
cx.stop_counting()

In [18]:
cx.get_counting_results().dT


Out[18]:
0    12.857321
Name: dT, dtype: float64

In [1]:
import epidag as dag
import complexism as cx
import complexism.fn as cmd

In [2]:
psc = """
PCore pSIR {
    beta = 0.4
    gamma = 0.5
    Infect ~ exp(beta)
    Recov ~ exp(0.5)
    Die ~ exp(0.02)
}
"""

dsc = """
CTBN SIR {
    life[Alive | Dead]
    sir[S | I | R]

    Alive{life:Alive}
    Dead{life:Dead}
    Inf{life:Alive, sir:I}
    Rec{life:Alive, sir:R}
    Sus{life:Alive, sir:S}

    Die -> Dead # from transition Die to state Dead by distribution Die
    Sus -- Infect -> Inf
    Inf -- Recov -> Rec

    Alive -- Die # from state Alive to transition Die
}
"""

In [3]:
da = cx.Director()
da.read_bayes_net(psc)
da.read_state_space_model(dsc)

In [4]:
mbp = da.new_sim_model('SIR', 'StSpABM')
mbp.set_agent(prefix='Ag', group='agent', dynamics='SIR')
mbp.add_behaviour('Dead', 'Reincarnation', s_death='Dead', s_birth='Sus')
mbp.get_parameter_hierarchy(dc=da.get_state_space_model('SIR'))


Out[4]:
{'SIR': ['agent'], 'agent': ['Die', 'Infect', 'Recov']}

In [5]:
mbp.generate('sir', bn='pSIR', da=da)


Out[5]:
<complexism.agentbased.statespace.abmstsp.StSpAgentBasedModel at 0x1a60cfcd1d0>

In [31]:



Out[31]:
({'ModelType': 'CTBN', 'ModelName': 'SIR', 'Microstates': {'life': ['Alive', 'Dead'], 'sir': ['S', 'I', 'R']}, 'States': {'Alive': {'life': 'Alive'}, 'Dead': {'life': 'Dead'}, 'Inf': {'life': 'Alive', 'sir': 'I'}, 'Rec': {'life': 'Alive', 'sir': 'R'}, 'Sus': {'life': 'Alive', 'sir': 'S'}}, 'Transitions': {'Die': {'To': 'Dead', 'Dist': 'Die'}, 'Infect': {'To': 'Inf', 'Dist': 'Infect'}, 'Recov': {'To': 'Rec', 'Dist': 'Recov'}}, 'Targets': {'Alive': ['Die'], 'Dead': [], 'Inf': ['Recov'], 'Rec': [], 'Sus': ['Infect']}, 'Order': ['life', 'sir']},
 gamma: 0.5, beta: 0.4)

In [29]:
pc.get_samplers()


Out[29]:
{}

In [25]:



Out[25]:
Name:	pSIR
Nodes:
	Die ~ exp(0.02)
	Recov ~ exp(0.5)
	gamma = 0.5
	beta = 0.4
	Infect ~ exp(beta)

Three types of agents are supported by PyComplexism

  • StSpAgent (State space agent): agents with states from state-space models
  • DiffEqAgent (Differential equation agent): agents with inner dynamics from differential equations
  • GenericAgent: agents allow fully customisation

Building an agent-based model

  1. Design a parameter model
  2. Design a dynamic model: ctmc, ctbn, or none
  3. Design agents: state-space, diffeq, generic
  4. Design population structure
  5. Add mods

In [3]:
model_blueprint = {
    'agent': {
        'prefix': 'agent',
        'group': 'agent',
        'exo': {},
        'type': 'stsp',
        'dynamics': 'SIR',
        'default': {
            'st': 'Sus'
        }
    },
    'population': {
        'networks': {}
    },
    'mods': {
        
    }
}

In [4]:
model_blueprint = {
    'agent': {
        'prefix': 'Helen',
        'group': 'agent',
        'exo': {},
        'type': 'stsp',
        'dynamics': 'SIR',
        'default': {
            'st': 'Sus'
        }
    }
}

Name = 'M1'
Gene = sm.generate()
proto = Gene.get_prototype('agent')
stsp = dc.generate_model('agent', **proto.get_samplers())
ag = cx.StSpAgent('Helen', stsp['Sus'], proto.get_sibling('Helen'))
model = cx.SingleIndividualABM(Name, ag)
cx.simulate(model, None, 0, 10, 1)


Out[4]:
Name State Infect Recov
Time
0.0 Helen Sus 0.0 0.0
1.0 Helen Inf 1.0 0.0
2.0 Helen Inf 0.0 0.0
3.0 Helen Inf 0.0 0.0
4.0 Helen Rec 0.0 1.0
5.0 Helen Rec 0.0 0.0
6.0 Helen Rec 0.0 0.0
7.0 Helen Rec 0.0 0.0
8.0 Helen Rec 0.0 0.0
9.0 Helen Rec 0.0 0.0
10.0 Helen Rec 0.0 0.0

In [5]:
model_blueprint = {
    'agent': {
        'prefix': 'agent',
        'group': 'agent',
        'exo': {},
        'type': 'stsp',
        'dynamics': 'SIR',
        'default': {
            'st': 'Sus'
        }
    },
    'population': {
        'networks': {}
    },
    'mods': {
        
    }
}


y0 = [
    {'n': 95, 'attributes': {'st': 'Sus'}},
    {'n': 5, 'attributes': {'st': 'Inf'}},
]

Name = 'M1'
Gene = sm.generate()
eve = cx.StSpBreeder('Ag ', 'agent', Gene, dc)
pop = cx.Population(eve)
# model = cx.SingleIndividualABM(Name, ag)
# cx.simulate(model, None, 0, 10, 1)
model = cx.AgentBasedModel(Name, Gene, pop)
model.add_observing_event(pop.Eve.DCore.Transitions['Infect'])
model.add_observing_event(pop.Eve.DCore.Transitions['Recov'])
model.add_observing_event(pop.Eve.DCore.Transitions['Die'])

def f(model, tab, ti):
    tab['Sus'] = model.Population.count(st='Sus')
    tab['Inf'] = model.Population.count(st='Inf')
    tab['Rec'] = model.Population.count(st='Rec')
    tab['Alive'] = model.Population.count(st='Alive')
    tab['Dead'] = model.Population.count(st='Dead')
    

model.add_observing_function(f)

cx.simulate(model, y0, 0, 10, 1)


Out[5]:
Sus Inf Rec Alive Dead Tr(Name: Infect, To: Inf, By: exp(beta)) Tr(Name: Recov, To: Rec, By: exp(0.5)) Tr(Name: Die, To: Dead, By: exp(0.02))
Time
0.0 95 5 0 100 0 0.0 0.0 0.0
1.0 63 26 11 100 0 32.0 11.0 0.0
2.0 36 34 26 96 4 25.0 15.0 4.0
3.0 22 30 42 94 6 14.0 17.0 2.0
4.0 14 24 53 91 9 8.0 13.0 3.0
5.0 10 14 66 90 10 4.0 14.0 1.0
6.0 6 13 70 89 11 4.0 5.0 1.0
7.0 3 10 75 88 12 2.0 5.0 1.0
8.0 3 6 79 88 12 0.0 4.0 0.0
9.0 2 6 79 87 13 1.0 1.0 1.0
10.0 1 4 81 86 14 1.0 3.0 1.0

In [8]:
y0 = [
    {'n': 995, 'attributes': {'st': 'Sus'}},
    {'n': 5, 'attributes': {'st': 'Inf'}},
]

Name = 'M1'
Gene = sm.generate()
eve = cx.StSpBreeder('Ag ', 'agent', Gene, dc)
pop = cx.Population(eve)
# model = cx.SingleIndividualABM(Name, ag)
# cx.simulate(model, None, 0, 10, 1)
model = cx.StSpAgentBasedModel(Name, Gene, pop)

for tr in ['Infect', 'Recov', 'Die']:
    model.add_observing_transition(tr)

for st in ['Sus', 'Inf', 'Rec', 'Alive', 'Dead']:
    model.add_observing_state(st)

cx.simulate(model, y0, 0, 10, 1)


Out[8]:
Sus Inf Rec Alive Dead Infect Die Recov
Time
0.0 995 5 0 1000 0 0.0 0.0 0.0
1.0 654 249 78 981 19 324.0 19.0 78.0
2.0 434 311 214 959 41 210.0 22.0 139.0
3.0 276 286 376 938 62 149.0 21.0 167.0
4.0 185 220 514 919 81 86.0 19.0 145.0
5.0 115 165 616 896 104 66.0 23.0 115.0
6.0 72 134 677 883 117 43.0 13.0 71.0
7.0 51 101 704 856 144 19.0 27.0 46.0
8.0 30 66 733 829 171 18.0 27.0 50.0
9.0 19 52 744 815 185 10.0 14.0 24.0
10.0 13 33 754 800 200 6.0 15.0 23.0

In [ ]:
sm1 = dag.as_simulation_core(bn)
sm1.deep_print()

In [ ]:
mc_bp = BlueprintABM('AB_abm', 'pAB', 'AB_mc')
mc_bp.set_observations(states=['N', 'A', 'B', 'AB'])
pc = pc_bp.get_simulation_model().sample_core()
dc = dc_bp.generate_model(pc=pc)

model = mc_bp.generate('A', pc=pc, dc=dc)
out = simulate(model, y0={'N': 500}, fr=0, to=10)
model.output(mid=False)

In [ ]:
par_script = """ 
PCore pSIR{
    transmission_rate = 1.5/200
    rec_rate ~ triangle(0.1, 0.2, 0.3)
    beta ~ exp(transmission_rate)
    gamma ~ exp(rec_rate)
    Die ~ exp(0.2)
}
"""

dc_ctbn_script = '''
CTBN SIR_BN {
    life[Alive | Dead]
    sir[S | I | R]
    
    Alive{life:Alive}
    Dead{life:Dead}
    Inf{life:Alive, sir:I}
    Rec{life:Alive, sir:R}
    Sus{life:Alive, sir:S}

    Die -> Dead # from transition Die to state Dead by distribution Die
    Sus -- Infect_Net(beta) -> Inf
    Sus -- Infect(beta) -> Inf 
    Inf -- Recov(gamma) -> Rec
    
    Alive -- Die # from state Alive to transition Die
}
'''

da = Director()
da.read_pc(par_script)
da.read_dc(dc_ctbn_script)

In [ ]:
pc = da.get_pc('pSIR')
pc = pc.sample_core()
pc.Locus

In [ ]:
cfd = da.new_mc('ABM_M2', 'ABM', tar_pc='pSIR', tar_dc='SIR_BN')
cfd.add_behaviour('cycle', be_type='Reincarnation', s_birth = 'Sus', s_death = 'Dead')
cfd.add_behaviour('foi', be_type='ComFDShock', s_src='Inf', t_tar = 'Infect', dt=0.5)
cfd.add_behaviour('step', be_type='TimeStep', ts=[0.5, 4], ys=[1, 0.1, 5], t_tar = 'Infect')

cfd.set_observations(states=['Sus', 'Inf', 'Rec'])

mod, out = da.simulate('ABM_M2', y0={'Sus': 95, 'Inf': 5}, fr=0 ,to=10, dt=.01)
out.plot()
plt.show()

In [ ]:
cfd = da.new_mc('ABM_M2', 'ABM', tar_pc='pSIR', tar_dc='SIR_BN')
cfd.add_network('IDU', 'BA', m=2)
cfd.add_behaviour('cycle', be_type='Reincarnation', s_birth = 'Sus', s_death = 'Dead')
cfd.add_behaviour('transmission', be_type='NetShock', s_src = 'Inf', t_tar = 'Infect_Net', net='IDU')
cfd.add_behaviour('foi', be_type='ForeignShock', t_tar = 'Infect')

cfd.set_observations(states=['Inf'], behaviours=['foi'])

cfd = da.new_mc('ABM_M5', 'ABM', tar_pc='pSIR', tar_dc='SIR_BN')
cfd.add_network('IDU', 'BA', m=5)
cfd.add_behaviour('cycle', be_type='Reincarnation', s_birth = 'Sus', s_death = 'Dead')
cfd.add_behaviour('transmission', be_type='NetShock', s_src = 'Inf', t_tar = 'Infect_Net', net='IDU')
cfd.add_behaviour('foi', be_type='ForeignShock', t_tar = 'Infect')

cfd.set_observations(states=['Inf'], behaviours=['foi'])

In [ ]:
lyo = da.new_layout('Lyo1')

lyo.add_entry('A', 'ABM_M2', {'Sus': 20, 'Inf': 10})
lyo.add_entry('B', 'ABM_M2', {'Sus': 20}, size=3)
lyo.add_entry('C', 'ABM_M5', {'Sus': 20, 'Inf': 10}, size=2)
lyo.add_relation('*@Inf', 'Lyo1@FOI')
lyo.add_relation('Lyo1@FOI', '*@foi')
lyo.set_observations(['B_2', 'B_1', '*'])

In [ ]:
mod, out = da.simulate('Lyo1', fr=0, to=10)
out.plot()
plt.show()

In [ ]:
pc, dc = generate_pc_dc(da.get_pc('pSIR'), da.get_dc('SIR_BN'))
mc = CoreODE(dc)
mc.Mods['FOI'] = InfectionFD('FOI', 'Infect', 'Inf')
mc.Mods['Dead'] = Reincarnation('Dead', s_death='Dead', s_birth='Sus')
model = ODEModel('SIR', mc, dt=0.01)
model.add_obs_transition('Infect')
model.add_obs_state('Alive')
model.add_obs_state('Inf')
model.add_obs_state('Sus')   
model.add_obs_behaviour('Dead')

In [ ]:
cfd = da.new_mc('EBM', 'CoreODE', tar_pc='pSIR', tar_dc='SIR_BN')
cfd.add_behaviour('FOI', be_type='InfectionDD', s_src = 'Inf', t_tar = 'Infect')
cfd.add_behaviour('Dead', be_type='Reincarnation', s_death='Dead', s_birth='Sus')
cfd.set_arguments('dt', 0.5)
cfd.set_observations(states=['Sus', 'Inf', 'Rec', 'Alive'], behaviours=['FOI'])

In [ ]:
mod, out = da.simulate('EBM', y0={'Sus': 95, 'Inf': 5}, fr=0 ,to=10, dt=1)
#da.copy_model(mod_src=mod)
out.plot()
plt.show()

In [ ]:
out = simulate(model, y0={'Sus': 95, 'Inf': 5}, fr=0 ,to=10, dt=0.1)
out.plot()
plt.show()

In [5]:
class A:
    def __init__(self, ls):
        self.List = ls
        
    def __iter__(self):
        return iter(self.List)

In [6]:
a = A([1,2,3])
for i in a:
    print(i)


1
2
3

In [14]:
import matplotlib.pyplot as plt
import complexism as cx
import complexism.agentbased.statespace as ss
import epidag as dag


import matplotlib.pyplot as plt
import complexism as cx
import complexism.agentbased.statespace as ss
import epidag as dag


model_name = 'M_SIR'

# Step 1 set a parameter core
bn = cx.read_bn_script(cx.load_txt('example/scripts/pSIR.txt'))
sm = dag.as_simulation_core(bn,
                            hie={'city': ['agent'],
                                 'agent': ['Infect', 'Recov', 'Die']})
pc = sm.generate(model_name)


# Step 1- set dynamic cores as agents need
dbp = cx.read_dbp_script(cx.load_txt('example/scripts/SIR_BN.txt'))


# Step 2 define at least one type of agent
eve = ss.StSpBreeder('Ag', 'agent', pc, dbp)
pop = cx.Population(eve)


# Step 3 generate a model
model = cx.StSpAgentBasedModel(model_name, pc, pop)


# Step 4 add behaviours to the model
# ss.FDShock.decorate('FOI', model, s_src='Inf', t_tar='Infect')
# ss.FDShockFast.decorate('FOI', model=model, s_src='Inf', t_tar='Infect', dt=0.1)
pc.impulse({'beta': pc['beta']/300})
# ss.DDShock.decorate('FOI', model=model, s_src='Inf', t_tar='Infect')
ss.NetShock.decorate('FOI', model=model, s_src='Inf', t_tar='Infect', net='net')


# Step 5 decide outputs
for tr in ['Infect', 'Recov', 'Die']:
    model.add_observing_transition(tr)

for st in ['Sus', 'Inf', 'Rec', 'Alive', 'Dead']:
    model.add_observing_state(st)

model.add_observing_behaviour('FOI')


# Step 6 simulate
y0 = [
    {'n': 290, 'attributes': {'st': 'Sus'}},
    {'n': 10, 'attributes': {'st': 'Inf'}}
]

output = cx.simulate(model, y0, 0, 10, 1)
print(output)


# Step 7 inference, draw figures, and manage outputs
fig, axes = plt.subplots(nrows=3, ncols=1)

output[['Sus', 'Inf', 'Rec']].plot(ax=axes[0])
output[['Recov', 'Infect']].plot(ax=axes[1])
output[['FOI']].plot(ax=axes[2])
plt.show()


---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-14-03cca1a038bf> in <module>()
     58 ]
     59 
---> 60 output = cx.simulate(model, y0, 0, 10, 1)
     61 print(output)
     62 

D:\Model\PyABMS\complexism\fn.py in simulate(model, y0, fr, to, dt, seed, mid, log)
    135         return model.output(mid=mid)
    136     sim = Simulator(model, seed=seed, keep_log=log)
--> 137     sim.simulate(y0, fr, to, dt)
    138     return model.output(mid=mid)
    139 

D:\Model\PyABMS\complexism\mcore\simulator.py in simulate(self, y0, fr, to, dt)
     36     def simulate(self, y0, fr, to, dt):
     37         self.Time = fr
---> 38         self.Model.initialise(ti=fr, y0=y0)
     39         self.deal_with_disclosures(fr, None)
     40         self.Model.initialise_observations(fr)

D:\Model\PyABMS\complexism\mcore\modelnode.py in initialise(self, ti, y0)
    157                 y0.match_model(self)
    158             self.read_y0(y0, ti)
--> 159         self.preset(ti)
    160 
    161     def preset(self, ti):

D:\Model\PyABMS\complexism\agentbased\abm.py in preset(self, ti)
     81     def preset(self, ti):
     82         for be in self.Behaviours.values():
---> 83             be.initialise(ti=ti, model=self)
     84         for ag in self.Population.Agents.values():
     85             ag.initialise(ti=ti, model=self)

D:\Model\PyABMS\complexism\agentbased\statespace\be\modbe.py in initialise(self, ti, model, *args, **kwargs)
    265     def initialise(self, ti, model, *args, **kwargs):
    266         for ag in model.agents:
--> 267             val = model.Pop.count_neighbours(ag, st=self.S_src, net=self.Net)
    268             ag.shock(self.Name, val, ti)
    269 

AttributeError: 'StSpAgentBasedModel' object has no attribute 'Pop'