Beispiel #1
0
    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])
Beispiel #2
0
    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.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)
    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)
Beispiel #4
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]
        self.assertEqual(len(blocks), 2)
        for block in blocks:
            self.assertEqual(intf.size(block), (10, 6))
Beispiel #5
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))
Beispiel #6
0
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))
Beispiel #7
0
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))
Beispiel #8
0
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_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.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._dcp_attr.sign.neg_mat.shape, (1, 2))

        # 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._dcp_attr.sign.pos_mat.shape, (2, 1))
        exp = c.T * self.A
        self.assertEqual(exp._dcp_attr.sign.pos_mat.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))

        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

    # 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)")

    # 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 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)
        print cm.exception
        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._dcp_attr.sign.pos_mat.shape, (1, 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)

    # 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.POSITIVE_KEY)
        assert exp.is_positive()
        self.assertEqual(c[0, 1].sign, u.Sign.ZERO_KEY)
        assert c[0, 1].is_zero()
        self.assertEqual(c[1, 0].sign, u.Sign.NEGATIVE_KEY)
        assert c[1, 0].is_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_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))
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_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)

    # 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._dcp_attr.sign.neg_mat.shape, (1,2))

        # 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._dcp_attr.sign.pos_mat.shape, (2,1))
        exp = c.T*self.A
        self.assertEqual(exp._dcp_attr.sign.pos_mat.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))

        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

    # 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.")

        # 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.")


    # 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.")

        # 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.")

    # 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)
        print cm.exception
        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_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._dcp_attr.sign.pos_mat.shape, (1,2))

    # 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.POSITIVE_KEY)
        assert exp.is_positive()
        self.assertEqual(c[0,1].sign, u.Sign.ZERO_KEY)
        assert c[0, 1].is_zero()
        self.assertEqual(c[1,0].sign, u.Sign.NEGATIVE_KEY)
        assert c[1,0].is_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_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))
Beispiel #10
0
class test_coefficients(unittest.TestCase):
    """ Unit tests for the expressions.affine module. """
    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 test_leaf_coeffs(self):
        """Test the coefficients for Variables and Constants.
        """
        # Scalars
        coeffs = self.a.coefficients()
        self.assertItemsEqual(coeffs.keys(), [self.a])
        blocks = coeffs[self.a]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0], 1)

        # Vectors
        coeffs = self.x.coefficients()
        self.assertItemsEqual(coeffs.keys(), [self.x])
        blocks = coeffs[self.x]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].size, (2,2))

        # Matrices
        coeffs = self.A.coefficients()
        self.assertItemsEqual(coeffs.keys(), [self.A])
        blocks = coeffs[self.A]
        self.assertEqual(len(blocks), 2)
        self.assertEqual(blocks[0].size, (2,4))

        # Constants
        coeffs = self.c.coefficients()
        self.assertItemsEqual(coeffs.keys(), [s.CONSTANT])
        blocks = coeffs[s.CONSTANT]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0], 3)

        coeffs = self.C.coefficients()
        self.assertItemsEqual(coeffs.keys(), [s.CONSTANT])
        blocks = coeffs[s.CONSTANT]
        self.assertEqual(len(blocks), 2)
        self.assertEqual(blocks[0].size, (2,1))
        self.assertEqual(blocks[0][0,0], 1)

    def test_add(self):
        """Test adding coefficients.
        """
        coeffs = cu.add(self.x.coefficients(), self.y.coefficients())
        self.assertItemsEqual(coeffs.keys(), [self.x, self.y])
        blocks = coeffs[self.x]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].size, (2,2))

        coeffs = cu.add(coeffs, coeffs)
        self.assertItemsEqual(coeffs.keys(), [self.x, self.y])
        blocks = coeffs[self.x]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].size, (2,2))
        self.assertEqual(blocks[0][0,0], 2)

        coeffs = cu.add(coeffs, self.C.coefficients())
        self.assertItemsEqual(coeffs.keys(), [self.x, self.y, s.CONSTANT])
        blocks = coeffs[s.CONSTANT]
        self.assertEqual(len(blocks), 2)
        self.assertEqual(blocks[0].size, (2,1))
        self.assertEqual(blocks[0][0,0], 1)

    def test_neg(self):
        """Test negating coefficients.
        """
        coeffs = cu.neg(self.a.coefficients())
        self.assertItemsEqual(coeffs.keys(), [self.a])
        blocks = coeffs[self.a]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0], -1)

        coeffs = cu.neg(self.A.coefficients())
        self.assertItemsEqual(coeffs.keys(), [self.A])
        blocks = coeffs[self.A]
        self.assertEqual(len(blocks), 2)
        self.assertEqual(blocks[0].size, (2,4))
        self.assertEqual(blocks[0][0,0], -1)

    def test_sub(self):
        """Test subtracting coefficients.
        """
        coeffs = cu.sub(self.x.coefficients(), self.y.coefficients())
        self.assertItemsEqual(coeffs.keys(), [self.x, self.y])
        blocks = coeffs[self.y]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].size, (2,2))
        self.assertEqual(blocks[0][0,0], -1)

        coeffs = cu.sub(coeffs, self.x.coefficients())
        self.assertItemsEqual(coeffs.keys(), [self.x, self.y])
        blocks = coeffs[self.x]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].size, (2,2))
        self.assertEqual(blocks[0][0,0], 0)

    def test_mul(self):
        """Test multiplying coefficients.
        """
        coeffs = cu.add(self.x.coefficients(), self.y.coefficients())
        coeffs = cu.mul(self.C.coefficients(), coeffs)
        self.assertItemsEqual(coeffs.keys(), [self.x, self.y])
        blocks = coeffs[self.y]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].size, (2,2))
        self.assertEqual(blocks[0][1,0], 2)

        # Scalar by Matrix multiplication.
        coeffs = cu.add(self.x.coefficients(), self.y.coefficients())
        coeffs = cu.mul(self.c.coefficients(), coeffs)
        self.assertItemsEqual(coeffs.keys(), [self.x, self.y])
        blocks = coeffs[self.y]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].size, (2,2))
        self.assertEqual(blocks[0][0,0], 3)

        # Matrix by Scalar multiplication.
        coeffs = self.a.coefficients()
        coeffs = cu.mul(self.C.coefficients(), coeffs)
        self.assertItemsEqual(coeffs.keys(), [self.a])
        blocks = coeffs[self.a]
        self.assertEqual(len(blocks), 2)
        self.assertEqual(blocks[0].size, (2,1))
        self.assertEqual(blocks[0][1,0], 2)
        self.assertEqual(blocks[1].size, (2,1))
        self.assertEqual(blocks[1][1,0], 2)

    def test_index(self):
        """Test indexing/slicing into coefficients.
        """
        # Index.
        sum_coeffs = cu.add(self.x.coefficients(), self.y.coefficients())
        key = ku.validate_key((1, 0), self.x.shape)
        coeffs = cu.index(sum_coeffs, key)
        self.assertItemsEqual(coeffs.keys(), [self.x, self.y])
        blocks = coeffs[self.y]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].size, (1,2))
        self.assertEqual(blocks[0][0,0], 0)

        # Slice.
        sum_coeffs = cu.add(self.A.coefficients(), self.C.coefficients())
        key = ku.validate_key((slice(None, None, None), 1), self.A.shape)
        coeffs = cu.index(sum_coeffs, key)
        self.assertItemsEqual(coeffs.keys(), [self.A, s.CONSTANT])
        # Variable.
        blocks = coeffs[self.A]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].size, (2,4))
        # Constant.
        blocks = coeffs[s.CONSTANT]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].size, (2,1))
Beispiel #11
0
class test_coefficients(unittest.TestCase):
    """ Unit tests for the expressions.affine module. """
    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 test_leaf_coeffs(self):
        """Test the coefficients for Variables and Constants.
        """
        # Scalars
        coeffs = self.a.coefficients()
        self.assertItemsEqual(coeffs.keys(), [self.a])
        blocks = coeffs[self.a]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0], 1)

        # Vectors
        coeffs = self.x.coefficients()
        self.assertItemsEqual(coeffs.keys(), [self.x])
        blocks = coeffs[self.x]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].shape, (2, 2))

        # Matrices
        coeffs = self.A.coefficients()
        self.assertItemsEqual(coeffs.keys(), [self.A])
        blocks = coeffs[self.A]
        self.assertEqual(len(blocks), 2)
        self.assertEqual(blocks[0].shape, (2, 4))

        # Constants
        coeffs = self.c.coefficients()
        self.assertItemsEqual(coeffs.keys(), [s.CONSTANT])
        blocks = coeffs[s.CONSTANT]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0], 3)

        coeffs = self.C.coefficients()
        self.assertItemsEqual(coeffs.keys(), [s.CONSTANT])
        blocks = coeffs[s.CONSTANT]
        self.assertEqual(len(blocks), 2)
        print blocks[0]
        self.assertEqual(blocks[0].shape, (2, 1))
        self.assertEqual(blocks[0][0, 0], 1)

    def test_add(self):
        """Test adding coefficients.
        """
        coeffs = cu.add(self.x.coefficients(), self.y.coefficients())
        self.assertItemsEqual(coeffs.keys(), [self.x, self.y])
        blocks = coeffs[self.x]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].shape, (2, 2))

        coeffs = cu.add(coeffs, coeffs)
        self.assertItemsEqual(coeffs.keys(), [self.x, self.y])
        blocks = coeffs[self.x]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].shape, (2, 2))
        self.assertEqual(blocks[0][0, 0], 2)

        coeffs = cu.add(coeffs, self.C.coefficients())
        self.assertItemsEqual(coeffs.keys(), [self.x, self.y, s.CONSTANT])
        blocks = coeffs[s.CONSTANT]
        self.assertEqual(len(blocks), 2)
        self.assertEqual(blocks[0].shape, (2, 1))
        self.assertEqual(blocks[0][0, 0], 1)

    def test_neg(self):
        """Test negating coefficients.
        """
        coeffs = cu.neg(self.a.coefficients())
        self.assertItemsEqual(coeffs.keys(), [self.a])
        blocks = coeffs[self.a]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0], -1)

        coeffs = cu.neg(self.A.coefficients())
        self.assertItemsEqual(coeffs.keys(), [self.A])
        blocks = coeffs[self.A]
        self.assertEqual(len(blocks), 2)
        self.assertEqual(blocks[0].shape, (2, 4))
        self.assertEqual(blocks[0][0, 0], -1)

    def test_sub(self):
        """Test subtracting coefficients.
        """
        coeffs = cu.sub(self.x.coefficients(), self.y.coefficients())
        self.assertItemsEqual(coeffs.keys(), [self.x, self.y])
        blocks = coeffs[self.y]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].shape, (2, 2))
        self.assertEqual(blocks[0][0, 0], -1)

        coeffs = cu.sub(coeffs, self.x.coefficients())
        self.assertItemsEqual(coeffs.keys(), [self.x, self.y])
        blocks = coeffs[self.x]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].shape, (2, 2))
        self.assertEqual(blocks[0][0, 0], 0)

    def test_mul(self):
        """Test multiplying coefficients.
        """
        coeffs = cu.add(self.x.coefficients(), self.y.coefficients())
        coeffs = cu.mul(self.C.coefficients(), coeffs)
        self.assertItemsEqual(coeffs.keys(), [self.x, self.y])
        blocks = coeffs[self.y]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].shape, (2, 2))
        self.assertEqual(blocks[0][1, 0], 2)

        # Scalar by Matrix multiplication.
        coeffs = cu.add(self.x.coefficients(), self.y.coefficients())
        coeffs = cu.mul(self.c.coefficients(), coeffs)
        self.assertItemsEqual(coeffs.keys(), [self.x, self.y])
        blocks = coeffs[self.y]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].shape, (2, 2))
        self.assertEqual(blocks[0][0, 0], 3)

        # Matrix by Scalar multiplication.
        coeffs = self.a.coefficients()
        coeffs = cu.mul(self.C.coefficients(), coeffs)
        self.assertItemsEqual(coeffs.keys(), [self.a])
        blocks = coeffs[self.a]
        self.assertEqual(len(blocks), 2)
        self.assertEqual(blocks[0].shape, (2, 1))
        self.assertEqual(blocks[0][1, 0], 2)
        self.assertEqual(blocks[1].shape, (2, 1))
        self.assertEqual(blocks[1][1, 0], 2)

    def test_index(self):
        """Test indexing/slicing into coefficients.
        """
        # Index.
        sum_coeffs = cu.add(self.x.coefficients(), self.y.coefficients())
        key = ku.validate_key((1, 0), self.x.shape)
        coeffs = cu.index(sum_coeffs, key)
        self.assertItemsEqual(coeffs.keys(), [self.x, self.y])
        blocks = coeffs[self.y]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].shape, (1, 2))
        self.assertEqual(blocks[0][0, 0], 0)

        # Slice.
        sum_coeffs = cu.add(self.A.coefficients(), self.C.coefficients())
        key = ku.validate_key((slice(None, None, None), 1), self.A.shape)
        coeffs = cu.index(sum_coeffs, key)
        self.assertItemsEqual(coeffs.keys(), [self.A, s.CONSTANT])
        # Variable.
        blocks = coeffs[self.A]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].shape, (2, 4))
        # Constant.
        blocks = coeffs[s.CONSTANT]
        self.assertEqual(len(blocks), 1)
        self.assertEqual(blocks[0].shape, (2, 1))
class TestAffObjective(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 = 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

    # Test adding AffObjectives.
    def test_add(self):
        add = self.xAff + self.yAff
        self.assertItemsEqual(add._terms, [deque([self.x]), deque([self.y])])
        self.assertItemsEqual(add.variables(), [self.x, self.y])

        add = self.xAff + self.xAff
        self.assertItemsEqual(add._terms, [deque([self.x]), deque([self.x])])
        self.assertItemsEqual(add.variables(), [self.x, self.x])

        with self.assertRaises(Exception) as cm:
            self.xAff + self.constAff
        self.assertEqual(str(cm.exception), "Incompatible dimensions.")

    # Test multiplying AffObjectives.
    def test_mul(self):
        mul = self.constAff * self.xAff
        self.assertItemsEqual(mul._terms, [deque([self.x, self.A])])
        self.assertItemsEqual(mul.variables(), [self.x])

        mul = self.constAff * (self.yAff + self.xAff)
        self.assertItemsEqual(mul._terms, [deque([self.x, self.A]), deque([self.y, self.A])])
        self.assertItemsEqual(mul.variables(), [self.x, self.y])

        with self.assertRaises(Exception) as cm:
            self.xAff * self.yAff
        self.assertEqual(str(cm.exception), "Incompatible dimensions.")

    # Test negating AffObjectives.
    def test_neg(self):
        neg = -self.xAff
        self.assertEqual(neg._terms[0][1].name(), "-1")
        self.assertItemsEqual(neg.variables(), [self.x])

    # Test subtracting AffObjectives.
    def test_sub(self):
        sub = self.xAff - self.yAff
        self.assertItemsEqual(sub._terms, (self.xAff + -self.yAff)._terms)
        self.assertItemsEqual(sub.variables(), [self.x, self.y])

        with self.assertRaises(Exception) as cm:
            self.xAff - self.constAff
        self.assertEqual(str(cm.exception), "Incompatible dimensions.")

    # Test coefficients method.
    def test_coefficients(self):
        # Leaf
        coeffs = self.xAff.coefficients(self.intf)
        self.assertEqual(coeffs.keys(), self.x.coefficients(self.intf).keys())

        # Sum with different keys
        exp = self.xAff + self.yAff
        coeffs = exp.coefficients(self.intf)
        keys = self.x.coefficients(self.intf).keys() + self.y.coefficients(self.intf).keys()
        self.assertItemsEqual(coeffs.keys(), keys)

        # Sum with same keys
        exp = self.xAff + self.xAff
        coeffs = exp.coefficients(self.intf)
        xCoeffs = self.x.coefficients(self.intf)
        self.assertItemsEqual(coeffs.keys(), xCoeffs)
        self.assertEqual(list(coeffs[self.x]), [2, 0, 0, 2])

        # Product
        exp = self.constAff * self.yAff
        coeffs = exp.coefficients(self.intf)
        yCoeffs = self.y.coefficients(self.intf)
        self.assertItemsEqual(coeffs.keys(), yCoeffs)
        self.assertEqual(list(coeffs[self.y]), [1, 2, 1, 2])

        # Distributed product
        exp = self.constAff * (self.xAff + self.yAff)
        coeffs = exp.coefficients(self.intf)
        xCoeffs = self.x.coefficients(self.intf)
        yCoeffs = self.y.coefficients(self.intf)
        self.assertItemsEqual(coeffs.keys(), xCoeffs.keys() + yCoeffs.keys())
        self.assertEqual(list(coeffs[self.x]), [1, 2, 1, 2])