Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions src/pyscipopt/scip.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,7 @@ cdef extern from "scip/scip.h":
SCIP_Real SCIPgetDualbound(SCIP* scip)
SCIP_Real SCIPgetDualboundRoot(SCIP* scip)
SCIP_Real SCIPgetVarRedcost(SCIP* scip, SCIP_VAR* var)
SCIP_RETCODE SCIPgetDualSolVal(SCIP* scip, SCIP_CONS* cons, SCIP_Real* dualsolval, SCIP_Bool* boundconstraint)

# Reader plugin
SCIP_RETCODE SCIPincludeReader(SCIP* scip,
Expand Down
56 changes: 32 additions & 24 deletions src/pyscipopt/scip.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2053,36 +2053,44 @@ cdef class Model:
:param Constraint cons: linear constraint

"""
# TODO this should ideally be handled on the SCIP side
cdef SCIP_Real dualsolval
cdef SCIP_Bool boundconstraint
cdef int _nvars
cdef SCIP_VAR** _vars
cdef SCIP_Real* _vals
cdef SCIP_Bool _success
dual = 0.0

constype = bytes(SCIPconshdlrGetName(SCIPconsGetHdlr(cons.cons))).decode('UTF-8')
if not constype == 'linear':
raise Warning("dual solution values not available for constraints of type ", constype)
if self.version() > 6.0:
PY_SCIP_CALL( SCIPgetDualSolVal(self._scip, cons.cons, &dualsolval, &boundconstraint) )
return dualsolval
else:
dual = 0.0

try:
_nvars = SCIPgetNVarsLinear(self._scip, cons.cons)
if cons.isOriginal():
transcons = <Constraint>self.getTransformedCons(cons)
else:
transcons = cons
dual = SCIPgetDualsolLinear(self._scip, transcons.cons)
if dual == 0.0 and _nvars == 1:
_vars = SCIPgetVarsLinear(self._scip, transcons.cons)
LPsol = SCIPvarGetLPSol(_vars[0])
rhs = SCIPgetRhsLinear(self._scip, transcons.cons)
lhs = SCIPgetLhsLinear(self._scip, transcons.cons)
if (LPsol == rhs) or (LPsol == lhs):
dual = SCIPgetVarRedcost(self._scip, _vars[0])
constype = bytes(SCIPconshdlrGetName(SCIPconsGetHdlr(cons.cons))).decode('UTF-8')
if not constype == 'linear':
raise Warning("dual solution values not available for constraints of type ", constype)

if self.getObjectiveSense() == "maximize":
dual = -dual
except:
raise Warning("no dual solution available for constraint " + cons.name)
return dual
try:
_nvars = SCIPgetNVarsLinear(self._scip, cons.cons)
if cons.isOriginal():
transcons = <Constraint>self.getTransformedCons(cons)
else:
transcons = cons
dual = SCIPgetDualsolLinear(self._scip, transcons.cons)
if dual == 0.0 and _nvars == 1:
_vars = SCIPgetVarsLinear(self._scip, transcons.cons)
_vals = SCIPgetValsLinear(self._scip, transcons.cons)
activity = SCIPvarGetLPSol(_vars[0]) * _vals[0]
rhs = SCIPgetRhsLinear(self._scip, transcons.cons)
lhs = SCIPgetLhsLinear(self._scip, transcons.cons)
if (activity == rhs) or (activity == lhs):
dual = SCIPgetVarRedcost(self._scip, _vars[0])

if self.getObjectiveSense() == "maximize" and not dual == 0.0:
dual = -dual
except:
raise Warning("no dual solution available for constraint " + cons.name)
return dual

def getDualfarkasLinear(self, Constraint cons):
"""Retrieve the dual farkas value to a linear constraint.
Expand Down