Skip to content

Commit 52f7384

Browse files
committed
Merge branch 'feature/disjunctive-constraint' of github.com:ctdunc/pyscipopt into feature/disjunctive-constraint
2 parents 749c87c + 83d71c8 commit 52f7384

File tree

16 files changed

+325
-44
lines changed

16 files changed

+325
-44
lines changed

.github/workflows/coverage.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ jobs:
4343
4444
- name: Run pyscipopt tests
4545
run: |
46+
sudo apt-get install tzdata locales -y && sudo locale-gen pt_PT && sudo update-locale # add pt_PT locale that is used in tests
4647
coverage run -m pytest
4748
coverage report -m
4849
coverage xml

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,15 @@
22

33
## Unreleased
44
### Added
5+
- Added recipe for nonlinear objective functions
6+
- Added method for adding piecewise linear constraints
57
- Add SCIP function SCIPgetTreesizeEstimation and wrapper getTreesizeEstimation
8+
- New test for model setLogFile
69
### Fixed
10+
- Fixed model.setLogFile(None) error
11+
- Add recipes sub-package
12+
- Fixed "weakly-referenced object no longer exists" when calling dropEvent in test_customizedbenders
13+
- Fixed incorrect writing/printing when user had a non-default locale
714
### Changed
815
### Removed
916

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Building and solving a model
5555

5656
There are several [examples](https://github.com/scipopt/PySCIPOpt/blob/master/examples/finished) and
5757
[tutorials](https://github.com/scipopt/PySCIPOpt/blob/master/examples/tutorial). These display some functionality of the
58-
interface and can serve as an entry point for writing more complex code.
58+
interface and can serve as an entry point for writing more complex code. Some of the common usecases are also available in the [recipes](https://github.com/scipopt/PySCIPOpt/blob/master/src/pyscipopt/recipes) sub-package.
5959
You might also want to have a look at this article about PySCIPOpt:
6060
<https://opus4.kobv.de/opus4-zib/frontdoor/index/index/docId/6045>. The
6161
following steps are always required when using the interface:

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from setuptools import setup, Extension
1+
from setuptools import find_packages, setup, Extension
22
import os, platform, sys, re
33

44
# look for environment variable that specifies path to SCIP
@@ -124,7 +124,7 @@
124124
"Topic :: Scientific/Engineering :: Mathematics",
125125
],
126126
ext_modules=extensions,
127-
packages=["pyscipopt"],
127+
packages=find_packages(where="src"),
128128
package_dir={"pyscipopt": packagedir},
129129
package_data={"pyscipopt": ["scip.pyx", "scip.pxd", "*.pxi", "scip/lib/*"]},
130130
include_package_data=True,

src/pyscipopt/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
# export user-relevant objects:
1010
from pyscipopt.Multidict import multidict
1111
from pyscipopt.scip import Model
12+
from pyscipopt.scip import Variable
13+
from pyscipopt.scip import Constraint
1214
from pyscipopt.scip import Benders
1315
from pyscipopt.scip import Benderscut
1416
from pyscipopt.scip import Branchrule

src/pyscipopt/recipes/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Recipes sub-package
2+
3+
This sub-package provides a set of functions for common usecases for pyscipopt. This sub-package is for all functions that don't necessarily reflect the core functionality of SCIP, but are useful for working with the solver. The functions implemented in this sub-package might not be the most efficient way to solve/formulate a problem but would provide a good starting point.

src/pyscipopt/recipes/__init__.py

Whitespace-only changes.

src/pyscipopt/recipes/nonlinear.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from pyscipopt import Model
2+
3+
def set_nonlinear_objective(model: Model, expr, sense="minimize"):
4+
"""
5+
Takes a nonlinear expression and performs an epigraph reformulation.
6+
"""
7+
8+
assert expr.degree() > 1, "For linear objectives, please use the setObjective method."
9+
new_obj = model.addVar(lb=-float("inf"),obj=1)
10+
if sense == "minimize":
11+
model.addCons(expr <= new_obj)
12+
model.setMinimize()
13+
elif sense == "maximize":
14+
model.addCons(expr >= new_obj)
15+
model.setMaximize()
16+
else:
17+
raise Warning("unrecognized optimization sense: %s" % sense)
18+

src/pyscipopt/recipes/piecewise.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
from pyscipopt import Model, quicksum, Variable, Constraint
3+
4+
def add_piecewise_linear_cons(model: Model, X: Variable, Y: Variable, a: list[float], b: list[float]) -> Constraint:
5+
"""add constraint of the form y = f(x), where f is a piecewise linear function
6+
7+
:param X: x variable
8+
:param Y: y variable
9+
:param a: array with x-coordinates of the points in the piecewise linear relation
10+
:param b: array with y-coordinate of the points in the piecewise linear relation
11+
12+
Disclaimer: For the moment, can only model 2d piecewise linear functions
13+
Adapted from https://github.com/scipopt/PySCIPOpt/blob/master/examples/finished/piecewise.py
14+
"""
15+
assert len(a) == len(b), "Must have the same number of x and y-coordinates"
16+
17+
K = len(a)-1
18+
w,z = {},{}
19+
for k in range(K):
20+
w[k] = model.addVar(lb=-model.infinity())
21+
z[k] = model.addVar(vtype="B")
22+
23+
for k in range(K):
24+
model.addCons(w[k] >= a[k]*z[k])
25+
model.addCons(w[k] <= a[k+1]*z[k])
26+
27+
model.addCons(quicksum(z[k] for k in range(K)) == 1)
28+
29+
model.addCons(X == quicksum(w[k] for k in range(K)))
30+
31+
c = [float(b[k+1]-b[k]) / (a[k+1]-a[k]) for k in range(K)]
32+
d = [b[k] - c[k]*a[k] for k in range(K)]
33+
34+
new_cons = model.addCons(Y == quicksum(d[k]*z[k] + c[k]*w[k] for k in range(K)))
35+
36+
return new_cons

0 commit comments

Comments
 (0)