egttools.games.AbstractNPlayerStateGame

class AbstractNPlayerStateGame(self: egttools.numerical.numerical_.games.AbstractNPlayerStateGame, nb_strategies: SupportsInt | SupportsIndex, group_size: SupportsInt | SupportsIndex)

Bases: AbstractNPlayerGame

Abstract base class for N-player games with state-dependent payoffs.

Use this class when payoffs cannot be precomputed at initialization because they depend on the current population state (e.g., games with variable risk functions whose value changes with population composition).

Subclasses must implement get_payoffs_for_player, which is called once per calculate_fitness invocation. The C++ base class then runs the full hypergeometric sampling loop in C++, reducing the number of Python call-throughs from O(nb_group_configurations) to exactly 1 per fitness evaluation.

Parameters:
  • nb_strategies (int) – Number of strategies in the game.

  • group_size (int) – Number of players per interacting group.

  • Methods (Abstract)

  • ----------------

  • get_payoffs_for_player(player_type – Returns a 1-D array of length nb_group_configurations with the expected payoff for player_type under each possible group configuration, given that the full population state (including the focal player) has linear index state_index.

  • state_index – Returns a 1-D array of length nb_group_configurations with the expected payoff for player_type under each possible group configuration, given that the full population state (including the focal player) has linear index state_index.

  • np.ndarray (calculate_payoffs() ->) – Returns a 1-D array of length nb_group_configurations with the expected payoff for player_type under each possible group configuration, given that the full population state (including the focal player) has linear index state_index.

  • play(group_composition – Fills game_payoffs in-place for a concrete group sample.

  • game_payoffs) – Fills game_payoffs in-place for a concrete group sample.

  • np.ndarray – Optionally pre-computes and stores the payoff matrix for inspection. Not used by calculate_fitness.

Notes

The state_index passed to get_payoffs_for_player is computed by egttools.calculate_state(group_size, full_state), where full_state is state with state[player_type] + 1.

Example

>>> import numpy as np
>>> import egttools as egt
>>>
>>> class MyGame(egt.games.AbstractNPlayerStateGame):
...     def __init__(self, nb_strategies, group_size, risk_func, payoff_func):
...         super().__init__(nb_strategies, group_size)
...         self._configs = [egt.sample_simplex(i, group_size, nb_strategies)
...                          for i in range(self.nb_group_configurations)]
...         self.risk_func = risk_func
...         self.payoff_func = payoff_func
...
...     def get_payoffs_for_player(self, player_type, state_index, state):
...         risk = self.risk_func(state_index)
...         return np.array([self.payoff_func(risk, gc)[player_type]
...                          for gc in self._configs])
...
...     def play(self, group_composition, game_payoffs): ...
...     def calculate_payoffs(self): return self.payoffs()
...     def payoffs(self): return np.zeros((self.nb_strategies, self.nb_group_configurations))
...     def payoff(self, strategy, group_composition): return 0.0
...     def save_payoffs(self, file_name): pass
...     def __str__(self): return "MyGame"
...     def type(self): return "MyGame"

Methods

calculate_fitness

Computes the fitness of player_type in a population with state strategies.

calculate_payoffs

get_payoffs_for_player

Returns the payoff row for player_type across all group configurations.

group_size

nb_group_configurations

nb_strategies

payoff

payoffs

play

save_payoffs

type

update_payoff

Updates an entry in the payoff matrix.

__init__(self: egttools.numerical.numerical_.games.AbstractNPlayerStateGame, nb_strategies: SupportsInt | SupportsIndex, group_size: SupportsInt | SupportsIndex) None
__new__(**kwargs)
__str__(self: egttools.numerical.numerical_.games.AbstractNPlayerStateGame) str
calculate_fitness(self: egttools.numerical.numerical_.games.AbstractNPlayerStateGame, player_type: SupportsInt | SupportsIndex, pop_size: SupportsInt | SupportsIndex, strategies: Annotated[numpy.typing.NDArray[numpy.uint64], '[m, 1]']) float

Computes the fitness of player_type in a population with state strategies.

Calls get_payoffs_for_player once to obtain the full payoff row, then evaluates the hypergeometric expectation in C++.

Parameters:
  • player_type (int) – Index of the focal player’s strategy.

  • pop_size (int) – Total population size (excluding the focal player).

  • strategies (np.ndarray) – Strategy counts in the population, excluding the focal player.

Returns:

Expected fitness of player_type.

Return type:

float

calculate_payoffs(self: egttools.numerical.numerical_.games.AbstractNPlayerStateGame) Annotated[numpy.typing.NDArray[numpy.float64], '[m, n]']
get_payoffs_for_player(self: egttools.numerical.numerical_.games.AbstractNPlayerStateGame, player_type: SupportsInt | SupportsIndex, state_index: SupportsInt | SupportsIndex, state: Annotated[numpy.typing.NDArray[numpy.uint64], '[m, 1]']) Annotated[numpy.typing.NDArray[numpy.float64], '[m, 1]']

Returns the payoff row for player_type across all group configurations.

This method is called once per calculate_fitness invocation. Implement it in your Python subclass to return the payoffs that depend on the current population state.

Parameters:
  • player_type (int) – Index of the focal player’s strategy.

  • state_index (int) – Linear index of the full population state (including the focal player), as returned by egttools.calculate_state(group_size, full_state).

  • state (np.ndarray) – Population state vector excluding the focal player (same as the strategies argument passed to calculate_fitness).

Returns:

1-D array of length nb_group_configurations with the payoff for player_type in each possible group composition drawn from state.

Return type:

np.ndarray

group_size(self: egttools.numerical.numerical_.games.AbstractNPlayerStateGame) int
nb_group_configurations(self: egttools.numerical.numerical_.games.AbstractNPlayerStateGame) int
nb_strategies(self: egttools.numerical.numerical_.games.AbstractNPlayerStateGame) int
payoff(self: egttools.numerical.numerical_.games.AbstractNPlayerStateGame, strategy: SupportsInt | SupportsIndex, group_composition: collections.abc.Sequence[SupportsInt | SupportsIndex]) float
payoffs(self: egttools.numerical.numerical_.games.AbstractNPlayerStateGame) Annotated[numpy.typing.NDArray[numpy.float64], '[m, n]']
play(self: egttools.numerical.numerical_.games.AbstractNPlayerStateGame, group_composition: collections.abc.Sequence[SupportsInt | SupportsIndex], game_payoffs: collections.abc.Sequence[SupportsFloat | SupportsIndex]) None
save_payoffs(self: egttools.numerical.numerical_.games.AbstractNPlayerStateGame, file_name: str) None
type(self: egttools.numerical.numerical_.games.AbstractNPlayerStateGame) str
update_payoff(self: egttools.numerical.numerical_.games.AbstractNPlayerGame, strategy_index: SupportsInt | SupportsIndex, group_configuration_index: SupportsInt | SupportsIndex, value: SupportsFloat | SupportsIndex) None

Updates an entry in the payoff matrix.

Parameters:
  • strategy_index (int) – Index of the strategy.

  • group_configuration_index (int) – Index of the group composition.

  • value (float) – The new payoff value.

__annotations__ = {}