Simplified 2-Simplex plot

In the Plot the evolutionary dynamics in a 2-Simplex example, we show how to use the Simplex2D class to visualize dynamics on a 2 Simplex using arbitrary gradient function (although the examples were shown only for the replicator equation and the Moran process defined in a finite population of strategies).

However, when we want to use the replicator_equation and StochDynamics provided in egttools, then we can simplify the plotting process by using two utility functions: egttools.plotting.plot_replicator_dynamics_in_simplex and egttools.plotting.plot_pairwise_comparison_rule_dynamics_in_simplex.

[1]:
import numpy as np
import matplotlib.pyplot as plt

%matplotlib inline
[2]:
from egttools.plotting.simplified import plot_replicator_dynamics_in_simplex, plot_pairwise_comparison_rule_dynamics_in_simplex_without_roots
from egttools.utils import calculate_stationary_distribution

Evolutionary dynamics in infinite populations

In infinite populations the dynamics are given by the replicator equation. Following we calculate the gradients for all the points in a grid and plot them in a 2-simplex using the Simplex2D class.

We will also be plotting in the simplex the stationary points. We will use black circle to represent stable equilibrium and white circles to represent unstable ones. The arrows indicate the direction of the selective pressure.

Define payoff matrix

[3]:
payoffs = np.array([[1, 0, 0],
                    [0, 2, 0],
                    [0, 0, 3]])
[4]:
type_labels = ['A', 'B', 'C']

Plot the trajectories from the stationary points

[5]:
fig, ax = plt.subplots(figsize=(10,8))

simplex, gradient_function, roots, roots_xy, stability = plot_replicator_dynamics_in_simplex(payoffs,
                                                                                             nb_of_initial_points_for_root_search=100,
                                                                                             ax=ax)

plot = (simplex.draw_triangle()
           .add_vertex_labels(type_labels)
           .draw_stationary_points(roots_xy, stability)
           .draw_trajectory_from_roots(gradient_function,
                                       roots,
                                       stability,
                                       trajectory_length=15,
                                       linewidth=1,
                                       step=0.01,
                                       color='k', draw_arrow=True, arrowdirection='right', arrowsize=30, zorder=4, arrowstyle='fancy')
           .draw_scatter_shadow(gradient_function, 300, color='gray', marker='.', s=0.1)
          )

ax.axis('off')
ax.set_aspect('equal')

plt.xlim((-.05,1.05))
plt.ylim((-.02, simplex.top_corner + 0.05))
plt.show()
../_images/examples_plot_simplex_simplified_10_0.png

Plot the gradient field using a streamplot

[6]:
fig, ax = plt.subplots(figsize=(10,8))

plot = (simplex.add_axis(ax=ax)
           .draw_triangle()
           .draw_gradients(zorder=0)
           .add_colorbar()
           .add_vertex_labels(type_labels)
           .draw_stationary_points(roots_xy, stability)
           .draw_trajectory_from_roots(gradient_function,
                                       roots,
                                       stability,
                                       trajectory_length=15,
                                       linewidth=1,
                                       step=0.01,
                                       color='k', draw_arrow=True, arrowdirection='right', arrowsize=30, zorder=4, arrowstyle='fancy')
           .draw_scatter_shadow(gradient_function, 300, color='gray', marker='.', s=0.1, zorder=0)
          )

ax.axis('off')
ax.set_aspect('equal')

plt.xlim((-.05,1.05))
plt.ylim((-.02, simplex.top_corner + 0.05))
plt.show()
../_images/examples_plot_simplex_simplified_12_0.png

Stochastic Dynamics in finite populations - Moran process with pairwise comparison

In finite populations we will model the dynamics using a Moran process. The calculation of the gradients is implemented in EGTtools in the StochDynamics class. In this case, since we want to calculate the gradient at any point in the simplex, we will use the full_gradient_selection method

Define the population size and the intensity of selection

[7]:
Z = 100
beta = 1
mu = 1/Z

Plot the gradient field and the stationary distribution

We can also plot the stationary distribution inside the simplex. It will give us an idea on where our population is going to spend most of the time

[8]:
fig, ax = plt.subplots(figsize=(15,10))

simplex, gradient_function, game, evolver = plot_pairwise_comparison_rule_dynamics_in_simplex_without_roots(payoff_matrix=payoffs, population_size=Z, beta=beta, ax=ax)

transitions = evolver.calculate_transition_matrix(beta=beta, mu=mu)
sd = calculate_stationary_distribution(transitions.transpose())

plot = (simplex.add_axis(ax=ax)
           # .draw_triangle()
           .draw_gradients(zorder=5)
           .add_colorbar()
           .add_vertex_labels(type_labels)
           .draw_stationary_distribution(sd, alpha=1, edgecolors='gray', cmap='binary', shading='gouraud', zorder=0)
          )

ax.axis('off')
ax.set_aspect('equal')

plt.xlim((-.05,1.05))
plt.ylim((-.02, simplex.top_corner + 0.05))
plt.show()
../_images/examples_plot_simplex_simplified_18_0.png
[ ]: