Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
40 changes: 39 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,41 @@ 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 thw new value is a weighted sum of the all the updates
assert m.isEQ(p, 12.0001)