메이-레너드 경쟁 모델

메이-레너드 경쟁 모델

개요

메이-레너드 경쟁 모델은 세 가지 집단이 포함된 경쟁 상태에서의 인구 동역학 모델로, 세 집단이 서로 먹고 먹히는 삼각 관계를 묘사한다. 세 개의 당이나 기업, 혹은 실제로 상성이 있는 경쟁이 될 수도 있다.

모델1

$$ \begin{align*} x_{1}' =& x_{1} \left( 1 - x_{1} - b x_{2} - a x_{3} \right) \\ x_{2}' =& x_{2} \left( 1 - a x_{1} - x_{2} - b x_{3} \right) \\ x_{3}' =& x_{3} \left( 1 - b x_{1} - a x_{2} - x_{3} \right) \end{align*} $$

변수

파라메터

설명

메이-레너드 모델은 $3$차원의 시스템으로써 파라메터가 둘밖에 없지만, 이는 세 집단 간의 경쟁에만 집중하고 실제 인구에 관계된 파라메터는 모두 날려서 정규화했기 때문이다. $x_{1}$, $x_{2}$, $x_{3}$ 세 개의 축에서 각각의 값은 $[0,1]$ 을 벗어날 일이 없다.

사실 메이-레너드 경쟁 모델이라는 명칭은 그다지 자주 쓰이는 편은 아닌데, 더 일반적인 폼인 롯카-볼테라 경쟁 모델이 있기 때문이다. 다만 정밀한 생태계의 묘사가 아니라면 그 중에서도 딱 세 개의 종을 다루면서 파라메터 세팅이 아주 단순한 메이-레너드 모델이 수학적으로 더욱 매력적일 수 있다.

현실 속에서 이러한 $3$자 대립을 이루는 관계는 다음과 같은 예들을 생각해볼 수 있다:

유도

$$ \begin{align*} x_{1}' =& r_{1} x_{1} {{ K_{1} - x_{1} - \beta_{12} x_{2} } \over { K_{1} }} \\ x_{2}' =& r_{2} x_{2} {{ K_{2} - x_{2} - \beta_{21} x_{1} } \over { K_{2} }} \end{align*} $$

별달리 유도과정이랄 게 없고, 롯카-볼테라 경쟁 모델에서 집단을 하나 추가하고 고유 성장률, 환경 수용량을 1로 두었을 뿐이다.

일반화

시뮬레이션

가위바위보RPS, Rock-Paper-Scissors 게임을 격자 모델로 시뮬레이션 해보자. 각 색상은 다음과 같은 패를 나타낸다. 컬러 매칭은 RGB 순으로 나타내는 것보다는 요즘 게임에서 많이 사용하는 불<물<풀 상성에 맞추고 파스텔 톤을 주었다:

RPS_game_20

위의 움짤은 20x20 격자 공간에서 세 집단의 경쟁을 보여준다. 잘 보면 공간 대부분을 차지하는 대세가 계속 바뀌는 것으로 보이는데, 가장 먼저 녹색이 흥하는 듯하다가 청색이 너무 적어지자 천적이 적어진 적색이 득세하는 등 우리가 예상한 대로의 추세를 보여준다. 그러나 공간이 너무 좁기 때문에 운이 너무 많이 작용하고, 녹색이 기회를 잡고 천통에 성공하고 만다.

RPS_game_100

해상도와 fps를 올려서 보면 위에서 보았던 격전이 곳곳에서 일어나며 전체적인 균형이 유지되는 것을 볼 수 있다.

코드

다음은 줄리아로 구현된 전체 코드다.

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

@time using Plots
@time using Random

# 0:W: Empty
# 1:R:R: Rock
# 2:B:P: Paper
# 3:G:S: scissors
colormap_RPS = [colorant"#FFFFFF", colorant"#FFCCCC", colorant"#99CCFF", colorant"#CCFFCC"]
row_size = 20
column_size = 20
p = 3/4
Random.seed!(0);

stage_lattice = zeros(Int64, row_size, column_size)
stage_lattice[rand(2:(row_size-1)), rand(2:(column_size-1))] = 1; stage_lattice
stage_lattice[rand(2:(row_size-1)), rand(2:(column_size-1))] = 2; stage_lattice
stage_lattice[rand(2:(row_size-1)), rand(2:(column_size-1))] = 3; stage_lattice
figure = heatmap(reverse(stage_lattice,dims=1), color=colormap_RPS,
  xaxis=false,yaxis=false,axis=nothing, size = [400,400], legend = false)
png(figure, "08-01.png")

function duel(A::Int, B::Int; p=0.5)
  if A > B
    A, B = B, A
  end

  if A == 0 || A == B
    return B
  elseif A == 1 && B == 3
    if rand() < p
      return 1
    else
      return 3
    end
  elseif rand() < p
    return B
  else
    return A
  end
end

stage_duel = copy(stage_lattice)
for i in 2:(row_size-1)
  for j in 2:(row_size-1)
    I = i + rand([-1,0,1])
    J = j + rand([-1,0,1])
    A = stage_lattice[I, J]

    I = i + rand([-1,0,1])
    J = j + rand([-1,0,1])
    B = stage_lattice[I, J] #중복 허용
    if A != 0 || B != 0
      stage_duel[i,j] = duel(A, B, p=1)
    end
  end
end
stage_lattice = stage_duel
figure = heatmap(reverse(stage_lattice,dims=1), color=colormap_RPS,
  xaxis=false,yaxis=false,axis=nothing, size = [400,400], legend = false)
png(figure, "08-02.png")

let
  Random.seed!(0);
  row_size = 20
  column_size = 20

  stage_lattice = zeros(Int64, row_size, column_size)
  stage_lattice[rand(2:(row_size-1)), rand(2:(column_size-1))] = 1; stage_lattice
  stage_lattice[rand(2:(row_size-1)), rand(2:(column_size-1))] = 2; stage_lattice
  stage_lattice[rand(2:(row_size-1)), rand(2:(column_size-1))] = 3; stage_lattice
  figure = heatmap(reverse(stage_lattice,dims=1), color=colormap_RPS,
    xaxis=false,yaxis=false,axis=nothing, size = [400,400], legend = false)

  anim = @animate for t = 1:400
    stage_duel = copy(stage_lattice)
    for i in 2:(row_size-1)
      for j in 2:(row_size-1)
        I = i + rand([-1,0,1])
        J = j + rand([-1,0,1])
        A = stage_lattice[I, J]
    
        I = i + rand([-1,0,1])
        J = j + rand([-1,0,1])
        B = stage_lattice[I, J] #중복 허용
        if A != 0 || B != 0
          stage_duel[i,j] = duel(A, B, p=1)
        end
      end
    end
    stage_lattice = stage_duel
    figure = heatmap(reverse(stage_lattice,dims=1), color=colormap_RPS,
      xaxis=false,yaxis=false,axis=nothing, size = [400,400], legend = false)
    end
  gif(anim, "RPS_game_20.gif", fps = 4)
end

  1. Allen. (2006). An Introduction to Mathematical Biology: p251. ↩︎

  2. Barry Sinervo. (1996). The rock-paper-scissors game and the evolution of alternative male strategies ↩︎

  3. https://en.wikipedia.org/wiki/Common_side-blotched_lizard ↩︎

댓글