메이-레너드 경쟁 모델

메이-레너드 경쟁 모델

May-leonard competition model

개요

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

모델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*} $$

변수

  • $x_{1}(t)$: $t$ 시점에서 집단 $x_{1}$ 의 개체수를 나타낸다.
  • $x_{2}(t)$: $t$ 시점에서 집단 $x_{2}$ 의 개체수를 나타낸다.
  • $x_{3}(t)$: $t$ 시점에서 집단 $x_{3}$ 의 개체수를 나타낸다.

파라메터

  • $0<a<1$: 상대적으로 유리한 집단으로부터 받는 경쟁 계수다.
  • $b>1$: 상대적으로 불리한 집단으로부터 받는 경쟁 계수다.

설명

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

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

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

  • 포켓몬: 역사적으로 넘버링 시리즈에서 스타팅 포켓몬은 풀, 불, 물 세가지 타입을 가져왔다. 풀 타입의 방어체계가 셋 중 제일 안 좋다거나 진화하면 역상성이 된다거나 하는 점은 제쳐두더라도, 이들 삼자의 상성 자체가 먹고 먹히는 관계라는 것은 바뀐 적이 없다. 포켓몬
  • 땅유타도마뱀Uta stansburiana: 수컷 땅유타도마뱀은 같은 종임에도 불구하고 다음과 같은 세가지 유형으로 나뉘는데, 목에 있는 무늬(이하 목도리)의 색에 따라 번식전략을 달리한다. 23 uta_lizard.png
    • 주황색, 극우성: 몸집이 가장 크고 공격적이며, 넓은 생활 반경을 가지고 많은 암컷들을 거느린다. 남색 목도리들의 짝을 빼앗는데 능하지만 샛노란 목도리들의 위장에 취약하다.
    • 남색, 우성: 중간 사이즈에 덜 공격적이고 더 작은 생활 반경에 하나의 짝과 함께한다. 하나의 짝만 있을 땐 샛노란 목도리의 위장을 잘 간파하지만 그와 상관없이 주황 목도리에게 짝을 빼앗길 수 있다.
    • 샛노란색, 좀도둑: 딱히 영역을 가지지 않는 대신 다른 도마뱀의 생활 반경을 포함해 가장 넓은 영역을 돌아다닌다. 성숙한 암컷과 비슷하게 생긴 덕에 다른 종류의 수컷들에게 들키지 않고 숨어 들어가 몰래 교미를 한다.

유도

$$ \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로 두었을 뿐이다.

일반화

  • $n$개 집단에 대한 롯카-볼테라 경쟁 모델의 일반화는 $i = 1 , \cdots , n$ 에 대해 다음과 같이 나타낼 수 있다. $$ { { d x_{i} } \over { d x_{t} } } = x_{i} \left( a_{i0} - \sum_{j=1}^{n} a_{ij} x_{j} \right) $$

시뮬레이션

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

  • 적색 - Rock
  • 청색 - Paper
  • 녹색 - Scissors

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 ↩︎

댓글