This example uses a handicap function and data taken from a talk by Hazard. This example appears on Slide 36.
Hazard, C. J. 2010. What every game designer should know about game theory. Triangle Game Conference. Raleigh, North Carolina
First, we import the packages we need.
In [1]:
import _initpath
import numpy
import zerosum.balance
Then we take the data as it appeared in Hazard's slides. The example given was symmetric, which means that the base matrix is log-skew-symmetric (every element is the reciprocal of its transpose). However, this payoff function can also work for non-symmetric cases.
In [2]:
data = numpy.array([
[1.0, 3.0, 0.5],
[1.0 / 3.0, 1.0, 0.5],
[2.0, 2.0, 1.0]])
names = ['Hammer', 'Spear', 'Curse']
Hazard's talk used the convention that the elements of the matrix are how many of the row player's unit it takes to equal one of the column player's unit. We use the opposite convention, where higher is better for the row player, so we take the inverse, which for the symmetric case is the same as the transpose.
In [3]:
data = 1.0 / data
Now we can construct our problem instance and solve it.
In [4]:
balance = zerosum.balance.HazardSymmetricBalance(data)
result = balance.optimize()
Finally we print the result, normalizing the handicaps so that they sum to 1. Note that a global scale in the handicaps merely scales the global payoffs and does not change the Nash equilibrium. Since the value of the (balanced) game is 0 this does not change the value either.
In [5]:
for name, handicap in zip(names, result.handicaps / numpy.sum(result.handicaps)):
print("%8s: %0.3f" % (name, handicap))
Naturally, this matches the result from the talk.