From 05df9667f6e2544bfbe6125f3b2502de51c78477 Mon Sep 17 00:00:00 2001 From: Joao-Dionisio Date: Mon, 9 Dec 2024 15:01:10 +0100 Subject: [PATCH 1/2] Add transformed option to getVarDict --- CHANGELOG.md | 1 + src/pyscipopt/scip.pxi | 9 +++++++-- tests/test_model.py | 11 +++++++++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36feae61..cc662cc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased ### Added +- Added transformed option to getVarDict, updated test - Added categorical data example - Added printProblem to print problem to stdout - Added stage checks to presolve, freereoptsolve, freetransform diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi index 6a5513cd..d95e45ea 100644 --- a/src/pyscipopt/scip.pxi +++ b/src/pyscipopt/scip.pxi @@ -3458,17 +3458,22 @@ cdef class Model: """ return SCIPgetNContVars(self._scip) - def getVarDict(self): + def getVarDict(self, transformed=False): """ Gets dictionary with variables names as keys and current variable values as items. + Parameters + ---------- + transformed : bool, optional + Get transformed variables instead of original (Default value = False) + Returns ------- dict of str to float """ var_dict = {} - for var in self.getVars(): + for var in self.getVars(transformed=transformed): var_dict[var.name] = self.getVal(var) return var_dict diff --git a/tests/test_model.py b/tests/test_model.py index a87548e9..516c7325 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -244,14 +244,21 @@ def test_getVarsDict(): x = {} for i in range(5): x[i] = model.addVar(lb = -i, ub = i, vtype="C") - for i in range(10,15): + for i in range(5,10): x[i] = model.addVar(lb = -i, ub = i, vtype="I") - for i in range(20,25): + for i in range(10,15): x[i] = model.addVar(vtype="B") + + model.addConsIndicator(x[0] <= 4, x[10]) + model.setPresolve(0) model.hideOutput() model.optimize() var_dict = model.getVarDict() + var_dict_transformed = model.getVarDict(transformed=True) + assert len(var_dict) == model.getNVars(transformed=False) + assert len(var_dict_transformed) == model.getNVars(transformed=True) + for v in x.values(): assert v.name in var_dict assert model.getVal(v) == var_dict[v.name] From 30aba21630e1b7b6ecca260fc0571ebb62988bfc Mon Sep 17 00:00:00 2001 From: Joao-Dionisio Date: Mon, 9 Dec 2024 16:43:13 +0100 Subject: [PATCH 2/2] Add option for get Rhs, Lhs of nonlinear cons. Remove some mentions of quadratic cons --- CHANGELOG.md | 1 + src/pyscipopt/scip.pxi | 20 ++++++++++---------- tests/test_nonlinear.py | 11 +++++++++++ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc662cc4..5923c670 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased ### Added +- Added option to get Lhs, Rhs of nonlinear constraints - Added transformed option to getVarDict, updated test - Added categorical data example - Added printProblem to print problem to stdout diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi index d95e45ea..1076a6fa 100644 --- a/src/pyscipopt/scip.pxi +++ b/src/pyscipopt/scip.pxi @@ -4265,7 +4265,7 @@ cdef class Model: if len(v) == 1: # linear var = v[0] PY_SCIP_CALL(SCIPaddLinearVarNonlinear(self._scip, scip_cons, var.scip_var, c)) - else: # quadratic + else: # nonlinear assert len(v) == 2, 'term length must be 1 or 2 but it is %s' % len(v) varexprs = malloc(2 * sizeof(SCIP_EXPR*)) @@ -4624,7 +4624,7 @@ cdef class Model: enforce=True, check=True, propagate=True, local=False, modifiable=False, dynamic=False, removable=False, stickingatnode=False): - """Adds multiple linear or quadratic constraints. + """Adds multiple constraints. Each of the constraints is added to the model using Model.addCons(). @@ -5578,7 +5578,7 @@ cdef class Model: Parameters ---------- cons : Constraint - linear or quadratic constraint + constraint to change the right-hand side from rhs : float or None new right-hand side (set to None for +infinity) @@ -5602,7 +5602,7 @@ cdef class Model: Parameters ---------- cons : Constraint - linear or quadratic constraint + constraint to change the left-hand side from lhs : float or None new left-hand side (set to None for -infinity) @@ -5626,7 +5626,7 @@ cdef class Model: Parameters ---------- cons : Constraint - linear or quadratic constraint + constraint to get the right-hand side from Returns ------- @@ -5636,7 +5636,7 @@ cdef class Model: constype = bytes(SCIPconshdlrGetName(SCIPconsGetHdlr(cons.scip_cons))).decode('UTF-8') if constype == 'linear': return SCIPgetRhsLinear(self._scip, cons.scip_cons) - elif constype == 'quadratic': + elif constype == 'nonlinear': return SCIPgetRhsNonlinear(cons.scip_cons) else: raise Warning("method cannot be called for constraints of type " + constype) @@ -5648,7 +5648,7 @@ cdef class Model: Parameters ---------- cons : Constraint - linear or quadratic constraint + linear or nonlinear constraint Returns ------- @@ -5658,7 +5658,7 @@ cdef class Model: constype = bytes(SCIPconshdlrGetName(SCIPconsGetHdlr(cons.scip_cons))).decode('UTF-8') if constype == 'linear': return SCIPgetLhsLinear(self._scip, cons.scip_cons) - elif constype == 'quadratic': + elif constype == 'nonlinear': return SCIPgetLhsNonlinear(cons.scip_cons) else: raise Warning("method cannot be called for constraints of type " + constype) @@ -5724,7 +5724,7 @@ cdef class Model: Parameters ---------- cons : Constraint - linear or quadratic constraint + linear constraint sol : Solution or None, optional solution to compute activity of, None to use current node's solution (Default value = None) @@ -5761,7 +5761,7 @@ cdef class Model: Parameters ---------- cons : Constraint - linear or quadratic constraint + linear constraint sol : Solution or None, optional solution to compute slack of, None to use current node's solution (Default value = None) side : str or None, optional diff --git a/tests/test_nonlinear.py b/tests/test_nonlinear.py index 0cec9994..383532f2 100644 --- a/tests/test_nonlinear.py +++ b/tests/test_nonlinear.py @@ -305,3 +305,14 @@ def test_addExprNonLinear(): assert m.getNSols() > 0 assert m.isEQ(m.getVal(y), 2) assert m.isEQ(m.getVal(z), 27) + +def test_nonlinear_lhs_rhs(): + from helpers.utils import random_nlp_1 + + m = random_nlp_1() + c = m.getConss() + + m.hideOutput() + m.optimize() + assert m.isInfinity(-m.getLhs(c[0])) + assert m.isEQ(m.getRhs(c[0]), 5) \ No newline at end of file