Skip to content

Add feastol numerics checks #997

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
May 18, 2025
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
## Unreleased
### Added
- Added support for knapsack constraints
- Added isPositive(), isNegative(), isFeasLE(), isFeasLT(), isFeasGE(), isFeasGT(), isHugeValue(), and tests
- Added SCIP_LOCKTYPE, addVarLocksType(), getNLocksDown(), getNLocksUp(), getNLocksDownType(), getNLocksUpType(), and tests
### Fixed
### Changed
### Removed
Expand Down
1 change: 1 addition & 0 deletions src/pyscipopt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
from pyscipopt.scip import PY_SCIP_PRESOLTIMING as SCIP_PRESOLTIMING
from pyscipopt.scip import PY_SCIP_HEURTIMING as SCIP_HEURTIMING
from pyscipopt.scip import PY_SCIP_EVENTTYPE as SCIP_EVENTTYPE
from pyscipopt.scip import PY_SCIP_LOCKTYPE as SCIP_LOCKTYPE
from pyscipopt.scip import PY_SCIP_LPSOLSTAT as SCIP_LPSOLSTAT
from pyscipopt.scip import PY_SCIP_BRANCHDIR as SCIP_BRANCHDIR
from pyscipopt.scip import PY_SCIP_BENDERSENFOTYPE as SCIP_BENDERSENFOTYPE
Expand Down
78 changes: 43 additions & 35 deletions src/pyscipopt/scip.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,6 @@ cdef extern from "scip/scip.h":
SCIP_EVENTTYPE SCIP_EVENTTYPE_ROWCHANGED
SCIP_EVENTTYPE SCIP_EVENTTYPE_ROWEVENT


ctypedef int SCIP_LPSOLQUALITY
cdef extern from "lpi/type_lpi.h":
SCIP_LPSOLQUALITY SCIP_LPSOLQUALITY_ESTIMCONDITION
Expand Down Expand Up @@ -541,9 +540,9 @@ cdef extern from "scip/scip.h":
ctypedef union SCIP_DOMCHG:
pass

ctypedef void (*messagecallback) (SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *msg) noexcept
ctypedef void (*errormessagecallback) (void *data, FILE *file, const char *msg)
ctypedef SCIP_RETCODE (*messagehdlrfree) (SCIP_MESSAGEHDLR *messagehdlr)
ctypedef void (*messagecallback) (SCIP_MESSAGEHDLR* messagehdlr, FILE* file, const char* msg) noexcept
ctypedef void (*errormessagecallback) (void* data, FILE* file, const char* msg)
ctypedef SCIP_RETCODE (*messagehdlrfree) (SCIP_MESSAGEHDLR* messagehdlr)

# General SCIP Methods
SCIP_RETCODE SCIPcreate(SCIP** scip)
Expand All @@ -569,15 +568,15 @@ cdef extern from "scip/scip.h":
SCIP_Bool* valid)
SCIP_RETCODE SCIPcopyOrigVars(SCIP* sourcescip, SCIP* targetscip, SCIP_HASHMAP* varmap, SCIP_HASHMAP* consmap, SCIP_VAR** fixedvars, SCIP_Real* fixedvals, int nfixedvars )
SCIP_RETCODE SCIPcopyOrigConss(SCIP* sourcescip, SCIP* targetscip, SCIP_HASHMAP* varmap, SCIP_HASHMAP* consmap, SCIP_Bool enablepricing, SCIP_Bool* valid)
SCIP_RETCODE SCIPmessagehdlrCreate(SCIP_MESSAGEHDLR **messagehdlr,
SCIP_RETCODE SCIPmessagehdlrCreate(SCIP_MESSAGEHDLR** messagehdlr,
SCIP_Bool bufferedoutput,
const char *filename,
const char* filename,
SCIP_Bool quiet,
messagecallback,
messagecallback,
messagecallback,
messagehdlrfree,
SCIP_MESSAGEHDLRDATA *messagehdlrdata)
SCIP_MESSAGEHDLRDATA* messagehdlrdata)

SCIP_RETCODE SCIPsetMessagehdlr(SCIP* scip, SCIP_MESSAGEHDLR* messagehdlr)
void SCIPsetMessagehdlrQuiet(SCIP* scip, SCIP_Bool quiet)
Expand Down Expand Up @@ -787,6 +786,11 @@ cdef extern from "scip/scip.h":
SCIP_RETCODE SCIPtransformVar(SCIP* scip, SCIP_VAR* var, SCIP_VAR** transvar)
SCIP_RETCODE SCIPgetTransformedVar(SCIP* scip, SCIP_VAR* var, SCIP_VAR** transvar)
SCIP_RETCODE SCIPaddVarLocks(SCIP* scip, SCIP_VAR* var, int nlocksdown, int nlocksup)
SCIP_RETCODE SCIPaddVarLocksType(SCIP* scip, SCIP_VAR* var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
int SCIPvarGetNLocksDown(SCIP_VAR* var)
int SCIPvarGetNLocksUp(SCIP_VAR* var)
int SCIPvarGetNLocksDownType(SCIP_VAR* var, SCIP_LOCKTYPE locktype)
int SCIPvarGetNLocksUpType(SCIP_VAR* var, SCIP_LOCKTYPE locktype)
SCIP_VAR** SCIPgetVars(SCIP* scip)
SCIP_VAR** SCIPgetOrigVars(SCIP* scip)
const char* SCIPvarGetName(SCIP_VAR* var)
Expand All @@ -813,11 +817,11 @@ cdef extern from "scip/scip.h":
void SCIPvarSetData(SCIP_VAR* var, SCIP_VARDATA* vardata)
SCIP_VARDATA* SCIPvarGetData(SCIP_VAR* var)
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR* var)
SCIP_Real SCIPgetVarPseudocost(SCIP* scip, SCIP_VAR *var, SCIP_BRANCHDIR dir)
SCIP_Real SCIPgetVarPseudocost(SCIP* scip, SCIP_VAR* var, SCIP_BRANCHDIR dir)
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR* var, SCIP_BRANCHDIR dir)
SCIP_Longint SCIPvarGetNBranchings(SCIP_VAR* var, SCIP_BRANCHDIR dir)
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR* var)
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR * var)
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR* var)

# LP Methods
SCIP_RETCODE SCIPgetLPColsData(SCIP* scip, SCIP_COL*** cols, int* ncols)
Expand All @@ -831,8 +835,8 @@ cdef extern from "scip/scip.h":
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP* scip)
int SCIPgetNLPRows(SCIP* scip)
int SCIPgetNLPCols(SCIP* scip)
SCIP_COL** SCIPgetLPCols(SCIP *scip)
SCIP_ROW** SCIPgetLPRows(SCIP *scip)
SCIP_COL** SCIPgetLPCols(SCIP* scip)
SCIP_ROW** SCIPgetLPRows(SCIP* scip)
SCIP_Bool SCIPallColsInLP(SCIP* scip)

# Cutting Plane Methods
Expand Down Expand Up @@ -872,11 +876,11 @@ cdef extern from "scip/scip.h":
const char* SCIPconshdlrGetName(SCIP_CONSHDLR* conshdlr)
SCIP_RETCODE SCIPdelConsLocal(SCIP* scip, SCIP_CONS* cons)
SCIP_RETCODE SCIPdelCons(SCIP* scip, SCIP_CONS* cons)
SCIP_RETCODE SCIPsetConsChecked(SCIP *scip, SCIP_CONS *cons, SCIP_Bool check)
SCIP_RETCODE SCIPsetConsRemovable(SCIP *scip, SCIP_CONS *cons, SCIP_Bool removable)
SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
SCIP_RETCODE SCIPsetConsModifiable(SCIP *scip, SCIP_CONS *cons, SCIP_Bool modifiable)
SCIP_RETCODE SCIPsetConsEnforced(SCIP *scip, SCIP_CONS *cons, SCIP_Bool enforce)
SCIP_RETCODE SCIPsetConsChecked(SCIP* scip, SCIP_CONS* cons, SCIP_Bool check)
SCIP_RETCODE SCIPsetConsRemovable(SCIP* scip, SCIP_CONS* cons, SCIP_Bool removable)
SCIP_RETCODE SCIPsetConsInitial(SCIP* scip, SCIP_CONS* cons, SCIP_Bool initial)
SCIP_RETCODE SCIPsetConsModifiable(SCIP* scip, SCIP_CONS* cons, SCIP_Bool modifiable)
SCIP_RETCODE SCIPsetConsEnforced(SCIP* scip, SCIP_CONS* cons, SCIP_Bool enforce)

# Primal Solution Methods
SCIP_SOL** SCIPgetSols(SCIP* scip)
Expand Down Expand Up @@ -906,8 +910,8 @@ cdef extern from "scip/scip.h":
SCIP_Real SCIPgetGap(SCIP* scip)
int SCIPgetDepth(SCIP* scip)
SCIP_RETCODE SCIPcutoffNode(SCIP* scip, SCIP_NODE* node)
SCIP_Bool SCIPhasPrimalRay(SCIP * scip)
SCIP_Real SCIPgetPrimalRayVal(SCIP * scip, SCIP_VAR * var)
SCIP_Bool SCIPhasPrimalRay(SCIP* scip)
SCIP_Real SCIPgetPrimalRayVal(SCIP* scip, SCIP_VAR* var)
SCIP_RETCODE SCIPaddSolFree(SCIP* scip, SCIP_SOL** sol, SCIP_Bool* stored)
SCIP_RETCODE SCIPaddSol(SCIP* scip, SCIP_SOL* sol, SCIP_Bool* stored)
SCIP_RETCODE SCIPreadSol(SCIP* scip, const char* filename)
Expand Down Expand Up @@ -1051,7 +1055,7 @@ cdef extern from "scip/scip.h":
SCIP_RETCODE (*consgetnvars) (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, int* nvars, SCIP_Bool* success),
SCIP_RETCODE (*consgetdivebdchgs) (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_DIVESET* diveset, SCIP_SOL* sol, SCIP_Bool* success, SCIP_Bool* infeasible),
SCIP_RETCODE (*consgetpermsymgraph)(SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SYM_GRAPH* graph, SCIP_Bool* success),
SCIP_RETCODE (*consgetsignedpermsymgraph)(SCIP * scip, SCIP_CONSHDLR * conshdlr, SCIP_CONS * cons, SYM_GRAPH * graph, SCIP_Bool * success),
SCIP_RETCODE (*consgetsignedpermsymgraph)(SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, SYM_GRAPH* graph, SCIP_Bool* success),
SCIP_CONSHDLRDATA* conshdlrdata)
SCIP_CONSHDLRDATA* SCIPconshdlrGetData(SCIP_CONSHDLR* conshdlr)
SCIP_CONSHDLR* SCIPfindConshdlr(SCIP* scip, const char* name)
Expand Down Expand Up @@ -1339,13 +1343,17 @@ cdef extern from "scip/scip.h":
SCIP_Bool SCIPisLT(SCIP* scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisGE(SCIP* scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisGT(SCIP* scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPgetTreesizeEstimation(SCIP *scip)
SCIP_Bool SCIPisEQ(SCIP* scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasEQ(SCIP* scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasLT(SCIP* scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasGT(SCIP* scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasLE(SCIP* scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasGE(SCIP* scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisHugeValue(SCIP* scip, SCIP_Real val)
SCIP_Bool SCIPisPositive(SCIP* scip, SCIP_Real val)
SCIP_Bool SCIPisNegative(SCIP* scip, SCIP_Real val)
SCIP_Bool SCIPisIntegral(SCIP* scip, SCIP_Real val)
SCIP_Real SCIPgetTreesizeEstimation(SCIP* scip)

# Statistic Methods
SCIP_RETCODE SCIPprintStatistics(SCIP* scip, FILE* outfile)
Expand Down Expand Up @@ -1611,22 +1619,22 @@ cdef extern from "scip/cons_sos2.h":
SCIP_VAR* var)

cdef extern from "scip/cons_disjunction.h":
SCIP_RETCODE SCIPcreateConsDisjunction(SCIP *scip,
SCIP_CONS **cons,
const char *name,
SCIP_RETCODE SCIPcreateConsDisjunction(SCIP* scip,
SCIP_CONS** cons,
const char* name,
int nconss,
SCIP_CONS **conss,
SCIP_CONS *relaxcons,
SCIP_CONS** conss,
SCIP_CONS* relaxcons,
SCIP_Bool initial,
SCIP_Bool enforce,
SCIP_Bool check,
SCIP_Bool local,
SCIP_Bool modifiable,
SCIP_Bool dynamic)

SCIP_RETCODE SCIPaddConsElemDisjunction(SCIP *scip,
SCIP_CONS *cons,
SCIP_CONS *addcons)
SCIP_RETCODE SCIPaddConsElemDisjunction(SCIP* scip,
SCIP_CONS* cons,
SCIP_CONS* addcons)

cdef extern from "scip/cons_and.h":
SCIP_RETCODE SCIPcreateConsAnd(SCIP* scip,
Expand Down Expand Up @@ -1963,7 +1971,7 @@ cdef extern from "scip/pub_lp.h":
SCIP_Real* SCIPcolGetVals(SCIP_COL* col)
int SCIPcolGetAge(SCIP_COL* col)
int SCIPcolGetIndex(SCIP_COL* col)
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
SCIP_Real SCIPcolGetObj(SCIP_COL* col)

cdef extern from "scip/scip_tree.h":
SCIP_RETCODE SCIPgetOpenNodesData(SCIP* scip, SCIP_NODE*** leaves, SCIP_NODE*** children, SCIP_NODE*** siblings, int* nleaves, int* nchildren, int* nsiblings)
Expand Down
143 changes: 141 additions & 2 deletions src/pyscipopt/scip.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,9 @@ cdef class PY_SCIP_EVENTTYPE:
ROWCHANGED = SCIP_EVENTTYPE_ROWCHANGED
ROWEVENT = SCIP_EVENTTYPE_ROWEVENT

cdef class PY_SCIP_LOCKTYPE:
MODEL = SCIP_LOCKTYPE_MODEL
CONFLICT = SCIP_LOCKTYPE_CONFLICT

cdef class PY_SCIP_LPSOLSTAT:
NOTSOLVED = SCIP_LPSOLSTAT_NOTSOLVED
Expand Down Expand Up @@ -1671,6 +1674,60 @@ cdef class Variable(Expr):
"""
return SCIPvarGetAvgSol(self.scip_var)

def getNLocksDown(self):
"""
Returns the number of locks for rounding down.

Returns
-------
int

"""
return SCIPvarGetNLocksDown(self.scip_var)

def getNLocksUp(self):
"""
Returns the number of locks for rounding up.

Returns
-------
int

"""
return SCIPvarGetNLocksUp(self.scip_var)

def getNLocksDownType(self, locktype):
"""
Returns the number of locks for rounding down of a certain type.

Parameters
----------
locktype: PY_SCIP_LOCKTYPE
type of variable locks

Returns
-------
int

"""
return SCIPvarGetNLocksDownType(self.scip_var, locktype)

def getNLocksUpType(self, locktype):
"""
Returns the number of locks for rounding up of a certain type.

Parameters
----------
locktype: PY_SCIP_LOCKTYPE
type of variable locks

Returns
-------
int

"""
return SCIPvarGetNLocksUpType(self.scip_var, locktype)

def varMayRound(self, direction="down"):
"""
Checks whether it is possible to round variable up / down and stay feasible for the relaxation.
Expand Down Expand Up @@ -3070,7 +3127,7 @@ cdef class Model:

def isFeasEQ(self, val1, val2):
"""
Checks, if relative difference of values is in range of feasibility tolerance.
Returns if relative difference between val1 and val2 is in range of feasibility tolerance.

Parameters
----------
Expand All @@ -3083,6 +3140,70 @@ cdef class Model:

"""
return SCIPisFeasEQ(self._scip, val1, val2)

def isFeasLT(self, val1, val2):
"""
Returns whether relative difference between val1 and val2 is lower than minus feasibility tolerance.

Parameters
----------
val1 : float
val2 : float

Returns
-------
bool

"""
return SCIPisFeasLT(self._scip, val1, val2)

def isFeasLE(self, val1, val2):
"""
Returns whether relative difference between val1 and val2 is not greater than feasibility tolerance.

Parameters
----------
val1 : float
val2 : float

Returns
-------
bool

"""
return SCIPisFeasLE(self._scip, val1, val2)

def isFeasGT(self, val1, val2):
"""
Returns whether relative difference between val1 and val2 is greater than feasibility tolerance.

Parameters
----------
val1 : float
val2 : float

Returns
-------
bool

"""
return SCIPisFeasGT(self._scip, val1, val2)

def isFeasGE(self, val1, val2):
"""
Returns whether relative difference of val1 and val2 is not lower than minus feasibility tolerance.

Parameters
----------
val1 : float
val2 : float

Returns
-------
bool

"""
return SCIPisFeasGE(self._scip, val1, val2)

def isLE(self, val1, val2):
"""
Expand Down Expand Up @@ -3792,7 +3913,7 @@ cdef class Model:

return Variable.create(_tvar)

def addVarLocks(self, Variable var, nlocksdown, nlocksup):
def addVarLocks(self, Variable var, int nlocksdown, int nlocksup):
"""
Adds given values to lock numbers of variable for rounding.

Expand All @@ -3808,6 +3929,24 @@ cdef class Model:
"""
PY_SCIP_CALL(SCIPaddVarLocks(self._scip, var.scip_var, nlocksdown, nlocksup))

def addVarLocksType(self, Variable var, int locktype, int nlocksdown, int nlocksup):
"""
adds given values to lock numbers of type locktype of variable for rounding

Parameters
----------
var : Variable
variable to adjust the locks for
locktype : PY_SCIP_LOCKTYPE
type of variable locks
nlocksdown : int
modification in number of down locks
nlocksup : int
modification in number of up locks

"""
PY_SCIP_CALL(SCIPaddVarLocksType(self._scip, var.scip_var, locktype, nlocksdown, nlocksup))

def fixVar(self, Variable var, val):
"""
Fixes the variable var to the value val if possible.
Expand Down
Loading