]> gitweb.michael.orlitzky.com - dunshire.git/commitdiff
Add the player2_start() method and some tests for it.
authorMichael Orlitzky <michael@orlitzky.com>
Fri, 11 Nov 2016 14:39:59 +0000 (09:39 -0500)
committerMichael Orlitzky <michael@orlitzky.com>
Sun, 13 Nov 2016 20:19:26 +0000 (15:19 -0500)
dunshire/games.py
test/symmetric_linear_game_test.py

index 77c83300a586e7e9f8a98a766d242f98738635f1..0a473915716de7f4be4ce7d99cbc64d87c960795 100644 (file)
@@ -846,6 +846,37 @@ class SymmetricLinearGame:
         return {'x': x, 's': s}
 
 
+    def player2_start(self):
+        """
+        Return a feasible starting point for player two.
+        """
+        q = self.e1() / (norm(self.e1()) ** 2)
+
+        # Compute the distance from p to the outside of K.
+        if isinstance(self.K(), NonnegativeOrthant):
+            # How far is it to a wall?
+            dist = min(list(self.e2()))
+        elif isinstance(self.K(), IceCream):
+            # How far is it to the boundary of the ball that defines
+            # the ice-cream cone at a given height? Now draw a
+            # 45-45-90 triangle and the shortest distance to the
+            # outside of the cone should be 1/sqrt(2) of that.
+            # It works in R^2, so it works everywhere, right?
+            height = self.e2()[0]
+            radius = norm(self.e2()[1:])
+            dist = (height - radius) / sqrt(2)
+        else:
+            raise NotImplementedError
+
+        omega = specnorm(self.L())/(dist*norm(self.e1()))
+        y = matrix([omega])
+        z2 = q
+        z1 = y*self.e2() - self.L().trans()*z2
+        z = matrix([z1,z2], (self.dimension()*2, 1))
+
+        return {'y': y, 'z': z}
+
+
     def solution(self):
         """
         Solve this linear game and return a :class:`Solution`.
index b6bd9b89abdbf9ebb10820c9701faee5fadd240c..6327592b1268429e53cc54df757b275b5e894ad5 100644 (file)
@@ -93,6 +93,29 @@ class SymmetricLinearGameTest(TestCase): # pylint: disable=R0904
         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