Jeg introducerede tidligere den første sprint af et agentbaseret modellerings- og simuleringsrammeværk, som jeg arbejder på. I dette blogindlæg implementerer jeg en agentbaseret segregationsmodel i Python. Lignende modeller, med nogle justeringer og afvigelser, bruges fx til at forstå social segregation. Det primære formål med dette blogindlæg er at levere endnu en demonstration af agentbaseret modellering og simulering i Python. Den anvendte ramme er abm_framework i Python.
Ramme for agent-baseret modellering i Python
Jeg udvikler en segregationsmodel som endnu et applikationseksempel på den agentbaserede modelleringsramme, som jeg arbejder på i Python. Du kan downloade rammeværket på GitHub her:
GitHub-lageret indeholder en demo-mappe. Eksemplariske ansøgninger er tilgængelige her. På tidspunktet for offentliggørelsen af denne artikel er der ikke så mange demomodeller tilgængelige endnu. Jeg vil tilføje flere demomodeller i de kommende uger, og de eksisterende moduler vil blive udvidet til at understøtte en bredere vifte af agentbaserede modelleringsapplikationer.
I abm_framework er de vigtige moduler følgende:
- framework.py til modellering af fx agenter, agentpopulationer og simuleringsmiljøet
- data.py til styring af databaseoperationer til skrivning og læsning af simuleringsresultater
- stats.py til at plotte simuleringsresultater (også uafhængigt af simuleringskørsel)
- config.py til fx at angive relevante stier, fx databasefilstien
- animation.py til at animere simuleringsresultater
Nedenstående figur opsummerer indholdet af abm_framework- depotet på GitHub.
Filen model.py er selve simuleringsmodellen . I tilfælde af eksemplet beskrevet i artiklen ved hånden, navngav jeg f.eks. filen segregation.py . Modelfilen implementerer en specifik model. Rammen (med alle moduler beskrevet ovenfor) fungerer som en værktøjskasse. Med andre ord skal rammeværket gøre det nemmere at implementere en specifik simuleringsmodel .
Beskrivelse af konceptuel agentbaseret segregationsmodel
Da jeg bruger den agent-baserede modelleringsramme, som jeg har præsenteret i tidligere artikler, udvikler jeg en grid-baseret agent-baseret simuleringsmodel . Det vil sige, at jeg tildeler agent til et gitter. Agenter har således lokationer. Agenter har også et kvarter med en specificeret radius. Interaktion mellem agenter finder sted i dette kvarter. Nedenstående figur, taget fra mit tidligere indlæg om agentbaseret SIR-modelimplementering i Python, illustrerer dette koncept.
I denne eksemplariske agentbaserede adskillelsesmodel letter jeg adskillelsesmekanismer ved at implementere nedenstående flowdiagram:
For hver iteration vælger jeg en agent tilfældigt. Jeg beregner så nyttepåvirkningen i agentens nuværende celle. Denne nyttepåvirkning beregnes ved at iterere over alle tilstødende agenter. Er naboen af ”samme type” som selve agenten, øges nyttepåvirkningen (positiv påvirkning). Hvis naboen ikke er af “samme type” mindskes nyttepåvirkningen (negativ påvirkning).
Dernæst vælges en tilfældig fri celle på gitteret, og den hypotetiske nyttepåvirkning i den celle beregnes. For denne beregning gælder samme logik som beskrevet ovenfor. Hvis den hypotetiske nyttepåvirkning i den pågældende celle er positiv, flytter agenten til denne placering og opdaterer dens nytte igen. Hvis ikke, vælges en anden ledig celle, og den samme test gælder. Processen gentager sig op til en maksimal søgegrænse, dvs. et angivet maksimalt antal gentagelser.
Agentbaseret adskillelsesmodelimplementering i Python
Nedenfor er koden, der implementerer den agentbaserede segregationsmodel.
__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)
# create initial population of healthy humans
attrs = ["utility","type"]
datatypes = ["REAL","TEXT"]
pops = framework.Populations(amount = 2, env = env, db_manager = db_manager, attributes = attrs, datatypes = datatypes)
pops.add_population(name = "natives",
size = 50,
attributes = attrs,
datatypes = datatypes,
initialvals = [100, "native"]
)
pops.add_population(name = "immigrants",
size = 50,
attributes = attrs,
datatypes = datatypes,
initialvals = [100, "immigrant"]
)
# setup simulation
sim = framework.Simulation(1000)
# make sure that environment and agents tables in database are set
pops.write_env_to_db(sim.Iteration)
pops.write_agents_to_db(sim.Iteration)
agents = pops.get_agents()
# other model specific global settings
_max_search = 10
_impactarea = 1
# execute simulation run
while sim.run():
# select one random agent
agent = random.choice(agents)
# get that agents neighbourhood
neighbours = env.get_neighbourhood(agent, mode = "moore", radius = _impactarea)
util_is = 0.0
# if there are neighbours, then recalculate the utility of the agent
for o in neighbours:
if o.get_attr_value("type") == agent.get_attr_value("type"):
util_is += 10
else:
util_is += -10
# update agent utility
agent.increase_attr_value("utility",util_is)
# for search up to maximum limit of random free cells
cells = env.get_freecells(n = _max_search)
for c in cells:
util_new = 0.0
neighbours = env.get_neighbourhood(c, "moore", radius = _impactarea)
for o in neighbours:
if o.get_attr_value("type") == agent.get_attr_value("type"):
util_new += 10
else:
util_new += -10
if util_new > util_is:
# relocate agent, then break loop
env.relocate(agent, c)
agent.increase_attr_value("utility",util_new)
break
# update results in database, for agents and for environment
if (sim.Iteration % 10) == 0:
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
agents_df = db_manager.get_agentsdf()
env_df = db_manager.get_environmentdf()
density_df = db_manager.get_densitydf()
# visualize simulation data
stats.set_fontsizes(8,10,12)
stats.plot_grid_occupation(env_df, ["natives","immigrants"], colors = ["#F52D2D","#4A87F1"], maxtime=0, markersize = 150.0)
stats.save_plot("segplt_early_ia1_50agents_1000it")
stats.plot_grid_occupation(env_df, ["natives","immigrants"], colors = ["#F52D2D","#4A87F1"], maxtime=500, markersize = 150.0)
stats.save_plot("segplt_intermediate_ia1_50agents_1000it")
stats.plot_grid_occupation(env_df, ["natives","immigrants"], colors = ["#F52D2D","#4A87F1"], maxtime=1000, markersize = 150.0)
stats.save_plot("segplt_late_ia1_50agents_1000it")
stats.plot_avgattr_lines(["utility"], agents_df)
stats.save_plot("avgutil_ia1_50agents_1000it")
animation.animate_grid_occupation(
df = env_df,
filename = "segvid_ia1_50agents_1000it",
population = ["natives","immigrants"],
colors = ["#F52D2D","#4A87F1"],
tpf = 0.20, # time per frame
mintime = 0,
maxtime = 1000,
markersize = 150.0
)
animation.animate_density(
df = density_df,
filename = "segdens_ia1_50agents_1000it",
attr = "utility",
defaultsize = 150,
color = "#F52D2D",
tpf = 0.20,
maxtime = 1000
)
# end program
db.close()
print("demo ends")
Da dette kun er en eksemplarisk artikel, der demonstrerer, hvordan du kan bruge den grid-baserede agent-baserede modelleringsramme til agent-baserede segregationsmodeller, udfører jeg kun 250 iterationer. For et begrænset antal iterationer kan jeg skrive de aktuelle systemtilstande (agent attributværdier, grid occupation etc.) ind i min resultatdatabase. Hvis jeg har et meget højere antal iterationer, bør jeg dog kun skrive en delmængde af iterationer ind i min database. Fx hver 10. iteration. Ligeledes, for at gøre animationsoprettelse hurtigere, kan jeg f.eks. undersætte resultater ved kun at trække hver n. simuleringstid fra databasen. Når jeg bruger matplotlib til animationer, bør jeg desuden undgå at bruge loc = “best” til valg af legendeplacering.
Agent-baserede segregationsmodel simuleringsresultater
I dette afsnit præsenterer jeg visualiseringer genereret af ovenstående simuleringskørsel. Visualiseringerne kommer i en standardiseret form. Jeg oprettede dem ved at gøre brug af mit GitHub-lager (abm_framework). Det vil sige, at rammeværket understøtter databasestyring til lagring af simuleringsresultater, og visualisering samt animation af simuleringsresultater.
Nedenstående plot visualiserer nettets besættelse ved simuleringsstart.
Og endelig et plot, der visualiserer grid-besættelse efter 1000 iterationer.
For at fuldføre dette afsnit vil jeg også se på den gennemsnitlige agent nytte gennem simuleringstiden. Jeg kan visualisere dette ved hjælp af funktionen plot_avgattr_lines() leveret af stats.py fra abm_framework .
Den gennemsnitlige forsyningslinje bliver ved med at stige. Det indikerer, at agenter i gennemsnit er i en tilstand, hvor de akkumulerer mere nytte. Denne tilstand er højst sandsynligt ikke stationær, og der er segregationsmodeller, der f.eks. begrænser den maksimale nytteværdi af en agent, eller kun tager højde for ændringer i nytten, når miljøet ændrer sig. Der er også agentbaserede adskillelsesmodeller, der kun tillader en agent at flytte, hvis den respektive agents situation er “slem nok” (dvs. agenter kan tolerere nyttetab op til en vis grænse).
Som nævnt understøtter stats.py- modulet også animationer. I det følgende afsnit vil to animationer af den agent-baserede segreringsmodel blive præsenteret.
Animation af agentbaseret segregationsmodel
Til denne eksemplariske rammeimplementering gjorde jeg brug af to standardiserede animationer. Den første viser ændringer i agentplaceringer gennem tiden.
Den anden animation viser, hvordan forsyningstætheden ændrer sig over tid. Der dannes klynger med meget høj nytteværdi. Samtidig lider andre områder af meget lav nytteværdi (sammenlignet med andre midler).
Hvis jeg ville, kunne jeg nu f.eks. gå videre med at se nærmere på fordelingen af agent nytte osv. Men dette blogindlæg skulle demonstrere, hvordan mit agentbaserede rammeværk (i øjeblikket i sine tidlige stadier) kan anvendes til segregationsmodellen udvikling. Det har jeg gjort nu. Jeg vil dokumentere andre eksemplariske anvendelser af ABM-rammerne i fremtidige blogindlæg.
Relateret agentbaseret modelleringsindhold
Yderligere indhold relateret til agent-baseret modellering og agent-baseret simulering er tilgængeligt på vores blog. Her er nogle relaterede artikler, der kan være interessante for dig:
- Link : Agent-baseret SIR-model Python-eksempel
- Link : Agent-baseret modellering i Python
- Link : Agentbaseret simulering i Python
- Link : Agent-baseret model i Python
- Link : Simuleringsmetoder for SCM-analytikere
Industriingeniør som gerne beskæftiger sig med optimering, simulation og matematisk modellering i R, SQL, VBA og Python
Leave a Reply