From 48ae2080683b37814cf757c0ab2cdc8e592a555a Mon Sep 17 00:00:00 2001 From: Simon Renard Date: Mon, 28 Jul 2025 14:17:55 +0200 Subject: [PATCH 1/4] Add getVarPseudocostScore and SCIPgetVarPseudocostScore --- CHANGELOG.md | 1 + src/pyscipopt/scip.pxd | 1 + src/pyscipopt/scip.pxi | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce0a27178..678b96e5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Wrapped SCIPgetNLPBranchCands - Added getConsVals() to get coefficients of any linear type constraint - Generalized getLhs() and getRhs() to additionally support any linear type constraint +- Added getVarPseudocostScore and SCIPgetVarPseudocostScore ### Fixed - Raised an error when an expression is used when a variable is required - Fixed some compile warnings diff --git a/src/pyscipopt/scip.pxd b/src/pyscipopt/scip.pxd index 7059a9f3c..599a282c1 100644 --- a/src/pyscipopt/scip.pxd +++ b/src/pyscipopt/scip.pxd @@ -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) diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi index 26abf8c29..c68c5618d 100644 --- a/src/pyscipopt/scip.pxi +++ b/src/pyscipopt/scip.pxi @@ -4430,6 +4430,40 @@ cdef class Model: 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), From f049ac355b2c664795d5fe3344d6380ed544a74f Mon Sep 17 00:00:00 2001 From: Simon Renard Date: Mon, 28 Jul 2025 14:18:51 +0200 Subject: [PATCH 2/4] typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 678b96e5d..a7a42e781 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ - Wrapped SCIPgetNLPBranchCands - Added getConsVals() to get coefficients of any linear type constraint - Generalized getLhs() and getRhs() to additionally support any linear type constraint -- Added getVarPseudocostScore and SCIPgetVarPseudocostScore +- Added getVarPseudocostScore and getVarPseudocost ### Fixed - Raised an error when an expression is used when a variable is required - Fixed some compile warnings From e299a405e1747ea052558298ae3d22d00721a4b3 Mon Sep 17 00:00:00 2001 From: Simon Renard Date: Tue, 29 Jul 2025 09:08:00 +0200 Subject: [PATCH 3/4] Test getVarPseudocostScore and getVarPseudocost --- tests/test_model.py | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/tests/test_model.py b/tests/test_model.py index ee95e8e42..84564d230 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -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(): @@ -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) \ No newline at end of file From 2e0eb605f7bf5364eee3370c15b690fb7e11d0d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Dion=C3=ADsio?= <57299939+Joao-Dionisio@users.noreply.github.com> Date: Tue, 29 Jul 2025 11:03:27 +0100 Subject: [PATCH 4/4] Apply suggestions from code review --- tests/test_model.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_model.py b/tests/test_model.py index 84564d230..391b21c41 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -546,7 +546,6 @@ def test_getVarPseudocostScore(): p = m.getVarPseudocostScore(var, 0.5) assert m.isEQ(p, 0.25) - def test_getVarPseudocost(): m = Model() @@ -564,5 +563,5 @@ def test_getVarPseudocost(): 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 + # Not exactly 12 because the new value is a weighted sum of all the updates assert m.isEQ(p, 12.0001) \ No newline at end of file