Skip to content

Commit 5a58058

Browse files
authored
Merge branch 'master' into addmatrixcons
2 parents 88ffccf + 5eecd95 commit 5a58058

File tree

4 files changed

+88
-12
lines changed

4 files changed

+88
-12
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
- Added addMatrixConsIndicator(), and tests
1010
- Added SCIPvarMarkRelaxationOnly, SCIPvarIsRelaxationOnly, SCIPvarMarkDeletable, SCIPvarIsDeletable, and tests
1111
- 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
1214
### Fixed
1315
- Raised an error when an expression is used when a variable is required
1416
### Changed

src/pyscipopt/scip.pxd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,7 @@ cdef extern from "scip/scip.h":
858858
SCIP_RETCODE SCIPtransformCons(SCIP* scip, SCIP_CONS* cons, SCIP_CONS** transcons)
859859
SCIP_RETCODE SCIPgetTransformedCons(SCIP* scip, SCIP_CONS* cons, SCIP_CONS** transcons)
860860
SCIP_RETCODE SCIPgetConsVars(SCIP* scip, SCIP_CONS* cons, SCIP_VAR** vars, int varssize, SCIP_Bool* success)
861+
SCIP_RETCODE SCIPgetConsVals(SCIP* scip, SCIP_CONS* cons, SCIP_Real* vals, int valssize, SCIP_Bool* success)
861862
SCIP_RETCODE SCIPgetConsNVars(SCIP* scip, SCIP_CONS* cons, int* nvars, SCIP_Bool* success)
862863
SCIP_CONS** SCIPgetConss(SCIP* scip)
863864
const char* SCIPconsGetName(SCIP_CONS* cons)
@@ -1477,6 +1478,8 @@ cdef extern from "scip/cons_linear.h":
14771478
SCIP_RETCODE SCIPchgRhsLinear(SCIP* scip, SCIP_CONS* cons, SCIP_Real rhs)
14781479
SCIP_Real SCIPgetLhsLinear(SCIP* scip, SCIP_CONS* cons)
14791480
SCIP_Real SCIPgetRhsLinear(SCIP* scip, SCIP_CONS* cons)
1481+
SCIP_Real SCIPconsGetLhs(SCIP* scip, SCIP_CONS* cons, SCIP_Bool* success)
1482+
SCIP_Real SCIPconsGetRhs(SCIP* scip, SCIP_CONS* cons, SCIP_Bool* success)
14801483
SCIP_RETCODE SCIPchgCoefLinear(SCIP* scip, SCIP_CONS* cons, SCIP_VAR* var, SCIP_Real newval)
14811484
SCIP_RETCODE SCIPdelCoefLinear(SCIP* scip, SCIP_CONS* cons, SCIP_VAR*)
14821485
SCIP_RETCODE SCIPaddCoefLinear(SCIP* scip, SCIP_CONS* cons, SCIP_VAR*, SCIP_Real val)

src/pyscipopt/scip.pxi

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2196,6 +2196,18 @@ cdef class Constraint:
21962196
constype = bytes(SCIPconshdlrGetName(SCIPconsGetHdlr(self.scip_cons))).decode('UTF-8')
21972197
return constype == 'knapsack'
21982198

2199+
def isLinearType(self):
2200+
"""
2201+
Returns True if constraint can be represented as a linear constraint.
2202+
2203+
Returns
2204+
-------
2205+
bool
2206+
2207+
"""
2208+
constype = bytes(SCIPconshdlrGetName(SCIPconsGetHdlr(self.scip_cons))).decode('UTF-8')
2209+
return constype in ('linear', 'knapsack', 'setppc', 'logicor', 'varbound')
2210+
21992211
def isNonlinear(self):
22002212
"""
22012213
Returns True if constraint is nonlinear.
@@ -6024,7 +6036,11 @@ cdef class Model:
60246036

60256037
SCIPgetConsNVars(self._scip, constraint.scip_cons, &nvars, &success)
60266038
_vars = <SCIP_VAR**> malloc(nvars * sizeof(SCIP_VAR*))
6027-
SCIPgetConsVars(self._scip, constraint.scip_cons, _vars, nvars*sizeof(SCIP_VAR*), &success)
6039+
SCIPgetConsVars(self._scip, constraint.scip_cons, _vars, nvars, &success)
6040+
6041+
if not success:
6042+
free(_vars)
6043+
return None
60286044

60296045
vars = []
60306046
for i in range(nvars):
@@ -6039,7 +6055,39 @@ cdef class Model:
60396055
self._modelvars[ptr] = var
60406056
vars.append(var)
60416057

6058+
free(_vars)
60426059
return vars
6060+
6061+
def getConsVals(self, Constraint constraint):
6062+
"""
6063+
Returns the value array of an arbitrary SCIP constraint that can be represented as a single linear constraint.
6064+
6065+
Parameters
6066+
----------
6067+
constraint : Constraint
6068+
Constraint to get the values from.
6069+
6070+
Returns
6071+
-------
6072+
list of float
6073+
6074+
"""
6075+
cdef SCIP_Real* _vals
6076+
cdef int nvars
6077+
cdef SCIP_Bool success
6078+
cdef int i
6079+
6080+
nvars = self.getConsNVars(constraint)
6081+
_vals = <SCIP_Real*> malloc(nvars * sizeof(SCIP_Real))
6082+
PY_SCIP_CALL(SCIPgetConsVals(self._scip, constraint.scip_cons, _vals, nvars, &success))
6083+
6084+
if not success:
6085+
free(_vals)
6086+
return None
6087+
6088+
vals = [_vals[i] for i in range(nvars)]
6089+
free(_vals)
6090+
return vals
60436091

60446092
def getNVarsAnd(self, Constraint and_cons):
60456093
"""
@@ -6055,8 +6103,6 @@ cdef class Model:
60556103
int
60566104
60576105
"""
6058-
cdef int nvars
6059-
cdef SCIP_Bool success
60606106

60616107
return SCIPgetNVarsAnd(self._scip, and_cons.scip_cons)
60626108

@@ -6074,9 +6120,9 @@ cdef class Model:
60746120
list of Variable
60756121
60766122
"""
6123+
60776124
cdef SCIP_VAR** _vars
60786125
cdef int nvars
6079-
cdef SCIP_Bool success
60806126
cdef int i
60816127

60826128
constype = bytes(SCIPconshdlrGetName(SCIPconsGetHdlr(and_cons.scip_cons))).decode('UTF-8')
@@ -6114,8 +6160,8 @@ cdef class Model:
61146160
Variable
61156161
61166162
"""
6163+
61176164
cdef SCIP_VAR* _resultant
6118-
cdef SCIP_Bool success
61196165

61206166
_resultant = SCIPgetResultantAnd(self._scip, and_cons.scip_cons)
61216167

@@ -6145,8 +6191,7 @@ cdef class Model:
61456191
bool
61466192
61476193
"""
6148-
cdef SCIP_Bool success
6149-
6194+
61506195
return SCIPisAndConsSorted(self._scip, and_cons.scip_cons)
61516196

61526197
def sortAndCons(self, Constraint and_cons):
@@ -6159,7 +6204,6 @@ cdef class Model:
61596204
Constraint to sort.
61606205
61616206
"""
6162-
cdef SCIP_Bool success
61636207

61646208
PY_SCIP_CALL(SCIPsortAndCons(self._scip, and_cons.scip_cons))
61656209

@@ -7275,9 +7319,13 @@ cdef class Model:
72757319
float
72767320
72777321
"""
7322+
cdef SCIP_Bool success
72787323
constype = bytes(SCIPconshdlrGetName(SCIPconsGetHdlr(cons.scip_cons))).decode('UTF-8')
7279-
if constype == 'linear':
7280-
return SCIPgetRhsLinear(self._scip, cons.scip_cons)
7324+
7325+
if cons.isLinearType():
7326+
rhs = SCIPconsGetRhs(self._scip, cons.scip_cons, &success)
7327+
assert(success)
7328+
return rhs
72817329
elif constype == 'nonlinear':
72827330
return SCIPgetRhsNonlinear(cons.scip_cons)
72837331
else:
@@ -7316,9 +7364,13 @@ cdef class Model:
73167364
float
73177365
73187366
"""
7367+
cdef SCIP_Bool success
73197368
constype = bytes(SCIPconshdlrGetName(SCIPconsGetHdlr(cons.scip_cons))).decode('UTF-8')
7320-
if constype == 'linear':
7321-
return SCIPgetLhsLinear(self._scip, cons.scip_cons)
7369+
7370+
if cons.isLinearType():
7371+
lhs = SCIPconsGetLhs(self._scip, cons.scip_cons, &success)
7372+
assert(success)
7373+
return lhs
73227374
elif constype == 'nonlinear':
73237375
return SCIPgetLhsNonlinear(cons.scip_cons)
73247376
else:

tests/test_cons.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,23 @@ def test_getConsVars():
2727
c = m.addCons(quicksum(x[i] for i in x) <= 1)
2828
assert m.getConsVars(c) == [x[i] for i in x]
2929

30+
def test_getConsVals():
31+
n_vars = 100
32+
m = Model()
33+
x = {}
34+
for i in range(n_vars):
35+
x[i] = m.addVar("%i" % i, vtype="B")
36+
37+
c1 = m.addCons(quicksum(x[i] for i in x) <= 1)
38+
c2 = m.addConsKnapsack([x[i] for i in x], [i for i in range(1, n_vars+1)], 10)
39+
vals1 = m.getConsVals(c1)
40+
vals2 = m.getConsVals(c2)
41+
42+
assert len(vals1) == n_vars
43+
assert all(isinstance(v, float) for v in vals1)
44+
assert len(vals2) == n_vars
45+
assert all(isinstance(v, float) for v in vals2)
46+
assert m.getConsVals(c2) == [i for i in range(1, n_vars+1)]
3047

3148
def test_constraint_option_setting():
3249
m = Model()
@@ -266,6 +283,8 @@ def test_cons_knapsack():
266283
m.chgCapacityKnapsack(knapsack_cons, 5)
267284

268285
assert m.getCapacityKnapsack(knapsack_cons) == 5
286+
assert m.getRhs(knapsack_cons) == 5
287+
assert m.getLhs(knapsack_cons) == -m.infinity()
269288

270289
m.addCoefKnapsack(knapsack_cons, z, 3)
271290
weights = m.getWeightsKnapsack(knapsack_cons)

0 commit comments

Comments
 (0)