def generate_games(num): # pylint: disable=too-many-branches """Produce num random games per type""" np.random.seed(0) with open(path.join(_DIR, 'example_games', 'hard_nash.json')) as fil: yield 'hard', gamereader.load(fil).normalize() with open(path.join(_DIR, 'example_games', '2x2x2.nfg')) as fil: yield 'gambit', gamereader.load(fil).normalize() for _ in range(num): yield 'random', gamegen.game(*random_small()).normalize() for _ in range(num): strats = np.random.randint(2, 5, np.random.randint(2, 4)) yield 'covariant', gamegen.covariant_game(strats).normalize() for _ in range(num): strats = np.random.randint(2, 5, 2) yield 'zero sum', gamegen.two_player_zero_sum_game(strats).normalize() for _ in range(num): yield 'prisoners', gamegen.prisoners_dilemma().normalize() for _ in range(num): yield 'chicken', gamegen.sym_2p2s_game(0, 3, 1, 2).normalize() for _ in range(num): prob = np.random.random() yield 'mix', gamegen.sym_2p2s_known_eq(prob).normalize() for _ in range(num): strats = np.random.randint(2, 4) plays = np.random.randint(2, 4) yield 'polymatrix', gamegen.polymatrix_game(plays, strats).normalize() for _ in range(num): wins = np.random.random(3) + .5 loss = -np.random.random(3) - .5 yield 'roshambo', gamegen.rock_paper_scissors(wins, loss).normalize() yield 'shapley easy', gamegen.rock_paper_scissors(win=2).normalize() yield 'shapley normal', gamegen.rock_paper_scissors(win=1).normalize() yield 'shapley hard', gamegen.rock_paper_scissors(win=0.5).normalize() for _ in range(num): yield 'normagg small', gamegen.normal_aggfn(*random_agg_small()) for _ in range(num): yield 'polyagg small', gamegen.poly_aggfn(*random_agg_small()) for _ in range(num): yield 'sineagg small', gamegen.sine_aggfn(*random_agg_small()) for _ in range(num): facs = np.random.randint(2, 6) req = np.random.randint(1, facs) players = np.random.randint(2, 11) yield 'congestion', gamegen.congestion(players, facs, req) for _ in range(num): strats = np.random.randint(2, 6) players = np.random.randint(2, 11) yield 'local effect', gamegen.local_effect(players, strats) for _ in range(num): yield 'normagg large', gamegen.normal_aggfn(*random_agg_large()) for _ in range(num): yield 'polyagg large', gamegen.poly_aggfn(*random_agg_large()) for _ in range(num): yield 'sineagg large', gamegen.sine_aggfn(*random_agg_large()) for _ in range(num): agg = gamegen.sine_aggfn(*random_agg_small()) with warnings.catch_warnings(): warnings.simplefilter('ignore', UserWarning) yield 'rbf', learning.rbfgame_train(agg)
def test_mixed_roshambo(methods): game = gamegen.rock_paper_scissors() eqa = nash.mixed_nash(game, dist_thresh=1e-2, processes=1, **methods) assert eqa.shape[0] == 1, \ "didn't find right number of equilibria in roshambo" assert np.allclose(1/3, eqa), \ "roshambo equilibria wasn't uniform"
def test_noop_and_serial_nash(): """Test that no op works""" game = gamegen.rock_paper_scissors() req, eqm = nash._serial_nash_func(game, (nash._noop, [1 / 2, 0, 1 / 2], True)) # pylint: disable=protected-access assert np.allclose(eqm, [1 / 2, 0, 1 / 2]) assert req
def test_nash_8(): with tempfile.NamedTemporaryFile('w') as game: sgame = gamegen.rock_paper_scissors() serial = gamegen.serializer(sgame) json.dump(serial.to_game_json(sgame), game) game.flush() run('nash', '-tpure', '--one', '-i', game.name)
def test_hard_roshambo(): game = gamegen.rock_paper_scissors(loss=[-2, -3, -3]) eqa = nash.mixed_nash(game) assert eqa.shape[0] == 1, \ "didn't find right number of equilibria in roshambo" assert np.allclose([0.3125, 0.40625, 0.28125], eqa), \ "roshambo equilibria wasn't uniform"
def test_minreg_grid_roshambo(): game = gamegen.rock_paper_scissors() eqm = nash.min_regret_grid_mixture(game, 3) # Not enough for eq assert np.isclose(regret.mixture_regret(game, eqm), .5), \ "min regret grid didn't find [.5, .5, 0] profile with regret .5" eqm = nash.min_regret_grid_mixture(game, 4) # hit eqa perfectly assert np.isclose(regret.mixture_regret(game, eqm), 0), \ "min regret grid didn't find equilibrium"
def test_deviation_payoffs_jacobian(): game = gamegen.rock_paper_scissors() eqm = np.array([1 / 3] * 3) dp, dpj = game.deviation_payoffs(eqm, jacobian=True) assert np.allclose(dp, 0) expected_jac = np.array([[0., -1., 1.], [1., 0., -1.], [-1., 1., 0.]]) assert np.allclose(dpj, expected_jac)
def test_pure_roshambo(): game = gamegen.rock_paper_scissors() eqa = nash.pure_nash(game) assert eqa.size == 0, "found a pure equilibrium in roshambo" eqa = nash.pure_nash(game, 1) assert eqa.shape[0] == 3, \ "didn't find low regret ties in roshambo" eqa = nash.pure_nash(game, 2) assert eqa.shape[0] == game.num_all_profiles, \ "found profiles with more than 2 regret in roshambo"
def test_pure_roshambo(): """Test roshambo""" game = gamegen.rock_paper_scissors() eqa = nash.pure_equilibria(game) assert eqa.size == 0, 'found a pure equilibrium in roshambo' eqa = nash.pure_equilibria(game, epsilon=1) assert eqa.shape[0] == 3, \ "didn't find low regret ties in roshambo" eqa = nash.pure_equilibria(game, epsilon=2) assert eqa.shape[0] == game.num_all_profiles, \ 'found profiles with more than 2 regret in roshambo'
def test_nash(): with open(GAME) as f: assert not subprocess.run([GA, 'nash'], stdin=f).returncode assert not subprocess.run([ GA, 'nash', '-i', GAME, '-o/dev/null', '-r1e-2', '-d1e-2', '-c1e-7', '-x100', '-s1e-2', '-m5', '-n', '-p1']).returncode assert not subprocess.run([GA, 'nash', '-tpure', '-i', GAME]).returncode assert not subprocess.run([GA, 'nash', '-tmin-reg-prof', '-i', GAME]).returncode assert not subprocess.run([GA, 'nash', '-tmin-reg-grid', '-i', GAME]).returncode assert not subprocess.run([GA, 'nash', '-tmin-reg-rand', '-m10', '-i', GAME]).returncode assert not subprocess.run([GA, 'nash', '-trand', '-m10', '-i', GAME]).returncode assert subprocess.run([GA, 'nash', '-tfail', '-i', GAME]).returncode with tempfile.NamedTemporaryFile('w') as game: sgame = gamegen.rock_paper_scissors() serial = gamegen.game_serializer(sgame) json.dump(sgame.to_json(serial), game) game.flush() assert not subprocess.run([GA, 'nash', '-tpure', '--one', '-i', game.name]).returncode
def test_fictitious_play(): """Test that fictitious play works""" game = gamegen.rock_paper_scissors(win=2) eqm = nash.fictitious_play(game, [0.6, 0.3, 0.1], max_iters=10000) # pylint: disable=unexpected-keyword-arg assert np.allclose(eqm, [1 / 3, 1 / 3, 1 / 3], atol=1e-4)
def test_rock_paper_scissors_defaults(): """Test rock paper scissors with default arguments""" game = gamegen.rock_paper_scissors() assert np.allclose(game.get_payoffs([1, 1, 0]), [-1, 1, 0])
def test_min_regret_profile(): """Test minimum regret profile on rps""" game = gamegen.rock_paper_scissors() eqm = nash.min_regret_profile(game) assert utils.allequal_perm(eqm, [0, 0, 2]), \ 'min regret profile was not rr, pp, or ss'
def test_rock_paper_scissors(win, loss): """Test rock paper scissors""" game = gamegen.rock_paper_scissors(win, loss) assert game.strat_names == (('paper', 'rock', 'scissors'),) assert np.allclose(game.get_payoffs([1, 1, 0]), [_first(loss), _first(win), 0])
def test_multiplicative_weights_bandit(): """Test that multiplicative weights bandit works""" game = gamegen.rock_paper_scissors(win=2) eqm = nash.multiplicative_weights_bandit( game, [0.6, 0.3, 0.1], max_iters=100000) assert np.allclose(eqm, [1/3, 1/3, 1/3], atol=0.1)
def test_regret_minimize(): """Test that regret minimize works""" game = gamegen.rock_paper_scissors() eqm = nash.regret_minimize(game, [0.6, 0.3, 0.1]) assert np.allclose(eqm, [1 / 3, 1 / 3, 1 / 3], atol=1e-4)
def test_rock_paper_scissors_defaults(): game = gamegen.rock_paper_scissors() assert np.allclose(game.get_payoffs([1, 1, 0]), [-1, 1, 0])
def test_regret_matching_noop(): """Test that we can make fictitious play noop""" game = gamegen.rock_paper_scissors() eqm = nash.regret_matching(game, [2, 0, 0], max_iters=0) # pylint: disable=unexpected-keyword-arg assert np.allclose(eqm, [1, 0, 0])
def test_fictitious_play_noop(): """Test that we can make fictitious play noop""" game = gamegen.rock_paper_scissors() eqm = nash.fictitious_play(game, [0.6, 0.3, 0.1], max_iters=0) # pylint: disable=unexpected-keyword-arg assert np.allclose(eqm, [0.6, 0.3, 0.1])
def test_regret_minimize(): """Test that regret minimize works""" game = gamegen.rock_paper_scissors() eqm = nash.regret_minimize(game, [0.6, 0.3, 0.1]) assert np.allclose(eqm, [1/3, 1/3, 1/3], atol=1e-4)
def test_regret_matching(): """Test that it works for games we know it works for""" game = gamegen.rock_paper_scissors() eqm = nash._regret_matching_mix(game, [1/2, 0, 1/2]) # pylint: disable=protected-access assert np.allclose(eqm, [1/3, 1/3, 1/3], atol=5e-2)
def test_replicator_dynamics_failure(): """Test that it fails on divergent games""" game = gamegen.rock_paper_scissors() eqm = nash.replicator_dynamics(game, [0.6, 0.3, 0.1]) assert utils.allclose_perm(eqm, [1, 0, 0])
def test_fictitious_play_convergence(): """Test that fictitious play converges""" game = gamegen.rock_paper_scissors(win=2) eqm = nash.fictitious_play(game, [0.3, 0.4, 0.3], converge_thresh=1e-3) # pylint: disable=unexpected-keyword-arg assert np.allclose(eqm, [1 / 3, 1 / 3, 1 / 3], atol=1e-3)
def test_regret_matching(): """Test that it works for games we know it works for""" game = gamegen.rock_paper_scissors() eqm = nash._regret_matching_mix(game, [1 / 2, 0, 1 / 2]) # pylint: disable=protected-access assert np.allclose(eqm, [1 / 3, 1 / 3, 1 / 3], atol=5e-2)
def test_fictitious_play_failure(): """Test that fictitious play fails""" game = gamegen.rock_paper_scissors(win=0.5) eqm = nash.fictitious_play(game, [0.6, 0.3, 0.1], max_iters=10000) # pylint: disable=unexpected-keyword-arg assert regret.mixture_regret(game, eqm) > 0.1
def test_rock_paper_scissors(win, loss): game, conv = gamegen.rock_paper_scissors(win, loss, return_serial=True) assert conv.strat_names == (('rock', 'paper', 'scissors'),) assert np.allclose(game.get_payoffs([1, 1, 0]), [_first(loss), _first(win), 0])
def test_multiplicative_weights_dist(): """Test that multiplicative weights dist works""" game = gamegen.rock_paper_scissors(win=2) eqm = nash.multiplicative_weights_dist(game, [0.6, 0.3, 0.1]) assert np.allclose(eqm, [1 / 3, 1 / 3, 1 / 3], atol=1e-3)
def test_multiplicative_weights_failure(): """Test that multiplicative weights fails""" game = gamegen.rock_paper_scissors(win=0.5) eqm = nash.multiplicative_weights_dist(game, [0.6, 0.3, 0.1]) assert regret.mixture_regret(game, eqm) > 0.1
def test_multiplicative_weights_bandit(): """Test that multiplicative weights bandit works""" game = gamegen.rock_paper_scissors(win=2) eqm = nash.multiplicative_weights_bandit(game, [0.6, 0.3, 0.1], max_iters=100000) assert np.allclose(eqm, [1 / 3, 1 / 3, 1 / 3], atol=0.1)
def test_nash_pure_one(): """Test nash with at_least_one""" sgame = gamegen.rock_paper_scissors() sgame_str = json.dumps(sgame.to_json()) with stdin(sgame_str), stderr() as err: assert run('nash', '--pure', '--style', 'best*'), err.getvalue()
def test_rock_paper_scissors(win, loss): """Test rock paper scissors""" game = gamegen.rock_paper_scissors(win, loss) assert game.strat_names == (('paper', 'rock', 'scissors'), ) assert np.allclose(game.get_payoffs([1, 1, 0]), [_first(loss), _first(win), 0])
def test_scarf(): """Test that scarfs algorithm works""" game = gamegen.rock_paper_scissors(win=0.5) eqm = nash.scarfs_algorithm(game, [0.6, 0.3, 0.1]) assert np.allclose(eqm, [1/3, 1/3, 1/3], atol=1e-4)
def test_multiplicative_weights_dist(): """Test that multiplicative weights dist works""" game = gamegen.rock_paper_scissors(win=2) eqm = nash.multiplicative_weights_dist(game, [0.6, 0.3, 0.1]) assert np.allclose(eqm, [1/3, 1/3, 1/3], atol=1e-3)
def test_noop_and_serial_nash(): """Test that no op works""" game = gamegen.rock_paper_scissors() req, eqm = nash._serial_nash_func(game, (nash._noop, [1/2, 0, 1/2], True)) # pylint: disable=protected-access assert np.allclose(eqm, [1/2, 0, 1/2]) assert req
def test_fictitious_play_convergence(): """Test that fictitious play converges""" game = gamegen.rock_paper_scissors(win=2) eqm = nash.fictitious_play(game, [0.3, 0.4, 0.3], converge_thresh=1e-3) # pylint: disable=unexpected-keyword-arg assert np.allclose(eqm, [1/3, 1/3, 1/3], atol=1e-3)
def test_fictitious_play(): """Test that fictitious play works""" game = gamegen.rock_paper_scissors(win=2) eqm = nash.fictitious_play(game, [0.6, 0.3, 0.1], max_iters=10000) # pylint: disable=unexpected-keyword-arg assert np.allclose(eqm, [1/3, 1/3, 1/3], atol=1e-4)
def test_minreg_roshambo(): game = gamegen.rock_paper_scissors() eqm = nash.min_regret_profile(game) assert np.all(np.sort(eqm) == [0, 0, 2]), \ "min regret profile was not rr, pp, or ss"
def test_scarf(): """Test that scarfs algorithm works""" game = gamegen.rock_paper_scissors(win=0.5) eqm = nash.scarfs_algorithm(game, [0.6, 0.3, 0.1]) assert np.allclose(eqm, [1 / 3, 1 / 3, 1 / 3], atol=1e-4)
def test_minreg_rand_roshambo(): game = gamegen.rock_paper_scissors() eqm = nash.min_regret_rand_mixture(game, 20) assert regret.mixture_regret(game, eqm) < 2 + 1e-7, \ "Found a mixture with greater than maximum regret"