blob: e0a8f616412624c199bed277f841af71b97e9962 [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
Ravago Jones26f7ad02021-02-05 15:45:59 -080011
brians343bc112013-02-10 01:53:46 +000012def MakePoint(*args):
Austin Schuh5ea48472021-02-02 20:46:41 -080013 """Makes a point from a set of arguments."""
14 return numpy.matrix([[arg] for arg in args])
brians343bc112013-02-10 01:53:46 +000015
Ravago Jones26f7ad02021-02-05 15:45:59 -080016
brians343bc112013-02-10 01:53:46 +000017class TestHPolytope(unittest.TestCase):
Ravago Jones5127ccc2022-07-31 16:32:45 -070018
Austin Schuh5ea48472021-02-02 20:46:41 -080019 def setUp(self):
20 """Builds a simple box polytope."""
Ravago Jones26f7ad02021-02-05 15:45:59 -080021 self.H = numpy.matrix([[1, 0], [-1, 0], [0, 1], [0, -1]])
22 self.k = numpy.matrix([[12], [12], [12], [12]])
Austin Schuh5ea48472021-02-02 20:46:41 -080023 self.p = polytope.HPolytope(self.H, self.k)
brians343bc112013-02-10 01:53:46 +000024
Austin Schuh5ea48472021-02-02 20:46:41 -080025 def test_Hk(self):
26 """Tests that H and k are saved correctly."""
27 assert_array_equal(self.p.H, self.H)
28 assert_array_equal(self.p.k, self.k)
brians343bc112013-02-10 01:53:46 +000029
Austin Schuh5ea48472021-02-02 20:46:41 -080030 def test_IsInside(self):
31 """Tests IsInside for various points."""
32 inside_points = [
Ravago Jones26f7ad02021-02-05 15:45:59 -080033 MakePoint(0, 0),
34 MakePoint(6, 6),
35 MakePoint(12, 6),
36 MakePoint(-6, 10)
37 ]
Austin Schuh5ea48472021-02-02 20:46:41 -080038 outside_points = [
Ravago Jones26f7ad02021-02-05 15:45:59 -080039 MakePoint(14, 0),
40 MakePoint(-14, 0),
41 MakePoint(0, 14),
42 MakePoint(0, -14),
43 MakePoint(14, -14)
44 ]
brians343bc112013-02-10 01:53:46 +000045
Austin Schuh5ea48472021-02-02 20:46:41 -080046 for inside_point in inside_points:
Ravago Jones5127ccc2022-07-31 16:32:45 -070047 self.assertTrue(self.p.IsInside(inside_point),
48 msg='Point is' + str(inside_point))
brians343bc112013-02-10 01:53:46 +000049
Austin Schuh5ea48472021-02-02 20:46:41 -080050 for outside_point in outside_points:
Ravago Jones5127ccc2022-07-31 16:32:45 -070051 self.assertFalse(self.p.IsInside(outside_point),
52 msg='Point is' + str(outside_point))
brians343bc112013-02-10 01:53:46 +000053
Austin Schuh5ea48472021-02-02 20:46:41 -080054 def AreVertices(self, p, vertices):
55 """Checks that all the vertices are on corners of the set."""
56 for i in range(vertices.shape[0]):
57 # Check that all the vertices have the correct number of active
58 # constraints.
Ravago Jones26f7ad02021-02-05 15:45:59 -080059 lmda = p.H * vertices[i, :].T - p.k
Austin Schuh5ea48472021-02-02 20:46:41 -080060 num_active_constraints = 0
61 for j in range(lmda.shape[0]):
62 # Verify that the constraints are either active, or not violated.
63 if numpy.abs(lmda[j, 0]) <= 1e-9:
64 num_active_constraints += 1
65 else:
66 self.assertLessEqual(lmda[j, 0], 0.0)
brians343bc112013-02-10 01:53:46 +000067
Austin Schuh5ea48472021-02-02 20:46:41 -080068 self.assertEqual(p.ndim, num_active_constraints)
brians343bc112013-02-10 01:53:46 +000069
Austin Schuh5ea48472021-02-02 20:46:41 -080070 def HasSamePoints(self, expected, actual):
71 """Verifies that the points in expected are in actual."""
72 found_points = set()
73 self.assertEqual(expected.shape, actual.shape)
74 for index in range(expected.shape[0]):
75 expected_point = expected[index, :]
76 for actual_index in range(actual.shape[0]):
77 actual_point = actual[actual_index, :]
78 if numpy.abs(expected_point - actual_point).max() <= 1e-4:
79 found_points.add(actual_index)
80 break
brians343bc112013-02-10 01:53:46 +000081
Ravago Jones5127ccc2022-07-31 16:32:45 -070082 self.assertEqual(len(found_points),
83 actual.shape[0],
84 msg="Expected:\n" + str(expected) + "\nActual:\n" +
85 str(actual))
brians343bc112013-02-10 01:53:46 +000086
Austin Schuh5ea48472021-02-02 20:46:41 -080087 def test_Skewed_Nonsym_Vertices(self):
88 """Tests the vertices of a severely skewed space."""
Ravago Jones26f7ad02021-02-05 15:45:59 -080089 self.H = numpy.matrix([[10, -1], [-1, -1], [-1, 10], [10, 10]])
90 self.k = numpy.matrix([[2], [2], [2], [2]])
Austin Schuh5ea48472021-02-02 20:46:41 -080091 self.p = polytope.HPolytope(self.H, self.k)
92 vertices = self.p.Vertices()
93 self.AreVertices(self.p, vertices)
brians343bc112013-02-10 01:53:46 +000094
Austin Schuh5ea48472021-02-02 20:46:41 -080095 self.HasSamePoints(
Ravago Jones26f7ad02021-02-05 15:45:59 -080096 numpy.matrix([[0., 0.2], [0.2, 0.], [-2., 0.], [0., -2.]]),
Austin Schuh5ea48472021-02-02 20:46:41 -080097 vertices)
brians343bc112013-02-10 01:53:46 +000098
Austin Schuh5ea48472021-02-02 20:46:41 -080099 def test_Vertices_Nonsym(self):
100 """Tests the vertices of a nonsymetric space."""
Ravago Jones26f7ad02021-02-05 15:45:59 -0800101 self.k = numpy.matrix([[6], [12], [2], [10]])
Austin Schuh5ea48472021-02-02 20:46:41 -0800102 self.p = polytope.HPolytope(self.H, self.k)
103 vertices = self.p.Vertices()
104 self.AreVertices(self.p, vertices)
brians343bc112013-02-10 01:53:46 +0000105
Austin Schuh5ea48472021-02-02 20:46:41 -0800106 self.HasSamePoints(
Ravago Jones26f7ad02021-02-05 15:45:59 -0800107 numpy.matrix([[6., 2.], [6., -10.], [-12., -10.], [-12., 2.]]),
Austin Schuh5ea48472021-02-02 20:46:41 -0800108 vertices)
brians343bc112013-02-10 01:53:46 +0000109
Austin Schuh5ea48472021-02-02 20:46:41 -0800110 def test_Vertices(self):
111 """Tests the vertices of a nonsymetric space."""
Ravago Jones26f7ad02021-02-05 15:45:59 -0800112 self.HasSamePoints(
113 self.p.Vertices(),
114 numpy.matrix([[12., 12.], [12., -12.], [-12., -12.], [-12., 12.]]))
brians343bc112013-02-10 01:53:46 +0000115
Austin Schuh5ea48472021-02-02 20:46:41 -0800116 def test_concat(self):
117 """Tests that the concat function works for simple inputs."""
118 self.assertEqual(["asd", "qwe"],
119 list(
120 polytope._PiecewiseConcat(["a", "q"], ["s", "w"],
121 ["d", "e"])))
brians343bc112013-02-10 01:53:46 +0000122
Austin Schuh5ea48472021-02-02 20:46:41 -0800123 def test_str(self):
124 """Verifies that the str method works for the provided p."""
Ravago Jones26f7ad02021-02-05 15:45:59 -0800125 self.assertEqual(
126 '[[ 1 0] [[12] \n'
127 ' [-1 0] [[x0] <= [12] \n'
128 ' [ 0 1] [x1]] [12] \n'
129 ' [ 0 -1]] [12]] ', str(self.p))
brians343bc112013-02-10 01:53:46 +0000130
Austin Schuh5ea48472021-02-02 20:46:41 -0800131 def MakePWithDims(self, num_constraints, num_dims):
132 """Makes a zeroed out polytope with the correct size."""
133 self.p = polytope.HPolytope(
134 numpy.matrix(numpy.zeros((num_constraints, num_dims))),
135 numpy.matrix(numpy.zeros((num_constraints, 1))))
brians343bc112013-02-10 01:53:46 +0000136
Austin Schuh5ea48472021-02-02 20:46:41 -0800137 def test_few_constraints_odd_constraint_even_dims_str(self):
138 """Tests printing out the set with odd constraints and even dimensions."""
139 self.MakePWithDims(num_constraints=5, num_dims=2)
Ravago Jones26f7ad02021-02-05 15:45:59 -0800140 self.assertEqual(
141 '[[0. 0.] [[0.] \n'
142 ' [0. 0.] [[x0] [0.] \n'
143 ' [0. 0.] [x1]] <= [0.] \n'
144 ' [0. 0.] [0.] \n'
145 ' [0. 0.]] [0.]] ', str(self.p))
brians343bc112013-02-10 01:53:46 +0000146
Austin Schuh5ea48472021-02-02 20:46:41 -0800147 def test_few_constraints_odd_constraint_small_dims_str(self):
148 """Tests printing out the set with odd constraints and odd dimensions."""
149 self.MakePWithDims(num_constraints=5, num_dims=1)
Ravago Jones26f7ad02021-02-05 15:45:59 -0800150 self.assertEqual(
151 '[[0.] [[0.] \n'
152 ' [0.] [0.] \n'
153 ' [0.] [[x0]] <= [0.] \n'
154 ' [0.] [0.] \n'
155 ' [0.]] [0.]] ', str(self.p))
brians343bc112013-02-10 01:53:46 +0000156
Austin Schuh5ea48472021-02-02 20:46:41 -0800157 def test_few_constraints_odd_constraint_odd_dims_str(self):
158 """Tests printing out the set with odd constraints and odd dimensions."""
159 self.MakePWithDims(num_constraints=5, num_dims=3)
Ravago Jones26f7ad02021-02-05 15:45:59 -0800160 self.assertEqual(
161 '[[0. 0. 0.] [[0.] \n'
162 ' [0. 0. 0.] [[x0] [0.] \n'
163 ' [0. 0. 0.] [x1] <= [0.] \n'
164 ' [0. 0. 0.] [x2]] [0.] \n'
165 ' [0. 0. 0.]] [0.]] ', str(self.p))
brians343bc112013-02-10 01:53:46 +0000166
Austin Schuh5ea48472021-02-02 20:46:41 -0800167 def test_many_constraints_even_constraint_odd_dims_str(self):
168 """Tests printing out the set with even constraints and odd dimensions."""
169 self.MakePWithDims(num_constraints=2, num_dims=3)
Ravago Jones26f7ad02021-02-05 15:45:59 -0800170 self.assertEqual(
171 '[[0. 0. 0.] [[x0] [[0.] \n'
172 ' [0. 0. 0.]] [x1] <= [0.]] \n'
173 ' [x2]] ', str(self.p))
brians343bc112013-02-10 01:53:46 +0000174
175
176if __name__ == '__main__':
Austin Schuh5ea48472021-02-02 20:46:41 -0800177 unittest.main()