Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TEST: Increase coverage on game_theory #343

Merged
merged 8 commits into from Oct 1, 2017
97 changes: 95 additions & 2 deletions quantecon/game_theory/tests/test_mclennan_tourky.py
Expand Up @@ -5,8 +5,12 @@

"""
import numpy as np
from nose.tools import ok_
from numpy.testing import assert_array_equal
from nose.tools import ok_, raises
from quantecon.game_theory import Player, NormalFormGame, mclennan_tourky
from quantecon.game_theory.mclennan_tourky import (
_best_response_selection, _flatten_action_profile, _is_epsilon_nash
)


class TestMclennanTourky():
Expand Down Expand Up @@ -54,13 +58,102 @@ def test_pure_nash(self):
NE, res = mclennan_tourky(d['g'], init=init, full_output=True)
ok_(res.num_iter==1)

def test_epsilon_nash(self):

class TestMclennanTourkyInvalidInputs():
def setUp(self):
self.bimatrix = [[(3, 3), (3, 2)],
[(2, 2), (5, 6)],
[(0, 3), (6, 1)]]
self.g = NormalFormGame(self.bimatrix)

@raises(TypeError)
def test_mclennan_tourky_invalid_g(self):
mclennan_tourky(self.bimatrix)

@raises(TypeError)
def test_mclennan_tourky_invalid_init_type(self):
mclennan_tourky(self.g, 1)

@raises(ValueError)
def test_mclennan_tourky_invalid_init_length(self):
mclennan_tourky(self.g, [1])


class TestEpsilonNash():
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)

def test_epsilon_nash_with_full_output(self):
for d in self.game_dicts:
NE, res = \
mclennan_tourky(d['g'], epsilon=d['epsilon'], full_output=True)
for i in range(d['g'].N):
ok_(d['lb'] < NE[i][0] < d['ub'])

def test_epsilon_nash_without_full_output(self):
for d in self.game_dicts:
NE = mclennan_tourky(d['g'], epsilon=d['epsilon'],
full_output=False)
for i in range(d['g'].N):
ok_(d['lb'] < NE[i][0] < d['ub'])

def test_is_epsilon_nash_no_indptr(self):
ok_(_is_epsilon_nash([1., 0., 0., 1., 0.], self.g, 1e-5))


def test_flatten_action_profile():
unflattened_actions = [[1/3, 1/3, 1/3], [1/2, 1/2]]
flattened_actions = [1/3, 1/3, 1/3, 1/2, 1/2]
test_obj = _flatten_action_profile(unflattened_actions, [0, 3, 5])
assert_array_equal(test_obj, flattened_actions)


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)


if __name__ == '__main__':
import sys
Expand Down
10 changes: 9 additions & 1 deletion quantecon/game_theory/tests/test_support_enumeration.py
Expand Up @@ -6,7 +6,7 @@
"""
import numpy as np
from numpy.testing import assert_allclose
from nose.tools import eq_
from nose.tools import eq_, raises
from quantecon.util import check_random_state
from quantecon.game_theory import Player, NormalFormGame, support_enumeration

Expand Down Expand Up @@ -71,6 +71,14 @@ def test_no_error_skew_sym(self):
NEs = support_enumeration(g)


@raises(TypeError)
def test_support_enumeration_invalid_g():
bimatrix = [[(3, 3), (3, 2)],
[(2, 2), (5, 6)],
[(0, 3), (6, 1)]]
support_enumeration(bimatrix)


if __name__ == '__main__':
import sys
import nose
Expand Down
19 changes: 18 additions & 1 deletion quantecon/game_theory/tests/test_vertex_enumeration.py
Expand Up @@ -6,7 +6,7 @@
"""
import numpy as np
from numpy.testing import assert_allclose, assert_array_equal
from nose.tools import eq_
from nose.tools import eq_, raises
from quantecon.game_theory import NormalFormGame, vertex_enumeration
from quantecon.game_theory.vertex_enumeration import _BestResponsePolytope

Expand Down Expand Up @@ -46,6 +46,14 @@ def test_vertex_enumeration(self):
assert_allclose(action_computed, action)


@raises(TypeError)
def test_vertex_enumeration_invalid_g():
bimatrix = [[(3, 3), (3, 2)],
[(2, 2), (5, 6)],
[(0, 3), (6, 1)]]
vertex_enumeration(bimatrix)


class TestBestResponsePolytope:
def setUp(self):
# From von Stengel 2007 in Algorithmic Game Theory
Expand Down Expand Up @@ -98,6 +106,15 @@ def test_best_response_polytope(self):
assert_allclose(vertices_computed, self.vertices_P, atol=1e-15)


@raises(TypeError)
def test_best_response_polytope_invalid_player_instance():
bimatrix = [[(3, 3), (3, 2)],
[(2, 2), (5, 6)],
[(0, 3), (6, 1)]]
g = NormalFormGame(bimatrix)
_BestResponsePolytope(g)


if __name__ == '__main__':
import sys
import nose
Expand Down