Asymmetric replicator dynamics

The asymmetric replicator dynamics algorithm is implemented in Nashpy based on the work presented in [Elvio2011]. This is considered as the asymmetric version of the symmetric Replicator dynamics.

There exists a population with two types of individuals where each type has their own strategy set. Strategies are assigned amongst the population. Individuals randomly encounter individuals of the opposite type and play their assigned strategies.

As the game progresses the proportion of each type playing each strategy changes based on their previous interactions.

The row player represents the first type of individuals and the column player represents the other one.

Given two matrices \(A\in\mathbb{R}^{m\times n}\) and \(B\in\mathbb{R}^{m\times n}\) that correspond to the utilities of the row player and column player respectively, we define:

\[\begin{split}f_x = Ay \\ f_y = x^T B\end{split}\]

Where \(x\in\mathbb{R}^{m\times 1}\) and \(y\in\mathbb{R}^{n\times 1}\) corresponds to the population size of the strategies of the two players and \(f_x\in\mathbb{R}^{n\times1}\) and \(f_y\in\mathbb{R}^{1\times m}\) corresponds to the fitness of the strategies of the row player and the column player respectively.

Similarly, the average fitness for the two types of populations is given by \(\phi_x\) and \(\phi_y\) where:

\[\begin{split}\phi_x = f_x x^T \\ \phi_y = f_y y\end{split}\]

In matrix notation the rate of change of the strategies of both types of individuals is captured by:

\[\begin{split}\frac{dx}{dt}_i = x_i((f_x)_i - \phi_x) \text{ for all }i \\ \frac{dy}{dt}_i = y_i((f_y)_i - \phi_y) \text{ for all }i\end{split}\]

Discussion

Stability is achieved in asymmetric replicator dynamics when both \(\frac{dx}{dt} = 0\) and \(\frac{dy}{dt} = 0\). Every stable steady state is a Nash equilibria, and every Nash equilibria is a steady state in asymmetric replicator dynamics.

Similarly to Replicator dynamics, a game is not guaranteed to converge to a steady state. Find below the probability distributions for both the row player and the column player over time, of a game that does not converge:

>>> import matplotlib.pyplot as plt
>>> import nashpy as nash
>>> import numpy as np
>>> A = np.array([[0, -1, 1], [1, 0, -1], [-1, 1, 0]])
>>> B = A.transpose()
>>> game = nash.Game(A, B)
>>> x0 = np.array([0.3, 0.35, 0.35])
>>> y0 = np.array([0.3, 0.35, 0.35])
>>> xs, ys = game.asymmetric_replicator_dynamics(x0=x0, y0=y0)
>>> plt.figure(figsize=(15, 5)) 
>>> plt.subplot(1, 2, 1) 
>>> plt.plot(xs) 
>>> plt.title("Probability distribution of strategies over time for row player") 
>>> plt.legend([f"$s_{0}$", f"$s_{1}$", f"$s_{2}$"]) 
>>> plt.subplot(1, 2, 2) 
>>> plt.plot(ys) 
>>> plt.xlabel("Timepoints") 
>>> plt.ylabel("Probability") 
>>> plt.title("Probability distribution of strategies over time for column player") 
>>> plt.legend([f"$s_{0}$", f"$s_{1}$", f"$s_{2}$"]) 
../_images/main.svg

Find below an example of a game that is able to reach a stable steady state:

>>> import matplotlib.pyplot as plt
>>> import nashpy as nash
>>> import numpy as np
>>> A = np.array([[2, 2], [3, 4]])
>>> B = np.array([[4, 3], [3, 2]])
>>> game = nash.Game(A, B)
>>> x0 = np.array([0.9, 0.1])
>>> y0 = np.array([0.3, 0.7])
>>> xs, ys = game.asymmetric_replicator_dynamics(x0=x0, y0=y0)
>>> plt.figure(figsize=(15, 5)) 
>>> plt.subplot(1, 2, 1) 
>>> plt.plot(xs) 
>>> plt.title("Probability distribution of strategies over time for row player") 
>>> plt.legend([f"$s_{0}$", f"$s_{1}$"]) 
>>> plt.subplot(1, 2, 2) 
>>> plt.plot(ys) 
>>> plt.xlabel("Timepoints") 
>>> plt.ylabel("Probability") 
>>> plt.title("Probability distribution of strategies over time for column player") 
>>> plt.legend([f"$s_{0}$", f"$s_{1}$"]) 
../_images/main1.svg