From c3c6bd1b0b4a5a8fed15e2d0de5ad981f4b3f2bb Mon Sep 17 00:00:00 2001 From: Daisuke Oyama Date: Sun, 4 Nov 2018 15:30:20 +0900 Subject: [PATCH 1/2] FIX: Disallow 0 actions --- quantecon/game_theory/normal_form_game.py | 2 ++ quantecon/game_theory/tests/test_normal_form_game.py | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/quantecon/game_theory/normal_form_game.py b/quantecon/game_theory/normal_form_game.py index 8313144f6..6df250df6 100644 --- a/quantecon/game_theory/normal_form_game.py +++ b/quantecon/game_theory/normal_form_game.py @@ -168,6 +168,8 @@ def __init__(self, payoff_array): if self.payoff_array.ndim == 0: raise ValueError('payoff_array must be an array_like') + if np.prod(self.payoff_array.shape) == 0: + raise ValueError('every player must have at least one action') self.num_opponents = self.payoff_array.ndim - 1 self.num_actions = self.payoff_array.shape[0] diff --git a/quantecon/game_theory/tests/test_normal_form_game.py b/quantecon/game_theory/tests/test_normal_form_game.py index a993b256e..e390757db 100644 --- a/quantecon/game_theory/tests/test_normal_form_game.py +++ b/quantecon/game_theory/tests/test_normal_form_game.py @@ -393,6 +393,11 @@ def test_player_repr(): # Invalid inputs # +@raises(ValueError) +def test_player_zero_actions(): + p = Player([[]]) + + @raises(ValueError) def test_normalformgame_invalid_input_players_shape_inconsistent(): p0 = Player(np.zeros((2, 3))) @@ -424,6 +429,11 @@ def test_normalformgame_invalid_input_payoff_profiles(): g = NormalFormGame(np.zeros((2, 2, 1))) +@raises(ValueError) +def test_normalformgame_zero_actions(): + g = NormalFormGame((2, 0)) + + # Utility functions # def test_pure2mixed(): From 281ce2cbca28ba7aa5161212c2e9350606b59aba Mon Sep 17 00:00:00 2001 From: Daisuke Oyama Date: Sun, 4 Nov 2018 16:56:29 +0900 Subject: [PATCH 2/2] FIX: is_dominated: Return False if num_actions == 1 --- quantecon/game_theory/normal_form_game.py | 2 ++ .../game_theory/tests/test_normal_form_game.py | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/quantecon/game_theory/normal_form_game.py b/quantecon/game_theory/normal_form_game.py index 6df250df6..8feb1b942 100644 --- a/quantecon/game_theory/normal_form_game.py +++ b/quantecon/game_theory/normal_form_game.py @@ -420,6 +420,8 @@ def is_dominated(self, action, tol=None, method=None): ind[action] = False D = payoff_array[ind] D -= payoff_array[action] + if D.shape[0] == 0: # num_actions == 1 + return False if self.num_opponents >= 2: D.shape = (D.shape[0], np.prod(D.shape[1:])) diff --git a/quantecon/game_theory/tests/test_normal_form_game.py b/quantecon/game_theory/tests/test_normal_form_game.py index e390757db..bd583ff30 100644 --- a/quantecon/game_theory/tests/test_normal_form_game.py +++ b/quantecon/game_theory/tests/test_normal_form_game.py @@ -376,6 +376,24 @@ def test_normalformgame_setitem_1p(): eq_(g.players[0].payoff_array[0], 10) +# Trivial cases with one action # + +class TestPlayer_1action: + def setUp(self): + """Setup a Player instance""" + self.payoffs = [[0, 1]] + self.player = Player(self.payoffs) + + def test_is_dominated(self): + for action in range(self.player.num_actions): + for method in LP_METHODS: + eq_(self.player.is_dominated(action, method=method), False) + + def test_dominated_actions(self): + for method in LP_METHODS: + eq_(self.player.dominated_actions(method=method), []) + + # Test __repr__ # def test_player_repr():