Skip to content

Commit 9553fef

Browse files
authored
Mt/cut selector plugin (#565)
* Adds cutsel plugin * Adds basic test_cutsel * Makes test_cutsel more difficult, and actually use the cut-selector * Adds intsupport and objparal getter functions * Removed bug with sorting forcedcuts * Adds getRowParallelism function to scip calls * Adds SCIP(rowIsLocal,rowIsInGlobalCutPool,getCutLPSolCutoffDistance) * Removes PY_SCIP_CALL wrapper in getRowNumIntCols * Solution is now mandatorz for getCutLPSolCutoffDistance call * Corrects the sorting order of the test_cutsel * Fixed misspelling of parallel and adds getRowLinear() * Fixes error with misses arg in PySepaExecSol * Adds missing depth argument to PySepaExecsol * Adds getdualsolval functionality * Should look more cloesly at the conflict.... * Adds wrapper method for retrieval of dual sol of a row * Adds wrapped functions for objective coefficient retrieval and norm of a row * Adds scipGetNSepaRounds call * Adds writing of best transformed solution * Adds writeTransSol method * Adds gil calls to cutsel functions * Updates CHANGELOG Co-authored-by: Mark <[email protected]>
1 parent 0fbd25d commit 9553fef

File tree

5 files changed

+360
-0
lines changed

5 files changed

+360
-0
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,29 @@
22

33
## Unreleased
44
### Added
5+
- Interface to include custom cut selector plugins
6+
- New test for cut selector plugin
7+
- Add SCIP function SCIPgetCutLPSolCutoffDistance and wrapper getCutLPSolCutoffDistance
8+
- Add SCIP function SCIPprintBestTransSol and wrapper writeBestTransSol
9+
- Add SCIP function SCIPprintTransSol and wrapper writeTransSol
10+
- Add SCIP function SCIPgetRowNumIntCols and wrapper getRowNumIntCols
11+
- Add SCIP function SCIProwGetNNonz and wrapper rowGetNNonz
12+
- Add SCIP function SCIPgetRowObjParallelism and wrapper getRowObjParallelism
13+
- Add SCIP function SCIPgetNSepaRounds and wrapper getNSepaRounds
14+
- Add SCIP function SCIPgetRowLinear and wrapper getRowLinear
15+
- Add SCIP function SCIProwIsInGlobalCutpool and wrapper isInGlobalCutpool
16+
- Add SCIP function SCIProwGetParallelism and wrapper getRowParallelism
17+
- Add getObjCoeff call to Column
18+
- Add isLocal call to Row
19+
- Add getNorm call to Row
20+
- Add getRowDualSol to Row
21+
- Add getDualSolVal to Model
522
- added activeone parameter of addConsIndicator() allows to activate the constraint if the binary (indicator) variable is 1 or 0.
623
- added function getSlackVarIndicator(), returns the slack variable of the indicator constraint.
724
### Fixed
825
- cmake / make install works from build directory
926
### Changed
27+
1028
### Removed
1129

1230
## 4.0.0 - 2021-12-15

src/pyscipopt/cutsel.pxi

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
##@file cutsel.pxi
2+
#@brief Base class of the Cutsel Plugin
3+
cdef class Cutsel:
4+
cdef public Model model
5+
6+
def cutselfree(self):
7+
'''frees memory of cut selector'''
8+
pass
9+
10+
def cutselinit(self):
11+
''' executed after the problem is transformed. use this call to initialize cut selector data.'''
12+
pass
13+
14+
def cutselexit(self):
15+
'''executed before the transformed problem is freed'''
16+
pass
17+
18+
def cutselinitsol(self):
19+
'''executed when the presolving is finished and the branch-and-bound process is about to begin'''
20+
pass
21+
22+
def cutselexitsol(self):
23+
'''executed before the branch-and-bound process is freed'''
24+
pass
25+
26+
def cutselselect(self, cuts, forcedcuts, root, maxnselectedcuts):
27+
'''first method called in each iteration in the main solving loop. '''
28+
# this method needs to be implemented by the user
29+
return {}
30+
31+
32+
cdef SCIP_RETCODE PyCutselCopy (SCIP* scip, SCIP_CUTSEL* cutsel) with gil:
33+
return SCIP_OKAY
34+
35+
cdef SCIP_RETCODE PyCutselFree (SCIP* scip, SCIP_CUTSEL* cutsel) with gil:
36+
cdef SCIP_CUTSELDATA* cutseldata
37+
cutseldata = SCIPcutselGetData(cutsel)
38+
PyCutsel = <Cutsel>cutseldata
39+
PyCutsel.cutselfree()
40+
Py_DECREF(PyCutsel)
41+
return SCIP_OKAY
42+
43+
cdef SCIP_RETCODE PyCutselInit (SCIP* scip, SCIP_CUTSEL* cutsel) with gil:
44+
cdef SCIP_CUTSELDATA* cutseldata
45+
cutseldata = SCIPcutselGetData(cutsel)
46+
PyCutsel = <Cutsel>cutseldata
47+
PyCutsel.cutselinit()
48+
return SCIP_OKAY
49+
50+
51+
cdef SCIP_RETCODE PyCutselExit (SCIP* scip, SCIP_CUTSEL* cutsel) with gil:
52+
cdef SCIP_CUTSELDATA* cutseldata
53+
cutseldata = SCIPcutselGetData(cutsel)
54+
PyCutsel = <Cutsel>cutseldata
55+
PyCutsel.cutselexit()
56+
return SCIP_OKAY
57+
58+
cdef SCIP_RETCODE PyCutselInitsol (SCIP* scip, SCIP_CUTSEL* cutsel) with gil:
59+
cdef SCIP_CUTSELDATA* cutseldata
60+
cutseldata = SCIPcutselGetData(cutsel)
61+
PyCutsel = <Cutsel>cutseldata
62+
PyCutsel.cutselinitsol()
63+
return SCIP_OKAY
64+
65+
cdef SCIP_RETCODE PyCutselExitsol (SCIP* scip, SCIP_CUTSEL* cutsel) with gil:
66+
cdef SCIP_CUTSELDATA* cutseldata
67+
cutseldata = SCIPcutselGetData(cutsel)
68+
PyCutsel = <Cutsel>cutseldata
69+
PyCutsel.cutselexitsol()
70+
return SCIP_OKAY
71+
72+
cdef SCIP_RETCODE PyCutselSelect (SCIP* scip, SCIP_CUTSEL* cutsel, SCIP_ROW** cuts, int ncuts,
73+
SCIP_ROW** forcedcuts, int nforcedcuts, SCIP_Bool root, int maxnselectedcuts,
74+
int* nselectedcuts, SCIP_RESULT* result) with gil:
75+
cdef SCIP_CUTSELDATA* cutseldata
76+
cdef SCIP_ROW* scip_row
77+
cutseldata = SCIPcutselGetData(cutsel)
78+
PyCutsel = <Cutsel>cutseldata
79+
80+
# translate cuts to python
81+
pycuts = [Row.create(cuts[i]) for i in range(ncuts)]
82+
pyforcedcuts = [Row.create(forcedcuts[i]) for i in range(nforcedcuts)]
83+
result_dict = PyCutsel.cutselselect(pycuts, pyforcedcuts, root, maxnselectedcuts)
84+
85+
# Retrieve the sorted cuts. Note that these do not need to be returned explicitly in result_dict.
86+
# Pycuts could have been sorted in place in cutselselect()
87+
pycuts = result_dict.get('cuts', pycuts)
88+
89+
assert len(pycuts) == ncuts
90+
assert len(pyforcedcuts) == nforcedcuts
91+
92+
#sort cuts
93+
for i,cut in enumerate(pycuts):
94+
cuts[i] = <SCIP_ROW *>((<Row>cut).scip_row)
95+
96+
nselectedcuts[0] = result_dict.get('nselectedcuts', 0)
97+
result[0] = result_dict.get('result', <SCIP_RESULT>result[0])
98+
99+
return SCIP_OKAY

src/pyscipopt/scip.pxd

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,12 @@ cdef extern from "scip/scip.h":
364364
ctypedef struct SCIP_BRANCHRULEDATA:
365365
pass
366366

367+
ctypedef struct SCIP_CUTSEL:
368+
pass
369+
370+
ctypedef struct SCIP_CUTSELDATA:
371+
pass
372+
367373
ctypedef struct SCIP_PRESOL:
368374
pass
369375

@@ -736,6 +742,7 @@ cdef extern from "scip/scip.h":
736742
SCIP_RETCODE SCIPaddPoolCut(SCIP* scip, SCIP_ROW* row)
737743
SCIP_Real SCIPgetCutEfficacy(SCIP* scip, SCIP_SOL* sol, SCIP_ROW* cut)
738744
SCIP_Bool SCIPisCutEfficacious(SCIP* scip, SCIP_SOL* sol, SCIP_ROW* cut)
745+
SCIP_Real SCIPgetCutLPSolCutoffDistance(SCIP* scip, SCIP_SOL* sol, SCIP_ROW* cut)
739746
int SCIPgetNCuts(SCIP* scip)
740747
int SCIPgetNCutsApplied(SCIP* scip)
741748
SCIP_RETCODE SCIPseparateSol(SCIP* scip, SCIP_SOL* sol, SCIP_Bool pretendroot, SCIP_Bool allowlocal, SCIP_Bool onlydelayed, SCIP_Bool* delayed, SCIP_Bool* cutoff)
@@ -789,7 +796,9 @@ cdef extern from "scip/scip.h":
789796
SCIP_RETCODE SCIPtrySol(SCIP* scip, SCIP_SOL* sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool* stored)
790797
SCIP_RETCODE SCIPfreeSol(SCIP* scip, SCIP_SOL** sol)
791798
SCIP_RETCODE SCIPprintBestSol(SCIP* scip, FILE* outfile, SCIP_Bool printzeros)
799+
SCIP_RETCODE SCIPprintBestTransSol(SCIP* scip, FILE* outfile, SCIP_Bool printzeros)
792800
SCIP_RETCODE SCIPprintSol(SCIP* scip, SCIP_SOL* sol, FILE* outfile, SCIP_Bool printzeros)
801+
SCIP_RETCODE SCIPprintTransSol(SCIP* scip, SCIP_SOL* sol, FILE* outfile, SCIP_Bool printzeros)
793802
SCIP_Real SCIPgetPrimalbound(SCIP* scip)
794803
SCIP_Real SCIPgetGap(SCIP* scip)
795804
int SCIPgetDepth(SCIP* scip)
@@ -815,6 +824,9 @@ cdef extern from "scip/scip.h":
815824
SCIP_RETCODE SCIPflushRowExtensions(SCIP* scip, SCIP_ROW* row)
816825
SCIP_RETCODE SCIPaddVarToRow(SCIP* scip, SCIP_ROW* row, SCIP_VAR* var, SCIP_Real val)
817826
SCIP_RETCODE SCIPprintRow(SCIP* scip, SCIP_ROW* row, FILE* file)
827+
int SCIPgetRowNumIntCols(SCIP* scip, SCIP_ROW* row)
828+
int SCIProwGetNNonz(SCIP_ROW* row)
829+
SCIP_Real SCIPgetRowObjParallelism(SCIP* scip, SCIP_ROW* row)
818830

819831
# Column Methods
820832
SCIP_Real SCIPgetColRedcost(SCIP* scip, SCIP_COL* col)
@@ -1081,6 +1093,24 @@ cdef extern from "scip/scip.h":
10811093
const char* SCIPbranchruleGetName(SCIP_BRANCHRULE* branchrule)
10821094
SCIP_BRANCHRULE* SCIPfindBranchrule(SCIP* scip, const char* name)
10831095

1096+
# cut selector plugin
1097+
SCIP_RETCODE SCIPincludeCutsel(SCIP* scip,
1098+
const char* name,
1099+
const char* desc,
1100+
int priority,
1101+
SCIP_RETCODE (*cutselcopy) (SCIP* scip, SCIP_CUTSEL* cutsel),
1102+
SCIP_RETCODE (*cutselfree) (SCIP* scip, SCIP_CUTSEL* cutsel),
1103+
SCIP_RETCODE (*cutselinit) (SCIP* scip, SCIP_CUTSEL* cutsel),
1104+
SCIP_RETCODE (*cutselexit) (SCIP* scip, SCIP_CUTSEL* cutsel),
1105+
SCIP_RETCODE (*cutselinitsol) (SCIP* scip, SCIP_CUTSEL* cutsel),
1106+
SCIP_RETCODE (*cutselexitsol) (SCIP* scip, SCIP_CUTSEL* cutsel),
1107+
SCIP_RETCODE (*cutselselect) (SCIP* scip, SCIP_CUTSEL* cutsel, SCIP_ROW** cuts,
1108+
int ncuts, SCIP_ROW** forcedcuts, int nforcedcuts,
1109+
SCIP_Bool root, int maxnselectedcuts,
1110+
int* nselectedcuts, SCIP_RESULT* result),
1111+
SCIP_CUTSELDATA* cutseldata)
1112+
SCIP_CUTSELDATA* SCIPcutselGetData(SCIP_CUTSEL* cutsel)
1113+
10841114
# Benders' decomposition plugin
10851115
SCIP_RETCODE SCIPincludeBenders(SCIP* scip,
10861116
const char* name,
@@ -1198,6 +1228,7 @@ cdef extern from "scip/scip.h":
11981228
SCIP_Longint SCIPgetNInfeasibleLeaves(SCIP* scip)
11991229
SCIP_Longint SCIPgetNLPs(SCIP* scip)
12001230
SCIP_Longint SCIPgetNLPIterations(SCIP* scip)
1231+
int SCIPgetNSepaRounds(SCIP* scip)
12011232

12021233
# Parameter Functions
12031234
SCIP_RETCODE SCIPsetBoolParam(SCIP* scip, char* name, SCIP_Bool value)
@@ -1301,6 +1332,7 @@ cdef extern from "scip/cons_linear.h":
13011332
SCIP_VAR** SCIPgetVarsLinear(SCIP* scip, SCIP_CONS* cons)
13021333
int SCIPgetNVarsLinear(SCIP* scip, SCIP_CONS* cons)
13031334
SCIP_Real* SCIPgetValsLinear(SCIP* scip, SCIP_CONS* cons)
1335+
SCIP_ROW* SCIPgetRowLinear(SCIP* scip, SCIP_CONS* cons)
13041336

13051337
cdef extern from "scip/cons_nonlinear.h":
13061338
SCIP_EXPR* SCIPgetExprNonlinear(SCIP_CONS* cons)
@@ -1690,12 +1722,14 @@ cdef extern from "scip/pub_lp.h":
16901722
SCIP_Bool SCIProwIsLocal(SCIP_ROW* row)
16911723
SCIP_Bool SCIProwIsModifiable(SCIP_ROW* row)
16921724
SCIP_Bool SCIProwIsRemovable(SCIP_ROW* row)
1725+
SCIP_Bool SCIProwIsInGlobalCutpool(SCIP_ROW* row)
16931726
int SCIProwGetNNonz(SCIP_ROW* row)
16941727
int SCIProwGetNLPNonz(SCIP_ROW* row)
16951728
SCIP_COL** SCIProwGetCols(SCIP_ROW* row)
16961729
SCIP_Real* SCIProwGetVals(SCIP_ROW* row)
16971730
SCIP_Real SCIProwGetNorm(SCIP_ROW* row)
16981731
SCIP_Real SCIProwGetDualsol(SCIP_ROW* row)
1732+
SCIP_Real SCIProwGetParallelism(SCIP_ROW* row1, SCIP_ROW* row2, const char orthofunc)
16991733
int SCIProwGetAge(SCIP_ROW* row)
17001734
SCIP_Bool SCIProwIsRemovable(SCIP_ROW* row)
17011735
SCIP_ROWORIGINTYPE SCIProwGetOrigintype(SCIP_ROW* row)

0 commit comments

Comments
 (0)