@@ -1052,10 +1052,12 @@ cdef class Solution:
10521052 cdef _VarArray wrapper
10531053 if isinstance (expr, Variable):
10541054 wrapper = _VarArray(expr)
1055+ self ._checkStage(" SCIPgetSolVal" )
10551056 return SCIPgetSolVal(self .scip, self .sol, wrapper.ptr[0 ])
10561057 return sum (self ._evaluate(term)* coeff for term, coeff in expr.terms.items() if coeff != 0 )
10571058
10581059 def _evaluate (self , term ):
1060+ self ._checkStage(" SCIPgetSolVal" )
10591061 result = 1
10601062 cdef _VarArray wrapper
10611063 wrapper = _VarArray(term.vartuple)
@@ -1070,6 +1072,7 @@ cdef class Solution:
10701072 cdef SCIP_VAR* scip_var
10711073 cdef int i
10721074 vals = {}
1075+ self ._checkStage(" SCIPgetSolVal" )
10731076 for i in range (SCIPgetNOrigVars(self .scip)):
10741077 scip_var = SCIPgetOrigVars(self .scip)[i]
10751078 # extract name
@@ -1078,6 +1081,12 @@ cdef class Solution:
10781081 vals[name] = SCIPgetSolVal(self .scip, self .sol, scip_var)
10791082 return str (vals)
10801083
1084+ def _checkStage (self , method ):
1085+ if method in [" SCIPgetSolVal" , " getSolObjVal" ]:
1086+ stage_check = SCIPgetStage(self .scip) not in [SCIP_STAGE_INIT, SCIP_STAGE_FREE]
1087+ if not stage_check or self .sol == NULL and SCIPgetStage(self .scip) != SCIP_STAGE_SOLVING:
1088+ raise Warning (f" {method} can only be called with a valid solution or in stage SOLVING (current stage: {SCIPgetStage(self.scip)})" )
1089+
10811090 def getOrigin (self ):
10821091 """
10831092 Returns origin of solution: where to retrieve uncached elements.
@@ -2791,6 +2800,14 @@ cdef class Model:
27912800 def freeTransform (self ):
27922801 """ Frees all solution process data including presolving and
27932802 transformed problem, only original problem is kept."""
2803+ if self .getStage() not in [SCIP_STAGE_INIT,
2804+ SCIP_STAGE_PROBLEM,
2805+ SCIP_STAGE_TRANSFORMED,
2806+ SCIP_STAGE_PRESOLVING,
2807+ SCIP_STAGE_PRESOLVED,
2808+ SCIP_STAGE_SOLVING,
2809+ SCIP_STAGE_SOLVED]:
2810+ raise Warning (" method cannot be called in stage %i ." % self .getStage())
27942811
27952812 self ._modelvars = {
27962813 var: value
@@ -6432,6 +6449,7 @@ cdef class Model:
64326449 coef : float
64336450
64346451 """
6452+ assert self .getStage() == 1 , " addExprNonlinear cannot be called in stage %i ." % self .getStage()
64356453 assert cons.isNonlinear(), " addExprNonlinear can only be called with nonlinear constraints."
64366454
64376455 cdef Constraint temp_cons
@@ -7640,6 +7658,9 @@ cdef class Model:
76407658 cdef SCIP_Real activity
76417659 cdef SCIP_SOL* scip_sol
76427660
7661+ if not self .getStage() >= SCIP_STAGE_SOLVING:
7662+ raise Warning (" method cannot be called before problem is solved" )
7663+
76437664 if isinstance (sol, Solution):
76447665 scip_sol = sol.sol
76457666 else :
@@ -7675,6 +7696,10 @@ cdef class Model:
76757696 cdef SCIP_Real activity
76767697 cdef SCIP_SOL* scip_sol
76777698
7699+
7700+ if not self .getStage() >= SCIP_STAGE_SOLVING:
7701+ raise Warning (" method cannot be called before problem is solved" )
7702+
76787703 if isinstance (sol, Solution):
76797704 scip_sol = sol.sol
76807705 else :
@@ -8282,6 +8307,10 @@ cdef class Model:
82828307
82838308 def presolve (self ):
82848309 """ Presolve the problem."""
8310+ if self .getStage() not in [SCIP_STAGE_PROBLEM, SCIP_STAGE_TRANSFORMED,\
8311+ SCIP_STAGE_PRESOLVING, SCIP_STAGE_PRESOLVED, \
8312+ SCIP_STAGE_SOLVED]:
8313+ raise Warning (" method cannot be called in stage %i ." % self .getStage())
82858314
82868315 PY_SCIP_CALL(SCIPpresolve(self ._scip))
82878316 self ._bestSol = Solution.create(self ._scip, SCIPgetBestSol(self ._scip))
@@ -10370,6 +10399,8 @@ cdef class Model:
1037010399 if sol == None :
1037110400 sol = Solution.create(self ._scip, NULL )
1037210401
10402+ sol._checkStage(" getSolObjVal" )
10403+
1037310404 if original:
1037410405 objval = SCIPgetSolOrigObj(self ._scip, sol.sol)
1037510406 else :
@@ -10406,9 +10437,21 @@ cdef class Model:
1040610437 float
1040710438
1040810439 """
10409- if SCIPgetNSols(self ._scip) != 0 :
10440+
10441+ if SCIPgetNSols(self ._scip) == 0 :
10442+ if self .getStage() != SCIP_STAGE_SOLVING:
10443+ raise Warning (" Without a solution, method can only be called in stage SOLVING." )
10444+ else :
1041010445 assert self ._bestSol.sol != NULL
1041110446
10447+ if SCIPsolIsOriginal(self ._bestSol.sol):
10448+ min_stage_requirement = SCIP_STAGE_PROBLEM
10449+ else :
10450+ min_stage_requirement = SCIP_STAGE_TRANSFORMING
10451+
10452+ if not self .getStage() >= min_stage_requirement:
10453+ raise Warning (" method cannot be called in stage %i ." % self .getStage)
10454+
1041210455 return self .getSolObjVal(self ._bestSol, original)
1041310456
1041410457 def getSolVal (self , Solution sol , Expr expr ):
@@ -10459,6 +10502,10 @@ cdef class Model:
1045910502 A variable is also an expression.
1046010503
1046110504 """
10505+ stage_check = SCIPgetStage(self ._scip) not in [SCIP_STAGE_INIT, SCIP_STAGE_FREE]
10506+
10507+ if not stage_check or self ._bestSol.sol == NULL and SCIPgetStage(self ._scip) != SCIP_STAGE_SOLVING:
10508+ raise Warning (" Method cannot be called in stage " , self .getStage())
1046210509
1046310510 if isinstance (expr, MatrixExpr):
1046410511 result = np.empty(expr.shape, dtype = float )
@@ -11203,6 +11250,14 @@ cdef class Model:
1120311250 def freeReoptSolve (self ):
1120411251 """ Frees all solution process data and prepares for reoptimization."""
1120511252
11253+ if self .getStage() not in [SCIP_STAGE_INIT,
11254+ SCIP_STAGE_PROBLEM,
11255+ SCIP_STAGE_TRANSFORMED,
11256+ SCIP_STAGE_PRESOLVING,
11257+ SCIP_STAGE_PRESOLVED,
11258+ SCIP_STAGE_SOLVING,
11259+ SCIP_STAGE_SOLVED]:
11260+ raise Warning (" method cannot be called in stage %i ." % self .getStage())
1120611261 PY_SCIP_CALL(SCIPfreeReoptSolve(self ._scip))
1120711262
1120811263 def chgReoptObjective (self , coeffs , sense = ' minimize' ):
0 commit comments