Source code for quantecon.game_theory.logitdyn

import numpy as np
import numbers
from .normal_form_game import NormalFormGame
from ..util import check_random_state, rng_integers
from .random import random_pure_actions


[docs]class LogitDynamics: """ Class representing the logit-response dynamics model. Parameters ---------- data : NormalFormGame or array_like The game played in the logit-response dynamics model. beta : scalar(float) The level of noise in player's decision. Attributes ---------- N : scalar(int) The number of players in the game. players : list(Player) The list consisting of all players with the given payoff matrix. nums_actions : tuple(int) Tuple of the number of actions, one for each player. beta : scalar(float) See parameters. player.logit_choice_cdfs : array_like(float) The choice probability of each actions given opponents' actions. """ def __init__(self, data, beta=1.0): if isinstance(data, NormalFormGame): self.g = data else: # data must be array_like self.g = NormalFormGame(data) self.N = self.g.N self.players = self.g.players self.nums_actions = self.g.nums_actions self.beta = beta for player in self.players: payoff_array_rotated = \ player.payoff_array.transpose(list(range(1, self.N)) + [0]) payoff_array_rotated -= \ payoff_array_rotated.max(axis=-1)[..., np.newaxis] player.logit_choice_cdfs = \ np.exp(payoff_array_rotated*self.beta).cumsum(axis=-1)
[docs] def logit_choice_cdfs(self): """ Return the tuple of choice probabilities. """ return tuple(player.logit_choice_cdfs for player in self.players)
def _play(self, player_ind, actions, random_state): i = player_ind # Tuple of the actions of opponent players i+1, ..., N, 0, ..., i-1 opponent_actions = \ tuple(actions[i+1:]) + tuple(actions[:i]) cdf = self.players[i].logit_choice_cdfs[opponent_actions] random_value = random_state.random() next_action = cdf.searchsorted(random_value*cdf[-1], side='right') return next_action
[docs] def play(self, init_actions=None, player_ind_seq=None, num_reps=1, random_state=None): """ Return a new action profile which is updated `num_reps` times. Parameters ---------- init_actions : tuple(int), optional(default=None) The action profile in the initial period. If None, selected randomly. player_ind_seq : list(int), optional(default=None) The sequence of player indices. If None, selected randomly. num_reps : scalar(int), optional(default=1) The number of iterations. random_state : int or np.random.RandomState/Generator, optional Random number generator used. Returns ------- tuple(int) The action profile after iterations. """ random_state = check_random_state(random_state) if init_actions is None: init_actions = random_pure_actions(self.nums_actions, random_state) init_actions = list(init_actions) if player_ind_seq is None: random_state = check_random_state(random_state) player_ind_seq = rng_integers(random_state, self.N, size=num_reps) if isinstance(player_ind_seq, numbers.Integral): player_ind_seq = [player_ind_seq] for t, player_ind in enumerate(player_ind_seq): random_state = check_random_state(random_state) init_actions[player_ind] = self._play(player_ind, init_actions, random_state) return tuple(init_actions)
[docs] def time_series(self, ts_length, init_actions=None, random_state=None): """ Return the array representing time series of action profiles. Parameters ---------- ts_length : scalar(int) The number of iterations. init_actions : tuple(int), optional(default=None) The action profile in the initial period. If None, selected randomly. random_state : int or np.random.RandomState/Generator, optional Random number generator used. Returns ------- ndarray(int) The array representing the time series of action profiles. """ if init_actions is None: random_state = check_random_state(random_state) init_actions = random_pure_actions(self.nums_actions, random_state) actions = list(init_actions) out = np.empty((ts_length, self.N), dtype=int) random_state = check_random_state(random_state) player_ind_seq = rng_integers(random_state, self.N, size=ts_length) for t, player_ind in enumerate(player_ind_seq): out[t, :] = actions[:] random_state = check_random_state(random_state) actions[player_ind] = self._play(player_ind, actions, random_state) return out