logo

에이전트 기반 모델 시뮬레이션에서의 번식 📂동역학

에이전트 기반 모델 시뮬레이션에서의 번식

시뮬레이션

malthusian\_growth\_simulation.gif

이 포스트에서는 생성된 에이전트에게 스스로 복제하는 액션을 주어 거시적인 관점에서 집단의 성장을 모방하려고 한다. 이 시뮬레이션에서 공간이나 이동에 관련된 모든 것들은 단지 시각화를 위한 것이며, 실제 목적과는 아무런 관계가 없다.

변수

  • $t$: 현재 턴을 의미한다.
  • $N(t)$: $t$ 턴에서 에이전트의 수를 나타낸다.

파라미터

  • $N_{0} \in \mathbb{N}$: 시뮬레이션이 시작할 때 에이전트의 수를 나타낸다.
  • $b \in [0,1]$: 번식률birth rate로써 에이전트가 번식할 확률을 나타낸다.
  • $t_{\text{end}} \in \mathbb{N}$: 시뮬레이션이 끝나는 턴을 정한다.

액션

(모든 에이전트가, 매 턴마다)

  • 번식: b의 확률로 자신의 위치에 새로운 에이전트를 만든다.
  • 이동: 이변수 정규분포 $N \left( \mathbb{0} , \Sigma \right)$ 에서 뽑은 벡터대로 이동한다.

코드 리뷰

Step 1. 초기화 및 에이전트 생성

julia> N0 = 5 # 초기 인구수
5

julia> b = 0.05 # 번식률
0.05

julia> max\_iteration = 180 # 시뮬레이션 기간
180

julia> gaussian2 = MvNormal([0.0; 0.0], 0.02I) # 2차원 정규분포
IsoNormal(
dim: 2
μ: [0.0, 0.0]
Σ: [0.02 0.0; 0.0 0.02]
)

julia> Random.seed!(2);

julia> Time\_evolution = [] # 인구수를 기록하기 위한 스택
Any[]

에이전트 기반 시뮬레이션 튜토리얼과 비슷하게 에이전트를 생성한다. 여기서 각 변수들은 위의 파라미터 세팅을 반영한다.

  • N0 $\leftarrow N_{0} = 5$
  • b $\leftarrow b = 0.05$
  • max\_iteration $\leftarrow t_{\text{end}} = 180$

Random.seed!(2)은 결과를 재현하기 위한 시드넘버 설정, time_evolution은 개체수를 기록하기 위한 스택으로 시뮬레이션 자체에는 영향을 미치지 않으나 시뮬레이션을 반복하고 분석하기 위해 중요하게 쓰이는 테크닉이다.

julia> coordinate = rand(gaussian2, N0)'
5×2 Adjoint{Float64,Array{Float64,2}}:
  0.104598   -0.105289
 -0.086056   -0.243734
 -0.0955465   0.0787217
 -0.121846    0.0732683
  0.176526    0.165338

julia> N = N0
5

$N$ 은 개체수를 나타내므로 우선 $N \gets N_{0}$ 와 같이 초기 개체수를 받아 주어야한다.

20201112\_193047.png

에이전트들의 위치를 산점도로 나타내보면 위와 같이 오밀조밀하게 모여있는 것을 확인할 수 있다.


Step 2. 에이전트의 번식

julia> replicated = (rand(N) .< b)
5-element BitArray{1}:
 0
 0
 1
 0
 0

julia> new\_coordinate = coordinate[replicated,:]
1×2 Array{Float64,2}:
 -0.0955465  0.0787217

julia> coordinate = cat(coordinate, new\_coordinate, dims = 1)
6×2 Array{Float64,2}:
  0.104598   -0.105289
 -0.086056   -0.243734
 -0.0955465   0.0787217
 -0.121846    0.0732683
  0.176526    0.165338
 -0.0955465   0.0787217

현재 에이전트의 수만큼 0과 1사이에서 난수를 뽑는다. 이것이 b보다 작다는 것은 b의 확률로 번식 이 일어났다는 뜻이다. 위 스크린샷에서는 세번째 에이전트가 $5\%$ 의 확률로 번식한 것으로 Step 1. 에서 확인했던 좌표 중 세번째 행이 그대로 새로운 행으로 추가되었다.


Step 3. 기록과 에이전트 이동

julia> N = size(coordinate, 1)
6

julia> push!(time\_evolution, N)
1-element Array{Any,1}:
 6

julia> coordinate = coordinate + rand(gaussian2, N)'
6×2 Array{Float64,2}:
  0.0678177  -0.0642068
 -0.137464   -0.0672691
 -0.0571189   0.06278
 -0.0635334   0.226498
  0.18355     0.180084
  0.0920502   0.0682156

위의 Step 2. 에서 에이전트가 하나 더 늘어났으므로 $N$ 역시 업데이트 해주었고, 이 때의 개체수를 기록했다. 각 에이전트의 좌표는 행렬로 표현되고 있으므로 이변수 정규분포를 $N$ 번 뽑아 쌓은 $N \times 2$ 행렬을 더하면 에이전트가 이동한 것을 구현할 수 있다. 실제로 산점도를 그려보면 다음과 같이 Step 1. 과는 달리 조금 이동한 것을 알 수 있다.

20201112\_192927.png

이를 마치고 Step 2. 로 돌아간다. 계속해서 반복하다가, $t = t_{\text{end}}$ 가 되면 멈춘다.

위 과정을 반복하기만하면 포스트 상단의 움짤과 같은 현상을 볼 수 있다.

전체 코드

다음은 이 포스트에 쓰인 줄리아 코드다.

cd(@__DIR__) # 파일 저장 경로

@time using Plots
@time using Random
@time using Distributions
@time using LinearAlgebra

N0 = 5 # 초기 인구수
b = 0.05 # 번식률
max_iteration = 180 # 시뮬레이션 기간
gaussian2 = MvNormal([0.0; 0.0], 0.02I) # 2차원 정규분포

Random.seed!(2);
time_evolution = [] # 인구수를 기록하기 위한 스택
let
  coordinate = rand(gaussian2, N0)'
  N = N0

  anim = @animate for t = (0:max_iteration)/100
    plot(coordinate[:,1], coordinate[:,2], Seriestype = :scatter,
      markercolor = RGB(1.,94/255,0.), markeralpha = 0.4, markerstrokewidth	= 0.1,
      title = "t = $t", aspect_ratio = 1, size = [400,400],
      xaxis=true,yaxis=true,axis=nothing, legend = false)
      xlims!(-10.,10.)
      ylims!(-10.,10.)

    replicated = (rand(N) .< b)
    new_coordinate = coordinate[replicated,:]
    coordinate = cat(coordinate, new_coordinate, dims = 1)

    N = size(coordinate, 1)
    push!(time_evolution, N)
    coordinate = coordinate + rand(gaussian2, N)'
  end
  gif(anim, "malthusian_growth_simulation.gif", fps = 18)
end