Source code for gameanalysis.reduction.hierarchical
"""Hierarchical reduction"""
import numpy as np
from gameanalysis import paygame
from gameanalysis import restrict
from gameanalysis import rsgame
from gameanalysis import utils
from gameanalysis.reduction import _common
[docs]def reduce_game(full_game, red_players):
"""Reduce a game using hierarchical reduction
Parameters
----------
full_game : Game
The game to reduce.
red_players : ndarray-like
The reduced number of players for each role. This will be coerced
into the proper shape if necessary.
"""
red_game = rsgame.empty_names(
full_game.role_names, red_players, full_game.strat_names
)
utils.check(
np.all(red_game.num_role_players > 0),
"all reduced players must be greater than zero",
)
utils.check(
np.all(full_game.num_role_players >= red_game.num_role_players),
"all full counts must not be less than reduced counts",
)
if full_game.is_empty():
return red_game
elif full_game.num_profiles < red_game.num_all_profiles:
profiles = full_game.profiles()
payoffs = full_game.payoffs()
else:
profiles = expand_profiles(full_game, red_game.all_profiles())
payoffs = full_game.get_payoffs(profiles)
valid = ~np.all(np.isnan(payoffs) | (profiles == 0), 1)
profiles = profiles[valid]
payoffs = payoffs[valid]
red_profiles, mask = _common.reduce_profiles(
full_game, red_game.num_role_players[None], profiles
)
return paygame.game_replace(red_game, red_profiles, payoffs[mask])
[docs]def reduce_profiles(red_game, profiles):
"""Reduce profiles hierarchically
Parameters
----------
red_game : Game
Game that reduced profiles will be profiles for.
profiles : ndarray-like
The profiles to reduce.
"""
profiles = np.asarray(profiles, int)
utils.check(
profiles.shape[-1] == red_game.num_strats, "profiles must be appropriate shape"
)
return _common.reduce_profiles(
red_game,
red_game.num_role_players[None],
profiles.reshape((-1, red_game.num_strats)),
)[0]
[docs]def expand_profiles(full_game, profiles):
"""Expand profiles hierarchically
Parameters
----------
full_game : Game
Game that expanded profiles will be valid for.
profiles : ndarray-like
The profiles to expand
"""
profiles = np.asarray(profiles, int)
utils.check(
profiles.shape[-1] == full_game.num_strats, "profiles must be appropriate shape"
)
return _common.expand_profiles(
full_game,
full_game.num_role_players[None],
profiles.reshape((-1, full_game.num_strats)),
)
[docs]def expand_deviation_profiles(full_game, rest, red_players, role_index=None):
"""Expand all deviation profiles from a restricted game
Parameters
----------
full_game : Game
The game the deviations profiles will be valid for.
rest : [bool]
The restriction to get deviations from.
red_players : ndarray-like
The number of players in each role in the reduced game.
role_index : int, optional
If specified , only expand deviations for the role selected.
"""
utils.check(full_game.is_restriction(rest), "restriction must be valid")
return expand_profiles(
full_game,
restrict.deviation_profiles(
rsgame.empty(red_players, full_game.num_role_strats), rest, role_index
),
)