저는 이전에 제가 작업하고 있는 에이전트 기반 모델링 및 시뮬레이션 프레임워크의 첫 번째 스프린트를 소개했습니다. 이 블로그 게시물 에서는 Python에서 에이전트 기반 분리 모델을 구현합니다. 일부 조정 및 편차가 있는 유사한 모델은 예를 들어 사회적 분리를 이해하는 데 사용됩니다. 이 블로그 게시물 의 주요 목표는 Python에서 에이전트 기반 모델링 및 시뮬레이션에 대한 또 다른 데모를 제공하는 것입니다. 사용된 프레임워크는 Python 의 abm_framework 입니다.
Python의 에이전트 기반 모델링을 위한 프레임워크
저는 Python에서 작업하고 있는 에이전트 기반 모델링 프레임워크의 또 다른 응용 사례로 분리 모델을 개발합니다. 여기 GitHub에서 프레임워크를 다운로드할 수 있습니다.
GitHub 리포지토리에는 데모 폴더가 있습니다. 예시 애플리케이션은 여기에서 사용할 수 있습니다. 이 기사를 게시할 당시에는 아직 사용할 수 있는 데모 모델이 많지 않습니다. 앞으로 몇 주 안에 더 많은 데모 모델을 추가할 예정이며 기존 모듈은 더 광범위한 에이전트 기반 모델링 응용 프로그램을 지원하도록 확장될 것입니다.
abm_framework 에서 중요한 모듈은 다음과 같습니다.
- 에이전트, 에이전트 모집단 및 시뮬레이션 환경과 같은 모델링을 위한 framework.py
- 시뮬레이션 결과 쓰기 및 읽기를 위한 데이터베이스 작업 관리를 위한 data.py
- 시뮬레이션 결과를 플로팅하기 위한 stats.py (시뮬레이션 실행 실행과 별개로)
- 예를 들어 관련 경로를 지정하기 위한 config.py (예: 데이터베이스 파일 경로)
- 시뮬레이션 결과 애니메이션 을 위한 animation.py
아래 그림은 GitHub 의 abm_framework 저장소 내용을 요약한 것입니다.
model.py 파일 은 시뮬레이션 모델 자체입니다. 현재 기사에 설명된 예의 경우 파일 이름을 segregation.py 로 지정했습니다 . 모델 파일은 특정 모델을 구현합니다. 프레임워크(위에 설명된 모든 모듈 포함)는 도구 상자 역할을 합니다. 즉, 프레임워크는 특정 시뮬레이션 모델 을 보다 쉽게 구현할 수 있도록 하기 위한 것 입니다.
개념적 에이전트 기반 분리 모델 설명
이전 글에서 제시한 에이전트 기반 모델링 프레임워크를 사용하면서 그리드 기반 에이전트 기반 시뮬레이션 모델을 개발 중입니다. 즉, 에이전트를 그리드에 할당합니다. 따라서 에이전트에는 위치가 있습니다. 에이전트에는 지정된 반경의 이웃도 있습니다. 에이전트 간의 상호 작용은 이 이웃 내에서 발생합니다. Python에서 에이전트 기반 SIR 모델 구현에 대한 이전 게시물에서 가져온 아래 그림 은 이 개념을 보여줍니다.
이 예시적인 에이전트 기반 분리 모델에서 저는 아래 순서도를 구현하여 분리 메커니즘을 용이하게 합니다.
모든 반복에 대해 한 에이전트를 무작위로 선택합니다. 그런 다음 에이전트의 현재 셀에서 유틸리티 영향을 계산합니다. 이 유틸리티 영향은 모든 인접 에이전트를 반복하여 계산됩니다. 이웃이 에이전트 자체와 “동일한 유형”이면 유틸리티 영향이 증가합니다(긍정적인 영향). 이웃이 “동일한 유형”이 아닌 경우 유틸리티 영향이 감소합니다(부정적 영향).
다음으로 그리드의 임의의 자유 셀이 선택되고 해당 셀의 가상 유틸리티 영향이 계산됩니다. 이 계산에는 위에서 설명한 것과 동일한 논리가 적용됩니다. 해당 셀의 가상 유틸리티 영향이 긍정적인 경우 에이전트는 해당 위치로 재배치하고 유틸리티를 다시 업데이트합니다. 그렇지 않은 경우 다른 빈 셀이 선택되고 동일한 테스트가 적용됩니다. 프로세스는 최대 검색 한계, 즉 지정된 최대 반복 횟수까지 반복됩니다.
Python에서 에이전트 기반 분리 모델 구현
다음은 에이전트 기반 분리 모델을 구현하는 코드입니다.
__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")
이것은 에이전트 기반 분리 모델에 그리드 기반 에이전트 기반 모델링 프레임워크를 사용하는 방법을 보여주는 예시적인 기사이므로 250번의 반복만 실행합니다. 제한된 수의 반복에 대해 현재 시스템 상태(에이전트 속성 값, 그리드 점유 등)를 결과 데이터베이스에 쓸 수 있습니다. 훨씬 더 많은 수의 반복이 있는 경우 데이터베이스에 반복의 하위 집합만 작성해야 합니다. 예를 들어 매 10번째 반복. 마찬가지로, 애니메이션 생성을 더 빠르게 하기 위해 데이터베이스에서 매 n번째 시뮬레이션 시간만 가져와서 결과를 하위 집합으로 만들 수 있습니다. 애니메이션에 matplotlib 를 사용할 때 범례 위치 선택에 loc = “best” 를 사용하는 것도 피해야 합니다.
에이전트 기반 분리 모델 시뮬레이션 결과
이 섹션에서는 위의 시뮬레이션 실행으로 생성된 시각화를 제시합니다. 시각화는 표준화된 형식으로 제공됩니다. 내 GitHub 리포지토리(abm_framework)를 사용하여 만들었습니다. 즉, 프레임워크는 시뮬레이션 결과의 저장을 위한 데이터베이스 관리, 시뮬레이션 결과의 시각화 및 애니메이션을 지원합니다.
아래 플롯은 시뮬레이션 시작 시 그리드 점유를 시각화합니다.
마지막으로 1000회 반복 후 그리드 점유를 시각화하는 플롯입니다.
이 섹션을 완료하기 위해 시뮬레이션 시간 동안 평균 에이전트 유틸리티도 살펴보고 싶습니다. abm_framework 의 stats.py 에서 제공하는 plot_avgattr_lines() 함수 를 사용하여 이것을 시각화할 수 있습니다 .
평균 유틸리티 라인은 계속 증가하고 있습니다. 이는 평균적으로 에이전트가 더 많은 효용을 축적하는 상태에 있음을 나타냅니다. 이 상태는 고정되어 있지 않을 가능성이 높으며 예를 들어 에이전트의 최대 효용을 제한하거나 환경이 변할 때 효용의 변화만 고려하는 분리 모델이 있습니다. 또한 해당 에이전트의 상황이 “충분히 나쁜” 경우에만 에이전트가 재배치할 수 있도록 하는 에이전트 기반 분리 모델도 있습니다(즉, 에이전트는 특정 한계까지 유틸리티 손실을 견딜 수 있음).
언급한 바와 같이 stats.py 모듈은 애니메이션도 지원합니다. 다음 섹션에서는 에이전트 기반 분리 모델의 두 가지 애니메이션이 제공됩니다.
에이전트 기반 분리 모델 애니메이션
이 예시적인 프레임워크 구현을 위해 두 개의 표준화된 애니메이션을 사용했습니다. 첫 번째는 시간 경과에 따른 에이전트 위치의 변화를 보여줍니다.
두 번째 애니메이션은 유틸리티 밀도가 시간에 따라 어떻게 변하는지 보여줍니다. 활용도가 매우 높은 클러스터가 형성됩니다. 동시에 다른 지역은 (다른 에이전트와 비교할 때) 매우 낮은 효용을 겪고 있습니다.
내가 원한다면 이제 에이전트 유틸리티 등의 분포를 자세히 살펴보고 진행할 수 있습니다. 그러나 이 블로그 게시물은 내 에이전트 기반 프레임워크 (현재 초기 단계에 있음)를 분리 모델에 적용할 수 있는 방법을 보여주기 위한 것 입니다. 개발. 나는 지금 그렇게 했다. 향후 블로그 게시물에서 ABM 프레임워크의 다른 예시적인 응용 프로그램을 문서화할 것입니다.
관련 에이전트 기반 모델링 콘텐츠
에이전트 기반 모델링 및 에이전트 기반 시뮬레이션 과 관련된 추가 콘텐츠 는 블로그에서 확인할 수 있습니다. 다음은 귀하가 관심을 가질 만한 관련 기사입니다.
- 링크 : 에이전트 기반 SIR 모델 Python 예제
- 링크 : Python의 에이전트 기반 모델링
- 링크 : Python의 에이전트 기반 시뮬레이션
- 링크 : Python의 에이전트 기반 모델
- 링크 : SCM 분석가를 위한 시뮬레이션 방법
최적화 및 시뮬레이션을 전문으로하는 산업 엔지니어 (R, Python, SQL, VBA)
Leave a Reply