Skip to content

Commit

Permalink
Migrate docstrings for mixed behavior profile operations.
Browse files Browse the repository at this point in the history
  • Loading branch information
tturocy committed Sep 1, 2023
1 parent 6fade51 commit 74c93f7
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 121 deletions.
111 changes: 0 additions & 111 deletions doc/pyapi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -579,118 +579,7 @@ Game representations
restriction was based.


Representations of play of games
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The main responsibility of these classes is to capture information
about a plan of play of a game, by one or more players.


.. py:class:: MixedBehaviorProfile
Represents a behavior strategy profile over a :py:class:`Game`.

.. py:method:: __getitem__(index)
Returns a slice of the profile based on the parameter
``index``.

* If ``index`` is a :py:class:`Action`,
returns the probability with which that action is played in
the profile.
* If ``index`` is an :py:class:`Infoset`,
returns a list of probabilities, one for each action belonging
to that information set.
* If ``index`` is a :py:class:`Player`,
returns a list of lists of probabilities, one list for each
information set controlled by the player.
* If ``index`` is an integer, returns the
``index`` th entry in the profile, treating the profile as a
flat list of probabilities.

.. py:method:: __setitem__(action, prob)
Sets the probability ``action`` is played in the profile to ``prob``.

.. py:method:: as_strategy()
Returns a :py:class:`MixedStrategyProfile` which is equivalent
to the profile.

.. py:method:: belief(node)
Returns the probability ``node`` is reached, given its information
set was reached.

.. py:method:: belief(infoset)
Returns a list of belief probabilities of each node in ``infoset``.

.. py:method:: copy()
Creates a copy of the behavior strategy profile.

.. py:method:: payoff(player)
Returns the expected payoff to ``player`` if all players play
according to the profile.

.. py:method:: payoff(action)
Returns the expected payoff to choosing ``action``, conditional
on having reached the information set, if all
other players play according to the profile.

.. py:method:: payoff(infoset)
Returns the expected payoff to the player who has the move at
``infoset``, conditional on the information set being reached,
if all players play according to the profile.

.. py:method:: regret(action)
Returns the regret associated to ``action``.

.. py:method:: realiz_prob(infoset)
Returns the probability with which information set ``infoset``
is reached, if all players play according to the profile.

.. py:method:: liap_value()
Returns the Lyapunov value (see [McK91]_) of the strategy profile. The
Lyapunov value is a non-negative number which is zero exactly at
Nash equilibria.

.. py:method:: normalize()
Each information set's component of the profile is not enforced to sum to
one, so that, for example, counts rather than probabilities can
be expressed. Calling this returns a profile in which the
probability distribution over each information set's actions
sums to one.

.. versionchanged:: 16.1.0

Returns the normalized profile as a copy and leaves the
original changed. Previously the original profile
was normalized in place.

.. py:method:: randomize(denom)
Randomizes the probabilities in the profile. These are
generated as uniform distributions over the actions at each
information set. If
``denom`` is specified, all probabilities are divisible by
``denom``, that is, the distribution is uniform over a discrete
grid of mixed strategies. ``denom`` is required for profiles
in which the probabilities are rational numbers.

:raises TypeError: if ``denom`` is not specified for a profile
with rational probabilities.



Analysis of quantal response equilibria
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~---------

Expand Down
88 changes: 78 additions & 10 deletions src/pygambit/core/behav.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ import functools
from cython.operator cimport dereference as deref

cdef class MixedBehaviorProfile:
def __repr__(self):
"""A behavior strategy profile over the actions in a game."""
def __repr__(self):
return str([ self[player] for player in self.game.players ])

def _repr_latex_(self):
return r"$\left[" + ",".join([ self[player]._repr_latex_().replace("$","") for player in self.game.players ]) + r"\right]$"

Expand Down Expand Up @@ -95,6 +97,22 @@ cdef class MixedBehaviorProfile:
(len(index.actions), len(value)))

def __getitem__(self, index):
"""Returns a slice of the profile based on the parameter
` `index``.
* If ``index`` is a :py:class:`Action`,
returns the probability with which that action is played in
the profile.
* If ``index`` is an :py:class:`Infoset`,
returns a list of probabilities, one for each action belonging
to that information set.
* If ``index`` is a :py:class:`Player`,
returns a list of lists of probabilities, one list for each
information set controlled by the player.
* If ``index`` is an integer, returns the
``index`` th entry in the profile, treating the profile as a
flat list of probabilities.
"""
if isinstance(index, int):
return self._getprob(index+1)
elif isinstance(index, Action):
Expand Down Expand Up @@ -148,6 +166,9 @@ cdef class MixedBehaviorProfile:
index.__class__.__name__)

def __setitem__(self, index, value):
"""Sets the probability ``action`` is played in the profile
to ``prob``.
"""
if isinstance(index, int):
self._setprob(index+1, value)
elif isinstance(index, Action):
Expand All @@ -173,6 +194,9 @@ cdef class MixedBehaviorProfile:
return self._is_defined_at(infoset)

def belief(self, node):
"""Returns the probability ``node`` is reached, given its
information set was reached.
"""
if isinstance(node, Node):
return self._belief(node)
elif isinstance(node, Infoset):
Expand All @@ -191,6 +215,9 @@ cdef class MixedBehaviorProfile:
return self._action_prob(action)

def payoff(self, player_infoset_or_action):
"""Returns the expected payoff to a player, information set, or
action, if all players play according to the profile.
"""
if isinstance(player_infoset_or_action, Player):
return self._payoff(player_infoset_or_action)
elif isinstance(player_infoset_or_action, Infoset):
Expand All @@ -211,6 +238,9 @@ cdef class MixedBehaviorProfile:
player_infoset_or_action.__class__.__name__)

def realiz_prob(self, infoset_or_action):
"""Returns the probability with which an information set is
reached.
"""
if isinstance(infoset_or_action, Infoset):
return self._infoset_prob(infoset_or_action)
elif isinstance(infoset_or_action, Action):
Expand All @@ -225,6 +255,7 @@ cdef class MixedBehaviorProfile:
infoset_or_action.__class__.__name__)

def regret(self, action):
"""Returns the regret associated with `action`."""
if isinstance(action, str):
action = self._resolve_index(action, players=False)
if not isinstance(action, Action):
Expand All @@ -239,6 +270,7 @@ cdef class MixedBehaviorProfileDouble(MixedBehaviorProfile):

def __dealloc__(self):
del self.profile

def __len__(self):
return self.profile.Length()

Expand Down Expand Up @@ -267,29 +299,48 @@ cdef class MixedBehaviorProfileDouble(MixedBehaviorProfile):
def _regret(self, Action action):
return self.profile.GetRegret(action.action)

def copy(self):
def copy(self) -> MixedBehaviorProfileDouble:
"""Creates a copy of the behavior strategy profile."""
cdef MixedBehaviorProfileDouble behav
behav = MixedBehaviorProfileDouble()
behav.profile = new c_MixedBehaviorProfileDouble(deref(self.profile))
return behav
def as_strategy(self):

def as_strategy(self) -> MixedStrategyProfileDouble:
"""Returns a `MixedStrategyProfile` which is equivalent
to the profile.
"""
cdef MixedStrategyProfileDouble mixed
mixed = MixedStrategyProfileDouble()
mixed.profile = new c_MixedStrategyProfileDouble(deref(self.profile).ToMixedProfile())
return mixed
def liap_value(self):

def liap_value(self) -> float:
"""Returns the Lyapunov value (see [McK91]_) of the strategy profile. The
Lyapunov value is a non-negative number which is zero exactly at
Nash equilibria.
"""
return self.profile.GetLiapValue()
def set_centroid(self): self.profile.SetCentroid()

def set_centroid(self):
self.profile.SetCentroid()

def normalize(self) -> MixedBehaviorProfileDouble:
"""Create a profile with the same action proportions as this
one, but normalised so probabilites for each infoset sum to one.
one, but normalised so probabilities for each infoset sum to one.
"""
profile = MixedBehaviorProfileDouble()
profile.profile = new c_MixedBehaviorProfileDouble(self.profile.Normalize())
return profile

def randomize(self, denom=None):
"""Randomizes the probabilities in the profile. These are
generated as uniform distributions over the actions at each
information set. If
``denom`` is specified, all probabilities are divisible by
``denom``, that is, the distribution is uniform over a discrete
grid of mixed strategies.
"""
if denom is None:
self.profile.Randomize()
else:
Expand All @@ -310,6 +361,7 @@ cdef class MixedBehaviorProfileRational(MixedBehaviorProfile):

def __dealloc__(self):
del self.profile

def __len__(self):
return self.profile.Length()

Expand Down Expand Up @@ -345,19 +397,31 @@ cdef class MixedBehaviorProfileRational(MixedBehaviorProfile):
def _regret(self, Action action):
return rat_to_py(self.profile.GetRegret(action.action))

def copy(self):
def copy(self) -> MixedBehaviorProfileRational:
"""Creates a copy of the behavior strategy profile."""
cdef MixedBehaviorProfileRational behav
behav = MixedBehaviorProfileRational()
behav.profile = new c_MixedBehaviorProfileRational(deref(self.profile))
return behav
def as_strategy(self):

def as_strategy(self) -> MixedStrategyProfileRational:
"""Returns a `MixedStrategyProfile` which is equivalent
to the profile.
"""
cdef MixedStrategyProfileRational mixed
mixed = MixedStrategyProfileRational()
mixed.profile = new c_MixedStrategyProfileRational(deref(self.profile).ToMixedProfile())
return mixed
def liap_value(self):

def liap_value(self) -> Rational:
"""Returns the Lyapunov value (see [McK91]_) of the strategy profile. The
Lyapunov value is a non-negative number which is zero exactly at
Nash equilibria.
"""
return rat_to_py(self.profile.GetLiapValue())
def set_centroid(self): self.profile.SetCentroid()

def set_centroid(self):
self.profile.SetCentroid()

def normalize(self) -> MixedBehaviorProfileRational:
"""Create a profile with the same action proportions as this
Expand All @@ -368,6 +432,10 @@ cdef class MixedBehaviorProfileRational(MixedBehaviorProfile):
return profile

def randomize(self, denom):
"""Randomizes the probabilities in the profile. These are
generated as uniform distributions over the actions at each
information set.
"""
self.profile.Randomize(denom)

@property
Expand Down

0 comments on commit 74c93f7

Please sign in to comment.