I denne artikel implementerer jeg en SIR-model i Python ved hjælp af et bibliotek, som jeg udviklede til agentbaseret modellering i Python. Med andre ord bruger jeg en eksisterende ramme til at implementere en agent-baseret SIR-model.
Introduktion af agentbaseret SIR-model
SIR står for modtagelig , inficeret og genvundet . Som illustreret i nedenstående figur, i en SIR-model, kan agenter opleve følgende tilstandsovergange: Fra modtagelig til inficeret, fra inficeret til genoprettet og fra genoprettet til modtagelig.
Tilstandsovergangene illustreret i ovenstående figur er normalt implementeret med en tilfældig fordeling og en vis specificeret sandsynlighed. Desuden behøver du ikke at tillade alle statsovergange. I denne artikel vil jeg for eksempel ikke tillade, at agenter falder tilbage fra deres genoprettede tilstand til en modtagelig tilstand. Nedenfor er SIR-modellen implementeret i denne artikel.
På samme måde kunne du også formulere en SIR-model, hvor du giver mulighed for at falde tilbage fra genoprettet tilstand til inficeret tilstand, ikke kun den modtagelige tilstand.
Agentbaseret modelleringsramme i Python
Jeg lavede en ramme for agent-baseret modellering. Rammerne er beregnet til at blive udvidet og opgraderet over tid. Det understøtter i øjeblikket en opsætning, der gør det muligt at placere agenter, simuleringsmiljø og populationer i en grid-baseret model. Simuleringsresultater kan skrives ind i en SQLite-database i standardiseret format, og visualiseringer og animationer genereres baseret på de data, der er gemt i den pågældende database. Rammen kommer i form af flere Python-filer (moduler), der kan redigeres for at tilføje brugerdefineret funktionalitet.
Hvis du vil tjekke rammerne ud, kan du følge den på GitHub . Her er linket:
Den særlige ting at bemærke her er, at rammen understøtter grid-baseret agent-baseret modellering. Agenter interagerer i et 2D-gitter. Dette 2D-gitter letter simuleringsmiljøet. En eller flere agenter kan være placeret i samme celle, afhængigt af modelindstillinger. Agenter kan interagere med andre agenter inden for et specificeret kvarter. I denne artikel refererer ineraktioner til sygdomsoverførsel, hvilket resulterer i sygdomsspredning.
Agenter har attributter og funktionalitet, repræsenteret ved indre dynamik, variabler og tilstande. En agents indre virke påvirker dens handlinger, beslutninger og interaktioner med andre agenter. Disse interaktioner kan også påvirkes af interaktionsmiljøet.
Jeg vil nu fortsætte med at dokumentere relevant ABM-modelimplementering i Python.
Implementering af den agent-baserede SIR-model i Python
I nedenstående kode gør jeg brug af den agent-baserede modelleringsramme. Jeg satte en simuleringskørsel op, der varer i 300 iterationer. Sandsynligheden for, at modtagelige agenser bliver inficeret, er 7 %, for hvert møde med et inficeret agens. For hver iteration har et inficeret agens på den anden side en 3% sandsynlighed for at komme sig.
__author__ = "Linnart Felkl"
__email__ = "LinnartSF@gmail.com"
if __name__ == "__main__":
print("demo starts")
import sys
from pathlib import Path
file = Path(__file__).resolve()
parent, root = file.parent, file.parents[1]
sys.path.append(str(root))
# remove the current file's directory from sys.path, unless already removed
try:
sys.path.remove(str(parent))
except ValueError:
pass
import data
import stats
import config
import framework
import random
import animation
# setup database manager and connection
db = data.Database("sqlite3", config.path_databasefile)
db_manager = data.Manager(db)
# create an empty environment
env = framework.Environment(1, True, 20, 20, db_manager) # Environment constructor implicitly resets environment table in database
# create initial population of healthy humans
pops = framework.Populations(amount = 1, env = env, db_manager = db_manager, attributes = ["infected","recovered"], datatypes = ["INTEGER","INTEGER"])
pops.add_population(name = "humans",
size = 200,
attributes = ["infected","recovered"],
datatypes = ["INTEGER","INTEGER"],
initialvals = [0, 0]
)
# randomly infect 5%
pop = pops.Populations["humans"]
sampleagents = pop.get_agents(int(0.05*pop.Size))
for agent in sampleagents: agent.Attributes["infected"] = 1
_prob_infection = 0.07
_prob_recovery = 0.03
# setup simulation
sim = framework.Simulation(300)
# make sure that environment and agents tables in database are setup at this time
pops.write_env_to_db(sim.Iteration)
pops.write_agents_to_db(sim.Iteration)
# execute simulation run, store every 10th run into the database
while sim.run():
# look at every agent
for agent in pop.get_agents():
if agent.get_attr_value("infected") == 1:
neighbours = env.get_neighbourhood(agent)
for neighbour in neighbours:
if neighbour.get_attr_value("infected") == 0 and neighbour.get_attr_value("recovered") == 0:
# this neighbour is not resistant and not infected; infect with specified probability
if random.uniform(0, 1) < _prob_infection: neighbour.set_attr_value("infected", 1)
# the infected agent recovers with a specified probability
if random.uniform(0, 1) < _prob_recovery:
agent.set_attr_value("recovered", 1)
agent.set_attr_value("infected", 0)
# update results in database, for agents and for environment
pops.write_agents_to_db(sim.Iteration)
pops.write_env_to_db(sim.Iteration)
pops.write_density_to_db(sim.Iteration)
# get dataframes with simulation results
humans_df = db_manager.get_populationdf(pop = "humans")
env_df = db_manager.get_environmentdf()
density_df = db_manager.get_densitydf()
# visualize simulation data
stats.set_fontsizes(8,10,12)
stats.plot_agentattr_lines("infected", humans_df)
stats.save_plot("infection_curves")
stats.plot_agentattr_lines("recovered", humans_df)
stats.save_plot("recovery_curves")
stats.plot_grid_occupation(env_df, ["humans"])
stats.save_plot("human_locations")
stats.plot_density_markersize(density_df, "infected", 50, "red")
stats.save_plot("infection_density")
stats.plot_density_markersize(density_df, "recovered", 50, "green")
stats.save_plot("recovery_density")
stats.plot_avgattr_lines(["infected","recovered"], humans_df)
stats.save_plot("avginfectedavgrecovered")
# create and save animations
animation.animate_density(
df = density_df,
filename = "infectionanimation",
attr = "infected",
defaultsize = 50,
color = "red",
tpf = 0.05
)
animation.animate_density(
df = density_df,
filename = "recoveryanimation",
attr = "recovered",
defaultsize = 50,
color = "green",
tpf = 0.05
)
# end program
db.close()
print("demo ends")
Ovenstående agentbaserede SIR-modelimplementering genererer resultater, der er gemt i en SQLite-database. Denne database bruges så senere til visualiseringer. Disse visualiseringer kan implementeres i et separat script, af en anden analytiker og på et andet tidspunkt. Dvs. modeludførelse og datavisualisering er to separate aktiviteter, der er afkoblet af databasen.
Agent-baserede SIR model simuleringsresultater
Jeg kan nu endelig gennemgå de resultater, der blev genereret af den grid-baserede agent-baserede SIR-model. Nedenfor er en visualisering af agentplaceringer i hele denne simuleringskørsel.
Nedenstående animation viser, hvilke midler der var inficeret gennem tiden. Animationen viser desuden agentplaceringer. I dette simple eksempel er agentplaceringerne statiske.
Dernæst en animation af agentgendannelse gennem simuleringstiden.
Nedenstående diagram visualiserer den gennemsnitlige sandsynlighed for, at et middel bliver inficeret eller genoprettet på det givne simuleringstidspunkt.
Agentgendannelse sikrer, at ikke alle midler er inficerede. Agenter i denne model har dog statiske placeringer. I en anden simuleringskørsel kunne vi tillade dynamiske agentplaceringer eller endda en form for diffusion/migrering. Dette vil højst sandsynligt øge den samlede mængde af midler, der er inficeret gennem simuleringskørslen.
Den agentbaserede modelleringsramme, der anvendes i denne artikel, kan levere yderligere diagrammer. Desuden forbliver simuleringsresultaterne gemt i en SQLite-database, der kan analyseres på enhver brugerdefineret måde. Dette ville dog kræve en vis yderligere tilpasning/tilpasning, dvs. kodning.
Afsluttende bemærkninger og relateret indhold
Agentbaseret simulering er en simuleringsmetode, der søger at forklare kompleks makroskopisk systemadfærd ved at beskrive agentdynamik og interaktioner på det mikroskopiske systemniveau. Det er en metode, der er ret abstrakt og ofte bruges til at forstå komplekse systemer. Komplekse systemer er, ja, mere komplekse end komplicerede systemer, og på den anden side mindre komplekse end kaotiske systemer. Den amerikanske økonomi, synlig på det makroskopiske plan i form af f.eks. bruttonationalproduktet, er et eksempel på et komplekst system. Agentbaserede modeller kan fx bruges til at forstå fremkomsten af visse fænomener og tendenser i amerikansk økonomi.
I denne artikel implementerede jeg en for nylig meget populær model for sygdomsspredning. Dette er faktisk et andet interessant område, hvor agent-baseret modellering ofte anvendes. Ved at bruge en ramme for agent-baseret modellering implementerede jeg en agent-baseret SIR-model. Frameworkets visualiserings- og animationsfunktioner blev brugt til at gennemgå simuleringsresultater. Selve rammeværket kan bruges til at implementere andre typer Agent-baserede simuleringsmodeller – og rammeværket vil blive opgraderet og løbende udvidet over tid.
Her er nogle andre SCDA relateret til Agent-baseret simulering :
- Link : Simuleringsmetoder for SCM-analytikere
- Link : En simpel agentbaseret simuleringskørsel visualiseret ved hjælp af Matplotlib i Python
- Link : Agent-baseret modellering i Python
- Link : Udvikling af en simpel agentbaseret simuleringsmodel i Python
- Link : Visualisering af 2D-gitter og arrays ved hjælp af Matplotlib i Python
Industriingeniør som gerne beskæftiger sig med optimering, simulation og matematisk modellering i R, SQL, VBA og Python
Leave a Reply