From dc6e32502da5c6fb4283d525f2044402ec11b77c Mon Sep 17 00:00:00 2001 From: Joao-Dionisio Date: Fri, 24 Jan 2025 12:45:36 +0100 Subject: [PATCH 01/12] add missing type --- src/pyscipopt/scip.pxi | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi index f1eea0370..36e3a8979 100644 --- a/src/pyscipopt/scip.pxi +++ b/src/pyscipopt/scip.pxi @@ -4342,7 +4342,11 @@ cdef class Model: cdef SCIP_EXPR** monomials cdef int* idxs cdef SCIP_CONS* scip_cons - + cdef int i + cdef int idx + cdef int j + cdef SCIP_Real coef + terms = cons.expr.terms # collect variables From 4fb004d306356f74ce3331fe09970ef21aec4c68 Mon Sep 17 00:00:00 2001 From: Joao-Dionisio Date: Fri, 24 Jan 2025 12:41:35 +0100 Subject: [PATCH 02/12] Typed loop variables --- CHANGELOG.md | 1 + src/pyscipopt/benders.pxi | 1 + src/pyscipopt/conshdlr.pxi | 16 +++++++ src/pyscipopt/cutsel.pxi | 1 + src/pyscipopt/lp.pxi | 24 ++++++++++- src/pyscipopt/reader.pxi | 1 + src/pyscipopt/scip.pxi | 87 ++++++++++++++++++++++++++++++++------ tests/test_event.py | 6 +-- 8 files changed, 121 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72dd6bf63..9b7155cc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased ### Added +- Added cdef to loop variables for slight speedup - Added wrappers for setting and getting heuristic timing - Added transformed option to getVarDict, updated test - Added categorical data example diff --git a/src/pyscipopt/benders.pxi b/src/pyscipopt/benders.pxi index 66a394d8d..ea0424357 100644 --- a/src/pyscipopt/benders.pxi +++ b/src/pyscipopt/benders.pxi @@ -175,6 +175,7 @@ cdef SCIP_RETCODE PyBendersSolvesub (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL cdef SCIP_RETCODE PyBendersPostsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, SCIP_BENDERSENFOTYPE type, int* mergecands, int npriomergecands, int nmergecands, SCIP_Bool checkint, SCIP_Bool infeasible, SCIP_Bool* merged) noexcept with gil: + cdef int i cdef SCIP_BENDERSDATA* bendersdata bendersdata = SCIPbendersGetData(benders) PyBenders = bendersdata diff --git a/src/pyscipopt/conshdlr.pxi b/src/pyscipopt/conshdlr.pxi index 207177802..4b8e15947 100644 --- a/src/pyscipopt/conshdlr.pxi +++ b/src/pyscipopt/conshdlr.pxi @@ -169,6 +169,7 @@ cdef SCIP_RETCODE PyConsFree (SCIP* scip, SCIP_CONSHDLR* conshdlr) noexcept with cdef SCIP_RETCODE PyConsInit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: PyConshdlr = getPyConshdlr(conshdlr) + cdef int i cdef constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) @@ -178,6 +179,7 @@ cdef SCIP_RETCODE PyConsInit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** c cdef SCIP_RETCODE PyConsExit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] + cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consexit(constraints) @@ -186,6 +188,7 @@ cdef SCIP_RETCODE PyConsExit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** c cdef SCIP_RETCODE PyConsInitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] + cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consinitpre(constraints) @@ -194,6 +197,7 @@ cdef SCIP_RETCODE PyConsInitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cdef SCIP_RETCODE PyConsExitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] + cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consexitpre(constraints) @@ -202,6 +206,7 @@ cdef SCIP_RETCODE PyConsExitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cdef SCIP_RETCODE PyConsInitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] + cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consinitsol(constraints) @@ -210,6 +215,7 @@ cdef SCIP_RETCODE PyConsInitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cdef SCIP_RETCODE PyConsExitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool restart) noexcept with gil: PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] + cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consexitsol(constraints, restart) @@ -246,6 +252,7 @@ cdef SCIP_RETCODE PyConsTrans (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* s cdef SCIP_RETCODE PyConsInitlp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool* infeasible) noexcept with gil: PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] + cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) result_dict = PyConshdlr.consinitlp(constraints) @@ -255,6 +262,7 @@ cdef SCIP_RETCODE PyConsInitlp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** cdef SCIP_RETCODE PyConsSepalp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_RESULT* result) noexcept with gil: PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] + cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) result_dict = PyConshdlr.conssepalp(constraints, nusefulconss) @@ -265,6 +273,7 @@ cdef SCIP_RETCODE PyConsSepasol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* SCIP_SOL* sol, SCIP_RESULT* result) noexcept with gil: PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] + cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) solution = Solution.create(scip, sol) @@ -276,6 +285,7 @@ cdef SCIP_RETCODE PyConsEnfolp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** SCIP_Bool solinfeasible, SCIP_RESULT* result) noexcept with gil: PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] + cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) result_dict = PyConshdlr.consenfolp(constraints, nusefulconss, solinfeasible) @@ -285,6 +295,7 @@ cdef SCIP_RETCODE PyConsEnfolp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** cdef SCIP_RETCODE PyConsEnforelax (SCIP* scip, SCIP_SOL* sol, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_Bool solinfeasible, SCIP_RESULT* result) noexcept with gil: PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] + cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) solution = Solution.create(scip, sol) @@ -296,6 +307,7 @@ cdef SCIP_RETCODE PyConsEnfops (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** SCIP_Bool solinfeasible, SCIP_Bool objinfeasible, SCIP_RESULT* result) noexcept with gil: PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] + cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) result_dict = PyConshdlr.consenfops(constraints, nusefulconss, solinfeasible, objinfeasible) @@ -306,6 +318,7 @@ cdef SCIP_RETCODE PyConsCheck (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_Bool completely, SCIP_RESULT* result) noexcept with gil: PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] + cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) solution = Solution.create(scip, sol) @@ -317,6 +330,7 @@ cdef SCIP_RETCODE PyConsProp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** c SCIP_PROPTIMING proptiming, SCIP_RESULT* result) noexcept with gil: PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] + cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) result_dict = PyConshdlr.consprop(constraints, nusefulconss, nmarkedconss, proptiming) @@ -330,6 +344,7 @@ cdef SCIP_RETCODE PyConsPresol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) noexcept with gil: PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] + cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) # dictionary for input/output parameters @@ -403,6 +418,7 @@ cdef SCIP_RETCODE PyConsDisable (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cdef SCIP_RETCODE PyConsDelvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] + cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consdelvars(constraints) diff --git a/src/pyscipopt/cutsel.pxi b/src/pyscipopt/cutsel.pxi index d259fb28e..ea7239622 100644 --- a/src/pyscipopt/cutsel.pxi +++ b/src/pyscipopt/cutsel.pxi @@ -72,6 +72,7 @@ cdef SCIP_RETCODE PyCutselExitsol (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept wit cdef SCIP_RETCODE PyCutselSelect (SCIP* scip, SCIP_CUTSEL* cutsel, SCIP_ROW** cuts, int ncuts, SCIP_ROW** forcedcuts, int nforcedcuts, SCIP_Bool root, int maxnselectedcuts, int* nselectedcuts, SCIP_RESULT* result) noexcept with gil: + cdef int i cdef SCIP_CUTSELDATA* cutseldata cdef SCIP_ROW* scip_row cutseldata = SCIPcutselGetData(cutsel) diff --git a/src/pyscipopt/lp.pxi b/src/pyscipopt/lp.pxi index 04f6fde3d..11bebc028 100644 --- a/src/pyscipopt/lp.pxi +++ b/src/pyscipopt/lp.pxi @@ -63,6 +63,7 @@ cdef class LP: lb -- lower bound (default 0.0) ub -- upper bound (default infinity) """ + cdef int i nnonz = len(entries) cdef SCIP_Real* c_coefs = malloc(nnonz * sizeof(SCIP_Real)) @@ -95,7 +96,8 @@ cdef class LP: lbs -- lower bounds (default 0.0) ubs -- upper bounds (default infinity) """ - + cdef int i + ncols = len(entrieslist) nnonz = sum(len(entries) for entries in entrieslist) @@ -158,6 +160,8 @@ cdef class LP: lhs -- left-hand side of the row (default 0.0) rhs -- right-hand side of the row (default infinity) """ + cdef int i + beg = 0 nnonz = len(entries) @@ -188,6 +192,8 @@ cdef class LP: lhss -- left-hand side of the row (default 0.0) rhss -- right-hand side of the row (default infinity) """ + cdef int i + nrows = len(entrieslist) nnonz = sum(len(entries) for entries in entrieslist) @@ -232,6 +238,8 @@ cdef class LP: firstcol -- first column (default 0) lastcol -- last column (default ncols - 1) """ + cdef int i + lastcol = lastcol if lastcol != None else self.ncols() - 1 if firstcol > lastcol: @@ -261,6 +269,8 @@ cdef class LP: firstrow -- first row (default 0) lastrow -- last row (default nrows - 1) """ + cdef int i + lastrow = lastrow if lastrow != None else self.nrows() - 1 if firstrow > lastrow: @@ -363,6 +373,8 @@ cdef class LP: def getPrimal(self): """Returns the primal solution of the last LP solve.""" + cdef int i + ncols = self.ncols() cdef SCIP_Real* c_primalsol = malloc(ncols * sizeof(SCIP_Real)) PY_SCIP_CALL(SCIPlpiGetSol(self.lpi, NULL, c_primalsol, NULL, NULL, NULL)) @@ -379,6 +391,8 @@ cdef class LP: def getDual(self): """Returns the dual solution of the last LP solve.""" + cdef int i + nrows = self.nrows() cdef SCIP_Real* c_dualsol = malloc(nrows * sizeof(SCIP_Real)) PY_SCIP_CALL(SCIPlpiGetSol(self.lpi, NULL, NULL, c_dualsol, NULL, NULL)) @@ -395,6 +409,8 @@ cdef class LP: def getPrimalRay(self): """Returns a primal ray if possible, None otherwise.""" + cdef int i + if not SCIPlpiHasPrimalRay(self.lpi): return None ncols = self.ncols() @@ -409,6 +425,8 @@ cdef class LP: def getDualRay(self): """Returns a dual ray if possible, None otherwise.""" + cdef int i + if not SCIPlpiHasDualRay(self.lpi): return None nrows = self.nrows() @@ -429,6 +447,8 @@ cdef class LP: def getRedcost(self): """Returns the reduced cost vector of the last LP solve.""" + cdef int i + ncols = self.ncols() cdef SCIP_Real* c_redcost = malloc(ncols * sizeof(SCIP_Real)) @@ -443,6 +463,8 @@ cdef class LP: def getBasisInds(self): """Returns the indices of the basic columns and rows; index i >= 0 corresponds to column i, index i < 0 to row -i-1""" + cdef int i + nrows = self.nrows() cdef int* c_binds = malloc(nrows * sizeof(int)) diff --git a/src/pyscipopt/reader.pxi b/src/pyscipopt/reader.pxi index 2c45585d6..b8f51fff7 100644 --- a/src/pyscipopt/reader.pxi +++ b/src/pyscipopt/reader.pxi @@ -45,6 +45,7 @@ cdef SCIP_RETCODE PyReaderWrite (SCIP* scip, SCIP_READER* reader, FILE* file, SCIP_VAR** fixedvars, int nfixedvars, int startnvars, SCIP_CONS** conss, int nconss, int maxnconss, int startnconss, SCIP_Bool genericnames, SCIP_RESULT* result) noexcept with gil: + cdef int i cdef SCIP_READERDATA* readerdata readerdata = SCIPreaderGetData(reader) cdef int fd = fileno(file) diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi index 36e3a8979..2b5ad69b3 100644 --- a/src/pyscipopt/scip.pxi +++ b/src/pyscipopt/scip.pxi @@ -806,6 +806,7 @@ cdef class Row: list of Column """ + cdef int i cdef SCIP_COL** cols = SCIProwGetCols(self.scip_row) return [Column.create(cols[i]) for i in range(self.getNNonz())] @@ -818,6 +819,7 @@ cdef class Row: list of int """ + cdef int i cdef SCIP_Real* vals = SCIProwGetVals(self.scip_row) return [vals[i] for i in range(self.getNNonz())] @@ -903,6 +905,7 @@ cdef class NLRow: cdef SCIP_VAR** linvars = SCIPnlrowGetLinearVars(self.scip_nlrow) cdef SCIP_Real* lincoefs = SCIPnlrowGetLinearCoefs(self.scip_nlrow) cdef int nlinvars = SCIPnlrowGetNLinearVars(self.scip_nlrow) + cdef int i return [(Variable.create(linvars[i]), lincoefs[i]) for i in range(nlinvars)] def getLhs(self): @@ -981,6 +984,7 @@ cdef class Solution: def __getitem__(self, Expr expr): # fast track for Variable + cdef SCIP_Real coeff if isinstance(expr, Variable): self._checkStage("SCIPgetSolVal") var = expr @@ -999,6 +1003,7 @@ cdef class Solution: def __repr__(self): cdef SCIP_VAR* scip_var + cdef int i vals = {} self._checkStage("SCIPgetSolVal") @@ -1175,6 +1180,7 @@ cdef class DomainChanges: list of BoundChange """ + cdef int i nboundchgs = SCIPdomchgGetNBoundchgs(self.scip_domchg) return [BoundChange.create(SCIPdomchgGetBoundchg(self.scip_domchg, i)) for i in range(nboundchgs)] @@ -1280,6 +1286,7 @@ cdef class Node: """ cdef int addedconsssize = SCIPnodeGetNAddedConss(self.scip_node) + cdef int i if addedconsssize == 0: return [] cdef SCIP_CONS** addedconss = malloc(addedconsssize * sizeof(SCIP_CONS*)) @@ -1355,6 +1362,7 @@ cdef class Node: list of int """ + cdef int i cdef int nbranchvars = self.getNParentBranchings() if nbranchvars == 0: return None @@ -2717,6 +2725,8 @@ cdef class Model: cdef SCIP_VAR** _vars cdef int _nvars + cdef int i + cdef SCIP_Real coef # turn the constant value into an Expr instance for further processing if not isinstance(expr, Expr): @@ -3408,6 +3418,7 @@ cdef class Model: cdef SCIP_VAR** _vars cdef SCIP_VAR* _var cdef int _nvars + cdef int i vars = [] if transformed: @@ -3633,6 +3644,7 @@ cdef class Model: cdef int _nleaves cdef int _nchildren cdef int _nsiblings + cdef int i PY_SCIP_CALL(SCIPgetOpenNodesData(self._scip, &_leaves, &_children, &_siblings, &_nleaves, &_nchildren, &_nsiblings)) @@ -3699,6 +3711,7 @@ cdef class Model: """ cdef SCIP_COL** cols cdef int ncols + cdef int i PY_SCIP_CALL(SCIPgetLPColsData(self._scip, &cols, &ncols)) return [Column.create(cols[i]) for i in range(ncols)] @@ -3714,6 +3727,7 @@ cdef class Model: """ cdef SCIP_ROW** rows cdef int nrows + cdef int i PY_SCIP_CALL(SCIPgetLPRowsData(self._scip, &rows, &nrows)) return [Row.create(rows[i]) for i in range(nrows)] @@ -3752,6 +3766,7 @@ cdef class Model: """ cdef int nrows = SCIPgetNLPRows(self._scip) cdef int* inds = malloc(nrows * sizeof(int)) + cdef int i PY_SCIP_CALL(SCIPgetLPBasisInd(self._scip, inds)) result = [inds[i] for i in range(nrows)] @@ -3775,7 +3790,8 @@ cdef class Model: # TODO: sparsity information cdef int nrows = SCIPgetNLPRows(self._scip) cdef SCIP_Real* coefs = malloc(nrows * sizeof(SCIP_Real)) - + cdef int i + PY_SCIP_CALL(SCIPgetLPBInvRow(self._scip, row, coefs, NULL, NULL)) result = [coefs[i] for i in range(nrows)] free(coefs) @@ -3798,7 +3814,8 @@ cdef class Model: # TODO: sparsity information cdef int ncols = SCIPgetNLPCols(self._scip) cdef SCIP_Real* coefs = malloc(ncols * sizeof(SCIP_Real)) - + cdef int i + PY_SCIP_CALL(SCIPgetLPBInvARow(self._scip, row, NULL, coefs, NULL, NULL)) result = [coefs[i] for i in range(ncols)] free(coefs) @@ -4249,6 +4266,9 @@ cdef class Model: cdef int nvars = len(terms.items()) + cdef int i + cdef SCIP_Real coeff + vars_array = malloc(nvars * sizeof(SCIP_VAR*)) coeffs_array = malloc(nvars * sizeof(SCIP_Real)) @@ -4345,8 +4365,7 @@ cdef class Model: cdef int i cdef int idx cdef int j - cdef SCIP_Real coef - + terms = cons.expr.terms # collect variables @@ -4414,6 +4433,8 @@ cdef class Model: cdef SCIP_EXPR** scipexprs cdef SCIP_CONS* scip_cons cdef int nchildren + cdef int i + cdef int c # get arrays from python's expression tree expr = cons.expr @@ -4709,6 +4730,9 @@ cdef class Model: The created and added Constraint objects. """ + cdef int idx + cdef int i + def ensure_iterable(elem, length): if isinstance(elem, Iterable): return elem @@ -4781,6 +4805,8 @@ cdef class Model: The created disjunction constraint """ + cdef int i + def ensure_iterable(elem, length): if isinstance(elem, Iterable): return elem @@ -4882,6 +4908,7 @@ cdef class Model: list of Variable """ + cdef int i cdef SCIP_Bool success cdef int _nvars @@ -5049,6 +5076,7 @@ cdef class Model: """ cdef SCIP_CONS* scip_cons cdef int _nvars + cdef int i PY_SCIP_CALL(SCIPcreateConsSOS1(self._scip, &scip_cons, str_conversion(name), 0, NULL, NULL, initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode)) @@ -5109,6 +5137,7 @@ cdef class Model: """ cdef SCIP_CONS* scip_cons cdef int _nvars + cdef int i PY_SCIP_CALL(SCIPcreateConsSOS2(self._scip, &scip_cons, str_conversion(name), 0, NULL, NULL, initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode)) @@ -5168,6 +5197,7 @@ cdef class Model: """ cdef SCIP_CONS* scip_cons + cdef int idx nvars = len(vars) @@ -5229,6 +5259,7 @@ cdef class Model: """ cdef SCIP_CONS* scip_cons + cdef int idx nvars = len(vars) @@ -5290,6 +5321,7 @@ cdef class Model: """ cdef SCIP_CONS* scip_cons + cdef int idx nvars = len(vars) @@ -5359,6 +5391,7 @@ cdef class Model: """ cdef SCIP_CONS* scip_cons cdef SCIP_VAR* indvar + cdef int i PY_SCIP_CALL(SCIPcreateConsCardinality(self._scip, &scip_cons, str_conversion(name), 0, NULL, cardval, NULL, NULL, initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode)) @@ -5433,6 +5466,8 @@ cdef class Model: assert isinstance(cons, ExprCons), "given constraint is not ExprCons but %s" % cons.__class__.__name__ cdef SCIP_CONS* scip_cons cdef SCIP_VAR* _binVar + cdef SCIP_Real coeff + if cons._lhs is not None and cons._rhs is not None: raise ValueError("expected inequality that has either only a left or right hand side") @@ -5892,6 +5927,7 @@ cdef class Model: """ cdef SCIP_NLROW** nlrows + cdef int i nlrows = SCIPgetNLPNlRows(self._scip) return [NLRow.create(nlrows[i]) for i in range(self.getNNlRows())] @@ -6003,6 +6039,7 @@ cdef class Model: """ cdef SCIP_EXPR* expr + cdef int termidx # linear terms cdef SCIP_EXPR** _linexprs @@ -6087,6 +6124,8 @@ cdef class Model: """ cdef SCIP_CONS** _conss cdef int _nconss + cdef int i + conss = [] if transformed: @@ -6156,6 +6195,7 @@ cdef class Model: """ cdef SCIP_Real* _vals cdef SCIP_VAR** _vars + cdef int i constype = bytes(SCIPconshdlrGetName(SCIPconsGetHdlr(cons.scip_cons))).decode('UTF-8') if not constype == 'linear': @@ -6349,6 +6389,7 @@ cdef class Model: """ cdef SCIP** subprobs cdef SCIP_BENDERS* benders + cdef int idx # checking whether subproblems is a dictionary if isinstance(subproblems, dict): @@ -6388,6 +6429,8 @@ cdef class Model: cdef SCIP_Bool _infeasible cdef int nbenders cdef int nsubproblems + cdef int i + cdef int j solvecip = True @@ -6409,6 +6452,8 @@ cdef class Model: cdef SCIP_BENDERS** _benders cdef int nbenders cdef int nsubproblems + cdef int i + cdef int j nbenders = SCIPgetNActiveBenders(self._scip) _benders = SCIPgetBenders(self._scip) @@ -6854,7 +6899,9 @@ cdef class Model: model : Model A model containing the created copy """ - + cdef SCIP_Real val + cdef int i + orig_vars = SCIPgetVars(self._scip) vars = malloc(len(to_fix) * sizeof(SCIP_VAR*)) vals = malloc(len(fix_vals) * sizeof(SCIP_Real)) @@ -6900,6 +6947,7 @@ cdef class Model: solution : Solution The corresponding solution in the main model """ + cdef int i cdef SCIP_SOL* real_sol cdef SCIP_SOL* subscip_sol @@ -7367,6 +7415,7 @@ cdef class Model: cdef int nlpcands cdef int npriolpcands cdef int nfracimplvars + cdef int i cdef SCIP_VAR** lpcands cdef SCIP_Real* lpcandssol @@ -7395,6 +7444,7 @@ cdef class Model: """ cdef int npseudocands cdef int npriopseudocands + cdef int i cdef SCIP_VAR** pseudocands @@ -8333,6 +8383,7 @@ cdef class Model: """ cdef SCIP_SOL** _sols cdef SCIP_SOL* _sol + cdef int i _sols = SCIPgetSols(self._scip) nsols = SCIPgetNSols(self._scip) sols = [] @@ -8519,6 +8570,7 @@ cdef class Model: """ assert SCIPhasPrimalRay(self._scip), "The problem does not have a primal ray." + cdef int i cdef int _nvars = SCIPgetNVars(self._scip) cdef SCIP_VAR ** _vars = SCIPgetVars(self._scip) @@ -8604,6 +8656,8 @@ cdef class Model: def _getStageNames(self): """Gets names of stages.""" + cdef str name + for name in dir(PY_SCIP_STAGE): attr = getattr(PY_SCIP_STAGE, name) if isinstance(attr, int): @@ -9051,6 +9105,7 @@ cdef class Model: """ cdef SCIP_PARAM** params + cdef int i params = SCIPgetParams(self._scip) result = {} @@ -9069,6 +9124,7 @@ cdef class Model: dict mapping parameter names to their values. """ + cdef str name for name, value in params.items(): self.setParam(name, value) @@ -9239,6 +9295,8 @@ cdef class Model: """ cdef SCIP_OBJSENSE objsense + cdef int i + cdef SCIP_Real coef if sense == "minimize": objsense = SCIP_OBJSENSE_MINIMIZE @@ -9461,7 +9519,7 @@ cdef class Model: float """ - + cdef int i assert isinstance(gains, list) nchildren = len(gains) @@ -9554,7 +9612,7 @@ cdef class Model: "basis_zero": 15, "best_incumbent_val": 16, "avg_incumbent_val": 17, "age": 18} if prev_col_features is None: - col_features = [[0 for _ in range(n_col_features)] for _ in range(ncols)] + col_features = [[0 for i in range(n_col_features)] for j in range(ncols)] else: assert len(prev_col_features) > 0, "Previous column features is empty" col_features = prev_col_features @@ -9562,7 +9620,7 @@ cdef class Model: if not suppress_warnings: raise Warning(f"The number of columns has changed. Previous column data being ignored") else: - col_features = [[0 for _ in range(n_col_features)] for _ in range(ncols)] + col_features = [[0 for i in range(n_col_features)] for j in range(ncols)] prev_col_features = None if len(prev_col_features[0]) != n_col_features: raise Warning(f"Dimension mismatch in provided previous features and new features:" @@ -9650,7 +9708,7 @@ cdef class Model: "basis_lower": 10, "basis_basic": 11, "basis_upper": 12, "basis_zero": 13} if prev_row_features is None: - row_features = [[0 for _ in range(n_row_features)] for _ in range(nrows)] + row_features = [[0 for i in range(n_row_features)] for j in range(nrows)] else: assert len(prev_row_features) > 0, "Previous row features is empty" row_features = prev_row_features @@ -9658,7 +9716,7 @@ cdef class Model: if not suppress_warnings: raise Warning(f"The number of rows has changed. Previous row data being ignored") else: - row_features = [[0 for _ in range(n_row_features)] for _ in range(nrows)] + row_features = [[0 for i in range(n_row_features)] for j in range(nrows)] prev_row_features = None if len(prev_row_features[0]) != n_row_features: raise Warning(f"Dimension mismatch in provided previous features and new features:" @@ -9725,7 +9783,7 @@ cdef class Model: n_edge_features = 3 edge_feature_map = {"col_idx": 0, "row_idx": 1, "coef": 2} if prev_edge_features is None: - edge_features = [[0 for _ in range(n_edge_features)] for _ in range(nnzrs)] + edge_features = [[0 for i in range(n_edge_features)] for j in range(nnzrs)] j = 0 for i in range(nrows): # coefficient indexes and values @@ -9743,7 +9801,7 @@ cdef class Model: if not suppress_warnings: raise Warning(f"The number of coefficients in the LP has changed. Previous edge data being ignored") else: - edge_features = [[0 for _ in range(3)] for _ in range(nnzrs)] + edge_features = [[0 for i in range(3)] for j in range(nnzrs)] prev_edge_features = None if len(prev_edge_features[0]) != 3: raise Warning(f"Dimension mismatch in provided previous features and new features:" @@ -9912,6 +9970,11 @@ def readStatistics(filename): Statistics """ + cdef int i + cdef str line + cdef str var_type + cdef str con_type + result = {} file = open(filename) data = file.readlines() diff --git a/tests/test_event.py b/tests/test_event.py index 1cd4c59d6..ec5103a6a 100644 --- a/tests/test_event.py +++ b/tests/test_event.py @@ -82,8 +82,7 @@ def test_event(): s.addCons(quicksum(x[i] for i in range(100) if i%j==0) >= random.randint(10,100)) s.optimize() - - + def test_event_handler_callback(): m = Model() @@ -100,4 +99,5 @@ def callback(model, event): m.optimize() - assert number_of_calls == 2 \ No newline at end of file + assert number_of_calls == 2 +test_event_handler_callback() \ No newline at end of file From f7e736cef0a073e435503d24364d619b5d3251d3 Mon Sep 17 00:00:00 2001 From: Joao-Dionisio Date: Fri, 24 Jan 2025 14:49:31 +0100 Subject: [PATCH 03/12] remove forgotten stuff --- tests/test_event.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_event.py b/tests/test_event.py index ec5103a6a..f167a2fc9 100644 --- a/tests/test_event.py +++ b/tests/test_event.py @@ -99,5 +99,4 @@ def callback(model, event): m.optimize() - assert number_of_calls == 2 -test_event_handler_callback() \ No newline at end of file + assert number_of_calls == 2 \ No newline at end of file From edb7007ec1530d6538ecb63091a8225c22c5b980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Dion=C3=ADsio?= <57299939+Joao-Dionisio@users.noreply.github.com> Date: Sun, 26 Jan 2025 16:39:30 +0000 Subject: [PATCH 04/12] Update CHANGELOG.md Co-authored-by: DominikKamp <130753997+DominikKamp@users.noreply.github.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b7155cc9..dbed40edd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased ### Added -- Added cdef to loop variables for slight speedup +- Added cdef type declaration of loop variables for slight speedup - Added wrappers for setting and getting heuristic timing - Added transformed option to getVarDict, updated test - Added categorical data example From 3cea4a6dea0d0bb8a330627d88a431367d6e059b Mon Sep 17 00:00:00 2001 From: Joao-Dionisio Date: Sun, 26 Jan 2025 18:39:12 +0100 Subject: [PATCH 05/12] Dominik's comments --- src/pyscipopt/benders.pxi | 3 ++- src/pyscipopt/cutsel.pxi | 3 ++- src/pyscipopt/lp.pxi | 25 +++++++++++--------- src/pyscipopt/reader.pxi | 4 +++- src/pyscipopt/scip.pxi | 48 ++++++++++++++++++++++++--------------- 5 files changed, 51 insertions(+), 32 deletions(-) diff --git a/src/pyscipopt/benders.pxi b/src/pyscipopt/benders.pxi index ea0424357..0a592f553 100644 --- a/src/pyscipopt/benders.pxi +++ b/src/pyscipopt/benders.pxi @@ -175,8 +175,9 @@ cdef SCIP_RETCODE PyBendersSolvesub (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL cdef SCIP_RETCODE PyBendersPostsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, SCIP_BENDERSENFOTYPE type, int* mergecands, int npriomergecands, int nmergecands, SCIP_Bool checkint, SCIP_Bool infeasible, SCIP_Bool* merged) noexcept with gil: - cdef int i cdef SCIP_BENDERSDATA* bendersdata + cdef int i + bendersdata = SCIPbendersGetData(benders) PyBenders = bendersdata if sol == NULL: diff --git a/src/pyscipopt/cutsel.pxi b/src/pyscipopt/cutsel.pxi index ea7239622..5739a1043 100644 --- a/src/pyscipopt/cutsel.pxi +++ b/src/pyscipopt/cutsel.pxi @@ -72,9 +72,10 @@ cdef SCIP_RETCODE PyCutselExitsol (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept wit cdef SCIP_RETCODE PyCutselSelect (SCIP* scip, SCIP_CUTSEL* cutsel, SCIP_ROW** cuts, int ncuts, SCIP_ROW** forcedcuts, int nforcedcuts, SCIP_Bool root, int maxnselectedcuts, int* nselectedcuts, SCIP_RESULT* result) noexcept with gil: - cdef int i cdef SCIP_CUTSELDATA* cutseldata cdef SCIP_ROW* scip_row + cdef int i + cutseldata = SCIPcutselGetData(cutsel) PyCutsel = cutseldata diff --git a/src/pyscipopt/lp.pxi b/src/pyscipopt/lp.pxi index 11bebc028..2532da7f6 100644 --- a/src/pyscipopt/lp.pxi +++ b/src/pyscipopt/lp.pxi @@ -63,8 +63,7 @@ cdef class LP: lb -- lower bound (default 0.0) ub -- upper bound (default infinity) """ - cdef int i - nnonz = len(entries) + cdef int nnonz = len(entries) cdef SCIP_Real* c_coefs = malloc(nnonz * sizeof(SCIP_Real)) cdef int* c_inds = malloc(nnonz * sizeof(int)) @@ -72,6 +71,7 @@ cdef class LP: cdef SCIP_Real c_lb cdef SCIP_Real c_ub cdef int c_beg + cdef int i c_obj = obj c_lb = lb @@ -96,10 +96,10 @@ cdef class LP: lbs -- lower bounds (default 0.0) ubs -- upper bounds (default infinity) """ - cdef int i - ncols = len(entrieslist) - nnonz = sum(len(entries) for entries in entrieslist) + cdef ncols = len(entrieslist) + cdef nnonz = sum(len(entries) for entries in entrieslist) + cdef int i cdef SCIP_Real* c_objs = malloc(ncols * sizeof(SCIP_Real)) cdef SCIP_Real* c_lbs = malloc(ncols * sizeof(SCIP_Real)) @@ -160,8 +160,6 @@ cdef class LP: lhs -- left-hand side of the row (default 0.0) rhs -- right-hand side of the row (default infinity) """ - cdef int i - beg = 0 nnonz = len(entries) @@ -170,6 +168,7 @@ cdef class LP: cdef SCIP_Real c_lhs cdef SCIP_Real c_rhs cdef int c_beg + cdef int i c_lhs = lhs c_rhs = rhs if rhs != None else self.infinity() @@ -192,8 +191,6 @@ cdef class LP: lhss -- left-hand side of the row (default 0.0) rhss -- right-hand side of the row (default infinity) """ - cdef int i - nrows = len(entrieslist) nnonz = sum(len(entries) for entries in entrieslist) @@ -202,6 +199,7 @@ cdef class LP: cdef SCIP_Real* c_coefs = malloc(nnonz * sizeof(SCIP_Real)) cdef int* c_inds = malloc(nnonz * sizeof(int)) cdef int* c_beg = malloc(nrows * sizeof(int)) + cdef int i tmp = 0 for i,entries in enumerate(entrieslist): @@ -302,6 +300,7 @@ cdef class LP: """ cdef int c_col = col cdef SCIP_Real c_obj = obj + PY_SCIP_CALL(SCIPlpiChgObj(self.lpi, 1, &c_col, &c_obj)) def chgCoef(self, row, col, newval): @@ -325,6 +324,7 @@ cdef class LP: cdef int c_col = col cdef SCIP_Real c_lb = lb cdef SCIP_Real c_ub = ub + PY_SCIP_CALL(SCIPlpiChgBounds(self.lpi, 1, &c_col, &c_lb, &c_ub)) def chgSide(self, row, lhs, rhs): @@ -338,6 +338,7 @@ cdef class LP: cdef int c_row = row cdef SCIP_Real c_lhs = lhs cdef SCIP_Real c_rhs = rhs + PY_SCIP_CALL(SCIPlpiChgSides(self.lpi, 1, &c_row, &c_lhs, &c_rhs)) def clear(self): @@ -347,12 +348,14 @@ cdef class LP: def nrows(self): """Returns the number of rows.""" cdef int nrows + PY_SCIP_CALL(SCIPlpiGetNRows(self.lpi, &nrows)) return nrows def ncols(self): """Returns the number of columns.""" cdef int ncols + PY_SCIP_CALL(SCIPlpiGetNCols(self.lpi, &ncols)) return ncols @@ -442,6 +445,7 @@ cdef class LP: def getNIterations(self): """Returns the number of LP iterations of the last LP solve.""" cdef int niters + PY_SCIP_CALL(SCIPlpiGetIterations(self.lpi, &niters)) return niters @@ -463,10 +467,9 @@ cdef class LP: def getBasisInds(self): """Returns the indices of the basic columns and rows; index i >= 0 corresponds to column i, index i < 0 to row -i-1""" - cdef int i - nrows = self.nrows() cdef int* c_binds = malloc(nrows * sizeof(int)) + cdef int i PY_SCIP_CALL(SCIPlpiGetBasisInd(self.lpi, c_binds)) diff --git a/src/pyscipopt/reader.pxi b/src/pyscipopt/reader.pxi index b8f51fff7..8672e2fae 100644 --- a/src/pyscipopt/reader.pxi +++ b/src/pyscipopt/reader.pxi @@ -45,10 +45,12 @@ cdef SCIP_RETCODE PyReaderWrite (SCIP* scip, SCIP_READER* reader, FILE* file, SCIP_VAR** fixedvars, int nfixedvars, int startnvars, SCIP_CONS** conss, int nconss, int maxnconss, int startnconss, SCIP_Bool genericnames, SCIP_RESULT* result) noexcept with gil: - cdef int i cdef SCIP_READERDATA* readerdata + cdef int i + readerdata = SCIPreaderGetData(reader) cdef int fd = fileno(file) + PyFile = os.fdopen(fd, "w", closefd=False) PyName = name.decode('utf-8') PyBinVars = [Variable.create(vars[i]) for i in range(nbinvars)] diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi index 2b5ad69b3..adcad2657 100644 --- a/src/pyscipopt/scip.pxi +++ b/src/pyscipopt/scip.pxi @@ -806,8 +806,9 @@ cdef class Row: list of Column """ - cdef int i cdef SCIP_COL** cols = SCIProwGetCols(self.scip_row) + cdef int i + return [Column.create(cols[i]) for i in range(self.getNNonz())] def getVals(self): @@ -819,8 +820,9 @@ cdef class Row: list of int """ - cdef int i cdef SCIP_Real* vals = SCIProwGetVals(self.scip_row) + cdef int i + return [vals[i] for i in range(self.getNNonz())] def getAge(self): @@ -906,6 +908,7 @@ cdef class NLRow: cdef SCIP_Real* lincoefs = SCIPnlrowGetLinearCoefs(self.scip_nlrow) cdef int nlinvars = SCIPnlrowGetNLinearVars(self.scip_nlrow) cdef int i + return [(Variable.create(linvars[i]), lincoefs[i]) for i in range(nlinvars)] def getLhs(self): @@ -985,6 +988,7 @@ cdef class Solution: def __getitem__(self, Expr expr): # fast track for Variable cdef SCIP_Real coeff + if isinstance(expr, Variable): self._checkStage("SCIPgetSolVal") var = expr @@ -1181,6 +1185,7 @@ cdef class DomainChanges: """ cdef int i + nboundchgs = SCIPdomchgGetNBoundchgs(self.scip_domchg) return [BoundChange.create(SCIPdomchgGetBoundchg(self.scip_domchg, i)) for i in range(nboundchgs)] @@ -1287,10 +1292,13 @@ cdef class Node: """ cdef int addedconsssize = SCIPnodeGetNAddedConss(self.scip_node) cdef int i + if addedconsssize == 0: return [] + cdef SCIP_CONS** addedconss = malloc(addedconsssize * sizeof(SCIP_CONS*)) cdef int nconss + SCIPnodeGetAddedConss(self.scip_node, addedconss, &nconss, addedconsssize) assert nconss == addedconsssize constraints = [Constraint.create(addedconss[i]) for i in range(nconss)] @@ -1343,6 +1351,7 @@ cdef class Node: cdef SCIP_Real dummy_branchbounds cdef SCIP_BOUNDTYPE dummy_boundtypes cdef int nbranchvars + # This is a hack: the SCIP interface has no function to directly get the # number of parent branchings, i.e., SCIPnodeGetNParentBranchings() does # not exist. @@ -1362,8 +1371,9 @@ cdef class Node: list of int """ - cdef int i cdef int nbranchvars = self.getNParentBranchings() + cdef int i + if nbranchvars == 0: return None @@ -1397,6 +1407,7 @@ cdef class Node: cdef int nbranchings cdef int nconsprop cdef int nprop + SCIPnodeGetNDomchg(self.scip_node, &nbranchings, &nconsprop, &nprop) return nbranchings, nconsprop, nprop @@ -2669,8 +2680,9 @@ cdef class Model: """ cdef SCIP_LPI* lpi - PY_SCIP_CALL(SCIPgetLPI(self._scip, &lpi)) cdef int iters = 0 + + PY_SCIP_CALL(SCIPgetLPI(self._scip, &lpi)) PY_SCIP_CALL(SCIPlpiGetIterations(lpi, &iters)) return iters @@ -2725,8 +2737,8 @@ cdef class Model: cdef SCIP_VAR** _vars cdef int _nvars - cdef int i cdef SCIP_Real coef + cdef int i # turn the constant value into an Expr instance for further processing if not isinstance(expr, Expr): @@ -3419,8 +3431,8 @@ cdef class Model: cdef SCIP_VAR* _var cdef int _nvars cdef int i - vars = [] + vars = [] if transformed: _vars = SCIPgetVars(self._scip) _nvars = SCIPgetNVars(self._scip) @@ -4263,11 +4275,9 @@ cdef class Model: terms = lincons.expr.terms cdef SCIP_CONS* scip_cons - cdef int nvars = len(terms.items()) - - cdef int i cdef SCIP_Real coeff + cdef int i vars_array = malloc(nvars * sizeof(SCIP_VAR*)) coeffs_array = malloc(nvars * sizeof(SCIP_Real)) @@ -4360,8 +4370,8 @@ cdef class Model: cdef SCIP_EXPR* expr cdef SCIP_EXPR** varexprs cdef SCIP_EXPR** monomials - cdef int* idxs cdef SCIP_CONS* scip_cons + cdef int* idxs cdef int i cdef int idx cdef int j @@ -4433,8 +4443,8 @@ cdef class Model: cdef SCIP_EXPR** scipexprs cdef SCIP_CONS* scip_cons cdef int nchildren - cdef int i cdef int c + cdef int i # get arrays from python's expression tree expr = cons.expr @@ -4908,9 +4918,9 @@ cdef class Model: list of Variable """ - cdef int i cdef SCIP_Bool success cdef int _nvars + cdef int i SCIPgetConsNVars(self._scip, constraint.scip_cons, &_nvars, &success) @@ -8384,6 +8394,7 @@ cdef class Model: cdef SCIP_SOL** _sols cdef SCIP_SOL* _sol cdef int i + _sols = SCIPgetSols(self._scip) nsols = SCIPgetNSols(self._scip) sols = [] @@ -8570,10 +8581,9 @@ cdef class Model: """ assert SCIPhasPrimalRay(self._scip), "The problem does not have a primal ray." - cdef int i - cdef int _nvars = SCIPgetNVars(self._scip) cdef SCIP_VAR ** _vars = SCIPgetVars(self._scip) + cdef int i ray = [] for i in range(_nvars): @@ -9295,8 +9305,8 @@ cdef class Model: """ cdef SCIP_OBJSENSE objsense - cdef int i cdef SCIP_Real coef + cdef int i if sense == "minimize": objsense = SCIP_OBJSENSE_MINIMIZE @@ -9314,6 +9324,7 @@ cdef class Model: cdef SCIP_VAR** _vars cdef int _nvars + _vars = SCIPgetOrigVars(self._scip) _nvars = SCIPgetNOrigVars(self._scip) _coeffs = malloc(_nvars * sizeof(SCIP_Real)) @@ -9588,9 +9599,9 @@ cdef class Model: """ cdef SCIP* scip = self._scip - cdef int i, j, k, col_i cdef SCIP_VARTYPE vtype cdef SCIP_Real sim, prod + cdef int i, j, k, col_i # Check if SCIP is in the correct stage if SCIPgetStage(scip) != SCIP_STAGE_SOLVING: @@ -9695,8 +9706,8 @@ cdef class Model: col_features[col_i][col_feature_map["avg_incumbent_val"]] = SCIPvarGetAvgSol(var) # Generate row features - cdef int nrows = SCIPgetNLPRows(scip) cdef SCIP_ROW** rows = SCIPgetLPRows(scip) + cdef int nrows = SCIPgetNLPRows(scip) if static_only: n_row_features = 6 @@ -9724,6 +9735,7 @@ cdef class Model: cdef int nnzrs = 0 cdef SCIP_Real lhs, rhs, cst + for i in range(nrows): # lhs <= activity + cst <= rhs @@ -9970,10 +9982,10 @@ def readStatistics(filename): Statistics """ - cdef int i cdef str line cdef str var_type cdef str con_type + cdef int i result = {} file = open(filename) From 0aff74b073f709946d7a7301455a0fea291bd101 Mon Sep 17 00:00:00 2001 From: Joao-Dionisio Date: Sun, 26 Jan 2025 18:39:35 +0100 Subject: [PATCH 06/12] Also on conshdlr, even though it looks ugly --- src/pyscipopt/conshdlr.pxi | 48 +++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/src/pyscipopt/conshdlr.pxi b/src/pyscipopt/conshdlr.pxi index 4b8e15947..91cb0c40a 100644 --- a/src/pyscipopt/conshdlr.pxi +++ b/src/pyscipopt/conshdlr.pxi @@ -168,8 +168,9 @@ cdef SCIP_RETCODE PyConsFree (SCIP* scip, SCIP_CONSHDLR* conshdlr) noexcept with return SCIP_OKAY cdef SCIP_RETCODE PyConsInit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) cdef int i + + PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) @@ -177,45 +178,50 @@ cdef SCIP_RETCODE PyConsInit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** c return SCIP_OKAY cdef SCIP_RETCODE PyConsExit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: + cdef int i + PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] - cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consexit(constraints) return SCIP_OKAY cdef SCIP_RETCODE PyConsInitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: + cdef int i + PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] - cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consinitpre(constraints) return SCIP_OKAY cdef SCIP_RETCODE PyConsExitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: + cdef int i + PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] - cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consexitpre(constraints) return SCIP_OKAY cdef SCIP_RETCODE PyConsInitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: + cdef int i + PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] - cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consinitsol(constraints) return SCIP_OKAY cdef SCIP_RETCODE PyConsExitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool restart) noexcept with gil: + cdef int i + PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] - cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consexitsol(constraints, restart) @@ -250,9 +256,10 @@ cdef SCIP_RETCODE PyConsTrans (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* s return SCIP_OKAY cdef SCIP_RETCODE PyConsInitlp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool* infeasible) noexcept with gil: + cdef int i + PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] - cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) result_dict = PyConshdlr.consinitlp(constraints) @@ -260,9 +267,10 @@ cdef SCIP_RETCODE PyConsInitlp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** return SCIP_OKAY cdef SCIP_RETCODE PyConsSepalp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_RESULT* result) noexcept with gil: + cdef int i + PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] - cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) result_dict = PyConshdlr.conssepalp(constraints, nusefulconss) @@ -271,9 +279,10 @@ cdef SCIP_RETCODE PyConsSepalp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** cdef SCIP_RETCODE PyConsSepasol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_SOL* sol, SCIP_RESULT* result) noexcept with gil: + cdef int i + PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] - cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) solution = Solution.create(scip, sol) @@ -283,9 +292,10 @@ cdef SCIP_RETCODE PyConsSepasol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cdef SCIP_RETCODE PyConsEnfolp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_Bool solinfeasible, SCIP_RESULT* result) noexcept with gil: + cdef int i + PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] - cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) result_dict = PyConshdlr.consenfolp(constraints, nusefulconss, solinfeasible) @@ -293,9 +303,10 @@ cdef SCIP_RETCODE PyConsEnfolp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** return SCIP_OKAY cdef SCIP_RETCODE PyConsEnforelax (SCIP* scip, SCIP_SOL* sol, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_Bool solinfeasible, SCIP_RESULT* result) noexcept with gil: + cdef int i + PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] - cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) solution = Solution.create(scip, sol) @@ -305,9 +316,10 @@ cdef SCIP_RETCODE PyConsEnforelax (SCIP* scip, SCIP_SOL* sol, SCIP_CONSHDLR* con cdef SCIP_RETCODE PyConsEnfops (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_Bool solinfeasible, SCIP_Bool objinfeasible, SCIP_RESULT* result) noexcept with gil: + cdef int i + PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] - cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) result_dict = PyConshdlr.consenfops(constraints, nusefulconss, solinfeasible, objinfeasible) @@ -316,9 +328,10 @@ cdef SCIP_RETCODE PyConsEnfops (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** cdef SCIP_RETCODE PyConsCheck (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_SOL* sol, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_Bool completely, SCIP_RESULT* result) noexcept with gil: + cdef int i + PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] - cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) solution = Solution.create(scip, sol) @@ -328,9 +341,10 @@ cdef SCIP_RETCODE PyConsCheck (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** cdef SCIP_RETCODE PyConsProp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, int nmarkedconss, SCIP_PROPTIMING proptiming, SCIP_RESULT* result) noexcept with gil: + cdef int i + PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] - cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) result_dict = PyConshdlr.consprop(constraints, nusefulconss, nmarkedconss, proptiming) @@ -342,9 +356,10 @@ cdef SCIP_RETCODE PyConsPresol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** int nnewdelconss, int nnewaddconss, int nnewupgdconss, int nnewchgcoefs, int nnewchgsides, int* nfixedvars, int* naggrvars, int* nchgvartypes, int* nchgbds, int* naddholes, int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) noexcept with gil: + cdef int i + PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] - cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) # dictionary for input/output parameters @@ -416,9 +431,10 @@ cdef SCIP_RETCODE PyConsDisable (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* return SCIP_OKAY cdef SCIP_RETCODE PyConsDelvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: + cdef int i + PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] - cdef int i for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consdelvars(constraints) From 6111ed1b0b3b2d6ca1885d71543291e8946bbefe Mon Sep 17 00:00:00 2001 From: Joao-Dionisio Date: Mon, 27 Jan 2025 13:13:34 +0100 Subject: [PATCH 07/12] fixing some more stuff --- src/pyscipopt/conshdlr.pxi | 2 +- src/pyscipopt/lp.pxi | 10 +++++----- src/pyscipopt/scip.pxi | 17 ++++++++++------- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/pyscipopt/conshdlr.pxi b/src/pyscipopt/conshdlr.pxi index 91cb0c40a..9b9bd8acc 100644 --- a/src/pyscipopt/conshdlr.pxi +++ b/src/pyscipopt/conshdlr.pxi @@ -168,9 +168,9 @@ cdef SCIP_RETCODE PyConsFree (SCIP* scip, SCIP_CONSHDLR* conshdlr) noexcept with return SCIP_OKAY cdef SCIP_RETCODE PyConsInit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: + PyConshdlr = getPyConshdlr(conshdlr) cdef int i - PyConshdlr = getPyConshdlr(conshdlr) cdef constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) diff --git a/src/pyscipopt/lp.pxi b/src/pyscipopt/lp.pxi index 2532da7f6..f6645db54 100644 --- a/src/pyscipopt/lp.pxi +++ b/src/pyscipopt/lp.pxi @@ -97,8 +97,8 @@ cdef class LP: ubs -- upper bounds (default infinity) """ - cdef ncols = len(entrieslist) - cdef nnonz = sum(len(entries) for entries in entrieslist) + cdef int ncols = len(entrieslist) + cdef int nnonz = sum(len(entries) for entries in entrieslist) cdef int i cdef SCIP_Real* c_objs = malloc(ncols * sizeof(SCIP_Real)) @@ -161,7 +161,7 @@ cdef class LP: rhs -- right-hand side of the row (default infinity) """ beg = 0 - nnonz = len(entries) + cdef int nnonz = len(entries) cdef SCIP_Real* c_coefs = malloc(nnonz * sizeof(SCIP_Real)) cdef int* c_inds = malloc(nnonz * sizeof(int)) @@ -191,8 +191,8 @@ cdef class LP: lhss -- left-hand side of the row (default 0.0) rhss -- right-hand side of the row (default infinity) """ - nrows = len(entrieslist) - nnonz = sum(len(entries) for entries in entrieslist) + cdef int nrows = len(entrieslist) + cdef int nnonz = sum(len(entries) for entries in entrieslist) cdef SCIP_Real* c_lhss = malloc(nrows * sizeof(SCIP_Real)) cdef SCIP_Real* c_rhss = malloc(nrows * sizeof(SCIP_Real)) diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi index adcad2657..2fd4fd9ea 100644 --- a/src/pyscipopt/scip.pxi +++ b/src/pyscipopt/scip.pxi @@ -4752,7 +4752,7 @@ cdef class Model: assert isinstance(conss, Iterable), "Given constraint list is not iterable." conss = list(conss) - n_conss = len(conss) + cdef int n_conss = len(conss) if isinstance(name, str): if name == "": @@ -4825,7 +4825,7 @@ cdef class Model: assert isinstance(conss, Iterable), "Given constraint list is not iterable" conss = list(conss) - n_conss = len(conss) + cdef int n_conss = len(conss) cdef SCIP_CONS* disj_cons @@ -5086,6 +5086,7 @@ cdef class Model: """ cdef SCIP_CONS* scip_cons cdef int _nvars + cdef int nvars cdef int i PY_SCIP_CALL(SCIPcreateConsSOS1(self._scip, &scip_cons, str_conversion(name), 0, NULL, NULL, @@ -5147,6 +5148,7 @@ cdef class Model: """ cdef SCIP_CONS* scip_cons cdef int _nvars + cdef int nvars cdef int i PY_SCIP_CALL(SCIPcreateConsSOS2(self._scip, &scip_cons, str_conversion(name), 0, NULL, NULL, @@ -5207,10 +5209,9 @@ cdef class Model: """ cdef SCIP_CONS* scip_cons + cdef int nvars = len(vars) cdef int idx - nvars = len(vars) - _vars = malloc(len(vars) * sizeof(SCIP_VAR*)) for idx, var in enumerate(vars): _vars[idx] = (var).scip_var @@ -5269,9 +5270,9 @@ cdef class Model: """ cdef SCIP_CONS* scip_cons + cdef int nvars = len(vars) cdef int idx - nvars = len(vars) _vars = malloc(len(vars) * sizeof(SCIP_VAR*)) for idx, var in enumerate(vars): @@ -5331,9 +5332,9 @@ cdef class Model: """ cdef SCIP_CONS* scip_cons + cdef int nvars = len(vars) cdef int idx - nvars = len(vars) assert type(rhsvar) is type(bool()), "Provide BOOLEAN value as rhsvar, you gave %s." % type(rhsvar) _vars = malloc(len(vars) * sizeof(SCIP_VAR*)) @@ -6399,6 +6400,7 @@ cdef class Model: """ cdef SCIP** subprobs cdef SCIP_BENDERS* benders + cdef int nsubproblems cdef int idx # checking whether subproblems is a dictionary @@ -9531,8 +9533,9 @@ cdef class Model: """ cdef int i + assert isinstance(gains, list) - nchildren = len(gains) + cdef int nchildren = len(gains) cdef int _nchildren = nchildren _gains = malloc(_nchildren * sizeof(SCIP_Real)) From 6950e696929430eed24e96d01e516ad151194af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Dion=C3=ADsio?= <57299939+Joao-Dionisio@users.noreply.github.com> Date: Mon, 27 Jan 2025 12:15:31 +0000 Subject: [PATCH 08/12] Update src/pyscipopt/reader.pxi Co-authored-by: DominikKamp <130753997+DominikKamp@users.noreply.github.com> --- src/pyscipopt/reader.pxi | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pyscipopt/reader.pxi b/src/pyscipopt/reader.pxi index 8672e2fae..22534dfc2 100644 --- a/src/pyscipopt/reader.pxi +++ b/src/pyscipopt/reader.pxi @@ -46,11 +46,10 @@ cdef SCIP_RETCODE PyReaderWrite (SCIP* scip, SCIP_READER* reader, FILE* file, SCIP_CONS** conss, int nconss, int maxnconss, int startnconss, SCIP_Bool genericnames, SCIP_RESULT* result) noexcept with gil: cdef SCIP_READERDATA* readerdata - cdef int i + cdef int fd = fileno(file) + cdef int i readerdata = SCIPreaderGetData(reader) - cdef int fd = fileno(file) - PyFile = os.fdopen(fd, "w", closefd=False) PyName = name.decode('utf-8') PyBinVars = [Variable.create(vars[i]) for i in range(nbinvars)] From 3946297947560fe0050ccd9a7302f8405e95a4e1 Mon Sep 17 00:00:00 2001 From: Joao-Dionisio Date: Mon, 27 Jan 2025 14:47:00 +0100 Subject: [PATCH 09/12] added some consistency to variable names --- src/pyscipopt/scip.pxi | 70 ++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi index 2fd4fd9ea..a5ffa6b33 100644 --- a/src/pyscipopt/scip.pxi +++ b/src/pyscipopt/scip.pxi @@ -1184,9 +1184,9 @@ cdef class DomainChanges: list of BoundChange """ + cdef nboundchgs = SCIPdomchgGetNBoundchgs(self.scip_domchg) cdef int i - nboundchgs = SCIPdomchgGetNBoundchgs(self.scip_domchg) return [BoundChange.create(SCIPdomchgGetBoundchg(self.scip_domchg, i)) for i in range(nboundchgs)] @@ -1291,13 +1291,13 @@ cdef class Node: """ cdef int addedconsssize = SCIPnodeGetNAddedConss(self.scip_node) - cdef int i if addedconsssize == 0: return [] cdef SCIP_CONS** addedconss = malloc(addedconsssize * sizeof(SCIP_CONS*)) cdef int nconss + cdef int i SCIPnodeGetAddedConss(self.scip_node, addedconss, &nconss, addedconsssize) assert nconss == addedconsssize @@ -1372,7 +1372,6 @@ cdef class Node: """ cdef int nbranchvars = self.getNParentBranchings() - cdef int i if nbranchvars == 0: return None @@ -1380,6 +1379,7 @@ cdef class Node: cdef SCIP_VAR** branchvars = malloc(nbranchvars * sizeof(SCIP_VAR*)) cdef SCIP_Real* branchbounds = malloc(nbranchvars * sizeof(SCIP_Real)) cdef SCIP_BOUNDTYPE* boundtypes = malloc(nbranchvars * sizeof(SCIP_BOUNDTYPE)) + cdef int i SCIPnodeGetParentBranchings(self.scip_node, branchvars, branchbounds, boundtypes, &nbranchvars, nbranchvars) @@ -2736,7 +2736,7 @@ cdef class Model: """ cdef SCIP_VAR** _vars - cdef int _nvars + cdef int nvars cdef SCIP_Real coef cdef int i @@ -2752,8 +2752,8 @@ cdef class Model: # clear existing objective function self.addObjoffset(-self.getObjoffset()) _vars = SCIPgetOrigVars(self._scip) - _nvars = SCIPgetNOrigVars(self._scip) - for i in range(_nvars): + nvars = SCIPgetNOrigVars(self._scip) + for i in range(nvars): PY_SCIP_CALL(SCIPchgVarObj(self._scip, _vars[i], 0.0)) if expr[CONST] != 0.0: @@ -3429,18 +3429,18 @@ cdef class Model: """ cdef SCIP_VAR** _vars cdef SCIP_VAR* _var - cdef int _nvars + cdef int nvars cdef int i vars = [] if transformed: _vars = SCIPgetVars(self._scip) - _nvars = SCIPgetNVars(self._scip) + nvars = SCIPgetNVars(self._scip) else: _vars = SCIPgetOrigVars(self._scip) - _nvars = SCIPgetNOrigVars(self._scip) + nvars = SCIPgetNOrigVars(self._scip) - for i in range(_nvars): + for i in range(nvars): ptr = (_vars[i]) # check whether the corresponding variable exists already @@ -4373,7 +4373,6 @@ cdef class Model: cdef SCIP_CONS* scip_cons cdef int* idxs cdef int i - cdef int idx cdef int j terms = cons.expr.terms @@ -4381,7 +4380,7 @@ cdef class Model: # collect variables variables = {var.ptr():var for term in terms for var in term} variables = list(variables.values()) - varindex = {var.ptr():idx for (idx,var) in enumerate(variables)} + varindex = {var.ptr():i for (i,var) in enumerate(variables)} # create monomials for terms monomials = malloc(len(terms) * sizeof(SCIP_EXPR*)) @@ -4740,7 +4739,6 @@ cdef class Model: The created and added Constraint objects. """ - cdef int idx cdef int i def ensure_iterable(elem, length): @@ -4756,9 +4754,10 @@ cdef class Model: if isinstance(name, str): if name == "": - name = ["" for idx in range(n_conss)] + name = ["" for i in range(n_conss)] else: - name = ["%s_%s" % (name, idx) for idx in range(n_conss)] + name = ["%s_%s" % (name, i) for i in range(n_conss)] + initial = ensure_iterable(initial, n_conss) separate = ensure_iterable(separate, n_conss) enforce = ensure_iterable(enforce, n_conss) @@ -4919,16 +4918,16 @@ cdef class Model: """ cdef SCIP_Bool success - cdef int _nvars + cdef int nvars cdef int i - SCIPgetConsNVars(self._scip, constraint.scip_cons, &_nvars, &success) + SCIPgetConsNVars(self._scip, constraint.scip_cons, &nvars, &success) - cdef SCIP_VAR** _vars = malloc(_nvars * sizeof(SCIP_VAR*)) - SCIPgetConsVars(self._scip, constraint.scip_cons, _vars, _nvars*sizeof(SCIP_VAR*), &success) + cdef SCIP_VAR** _vars = malloc(nvars * sizeof(SCIP_VAR*)) + SCIPgetConsVars(self._scip, constraint.scip_cons, _vars, nvars*sizeof(SCIP_VAR*), &success) vars = [] - for i in range(_nvars): + for i in range(nvars): ptr = (_vars[i]) # check whether the corresponding variable exists already if ptr in self._modelvars: @@ -5085,7 +5084,6 @@ cdef class Model: """ cdef SCIP_CONS* scip_cons - cdef int _nvars cdef int nvars cdef int i @@ -5147,7 +5145,6 @@ cdef class Model: """ cdef SCIP_CONS* scip_cons - cdef int _nvars cdef int nvars cdef int i @@ -5210,11 +5207,11 @@ cdef class Model: """ cdef SCIP_CONS* scip_cons cdef int nvars = len(vars) - cdef int idx + cdef int i _vars = malloc(len(vars) * sizeof(SCIP_VAR*)) - for idx, var in enumerate(vars): - _vars[idx] = (var).scip_var + for i, var in enumerate(vars): + _vars[i] = (var).scip_var _resVar = (resvar).scip_var PY_SCIP_CALL(SCIPcreateConsAnd(self._scip, &scip_cons, str_conversion(name), _resVar, nvars, _vars, @@ -5271,12 +5268,11 @@ cdef class Model: """ cdef SCIP_CONS* scip_cons cdef int nvars = len(vars) - cdef int idx - + cdef int i _vars = malloc(len(vars) * sizeof(SCIP_VAR*)) - for idx, var in enumerate(vars): - _vars[idx] = (var).scip_var + for i, var in enumerate(vars): + _vars[i] = (var).scip_var _resVar = (resvar).scip_var PY_SCIP_CALL(SCIPcreateConsOr(self._scip, &scip_cons, str_conversion(name), _resVar, nvars, _vars, @@ -8583,12 +8579,12 @@ cdef class Model: """ assert SCIPhasPrimalRay(self._scip), "The problem does not have a primal ray." - cdef int _nvars = SCIPgetNVars(self._scip) + cdef int nvars = SCIPgetNVars(self._scip) cdef SCIP_VAR ** _vars = SCIPgetVars(self._scip) cdef int i ray = [] - for i in range(_nvars): + for i in range(nvars): ray.append(float(SCIPgetPrimalRayVal(self._scip, _vars[i]))) return ray @@ -9325,13 +9321,13 @@ cdef class Model: raise ValueError("Constant offsets in objective are not supported!") cdef SCIP_VAR** _vars - cdef int _nvars + cdef int nvars _vars = SCIPgetOrigVars(self._scip) - _nvars = SCIPgetNOrigVars(self._scip) - _coeffs = malloc(_nvars * sizeof(SCIP_Real)) + nvars = SCIPgetNOrigVars(self._scip) + _coeffs = malloc(nvars * sizeof(SCIP_Real)) - for i in range(_nvars): + for i in range(nvars): _coeffs[i] = 0.0 for term, coef in coeffs.terms.items(): @@ -9339,11 +9335,11 @@ cdef class Model: if term != CONST: assert len(term) == 1 var = term[0] - for i in range(_nvars): + for i in range(nvars): if _vars[i] == var.scip_var: _coeffs[i] = coef - PY_SCIP_CALL(SCIPchgReoptObjective(self._scip, objsense, _vars, &_coeffs[0], _nvars)) + PY_SCIP_CALL(SCIPchgReoptObjective(self._scip, objsense, _vars, &_coeffs[0], nvars)) free(_coeffs) From a36a72c0a83bcf55df80a5a131622a5121556ac2 Mon Sep 17 00:00:00 2001 From: Dominik Kamp Date: Sat, 1 Feb 2025 10:11:55 +0100 Subject: [PATCH 10/12] Remove additional lines --- src/pyscipopt/scip.pxi | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi index a5ffa6b33..130486a2d 100644 --- a/src/pyscipopt/scip.pxi +++ b/src/pyscipopt/scip.pxi @@ -808,7 +808,6 @@ cdef class Row: """ cdef SCIP_COL** cols = SCIProwGetCols(self.scip_row) cdef int i - return [Column.create(cols[i]) for i in range(self.getNNonz())] def getVals(self): @@ -822,7 +821,6 @@ cdef class Row: """ cdef SCIP_Real* vals = SCIProwGetVals(self.scip_row) cdef int i - return [vals[i] for i in range(self.getNNonz())] def getAge(self): @@ -908,7 +906,6 @@ cdef class NLRow: cdef SCIP_Real* lincoefs = SCIPnlrowGetLinearCoefs(self.scip_nlrow) cdef int nlinvars = SCIPnlrowGetNLinearVars(self.scip_nlrow) cdef int i - return [(Variable.create(linvars[i]), lincoefs[i]) for i in range(nlinvars)] def getLhs(self): @@ -988,7 +985,6 @@ cdef class Solution: def __getitem__(self, Expr expr): # fast track for Variable cdef SCIP_Real coeff - if isinstance(expr, Variable): self._checkStage("SCIPgetSolVal") var = expr @@ -1008,23 +1004,19 @@ cdef class Solution: def __repr__(self): cdef SCIP_VAR* scip_var cdef int i - vals = {} self._checkStage("SCIPgetSolVal") for i in range(SCIPgetNOrigVars(self.scip)): scip_var = SCIPgetOrigVars(self.scip)[i] - # extract name cname = bytes(SCIPvarGetName(scip_var)) name = cname.decode('utf-8') - vals[name] = SCIPgetSolVal(self.scip, self.sol, scip_var) return str(vals) def _checkStage(self, method): if method in ["SCIPgetSolVal", "getSolObjVal"]: stage_check = SCIPgetStage(self.scip) not in [SCIP_STAGE_INIT, SCIP_STAGE_FREE] - if not stage_check or self.sol == NULL and SCIPgetStage(self.scip) != SCIP_STAGE_SOLVING: raise Warning(f"{method} can only be called with a valid solution or in stage SOLVING (current stage: {SCIPgetStage(self.scip)})") @@ -1058,7 +1050,6 @@ cdef class Solution: PY_SCIP_CALL(SCIPretransformSol(self.scip, self.sol)) cdef Solution targetSol = Solution.create(target._scip, NULL) cdef SCIP_VAR** source_vars = SCIPgetOrigVars(self.scip) - PY_SCIP_CALL(SCIPtranslateSubSol(target._scip, self.scip, self.sol, NULL, source_vars, &(targetSol.sol))) return targetSol @@ -1186,7 +1177,6 @@ cdef class DomainChanges: """ cdef nboundchgs = SCIPdomchgGetNBoundchgs(self.scip_domchg) cdef int i - return [BoundChange.create(SCIPdomchgGetBoundchg(self.scip_domchg, i)) for i in range(nboundchgs)] @@ -1291,14 +1281,11 @@ cdef class Node: """ cdef int addedconsssize = SCIPnodeGetNAddedConss(self.scip_node) - if addedconsssize == 0: return [] - cdef SCIP_CONS** addedconss = malloc(addedconsssize * sizeof(SCIP_CONS*)) cdef int nconss cdef int i - SCIPnodeGetAddedConss(self.scip_node, addedconss, &nconss, addedconsssize) assert nconss == addedconsssize constraints = [Constraint.create(addedconss[i]) for i in range(nconss)] @@ -1351,7 +1338,6 @@ cdef class Node: cdef SCIP_Real dummy_branchbounds cdef SCIP_BOUNDTYPE dummy_boundtypes cdef int nbranchvars - # This is a hack: the SCIP interface has no function to directly get the # number of parent branchings, i.e., SCIPnodeGetNParentBranchings() does # not exist. @@ -1372,22 +1358,18 @@ cdef class Node: """ cdef int nbranchvars = self.getNParentBranchings() - if nbranchvars == 0: return None - cdef SCIP_VAR** branchvars = malloc(nbranchvars * sizeof(SCIP_VAR*)) cdef SCIP_Real* branchbounds = malloc(nbranchvars * sizeof(SCIP_Real)) cdef SCIP_BOUNDTYPE* boundtypes = malloc(nbranchvars * sizeof(SCIP_BOUNDTYPE)) cdef int i - SCIPnodeGetParentBranchings(self.scip_node, branchvars, branchbounds, boundtypes, &nbranchvars, nbranchvars) py_variables = [Variable.create(branchvars[i]) for i in range(nbranchvars)] py_branchbounds = [branchbounds[i] for i in range(nbranchvars)] py_boundtypes = [boundtypes[i] for i in range(nbranchvars)] - free(boundtypes) free(branchbounds) free(branchvars) @@ -1407,7 +1389,6 @@ cdef class Node: cdef int nbranchings cdef int nconsprop cdef int nprop - SCIPnodeGetNDomchg(self.scip_node, &nbranchings, &nconsprop, &nprop) return nbranchings, nconsprop, nprop @@ -1657,7 +1638,6 @@ cdef class Variable(Expr): mayround = SCIPvarMayRoundDown(self.scip_var) else: mayround = SCIPvarMayRoundUp(self.scip_var) - return mayround cdef class Constraint: @@ -10088,7 +10068,7 @@ def readStatistics(filename): stats = Statistics(**treated_result) return stats - + # debugging memory management def is_memory_freed(): return BMSgetMemoryUsed() == 0 From d81eb69f04dac5b369310f0260243a8356f1dbe9 Mon Sep 17 00:00:00 2001 From: Dominik Kamp Date: Sat, 1 Feb 2025 17:32:06 +0100 Subject: [PATCH 11/12] Reorder variable declarations --- src/pyscipopt/scip.pxi | 292 ++++++++++++++++++++--------------------- 1 file changed, 144 insertions(+), 148 deletions(-) diff --git a/src/pyscipopt/scip.pxi b/src/pyscipopt/scip.pxi index 130486a2d..5636d5788 100644 --- a/src/pyscipopt/scip.pxi +++ b/src/pyscipopt/scip.pxi @@ -1175,7 +1175,7 @@ cdef class DomainChanges: list of BoundChange """ - cdef nboundchgs = SCIPdomchgGetNBoundchgs(self.scip_domchg) + cdef int nboundchgs = SCIPdomchgGetNBoundchgs(self.scip_domchg) cdef int i return [BoundChange.create(SCIPdomchgGetBoundchg(self.scip_domchg, i)) for i in range(nboundchgs)] @@ -2664,6 +2664,7 @@ cdef class Model: PY_SCIP_CALL(SCIPgetLPI(self._scip, &lpi)) PY_SCIP_CALL(SCIPlpiGetIterations(lpi, &iters)) + return iters # Objective function @@ -2714,11 +2715,10 @@ cdef class Model: set all other variables objective coefficient to zero (Default value = 'true') """ - - cdef SCIP_VAR** _vars + cdef SCIP_VAR** vars cdef int nvars cdef SCIP_Real coef - cdef int i + cdef int i # turn the constant value into an Expr instance for further processing if not isinstance(expr, Expr): @@ -2731,10 +2731,10 @@ cdef class Model: if clear: # clear existing objective function self.addObjoffset(-self.getObjoffset()) - _vars = SCIPgetOrigVars(self._scip) + vars = SCIPgetOrigVars(self._scip) nvars = SCIPgetNOrigVars(self._scip) for i in range(nvars): - PY_SCIP_CALL(SCIPchgVarObj(self._scip, _vars[i], 0.0)) + PY_SCIP_CALL(SCIPchgVarObj(self._scip, vars[i], 0.0)) if expr[CONST] != 0.0: self.addObjoffset(expr[CONST]) @@ -3408,7 +3408,6 @@ cdef class Model: """ cdef SCIP_VAR** _vars - cdef SCIP_VAR* _var cdef int nvars cdef int i @@ -3706,6 +3705,7 @@ cdef class Model: cdef int i PY_SCIP_CALL(SCIPgetLPColsData(self._scip, &cols, &ncols)) + return [Column.create(cols[i]) for i in range(ncols)] def getLPRowsData(self): @@ -3722,6 +3722,7 @@ cdef class Model: cdef int i PY_SCIP_CALL(SCIPgetLPRowsData(self._scip, &rows, &nrows)) + return [Row.create(rows[i]) for i in range(nrows)] def getNLPRows(self): @@ -3763,6 +3764,7 @@ cdef class Model: PY_SCIP_CALL(SCIPgetLPBasisInd(self._scip, inds)) result = [inds[i] for i in range(nrows)] free(inds) + return result def getLPBInvRow(self, row): @@ -3783,10 +3785,11 @@ cdef class Model: cdef int nrows = SCIPgetNLPRows(self._scip) cdef SCIP_Real* coefs = malloc(nrows * sizeof(SCIP_Real)) cdef int i - + PY_SCIP_CALL(SCIPgetLPBInvRow(self._scip, row, coefs, NULL, NULL)) result = [coefs[i] for i in range(nrows)] free(coefs) + return result def getLPBInvARow(self, row): @@ -3807,10 +3810,11 @@ cdef class Model: cdef int ncols = SCIPgetNLPCols(self._scip) cdef SCIP_Real* coefs = malloc(ncols * sizeof(SCIP_Real)) cdef int i - + PY_SCIP_CALL(SCIPgetLPBInvARow(self._scip, row, NULL, coefs, NULL, NULL)) result = [coefs[i] for i in range(ncols)] free(coefs) + return result def isLPSolBasic(self): @@ -4254,14 +4258,13 @@ cdef class Model: assert lincons.expr.degree() <= 1, "given constraint is not linear, degree == %d" % lincons.expr.degree() terms = lincons.expr.terms - cdef SCIP_CONS* scip_cons cdef int nvars = len(terms.items()) + cdef SCIP_VAR** vars_array = malloc(nvars * sizeof(SCIP_VAR*)) + cdef SCIP_Real* coeffs_array = malloc(nvars * sizeof(SCIP_Real)) + cdef SCIP_CONS* scip_cons cdef SCIP_Real coeff cdef int i - vars_array = malloc(nvars * sizeof(SCIP_VAR*)) - coeffs_array = malloc(nvars * sizeof(SCIP_Real)) - for i, (key, coeff) in enumerate(terms.items()): vars_array[i] = (key[0]).scip_var coeffs_array[i] = coeff @@ -4277,6 +4280,7 @@ cdef class Model: free(vars_array) free(coeffs_array) + return PyCons def _createConsQuadratic(self, ExprCons quadcons, **kwargs): @@ -4358,9 +4362,9 @@ cdef class Model: terms = cons.expr.terms # collect variables - variables = {var.ptr():var for term in terms for var in term} + variables = {var.ptr(): var for term in terms for var in term} variables = list(variables.values()) - varindex = {var.ptr():i for (i,var) in enumerate(variables)} + varindex = {var.ptr(): i for (i, var) in enumerate(variables)} # create monomials for terms monomials = malloc(len(terms) * sizeof(SCIP_EXPR*)) @@ -4401,6 +4405,7 @@ cdef class Model: PY_SCIP_CALL(SCIPreleaseExpr(self._scip, &monomials[i])) free(monomials) free(termcoefs) + return PyCons def _createConsGenNonlinear(self, cons, **kwargs): @@ -4719,6 +4724,7 @@ cdef class Model: The created and added Constraint objects. """ + cdef int n_conss cdef int i def ensure_iterable(elem, length): @@ -4730,7 +4736,7 @@ cdef class Model: assert isinstance(conss, Iterable), "Given constraint list is not iterable." conss = list(conss) - cdef int n_conss = len(conss) + n_conss = len(conss) if isinstance(name, str): if name == "": @@ -4794,6 +4800,10 @@ cdef class Model: The created disjunction constraint """ + cdef SCIP_EXPR* scip_expr + cdef SCIP_CONS* scip_cons + cdef SCIP_CONS* disj_cons + cdef int n_conss cdef int i def ensure_iterable(elem, length): @@ -4804,13 +4814,7 @@ cdef class Model: assert isinstance(conss, Iterable), "Given constraint list is not iterable" conss = list(conss) - cdef int n_conss = len(conss) - - cdef SCIP_CONS* disj_cons - - cdef SCIP_CONS* scip_cons - - cdef SCIP_EXPR* scip_expr + n_conss = len(conss) PY_SCIP_CALL(SCIPcreateConsDisjunction( self._scip, &disj_cons, str_conversion(name), 0, &scip_cons, NULL, @@ -4829,6 +4833,7 @@ cdef class Model: PY_SCIP_CALL(SCIPaddCons(self._scip, disj_cons)) PyCons = Constraint.create(disj_cons) PY_SCIP_CALL(SCIPreleaseCons(self._scip, &disj_cons)) + return PyCons def addConsElemDisjunction(self, Constraint disj_cons, Constraint cons): @@ -4897,13 +4902,13 @@ cdef class Model: list of Variable """ - cdef SCIP_Bool success + cdef SCIP_VAR** _vars cdef int nvars + cdef SCIP_Bool success cdef int i SCIPgetConsNVars(self._scip, constraint.scip_cons, &nvars, &success) - - cdef SCIP_VAR** _vars = malloc(nvars * sizeof(SCIP_VAR*)) + _vars = malloc(nvars * sizeof(SCIP_VAR*)) SCIPgetConsVars(self._scip, constraint.scip_cons, _vars, nvars*sizeof(SCIP_VAR*), &success) vars = [] @@ -4918,6 +4923,7 @@ cdef class Model: assert var.ptr() == ptr self._modelvars[ptr] = var vars.append(var) + return vars def printCons(self, Constraint constraint): @@ -5081,6 +5087,7 @@ cdef class Model: PY_SCIP_CALL(SCIPaddVarSOS1(self._scip, scip_cons, var.scip_var, weights[i])) PY_SCIP_CALL(SCIPaddCons(self._scip, scip_cons)) + return Constraint.create(scip_cons) def addConsSOS2(self, vars, weights=None, name="SOS2cons", @@ -5142,7 +5149,8 @@ cdef class Model: PY_SCIP_CALL(SCIPaddVarSOS2(self._scip, scip_cons, var.scip_var, weights[i])) PY_SCIP_CALL(SCIPaddCons(self._scip, scip_cons)) - return Constraint.create(scip_cons) + + return Constraint.create(scip_cons) def addConsAnd(self, vars, resvar, name="ANDcons", initial=True, separate=True, enforce=True, check=True, @@ -5185,16 +5193,17 @@ cdef class Model: The newly created AND constraint """ - cdef SCIP_CONS* scip_cons cdef int nvars = len(vars) + cdef SCIP_VAR** _vars = malloc(nvars * sizeof(SCIP_VAR*)) + cdef SCIP_VAR* _resvar + cdef SCIP_CONS* scip_cons cdef int i - _vars = malloc(len(vars) * sizeof(SCIP_VAR*)) + _resvar = (resvar).scip_var for i, var in enumerate(vars): _vars[i] = (var).scip_var - _resVar = (resvar).scip_var - PY_SCIP_CALL(SCIPcreateConsAnd(self._scip, &scip_cons, str_conversion(name), _resVar, nvars, _vars, + PY_SCIP_CALL(SCIPcreateConsAnd(self._scip, &scip_cons, str_conversion(name), _resvar, nvars, _vars, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode)) PY_SCIP_CALL(SCIPaddCons(self._scip, scip_cons)) @@ -5246,16 +5255,17 @@ cdef class Model: The newly created OR constraint """ - cdef SCIP_CONS* scip_cons cdef int nvars = len(vars) + cdef SCIP_VAR** _vars = malloc(nvars * sizeof(SCIP_VAR*)) + cdef SCIP_VAR* _resvar + cdef SCIP_CONS* scip_cons cdef int i - _vars = malloc(len(vars) * sizeof(SCIP_VAR*)) + _resvar = (resvar).scip_var for i, var in enumerate(vars): _vars[i] = (var).scip_var - _resVar = (resvar).scip_var - PY_SCIP_CALL(SCIPcreateConsOr(self._scip, &scip_cons, str_conversion(name), _resVar, nvars, _vars, + PY_SCIP_CALL(SCIPcreateConsOr(self._scip, &scip_cons, str_conversion(name), _resvar, nvars, _vars, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode)) PY_SCIP_CALL(SCIPaddCons(self._scip, scip_cons)) @@ -5307,15 +5317,14 @@ cdef class Model: The newly created XOR constraint """ - cdef SCIP_CONS* scip_cons cdef int nvars = len(vars) - cdef int idx - + cdef SCIP_VAR** _vars = malloc(nvars * sizeof(SCIP_VAR*)) + cdef SCIP_CONS* scip_cons + cdef int i assert type(rhsvar) is type(bool()), "Provide BOOLEAN value as rhsvar, you gave %s." % type(rhsvar) - _vars = malloc(len(vars) * sizeof(SCIP_VAR*)) - for idx, var in enumerate(vars): - _vars[idx] = (var).scip_var + for i, var in enumerate(vars): + _vars[i] = (var).scip_var PY_SCIP_CALL(SCIPcreateConsXor(self._scip, &scip_cons, str_conversion(name), rhsvar, nvars, _vars, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode)) @@ -5376,8 +5385,8 @@ cdef class Model: The newly created Cardinality constraint """ - cdef SCIP_CONS* scip_cons cdef SCIP_VAR* indvar + cdef SCIP_CONS* scip_cons cdef int i PY_SCIP_CALL(SCIPcreateConsCardinality(self._scip, &scip_cons, str_conversion(name), 0, NULL, cardval, NULL, NULL, @@ -5450,10 +5459,10 @@ cdef class Model: The newly created Indicator constraint """ - assert isinstance(cons, ExprCons), "given constraint is not ExprCons but %s" % cons.__class__.__name__ - cdef SCIP_CONS* scip_cons cdef SCIP_VAR* _binVar - cdef SCIP_Real coeff + cdef SCIP_CONS* scip_cons + cdef SCIP_Real coeff + assert isinstance(cons, ExprCons), "given constraint is not ExprCons but %s" % cons.__class__.__name__ if cons._lhs is not None and cons._rhs is not None: raise ValueError("expected inequality that has either only a left or right hand side") @@ -5913,10 +5922,9 @@ cdef class Model: list of NLRow """ - cdef SCIP_NLROW** nlrows + cdef SCIP_NLROW** nlrows = SCIPgetNLPNlRows(self._scip) cdef int i - nlrows = SCIPgetNLPNlRows(self._scip) return [NLRow.create(nlrows[i]) for i in range(self.getNNlRows())] def getNlRowSolActivity(self, NLRow nlrow, Solution sol = None): @@ -6029,21 +6037,21 @@ cdef class Model: cdef int termidx # linear terms - cdef SCIP_EXPR** _linexprs - cdef SCIP_Real* _lincoefs - cdef int _nlinvars + cdef SCIP_EXPR** linexprs + cdef SCIP_Real* lincoefs + cdef SCIP_Real lincoef + cdef int nlinvars # bilinear terms - cdef int _nbilinterms cdef SCIP_EXPR* bilinterm1 cdef SCIP_EXPR* bilinterm2 cdef SCIP_Real bilincoef + cdef int nbilinterms # quadratic terms - cdef int _nquadterms - cdef SCIP_Real sqrcoef - cdef SCIP_Real lincoef cdef SCIP_EXPR* sqrexpr + cdef SCIP_Real sqrcoef + cdef int nquadterms # variables cdef SCIP_VAR* scipvar1 @@ -6053,17 +6061,17 @@ cdef class Model: assert self.checkQuadraticNonlinear(cons), "constraint is not quadratic" expr = SCIPgetExprNonlinear(cons.scip_cons) - SCIPexprGetQuadraticData(expr, NULL, &_nlinvars, &_linexprs, &_lincoefs, &_nquadterms, &_nbilinterms, NULL, NULL) + SCIPexprGetQuadraticData(expr, NULL, &nlinvars, &linexprs, &lincoefs, &nquadterms, &nbilinterms, NULL, NULL) linterms = [] bilinterms = [] quadterms = [] - for termidx in range(_nlinvars): - var = Variable.create(SCIPgetVarExprVar(_linexprs[termidx])) - linterms.append((var,_lincoefs[termidx])) + for termidx in range(nlinvars): + var = Variable.create(SCIPgetVarExprVar(linexprs[termidx])) + linterms.append((var, lincoefs[termidx])) - for termidx in range(_nbilinterms): + for termidx in range(nbilinterms): SCIPexprGetQuadraticBilinTerm(expr, termidx, &bilinterm1, &bilinterm2, &bilincoef, NULL, NULL) scipvar1 = SCIPgetVarExprVar(bilinterm1) scipvar2 = SCIPgetVarExprVar(bilinterm2) @@ -6074,7 +6082,7 @@ cdef class Model: else: quadterms.append((var1,bilincoef,0.0)) - for termidx in range(_nquadterms): + for termidx in range(nquadterms): SCIPexprGetQuadraticQuadTerm(expr, termidx, NULL, &lincoef, &sqrcoef, NULL, NULL, &sqrexpr) if sqrexpr == NULL: continue @@ -6109,19 +6117,18 @@ cdef class Model: list of Constraint """ - cdef SCIP_CONS** _conss - cdef int _nconss + cdef SCIP_CONS** conss + cdef int nconss cdef int i - conss = [] - if transformed: - _conss = SCIPgetConss(self._scip) - _nconss = SCIPgetNConss(self._scip) + conss = SCIPgetConss(self._scip) + nconss = SCIPgetNConss(self._scip) else: - _conss = SCIPgetOrigConss(self._scip) - _nconss = SCIPgetNOrigConss(self._scip) - return [Constraint.create(_conss[i]) for i in range(_nconss)] + conss = SCIPgetOrigConss(self._scip) + nconss = SCIPgetNOrigConss(self._scip) + + return [Constraint.create(conss[i]) for i in range(nconss)] def getNConss(self, transformed=True): """ @@ -6180,20 +6187,21 @@ cdef class Model: dict of str to float """ - cdef SCIP_Real* _vals - cdef SCIP_VAR** _vars + cdef SCIP_VAR** vars + cdef SCIP_Real* vals cdef int i constype = bytes(SCIPconshdlrGetName(SCIPconsGetHdlr(cons.scip_cons))).decode('UTF-8') if not constype == 'linear': raise Warning("coefficients not available for constraints of type ", constype) - _vals = SCIPgetValsLinear(self._scip, cons.scip_cons) - _vars = SCIPgetVarsLinear(self._scip, cons.scip_cons) + vals = SCIPgetValsLinear(self._scip, cons.scip_cons) + vars = SCIPgetVarsLinear(self._scip, cons.scip_cons) valsdict = {} for i in range(SCIPgetNVarsLinear(self._scip, cons.scip_cons)): - valsdict[bytes(SCIPvarGetName(_vars[i])).decode('utf-8')] = _vals[i] + valsdict[bytes(SCIPvarGetName(vars[i])).decode('utf-8')] = vals[i] + return valsdict def getRowLinear(self, Constraint cons): @@ -6377,7 +6385,7 @@ cdef class Model: cdef SCIP** subprobs cdef SCIP_BENDERS* benders cdef int nsubproblems - cdef int idx + cdef int i # checking whether subproblems is a dictionary if isinstance(subproblems, dict): @@ -6392,8 +6400,8 @@ cdef class Model: # if subproblems is a dictionary, then the dictionary is turned into a c array if isdict: - for idx, subprob in enumerate(subproblems.values()): - subprobs[idx] = (subprob)._scip + for i, subprob in enumerate(subproblems.values()): + subprobs[i] = (subprob)._scip else: subprobs[0] = (subproblems)._scip @@ -6413,44 +6421,37 @@ cdef class Model: If the user wants to resolve the subproblems, they must free them by calling freeBendersSubproblems() """ - cdef SCIP_BENDERS** _benders - cdef SCIP_Bool _infeasible - cdef int nbenders + cdef SCIP_BENDERS** benders = SCIPgetBenders(self._scip) + cdef SCIP_Bool infeasible + cdef SCIP_Bool solvecip = True + cdef int nbenders = SCIPgetNActiveBenders(self._scip) cdef int nsubproblems cdef int i cdef int j - solvecip = True - - nbenders = SCIPgetNActiveBenders(self._scip) - _benders = SCIPgetBenders(self._scip) - # solving all subproblems from all Benders' decompositions for i in range(nbenders): - nsubproblems = SCIPbendersGetNSubproblems(_benders[i]) + nsubproblems = SCIPbendersGetNSubproblems(benders[i]) for j in range(nsubproblems): PY_SCIP_CALL(SCIPsetupBendersSubproblem(self._scip, - _benders[i], self._bestSol.sol, j, SCIP_BENDERSENFOTYPE_CHECK)) + benders[i], self._bestSol.sol, j, SCIP_BENDERSENFOTYPE_CHECK)) PY_SCIP_CALL(SCIPsolveBendersSubproblem(self._scip, - _benders[i], self._bestSol.sol, j, &_infeasible, solvecip, NULL)) + benders[i], self._bestSol.sol, j, &infeasible, solvecip, NULL)) def freeBendersSubproblems(self): """Calls the free subproblem function for the Benders' decomposition. This will free all subproblems for all decompositions. """ - cdef SCIP_BENDERS** _benders - cdef int nbenders + cdef SCIP_BENDERS** benders = SCIPgetBenders(self._scip) + cdef int nbenders = SCIPgetNActiveBenders(self._scip) cdef int nsubproblems cdef int i cdef int j - nbenders = SCIPgetNActiveBenders(self._scip) - _benders = SCIPgetBenders(self._scip) - # solving all subproblems from all Benders' decompositions for i in range(nbenders): - nsubproblems = SCIPbendersGetNSubproblems(_benders[i]) + nsubproblems = SCIPbendersGetNSubproblems(benders[i]) for j in range(nsubproblems): - PY_SCIP_CALL(SCIPfreeBendersSubproblem(self._scip, _benders[i], + PY_SCIP_CALL(SCIPfreeBendersSubproblem(self._scip, benders[i], j)) def updateBendersLowerbounds(self, lowerbounds, Benders benders=None): @@ -6887,13 +6888,17 @@ cdef class Model: model : Model A model containing the created copy """ + cdef SCIP* subscip + cdef SCIP_HASHMAP* varmap + cdef SCIP_VAR** orig_vars = SCIPgetVars(self._scip) + cdef SCIP_VAR** vars = malloc(len(to_fix) * sizeof(SCIP_VAR*)) + cdef SCIP_Real* vals = malloc(len(fix_vals) * sizeof(SCIP_Real)) cdef SCIP_Real val + cdef SCIP_Bool valid + cdef SCIP_Bool success cdef int i + cdef int j = 0 - orig_vars = SCIPgetVars(self._scip) - vars = malloc(len(to_fix) * sizeof(SCIP_VAR*)) - vals = malloc(len(fix_vals) * sizeof(SCIP_Real)) - j = 0 name_to_val = {var.name: val for var, val in zip(to_fix, fix_vals)} for i, var in enumerate(self.getVars()): if var.name in name_to_val: @@ -6901,11 +6906,6 @@ cdef class Model: vals[j] = name_to_val[var.name] j+= 1 - cdef SCIP_Bool success - cdef SCIP_Bool valid - cdef SCIP* subscip - cdef SCIP_HASHMAP* varmap - PY_SCIP_CALL(SCIPcreate(&subscip)) PY_SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(subscip), self.getNVars()) ) PY_SCIP_CALL( SCIPcopyLargeNeighborhoodSearch(self._scip, subscip, varmap, "LNhS_subscip", vars, vals, @@ -6915,6 +6915,7 @@ cdef class Model: free(vars) free(vals) SCIPhashmapFree(&varmap) + return sub_model def translateSubSol(self, Model sub_model, Solution sol, heur) -> Solution: @@ -6935,22 +6936,22 @@ cdef class Model: solution : Solution The corresponding solution in the main model """ - cdef int i - + cdef SCIP_VAR** vars = malloc(self.getNVars() * sizeof(SCIP_VAR*)) cdef SCIP_SOL* real_sol - cdef SCIP_SOL* subscip_sol + cdef SCIP_SOL* subscip_sol = sol.sol + cdef SCIP_HEUR* _heur cdef SCIP_Bool success - subscip_sol = sol.sol - vars = malloc(self.getNVars() * sizeof(SCIP_VAR*)) + cdef int i + for i, var in enumerate(sub_model.getVars()): vars[i] = (var).scip_var - cdef SCIP_HEUR* _heur name = str_conversion(heur.name) _heur = SCIPfindHeur(self._scip, name) PY_SCIP_CALL( SCIPtranslateSubSol(self._scip, sub_model._scip, subscip_sol, _heur, vars, &real_sol) ) solution = Solution.create(self._scip, real_sol) free(vars) + return solution def createCons(self, Conshdlr conshdlr, name, initial=True, separate=True, enforce=True, check=True, propagate=True, @@ -7399,16 +7400,15 @@ cdef class Model: number of fractional implicit integer variables """ + cdef SCIP_VAR** lpcands + cdef SCIP_Real* lpcandssol + cdef SCIP_Real* lpcandsfrac cdef int ncands cdef int nlpcands cdef int npriolpcands cdef int nfracimplvars cdef int i - cdef SCIP_VAR** lpcands - cdef SCIP_Real* lpcandssol - cdef SCIP_Real* lpcandsfrac - PY_SCIP_CALL(SCIPgetLPBranchCands(self._scip, &lpcands, &lpcandssol, &lpcandsfrac, &nlpcands, &npriolpcands, &nfracimplvars)) @@ -7430,12 +7430,11 @@ cdef class Model: number of candidates with maximal priority """ + cdef SCIP_VAR** pseudocands cdef int npseudocands cdef int npriopseudocands cdef int i - cdef SCIP_VAR** pseudocands - PY_SCIP_CALL(SCIPgetPseudoBranchCands(self._scip, &pseudocands, &npseudocands, &npriopseudocands)) return ([Variable.create(pseudocands[i]) for i in range(npseudocands)], npseudocands, npriopseudocands) @@ -8369,12 +8368,10 @@ cdef class Model: list of Solution """ - cdef SCIP_SOL** _sols - cdef SCIP_SOL* _sol + cdef SCIP_SOL** _sols = SCIPgetSols(self._scip) + cdef int nsols = SCIPgetNSols(self._scip) cdef int i - _sols = SCIPgetSols(self._scip) - nsols = SCIPgetNSols(self._scip) sols = [] for i in range(nsols): @@ -8559,13 +8556,13 @@ cdef class Model: """ assert SCIPhasPrimalRay(self._scip), "The problem does not have a primal ray." + cdef SCIP_VAR** vars = SCIPgetVars(self._scip) cdef int nvars = SCIPgetNVars(self._scip) - cdef SCIP_VAR ** _vars = SCIPgetVars(self._scip) cdef int i ray = [] for i in range(nvars): - ray.append(float(SCIPgetPrimalRayVal(self._scip, _vars[i]))) + ray.append(float(SCIPgetPrimalRayVal(self._scip, vars[i]))) return ray @@ -8644,8 +8641,6 @@ cdef class Model: def _getStageNames(self): """Gets names of stages.""" - cdef str name - for name in dir(PY_SCIP_STAGE): attr = getattr(PY_SCIP_STAGE, name) if isinstance(attr, int): @@ -9092,14 +9087,14 @@ cdef class Model: dict mapping parameter names to their values. """ - cdef SCIP_PARAM** params + cdef SCIP_PARAM** params = SCIPgetParams(self._scip) cdef int i - params = SCIPgetParams(self._scip) result = {} for i in range(SCIPgetNParams(self._scip)): name = SCIPparamGetName(params[i]).decode('utf-8') result[name] = self.getParam(name) + return result def setParams(self, params): @@ -9112,7 +9107,6 @@ cdef class Model: dict mapping parameter names to their values. """ - cdef str name for name, value in params.items(): self.setParam(name, value) @@ -9281,7 +9275,9 @@ cdef class Model: the objective sense (Default value = 'minimize') """ - + cdef SCIP_VAR** vars + cdef int nvars + cdef SCIP_Real* _coeffs cdef SCIP_OBJSENSE objsense cdef SCIP_Real coef cdef int i @@ -9300,10 +9296,7 @@ cdef class Model: if coeffs[CONST] != 0.0: raise ValueError("Constant offsets in objective are not supported!") - cdef SCIP_VAR** _vars - cdef int nvars - - _vars = SCIPgetOrigVars(self._scip) + vars = SCIPgetOrigVars(self._scip) nvars = SCIPgetNOrigVars(self._scip) _coeffs = malloc(nvars * sizeof(SCIP_Real)) @@ -9316,10 +9309,10 @@ cdef class Model: assert len(term) == 1 var = term[0] for i in range(nvars): - if _vars[i] == var.scip_var: + if vars[i] == var.scip_var: _coeffs[i] = coef - PY_SCIP_CALL(SCIPchgReoptObjective(self._scip, objsense, _vars, &_coeffs[0], nvars)) + PY_SCIP_CALL(SCIPchgReoptObjective(self._scip, objsense, vars, &_coeffs[0], nvars)) free(_coeffs) @@ -9508,17 +9501,15 @@ cdef class Model: float """ - cdef int i - assert isinstance(gains, list) cdef int nchildren = len(gains) + cdef SCIP_Real* _gains = malloc(nchildren * sizeof(SCIP_Real)) + cdef int i - cdef int _nchildren = nchildren - _gains = malloc(_nchildren * sizeof(SCIP_Real)) - for i in range(_nchildren): + for i in range(nchildren): _gains[i] = gains[i] - score = SCIPgetBranchScoreMultiple(self._scip, var.scip_var, _nchildren, _gains) + score = SCIPgetBranchScoreMultiple(self._scip, var.scip_var, nchildren, _gains) free(_gains) @@ -9576,11 +9567,13 @@ cdef class Model: The feature mappings for the columns, edges, and rows """ - cdef SCIP* scip = self._scip cdef SCIP_VARTYPE vtype cdef SCIP_Real sim, prod - cdef int i, j, k, col_i + cdef int col_i + cdef int i + cdef int j + cdef int k # Check if SCIP is in the correct stage if SCIPgetStage(scip) != SCIP_STAGE_SOLVING: @@ -9618,8 +9611,11 @@ cdef class Model: cdef SCIP_SOL* sol = SCIPgetBestSol(scip) cdef SCIP_VAR* var - cdef SCIP_Real lb, ub, solval + cdef SCIP_Real lb + cdef SCIP_Real ub + cdef SCIP_Real solval cdef SCIP_BASESTAT basis_status + for i in range(ncols): col_i = SCIPcolGetLPPos(cols[i]) var = SCIPcolGetVar(cols[i]) @@ -9712,8 +9708,10 @@ cdef class Model: raise Warning(f"Dimension mismatch in provided previous features and new features:" f"{len(prev_row_features[0])} != {n_row_features}") + cdef SCIP_Real lhs + cdef SCIP_Real rhs + cdef SCIP_Real cst cdef int nnzrs = 0 - cdef SCIP_Real lhs, rhs, cst for i in range(nrows): @@ -9771,6 +9769,7 @@ cdef class Model: # Generate edge (coefficient) features cdef SCIP_COL** row_cols cdef SCIP_Real * row_vals + n_edge_features = 3 edge_feature_map = {"col_idx": 0, "row_idx": 1, "coef": 2} if prev_edge_features is None: @@ -9798,7 +9797,6 @@ cdef class Model: raise Warning(f"Dimension mismatch in provided previous features and new features:" f"{len(prev_edge_features[0])} != 3") - return (col_features, edge_features, row_features, {"col": col_feature_map, "edge": edge_feature_map, "row": row_feature_map}) @@ -9961,9 +9959,6 @@ def readStatistics(filename): Statistics """ - cdef str line - cdef str var_type - cdef str con_type cdef int i result = {} @@ -10067,6 +10062,7 @@ def readStatistics(filename): treated_result = dict((treated_keys[key], value) for (key, value) in result.items()) stats = Statistics(**treated_result) + return stats # debugging memory management From a9261a58f8977deaace84ccf7d1657d0080bb55c Mon Sep 17 00:00:00 2001 From: Dominik Kamp Date: Sat, 1 Feb 2025 17:32:35 +0100 Subject: [PATCH 12/12] Reformat variable declarations --- src/pyscipopt/benders.pxi | 4 +- src/pyscipopt/conshdlr.pxi | 50 ++++++------------ src/pyscipopt/cutsel.pxi | 5 +- src/pyscipopt/lp.pxi | 105 ++++++++++++++++++------------------- src/pyscipopt/reader.pxi | 4 +- tests/test_event.py | 4 +- 6 files changed, 74 insertions(+), 98 deletions(-) diff --git a/src/pyscipopt/benders.pxi b/src/pyscipopt/benders.pxi index 0a592f553..4f171709a 100644 --- a/src/pyscipopt/benders.pxi +++ b/src/pyscipopt/benders.pxi @@ -175,10 +175,8 @@ cdef SCIP_RETCODE PyBendersSolvesub (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL cdef SCIP_RETCODE PyBendersPostsolve (SCIP* scip, SCIP_BENDERS* benders, SCIP_SOL* sol, SCIP_BENDERSENFOTYPE type, int* mergecands, int npriomergecands, int nmergecands, SCIP_Bool checkint, SCIP_Bool infeasible, SCIP_Bool* merged) noexcept with gil: - cdef SCIP_BENDERSDATA* bendersdata + cdef SCIP_BENDERSDATA* bendersdata = SCIPbendersGetData(benders) cdef int i - - bendersdata = SCIPbendersGetData(benders) PyBenders = bendersdata if sol == NULL: solution = None diff --git a/src/pyscipopt/conshdlr.pxi b/src/pyscipopt/conshdlr.pxi index 9b9bd8acc..2410fec47 100644 --- a/src/pyscipopt/conshdlr.pxi +++ b/src/pyscipopt/conshdlr.pxi @@ -168,10 +168,9 @@ cdef SCIP_RETCODE PyConsFree (SCIP* scip, SCIP_CONSHDLR* conshdlr) noexcept with return SCIP_OKAY cdef SCIP_RETCODE PyConsInit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: - PyConshdlr = getPyConshdlr(conshdlr) cdef int i - - cdef constraints = [] + PyConshdlr = getPyConshdlr(conshdlr) + constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consinit(constraints) @@ -179,9 +178,8 @@ cdef SCIP_RETCODE PyConsInit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** c cdef SCIP_RETCODE PyConsExit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: cdef int i - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] + constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consexit(constraints) @@ -189,9 +187,8 @@ cdef SCIP_RETCODE PyConsExit (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** c cdef SCIP_RETCODE PyConsInitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: cdef int i - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] + constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consinitpre(constraints) @@ -199,9 +196,8 @@ cdef SCIP_RETCODE PyConsInitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cdef SCIP_RETCODE PyConsExitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: cdef int i - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] + constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consexitpre(constraints) @@ -209,9 +205,8 @@ cdef SCIP_RETCODE PyConsExitpre (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cdef SCIP_RETCODE PyConsInitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: cdef int i - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] + constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consinitsol(constraints) @@ -219,9 +214,8 @@ cdef SCIP_RETCODE PyConsInitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cdef SCIP_RETCODE PyConsExitsol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool restart) noexcept with gil: cdef int i - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] + constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consexitsol(constraints, restart) @@ -257,9 +251,8 @@ cdef SCIP_RETCODE PyConsTrans (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* s cdef SCIP_RETCODE PyConsInitlp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_Bool* infeasible) noexcept with gil: cdef int i - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] + constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) result_dict = PyConshdlr.consinitlp(constraints) @@ -268,9 +261,8 @@ cdef SCIP_RETCODE PyConsInitlp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** cdef SCIP_RETCODE PyConsSepalp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_RESULT* result) noexcept with gil: cdef int i - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] + constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) result_dict = PyConshdlr.conssepalp(constraints, nusefulconss) @@ -280,9 +272,8 @@ cdef SCIP_RETCODE PyConsSepalp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** cdef SCIP_RETCODE PyConsSepasol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_SOL* sol, SCIP_RESULT* result) noexcept with gil: cdef int i - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] + constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) solution = Solution.create(scip, sol) @@ -293,9 +284,8 @@ cdef SCIP_RETCODE PyConsSepasol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cdef SCIP_RETCODE PyConsEnfolp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_Bool solinfeasible, SCIP_RESULT* result) noexcept with gil: cdef int i - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] + constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) result_dict = PyConshdlr.consenfolp(constraints, nusefulconss, solinfeasible) @@ -304,9 +294,8 @@ cdef SCIP_RETCODE PyConsEnfolp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** cdef SCIP_RETCODE PyConsEnforelax (SCIP* scip, SCIP_SOL* sol, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_Bool solinfeasible, SCIP_RESULT* result) noexcept with gil: cdef int i - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] + constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) solution = Solution.create(scip, sol) @@ -317,9 +306,8 @@ cdef SCIP_RETCODE PyConsEnforelax (SCIP* scip, SCIP_SOL* sol, SCIP_CONSHDLR* con cdef SCIP_RETCODE PyConsEnfops (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, SCIP_Bool solinfeasible, SCIP_Bool objinfeasible, SCIP_RESULT* result) noexcept with gil: cdef int i - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] + constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) result_dict = PyConshdlr.consenfops(constraints, nusefulconss, solinfeasible, objinfeasible) @@ -329,9 +317,8 @@ cdef SCIP_RETCODE PyConsEnfops (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** cdef SCIP_RETCODE PyConsCheck (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, SCIP_SOL* sol, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_Bool completely, SCIP_RESULT* result) noexcept with gil: cdef int i - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] + constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) solution = Solution.create(scip, sol) @@ -342,9 +329,8 @@ cdef SCIP_RETCODE PyConsCheck (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** cdef SCIP_RETCODE PyConsProp (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, int nusefulconss, int nmarkedconss, SCIP_PROPTIMING proptiming, SCIP_RESULT* result) noexcept with gil: cdef int i - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] + constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) result_dict = PyConshdlr.consprop(constraints, nusefulconss, nmarkedconss, proptiming) @@ -357,9 +343,8 @@ cdef SCIP_RETCODE PyConsPresol (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** int* nfixedvars, int* naggrvars, int* nchgvartypes, int* nchgbds, int* naddholes, int* ndelconss, int* naddconss, int* nupgdconss, int* nchgcoefs, int* nchgsides, SCIP_RESULT* result) noexcept with gil: cdef int i - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] + constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) # dictionary for input/output parameters @@ -432,9 +417,8 @@ cdef SCIP_RETCODE PyConsDisable (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cdef SCIP_RETCODE PyConsDelvars (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss) noexcept with gil: cdef int i - PyConshdlr = getPyConshdlr(conshdlr) - cdef constraints = [] + constraints = [] for i in range(nconss): constraints.append(getPyCons(conss[i])) PyConshdlr.consdelvars(constraints) diff --git a/src/pyscipopt/cutsel.pxi b/src/pyscipopt/cutsel.pxi index 5739a1043..93b44531a 100644 --- a/src/pyscipopt/cutsel.pxi +++ b/src/pyscipopt/cutsel.pxi @@ -72,11 +72,10 @@ cdef SCIP_RETCODE PyCutselExitsol (SCIP* scip, SCIP_CUTSEL* cutsel) noexcept wit cdef SCIP_RETCODE PyCutselSelect (SCIP* scip, SCIP_CUTSEL* cutsel, SCIP_ROW** cuts, int ncuts, SCIP_ROW** forcedcuts, int nforcedcuts, SCIP_Bool root, int maxnselectedcuts, int* nselectedcuts, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_CUTSELDATA* cutseldata + cdef SCIP_CUTSELDATA* cutseldata = SCIPcutselGetData(cutsel) cdef SCIP_ROW* scip_row cdef int i - - cutseldata = SCIPcutselGetData(cutsel) + PyCutsel = cutseldata # translate cuts to python diff --git a/src/pyscipopt/lp.pxi b/src/pyscipopt/lp.pxi index f6645db54..c17c900ad 100644 --- a/src/pyscipopt/lp.pxi +++ b/src/pyscipopt/lp.pxi @@ -64,20 +64,14 @@ cdef class LP: ub -- upper bound (default infinity) """ cdef int nnonz = len(entries) - cdef SCIP_Real* c_coefs = malloc(nnonz * sizeof(SCIP_Real)) cdef int* c_inds = malloc(nnonz * sizeof(int)) - cdef SCIP_Real c_obj - cdef SCIP_Real c_lb - cdef SCIP_Real c_ub - cdef int c_beg + cdef SCIP_Real c_obj = obj + cdef SCIP_Real c_lb = lb + cdef SCIP_Real c_ub = ub if ub != None else self.infinity() + cdef int c_beg = 0 cdef int i - c_obj = obj - c_lb = lb - c_ub = ub if ub != None else self.infinity() - c_beg = 0 - for i,entry in enumerate(entries): c_inds[i] = entry[0] c_coefs[i] = entry[1] @@ -96,18 +90,15 @@ cdef class LP: lbs -- lower bounds (default 0.0) ubs -- upper bounds (default infinity) """ - cdef int ncols = len(entrieslist) - cdef int nnonz = sum(len(entries) for entries in entrieslist) - cdef int i - cdef SCIP_Real* c_objs = malloc(ncols * sizeof(SCIP_Real)) cdef SCIP_Real* c_lbs = malloc(ncols * sizeof(SCIP_Real)) cdef SCIP_Real* c_ubs = malloc(ncols * sizeof(SCIP_Real)) cdef SCIP_Real* c_coefs cdef int* c_inds cdef int* c_beg - + cdef int nnonz = sum(len(entries) for entries in entrieslist) + cdef int i if nnonz > 0: c_coefs = malloc(nnonz * sizeof(SCIP_Real)) @@ -160,19 +151,13 @@ cdef class LP: lhs -- left-hand side of the row (default 0.0) rhs -- right-hand side of the row (default infinity) """ - beg = 0 cdef int nnonz = len(entries) - cdef SCIP_Real* c_coefs = malloc(nnonz * sizeof(SCIP_Real)) cdef int* c_inds = malloc(nnonz * sizeof(int)) - cdef SCIP_Real c_lhs - cdef SCIP_Real c_rhs - cdef int c_beg - cdef int i - - c_lhs = lhs - c_rhs = rhs if rhs != None else self.infinity() - c_beg = 0 + cdef SCIP_Real c_lhs = lhs + cdef SCIP_Real c_rhs = rhs if rhs != None else self.infinity() + cdef int c_beg = 0 + cdef int i for i,entry in enumerate(entries): c_inds[i] = entry[0] @@ -192,16 +177,15 @@ cdef class LP: rhss -- right-hand side of the row (default infinity) """ cdef int nrows = len(entrieslist) - cdef int nnonz = sum(len(entries) for entries in entrieslist) - cdef SCIP_Real* c_lhss = malloc(nrows * sizeof(SCIP_Real)) cdef SCIP_Real* c_rhss = malloc(nrows * sizeof(SCIP_Real)) + cdef int* c_beg = malloc(nrows * sizeof(int)) + cdef int nnonz = sum(len(entries) for entries in entrieslist) cdef SCIP_Real* c_coefs = malloc(nnonz * sizeof(SCIP_Real)) cdef int* c_inds = malloc(nnonz * sizeof(int)) - cdef int* c_beg = malloc(nrows * sizeof(int)) - cdef int i + cdef int tmp = 0 + cdef int i - tmp = 0 for i,entries in enumerate(entrieslist): c_lhss[i] = lhss[i] if lhss != None else 0.0 c_rhss[i] = rhss[i] if rhss != None else self.infinity() @@ -236,7 +220,7 @@ cdef class LP: firstcol -- first column (default 0) lastcol -- last column (default ncols - 1) """ - cdef int i + cdef int i lastcol = lastcol if lastcol != None else self.ncols() - 1 @@ -267,7 +251,7 @@ cdef class LP: firstrow -- first row (default 0) lastrow -- last row (default nrows - 1) """ - cdef int i + cdef int i lastrow = lastrow if lastrow != None else self.nrows() - 1 @@ -298,8 +282,8 @@ cdef class LP: col -- column to change obj -- new objective coefficient """ - cdef int c_col = col cdef SCIP_Real c_obj = obj + cdef int c_col = col PY_SCIP_CALL(SCIPlpiChgObj(self.lpi, 1, &c_col, &c_obj)) @@ -321,9 +305,9 @@ cdef class LP: lb -- new lower bound ub -- new upper bound """ - cdef int c_col = col cdef SCIP_Real c_lb = lb cdef SCIP_Real c_ub = ub + cdef int c_col = col PY_SCIP_CALL(SCIPlpiChgBounds(self.lpi, 1, &c_col, &c_lb, &c_ub)) @@ -335,9 +319,9 @@ cdef class LP: lhs -- new left-hand side rhs -- new right-hand side """ - cdef int c_row = row cdef SCIP_Real c_lhs = lhs cdef SCIP_Real c_rhs = rhs + cdef int c_row = row PY_SCIP_CALL(SCIPlpiChgSides(self.lpi, 1, &c_row, &c_lhs, &c_rhs)) @@ -350,6 +334,7 @@ cdef class LP: cdef int nrows PY_SCIP_CALL(SCIPlpiGetNRows(self.lpi, &nrows)) + return nrows def ncols(self): @@ -357,6 +342,7 @@ cdef class LP: cdef int ncols PY_SCIP_CALL(SCIPlpiGetNCols(self.lpi, &ncols)) + return ncols def solve(self, dual=True): @@ -372,14 +358,15 @@ cdef class LP: cdef SCIP_Real objval PY_SCIP_CALL(SCIPlpiGetObjval(self.lpi, &objval)) + return objval def getPrimal(self): """Returns the primal solution of the last LP solve.""" - cdef int i - - ncols = self.ncols() + cdef int ncols = self.ncols() cdef SCIP_Real* c_primalsol = malloc(ncols * sizeof(SCIP_Real)) + cdef int i + PY_SCIP_CALL(SCIPlpiGetSol(self.lpi, NULL, c_primalsol, NULL, NULL, NULL)) primalsol = [0.0] * ncols for i in range(ncols): @@ -394,10 +381,10 @@ cdef class LP: def getDual(self): """Returns the dual solution of the last LP solve.""" - cdef int i - - nrows = self.nrows() + cdef int nrows = self.nrows() cdef SCIP_Real* c_dualsol = malloc(nrows * sizeof(SCIP_Real)) + cdef int i + PY_SCIP_CALL(SCIPlpiGetSol(self.lpi, NULL, NULL, c_dualsol, NULL, NULL)) dualsol = [0.0] * nrows for i in range(nrows): @@ -412,12 +399,16 @@ cdef class LP: def getPrimalRay(self): """Returns a primal ray if possible, None otherwise.""" - cdef int i - + cdef int ncols + cdef SCIP_Real* c_ray + cdef int i + if not SCIPlpiHasPrimalRay(self.lpi): return None + ncols = self.ncols() - cdef SCIP_Real* c_ray = malloc(ncols * sizeof(SCIP_Real)) + c_ray = malloc(ncols * sizeof(SCIP_Real)) + PY_SCIP_CALL(SCIPlpiGetPrimalRay(self.lpi, c_ray)) ray = [0.0] * ncols for i in range(ncols): @@ -428,12 +419,16 @@ cdef class LP: def getDualRay(self): """Returns a dual ray if possible, None otherwise.""" - cdef int i - + cdef int nrows + cdef SCIP_Real* c_ray + cdef int i + if not SCIPlpiHasDualRay(self.lpi): return None + nrows = self.nrows() - cdef SCIP_Real* c_ray = malloc(nrows * sizeof(SCIP_Real)) + c_ray = malloc(nrows * sizeof(SCIP_Real)) + PY_SCIP_CALL(SCIPlpiGetDualfarkas(self.lpi, c_ray)) ray = [0.0] * nrows for i in range(nrows): @@ -447,15 +442,15 @@ cdef class LP: cdef int niters PY_SCIP_CALL(SCIPlpiGetIterations(self.lpi, &niters)) + return niters def getRedcost(self): """Returns the reduced cost vector of the last LP solve.""" - cdef int i - - ncols = self.ncols() - + cdef int ncols = self.ncols() cdef SCIP_Real* c_redcost = malloc(ncols * sizeof(SCIP_Real)) + cdef int i + PY_SCIP_CALL(SCIPlpiGetSol(self.lpi, NULL, NULL, NULL, NULL, c_redcost)) redcost = [] @@ -463,13 +458,14 @@ cdef class LP: redcost[i].append(c_redcost[i]) free(c_redcost) + return redcost def getBasisInds(self): """Returns the indices of the basic columns and rows; index i >= 0 corresponds to column i, index i < 0 to row -i-1""" - nrows = self.nrows() - cdef int* c_binds = malloc(nrows * sizeof(int)) - cdef int i + cdef int nrows = self.nrows() + cdef int* c_binds = malloc(nrows * sizeof(int)) + cdef int i PY_SCIP_CALL(SCIPlpiGetBasisInd(self.lpi, c_binds)) @@ -478,4 +474,5 @@ cdef class LP: binds.append(c_binds[i]) free(c_binds) + return binds diff --git a/src/pyscipopt/reader.pxi b/src/pyscipopt/reader.pxi index 22534dfc2..13fc13d1b 100644 --- a/src/pyscipopt/reader.pxi +++ b/src/pyscipopt/reader.pxi @@ -45,11 +45,10 @@ cdef SCIP_RETCODE PyReaderWrite (SCIP* scip, SCIP_READER* reader, FILE* file, SCIP_VAR** fixedvars, int nfixedvars, int startnvars, SCIP_CONS** conss, int nconss, int maxnconss, int startnconss, SCIP_Bool genericnames, SCIP_RESULT* result) noexcept with gil: - cdef SCIP_READERDATA* readerdata + cdef SCIP_READERDATA* readerdata = SCIPreaderGetData(reader) cdef int fd = fileno(file) cdef int i - readerdata = SCIPreaderGetData(reader) PyFile = os.fdopen(fd, "w", closefd=False) PyName = name.decode('utf-8') PyBinVars = [Variable.create(vars[i]) for i in range(nbinvars)] @@ -63,4 +62,5 @@ cdef SCIP_RETCODE PyReaderWrite (SCIP* scip, SCIP_READER* reader, FILE* file, PyBinVars, PyIntVars, PyImplVars, PyContVars, PyFixedVars, startnvars, PyConss, maxnconss, startnconss, genericnames) result[0] = result_dict.get("result", result[0]) + return SCIP_OKAY diff --git a/tests/test_event.py b/tests/test_event.py index f167a2fc9..b4b292ffd 100644 --- a/tests/test_event.py +++ b/tests/test_event.py @@ -60,7 +60,6 @@ def eventexec(self, event): else: assert event.getType() == self.event_type - def test_event(): all_events = [SCIP_EVENTTYPE.DISABLED,SCIP_EVENTTYPE.VARADDED,SCIP_EVENTTYPE.VARDELETED,SCIP_EVENTTYPE.VARFIXED,SCIP_EVENTTYPE.VARUNLOCKED,SCIP_EVENTTYPE.OBJCHANGED,SCIP_EVENTTYPE.GLBCHANGED,SCIP_EVENTTYPE.GUBCHANGED,SCIP_EVENTTYPE.LBTIGHTENED,SCIP_EVENTTYPE.LBRELAXED,SCIP_EVENTTYPE.UBTIGHTENED,SCIP_EVENTTYPE.UBRELAXED,SCIP_EVENTTYPE.GHOLEADDED,SCIP_EVENTTYPE.GHOLEREMOVED,SCIP_EVENTTYPE.LHOLEADDED,SCIP_EVENTTYPE.LHOLEREMOVED,SCIP_EVENTTYPE.IMPLADDED,SCIP_EVENTTYPE.PRESOLVEROUND,SCIP_EVENTTYPE.NODEFOCUSED,SCIP_EVENTTYPE.NODEFEASIBLE,SCIP_EVENTTYPE.NODEINFEASIBLE,SCIP_EVENTTYPE.NODEBRANCHED,SCIP_EVENTTYPE.NODEDELETE,SCIP_EVENTTYPE.FIRSTLPSOLVED,SCIP_EVENTTYPE.LPSOLVED,SCIP_EVENTTYPE.POORSOLFOUND,SCIP_EVENTTYPE.BESTSOLFOUND,SCIP_EVENTTYPE.ROWADDEDSEPA,SCIP_EVENTTYPE.ROWDELETEDSEPA,SCIP_EVENTTYPE.ROWADDEDLP,SCIP_EVENTTYPE.ROWDELETEDLP,SCIP_EVENTTYPE.ROWCOEFCHANGED,SCIP_EVENTTYPE.ROWCONSTCHANGED,SCIP_EVENTTYPE.ROWSIDECHANGED,SCIP_EVENTTYPE.SYNC,SCIP_EVENTTYPE.GBDCHANGED,SCIP_EVENTTYPE.LBCHANGED,SCIP_EVENTTYPE.UBCHANGED,SCIP_EVENTTYPE.BOUNDTIGHTENED,SCIP_EVENTTYPE.BOUNDRELAXED,SCIP_EVENTTYPE.BOUNDCHANGED,SCIP_EVENTTYPE.LHOLECHANGED,SCIP_EVENTTYPE.HOLECHANGED,SCIP_EVENTTYPE.DOMCHANGED,SCIP_EVENTTYPE.VARCHANGED,SCIP_EVENTTYPE.VAREVENT,SCIP_EVENTTYPE.NODESOLVED,SCIP_EVENTTYPE.NODEEVENT,SCIP_EVENTTYPE.LPEVENT,SCIP_EVENTTYPE.SOLFOUND,SCIP_EVENTTYPE.SOLEVENT,SCIP_EVENTTYPE.ROWCHANGED,SCIP_EVENTTYPE.ROWEVENT] @@ -82,7 +81,6 @@ def test_event(): s.addCons(quicksum(x[i] for i in range(100) if i%j==0) >= random.randint(10,100)) s.optimize() - def test_event_handler_callback(): m = Model() @@ -99,4 +97,4 @@ def callback(model, event): m.optimize() - assert number_of_calls == 2 \ No newline at end of file + assert number_of_calls == 2