Skip to content

Commit 3e586c4

Browse files
Merge branch 'master' into debugSol
2 parents c3d59f6 + ec86843 commit 3e586c4

17 files changed

Lines changed: 536 additions & 44 deletions

.github/workflows/coverage.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ jobs:
4040
4141
- name: Install PySCIPOpt
4242
run: |
43-
export CFLAGS="-O0 -ggdb" # disable compiler optimizations for faster builds
44-
python -m pip install .
43+
export CFLAGS="-O0 -ggdb -Wall -Wextra -Werror" # Debug mode. More warnings. Warnings as errors.
44+
python -m pip install . -v 2>&1 | tee build.log
45+
grep -i "warning" build.log || true
4546
4647
- name: Run pyscipopt tests
4748
run: |

CHANGELOG.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,22 @@
22

33
## Unreleased
44
### Added
5-
- Added enableDebugSol() and disableDebugSol() for controlling the debug solution mechanism if DEBUGSOL=true
65
- More support for AND-Constraints
76
- Added support for knapsack constraints
87
- Added isPositive(), isNegative(), isFeasLE(), isFeasLT(), isFeasGE(), isFeasGT(), isHugeValue(), and tests
98
- Added SCIP_LOCKTYPE, addVarLocksType(), getNLocksDown(), getNLocksUp(), getNLocksDownType(), getNLocksUpType(), and tests
9+
- Added addMatrixConsIndicator(), and tests
10+
- Added SCIPvarMarkRelaxationOnly, SCIPvarIsRelaxationOnly, SCIPvarMarkDeletable, SCIPvarIsDeletable, and tests
11+
- Wrapped SCIPgetNLPBranchCands
12+
- Added getConsVals() to get coefficients of any linear type constraint
13+
- Generalized getLhs() and getRhs() to additionally support any linear type constraint
14+
- Added recipe for getting local constraints
15+
- Added enableDebugSol() and disableDebugSol() for controlling the debug solution mechanism if DEBUGSOL=true
1016
### Fixed
1117
- Raised an error when an expression is used when a variable is required
18+
- Fixed some compile warnings
1219
### Changed
20+
- MatrixExpr.sum() now supports axis arguments and can return either a scalar or MatrixExpr depending on the result dimensions
1321
### Removed
1422

1523
## 5.5.0 - 2025.05.06

INSTALL.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ If installing SCIP from source or using PyPI with a python and operating system
2626
you need to specify the install location using the environment variable
2727
`SCIPOPTDIR`:
2828

29-
- on Linux and OS X:\
29+
- on Linux and MacOS:\
3030
`export SCIPOPTDIR=<path_to_install_dir>`
3131
- on Windows:\
3232
`set SCIPOPTDIR=<path_to_install_dir>` (**cmd**, **Cmder**, **WSL**)\
@@ -45,8 +45,9 @@ contains the corresponding header files:
4545
> nlpi
4646
> ...
4747

48-
Please note that some Mac configurations require adding the library installation path to `DYLD_LIBRARY_PATH` when using a locally installed version of SCIP.
48+
On MacOS, to ensure that the SCIP dynamic library can be located at runtime by PySCIPOpt, you should add your SCIP installation path to the ``DYLD_LIBRARY_PATH`` environment variable by running:
4949

50+
`export DYLD_LIBRARY_PATH="<path_to_install_dir>/lib:$DYLD_LIBRARY_PATH"`
5051

5152
When building SCIP from source using Windows it is highly recommended to use the [Anaconda Python
5253
Platform](https://www.anaconda.com/).
@@ -75,7 +76,7 @@ at runtime by adjusting your `PATH` environment variable:
7576

7677
- on Windows: `set PATH=%PATH%;%SCIPOPTDIR%\bin`
7778

78-
On Linux and OS X this is encoded in the generated PySCIPOpt library and
79+
On Linux and MacOS this is encoded in the generated PySCIPOpt library and
7980
therefore not necessary.
8081

8182
Building everything from source

docs/build.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,15 @@ For Linux and MacOS systems set the variable with the following command:
100100
101101
export SCIPOPTDIR=<path_to_install_dir>
102102
103+
.. note::
104+
105+
For macOS users, to ensure that the SCIP dynamic library can be found at runtime by PySCIPOpt,
106+
you should add your SCIP installation path to the ``DYLD_LIBRARY_PATH`` environment variable by running:
107+
108+
.. code-block::
109+
110+
export DYLD_LIBRARY_PATH="<path_to_install_dir>/lib:$DYLD_LIBRARY_PATH"
111+
103112
For Windows use the following command:
104113

105114
.. code-block:: bash

src/pyscipopt/event.pxi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ cdef class Eventhdlr:
3939

4040

4141
# local helper functions for the interface
42-
cdef Eventhdlr getPyEventhdlr(SCIP_EVENTHDLR* eventhdlr) noexcept with gil:
42+
cdef Eventhdlr getPyEventhdlr(SCIP_EVENTHDLR* eventhdlr):
4343
cdef SCIP_EVENTHDLRDATA* eventhdlrdata
4444
eventhdlrdata = SCIPeventhdlrGetData(eventhdlr)
4545
return <Eventhdlr>eventhdlrdata

src/pyscipopt/expr.pxi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ cdef class ExprCons:
358358
def __repr__(self):
359359
return 'ExprCons(%s, %s, %s)' % (self.expr, self._lhs, self._rhs)
360360

361-
def __nonzero__(self):
361+
def __bool__(self):
362362
'''Make sure that equality of expressions is not asserted with =='''
363363

364364
msg = """Can't evaluate constraints as booleans.

src/pyscipopt/lp.pxi

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ cdef class LP:
5858
"""Adds a single column to the LP.
5959
6060
Keyword arguments:
61-
entries -- list of tuples, each tuple consists of a row index and a coefficient
61+
entries -- a list of tuples; if p is the index of the new column, then each tuple (i, k) indicates that
62+
A[i][p] = k, where A is the constraint matrix and k is a nonzero entry.
6263
obj -- objective coefficient (default 0.0)
6364
lb -- lower bound (default 0.0)
6465
ub -- upper bound (default infinity)
@@ -85,7 +86,8 @@ cdef class LP:
8586
"""Adds multiple columns to the LP.
8687
8788
Keyword arguments:
88-
entrieslist -- list containing lists of tuples, each tuple contains a coefficient and a row index
89+
entrieslist -- a list of lists, where the j-th inner list contains tuples (i, k) such that A[i][p] = k,
90+
where A is the constraint matrix, p is the index of the j-th new column, and k is a nonzero entry.
8991
objs -- objective coefficient (default 0.0)
9092
lbs -- lower bounds (default 0.0)
9193
ubs -- upper bounds (default infinity)
@@ -147,7 +149,8 @@ cdef class LP:
147149
"""Adds a single row to the LP.
148150
149151
Keyword arguments:
150-
entries -- list of tuples, each tuple contains a coefficient and a column index
152+
entries -- a list of tuples; if q is the index of the new row, then each tuple (j, k) indicates that
153+
A[q][j] = k, where A is the constraint matrix and k is a nonzero entry.
151154
lhs -- left-hand side of the row (default 0.0)
152155
rhs -- right-hand side of the row (default infinity)
153156
"""
@@ -172,7 +175,8 @@ cdef class LP:
172175
"""Adds multiple rows to the LP.
173176
174177
Keyword arguments:
175-
entrieslist -- list containing lists of tuples, each tuple contains a coefficient and a column index
178+
entrieslist -- a list of lists, where the i-th inner list contains tuples (j, k) such that A[q][j] = k,
179+
where A is the constraint matrix, q is the index of the i-th new row, and k is a nonzero entry.
176180
lhss -- left-hand side of the row (default 0.0)
177181
rhss -- right-hand side of the row (default infinity)
178182
"""

src/pyscipopt/matrix.pxi

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@ def _is_number(e):
1717

1818
class MatrixExpr(np.ndarray):
1919
def sum(self, **kwargs):
20-
return super().sum(**kwargs).item()
21-
20+
"""
21+
Based on `numpy.ndarray.sum`, but returns a scalar if the result is a single value.
22+
This is useful for matrix expressions where the sum might reduce to a single value.
23+
"""
24+
res = super().sum(**kwargs)
25+
return res if res.size > 1 else res.item()
26+
2227
def __le__(self, other: Union[float, int, Variable, np.ndarray, 'MatrixExpr']) -> np.ndarray:
2328

2429
expr_cons_matrix = np.empty(self.shape, dtype=object)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from pyscipopt import Model, Constraint
2+
3+
def getLocalConss(model: Model, node = None) -> list[list[Constraint]]:
4+
"""
5+
Returns local constraints.
6+
7+
Parameters
8+
----------
9+
model : Model
10+
The model from which to retrieve the local constraints.
11+
node : Node, optional
12+
The node from which to retrieve the local constraints. If not provided, the current node is used.
13+
14+
Returns
15+
-------
16+
list[Constraint]
17+
A list of local constraints. First entry are global constraints, second entry are all the added constraints.
18+
"""
19+
20+
if node is None:
21+
assert model.getStageName() in ["INITPRESOLVE", "PRESOLVING", "EXITPRESOLVE", "SOLVING"], "Model cannot be called in stage %s." % model.getStageName()
22+
cur_node = model.getCurrentNode()
23+
else:
24+
cur_node = node
25+
26+
added_conss = []
27+
while cur_node is not None:
28+
added_conss = cur_node.getAddedConss() + added_conss
29+
cur_node = cur_node.getParent()
30+
31+
return [model.getConss(), added_conss]
32+
33+
def getNLocalConss(model: Model, node = None) -> tuple[int,int]:
34+
"""
35+
Returns the number of local constraints of a node.
36+
37+
Parameters
38+
----------
39+
model : Model
40+
The model from which to retrieve the number of local constraints.
41+
node : Node, optional
42+
The node from which to retrieve the number of local constraints. If not provided, the current node is used.
43+
44+
Returns
45+
-------
46+
list[int]
47+
A list of the number of local constraints. First entry is the number of global constraints, second entry is the number of all the added constraints.
48+
"""
49+
local_conss = getLocalConss(model, node)
50+
return [len(local_conss[0]), len(local_conss[1])]

src/pyscipopt/recipes/nonlinear.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from pyscipopt import Model
22

3-
43
def set_nonlinear_objective(model: Model, expr, sense="minimize"):
54
"""
65
Takes a nonlinear expression and performs an epigraph reformulation.

0 commit comments

Comments
 (0)