blob: 68401c20e2d959c5cc0a06973b7882f5d28051c4 [file] [log] [blame]
Austin Schuh085eab92020-11-26 13:54:51 -08001#!/usr/bin/python3
brians343bc112013-02-10 01:53:46 +00002
3import numpy
4from numpy.testing import *
brians343bc112013-02-10 01:53:46 +00005import unittest
6
Brian Silverman9c89c0a2016-01-08 01:04:57 -08007import frc971.control_loops.python.polytope as polytope
8
brians343bc112013-02-10 01:53:46 +00009__author__ = 'Austin Schuh (austin.linux@gmail.com)'
10
11def MakePoint(*args):
Austin Schuh5ea48472021-02-02 20:46:41 -080012 """Makes a point from a set of arguments."""
13 return numpy.matrix([[arg] for arg in args])
brians343bc112013-02-10 01:53:46 +000014
15class TestHPolytope(unittest.TestCase):
Austin Schuh5ea48472021-02-02 20:46:41 -080016 def setUp(self):
17 """Builds a simple box polytope."""
18 self.H = numpy.matrix([[1, 0],
19 [-1, 0],
20 [0, 1],
21 [0, -1]])
22 self.k = numpy.matrix([[12],
23 [12],
24 [12],
25 [12]])
26 self.p = polytope.HPolytope(self.H, self.k)
brians343bc112013-02-10 01:53:46 +000027
Austin Schuh5ea48472021-02-02 20:46:41 -080028 def test_Hk(self):
29 """Tests that H and k are saved correctly."""
30 assert_array_equal(self.p.H, self.H)
31 assert_array_equal(self.p.k, self.k)
brians343bc112013-02-10 01:53:46 +000032
Austin Schuh5ea48472021-02-02 20:46:41 -080033 def test_IsInside(self):
34 """Tests IsInside for various points."""
35 inside_points = [
36 MakePoint(0, 0),
37 MakePoint(6, 6),
38 MakePoint(12, 6),
39 MakePoint(-6, 10)]
40 outside_points = [
41 MakePoint(14, 0),
42 MakePoint(-14, 0),
43 MakePoint(0, 14),
44 MakePoint(0, -14),
45 MakePoint(14, -14)]
brians343bc112013-02-10 01:53:46 +000046
Austin Schuh5ea48472021-02-02 20:46:41 -080047 for inside_point in inside_points:
48 self.assertTrue(self.p.IsInside(inside_point),
49 msg='Point is' + str(inside_point))
brians343bc112013-02-10 01:53:46 +000050
Austin Schuh5ea48472021-02-02 20:46:41 -080051 for outside_point in outside_points:
52 self.assertFalse(self.p.IsInside(outside_point),
53 msg='Point is' + str(outside_point))
brians343bc112013-02-10 01:53:46 +000054
Austin Schuh5ea48472021-02-02 20:46:41 -080055 def AreVertices(self, p, vertices):
56 """Checks that all the vertices are on corners of the set."""
57 for i in range(vertices.shape[0]):
58 # Check that all the vertices have the correct number of active
59 # constraints.
60 lmda = p.H * vertices[i,:].T - p.k
61 num_active_constraints = 0
62 for j in range(lmda.shape[0]):
63 # Verify that the constraints are either active, or not violated.
64 if numpy.abs(lmda[j, 0]) <= 1e-9:
65 num_active_constraints += 1
66 else:
67 self.assertLessEqual(lmda[j, 0], 0.0)
brians343bc112013-02-10 01:53:46 +000068
Austin Schuh5ea48472021-02-02 20:46:41 -080069 self.assertEqual(p.ndim, num_active_constraints)
brians343bc112013-02-10 01:53:46 +000070
Austin Schuh5ea48472021-02-02 20:46:41 -080071 def HasSamePoints(self, expected, actual):
72 """Verifies that the points in expected are in actual."""
73 found_points = set()
74 self.assertEqual(expected.shape, actual.shape)
75 for index in range(expected.shape[0]):
76 expected_point = expected[index, :]
77 for actual_index in range(actual.shape[0]):
78 actual_point = actual[actual_index, :]
79 if numpy.abs(expected_point - actual_point).max() <= 1e-4:
80 found_points.add(actual_index)
81 break
brians343bc112013-02-10 01:53:46 +000082
Austin Schuh5ea48472021-02-02 20:46:41 -080083 self.assertEqual(len(found_points), actual.shape[0],
84 msg="Expected:\n" + str(expected) + "\nActual:\n" + str(actual))
brians343bc112013-02-10 01:53:46 +000085
Austin Schuh5ea48472021-02-02 20:46:41 -080086 def test_Skewed_Nonsym_Vertices(self):
87 """Tests the vertices of a severely skewed space."""
88 self.H = numpy.matrix([[10, -1],
89 [-1, -1],
90 [-1, 10],
91 [10, 10]])
92 self.k = numpy.matrix([[2],
93 [2],
94 [2],
95 [2]])
96 self.p = polytope.HPolytope(self.H, self.k)
97 vertices = self.p.Vertices()
98 self.AreVertices(self.p, vertices)
brians343bc112013-02-10 01:53:46 +000099
Austin Schuh5ea48472021-02-02 20:46:41 -0800100 self.HasSamePoints(
101 numpy.matrix([[0., 0.2],
102 [0.2, 0.],
103 [-2., 0.],
104 [0., -2.]]),
105 vertices)
brians343bc112013-02-10 01:53:46 +0000106
Austin Schuh5ea48472021-02-02 20:46:41 -0800107 def test_Vertices_Nonsym(self):
108 """Tests the vertices of a nonsymetric space."""
109 self.k = numpy.matrix([[6],
110 [12],
111 [2],
112 [10]])
113 self.p = polytope.HPolytope(self.H, self.k)
114 vertices = self.p.Vertices()
115 self.AreVertices(self.p, vertices)
brians343bc112013-02-10 01:53:46 +0000116
Austin Schuh5ea48472021-02-02 20:46:41 -0800117 self.HasSamePoints(
118 numpy.matrix([[6., 2.],
119 [6., -10.],
120 [-12., -10.],
121 [-12., 2.]]),
122 vertices)
brians343bc112013-02-10 01:53:46 +0000123
Austin Schuh5ea48472021-02-02 20:46:41 -0800124 def test_Vertices(self):
125 """Tests the vertices of a nonsymetric space."""
126 self.HasSamePoints(self.p.Vertices(),
127 numpy.matrix([[12., 12.],
128 [12., -12.],
129 [-12., -12.],
130 [-12., 12.]]))
brians343bc112013-02-10 01:53:46 +0000131
Austin Schuh5ea48472021-02-02 20:46:41 -0800132 def test_concat(self):
133 """Tests that the concat function works for simple inputs."""
134 self.assertEqual(["asd", "qwe"],
135 list(
136 polytope._PiecewiseConcat(["a", "q"], ["s", "w"],
137 ["d", "e"])))
brians343bc112013-02-10 01:53:46 +0000138
Austin Schuh5ea48472021-02-02 20:46:41 -0800139 def test_str(self):
140 """Verifies that the str method works for the provided p."""
141 self.assertEqual('[[ 1 0] [[12] \n'
142 ' [-1 0] [[x0] <= [12] \n'
143 ' [ 0 1] [x1]] [12] \n'
144 ' [ 0 -1]] [12]] ',
145 str(self.p))
brians343bc112013-02-10 01:53:46 +0000146
Austin Schuh5ea48472021-02-02 20:46:41 -0800147 def MakePWithDims(self, num_constraints, num_dims):
148 """Makes a zeroed out polytope with the correct size."""
149 self.p = polytope.HPolytope(
150 numpy.matrix(numpy.zeros((num_constraints, num_dims))),
151 numpy.matrix(numpy.zeros((num_constraints, 1))))
brians343bc112013-02-10 01:53:46 +0000152
Austin Schuh5ea48472021-02-02 20:46:41 -0800153 def test_few_constraints_odd_constraint_even_dims_str(self):
154 """Tests printing out the set with odd constraints and even dimensions."""
155 self.MakePWithDims(num_constraints=5, num_dims=2)
Austin Schuh085eab92020-11-26 13:54:51 -0800156 self.assertEqual('[[0. 0.] [[0.] \n'
157 ' [0. 0.] [[x0] [0.] \n'
158 ' [0. 0.] [x1]] <= [0.] \n'
159 ' [0. 0.] [0.] \n'
160 ' [0. 0.]] [0.]] ',
Austin Schuh5ea48472021-02-02 20:46:41 -0800161 str(self.p))
brians343bc112013-02-10 01:53:46 +0000162
Austin Schuh5ea48472021-02-02 20:46:41 -0800163 def test_few_constraints_odd_constraint_small_dims_str(self):
164 """Tests printing out the set with odd constraints and odd dimensions."""
165 self.MakePWithDims(num_constraints=5, num_dims=1)
Austin Schuh085eab92020-11-26 13:54:51 -0800166 self.assertEqual('[[0.] [[0.] \n'
167 ' [0.] [0.] \n'
168 ' [0.] [[x0]] <= [0.] \n'
169 ' [0.] [0.] \n'
170 ' [0.]] [0.]] ',
Austin Schuh5ea48472021-02-02 20:46:41 -0800171 str(self.p))
brians343bc112013-02-10 01:53:46 +0000172
Austin Schuh5ea48472021-02-02 20:46:41 -0800173 def test_few_constraints_odd_constraint_odd_dims_str(self):
174 """Tests printing out the set with odd constraints and odd dimensions."""
175 self.MakePWithDims(num_constraints=5, num_dims=3)
Austin Schuh085eab92020-11-26 13:54:51 -0800176 self.assertEqual('[[0. 0. 0.] [[0.] \n'
177 ' [0. 0. 0.] [[x0] [0.] \n'
178 ' [0. 0. 0.] [x1] <= [0.] \n'
179 ' [0. 0. 0.] [x2]] [0.] \n'
180 ' [0. 0. 0.]] [0.]] ',
Austin Schuh5ea48472021-02-02 20:46:41 -0800181 str(self.p))
brians343bc112013-02-10 01:53:46 +0000182
Austin Schuh5ea48472021-02-02 20:46:41 -0800183 def test_many_constraints_even_constraint_odd_dims_str(self):
184 """Tests printing out the set with even constraints and odd dimensions."""
185 self.MakePWithDims(num_constraints=2, num_dims=3)
Austin Schuh085eab92020-11-26 13:54:51 -0800186 self.assertEqual('[[0. 0. 0.] [[x0] [[0.] \n'
187 ' [0. 0. 0.]] [x1] <= [0.]] \n'
188 ' [x2]] ',
Austin Schuh5ea48472021-02-02 20:46:41 -0800189 str(self.p))
brians343bc112013-02-10 01:53:46 +0000190
191
192if __name__ == '__main__':
Austin Schuh5ea48472021-02-02 20:46:41 -0800193 unittest.main()