From 9e6edf9a078b1fdf33e302b9869ee3235c925832 Mon Sep 17 00:00:00 2001 From: 40% Date: Fri, 25 Jul 2025 09:31:57 +0800 Subject: [PATCH 01/14] API: `addMatrixCons` supports `ExprCons` --- src/pyscipopt/scip.pxi | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi index b615f96f2..303f5bb2e 100644 --- a/src/pyscipopt/scip.pxi +++ b/src/pyscipopt/scip.pxi @@ -5722,7 +5722,7 @@ cdef class Model: return constraints def addMatrixCons(self, - cons: MatrixExprCons, + cons: Union[ExprCons, MatrixExprCons], name: Union[str, np.ndarray] ='', initial: Union[bool, np.ndarray] = True, separate: Union[bool, np.ndarray] = True, @@ -5739,8 +5739,8 @@ cdef class Model: Parameters ---------- - cons : MatrixExprCons - The matrix expression constraint that is not yet an actual constraint + cons : ExprCons or MatrixExprCons + the matrix expression constraint or expression constraint following matrix dimension reduction name : str or np.ndarray, optional the name of the matrix constraint, generic name if empty (Default value = "") initial : bool or np.ndarray, optional @@ -5767,12 +5767,17 @@ cdef class Model: Returns ------- - MatrixConstraint - The created and added MatrixConstraint object. - + Constraint or MatrixConstraint + The created and added Constraint or MatrixConstraint object based on inputting. """ - assert isinstance(cons, MatrixExprCons), ( - "given constraint is not MatrixExprCons but %s" % cons.__class__.__name__) + assert isinstance(cons, (ExprCons, MatrixExprCons)), ( + "given constraint is not ExprCons or MatrixExprCons but %s" % cons.__class__.__name__) + + if isinstance(cons, ExprCons): + return self.addCons(cons, name=name, initial=initial, separate=separate, + enforce=enforce, check=check, propagate=propagate, + local=local, modifiable=modifiable, dynamic=dynamic, + removable=removable, stickingatnode=stickingatnode) shape = cons.shape From bd5d865924ea97464b529cd962263fb9afa65830 Mon Sep 17 00:00:00 2001 From: 40% Date: Fri, 25 Jul 2025 09:32:28 +0800 Subject: [PATCH 02/14] test error --- tests/test_matrix_variable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_matrix_variable.py b/tests/test_matrix_variable.py index 6242e97e7..2d6c436da 100644 --- a/tests/test_matrix_variable.py +++ b/tests/test_matrix_variable.py @@ -16,7 +16,7 @@ def test_catching_errors(): rhs = np.ones((2, 1)) with pytest.raises(Exception): - m.addMatrixCons(x <= 1) + m.addMatrixCons(x) with pytest.raises(Exception): m.addCons(y <= 3) From 2032732219f745aa646ae097033485dee3a6239a Mon Sep 17 00:00:00 2001 From: 40% Date: Fri, 25 Jul 2025 09:32:49 +0800 Subject: [PATCH 03/14] test accepting `ExprCons` --- tests/test_matrix_variable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_matrix_variable.py b/tests/test_matrix_variable.py index 2d6c436da..924afb443 100644 --- a/tests/test_matrix_variable.py +++ b/tests/test_matrix_variable.py @@ -169,7 +169,7 @@ def test_matrix_sum_argument(): # compare the result of summing 2d array to a scalar with a scalar x = m.addMatrixVar((2, 3), "x", "I", ub=4) - m.addCons(x.sum() == 24) + m.addMatrixCons(x.sum() == 24) # compare the result of summing 2d array to 1d array y = m.addMatrixVar((2, 4), "y", "I", ub=4) From 88ffccf9087e1d13dce0e954106c156ce01e2061 Mon Sep 17 00:00:00 2001 From: 40% Date: Fri, 25 Jul 2025 09:36:17 +0800 Subject: [PATCH 04/14] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b55ccad09..116df8d84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - Raised an error when an expression is used when a variable is required ### Changed - MatrixExpr.sum() now supports axis arguments and can return either a scalar or MatrixExpr depending on the result dimensions +- AddMatrixCons supports accepting ExprCons following matrix dimension reduction via MatrixExpr.sum() or more operation. ### Removed ## 5.5.0 - 2025.05.06 From e697bede09ffd3a6d6f9054a588aeb9313a70b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Dion=C3=ADsio?= <57299939+Joao-Dionisio@users.noreply.github.com> Date: Sun, 27 Jul 2025 08:51:01 +0100 Subject: [PATCH 05/14] Update CHANGELOG.md --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b8d395e9..e00177b46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,8 +16,8 @@ - Raised an error when an expression is used when a variable is required - Fixed some compile warnings ### Changed -- MatrixExpr.sum() now supports axis arguments and can return either a scalar or MatrixExpr depending on the result dimensions -- AddMatrixCons supports accepting ExprCons following matrix dimension reduction via MatrixExpr.sum() or more operation. +- MatrixExpr.sum() now supports axis arguments and can return either a scalar or MatrixExpr, depending on the result dimensions. +- AddMatrixCons also accepts ExprCons. ### Removed ## 5.5.0 - 2025.05.06 From b6e075dd04d187aaeca0b7b6f9ce35af8418d8ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Dion=C3=ADsio?= <57299939+Joao-Dionisio@users.noreply.github.com> Date: Sun, 27 Jul 2025 08:53:02 +0100 Subject: [PATCH 06/14] Update scip.pxi --- src/pyscipopt/scip.pxi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi index a469f03a2..a77a09cf4 100644 --- a/src/pyscipopt/scip.pxi +++ b/src/pyscipopt/scip.pxi @@ -5752,7 +5752,7 @@ cdef class Model: Parameters ---------- cons : ExprCons or MatrixExprCons - the matrix expression constraint or expression constraint following matrix dimension reduction + The matrix expression constraint or expression constraint name : str or np.ndarray, optional the name of the matrix constraint, generic name if empty (Default value = "") initial : bool or np.ndarray, optional @@ -5780,10 +5780,10 @@ cdef class Model: Returns ------- Constraint or MatrixConstraint - The created and added Constraint or MatrixConstraint object based on inputting. + The created and added Constraint or MatrixConstraint object based on the input. """ assert isinstance(cons, (ExprCons, MatrixExprCons)), ( - "given constraint is not ExprCons or MatrixExprCons but %s" % cons.__class__.__name__) + "given constraint is not MatrixExprCons nor ExprCons but %s" % cons.__class__.__name__) if isinstance(cons, ExprCons): return self.addCons(cons, name=name, initial=initial, separate=separate, From 812348ab58a191163f54971e0c9c98b5ca336faa Mon Sep 17 00:00:00 2001 From: 40% Date: Tue, 29 Jul 2025 09:03:13 +0800 Subject: [PATCH 07/14] Add comments to clarify error tests in matrix variable tests Added comments to the test_catching_errors function in test_matrix_variable.py to clarify the purpose of each exception test case. --- tests/test_matrix_variable.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_matrix_variable.py b/tests/test_matrix_variable.py index 924afb443..63610d7e1 100644 --- a/tests/test_matrix_variable.py +++ b/tests/test_matrix_variable.py @@ -15,12 +15,15 @@ def test_catching_errors(): y = m.addMatrixVar(shape=(3, 3)) rhs = np.ones((2, 1)) + # require MatrixExprCons or ExprCons with pytest.raises(Exception): m.addMatrixCons(x) + # require ExprCons with pytest.raises(Exception): m.addCons(y <= 3) + # test shape mismatch with pytest.raises(Exception): m.addMatrixCons(y <= rhs) From 2c4445c95aaf069b8c531c1acc0bb6d0921fc2c6 Mon Sep 17 00:00:00 2001 From: 40% Date: Tue, 29 Jul 2025 09:04:35 +0800 Subject: [PATCH 08/14] Move addCons testcase to top --- tests/test_matrix_variable.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_matrix_variable.py b/tests/test_matrix_variable.py index 63610d7e1..0308bb694 100644 --- a/tests/test_matrix_variable.py +++ b/tests/test_matrix_variable.py @@ -15,14 +15,14 @@ def test_catching_errors(): y = m.addMatrixVar(shape=(3, 3)) rhs = np.ones((2, 1)) - # require MatrixExprCons or ExprCons - with pytest.raises(Exception): - m.addMatrixCons(x) - # require ExprCons with pytest.raises(Exception): m.addCons(y <= 3) + # require MatrixExprCons or ExprCons + with pytest.raises(Exception): + m.addMatrixCons(x) + # test shape mismatch with pytest.raises(Exception): m.addMatrixCons(y <= rhs) From b3b40089ccf178215c39e1f03cf15c3ab9810f4f Mon Sep 17 00:00:00 2001 From: 40% Date: Tue, 29 Jul 2025 09:17:43 +0800 Subject: [PATCH 09/14] Add test for shape mismatch in addMatrixCons Added a test case to ensure addMatrixCons raises a ValueError when provided with an initial array of incorrect shape. --- tests/test_matrix_variable.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_matrix_variable.py b/tests/test_matrix_variable.py index 0308bb694..6fa34b1d2 100644 --- a/tests/test_matrix_variable.py +++ b/tests/test_matrix_variable.py @@ -27,6 +27,9 @@ def test_catching_errors(): with pytest.raises(Exception): m.addMatrixCons(y <= rhs) + # test shape mismatch + with pytest.raises(ValueError): + m.addMatrixCons(x == y.sum(), initial=np.array([False, True])) def test_add_matrixVar(): m = Model() From 3e249eac577e5bebebad10b9f165b10fdcae0a12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Dion=C3=ADsio?= <57299939+Joao-Dionisio@users.noreply.github.com> Date: Fri, 1 Aug 2025 20:13:26 +0100 Subject: [PATCH 10/14] Apply suggestions from code review --- CHANGELOG.md | 2 +- src/pyscipopt/scip.pxi | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4614bbd9..46a82d167 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ - Fixed some compile warnings ### Changed - MatrixExpr.sum() now supports axis arguments and can return either a scalar or MatrixExpr, depending on the result dimensions. -- AddMatrixCons also accepts ExprCons. +- AddMatrixCons() also accepts ExprCons. ### Removed ## 5.5.0 - 2025.05.06 diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi index 6cec62c2b..660013786 100644 --- a/src/pyscipopt/scip.pxi +++ b/src/pyscipopt/scip.pxi @@ -5793,7 +5793,7 @@ cdef class Model: Parameters ---------- cons : ExprCons or MatrixExprCons - The matrix expression constraint or expression constraint + The matrix expression constraint or expression constraint, that are not yet an actual constraint name : str or np.ndarray, optional the name of the matrix constraint, generic name if empty (Default value = "") initial : bool or np.ndarray, optional @@ -5821,7 +5821,7 @@ cdef class Model: Returns ------- Constraint or MatrixConstraint - The created and added Constraint or MatrixConstraint object based on the input. + The created and added Constraint or MatrixConstraint. """ assert isinstance(cons, (ExprCons, MatrixExprCons)), ( "given constraint is not MatrixExprCons nor ExprCons but %s" % cons.__class__.__name__) From bf226502280997ebfef8539753277346dc3e0153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Dion=C3=ADsio?= <57299939+Joao-Dionisio@users.noreply.github.com> Date: Sat, 2 Aug 2025 08:01:31 +0100 Subject: [PATCH 11/14] Update test_matrix_variable.py --- tests/test_matrix_variable.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/test_matrix_variable.py b/tests/test_matrix_variable.py index 6fa34b1d2..0308bb694 100644 --- a/tests/test_matrix_variable.py +++ b/tests/test_matrix_variable.py @@ -27,9 +27,6 @@ def test_catching_errors(): with pytest.raises(Exception): m.addMatrixCons(y <= rhs) - # test shape mismatch - with pytest.raises(ValueError): - m.addMatrixCons(x == y.sum(), initial=np.array([False, True])) def test_add_matrixVar(): m = Model() From da751bd333059c20cabd17cecfa0d1f6b73aaf27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Dion=C3=ADsio?= <57299939+Joao-Dionisio@users.noreply.github.com> Date: Sat, 2 Aug 2025 08:03:13 +0100 Subject: [PATCH 12/14] Update scip.pxi --- src/pyscipopt/scip.pxi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi index 660013786..19380e267 100644 --- a/src/pyscipopt/scip.pxi +++ b/src/pyscipopt/scip.pxi @@ -5823,8 +5823,8 @@ cdef class Model: Constraint or MatrixConstraint The created and added Constraint or MatrixConstraint. """ - assert isinstance(cons, (ExprCons, MatrixExprCons)), ( - "given constraint is not MatrixExprCons nor ExprCons but %s" % cons.__class__.__name__) + if not isinstance(cons, (ExprCons, MatrixExprCons)): + raise TypeError("given constraint is not MatrixExprCons nor ExprCons but %s" % cons.__class__.__name__) if isinstance(cons, ExprCons): return self.addCons(cons, name=name, initial=initial, separate=separate, From 490d9592938e08ebaff1463787dc8772ac041157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Dion=C3=ADsio?= <57299939+Joao-Dionisio@users.noreply.github.com> Date: Sat, 2 Aug 2025 08:12:31 +0100 Subject: [PATCH 13/14] tabs spaces --- src/pyscipopt/scip.pxi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi index 19380e267..1767ee78a 100644 --- a/src/pyscipopt/scip.pxi +++ b/src/pyscipopt/scip.pxi @@ -5824,7 +5824,7 @@ cdef class Model: The created and added Constraint or MatrixConstraint. """ if not isinstance(cons, (ExprCons, MatrixExprCons)): - raise TypeError("given constraint is not MatrixExprCons nor ExprCons but %s" % cons.__class__.__name__) + raise TypeError("given constraint is not MatrixExprCons nor ExprCons but %s" % cons.__class__.__name__) if isinstance(cons, ExprCons): return self.addCons(cons, name=name, initial=initial, separate=separate, From e0da92e4463383cccd6fdfc65d62bf03f94b8bee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Dion=C3=ADsio?= <57299939+Joao-Dionisio@users.noreply.github.com> Date: Sat, 2 Aug 2025 08:22:49 +0100 Subject: [PATCH 14/14] tabs and spaces finally? --- src/pyscipopt/scip.pxi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi index 1767ee78a..fa33be017 100644 --- a/src/pyscipopt/scip.pxi +++ b/src/pyscipopt/scip.pxi @@ -5823,8 +5823,8 @@ cdef class Model: Constraint or MatrixConstraint The created and added Constraint or MatrixConstraint. """ - if not isinstance(cons, (ExprCons, MatrixExprCons)): - raise TypeError("given constraint is not MatrixExprCons nor ExprCons but %s" % cons.__class__.__name__) + if not isinstance(cons, (ExprCons, MatrixExprCons)): + raise TypeError("given constraint is not MatrixExprCons nor ExprCons but %s" % cons.__class__.__name__) if isinstance(cons, ExprCons): return self.addCons(cons, name=name, initial=initial, separate=separate,