Skip to content

Commit

Permalink
Merge pull request #7 from HC-HC/master
Browse files Browse the repository at this point in the history
Increase code coverage
  • Loading branch information
rileyjmurray committed Jan 29, 2021
2 parents 001fc80 + 8edadf6 commit 4ee48e1
Show file tree
Hide file tree
Showing 4 changed files with 318 additions and 7 deletions.
8 changes: 4 additions & 4 deletions sageopt/symbolic/polynomials.py
Expand Up @@ -222,7 +222,7 @@ def hess(self):

def __mul__(self, other):
if not isinstance(other, Polynomial):
if isinstance(other, Signomial): # pragma: no cover
if isinstance(other, Signomial):
raise RuntimeError('Cannot multiply signomials and polynomials.')
other = self.upcast_to_signomial(other)
other = other.as_polynomial()
Expand All @@ -235,13 +235,13 @@ def __mul__(self, other):
return temp

def __truediv__(self, other):
if not isinstance(other, __NUMERIC_TYPES__): # pragma: no cover
raise RuntimeError('Cannot divide a polynomial by the non-numeric type: ' + type(other) + '.')
if not isinstance(other, __NUMERIC_TYPES__):
raise RuntimeError('Cannot divide a polynomial by the non-numeric type: ' + str(type(other)) + '.')
other_inv = 1 / other
return self.__mul__(other_inv)

def __add__(self, other):
if isinstance(other, Signomial) and not isinstance(other, Polynomial): # pragma: no cover
if isinstance(other, Signomial) and not isinstance(other, Polynomial):
raise RuntimeError('Cannot add signomials to polynomials.')
temp = Signomial.__add__(self, other)
temp = temp.as_polynomial()
Expand Down
200 changes: 200 additions & 0 deletions sageopt/tests/test_coniclifts/test_affine_operators.py
Expand Up @@ -106,3 +106,203 @@ def test_trace_and_diag(self):
expr0 = aff.trace(temp)
expr1 = aff.sum(x)
assert Expression.are_equivalent(expr0, expr1)

def test_block(self):
A = np.eye(2) * 2
A_cl = Variable(shape=A.shape)
A_cl.value = A
B = np.eye(3) * 3
expected = np.block([
[A, np.zeros((2, 3))],
[np.ones((3, 2)), B]
])
actual = aff.block([
[A_cl, np.zeros((2, 3))],
[np.ones((3, 2)), B]
])
assert np.allclose(expected, actual.value)
A_cl.value = 1 + A # or 2*A, or really anything different from A itself.
assert not np.allclose(expected, actual.value)

def test_concatenate(self):
a = np.array([[1, 2], [3, 4]])
a_cl = Variable(shape=a.shape)
a_cl.value = a
b = np.array([[5, 6]])
b_cl = Variable(shape=b.shape)
b_cl.value = b
expected = np.concatenate((a, b))
actual = aff.concatenate((a_cl, b_cl))
assert np.allclose(expected, actual.value)
expected1 = np.concatenate((b, a))
actual1 = aff.concatenate((b_cl, a_cl))
assert np.allclose(expected1, actual1.value)

a_cl.value = 1 + a
assert not np.allclose(expected, actual.value)
assert not np.allclose(expected1, actual1.value)

def test_stack(self):
array = np.random.randn(3, 4)
arrays = [array for _ in range(10)]
a_cl = Variable(shape=array.shape)
a_cl.value = array
arrays_cl = [a_cl for _ in range(10)]
expected = np.stack(arrays, axis=0)
actual = aff.stack(arrays_cl, axis=0)
assert np.allclose(expected, actual.value)
assert Expression.are_equivalent(expected.shape, actual.shape)

expected1 = np.stack(arrays, axis=1)
actual1 = aff.stack(arrays_cl, axis=1)
assert np.allclose(expected1, actual1.value)
assert Expression.are_equivalent(expected.shape, actual.shape)

a_cl.value = 1 + array
assert not np.allclose(expected, actual.value)
assert not np.allclose(expected1, actual1.value)

def test_column_stack(self):
a = np.array((1, 2, 3))
b = np.array((2, 3, 4))
a_cl = Variable(shape=a.shape)
a_cl.value = a
b_cl = Variable(shape=b.shape)
b_cl.value = b
expected = np.column_stack((a, b))
actual = aff.column_stack((a_cl, b_cl))
assert np.allclose(expected, actual.value)
a_cl.value = 1 + a
assert not np.allclose(expected, actual.value)

def test_dstack(self):
a = np.array((1, 2, 3))
b = np.array((2, 3, 4))
a_cl = Variable(shape=a.shape)
a_cl.value = a
b_cl = Variable(shape=b.shape)
b_cl.value = b
expected = np.dstack((a, b))
actual = aff.dstack((a_cl, b_cl))
assert np.allclose(expected, actual.value)
c = np.array([[1], [2], [3]])
d = np.array([[2], [3], [4]])
expected1 = np.dstack((c, d))
c_cl = Variable(shape=c.shape)
c_cl.value = c
d_cl = Variable(shape=d.shape)
d_cl.value = d
actual1 = aff.dstack((c_cl, d_cl))
assert np.allclose(expected1, actual1.value)

a_cl.value = 1 + a
assert not np.allclose(expected, actual.value)
c_cl.value = 1 + c
assert not np.allclose(expected1, actual1.value)

def test_split(self):
x = np.arange(9.0)
x_cl = Variable(shape=x.shape)
x_cl.value = x
expected = np.split(x, 3)
actual = aff.split(x_cl, 3)
assert np.all([np.allclose(expected[i], actual[i].value) for i in range(3)])
x_cl.value = 1 + x
assert not np.all([np.allclose(expected[i], actual[i].value) for i in range(3)])

def test_hsplit(self):
x = np.arange(16.0).reshape(4, 4)
x_cl = Variable(shape=x.shape)
x_cl.value = x
expected = np.hsplit(x, 2)
actual = aff.hsplit(x_cl, 2)
assert np.all([np.allclose(expected[i], actual[i].value) for i in range(2)])
x_cl.value = 1 + x
assert not np.all([np.allclose(expected[i], actual[i].value) for i in range(2)])

def test_vsplit(self):
x = np.arange(16.0).reshape(4, 4)
x_cl = Variable(shape=x.shape)
x_cl.value = x
expected = np.vsplit(x, 2)
actual = aff.vsplit(x_cl, 2)
assert np.all([np.allclose(expected[i], actual[i].value) for i in range(2)])
x_cl.value = 1 + x
assert not np.all([np.allclose(expected[i], actual[i].value) for i in range(2)])

def test_dsplit(self):
x = np.arange(16.0).reshape(2, 2, 4)
x_cl = Variable(shape=x.shape)
x_cl.value = x
expected = np.dsplit(x, 2)
actual = aff.dsplit(x_cl, 2)
assert np.all([np.allclose(expected[i], actual[i].value) for i in range(2)])
x_cl.value = 1 + x
assert not np.all([np.allclose(expected[i], actual[i].value) for i in range(2)])

def test_array_split(self):
x = np.arange(8.0)
x_cl = Variable(shape=x.shape)
x_cl.value = x
expected = np.array_split(x, 3)
actual = aff.array_split(x_cl, 3)
assert np.all([np.allclose(expected[i], actual[i].value) for i in range(3)])
x_cl.value = 1 + x
assert not np.all([np.allclose(expected[i], actual[i].value) for i in range(3)])

def test_tile(self):
x = np.array([0, 1, 2])
x_cl = Variable(shape=x.shape)
x_cl.value = x
A = aff.tile(x_cl, 2)
assert np.allclose(np.tile(x, 2), A.value)
expr0 = aff.sum(A)
expr1 = aff.sum(x) * 2
assert Expression.are_equivalent(expr0.value, expr1)

def test_repeat(self):
x = np.array([3])
x_cl = Variable(shape=x.shape)
x_cl.value = x
A = aff.repeat(x_cl, 4)
assert np.allclose(np.repeat(x, 4), A.value)
expr0 = aff.sum(A.value)
expr1 = aff.sum(x_cl) * 4
assert Expression.are_equivalent(expr0, expr1.value)
# x_cl.value = x + 1
# assert not np.allclose(np.repeat(x, 4), A)

x1 = np.array([[1, 2], [3, 4]])
x1_cl = Variable(shape=x1.shape)
x1_cl.value = x1
A1 = aff.repeat(x1_cl, 2)
assert np.allclose(np.repeat(x1, 2), A1.value)
expr2 = aff.sum(A1.value)
expr3 = aff.sum(x1_cl) * 2
assert Expression.are_equivalent(expr2, expr3.value)

def test_diagflat(self):
x = np.array([[1, 2], [3, 4]])
x_cl = Variable(shape=x.shape)
x_cl.value = x
expected = np.diagflat(x)
actual = aff.diagflat(x_cl)
assert np.allclose(expected, actual.value)

def test_tril(self):
A = np.random.randn(5, 5).round(decimals=3)
A_cl = Variable(shape=A.shape)
A_cl.value = A
temp = aff.tril(A)
expr0 = aff.sum(temp)
expr1 = aff.sum(np.tril(A_cl))
assert Expression.are_equivalent(expr0, expr1.value)

def test_triu(self):
A = np.random.randn(5, 5).round(decimals=3)
A_cl = Variable(shape=A.shape)
A_cl.value = A
temp = aff.triu(A)
expr0 = aff.sum(temp)
expr1 = aff.sum(np.triu(A_cl))
assert Expression.are_equivalent(expr0, expr1.value)
46 changes: 46 additions & 0 deletions sageopt/tests/test_coniclifts/test_problem.py
@@ -0,0 +1,46 @@
import unittest
import numpy as np
import time
from sageopt.coniclifts.standards import constants as CL_CONSTANTS
from sageopt.coniclifts.problems.solvers.ecos import ECOS
from sageopt.coniclifts.problems.solvers.mosek import Mosek
from sageopt.coniclifts.compilers import compile_problem
from sageopt.coniclifts.base import Expression, Variable
from sageopt.coniclifts import Problem, Constraint
import sageopt.coniclifts as cl

class TestProblem(unittest.TestCase):
def test_parse_integer_constraints(self):
x = Variable(shape=(3,), name='my_name_x')
y = Variable(shape=(3,), name='my_name_y')
z = Variable(shape=(3,), name='my_name_z')
invalid_lst = [2, 4, 6]
self.assertRaises(ValueError, Problem._parse_integer_constraints, x, invalid_lst)
valid_lst = [x, y, z]

prob = cl.Problem(cl.MIN, cl.sum(x), [x==1, y == 0, z == -1])
prob.variable_map = {'my_name_x': np.array([0, 1]),
'my_name_y': np.array([1, 2]),
'my_name_z': np.array([2, 3])
}
prob._parse_integer_constraints(valid_lst)
int_indices_expected = [0, 1, 1, 2, 2, 3]
assert Expression.are_equivalent(int_indices_expected, prob._integer_indices)
prob1 = cl.Problem(cl.MIN, cl.sum(x), [x==1, y == 0, z[:-1] == -1])
self.assertRaises(ValueError, Problem._parse_integer_constraints, prob1, valid_lst)
z_part = z[:-1]
self.assertRaises(ValueError, Problem._parse_integer_constraints, prob1, [x, y, z_part])

def test_variables(self):
# random problem data
G = np.random.randn(3, 6)
h = G @ np.random.rand(6)
c = np.random.rand(6)
# input to coniclift's Problem constructor
x = cl.Variable(shape=(6,))
constrs = [0 <= x, G @ x == h]
objective_expression = c @ x
prob = cl.Problem(cl.MIN, objective_expression, constrs)
x = Variable(shape=(3,), name='my_name')
shallow_copy = [v for v in prob.all_variables]
assert Expression.are_equivalent(shallow_copy, prob.variables())

0 comments on commit 4ee48e1

Please sign in to comment.