Use stochastic fictitious playΒΆ
One of the learning algorithms implemented in Nashpy
is called
Stochastic fictitious play, this is implemented as a method on the Game
class:
>>> import nashpy as nash
>>> import numpy as np
>>> A = np.array([[3, 1], [0, 2]])
>>> B = np.array([[2, 0], [1, 3]])
>>> game = nash.Game(A, B)
The stochastic_fictitious_play
method returns a generator of a given collection of
learning steps, comprising of the play counts and the mixed strategy of each player:
>>> np.random.seed(0)
>>> iterations = 500
>>> play_counts_and_distributions = game.stochastic_fictitious_play(iterations=iterations)
>>> for play_counts, distributions in play_counts_and_distributions:
... row_play_counts, column_play_counts = play_counts
... row_distributions, column_distributions = distributions
... print(row_play_counts, column_play_counts, row_distributions, column_distributions)
[0 0] [0 0] None None
[1. 0.] [0. 1.] [9.99953841e-01 4.61594628e-05] [0.501447 0.498553]
...
[498. 1.] [497. 2.] [1.00000000e+00 1.07557011e-13] [9.99999998e-01 2.32299935e-09]
[499. 1.] [498. 2.] [1.00000000e+00 1.17304491e-13] [9.99999998e-01 2.18403537e-09]
Note that this process is stochastic:
>>> np.random.seed(1)
>>> play_counts_and_distributions = game.stochastic_fictitious_play(iterations=iterations)
>>> for play_counts, distributions in play_counts_and_distributions:
... row_play_counts, column_play_counts = play_counts
... row_distributions, column_distributions = distributions
... print(row_play_counts, column_play_counts)
[0 0] [0 0]
[1. 0.] [1. 0.]
...
[499. 0.] [499. 0.]
[500. 0.] [500. 0.]
It is also possible to pass a play_counts
variable to give a starting
point for the algorithm:
>>> np.random.seed(0)
>>> play_counts = (np.array([0., 500.]), np.array([0., 500.]))
>>> play_counts_and_distributions = game.stochastic_fictitious_play(iterations=iterations, play_counts=play_counts)
>>> for play_counts, distributions in play_counts_and_distributions:
... row_play_counts, column_play_counts = play_counts
... row_distributions, column_distributions = distributions
... print(row_play_counts, column_play_counts)
...
[ 0. 500.] [ 0. 500.]
[ 0. 501.] [ 0. 501.]
...
[ 0. 999.] [ 0. 999.]
[ 0. 1000.] [ 0. 1000.]
A value of etha
and epsilon_bar
can be passed.
See the Stochastic fictitious play reference section for more information. The default values for etha and epsilon bar are
\(10^-1\) and \(10^-2\) respectively:
>>> np.random.seed(0)
>>> etha = 10**-2
>>> epsilon_bar = 10**-3
>>> play_counts_and_distributions = game.stochastic_fictitious_play(iterations=iterations, etha=etha, epsilon_bar=epsilon_bar)
>>> for play_counts, distributions in play_counts_and_distributions:
... row_play_counts, column_play_counts = play_counts
... row_distributions, column_distributions = distributions
... print(row_play_counts, column_play_counts)
...
[0 0] [0 0]
[1. 0.] [0. 1.]
...
[498. 1.] [497. 2.]
[499. 1.] [498. 2.]