]> gitweb.michael.orlitzky.com - dunshire.git/blobdiff - test/symmetric_linear_game_test.py
Rename epsilon_scale() to tolerance_scale().
[dunshire.git] / test / symmetric_linear_game_test.py
index 887831a44a68aeae7e8b25514154cfbe53f0309c..b9c29fe68056f52da980443809e881ce6faa28ad 100644 (file)
@@ -42,12 +42,19 @@ class SymmetricLinearGameTest(TestCase): # pylint: disable=R0904
         self.assertTrue(abs(first - second) < options.ABS_TOL*modifier)
 
 
         self.assertTrue(abs(first - second) < options.ABS_TOL*modifier)
 
 
-    def test_solutions_dont_change(self):
+    def test_solutions_dont_change_orthant(self):
+        G = random_orthant_game()
+        self.assert_solutions_dont_change(G)
+
+    def test_solutions_dont_change_icecream(self):
+        G = random_icecream_game()
+        self.assert_solutions_dont_change(G)
+
+    def assert_solutions_dont_change(self, G):
         """
         If we solve the same problem twice, we should get
         the same answer both times.
         """
         """
         If we solve the same problem twice, we should get
         the same answer both times.
         """
-        G = random_orthant_game()
         soln1 = G.solution()
         soln2 = G.solution()
         p1_diff = norm(soln1.player1_optimal() - soln2.player1_optimal())
         soln1 = G.solution()
         soln2 = G.solution()
         p1_diff = norm(soln1.player1_optimal() - soln2.player1_optimal())
@@ -61,6 +68,54 @@ class SymmetricLinearGameTest(TestCase): # pylint: disable=R0904
         self.assertTrue(p1_close and p2_close and gv_close)
 
 
         self.assertTrue(p1_close and p2_close and gv_close)
 
 
+    def assert_player1_start_valid(self, G):
+        x = G.player1_start()['x']
+        s = G.player1_start()['s']
+        s1 = s[0:G.dimension()]
+        s2 = s[G.dimension():]
+        self.assert_within_tol(norm(G.A()*x - G.b()), 0)
+        self.assertTrue((s1, s2) in G.C())
+
+
+    def test_player1_start_valid_orthant(self):
+        """
+        Ensure that player one's starting point is in the orthant.
+        """
+        G = random_orthant_game()
+        self.assert_player1_start_valid(G)
+
+
+    def test_player1_start_valid_icecream(self):
+        """
+        Ensure that player one's starting point is in the ice-cream cone.
+        """
+        G = random_icecream_game()
+        self.assert_player1_start_valid(G)
+
+
+    def assert_player2_start_valid(self, G):
+        z = G.player2_start()['z']
+        z1 = z[0:G.dimension()]
+        z2 = z[G.dimension():]
+        self.assertTrue((z1, z2) in G.C())
+
+
+    def test_player2_start_valid_orthant(self):
+        """
+        Ensure that player two's starting point is in the orthant.
+        """
+        G = random_orthant_game()
+        self.assert_player2_start_valid(G)
+
+
+    def test_player2_start_valid_icecream(self):
+        """
+        Ensure that player two's starting point is in the ice-cream cone.
+        """
+        G = random_icecream_game()
+        self.assert_player2_start_valid(G)
+
+
     def test_condition_lower_bound(self):
         """
         Ensure that the condition number of a game is greater than or
     def test_condition_lower_bound(self):
         """
         Ensure that the condition number of a game is greater than or
@@ -82,9 +137,13 @@ class SymmetricLinearGameTest(TestCase): # pylint: disable=R0904
         of the game by the same number.
         """
         (alpha, H) = random_nn_scaling(G)
         of the game by the same number.
         """
         (alpha, H) = random_nn_scaling(G)
-        value1 = G.solution().game_value()
-        value2 = H.solution().game_value()
-        modifier = 4*max(abs(alpha), 1)
+        soln1 = G.solution()
+        soln2 = H.solution()
+        value1 = soln1.game_value()
+        value2 = soln2.game_value()
+        modifier1 = G.tolerance_scale(soln1)
+        modifier2 = H.tolerance_scale(soln2)
+        modifier = max(modifier1, modifier2)
         self.assert_within_tol(alpha*value1, value2, modifier)
 
 
         self.assert_within_tol(alpha*value1, value2, modifier)
 
 
@@ -123,7 +182,7 @@ class SymmetricLinearGameTest(TestCase): # pylint: disable=R0904
         (alpha, H) = random_translation(G)
         value2 = H.solution().game_value()
 
         (alpha, H) = random_translation(G)
         value2 = H.solution().game_value()
 
-        modifier = 4*max(abs(alpha), 1)
+        modifier = G.tolerance_scale(soln1)
         self.assert_within_tol(value1 + alpha, value2, modifier)
 
         # Make sure the same optimal pair works.
         self.assert_within_tol(value1 + alpha, value2, modifier)
 
         # Make sure the same optimal pair works.
@@ -166,14 +225,12 @@ class SymmetricLinearGameTest(TestCase): # pylint: disable=R0904
         y_bar = soln1.player2_optimal()
         soln2 = H.solution()
 
         y_bar = soln1.player2_optimal()
         soln2 = H.solution()
 
-        # The modifier of 4 is because each could be off by 2*ABS_TOL,
-        # which is how far apart the primal/dual objectives have been
-        # observed being.
-        self.assert_within_tol(-soln1.game_value(), soln2.game_value(), 4)
+        mod = G.tolerance_scale(soln1)
+        self.assert_within_tol(-soln1.game_value(), soln2.game_value(), mod)
 
         # Make sure the switched optimal pair works. Since x_bar and
         # y_bar come from G, we use the same modifier.
 
         # Make sure the switched optimal pair works. Since x_bar and
         # y_bar come from G, we use the same modifier.
-        self.assert_within_tol(soln2.game_value(), H.payoff(y_bar, x_bar), 4)
+        self.assert_within_tol(soln2.game_value(), H.payoff(y_bar, x_bar), mod)
 
 
 
 
 
 
@@ -208,13 +265,9 @@ class SymmetricLinearGameTest(TestCase): # pylint: disable=R0904
         ip1 = inner_product(y_bar, G.L()*x_bar - value*G.e1())
         ip2 = inner_product(value*G.e2() - G.L().trans()*y_bar, x_bar)
 
         ip1 = inner_product(y_bar, G.L()*x_bar - value*G.e1())
         ip2 = inner_product(value*G.e2() - G.L().trans()*y_bar, x_bar)
 
-        # Huh.. well, y_bar and x_bar can each be epsilon away, but
-        # x_bar is scaled by L, so that's (norm(L) + 1), and then
-        # value could be off by epsilon, so that's another norm(e1) or
-        # norm(e2). On the other hand, this test seems to pass most of
-        # the time even with a modifier of one. How about.. four?
-        self.assert_within_tol(ip1, 0, 4)
-        self.assert_within_tol(ip2, 0, 4)
+        modifier = G.tolerance_scale(soln)
+        self.assert_within_tol(ip1, 0, modifier)
+        self.assert_within_tol(ip2, 0, modifier)
 
 
     def test_orthogonality_orthant(self):
 
 
     def test_orthogonality_orthant(self):
@@ -270,11 +323,9 @@ class SymmetricLinearGameTest(TestCase): # pylint: disable=R0904
             negative_stable = all([eig < options.ABS_TOL for eig in eigs])
             self.assertTrue(negative_stable)
 
             negative_stable = all([eig < options.ABS_TOL for eig in eigs])
             self.assertTrue(negative_stable)
 
-        # The dual game's value should always equal the primal's.
-        # The modifier of 4 is because even though the games are dual,
-        # CVXOPT doesn't know that, and each could be off by 2*ABS_TOL.
         dualsoln = G.dual().solution()
         dualsoln = G.dual().solution()
-        self.assert_within_tol(dualsoln.game_value(), soln.game_value(), 4)
+        mod = G.tolerance_scale(soln)
+        self.assert_within_tol(dualsoln.game_value(), soln.game_value(), mod)
 
 
     def test_lyapunov_orthant(self):
 
 
     def test_lyapunov_orthant(self):