nash_se

jlgametheory.nash_se(g, *, full_output=False, **options)[source]

Compute mixed-action Nash equilibria of an N-player normal form game by support enumeration, solving the indifference conditions on each support profile with linear or nonlinear programming.

This function calls nash_se of StrategicGames.jl, which solves the linear programs with HiGHS for N = 2 and the nonlinear programs with Ipopt for N >= 3.

Parameters

gNormalFormGame

NormalFormGame instance with N >= 2 players.

full_outputbool, optional(default=False)

If False, only the list of computed Nash equilibria is returned. If True, the return value is (NEs, res), where res is a NashResult object.

options :

Optional keyword arguments to pass to StrategicGames.nash_se. In particular, max_samples is the maximum number of Nash equilibria to find (default 1; float('inf') for no limit). See the StrategicGames.jl documentation for details.

Returns

NEslist(tuple(ndarray(float, ndim=1)))

List containing tuples of computed Nash equilibrium mixed actions.

resNashResult

Object containing the information about the result, returned only when full_output is True, with the following attributes: NEs (same as NEs above), expected_payoffs (list of ndarrays of the payoffs of the players at each equilibrium), and supports (list of tuples of 0-based int ndarrays of the support profile on which each equilibrium was found).

Examples

Consider the 3-player 2-action game with 9 Nash equilibria in McKelvey and McLennan (1996) “Computation of Equilibria in Finite Games”:

>>> import numpy as np
>>> import quantecon.game_theory as gt
>>> import jlgametheory as jgt
>>> from pprint import pprint
>>> np.set_printoptions(precision=3)  # Reduce the digits printed
>>> g = gt.NormalFormGame((2, 2, 2))
>>> g[0, 0, 0] = 9, 8, 12
>>> g[1, 1, 0] = 9, 8, 2
>>> g[0, 1, 1] = 3, 4, 6
>>> g[1, 0, 1] = 3, 4, 4
>>> NEs = jgt.nash_se(g)
>>> NEs
[(array([1., 0.]), array([1., 0.]), array([1., 0.]))]
>>> NEs = jgt.nash_se(g, max_samples=float('inf'))
>>> len(NEs)
8
>>> pprint(NEs)
[(array([1., 0.]), array([1., 0.]), array([1., 0.])),
 (array([0., 1.]), array([0., 1.]), array([1., 0.])),
 (array([0., 1.]), array([1., 0.]), array([0., 1.])),
 (array([1., 0.]), array([0., 1.]), array([0., 1.])),
 (array([0.5, 0.5]), array([0.5, 0.5]), array([1., 0.])),
 (array([0.25, 0.75]), array([1., 0.]), array([0.25, 0.75])),
 (array([0., 1.]), array([0.333, 0.667]), array([0.333, 0.667])),
 (array([0.5, 0.5]), array([0.333, 0.667]), array([0.25, 0.75]))]
>>> all(g.is_nash(NE, tol=1e-5) for NE in NEs)  # Relax tolerance
True

This game in fact has two full-support equilibria: nash_se returns at most one equilibrium per support profile and thus does not reach one of those equilibria.