Skip to content

Commit

Permalink
removing value errors when declaring multiple attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
William Zijie Zhang authored and William Zijie Zhang committed Aug 5, 2024
1 parent 209660c commit ad53ec7
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 21 deletions.
9 changes: 0 additions & 9 deletions cvxpy/expressions/leaf.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,6 @@ def __init__(
else:
self.integer_idx = []

# Only one attribute be True (except can be boolean and integer).
true_attr = sum(1 for k, v in self.attributes.items() if v)
# HACK we should remove this feature or allow multiple attributes in general.
if boolean and integer:
true_attr -= 1
if true_attr > 1:
raise ValueError("Cannot set more than one special attribute in %s."
% self.__class__.__name__)

if value is not None:
self.value = value

Expand Down
41 changes: 29 additions & 12 deletions cvxpy/tests/test_expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"""

import warnings
from itertools import combinations

import numpy as np
import pytest
Expand Down Expand Up @@ -68,8 +69,6 @@ def test_variable(self) -> None:
self.assertEqual(x.shape, (2,))
self.assertEqual(y.shape, tuple())
self.assertEqual(x.curvature, s.AFFINE)
# self.assertEqual(x.canonical_form[0].shape, (2, 1))
# self.assertEqual(x.canonical_form[1], [])

self.assertEqual(repr(self.x), "Variable((2,), x)")
self.assertEqual(repr(self.A), "Variable((2, 2), A)")
Expand All @@ -79,11 +78,6 @@ def test_variable(self) -> None:
# Test shape provided as list instead of tuple
self.assertEqual(cp.Variable(shape=[2], integer=True).shape, (2,))

with self.assertRaises(Exception) as cm:
Variable((2, 2), diag=True, symmetric=True)
self.assertEqual(str(cm.exception),
"Cannot set more than one special attribute in Variable.")

with self.assertRaises(Exception) as cm:
Variable((2, 0))
self.assertEqual(str(cm.exception), "Invalid dimensions (2, 0).")
Expand Down Expand Up @@ -450,11 +444,6 @@ def test_parameters_failures(self) -> None:
p = Parameter((4, 3), nonneg=True, value=[1, 2])
self.assertEqual(str(cm.exception), "Invalid dimensions (2,) for Parameter value.")

with self.assertRaises(Exception) as cm:
p = Parameter((2, 2), diag=True, symmetric=True)
self.assertEqual(str(cm.exception),
"Cannot set more than one special attribute in Parameter.")

# Boolean
with self.assertRaises(Exception) as cm:
p = Parameter((2, 2), boolean=True, value=[[1, 1], [1, -1]])
Expand Down Expand Up @@ -1621,3 +1610,31 @@ def is_zero_dim_output(axis):
prob = cp.Problem(self.obj, [expr == y])
prob.solve(canon_backend=cp.SCIPY_CANON_BACKEND)
assert np.allclose(expr.value, y)

class Test_Attributes():

def test_multiple_attributes(self) -> None:
x = cp.Variable(shape=(2,2), symmetric=True, nonneg=True, integer=True, boolean=True)
target = np.array(np.eye(2))
prob = cp.Problem(cp.Minimize(0), [x == target])
prob.solve()
assert np.allclose(x.value, target)

# Define the attributes to test
attributes = [
'nonneg', 'pos', 'nonpos', 'neg', 'diag', 'PSD', 'NSD', 'imag', 'boolean', 'integer'
]

# Generate combinations of attributes
combinations_of_attributes = []
for r in range(1, len(attributes) + 1):
combinations_of_attributes.extend(combinations(attributes, r))

@pytest.mark.parametrize("attributes", combinations_of_attributes)
def test_variable_combinations(self, attributes):
kwargs = {attr: True for attr in attributes}
var = cp.Variable(shape=(2, 2), **kwargs)
target = np.array([[0, 1], [1, 0]])
prob = cp.Problem(cp.Minimize(0), [var == target])
prob.solve()
assert np.allclose(var.value, target)

0 comments on commit ad53ec7

Please sign in to comment.