Source code for nashpy.algorithms.vertex_enumeration
"""A class for the vertex enumeration algorithm"""
import numpy as np
import numpy.typing as npt
from typing import Generator, Tuple, Any
from nashpy.polytope import build_halfspaces, non_trivial_vertices
[docs]def vertex_enumeration(
A: npt.NDArray, B: npt.NDArray
) -> Generator[Tuple[float, float], Any, None]:
"""
Obtain the Nash equilibria using enumeration of the vertices of the best
response polytopes.
Algorithm implemented here is Algorithm 3.5 of [Nisan2007]_
1. Build best responses polytopes of both players
2. For each vertex pair of both polytopes
3. Check if pair is fully labelled
4. Return the normalised pair
Parameters
----------
A : array
The row player utility matrix.
B : array
The column player utility matrix
Yields
-------
Generator
The equilibria.
"""
if np.min(A) < 0:
A = A + abs(np.min(A))
if np.min(B) < 0:
B = B + abs(np.min(B))
number_of_row_strategies, row_dimension = A.shape
max_label = number_of_row_strategies + row_dimension
full_labels = set(range(max_label))
row_halfspaces = build_halfspaces(B.transpose())
col_halfspaces = build_halfspaces(A)
for row_v, row_l in non_trivial_vertices(row_halfspaces):
adjusted_row_l = set(
(label + number_of_row_strategies) % (max_label) for label in row_l
)
for col_v, col_l in non_trivial_vertices(col_halfspaces):
if adjusted_row_l.union(col_l) == full_labels:
yield row_v / sum(row_v), col_v / sum(col_v)