Skip to content

BUG: _VarArray can't handle MatrixVar #1044

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
Aug 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
885865a
Refactor _VarArray initialization and type checks
Zeroto521 Jul 31, 2025
9451cc6
Refactor _VarArray to support MatrixVariable input
Zeroto521 Jul 31, 2025
7ee3a6f
Add test for indicator constraint with matrix binary var
Zeroto521 Jul 31, 2025
2cde7a6
Update CHANGELOG.md
Zeroto521 Jul 31, 2025
50bb995
Declare ptr variable in create_ptr function
Zeroto521 Jul 31, 2025
d72f951
Refactor create_ptr to remove redundant size argument
Zeroto521 Jul 31, 2025
110679f
Refactor _VarArray initialization logic
Zeroto521 Jul 31, 2025
f181cf4
Update CHANGELOG
Zeroto521 Jul 31, 2025
0346c52
Update test for addConsIndicator with activeone flag
Zeroto521 Jul 31, 2025
68f2e44
ENH: flatten list
Zeroto521 Aug 1, 2025
5580e12
BUG: use `np.ravel` avoid to run out of vars range
Zeroto521 Aug 1, 2025
8fc900c
Merge branch 'master' into fix/1043
Joao-Dionisio Aug 2, 2025
d52eb54
test binvar with (1, 1, 1) matrix
Zeroto521 Aug 3, 2025
8424c6d
test binvar with (2, 3) matrix
Zeroto521 Aug 3, 2025
710a836
test binvar with (2, 1) list of lists
Zeroto521 Aug 3, 2025
3b64e79
correct index
Zeroto521 Aug 3, 2025
2be1117
Add TypeError test for addConsIndicator with binvar
Zeroto521 Aug 4, 2025
7277e55
Merge branch 'master' into fix/1043
Joao-Dionisio Aug 16, 2025
09e3a0f
Only requiring a 1D array
Zeroto521 Aug 18, 2025
c749183
TST: raise an error while get not 1D array
Zeroto521 Aug 18, 2025
cba76c2
MAINT: Update error message
Zeroto521 Aug 18, 2025
44de7b7
TST: update error type
Zeroto521 Aug 18, 2025
1fd24a9
Update CHANGELOG.md
Zeroto521 Aug 18, 2025
1a3d2e1
Fix _VarArray initialization for empty input
Zeroto521 Aug 18, 2025
e17f68b
Remove _VarArray changing from changelog
Zeroto521 Aug 18, 2025
d280764
TST: update the comparing method
Zeroto521 Aug 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 15 additions & 13 deletions src/pyscipopt/scip.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@
if rc == SCIP_OKAY:
pass
elif rc == SCIP_ERROR:
raise Exception('SCIP: unspecified error!')

Check failure on line 311 in src/pyscipopt/scip.pxi

View workflow job for this annotation

GitHub Actions / test-coverage (3.11)

SCIP: unspecified error!
elif rc == SCIP_NOMEMORY:
raise MemoryError('SCIP: insufficient memory error!')
elif rc == SCIP_READERROR:
Expand Down Expand Up @@ -2498,22 +2498,24 @@
cdef int size

def __cinit__(self, object vars):
self.ptr = NULL
self.size = 0

if isinstance(vars, Variable):
self.size = 1
self.ptr = <SCIP_VAR**> malloc(sizeof(SCIP_VAR*))
self.ptr[0] = (<Variable>vars).scip_var
vars = [vars]
elif isinstance(vars, (list, tuple, MatrixVariable)):
if (ndim := np.ndim(vars)) != 1:
raise ValueError(f"Expected a 1D array, but got a {ndim}D array.")
else:
if not isinstance(vars, (list, tuple)):
raise TypeError("Expected Variable or list of Variable, got %s." % type(vars))
raise TypeError(f"Expected Variable or list of Variable, got {type(vars)}.")

if vars:
self.size = len(vars)
if self.size == 0:
self.ptr = NULL
else:
self.ptr = <SCIP_VAR**> malloc(self.size * sizeof(SCIP_VAR*))
for i, var in enumerate(vars):
if not isinstance(var, Variable):
raise TypeError("Expected Variable, got %s." % type(var))
self.ptr[i] = (<Variable>var).scip_var
self.ptr = <SCIP_VAR**> malloc(self.size * sizeof(SCIP_VAR*))
for i, var in enumerate(vars):
if not isinstance(var, Variable):
raise TypeError(f"Expected Variable, got {type(var)}.")
self.ptr[i] = (<Variable>var).scip_var

def __dealloc__(self):
if self.ptr != NULL:
Expand Down
31 changes: 31 additions & 0 deletions tests/test_cons.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,37 @@ def test_cons_indicator():
assert m.isEQ(m.getVal(x), 1)
assert c1.getConshdlrName() == "indicator"

def test_cons_indicator_with_matrix_binvar():
# test matrix variable binvar #1043
m = Model()
x = m.addVar(vtype="B")

# test binvar with int
with pytest.raises(TypeError):
m.addConsIndicator(x <= 0, 1)

# test binvar with (1, 1, 1) shape of matrix variable
with pytest.raises(ValueError):
m.addConsIndicator(x <= 0, m.addMatrixVar(((1, 1, 1)), vtype="B"))

# test binvar with (2, 3) shape of matrix variable
with pytest.raises(ValueError):
m.addConsIndicator(x <= 0, m.addMatrixVar(((2, 3)), vtype="B"))

# test binvar with (2, 1) shape of list of lists
with pytest.raises(ValueError):
m.addConsIndicator(x <= 0, [[m.addVar(vtype="B")], [m.addVar(vtype="B")]])

# test binvar with requiring type and dimension
binvar = m.addMatrixVar(1, vtype="B")
m.addConsIndicator(x >= 1, binvar, activeone=True)
m.addConsIndicator(x <= 0, binvar, activeone=False)

m.setObjective(binvar.sum(), "maximize")
m.optimize()

assert m.isEQ(m.getVal(x), 1)

@pytest.mark.xfail(
reason="addConsIndicator doesn't behave as expected when binary variable is False. See Issue #717."
)
Expand Down