Beispiel #1
0
class TestNormalFormGame_3p:
    """Test the methods of NormalFormGame with three players"""
    def setUp(self):
        """Setup a NormalFormGame instance"""
        payoffs_2opponents = [[[3, 6], [4, 2]], [[1, 0], [5, 7]]]
        player = Player(payoffs_2opponents)
        self.g = NormalFormGame([player for i in range(3)])

    def test_getitem(self):
        assert_array_equal(self.g[0, 0, 1], [6, 4, 1])

    def test_delete_action(self):
        action_to_delete = 0
        for i, player in enumerate(self.g.players):
            g_new = self.g.delete_action(i, action_to_delete)
            actions_to_remain = \
                np.setdiff1d(np.arange(player.num_actions), action_to_delete)
            assert_array_equal(
                g_new.payoff_profile_array,
                self.g.payoff_profile_array.take(actions_to_remain, axis=i))

    def test_is_nash_pure(self):
        ok_(self.g.is_nash((0, 0, 0)))
        ok_(not self.g.is_nash((0, 0, 1)))

    def test_is_nash_mixed(self):
        p = (1 + np.sqrt(65)) / 16
        ok_(self.g.is_nash(([1 - p, p], [1 - p, p], [1 - p, p])))
Beispiel #2
0
class TestNormalFormGame_Asym2p:
    """Test the methods of NormalFormGame with asymmetric two players"""

    def setUp(self):
        """Setup a NormalFormGame instance"""
        self.BoS_bimatrix = np.array([[(3, 2), (1, 1)],
                                      [(0, 0), (2, 3)]])
        self.g = NormalFormGame(self.BoS_bimatrix)

    def test_getitem(self):
        action_profile = (1, 0)
        assert_array_equal(self.g[action_profile],
                           self.BoS_bimatrix[action_profile])

    def test_is_nash_pure(self):
        ok_(not self.g.is_nash((1, 0)))

    def test_is_nash_mixed(self):
        ok_(self.g.is_nash(([3/4, 1/4], [1/4, 3/4])))

    def test_payoff_arrays(self):
        assert_array_equal(
            self.g.payoff_arrays[0], self.BoS_bimatrix[:, :, 0]
        )
        assert_array_equal(
            self.g.payoff_arrays[1], self.BoS_bimatrix[:, :, 1].T
        )
    def setUp(self):
        self.game_dicts = []

        # Example from Abreu and Sannikov (2014)
        bimatrix = [[(16, 9), (3, 13), (0, 3)],
                    [(21, 1), (10, 4), (-1, 0)],
                    [(9, 0), (5, -4), (-5, -15)]]
        vertices = np.array([[7.33770472e+00, 1.09826253e+01],
                             [1.12568240e+00, 2.80000000e+00],
                             [7.33770472e+00, 4.44089210e-16],
                             [7.86308964e+00, 4.44089210e-16],
                             [1.97917977e+01, 2.80000000e+00],
                             [1.55630896e+01, 9.10000000e+00]])
        d = {'sg': NormalFormGame(bimatrix),
             'delta': 0.3,
             'vertices': vertices,
             'u': np.zeros(2)}
        self.game_dicts.append(d)

        # Prisoner's dilemma
        bimatrix = [[(9, 9), (1, 10)],
                    [(10, 1), (3, 3)]]
        vertices = np.array([[3.  ,   3.],
                             [9.75, 3.  ],
                             [9.  , 9.  ],
                             [3.  , 9.75]])
        d = {'sg': NormalFormGame(bimatrix),
             'delta': 0.9,
             'vertices': vertices,
             'u': np.array([3., 3.])}
        self.game_dicts.append(d)
Beispiel #4
0
def test_normalformgame_constant_payoffs():
    g = NormalFormGame((2, 2))

    ok_(g.is_nash((0, 0)))
    ok_(g.is_nash((0, 1)))
    ok_(g.is_nash((1, 0)))
    ok_(g.is_nash((1, 1)))
class TestNormalFormGame_3p:
    """Test the methods of NormalFormGame with three players"""

    def setUp(self):
        """Setup a NormalFormGame instance"""
        payoffs_2opponents = [[[3, 6],
                               [4, 2]],
                              [[1, 0],
                               [5, 7]]]
        player = Player(payoffs_2opponents)
        self.g = NormalFormGame([player for i in range(3)])

    def test_getitem(self):
        assert_array_equal(self.g[0, 0, 1], [6, 4, 1])

    def test_delete_action(self):
        action_to_delete = 0
        for i, player in enumerate(self.g.players):
            g_new = self.g.delete_action(i, action_to_delete)
            actions_to_remain = \
                np.setdiff1d(np.arange(player.num_actions), action_to_delete)
            assert_array_equal(
                g_new.payoff_profile_array,
                self.g.payoff_profile_array.take(actions_to_remain, axis=i)
            )

    def test_is_nash_pure(self):
        ok_(self.g.is_nash((0, 0, 0)))
        ok_(not self.g.is_nash((0, 0, 1)))

    def test_is_nash_mixed(self):
        p = (1 + np.sqrt(65)) / 16
        ok_(self.g.is_nash(([1 - p, p], [1 - p, p], [1 - p, p])))
Beispiel #6
0
class TestNormalFormGame_1p:
    """Test for trivial NormalFormGame with a single player"""
    def setUp(self):
        """Setup a NormalFormGame instance"""
        data = [[0], [1], [1]]
        self.g = NormalFormGame(data)

    def test_construction(self):
        """Trivial game: construction"""
        ok_(self.g.N == 1)
        assert_array_equal(self.g.players[0].payoff_array, [0, 1, 1])

    def test_getitem(self):
        """Trivial game: __getitem__"""
        eq_(self.g[0], 0)

    def test_delete_action(self):
        actions_to_delete = [1, 2]
        for i, player in enumerate(self.g.players):
            g_new = self.g.delete_action(i, actions_to_delete)
            actions_to_remain = \
                np.setdiff1d(np.arange(player.num_actions), actions_to_delete)
            assert_array_equal(
                g_new.payoff_profile_array,
                self.g.payoff_profile_array.take(actions_to_remain, axis=i))

    def test_is_nash_pure(self):
        """Trivial game: is_nash with pure action"""
        ok_(self.g.is_nash((1, )))
        ok_(not self.g.is_nash((0, )))

    def test_is_nash_mixed(self):
        """Trivial game: is_nash with mixed action"""
        ok_(self.g.is_nash(([0, 1 / 2, 1 / 2], )))
Beispiel #7
0
class TestNormalFormGame_1p:
    """Test for trivial NormalFormGame with a single player"""

    def setUp(self):
        """Setup a NormalFormGame instance"""
        data = [[0], [1], [1]]
        self.g = NormalFormGame(data)

    def test_construction(self):
        """Trivial game: construction"""
        ok_(self.g.N == 1)
        assert_array_equal(self.g.players[0].payoff_array, [0, 1, 1])

    def test_getitem(self):
        """Trivial game: __getitem__"""
        eq_(self.g[0], 0)

    def test_is_nash_pure(self):
        """Trivial game: is_nash with pure action"""
        ok_(self.g.is_nash((1,)))
        ok_(not self.g.is_nash((0,)))

    def test_is_nash_mixed(self):
        """Trivial game: is_nash with mixed action"""
        ok_(self.g.is_nash(([0, 1/2, 1/2],)))
Beispiel #8
0
    def setup(self):
        self.game_dicts = []

        # Matching Pennies game with no pure nash equilibrium
        MP_bimatrix = [[(1, -1), (-1, 1)], [(-1, 1), (1, -1)]]
        MP_NE = []

        # Prisoners' Dilemma game with one pure nash equilibrium
        PD_bimatrix = [[(1, 1), (-2, 3)], [(3, -2), (0, 0)]]
        PD_NE = [(1, 1)]

        # Battle of the Sexes game with two pure nash equilibria
        BoS_bimatrix = [[(3, 2), (1, 0)], [(0, 1), (2, 3)]]
        BoS_NE = [(0, 0), (1, 1)]

        # Unanimity Game with more than two players
        N = 4
        a, b = 1, 2
        g_Unanimity = NormalFormGame((2, ) * N)
        g_Unanimity[(0, ) * N] = (a, ) * N
        g_Unanimity[(1, ) * N] = (b, ) * N

        Unanimity_NE = [(0, ) * N]
        for k in range(2, N - 2 + 1):
            for ind in itertools.combinations(range(N), k):
                a = np.ones(N, dtype=int)
                a[list(ind)] = 0
                Unanimity_NE.append(tuple(a))
        Unanimity_NE.append((1, ) * N)

        for bimatrix, NE in zip([MP_bimatrix, PD_bimatrix, BoS_bimatrix],
                                [MP_NE, PD_NE, BoS_NE]):
            d = {'g': NormalFormGame(bimatrix), 'NEs': NE}
            self.game_dicts.append(d)
        self.game_dicts.append({'g': g_Unanimity, 'NEs': Unanimity_NE})
class TestNormalFormGame_1p:
    """Test for trivial NormalFormGame with a single player"""

    def setUp(self):
        """Setup a NormalFormGame instance"""
        data = [[0], [1], [1]]
        self.g = NormalFormGame(data)

    def test_construction(self):
        """Trivial game: construction"""
        ok_(self.g.N == 1)
        assert_array_equal(self.g.players[0].payoff_array, [0, 1, 1])

    def test_getitem(self):
        """Trivial game: __getitem__"""
        eq_(self.g[0], 0)

    def test_is_nash_pure(self):
        """Trivial game: is_nash with pure action"""
        ok_(self.g.is_nash((1,)))
        ok_(not self.g.is_nash((0,)))

    def test_is_nash_mixed(self):
        """Trivial game: is_nash with mixed action"""
        ok_(self.g.is_nash(([0, 1 / 2, 1 / 2],)))
Beispiel #10
0
class TestNormalFormGame_Asym2p:
    """Test the methods of NormalFormGame with asymmetric two players"""
    def setUp(self):
        """Setup a NormalFormGame instance"""
        self.BoS_bimatrix = np.array([[(3, 2), (1, 1)], [(0, 0), (2, 3)]])
        self.g = NormalFormGame(self.BoS_bimatrix)

    def test_getitem(self):
        action_profile = (1, 0)
        assert_array_equal(self.g[action_profile],
                           self.BoS_bimatrix[action_profile])

    def test_delete_action(self):
        action_to_delete = 0
        for i, player in enumerate(self.g.players):
            g_new = self.g.delete_action(i, action_to_delete)
            actions_to_remain = \
                np.setdiff1d(np.arange(player.num_actions), action_to_delete)
            assert_array_equal(
                g_new.payoff_profile_array,
                self.g.payoff_profile_array.take(actions_to_remain, axis=i))

    def test_is_nash_pure(self):
        ok_(not self.g.is_nash((1, 0)))

    def test_is_nash_mixed(self):
        ok_(self.g.is_nash(([3 / 4, 1 / 4], [1 / 4, 3 / 4])))

    def test_payoff_arrays(self):
        assert_array_equal(self.g.payoff_arrays[0], self.BoS_bimatrix[:, :, 0])
        assert_array_equal(self.g.payoff_arrays[1], self.BoS_bimatrix[:, :,
                                                                      1].T)
def test_normalformgame_constant_payoffs():
    g = NormalFormGame((2, 2))

    ok_(g.is_nash((0, 0)))
    ok_(g.is_nash((0, 1)))
    ok_(g.is_nash((1, 0)))
    ok_(g.is_nash((1, 1)))
Beispiel #12
0
 def setUp(self):
     """Setup a NormalFormGame instance"""
     payoffs_2opponents = [[[3, 6],
                            [4, 2]],
                           [[1, 0],
                            [5, 7]]]
     player = Player(payoffs_2opponents)
     self.g = NormalFormGame([player for i in range(3)])
Beispiel #13
0
def test_normalformgame_payoff_profile_array():
    nums_actions = (2, 3, 4)
    for N in range(1, len(nums_actions) + 1):
        payoff_arrays = [
            np.arange(np.prod(nums_actions[0:N])).reshape(nums_actions[i:N] +
                                                          nums_actions[0:i])
            for i in range(N)
        ]
        players = [Player(payoff_array) for payoff_array in payoff_arrays]
        g = NormalFormGame(players)
        g_new = NormalFormGame(g.payoff_profile_array)
        for player_new, payoff_array in zip(g_new.players, payoff_arrays):
            assert_array_equal(player_new.payoff_array, payoff_array)
Beispiel #14
0
class TestNormalFormGame_Asym2p:
    """Test the methods of NormalFormGame with asymmetric two players"""
    def setUp(self):
        """Setup a NormalFormGame instance"""
        matching_pennies_bimatrix = [[(1, -1), (-1, 1)], [(-1, 1), (1, -1)]]
        self.g = NormalFormGame(matching_pennies_bimatrix)

    def test_getitem(self):
        assert_array_equal(self.g[1, 0], [-1, 1])

    def test_is_nash_against_pure(self):
        ok_(not self.g.is_nash((0, 0)))

    def test_is_nash_against_mixed(self):
        ok_(self.g.is_nash(([1 / 2, 1 / 2], [1 / 2, 1 / 2])))
    def test_random_matrix(self):
        seed = 12345
        rng = np.random.default_rng(seed)
        size = (10, 15)
        A = rng.normal(size=size)
        v, x, y = minmax(A)

        for z in [x, y]:
            assert_((z >= 0).all())
            assert_allclose(z.sum(), 1)

        g = NormalFormGame((Player(A), Player(-A.T)))
        NE = lemke_howson(g)
        assert_allclose(v, NE[0] @ A @ NE[1])
        assert_(g.is_nash((x, y)))
Beispiel #16
0
class TestNormalFormGame_Sym2p:
    """Test the methods of NormalFormGame with symmetric two players"""
    def setUp(self):
        """Setup a NormalFormGame instance"""
        coordination_game_matrix = [[4, 0], [3, 2]]
        self.g = NormalFormGame(coordination_game_matrix)

    def test_getitem(self):
        assert_array_equal(self.g[0, 1], [0, 3])

    def test_is_nash_pure(self):
        ok_(self.g.is_nash((0, 0)))

    def test_is_nash_mixed(self):
        ok_(self.g.is_nash(([2 / 3, 1 / 3], [2 / 3, 1 / 3])))
    def setup(self):
        # From von Stengel 2007 in Algorithmic Game Theory
        bimatrix = [[(3, 3), (3, 2)], [(2, 2), (5, 6)], [(0, 3), (6, 1)]]
        g = NormalFormGame(bimatrix)

        # Original best response polytope for player 0
        vertices_P = np.array([
            [0, 0, 0],  # 0
            [1 / 3, 0, 0],  # a
            [2 / 7, 1 / 14, 0],  # b
            [0, 1 / 6, 0],  # c
            [0, 1 / 8, 1 / 4],  # d
            [0, 0, 1 / 3]  # e
        ])
        labelings_P = np.array([
            [0, 1, 2],  # 0
            [1, 2, 3],  # a
            [2, 3, 4],  # b
            [0, 2, 4],  # c
            [0, 3, 4],  # d
            [0, 1, 3]  # e
        ])

        # Sort rows lexicographically
        K = labelings_P.shape[1]
        ind = np.lexsort([labelings_P[:, K - k - 1] for k in range(K)])
        self.labelings_P = labelings_P[ind]
        self.vertices_P = vertices_P[ind]

        # Translated best response polytope for player 0
        self.brp0 = _BestResponsePolytope(g.players[1], idx=0)
Beispiel #18
0
def test_normalformgame_setitem_1p():
    g = NormalFormGame(2)

    eq_(g.N, 1)  # Number of players

    g[0] = 10  # Set payoff 10 for action 0
    eq_(g.players[0].payoff_array[0], 10)
class TestNormalFormGame_Asym2p:
    """Test the methods of NormalFormGame with asymmetric two players"""

    def setUp(self):
        """Setup a NormalFormGame instance"""
        matching_pennies_bimatrix = [[(1, -1), (-1, 1)], [(-1, 1), (1, -1)]]
        self.g = NormalFormGame(matching_pennies_bimatrix)

    def test_getitem(self):
        assert_array_equal(self.g[1, 0], [-1, 1])

    def test_is_nash_against_pure(self):
        ok_(not self.g.is_nash((0, 0)))

    def test_is_nash_against_mixed(self):
        ok_(self.g.is_nash(([1 / 2, 1 / 2], [1 / 2, 1 / 2])))
def test_lemke_howson_capping():
    bimatrix = [[(3, 3), (3, 2)], [(2, 2), (5, 6)], [(0, 3), (6, 1)]]
    g = NormalFormGame(bimatrix)
    m, n = g.nums_actions
    max_iter = 10**6  # big number

    for k in range(m + n):
        NE0, res0 = lemke_howson(g,
                                 init_pivot=k,
                                 max_iter=max_iter,
                                 capping=None,
                                 full_output=True)
        NE1, res1 = lemke_howson(g,
                                 init_pivot=k,
                                 max_iter=max_iter,
                                 capping=max_iter,
                                 full_output=True)
        for action0, action1 in zip(NE0, NE1):
            assert_allclose(action0, action1)
        eq_(res0.init, res1.init)

    init_pivot = 1
    max_iter = m + n
    NE, res = lemke_howson(g,
                           init_pivot=init_pivot,
                           max_iter=max_iter,
                           capping=1,
                           full_output=True)
    eq_(res.num_iter, max_iter)
    eq_(res.init, init_pivot - 1)
 def anti_coordination(N, v):
     payoff_array = np.empty((2, ) * N)
     payoff_array[0, :] = 1
     payoff_array[1, :] = 0
     payoff_array[1].flat[0] = v
     g = NormalFormGame((Player(payoff_array), ) * N)
     return g
    def setUp(self):
        def anti_coordination(N, v):
            payoff_array = np.empty((2, ) * N)
            payoff_array[0, :] = 1
            payoff_array[1, :] = 0
            payoff_array[1].flat[0] = v
            g = NormalFormGame((Player(payoff_array), ) * N)
            return g

        def p_star(N, v):
            # Unique symmetric NE mixed action: [p_star, 1-p_star]
            return 1 / (v**(1 / (N - 1)))

        def epsilon_nash_interval(N, v, epsilon):
            # Necessary, but not sufficient, condition: lb < p < ub
            lb = p_star(N, v) - epsilon / ((N - 1) * (v**(1 / (N - 1)) - 1))
            ub = p_star(N, v) + epsilon / (N - 1)
            return lb, ub

        self.game_dicts = []
        v = 2
        epsilon = 1e-5

        Ns = [2, 3, 4]
        for N in Ns:
            g = anti_coordination(N, v)
            lb, ub = epsilon_nash_interval(N, v, epsilon)
            d = {'g': g, 'epsilon': epsilon, 'lb': lb, 'ub': ub}
            self.game_dicts.append(d)

        self.bimatrix = [[(3, 3), (3, 2)], [(2, 2), (5, 6)], [(0, 3), (6, 1)]]
        self.g = NormalFormGame(self.bimatrix)
class TestNormalFormGame_Sym2p:
    """Test the methods of NormalFormGame with symmetric two players"""

    def setUp(self):
        """Setup a NormalFormGame instance"""
        coordination_game_matrix = [[4, 0], [3, 2]]
        self.g = NormalFormGame(coordination_game_matrix)

    def test_getitem(self):
        assert_array_equal(self.g[0, 1], [0, 3])

    def test_is_nash_pure(self):
        ok_(self.g.is_nash((0, 0)))

    def test_is_nash_mixed(self):
        ok_(self.g.is_nash(([2 / 3, 1 / 3], [2 / 3, 1 / 3])))
def test_best_response_selection_no_indptr():
    bimatrix = [[(3, 3), (3, 2)], [(2, 2), (5, 6)], [(0, 3), (6, 1)]]
    g = NormalFormGame(bimatrix)

    test_obj = _best_response_selection([1 / 3, 1 / 3, 1 / 3, 1 / 2, 1 / 2], g)
    expected_output = np.array([0., 1., 0., 0., 1.])

    assert_array_equal(test_obj, expected_output)
Beispiel #25
0
def test_normalformgame_payoff_profile_array_c_contiguous():
    nums_actions = (2, 3, 4)
    shape = nums_actions + (len(nums_actions), )
    payoff_profile_array = \
        np.arange(np.prod(shape)).reshape(shape)
    g = NormalFormGame(payoff_profile_array)
    for player in g.players:
        ok_(player.payoff_array.flags['C_CONTIGUOUS'])
Beispiel #26
0
def test_normalformgame_input_action_sizes():
    g = NormalFormGame((2, 3, 4))

    eq_(g.N, 3)  # Number of players

    assert_array_equal(g.players[0].payoff_array, np.zeros((2, 3, 4)))
    assert_array_equal(g.players[1].payoff_array, np.zeros((3, 4, 2)))
    assert_array_equal(g.players[2].payoff_array, np.zeros((4, 2, 3)))
Beispiel #27
0
def test_normalformgame_setitem():
    g = NormalFormGame((2, 2))
    g[0, 0] = (0, 10)
    g[0, 1] = (0, 10)
    g[1, 0] = (3, 5)
    g[1, 1] = (-2, 0)

    assert_array_equal(g.players[0].payoff_array, [[0, 0], [3, -2]])
    assert_array_equal(g.players[1].payoff_array, [[10, 5], [10, 0]])
Beispiel #28
0
class TestNormalFormGame_3p:
    """Test the methods of NormalFormGame with three players"""
    def setUp(self):
        """Setup a NormalFormGame instance"""
        payoffs_2opponents = [[[3, 6], [4, 2]], [[1, 0], [5, 7]]]
        player = Player(payoffs_2opponents)
        self.g = NormalFormGame([player for i in range(3)])

    def test_getitem(self):
        assert_array_equal(self.g[0, 0, 1], [6, 4, 1])

    def test_is_nash_pure(self):
        ok_(self.g.is_nash((0, 0, 0)))
        ok_(not self.g.is_nash((0, 0, 1)))

    def test_is_nash_mixed(self):
        p = (1 + np.sqrt(65)) / 16
        ok_(self.g.is_nash(([1 - p, p], [1 - p, p], [1 - p, p])))
Beispiel #29
0
def test_normalformgame_input_action_sizes_1p():
    g = NormalFormGame(2)

    eq_(g.N, 1)  # Number of players

    assert_array_equal(
        g.players[0].payoff_array,
        np.zeros(2)
    )
class TestNormalFormGame_3p:
    """Test the methods of NormalFormGame with three players"""

    def setUp(self):
        """Setup a NormalFormGame instance"""
        payoffs_2opponents = [[[3, 6], [4, 2]], [[1, 0], [5, 7]]]
        player = Player(payoffs_2opponents)
        self.g = NormalFormGame([player for i in range(3)])

    def test_getitem(self):
        assert_array_equal(self.g[0, 0, 1], [6, 4, 1])

    def test_is_nash_pure(self):
        ok_(self.g.is_nash((0, 0, 0)))
        ok_(not self.g.is_nash((0, 0, 1)))

    def test_is_nash_mixed(self):
        p = (1 + np.sqrt(65)) / 16
        ok_(self.g.is_nash(([1 - p, p], [1 - p, p], [1 - p, p])))
    def setUp(self):
        self.game_dicts = []

        # From von Stengel 2007 in Algorithmic Game Theory
        bimatrix = [[(3, 3), (3, 2)], [(2, 2), (5, 6)], [(0, 3), (6, 1)]]
        NEs_dict = {
            0: ([1, 0, 0], [1, 0]),
            1: ([0, 1 / 3, 2 / 3], [1 / 3, 2 / 3])
        }  # init_pivot: NE
        d = {'g': NormalFormGame(bimatrix), 'NEs_dict': NEs_dict}
        self.game_dicts.append(d)
Beispiel #32
0
    def setUp(self):
        self.game_dicts = []

        # From von Stengel 2007 in Algorithmic Game Theory
        bimatrix = [[(3, 3), (3, 2)], [(2, 2), (5, 6)], [(0, 3), (6, 1)]]
        d = {
            'g':
            NormalFormGame(bimatrix),
            'NEs': [([1, 0, 0], [1, 0]), ([4 / 5, 1 / 5, 0], [2 / 3, 1 / 3]),
                    ([0, 1 / 3, 2 / 3], [1 / 3, 2 / 3])]
        }
        self.game_dicts.append(d)

        # Degenerate game
        # NEs ([0, p, 1-p], [1/2, 1/2]), 0 <= p <= 1, are not detected.
        bimatrix = [[(1, 1), (-1, 0)], [(-1, 0), (1, 0)], [(0, 0), (0, 0)]]
        d = {
            'g': NormalFormGame(bimatrix),
            'NEs': [([1, 0, 0], [1, 0]), ([0, 1, 0], [0, 1])]
        }
        self.game_dicts.append(d)
Beispiel #33
0
    def test_tol(self):
        # Prisoners' Dilemma game with one NE and one epsilon NE
        epsilon = 1e-08

        PD_bimatrix = [[(1, 1), (-2, 1 + epsilon)], [(1 + epsilon, -2),
                                                     (0, 0)]]

        NEs = [(1, 1)]
        epsilon_NEs = [(1, 1), (0, 0)]

        g = NormalFormGame(PD_bimatrix)
        for tol, answer in zip([0, epsilon], [NEs, epsilon_NEs]):
            assert_(sorted(pure_nash_brute(g, tol=tol)) == sorted(answer))
    def setUp(self):
        self.game_dicts = []

        # From von Stengel 2007 in Algorithmic Game Theory
        bimatrix = [[(3, 3), (3, 3)], [(2, 2), (5, 6)], [(0, 3), (6, 1)]]
        NEs_dict = {0: ([0, 1 / 3, 2 / 3], [1 / 3, 2 / 3])}
        d = {
            'g': NormalFormGame(bimatrix),
            'NEs_dict': NEs_dict,
            'converged': True
        }
        self.game_dicts.append(d)

        # == Examples of cycles by "ad hoc" tie breaking rules == #

        # Example where tie breaking that picks the variable with
        # the smallest row index in the tableau leads to cycling
        A = np.array([[0, 0, 0], [0, 1, 1], [1, 1, 0]])
        B = np.array([[1, 0, 1], [1, 1, 0], [0, 0, 2]])
        NEs_dict = {0: ([0, 2 / 3, 1 / 3], [0, 1, 0])}
        d = {
            'g': NormalFormGame((Player(A), Player(B))),
            'NEs_dict': NEs_dict,
            'converged': True
        }
        self.game_dicts.append(d)

        # Example where tie breaking that picks the variable with
        # the smallest variable index in the tableau leads to cycling
        perm = [2, 0, 1]
        C = A[:, perm]
        D = B[perm, :]
        NEs_dict = {0: ([0, 2 / 3, 1 / 3], [0, 0, 1])}
        d = {
            'g': NormalFormGame((Player(C), Player(D))),
            'NEs_dict': NEs_dict,
            'converged': True
        }
        self.game_dicts.append(d)
    def setup(self):
        self.game_dicts = []

        # From von Stengel 2007 in Algorithmic Game Theory
        bimatrix = [[(3, 3), (3, 2)], [(2, 2), (5, 6)], [(0, 3), (6, 1)]]
        d = {
            'g':
            NormalFormGame(bimatrix),
            'NEs': [([1, 0, 0], [1, 0]), ([4 / 5, 1 / 5, 0], [2 / 3, 1 / 3]),
                    ([0, 1 / 3, 2 / 3], [1 / 3, 2 / 3])]
        }
        self.game_dicts.append(d)

        # Degenerate game
        bimatrix = [[(3, 3), (3, 3)], [(2, 2), (5, 6)], [(0, 3), (6, 1)]]
        d = {
            'g':
            NormalFormGame(bimatrix),
            'NEs': [([1, 0, 0], [1, 0]), ([1, 0, 0], [2 / 3, 1 / 3]),
                    ([0, 1 / 3, 2 / 3], [1 / 3, 2 / 3])]
        }
        self.game_dicts.append(d)
class TestNormalFormGame_Asym2p:
    """Test the methods of NormalFormGame with asymmetric two players"""

    def setUp(self):
        """Setup a NormalFormGame instance"""
        self.BoS_bimatrix = np.array([[(3, 2), (1, 1)],
                                      [(0, 0), (2, 3)]])
        self.g = NormalFormGame(self.BoS_bimatrix)

    def test_getitem(self):
        action_profile = (1, 0)
        assert_array_equal(self.g[action_profile],
                           self.BoS_bimatrix[action_profile])

    def test_delete_action(self):
        action_to_delete = 0
        for i, player in enumerate(self.g.players):
            g_new = self.g.delete_action(i, action_to_delete)
            actions_to_remain = \
                np.setdiff1d(np.arange(player.num_actions), action_to_delete)
            assert_array_equal(
                g_new.payoff_profile_array,
                self.g.payoff_profile_array.take(actions_to_remain, axis=i)
            )

    def test_is_nash_pure(self):
        ok_(not self.g.is_nash((1, 0)))

    def test_is_nash_mixed(self):
        ok_(self.g.is_nash(([3/4, 1/4], [1/4, 3/4])))

    def test_payoff_arrays(self):
        assert_array_equal(
            self.g.payoff_arrays[0], self.BoS_bimatrix[:, :, 0]
        )
        assert_array_equal(
            self.g.payoff_arrays[1], self.BoS_bimatrix[:, :, 1].T
        )
def test_vertex_enumeration_qhull_options():
    # Degenerate game, player 0's actions reordered
    bimatrix = [[(0, 3), (6, 1)], [(2, 2), (5, 6)], [(3, 3), (3, 3)]]
    g = NormalFormGame(bimatrix)
    NEs_expected = [([0, 0, 1], [1, 0]), ([0, 0, 1], [2 / 3, 1 / 3]),
                    ([2 / 3, 1 / 3, 0], [1 / 3, 2 / 3])]
    qhull_options = 'QJ'
    NEs_computed = vertex_enumeration(g, qhull_options=qhull_options)
    assert_(len(NEs_computed) == len(NEs_expected))
    for NEs in (NEs_computed, NEs_expected):
        NEs.sort(key=lambda x: (list(x[1]), list(x[0])))
    for actions_computed, actions in zip(NEs_computed, NEs_expected):
        for action_computed, action in zip(actions_computed, actions):
            assert_allclose(action_computed, action, atol=1e-10)
class TestNormalFormGame_1p:
    """Test for trivial NormalFormGame with a single player"""

    def setUp(self):
        """Setup a NormalFormGame instance"""
        data = [[0], [1], [1]]
        self.g = NormalFormGame(data)

    def test_construction(self):
        """Trivial game: construction"""
        ok_(self.g.N == 1)
        assert_array_equal(self.g.players[0].payoff_array, [0, 1, 1])

    def test_getitem(self):
        """Trivial game: __getitem__"""
        eq_(self.g[0], 0)

    def test_delete_action(self):
        actions_to_delete = [1, 2]
        for i, player in enumerate(self.g.players):
            g_new = self.g.delete_action(i, actions_to_delete)
            actions_to_remain = \
                np.setdiff1d(np.arange(player.num_actions), actions_to_delete)
            assert_array_equal(
                g_new.payoff_profile_array,
                self.g.payoff_profile_array.take(actions_to_remain, axis=i)
            )

    def test_is_nash_pure(self):
        """Trivial game: is_nash with pure action"""
        ok_(self.g.is_nash((1,)))
        ok_(not self.g.is_nash((0,)))

    def test_is_nash_mixed(self):
        """Trivial game: is_nash with mixed action"""
        ok_(self.g.is_nash(([0, 1/2, 1/2],)))
 def setUp(self):
     """Setup a NormalFormGame instance"""
     data = [[0], [1], [1]]
     self.g = NormalFormGame(data)
 def setUp(self):
     """Setup a NormalFormGame instance"""
     self.BoS_bimatrix = np.array([[(3, 2), (1, 1)],
                                   [(0, 0), (2, 3)]])
     self.g = NormalFormGame(self.BoS_bimatrix)
 def setUp(self):
     """Setup a NormalFormGame instance"""
     matching_pennies_bimatrix = [[(1, -1), (-1, 1)], [(-1, 1), (1, -1)]]
     self.g = NormalFormGame(matching_pennies_bimatrix)
 def setUp(self):
     """Setup a NormalFormGame instance"""
     coordination_game_matrix = [[4, 0], [3, 2]]
     self.g = NormalFormGame(coordination_game_matrix)