A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://scipopt.github.io/PySCIPOpt/docs/html/scip_8pxi_source.html below:

PySCIPOpt: src/pyscipopt/scip.pxi Source File

4 from

os.path

import

abspath

5 from

os.path

import

splitext

12 from

cpython cimport Py_INCREF, Py_DECREF

13 from

cpython.pycapsule cimport PyCapsule_New, PyCapsule_IsValid, PyCapsule_GetPointer

14 from

libc.stdlib cimport malloc, free

15 from

libc.stdio cimport fdopen, fclose

16 from

posix.stdio cimport fileno

18 from

collections.abc

import

Iterable

19 from

itertools

import

repeat

20 from

dataclasses

import

dataclass

25

include

"benderscut.pxi" 26

include

"branchrule.pxi" 27

include

"conshdlr.pxi" 30

include

"heuristic.pxi" 33

include

"propagator.pxi" 47 if

sys.version_info >= (3, 0):

48

str_conversion =

lambda

x:bytes(x,

'utf-8'

)

50

str_conversion =

lambda

x:x

52

_SCIP_BOUNDTYPE_TO_STRING = {SCIP_BOUNDTYPE_UPPER:

'<='

,

53

SCIP_BOUNDTYPE_LOWER:

'>='

}

59

cdef

class

PY_SCIP_RESULT:

60

DIDNOTRUN = SCIP_DIDNOTRUN

61

DELAYED = SCIP_DELAYED

62

DIDNOTFIND = SCIP_DIDNOTFIND

63

FEASIBLE = SCIP_FEASIBLE

64

INFEASIBLE = SCIP_INFEASIBLE

65

UNBOUNDED = SCIP_UNBOUNDED

67

SEPARATED = SCIP_SEPARATED

68

NEWROUND = SCIP_NEWROUND

69

REDUCEDDOM = SCIP_REDUCEDDOM

70

CONSADDED = SCIP_CONSADDED

71

CONSCHANGED = SCIP_CONSCHANGED

72

BRANCHED = SCIP_BRANCHED

73

SOLVELP = SCIP_SOLVELP

74

FOUNDSOL = SCIP_FOUNDSOL

75

SUSPENDED = SCIP_SUSPENDED

76

SUCCESS = SCIP_SUCCESS

78

cdef

class

PY_SCIP_PARAMSETTING:

79

DEFAULT = SCIP_PARAMSETTING_DEFAULT

80

AGGRESSIVE = SCIP_PARAMSETTING_AGGRESSIVE

81

FAST = SCIP_PARAMSETTING_FAST

82

OFF = SCIP_PARAMSETTING_OFF

84

cdef

class

PY_SCIP_PARAMEMPHASIS:

85

DEFAULT = SCIP_PARAMEMPHASIS_DEFAULT

86

CPSOLVER = SCIP_PARAMEMPHASIS_CPSOLVER

87

EASYCIP = SCIP_PARAMEMPHASIS_EASYCIP

88

FEASIBILITY = SCIP_PARAMEMPHASIS_FEASIBILITY

89

HARDLP = SCIP_PARAMEMPHASIS_HARDLP

90

OPTIMALITY = SCIP_PARAMEMPHASIS_OPTIMALITY

91

COUNTER = SCIP_PARAMEMPHASIS_COUNTER

92

PHASEFEAS = SCIP_PARAMEMPHASIS_PHASEFEAS

93

PHASEIMPROVE = SCIP_PARAMEMPHASIS_PHASEIMPROVE

94

PHASEPROOF = SCIP_PARAMEMPHASIS_PHASEPROOF

95

NUMERICS = SCIP_PARAMEMPHASIS_NUMERICS

96

BENCHMARK = SCIP_PARAMEMPHASIS_BENCHMARK

98

cdef

class

PY_SCIP_STATUS:

99

UNKNOWN = SCIP_STATUS_UNKNOWN

100

USERINTERRUPT = SCIP_STATUS_USERINTERRUPT

101

NODELIMIT = SCIP_STATUS_NODELIMIT

102

TOTALNODELIMIT = SCIP_STATUS_TOTALNODELIMIT

103

STALLNODELIMIT = SCIP_STATUS_STALLNODELIMIT

104

TIMELIMIT = SCIP_STATUS_TIMELIMIT

105

MEMLIMIT = SCIP_STATUS_MEMLIMIT

106

GAPLIMIT = SCIP_STATUS_GAPLIMIT

107

SOLLIMIT = SCIP_STATUS_SOLLIMIT

108

BESTSOLLIMIT = SCIP_STATUS_BESTSOLLIMIT

109

RESTARTLIMIT = SCIP_STATUS_RESTARTLIMIT

110

PRIMALLIMIT = SCIP_STATUS_PRIMALLIMIT

111

DUALLIMIT = SCIP_STATUS_DUALLIMIT

112

OPTIMAL = SCIP_STATUS_OPTIMAL

113

INFEASIBLE = SCIP_STATUS_INFEASIBLE

114

UNBOUNDED = SCIP_STATUS_UNBOUNDED

115

INFORUNBD = SCIP_STATUS_INFORUNBD

119

cdef

class

PY_SCIP_STAGE:

120

INIT = SCIP_STAGE_INIT

121

PROBLEM = SCIP_STAGE_PROBLEM

122

TRANSFORMING = SCIP_STAGE_TRANSFORMING

123

TRANSFORMED = SCIP_STAGE_TRANSFORMED

124

INITPRESOLVE = SCIP_STAGE_INITPRESOLVE

125

PRESOLVING = SCIP_STAGE_PRESOLVING

126

EXITPRESOLVE = SCIP_STAGE_EXITPRESOLVE

127

PRESOLVED = SCIP_STAGE_PRESOLVED

128

INITSOLVE = SCIP_STAGE_INITSOLVE

129

SOLVING = SCIP_STAGE_SOLVING

130

SOLVED = SCIP_STAGE_SOLVED

131

EXITSOLVE = SCIP_STAGE_EXITSOLVE

132

FREETRANS = SCIP_STAGE_FREETRANS

133

FREE = SCIP_STAGE_FREE

135

cdef

class

PY_SCIP_NODETYPE:

136

FOCUSNODE = SCIP_NODETYPE_FOCUSNODE

137

PROBINGNODE = SCIP_NODETYPE_PROBINGNODE

138

SIBLING = SCIP_NODETYPE_SIBLING

139

CHILD = SCIP_NODETYPE_CHILD

140

LEAF = SCIP_NODETYPE_LEAF

141

DEADEND = SCIP_NODETYPE_DEADEND

142

JUNCTION = SCIP_NODETYPE_JUNCTION

143

PSEUDOFORK = SCIP_NODETYPE_PSEUDOFORK

144

FORK = SCIP_NODETYPE_FORK

145

SUBROOT = SCIP_NODETYPE_SUBROOT

146

REFOCUSNODE = SCIP_NODETYPE_REFOCUSNODE

149

cdef

class

PY_SCIP_PROPTIMING:

150

BEFORELP = SCIP_PROPTIMING_BEFORELP

151

DURINGLPLOOP = SCIP_PROPTIMING_DURINGLPLOOP

152

AFTERLPLOOP = SCIP_PROPTIMING_AFTERLPLOOP

153

AFTERLPNODE = SCIP_PROPTIMING_AFTERLPNODE

155

cdef

class

PY_SCIP_PRESOLTIMING:

156

NONE = SCIP_PRESOLTIMING_NONE

157

FAST = SCIP_PRESOLTIMING_FAST

158

MEDIUM = SCIP_PRESOLTIMING_MEDIUM

159

EXHAUSTIVE = SCIP_PRESOLTIMING_EXHAUSTIVE

161

cdef

class

PY_SCIP_HEURTIMING:

162

BEFORENODE = SCIP_HEURTIMING_BEFORENODE

163

DURINGLPLOOP = SCIP_HEURTIMING_DURINGLPLOOP

164

AFTERLPLOOP = SCIP_HEURTIMING_AFTERLPLOOP

165

AFTERLPNODE = SCIP_HEURTIMING_AFTERLPNODE

166

AFTERPSEUDONODE = SCIP_HEURTIMING_AFTERPSEUDONODE

167

AFTERLPPLUNGE = SCIP_HEURTIMING_AFTERLPPLUNGE

168

AFTERPSEUDOPLUNGE = SCIP_HEURTIMING_AFTERPSEUDOPLUNGE

169

DURINGPRICINGLOOP = SCIP_HEURTIMING_DURINGPRICINGLOOP

170

BEFOREPRESOL = SCIP_HEURTIMING_BEFOREPRESOL

171

DURINGPRESOLLOOP = SCIP_HEURTIMING_DURINGPRESOLLOOP

172

AFTERPROPLOOP = SCIP_HEURTIMING_AFTERPROPLOOP

176

cdef

class

PY_SCIP_EVENTTYPE:

177

DISABLED = SCIP_EVENTTYPE_DISABLED

178

VARADDED = SCIP_EVENTTYPE_VARADDED

179

VARDELETED = SCIP_EVENTTYPE_VARDELETED

180

VARFIXED = SCIP_EVENTTYPE_VARFIXED

181

VARUNLOCKED = SCIP_EVENTTYPE_VARUNLOCKED

182

OBJCHANGED = SCIP_EVENTTYPE_OBJCHANGED

183

GLBCHANGED = SCIP_EVENTTYPE_GLBCHANGED

184

GUBCHANGED = SCIP_EVENTTYPE_GUBCHANGED

185

LBTIGHTENED = SCIP_EVENTTYPE_LBTIGHTENED

186

LBRELAXED = SCIP_EVENTTYPE_LBRELAXED

187

UBTIGHTENED = SCIP_EVENTTYPE_UBTIGHTENED

188

UBRELAXED = SCIP_EVENTTYPE_UBRELAXED

189

GHOLEADDED = SCIP_EVENTTYPE_GHOLEADDED

190

GHOLEREMOVED = SCIP_EVENTTYPE_GHOLEREMOVED

191

LHOLEADDED = SCIP_EVENTTYPE_LHOLEADDED

192

LHOLEREMOVED = SCIP_EVENTTYPE_LHOLEREMOVED

193

IMPLADDED = SCIP_EVENTTYPE_IMPLADDED

194

PRESOLVEROUND = SCIP_EVENTTYPE_PRESOLVEROUND

195

NODEFOCUSED = SCIP_EVENTTYPE_NODEFOCUSED

196

NODEFEASIBLE = SCIP_EVENTTYPE_NODEFEASIBLE

197

NODEINFEASIBLE = SCIP_EVENTTYPE_NODEINFEASIBLE

198

NODEBRANCHED = SCIP_EVENTTYPE_NODEBRANCHED

199

NODEDELETE = SCIP_EVENTTYPE_NODEDELETE

200

FIRSTLPSOLVED = SCIP_EVENTTYPE_FIRSTLPSOLVED

201

LPSOLVED = SCIP_EVENTTYPE_LPSOLVED

202

LPEVENT = SCIP_EVENTTYPE_LPEVENT

203

POORSOLFOUND = SCIP_EVENTTYPE_POORSOLFOUND

204

BESTSOLFOUND = SCIP_EVENTTYPE_BESTSOLFOUND

205

ROWADDEDSEPA = SCIP_EVENTTYPE_ROWADDEDSEPA

206

ROWDELETEDSEPA = SCIP_EVENTTYPE_ROWDELETEDSEPA

207

ROWADDEDLP = SCIP_EVENTTYPE_ROWADDEDLP

208

ROWDELETEDLP = SCIP_EVENTTYPE_ROWDELETEDLP

209

ROWCOEFCHANGED = SCIP_EVENTTYPE_ROWCOEFCHANGED

210

ROWCONSTCHANGED = SCIP_EVENTTYPE_ROWCONSTCHANGED

211

ROWSIDECHANGED = SCIP_EVENTTYPE_ROWSIDECHANGED

212

SYNC = SCIP_EVENTTYPE_SYNC

213

GBDCHANGED = SCIP_EVENTTYPE_GBDCHANGED

214

LBCHANGED = SCIP_EVENTTYPE_LBCHANGED

215

UBCHANGED = SCIP_EVENTTYPE_UBCHANGED

216

BOUNDTIGHTENED = SCIP_EVENTTYPE_BOUNDTIGHTENED

217

BOUNDRELAXED = SCIP_EVENTTYPE_BOUNDRELAXED

218

BOUNDCHANGED = SCIP_EVENTTYPE_BOUNDCHANGED

219

GHOLECHANGED = SCIP_EVENTTYPE_GHOLECHANGED

220

LHOLECHANGED = SCIP_EVENTTYPE_LHOLECHANGED

221

HOLECHANGED = SCIP_EVENTTYPE_HOLECHANGED

222

DOMCHANGED = SCIP_EVENTTYPE_DOMCHANGED

223

VARCHANGED = SCIP_EVENTTYPE_VARCHANGED

224

VAREVENT = SCIP_EVENTTYPE_VAREVENT

225

NODESOLVED = SCIP_EVENTTYPE_NODESOLVED

226

NODEEVENT = SCIP_EVENTTYPE_NODEEVENT

227

SOLFOUND = SCIP_EVENTTYPE_SOLFOUND

228

SOLEVENT = SCIP_EVENTTYPE_SOLEVENT

229

ROWCHANGED = SCIP_EVENTTYPE_ROWCHANGED

230

ROWEVENT = SCIP_EVENTTYPE_ROWEVENT

233

cdef

class

PY_SCIP_LPSOLSTAT:

234

NOTSOLVED = SCIP_LPSOLSTAT_NOTSOLVED

235

OPTIMAL = SCIP_LPSOLSTAT_OPTIMAL

236

INFEASIBLE = SCIP_LPSOLSTAT_INFEASIBLE

237

UNBOUNDEDRAY = SCIP_LPSOLSTAT_UNBOUNDEDRAY

238

OBJLIMIT = SCIP_LPSOLSTAT_OBJLIMIT

239

ITERLIMIT = SCIP_LPSOLSTAT_ITERLIMIT

240

TIMELIMIT = SCIP_LPSOLSTAT_TIMELIMIT

241

ERROR = SCIP_LPSOLSTAT_ERROR

243

cdef

class

PY_SCIP_BRANCHDIR:

244

DOWNWARDS = SCIP_BRANCHDIR_DOWNWARDS

245

UPWARDS = SCIP_BRANCHDIR_UPWARDS

246

FIXED = SCIP_BRANCHDIR_FIXED

247

AUTO = SCIP_BRANCHDIR_AUTO

249

cdef

class

PY_SCIP_BENDERSENFOTYPE:

250

LP = SCIP_BENDERSENFOTYPE_LP

251

RELAX = SCIP_BENDERSENFOTYPE_RELAX

252

PSEUDO = SCIP_BENDERSENFOTYPE_PSEUDO

253

CHECK = SCIP_BENDERSENFOTYPE_CHECK

255

cdef

class

PY_SCIP_ROWORIGINTYPE:

256

UNSPEC = SCIP_ROWORIGINTYPE_UNSPEC

257

CONS = SCIP_ROWORIGINTYPE_CONS

258

SEPA = SCIP_ROWORIGINTYPE_SEPA

259

REOPT = SCIP_ROWORIGINTYPE_REOPT

261 def

PY_SCIP_CALL(SCIP_RETCODE rc):

264  elif

rc == SCIP_ERROR:

265  raise

Exception(

'SCIP: unspecified error!'

)

266  elif

rc == SCIP_NOMEMORY:

267  raise

MemoryError(

'SCIP: insufficient memory error!'

)

268  elif

rc == SCIP_READERROR:

269  raise

IOError(

'SCIP: read error!'

)

270  elif

rc == SCIP_WRITEERROR:

271  raise

IOError(

'SCIP: write error!'

)

272  elif

rc == SCIP_NOFILE:

273  raise

IOError(

'SCIP: file not found error!'

)

274  elif

rc == SCIP_FILECREATEERROR:

275  raise

IOError(

'SCIP: cannot create file!'

)

276  elif

rc == SCIP_LPERROR:

277  raise

Exception(

'SCIP: error in LP solver!'

)

278  elif

rc == SCIP_NOPROBLEM:

279  raise

Exception(

'SCIP: no problem exists!'

)

280  elif

rc == SCIP_INVALIDCALL:

281  raise

Exception(

'SCIP: method cannot be called at this time' 282

+

' in solution process!'

)

283  elif

rc == SCIP_INVALIDDATA:

284  raise

Exception(

'SCIP: error in input data!'

)

285  elif

rc == SCIP_INVALIDRESULT:

286  raise

Exception(

'SCIP: method returned an invalid result code!'

)

287  elif

rc == SCIP_PLUGINNOTFOUND:

288  raise

Exception(

'SCIP: a required plugin was not found !'

)

289  elif

rc == SCIP_PARAMETERUNKNOWN:

290  raise

KeyError(

'SCIP: the parameter with the given name was not found!'

)

291  elif

rc == SCIP_PARAMETERWRONGTYPE:

292  raise

LookupError(

'SCIP: the parameter is not of the expected type!'

)

293  elif

rc == SCIP_PARAMETERWRONGVAL:

294  raise

ValueError(

'SCIP: the value is invalid for the given parameter!'

)

295  elif

rc == SCIP_KEYALREADYEXISTING:

296  raise

KeyError(

'SCIP: the given key is already existing in table!'

)

297  elif

rc == SCIP_MAXDEPTHLEVEL:

298  raise

Exception(

'SCIP: maximal branching depth level exceeded!'

)

300  raise

Exception(

'SCIP: unknown return code!'

)

303  """Base class holding a pointer to corresponding SCIP_EVENT""" 306

cdef create(SCIP_EVENT* scip_event):

307  if

scip_event == NULL:

308  raise

Warning(

"cannot create Event with SCIP_EVENT* == NULL"

)

310

event.event = scip_event

314  """gets type of event""" 318  """gets name of event""" 321  return

EventNames[self.

getType

()]

323  def

_getEventNames(self):

324  """gets event names""" 325  for

name

in

dir(PY_SCIP_EVENTTYPE):

326

attr = getattr(PY_SCIP_EVENTTYPE, name)

327  if

isinstance(attr, int):

328

EventNames[attr] = name

337  """gets new bound for a bound change event""" 341  """gets old bound for a bound change event""" 345  """gets variable for a variable event (var added, var deleted, var fixed, objective value or domain change, domain hole added or removed)""" 347  return

Variable.create(var)

350  """gets node for a node or LP event""" 352  return

Node.create(node)

355  """gets row for a row event""" 357  return

Row.create(row)

360  return

hash(<size_t>self.

event

)

363  return

(self.

__class__

== other.__class__

364  and

self.

event

== (<Event>other).event)

367  """Base class holding a pointer to corresponding SCIP_COL""" 370

cdef create(SCIP_COL* scipcol):

372  raise

Warning(

"cannot create Column with SCIP_COL* == NULL"

)

374

col.scip_col = scipcol

378  """gets position of column in current LP, or -1 if it is not in LP""" 382  """gets the basis status of a column in the LP solution, Note: returns basis status `zero` for columns not in the current SCIP LP""" 384  if

stat == SCIP_BASESTAT_LOWER:

386  elif

stat == SCIP_BASESTAT_BASIC:

388  elif

stat == SCIP_BASESTAT_UPPER:

390  elif

stat == SCIP_BASESTAT_ZERO:

393  raise

Exception(

'SCIP returned unknown base status!'

)

396  """returns whether the associated variable is of integral type (binary, integer, implicit integer)""" 400  """gets variable this column represents""" 402  return

Variable.create(var)

405  """gets the primal LP solution of a column""" 409  """gets lower bound of column""" 413  """gets upper bound of column""" 417  """gets objective value coefficient of a column""" 421  """Gets the age of the column, i.e., the total number of successive times a column was in the LP 422  and was 0.0 in the solution""" 426  return

hash(<size_t>self.

scip_col

)

429  return

(self.

__class__

== other.__class__

430  and

self.

scip_col

== (<Column>other).scip_col)

433  """Base class holding a pointer to corresponding SCIP_ROW""" 436

cdef create(SCIP_ROW* sciprow):

438  raise

Warning(

"cannot create Row with SCIP_ROW* == NULL"

)

440

row.scip_row = sciprow

446  return

cname.decode(

'utf-8'

)

449  """returns the left hand side of row""" 453  """returns the right hand side of row""" 457  """gets constant shift of row""" 461  """gets position of row in current LP, or -1 if it is not in LP""" 465  """gets the basis status of a row in the LP solution, Note: returns basis status `basic` for rows not in the current SCIP LP""" 467  if

stat == SCIP_BASESTAT_LOWER:

469  elif

stat == SCIP_BASESTAT_BASIC:

471  elif

stat == SCIP_BASESTAT_UPPER:

473  elif

stat == SCIP_BASESTAT_ZERO:

475  raise

Exception(

'SCIP returned base status zero for a row!'

)

477  raise

Exception(

'SCIP returned unknown base status!'

)

480  """returns TRUE iff the activity of the row (without the row's constant) is always integral in a feasible solution """ 484  """returns TRUE iff the row is only valid locally """ 488  """returns TRUE iff row is modifiable during node processing (subject to column generation) """ 492  """returns TRUE iff row is removable from the LP (due to aging or cleanup)""" 496  """return TRUE iff row is a member of the global cut pool""" 500  """returns type of origin that created the row""" 504  """returns type of constraint handler that created the row""" 509  """get number of nonzero entries in row vector""" 513  """get number of nonzero entries in row vector that correspond to columns currently in the SCIP LP""" 517  """gets list with columns of nonzero entries""" 519  return

[Column.create(cols[i])

for

i

in

range(self.

getNNonz

())]

522  """gets list with coefficients of nonzero entries""" 524  return

[vals[i]

for

i

in

range(self.

getNNonz

())]

527  """Gets the age of the row. (The consecutive times the row has been non-active in the LP)""" 531  """gets Euclidean norm of row vector """ 535  return

hash(<size_t>self.

scip_row

)

538  return

(self.

__class__

== other.__class__

539  and

self.

scip_row

== (<Row>other).scip_row)

542  """Base class holding a pointer to corresponding SCIP_NLROW""" 545

cdef create(SCIP_NLROW* scipnlrow):

546  if

scipnlrow == NULL:

547  raise

Warning(

"cannot create NLRow with SCIP_NLROW* == NULL"

)

549

nlrow.scip_nlrow = scipnlrow

555  return

cname.decode(

'utf-8'

)

558  """returns the constant of a nonlinear row""" 562  """returns a list of tuples (var, coef) representing the linear part of a nonlinear row""" 566  return

[(Variable.create(linvars[i]), lincoefs[i])

for

i

in

range(nlinvars)]

569  """returns the left hand side of a nonlinear row""" 573  """returns the right hand side of a nonlinear row""" 577  """gets the dual NLP solution of a nonlinear row""" 584  return

(self.

__class__

== other.__class__

585  and

self.

scip_nlrow

== (<NLRow>other).scip_nlrow)

588  """Base class holding a pointer to corresponding SCIP_SOL""" 593  raise

ValueError(

"To create a solution you should use the createSol method of the Model class."

)

596

cdef create(SCIP* scip, SCIP_SOL* scip_sol):

598  raise

Warning(

"cannot create Solution with SCIP* == NULL"

)

606  if

isinstance(expr, Variable):

608

var = <Variable> expr

610  return

sum(self.

_evaluate

(term)*coeff

for

term, coeff

in

expr.terms.items()

if

coeff != 0)

612  def

_evaluate(self, term):

615  for

var

in

term.vartuple:

623

cdef SCIP_VAR* scip_var

632

name = cname.decode(

'utf-8'

)

637  def

_checkStage(self, method):

638  if

method

in

[

"SCIPgetSolVal"

,

"getSolObjVal"

]:

639

stage_check =

SCIPgetStage

(self.

scip

)

not in

[SCIP_STAGE_INIT, SCIP_STAGE_FREE]

641  if not

stage_check

or

self.

sol

== NULL

and SCIPgetStage

(self.

scip

) != SCIP_STAGE_SOLVING:

642  raise

Warning(f

"{method} can only be called with a valid solution or in stage SOLVING (current stage: {SCIPgetStage(self.scip)})"

)

649

cdef create(SCIP_BOUNDCHG* scip_boundchg):

650  if

scip_boundchg == NULL:

651  raise

Warning(

"cannot create BoundChange with SCIP_BOUNDCHG* == NULL"

)

653

boundchg.scip_boundchg = scip_boundchg

657  """Returns the new value of the bound in the bound change.""" 661  """Returns the variable of the bound change.""" 665  """Returns the bound change type of the bound change.""" 669  """Returns the bound type of the bound change.""" 673  """Returns whether the bound change is redundant due to a more global bound that is at least as strong.""" 677  return "{} {} {}"

.format(self.

getVar

(),

682  """Set of domain changes.""" 685

cdef create(SCIP_DOMCHG* scip_domchg):

686  if

scip_domchg == NULL:

687  raise

Warning(

"cannot create DomainChanges with SCIP_DOMCHG* == NULL"

)

689

domchg.scip_domchg = scip_domchg

693  """Returns the bound changes in the domain change.""" 696  for

i

in

range(nboundchgs)]

699  """Base class holding a pointer to corresponding SCIP_NODE""" 702

cdef create(SCIP_NODE* scipnode):

706

node.scip_node = scipnode

710  """Retrieve parent node (or None if the node has no parent node).""" 714  """Retrieve number of node.""" 718  """Retrieve depth of node.""" 722  """Retrieve type of node.""" 726  """Retrieve lower bound of node.""" 730  """Retrieve the estimated value of the best feasible solution in subtree of the node""" 734  """Retrieve all constraints added at this node.""" 736  if

addedconsssize == 0:

738

cdef SCIP_CONS** addedconss = <SCIP_CONS**> malloc(addedconsssize * sizeof(SCIP_CONS*))

741  assert

nconss == addedconsssize

742

constraints = [Constraint.create(addedconss[i])

for

i

in

range(nconss)]

747  """Retrieve number of added constraints at this node""" 751  """Is the node in the path to the current node?""" 755  """Is the node marked to be propagated again?""" 759  """Retrieve the number of variable branchings that were performed in the parent node to create this node.""" 760

cdef SCIP_VAR* dummy_branchvars

761

cdef SCIP_Real dummy_branchbounds

762

cdef SCIP_BOUNDTYPE dummy_boundtypes

768

&dummy_branchbounds, &dummy_boundtypes,

773  """Retrieve the set of variable branchings that were performed in the parent node to create this node.""" 778

cdef SCIP_VAR** branchvars = <SCIP_VAR**> malloc(nbranchvars * sizeof(SCIP_VAR*))

779

cdef SCIP_Real* branchbounds = <SCIP_Real*> malloc(nbranchvars * sizeof(SCIP_Real))

780

cdef SCIP_BOUNDTYPE* boundtypes = <SCIP_BOUNDTYPE*> malloc(nbranchvars * sizeof(SCIP_BOUNDTYPE))

783

boundtypes, &nbranchvars, nbranchvars)

785

py_variables = [Variable.create(branchvars[i])

for

i

in

range(nbranchvars)]

786

py_branchbounds = [branchbounds[i]

for

i

in

range(nbranchvars)]

787

py_boundtypes = [boundtypes[i]

for

i

in

range(nbranchvars)]

792  return

py_variables, py_branchbounds, py_boundtypes

795  """Retrieve the number of bound changes due to branching, constraint propagation, and propagation.""" 800  return

nbranchings, nconsprop, nprop

803  """Retrieve domain changes for this node.""" 807  return

DomainChanges.create(domchg)

813  return

(self.

__class__

== other.__class__

814  and

self.

scip_node

== (<Node>other).scip_node)

817  """Is a linear expression and has SCIP_VAR*""" 820

cdef create(SCIP_VAR* scipvar):

822  raise

Warning(

"cannot create Variable with SCIP_VAR* == NULL"

)

824

var.scip_var = scipvar

825

Expr.__init__(var, {Term(var) : 1.0})

831  return

cname.decode(

'utf-8'

)

841  """Retrieve the variables type (BINARY, INTEGER, IMPLINT or CONTINUOUS)""" 843  if

vartype == SCIP_VARTYPE_BINARY:

845  elif

vartype == SCIP_VARTYPE_INTEGER:

847  elif

vartype == SCIP_VARTYPE_CONTINUOUS:

849  elif

vartype == SCIP_VARTYPE_IMPLINT:

853  """Retrieve whether the variable belongs to the original problem""" 857  """Retrieve whether the variable is a COLUMN variable that is member of the current LP""" 862  """Retrieve the unique index of the variable.""" 866  """Retrieve column of COLUMN variable""" 867

cdef SCIP_COL* scip_col

869  return

Column.create(scip_col)

872  """Retrieve original lower bound of variable""" 876  """Retrieve original upper bound of variable""" 880  """Retrieve global lower bound of variable""" 884  """Retrieve global upper bound of variable""" 888  """Retrieve current lower bound of variable""" 892  """Retrieve current upper bound of variable""" 896  """Retrieve current objective value of variable""" 900  """Retrieve the current LP solution value of variable""" 904  """Get the weighted average solution of variable in all feasible primal solutions found""" 908  """Base class holding a pointer to corresponding SCIP_CONS""" 911

cdef create(SCIP_CONS* scipcons):

913  raise

Warning(

"cannot create Constraint with SCIP_CONS* == NULL"

)

915

cons.scip_cons = scipcons

921  return

cname.decode(

'utf-8'

)

927  """Retrieve whether the constraint belongs to the original problem""" 931  """Retrieve True if the relaxation of the constraint should be in the initial LP""" 935  """Retrieve True if constraint should be separated during LP processing""" 939  """Retrieve True if constraint should be enforced during node processing""" 943  """Retrieve True if constraint should be checked for feasibility""" 947  """Retrieve True if constraint should be propagated during node processing""" 951  """Retrieve True if constraint is only locally valid or not added to any (sub)problem""" 955  """Retrieve True if constraint is modifiable (subject to column generation)""" 959  """Retrieve True if constraint is subject to aging""" 963  """Retrieve True if constraint's relaxation should be removed from the LP due to aging or cleanup""" 967  """Retrieve True if constraint is only locally valid or not added to any (sub)problem""" 971  """returns True iff constraint is active in the current node""" 975  """Retrieve True if constraint is linear""" 977  return

constype ==

'linear' 980  """Retrieve True if constraint is nonlinear""" 982  return

constype ==

'nonlinear' 985  """Return the constraint handler's name""" 993  return

(self.

__class__

== other.__class__

994  and

self.

scip_cons

== (<Constraint>other).scip_cons)

997

cdef void relayMessage(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *msg) noexcept:

998

sys.stdout.write(msg.decode(

'UTF-8'

))

1000

cdef void relayErrorMessage(void *messagehdlr, FILE *file, const char *msg) noexcept:

1001

sys.stderr.write(msg.decode(

'UTF-8'

))

1010  """Main class holding a pointer to SCIP for managing most interactions""" 1012  def __init__

(self, problemName='model', defaultPlugins=True, Model sourceModel=None, origcopy=False, globalcopy=True, enablepricing=False, createscip=True, threadsafe=False):

1014  :param problemName: name of the problem (default 'model') 1015  :param defaultPlugins: use default plugins? (default True) 1016  :param sourceModel: create a copy of the given Model instance (default None) 1017  :param origcopy: whether to call copy or copyOrig (default False) 1018  :param globalcopy: whether to create a global or a local copy (default True) 1019  :param enablepricing: whether to enable pricing in copy (default False) 1020  :param createscip: initialize the Model object and creates a SCIP instance 1021  :param threadsafe: False if data can be safely shared between the source and target problem 1024  raise

Exception(

"linked SCIP is not compatible to this version of PySCIPOpt - use at least version"

, MAJOR)

1025  if

self.

version

() < MAJOR + MINOR/10.0 + PATCH/100.0:

1026

warnings.warn(

"linked SCIP {} is not recommended for this version of PySCIPOpt - use version {}.{}.{}"

.format(self.

version

(), MAJOR, MINOR, PATCH))

1036  elif

sourceModel

is None

:

1044

self.

_bestSol

= <Solution> sourceModel._bestSol

1047

PY_SCIP_CALL(

SCIPcopyOrig

(sourceModel._scip, self.

_scip

, NULL, NULL, n, enablepricing, threadsafe,

True

, self._valid))

1049

PY_SCIP_CALL(

SCIPcopy

(sourceModel._scip, self.

_scip

, NULL, NULL, n, globalcopy, enablepricing, threadsafe,

True

, self._valid))

1058  return

hash(<size_t>self.

_scip

)

1061  return

(self.

__class__

== other.__class__

1062  and

self.

_scip

== (<Model>other)._scip)

1065

cdef create(SCIP* scip):

1066  """Creates a model and appropriately assigns the scip and bestsol parameters 1069  raise

Warning(

"cannot create Model with SCIP* == NULL"

)

1076  def

_freescip(self):

1077  """Return whether the underlying Scip pointer gets deallocted when the current 1083  def

_freescip(self, val):

1084  """Set whether the underlying Scip pointer gets deallocted when the current 1089

@cython.always_allow_keywords(

True

)

1092  """Create a Model from a given pointer. 1094  :param cpasule: The PyCapsule containing the SCIP pointer under the name "scip". 1095  :param take_ownership: Whether the newly created Model assumes ownership of the 1096  underlying Scip pointer (see `_freescip`). 1098  if not

PyCapsule_IsValid(capsule,

"scip"

):

1099  raise

ValueError(

"The given capsule does not contain a valid scip pointer"

)

1100

model = Model.create(<SCIP*>PyCapsule_GetPointer(capsule,

"scip"

))

1101

model._freescip = take_ownership

1104

@cython.always_allow_keywords(

True

)

1106  """Return the underlying Scip pointer to the current Model. 1108  :param give_ownership: Whether the current Model gives away ownership of the 1109  underlying Scip pointer (see `_freescip`). 1110  :return capsule: The underlying pointer to the current Model, wrapped in a 1111  PyCapsule under the name "scip". 1113

capsule = PyCapsule_New(<void*>self.

_scip

,

"scip"

, NULL)

1119  """Includes all default plug-ins into SCIP""" 1120

PY_SCIP_CALL(SCIPincludeDefaultPlugins(self.

_scip

))

1123  """Create new problem instance with given name 1125  :param problemName: name of model or problem (Default value = 'model') 1132  """Frees problem and solution process data""" 1136  """Frees all solution process data including presolving and transformed problem, only original problem is kept""" 1140  if

value.isOriginal()

1145  """Retrieve SCIP version""" 1149  """Print version, copyright information and compile mode""" 1150

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

1151

locale.setlocale(locale.LC_NUMERIC,

"C"

)

1155

locale.setlocale(locale.LC_NUMERIC,user_locale)

1158  """Print external code versions, e.g. symmetry, non-linear solver, lp solver""" 1159

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

1160

locale.setlocale(locale.LC_NUMERIC,

"C"

)

1164

locale.setlocale(locale.LC_NUMERIC,user_locale)

1167  """Retrieve problem name""" 1171  """Retrieve the current total SCIP time in seconds, i.e. the total time since the SCIP instance has been created""" 1175  """Retrieve the current solving time in seconds""" 1179  """Retrieve the current reading time in seconds""" 1183  """Retrieve the curernt presolving time in seconds""" 1187  """Retrieve the total number of LP iterations so far.""" 1191  """gets number of processed nodes in current run, including the focus node.""" 1195  """gets number of processed nodes in all runs, including the focus node.""" 1199  """Retrieve number of leaf nodes processed with feasible relaxation solution.""" 1203  """gets number of infeasible leaf nodes processed.""" 1207  """gets number of leaves in the tree.""" 1211  """gets number of children of focus node.""" 1215  """gets number of siblings of focus node.""" 1219  """Retrieve current node.""" 1223  """Retrieve the gap, i.e. |(primalbound - dualbound)/min(|primalbound|,|dualbound|)|.""" 1227  """Retrieve the depth of the current node""" 1231  """Retrieve SCIP's infinity value""" 1235  """Retrieve epsilon for e.g. equality checks""" 1239  """Retrieve feasibility tolerance""" 1243  """returns fractional part of value, i.e. x - floor(x) in feasible tolerance: x - floor(x+feastol)""" 1247  """returns fractional part of value, i.e. x - floor(x) in epsilon tolerance: x - floor(x+eps)""" 1251  """returns whether abs(value) < eps""" 1255  """returns whether abs(value) < feastol""" 1259  """returns whether value is SCIP's infinity""" 1263  """returns whether value < -feastol""" 1267  """returns whether value is integral within the LP feasibility bounds""" 1271  """checks, if values are in range of epsilon""" 1275  """checks, if relative difference of values is in range of feasibility tolerance""" 1279  """returns whether val1 <= val2 + eps""" 1283  """returns whether val1 < val2 - eps""" 1287  """returns whether val1 >= val2 - eps""" 1291  """returns whether val1 > val2 + eps""" 1295  """Get the current LP's condition number 1297  :param exact: whether to get an estimate or the exact value (Default value = False) 1302

cdef SCIP_Real quality = 0

1311  """include specific heuristics and branching rules for reoptimization""" 1315  """Get the iteration count of the last solved LP""" 1325  """Set the objective sense to minimization.""" 1329  """Set the objective sense to maximization.""" 1333  """Set a limit on the objective function. 1334  Only solutions with objective value better than this limit are accepted. 1336  :param objlimit: limit on the objective function 1342  """returns current limit on objective function.""" 1346  """Establish the objective function as a linear expression. 1348  :param expr: the objective function SCIP Expr, or constant value 1349  :param sense: the objective sense (Default value = 'minimize') 1350  :param clear: set all other variables objective coefficient to zero (Default value = 'true') 1354

cdef SCIP_VAR** _vars

1358  if not

isinstance(expr, Expr):

1359

assert(_is_number(expr)),

"given coefficients are neither Expr or number but %s"

% expr.__class__.__name__

1360

expr = Expr() + expr

1362  if

expr.degree() > 1:

1363  raise

ValueError(

"SCIP does not support nonlinear objective functions. Consider using set_nonlinear_objective in the pyscipopt.recipe.nonlinear"

)

1370  for

i

in

range(_nvars):

1373  if

expr[CONST] != 0.0:

1376  for

term, coef

in

expr.terms.items():

1379  assert

len(term) == 1

1380

var = <Variable>term[0]

1383  if

sense ==

"minimize"

:

1385  elif

sense ==

"maximize"

:

1388  raise

Warning(

"unrecognized optimization sense: %s"

% sense)

1391  """Retrieve objective function as Expr""" 1394  for

var

in

variables:

1395

coeff = var.getObj()

1397

objective += coeff * var

1398

objective.normalize()

1402  """Add constant offset to objective 1404  :param offset: offset to add 1405  :param solutions: add offset also to existing solutions (Default value = False) 1414  """Retrieve constant objective offset 1416  :param original: offset of original or transformed problem (Default value = True) 1425  """informs SCIP that the objective value is always integral in every feasible solution 1426  Note: This function should be used to inform SCIP that the objective function is integral, helping to improve the 1427  performance. This is useful when using column generation. If no column generation (pricing) is used, SCIP 1428  automatically detects whether the objective function is integral or can be scaled to be integral. However, in 1429  any case, the user has to make sure that no variable is added during the solving process that destroys this 1435  """gets estimate of best primal solution w.r.t. original or transformed problem contained in current subtree 1437  :param original: estimate of original or transformed problem (Default value = False) 1446  """Set presolving parameter settings. 1448  :param setting: the parameter settings (SCIP_PARAMSETTING) 1454  """Set problem name""" 1459  """Set separating parameter settings. 1461  :param setting: the parameter settings (SCIP_PARAMSETTING) 1467  """Set heuristics parameter settings. 1469  :param setting: the parameter setting (SCIP_PARAMSETTING) 1475  """Disables propagation in SCIP to avoid modifying the original problem during transformation. 1477  :param onlyroot: use propagation when root processing is finished (Default value = False) 1480

self.

setIntParam

(

"propagating/maxroundsroot"

, 0)

1484  def writeProblem

(self, filename='model.cip', trans=False, genericnames=False, verbose=True):

1485  """Write current model/problem to a file. 1487  :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. 1488  :param trans: indicates whether the transformed problem is written to file (Default value = False) 1489  :param genericnames: indicates whether the problem should be written with generic variable and constraint names (Default value = False) 1490  :param verbose: indicates whether a success message should be printed 1492

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

1493

locale.setlocale(locale.LC_NUMERIC,

"C"

)

1495

str_absfile = abspath(filename)

1497

fn, ext = splitext(absfile)

1510

print(

'wrote problem to file '

+ str_absfile)

1512

locale.setlocale(locale.LC_NUMERIC,user_locale)

1516  def addVar

(self, name='', vtype='C', lb=0.0, ub=None, obj=0.0, pricedVar=False, pricedVarScore=1.0):

1517  """Create a new variable. Default variable is non-negative and continuous. 1519  :param name: name of the variable, generic if empty (Default value = '') 1520  :param vtype: type of the variable: 'C' continuous, 'I' integer, 'B' binary, and 'M' implicit integer 1521  (see https://www.scipopt.org/doc/html/FAQ.php#implicitinteger) (Default value = 'C') 1522  :param lb: lower bound of the variable, use None for -infinity (Default value = 0.0) 1523  :param ub: upper bound of the variable, use None for +infinity (Default value = None) 1524  :param obj: objective value of variable (Default value = 0.0) 1525  :param pricedVar: is the variable a pricing candidate? (Default value = False) 1526  :param pricedVarScore: score of variable in case it is priced, the higher the better (Default value = 1.0) 1529

cdef SCIP_VAR* scip_var

1542

vtype = vtype.upper()

1543  if

vtype

in

[

'C'

,

'CONTINUOUS'

]:

1545  elif

vtype

in

[

'B'

,

'BINARY'

]:

1551  elif

vtype

in

[

'I'

,

'INTEGER'

]:

1553  elif

vtype

in

[

'M'

,

'IMPLINT'

]:

1556  raise

Warning(

"unrecognized variable type"

)

1563

pyVar = Variable.create(scip_var)

1575  """Retrieve the transformed variable. 1577  :param Variable var: original variable to get the transformed of 1580

cdef SCIP_VAR* _tvar

1583  return

Variable.create(_tvar)

1586  """adds given values to lock numbers of variable for rounding 1588  :param Variable var: variable to adjust the locks for 1589  :param nlocksdown: new number of down locks 1590  :param nlocksup: new number of up locks 1596  """Fixes the variable var to the value val if possible. 1598  :param Variable var: variable to fix 1599  :param val: float, the fix value 1600  :return: tuple (infeasible, fixed) of booleans 1603

cdef SCIP_Bool infeasible

1604

cdef SCIP_Bool fixed

1605

PY_SCIP_CALL(

SCIPfixVar

(self.

_scip

, var.scip_var, val, &infeasible, &fixed))

1606  return

infeasible, fixed

1609  """Delete a variable. 1611  :param var: the variable which shall be deleted 1612  :return: bool, was deleting succesful 1615

cdef SCIP_Bool deleted

1622  """Tighten the lower bound in preprocessing or current node, if the bound is tighter. 1624  :param var: SCIP variable 1625  :param lb: possible new lower bound 1626  :param force: force tightening even if below bound strengthening tolerance 1627  :return: tuple of bools, (infeasible, tightened) 1628  infeasible: whether new domain is empty 1629  tightened: whether the bound was tightened 1632

cdef SCIP_Bool infeasible

1633

cdef SCIP_Bool tightened

1635  return

infeasible, tightened

1638  """Tighten the upper bound in preprocessing or current node, if the bound is tighter. 1640  :param var: SCIP variable 1641  :param ub: possible new upper bound 1642  :param force: force tightening even if below bound strengthening tolerance 1643  :return: tuple of bools, (infeasible, tightened) 1644  infeasible: whether new domain is empty 1645  tightened: whether the bound was tightened 1648

cdef SCIP_Bool infeasible

1649

cdef SCIP_Bool tightened

1651  return

infeasible, tightened

1654  """Tighten the global upper bound, if the bound is tighter. 1656  :param var: SCIP variable 1657  :param ub: possible new upper bound 1658  :param force: force tightening even if below bound strengthening tolerance 1659  :return: tuple of bools, (infeasible, tightened) 1660  infeasible: whether new domain is empty 1661  tightened: whether the bound was tightened 1664

cdef SCIP_Bool infeasible

1665

cdef SCIP_Bool tightened

1667  return

infeasible, tightened

1670  """Tighten the global upper bound, if the bound is tighter. 1672  :param var: SCIP variable 1673  :param lb: possible new upper bound 1674  :param force: force tightening even if below bound strengthening tolerance 1675  :return: tuple of bools, (infeasible, tightened) 1676  infeasible: whether new domain is empty 1677  tightened: whether the bound was tightened 1680

cdef SCIP_Bool infeasible

1681

cdef SCIP_Bool tightened

1683  return

infeasible, tightened

1686  """Changes the lower bound of the specified variable. 1688  :param Variable var: variable to change bound of 1689  :param lb: new lower bound (set to None for -infinity) 1697  """Changes the upper bound of the specified variable. 1699  :param Variable var: variable to change bound of 1700  :param ub: new upper bound (set to None for +infinity) 1708  """Changes the global lower bound of the specified variable. 1710  :param Variable var: variable to change bound of 1711  :param lb: new lower bound (set to None for -infinity) 1719  """Changes the global upper bound of the specified variable. 1721  :param Variable var: variable to change bound of 1722  :param ub: new upper bound (set to None for +infinity) 1730  """Changes the lower bound of the specified variable at the given node. 1732  :param Variable var: variable to change bound of 1733  :param lb: new lower bound (set to None for -infinity) 1741  """Changes the upper bound of the specified variable at the given node. 1743  :param Variable var: variable to change bound of 1744  :param ub: new upper bound (set to None for +infinity) 1752  """Changes the type of a variable 1754  :param Variable var: variable to change type of 1755  :param vtype: new variable type 1758

cdef SCIP_Bool infeasible

1759  if

vtype

in

[

'C'

,

'CONTINUOUS'

]:

1760

PY_SCIP_CALL(

SCIPchgVarType

(self.

_scip

, var.scip_var, SCIP_VARTYPE_CONTINUOUS, &infeasible))

1761  elif

vtype

in

[

'B'

,

'BINARY'

]:

1762

PY_SCIP_CALL(

SCIPchgVarType

(self.

_scip

, var.scip_var, SCIP_VARTYPE_BINARY, &infeasible))

1763  elif

vtype

in

[

'I'

,

'INTEGER'

]:

1764

PY_SCIP_CALL(

SCIPchgVarType

(self.

_scip

, var.scip_var, SCIP_VARTYPE_INTEGER, &infeasible))

1765  elif

vtype

in

[

'M'

,

'IMPLINT'

]:

1766

PY_SCIP_CALL(

SCIPchgVarType

(self.

_scip

, var.scip_var, SCIP_VARTYPE_IMPLINT, &infeasible))

1768  raise

Warning(

"unrecognized variable type"

)

1770

print(

'could not change variable type of variable %s'

% var)

1773  """Retrieve all variables. 1775  :param transformed: get transformed variables instead of original (Default value = False) 1778

cdef SCIP_VAR** _vars

1790  for

i

in

range(_nvars):

1791

ptr = <size_t>(_vars[i])

1798

var = Variable.create(_vars[i])

1799  assert

var.ptr() == ptr

1806  """Retrieve number of variables in the problems. 1808  :param transformed: get transformed variables instead of original (Default value = True) 1816  """gets number of integer active problem variables""" 1820  """gets number of binary active problem variables""" 1824  """gets dictionary with variables names as keys and current variable values as items""" 1827

var_dict[var.name] = self.

getVal

(var)

1831  """if given value is larger than the node's lower bound (in transformed problem), 1832  sets the node's lower bound to the new value 1834  :param node: Node, the node to update 1835  :param newbound: float, new bound (if greater) for the node 1841  """Relaxes the integrality restrictions of the model""" 1842  if

self.

getStage

() != SCIP_STAGE_PROBLEM:

1843  raise

Warning(

"method can only be called in stage PROBLEM"

)

1850  """gets the best child of the focus node w.r.t. the node selection strategy.""" 1854  """gets the best sibling of the focus node w.r.t. the node selection strategy.""" 1858  """gets the best leaf from the node queue w.r.t. the node selection strategy.""" 1862  """gets the best node from the tree (child, sibling, or leaf) w.r.t. the node selection strategy.""" 1866  """gets the node with smallest lower bound from the tree (child, sibling, or leaf).""" 1870  """access to all data of open nodes (leaves, children, and siblings) 1872  :return: three lists containing open leaves, children, siblings 1874

cdef SCIP_NODE** _leaves

1875

cdef SCIP_NODE** _children

1876

cdef SCIP_NODE** _siblings

1881

PY_SCIP_CALL(

SCIPgetOpenNodesData

(self.

_scip

, &_leaves, &_children, &_siblings, &_nleaves, &_nchildren, &_nsiblings))

1883

leaves = [Node.create(_leaves[i])

for

i

in

range(_nleaves)]

1884

children = [Node.create(_children[i])

for

i

in

range(_nchildren)]

1885

siblings = [Node.create(_siblings[i])

for

i

in

range(_nsiblings)]

1887  return

leaves, children, siblings

1890  """marks the given node to be propagated again the next time a node of its subtree is processed""" 1896  """Gets solution status of current LP""" 1901  """makes sure that the LP of the current node is loaded and 1902  may be accessed through the LP information methods 1904  :return: bool cutoff, i.e. can the node be cut off? 1907

cdef SCIP_Bool cutoff

1912  """gets objective value of current LP (which is the sum of column and loose objective value)""" 1917  """Retrieve current LP columns""" 1918

cdef SCIP_COL** cols

1922  return

[Column.create(cols[i])

for

i

in

range(ncols)]

1925  """Retrieve current LP rows""" 1926

cdef SCIP_ROW** rows

1930  return

[Row.create(rows[i])

for

i

in

range(nrows)]

1933  """Retrieve the number of rows currently in the LP""" 1937  """Retrieve the number of cols currently in the LP""" 1941  """Gets all indices of basic columns and rows: index i >= 0 corresponds to column i, index i < 0 to row -i-1""" 1943

cdef int* inds = <int *> malloc(nrows * sizeof(int))

1946

result = [inds[i]

for

i

in

range(nrows)]

1951  """gets a row from the inverse basis matrix B^-1""" 1954

cdef SCIP_Real* coefs = <SCIP_Real*> malloc(nrows * sizeof(SCIP_Real))

1957

result = [coefs[i]

for

i

in

range(nrows)]

1962  """gets a row from B^-1 * A""" 1965

cdef SCIP_Real* coefs = <SCIP_Real*> malloc(ncols * sizeof(SCIP_Real))

1968

result = [coefs[i]

for

i

in

range(ncols)]

1973  """returns whether the current LP solution is basic, i.e. is defined by a valid simplex basis""" 1977  """checks if all columns, i.e. every variable with non-empty column is present in the LP. 1978  This is not True when performing pricing for instance.""" 1984  """gets the reduced cost of the column in the current LP 1986  :param Column col: the column of the LP for which the reduced cost will be retrieved 1992  def createEmptyRowSepa

(self, Sepa sepa, name="row", lhs = 0.0, rhs = None, local = True, modifiable = False, removable = True):

1993  """creates and captures an LP row without any coefficients from a separator 1995  :param sepa: separator that creates the row 1996  :param name: name of row (Default value = "row") 1997  :param lhs: left hand side of row (Default value = 0) 1998  :param rhs: right hand side of row (Default value = None) 1999  :param local: is row only valid locally? (Default value = True) 2000  :param modifiable: is row modifiable during node processing (subject to column generation)? (Default value = False) 2001  :param removable: should the row be removed from the LP due to aging or cleanup? (Default value = True) 2008

PyRow = Row.create(row)

2011  def createEmptyRowUnspec

(self, name="row", lhs = 0.0, rhs = None, local = True, modifiable = False, removable = True):

2012  """creates and captures an LP row without any coefficients from an unspecified source 2014  :param name: name of row (Default value = "row") 2015  :param lhs: left hand side of row (Default value = 0) 2016  :param rhs: right hand side of row (Default value = None) 2017  :param local: is row only valid locally? (Default value = True) 2018  :param modifiable: is row modifiable during node processing (subject to column generation)? (Default value = False) 2019  :param removable: should the row be removed from the LP due to aging or cleanup? (Default value = True) 2025

PyRow = Row.create(row)

2029  """returns the activity of a row in the last LP or pseudo solution""" 2033  """returns the activity of a row in the last LP solution""" 2038  """decreases usage counter of LP row, and frees memory if necessary""" 2042  """informs row, that all subsequent additions of variables to the row should be cached and not directly applied; 2043  after all additions were applied, flushRowExtensions() must be called; 2044  while the caching of row extensions is activated, information methods of the row give invalid results; 2045  caching should be used, if a row is build with addVarToRow() calls variable by variable to increase the performance""" 2049  """flushes all cached row extensions after a call of cacheRowExtensions() and merges coefficients with equal columns into a single coefficient""" 2052  def addVarToRow

(self, Row row not None, Variable var not None, value):

2053  """resolves variable to columns and adds them with the coefficient to the row""" 2061  """Returns number of intergal columns in the row""" 2065  """Returns 1 if the row is parallel, and 0 if orthogonal""" 2069  """Returns the degree of parallelism between hyplerplanes. 1 if perfectly parallel, 0 if orthogonal. 2070  For two row vectors v, w the parallelism is calculated as: |v*w|/(|v|*|w|). 2071  101 in this case is an 'e' (euclidean) in ASCII. The other acceptable input is 100 (d for discrete).""" 2075  """Gets the dual LP solution of a row""" 2080  """if not already existing, adds row to global cut pool""" 2084  """returns efficacy of the cut with respect to the given primal solution or the current LP solution: e = -feasibility/norm""" 2088  """ 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""" 2092  """ returns row's cutoff distance in the direction of the given primal solution""" 2095  def addCut

(self, Row cut not None, forcecut = False):

2096  """adds cut to separation storage and returns whether cut has been detected to be infeasible for local bounds""" 2097

cdef SCIP_Bool infeasible

2098

PY_SCIP_CALL(

SCIPaddRow

(self.

_scip

, cut.scip_row, forcecut, &infeasible))

2102  """Retrieve total number of cuts in storage""" 2106  """Retrieve number of currently applied cuts""" 2110  """Retrieve the number of separation rounds that have been performed 2111  at the current node""" 2114  def separateSol

(self, Solution sol = None, pretendroot = False, allowlocal = True, onlydelayed = False):

2115  """separates the given primal solution or the current LP solution by calling the separators and constraint handlers' 2117  the generated cuts are stored in the separation storage and can be accessed with the methods SCIPgetCuts() and 2119  after evaluating the cuts, you have to call SCIPclearCuts() in order to remove the cuts from the 2121  it is possible to call SCIPseparateSol() multiple times with different solutions and evaluate the found cuts 2123  :param Solution sol: solution to separate, None to use current lp solution (Default value = None) 2124  :param pretendroot: should the cut separators be called as if we are at the root node? (Default value = "False") 2125  :param allowlocal: should the separator be asked to separate local cuts (Default value = True) 2126  :param onlydelayed: should only separators be called that were delayed in the previous round? (Default value = False) 2128  delayed -- whether a separator was delayed 2129  cutoff -- whether the node can be cut off 2131

cdef SCIP_Bool delayed

2132

cdef SCIP_Bool cutoff

2134

PY_SCIP_CALL(

SCIPseparateSol

(self.

_scip

, NULL

if

sol

is None else

sol.sol, pretendroot, allowlocal, onlydelayed, &delayed, &cutoff) )

2135  return

delayed, cutoff

2137  def

_createConsLinear(self, ExprCons lincons, **kwargs):

2138  assert

isinstance(lincons, ExprCons),

"given constraint is not ExprCons but %s"

% lincons.__class__.__name__

2140  assert

lincons.expr.degree() <= 1,

"given constraint is not linear, degree == %d"

% lincons.expr.degree()

2141

terms = lincons.expr.terms

2143

cdef SCIP_CONS* scip_cons

2145

cdef int nvars = len(terms.items())

2147

vars_array = <SCIP_VAR**> malloc(nvars * sizeof(SCIP_VAR*))

2148

coeffs_array = <SCIP_Real*> malloc(nvars * sizeof(SCIP_Real))

2150  for

i, (key, coeff)

in

enumerate(terms.items()):

2151

vars_array[i] = <SCIP_VAR*>(<Variable>key[0]).scip_var

2152

coeffs_array[i] = <SCIP_Real>coeff

2155

self.

_scip

, &scip_cons,

str_conversion

(kwargs[

'name'

]), nvars, vars_array, coeffs_array,

2156

kwargs[

'lhs'

], kwargs[

'rhs'

], kwargs[

'initial'

],

2157

kwargs[

'separate'

], kwargs[

'enforce'

], kwargs[

'check'

],

2158

kwargs[

'propagate'

], kwargs[

'local'

], kwargs[

'modifiable'

],

2159

kwargs[

'dynamic'

], kwargs[

'removable'

], kwargs[

'stickingatnode'

]))

2161

PyCons = Constraint.create(scip_cons)

2167  def

_createConsQuadratic(self, ExprCons quadcons, **kwargs):

2168

terms = quadcons.expr.terms

2169  assert

quadcons.expr.degree() <= 2,

"given constraint is not quadratic, degree == %d"

% quadcons.expr.degree()

2171

cdef SCIP_CONS* scip_cons

2172

cdef SCIP_EXPR* prodexpr

2176

0, NULL, NULL, NULL,

2177

kwargs[

'lhs'

], kwargs[

'rhs'

],

2178

kwargs[

'initial'

], kwargs[

'separate'

], kwargs[

'enforce'

],

2179

kwargs[

'check'

], kwargs[

'propagate'

], kwargs[

'local'

],

2180

kwargs[

'modifiable'

], kwargs[

'dynamic'

], kwargs[

'removable'

]))

2182  for

v, c

in

terms.items():

2184

var = <Variable>v[0]

2187  assert

len(v) == 2,

'term length must be 1 or 2 but it is %s'

% len(v)

2189

varexprs = <SCIP_EXPR**> malloc(2 * sizeof(SCIP_EXPR*))

2190

var1, var2 = <Variable>v[0], <Variable>v[1]

2202

PyCons = Constraint.create(scip_cons)

2206  def

_createConsNonlinear(self, cons, **kwargs):

2207

cdef SCIP_EXPR* expr

2208

cdef SCIP_EXPR** varexprs

2209

cdef SCIP_EXPR** monomials

2211

cdef SCIP_CONS* scip_cons

2213

terms = cons.expr.terms

2216

variables = {var.ptr():var

for

term

in

terms

for

var

in

term}

2217

variables = list(variables.values())

2218

varindex = {var.ptr():idx

for

(idx,var)

in

enumerate(variables)}

2221

monomials = <SCIP_EXPR**> malloc(len(terms) * sizeof(SCIP_EXPR*))

2222

termcoefs = <SCIP_Real*> malloc(len(terms) * sizeof(SCIP_Real))

2223  for

i, (term, coef)

in

enumerate(terms.items()):

2224

termvars = <SCIP_VAR**> malloc(len(term) * sizeof(SCIP_VAR*))

2225  for

j, var

in

enumerate(term):

2226

termvars[j] = (<Variable>var).scip_var

2228

termcoefs[i] = <SCIP_Real>coef

2232

PY_SCIP_CALL(

SCIPcreateExprSum

(self.

_scip

, &expr, <int>len(terms), monomials, termcoefs, 0.0, NULL, NULL))

2242

kwargs[

'initial'

],

2243

kwargs[

'separate'

],

2244

kwargs[

'enforce'

],

2246

kwargs[

'propagate'

],

2248

kwargs[

'modifiable'

],

2249

kwargs[

'dynamic'

],

2250

kwargs[

'removable'

]) )

2252

PyCons = Constraint.create(scip_cons)

2255  for

i

in

range(<int>len(terms)):

2261  def

_createConsGenNonlinear(self, cons, **kwargs):

2262

cdef SCIP_EXPR** childrenexpr

2263

cdef SCIP_EXPR** scipexprs

2264

cdef SCIP_CONS* scip_cons

2281  if

node[0] == Operator.varidx:

2283

vars = <SCIP_VAR**> malloc(nvars * sizeof(SCIP_VAR*))

2286

scipexprs = <SCIP_EXPR**> malloc(len(nodes) * sizeof(SCIP_EXPR*))

2287  for

i,node

in

enumerate(nodes):

2289  if

opidx == Operator.varidx:

2290  assert

len(node[1]) == 1

2293

vars[varpos] = (<Variable>pyvar).scip_var

2296  if

opidx == Operator.const:

2297  assert

len(node[1]) == 1

2301  if

opidx == Operator.add:

2302

nchildren = len(node[1])

2303

childrenexpr = <SCIP_EXPR**> malloc(nchildren * sizeof(SCIP_EXPR*))

2304

coefs = <SCIP_Real*> malloc(nchildren * sizeof(SCIP_Real))

2305  for

c, pos

in

enumerate(node[1]):

2306

childrenexpr[c] = scipexprs[pos]

2308

PY_SCIP_CALL(

SCIPcreateExprSum

(self.

_scip

, &scipexprs[i], nchildren, childrenexpr, coefs, 0, NULL, NULL))

2312  if

opidx == Operator.prod:

2313

nchildren = len(node[1])

2314

childrenexpr = <SCIP_EXPR**> malloc(nchildren * sizeof(SCIP_EXPR*))

2315  for

c, pos

in

enumerate(node[1]):

2316

childrenexpr[c] = scipexprs[pos]

2320  if

opidx == Operator.power:

2322

valuenode = nodes[node[1][1]]

2323  assert

valuenode[0] == Operator.const

2324

exponent = valuenode[1][0]

2325

PY_SCIP_CALL(

SCIPcreateExprPow

(self.

_scip

, &scipexprs[i], scipexprs[node[1][0]], <SCIP_Real>exponent, NULL, NULL ))

2327  if

opidx == Operator.exp:

2328  assert

len(node[1]) == 1

2331  if

opidx == Operator.log:

2332  assert

len(node[1]) == 1

2335  if

opidx == Operator.sqrt:

2336  assert

len(node[1]) == 1

2337

PY_SCIP_CALL(

SCIPcreateExprPow

(self.

_scip

, &scipexprs[i], scipexprs[node[1][0]], <SCIP_Real>0.5, NULL, NULL) )

2339  if

opidx == Operator.sin:

2340  assert

len(node[1]) == 1

2343  if

opidx == Operator.cos:

2344  assert

len(node[1]) == 1

2347  if

opidx == Operator.fabs:

2348  assert

len(node[1]) == 1

2352  raise

NotImplementedError

2353  assert

varpos == nvars

2360

scipexprs[len(nodes) - 1],

2363

kwargs[

'initial'

],

2364

kwargs[

'separate'

],

2365

kwargs[

'enforce'

],

2367

kwargs[

'propagate'

],

2369

kwargs[

'modifiable'

],

2370

kwargs[

'dynamic'

],

2371

kwargs[

'removable'

]) )

2372

PyCons = Constraint.create(scip_cons)

2373  for

i

in

range(len(nodes)):

2383

enforce=True, check=True, propagate=True, local=False,

2384

modifiable=False, dynamic=False, removable=False,

2385

stickingatnode=False):

2386  """Create a linear or nonlinear constraint without adding it to the SCIP problem. This is useful for creating disjunction constraints 2387  without also enforcing the individual constituents. Currently, this can only be used as an argument to `.addConsElemDisjunction`. To add 2388  an individual linear/nonlinear constraint, prefer `.addCons()`. 2390  :param cons: constraint object 2391  :param name: the name of the constraint, generic name if empty (Default value = '') 2392  :param initial: should the LP relaxation of constraint be in the initial LP? (Default value = True) 2393  :param separate: should the constraint be separated during LP processing? (Default value = True) 2394  :param enforce: should the constraint be enforced during node processing? (Default value = True) 2395  :param check: should the constraint be checked for feasibility? (Default value = True) 2396  :param propagate: should the constraint be propagated during node processing? (Default value = True) 2397  :param local: is the constraint only valid locally? (Default value = False) 2398  :param modifiable: is the constraint modifiable (subject to column generation)? (Default value = False) 2399  :param dynamic: is the constraint subject to aging? (Default value = False) 2400  :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False) 2401  :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) 2402  :return The created @ref scip#Constraint "Constraint" object. 2408

kwargs = dict(name=name, initial=initial, separate=separate,

2409

enforce=enforce, check=check,

2410

propagate=propagate, local=local,

2411

modifiable=modifiable, dynamic=dynamic,

2412

removable=removable,

2413

stickingatnode=stickingatnode)

2414

kwargs[

'lhs'

] = -

SCIPinfinity

(self.

_scip

)

if

cons._lhs

is None else

cons._lhs

2415

kwargs[

'rhs'

] =

SCIPinfinity

(self.

_scip

)

if

cons._rhs

is None else

cons._rhs

2417

deg = cons.expr.degree()

2422  elif

deg == float(

'inf'

):

2428  def addCons

(self, cons, name='', initial=True, separate=True,

2429

enforce=True, check=True, propagate=True, local=False,

2430

modifiable=False, dynamic=False, removable=False,

2431

stickingatnode=False):

2432  """Add a linear or nonlinear constraint. 2434  :param cons: constraint object 2435  :param name: the name of the constraint, generic name if empty (Default value = '') 2436  :param initial: should the LP relaxation of constraint be in the initial LP? (Default value = True) 2437  :param separate: should the constraint be separated during LP processing? (Default value = True) 2438  :param enforce: should the constraint be enforced during node processing? (Default value = True) 2439  :param check: should the constraint be checked for feasibility? (Default value = True) 2440  :param propagate: should the constraint be propagated during node processing? (Default value = True) 2441  :param local: is the constraint only valid locally? (Default value = False) 2442  :param modifiable: is the constraint modifiable (subject to column generation)? (Default value = False) 2443  :param dynamic: is the constraint subject to aging? (Default value = False) 2444  :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False) 2445  :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) 2446  :return The added @ref scip#Constraint "Constraint" object. 2449  assert

isinstance(cons, ExprCons),

"given constraint is not ExprCons but %s"

% cons.__class__.__name__

2451

cdef SCIP_CONS* scip_cons

2453

kwargs = dict(name=name, initial=initial, separate=separate,

2454

enforce=enforce, check=check,

2455

propagate=propagate, local=local,

2456

modifiable=modifiable, dynamic=dynamic,

2457

removable=removable,

2458

stickingatnode=stickingatnode)

2464

scip_cons = (<Constraint>pycons_initial).scip_cons

2467

pycons = Constraint.create(scip_cons)

2472  def addConss

(self, conss, name='', initial=True, separate=True,

2473

enforce=True, check=True, propagate=True, local=False,

2474

modifiable=False, dynamic=False, removable=False,

2475

stickingatnode=False):

2476  """Adds multiple linear or quadratic constraints. 2478  Each of the constraints is added to the model using Model.addCons(). 2480  For all parameters, except @p conss, this method behaves differently depending on the type of the passed argument: 2481  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. 2482  2. Else, the (default) value will be applied to all of the constraints. 2484  :param conss An iterable of constraint objects. Any iterable will be converted into a list before further processing. 2485  :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). 2486  :param initial: should the LP relaxation of constraints be in the initial LP? (Default value = True) 2487  :param separate: should the constraints be separated during LP processing? (Default value = True) 2488  :param enforce: should the constraints be enforced during node processing? (Default value = True) 2489  :param check: should the constraints be checked for feasibility? (Default value = True) 2490  :param propagate: should the constraints be propagated during node processing? (Default value = True) 2491  :param local: are the constraints only valid locally? (Default value = False) 2492  :param modifiable: are the constraints modifiable (subject to column generation)? (Default value = False) 2493  :param dynamic: are the constraints subject to aging? (Default value = False) 2494  :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False) 2495  :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) 2496  :return A list of added @ref scip#Constraint "Constraint" objects. 2500  def

ensure_iterable(elem, length):

2501  if

isinstance(elem, Iterable):

2504  return

list(repeat(elem, length))

2506  assert

isinstance(conss, Iterable),

"Given constraint list is not iterable." 2509

n_conss = len(conss)

2511  if

isinstance(name, str):

2513

name = [

"" for

idx

in

range(n_conss)]

2515

name = [

"%s_%s"

% (name, idx)

for

idx

in

range(n_conss)]

2516

initial = ensure_iterable(initial, n_conss)

2517

separate = ensure_iterable(separate, n_conss)

2518

enforce = ensure_iterable(enforce, n_conss)

2519

check = ensure_iterable(check, n_conss)

2520

propagate = ensure_iterable(propagate, n_conss)

2521

local = ensure_iterable(local, n_conss)

2522

modifiable = ensure_iterable(modifiable, n_conss)

2523

dynamic = ensure_iterable(dynamic, n_conss)

2524

removable = ensure_iterable(removable, n_conss)

2525

stickingatnode = ensure_iterable(stickingatnode, n_conss)

2528  for

i, cons

in

enumerate(conss):

2530

self.

addCons

(cons, name[i], initial[i], separate[i], enforce[i],

2531

check[i], propagate[i], local[i], modifiable[i],

2532

dynamic[i], removable[i], stickingatnode[i])

2538

relaxcons = None, enforce=True, check =True,

2539

local=False, modifiable = False, dynamic = False):

2540  """Add a disjunction constraint. 2542  :param Iterable[Constraint] conss: An iterable of constraint objects to be included initially in the disjunction. Currently, these must be expressions. 2543  :param name: the name of the disjunction constraint. 2544  :param initial: should the LP relaxation of disjunction constraint be in the initial LP? (Default value = True) 2545  :param relaxcons: a conjunction constraint containing the linear relaxation of the disjunction constraint, or None. (Default value = None) 2546  :param enforce: should the constraint be enforced during node processing? (Default value = True) 2547  :param check: should the constraint be checked for feasibility? (Default value = True) 2548  :param local: is the constraint only valid locally? (Default value = False) 2549  :param modifiable: is the constraint modifiable (subject to column generation)? (Default value = False) 2550  :param dynamic: is the constraint subject to aging? (Default value = False) 2551  :return The added @ref scip#Constraint "Constraint" object. 2553  def

ensure_iterable(elem, length):

2554  if

isinstance(elem, Iterable):

2557  return

list(repeat(elem, length))

2558  assert

isinstance(conss, Iterable),

"Given constraint list is not iterable" 2561

n_conss = len(conss)

2563

cdef SCIP_CONS* disj_cons

2565

cdef SCIP_CONS* scip_cons

2567

cdef SCIP_EXPR* scip_expr

2571

initial, enforce, check, local, modifiable, dynamic

2576  for

i, cons

in

enumerate(conss):

2578

enforce=enforce, check=check,

2579

local=local, modifiable=modifiable, dynamic=dynamic

2584

PyCons = Constraint.create(disj_cons)

2589  """Appends a constraint to a disjunction. 2591  :param Constraint disj_cons: the disjunction constraint to append to. 2592  :param Constraint cons: the Constraint to append 2593  :return The disjunction constraint with added @ref scip#Constraint object. 2601  Gets number of variables in a constraint. 2603  :param constraint: Constraint to get the number of variables from. 2606

cdef SCIP_Bool success

2613  raise

TypeError(

"The constraint handler %s does not have this functionality."

% conshdrlname)

2619  Gets variables in a constraint. 2621  :param constraint: Constraint to get the variables from. 2623

cdef SCIP_Bool success

2628

cdef SCIP_VAR** _vars = <SCIP_VAR**> malloc(_nvars * sizeof(SCIP_VAR*))

2629  SCIPgetConsVars

(self.

_scip

, constraint.scip_cons, _vars, _nvars*sizeof(SCIP_VAR*), &success)

2632  for

i

in

range(_nvars):

2633

ptr = <size_t>(_vars[i])

2639

var = Variable.create(_vars[i])

2640  assert

var.ptr() == ptr

2649  from

typing

import

Union

2652  Add coef*expr to nonlinear constraint. 2654  assert

self.

getStage

() == 1,

"addExprNonlinear cannot be called in stage %i."

% self.

getStage

()

2655  assert

cons.isNonlinear(),

"addExprNonlinear can only be called with nonlinear constraints." 2657

cdef Constraint temp_cons

2658

cdef SCIP_EXPR* scip_expr

2660

temp_cons = self.

addCons

(expr <= 0)

2667  """Add coefficient to the linear constraint (if non-zero). 2669  :param Constraint cons: constraint to be changed 2670  :param Variable var: variable to be added 2671  :param coeff: coefficient of new variable 2676  def addConsNode

(self, Node node, Constraint cons, Node validnode=None):

2677  """Add a constraint to the given node 2679  :param Node node: node to add the constraint to 2680  :param Constraint cons: constraint to add 2681  :param Node validnode: more global node where cons is also valid 2684  if

isinstance(validnode, Node):

2685

PY_SCIP_CALL(

SCIPaddConsNode

(self.

_scip

, node.scip_node, cons.scip_cons, validnode.scip_node))

2691  """Add a constraint to the current node 2693  :param Constraint cons: constraint to add 2694  :param Node validnode: more global node where cons is also valid 2697  if

isinstance(validnode, Node):

2704

initial=True, separate=True, enforce=True, check=True,

2705

propagate=True, local=False, dynamic=False,

2706

removable=False, stickingatnode=False):

2707  """Add an SOS1 constraint. 2709  :param vars: list of variables to be included 2710  :param weights: list of weights (Default value = None) 2711  :param name: name of the constraint (Default value = "SOS1cons") 2712  :param initial: should the LP relaxation of constraint be in the initial LP? (Default value = True) 2713  :param separate: should the constraint be separated during LP processing? (Default value = True) 2714  :param enforce: should the constraint be enforced during node processing? (Default value = True) 2715  :param check: should the constraint be checked for feasibility? (Default value = True) 2716  :param propagate: should the constraint be propagated during node processing? (Default value = True) 2717  :param local: is the constraint only valid locally? (Default value = False) 2718  :param dynamic: is the constraint subject to aging? (Default value = False) 2719  :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False) 2720  :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) 2723

cdef SCIP_CONS* scip_cons

2727

initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode))

2729  if

weights

is None

:

2735  for

i

in

range(nvars):

2736

var = <Variable>vars[i]

2740  return

Constraint.create(scip_cons)

2743

initial=True, separate=True, enforce=True, check=True,

2744

propagate=True, local=False, dynamic=False,

2745

removable=False, stickingatnode=False):

2746  """Add an SOS2 constraint. 2748  :param vars: list of variables to be included 2749  :param weights: list of weights (Default value = None) 2750  :param name: name of the constraint (Default value = "SOS2cons") 2751  :param initial: should the LP relaxation of constraint be in the initial LP? (Default value = True) 2752  :param separate: should the constraint be separated during LP processing? (Default value = True) 2753  :param enforce: should the constraint be enforced during node processing? (Default value = True) 2754  :param check: should the constraint be checked for feasibility? (Default value = True) 2755  :param propagate: is the constraint only valid locally? (Default value = True) 2756  :param local: is the constraint only valid locally? (Default value = False) 2757  :param dynamic: is the constraint subject to aging? (Default value = False) 2758  :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False) 2759  :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) 2762

cdef SCIP_CONS* scip_cons

2766

initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode))

2768  if

weights

is None

:

2774  for

i

in

range(nvars):

2775

var = <Variable>vars[i]

2779  return

Constraint.create(scip_cons)

2782

initial=True, separate=True, enforce=True, check=True,

2783

propagate=True, local=False, modifiable=False, dynamic=False,

2784

removable=False, stickingatnode=False):

2785  """Add an AND-constraint. 2786  :param vars: list of BINARY variables to be included (operators) 2787  :param resvar: BINARY variable (resultant) 2788  :param name: name of the constraint (Default value = "ANDcons") 2789  :param initial: should the LP relaxation of constraint be in the initial LP? (Default value = True) 2790  :param separate: should the constraint be separated during LP processing? (Default value = True) 2791  :param enforce: should the constraint be enforced during node processing? (Default value = True) 2792  :param check: should the constraint be checked for feasibility? (Default value = True) 2793  :param propagate: should the constraint be propagated during node processing? (Default value = True) 2794  :param local: is the constraint only valid locally? (Default value = False) 2795  :param modifiable: is the constraint modifiable (subject to column generation)? (Default value = False) 2796  :param dynamic: is the constraint subject to aging? (Default value = False) 2797  :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False) 2798  :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) 2800

cdef SCIP_CONS* scip_cons

2804

_vars = <SCIP_VAR**> malloc(len(vars) * sizeof(SCIP_VAR*))

2805  for

idx, var

in

enumerate(vars):

2806

_vars[idx] = (<Variable>var).scip_var

2807

_resVar = (<Variable>resvar).scip_var

2810

initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode))

2813

pyCons = Constraint.create(scip_cons)

2821

initial=True, separate=True, enforce=True, check=True,

2822

propagate=True, local=False, modifiable=False, dynamic=False,

2823

removable=False, stickingatnode=False):

2824  """Add an OR-constraint. 2825  :param vars: list of BINARY variables to be included (operators) 2826  :param resvar: BINARY variable (resultant) 2827  :param name: name of the constraint (Default value = "ORcons") 2828  :param initial: should the LP relaxation of constraint be in the initial LP? (Default value = True) 2829  :param separate: should the constraint be separated during LP processing? (Default value = True) 2830  :param enforce: should the constraint be enforced during node processing? (Default value = True) 2831  :param check: should the constraint be checked for feasibility? (Default value = True) 2832  :param propagate: should the constraint be propagated during node processing? (Default value = True) 2833  :param local: is the constraint only valid locally? (Default value = False) 2834  :param modifiable: is the constraint modifiable (subject to column generation)? (Default value = False) 2835  :param dynamic: is the constraint subject to aging? (Default value = False) 2836  :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False) 2837  :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) 2839

cdef SCIP_CONS* scip_cons

2843

_vars = <SCIP_VAR**> malloc(len(vars) * sizeof(SCIP_VAR*))

2844  for

idx, var

in

enumerate(vars):

2845

_vars[idx] = (<Variable>var).scip_var

2846

_resVar = (<Variable>resvar).scip_var

2849

initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode))

2852

pyCons = Constraint.create(scip_cons)

2860

initial=True, separate=True, enforce=True, check=True,

2861

propagate=True, local=False, modifiable=False, dynamic=False,

2862

removable=False, stickingatnode=False):

2863  """Add a XOR-constraint. 2864  :param vars: list of BINARY variables to be included (operators) 2865  :param rhsvar: BOOLEAN value, explicit True, False or bool(obj) is needed (right-hand side) 2866  :param name: name of the constraint (Default value = "XORcons") 2867  :param initial: should the LP relaxation of constraint be in the initial LP? (Default value = True) 2868  :param separate: should the constraint be separated during LP processing? (Default value = True) 2869  :param enforce: should the constraint be enforced during node processing? (Default value = True) 2870  :param check: should the constraint be checked for feasibility? (Default value = True) 2871  :param propagate: should the constraint be propagated during node processing? (Default value = True) 2872  :param local: is the constraint only valid locally? (Default value = False) 2873  :param modifiable: is the constraint modifiable (subject to column generation)? (Default value = False) 2874  :param dynamic: is the constraint subject to aging? (Default value = False) 2875  :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False) 2876  :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) 2878

cdef SCIP_CONS* scip_cons

2882  assert

type(rhsvar)

is

type(bool()),

"Provide BOOLEAN value as rhsvar, you gave %s."

% type(rhsvar)

2883

_vars = <SCIP_VAR**> malloc(len(vars) * sizeof(SCIP_VAR*))

2884  for

idx, var

in

enumerate(vars):

2885

_vars[idx] = (<Variable>var).scip_var

2888

initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode))

2891

pyCons = Constraint.create(scip_cons)

2899

initial=True, separate=True, enforce=True, check=True,

2900

propagate=True, local=False, dynamic=False,

2901

removable=False, stickingatnode=False):

2902  """Add a cardinality constraint that allows at most 'cardval' many nonzero variables. 2904  :param consvars: list of variables to be included 2905  :param cardval: nonnegative integer 2906  :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) 2907  :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) 2908  :param name: name of the constraint (Default value = "CardinalityCons") 2909  :param initial: should the LP relaxation of constraint be in the initial LP? (Default value = True) 2910  :param separate: should the constraint be separated during LP processing? (Default value = True) 2911  :param enforce: should the constraint be enforced during node processing? (Default value = True) 2912  :param check: should the constraint be checked for feasibility? (Default value = True) 2913  :param propagate: should the constraint be propagated during node processing? (Default value = True) 2914  :param local: is the constraint only valid locally? (Default value = False) 2915  :param dynamic: is the constraint subject to aging? (Default value = False) 2916  :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False) 2917  :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) 2920

cdef SCIP_CONS* scip_cons

2921

cdef SCIP_VAR* indvar

2924

initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode))

2927  if

weights

is None

:

2928

weights = list(range(1, len(consvars) + 1))

2930  for

i, v

in

enumerate(consvars):

2933

indvar = (<Variable>indvars[i]).scip_var

2936  if

weights

is None

:

2942

pyCons = Constraint.create(scip_cons)

2949

initial=True, separate=True, enforce=True, check=True,

2950

propagate=True, local=False, dynamic=False,

2951

removable=False, stickingatnode=False):

2952  """Add an indicator constraint for the linear inequality 'cons'. 2954  The 'binvar' argument models the redundancy of the linear constraint. A solution for which 2955  'binvar' is 1 must satisfy the constraint. 2957  :param cons: a linear inequality of the form "<=" 2958  :param binvar: binary indicator variable, or None if it should be created (Default value = None) 2959  :param activeone: constraint should active if binvar is 1 (0 if activeone = False) 2960  :param name: name of the constraint (Default value = "IndicatorCons") 2961  :param initial: should the LP relaxation of constraint be in the initial LP? (Default value = True) 2962  :param separate: should the constraint be separated during LP processing? (Default value = True) 2963  :param enforce: should the constraint be enforced during node processing? (Default value = True) 2964  :param check: should the constraint be checked for feasibility? (Default value = True) 2965  :param propagate: should the constraint be propagated during node processing? (Default value = True) 2966  :param local: is the constraint only valid locally? (Default value = False) 2967  :param dynamic: is the constraint subject to aging? (Default value = False) 2968  :param removable: should the relaxation be removed from the LP due to aging or cleanup? (Default value = False) 2969  :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) 2972  assert

isinstance(cons, ExprCons),

"given constraint is not ExprCons but %s"

% cons.__class__.__name__

2973

cdef SCIP_CONS* scip_cons

2974

cdef SCIP_VAR* _binVar

2975  if

cons._lhs

is not None and

cons._rhs

is not None

:

2976  raise

ValueError(

"expected inequality that has either only a left or right hand side"

)

2978  if

cons.expr.degree() > 1:

2979  raise

ValueError(

"expected linear inequality, expression has degree %d"

% cons.expr.degree())

2981  if

cons._rhs

is not None

:

2988  if

binvar

is not None

:

2989

_binVar = (<Variable>binvar).scip_var

2996

initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode))

2997

terms = cons.expr.terms

2999  for

key, coeff

in

terms.items():

3000

var = <Variable>key[0]

3006

pyCons = Constraint.create(scip_cons)

3013  """Get slack variable of an indicator constraint. 3015  :param Constraint cons: indicator constraint 3019  return

Variable.create(var)

3022  """Adds a customly created cons. 3024  :param Constraint cons: constraint to add 3031  """Add variable to SOS1 constraint. 3033  :param Constraint cons: SOS1 constraint 3034  :param Variable var: new variable 3035  :param weight: weight of new variable 3041  """Append variable to SOS1 constraint. 3043  :param Constraint cons: SOS1 constraint 3044  :param Variable var: variable to append 3050  """Add variable to SOS2 constraint. 3052  :param Constraint cons: SOS2 constraint 3053  :param Variable var: new variable 3054  :param weight: weight of new variable 3060  """Append variable to SOS2 constraint. 3062  :param Constraint cons: SOS2 constraint 3063  :param Variable var: variable to append 3069  """Set "initial" flag of a constraint. 3073  newInit -- new initial value 3078  """Set "removable" flag of a constraint. 3082  newRem -- new removable value 3087  """Set "enforced" flag of a constraint. 3091  newEnf -- new enforced value 3096  """Set "check" flag of a constraint. 3100  newCheck -- new check value 3105  """Change right hand side value of a constraint. 3107  :param Constraint cons: linear or quadratic constraint 3108  :param rhs: new right hand side (set to None for +infinity) 3116  if

constype ==

'linear'

:

3118  elif

constype ==

'nonlinear'

:

3121  raise

Warning(

"method cannot be called for constraints of type "

+ constype)

3124  """Change left hand side value of a constraint. 3126  :param Constraint cons: linear or quadratic constraint 3127  :param lhs: new left hand side (set to None for -infinity) 3135  if

constype ==

'linear'

:

3137  elif

constype ==

'nonlinear'

:

3140  raise

Warning(

"method cannot be called for constraints of type "

+ constype)

3143  """Retrieve right hand side value of a constraint. 3145  :param Constraint cons: linear or quadratic constraint 3149  if

constype ==

'linear'

:

3151  elif

constype ==

'quadratic'

:

3154  raise

Warning(

"method cannot be called for constraints of type "

+ constype)

3157  """Retrieve left hand side value of a constraint. 3159  :param Constraint cons: linear or quadratic constraint 3163  if

constype ==

'linear'

:

3165  elif

constype ==

'quadratic'

:

3168  raise

Warning(

"method cannot be called for constraints of type "

+ constype)

3171  """Changes coefficient of variable in linear constraint; 3172  deletes the variable if coefficient is zero; adds variable if not yet contained in the constraint 3173  This method may only be called during problem creation stage for an original constraint and variable. 3174  This method requires linear time to search for occurences of the variable in the constraint data. 3176  :param Constraint cons: linear constraint 3177  :param Variable var: variable of constraint entry 3178  :param value: new coefficient of constraint entry 3184  """Deletes variable from linear constraint 3185  This method may only be called during problem creation stage for an original constraint and variable. 3186  This method requires linear time to search for occurences of the variable in the constraint data. 3188  :param Constraint cons: linear constraint 3189  :param Variable var: variable of constraint entry 3196  """Adds coefficient to linear constraint (if it is not zero) 3198  :param Constraint cons: linear constraint 3199  :param Variable var: variable of constraint entry 3200  :param value: coefficient of constraint entry 3207  """Retrieve activity of given constraint. 3208  Can only be called after solving is completed. 3210  :param Constraint cons: linear or quadratic constraint 3211  :param Solution sol: solution to compute activity of, None to use current node's solution (Default value = None) 3214

cdef SCIP_Real activity

3215

cdef SCIP_SOL* scip_sol

3217  if not

self.

getStage

() >= SCIP_STAGE_SOLVING:

3218  raise

Warning(

"method cannot be called before problem is solved"

)

3220  if

isinstance(sol, Solution):

3226  if

constype ==

'linear'

:

3229  raise

Warning(

"method cannot be called for constraints of type "

+ constype)

3234  def getSlack

(self, Constraint cons, Solution sol = None, side = None):

3235  """Retrieve slack of given constraint. 3236  Can only be called after solving is completed. 3239  :param Constraint cons: linear or quadratic constraint 3240  :param Solution sol: solution to compute slack of, None to use current node's solution (Default value = None) 3241  :param side: whether to use 'lhs' or 'rhs' for ranged constraints, None to return minimum (Default value = None) 3244

cdef SCIP_Real activity

3245

cdef SCIP_SOL* scip_sol

3248  if not

self.

getStage

() >= SCIP_STAGE_SOLVING:

3249  raise

Warning(

"method cannot be called before problem is solved"

)

3251  if

isinstance(sol, Solution):

3257  if

constype ==

'linear'

:

3262  raise

Warning(

"method cannot be called for constraints of type "

+ constype)

3264

lhsslack = activity - lhs

3265

rhsslack = rhs - activity

3269  elif

side ==

'rhs'

:

3272  return

min(lhsslack, rhsslack)

3275  """Retrieve transformed constraint. 3277  :param Constraint cons: constraint 3280

cdef SCIP_CONS* transcons

3282  return

Constraint.create(transcons)

3285  """returns whether SCIP's internal NLP has been constructed""" 3289  """gets current number of nonlinear rows in SCIP's internal NLP""" 3293  """returns a list with the nonlinear rows in SCIP's internal NLP""" 3294

cdef SCIP_NLROW** nlrows

3297  return

[NLRow.create(nlrows[i])

for

i

in

range(self.

getNNlRows

())]

3300  """gives the activity of a nonlinear row for a given primal solution 3302  nlrow -- nonlinear row 3303  solution -- a primal solution, if None, then the current LP solution is used 3305

cdef SCIP_Real activity

3306

cdef SCIP_SOL* solptr

3308

solptr = sol.sol

if not

sol

is None else

NULL

3313  """gives the feasibility of a nonlinear row for a given primal solution 3315  nlrow -- nonlinear row 3316  solution -- a primal solution, if None, then the current LP solution is used 3318

cdef SCIP_Real feasibility

3319

cdef SCIP_SOL* solptr

3321

solptr = sol.sol

if not

sol

is None else

NULL

3326  """gives the minimal and maximal activity of a nonlinear row w.r.t. the variable's bounds""" 3327

cdef SCIP_Real minactivity

3328

cdef SCIP_Real maxactivity

3331  return

(minactivity, maxactivity)

3334  """prints nonlinear row""" 3338  """returns if the given constraint is quadratic 3340  :param Constraint cons: constraint 3343

cdef SCIP_Bool isquadratic

3348  """Retrieve bilinear, quadratic, and linear terms of a quadratic constraint. 3350  :param Constraint cons: constraint 3353

cdef SCIP_EXPR* expr

3356

cdef SCIP_EXPR** _linexprs

3357

cdef SCIP_Real* _lincoefs

3361

cdef int _nbilinterms

3362

cdef SCIP_EXPR* bilinterm1

3363

cdef SCIP_EXPR* bilinterm2

3364

cdef SCIP_Real bilincoef

3367

cdef int _nquadterms

3368

cdef SCIP_Real sqrcoef

3369

cdef SCIP_Real lincoef

3370

cdef SCIP_EXPR* sqrexpr

3373

cdef SCIP_VAR* scipvar1

3374

cdef SCIP_VAR* scipvar2

3376  assert

cons.isNonlinear(),

"constraint is not nonlinear" 3386  for

termidx

in

range(_nlinvars):

3388

linterms.append((var,_lincoefs[termidx]))

3390  for

termidx

in

range(_nbilinterms):

3394

var1 = Variable.create(scipvar1)

3395

var2 = Variable.create(scipvar2)

3396  if

scipvar1 != scipvar2:

3397

bilinterms.append((var1,var2,bilincoef))

3399

quadterms.append((var1,bilincoef,0.0))

3401  for

termidx

in

range(_nquadterms):

3406

quadterms.append((var,sqrcoef,lincoef))

3408  return

(bilinterms, quadterms, linterms)

3411  """sets the value of the given variable in the global relaxation solution""" 3415  """Retrieve all constraints. 3417  :param transformed: get transformed variables instead of original (Default value = True) 3419

cdef SCIP_CONS** _conss

3429  return

[Constraint.create(_conss[i])

for

i

in

range(_nconss)]

3432  """Retrieve number of all constraints""" 3439  """Delete constraint from the model 3441  :param Constraint cons: constraint to be deleted 3447  """Delete constraint from the current node and it's children 3449  :param Constraint cons: constraint to be deleted 3455  """Retrieve the coefficients of a linear constraint 3457  :param Constraint cons: linear constraint to get the coefficients of 3460

cdef SCIP_Real* _vals

3461

cdef SCIP_VAR** _vars

3464  if not

constype ==

'linear'

:

3465  raise

Warning(

"coefficients not available for constraints of type "

, constype)

3472

valsdict[bytes(

SCIPvarGetName

(_vars[i])).decode(

'utf-8'

)] = _vals[i]

3476  """Retrieve the linear relaxation of the given linear constraint as a row. 3477  may return NULL if no LP row was yet created; the user must not modify the row! 3479  :param Constraint cons: linear constraint to get the coefficients of 3483  if not

constype ==

'linear'

:

3484  raise

Warning(

"coefficients not available for constraints of type "

, constype)

3487  return

Row.create(row)

3490  """Retrieve the dual solution to a linear constraint. 3492  :param Constraint cons: linear constraint 3496  if not

constype ==

'linear'

:

3497  raise

Warning(

"dual solution values not available for constraints of type "

, constype)

3498  if

cons.isOriginal():

3505  """DEPRECATED: Retrieve the dual solution to a linear constraint. 3507  :param Constraint cons: linear constraint 3510  raise

Warning(

"model.getDualMultiplier(cons) is deprecated: please use model.getDualsolLinear(cons)"

)

3514  """Retrieve the dual farkas value to a linear constraint. 3516  :param Constraint cons: linear constraint 3520  if

cons.isOriginal():

3527  """Retrieve the reduced cost of a variable. 3529  :param Variable var: variable to get the reduced cost of 3538  raise

Warning(

"no reduced cost available for variable "

+ var.name)

3542  """Retrieve returns dual solution value of a constraint. 3544  :param Constraint cons: constraint to get the dual solution value of 3545  :param boundconstraint bool: Decides whether to store a bool if the constraint is a bound constraint 3548

cdef SCIP_Real _dualsol

3549

cdef SCIP_Bool _bounded

3559  """Optimize the problem.""" 3564  """Transforms, presolves, and solves problem using additional solvers which emphasize on 3565  finding solutions.""" 3566  if

SCIPtpiGetNumThreads() == 1:

3567

warnings.warn(

"SCIP was compiled without task processing interface. Parallel solve not possible - using optimize() instead of solveConcurrent()"

)

3574  """Presolve the problem.""" 3580  """initialises the default Benders' decomposition with a dictionary of subproblems 3583  subproblems -- a single Model instance or dictionary of Model instances 3585

cdef SCIP** subprobs

3586

cdef SCIP_BENDERS* benders

3589  if

isinstance(subproblems, dict):

3591

nsubproblems = len(subproblems)

3597

subprobs = <SCIP**> malloc(nsubproblems * sizeof(SCIP*))

3601  for

idx, subprob

in

enumerate(subproblems.values()):

3602

subprobs[idx] = (<Model>subprob)._scip

3604

subprobs[0] = (<Model>subproblems)._scip

3611

self.

setBoolParam

(

"constraints/benderslp/active"

,

True

)

3612

self.

setBoolParam

(

"constraints/benders/active"

,

True

)

3616  """Solves the subproblems with the best solution to the master problem. 3617  Afterwards, the best solution from each subproblem can be queried to get 3618  the solution to the original problem. 3620  If the user wants to resolve the subproblems, they must free them by 3621  calling freeBendersSubproblems() 3623

cdef SCIP_BENDERS** _benders

3624

cdef SCIP_Bool _infeasible

3626

cdef int nsubproblems

3634  for

i

in

range(nbenders):

3636  for

j

in

range(nsubproblems):

3638

_benders[i], self.

_bestSol

.sol, j, SCIP_BENDERSENFOTYPE_CHECK))

3640

_benders[i], self.

_bestSol

.sol, j, &_infeasible, solvecip, NULL))

3643  """Calls the free subproblem function for the Benders' decomposition. 3644  This will free all subproblems for all decompositions. 3646

cdef SCIP_BENDERS** _benders

3648

cdef int nsubproblems

3654  for

i

in

range(nbenders):

3656  for

j

in

range(nsubproblems):

3661  """"updates the subproblem lower bounds for benders using 3662  the lowerbounds dict. If benders is None, then the default 3663  Benders' decomposition is updated 3665

cdef SCIP_BENDERS* _benders

3667  assert

type(lowerbounds)

is

dict

3669  if

benders

is None

:

3672

_benders = benders._benders

3674  for

d

in

lowerbounds.keys():

3678  """Activates the Benders' decomposition plugin with the input name 3681  benders -- the Benders' decomposition to which the subproblem belongs to 3682  nsubproblems -- the number of subproblems in the Benders' decomposition 3687  """adds a subproblem to the Benders' decomposition given by the input 3691  benders -- the Benders' decomposition to which the subproblem belongs to 3692  subproblem -- the subproblem to add to the decomposition 3693  isconvex -- can be used to specify whether the subproblem is convex 3698  """sets a flag indicating whether the subproblem is convex 3701  benders -- the Benders' decomposition which contains the subproblem 3702  probnumber -- the problem number of the subproblem that the convexity will be set for 3703  isconvex -- flag to indicate whether the subproblem is convex 3707  def setupBendersSubproblem

(self, probnumber, Benders benders = None, Solution solution = None, checktype = PY_SCIP_BENDERSENFOTYPE.LP):

3708  """ sets up the Benders' subproblem given the master problem solution 3711  probnumber -- the index of the problem that is to be set up 3712  benders -- the Benders' decomposition to which the subproblem belongs to 3713  solution -- the master problem solution that is used for the set up, if None, then the LP solution is used 3714  checktype -- the type of solution check that prompted the solving of the Benders' subproblems, either 3715  PY_SCIP_BENDERSENFOTYPE: LP, RELAX, PSEUDO or CHECK. Default is LP 3717

cdef SCIP_BENDERS* scip_benders

3718

cdef SCIP_SOL* scip_sol

3720  if

isinstance(solution, Solution):

3721

scip_sol = solution.sol

3725  if

benders

is None

:

3728

scip_benders = benders._benders

3732

PY_SCIP_CALL(retcode)

3735  """ solves the Benders' decomposition subproblem. The convex relaxation will be solved unless 3736  the parameter solvecip is set to True. 3739  probnumber -- the index of the problem that is to be set up 3740  solvecip -- should the CIP of the subproblem be solved, if False, then only the convex relaxation is solved 3741  benders -- the Benders' decomposition to which the subproblem belongs to 3742  solution -- the master problem solution that is used for the set up, if None, then the LP solution is used 3745

cdef SCIP_BENDERS* scip_benders

3746

cdef SCIP_SOL* scip_sol

3747

cdef SCIP_Real objective

3748

cdef SCIP_Bool infeasible

3750  if

isinstance(solution, Solution):

3751

scip_sol = solution.sol

3755  if

benders

is None

:

3758

scip_benders = benders._benders

3761

probnumber, &infeasible, solvecip, &objective))

3763  return

infeasible, objective

3766  """Returns a Model object that wraps around the SCIP instance of the subproblem. 3767  NOTE: This Model object is just a place holder and SCIP instance will not be freed when the object is destroyed. 3770  probnumber -- the problem number for subproblem that is required 3771  benders -- the Benders' decomposition object for the that the subproblem belongs to (Default = None) 3773

cdef SCIP_BENDERS* scip_benders

3774

cdef SCIP* scip_subprob

3776  if

benders

is None

:

3779

scip_benders = benders._benders

3783  return

Model.create(scip_subprob)

3785  def getBendersVar

(self, Variable var, Benders benders = None, probnumber = -1):

3786  """Returns the variable for the subproblem or master problem 3787  depending on the input probnumber 3790  var -- the source variable for which the target variable is requested 3791  benders -- the Benders' decomposition to which the subproblem variables belong to 3792  probnumber -- the problem number for which the target variable belongs, -1 for master problem 3794

cdef SCIP_BENDERS* _benders

3795

cdef SCIP_VAR* _mappedvar

3797  if

benders

is None

:

3800

_benders = benders._benders

3802  if

probnumber == -1:

3807  if

_mappedvar == NULL:

3810

mappedvar = Variable.create(_mappedvar)

3815  """Returns the auxiliary variable that is associated with the input problem number 3818  probnumber -- the problem number for which the target variable belongs, -1 for master problem 3819  benders -- the Benders' decomposition to which the subproblem variables belong to 3821

cdef SCIP_BENDERS* _benders

3822

cdef SCIP_VAR* _auxvar

3824  if

benders

is None

:

3827

_benders = benders._benders

3830

auxvar = Variable.create(_auxvar)

3835  """Returns whether the subproblem is optimal w.r.t the master problem auxiliary variables. 3838  solution -- the master problem solution that is being checked for optimamlity 3839  probnumber -- the problem number for which optimality is being checked 3840  benders -- the Benders' decomposition to which the subproblem belongs to 3842

cdef SCIP_BENDERS* _benders

3843

cdef SCIP_SOL* scip_sol

3844

cdef SCIP_Bool optimal

3846  if

benders

is None

:

3849

_benders = benders._benders

3851  if

isinstance(solution, Solution):

3852

scip_sol = solution.sol

3857

scip_sol, probnumber, &optimal) )

3862  """includes the default Benders' decomposition cuts to the custom Benders' decomposition plugin 3865  benders -- the Benders' decomposition that the default cuts will be applied to 3867

PY_SCIP_CALL( SCIPincludeBendersDefaultCuts(self.

_scip

, benders._benders) )

3871  """Include an event handler. 3874  eventhdlr -- event handler 3875  name -- name of event handler 3876  desc -- description of event handler 3889

<SCIP_EVENTHDLRDATA*>eventhdlr))

3890

eventhdlr.model = <Model>weakref.proxy(self)

3891

eventhdlr.name = name

3892

Py_INCREF(eventhdlr)

3895  """Include a pricer. 3897  :param Pricer pricer: pricer 3898  :param name: name of pricer 3899  :param desc: description of pricer 3900  :param priority: priority of pricer (Default value = 1) 3901  :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) 3908

PyPricerCopy, PyPricerFree, PyPricerInit, PyPricerExit, PyPricerInitsol, PyPricerExitsol, PyPricerRedcost, PyPricerFarkas,

3909

<SCIP_PRICERDATA*>pricer))

3910

cdef SCIP_PRICER* scip_pricer

3913

pricer.model = <Model>weakref.proxy(self)

3917

enfopriority=0, chckpriority=0, sepafreq=-1, propfreq=-1,

3918

eagerfreq=100, maxprerounds=-1, delaysepa=False,

3919

delayprop=False, needscons=True,

3920

proptiming=PY_SCIP_PROPTIMING.BEFORELP,

3921

presoltiming=PY_SCIP_PRESOLTIMING.MEDIUM):

3922  """Include a constraint handler 3924  :param Conshdlr conshdlr: constraint handler 3925  :param name: name of constraint handler 3926  :param desc: description of constraint handler 3927  :param sepapriority: priority for separation (Default value = 0) 3928  :param enfopriority: priority for constraint enforcing (Default value = 0) 3929  :param chckpriority: priority for checking feasibility (Default value = 0) 3930  :param sepafreq: frequency for separating cuts; 0 = only at root node (Default value = -1) 3931  :param propfreq: frequency for propagating domains; 0 = only preprocessing propagation (Default value = -1) 3932  :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) 3933  :param maxprerounds: maximal number of presolving rounds the constraint handler participates in (Default value = -1) 3934  :param delaysepa: should separation method be delayed, if other separators found cuts? (Default value = False) 3935  :param delayprop: should propagation method be delayed, if other propagators found reductions? (Default value = False) 3936  :param needscons: should the constraint handler be skipped, if no constraints are available? (Default value = True) 3937  :param proptiming: positions in the node solving loop where propagation method of constraint handlers should be executed (Default value = SCIP_PROPTIMING.BEFORELP) 3938  :param presoltiming: timing mask of the constraint handler's presolving method (Default value = SCIP_PRESOLTIMING.MEDIUM) 3943

PY_SCIP_CALL(

SCIPincludeConshdlr

(self.

_scip

, n, d, sepapriority, enfopriority, chckpriority, sepafreq, propfreq, eagerfreq,

3944

maxprerounds, delaysepa, delayprop, needscons, proptiming, presoltiming,

3945

PyConshdlrCopy, PyConsFree, PyConsInit, PyConsExit, PyConsInitpre, PyConsExitpre,

3946

PyConsInitsol, PyConsExitsol, PyConsDelete, PyConsTrans, PyConsInitlp, PyConsSepalp, PyConsSepasol,

3947

PyConsEnfolp, PyConsEnforelax, PyConsEnfops, PyConsCheck, PyConsProp, PyConsPresol, PyConsResprop, PyConsLock,

3948

PyConsActive, PyConsDeactive, PyConsEnable, PyConsDisable, PyConsDelvars, PyConsPrint, PyConsCopy,

3949

PyConsParse, PyConsGetvars, PyConsGetnvars, PyConsGetdivebdchgs, PyConsGetPermSymGraph, PyConsGetSignedPermSymGraph,

3950

<SCIP_CONSHDLRDATA*>conshdlr))

3951

conshdlr.model = <Model>weakref.proxy(self)

3952

conshdlr.name = name

3955  def createCons

(self, Conshdlr conshdlr, name, initial=True, separate=True, enforce=True, check=True, propagate=True,

3956

local=False, modifiable=False, dynamic=False, removable=False, stickingatnode=False):

3957  """Create a constraint of a custom constraint handler 3959  :param Conshdlr conshdlr: constraint handler 3960  :param name: name of constraint 3961  :param initial: (Default value = True) 3962  :param separate: (Default value = True) 3963  :param enforce: (Default value = True) 3964  :param check: (Default value = True) 3965  :param propagate: (Default value = True) 3966  :param local: (Default value = False) 3967  :param modifiable: (Default value = False) 3968  :param dynamic: (Default value = False) 3969  :param removable: (Default value = False) 3970  :param stickingatnode: (Default value = False) 3975

cdef SCIP_CONSHDLR* scip_conshdlr

3978

PY_SCIP_CALL(

SCIPcreateCons

(self.

_scip

, &(constraint.scip_cons), n, scip_conshdlr, <SCIP_CONSDATA*>constraint,

3979

initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode))

3982  def includePresol

(self, Presol presol, name, desc, priority, maxrounds, timing=SCIP_PRESOLTIMING_FAST):

3983  """Include a presolver 3985  :param Presol presol: presolver 3986  :param name: name of presolver 3987  :param desc: description of presolver 3988  :param priority: priority of the presolver (>= 0: before, < 0: after constraint handlers) 3989  :param maxrounds: maximal number of presolving rounds the presolver participates in (-1: no limit) 3990  :param timing: timing mask of presolver (Default value = SCIP_PRESOLTIMING_FAST) 3995

PY_SCIP_CALL(

SCIPincludePresol

(self.

_scip

, n, d, priority, maxrounds, timing, PyPresolCopy, PyPresolFree, PyPresolInit,

3996

PyPresolExit, PyPresolInitpre, PyPresolExitpre, PyPresolExec, <SCIP_PRESOLDATA*>presol))

3997

presol.model = <Model>weakref.proxy(self)

4000  def includeSepa

(self, Sepa sepa, name, desc, priority=0, freq=10, maxbounddist=1.0, usessubscip=False, delay=False):

4001  """Include a separator 4003  :param Sepa sepa: separator 4004  :param name: name of separator 4005  :param desc: description of separator 4006  :param priority: priority of separator (>= 0: before, < 0: after constraint handlers) 4007  :param freq: frequency for calling separator 4008  :param maxbounddist: maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for applying separation 4009  :param usessubscip: does the separator use a secondary SCIP instance? (Default value = False) 4010  :param delay: should separator be delayed, if other separators found cuts? (Default value = False) 4015

PY_SCIP_CALL(

SCIPincludeSepa

(self.

_scip

, n, d, priority, freq, maxbounddist, usessubscip, delay, PySepaCopy, PySepaFree,

4016

PySepaInit, PySepaExit, PySepaInitsol, PySepaExitsol, PySepaExeclp, PySepaExecsol, <SCIP_SEPADATA*>sepa))

4017

sepa.model = <Model>weakref.proxy(self)

4024  :param Reader reader: reader 4025  :param name: name of reader 4026  :param desc: description of reader 4027  :param ext: file extension of reader 4034

PyReaderRead, PyReaderWrite, <SCIP_READERDATA*>reader))

4035

reader.model = <Model>weakref.proxy(self)

4039  def includeProp

(self, Prop prop, name, desc, presolpriority, presolmaxrounds,

4040

proptiming, presoltiming=SCIP_PRESOLTIMING_FAST, priority=1, freq=1, delay=True):

4041  """Include a propagator. 4043  :param Prop prop: propagator 4044  :param name: name of propagator 4045  :param desc: description of propagator 4046  :param presolpriority: presolving priority of the propgator (>= 0: before, < 0: after constraint handlers) 4047  :param presolmaxrounds: maximal number of presolving rounds the propagator participates in (-1: no limit) 4048  :param proptiming: positions in the node solving loop where propagation method of constraint handlers should be executed 4049  :param presoltiming: timing mask of the constraint handler's presolving method (Default value = SCIP_PRESOLTIMING_FAST) 4050  :param priority: priority of the propagator (Default value = 1) 4051  :param freq: frequency for calling propagator (Default value = 1) 4052  :param delay: should propagator be delayed if other propagators have found reductions? (Default value = True) 4058

priority, freq, delay,

4059

proptiming, presolpriority, presolmaxrounds,

4060

presoltiming, PyPropCopy, PyPropFree, PyPropInit, PyPropExit,

4061

PyPropInitpre, PyPropExitpre, PyPropInitsol, PyPropExitsol,

4062

PyPropPresol, PyPropExec, PyPropResProp,

4063

<SCIP_PROPDATA*> prop))

4064

prop.model = <Model>weakref.proxy(self)

4067  def includeHeur

(self, Heur heur, name, desc, dispchar, priority=10000, freq=1, freqofs=0,

4068

maxdepth=-1, timingmask=SCIP_HEURTIMING_BEFORENODE, usessubscip=False):

4069  """Include a primal heuristic. 4071  :param Heur heur: heuristic 4072  :param name: name of heuristic 4073  :param desc: description of heuristic 4074  :param dispchar: display character of heuristic 4075  :param priority: priority of the heuristic (Default value = 10000) 4076  :param freq: frequency for calling heuristic (Default value = 1) 4077  :param freqofs: frequency offset for calling heuristic (Default value = 0) 4078  :param maxdepth: maximal depth level to call heuristic at (Default value = -1) 4079  :param timingmask: positions in the node solving loop where heuristic should be executed (Default value = SCIP_HEURTIMING_BEFORENODE) 4080  :param usessubscip: does the heuristic use a secondary SCIP instance? (Default value = False) 4087

priority, freq, freqofs,

4088

maxdepth, timingmask, usessubscip,

4089

PyHeurCopy, PyHeurFree, PyHeurInit, PyHeurExit,

4090

PyHeurInitsol, PyHeurExitsol, PyHeurExec,

4091

<SCIP_HEURDATA*> heur))

4092

heur.model = <Model>weakref.proxy(self)

4097  """Include a relaxation handler. 4099  :param Relax relax: relaxation handler 4100  :param name: name of relaxation handler 4101  :param desc: description of relaxation handler 4102  :param priority: priority of the relaxation handler (negative: after LP, non-negative: before LP, Default value = 10000) 4103  :param freq: frequency for calling relaxation handler 4108

PY_SCIP_CALL(

SCIPincludeRelax

(self.

_scip

, nam, des, priority, freq, PyRelaxCopy, PyRelaxFree, PyRelaxInit, PyRelaxExit,

4109

PyRelaxInitsol, PyRelaxExitsol, PyRelaxExec, <SCIP_RELAXDATA*> relax))

4110

relax.model = <Model>weakref.proxy(self)

4116  """include a cut selector 4118  :param Cutsel cutsel: cut selector 4119  :param name: name of cut selector 4120  :param desc: description of cut selector 4121  :param priority: priority of the cut selector 4127

priority, PyCutselCopy, PyCutselFree, PyCutselInit, PyCutselExit,

4128

PyCutselInitsol, PyCutselExitsol, PyCutselSelect,

4129

<SCIP_CUTSELDATA*> cutsel))

4130

cutsel.model = <Model>weakref.proxy(self)

4134  """Include a branching rule. 4136  :param Branchrule branchrule: branching rule 4137  :param name: name of branching rule 4138  :param desc: description of branching rule 4139  :param priority: priority of branching rule 4140  :param maxdepth: maximal depth level up to which this branching rule should be used (or -1) 4141  :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) 4147

priority, maxdepth, maxbounddist,

4148

PyBranchruleCopy, PyBranchruleFree, PyBranchruleInit, PyBranchruleExit,

4149

PyBranchruleInitsol, PyBranchruleExitsol, PyBranchruleExeclp, PyBranchruleExecext,

4150

PyBranchruleExecps, <SCIP_BRANCHRULEDATA*> branchrule))

4151

branchrule.model = <Model>weakref.proxy(self)

4152

Py_INCREF(branchrule)

4154  def includeNodesel

(self, Nodesel nodesel, name, desc, stdpriority, memsavepriority):

4155  """Include a node selector. 4157  :param Nodesel nodesel: node selector 4158  :param name: name of node selector 4159  :param desc: description of node selector 4160  :param stdpriority: priority of the node selector in standard mode 4161  :param memsavepriority: priority of the node selector in memory saving mode 4167

stdpriority, memsavepriority,

4168

PyNodeselCopy, PyNodeselFree, PyNodeselInit, PyNodeselExit,

4169

PyNodeselInitsol, PyNodeselExitsol, PyNodeselSelect, PyNodeselComp,

4170

<SCIP_NODESELDATA*> nodesel))

4171

nodesel.model = <Model>weakref.proxy(self)

4174  def includeBenders

(self, Benders benders, name, desc, priority=1, cutlp=True, cutpseudo=True, cutrelax=True,

4176  """Include a Benders' decomposition. 4179  benders -- the Benders decomposition 4181  desc -- the description 4182  priority -- priority of the Benders' decomposition 4183  cutlp -- should Benders' cuts be generated from LP solutions 4184  cutpseudo -- should Benders' cuts be generated from pseudo solutions 4185  cutrelax -- should Benders' cuts be generated from relaxation solutions 4186  shareaux -- should the Benders' decomposition share the auxiliary variables of the highest priority Benders' decomposition 4191

priority, cutlp, cutrelax, cutpseudo, shareaux,

4192

PyBendersCopy, PyBendersFree, PyBendersInit, PyBendersExit, PyBendersInitpre,

4193

PyBendersExitpre, PyBendersInitsol, PyBendersExitsol, PyBendersGetvar,

4194

PyBendersCreatesub, PyBendersPresubsolve, PyBendersSolvesubconvex,

4195

PyBendersSolvesub, PyBendersPostsolve, PyBendersFreesub,

4196

<SCIP_BENDERSDATA*>benders))

4197

cdef SCIP_BENDERS* scip_benders

4199

benders.model = <Model>weakref.proxy(self)

4201

benders._benders = scip_benders

4204  def includeBenderscut

(self, Benders benders, Benderscut benderscut, name, desc, priority=1, islpcut=True):

4205  """ Include a Benders' decomposition cutting method 4208  benders -- the Benders' decomposition that this cutting method is attached to 4209  benderscut --- the Benders' decomposition cutting method 4211  desc -- the description 4212  priority -- priority of the Benders' decomposition 4213  islpcut -- is this cutting method suitable for generating cuts for convex relaxations? 4215

cdef SCIP_BENDERS* _benders

4217

_benders = benders._benders

4222

PyBenderscutCopy, PyBenderscutFree, PyBenderscutInit, PyBenderscutExit,

4223

PyBenderscutInitsol, PyBenderscutExitsol, PyBenderscutExec,

4224

<SCIP_BENDERSCUTDATA*>benderscut))

4226

cdef SCIP_BENDERSCUT* scip_benderscut

4228

benderscut.model = <Model>weakref.proxy(self)

4229

benderscut.benders = benders

4230

benderscut.name = name

4232

Py_INCREF(benderscut)

4236  """gets branching candidates for LP solution branching (fractional variables) along with solution values, 4237  fractionalities, and number of branching candidates; The number of branching candidates does NOT account 4238  for fractional implicit integer variables which should not be used for branching decisions. Fractional 4239  implicit integer variables are stored at the positions *nlpcands to *nlpcands + *nfracimplvars - 1 4240  branching rules should always select the branching candidate among the first npriolpcands of the candidate list 4242  :return tuple (lpcands, lpcandssol, lpcadsfrac, nlpcands, npriolpcands, nfracimplvars) where 4244  lpcands: list of variables of LP branching candidates 4245  lpcandssol: list of LP candidate solution values 4246  lpcandsfrac list of LP candidate fractionalities 4247  nlpcands: number of LP branching candidates 4248  npriolpcands: number of candidates with maximal priority 4249  nfracimplvars: number of fractional implicit integer variables 4254

cdef int npriolpcands

4255

cdef int nfracimplvars

4257

cdef SCIP_VAR** lpcands

4258

cdef SCIP_Real* lpcandssol

4259

cdef SCIP_Real* lpcandsfrac

4262

&nlpcands, &npriolpcands, &nfracimplvars))

4264  return

([Variable.create(lpcands[i])

for

i

in

range(nlpcands)], [lpcandssol[i]

for

i

in

range(nlpcands)],

4265

[lpcandsfrac[i]

for

i

in

range(nlpcands)], nlpcands, npriolpcands, nfracimplvars)

4268  """gets branching candidates for pseudo solution branching (non-fixed variables) 4269  along with the number of candidates. 4271  :return tuple (pseudocands, npseudocands, npriopseudocands) where 4273  pseudocands: list of variables of pseudo branching candidates 4274  npseudocands: number of pseudo branching candidates 4275  npriopseudocands: number of candidates with maximal priority 4278

cdef int npseudocands

4279

cdef int npriopseudocands

4281

cdef SCIP_VAR** pseudocands

4285  return

([Variable.create(pseudocands[i])

for

i

in

range(npseudocands)], npseudocands, npriopseudocands)

4288  """Branch on a non-continuous variable. 4290  :param variable: Variable to branch on 4291  :return: tuple(downchild, eqchild, upchild) of Nodes of the left, middle and right child. Middle child only exists 4292  if branch variable is integer (it is None otherwise) 4295

cdef SCIP_NODE* downchild

4296

cdef SCIP_NODE* eqchild

4297

cdef SCIP_NODE* upchild

4299

PY_SCIP_CALL(

SCIPbranchVar

(self.

_scip

, (<Variable>variable).scip_var, &downchild, &eqchild, &upchild))

4300  return

Node.create(downchild), Node.create(eqchild), Node.create(upchild)

4304  """Branches on variable using a value which separates the domain of the variable. 4306  :param variable: Variable to branch on 4307  :param value: float, value to branch on 4308  :return: tuple(downchild, eqchild, upchild) of Nodes of the left, middle and right child. Middle child only exists 4309  if branch variable is integer (it is None otherwise) 4312

cdef SCIP_NODE* downchild

4313

cdef SCIP_NODE* eqchild

4314

cdef SCIP_NODE* upchild

4316

PY_SCIP_CALL(

SCIPbranchVarVal

(self.

_scip

, (<Variable>variable).scip_var, value, &downchild, &eqchild, &upchild))

4318  return

Node.create(downchild), Node.create(eqchild), Node.create(upchild)

4321  """calculates the node selection priority for moving the given variable's LP value 4322  to the given target value; 4323  this node selection priority can be given to the SCIPcreateChild() call 4325  :param variable: variable on which the branching is applied 4326  :param branchdir: type of branching that was performed 4327  :param targetvalue: new value of the variable in the child node 4328  :return: node selection priority for moving the given variable's LP value to the given target value 4334  """Calculates an estimate for the objective of the best feasible solution 4335  contained in the subtree after applying the given branching; 4336  this estimate can be given to the SCIPcreateChild() call 4338  :param variable: Variable to compute the estimate for 4339  :param targetvalue: new value of the variable in the child node 4340  :return: objective estimate of the best solution in the subtree after applying the given branching 4346  """Create a child node of the focus node. 4348  :param nodeselprio: float, node selection priority of new node 4349  :param estimate: float, estimate for(transformed) objective value of best feasible solution in subtree 4350  :return: Node, the child which was created 4353

cdef SCIP_NODE* child

4355  return

Node.create(child)

4359  """Initiates LP diving 4360  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, 4361  SCIP will undo all changes done and recover the LP it had before startDive 4366  """Quits probing and resets bounds and constraints to the focus node's environment""" 4370  """changes (column) variable's objective value in current dive""" 4374  """changes variable's current lb in current dive""" 4378  """changes variable's current ub in current dive""" 4382  """returns variable's current lb in current dive""" 4386  """returns variable's current ub in current dive""" 4390  """changes row lhs in current dive, change will be undone after diving 4391  ends, for permanent changes use SCIPchgRowLhs() 4396  """changes row rhs in current dive, change will be undone after diving 4397  ends, for permanent changes use SCIPchgRowLhs() 4402  """adds a row to the LP in current dive""" 4406  """solves the LP of the current dive no separation or pricing is applied 4407  no separation or pricing is applied 4408  :param itlim: maximal number of LP iterations to perform (Default value = -1, that is, no limit) 4409  returns two booleans: 4410  lperror -- if an unresolved lp error occured 4411  cutoff -- whether the LP was infeasible or the objective limit was reached 4413

cdef SCIP_Bool lperror

4414

cdef SCIP_Bool cutoff

4417  return

lperror, cutoff

4420  """returns if the current node is already solved and only propagated again.""" 4425  """Initiates probing, making methods SCIPnewProbingNode(), SCIPbacktrackProbing(), SCIPchgVarLbProbing(), 4426  SCIPchgVarUbProbing(), SCIPfixVarProbing(), SCIPpropagateProbing(), SCIPsolveProbingLP(), etc available 4431  """Quits probing and resets bounds and constraints to the focus node's environment""" 4435  """creates a new probing sub node, whose changes can be undone by backtracking to a higher node in the 4436  probing path with a call to backtrackProbing() 4441  """undoes all changes to the problem applied in probing up to the given probing depth 4442  :param probingdepth: probing depth of the node in the probing path that should be reactivated 4447  """returns the current probing depth""" 4451  """changes (column) variable's objective value during probing mode""" 4455  """changes the variable lower bound during probing mode 4457  :param Variable var: variable to change bound of 4458  :param lb: new lower bound (set to None for -infinity) 4465  """changes the variable upper bound during probing mode 4467  :param Variable var: variable to change bound of 4468  :param ub: new upper bound (set to None for +infinity) 4475  """Fixes a variable at the current probing node.""" 4479  """returns whether the objective function has changed during probing mode""" 4483  """returns whether we are in probing mode; probing mode is activated via startProbing() and stopped via endProbing()""" 4487  """solves the LP at the current probing node (cannot be applied at preprocessing stage) 4488  no separation or pricing is applied 4489  :param itlim: maximal number of LP iterations to perform (Default value = -1, that is, no limit) 4490  returns two booleans: 4491  lperror -- if an unresolved lp error occured 4492  cutoff -- whether the LP was infeasible or the objective limit was reached 4494

cdef SCIP_Bool lperror

4495

cdef SCIP_Bool cutoff

4498  return

lperror, cutoff

4501  """applies the cuts in the separation storage to the LP and clears the storage afterwards; 4502  this method can only be applied during probing; the user should resolve the probing LP afterwards 4503  in order to get a new solution 4505  cutoff -- whether an empty domain was created 4507

cdef SCIP_Bool cutoff

4513  """applies domain propagation on the probing sub problem, that was changed after SCIPstartProbing() was called; 4514  the propagated domains of the variables can be accessed with the usual bound accessing calls SCIPvarGetLbLocal() 4515  and SCIPvarGetUbLocal(); the propagation is only valid locally, i.e. the local bounds as well as the changed 4516  bounds due to SCIPchgVarLbProbing(), SCIPchgVarUbProbing(), and SCIPfixVarProbing() are used for propagation 4517  :param maxproprounds: maximal number of propagation rounds (Default value = -1, that is, no limit) 4519  cutoff -- whether the probing node can be cutoff 4520  ndomredsfound -- number of domain reductions found 4522

cdef SCIP_Bool cutoff

4523

cdef SCIP_Longint ndomredsfound

4526  return

cutoff, ndomredsfound

4529  """Interrupt the solving process as soon as possible.""" 4533  """Restarts the solving process as soon as possible.""" 4539  """writes current LP to a file 4540  :param filename: file name (Default value = "LP.lp") 4542

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

4543

locale.setlocale(locale.LC_NUMERIC,

"C"

)

4548

locale.setlocale(locale.LC_NUMERIC,user_locale)

4551  """Create a new primal solution in the transformed space. 4553  :param Heur heur: heuristic that found the solution (Default value = None) 4556

cdef SCIP_HEUR* _heur

4559  if

isinstance(heur, Heur):

4565

solution = Solution.create(self.

_scip

, _sol)

4569  """Create a partial primal solution, initialized to unknown values. 4570  :param Heur heur: heuristic that found the solution (Default value = None) 4573

cdef SCIP_HEUR* _heur

4576  if

isinstance(heur, Heur):

4582

partialsolution = Solution.create(self.

_scip

, _sol)

4583  return

partialsolution

4586  """Create a new primal solution in the original space. 4588  :param Heur heur: heuristic that found the solution (Default value = None) 4591

cdef SCIP_HEUR* _heur

4594  if

isinstance(heur, Heur):

4601

solution = Solution.create(self.

_scip

, _sol)

4605  """Prints the best feasible primal solution.""" 4606

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

4607

locale.setlocale(locale.LC_NUMERIC,

"C"

)

4611

locale.setlocale(locale.LC_NUMERIC,user_locale)

4613  def printSol

(self, Solution solution=None, write_zeros=False):

4614  """Print the given primal solution. 4617  solution -- solution to print 4618  write_zeros -- include variables that are set to zero 4621

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

4622

locale.setlocale(locale.LC_NUMERIC,

"C"

)

4624  if

solution

is None

:

4629

locale.setlocale(locale.LC_NUMERIC,user_locale)

4632  """Write the best feasible primal solution to a file. 4635  filename -- name of the output file 4636  write_zeros -- include variables that are set to zero 4639

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

4640

locale.setlocale(locale.LC_NUMERIC,

"C"

)

4644  with

open(filename,

"w"

)

as

f:

4645

cfile = fdopen(f.fileno(),

"w"

)

4648

locale.setlocale(locale.LC_NUMERIC,user_locale)

4651  """Write the best feasible primal solution for the transformed problem to a file. 4654  filename -- name of the output file 4655  write_zeros -- include variables that are set to zero 4657

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

4658

locale.setlocale(locale.LC_NUMERIC,

"C"

)

4662  with

open(filename,

"w"

)

as

f:

4663

cfile = fdopen(f.fileno(),

"w"

)

4666

locale.setlocale(locale.LC_NUMERIC,user_locale)

4668  def writeSol

(self, Solution solution, filename="origprob.sol", write_zeros=False):

4669  """Write the given primal solution to a file. 4672  solution -- solution to write 4673  filename -- name of the output file 4674  write_zeros -- include variables that are set to zero 4676

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

4677

locale.setlocale(locale.LC_NUMERIC,

"C"

)

4681  with

open(filename,

"w"

)

as

f:

4682

cfile = fdopen(f.fileno(),

"w"

)

4685

locale.setlocale(locale.LC_NUMERIC,user_locale)

4687  def writeTransSol

(self, Solution solution, filename="transprob.sol", write_zeros=False):

4688  """Write the given transformed primal solution to a file. 4691  solution -- transformed solution to write 4692  filename -- name of the output file 4693  write_zeros -- include variables that are set to zero 4695

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

4696

locale.setlocale(locale.LC_NUMERIC,

"C"

)

4700  with

open(filename,

"w"

)

as

f:

4701

cfile = fdopen(f.fileno(),

"w"

)

4704

locale.setlocale(locale.LC_NUMERIC,user_locale)

4709  """Reads a given solution file, problem has to be transformed in advance. 4712  filename -- name of the input file 4714

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

4715

locale.setlocale(locale.LC_NUMERIC,

"C"

)

4720

locale.setlocale(locale.LC_NUMERIC, user_locale)

4723  """Reads a given solution file. 4725  Solution is created but not added to storage/the model. 4726  Use 'addSol' OR 'trySol' to add it. 4729  filename -- name of the input file 4731

cdef SCIP_Bool partial

4732

cdef SCIP_Bool error

4733

cdef SCIP_Bool stored

4734

cdef Solution solution

4736

str_absfile = abspath(filename)

4740

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

4741

locale.setlocale(locale.LC_NUMERIC,

"C"

)

4745

locale.setlocale(locale.LC_NUMERIC, user_locale)

4748  raise

Exception(

"SCIP: reading solution from file "

+ str_absfile +

" failed!"

)

4753  """Set a variable in a solution. 4755  :param Solution solution: solution to be modified 4756  :param Variable var: variable in the solution 4757  :param val: value of the specified variable 4761

_sol = <SCIP_SOL*>solution.sol

4763  assert

_sol != NULL,

"Cannot set value to a freed solution." 4766  def trySol

(self, Solution solution, printreason=True, completely=False, checkbounds=True, checkintegrality=True, checklprows=True, free=True):

4767  """Check given primal solution for feasibility and try to add it to the storage. 4769  :param Solution solution: solution to store 4770  :param printreason: should all reasons of violations be printed? (Default value = True) 4771  :param completely: should all violation be checked? (Default value = False) 4772  :param checkbounds: should the bounds of the variables be checked? (Default value = True) 4773  :param checkintegrality: has integrality to be checked? (Default value = True) 4774  :param checklprows: have current LP rows (both local and global) to be checked? (Default value = True) 4775  :param free: should solution be freed? (Default value = True) 4778

cdef SCIP_Bool stored

4780

PY_SCIP_CALL(

SCIPtrySolFree

(self.

_scip

, &solution.sol, printreason, completely, checkbounds, checkintegrality, checklprows, &stored))

4782

PY_SCIP_CALL(

SCIPtrySol

(self.

_scip

, solution.sol, printreason, completely, checkbounds, checkintegrality, checklprows, &stored))

4785  def checkSol

(self, Solution solution, printreason=True, completely=False, checkbounds=True, checkintegrality=True, checklprows=True, original=False):

4786  """Check given primal solution for feasibility without adding it to the storage. 4788  :param Solution solution: solution to store 4789  :param printreason: should all reasons of violations be printed? (Default value = True) 4790  :param completely: should all violation be checked? (Default value = False) 4791  :param checkbounds: should the bounds of the variables be checked? (Default value = True) 4792  :param checkintegrality: has integrality to be checked? (Default value = True) 4793  :param checklprows: have current LP rows (both local and global) to be checked? (Default value = True) 4794  :param original: must the solution be checked against the original problem (Default value = False) 4797

cdef SCIP_Bool feasible

4801

PY_SCIP_CALL(

SCIPcheckSol

(self.

_scip

, solution.sol, printreason, completely, checkbounds, checkintegrality, checklprows, &feasible))

4804  def addSol

(self, Solution solution, free=True):

4805  """Try to add a solution to the storage. 4807  :param Solution solution: solution to store 4808  :param free: should solution be freed afterwards? (Default value = True) 4811

cdef SCIP_Bool stored

4819  """Free given solution 4821  :param Solution solution: solution to be freed 4827  """gets number of feasible primal solutions stored in the solution storage in case the problem is transformed; 4828  in case the problem stage is SCIP_STAGE_PROBLEM, the number of solution in the original solution candidate 4834  """gets number of feasible primal solutions found so far""" 4838  """gets number of feasible primal solutions respecting the objective limit found so far""" 4842  """gets number of feasible primal solutions found so far, that improved the primal bound at the time they were found""" 4846  """Retrieve list of all feasible primal solutions stored in the solution storage.""" 4847

cdef SCIP_SOL** _sols

4853  for

i

in

range(nsols):

4854

sols.append(Solution.create(self.

_scip

, _sols[i]))

4859  """Retrieve currently best known feasible primal solution.""" 4864  """Retrieve the objective value of the solution. 4866  :param Solution sol: solution 4867  :param original: objective value in original space (Default value = True) 4871

sol = Solution.create(self.

_scip

, NULL)

4873

sol._checkStage(

"getSolObjVal"

)

4883  """Get clock time, when this solution was found. 4885  :param Solution sol: solution 4891  """Retrieve the objective value of value of best solution. 4893  :param original: objective value in original space (Default value = True) 4897  if

self.

getStage

() != SCIP_STAGE_SOLVING:

4898  raise

Warning(

"Without a solution, method can only be called in stage SOLVING."

)

4903

min_stage_requirement = SCIP_STAGE_PROBLEM

4905

min_stage_requirement = SCIP_STAGE_TRANSFORMING

4907  if not

self.

getStage

() >= min_stage_requirement:

4908  raise

Warning(

"method cannot be called in stage %i."

% self.

getStage

)

4913  """Retrieve value of given variable or expression in the given solution or in 4914  the LP/pseudo solution if sol == None 4916  :param Solution sol: solution 4917  :param Expr expr: polynomial expression to query the value of 4919  Note: a variable is also an expression 4922  if

sol ==

None and

isinstance(expr, Variable):

4923

var = <Variable> expr

4926

sol = Solution.create(self.

_scip

, NULL)

4930  """Retrieve the value of the given variable or expression in the best known solution. 4931  Can only be called after solving is completed. 4933  :param Expr expr: polynomial expression to query the value of 4935  Note: a variable is also an expression 4937

stage_check =

SCIPgetStage

(self.

_scip

)

not in

[SCIP_STAGE_INIT, SCIP_STAGE_FREE]

4940  raise

Warning(

"Method cannot be called in stage "

, self.

getStage

())

4946  Returns whether a primal ray is stored that proves unboundedness of the LP relaxation 4952  Gets value of given variable in primal ray causing unboundedness of the LP relaxation 4960  Gets primal ray causing unboundedness of the LP relaxation 4968  for

i

in

range(_nvars):

4974  """Retrieve the best primal bound.""" 4978  """Retrieve the best dual bound.""" 4982  """Retrieve the best root dual bound.""" 4986  """Write the name of the variable to the std out. 4988  :param Variable var: variable 4991

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

4992

locale.setlocale(locale.LC_NUMERIC,

"C"

)

4996

locale.setlocale(locale.LC_NUMERIC,user_locale)

4999  """Retrieve current SCIP stage""" 5003  """Returns name of current stage as string""" 5006  return

StageNames[self.

getStage

()]

5008  def

_getStageNames(self):

5009  """Gets names of stages""" 5010  for

name

in

dir(PY_SCIP_STAGE):

5011

attr = getattr(PY_SCIP_STAGE, name)

5012  if

isinstance(attr, int):

5013

StageNames[attr] = name

5016  """Retrieve solution status.""" 5018  if

stat == SCIP_STATUS_OPTIMAL:

5020  elif

stat == SCIP_STATUS_TIMELIMIT:

5022  elif

stat == SCIP_STATUS_INFEASIBLE:

5024  elif

stat == SCIP_STATUS_UNBOUNDED:

5026  elif

stat == SCIP_STATUS_USERINTERRUPT:

5027  return "userinterrupt" 5028  elif

stat == SCIP_STATUS_INFORUNBD:

5030  elif

stat == SCIP_STATUS_NODELIMIT:

5032  elif

stat == SCIP_STATUS_TOTALNODELIMIT:

5033  return "totalnodelimit" 5034  elif

stat == SCIP_STATUS_STALLNODELIMIT:

5035  return "stallnodelimit" 5036  elif

stat == SCIP_STATUS_GAPLIMIT:

5038  elif

stat == SCIP_STATUS_MEMLIMIT:

5040  elif

stat == SCIP_STATUS_SOLLIMIT:

5042  elif

stat == SCIP_STATUS_BESTSOLLIMIT:

5043  return "bestsollimit" 5044  elif

stat == SCIP_STATUS_RESTARTLIMIT:

5045  return "restartlimit" 5046  elif

stat == SCIP_STATUS_PRIMALLIMIT:

5047  return "primallimit" 5048  elif

stat == SCIP_STATUS_DUALLIMIT:

5054  """Retrieve objective sense.""" 5056  if

sense == SCIP_OBJSENSE_MAXIMIZE:

5058  elif

sense == SCIP_OBJSENSE_MINIMIZE:

5064  """catches a global (not variable or row dependent) event""" 5065

cdef SCIP_EVENTHDLR* _eventhdlr

5066  if

isinstance(eventhdlr, Eventhdlr):

5070  raise

Warning(

"event handler not found"

)

5076  """drops a global event (stops to track event)""" 5077

cdef SCIP_EVENTHDLR* _eventhdlr

5078  if

isinstance(eventhdlr, Eventhdlr):

5082  raise

Warning(

"event handler not found"

)

5088  """catches an objective value or domain change event on the given transformed variable""" 5089

cdef SCIP_EVENTHDLR* _eventhdlr

5090  if

isinstance(eventhdlr, Eventhdlr):

5094  raise

Warning(

"event handler not found"

)

5098  """drops an objective value or domain change event (stops to track event) on the given transformed variable""" 5099

cdef SCIP_EVENTHDLR* _eventhdlr

5100  if

isinstance(eventhdlr, Eventhdlr):

5104  raise

Warning(

"event handler not found"

)

5108  """catches a row coefficient, constant, or side change event on the given row""" 5109

cdef SCIP_EVENTHDLR* _eventhdlr

5110  if

isinstance(eventhdlr, Eventhdlr):

5114  raise

Warning(

"event handler not found"

)

5118  """drops a row coefficient, constant, or side change event (stops to track event) on the given row""" 5119

cdef SCIP_EVENTHDLR* _eventhdlr

5120  if

isinstance(eventhdlr, Eventhdlr):

5124  raise

Warning(

"event handler not found"

)

5130  """Print statistics.""" 5131

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

5132

locale.setlocale(locale.LC_NUMERIC,

"C"

)

5136

locale.setlocale(locale.LC_NUMERIC,user_locale)

5139  """Write statistics to a file. 5142  filename -- name of the output file 5144

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

5145

locale.setlocale(locale.LC_NUMERIC,

"C"

)

5149  with

open(filename,

"w"

)

as

f:

5150

cfile = fdopen(f.fileno(),

"w"

)

5153

locale.setlocale(locale.LC_NUMERIC,user_locale)

5157  Given a .stats file of a solved model, reads it and returns an instance of the Statistics class 5158  holding some statistics. 5161  filename -- name of the input file 5164

file = open(filename)

5165

data = file.readlines()

5167  assert "problem is solved" in

data[0],

"readStatistics can only be called if the problem was solved" 5168

available_stats = [

"Total Time"

,

"solving"

,

"presolving"

,

"reading"

,

"copying"

,

5169  "Problem name"

,

"Variables"

,

"Constraints"

,

"number of runs"

,

5170  "nodes"

,

"Solutions found"

,

"First Solution"

,

"Primal Bound"

,

5171  "Dual Bound"

,

"Gap"

,

"primal-dual"

]

5174  for

i, line

in

enumerate(data):

5175

split_line = line.split(

":"

)

5176

split_line[1] = split_line[1][:-1]

5177

stat_name = split_line[0].strip()

5179  if

seen_cons == 2

and

stat_name ==

"Constraints"

:

5182  if

stat_name

in

available_stats:

5183

cur_stat = split_line[0].strip()

5184

relevant_value = split_line[1].strip()

5186  if

stat_name ==

"Variables"

:

5187

relevant_value = relevant_value[:-1]

5189

split_var = relevant_value.split(

"("

)

5190

var_stats[

"total"

] = int(split_var[0])

5191

split_var = split_var[1].split(

","

)

5193  for

var_type

in

split_var:

5194

split_result = var_type.strip().split(

" "

)

5195

var_stats[split_result[1]] = int(split_result[0])

5197  if "Original" in

data[i-2]:

5198

result[

"Variables"

] = var_stats

5200

result[

"Presolved Variables"

] = var_stats

5204  if

stat_name ==

"Constraints"

:

5207

split_con = relevant_value.split(

","

)

5208  for

con_type

in

split_con:

5209

split_result = con_type.strip().split(

" "

)

5210

con_stats[split_result[1]] = int(split_result[0])

5212  if "Original" in

data[i-3]:

5213

result[

"Constraints"

] = con_stats

5215

result[

"Presolved Constraints"

] = con_stats

5218

relevant_value = relevant_value.split(

" "

)[0]

5219  if

stat_name ==

"Problem name"

:

5220  if "Original" in

data[i-1]:

5221

result[

"Problem name"

] = relevant_value

5223

result[

"Presolved Problem name"

] = relevant_value

5226  if

stat_name ==

"Gap"

:

5227

result[

"Gap (%)"

] = float(relevant_value[:-1])

5230  if

_is_number(relevant_value):

5231

result[cur_stat] = float(relevant_value)

5233

result[cur_stat] = relevant_value

5236

treated_keys = {

"Total Time"

:

"total_time"

,

"solving"

:

"solving_time"

,

"presolving"

:

"presolving_time"

,

"reading"

:

"reading_time"

,

"copying"

:

"copying_time"

,

5237  "Problem name"

:

"problem_name"

,

"Presolved Problem name"

:

"presolved_problem_name"

,

"Variables"

:

"_variables"

,

5238  "Presolved Variables"

:

"_presolved_variables"

,

"Constraints"

:

"_constraints"

,

"Presolved Constraints"

:

"_presolved_constraints"

,

5239  "number of runs"

:

"n_runs"

,

"nodes"

:

"n_nodes"

,

"Solutions found"

:

"n_solutions_found"

,

"First Solution"

:

"first_solution"

,

5240  "Primal Bound"

:

"primal_bound"

,

"Dual Bound"

:

"dual_bound"

,

"Gap (%)"

:

"gap"

,

"primal-dual"

:

"primal_dual_integral"

}

5241

treated_result = dict((treated_keys[key], value)

for

(key, value)

in

result.items())

5247  """gets total number of LPs solved so far""" 5255  :param quiet: hide output? (Default value = True) 5263  """Send output to python instead of terminal.""" 5265

cdef SCIP_MESSAGEHDLR *myMessageHandler

5267

PY_SCIP_CALL(SCIPmessagehdlrCreate(&myMessageHandler,

False

, NULL,

False

, relayMessage, relayMessage, relayMessage, NULL, NULL))

5269

SCIPmessageSetErrorPrinting(relayErrorMessage, NULL)

5272  """sets the log file name for the currently installed message handler 5273  :param path: name of log file, or None (no log) 5284  """Set a boolean-valued parameter. 5286  :param name: name of parameter 5287  :param value: value of parameter 5294  """Set an int-valued parameter. 5296  :param name: name of parameter 5297  :param value: value of parameter 5304  """Set a long-valued parameter. 5306  :param name: name of parameter 5307  :param value: value of parameter 5314  """Set a real-valued parameter. 5316  :param name: name of parameter 5317  :param value: value of parameter 5324  """Set a char-valued parameter. 5326  :param name: name of parameter 5327  :param value: value of parameter 5334  """Set a string-valued parameter. 5336  :param name: name of parameter 5337  :param value: value of parameter 5345  """Set a parameter with value in int, bool, real, long, char or str. 5347  :param name: name of parameter 5348  :param value: value of parameter 5350

cdef SCIP_PARAM* param

5356  raise

KeyError(

"Not a valid parameter name"

)

5358

paramtype = SCIPparamGetType(param)

5360  if

paramtype == SCIP_PARAMTYPE_BOOL:

5362  elif

paramtype == SCIP_PARAMTYPE_INT:

5364  elif

paramtype == SCIP_PARAMTYPE_LONGINT:

5366  elif

paramtype == SCIP_PARAMTYPE_REAL:

5368  elif

paramtype == SCIP_PARAMTYPE_CHAR:

5370  elif

paramtype == SCIP_PARAMTYPE_STRING:

5376  """Get the value of a parameter of type 5377  int, bool, real, long, char or str. 5379  :param name: name of parameter 5381

cdef SCIP_PARAM* param

5387  raise

KeyError(

"Not a valid parameter name"

)

5389

paramtype = SCIPparamGetType(param)

5391  if

paramtype == SCIP_PARAMTYPE_BOOL:

5392  return

SCIPparamGetBool(param)

5393  elif

paramtype == SCIP_PARAMTYPE_INT:

5394  return

SCIPparamGetInt(param)

5395  elif

paramtype == SCIP_PARAMTYPE_LONGINT:

5396  return

SCIPparamGetLongint(param)

5397  elif

paramtype == SCIP_PARAMTYPE_REAL:

5398  return

SCIPparamGetReal(param)

5399  elif

paramtype == SCIP_PARAMTYPE_CHAR:

5400  return

chr(SCIPparamGetChar(param))

5401  elif

paramtype == SCIP_PARAMTYPE_STRING:

5402  return

SCIPparamGetString(param).decode(

'utf-8'

)

5405  """Gets the values of all parameters as a dict mapping parameter names 5407

cdef SCIP_PARAM** params

5412

name = SCIPparamGetName(params[i]).decode(

'utf-8'

)

5413

result[name] = self.

getParam

(name)

5417  """Sets multiple parameters at once. 5419  :param params: dict mapping parameter names to their values. 5421  for

name, value

in

params.items():

5425  """Read an external parameter file. 5427  :param file: file to be read 5432

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

5433

locale.setlocale(locale.LC_NUMERIC,

"C"

)

5437

locale.setlocale(locale.LC_NUMERIC, user_locale)

5439  def writeParams

(self, filename='param.set', comments=True, onlychanged=True, verbose=True):

5440  """Write parameter settings to an external file. 5442  :param filename: file to be written (Default value = 'param.set') 5443  :param comments: write parameter descriptions as comments? (Default value = True) 5444  :param onlychanged: write only modified parameters (Default value = True) 5445  :param verbose: indicates whether a success message should be printed 5447

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

5448

locale.setlocale(locale.LC_NUMERIC,

"C"

)

5450

str_absfile = abspath(filename)

5455

print(

'wrote parameter settings to file '

+ str_absfile)

5457

locale.setlocale(locale.LC_NUMERIC,user_locale)

5460  """Reset parameter setting to its default value 5462  :param name: parameter to reset 5469  """Reset parameter settings to their default values""" 5473  """Set emphasis settings 5475  :param paraemphasis: emphasis to set 5476  :param quiet: hide output? (Default value = True) 5482  """Read a problem instance from an external file. 5484  :param filename: problem file name 5485  :param extension: specify file extension/type (Default value = None) 5488

user_locale = locale.getlocale(category=locale.LC_NUMERIC)

5489

locale.setlocale(locale.LC_NUMERIC,

"C"

)

5492  if

extension

is None

:

5498

locale.setlocale(locale.LC_NUMERIC, user_locale)

5503  """Counts the number of feasible points of problem.""" 5507  """Get number of currently available readers.""" 5511  """Get number of feasible solution.""" 5512

cdef SCIP_Bool valid

5513

cdef SCIP_Longint nsols

5517

print(

'total number of solutions found is not valid!'

)

5521  """Sets SCIP parameters such that a valid counting process is possible.""" 5525  """Frees all solution process data and prepares for reoptimization""" 5529  """Establish the objective function as a linear expression. 5531  :param coeffs: the coefficients 5532  :param sense: the objective sense (Default value = 'minimize') 5536

cdef SCIP_OBJSENSE objsense

5538  if

sense ==

"minimize"

:

5539

objsense = SCIP_OBJSENSE_MINIMIZE

5540  elif

sense ==

"maximize"

:

5541

objsense = SCIP_OBJSENSE_MAXIMIZE

5543  raise

Warning(

"unrecognized optimization sense: %s"

% sense)

5545  assert

isinstance(coeffs, Expr),

"given coefficients are not Expr but %s"

% coeffs.__class__.__name__

5547  if

coeffs.degree() > 1:

5548  raise

ValueError(

"Nonlinear objective functions are not supported!"

)

5549  if

coeffs[CONST] != 0.0:

5550  raise

ValueError(

"Constant offsets in objective are not supported!"

)

5552

cdef SCIP_VAR** _vars

5556

_coeffs = <SCIP_Real*> malloc(_nvars * sizeof(SCIP_Real))

5558  for

i

in

range(_nvars):

5561  for

term, coef

in

coeffs.terms.items():

5564  assert

len(term) == 1

5565

var = <Variable>term[0]

5566  for

i

in

range(_nvars):

5567  if

_vars[i] == var.scip_var:

5575  """Sets the branch priority of the variable. 5576  Variables with higher branch priority are always preferred to variables with lower priority in selection of branching variable. 5578  :param Variable var: variable to change priority of 5579  :param priority: the new priority of the variable (the default branching priority is 0) 5581  assert

isinstance(var, Variable),

"The given variable is not a pyvar, but %s"

% var.__class__.__name__

5585  """Start strong branching. Needs to be called before any strong branching. Must also later end strong branching. 5586  TODO: Propagation option has currently been disabled via Python. 5587  If propagation is enabled then strong branching is not done on the LP, but on additionally created nodes (has some overhead)""" 5592  """End strong branching. Needs to be called if startStrongBranching was called previously. 5593  Between these calls the user can access all strong branching functionality. """ 5598  """Get the results of the last strong branching call on this variable (potentially was called 5601  down - The dual bound of the LP after branching down on the variable 5602  up - The dual bound of the LP after branchign up on the variable 5603  downvalid - Whether down stores a valid dual bound or is NULL 5604  upvalid - Whether up stores a valid dual bound or is NULL 5605  solval - The solution value of the variable at the last strong branching call 5606  lpobjval - The LP objective value at the time of the last strong branching call 5608  :param Variable var: variable to get the previous strong branching information from 5613

cdef SCIP_Real solval

5614

cdef SCIP_Real lpobjval

5615

cdef SCIP_Bool downvalid

5616

cdef SCIP_Bool upvalid

5620  return

down, up, downvalid, upvalid, solval, lpobjval

5623  """Get the node number from the last time strong branching was called on the variable 5625  :param Variable var: variable to get the previous strong branching node from 5628

cdef SCIP_Longint node_num

5634  """ Strong branches and gets information on column variable. 5636  :param Variable var: Variable to get strong branching information on 5637  :param itlim: LP iteration limit for total strong branching calls 5638  :param idempotent: Should SCIP's state remain the same after the call? 5639  :param integral: Boolean on whether the variable is currently integer. 5644

cdef SCIP_Bool downvalid

5645

cdef SCIP_Bool upvalid

5646

cdef SCIP_Bool downinf

5647

cdef SCIP_Bool upinf

5648

cdef SCIP_Bool downconflict

5649

cdef SCIP_Bool upconflict

5650

cdef SCIP_Bool lperror

5654

&upvalid, &downinf, &upinf, &downconflict, &upconflict, &lperror))

5657

&upvalid, &downinf, &upinf, &downconflict, &upconflict, &lperror))

5659  return

down, up, downvalid, upvalid, downinf, upinf, downconflict, upconflict, lperror

5662  """Updates the pseudo costs of the given variable and the global pseudo costs after a change of valdelta 5663  in the variable's solution value and resulting change of objdelta in the LP's objective value. 5664  Update is ignored if objdelts is infinite. Weight is in range (0, 1], and affects how it updates 5665  the global weighted sum. 5667  :param Variable var: Variable whos pseudo cost will be updated 5668  :param valdelta: The change in variable value (e.g. the fractional amount removed or added by branching) 5669  :param objdelta: The change in objective value of the LP after valdelta change of the variable 5670  :param weight: the weight in range (0,1] of how the update affects the stored weighted sum. 5676  """Calculates the branching score out of the gain predictions for a branching with 5677  arbitrary many children. 5679  :param Variable var: variable to calculate the score for 5680  :param gains: list of gains for each child. 5683  assert

isinstance(gains, list)

5684

nchildren = len(gains)

5686

cdef int _nchildren = nchildren

5687

_gains = <SCIP_Real*> malloc(_nchildren * sizeof(SCIP_Real))

5688  for

i

in

range(_nchildren):

5689

_gains[i] = gains[i]

5698  """Get an estimation of the final tree size """ 5699  return

SCIPgetTreesizeEstimation(self.

_scip

)

5703

static_only=False, suppress_warnings=False):

5704  """This function generates the bipartite graph representation of an LP, which was first used in 5705  the following paper: 5706  @inproceedings{conf/nips/GasseCFCL19, 5707  title={Exact Combinatorial Optimization with Graph Convolutional Neural Networks}, 5708  author={Gasse, Maxime and Chételat, Didier and Ferroni, Nicola and Charlin, Laurent and Lodi, Andrea}, 5709  booktitle={Advances in Neural Information Processing Systems 32}, 5712  The exact features have been modified compared to the original implementation. 5713  This function is used mainly in the machine learning community for MIP. 5714  A user can only call it during the solving process, when there is an LP object. This means calling it 5715  from some user defined plugin on the Python side. 5716  An example plugin is a branching rule or an event handler, which is exclusively created to call this function. 5717  The user must then make certain to return the appropriate SCIP_RESULT (e.g. DIDNOTRUN) 5719  :param prev_col_features: The list of column features previously returned by this function 5720  :param prev_edge_features: The list of edge features previously returned by this function 5721  :param prev_row_features: The list of row features previously returned by this function 5722  :param static_only: Whether exclusively static features should be generated 5723  :param suppress_warnings: Whether warnings should be suppressed 5726

cdef SCIP* scip = self.

_scip 5727

cdef int i, j, k, col_i

5728

cdef SCIP_VARTYPE vtype

5729

cdef SCIP_Real sim, prod

5733  raise

Warning(

"This functionality can only been called in SCIP_STAGE SOLVING. The row and column" 5734  "information is then accessible"

)

5742

col_feature_map = {

"continuous"

: 0,

"binary"

: 1,

"integer"

: 2,

"implicit_integer"

: 3,

"obj_coef"

: 4}

5745

col_feature_map = {

"continuous"

: 0,

"binary"

: 1,

"integer"

: 2,

"implicit_integer"

: 3,

"obj_coef"

: 4,

5746  "has_lb"

: 5,

"has_ub"

: 6,

"sol_at_lb"

: 7,

"sol_at_ub"

: 8,

"sol_val"

: 9,

"sol_frac"

: 10,

5747  "red_cost"

: 11,

"basis_lower"

: 12,

"basis_basic"

: 13,

"basis_upper"

: 14,

5748  "basis_zero"

: 15,

"best_incumbent_val"

: 16,

"avg_incumbent_val"

: 17,

"age"

: 18}

5750  if

prev_col_features

is None

:

5751

col_features = [[0

for

_

in

range(n_col_features)]

for

_

in

range(ncols)]

5753  assert

len(prev_col_features) > 0,

"Previous column features is empty" 5754

col_features = prev_col_features

5755  if

len(prev_col_features) != ncols:

5756  if not

suppress_warnings:

5757  raise

Warning(f

"The number of columns has changed. Previous column data being ignored"

)

5759

col_features = [[0

for

_

in

range(n_col_features)]

for

_

in

range(ncols)]

5760

prev_col_features =

None 5761  if

len(prev_col_features[0]) != n_col_features:

5762  raise

Warning(f

"Dimension mismatch in provided previous features and new features:" 5763

f

"{len(prev_col_features[0])} != {n_col_features}"

)

5767

cdef SCIP_Real lb, ub, solval

5768

cdef SCIP_BASESTAT basis_status

5769  for

i

in

range(ncols):

5778  if

prev_col_features

is None

:

5781  if

vtype == SCIP_VARTYPE_BINARY:

5782

col_features[col_i][col_feature_map[

"binary"

]] = 1

5783  elif

vtype == SCIP_VARTYPE_INTEGER:

5784

col_features[col_i][col_feature_map[

"integer"

]] = 1

5785  elif

vtype == SCIP_VARTYPE_CONTINUOUS:

5786

col_features[col_i][col_feature_map[

"continuous"

]] = 1

5787  elif

vtype == SCIP_VARTYPE_IMPLINT:

5788

col_features[col_i][col_feature_map[

"implicit_integer"

]] = 1

5790

col_features[col_i][col_feature_map[

"obj_coef"

]] =

SCIPcolGetObj

(cols[i])

5796

col_features[col_i][col_feature_map[

"has_lb"

]] = 1

5800

col_features[col_i][col_feature_map[

"has_ub"

]] = 1

5804  if

basis_status == SCIP_BASESTAT_LOWER:

5805

col_features[col_i][col_feature_map[

"basis_lower"

]] = 1

5806  elif

basis_status == SCIP_BASESTAT_BASIC:

5807

col_features[col_i][col_feature_map[

"basis_basic"

]] = 1

5808  elif

basis_status == SCIP_BASESTAT_UPPER:

5809

col_features[col_i][col_feature_map[

"basis_upper"

]] = 1

5810  elif

basis_status == SCIP_BASESTAT_ZERO:

5811

col_features[col_i][col_feature_map[

"basis_zero"

]] = 1

5814

col_features[col_i][col_feature_map[

"red_cost"

]] =

SCIPgetColRedcost

(scip, cols[i])

5817

col_features[col_i][col_feature_map[

"age"

]] =

SCIPcolGetAge

(cols[i])

5820

col_features[col_i][col_feature_map[

"sol_val"

]] = solval

5821

col_features[col_i][col_feature_map[

"sol_frac"

]] =

SCIPfeasFrac

(scip, solval)

5822

col_features[col_i][col_feature_map[

"sol_at_lb"

]] = int(

SCIPisEQ

(scip, solval, lb))

5823

col_features[col_i][col_feature_map[

"sol_at_ub"

]] = int(

SCIPisEQ

(scip, solval, ub))

5827

col_features[col_i][col_feature_map[

"best_incumbent_val"

]] =

None 5828

col_features[col_i][col_feature_map[

"avg_incumbent_val"

]] =

None 5830

col_features[col_i][col_feature_map[

"best_incumbent_val"

]] =

SCIPgetSolVal

(scip, sol, var)

5831

col_features[col_i][col_feature_map[

"avg_incumbent_val"

]] =

SCIPvarGetAvgSol

(var)

5839

row_feature_map = {

"has_lhs"

: 0,

"has_rhs"

: 1,

"n_non_zeros"

: 2,

"obj_cosine"

: 3,

"bias"

: 4,

"norm"

: 5}

5842

row_feature_map = {

"has_lhs"

: 0,

"has_rhs"

: 1,

"n_non_zeros"

: 2,

"obj_cosine"

: 3,

"bias"

: 4,

"norm"

: 5,

5843  "sol_at_lhs"

: 6,

"sol_at_rhs"

: 7,

"dual_sol"

: 8,

"age"

: 9,

5844  "basis_lower"

: 10,

"basis_basic"

: 11,

"basis_upper"

: 12,

"basis_zero"

: 13}

5846  if

prev_row_features

is None

:

5847

row_features = [[0

for

_

in

range(n_row_features)]

for

_

in

range(nrows)]

5849  assert

len(prev_row_features) > 0,

"Previous row features is empty" 5850

row_features = prev_row_features

5851  if

len(prev_row_features) != nrows:

5852  if not

suppress_warnings:

5853  raise

Warning(f

"The number of rows has changed. Previous row data being ignored"

)

5855

row_features = [[0

for

_

in

range(n_row_features)]

for

_

in

range(nrows)]

5856

prev_row_features =

None 5857  if

len(prev_row_features[0]) != n_row_features:

5858  raise

Warning(f

"Dimension mismatch in provided previous features and new features:" 5859

f

"{len(prev_row_features[0])} != {n_row_features}"

)

5862

cdef SCIP_Real lhs, rhs, cst

5863  for

i

in

range(nrows):

5871  if

prev_row_features

is None

:

5874

nnzrs += row_features[i][row_feature_map[

"n_non_zeros"

]]

5878

row_features[i][row_feature_map[

"has_lhs"

]] = 1

5882

row_features[i][row_feature_map[

"has_rhs"

]] = 1

5885

row_features[i][row_feature_map[

"bias"

]] = cst

5891

row_features[i][row_feature_map[

"norm"

]] =

SCIProwGetNorm

(rows[i])

5900  if

basis_status == SCIP_BASESTAT_LOWER:

5901

row_features[i][row_feature_map[

"basis_lower"

]] = 1

5902  elif

basis_status == SCIP_BASESTAT_BASIC:

5903

row_features[i][row_feature_map[

"basis_basic"

]] = 1

5904  elif

basis_status == SCIP_BASESTAT_UPPER:

5905

row_features[i][row_feature_map[

"basis_upper"

]] = 1

5906  elif

basis_status == SCIP_BASESTAT_ZERO:

5907

row_features[i][row_feature_map[

"basis_zero"

]] = 1

5910

row_features[i][row_feature_map[

"age"

]] =

SCIProwGetAge

(rows[i])

5913

row_features[i][row_feature_map[

"sol_at_lhs"

]] = int(

SCIPisEQ

(scip, activity, lhs))

5914

row_features[i][row_feature_map[

"sol_at_rhs"

]] = int(

SCIPisEQ

(scip, activity, rhs))

5917

cdef SCIP_COL** row_cols

5918

cdef SCIP_Real * row_vals

5920

edge_feature_map = {

"col_idx"

: 0,

"row_idx"

: 1,

"coef"

: 2}

5921  if

prev_edge_features

is None

:

5922

edge_features = [[0

for

_

in

range(n_edge_features)]

for

_

in

range(nnzrs)]

5924  for

i

in

range(nrows):

5928  for

k

in

range(row_features[i][row_feature_map[

"n_non_zeros"

]]):

5929

edge_features[j][edge_feature_map[

"col_idx"

]] =

SCIPcolGetLPPos

(row_cols[k])

5930

edge_features[j][edge_feature_map[

"row_idx"

]] = i

5931

edge_features[j][edge_feature_map[

"coef"

]] = row_vals[k]

5934  assert

len(prev_edge_features) > 0,

"Previous edge features is empty" 5935

edge_features = prev_edge_features

5936  if

len(prev_edge_features) != nnzrs:

5937  if not

suppress_warnings:

5938  raise

Warning(f

"The number of coefficients in the LP has changed. Previous edge data being ignored"

)

5940

edge_features = [[0

for

_

in

range(3)]

for

_

in

range(nnzrs)]

5941

prev_edge_features =

None 5942  if

len(prev_edge_features[0]) != 3:

5943  raise

Warning(f

"Dimension mismatch in provided previous features and new features:" 5944

f

"{len(prev_edge_features[0])} != 3"

)

5947  return

(col_features, edge_features, row_features,

5948

{

"col"

: col_feature_map,

"edge"

: edge_feature_map,

"row"

: row_feature_map})

5956  Total time since model was created 5958  Time spent solving the problem 5959  presolving_time: float 5960  Time spent on presolving 5962  Time spent on reading 5964  Time spent on copying 5967  presolved_problem_name: str 5968  Name of presolved problem 5970  The number of nodes explored in the branch-and-bound tree 5971  n_solutions_found: int 5972  number of found solutions 5973  first_solution: float 5974  objective value of first found solution 5976  The best primal bound found 5978  The best dual bound found 5980  The gap between the primal and dual bounds 5981  primal_dual_integral: float 5982  The primal-dual integral 5984  number of variables in the model 5986  number of binary variables in the model 5988  number of integer variables in the model 5989  n_implicit_integer_vars: int 5990  number of implicit integer variables in the model 5991  n_continuous_vars: int 5992  number of continuous variables in the model 5993  n_presolved_vars: int 5994  number of variables in the presolved model 5995  n_presolved_continuous_vars: int 5996  number of continuous variables in the presolved model 5997  n_presolved_binary_vars: int 5998  number of binary variables in the presolved model 5999  n_presolved_integer_vars: int 6000  number of integer variables in the presolved model 6001  n_presolved_implicit_integer_vars: int 6002  number of implicit integer variables in the presolved model 6004  number of maximal constraints in the model 6006  number of initial constraints in the presolved model 6007  n_presolved_maximal_cons: int 6008  number of maximal constraints in the presolved model 6009  n_presolved_conss: int 6010  number of initial constraints in the model 6015

presolving_time: float

6019

presolved_problem_name: str

6021

_presolved_variables: dict

6023

_presolved_constraints: dict

6026

n_solutions_found: int

6027

first_solution: float

6031

primal_dual_integral: float

6037  return

self._variables[

"total"

]

6041  return

self._variables[

"binary"

]

6045  return

self._variables[

"integer"

]

6049  return

self._variables[

"implicit"

]

6053  return

self._variables[

"continuous"

]

6057  return

self._presolved_variables[

"total"

]

6061  return

self._presolved_variables[

"binary"

]

6065  return

self._presolved_variables[

"integer"

]

6069  return

self._presolved_variables[

"implicit"

]

6073  return

self._presolved_variables[

"continuous"

]

6077  return

self._constraints[

"initial"

]

6081  return

self._constraints[

"maximal"

]

6085  return

self._presolved_constraints[

"initial"

]

6089  return

self._presolved_constraints[

"maximal"

]

6093  return

BMSgetMemoryUsed() == 0

6096

BMScheckEmptyMemory()


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4