egttools.analytical.utils.StochDynamics

class StochDynamics(nb_strategies, payoffs, pop_size, group_size=2, mu=0)[source]

Bases: object

A class containing methods to calculate the stochastic evolutionary dynamics of a population.

Defines a class that contains methods to compute the stationary distribution for the limit of small mutation (only the monomorphic states) and the full transition matrix.

Parameters:
  • nb_strategies (int) – number of strategies in the population

  • payoffs (npt.NDArray[np.float64][numpy.float64[m,m]]) –

    Payoff matrix indicating the payoff of each strategy (rows) against each other (columns). When analyzing an N-player game (group_size > 2) the structure of the matrix is a bit more involved, and we can have 2 options for structuring the payoff matrix:

    1) If we consider a simplified version of the system with a reduced Markov Chain which only contains the states at the edges of the simplex (the Small Mutation Limit - SML), then, we can assume that, at most, there will be 2 strategies in a group at any given moment. In this case, StochDynamics expects a square matrix of size nb_strategies x nb_strategies, in which each entry is a function that takes 2 positional arguments k and group_size, and an optional *args argument, and will return the expected payoff of the row strategy A in a group with k A strategists and group_size - k B strategists (the column strategy). For all the elements in the diagonal, only 1 strategy should be present in the group, thus, this function should always return the same value, i.e., the payoff of a row strategy when all individuals in the group adopt the same strategy. See below for an example.

    2) If we want to consider the full Markov Chain composed of all possible states in the simplex, then the payoff matrix should be of the shape nb_strategies x nb_group_configurations, where the number of group configurations can be calculated using egttools.calculate_nb_states(group_size, nb_strategies). Moreover, the mapping between group configurations and integer indexes must be done using egttools.sample_simplex(index, group_size, nb_strategies). See below for an example

  • pop_size (int) – population size

  • group_size (int) – group size

  • mu (float) – mutation probability

Notes

We recommend that instead of`StochDynamics`, you use PairwiseComparison because the latter is implemented in C++, runs faster and supports more precise types.

Examples

Example of the payoff matrix for case 1) mu = 0:
>>> def get_payoff_a_vs_b(k, group_size, \*args):
...     pre_computed_payoffs = [4, 5, 2, ..., 4] # the size of this list should be group_size + 1
...     return pre_computed_payoffs[k]
>>> def get_payoff_b_vs_a(k, group_size, \*args):
...     pre_computed_payoffs = [0, 2, 1, ..., 0] # the size of this list should be group_size + 1
...     return pre_computed_payoffs[k]
>>> def get_payoff_a_vs_a(k, group_size, \*args):
...     pre_computed_payoffs = [1, 1, 1, ..., 1] # the size of this list should be group_size + 1
...     return pre_computed_payoffs[k]
>>> def get_payoff_b_vs_b(k, group_size, \*args):
...     pre_computed_payoffs = [0, 0, 0, ..., 0] # the size of this list should be group_size + 1
...     return pre_computed_payoffs[k]
>>> payoff_matrix = np.array([
...     [get_payoff_A_vs_A, get_payoff_A_vs_B],
...     [get_payoff_B_vs_A, get_payoff_B_vs_B]
...     ])
Example of payoff matrix for case 2) full markov chain (mu > 0):
>>> import egttools
>>> nb_group_combinations = egttools.calculate_nb_states(group_size, nb_strategies)
>>> payoff_matrix = np.zeros(shape=(nb_strategies, nb_group_combinations))
>>> for group_configuration_index in range(nb_group_combinations):
...     for strategy in range(nb_strategies):
...         group_configuration = egttools.sample_simplex(group_configuration_index, group_size, nb_strategies)
...         payoff_matrix[strategy, group_configuration_index] = get_payoff(strategy, group_configuration)

Methods

calculate_full_transition_matrix

Returns the full transition matrix in sparse representation.

calculate_stationary_distribution

Calculates the stationary distribution of the monomorphic states is mu = 0 (SML).

fermi

The fermi function determines the probability that the first type imitates the second.

fitness_group

In a population of x i-strategists and (pop_size-x) j strategists, where players interact in group of 'group_size' participants this function returns the average payoff of strategies i and j.

fitness_pair

Calculates the fitness of strategy i versus strategy j, in a population of x i-strategists and (pop_size-x) j strategists, considering a 2-player game.

fixation_probability

Function for calculating the fixation_probability probability of the invader in a population of residents.

full_fitness_difference_group

Calculate the fitness difference between strategies :param i and :param j assuming that player interacts in groups of size group_size > 2 (n-player games).

full_fitness_difference_pairwise

Calculates the fitness of strategy i in a population with state :param population_state, assuming pairwise interactions (2-player game).

full_gradient_selection

Calculates the gradient of selection for an invading strategy, given a population state.

full_gradient_selection_without_mutation

Calculates the gradient of selection for an invading strategy, given a population state.

gradient_selection

Calculates the gradient of selection given an invader and a resident strategy.

prob_increase_decrease

This function calculates for a given number of invaders the probability that the number increases or decreases with one.

prob_increase_decrease_with_mutation

This function calculates for a given number of invaders the probability that the number increases or decreases with taking into account a mutation rate.

transition_and_fixation_matrix

Calculates the transition matrix (only for the monomorphic states) and the fixation_probability probabilities.

update_group_size

Updates the groups size of the game (and the methods used to compute the fitness)

update_payoffs

Updates the payoff matrix

update_population_size

Updates the size of the population and the number of possible population states.

__init__(nb_strategies, payoffs, pop_size, group_size=2, mu=0)[source]
calculate_full_transition_matrix(beta, *args)[source]

Returns the full transition matrix in sparse representation.

Parameters:
  • beta (float) – Intensity of selection.

  • args (Optional[list]) – Other arguments. Can be used to pass extra arguments to functions contained in the payoff matrix.

Returns:

The full transition matrix between the two strategies in sparse format.

Return type:

scipy.sparse.csr_matrix

calculate_stationary_distribution(beta, *args)[source]

Calculates the stationary distribution of the monomorphic states is mu = 0 (SML). Otherwise, it calculates the stationary distribution including all possible population states.

This function is recommended only for Hermitian transition matrices.

Parameters:
  • beta (float) – intensity of selection.

  • args (Optional[list]) – extra arguments for calculating payoffs.

Returns:

A vector containing the stationary distribution

Return type:

npt.NDArray[np.float64]

static fermi(beta, fitness_diff)[source]

The fermi function determines the probability that the first type imitates the second.

Parameters:
  • beta (float) – intensity of selection

  • fitness_diff (float) – Difference in fitness between the strategies (f_a - f_b).

Returns:

the probability of imitation

Return type:

numpy.typing.ArrayLike

fitness_group(x, i, j, *args)[source]

In a population of x i-strategists and (pop_size-x) j strategists, where players interact in group of ‘group_size’ participants this function returns the average payoff of strategies i and j. This function expects that

\[x \in [1,pop_size-1]\]
Parameters:
  • x (int) – number of individuals adopting strategy i in the population

  • i (int) – index of strategy i

  • j (int) – index of strategy j

  • args (Optional[list]) – Other Parameters. This can be used to pass extra parameters to functions stored in the payoff matrix

Return type:

float

Returns:

float Returns the difference in fitness between strategy i and j

fitness_pair(x, i, j, *args)[source]

Calculates the fitness of strategy i versus strategy j, in a population of x i-strategists and (pop_size-x) j strategists, considering a 2-player game.

Parameters:
  • x (int) – number of i-strategists in the population

  • i (int) – index of strategy i

  • j (int) – index of strategy j

  • args (Optional[list])

Return type:

float

Returns:

float the fitness difference among the strategies

fixation_probability(invader, resident, beta, *args)[source]

Function for calculating the fixation_probability probability of the invader in a population of residents.

TODO: Requires more testing!

Parameters:
  • invader (int) – index of the invading strategy

  • resident (int) – index of the resident strategy

  • beta (float) – intensity of selection

  • args (Optional[list]) – Other arguments. Can be used to pass extra arguments to functions contained in the payoff matrix.

Returns:

The fixation_probability probability.

Return type:

float

full_fitness_difference_group(i, j, population_state)[source]

Calculate the fitness difference between strategies :param i and :param j assuming that player interacts in groups of size group_size > 2 (n-player games).

Parameters:
  • i (int) – index of the strategy that will reproduce

  • j (int) – index of the strategy that will die

  • population_state (npt.NDArray[np.float64][numpy.int64[m,1]]) – vector containing the counts of each strategy in the population

Return type:

float

Returns:

  • float

  • The fitness difference between strategies i and j

full_fitness_difference_pairwise(i, j, population_state)[source]

Calculates the fitness of strategy i in a population with state :param population_state, assuming pairwise interactions (2-player game).

Parameters:
  • i (int) – index of the strategy that will reproduce

  • j (int) – index of the strategy that will die

  • population_state (npt.NDArray[np.float64][numpy.int64[m,1]]) – vector containing the counts of each strategy in the population

Return type:

float

Returns:

  • float

  • The fitness difference between the two strategies for the given population state

full_gradient_selection(population_state, beta)[source]

Calculates the gradient of selection for an invading strategy, given a population state.

Parameters:
  • population_state (npt.NDArray[np.float64][np.int64[m,1]]) – structure of unsigned integers containing the counts of each strategy in the population

  • beta (float) – intensity of selection

Returns:

Matrix indicating the likelihood of change in the population given a starting point.

Return type:

npt.NDArray[np.float64][numpy.float64[m,m]]

full_gradient_selection_without_mutation(population_state, beta)[source]

Calculates the gradient of selection for an invading strategy, given a population state. It does not take into account mutation.

Parameters:
  • population_state (npt.NDArray[np.float64][np.int64[m,1]]) – structure of unsigned integers containing the counts of each strategy in the population

  • beta (float) – intensity of selection

Returns:

Matrix indicating the likelihood of change in the population given a starting point.

Return type:

npt.NDArray[np.float64][numpy.float64[m,m]]

gradient_selection(k, invader, resident, beta, *args)[source]

Calculates the gradient of selection given an invader and a resident strategy.

Parameters:
  • k (int) – number of invaders in the population

  • invader (int) – index of the invading strategy

  • resident (int) – index of the resident strategy

  • beta (float) – intensity of selection

  • args (Optional[List]) – other arguments. Can be used to pass extra arguments to functions contained in the payoff matrix.

Returns:

The gradient of selection.

Return type:

float

prob_increase_decrease(k, invader, resident, beta, *args)[source]

This function calculates for a given number of invaders the probability that the number increases or decreases with one.

Parameters:
  • k (int) – number of invaders in the population

  • invader (int) – index of the invading strategy

  • resident (int) – index of the resident strategy

  • beta (float) – intensity of selection

  • args (Optional[list]) – other arguments. Can be used to pass extra arguments to functions contained in the payoff matrix.

Returns:

tuple(probability of increasing the number of invaders, probability of decreasing)

Return type:

Tuple[numpy.typing.ArrayLike, numpy.typing.ArrayLike]

prob_increase_decrease_with_mutation(k, invader, resident, beta, *args)[source]

This function calculates for a given number of invaders the probability that the number increases or decreases with taking into account a mutation rate.

Parameters:
  • k (int) – number of invaders in the population

  • invader (int) – index of the invading strategy

  • resident (int) – index of the resident strategy

  • beta (float) – intensity of selection

  • args (Optional[list]) – other arguments. Can be used to pass extra arguments to functions contained in the payoff matrix.

Returns:

tuple(probability of increasing the number of invaders, probability of decreasing)

Return type:

Tuple[float, float]

transition_and_fixation_matrix(beta, *args)[source]

Calculates the transition matrix (only for the monomorphic states) and the fixation_probability probabilities.

This method calculates the transitions between monomorphic states. Thus, it assumes that we are in the small mutation limit (SML) of the moran process. Only use this method if this assumption is reasonable.

Parameters:
  • beta (float) – Intensity of selection.

  • args (Optional[list]) – Other arguments. Can be used to pass extra arguments to functions contained in the payoff matrix.

Returns:

This method returns a tuple with the transition matrix as first element, and the matrix of fixation probabilities.

Return type:

Tuple[npt.NDArray[np.float64][numpy.float64[m,m]], npt.NDArray[np.float64][numpy.float64[m,m]]]

update_group_size(group_size)[source]

Updates the groups size of the game (and the methods used to compute the fitness)

Parameters:

group_size (new group size)

Return type:

None

update_payoffs(payoffs, nb_strategies=None)[source]

Updates the payoff matrix

Parameters:
  • payoffs (payoff matrix)

  • nb_strategies (total number of strategies (optional). If not indicated, then the new payoff) – matrix must have the same dimensions as the previous one

Return type:

None

update_population_size(pop_size)[source]

Updates the size of the population and the number of possible population states.

Parameters:

pop_size (New population size)

Return type:

None

__annotations__ = {}