logo

May-Leonard Competition Model 📂Dynamics

May-Leonard Competition Model

Overview

The May-Leonard competition model is a population dynamics model in the state of competition involving three groups, depicting a triangular relationship where each group preys on and is preyed on by the others. These three parties could be political parties, companies, or actual competing species with natural advantages and disadvantages.

Model1

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

Variables

  • $x_{1}(t)$: represents the population of group $x_{1}$ at time $t$.
  • $x_{2}(t)$: represents the population of group $x_{2}$ at time $t$.
  • $x_{3}(t)$: represents the population of group $x_{3}$ at time $t$.

Parameters

  • $0<a<1$: the competitive coefficient from the relatively advantageous group.
  • $b>1$: the competitive coefficient from the relatively disadvantageous group.

Explanation

The May-Leonard model is a $3$-dimensional system with only two parameters, focusing solely on the competition among the three groups. All actual population-related parameters are normalized by being abstracted away. The values on the axes of $x_{1}$, $x_{2}$, and $x_{3}$ are confined within $[0,1]$.

The term “May-Leonard competition model” is not frequently used since there’s a more general form, the Lotka-Volterra competition model. However, for a simplistic representation of just three species with relatively straightforward parameter setting, the May-Leonard model may be more mathematically appealing.

In reality, tripartite oppositions can be observed in examples such as:

  • Pokémon: Historically, the starting Pokémon in the numbered series have been of three types: Grass, Fire, Water. Despite factors like the Grass-type’s defensive system being the weakest or evolution changing the type advantage, their inherent type advantage relationship of consuming and being consumed has remained unchanged. Pokémon
  • Side-blotched lizard: Male side-blotched lizards, despite being of the same species, are divided into three types based on the color of the throat fan (referred to as a “collar”) which determines their mating strategy. 2 3 uta_lizard.png
    • Orange, ultra-dominant: Largest and most aggressive, with a wide home range containing many females. Capable of stealing mates from blue-collared lizards but vulnerable to the sneak tactics of yellow-collared lizards.
    • Blue, dominant: Medium size, less aggressive, with a smaller home range and monogamous pairing. Good at detecting yellow-collared lizards’ sneak mating attempts but susceptible to mate theft by orange-collared lizards regardless.
    • Yellow, sneaker: Lacks a territory but roams the widest area. Mimics the appearance of a mature female to sneak into other males’ territories for clandestine mating.

Derivation

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

The derivation is straightforward, being an extension of the Lotka-Volterra competition model with the addition of one group and setting the intrinsic growth rates and the carrying capacity to 1.

Generalization

  • The generalization of the Lotka-Volterra competition model for $n$ groups can be represented as follows for $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) $$

Simulation

Let’s simulate a Rock-Paper-Scissors (RPS) game in a grid model. Each color represents the following elements, and color matching follows the common in-game pattern of Fire<Water<Grass with a pastel tone rather than the RGB sequence:

  • Red - Rock
  • Blue - Paper
  • Green - Scissors

RPS_game_20

The gif above shows the competition among the three groups in a 20x20 grid space. Notably, the dominant group keeps changing: green seems to thrive first, but as the blue population decreases, the red population, having lost its predator, gains dominance. However, due to the limited space, chance plays a significant role, and green eventually finds an opportunity for a breakthrough.

RPS_game_100

Increasing the resolution and fps, one can observe fierce battles occurring at various points, with an overall balance being maintained throughout the simulation.

Code

Below is the complete code implemented in Julia.

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