4 from os.path
import abspath
5 from os.path
import splitext
11 from cpython cimport Py_INCREF, Py_DECREF
12 from cpython.pycapsule cimport PyCapsule_New, PyCapsule_IsValid, PyCapsule_GetPointer
13 from libc.stdlib cimport malloc, free
14 from libc.stdio cimport fdopen, fclose
15 from posix.stdio cimport fileno
17 from collections.abc
import Iterable
18 from itertools
import repeat
23 include
"benderscut.pxi"
24 include
"branchrule.pxi"
25 include
"conshdlr.pxi"
28 include
"heuristic.pxi"
31 include
"propagator.pxi"
45 if sys.version_info >= (3, 0):
46 str_conversion =
lambda x:bytes(x,
'utf-8')
48 str_conversion =
lambda x:x
50 _SCIP_BOUNDTYPE_TO_STRING = {SCIP_BOUNDTYPE_UPPER:
'<=',
51 SCIP_BOUNDTYPE_LOWER:
'>='}
57 cdef
class PY_SCIP_RESULT:
58 DIDNOTRUN = SCIP_DIDNOTRUN
59 DELAYED = SCIP_DELAYED
60 DIDNOTFIND = SCIP_DIDNOTFIND
61 FEASIBLE = SCIP_FEASIBLE
62 INFEASIBLE = SCIP_INFEASIBLE
63 UNBOUNDED = SCIP_UNBOUNDED
65 SEPARATED = SCIP_SEPARATED
66 NEWROUND = SCIP_NEWROUND
67 REDUCEDDOM = SCIP_REDUCEDDOM
68 CONSADDED = SCIP_CONSADDED
69 CONSCHANGED = SCIP_CONSCHANGED
70 BRANCHED = SCIP_BRANCHED
71 SOLVELP = SCIP_SOLVELP
72 FOUNDSOL = SCIP_FOUNDSOL
73 SUSPENDED = SCIP_SUSPENDED
74 SUCCESS = SCIP_SUCCESS
76 cdef
class PY_SCIP_PARAMSETTING:
77 DEFAULT = SCIP_PARAMSETTING_DEFAULT
78 AGGRESSIVE = SCIP_PARAMSETTING_AGGRESSIVE
79 FAST = SCIP_PARAMSETTING_FAST
80 OFF = SCIP_PARAMSETTING_OFF
82 cdef
class PY_SCIP_PARAMEMPHASIS:
83 DEFAULT = SCIP_PARAMEMPHASIS_DEFAULT
84 CPSOLVER = SCIP_PARAMEMPHASIS_CPSOLVER
85 EASYCIP = SCIP_PARAMEMPHASIS_EASYCIP
86 FEASIBILITY = SCIP_PARAMEMPHASIS_FEASIBILITY
87 HARDLP = SCIP_PARAMEMPHASIS_HARDLP
88 OPTIMALITY = SCIP_PARAMEMPHASIS_OPTIMALITY
89 COUNTER = SCIP_PARAMEMPHASIS_COUNTER
90 PHASEFEAS = SCIP_PARAMEMPHASIS_PHASEFEAS
91 PHASEIMPROVE = SCIP_PARAMEMPHASIS_PHASEIMPROVE
92 PHASEPROOF = SCIP_PARAMEMPHASIS_PHASEPROOF
94 cdef
class PY_SCIP_STATUS:
95 UNKNOWN = SCIP_STATUS_UNKNOWN
96 USERINTERRUPT = SCIP_STATUS_USERINTERRUPT
97 NODELIMIT = SCIP_STATUS_NODELIMIT
98 TOTALNODELIMIT = SCIP_STATUS_TOTALNODELIMIT
99 STALLNODELIMIT = SCIP_STATUS_STALLNODELIMIT
100 TIMELIMIT = SCIP_STATUS_TIMELIMIT
101 MEMLIMIT = SCIP_STATUS_MEMLIMIT
102 GAPLIMIT = SCIP_STATUS_GAPLIMIT
103 SOLLIMIT = SCIP_STATUS_SOLLIMIT
104 BESTSOLLIMIT = SCIP_STATUS_BESTSOLLIMIT
105 RESTARTLIMIT = SCIP_STATUS_RESTARTLIMIT
106 OPTIMAL = SCIP_STATUS_OPTIMAL
107 INFEASIBLE = SCIP_STATUS_INFEASIBLE
108 UNBOUNDED = SCIP_STATUS_UNBOUNDED
109 INFORUNBD = SCIP_STATUS_INFORUNBD
111 cdef
class PY_SCIP_STAGE:
112 INIT = SCIP_STAGE_INIT
113 PROBLEM = SCIP_STAGE_PROBLEM
114 TRANSFORMING = SCIP_STAGE_TRANSFORMING
115 TRANSFORMED = SCIP_STAGE_TRANSFORMED
116 INITPRESOLVE = SCIP_STAGE_INITPRESOLVE
117 PRESOLVING = SCIP_STAGE_PRESOLVING
118 EXITPRESOLVE = SCIP_STAGE_EXITPRESOLVE
119 PRESOLVED = SCIP_STAGE_PRESOLVED
120 INITSOLVE = SCIP_STAGE_INITSOLVE
121 SOLVING = SCIP_STAGE_SOLVING
122 SOLVED = SCIP_STAGE_SOLVED
123 EXITSOLVE = SCIP_STAGE_EXITSOLVE
124 FREETRANS = SCIP_STAGE_FREETRANS
125 FREE = SCIP_STAGE_FREE
127 cdef
class PY_SCIP_NODETYPE:
128 FOCUSNODE = SCIP_NODETYPE_FOCUSNODE
129 PROBINGNODE = SCIP_NODETYPE_PROBINGNODE
130 SIBLING = SCIP_NODETYPE_SIBLING
131 CHILD = SCIP_NODETYPE_CHILD
132 LEAF = SCIP_NODETYPE_LEAF
133 DEADEND = SCIP_NODETYPE_DEADEND
134 JUNCTION = SCIP_NODETYPE_JUNCTION
135 PSEUDOFORK = SCIP_NODETYPE_PSEUDOFORK
136 FORK = SCIP_NODETYPE_FORK
137 SUBROOT = SCIP_NODETYPE_SUBROOT
138 REFOCUSNODE = SCIP_NODETYPE_REFOCUSNODE
141 cdef
class PY_SCIP_PROPTIMING:
142 BEFORELP = SCIP_PROPTIMING_BEFORELP
143 DURINGLPLOOP = SCIP_PROPTIMING_DURINGLPLOOP
144 AFTERLPLOOP = SCIP_PROPTIMING_AFTERLPLOOP
145 AFTERLPNODE = SCIP_PROPTIMING_AFTERLPNODE
147 cdef
class PY_SCIP_PRESOLTIMING:
148 NONE = SCIP_PRESOLTIMING_NONE
149 FAST = SCIP_PRESOLTIMING_FAST
150 MEDIUM = SCIP_PRESOLTIMING_MEDIUM
151 EXHAUSTIVE = SCIP_PRESOLTIMING_EXHAUSTIVE
153 cdef
class PY_SCIP_HEURTIMING:
154 BEFORENODE = SCIP_HEURTIMING_BEFORENODE
155 DURINGLPLOOP = SCIP_HEURTIMING_DURINGLPLOOP
156 AFTERLPLOOP = SCIP_HEURTIMING_AFTERLPLOOP
157 AFTERLPNODE = SCIP_HEURTIMING_AFTERLPNODE
158 AFTERPSEUDONODE = SCIP_HEURTIMING_AFTERPSEUDONODE
159 AFTERLPPLUNGE = SCIP_HEURTIMING_AFTERLPPLUNGE
160 AFTERPSEUDOPLUNGE = SCIP_HEURTIMING_AFTERPSEUDOPLUNGE
161 DURINGPRICINGLOOP = SCIP_HEURTIMING_DURINGPRICINGLOOP
162 BEFOREPRESOL = SCIP_HEURTIMING_BEFOREPRESOL
163 DURINGPRESOLLOOP = SCIP_HEURTIMING_DURINGPRESOLLOOP
164 AFTERPROPLOOP = SCIP_HEURTIMING_AFTERPROPLOOP
166 cdef
class PY_SCIP_EVENTTYPE:
167 DISABLED = SCIP_EVENTTYPE_DISABLED
168 VARADDED = SCIP_EVENTTYPE_VARADDED
169 VARDELETED = SCIP_EVENTTYPE_VARDELETED
170 VARFIXED = SCIP_EVENTTYPE_VARFIXED
171 VARUNLOCKED = SCIP_EVENTTYPE_VARUNLOCKED
172 OBJCHANGED = SCIP_EVENTTYPE_OBJCHANGED
173 GLBCHANGED = SCIP_EVENTTYPE_GLBCHANGED
174 GUBCHANGED = SCIP_EVENTTYPE_GUBCHANGED
175 LBTIGHTENED = SCIP_EVENTTYPE_LBTIGHTENED
176 LBRELAXED = SCIP_EVENTTYPE_LBRELAXED
177 UBTIGHTENED = SCIP_EVENTTYPE_UBTIGHTENED
178 UBRELAXED = SCIP_EVENTTYPE_UBRELAXED
179 GHOLEADDED = SCIP_EVENTTYPE_GHOLEADDED
180 GHOLEREMOVED = SCIP_EVENTTYPE_GHOLEREMOVED
181 LHOLEADDED = SCIP_EVENTTYPE_LHOLEADDED
182 LHOLEREMOVED = SCIP_EVENTTYPE_LHOLEREMOVED
183 IMPLADDED = SCIP_EVENTTYPE_IMPLADDED
184 PRESOLVEROUND = SCIP_EVENTTYPE_PRESOLVEROUND
185 NODEFOCUSED = SCIP_EVENTTYPE_NODEFOCUSED
186 NODEFEASIBLE = SCIP_EVENTTYPE_NODEFEASIBLE
187 NODEINFEASIBLE = SCIP_EVENTTYPE_NODEINFEASIBLE
188 NODEBRANCHED = SCIP_EVENTTYPE_NODEBRANCHED
189 FIRSTLPSOLVED = SCIP_EVENTTYPE_FIRSTLPSOLVED
190 LPSOLVED = SCIP_EVENTTYPE_LPSOLVED
191 LPEVENT = SCIP_EVENTTYPE_LPEVENT
192 POORSOLFOUND = SCIP_EVENTTYPE_POORSOLFOUND
193 BESTSOLFOUND = SCIP_EVENTTYPE_BESTSOLFOUND
194 ROWADDEDSEPA = SCIP_EVENTTYPE_ROWADDEDSEPA
195 ROWDELETEDSEPA = SCIP_EVENTTYPE_ROWDELETEDSEPA
196 ROWADDEDLP = SCIP_EVENTTYPE_ROWADDEDLP
197 ROWDELETEDLP = SCIP_EVENTTYPE_ROWDELETEDLP
198 ROWCOEFCHANGED = SCIP_EVENTTYPE_ROWCOEFCHANGED
199 ROWCONSTCHANGED = SCIP_EVENTTYPE_ROWCONSTCHANGED
200 ROWSIDECHANGED = SCIP_EVENTTYPE_ROWSIDECHANGED
201 SYNC = SCIP_EVENTTYPE_SYNC
202 NODESOLVED = SCIP_EVENTTYPE_NODEFEASIBLE | SCIP_EVENTTYPE_NODEINFEASIBLE | SCIP_EVENTTYPE_NODEBRANCHED
204 cdef
class PY_SCIP_LPSOLSTAT:
205 NOTSOLVED = SCIP_LPSOLSTAT_NOTSOLVED
206 OPTIMAL = SCIP_LPSOLSTAT_OPTIMAL
207 INFEASIBLE = SCIP_LPSOLSTAT_INFEASIBLE
208 UNBOUNDEDRAY = SCIP_LPSOLSTAT_UNBOUNDEDRAY
209 OBJLIMIT = SCIP_LPSOLSTAT_OBJLIMIT
210 ITERLIMIT = SCIP_LPSOLSTAT_ITERLIMIT
211 TIMELIMIT = SCIP_LPSOLSTAT_TIMELIMIT
212 ERROR = SCIP_LPSOLSTAT_ERROR
214 cdef
class PY_SCIP_BRANCHDIR:
215 DOWNWARDS = SCIP_BRANCHDIR_DOWNWARDS
216 UPWARDS = SCIP_BRANCHDIR_UPWARDS
217 FIXED = SCIP_BRANCHDIR_FIXED
218 AUTO = SCIP_BRANCHDIR_AUTO
220 cdef
class PY_SCIP_BENDERSENFOTYPE:
221 LP = SCIP_BENDERSENFOTYPE_LP
222 RELAX = SCIP_BENDERSENFOTYPE_RELAX
223 PSEUDO = SCIP_BENDERSENFOTYPE_PSEUDO
224 CHECK = SCIP_BENDERSENFOTYPE_CHECK
226 cdef
class PY_SCIP_ROWORIGINTYPE:
227 UNSPEC = SCIP_ROWORIGINTYPE_UNSPEC
228 CONS = SCIP_ROWORIGINTYPE_CONS
229 SEPA = SCIP_ROWORIGINTYPE_SEPA
230 REOPT = SCIP_ROWORIGINTYPE_REOPT
232 def PY_SCIP_CALL(SCIP_RETCODE rc):
235 elif rc == SCIP_ERROR:
236 raise Exception(
'SCIP: unspecified error!')
237 elif rc == SCIP_NOMEMORY:
238 raise MemoryError(
'SCIP: insufficient memory error!')
239 elif rc == SCIP_READERROR:
240 raise IOError(
'SCIP: read error!')
241 elif rc == SCIP_WRITEERROR:
242 raise IOError(
'SCIP: write error!')
243 elif rc == SCIP_NOFILE:
244 raise IOError(
'SCIP: file not found error!')
245 elif rc == SCIP_FILECREATEERROR:
246 raise IOError(
'SCIP: cannot create file!')
247 elif rc == SCIP_LPERROR:
248 raise Exception(
'SCIP: error in LP solver!')
249 elif rc == SCIP_NOPROBLEM:
250 raise Exception(
'SCIP: no problem exists!')
251 elif rc == SCIP_INVALIDCALL:
252 raise Exception(
'SCIP: method cannot be called at this time'
253 +
' in solution process!')
254 elif rc == SCIP_INVALIDDATA:
255 raise Exception(
'SCIP: error in input data!')
256 elif rc == SCIP_INVALIDRESULT:
257 raise Exception(
'SCIP: method returned an invalid result code!')
258 elif rc == SCIP_PLUGINNOTFOUND:
259 raise Exception(
'SCIP: a required plugin was not found !')
260 elif rc == SCIP_PARAMETERUNKNOWN:
261 raise KeyError(
'SCIP: the parameter with the given name was not found!')
262 elif rc == SCIP_PARAMETERWRONGTYPE:
263 raise LookupError(
'SCIP: the parameter is not of the expected type!')
264 elif rc == SCIP_PARAMETERWRONGVAL:
265 raise ValueError(
'SCIP: the value is invalid for the given parameter!')
266 elif rc == SCIP_KEYALREADYEXISTING:
267 raise KeyError(
'SCIP: the given key is already existing in table!')
268 elif rc == SCIP_MAXDEPTHLEVEL:
269 raise Exception(
'SCIP: maximal branching depth level exceeded!')
271 raise Exception(
'SCIP: unknown return code!')
274 """Base class holding a pointer to corresponding SCIP_EVENT"""
277 cdef create(SCIP_EVENT* scip_event):
278 if scip_event == NULL:
279 raise Warning(
"cannot create Event with SCIP_EVENT* == NULL")
281 event.event = scip_event
285 """gets type of event"""
292 """gets new bound for a bound change event"""
296 """gets old bound for a bound change event"""
300 """gets variable for a variable event (var added, var deleted, var fixed, objective value or domain change, domain hole added or removed)"""
302 return Variable.create(var)
305 """gets node for a node or LP event"""
307 return Node.create(node)
310 """gets row for a row event"""
312 return Row.create(row)
315 return hash(<size_t>self.
event)
318 return (self.
__class__ == other.__class__
319 and self.
event == (<Event>other).event)
322 """Base class holding a pointer to corresponding SCIP_COL"""
325 cdef create(SCIP_COL* scipcol):
327 raise Warning(
"cannot create Column with SCIP_COL* == NULL")
329 col.scip_col = scipcol
333 """gets position of column in current LP, or -1 if it is not in LP"""
337 """gets the basis status of a column in the LP solution, Note: returns basis status `zero` for columns not in the current SCIP LP"""
339 if stat == SCIP_BASESTAT_LOWER:
341 elif stat == SCIP_BASESTAT_BASIC:
343 elif stat == SCIP_BASESTAT_UPPER:
345 elif stat == SCIP_BASESTAT_ZERO:
348 raise Exception(
'SCIP returned unknown base status!')
351 """returns whether the associated variable is of integral type (binary, integer, implicit integer)"""
355 """gets variable this column represents"""
357 return Variable.create(var)
360 """gets the primal LP solution of a column"""
364 """gets lower bound of column"""
368 """gets upper bound of column"""
372 """gets objective value coefficient of a column"""
379 return (self.
__class__ == other.__class__
380 and self.
scip_col == (<Column>other).scip_col)
383 """Base class holding a pointer to corresponding SCIP_ROW"""
386 cdef create(SCIP_ROW* sciprow):
388 raise Warning(
"cannot create Row with SCIP_ROW* == NULL")
390 row.scip_row = sciprow
396 return cname.decode(
'utf-8')
399 """returns the left hand side of row"""
403 """returns the right hand side of row"""
407 """gets constant shift of row"""
411 """gets position of row in current LP, or -1 if it is not in LP"""
415 """gets the basis status of a row in the LP solution, Note: returns basis status `basic` for rows not in the current SCIP LP"""
417 if stat == SCIP_BASESTAT_LOWER:
419 elif stat == SCIP_BASESTAT_BASIC:
421 elif stat == SCIP_BASESTAT_UPPER:
423 elif stat == SCIP_BASESTAT_ZERO:
425 raise Exception(
'SCIP returned base status zero for a row!')
427 raise Exception(
'SCIP returned unknown base status!')
430 """returns TRUE iff the activity of the row (without the row's constant) is always integral in a feasible solution """
434 """returns TRUE iff the row is only valid locally """
438 """returns TRUE iff row is modifiable during node processing (subject to column generation) """
442 """returns TRUE iff row is removable from the LP (due to aging or cleanup)"""
446 """return TRUE iff row is a member of the global cut pool"""
450 """returns type of origin that created the row"""
454 """returns type of constraint handler that created the row"""
459 """get number of nonzero entries in row vector"""
463 """get number of nonzero entries in row vector that correspond to columns currently in the SCIP LP"""
467 """gets list with columns of nonzero entries"""
469 return [Column.create(cols[i])
for i
in range(self.
getNNonz())]
472 """gets list with coefficients of nonzero entries"""
474 return [vals[i]
for i
in range(self.
getNNonz())]
477 """gets Euclidean norm of row vector """
484 return (self.
__class__ == other.__class__
485 and self.
scip_row == (<Row>other).scip_row)
488 """Base class holding a pointer to corresponding SCIP_NLROW"""
491 cdef create(SCIP_NLROW* scipnlrow):
492 if scipnlrow == NULL:
493 raise Warning(
"cannot create NLRow with SCIP_NLROW* == NULL")
495 nlrow.scip_nlrow = scipnlrow
501 return cname.decode(
'utf-8')
504 """returns the constant of a nonlinear row"""
508 """returns a list of tuples (var, coef) representing the linear part of a nonlinear row"""
512 return [(Variable.create(linvars[i]), lincoefs[i])
for i
in range(nlinvars)]
515 """returns the left hand side of a nonlinear row"""
519 """returns the right hand side of a nonlinear row"""
523 """gets the dual NLP solution of a nonlinear row"""
530 return (self.
__class__ == other.__class__
531 and self.
scip_nlrow == (<NLRow>other).scip_nlrow)
534 """Base class holding a pointer to corresponding SCIP_SOL"""
537 cdef create(SCIP* scip, SCIP_SOL* scip_sol):
539 raise Warning(
"cannot create Solution with SCIP* == NULL")
547 if isinstance(expr, Variable):
549 var = <Variable> expr
551 return sum(self.
_evaluate(term)*coeff
for term, coeff
in expr.terms.items()
if coeff != 0)
553 def _evaluate(self, term):
556 for var
in term.vartuple:
564 cdef SCIP_VAR* scip_var
573 name = cname.decode(
'utf-8')
578 def _checkStage(self, method):
579 if method
in [
"SCIPgetSolVal",
"getSolObjVal"]:
581 raise Warning(f
"{method} can only be called in stage SOLVING with a valid solution (current stage: {SCIPgetStage(self.scip)})")
588 cdef create(SCIP_BOUNDCHG* scip_boundchg):
589 if scip_boundchg == NULL:
590 raise Warning(
"cannot create BoundChange with SCIP_BOUNDCHG* == NULL")
592 boundchg.scip_boundchg = scip_boundchg
596 """Returns the new value of the bound in the bound change."""
600 """Returns the variable of the bound change."""
604 """Returns the bound change type of the bound change."""
608 """Returns the bound type of the bound change."""
612 """Returns whether the bound change is redundant due to a more global bound that is at least as strong."""
616 return "{} {} {}".format(self.
getVar(),
621 """Set of domain changes."""
624 cdef create(SCIP_DOMCHG* scip_domchg):
625 if scip_domchg == NULL:
626 raise Warning(
"cannot create DomainChanges with SCIP_DOMCHG* == NULL")
628 domchg.scip_domchg = scip_domchg
632 """Returns the bound changes in the domain change."""
635 for i
in range(nboundchgs)]
638 """Base class holding a pointer to corresponding SCIP_NODE"""
641 cdef create(SCIP_NODE* scipnode):
645 node.scip_node = scipnode
649 """Retrieve parent node (or None if the node has no parent node)."""
653 """Retrieve number of node."""
657 """Retrieve depth of node."""
661 """Retrieve type of node."""
665 """Retrieve lower bound of node."""
669 """Retrieve the estimated value of the best feasible solution in subtree of the node"""
673 """Retrieve all constraints added at this node."""
675 if addedconsssize == 0:
677 cdef SCIP_CONS** addedconss = <SCIP_CONS**> malloc(addedconsssize * sizeof(SCIP_CONS*))
680 assert nconss == addedconsssize
681 constraints = [Constraint.create(addedconss[i])
for i
in range(nconss)]
686 """Retrieve number of added constraints at this node"""
690 """Is the node in the path to the current node?"""
694 """Is the node marked to be propagated again?"""
698 """Retrieve the number of variable branchings that were performed in the parent node to create this node."""
699 cdef SCIP_VAR* dummy_branchvars
700 cdef SCIP_Real dummy_branchbounds
701 cdef SCIP_BOUNDTYPE dummy_boundtypes
707 &dummy_branchbounds, &dummy_boundtypes,
712 """Retrieve the set of variable branchings that were performed in the parent node to create this node."""
717 cdef SCIP_VAR** branchvars = <SCIP_VAR**> malloc(nbranchvars * sizeof(SCIP_VAR*))
718 cdef SCIP_Real* branchbounds = <SCIP_Real*> malloc(nbranchvars * sizeof(SCIP_Real))
719 cdef SCIP_BOUNDTYPE* boundtypes = <SCIP_BOUNDTYPE*> malloc(nbranchvars * sizeof(SCIP_BOUNDTYPE))
722 boundtypes, &nbranchvars, nbranchvars)
724 py_variables = [Variable.create(branchvars[i])
for i
in range(nbranchvars)]
725 py_branchbounds = [branchbounds[i]
for i
in range(nbranchvars)]
726 py_boundtypes = [boundtypes[i]
for i
in range(nbranchvars)]
731 return py_variables, py_branchbounds, py_boundtypes
734 """Retrieve the number of bound changes due to branching, constraint propagation, and propagation."""
739 return nbranchings, nconsprop, nprop
742 """Retrieve domain changes for this node."""
746 return DomainChanges.create(domchg)
752 return (self.
__class__ == other.__class__
753 and self.
scip_node == (<Node>other).scip_node)
756 """Is a linear expression and has SCIP_VAR*"""
759 cdef create(SCIP_VAR* scipvar):
761 raise Warning(
"cannot create Variable with SCIP_VAR* == NULL")
763 var.scip_var = scipvar
764 Expr.__init__(var, {Term(var) : 1.0})
770 return cname.decode(
'utf-8')
780 """Retrieve the variables type (BINARY, INTEGER, IMPLINT or CONTINUOUS)"""
782 if vartype == SCIP_VARTYPE_BINARY:
784 elif vartype == SCIP_VARTYPE_INTEGER:
786 elif vartype == SCIP_VARTYPE_CONTINUOUS:
788 elif vartype == SCIP_VARTYPE_IMPLINT:
792 """Retrieve whether the variable belongs to the original problem"""
796 """Retrieve whether the variable is a COLUMN variable that is member of the current LP"""
801 """Retrieve the unique index of the variable."""
805 """Retrieve column of COLUMN variable"""
806 cdef SCIP_COL* scip_col
808 return Column.create(scip_col)
811 """Retrieve original lower bound of variable"""
815 """Retrieve original upper bound of variable"""
819 """Retrieve global lower bound of variable"""
823 """Retrieve global upper bound of variable"""
827 """Retrieve current lower bound of variable"""
831 """Retrieve current upper bound of variable"""
835 """Retrieve current objective value of variable"""
839 """Retrieve the current LP solution value of variable"""
843 """Base class holding a pointer to corresponding SCIP_CONS"""
846 cdef create(SCIP_CONS* scipcons):
848 raise Warning(
"cannot create Constraint with SCIP_CONS* == NULL")
850 cons.scip_cons = scipcons
856 return cname.decode(
'utf-8')
862 """Retrieve whether the constraint belongs to the original problem"""
866 """Retrieve True if the relaxation of the constraint should be in the initial LP"""
870 """Retrieve True if constraint should be separated during LP processing"""
874 """Retrieve True if constraint should be enforced during node processing"""
878 """Retrieve True if constraint should be checked for feasibility"""
882 """Retrieve True if constraint should be propagated during node processing"""
886 """Retrieve True if constraint is only locally valid or not added to any (sub)problem"""
890 """Retrieve True if constraint is modifiable (subject to column generation)"""
894 """Retrieve True if constraint is subject to aging"""
898 """Retrieve True if constraint's relaxation should be removed from the LP due to aging or cleanup"""
902 """Retrieve True if constraint is only locally valid or not added to any (sub)problem"""
906 """returns True iff constraint is active in the current node"""
910 """Retrieve True if constraint is linear"""
912 return constype ==
'linear'
915 """Retrieve True if constraint is nonlinear"""
917 return constype ==
'nonlinear'
923 return (self.
__class__ == other.__class__
924 and self.
scip_cons == (<Constraint>other).scip_cons)
927 cdef void relayMessage(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *msg):
928 sys.stdout.write(msg.decode(
'UTF-8'))
930 cdef void relayErrorMessage(void *messagehdlr, FILE *file, const char *msg):
931 sys.stderr.write(msg.decode(
'UTF-8'))
940 """Main class holding a pointer to SCIP for managing most interactions"""
942 def __init__(self, problemName='model', defaultPlugins=True, Model sourceModel=None, origcopy=False, globalcopy=True, enablepricing=False, createscip=True, threadsafe=False):
944 :param problemName: name of the problem (default 'model')
945 :param defaultPlugins: use default plugins? (default True)
946 :param sourceModel: create a copy of the given Model instance (default None)
947 :param origcopy: whether to call copy or copyOrig (default False)
948 :param globalcopy: whether to create a global or a local copy (default True)
949 :param enablepricing: whether to enable pricing in copy (default False)
950 :param createscip: initialize the Model object and creates a SCIP instance
951 :param threadsafe: False if data can be safely shared between the source and target problem
954 raise Exception(
"linked SCIP is not compatible to this version of PySCIPOpt - use at least version", MAJOR)
955 if self.
version() < MAJOR + MINOR/10.0 + PATCH/100.0:
956 warnings.warn(
"linked SCIP {} is not recommended for this version of PySCIPOpt - use version {}.{}.{}".format(self.
version(), MAJOR, MINOR, PATCH))
966 elif sourceModel
is None:
974 self.
_bestSol = <Solution> sourceModel._bestSol
977 PY_SCIP_CALL(
SCIPcopyOrig(sourceModel._scip, self.
_scip, NULL, NULL, n, enablepricing, threadsafe,
True, self._valid))
979 PY_SCIP_CALL(
SCIPcopy(sourceModel._scip, self.
_scip, NULL, NULL, n, globalcopy, enablepricing, threadsafe,
True, self._valid))
988 return hash(<size_t>self.
_scip)
991 return (self.
__class__ == other.__class__
992 and self.
_scip == (<Model>other)._scip)
995 cdef create(SCIP* scip):
996 """Creates a model and appropriately assigns the scip and bestsol parameters
999 raise Warning(
"cannot create Model with SCIP* == NULL")
1006 def _freescip(self):
1007 """Return whether the underlying Scip pointer gets deallocted when the current
1013 def _freescip(self, val):
1014 """Set whether the underlying Scip pointer gets deallocted when the current
1019 @cython.always_allow_keywords(
True)
1022 """Create a Model from a given pointer.
1024 :param cpasule: The PyCapsule containing the SCIP pointer under the name "scip".
1025 :param take_ownership: Whether the newly created Model assumes ownership of the
1026 underlying Scip pointer (see `_freescip`).
1028 if not PyCapsule_IsValid(capsule,
"scip"):
1029 raise ValueError(
"The given capsule does not contain a valid scip pointer")
1030 model = Model.create(<SCIP*>PyCapsule_GetPointer(capsule,
"scip"))
1031 model._freescip = take_ownership
1034 @cython.always_allow_keywords(
True)
1036 """Return the underlying Scip pointer to the current Model.
1038 :param give_ownership: Whether the current Model gives away ownership of the
1039 underlying Scip pointer (see `_freescip`).
1040 :return capsule: The underlying pointer to the current Model, wrapped in a
1041 PyCapsule under the name "scip".
1043 capsule = PyCapsule_New(<void*>self.
_scip,
"scip", NULL)
1049 """Includes all default plug-ins into SCIP"""
1050 PY_SCIP_CALL(SCIPincludeDefaultPlugins(self.
_scip))
1053 """Create new problem instance with given name
1055 :param problemName: name of model or problem (Default value = 'model')
1062 """Frees problem and solution process data"""
1066 """Frees all solution process data including presolving and transformed problem, only original problem is kept"""
1070 """Retrieve SCIP version"""
1074 """Print version, copyright information and compile mode"""
1078 """Retrieve problem name"""
1082 """Retrieve the current total SCIP time in seconds, i.e. the total time since the SCIP instance has been created"""
1086 """Retrieve the current solving time in seconds"""
1090 """Retrieve the current reading time in seconds"""
1094 """Retrieve the curernt presolving time in seconds"""
1098 """Retrieve the total number of LP iterations so far."""
1102 """gets number of processed nodes in current run, including the focus node."""
1106 """gets number of processed nodes in all runs, including the focus node."""
1110 """Retrieve number of leaf nodes processed with feasible relaxation solution."""
1114 """gets number of infeasible leaf nodes processed."""
1118 """gets number of leaves in the tree."""
1122 """gets number of children of focus node."""
1126 """gets number of siblings of focus node."""
1130 """Retrieve current node."""
1134 """Retrieve the gap, i.e. |(primalbound - dualbound)/min(|primalbound|,|dualbound|)|."""
1138 """Retrieve the depth of the current node"""
1142 """Retrieve SCIP's infinity value"""
1146 """Retrieve epsilon for e.g. equality checks"""
1150 """Retrieve feasibility tolerance"""
1154 """returns fractional part of value, i.e. x - floor(x) in feasible tolerance: x - floor(x+feastol)"""
1158 """returns fractional part of value, i.e. x - floor(x) in epsilon tolerance: x - floor(x+eps)"""
1162 """returns whether abs(value) < eps"""
1166 """returns whether abs(value) < feastol"""
1170 """returns whether value is SCIP's infinity"""
1174 """returns whether value < -feastol"""
1178 """returns whether value is integral within the LP feasibility bounds"""
1182 """checks, if values are in range of epsilon"""
1186 """checks, if relative difference of values is in range of feasibility tolerance"""
1190 """returns whether val1 <= val2 + eps"""
1194 """returns whether val1 < val2 - eps"""
1198 """returns whether val1 >= val2 - eps"""
1202 """returns whether val1 > val2 + eps"""
1206 """Get the current LP's condition number
1208 :param exact: whether to get an estimate or the exact value (Default value = False)
1213 cdef SCIP_Real quality = 0
1222 """include specific heuristics and branching rules for reoptimization"""
1226 """Get the iteration count of the last solved LP"""
1236 """Set the objective sense to minimization."""
1240 """Set the objective sense to maximization."""
1244 """Set a limit on the objective function.
1245 Only solutions with objective value better than this limit are accepted.
1247 :param objlimit: limit on the objective function
1253 """returns current limit on objective function."""
1257 """Establish the objective function as a linear expression.
1259 :param coeffs: the coefficients
1260 :param sense: the objective sense (Default value = 'minimize')
1261 :param clear: set all other variables objective coefficient to zero (Default value = 'true')
1264 cdef SCIP_VAR** _vars
1268 if not isinstance(coeffs, Expr):
1269 assert(_is_number(coeffs)),
"given coefficients are neither Expr or number but %s" % coeffs.__class__.__name__
1270 coeffs = Expr() + coeffs
1272 if coeffs.degree() > 1:
1273 raise ValueError(
"Nonlinear objective functions are not supported!")
1280 for i
in range(_nvars):
1283 if coeffs[CONST] != 0.0:
1286 for term, coef
in coeffs.terms.items():
1289 assert len(term) == 1
1290 var = <Variable>term[0]
1293 if sense ==
"minimize":
1295 elif sense ==
"maximize":
1298 raise Warning(
"unrecognized optimization sense: %s" % sense)
1301 """Retrieve objective function as Expr"""
1304 for var
in variables:
1305 coeff = var.getObj()
1307 objective += coeff * var
1308 objective.normalize()
1312 """Add constant offset to objective
1314 :param offset: offset to add
1315 :param solutions: add offset also to existing solutions (Default value = False)
1324 """Retrieve constant objective offset
1326 :param original: offset of original or transformed problem (Default value = True)
1336 """informs SCIP that the objective value is always integral in every feasible solution
1337 Note: This function should be used to inform SCIP that the objective function is integral, helping to improve the
1338 performance. This is useful when using column generation. If no column generation (pricing) is used, SCIP
1339 automatically detects whether the objective function is integral or can be scaled to be integral. However, in
1340 any case, the user has to make sure that no variable is added during the solving process that destroys this
1346 """gets estimate of best primal solution w.r.t. original or transformed problem contained in current subtree
1348 :param original: estimate of original or transformed problem (Default value = False)
1357 """Set presolving parameter settings.
1359 :param setting: the parameter settings (SCIP_PARAMSETTING)
1365 """Set problem name"""
1370 """Set separating parameter settings.
1372 :param setting: the parameter settings (SCIP_PARAMSETTING)
1378 """Set heuristics parameter settings.
1380 :param setting: the parameter setting (SCIP_PARAMSETTING)
1386 """Disables propagation in SCIP to avoid modifying the original problem during transformation.
1388 :param onlyroot: use propagation when root processing is finished (Default value = False)
1395 def writeProblem(self, filename='model.cip', trans=False, genericnames=False):
1396 """Write current model/problem to a file.
1398 :param filename: the name of the file to be used (Default value = 'model.cip'). Should have an extension corresponding to one of the readable file formats, described in https://www.scipopt.org/doc/html/group__FILEREADERS.php.
1399 :param trans: indicates whether the transformed problem is written to file (Default value = False)
1400 :param genericnames: indicates whether the problem should be written with generic variable and constraint names (Default value = False)
1403 str_absfile = abspath(filename)
1405 fn, ext = splitext(absfile)
1414 print(
'wrote problem to file ' + str_absfile)
1418 def addVar(self, name='', vtype='C', lb=0.0, ub=None, obj=0.0, pricedVar=False, pricedVarScore=1.0):
1419 """Create a new variable. Default variable is non-negative and continuous.
1421 :param name: name of the variable, generic if empty (Default value = '')
1422 :param vtype: type of the variable: 'C' continuous, 'I' integer, 'B' binary, and 'M' implicit integer
1423 (see https://www.scipopt.org/doc/html/FAQ.php#implicitinteger) (Default value = 'C')
1424 :param lb: lower bound of the variable, use None for -infinity (Default value = 0.0)
1425 :param ub: upper bound of the variable, use None for +infinity (Default value = None)
1426 :param obj: objective value of variable (Default value = 0.0)
1427 :param pricedVar: is the variable a pricing candidate? (Default value = False)
1428 :param pricedVarScore: score of variable in case it is priced, the higher the better (Default value = 1.0)
1431 cdef SCIP_VAR* scip_var
1444 vtype = vtype.upper()
1445 if vtype
in [
'C',
'CONTINUOUS']:
1447 elif vtype
in [
'B',
'BINARY']:
1453 elif vtype
in [
'I',
'INTEGER']:
1455 elif vtype
in [
'M',
'IMPLINT']:
1458 raise Warning(
"unrecognized variable type")
1465 pyVar = Variable.create(scip_var)
1477 """Retrieve the transformed variable.
1479 :param Variable var: original variable to get the transformed of
1482 cdef SCIP_VAR* _tvar
1485 return Variable.create(_tvar)
1488 """adds given values to lock numbers of variable for rounding
1490 :param Variable var: variable to adjust the locks for
1491 :param nlocksdown: new number of down locks
1492 :param nlocksup: new number of up locks
1498 """Fixes the variable var to the value val if possible.
1500 :param Variable var: variable to fix
1501 :param val: float, the fix value
1502 :return: tuple (infeasible, fixed) of booleans
1505 cdef SCIP_Bool infeasible
1506 cdef SCIP_Bool fixed
1507 PY_SCIP_CALL(
SCIPfixVar(self.
_scip, var.scip_var, val, &infeasible, &fixed))
1508 return infeasible, fixed
1511 """Delete a variable.
1513 :param var: the variable which shall be deleted
1514 :return: bool, was deleting succesful
1517 cdef SCIP_Bool deleted
1524 """Tighten the lower bound in preprocessing or current node, if the bound is tighter.
1526 :param var: SCIP variable
1527 :param lb: possible new lower bound
1528 :param force: force tightening even if below bound strengthening tolerance
1529 :return: tuple of bools, (infeasible, tightened)
1530 infeasible: whether new domain is empty
1531 tightened: whether the bound was tightened
1534 cdef SCIP_Bool infeasible
1535 cdef SCIP_Bool tightened
1537 return infeasible, tightened
1541 """Tighten the upper bound in preprocessing or current node, if the bound is tighter.
1543 :param var: SCIP variable
1544 :param ub: possible new upper bound
1545 :param force: force tightening even if below bound strengthening tolerance
1546 :return: tuple of bools, (infeasible, tightened)
1547 infeasible: whether new domain is empty
1548 tightened: whether the bound was tightened
1551 cdef SCIP_Bool infeasible
1552 cdef SCIP_Bool tightened
1554 return infeasible, tightened
1558 """Tighten the global upper bound, if the bound is tighter.
1560 :param var: SCIP variable
1561 :param ub: possible new upper bound
1562 :param force: force tightening even if below bound strengthening tolerance
1563 :return: tuple of bools, (infeasible, tightened)
1564 infeasible: whether new domain is empty
1565 tightened: whether the bound was tightened
1568 cdef SCIP_Bool infeasible
1569 cdef SCIP_Bool tightened
1571 return infeasible, tightened
1574 """Tighten the global upper bound, if the bound is tighter.
1576 :param var: SCIP variable
1577 :param lb: possible new upper bound
1578 :param force: force tightening even if below bound strengthening tolerance
1579 :return: tuple of bools, (infeasible, tightened)
1580 infeasible: whether new domain is empty
1581 tightened: whether the bound was tightened
1584 cdef SCIP_Bool infeasible
1585 cdef SCIP_Bool tightened
1587 return infeasible, tightened
1590 """Changes the lower bound of the specified variable.
1592 :param Variable var: variable to change bound of
1593 :param lb: new lower bound (set to None for -infinity)
1601 """Changes the upper bound of the specified variable.
1603 :param Variable var: variable to change bound of
1604 :param ub: new upper bound (set to None for +infinity)
1613 """Changes the global lower bound of the specified variable.
1615 :param Variable var: variable to change bound of
1616 :param lb: new lower bound (set to None for -infinity)
1624 """Changes the global upper bound of the specified variable.
1626 :param Variable var: variable to change bound of
1627 :param ub: new upper bound (set to None for +infinity)
1635 """Changes the lower bound of the specified variable at the given node.
1637 :param Variable var: variable to change bound of
1638 :param lb: new lower bound (set to None for -infinity)
1646 """Changes the upper bound of the specified variable at the given node.
1648 :param Variable var: variable to change bound of
1649 :param ub: new upper bound (set to None for +infinity)
1657 """Changes the type of a variable
1659 :param Variable var: variable to change type of
1660 :param vtype: new variable type
1663 cdef SCIP_Bool infeasible
1664 if vtype
in [
'C',
'CONTINUOUS']:
1665 PY_SCIP_CALL(
SCIPchgVarType(self.
_scip, var.scip_var, SCIP_VARTYPE_CONTINUOUS, &infeasible))
1666 elif vtype
in [
'B',
'BINARY']:
1668 elif vtype
in [
'I',
'INTEGER']:
1670 elif vtype
in [
'M',
'IMPLINT']:
1673 raise Warning(
"unrecognized variable type")
1675 print(
'could not change variable type of variable %s' % var)
1678 """Retrieve all variables.
1680 :param transformed: get transformed variables instead of original (Default value = False)
1683 cdef SCIP_VAR** _vars
1695 for i
in range(_nvars):
1696 ptr = <size_t>(_vars[i])
1703 var = Variable.create(_vars[i])
1704 assert var.ptr() == ptr
1711 """Retrieve number of variables in the problems"""
1715 """Retrieve the number of constraints."""
1719 """gets number of integer active problem variables"""
1723 """gets number of binary active problem variables"""
1727 """if given value is larger than the node's lower bound (in transformed problem),
1728 sets the node's lower bound to the new value
1730 :param node: Node, the node to update
1731 :param newbound: float, new bound (if greater) for the node
1738 """gets the best child of the focus node w.r.t. the node selection strategy."""
1742 """gets the best sibling of the focus node w.r.t. the node selection strategy."""
1746 """gets the best leaf from the node queue w.r.t. the node selection strategy."""
1750 """gets the best node from the tree (child, sibling, or leaf) w.r.t. the node selection strategy."""
1754 """gets the node with smallest lower bound from the tree (child, sibling, or leaf)."""
1758 """access to all data of open nodes (leaves, children, and siblings)
1760 :return: three lists containing open leaves, children, siblings
1762 cdef SCIP_NODE** _leaves
1763 cdef SCIP_NODE** _children
1764 cdef SCIP_NODE** _siblings
1771 leaves = [Node.create(_leaves[i])
for i
in range(_nleaves)]
1772 children = [Node.create(_children[i])
for i
in range(_nchildren)]
1773 siblings = [Node.create(_siblings[i])
for i
in range(_nsiblings)]
1775 return leaves, children, siblings
1778 """marks the given node to be propagated again the next time a node of its subtree is processed"""
1784 """Gets solution status of current LP"""
1789 """makes sure that the LP of the current node is loaded and
1790 may be accessed through the LP information methods
1792 :return: bool cutoff, i.e. can the node be cut off?
1795 cdef SCIP_Bool cutoff
1800 """gets objective value of current LP (which is the sum of column and loose objective value)"""
1805 """Retrieve current LP columns"""
1806 cdef SCIP_COL** cols
1810 return [Column.create(cols[i])
for i
in range(ncols)]
1813 """Retrieve current LP rows"""
1814 cdef SCIP_ROW** rows
1818 return [Row.create(rows[i])
for i
in range(nrows)]
1821 """Retrieve the number of rows currently in the LP"""
1825 """Retrieve the number of cols currently in the LP"""
1829 """Gets all indices of basic columns and rows: index i >= 0 corresponds to column i, index i < 0 to row -i-1"""
1831 cdef int* inds = <int *> malloc(nrows * sizeof(int))
1834 result = [inds[i]
for i
in range(nrows)]
1839 """gets a row from the inverse basis matrix B^-1"""
1842 cdef SCIP_Real* coefs = <SCIP_Real*> malloc(nrows * sizeof(SCIP_Real))
1845 result = [coefs[i]
for i
in range(nrows)]
1850 """gets a row from B^-1 * A"""
1853 cdef SCIP_Real* coefs = <SCIP_Real*> malloc(ncols * sizeof(SCIP_Real))
1856 result = [coefs[i]
for i
in range(ncols)]
1861 """returns whether the current LP solution is basic, i.e. is defined by a valid simplex basis"""
1866 def createEmptyRowSepa(self, Sepa sepa, name="row", lhs = 0.0, rhs = None, local = True, modifiable = False, removable = True):
1867 """creates and captures an LP row without any coefficients from a separator
1869 :param sepa: separator that creates the row
1870 :param name: name of row (Default value = "row")
1871 :param lhs: left hand side of row (Default value = 0)
1872 :param rhs: right hand side of row (Default value = None)
1873 :param local: is row only valid locally? (Default value = True)
1874 :param modifiable: is row modifiable during node processing (subject to column generation)? (Default value = False)
1875 :param removable: should the row be removed from the LP due to aging or cleanup? (Default value = True)
1882 PyRow = Row.create(row)
1885 def createEmptyRowUnspec(self, name="row", lhs = 0.0, rhs = None, local = True, modifiable = False, removable = True):
1886 """creates and captures an LP row without any coefficients from an unspecified source
1888 :param name: name of row (Default value = "row")
1889 :param lhs: left hand side of row (Default value = 0)
1890 :param rhs: right hand side of row (Default value = None)
1891 :param local: is row only valid locally? (Default value = True)
1892 :param modifiable: is row modifiable during node processing (subject to column generation)? (Default value = False)
1893 :param removable: should the row be removed from the LP due to aging or cleanup? (Default value = True)
1899 PyRow = Row.create(row)
1903 """returns the activity of a row in the last LP or pseudo solution"""
1907 """returns the activity of a row in the last LP solution"""
1912 """decreases usage counter of LP row, and frees memory if necessary"""
1916 """informs row, that all subsequent additions of variables to the row should be cached and not directly applied;
1917 after all additions were applied, flushRowExtensions() must be called;
1918 while the caching of row extensions is activated, information methods of the row give invalid results;
1919 caching should be used, if a row is build with addVarToRow() calls variable by variable to increase the performance"""
1923 """flushes all cached row extensions after a call of cacheRowExtensions() and merges coefficients with equal columns into a single coefficient"""
1926 def addVarToRow(self, Row row not None, Variable var not None, value):
1927 """resolves variable to columns and adds them with the coefficient to the row"""
1935 """Returns number of intergal columns in the row"""
1939 """Returns 1 if the row is parallel, and 0 if orthogonal"""
1943 """Returns the degree of parallelism between hyplerplanes. 1 if perfectly parallel, 0 if orthognal.
1944 101 in this case is an 'e' (euclidean) in ASCII. The other accpetable input is 100 (d for discrete)."""
1948 """Gets the dual LP solution of a row"""
1953 """if not already existing, adds row to global cut pool"""
1957 """returns efficacy of the cut with respect to the given primal solution or the current LP solution: e = -feasibility/norm"""
1961 """ returns whether the cut's efficacy with respect to the given primal solution or the current LP solution is greater than the minimal cut efficacy"""
1965 """ returns row's cutoff distance in the direction of the given primal solution"""
1968 def addCut(self, Row cut not None, forcecut = False):
1969 """adds cut to separation storage and returns whether cut has been detected to be infeasible for local bounds"""
1970 cdef SCIP_Bool infeasible
1971 PY_SCIP_CALL(
SCIPaddRow(self.
_scip, cut.scip_row, forcecut, &infeasible))
1975 """Retrieve total number of cuts in storage"""
1979 """Retrieve number of currently applied cuts"""
1983 """Retrieve the number of separation rounds that have been performed
1984 at the current node"""
1987 def separateSol(self, Solution sol = None, pretendroot = False, allowlocal = True, onlydelayed = False):
1988 """separates the given primal solution or the current LP solution by calling the separators and constraint handlers'
1990 the generated cuts are stored in the separation storage and can be accessed with the methods SCIPgetCuts() and
1992 after evaluating the cuts, you have to call SCIPclearCuts() in order to remove the cuts from the
1994 it is possible to call SCIPseparateSol() multiple times with different solutions and evaluate the found cuts
1996 :param Solution sol: solution to separate, None to use current lp solution (Default value = None)
1997 :param pretendroot: should the cut separators be called as if we are at the root node? (Default value = "False")
1998 :param allowlocal: should the separator be asked to separate local cuts (Default value = True)
1999 :param onlydelayed: should only separators be called that were delayed in the previous round? (Default value = False)
2001 delayed -- whether a separator was delayed
2002 cutoff -- whether the node can be cut off
2004 cdef SCIP_Bool delayed
2005 cdef SCIP_Bool cutoff
2007 PY_SCIP_CALL(
SCIPseparateSol(self.
_scip, NULL
if sol
is None else sol.sol, pretendroot, allowlocal, onlydelayed, &delayed, &cutoff) )
2008 return delayed, cutoff
2011 def addCons(self, cons, name='', initial=True, separate=True,
2012 enforce=True, check=True, propagate=True, local=False,
2013 modifiable=False, dynamic=False, removable=False,
2014 stickingatnode=False):
2015 """Add a linear or nonlinear constraint.
2017 :param cons: constraint object
2018 :param name: the name of the constraint, generic name if empty (Default value = '')
2019 :param initial: should the LP relaxation of constraint be in the initial LP? (Default value = True)
2020 :param separate: should the constraint be separated during LP processing? (Default value = True)
2021 :param enforce: should the constraint be enforced during node processing? (Default value = True)
2022 :param check: should the constraint be checked for feasibility? (Default value = True)
2023 :param propagate: should the constraint be propagated during node processing? (Default value = True)
2024 :param local: is the constraint only valid locally? (Default value = False)
2025 :param modifiable: is the constraint modifiable (subject to column generation)? (Default value = False)
2026 :param dynamic: is the constraint subject to aging? (Default value = False)
2027 :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False)
2028 :param stickingatnode: should the constraint always be kept at the node where it was added, even if it may be moved to a more global node? (Default value = False)
2029 :return The added @ref scip#Constraint "Constraint" object.
2032 assert isinstance(cons, ExprCons),
"given constraint is not ExprCons but %s" % cons.__class__.__name__
2038 kwargs = dict(name=name, initial=initial, separate=separate,
2039 enforce=enforce, check=check,
2040 propagate=propagate, local=local,
2041 modifiable=modifiable, dynamic=dynamic,
2042 removable=removable,
2043 stickingatnode=stickingatnode)
2047 deg = cons.expr.degree()
2052 elif deg == float(
'inf'):
2057 def addConss(self, conss, name='', initial=True, separate=True,
2058 enforce=True, check=True, propagate=True, local=False,
2059 modifiable=False, dynamic=False, removable=False,
2060 stickingatnode=False):
2061 """Adds multiple linear or quadratic constraints.
2063 Each of the constraints is added to the model using Model.addCons().
2065 For all parameters, except @p conss, this method behaves differently depending on the type of the passed argument:
2066 1. If the value is iterable, it must be of the same length as @p conss. For each constraint, Model.addCons() will be called with the value at the corresponding index.
2067 2. Else, the (default) value will be applied to all of the constraints.
2069 :param conss An iterable of constraint objects. Any iterable will be converted into a list before further processing.
2070 :param name: the names of the constraints, generic name if empty (Default value = ''). If a single string is passed, it will be suffixed by an underscore and the enumerated index of the constraint (starting with 0).
2071 :param initial: should the LP relaxation of constraints be in the initial LP? (Default value = True)
2072 :param separate: should the constraints be separated during LP processing? (Default value = True)
2073 :param enforce: should the constraints be enforced during node processing? (Default value = True)
2074 :param check: should the constraints be checked for feasibility? (Default value = True)
2075 :param propagate: should the constraints be propagated during node processing? (Default value = True)
2076 :param local: are the constraints only valid locally? (Default value = False)
2077 :param modifiable: are the constraints modifiable (subject to column generation)? (Default value = False)
2078 :param dynamic: are the constraints subject to aging? (Default value = False)
2079 :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False)
2080 :param stickingatnode: should the constraints always be kept at the node where it was added, even if it may be @oved to a more global node? (Default value = False)
2081 :return A list of added @ref scip#Constraint "Constraint" objects.
2085 def ensure_iterable(elem, length):
2086 if isinstance(elem, Iterable):
2089 return list(repeat(elem, length))
2091 assert isinstance(conss, Iterable),
"Given constraint list is not iterable."
2094 n_conss = len(conss)
2096 if isinstance(name, str):
2098 name = [
"" for idx
in range(n_conss)]
2100 name = [
"%s_%s" % (name, idx)
for idx
in range(n_conss)]
2101 initial = ensure_iterable(initial, n_conss)
2102 separate = ensure_iterable(separate, n_conss)
2103 enforce = ensure_iterable(enforce, n_conss)
2104 check = ensure_iterable(check, n_conss)
2105 propagate = ensure_iterable(propagate, n_conss)
2106 local = ensure_iterable(local, n_conss)
2107 modifiable = ensure_iterable(modifiable, n_conss)
2108 dynamic = ensure_iterable(dynamic, n_conss)
2109 removable = ensure_iterable(removable, n_conss)
2110 stickingatnode = ensure_iterable(stickingatnode, n_conss)
2113 for i, cons
in enumerate(conss):
2115 self.
addCons(cons, name[i], initial[i], separate[i], enforce[i],
2116 check[i], propagate[i], local[i], modifiable[i],
2117 dynamic[i], removable[i], stickingatnode[i])
2125 def _addLinCons(self, ExprCons lincons, **kwargs):
2126 assert isinstance(lincons, ExprCons),
"given constraint is not ExprCons but %s" % lincons.__class__.__name__
2128 assert lincons.expr.degree() <= 1,
"given constraint is not linear, degree == %d" % lincons.expr.degree()
2129 terms = lincons.expr.terms
2131 cdef SCIP_CONS* scip_cons
2133 cdef int nvars = len(terms.items())
2135 vars_array = <SCIP_VAR**> malloc(nvars * sizeof(SCIP_VAR*))
2136 coeffs_array = <SCIP_Real*> malloc(nvars * sizeof(SCIP_Real))
2138 for i, (key, coeff)
in enumerate(terms.items()):
2139 vars_array[i] = <SCIP_VAR*>(<Variable>key[0]).scip_var
2140 coeffs_array[i] = <SCIP_Real>coeff
2144 kwargs[
'lhs'], kwargs[
'rhs'], kwargs[
'initial'],
2145 kwargs[
'separate'], kwargs[
'enforce'], kwargs[
'check'],
2146 kwargs[
'propagate'], kwargs[
'local'], kwargs[
'modifiable'],
2147 kwargs[
'dynamic'], kwargs[
'removable'], kwargs[
'stickingatnode']))
2150 PyCons = Constraint.create(scip_cons)
2158 def _addQuadCons(self, ExprCons quadcons, **kwargs):
2159 terms = quadcons.expr.terms
2160 assert quadcons.expr.degree() <= 2,
"given constraint is not quadratic, degree == %d" % quadcons.expr.degree()
2162 cdef SCIP_CONS* scip_cons
2163 cdef SCIP_EXPR* prodexpr
2167 0, NULL, NULL, NULL,
2168 kwargs[
'lhs'], kwargs[
'rhs'],
2169 kwargs[
'initial'], kwargs[
'separate'], kwargs[
'enforce'],
2170 kwargs[
'check'], kwargs[
'propagate'], kwargs[
'local'],
2171 kwargs[
'modifiable'], kwargs[
'dynamic'], kwargs[
'removable']))
2173 for v, c
in terms.items():
2175 var = <Variable>v[0]
2178 assert len(v) == 2,
'term length must be 1 or 2 but it is %s' % len(v)
2180 varexprs = <SCIP_EXPR**> malloc(2 * sizeof(SCIP_EXPR*))
2181 var1, var2 = <Variable>v[0], <Variable>v[1]
2195 PyCons = Constraint.create(scip_cons)
2199 def _addNonlinearCons(self, ExprCons cons, **kwargs):
2200 cdef SCIP_EXPR* expr
2201 cdef SCIP_EXPR** varexprs
2202 cdef SCIP_EXPR** monomials
2204 cdef SCIP_CONS* scip_cons
2206 terms = cons.expr.terms
2209 variables = {var.ptr():var
for term
in terms
for var
in term}
2210 variables = list(variables.values())
2211 varindex = {var.ptr():idx
for (idx,var)
in enumerate(variables)}
2214 monomials = <SCIP_EXPR**> malloc(len(terms) * sizeof(SCIP_EXPR*))
2215 termcoefs = <SCIP_Real*> malloc(len(terms) * sizeof(SCIP_Real))
2216 for i, (term, coef)
in enumerate(terms.items()):
2217 termvars = <SCIP_VAR**> malloc(len(term) * sizeof(SCIP_VAR*))
2218 for j, var
in enumerate(term):
2219 termvars[j] = (<Variable>var).scip_var
2221 termcoefs[i] = <SCIP_Real>coef
2225 PY_SCIP_CALL(
SCIPcreateExprSum(self.
_scip, &expr, <int>len(terms), monomials, termcoefs, 0.0, NULL, NULL))
2239 kwargs[
'propagate'],
2241 kwargs[
'modifiable'],
2243 kwargs[
'removable']) )
2245 PyCons = Constraint.create(scip_cons)
2248 for i
in range(<int>len(terms)):
2254 def _addGenNonlinearCons(self, ExprCons cons, **kwargs):
2255 cdef SCIP_EXPR** childrenexpr
2256 cdef SCIP_EXPR** scipexprs
2257 cdef SCIP_CONS* scip_cons
2274 if node[0] == Operator.varidx:
2276 vars = <SCIP_VAR**> malloc(nvars * sizeof(SCIP_VAR*))
2279 scipexprs = <SCIP_EXPR**> malloc(len(nodes) * sizeof(SCIP_EXPR*))
2280 for i,node
in enumerate(nodes):
2282 if opidx == Operator.varidx:
2283 assert len(node[1]) == 1
2286 vars[varpos] = (<Variable>pyvar).scip_var
2289 if opidx == Operator.const:
2290 assert len(node[1]) == 1
2294 if opidx == Operator.add:
2295 nchildren = len(node[1])
2296 childrenexpr = <SCIP_EXPR**> malloc(nchildren * sizeof(SCIP_EXPR*))
2297 coefs = <SCIP_Real*> malloc(nchildren * sizeof(SCIP_Real))
2298 for c, pos
in enumerate(node[1]):
2299 childrenexpr[c] = scipexprs[pos]
2301 PY_SCIP_CALL(
SCIPcreateExprSum(self.
_scip, &scipexprs[i], nchildren, childrenexpr, coefs, 0, NULL, NULL))
2305 if opidx == Operator.prod:
2306 nchildren = len(node[1])
2307 childrenexpr = <SCIP_EXPR**> malloc(nchildren * sizeof(SCIP_EXPR*))
2308 for c, pos
in enumerate(node[1]):
2309 childrenexpr[c] = scipexprs[pos]
2313 if opidx == Operator.power:
2315 valuenode = nodes[node[1][1]]
2316 assert valuenode[0] == Operator.const
2317 exponent = valuenode[1][0]
2318 PY_SCIP_CALL(
SCIPcreateExprPow(self.
_scip, &scipexprs[i], scipexprs[node[1][0]], <SCIP_Real>exponent, NULL, NULL ))
2320 if opidx == Operator.exp:
2321 assert len(node[1]) == 1
2324 if opidx == Operator.log:
2325 assert len(node[1]) == 1
2328 if opidx == Operator.sqrt:
2329 assert len(node[1]) == 1
2330 PY_SCIP_CALL(
SCIPcreateExprPow(self.
_scip, &scipexprs[i], scipexprs[node[1][0]], <SCIP_Real>0.5, NULL, NULL) )
2332 if opidx == Operator.sin:
2333 assert len(node[1]) == 1
2336 if opidx == Operator.cos:
2337 assert len(node[1]) == 1
2340 if opidx == Operator.fabs:
2341 assert len(node[1]) == 1
2345 raise NotImplementedError
2346 assert varpos == nvars
2353 scipexprs[len(nodes) - 1],
2360 kwargs[
'propagate'],
2362 kwargs[
'modifiable'],
2364 kwargs[
'removable']) )
2366 PyCons = Constraint.create(scip_cons)
2368 for i
in range(len(nodes)):
2378 """Add coefficient to the linear constraint (if non-zero).
2380 :param Constraint cons: constraint to be changed
2381 :param Variable var: variable to be added
2382 :param coeff: coefficient of new variable
2387 def addConsNode(self, Node node, Constraint cons, Node validnode=None):
2388 """Add a constraint to the given node
2390 :param Node node: node to add the constraint to
2391 :param Constraint cons: constraint to add
2392 :param Node validnode: more global node where cons is also valid
2395 if isinstance(validnode, Node):
2402 """Add a constraint to the current node
2404 :param Constraint cons: constraint to add
2405 :param Node validnode: more global node where cons is also valid
2408 if isinstance(validnode, Node):
2415 initial=True, separate=True, enforce=True, check=True,
2416 propagate=True, local=False, dynamic=False,
2417 removable=False, stickingatnode=False):
2418 """Add an SOS1 constraint.
2420 :param vars: list of variables to be included
2421 :param weights: list of weights (Default value = None)
2422 :param name: name of the constraint (Default value = "SOS1cons")
2423 :param initial: should the LP relaxation of constraint be in the initial LP? (Default value = True)
2424 :param separate: should the constraint be separated during LP processing? (Default value = True)
2425 :param enforce: should the constraint be enforced during node processing? (Default value = True)
2426 :param check: should the constraint be checked for feasibility? (Default value = True)
2427 :param propagate: should the constraint be propagated during node processing? (Default value = True)
2428 :param local: is the constraint only valid locally? (Default value = False)
2429 :param dynamic: is the constraint subject to aging? (Default value = False)
2430 :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False)
2431 :param stickingatnode: should the constraint always be kept at the node where it was added, even if it may be moved to a more global node? (Default value = False)
2434 cdef SCIP_CONS* scip_cons
2438 initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode))
2446 for i
in range(nvars):
2447 var = <Variable>vars[i]
2451 return Constraint.create(scip_cons)
2454 initial=True, separate=True, enforce=True, check=True,
2455 propagate=True, local=False, dynamic=False,
2456 removable=False, stickingatnode=False):
2457 """Add an SOS2 constraint.
2459 :param vars: list of variables to be included
2460 :param weights: list of weights (Default value = None)
2461 :param name: name of the constraint (Default value = "SOS2cons")
2462 :param initial: should the LP relaxation of constraint be in the initial LP? (Default value = True)
2463 :param separate: should the constraint be separated during LP processing? (Default value = True)
2464 :param enforce: should the constraint be enforced during node processing? (Default value = True)
2465 :param check: should the constraint be checked for feasibility? (Default value = True)
2466 :param propagate: is the constraint only valid locally? (Default value = True)
2467 :param local: is the constraint only valid locally? (Default value = False)
2468 :param dynamic: is the constraint subject to aging? (Default value = False)
2469 :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False)
2470 :param stickingatnode: should the constraint always be kept at the node where it was added, even if it may be moved to a more global node? (Default value = False)
2473 cdef SCIP_CONS* scip_cons
2477 initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode))
2485 for i
in range(nvars):
2486 var = <Variable>vars[i]
2490 return Constraint.create(scip_cons)
2493 initial=True, separate=True, enforce=True, check=True,
2494 propagate=True, local=False, modifiable=False, dynamic=False,
2495 removable=False, stickingatnode=False):
2496 """Add an AND-constraint.
2497 :param vars: list of BINARY variables to be included (operators)
2498 :param resvar: BINARY variable (resultant)
2499 :param name: name of the constraint (Default value = "ANDcons")
2500 :param initial: should the LP relaxation of constraint be in the initial LP? (Default value = True)
2501 :param separate: should the constraint be separated during LP processing? (Default value = True)
2502 :param enforce: should the constraint be enforced during node processing? (Default value = True)
2503 :param check: should the constraint be checked for feasibility? (Default value = True)
2504 :param propagate: should the constraint be propagated during node processing? (Default value = True)
2505 :param local: is the constraint only valid locally? (Default value = False)
2506 :param modifiable: is the constraint modifiable (subject to column generation)? (Default value = False)
2507 :param dynamic: is the constraint subject to aging? (Default value = False)
2508 :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False)
2509 :param stickingatnode: should the constraint always be kept at the node where it was added, even if it may be moved to a more global node? (Default value = False)
2511 cdef SCIP_CONS* scip_cons
2515 _vars = <SCIP_VAR**> malloc(len(vars) * sizeof(SCIP_VAR*))
2516 for idx, var
in enumerate(vars):
2517 _vars[idx] = (<Variable>var).scip_var
2518 _resVar = (<Variable>resvar).scip_var
2521 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode))
2524 pyCons = Constraint.create(scip_cons)
2532 initial=True, separate=True, enforce=True, check=True,
2533 propagate=True, local=False, modifiable=False, dynamic=False,
2534 removable=False, stickingatnode=False):
2535 """Add an OR-constraint.
2536 :param vars: list of BINARY variables to be included (operators)
2537 :param resvar: BINARY variable (resultant)
2538 :param name: name of the constraint (Default value = "ORcons")
2539 :param initial: should the LP relaxation of constraint be in the initial LP? (Default value = True)
2540 :param separate: should the constraint be separated during LP processing? (Default value = True)
2541 :param enforce: should the constraint be enforced during node processing? (Default value = True)
2542 :param check: should the constraint be checked for feasibility? (Default value = True)
2543 :param propagate: should the constraint be propagated during node processing? (Default value = True)
2544 :param local: is the constraint only valid locally? (Default value = False)
2545 :param modifiable: is the constraint modifiable (subject to column generation)? (Default value = False)
2546 :param dynamic: is the constraint subject to aging? (Default value = False)
2547 :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False)
2548 :param stickingatnode: should the constraint always be kept at the node where it was added, even if it may be moved to a more global node? (Default value = False)
2550 cdef SCIP_CONS* scip_cons
2554 _vars = <SCIP_VAR**> malloc(len(vars) * sizeof(SCIP_VAR*))
2555 for idx, var
in enumerate(vars):
2556 _vars[idx] = (<Variable>var).scip_var
2557 _resVar = (<Variable>resvar).scip_var
2560 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode))
2563 pyCons = Constraint.create(scip_cons)
2571 initial=True, separate=True, enforce=True, check=True,
2572 propagate=True, local=False, modifiable=False, dynamic=False,
2573 removable=False, stickingatnode=False):
2574 """Add a XOR-constraint.
2575 :param vars: list of BINARY variables to be included (operators)
2576 :param rhsvar: BOOLEAN value, explicit True, False or bool(obj) is needed (right-hand side)
2577 :param name: name of the constraint (Default value = "XORcons")
2578 :param initial: should the LP relaxation of constraint be in the initial LP? (Default value = True)
2579 :param separate: should the constraint be separated during LP processing? (Default value = True)
2580 :param enforce: should the constraint be enforced during node processing? (Default value = True)
2581 :param check: should the constraint be checked for feasibility? (Default value = True)
2582 :param propagate: should the constraint be propagated during node processing? (Default value = True)
2583 :param local: is the constraint only valid locally? (Default value = False)
2584 :param modifiable: is the constraint modifiable (subject to column generation)? (Default value = False)
2585 :param dynamic: is the constraint subject to aging? (Default value = False)
2586 :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False)
2587 :param stickingatnode: should the constraint always be kept at the node where it was added, even if it may be moved to a more global node? (Default value = False)
2589 cdef SCIP_CONS* scip_cons
2593 assert type(rhsvar)
is type(bool()),
"Provide BOOLEAN value as rhsvar, you gave %s." % type(rhsvar)
2594 _vars = <SCIP_VAR**> malloc(len(vars) * sizeof(SCIP_VAR*))
2595 for idx, var
in enumerate(vars):
2596 _vars[idx] = (<Variable>var).scip_var
2599 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode))
2602 pyCons = Constraint.create(scip_cons)
2610 initial=True, separate=True, enforce=True, check=True,
2611 propagate=True, local=False, dynamic=False,
2612 removable=False, stickingatnode=False):
2613 """Add a cardinality constraint that allows at most 'cardval' many nonzero variables.
2615 :param consvars: list of variables to be included
2616 :param cardval: nonnegative integer
2617 :param indvars: indicator variables indicating which variables may be treated as nonzero in cardinality constraint, or None if new indicator variables should be introduced automatically (Default value = None)
2618 :param weights: weights determining the variable order, or None if variables should be ordered in the same way they were added to the constraint (Default value = None)
2619 :param name: name of the constraint (Default value = "CardinalityCons")
2620 :param initial: should the LP relaxation of constraint be in the initial LP? (Default value = True)
2621 :param separate: should the constraint be separated during LP processing? (Default value = True)
2622 :param enforce: should the constraint be enforced during node processing? (Default value = True)
2623 :param check: should the constraint be checked for feasibility? (Default value = True)
2624 :param propagate: should the constraint be propagated during node processing? (Default value = True)
2625 :param local: is the constraint only valid locally? (Default value = False)
2626 :param dynamic: is the constraint subject to aging? (Default value = False)
2627 :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False)
2628 :param stickingatnode: should the constraint always be kept at the node where it was added, even if it may be moved to a more global node? (Default value = False)
2631 cdef SCIP_CONS* scip_cons
2632 cdef SCIP_VAR* indvar
2635 initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode))
2639 weights = list(range(1, len(consvars) + 1))
2641 for i, v
in enumerate(consvars):
2644 indvar = (<Variable>indvars[i]).scip_var
2653 pyCons = Constraint.create(scip_cons)
2661 initial=True, separate=True, enforce=True, check=True,
2662 propagate=True, local=False, dynamic=False,
2663 removable=False, stickingatnode=False):
2664 """Add an indicator constraint for the linear inequality 'cons'.
2666 The 'binvar' argument models the redundancy of the linear constraint. A solution for which
2667 'binvar' is 1 must satisfy the constraint.
2669 :param cons: a linear inequality of the form "<="
2670 :param binvar: binary indicator variable, or None if it should be created (Default value = None)
2671 :param activeone: constraint should active if binvar is 1 (0 if activeone = False)
2672 :param name: name of the constraint (Default value = "IndicatorCons")
2673 :param initial: should the LP relaxation of constraint be in the initial LP? (Default value = True)
2674 :param separate: should the constraint be separated during LP processing? (Default value = True)
2675 :param enforce: should the constraint be enforced during node processing? (Default value = True)
2676 :param check: should the constraint be checked for feasibility? (Default value = True)
2677 :param propagate: should the constraint be propagated during node processing? (Default value = True)
2678 :param local: is the constraint only valid locally? (Default value = False)
2679 :param dynamic: is the constraint subject to aging? (Default value = False)
2680 :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False)
2681 :param stickingatnode: should the constraint always be kept at the node where it was added, even if it may be moved to a more global node? (Default value = False)
2684 assert isinstance(cons, ExprCons),
"given constraint is not ExprCons but %s" % cons.__class__.__name__
2685 cdef SCIP_CONS* scip_cons
2686 cdef SCIP_VAR* _binVar
2687 if cons._lhs
is not None and cons._rhs
is not None:
2688 raise ValueError(
"expected inequality that has either only a left or right hand side")
2690 if cons.expr.degree() > 1:
2691 raise ValueError(
"expected linear inequality, expression has degree %d" % cons.expr.degree())
2693 if cons._rhs
is not None:
2700 if binvar
is not None:
2701 _binVar = (<Variable>binvar).scip_var
2708 initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode))
2709 terms = cons.expr.terms
2711 for key, coeff
in terms.items():
2712 var = <Variable>key[0]
2718 pyCons = Constraint.create(scip_cons)
2725 """Get slack variable of an indicator constraint.
2727 :param Constraint cons: indicator constraint
2731 return Variable.create(var)
2734 """Adds a customly created cons.
2736 :param Constraint cons: constraint to add
2743 """Add variable to SOS1 constraint.
2745 :param Constraint cons: SOS1 constraint
2746 :param Variable var: new variable
2747 :param weight: weight of new variable
2753 """Append variable to SOS1 constraint.
2755 :param Constraint cons: SOS1 constraint
2756 :param Variable var: variable to append
2762 """Add variable to SOS2 constraint.
2764 :param Constraint cons: SOS2 constraint
2765 :param Variable var: new variable
2766 :param weight: weight of new variable
2772 """Append variable to SOS2 constraint.
2774 :param Constraint cons: SOS2 constraint
2775 :param Variable var: variable to append
2781 """Set "initial" flag of a constraint.
2785 newInit -- new initial value
2790 """Set "removable" flag of a constraint.
2794 newRem -- new removable value
2799 """Set "enforced" flag of a constraint.
2803 newEnf -- new enforced value
2808 """Set "check" flag of a constraint.
2812 newCheck -- new check value
2817 """Change right hand side value of a constraint.
2819 :param Constraint cons: linear or quadratic constraint
2820 :param rhs: new ride hand side (set to None for +infinity)
2828 if constype ==
'linear':
2830 elif constype ==
'nonlinear':
2833 raise Warning(
"method cannot be called for constraints of type " + constype)
2836 """Change left hand side value of a constraint.
2838 :param Constraint cons: linear or quadratic constraint
2839 :param lhs: new left hand side (set to None for -infinity)
2847 if constype ==
'linear':
2849 elif constype ==
'nonlinear':
2852 raise Warning(
"method cannot be called for constraints of type " + constype)
2855 """Retrieve right hand side value of a constraint.
2857 :param Constraint cons: linear or quadratic constraint
2861 if constype ==
'linear':
2863 elif constype ==
'quadratic':
2866 raise Warning(
"method cannot be called for constraints of type " + constype)
2869 """Retrieve left hand side value of a constraint.
2871 :param Constraint cons: linear or quadratic constraint
2875 if constype ==
'linear':
2877 elif constype ==
'quadratic':
2880 raise Warning(
"method cannot be called for constraints of type " + constype)
2883 """Retrieve activity of given constraint.
2884 Can only be called after solving is completed.
2886 :param Constraint cons: linear or quadratic constraint
2887 :param Solution sol: solution to compute activity of, None to use current node's solution (Default value = None)
2890 cdef SCIP_Real activity
2891 cdef SCIP_SOL* scip_sol
2893 if not self.
getStage() >= SCIP_STAGE_SOLVING:
2894 raise Warning(
"method cannot be called before problem is solved")
2896 if isinstance(sol, Solution):
2902 if constype ==
'linear':
2905 raise Warning(
"method cannot be called for constraints of type " + constype)
2910 def getSlack(self, Constraint cons, Solution sol = None, side = None):
2911 """Retrieve slack of given constraint.
2912 Can only be called after solving is completed.
2915 :param Constraint cons: linear or quadratic constraint
2916 :param Solution sol: solution to compute slack of, None to use current node's solution (Default value = None)
2917 :param side: whether to use 'lhs' or 'rhs' for ranged constraints, None to return minimum (Default value = None)
2920 cdef SCIP_Real activity
2921 cdef SCIP_SOL* scip_sol
2924 if not self.
getStage() >= SCIP_STAGE_SOLVING:
2925 raise Warning(
"method cannot be called before problem is solved")
2927 if isinstance(sol, Solution):
2933 if constype ==
'linear':
2938 raise Warning(
"method cannot be called for constraints of type " + constype)
2940 lhsslack = activity - lhs
2941 rhsslack = rhs - activity
2948 return min(lhsslack, rhsslack)
2951 """Retrieve transformed constraint.
2953 :param Constraint cons: constraint
2956 cdef SCIP_CONS* transcons
2958 return Constraint.create(transcons)
2961 """returns whether SCIP's internal NLP has been constructed"""
2965 """gets current number of nonlinear rows in SCIP's internal NLP"""
2969 """returns a list with the nonlinear rows in SCIP's internal NLP"""
2970 cdef SCIP_NLROW** nlrows
2973 return [NLRow.create(nlrows[i])
for i
in range(self.
getNNlRows())]
2976 """gives the activity of a nonlinear row for a given primal solution
2978 nlrow -- nonlinear row
2979 solution -- a primal solution, if None, then the current LP solution is used
2981 cdef SCIP_Real activity
2982 cdef SCIP_SOL* solptr
2984 solptr = sol.sol
if not sol
is None else NULL
2989 """gives the feasibility of a nonlinear row for a given primal solution
2991 nlrow -- nonlinear row
2992 solution -- a primal solution, if None, then the current LP solution is used
2994 cdef SCIP_Real feasibility
2995 cdef SCIP_SOL* solptr
2997 solptr = sol.sol
if not sol
is None else NULL
3002 """gives the minimal and maximal activity of a nonlinear row w.r.t. the variable's bounds"""
3003 cdef SCIP_Real minactivity
3004 cdef SCIP_Real maxactivity
3007 return (minactivity, maxactivity)
3010 """prints nonlinear row"""
3014 """returns if the given constraint is quadratic
3016 :param Constraint cons: constraint
3019 cdef SCIP_Bool isquadratic
3024 """Retrieve bilinear, quadratic, and linear terms of a quadratic constraint.
3026 :param Constraint cons: constraint
3029 cdef SCIP_EXPR* expr
3032 cdef SCIP_EXPR** _linexprs
3033 cdef SCIP_Real* _lincoefs
3037 cdef int _nbilinterms
3038 cdef SCIP_EXPR* bilinterm1
3039 cdef SCIP_EXPR* bilinterm2
3040 cdef SCIP_Real bilincoef
3043 cdef int _nquadterms
3044 cdef SCIP_Real sqrcoef
3045 cdef SCIP_Real lincoef
3046 cdef SCIP_EXPR* sqrexpr
3049 cdef SCIP_VAR* scipvar1
3050 cdef SCIP_VAR* scipvar2
3052 assert cons.isNonlinear(),
"constraint is not nonlinear"
3062 for termidx
in range(_nlinvars):
3064 linterms.append((var,_lincoefs[termidx]))
3066 for termidx
in range(_nbilinterms):
3070 var1 = Variable.create(scipvar1)
3071 var2 = Variable.create(scipvar2)
3072 if scipvar1 != scipvar2:
3073 bilinterms.append((var1,var2,bilincoef))
3075 quadterms.append((var1,bilincoef,0.0))
3077 for termidx
in range(_nquadterms):
3082 quadterms.append((var,sqrcoef,lincoef))
3084 return (bilinterms, quadterms, linterms)
3087 """sets the value of the given variable in the global relaxation solution"""
3091 """Retrieve all constraints."""
3092 cdef SCIP_CONS** _conss
3098 return [Constraint.create(_conss[i])
for i
in range(_nconss)]
3101 """Retrieve number of all constraints"""
3105 """Delete constraint from the model
3107 :param Constraint cons: constraint to be deleted
3113 """Delete constraint from the current node and it's children
3115 :param Constraint cons: constraint to be deleted
3121 """Retrieve the coefficients of a linear constraint
3123 :param Constraint cons: linear constraint to get the coefficients of
3126 cdef SCIP_Real* _vals
3127 cdef SCIP_VAR** _vars
3130 if not constype ==
'linear':
3131 raise Warning(
"coefficients not available for constraints of type ", constype)
3138 valsdict[bytes(
SCIPvarGetName(_vars[i])).decode(
'utf-8')] = _vals[i]
3142 """Retrieve the linear relaxation of the given linear constraint as a row.
3143 may return NULL if no LP row was yet created; the user must not modify the row!
3145 :param Constraint cons: linear constraint to get the coefficients of
3149 if not constype ==
'linear':
3150 raise Warning(
"coefficients not available for constraints of type ", constype)
3153 return Row.create(row)
3156 """Retrieve the dual solution to a linear constraint.
3158 :param Constraint cons: linear constraint
3162 if not constype ==
'linear':
3163 raise Warning(
"dual solution values not available for constraints of type ", constype)
3164 if cons.isOriginal():
3171 """DEPRECATED: Retrieve the dual solution to a linear constraint.
3173 :param Constraint cons: linear constraint
3176 raise Warning(
"model.getDualMultiplier(cons) is deprecated: please use model.getDualsolLinear(cons)")
3180 """Retrieve the dual farkas value to a linear constraint.
3182 :param Constraint cons: linear constraint
3186 if cons.isOriginal():
3193 """Retrieve the reduced cost of a variable.
3195 :param Variable var: variable to get the reduced cost of
3204 raise Warning(
"no reduced cost available for variable " + var.name)
3208 """Retrieve returns dual solution value of a constraint.
3210 :param Constraint cons: constraint to get the dual solution value of
3211 :param boundconstraint bool: Decides whether to store a bool if the constraint is a bound constraint
3214 cdef SCIP_Real _dualsol
3215 cdef SCIP_Bool _bounded
3226 """Optimize the problem."""
3231 """Transforms, presolves, and solves problem using additional solvers which emphasize on
3232 finding solutions."""
3233 if SCIPtpiGetNumThreads() == 1:
3234 warnings.warn(
"SCIP was compiled without task processing interface. Parallel solve not possible - using optimize() instead of solveConcurrent()")
3241 """Presolve the problem."""
3246 """initialises the default Benders' decomposition with a dictionary of subproblems
3249 subproblems -- a single Model instance or dictionary of Model instances
3251 cdef SCIP** subprobs
3252 cdef SCIP_BENDERS* benders
3255 if isinstance(subproblems, dict):
3257 nsubproblems = len(subproblems)
3263 subprobs = <SCIP**> malloc(nsubproblems * sizeof(SCIP*))
3267 for idx, subprob
in enumerate(subproblems.values()):
3268 subprobs[idx] = (<Model>subprob)._scip
3270 subprobs[0] = (<Model>subproblems)._scip
3277 self.
setBoolParam(
"constraints/benderslp/active",
True)
3282 """Solves the subproblems with the best solution to the master problem.
3283 Afterwards, the best solution from each subproblem can be queried to get
3284 the solution to the original problem.
3286 If the user wants to resolve the subproblems, they must free them by
3287 calling freeBendersSubproblems()
3289 cdef SCIP_BENDERS** _benders
3290 cdef SCIP_Bool _infeasible
3292 cdef int nsubproblems
3300 for i
in range(nbenders):
3302 for j
in range(nsubproblems):
3304 _benders[i], self.
_bestSol.sol, j, SCIP_BENDERSENFOTYPE_CHECK))
3306 _benders[i], self.
_bestSol.sol, j, &_infeasible, solvecip, NULL))
3309 """Calls the free subproblem function for the Benders' decomposition.
3310 This will free all subproblems for all decompositions.
3312 cdef SCIP_BENDERS** _benders
3314 cdef int nsubproblems
3320 for i
in range(nbenders):
3322 for j
in range(nsubproblems):
3327 """"updates the subproblem lower bounds for benders using
3328 the lowerbounds dict. If benders is None, then the default
3329 Benders' decomposition is updated
3331 cdef SCIP_BENDERS* _benders
3333 assert type(lowerbounds)
is dict
3338 _benders = benders._benders
3340 for d
in lowerbounds.keys():
3344 """Activates the Benders' decomposition plugin with the input name
3347 benders -- the Benders' decomposition to which the subproblem belongs to
3348 nsubproblems -- the number of subproblems in the Benders' decomposition
3353 """adds a subproblem to the Benders' decomposition given by the input
3357 benders -- the Benders' decomposition to which the subproblem belongs to
3358 subproblem -- the subproblem to add to the decomposition
3359 isconvex -- can be used to specify whether the subproblem is convex
3364 """sets a flag indicating whether the subproblem is convex
3367 benders -- the Benders' decomposition which contains the subproblem
3368 probnumber -- the problem number of the subproblem that the convexity will be set for
3369 isconvex -- flag to indicate whether the subproblem is convex
3373 def setupBendersSubproblem(self, probnumber, Benders benders = None, Solution solution = None, checktype = PY_SCIP_BENDERSENFOTYPE.LP):
3374 """ sets up the Benders' subproblem given the master problem solution
3377 probnumber -- the index of the problem that is to be set up
3378 benders -- the Benders' decomposition to which the subproblem belongs to
3379 solution -- the master problem solution that is used for the set up, if None, then the LP solution is used
3380 checktype -- the type of solution check that prompted the solving of the Benders' subproblems, either
3381 PY_SCIP_BENDERSENFOTYPE: LP, RELAX, PSEUDO or CHECK. Default is LP
3383 cdef SCIP_BENDERS* scip_benders
3384 cdef SCIP_SOL* scip_sol
3386 if isinstance(solution, Solution):
3387 scip_sol = solution.sol
3394 scip_benders = benders._benders
3398 PY_SCIP_CALL(retcode)
3401 """ solves the Benders' decomposition subproblem. The convex relaxation will be solved unless
3402 the parameter solvecip is set to True.
3405 probnumber -- the index of the problem that is to be set up
3406 solvecip -- should the CIP of the subproblem be solved, if False, then only the convex relaxation is solved
3407 benders -- the Benders' decomposition to which the subproblem belongs to
3408 solution -- the master problem solution that is used for the set up, if None, then the LP solution is used
3411 cdef SCIP_BENDERS* scip_benders
3412 cdef SCIP_SOL* scip_sol
3413 cdef SCIP_Real objective
3414 cdef SCIP_Bool infeasible
3416 if isinstance(solution, Solution):
3417 scip_sol = solution.sol
3424 scip_benders = benders._benders
3427 probnumber, &infeasible, solvecip, &objective))
3429 return infeasible, objective
3432 """Returns a Model object that wraps around the SCIP instance of the subproblem.
3433 NOTE: This Model object is just a place holder and SCIP instance will not be freed when the object is destroyed.
3436 probnumber -- the problem number for subproblem that is required
3437 benders -- the Benders' decomposition object for the that the subproblem belongs to (Default = None)
3439 cdef SCIP_BENDERS* scip_benders
3440 cdef SCIP* scip_subprob
3445 scip_benders = benders._benders
3449 return Model.create(scip_subprob)
3452 """Returns the variable for the subproblem or master problem
3453 depending on the input probnumber
3456 var -- the source variable for which the target variable is requested
3457 benders -- the Benders' decomposition to which the subproblem variables belong to
3458 probnumber -- the problem number for which the target variable belongs, -1 for master problem
3460 cdef SCIP_BENDERS* _benders
3461 cdef SCIP_VAR* _mappedvar
3466 _benders = benders._benders
3468 if probnumber == -1:
3473 if _mappedvar == NULL:
3476 mappedvar = Variable.create(_mappedvar)
3481 """Returns the auxiliary variable that is associated with the input problem number
3484 probnumber -- the problem number for which the target variable belongs, -1 for master problem
3485 benders -- the Benders' decomposition to which the subproblem variables belong to
3487 cdef SCIP_BENDERS* _benders
3488 cdef SCIP_VAR* _auxvar
3493 _benders = benders._benders
3496 auxvar = Variable.create(_auxvar)
3501 """Returns whether the subproblem is optimal w.r.t the master problem auxiliary variables.
3504 solution -- the master problem solution that is being checked for optimamlity
3505 probnumber -- the problem number for which optimality is being checked
3506 benders -- the Benders' decomposition to which the subproblem belongs to
3508 cdef SCIP_BENDERS* _benders
3509 cdef SCIP_SOL* scip_sol
3510 cdef SCIP_Bool optimal
3515 _benders = benders._benders
3517 if isinstance(solution, Solution):
3518 scip_sol = solution.sol
3523 scip_sol, probnumber, &optimal) )
3528 """includes the default Benders' decomposition cuts to the custom Benders' decomposition plugin
3531 benders -- the Benders' decomposition that the default cuts will be applied to
3533 PY_SCIP_CALL( SCIPincludeBendersDefaultCuts(self.
_scip, benders._benders) )
3537 """Include an event handler.
3540 eventhdlr -- event handler
3541 name -- name of event handler
3542 desc -- description of event handler
3555 <SCIP_EVENTHDLRDATA*>eventhdlr))
3556 eventhdlr.model = <Model>weakref.proxy(self)
3557 eventhdlr.name = name
3558 Py_INCREF(eventhdlr)
3561 """Include a pricer.
3563 :param Pricer pricer: pricer
3564 :param name: name of pricer
3565 :param desc: description of pricer
3566 :param priority: priority of pricer (Default value = 1)
3567 :param delay: should the pricer be delayed until no other pricers or already existing problem variables with negative reduced costs are found? (Default value = True)
3574 PyPricerCopy, PyPricerFree, PyPricerInit, PyPricerExit, PyPricerInitsol, PyPricerExitsol, PyPricerRedcost, PyPricerFarkas,
3575 <SCIP_PRICERDATA*>pricer))
3576 cdef SCIP_PRICER* scip_pricer
3579 pricer.model = <Model>weakref.proxy(self)
3583 enfopriority=0, chckpriority=0, sepafreq=-1, propfreq=-1,
3584 eagerfreq=100, maxprerounds=-1, delaysepa=False,
3585 delayprop=False, needscons=True,
3586 proptiming=PY_SCIP_PROPTIMING.BEFORELP,
3587 presoltiming=PY_SCIP_PRESOLTIMING.MEDIUM):
3588 """Include a constraint handler
3590 :param Conshdlr conshdlr: constraint handler
3591 :param name: name of constraint handler
3592 :param desc: description of constraint handler
3593 :param sepapriority: priority for separation (Default value = 0)
3594 :param enfopriority: priority for constraint enforcing (Default value = 0)
3595 :param chckpriority: priority for checking feasibility (Default value = 0)
3596 :param sepafreq: frequency for separating cuts; 0 = only at root node (Default value = -1)
3597 :param propfreq: frequency for propagating domains; 0 = only preprocessing propagation (Default value = -1)
3598 :param eagerfreq: frequency for using all instead of only the useful constraints in separation, propagation and enforcement; -1 = no eager evaluations, 0 = first only (Default value = 100)
3599 :param maxprerounds: maximal number of presolving rounds the constraint handler participates in (Default value = -1)
3600 :param delaysepa: should separation method be delayed, if other separators found cuts? (Default value = False)
3601 :param delayprop: should propagation method be delayed, if other propagators found reductions? (Default value = False)
3602 :param needscons: should the constraint handler be skipped, if no constraints are available? (Default value = True)
3603 :param proptiming: positions in the node solving loop where propagation method of constraint handlers should be executed (Default value = SCIP_PROPTIMING.BEFORELP)
3604 :param presoltiming: timing mask of the constraint handler's presolving method (Default value = SCIP_PRESOLTIMING.MEDIUM)
3609 PY_SCIP_CALL(
SCIPincludeConshdlr(self.
_scip, n, d, sepapriority, enfopriority, chckpriority, sepafreq, propfreq, eagerfreq,
3610 maxprerounds, delaysepa, delayprop, needscons, proptiming, presoltiming,
3611 PyConshdlrCopy, PyConsFree, PyConsInit, PyConsExit, PyConsInitpre, PyConsExitpre,
3612 PyConsInitsol, PyConsExitsol, PyConsDelete, PyConsTrans, PyConsInitlp, PyConsSepalp, PyConsSepasol,
3613 PyConsEnfolp, PyConsEnforelax, PyConsEnfops, PyConsCheck, PyConsProp, PyConsPresol, PyConsResprop, PyConsLock,
3614 PyConsActive, PyConsDeactive, PyConsEnable, PyConsDisable, PyConsDelvars, PyConsPrint, PyConsCopy,
3615 PyConsParse, PyConsGetvars, PyConsGetnvars, PyConsGetdivebdchgs,
3616 <SCIP_CONSHDLRDATA*>conshdlr))
3617 conshdlr.model = <Model>weakref.proxy(self)
3618 conshdlr.name = name
3621 def createCons(self, Conshdlr conshdlr, name, initial=True, separate=True, enforce=True, check=True, propagate=True,
3622 local=False, modifiable=False, dynamic=False, removable=False, stickingatnode=False):
3623 """Create a constraint of a custom constraint handler
3625 :param Conshdlr conshdlr: constraint handler
3626 :param name: name of constraint
3627 :param initial: (Default value = True)
3628 :param separate: (Default value = True)
3629 :param enforce: (Default value = True)
3630 :param check: (Default value = True)
3631 :param propagate: (Default value = True)
3632 :param local: (Default value = False)
3633 :param modifiable: (Default value = False)
3634 :param dynamic: (Default value = False)
3635 :param removable: (Default value = False)
3636 :param stickingatnode: (Default value = False)
3641 cdef SCIP_CONSHDLR* scip_conshdlr
3644 PY_SCIP_CALL(
SCIPcreateCons(self.
_scip, &(constraint.scip_cons), n, scip_conshdlr, <SCIP_CONSDATA*>constraint,
3645 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode))
3648 def includePresol(self, Presol presol, name, desc, priority, maxrounds, timing=SCIP_PRESOLTIMING_FAST):
3649 """Include a presolver
3651 :param Presol presol: presolver
3652 :param name: name of presolver
3653 :param desc: description of presolver
3654 :param priority: priority of the presolver (>= 0: before, < 0: after constraint handlers)
3655 :param maxrounds: maximal number of presolving rounds the presolver participates in (-1: no limit)
3656 :param timing: timing mask of presolver (Default value = SCIP_PRESOLTIMING_FAST)
3661 PY_SCIP_CALL(
SCIPincludePresol(self.
_scip, n, d, priority, maxrounds, timing, PyPresolCopy, PyPresolFree, PyPresolInit,
3662 PyPresolExit, PyPresolInitpre, PyPresolExitpre, PyPresolExec, <SCIP_PRESOLDATA*>presol))
3663 presol.model = <Model>weakref.proxy(self)
3666 def includeSepa(self, Sepa sepa, name, desc, priority=0, freq=10, maxbounddist=1.0, usessubscip=False, delay=False):
3667 """Include a separator
3669 :param Sepa sepa: separator
3670 :param name: name of separator
3671 :param desc: description of separator
3672 :param priority: priority of separator (>= 0: before, < 0: after constraint handlers)
3673 :param freq: frequency for calling separator
3674 :param maxbounddist: maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for applying separation
3675 :param usessubscip: does the separator use a secondary SCIP instance? (Default value = False)
3676 :param delay: should separator be delayed, if other separators found cuts? (Default value = False)
3681 PY_SCIP_CALL(
SCIPincludeSepa(self.
_scip, n, d, priority, freq, maxbounddist, usessubscip, delay, PySepaCopy, PySepaFree,
3682 PySepaInit, PySepaExit, PySepaInitsol, PySepaExitsol, PySepaExeclp, PySepaExecsol, <SCIP_SEPADATA*>sepa))
3683 sepa.model = <Model>weakref.proxy(self)
3690 :param Reader reader: reader
3691 :param name: name of reader
3692 :param desc: description of reader
3693 :param ext: file extension of reader
3700 PyReaderRead, PyReaderWrite, <SCIP_READERDATA*>reader))
3701 reader.model = <Model>weakref.proxy(self)
3705 def includeProp(self, Prop prop, name, desc, presolpriority, presolmaxrounds,
3706 proptiming, presoltiming=SCIP_PRESOLTIMING_FAST, priority=1, freq=1, delay=True):
3707 """Include a propagator.
3709 :param Prop prop: propagator
3710 :param name: name of propagator
3711 :param desc: description of propagator
3712 :param presolpriority: presolving priority of the propgator (>= 0: before, < 0: after constraint handlers)
3713 :param presolmaxrounds: maximal number of presolving rounds the propagator participates in (-1: no limit)
3714 :param proptiming: positions in the node solving loop where propagation method of constraint handlers should be executed
3715 :param presoltiming: timing mask of the constraint handler's presolving method (Default value = SCIP_PRESOLTIMING_FAST)
3716 :param priority: priority of the propagator (Default value = 1)
3717 :param freq: frequency for calling propagator (Default value = 1)
3718 :param delay: should propagator be delayed if other propagators have found reductions? (Default value = True)
3724 priority, freq, delay,
3725 proptiming, presolpriority, presolmaxrounds,
3726 presoltiming, PyPropCopy, PyPropFree, PyPropInit, PyPropExit,
3727 PyPropInitpre, PyPropExitpre, PyPropInitsol, PyPropExitsol,
3728 PyPropPresol, PyPropExec, PyPropResProp,
3729 <SCIP_PROPDATA*> prop))
3730 prop.model = <Model>weakref.proxy(self)
3733 def includeHeur(self, Heur heur, name, desc, dispchar, priority=10000, freq=1, freqofs=0,
3734 maxdepth=-1, timingmask=SCIP_HEURTIMING_BEFORENODE, usessubscip=False):
3735 """Include a primal heuristic.
3737 :param Heur heur: heuristic
3738 :param name: name of heuristic
3739 :param desc: description of heuristic
3740 :param dispchar: display character of heuristic
3741 :param priority: priority of the heuristic (Default value = 10000)
3742 :param freq: frequency for calling heuristic (Default value = 1)
3743 :param freqofs: frequency offset for calling heuristic (Default value = 0)
3744 :param maxdepth: maximal depth level to call heuristic at (Default value = -1)
3745 :param timingmask: positions in the node solving loop where heuristic should be executed (Default value = SCIP_HEURTIMING_BEFORENODE)
3746 :param usessubscip: does the heuristic use a secondary SCIP instance? (Default value = False)
3753 priority, freq, freqofs,
3754 maxdepth, timingmask, usessubscip,
3755 PyHeurCopy, PyHeurFree, PyHeurInit, PyHeurExit,
3756 PyHeurInitsol, PyHeurExitsol, PyHeurExec,
3757 <SCIP_HEURDATA*> heur))
3758 heur.model = <Model>weakref.proxy(self)
3763 """Include a relaxation handler.
3765 :param Relax relax: relaxation handler
3766 :param name: name of relaxation handler
3767 :param desc: description of relaxation handler
3768 :param priority: priority of the relaxation handler (negative: after LP, non-negative: before LP, Default value = 10000)
3769 :param freq: frequency for calling relaxation handler
3774 PY_SCIP_CALL(
SCIPincludeRelax(self.
_scip, nam, des, priority, freq, PyRelaxCopy, PyRelaxFree, PyRelaxInit, PyRelaxExit,
3775 PyRelaxInitsol, PyRelaxExitsol, PyRelaxExec, <SCIP_RELAXDATA*> relax))
3776 relax.model = <Model>weakref.proxy(self)
3782 """include a cut selector
3784 :param Cutsel cutsel: cut selector
3785 :param name: name of cut selector
3786 :param desc: description of cut selector
3787 :param priority: priority of the cut selector
3793 priority, PyCutselCopy, PyCutselFree, PyCutselInit, PyCutselExit,
3794 PyCutselInitsol, PyCutselExitsol, PyCutselSelect,
3795 <SCIP_CUTSELDATA*> cutsel))
3796 cutsel.model = <Model>weakref.proxy(self)
3800 """Include a branching rule.
3802 :param Branchrule branchrule: branching rule
3803 :param name: name of branching rule
3804 :param desc: description of branching rule
3805 :param priority: priority of branching rule
3806 :param maxdepth: maximal depth level up to which this branching rule should be used (or -1)
3807 :param maxbounddist: maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for applying branching rule (0.0: only on current best node, 1.0: on all nodes)
3813 priority, maxdepth, maxbounddist,
3814 PyBranchruleCopy, PyBranchruleFree, PyBranchruleInit, PyBranchruleExit,
3815 PyBranchruleInitsol, PyBranchruleExitsol, PyBranchruleExeclp, PyBranchruleExecext,
3816 PyBranchruleExecps, <SCIP_BRANCHRULEDATA*> branchrule))
3817 branchrule.model = <Model>weakref.proxy(self)
3818 Py_INCREF(branchrule)
3821 """Include a node selector.
3823 :param Nodesel nodesel: node selector
3824 :param name: name of node selector
3825 :param desc: description of node selector
3826 :param stdpriority: priority of the node selector in standard mode
3827 :param memsavepriority: priority of the node selector in memory saving mode
3833 stdpriority, memsavepriority,
3834 PyNodeselCopy, PyNodeselFree, PyNodeselInit, PyNodeselExit,
3835 PyNodeselInitsol, PyNodeselExitsol, PyNodeselSelect, PyNodeselComp,
3836 <SCIP_NODESELDATA*> nodesel))
3837 nodesel.model = <Model>weakref.proxy(self)
3840 def includeBenders(self, Benders benders, name, desc, priority=1, cutlp=True, cutpseudo=True, cutrelax=True,
3842 """Include a Benders' decomposition.
3845 benders -- the Benders decomposition
3847 desc -- the description
3848 priority -- priority of the Benders' decomposition
3849 cutlp -- should Benders' cuts be generated from LP solutions
3850 cutpseudo -- should Benders' cuts be generated from pseudo solutions
3851 cutrelax -- should Benders' cuts be generated from relaxation solutions
3852 shareaux -- should the Benders' decomposition share the auxiliary variables of the highest priority Benders' decomposition
3857 priority, cutlp, cutrelax, cutpseudo, shareaux,
3858 PyBendersCopy, PyBendersFree, PyBendersInit, PyBendersExit, PyBendersInitpre,
3859 PyBendersExitpre, PyBendersInitsol, PyBendersExitsol, PyBendersGetvar,
3860 PyBendersCreatesub, PyBendersPresubsolve, PyBendersSolvesubconvex,
3861 PyBendersSolvesub, PyBendersPostsolve, PyBendersFreesub,
3862 <SCIP_BENDERSDATA*>benders))
3863 cdef SCIP_BENDERS* scip_benders
3865 benders.model = <Model>weakref.proxy(self)
3867 benders._benders = scip_benders
3870 def includeBenderscut(self, Benders benders, Benderscut benderscut, name, desc, priority=1, islpcut=True):
3871 """ Include a Benders' decomposition cutting method
3874 benders -- the Benders' decomposition that this cutting method is attached to
3875 benderscut --- the Benders' decomposition cutting method
3877 desc -- the description
3878 priority -- priority of the Benders' decomposition
3879 islpcut -- is this cutting method suitable for generating cuts for convex relaxations?
3881 cdef SCIP_BENDERS* _benders
3883 _benders = benders._benders
3888 PyBenderscutCopy, PyBenderscutFree, PyBenderscutInit, PyBenderscutExit,
3889 PyBenderscutInitsol, PyBenderscutExitsol, PyBenderscutExec,
3890 <SCIP_BENDERSCUTDATA*>benderscut))
3892 cdef SCIP_BENDERSCUT* scip_benderscut
3894 benderscut.model = <Model>weakref.proxy(self)
3895 benderscut.benders = benders
3896 benderscut.name = name
3898 Py_INCREF(benderscut)
3902 """gets branching candidates for LP solution branching (fractional variables) along with solution values,
3903 fractionalities, and number of branching candidates; The number of branching candidates does NOT account
3904 for fractional implicit integer variables which should not be used for branching decisions. Fractional
3905 implicit integer variables are stored at the positions *nlpcands to *nlpcands + *nfracimplvars - 1
3906 branching rules should always select the branching candidate among the first npriolpcands of the candidate list
3908 :return tuple (lpcands, lpcandssol, lpcadsfrac, nlpcands, npriolpcands, nfracimplvars) where
3910 lpcands: list of variables of LP branching candidates
3911 lpcandssol: list of LP candidate solution values
3912 lpcandsfrac list of LP candidate fractionalities
3913 nlpcands: number of LP branching candidates
3914 npriolpcands: number of candidates with maximal priority
3915 nfracimplvars: number of fractional implicit integer variables
3920 cdef int npriolpcands
3921 cdef int nfracimplvars
3923 cdef SCIP_VAR** lpcands
3924 cdef SCIP_Real* lpcandssol
3925 cdef SCIP_Real* lpcandsfrac
3928 &nlpcands, &npriolpcands, &nfracimplvars))
3930 return ([Variable.create(lpcands[i])
for i
in range(nlpcands)], [lpcandssol[i]
for i
in range(nlpcands)],
3931 [lpcandsfrac[i]
for i
in range(nlpcands)], nlpcands, npriolpcands, nfracimplvars)
3934 """gets branching candidates for pseudo solution branching (non-fixed variables)
3935 along with the number of candidates.
3937 :return tuple (pseudocands, npseudocands, npriopseudocands) where
3939 pseudocands: list of variables of pseudo branching candidates
3940 npseudocands: number of pseudo branching candidates
3941 npriopseudocands: number of candidates with maximal priority
3944 cdef int npseudocands
3945 cdef int npriopseudocands
3947 cdef SCIP_VAR** pseudocands
3951 return ([Variable.create(pseudocands[i])
for i
in range(npseudocands)], npseudocands, npriopseudocands)
3954 """Branch on a non-continuous variable.
3956 :param variable: Variable to branch on
3957 :return: tuple(downchild, eqchild, upchild) of Nodes of the left, middle and right child. Middle child only exists
3958 if branch variable is integer (it is None otherwise)
3961 cdef SCIP_NODE* downchild
3962 cdef SCIP_NODE* eqchild
3963 cdef SCIP_NODE* upchild
3965 PY_SCIP_CALL(
SCIPbranchVar(self.
_scip, (<Variable>variable).scip_var, &downchild, &eqchild, &upchild))
3966 return Node.create(downchild), Node.create(eqchild), Node.create(upchild)
3970 """Branches on variable using a value which separates the domain of the variable.
3972 :param variable: Variable to branch on
3973 :param value: float, value to branch on
3974 :return: tuple(downchild, eqchild, upchild) of Nodes of the left, middle and right child. Middle child only exists
3975 if branch variable is integer (it is None otherwise)
3978 cdef SCIP_NODE* downchild
3979 cdef SCIP_NODE* eqchild
3980 cdef SCIP_NODE* upchild
3982 PY_SCIP_CALL(
SCIPbranchVarVal(self.
_scip, (<Variable>variable).scip_var, value, &downchild, &eqchild, &upchild))
3984 return Node.create(downchild), Node.create(eqchild), Node.create(upchild)
3987 """calculates the node selection priority for moving the given variable's LP value
3988 to the given target value;
3989 this node selection priority can be given to the SCIPcreateChild() call
3991 :param variable: variable on which the branching is applied
3992 :param branchdir: type of branching that was performed
3993 :param targetvalue: new value of the variable in the child node
3994 :return: node selection priority for moving the given variable's LP value to the given target value
4000 """Calculates an estimate for the objective of the best feasible solution
4001 contained in the subtree after applying the given branching;
4002 this estimate can be given to the SCIPcreateChild() call
4004 :param variable: Variable to compute the estimate for
4005 :param targetvalue: new value of the variable in the child node
4006 :return: objective estimate of the best solution in the subtree after applying the given branching
4012 """Create a child node of the focus node.
4014 :param nodeselprio: float, node selection priority of new node
4015 :param estimate: float, estimate for(transformed) objective value of best feasible solution in subtree
4016 :return: Node, the child which was created
4019 cdef SCIP_NODE* child
4021 return Node.create(child)
4025 """Initiates LP diving
4026 It allows the user to change the LP in several ways, solve, change again, etc, without affecting the actual LP that has. When endDive() is called,
4027 SCIP will undo all changes done and recover the LP it had before startDive
4032 """Quits probing and resets bounds and constraints to the focus node's environment"""
4036 """changes (column) variable's objective value in current dive"""
4040 """changes variable's current lb in current dive"""
4044 """changes variable's current ub in current dive"""
4048 """returns variable's current lb in current dive"""
4052 """returns variable's current ub in current dive"""
4056 """changes row lhs in current dive, change will be undone after diving
4057 ends, for permanent changes use SCIPchgRowLhs()
4062 """changes row rhs in current dive, change will be undone after diving
4063 ends, for permanent changes use SCIPchgRowLhs()
4068 """adds a row to the LP in current dive"""
4072 """solves the LP of the current dive no separation or pricing is applied
4073 no separation or pricing is applied
4074 :param itlim: maximal number of LP iterations to perform (Default value = -1, that is, no limit)
4075 returns two booleans:
4076 lperror -- if an unresolved lp error occured
4077 cutoff -- whether the LP was infeasible or the objective limit was reached
4079 cdef SCIP_Bool lperror
4080 cdef SCIP_Bool cutoff
4083 return lperror, cutoff
4086 """returns if the current node is already solved and only propagated again."""
4091 """Initiates probing, making methods SCIPnewProbingNode(), SCIPbacktrackProbing(), SCIPchgVarLbProbing(),
4092 SCIPchgVarUbProbing(), SCIPfixVarProbing(), SCIPpropagateProbing(), SCIPsolveProbingLP(), etc available
4097 """Quits probing and resets bounds and constraints to the focus node's environment"""
4101 """creates a new probing sub node, whose changes can be undone by backtracking to a higher node in the
4102 probing path with a call to backtrackProbing()
4107 """undoes all changes to the problem applied in probing up to the given probing depth
4108 :param probingdepth: probing depth of the node in the probing path that should be reactivated
4113 """returns the current probing depth"""
4117 """changes (column) variable's objective value during probing mode"""
4121 """changes the variable lower bound during probing mode
4123 :param Variable var: variable to change bound of
4124 :param lb: new lower bound (set to None for -infinity)
4131 """changes the variable upper bound during probing mode
4133 :param Variable var: variable to change bound of
4134 :param ub: new upper bound (set to None for +infinity)
4141 """Fixes a variable at the current probing node."""
4145 """returns whether the objective function has changed during probing mode"""
4149 """returns whether we are in probing mode; probing mode is activated via startProbing() and stopped via endProbing()"""
4153 """solves the LP at the current probing node (cannot be applied at preprocessing stage)
4154 no separation or pricing is applied
4155 :param itlim: maximal number of LP iterations to perform (Default value = -1, that is, no limit)
4156 returns two booleans:
4157 lperror -- if an unresolved lp error occured
4158 cutoff -- whether the LP was infeasible or the objective limit was reached
4160 cdef SCIP_Bool lperror
4161 cdef SCIP_Bool cutoff
4164 return lperror, cutoff
4167 """applies the cuts in the separation storage to the LP and clears the storage afterwards;
4168 this method can only be applied during probing; the user should resolve the probing LP afterwards
4169 in order to get a new solution
4171 cutoff -- whether an empty domain was created
4173 cdef SCIP_Bool cutoff
4179 """applies domain propagation on the probing sub problem, that was changed after SCIPstartProbing() was called;
4180 the propagated domains of the variables can be accessed with the usual bound accessing calls SCIPvarGetLbLocal()
4181 and SCIPvarGetUbLocal(); the propagation is only valid locally, i.e. the local bounds as well as the changed
4182 bounds due to SCIPchgVarLbProbing(), SCIPchgVarUbProbing(), and SCIPfixVarProbing() are used for propagation
4183 :param maxproprounds: maximal number of propagation rounds (Default value = -1, that is, no limit)
4185 cutoff -- whether the probing node can be cutoff
4186 ndomredsfound -- number of domain reductions found
4188 cdef SCIP_Bool cutoff
4189 cdef SCIP_Longint ndomredsfound
4192 return cutoff, ndomredsfound
4195 """Interrupt the solving process as soon as possible."""
4199 """Restarts the solving process as soon as possible."""
4205 """writes current LP to a file
4206 :param filename: file name (Default value = "LP.lp")
4212 """Create a new primal solution.
4214 :param Heur heur: heuristic that found the solution (Default value = None)
4217 cdef SCIP_HEUR* _heur
4220 if isinstance(heur, Heur):
4226 solution = Solution.create(self.
_scip, _sol)
4230 """Create a partial primal solution, initialized to unknown values.
4231 :param Heur heur: heuristic that found the solution (Default value = None)
4234 cdef SCIP_HEUR* _heur
4237 if isinstance(heur, Heur):
4243 partialsolution = Solution.create(self.
_scip, _sol)
4244 return partialsolution
4247 """Prints the best feasible primal solution."""
4250 def printSol(self, Solution solution=None, write_zeros=False):
4251 """Print the given primal solution.
4254 solution -- solution to print
4255 write_zeros -- include variables that are set to zero
4257 if solution
is None:
4263 """Write the best feasible primal solution to a file.
4266 filename -- name of the output file
4267 write_zeros -- include variables that are set to zero
4271 with open(filename,
"w")
as f:
4272 cfile = fdopen(f.fileno(),
"w")
4276 """Write the best feasible primal solution for the transformed problem to a file.
4279 filename -- name of the output file
4280 write_zeros -- include variables that are set to zero
4284 with open(filename,
"w")
as f:
4285 cfile = fdopen(f.fileno(),
"w")
4288 def writeSol(self, Solution solution, filename="origprob.sol", write_zeros=False):
4289 """Write the given primal solution to a file.
4292 solution -- solution to write
4293 filename -- name of the output file
4294 write_zeros -- include variables that are set to zero
4298 with open(filename,
"w")
as f:
4299 cfile = fdopen(f.fileno(),
"w")
4302 def writeTransSol(self, Solution solution, filename="transprob.sol", write_zeros=False):
4303 """Write the given transformed primal solution to a file.
4306 solution -- transformed solution to write
4307 filename -- name of the output file
4308 write_zeros -- include variables that are set to zero
4312 with open(filename,
"w")
as f:
4313 cfile = fdopen(f.fileno(),
"w")
4319 """Reads a given solution file, problem has to be transformed in advance.
4322 filename -- name of the input file
4328 """Reads a given solution file.
4330 Solution is created but not added to storage/the model.
4331 Use 'addSol' OR 'trySol' to add it.
4334 filename -- name of the input file
4336 cdef SCIP_Bool partial
4337 cdef SCIP_Bool error
4338 cdef SCIP_Bool stored
4339 cdef Solution solution
4341 str_absfile = abspath(filename)
4346 raise Exception(
"SCIP: reading solution from file " + str_absfile +
" failed!")
4351 """Set a variable in a solution.
4353 :param Solution solution: solution to be modified
4354 :param Variable var: variable in the solution
4355 :param val: value of the specified variable
4359 _sol = <SCIP_SOL*>solution.sol
4362 def trySol(self, Solution solution, printreason=True, completely=False, checkbounds=True, checkintegrality=True, checklprows=True, free=True):
4363 """Check given primal solution for feasibility and try to add it to the storage.
4365 :param Solution solution: solution to store
4366 :param printreason: should all reasons of violations be printed? (Default value = True)
4367 :param completely: should all violation be checked? (Default value = False)
4368 :param checkbounds: should the bounds of the variables be checked? (Default value = True)
4369 :param checkintegrality: has integrality to be checked? (Default value = True)
4370 :param checklprows: have current LP rows (both local and global) to be checked? (Default value = True)
4371 :param free: should solution be freed? (Default value = True)
4374 cdef SCIP_Bool stored
4376 PY_SCIP_CALL(
SCIPtrySolFree(self.
_scip, &solution.sol, printreason, completely, checkbounds, checkintegrality, checklprows, &stored))
4378 PY_SCIP_CALL(
SCIPtrySol(self.
_scip, solution.sol, printreason, completely, checkbounds, checkintegrality, checklprows, &stored))
4381 def checkSol(self, Solution solution, printreason=True, completely=False, checkbounds=True, checkintegrality=True, checklprows=True, original=False):
4382 """Check given primal solution for feasibility without adding it to the storage.
4384 :param Solution solution: solution to store
4385 :param printreason: should all reasons of violations be printed? (Default value = True)
4386 :param completely: should all violation be checked? (Default value = False)
4387 :param checkbounds: should the bounds of the variables be checked? (Default value = True)
4388 :param checkintegrality: has integrality to be checked? (Default value = True)
4389 :param checklprows: have current LP rows (both local and global) to be checked? (Default value = True)
4390 :param original: must the solution be checked against the original problem (Default value = False)
4393 cdef SCIP_Bool feasible
4397 PY_SCIP_CALL(
SCIPcheckSol(self.
_scip, solution.sol, printreason, completely, checkbounds, checkintegrality, checklprows, &feasible))
4400 def addSol(self, Solution solution, free=True):
4401 """Try to add a solution to the storage.
4403 :param Solution solution: solution to store
4404 :param free: should solution be freed afterwards? (Default value = True)
4407 cdef SCIP_Bool stored
4415 """Free given solution
4417 :param Solution solution: solution to be freed
4423 """gets number of feasible primal solutions stored in the solution storage in case the problem is transformed;
4424 in case the problem stage is SCIP_STAGE_PROBLEM, the number of solution in the original solution candidate
4430 """gets number of feasible primal solutions found so far"""
4434 """gets number of feasible primal solutions respecting the objective limit found so far"""
4438 """gets number of feasible primal solutions found so far, that improved the primal bound at the time they were found"""
4442 """Retrieve list of all feasible primal solutions stored in the solution storage."""
4443 cdef SCIP_SOL** _sols
4449 for i
in range(nsols):
4450 sols.append(Solution.create(self.
_scip, _sols[i]))
4455 """Retrieve currently best known feasible primal solution."""
4460 """Retrieve the objective value of the solution.
4462 :param Solution sol: solution
4463 :param original: objective value in original space (Default value = True)
4467 sol = Solution.create(self.
_scip, NULL)
4468 sol._checkStage(
"getSolObjVal")
4476 """Retrieve the objective value of value of best solution.
4477 Can only be called after solving is completed.
4479 :param original: objective value in original space (Default value = True)
4482 if not self.
getStage() >= SCIP_STAGE_SOLVING:
4483 raise Warning(
"method cannot be called before problem is solved")
4487 """Retrieve value of given variable or expression in the given solution or in
4488 the LP/pseudo solution if sol == None
4490 :param Solution sol: solution
4491 :param Expr expr: polynomial expression to query the value of
4493 Note: a variable is also an expression
4496 if sol ==
None and isinstance(expr, Variable):
4497 var = <Variable> expr
4500 sol = Solution.create(self.
_scip, NULL)
4504 """Retrieve the value of the given variable or expression in the best known solution.
4505 Can only be called after solving is completed.
4507 :param Expr expr: polynomial expression to query the value of
4509 Note: a variable is also an expression
4511 if not self.
getStage() >= SCIP_STAGE_SOLVING:
4512 raise Warning(
"method cannot be called before problem is solved")
4516 """Retrieve the best primal bound."""
4520 """Retrieve the best dual bound."""
4524 """Retrieve the best root dual bound."""
4528 """Write the name of the variable to the std out.
4530 :param Variable var: variable
4536 """Retrieve current SCIP stage"""
4540 """Retrieve solution status."""
4542 if stat == SCIP_STATUS_OPTIMAL:
4544 elif stat == SCIP_STATUS_TIMELIMIT:
4546 elif stat == SCIP_STATUS_INFEASIBLE:
4548 elif stat == SCIP_STATUS_UNBOUNDED:
4550 elif stat == SCIP_STATUS_USERINTERRUPT:
4551 return "userinterrupt"
4552 elif stat == SCIP_STATUS_INFORUNBD:
4554 elif stat == SCIP_STATUS_NODELIMIT:
4556 elif stat == SCIP_STATUS_TOTALNODELIMIT:
4557 return "totalnodelimit"
4558 elif stat == SCIP_STATUS_STALLNODELIMIT:
4559 return "stallnodelimit"
4560 elif stat == SCIP_STATUS_GAPLIMIT:
4562 elif stat == SCIP_STATUS_MEMLIMIT:
4564 elif stat == SCIP_STATUS_SOLLIMIT:
4566 elif stat == SCIP_STATUS_BESTSOLLIMIT:
4567 return "bestsollimit"
4568 elif stat == SCIP_STATUS_RESTARTLIMIT:
4569 return "restartlimit"
4574 """Retrieve objective sense."""
4576 if sense == SCIP_OBJSENSE_MAXIMIZE:
4578 elif sense == SCIP_OBJSENSE_MINIMIZE:
4584 """catches a global (not variable or row dependent) event"""
4585 cdef SCIP_EVENTHDLR* _eventhdlr
4586 if isinstance(eventhdlr, Eventhdlr):
4590 raise Warning(
"event handler not found")
4594 """drops a global event (stops to track event)"""
4595 cdef SCIP_EVENTHDLR* _eventhdlr
4596 if isinstance(eventhdlr, Eventhdlr):
4600 raise Warning(
"event handler not found")
4604 """catches an objective value or domain change event on the given transformed variable"""
4605 cdef SCIP_EVENTHDLR* _eventhdlr
4606 if isinstance(eventhdlr, Eventhdlr):
4610 raise Warning(
"event handler not found")
4614 """drops an objective value or domain change event (stops to track event) on the given transformed variable"""
4615 cdef SCIP_EVENTHDLR* _eventhdlr
4616 if isinstance(eventhdlr, Eventhdlr):
4620 raise Warning(
"event handler not found")
4624 """catches a row coefficient, constant, or side change event on the given row"""
4625 cdef SCIP_EVENTHDLR* _eventhdlr
4626 if isinstance(eventhdlr, Eventhdlr):
4630 raise Warning(
"event handler not found")
4634 """drops a row coefficient, constant, or side change event (stops to track event) on the given row"""
4635 cdef SCIP_EVENTHDLR* _eventhdlr
4636 if isinstance(eventhdlr, Eventhdlr):
4640 raise Warning(
"event handler not found")
4646 """Print statistics."""
4650 """Write statistics to a file.
4653 filename -- name of the output file
4657 with open(filename,
"w")
as f:
4658 cfile = fdopen(f.fileno(),
"w")
4662 """gets total number of LPs solved so far"""
4670 :param quiet: hide output? (Default value = True)
4678 """Send output to python instead of terminal."""
4680 cdef SCIP_MESSAGEHDLR *myMessageHandler
4682 PY_SCIP_CALL(SCIPmessagehdlrCreate(&myMessageHandler,
False, NULL,
False, relayMessage, relayMessage, relayMessage, NULL, NULL))
4684 SCIPmessageSetErrorPrinting(relayErrorMessage, NULL)
4687 """sets the log file name for the currently installed message handler
4688 :param path: name of log file, or None (no log)
4696 """Set a boolean-valued parameter.
4698 :param name: name of parameter
4699 :param value: value of parameter
4706 """Set an int-valued parameter.
4708 :param name: name of parameter
4709 :param value: value of parameter
4716 """Set a long-valued parameter.
4718 :param name: name of parameter
4719 :param value: value of parameter
4726 """Set a real-valued parameter.
4728 :param name: name of parameter
4729 :param value: value of parameter
4736 """Set a char-valued parameter.
4738 :param name: name of parameter
4739 :param value: value of parameter
4746 """Set a string-valued parameter.
4748 :param name: name of parameter
4749 :param value: value of parameter
4757 """Set a parameter with value in int, bool, real, long, char or str.
4759 :param name: name of parameter
4760 :param value: value of parameter
4762 cdef SCIP_PARAM* param
4768 raise KeyError(
"Not a valid parameter name")
4770 paramtype = SCIPparamGetType(param)
4772 if paramtype == SCIP_PARAMTYPE_BOOL:
4774 elif paramtype == SCIP_PARAMTYPE_INT:
4776 elif paramtype == SCIP_PARAMTYPE_LONGINT:
4778 elif paramtype == SCIP_PARAMTYPE_REAL:
4780 elif paramtype == SCIP_PARAMTYPE_CHAR:
4782 elif paramtype == SCIP_PARAMTYPE_STRING:
4788 """Get the value of a parameter of type
4789 int, bool, real, long, char or str.
4791 :param name: name of parameter
4793 cdef SCIP_PARAM* param
4799 raise KeyError(
"Not a valid parameter name")
4801 paramtype = SCIPparamGetType(param)
4803 if paramtype == SCIP_PARAMTYPE_BOOL:
4804 return SCIPparamGetBool(param)
4805 elif paramtype == SCIP_PARAMTYPE_INT:
4806 return SCIPparamGetInt(param)
4807 elif paramtype == SCIP_PARAMTYPE_LONGINT:
4808 return SCIPparamGetLongint(param)
4809 elif paramtype == SCIP_PARAMTYPE_REAL:
4810 return SCIPparamGetReal(param)
4811 elif paramtype == SCIP_PARAMTYPE_CHAR:
4812 return chr(SCIPparamGetChar(param))
4813 elif paramtype == SCIP_PARAMTYPE_STRING:
4814 return SCIPparamGetString(param).decode(
'utf-8')
4817 """Gets the values of all parameters as a dict mapping parameter names
4819 cdef SCIP_PARAM** params
4824 name = SCIPparamGetName(params[i]).decode(
'utf-8')
4829 """Sets multiple parameters at once.
4831 :param params: dict mapping parameter names to their values.
4833 for name, value
in params.items():
4837 """Read an external parameter file.
4839 :param file: file to be read
4845 def writeParams(self, filename='param.set', comments = True, onlychanged = True):
4846 """Write parameter settings to an external file.
4848 :param filename: file to be written (Default value = 'param.set')
4849 :param comments: write parameter descriptions as comments? (Default value = True)
4850 :param onlychanged: write only modified parameters (Default value = True)
4853 str_absfile = abspath(filename)
4856 print(
'wrote parameter settings to file ' + str_absfile)
4859 """Reset parameter setting to its default value
4861 :param name: parameter to reset
4868 """Reset parameter settings to their default values"""
4872 """Set emphasis settings
4874 :param paraemphasis: emphasis to set
4875 :param quiet: hide output? (Default value = True)
4881 """Read a problem instance from an external file.
4883 :param filename: problem file name
4884 :param extension: specify file extension/type (Default value = None)
4888 if extension
is None:
4897 """Counts the number of feasible points of problem."""
4901 """Get number of currently available readers."""
4905 """Get number of feasible solution."""
4906 cdef SCIP_Bool valid
4907 cdef SCIP_Longint nsols
4911 print(
'total number of solutions found is not valid!')
4915 """Sets SCIP parameters such that a valid counting process is possible."""
4919 """Frees all solution process data and prepares for reoptimization"""
4923 """Establish the objective function as a linear expression.
4925 :param coeffs: the coefficients
4926 :param sense: the objective sense (Default value = 'minimize')
4930 cdef SCIP_OBJSENSE objsense
4932 if sense ==
"minimize":
4933 objsense = SCIP_OBJSENSE_MINIMIZE
4934 elif sense ==
"maximize":
4935 objsense = SCIP_OBJSENSE_MAXIMIZE
4937 raise Warning(
"unrecognized optimization sense: %s" % sense)
4939 assert isinstance(coeffs, Expr),
"given coefficients are not Expr but %s" % coeffs.__class__.__name__
4941 if coeffs.degree() > 1:
4942 raise ValueError(
"Nonlinear objective functions are not supported!")
4943 if coeffs[CONST] != 0.0:
4944 raise ValueError(
"Constant offsets in objective are not supported!")
4946 cdef SCIP_VAR** _vars
4950 _coeffs = <SCIP_Real*> malloc(_nvars * sizeof(SCIP_Real))
4952 for i
in range(_nvars):
4955 for term, coef
in coeffs.terms.items():
4958 assert len(term) == 1
4959 var = <Variable>term[0]
4960 for i
in range(_nvars):
4961 if _vars[i] == var.scip_var:
4969 """Sets the branch priority of the variable.
4970 Variables with higher branch priority are always preferred to variables with lower priority in selection of branching variable.
4972 :param Variable var: variable to change priority of
4973 :param priority: the new priority of the variable (the default branching priority is 0)
4975 assert isinstance(var, Variable),
"The given variable is not a pyvar, but %s" % var.__class__.__name__
4980 return BMSgetMemoryUsed() == 0
4983 BMScheckEmptyMemory()