def test_power(self): x = Variable(3) y = Variable(3) self.assertFalse(x.is_constant()) self.assertTrue(x.is_affine()) self.assertTrue(x.is_quadratic()) with warnings.catch_warnings(): warnings.simplefilter("ignore") s = power(x.T*y, 0) self.assertTrue(s.is_constant()) self.assertTrue(s.is_affine()) self.assertTrue(s.is_quadratic()) t = power(x-y, 1) self.assertFalse(t.is_constant()) self.assertTrue(t.is_affine()) self.assertTrue(t.is_quadratic()) u = power(x+2*y, 2) self.assertFalse(u.is_constant()) self.assertFalse(u.is_affine()) self.assertTrue(u.is_quadratic()) self.assertTrue(u.is_dcp()) w = (x+2*y)**2 self.assertFalse(w.is_constant()) self.assertFalse(w.is_affine()) self.assertTrue(w.is_quadratic()) self.assertTrue(w.is_dcp())
def test_assign_var_value(self): """Test assigning a value to a variable. """ # Scalar variable. a = Variable() a.value = 1 self.assertEqual(a.value, 1) with self.assertRaises(Exception) as cm: a.value = [2, 1] self.assertEqual(str(cm.exception), "Invalid dimensions (2, 1) for Variable value.") # Test assigning None. a.value = 1 a.value = None assert a.value is None # Vector variable. x = Variable(2) x.value = [2, 1] self.assertItemsAlmostEqual(x.value, [2, 1]) # Matrix variable. A = Variable(3, 2) A.value = np.ones((3, 2)) self.assertItemsAlmostEqual(A.value, np.ones((3, 2))) # Test assigning negative val to nonnegative variable. x = NonNegative() with self.assertRaises(Exception) as cm: x.value = -2 self.assertEqual(str(cm.exception), "Invalid sign for NonNegative value.")
def test_partial_optimize_numeric_fn(self): x, y = Variable(1), Variable(1) xval = 4 # Solve the (simple) two-stage problem by "combining" the two stages (i.e., by solving a single linear program) p1 = Problem(Minimize(y), [xval + y >= 3]) p1.solve() # Solve the two-stage problem via partial_optimize constr = [y >= -100] p2 = Problem(Minimize(y), [x + y >= 3] + constr) g = cvxpy.partial_optimize(p2, [y], [x]) x.value = xval y.value = 42 constr[0].dual_variable.value = 42 result = g.value self.assertAlmostEqual(result, p1.value) self.assertAlmostEqual(y.value, 42) self.assertAlmostEqual(constr[0].dual_value, 42) # No variables optimized over. p2 = Problem(Minimize(y), [x + y >= 3]) g = cvxpy.partial_optimize(p2, [], [x, y]) x.value = xval y.value = 42 p2.constraints[0].dual_variable.value = 42 result = g.value self.assertAlmostEqual(result, y.value) self.assertAlmostEqual(y.value, 42) self.assertAlmostEqual(p2.constraints[0].dual_value, 42)
def test_consistency(self): """Test that variables and constraints keep a consistent order. """ import itertools num_solves = 4 vars_lists = [] ineqs_lists = [] for k in range(num_solves): sum = 0 constraints = [] for i in range(100): var = Variable(name=str(i)) sum += var constraints.append(var >= i) obj = Minimize(sum) p = Problem(obj, constraints) objective, constr_map, dims = p.canonicalize() all_ineq = itertools.chain(constr_map[s.EQ], constr_map[s.INEQ]) var_info = p._get_var_offsets(objective, all_ineq) sorted_vars, var_offsets, x_length = var_info vars_lists.append([int(v.name()) for v in sorted_vars]) ineqs_lists.append(constr_map[s.INEQ]) # Verify order of variables is consistent. for i in range(num_solves): self.assertEqual(range(100), vars_lists[i]) for i in range(num_solves): for idx, constr in enumerate(ineqs_lists[i]): var = constr.variables()[0] self.assertEqual(idx, int(var.name()))
def test_scipy_sparse(self): """Test scipy sparse matrices.""" # Constants. A = numpy.matrix( numpy.arange(8).reshape((4,2)) ) A = sp.csc_matrix(A) A = sp.eye(2).tocsc() key = (slice(0, 1, None), slice(None, None, None)) Aidx = intf.index(A, (slice(0, 2, None), slice(None, None, None))) Aidx = intf.index(Aidx, key) self.assertEqual(Aidx.shape, (1, 2)) self.assertEqual(Aidx[0,0], 1) self.assertEqual(Aidx[0,1], 0) # Linear ops. var = Variable(4, 2) A = numpy.matrix( numpy.arange(8).reshape((4,2)) ) A = sp.csc_matrix(A) B = sp.hstack([A, A]) self.assertExpression(var + A, (4, 2)) self.assertExpression(A + var, (4, 2)) self.assertExpression(B * var, (4, 2)) self.assertExpression(var - A, (4, 2)) self.assertExpression(A - A - var, (4, 2)) if PY35: self.assertExpression(var.__rmatmul__(B), (4,2))
def test_power(self): x = Variable(3) y = Variable(3) self.assertFalse(x.is_constant()) self.assertTrue(x.is_affine()) self.assertTrue(x.is_quadratic()) s = power(x.T*y, 0) self.assertTrue(s.is_constant()) self.assertTrue(s.is_affine()) self.assertTrue(s.is_quadratic()) t = power(x-y, 1) self.assertFalse(t.is_constant()) self.assertTrue(t.is_affine()) self.assertTrue(t.is_quadratic()) u = power(x+2*y, 2) self.assertFalse(u.is_constant()) self.assertFalse(u.is_affine()) self.assertTrue(u.is_quadratic()) self.assertTrue(u.is_dcp()) w = (x+2*y)**2 self.assertFalse(w.is_constant()) self.assertFalse(w.is_affine()) self.assertTrue(w.is_quadratic()) self.assertTrue(w.is_dcp())
def test_affine(self): """Test grad for affine atoms. """ expr = -self.a self.a.value = 2 self.assertAlmostEquals(expr.grad[self.a], -1) expr = -(self.x) self.x.value = [3,4] val = np.zeros((2,2)) - np.diag([1,1]) self.assertItemsAlmostEqual(expr.grad[self.x].todense(), val) expr = -(self.A) self.A.value = [[1,2], [3,4]] val = np.zeros((4,4)) - np.diag([1,1,1,1]) self.assertItemsAlmostEqual(expr.grad[self.A].todense(), val) expr = self.A[0,1] self.A.value = [[1,2], [3,4]] val = np.zeros((4,1)) val[2] = 1 self.assertItemsAlmostEqual(expr.grad[self.A].todense(), val) z = Variable(3) expr = vstack(self.x, z) self.x.value = [1,2] z.value = [1,2,3] val = np.zeros((2,5)) val[:,0:2] = np.eye(2) self.assertItemsAlmostEqual(expr.grad[self.x].todense(), val) val = np.zeros((3,5)) val[:,2:] = np.eye(3) self.assertItemsAlmostEqual(expr.grad[z].todense(), val)
def test_variable(self): x = Variable(2) y = Variable(2) assert y.name() != x.name() x = Variable(2, name='x') y = Variable() self.assertEqual(x.name(), 'x') self.assertEqual(x.size, (2,1)) self.assertEqual(y.size, (1,1)) self.assertEqual(x.curvature, u.Curvature.AFFINE) self.assertEqual(x.canonicalize()[0].size, (2,1)) self.assertEqual(x.canonicalize()[1], []) # Scalar variable coeff = self.a.coefficients(self.intf) self.assertEqual(coeff[self.a], 1) # Vector variable. coeffs = x.coefficients(self.intf) self.assertItemsEqual(coeffs.keys(), [x]) vec = coeffs[x] self.assertEqual(vec.size, (2,2)) self.assertEqual(list(vec), [1,0,0,1]) # Matrix variable. coeffs = self.A.coefficients(self.intf) self.assertItemsEqual(coeffs.keys(), [self.A]) mat = coeffs[self.A] self.assertEqual(mat.size, (2,2)) self.assertEqual(list(mat), [1,0,0,1])
def setUp(self): self.x = Variable(2, name='x') self.y = Variable(2, name='y') self.A = Variable(3,2, name='A') self.B = Variable(5,2, name='B') self.C = Constant([[1, 2], [1, 2]]) self.intf = intf.DEFAULT_INTERFACE
def setUp(self): self.x = Variable(2, name="x") self.y = Variable(2, name="y") self.A = Variable(3, 2, name="A") self.B = Variable(5, 2, name="B") self.C = Constant([[1, 2], [1, 2]]) self.intf = intf.DEFAULT_INTERFACE
def setUp(self): self.a = Variable() self.x = Variable(2, name='x') self.y = Variable(2, name='y') self.A = Variable(2,2) self.c = Constant(3) self.C = Constant([[1, 2], [1, 2]])
def setUp(self): self.x = Variable(2, name="x") self.y = Variable(2, name="y") self.A = Constant([[1, 2], [1, 2]]) self.xAff = AffObjective([self.x], [deque([self.x])], u.Shape(2, 1)) self.yAff = AffObjective([self.y], [deque([self.y])], u.Shape(2, 1)) self.constAff = AffObjective([self.A], [deque([self.A])], u.Shape(2, 2)) self.intf = intf.DEFAULT_INTERFACE
def setUp(self): self.a = Variable(name='a') self.b = Variable(name='b') self.x = Variable(2, name='x') self.y = Variable(3, name='y') self.z = Variable(2, name='z') self.A = Variable(2,2,name='A') self.B = Variable(2,2,name='B') self.C = Variable(3,2,name='C')
def test_var_copy(self): """Test the copy function for variable types. """ x = Variable(3, 4, name="x") y = x.copy() self.assertEqual(y.size, (3, 4)) self.assertEqual(y.name(), "x") x = Semidef(5, name="x") y = x.copy() self.assertEqual(y.size, (5, 5))
def setUp(self): self.a = Variable(name='a') self.x = Variable(2, name='x') self.y = Variable(3, name='y') self.z = Variable(2, name='z') self.A = Variable(2,2,name='A') self.B = Variable(2,2,name='B') self.C = Variable(3,2,name='C') self.intf = intf.DEFAULT_INTERFACE
def setUp(self): self.a = Variable(name="a") self.x = Variable(2, name="x") self.y = Variable(3, name="y") self.z = Variable(2, name="z") self.A = Variable(2, 2, name="A") self.B = Variable(2, 2, name="B") self.C = Variable(3, 2, name="C") self.intf = intf.DEFAULT_INTERFACE
def setUp(self): self.a = Variable(name="a") self.b = Variable(name="b") self.x = Variable(2, name="x") self.y = Variable(3, name="y") self.z = Variable(2, name="z") self.A = Variable(2, 2, name="A") self.B = Variable(2, 2, name="B") self.C = Variable(3, 2, name="C")
def test_matrix_multiplication(self): x = Variable(3, 5) y = Variable(3, 5) self.assertFalse(x.is_constant()) self.assertTrue(x.is_affine()) self.assertTrue(x.is_quadratic()) s = x.T*y self.assertFalse(s.is_constant()) self.assertFalse(s.is_affine()) self.assertTrue(s.is_quadratic()) self.assertFalse(s.is_dcp())
def test_partial_optimize_dcp(self): """Test DCP properties of partial optimize. """ # Evaluate the 1-norm in the usual way (i.e., in epigraph form). dims = 3 x, t = Variable(dims), Variable(dims) xval = [-5] * dims p2 = Problem(cvxpy.Minimize(sum_entries(t)), [-t <= x, x <= t]) g = cvxpy.partial_optimize(p2, [t], [x]) self.assertEquals(g.curvature, s.CONVEX) p2 = Problem(cvxpy.Maximize(sum_entries(t)), [-t <= x, x <= t]) g = cvxpy.partial_optimize(p2, [t], [x]) self.assertEquals(g.curvature, s.CONCAVE)
def test_variable(self): x = Variable(2) y = Variable(2) assert y.name() != x.name() x = Variable(2, name='x') y = Variable() self.assertEqual(x.name(), 'x') self.assertEqual(x.size, (2,1)) self.assertEqual(y.size, (1,1)) self.assertEqual(x.curvature, u.Curvature.AFFINE_KEY) self.assertEqual(x.canonical_form[0].size, (2,1)) self.assertEqual(x.canonical_form[1], []) # Scalar variable coeff = self.a.coefficients() self.assertEqual(coeff[self.a], [1]) # Vector variable. coeffs = x.coefficients() self.assertItemsEqual(coeffs.keys(), [x]) vec = coeffs[x][0] self.assertEqual(vec.size, (2,2)) self.assertEqual(vec[0,0], 1) # Matrix variable. coeffs = self.A.coefficients() self.assertItemsEqual(coeffs.keys(), [self.A]) self.assertEqual(len(coeffs[self.A]), 2) mat = coeffs[self.A][1] self.assertEqual(mat.size, (2,4)) self.assertEqual(mat[0,2], 1)
def test_max_sign(self): # One arg. self.assertEquals(max(1).sign, u.Sign.POSITIVE_KEY) self.assertEquals(max(-2).sign, u.Sign.NEGATIVE_KEY) self.assertEquals(max(Variable()).sign, u.Sign.UNKNOWN_KEY) self.assertEquals(max(0).sign, u.Sign.ZERO_KEY) # Two args. self.assertEquals(max(1, 2).sign, u.Sign.POSITIVE_KEY) self.assertEquals(max(1, Variable()).sign, u.Sign.POSITIVE_KEY) self.assertEquals(max(1, -2).sign, u.Sign.POSITIVE_KEY) self.assertEquals(max(1, 0).sign, u.Sign.POSITIVE_KEY) self.assertEquals(max(Variable(), 0).sign, u.Sign.POSITIVE_KEY) self.assertEquals(max(Variable(), Variable()).sign, u.Sign.UNKNOWN_KEY) self.assertEquals(max(Variable(), -2).sign, u.Sign.UNKNOWN_KEY) self.assertEquals(max(0, 0).sign, u.Sign.ZERO_KEY) self.assertEquals(max(0, -2).sign, u.Sign.ZERO_KEY) self.assertEquals(max(-3, -2).sign, u.Sign.NEGATIVE_KEY) # Many args. self.assertEquals( max(-2, Variable(), 0, -1, Variable(), 1).sign, u.Sign.POSITIVE_KEY)
def test_power(self): from fractions import Fraction for size in (1, 1), (3, 1), (2, 3): x = Variable(*size) y = Variable(*size) exp = x + y for p in 0, 1, 2, 3, 2.7, .67, -1, -2.3, Fraction(4, 5): atom = power(exp, p) self.assertEqual(atom.size, size) if p > 1 or p < 0: self.assertEqual(atom.curvature, s.CONVEX) elif p == 1: self.assertEqual(atom.curvature, s.AFFINE) elif p == 0: self.assertEqual(atom.curvature, s.CONSTANT) else: self.assertEqual(atom.curvature, s.CONCAVE) if p != 1: self.assertEqual(atom.sign, s.POSITIVE) # Test copy with args=None copy = atom.copy() self.assertTrue(type(copy) is type(atom)) # A new object is constructed, so copy.args == atom.args but copy.args # is not atom.args. self.assertEqual(copy.args, atom.args) self.assertFalse(copy.args is atom.args) self.assertEqual(copy.get_data(), atom.get_data()) # Test copy with new args copy = atom.copy(args=[self.y]) self.assertTrue(type(copy) is type(atom)) self.assertTrue(copy.args[0] is self.y) self.assertEqual(copy.get_data(), atom.get_data()) assert power(-1, 2).value == 1 with self.assertRaises(Exception) as cm: power(-1, 3).value self.assertEqual(str(cm.exception), "power(x, 3.0) cannot be applied to negative values.") with self.assertRaises(Exception) as cm: power(0, -1).value self.assertEqual(str(cm.exception), "power(x, -1.0) cannot be applied to negative or zero values.")
def test_sum_entries(self): """Test the sum_entries atom. """ self.assertEquals(sum_entries(1).sign, u.Sign.POSITIVE_KEY) self.assertEquals(sum_entries([1, -1]).sign, u.Sign.UNKNOWN_KEY) self.assertEquals( sum_entries([1, -1]).curvature, u.Curvature.CONSTANT_KEY) self.assertEquals(sum_entries(Variable(2)).sign, u.Sign.UNKNOWN_KEY) self.assertEquals(sum_entries(Variable(2)).size, (1, 1)) self.assertEquals( sum_entries(Variable(2)).curvature, u.Curvature.AFFINE_KEY) # Mixed curvature. mat = np.mat("1 -1") self.assertEquals( sum_entries(mat * square(Variable(2))).curvature, u.Curvature.UNKNOWN_KEY) # Test with axis argument. self.assertEquals(sum_entries(Variable(2), axis=0).size, (1, 1)) self.assertEquals(sum_entries(Variable(2), axis=1).size, (2, 1)) self.assertEquals(sum_entries(Variable(2, 3), axis=0).size, (1, 3)) self.assertEquals(sum_entries(Variable(2, 3), axis=1).size, (2, 1)) # Invalid axis. with self.assertRaises(Exception) as cm: sum_entries(self.x, axis=4) self.assertEqual(str(cm.exception), "Invalid argument for axis.")
def test_partial_optimize_stacked(self): # Minimize the 1-norm in the usual way dims = 3 x, t = Variable(dims), Variable(dims) p1 = Problem(Minimize(sum_entries(t)), [-t <= x, x <= t]) # Minimize the 1-norm via partial_optimize g = cvxpy.partial_optimize(p1, [t], [x]) g2 = cvxpy.partial_optimize(Problem(Minimize(g)), [x]) p2 = Problem(Minimize(g2)) p2.solve() p1.solve() self.assertAlmostEqual(p1.value, p2.value)
def test_matrix_multiplication(self): x = Variable(3, 5) y = Variable(3, 5) self.assertFalse(x.is_constant()) self.assertTrue(x.is_affine()) self.assertTrue(x.is_quadratic()) with warnings.catch_warnings(): warnings.simplefilter("ignore") s = x.T*y self.assertFalse(s.is_constant()) self.assertFalse(s.is_affine()) self.assertTrue(s.is_quadratic()) self.assertFalse(s.is_dcp())
def test_partial_optimize_numeric_fn(self): x, y = Variable(1), Variable(1) xval = 4 # Solve the (simple) two-stage problem by "combining" the two stages (i.e., by solving a single linear program) p1 = Problem(Minimize(y), [xval+y>=3]) p1.solve() # Solve the two-stage problem via partial_optimize p2 = Problem(Minimize(y), [x+y>=3]) g = cvxpy.partial_optimize(p2, [y], [x]) x.value = xval result = g.value self.assertAlmostEqual(result, p1.value)
def test_partial_optimize_numeric_fn(self): x,y = Variable(1), Variable(1) xval = 4 # Solve the (simple) two-stage problem by "combining" the two stages (i.e., by solving a single linear program) p1 = Problem(Minimize(y), [xval+y>=3]) p1.solve() # Solve the two-stage problem via partial_optimize p2 = Problem(Minimize(y), [x+y>=3]) g = partial_optimize(p2, [y], [x]) x.value = xval result = g.value self.assertAlmostEqual(result, p1.value)
def test_robust_svm(self): # Create problem data. m = 100 # num train points m_pos = math.floor(m / 2) m_neg = m - m_pos n = 2 # num dimensions mu_pos = 2 * numpy.ones(n) mu_neg = -2 * numpy.ones(n) sigma = 1 X = numpy.matrix( numpy.vstack((mu_pos + sigma * numpy.random.randn(m_pos, n), mu_neg + sigma * numpy.random.randn(m_neg, n)))) y = numpy.hstack((numpy.ones(m_pos), -1 * numpy.ones(m_neg))) C = 1 # regularization trade-off parameter ns = 50 eta = 0.1 # Create and solve optimization problem. w, b, xi = Variable(n), Variable(), NonNegative(m) constr = [] Sigma = 0.1 * numpy.eye(n) for i in range(m): mu = numpy.array(X[i])[0] x = NormalRandomVariable(mu, Sigma) chance = prob(-y[i] * (w.T * x + b) >= (xi[i] - 1), ns) constr += [chance <= eta] p = Problem(Minimize(norm(w, 2) + C * sum_entries(xi)), constr) p.solve(verbose=True) w_new = w.value b_new = b.value # Create and solve the canonical SVM problem. constr = [] for i in range(m): constr += [y[i] * (X[i] * w + b) >= (1 - xi[i])] p2 = Problem(Minimize(norm(w, 2) + C * sum_entries(xi)), constr) p2.solve() w_old = w.value b_old = b.value self.assert_feas(p)
def setUp(self): self.a = Variable(name='a') self.x = Variable(2, name='x') self.y = Variable(3, name='y') self.z = Variable(2, name='z') self.A = Variable(2, 2, name='A') self.B = Variable(2, 2, name='B') self.C = Variable(3, 2, name='C') self.intf = intf.DEFAULT_INTF
def test_quad_over_lin(self): x = Variable(3, 5) y = Variable(3, 5) z = Variable() s = quad_over_lin(x-y, z) self.assertFalse(s.is_constant()) self.assertFalse(s.is_affine()) self.assertFalse(s.is_quadratic()) self.assertTrue(s.is_dcp()) t = quad_over_lin(x+2*y, 5) self.assertFalse(t.is_constant()) self.assertFalse(t.is_affine()) self.assertTrue(t.is_quadratic()) self.assertTrue(t.is_dcp())
def test_non_quadratic(self): x = Variable() y = Variable() z = Variable() with warnings.catch_warnings(): warnings.simplefilter("ignore") with self.assertRaises(Exception) as cm: (x*y*z).is_quadratic() self.assertEqual(str(cm.exception), "Cannot multiply UNKNOWN and AFFINE.") s = max_entries(vstack(x, y, z))**2 self.assertFalse(s.is_quadratic()) t = max_entries(vstack(x**2, power(y, 2), z)) self.assertFalse(t.is_quadratic())
def test_partial_optimize_eval_1norm(self): # Evaluate the 1-norm in the usual way (i.e., in epigraph form). dims = 3 x, t = Variable(dims), Variable(dims) xval = [-5]*dims p1 = Problem(cvxpy.Minimize(sum_entries(t)), [-t <= xval, xval <= t]) p1.solve() # Minimize the 1-norm via partial_optimize. p2 = Problem(cvxpy.Minimize(sum_entries(t)), [-t <= x, x <= t]) g = cvxpy.partial_optimize(p2, [t], [x]) p3 = Problem(cvxpy.Minimize(g), [x == xval]) p3.solve() self.assertAlmostEqual(p1.value, p3.value) # Minimize the 1-norm using maximize. p2 = Problem(cvxpy.Maximize(sum_entries(-t)), [-t <= x, x <= t]) g = cvxpy.partial_optimize(p2, opt_vars=[t]) p3 = Problem(cvxpy.Maximize(g), [x == xval]) p3.solve() self.assertAlmostEqual(p1.value, -p3.value) # Try leaving out args. # Minimize the 1-norm via partial_optimize. p2 = Problem(cvxpy.Minimize(sum_entries(t)), [-t <= x, x <= t]) g = cvxpy.partial_optimize(p2, opt_vars=[t]) p3 = Problem(cvxpy.Minimize(g), [x == xval]) p3.solve() self.assertAlmostEqual(p1.value, p3.value) # Minimize the 1-norm via partial_optimize. g = cvxpy.partial_optimize(p2, dont_opt_vars=[x]) p3 = Problem(cvxpy.Minimize(g), [x == xval]) p3.solve() self.assertAlmostEqual(p1.value, p3.value) with self.assertRaises(Exception) as cm: g = cvxpy.partial_optimize(p2) self.assertEqual(str(cm.exception), "partial_optimize called with neither opt_vars nor dont_opt_vars.") with self.assertRaises(Exception) as cm: g = cvxpy.partial_optimize(p2, [], [x]) self.assertEqual(str(cm.exception), ("If opt_vars and new_opt_vars are both specified, " "they must contain all variables in the problem.") )
def setUp(self): self.a = Variable(name='a') self.b = Variable(name='b') self.c = Variable(name='c') self.x = Variable(2, name='x') self.y = Variable(3, name='y') self.z = Variable(2, name='z') self.A = Variable(2, 2, name='A') self.B = Variable(2, 2, name='B') self.C = Variable(3, 2, name='C')
def test_sum_entries(self): """Test the sum_entries atom. """ self.assertEquals(sum_entries(1).sign, u.Sign.POSITIVE_KEY) self.assertEquals(sum_entries([1, -1]).sign, u.Sign.UNKNOWN_KEY) self.assertEquals( sum_entries([1, -1]).curvature, u.Curvature.CONSTANT_KEY) self.assertEquals(sum_entries(Variable(2)).sign, u.Sign.UNKNOWN_KEY) self.assertEquals(sum_entries(Variable(2)).size, (1, 1)) self.assertEquals( sum_entries(Variable(2)).curvature, u.Curvature.AFFINE_KEY) # Mixed curvature. mat = np.mat("1 -1") self.assertEquals( sum_entries(mat * square(Variable(2))).curvature, u.Curvature.UNKNOWN_KEY)
def test_sum_squares(self): X = Variable(5, 4) P = np.asmatrix(np.random.randn(3, 5)) Q = np.asmatrix(np.random.randn(4, 7)) M = np.asmatrix(np.random.randn(3, 7)) y = P*X*Q + M self.assertFalse(y.is_constant()) self.assertTrue(y.is_affine()) self.assertTrue(y.is_quadratic()) self.assertTrue(y.is_dcp()) s = sum_squares(y) self.assertFalse(s.is_constant()) self.assertFalse(s.is_affine()) self.assertTrue(s.is_quadratic()) self.assertTrue(s.is_dcp()) # Frobenius norm squared is indeed quadratic # but can't show quadraticity using recursive rules t = norm(y, 'fro')**2 self.assertFalse(t.is_constant()) self.assertFalse(t.is_affine()) self.assertFalse(t.is_quadratic()) self.assertTrue(t.is_dcp())
def test_atom(): for atom_list, objective_type in atoms: for atom, obj_val in atom_list: for row in xrange(atom.size[0]): for col in xrange(atom.size[1]): for solver in [ECOS, SCS, CVXOPT]: # Atoms with Constant arguments. yield (run_atom, atom, Problem(objective_type(atom[row, col])), obj_val[row, col].value, solver) # Atoms with Variable arguments. variables = [] constraints = [] for idx, expr in enumerate(atom.subexpressions): # Special case for MulExpr because # can't multiply two variables. if (idx == 0 and isinstance(atom, MulExpression)): variables.append(expr) else: variables.append(Variable(*expr.size)) constraints.append(variables[-1] == expr) atom_func = atom.__class__ objective = objective_type( atom_func(*variables)[row, col]) yield (run_atom, atom, Problem(objective, constraints), obj_val[row, col].value, solver) # Atoms with Parameter arguments. parameters = [] for expr in atom.subexpressions: parameters.append(Parameter(*expr.size)) parameters[-1].value = expr.value objective = objective_type( atom_func(*parameters)[row, col]) yield (run_atom, atom, Problem(objective), obj_val[row, col].value, solver)
def test_value_at_risk(self): # Create problem data. n = numpy.random.randint(1, 10) pbar = numpy.random.randn(n) Sigma = numpy.eye(n) p = NormalRandomVariable(pbar, Sigma) o = numpy.ones((n, 1)) beta = 0.05 num_samples = 50 # Create and solve optimization problem. x = Variable(n) p1 = Problem(Minimize(-x.T * pbar), [ prob(-x.T * p >= 0, num_samples) <= beta, x.T * o == 1, x >= -0.1 ]) p1.solve() # Create and solve analytic form of optimization problem (as a check). p2 = Problem(Minimize(-x.T * pbar), [ x.T * pbar >= scipy.stats.norm.ppf(1 - beta) * norm2(sqrtm(Sigma) * x), x.T * o == 1, x >= -0.1 ]) p2.solve() tol = 0.1 if numpy.abs(p1.value - p2.value) < tol: self.assertAlmostEqual(1, 1) else: self.assertAlmostEqual(1, 0)
def test_add_expression(self): # Vectors c = Constant([2,2]) exp = self.x + c self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEqual(exp.sign, u.Sign.UNKNOWN_KEY) self.assertEqual(exp.canonical_form[0].size, (2,1)) self.assertEqual(exp.canonical_form[1], []) # self.assertEqual(exp.name(), self.x.name() + " + " + c.name()) self.assertEqual(exp.size, (2,1)) z = Variable(2, name='z') exp = exp + z + self.x with self.assertRaises(Exception) as cm: (self.x + self.y) self.assertEqual(str(cm.exception), "Incompatible dimensions (2, 1) (3, 1)") # Matrices exp = self.A + self.B self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEqual(exp.size, (2,2)) with self.assertRaises(Exception) as cm: (self.A + self.C) self.assertEqual(str(cm.exception), "Incompatible dimensions (2, 2) (3, 2)") with self.assertRaises(Exception) as cm: AddExpression([self.A, self.C]) self.assertEqual(str(cm.exception), "Incompatible dimensions (2, 2) (3, 2)") # Test that sum is flattened. exp = self.x + c + self.x self.assertEqual(len(exp.args), 3)
def test_pnorm(self): import numpy as np x = Variable(3, name='x') a = np.array([1.0, 2, 3]) for p in (1, 1.6, 1.2, 2, 1.99, 3, 3.7, np.inf): prob = Problem(Minimize(pnorm(x, p=p)), [x.T * a >= 1]) prob.solve() # formula is true for any a >= 0 with p > 1 if p == np.inf: x_true = np.ones_like(a) / sum(a) elif p == 1: # only works for the particular a = [1,2,3] x_true = np.array([0, 0, 1.0 / 3]) else: x_true = a**(1.0 / (p - 1)) / a.dot(a**(1.0 / (p - 1))) x_alg = np.array(x.value).flatten() self.assertTrue(np.allclose(x_alg, x_true, 1e-3)) self.assertTrue(np.allclose(prob.value, np.linalg.norm(x_alg, p))) self.assertTrue( np.allclose(np.linalg.norm(x_alg, p), pnorm(x_alg, p).value))
def test_sub_expression(self): # Vectors c = Constant([2, 2]) exp = self.x - c self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEqual(exp.sign, u.Sign.UNKNOWN_KEY) self.assertEqual(exp.canonical_form[0].size, (2, 1)) self.assertEqual(exp.canonical_form[1], []) # self.assertEqual(exp.name(), self.x.name() + " - " + Constant([2,2]).name()) self.assertEqual(exp.size, (2, 1)) z = Variable(2, name='z') exp = exp - z - self.x with self.assertRaises(Exception) as cm: (self.x - self.y) self.assertEqual(str(cm.exception), "Incompatible dimensions (2, 1) (3, 1)") # Matrices exp = self.A - self.B self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEqual(exp.size, (2, 2)) with self.assertRaises(Exception) as cm: (self.A - self.C) self.assertEqual(str(cm.exception), "Incompatible dimensions (2, 2) (3, 2)")
def test_atom(): for atom_list, objective_type in atoms: for atom, obj_val in atom_list: for row in xrange(atom.size[0]): for col in xrange(atom.size[1]): # Atoms with Constant arguments. yield run_atom, Problem(objective_type( atom[row, col])), obj_val[row, col].value # Atoms with Variable arguments. variables = [] constraints = [] for expr in atom.subexpressions: variables.append(Variable(*expr.size)) constraints.append(variables[-1] == expr) atom_func = atom.__class__ objective = objective_type(atom_func(*variables)[row, col]) yield run_atom, Problem(objective, constraints), obj_val[row, col].value # Atoms with Parameter arguments. parameters = [] for expr in atom.subexpressions: parameters.append(Parameter(*expr.size)) parameters[-1].value = expr.value objective = objective_type( atom_func(*parameters)[row, col]) yield run_atom, Problem(objective), obj_val[row, col].value
def test_partial_optimize_params(self): """Test partial optimize with parameters. """ x, y = Variable(1), Variable(1) gamma = Parameter() # Solve the (simple) two-stage problem by "combining" the two stages (i.e., by solving a single linear program) p1 = Problem(Minimize(x+y), [x+y>=gamma, y>=4, x>=5]) gamma.value = 3 p1.solve() # Solve the two-stage problem via partial_optimize p2 = Problem(Minimize(y), [x+y>=gamma, y>=4]) g = partial_optimize(p2, [y], [x]) p3 = Problem(Minimize(x+g), [x>=5]) p3.solve() self.assertAlmostEqual(p1.value, p3.value)
def test_atom(): for atom_list, objective_type in atoms: for atom, size, args, obj_val in atom_list: for row in range(size[0]): for col in range(size[1]): for solver in SOLVERS_TO_TRY: # Atoms with Constant arguments. const_args = [Constant(arg) for arg in args] yield (run_atom, atom, Problem( objective_type(atom(*const_args)[row, col])), obj_val[row, col].value, solver) # Atoms with Variable arguments. variables = [] constraints = [] for idx, expr in enumerate(args): variables.append(Variable(*intf.size(expr))) constraints.append(variables[-1] == expr) objective = objective_type(atom(*variables)[row, col]) yield (run_atom, atom, Problem(objective, constraints), obj_val[row, col].value, solver) # Atoms with Parameter arguments. parameters = [] for expr in args: parameters.append(Parameter(*intf.size(expr))) parameters[ -1].value = intf.DEFAULT_INTF.const_to_matrix( expr) objective = objective_type(atom(*parameters)[row, col]) yield (run_atom, atom, Problem(objective), obj_val[row, col].value, solver)
def test_indexing(self): # Vector variables p = Problem(Maximize(self.x[0, 0]), [self.x[0, 0] <= 2, self.x[1, 0] == 3]) result = p.solve() self.assertAlmostEqual(result, 2) self.assertItemsAlmostEqual(self.x.value, [2, 3]) n = 10 A = matrix(range(n * n), (n, n)) x = Variable(n, n) p = Problem(Minimize(sum_entries(x)), [x == A]) result = p.solve() answer = n * n * (n * n + 1) / 2 - n * n self.assertAlmostEqual(result, answer) # Matrix variables p = Problem( Maximize(sum(self.A[i, i] + self.A[i, 1 - i] for i in range(2))), [self.A <= [[1, -2], [-3, 4]]]) result = p.solve() self.assertAlmostEqual(result, 0) self.assertItemsAlmostEqual(self.A.value, [1, -2, -3, 4]) # Indexing arithmetic expressions. exp = [[1, 2], [3, 4]] * self.z + self.x p = Problem(Minimize(exp[1, 0]), [self.x == self.z, self.z == [1, 2]]) result = p.solve() self.assertAlmostEqual(result, 12) self.assertItemsAlmostEqual(self.x.value, self.z.value)
def test_hstack(self): c = matrix(1, (1, 5)) p = Problem(Minimize(c * hstack(self.x.T, self.y.T).T), [self.x == [1, 2], self.y == [3, 4, 5]]) result = p.solve() self.assertAlmostEqual(result, 15) c = matrix(1, (1, 4)) p = Problem(Minimize(c * hstack(self.x.T, self.x.T).T), [self.x == [1, 2]]) result = p.solve() self.assertAlmostEqual(result, 6) c = matrix(1, (2, 2)) p = Problem(Minimize(sum_entries(hstack(self.A.T, self.C.T))), [self.A >= 2 * c, self.C == -2]) result = p.solve() self.assertAlmostEqual(result, -4) D = Variable(3, 3) expr = hstack(self.C, D) p = Problem(Minimize(expr[0, 1] + sum_entries(hstack(expr, expr))), [self.C >= 0, D >= 0, D[0, 0] == 2, self.C[0, 1] == 3]) result = p.solve() self.assertAlmostEqual(result, 13) c = matrix([1, -1]) p = Problem(Minimize(c.T * hstack(square(self.a).T, sqrt(self.b).T).T), [self.a == 2, self.b == 16]) with self.assertRaises(Exception) as cm: p.solve() self.assertEqual(str(cm.exception), "Problem does not follow DCP rules.")
def test_variable_name_conflict(self): var = Variable(name='a') p = Problem(Maximize(self.a + var), [var == 2 + self.a, var <= 3]) result = p.solve() self.assertAlmostEqual(result, 4.0) self.assertAlmostEqual(self.a.value, 1) self.assertAlmostEqual(var.value, 3)
def test_neg_indices(self): """Test negative indices. """ c = Constant([[1, 2], [3, 4]]) exp = c[-1, -1] self.assertEquals(exp.value, 4) self.assertEquals(exp.size, (1, 1)) self.assertEquals(exp.curvature, u.Curvature.CONSTANT_KEY) c = Constant([1, 2, 3, 4]) exp = c[1:-1] self.assertItemsAlmostEqual(exp.value, [2, 3]) self.assertEquals(exp.size, (2, 1)) self.assertEquals(exp.curvature, u.Curvature.CONSTANT_KEY) c = Constant([1, 2, 3, 4]) exp = c[::-1] self.assertItemsAlmostEqual(exp.value, [4, 3, 2, 1]) self.assertEquals(exp.size, (4, 1)) self.assertEquals(exp.curvature, u.Curvature.CONSTANT_KEY) x = Variable(4) Problem(Minimize(0), [x[::-1] == c]).solve() self.assertItemsAlmostEqual(x.value, [4, 3, 2, 1]) self.assertEquals(x.size, (4, 1))
def test_min_entries_sign(self): """Test sign for min_entries. """ # One arg. self.assertEquals(min_entries(1).sign, u.Sign.POSITIVE_KEY) self.assertEquals(min_entries(-2).sign, u.Sign.NEGATIVE_KEY) self.assertEquals(min_entries(Variable()).sign, u.Sign.UNKNOWN_KEY) self.assertEquals(min_entries(0).sign, u.Sign.ZERO_KEY)
def test_min_entries_sign(self): """Test sign for min_entries. """ # One arg, test sign. self.assertEquals(min_entries(1).sign, s.POSITIVE) self.assertEquals(min_entries(-2).sign, s.NEGATIVE) self.assertEquals(min_entries(Variable()).sign, s.UNKNOWN) self.assertEquals(min_entries(0).sign, s.ZERO)
def test_power(self): x = Variable() prob = Problem( Minimize(power(x, 1.7) + power(x, -2.3) - power(x, .45))) prob.solve() x = x.value self.assertTrue(__builtins__['abs'](1.7 * x**.7 - 2.3 * x**-3.3 - .45 * x**-.55) <= 1e-3)
def test_kl_div(self): """Test domain for kl_div. """ b = Variable() dom = kl_div(self.a, b).domain Problem(Minimize(self.a + b), dom).solve() self.assertAlmostEqual(self.a.value, 0) self.assertAlmostEqual(b.value, 0)
class TestVstack(unittest.TestCase): """ Unit tests for the expressions.affine module. """ def setUp(self): self.x = Variable(2, name='x') self.y = Variable(2, name='y') self.A = Variable(3,2, name='A') self.B = Variable(5,2, name='B') self.C = Constant([[1, 2], [1, 2]]) self.intf = intf.DEFAULT_INTERFACE # Test the variables method. def test_variables(self): exp,constr = vstack(self.x, self.y, self.x+self.y).canonical_form self.assertEquals(constr, []) self.assertItemsEqual(exp.variables(), [self.x, self.y]) exp = vstack(self.A, self.B, self.C).canonical_form[0] self.assertItemsEqual(exp.variables(), [self.A, self.B]) # Test coefficients method. def test_coefficients(self): exp = vstack(self.x).canonical_form[0] coeffs = exp.coefficients() self.assertEqual(coeffs.keys(), self.x.coefficients().keys()) exp = vstack(self.x, self.y).canonical_form[0] coeffs = exp.coefficients() self.assertItemsEqual(coeffs.keys(), self.x.coefficients().keys() + \ self.y.coefficients().keys()) for k,blocks in coeffs.items(): self.assertEqual(len(blocks), 1) for block in blocks: self.assertEqual(intf.size(block), (4,2)) exp = vstack(self.A, self.B, self.C).canonical_form[0] coeffs = exp.coefficients() blocks = coeffs[self.A.id] self.assertEqual(len(blocks), 2) for block in blocks: self.assertEqual(intf.size(block), (10,6))
class TestAffVstack(unittest.TestCase): """ Unit tests for the expressions.affine module. """ def setUp(self): self.x = Variable(2, name='x') self.y = Variable(2, name='y') self.A = Variable(3,2, name='A') self.B = Variable(5,2, name='B') self.C = Constant([[1, 2], [1, 2]]) self.intf = intf.DEFAULT_INTERFACE # Test the variables method. def test_variables(self): exp = AffVstack(self.x, self.y, self.x+self.y) self.assertItemsEqual(exp.variables(), [self.x, self.y, self.x, self.y]) exp = AffVstack(self.A, self.B, self.C) self.assertItemsEqual(exp.variables(), [self.A, self.B]) # Test coefficients method. def test_coefficients(self): exp = AffVstack(self.x) coeffs = exp.coefficients(self.intf) self.assertEqual(coeffs.keys(), self.x.coefficients(self.intf).keys()) exp = AffVstack(self.x, self.y) coeffs = exp.coefficients(self.intf) self.assertItemsEqual(coeffs.keys(), self.x.coefficients(self.intf).keys() + \ self.y.coefficients(self.intf).keys()) for k,v in coeffs.items(): self.assertEqual(intf.size(v), (4,2)) exp = AffVstack(self.A, self.B, self.C) coeffs = exp.coefficients(self.intf) v = coeffs[self.A] self.assertEqual(intf.size(v), (10,3))
def test_variable(self): x = Variable(2) y = Variable(2) assert y.name() != x.name() x = Variable(2, name='x') y = Variable() self.assertEqual(x.name(), 'x') self.assertEqual(x.size, (2,1)) self.assertEqual(y.size, (1,1)) self.assertEqual(x.curvature, u.Curvature.AFFINE_KEY) self.assertEqual(x.canonical_form[0].size, (2,1)) self.assertEqual(x.canonical_form[1], [])
def test_log_det(self): """Test gradient for log_det """ expr = log_det(self.A) self.A.value = 2*np.eye(2) self.assertItemsAlmostEqual(expr.grad[self.A].todense(), 1.0/2*np.eye(2)) mat = np.matrix([[1, 2], [3, 5]]) self.A.value = mat.T*mat val = np.linalg.inv(self.A.value).T self.assertItemsAlmostEqual(expr.grad[self.A].todense(), val) self.A.value = np.zeros((2, 2)) self.assertAlmostEqual(expr.grad[self.A], None) self.A.value = -np.matrix([[1, 2], [3, 4]]) self.assertAlmostEqual(expr.grad[self.A], None) K = Variable(8, 8) expr = log_det(K[[1,2]][:,[1,2]]) K.value = np.eye(8) val = np.zeros((8,8)) val[[1,2],[1,2]] = 1 self.assertItemsAlmostEqual(expr.grad[K].todense(), val)
def test_variable(self): x = Variable(2) y = Variable(2) assert y.name() != x.name() x = Variable(2, name='x') y = Variable() self.assertEqual(x.name(), 'x') self.assertEqual(x.size, (2, 1)) self.assertEqual(y.size, (1, 1)) self.assertEqual(x.curvature, s.AFFINE) self.assertEqual(x.canonical_form[0].size, (2, 1)) self.assertEqual(x.canonical_form[1], []) self.assertEqual(repr(self.x), "Variable(2, 1)") self.assertEqual(repr(self.A), "Variable(2, 2)")
def test_min_elemwise(self): """Test domain for min_elemwise. """ b = Variable() expr = min_elemwise(self.a, b) self.a.value = 2 b.value = 4 self.assertAlmostEqual(expr.grad[self.a], 1) self.assertAlmostEqual(expr.grad[b], 0) self.a.value = 3 b.value = 0 self.assertAlmostEqual(expr.grad[self.a], 0) self.assertAlmostEqual(expr.grad[b], 1) self.a.value = -1 b.value = 2 self.assertAlmostEqual(expr.grad[self.a], 1) self.assertAlmostEqual(expr.grad[b], 0) y = Variable(2) expr = min_elemwise(self.x, y) self.x.value = [3, 4] y.value = [5, -5] val = np.zeros((2, 2)) + np.diag([1, 0]) self.assertItemsAlmostEqual(expr.grad[self.x].todense(), val) val = np.zeros((2, 2)) + np.diag([0, 1]) self.assertItemsAlmostEqual(expr.grad[y].todense(), val) expr = min_elemwise(self.x, y) self.x.value = [-1e-9, 4] y.value = [1, 4] val = np.zeros((2, 2)) + np.diag([1, 1]) self.assertItemsAlmostEqual(expr.grad[self.x].todense(), val) val = np.zeros((2, 2)) + np.diag([0, 0]) self.assertItemsAlmostEqual(expr.grad[y].todense(), val) expr = min_elemwise(self.A, self.B) self.A.value = [[1, 2], [3, 4]] self.B.value = [[5, 1], [3, 2.3]] div = (self.A.value/self.B.value).A.ravel(order='F') val = np.zeros((4, 4)) + np.diag([1, 0, 1, 0]) self.assertItemsAlmostEqual(expr.grad[self.A].todense(), val) val = np.zeros((4, 4)) + np.diag([0, 1, 0, 1]) self.assertItemsAlmostEqual(expr.grad[self.B].todense(), val)
def test_kl_div(self): """Test domain for kl_div. """ b = Variable() expr = kl_div(self.a, b) self.a.value = 2 b.value = 4 self.assertAlmostEqual(expr.grad[self.a], np.log(2/4)) self.assertAlmostEqual(expr.grad[b], 1 - (2/4)) self.a.value = 3 b.value = 0 self.assertAlmostEqual(expr.grad[self.a], None) self.assertAlmostEqual(expr.grad[b], None) self.a.value = -1 b.value = 2 self.assertAlmostEqual(expr.grad[self.a], None) self.assertAlmostEqual(expr.grad[b], None) y = Variable(2) expr = kl_div(self.x, y) self.x.value = [3, 4] y.value = [5, 8] val = np.zeros((2, 2)) + np.diag(np.log([3, 4]) - np.log([5, 8])) self.assertItemsAlmostEqual(expr.grad[self.x].todense(), val) val = np.zeros((2, 2)) + np.diag([1 - 3/5, 1 - 4/8]) self.assertItemsAlmostEqual(expr.grad[y].todense(), val) expr = kl_div(self.x, y) self.x.value = [-1e-9, 4] y.value = [1, 2] self.assertAlmostEqual(expr.grad[self.x], None) self.assertAlmostEqual(expr.grad[y], None) expr = kl_div(self.A, self.B) self.A.value = [[1, 2], [3, 4]] self.B.value = [[5, 1], [3.5, 2.3]] div = (self.A.value/self.B.value).A.ravel(order='F') val = np.zeros((4, 4)) + np.diag(np.log(div)) self.assertItemsAlmostEqual(expr.grad[self.A].todense(), val) val = np.zeros((4, 4)) + np.diag(1 - div) self.assertItemsAlmostEqual(expr.grad[self.B].todense(), val)
class TestExpressions(BaseTest): """ Unit tests for the expression/expression module. """ def setUp(self): self.a = Variable(name='a') self.x = Variable(2, name='x') self.y = Variable(3, name='y') self.z = Variable(2, name='z') self.A = Variable(2,2,name='A') self.B = Variable(2,2,name='B') self.C = Variable(3,2,name='C') self.intf = intf.DEFAULT_INTERFACE # Test the Variable class. def test_variable(self): x = Variable(2) y = Variable(2) assert y.name() != x.name() x = Variable(2, name='x') y = Variable() self.assertEqual(x.name(), 'x') self.assertEqual(x.size, (2,1)) self.assertEqual(y.size, (1,1)) self.assertEqual(x.curvature, u.Curvature.AFFINE_KEY) self.assertEqual(x.canonical_form[0].size, (2,1)) self.assertEqual(x.canonical_form[1], []) self.assertEquals(repr(self.x), "Variable(2, 1)") self.assertEquals(repr(self.A), "Variable(2, 2)") # # Scalar variable # coeff = self.a.coefficients() # self.assertEqual(coeff[self.a.id], [1]) # # Vector variable. # coeffs = x.coefficients() # self.assertItemsEqual(coeffs.keys(), [x.id]) # vec = coeffs[x.id][0] # self.assertEqual(vec.shape, (2,2)) # self.assertEqual(vec[0,0], 1) # # Matrix variable. # coeffs = self.A.coefficients() # self.assertItemsEqual(coeffs.keys(), [self.A.id]) # self.assertEqual(len(coeffs[self.A.id]), 2) # mat = coeffs[self.A.id][1] # self.assertEqual(mat.shape, (2,4)) # self.assertEqual(mat[0,2], 1) # Test tranposing variables. def test_transpose_variable(self): var = self.a.T self.assertEquals(var.name(), "a") self.assertEquals(var.size, (1,1)) self.a.save_value(2) self.assertEquals(var.value, 2) var = self.x.T self.assertEquals(var.name(), "x.T") self.assertEquals(var.size, (1,2)) self.x.save_value( matrix([1,2]) ) self.assertEquals(var.value[0,0], 1) self.assertEquals(var.value[0,1], 2) var = self.C.T self.assertEquals(var.name(), "C.T") self.assertEquals(var.size, (2,3)) # coeffs = var.canonical_form[0].coefficients() # mat = coeffs.values()[0][0] # self.assertEqual(mat.size, (2,6)) # self.assertEqual(mat[1,3], 1) index = var[1,0] self.assertEquals(index.name(), "C.T[1, 0]") self.assertEquals(index.size, (1,1)) var = self.x.T.T self.assertEquals(var.name(), "x.T.T") self.assertEquals(var.size, (2,1)) # Test the Constant class. def test_constants(self): c = Constant(2) self.assertEqual(c.name(), str(2)) c = Constant(2) self.assertEqual(c.value, 2) self.assertEqual(c.size, (1,1)) self.assertEqual(c.curvature, u.Curvature.CONSTANT_KEY) self.assertEqual(c.sign, u.Sign.POSITIVE_KEY) self.assertEqual(Constant(-2).sign, u.Sign.NEGATIVE_KEY) self.assertEqual(Constant(0).sign, u.Sign.ZERO_KEY) self.assertEqual(c.canonical_form[0].size, (1,1)) self.assertEqual(c.canonical_form[1], []) # coeffs = c.coefficients() # self.assertEqual(coeffs.keys(), [s.CONSTANT]) # self.assertEqual(coeffs[s.CONSTANT], [2]) # Test the sign. c = Constant([[2], [2]]) self.assertEqual(c.size, (1, 2)) self.assertEqual(c.sign, u.Sign.POSITIVE_KEY) self.assertEqual((-c).sign, u.Sign.NEGATIVE_KEY) self.assertEqual((0*c).sign, u.Sign.ZERO_KEY) c = Constant([[2], [-2]]) self.assertEqual(c.sign, u.Sign.UNKNOWN_KEY) # Test sign of a complex expression. c = Constant([1, 2]) A = Constant([[1,1],[1,1]]) exp = c.T*A*c self.assertEqual(exp.sign, u.Sign.POSITIVE_KEY) self.assertEqual((c.T*c).sign, u.Sign.POSITIVE_KEY) exp = c.T.T self.assertEqual(exp.sign, u.Sign.POSITIVE_KEY) exp = c.T*self.A self.assertEqual(exp.sign, u.Sign.UNKNOWN_KEY) # Test repr. self.assertEqual(repr(c), "Constant(CONSTANT, POSITIVE, (2, 1))") # def test_1D_array(self): # """Test NumPy 1D arrays as constants. # """ # c = np.array([1,2]) # p = Parameter(2) # with warnings.catch_warnings(record=True) as w: # # Cause all warnings to always be triggered. # warnings.simplefilter("always") # # Trigger a warning. # Constant(c) # self.x + c # p.value = c # # Verify some things # self.assertEqual(len(w), 3) # for warning in w: # self.assertEqual(str(warning.message), "NumPy 1D arrays are treated as column vectors.") # Test the Parameter class. def test_parameters(self): p = Parameter(name='p') self.assertEqual(p.name(), "p") self.assertEqual(p.size, (1,1)) p = Parameter(4, 3, sign="positive") with self.assertRaises(Exception) as cm: p.value = 1 self.assertEqual(str(cm.exception), "Invalid dimensions (1, 1) for Parameter value.") val = -np.ones((4,3)) val[0,0] = 2 p = Parameter(4, 3, sign="positive") with self.assertRaises(Exception) as cm: p.value = val self.assertEqual(str(cm.exception), "Invalid sign for Parameter value.") p = Parameter(4, 3, sign="negative") with self.assertRaises(Exception) as cm: p.value = val self.assertEqual(str(cm.exception), "Invalid sign for Parameter value.") # No error for unknown sign. p = Parameter(4, 3) p.value = val # Initialize a parameter with a value. p = Parameter(value=10) self.assertEqual(p.value, 10) with self.assertRaises(Exception) as cm: p = Parameter(2, 1, sign="negative", value=[2,1]) self.assertEqual(str(cm.exception), "Invalid sign for Parameter value.") with self.assertRaises(Exception) as cm: p = Parameter(4, 3, sign="positive", value=[1,2]) self.assertEqual(str(cm.exception), "Invalid dimensions (2, 1) for Parameter value.") # Test repr. p = Parameter(4, 3, sign="negative") self.assertEqual(repr(p), 'Parameter(4, 3, sign="NEGATIVE")') # Test the AddExpresion class. def test_add_expression(self): # Vectors c = Constant([2,2]) exp = self.x + c self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEqual(exp.sign, u.Sign.UNKNOWN_KEY) self.assertEqual(exp.canonical_form[0].size, (2,1)) self.assertEqual(exp.canonical_form[1], []) # self.assertEqual(exp.name(), self.x.name() + " + " + c.name()) self.assertEqual(exp.size, (2,1)) z = Variable(2, name='z') exp = exp + z + self.x with self.assertRaises(Exception) as cm: (self.x + self.y) self.assertEqual(str(cm.exception), "Incompatible dimensions (2, 1) (3, 1)") # Matrices exp = self.A + self.B self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEqual(exp.size, (2,2)) with self.assertRaises(Exception) as cm: (self.A + self.C) self.assertEqual(str(cm.exception), "Incompatible dimensions (2, 2) (3, 2)") with self.assertRaises(Exception) as cm: AddExpression([self.A, self.C]) self.assertEqual(str(cm.exception), "Incompatible dimensions (2, 2) (3, 2)") # Test that sum is flattened. exp = self.x + c + self.x self.assertEqual(len(exp.args), 3) # Test repr. self.assertEqual(repr(exp), "Expression(AFFINE, UNKNOWN, (2, 1))") # Test the SubExpresion class. def test_sub_expression(self): # Vectors c = Constant([2,2]) exp = self.x - c self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEqual(exp.sign, u.Sign.UNKNOWN_KEY) self.assertEqual(exp.canonical_form[0].size, (2,1)) self.assertEqual(exp.canonical_form[1], []) # self.assertEqual(exp.name(), self.x.name() + " - " + Constant([2,2]).name()) self.assertEqual(exp.size, (2,1)) z = Variable(2, name='z') exp = exp - z - self.x with self.assertRaises(Exception) as cm: (self.x - self.y) self.assertEqual(str(cm.exception), "Incompatible dimensions (2, 1) (3, 1)") # Matrices exp = self.A - self.B self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEqual(exp.size, (2,2)) with self.assertRaises(Exception) as cm: (self.A - self.C) self.assertEqual(str(cm.exception), "Incompatible dimensions (2, 2) (3, 2)") # Test repr. self.assertEqual(repr(self.x - c), "Expression(AFFINE, UNKNOWN, (2, 1))") # Test the MulExpresion class. def test_mul_expression(self): # Vectors c = Constant([[2],[2]]) exp = c*self.x self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEqual((c[0]*self.x).sign, u.Sign.UNKNOWN_KEY) self.assertEqual(exp.canonical_form[0].size, (1,1)) self.assertEqual(exp.canonical_form[1], []) # self.assertEqual(exp.name(), c.name() + " * " + self.x.name()) self.assertEqual(exp.size, (1,1)) with self.assertRaises(Exception) as cm: ([2,2,3]*self.x) self.assertEqual(str(cm.exception), "Incompatible dimensions (3, 1) (2, 1)") # Matrices with self.assertRaises(Exception) as cm: Constant([[2, 1],[2, 2]]) * self.C self.assertEqual(str(cm.exception), "Incompatible dimensions (2, 2) (3, 2)") with self.assertRaises(Exception) as cm: (self.A * self.B) self.assertEqual(str(cm.exception), "Cannot multiply two non-constants.") # Constant expressions T = Constant([[1,2,3],[3,5,5]]) exp = (T + T) * self.B self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEqual(exp.size, (3,2)) # Expression that would break sign multiplication without promotion. c = Constant([[2], [2], [-2]]) exp = [[1], [2]] + c*self.C self.assertEqual(exp.sign, u.Sign.UNKNOWN_KEY) # Scalar constants on the right should be moved left # instead of taking the transpose. expr = self.C*2 self.assertEqual(expr.args[0].value, 2) # Test the DivExpresion class. def test_div_expression(self): # Vectors exp = self.x/2 self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEqual(exp.sign, u.Sign.UNKNOWN_KEY) self.assertEqual(exp.canonical_form[0].size, (2,1)) self.assertEqual(exp.canonical_form[1], []) # self.assertEqual(exp.name(), c.name() + " * " + self.x.name()) self.assertEqual(exp.size, (2,1)) with self.assertRaises(Exception) as cm: (self.x/[2,2,3]) print cm.exception self.assertEqual(str(cm.exception), "Can only divide by a scalar constant.") # Constant expressions. c = Constant(2) exp = c/(3 - 5) self.assertEqual(exp.curvature, u.Curvature.CONSTANT_KEY) self.assertEqual(exp.size, (1,1)) self.assertEqual(exp.sign, u.Sign.NEGATIVE_KEY) # Parameters. p = Parameter(sign="positive") exp = 2/p p.value = 2 self.assertEquals(exp.value, 1) rho = Parameter(sign="positive") rho.value = 1 self.assertEquals(rho.sign, u.Sign.POSITIVE_KEY) self.assertEquals(Constant(2).sign, u.Sign.POSITIVE_KEY) self.assertEquals((Constant(2)/Constant(2)).sign, u.Sign.POSITIVE_KEY) self.assertEquals((Constant(2)*rho).sign, u.Sign.POSITIVE_KEY) self.assertEquals((rho/2).sign, u.Sign.POSITIVE_KEY) # Test the NegExpression class. def test_neg_expression(self): # Vectors exp = -self.x self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) assert exp.is_affine() self.assertEqual(exp.sign, u.Sign.UNKNOWN_KEY) assert not exp.is_positive() self.assertEqual(exp.canonical_form[0].size, (2,1)) self.assertEqual(exp.canonical_form[1], []) # self.assertEqual(exp.name(), "-%s" % self.x.name()) self.assertEqual(exp.size, self.x.size) # Matrices exp = -self.C self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEqual(exp.size, (3,2)) # Test promotion of scalar constants. def test_scalar_const_promotion(self): # Vectors exp = self.x + 2 self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) assert exp.is_affine() self.assertEqual(exp.sign, u.Sign.UNKNOWN_KEY) assert not exp.is_negative() self.assertEqual(exp.canonical_form[0].size, (2,1)) self.assertEqual(exp.canonical_form[1], []) # self.assertEqual(exp.name(), self.x.name() + " + " + Constant(2).name()) self.assertEqual(exp.size, (2,1)) self.assertEqual((4 - self.x).size, (2,1)) self.assertEqual((4 * self.x).size, (2,1)) self.assertEqual((4 <= self.x).size, (2,1)) self.assertEqual((4 == self.x).size, (2,1)) self.assertEqual((self.x >= 4).size, (2,1)) # Matrices exp = (self.A + 2) + 4 self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEqual((3 * self.A).size, (2,2)) self.assertEqual(exp.size, (2,2)) # Test indexing expression. def test_index_expression(self): # Tuple of integers as key. exp = self.x[1,0] # self.assertEqual(exp.name(), "x[1,0]") self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) assert exp.is_affine() self.assertEquals(exp.size, (1,1)) # coeff = exp.canonical_form[0].coefficients()[self.x][0] # self.assertEqual(coeff[0,1], 1) self.assertEqual(exp.value, None) exp = self.x[1,0].T # self.assertEqual(exp.name(), "x[1,0]") self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEquals(exp.size, (1,1)) with self.assertRaises(Exception) as cm: (self.x[2,0]) self.assertEqual(str(cm.exception), "Index/slice out of bounds.") # Slicing exp = self.C[0:2,1] # self.assertEquals(exp.name(), "C[0:2,1]") self.assertEquals(exp.size, (2,1)) exp = self.C[0:,0:2] # self.assertEquals(exp.name(), "C[0:,0:2]") self.assertEquals(exp.size, (3,2)) exp = self.C[0::2,0::2] # self.assertEquals(exp.name(), "C[0::2,0::2]") self.assertEquals(exp.size, (2,1)) exp = self.C[:3,:1:2] # self.assertEquals(exp.name(), "C[0:3,0]") self.assertEquals(exp.size, (3,1)) exp = self.C[0:,0] # self.assertEquals(exp.name(), "C[0:,0]") self.assertEquals(exp.size, (3,1)) c = Constant([[1,-2],[0,4]]) exp = c[1, 1] self.assertEqual(exp.curvature, u.Curvature.CONSTANT_KEY) self.assertEqual(exp.sign, u.Sign.UNKNOWN_KEY) self.assertEqual(c[0,1].sign, u.Sign.UNKNOWN_KEY) self.assertEqual(c[1,0].sign, u.Sign.UNKNOWN_KEY) self.assertEquals(exp.size, (1,1)) self.assertEqual(exp.value, 4) c = Constant([[1,-2,3],[0,4,5],[7,8,9]]) exp = c[0:3,0:4:2] self.assertEqual(exp.curvature, u.Curvature.CONSTANT_KEY) assert exp.is_constant() self.assertEquals(exp.size, (3,2)) self.assertEqual(exp[0,1].value, 7) # Slice of transpose exp = self.C.T[0:2,1] self.assertEquals(exp.size, (2,1)) # Arithmetic expression indexing exp = (self.x + self.z)[1,0] # self.assertEqual(exp.name(), "x[1,0] + z[1,0]") self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEqual(exp.sign, u.Sign.UNKNOWN_KEY) self.assertEquals(exp.size, (1,1)) exp = (self.x + self.a)[1,0] # self.assertEqual(exp.name(), "x[1,0] + a") self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEquals(exp.size, (1,1)) exp = (self.x - self.z)[1,0] # self.assertEqual(exp.name(), "x[1,0] - z[1,0]") self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEquals(exp.size, (1,1)) exp = (self.x - self.a)[1,0] # self.assertEqual(exp.name(), "x[1,0] - a") self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEquals(exp.size, (1,1)) exp = (-self.x)[1,0] # self.assertEqual(exp.name(), "-x[1,0]") self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEquals(exp.size, (1,1)) c = Constant([[1,2],[3,4]]) exp = (c*self.x)[1,0] # self.assertEqual(exp.name(), "[[2], [4]] * x[0:,0]") self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEquals(exp.size, (1,1)) c = Constant([[1,2],[3,4]]) exp = (c*self.a)[1,0] # self.assertEqual(exp.name(), "2 * a") self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY) self.assertEquals(exp.size, (1,1)) def test_neg_indices(self): """Test negative indices. """ c = Constant([[1,2],[3,4]]) exp = c[-1, -1] self.assertEquals(exp.value, 4) self.assertEquals(exp.size, (1, 1)) self.assertEquals(exp.curvature, u.Curvature.CONSTANT_KEY) c = Constant([1,2,3,4]) exp = c[1:-1] self.assertItemsAlmostEqual(exp.value, [2, 3]) self.assertEquals(exp.size, (2, 1)) self.assertEquals(exp.curvature, u.Curvature.CONSTANT_KEY) def test_logical_indices(self): """Test indexing with logical arrays. """ pass
class TestExpressions(unittest.TestCase): """ Unit tests for the expression/expression module. """ def setUp(self): self.a = Variable(name='a') self.x = Variable(2, name='x') self.y = Variable(3, name='y') self.z = Variable(2, name='z') self.A = Variable(2,2,name='A') self.B = Variable(2,2,name='B') self.C = Variable(3,2,name='C') self.intf = intf.DEFAULT_INTERFACE # Test the Variable class. def test_variable(self): x = Variable(2) y = Variable(2) assert y.name() != x.name() x = Variable(2, name='x') y = Variable() self.assertEqual(x.name(), 'x') self.assertEqual(x.size, (2,1)) self.assertEqual(y.size, (1,1)) self.assertEqual(x.curvature, u.Curvature.AFFINE) self.assertEqual(x.canonicalize()[0].size, (2,1)) self.assertEqual(x.canonicalize()[1], []) # Scalar variable coeff = self.a.coefficients(self.intf) self.assertEqual(coeff[self.a], 1) # Vector variable. coeffs = x.coefficients(self.intf) self.assertItemsEqual(coeffs.keys(), [x]) vec = coeffs[x] self.assertEqual(vec.size, (2,2)) self.assertEqual(list(vec), [1,0,0,1]) # Matrix variable. coeffs = self.A.coefficients(self.intf) self.assertItemsEqual(coeffs.keys(), [self.A]) mat = coeffs[self.A] self.assertEqual(mat.size, (2,2)) self.assertEqual(list(mat), [1,0,0,1]) # Test the TransposeVariable class. def test_transpose_variable(self): var = self.a.T self.assertEquals(var.name(), "a") self.assertEquals(var.size, (1,1)) self.a.save_value(2) self.assertEquals(var.value, 2) var = self.x.T self.assertEquals(var.name(), "x.T") self.assertEquals(var.size, (1,2)) self.x.save_value( matrix([1,2]) ) self.assertEquals(var.value[0,0], 1) self.assertEquals(var.value[0,1], 2) var = self.C.T self.assertEquals(var.name(), "C.T") self.assertEquals(var.size, (2,3)) coeffs = var.coefficients(self.intf) self.assertItemsEqual(coeffs.keys(), [var]) mat = coeffs[var] self.assertEqual(mat.size, (2,2)) self.assertEqual(list(mat), [1,0,0,1]) index = var[1,0] self.assertEquals(index.name(), "C[0,1]") self.assertEquals(index.size, (1,1)) var = self.x.T.T self.assertEquals(var.name(), "x") self.assertEquals(var.size, (2,1)) # Test the Constant class. def test_constants(self): c = Constant(2) self.assertEqual(c.name(), str(2)) c = Constant(2, name="c") self.assertEqual(c.name(), "c") self.assertEqual(c.value, 2) self.assertEqual(c.size, (1,1)) self.assertEqual(c.curvature, u.Curvature.CONSTANT) self.assertEqual(c.sign, u.Sign.POSITIVE) self.assertEqual(Constant(-2).sign, u.Sign.NEGATIVE) self.assertEqual(Constant(0).sign, u.Sign.ZERO) self.assertEqual(c.canonicalize()[0].size, (1,1)) self.assertEqual(c.canonicalize()[1], []) coeffs = c.coefficients(self.intf) self.assertEqual(coeffs.keys(), [s.CONSTANT]) self.assertEqual(coeffs[s.CONSTANT], 2) # Test the sign. c = Constant([[2],[2]]) self.assertEqual(c.size, (1,2)) self.assertEqual(c.sign.neg_mat.value.shape, (1,2)) # Test the Parameter class. def test_parameters(self): p = Parameter(name='p') self.assertEqual(p.name(), "p") self.assertEqual(p.size, (1,1)) # Test the AddExpresion class. def test_add_expression(self): # Vectors c = Constant([2,2]) exp = self.x + c self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEqual(exp.sign, u.Sign.UNKNOWN) self.assertEqual(exp.canonicalize()[0].size, (2,1)) self.assertEqual(exp.canonicalize()[1], []) self.assertEqual(exp.name(), self.x.name() + " + " + c.name()) self.assertEqual(exp.size, (2,1)) z = Variable(2, name='z') exp = exp + z + self.x with self.assertRaises(Exception) as cm: (self.x + self.y) self.assertEqual(str(cm.exception), "Incompatible dimensions.") # Matrices exp = self.A + self.B self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEqual(exp.size, (2,2)) with self.assertRaises(Exception) as cm: (self.A + self.C) self.assertEqual(str(cm.exception), "Incompatible dimensions.") # Test the SubExpresion class. def test_sub_expression(self): # Vectors c = Constant([2,2]) exp = self.x - c self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEqual(exp.sign, u.Sign.UNKNOWN) self.assertEqual(exp.canonicalize()[0].size, (2,1)) self.assertEqual(exp.canonicalize()[1], []) self.assertEqual(exp.name(), self.x.name() + " - " + Constant([2,2]).name()) self.assertEqual(exp.size, (2,1)) z = Variable(2, name='z') exp = exp - z - self.x with self.assertRaises(Exception) as cm: (self.x - self.y) self.assertEqual(str(cm.exception), "Incompatible dimensions.") # Matrices exp = self.A - self.B self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEqual(exp.size, (2,2)) with self.assertRaises(Exception) as cm: (self.A - self.C) self.assertEqual(str(cm.exception), "Incompatible dimensions.") # Test the MulExpresion class. def test_mul_expression(self): # Vectors c = Constant([[2],[2]]) exp = c*self.x self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEqual((c[0]*self.x).sign, u.Sign.UNKNOWN) self.assertEqual(exp.canonicalize()[0].size, (1,1)) self.assertEqual(exp.canonicalize()[1], []) self.assertEqual(exp.name(), c.name() + " * " + self.x.name()) self.assertEqual(exp.size, (1,1)) with self.assertRaises(Exception) as cm: ([2,2,3]*self.x) const_name = Constant([2,2,3]).name() self.assertEqual(str(cm.exception), "Incompatible dimensions.") # Matrices with self.assertRaises(Exception) as cm: Constant([[2, 1],[2, 2]]) * self.C self.assertEqual(str(cm.exception), "Incompatible dimensions.") with self.assertRaises(Exception) as cm: (self.A * self.B) self.assertEqual(str(cm.exception), "Cannot multiply two non-constants.") # Constant expressions T = Constant([[1,2,3],[3,5,5]]) exp = (T + T) * self.B self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEqual(exp.size, (3,2)) # Expression that would break sign multiplication without promotion. c = Constant([[2],[2],[-2]]) exp = [[1],[2]] + c*self.C self.assertEqual(exp.sign.pos_mat.value.shape, (1,2)) # Test the NegExpression class. def test_neg_expression(self): # Vectors exp = -self.x self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEqual(exp.sign, u.Sign.UNKNOWN) self.assertEqual(exp.canonicalize()[0].size, (2,1)) self.assertEqual(exp.canonicalize()[1], []) self.assertEqual(exp.name(), "-%s" % self.x.name()) self.assertEqual(exp.size, self.x.size) # Matrices exp = -self.C self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEqual(exp.size, (3,2)) # Test promotion of scalar constants. def test_scalar_const_promotion(self): # Vectors exp = self.x + 2 self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEqual(exp.sign, u.Sign.UNKNOWN) self.assertEqual(exp.canonicalize()[0].size, (2,1)) self.assertEqual(exp.canonicalize()[1], []) self.assertEqual(exp.name(), self.x.name() + " + " + Constant(2).name()) self.assertEqual(exp.size, (2,1)) self.assertEqual((4 - self.x).size, (2,1)) self.assertEqual((4 * self.x).size, (2,1)) self.assertEqual((4 <= self.x).size, (2,1)) self.assertEqual((4 == self.x).size, (2,1)) self.assertEqual((self.x >= 4).size, (2,1)) # Matrices exp = (self.A + 2) + 4 self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEqual((3 * self.A).size, (2,2)) self.assertEqual(exp.size, (2,2)) # Test indexing expression. def test_index_expression(self): # Tuple of integers as key. exp = self.x[1,0] self.assertEqual(exp.name(), "x[1,0]") self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEquals(exp.size, (1,1)) coeff = exp.coefficients(self.intf) self.assertEqual(coeff[exp], 1) self.assertEqual(exp.value, None) with self.assertRaises(Exception) as cm: (self.x[2,0]) self.assertEqual(str(cm.exception), "Invalid indices 2,0 for 'x'.") # Slicing exp = self.C[0:2,1] self.assertEquals(exp.name(), "C[0:2,1]") self.assertEquals(exp.size, (2,1)) exp = self.C[0:,0:2] self.assertEquals(exp.name(), "C[0:,0:2]") self.assertEquals(exp.size, (3,2)) exp = self.C[0::2,0::2] self.assertEquals(exp.name(), "C[0::2,0::2]") self.assertEquals(exp.size, (2,1)) exp = self.C[:3,:1:2] self.assertEquals(exp.name(), "C[0:3,0]") self.assertEquals(exp.size, (3,1)) c = Constant([[1,-2],[0,4]]) exp = c[1,1] print exp self.assertEqual(exp.curvature, u.Curvature.CONSTANT) self.assertEqual(exp.sign, u.Sign.POSITIVE) self.assertEqual(c[0,1].sign, u.Sign.ZERO) self.assertEqual(c[1,0].sign, u.Sign.NEGATIVE) self.assertEquals(exp.size, (1,1)) self.assertEqual(exp.value, 4) c = Constant([[1,-2,3],[0,4,5],[7,8,9]]) exp = c[0:3,0:4:2] self.assertEqual(exp.curvature, u.Curvature.CONSTANT) self.assertEquals(exp.size, (3,2)) self.assertEqual(exp[0,1].value, 7) # Arithmetic expression indexing exp = (self.x + self.z)[1,0] self.assertEqual(exp.name(), "x[1,0] + z[1,0]") self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEqual(exp.sign, u.Sign.UNKNOWN) self.assertEquals(exp.size, (1,1)) exp = (self.x + self.a)[1,0] self.assertEqual(exp.name(), "x[1,0] + a") self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEquals(exp.size, (1,1)) exp = (self.x - self.z)[1,0] self.assertEqual(exp.name(), "x[1,0] - z[1,0]") self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEquals(exp.size, (1,1)) exp = (self.x - self.a)[1,0] self.assertEqual(exp.name(), "x[1,0] - a") self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEquals(exp.size, (1,1)) exp = (-self.x)[1,0] self.assertEqual(exp.name(), "-x[1,0]") self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEquals(exp.size, (1,1)) c = Constant([[1,2],[3,4]]) exp = (c*self.x)[1,0] self.assertEqual(exp.name(), "[[2], [4]] * x[0:,0]") self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEquals(exp.size, (1,1)) c = Constant([[1,2],[3,4]]) exp = (c*self.a)[1,0] self.assertEqual(exp.name(), "2 * a") self.assertEqual(exp.curvature, u.Curvature.AFFINE) self.assertEquals(exp.size, (1,1))