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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- Generalized getLhs() and getRhs() to additionally support any linear type constraint
- Added recipe for getting local constraints
- Added enableDebugSol() and disableDebugSol() for controlling the debug solution mechanism if DEBUGSOL=true
- Added getVarPseudocostScore() and getVarPseudocost()
### Fixed
- Raised an error when an expression is used when a variable is required
- Fixed some compile warnings
Expand Down
1 change: 1 addition & 0 deletions src/pyscipopt/scip.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,7 @@ cdef extern from "scip/scip.h":
void SCIPvarMarkDeletable(SCIP_VAR* var)
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR* var)
SCIP_Real SCIPgetVarPseudocost(SCIP* scip, SCIP_VAR* var, SCIP_BRANCHDIR dir)
SCIP_Real SCIPgetVarPseudocostScore(SCIP* scip, SCIP_VAR* var, SCIP_Real solval)
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR* var, SCIP_BRANCHDIR dir)
SCIP_Longint SCIPvarGetNBranchings(SCIP_VAR* var, SCIP_BRANCHDIR dir)
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR* var)
Expand Down
34 changes: 34 additions & 0 deletions src/pyscipopt/scip.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@
if rc == SCIP_OKAY:
pass
elif rc == SCIP_ERROR:
raise Exception('SCIP: unspecified error!')

Check failure on line 311 in src/pyscipopt/scip.pxi

View workflow job for this annotation

GitHub Actions / test-coverage (3.11)

SCIP: unspecified error!
elif rc == SCIP_NOMEMORY:
raise MemoryError('SCIP: insufficient memory error!')
elif rc == SCIP_READERROR:
Expand Down Expand Up @@ -4437,6 +4437,40 @@
var_dict[var.name] = self.getVal(var)
return var_dict

def getVarPseudocostScore(self, Variable var, solVal):
"""
gets the variable's pseudo cost score value for the given LP solution value

Parameters
----------
variable : Variable
problem variable
solVal : float
difference of variable's new LP value - old LP value

Returns
-------
float
"""
return SCIPgetVarPseudocostScore(self._scip, var.scip_var, solVal)

def getVarPseudocost(self, Variable var, branchdir):
"""
gets the variable's pseudo cost value for the given direction

Parameters
----------
variable : Variable
problem variable
branchdir : PY_SCIP_BRANCHDIR
branching direction (downwards, or upwards)

Returns
-------
float
"""
return SCIPgetVarPseudocost(self._scip, var.scip_var, branchdir)

def updateNodeLowerbound(self, Node node, lb):
"""
If given value is larger than the node's lower bound (in transformed problem),
Expand Down
39 changes: 38 additions & 1 deletion tests/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os
import itertools

from pyscipopt import Model, SCIP_STAGE, SCIP_PARAMSETTING, quicksum
from pyscipopt import Model, SCIP_STAGE, SCIP_PARAMSETTING, SCIP_BRANCHDIR, quicksum
from helpers.utils import random_mip_1

def test_model():
Expand Down Expand Up @@ -528,3 +528,40 @@ def test_comparisons():
assert not model.isNegative(0.)

assert model.isHugeValue(inf)

def test_getVarPseudocostScore():
m = Model()

m.addVar("x", vtype='B', obj=1.0)
m.addVar("y", vtype='B', obj=2.0)

m.setPresolve(SCIP_PARAMSETTING.OFF)
m.presolve()

var = m.getVars(transformed=True)[0]

p = m.getVarPseudocostScore(var, 1)
assert m.isEQ(p, 1)

p = m.getVarPseudocostScore(var, 0.5)
assert m.isEQ(p, 0.25)

def test_getVarPseudocost():
m = Model()

m.addVar("x", vtype='B', obj=1.0)
m.addVar("y", vtype='B', obj=2.0)

m.setPresolve(SCIP_PARAMSETTING.OFF)
m.presolve()

var = m.getVars(transformed=True)[0]

p = m.getVarPseudocost(var, SCIP_BRANCHDIR.UPWARDS)
assert m.isEQ(p, 1)

m.updateVarPseudocost(var, 1, 12, 1)
p = m.getVarPseudocost(var, SCIP_BRANCHDIR.UPWARDS)

# Not exactly 12 because the new value is a weighted sum of all the updates
assert m.isEQ(p, 12.0001)