16 using namespace Couenne;
21 #include "scip/scip.h"
22 #include "scip/cons_linear.h"
23 #include "scip/scipdefplugins.h"
24 #include "scip/cons_bounddisjunction.h"
26 SCIP_RETCODE CouenneFeasPump::ScipSolve (
const double *nSol,
double* &sol,
int niter,
int* nsuciter,
CouNumber &obj) {
28 static int currentmilpmethod = 0;
30 int depth = (model_ -> currentNode ()) ? model_ -> currentNode () -> depth () : 0;
37 const SCIP_Real* objs;
39 const CoinPackedMatrix * matrix;
40 const CoinBigIndex* rowstarts;
41 const int* rowlengths;
42 const SCIP_Real* coeffs;
43 const SCIP_Real* lhss;
44 const SCIP_Real* rhss;
50 SCIP_Real *tabubounds;
51 SCIP_BOUNDTYPE *tabuboundtypes;
63 nvars =
milp_ -> getNumCols ();
64 nconss =
milp_ -> getNumRows ();
65 infinity =
milp_ -> getInfinity ();
68 lbs = CoinCopyOfArray (
milp_ -> getColLower (),
milp_ -> getNumCols ());
69 ubs = CoinCopyOfArray (
milp_ -> getColUpper (),
milp_ -> getNumCols ());
71 objs =
milp_ -> getObjCoefficients ();
72 vartypes =
milp_ -> getColType ();
77 if (
problem_ -> Var (i) -> Multiplicity () > 0) {
83 lhss =
milp_ -> getRowLower ();
84 rhss =
milp_ -> getRowUpper ();
87 matrix =
milp_ -> getMatrixByRow();
88 rowstarts = matrix -> getVectorStarts();
89 rowlengths = matrix -> getVectorLengths();
90 coeffs = matrix -> getElements();
91 indices = matrix -> getIndices();
96 SCIPdebugMessage(
"create SCIP problem instance with %d variables and %d constraints.\n", nvars, nconss);
100 SCIP_CALL( SCIPcreate (&scip) );
101 assert(scip != NULL);
104 SCIP_CALL( SCIPincludeDefaultPlugins(scip) );
113 SCIP_CALL( SCIPcreateProb(scip,
"auxiliary FeasPump MILP", NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
116 SCIP_CALL( SCIPallocMemoryArray(scip, &vars, nvars) );
120 SCIP_CALL( SCIPallocMemoryArray(scip, &tabuvars , 2*nvars) );
121 SCIP_CALL( SCIPallocMemoryArray(scip, &tabubounds , 2*nvars) );
122 SCIP_CALL( SCIPallocMemoryArray(scip, &tabuboundtypes, 2*nvars) );
127 for (
int i=0; i<nvars; i++) {
129 char varname[SCIP_MAXSTRLEN];
133 (
problem_ -> Var (i) -> Multiplicity () <= 0);
136 assert( 0 <= vartypes[i] && vartypes[i] <= 2);
140 checkInfinity(scip, lbs[i], infinity);
141 checkInfinity(scip, ubs[i], infinity);
145 (
void) SCIPsnprintf(varname, SCIP_MAXSTRLEN,
"x_%d", i);
146 SCIP_CALL( SCIPcreateVar(scip, &vars[i], varname,
147 CoinMin (lbs [i], ubs [i]),
148 CoinMax (lbs [i], ubs [i]),
150 vartypes[i] == 0 ? SCIP_VARTYPE_CONTINUOUS : (vartypes[i] == 1 ? SCIP_VARTYPE_BINARY : SCIP_VARTYPE_INTEGER),
151 TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
154 SCIP_CALL( SCIPaddVar(scip, vars[i]) );
157 for (std::set <CouenneFPsolution, compareSol>:: iterator i =
tabuPool_ . begin ();
160 const double *
x = i ->
x ();
164 SCIP_CONS *tabucons = NULL;
166 for (
int j = 0;
j < i ->
n (); ++
j) {
169 (
problem_ -> Var (
j) -> Multiplicity () > 0) &&
170 (fabs (ubs [
j] - lbs [
j]) > .5)) {
180 assert (fabs (x [j] - floor (x [j] + .5)) < SCIPfeastol (scip) * 1.e3);
182 assert (nEntries <= 2*nvars - 2);
184 double x_rounded = floor (x [j] + .5);
188 tabuvars [nEntries] = vars [
j];
189 tabubounds [nEntries] = x_rounded - 1.;
190 tabuboundtypes [nEntries++] = SCIP_BOUNDTYPE_UPPER;
194 tabuvars [nEntries] = vars [
j];
195 tabubounds [nEntries] = x_rounded + 1.;
196 tabuboundtypes [nEntries++] = SCIP_BOUNDTYPE_LOWER;
200 tabuvars [nEntries] = vars [
j];
201 tabubounds [nEntries] = x_rounded - 1.;
202 tabuboundtypes [nEntries++] = SCIP_BOUNDTYPE_UPPER;
204 tabuvars [nEntries] = vars [
j];
205 tabubounds [nEntries] = x_rounded + 1.;
206 tabuboundtypes [nEntries++] = SCIP_BOUNDTYPE_LOWER;
213 SCIP_CALL (SCIPcreateConsBounddisjunction (scip, &tabucons,
"Tabu Solution", nEntries,
214 tabuvars, tabuboundtypes, tabubounds,
215 TRUE, TRUE, TRUE, TRUE, TRUE,
216 FALSE, FALSE, FALSE, FALSE, FALSE));
218 SCIP_CALL( SCIPaddCons(scip, tabucons) );
220 SCIP_CALL (SCIPreleaseCons (scip, &tabucons));
225 for (
int i=0; i<nconss; i++) {
229 char consname[SCIP_MAXSTRLEN];
230 (
void) SCIPsnprintf(consname, SCIP_MAXSTRLEN,
"row_%d", i);
233 checkInfinity(scip, lhss[i], infinity);
234 checkInfinity(scip, rhss[i], infinity);
237 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, 0, NULL, NULL, lhss[i], rhss[i],
238 TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
241 for(
int j=rowstarts[i]; j<rowstarts[i]+rowlengths[i]; j++)
243 checkInfinity(scip, coeffs[j], infinity);
244 SCIP_CALL( SCIPaddCoefLinear(scip, cons, vars[indices[j]], coeffs[j]) );
248 SCIP_CALL( SCIPaddCons(scip, cons) );
249 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
258 currentmilpmethod = 2;
260 currentmilpmethod = 4;
270 SCIP_CALL( SCIPresetParams(scip) );
274 SCIP_CALL( SCIPsetIntParam(scip,
"display/verblevel", 0) );
278 SCIP_CALL( SCIPsetBoolParam(scip,
"misc/catchctrlc", FALSE) );
281 timelimit =
problem_ -> getMaxCpuTime () - CoinCpuTime ();
286 SCIP_CALL( SCIPsetRealParam(scip,
"limits/time", timelimit) );
289 SCIPinfoMessage(scip, NULL,
"using MILP method: %d\n",currentmilpmethod);
299 switch(currentmilpmethod)
304 SCIP_CALL( SCIPsetLongintParam(scip,
"constraints/rowcuts/maxcuttingrounds", 0) );
309 SCIP_CALL( SCIPsetIntParam(scip,
"limits/bestsol", 1) );
314 SCIP_CALL( SCIPsetLongintParam(scip,
"limits/stallnodes", 1000) );
315 SCIP_CALL( SCIPsetLongintParam(scip,
"limits/nodes", 10000) );
316 SCIP_CALL( SCIPsetRealParam (scip,
"limits/gap", .001) );
325 SCIP_CALL( SCIPsetHeuristics(scip, SCIP_PARAMSETTING_AGGRESSIVE, TRUE) );
355 SCIP_CALL( SCIPsetLongintParam(scip,
"limits/stallnodes", 500) );
356 SCIP_CALL( SCIPsetLongintParam(scip,
"limits/nodes", 5000) );
357 SCIP_CALL( SCIPsetRealParam (scip,
"limits/gap", .005) );
361 SCIP_CALL( SCIPsetSeparating(scip, SCIP_PARAMSETTING_FAST, TRUE) );
362 SCIP_CALL( SCIPsetPresolving(scip, SCIP_PARAMSETTING_FAST, TRUE) );
363 SCIP_CALL( SCIPsetIntParam(scip,
"branching/pscost/priority", INT_MAX/4) );
367 SCIP_CALL( SCIPsetLongintParam(scip,
"limits/nodes", 1) );
370 SCIP_CALL( SCIPsetSeparating(scip, SCIP_PARAMSETTING_OFF, TRUE) );
373 SCIP_CALL( SCIPsetPresolving(scip, SCIP_PARAMSETTING_FAST, TRUE) );
376 SCIP_CALL( SCIPsetHeuristics(scip, SCIP_PARAMSETTING_FAST, TRUE) );
379 if( SCIPfindBranchrule(scip,
"inference") != NULL )
381 SCIP_CALL( SCIPsetIntParam(scip,
"branching/inference/priority", INT_MAX/4) );
385 if( SCIPfindHeur(scip,
"rens") != NULL )
387 SCIP_CALL( SCIPsetIntParam(scip,
"heuristics/rens/freq", 0) );
388 SCIP_CALL( SCIPsetRealParam(scip,
"heuristics/rens/minfixingrate", 0.0) );
392 SCIP_CALL( SCIPsetLongintParam(scip,
"constraints/rowcuts/maxcuttingrounds", 0) );
397 SCIP_CALL( SCIPsetLongintParam(scip,
"limits/nodes", 1) );
400 SCIP_CALL( SCIPsetSeparating(scip, SCIP_PARAMSETTING_OFF, TRUE) );
403 SCIP_CALL( SCIPsetPresolving(scip, SCIP_PARAMSETTING_FAST, TRUE) );
406 SCIP_CALL( SCIPsetHeuristics(scip, SCIP_PARAMSETTING_FAST, TRUE) );
409 if( SCIPfindBranchrule(scip,
"inference") != NULL )
411 SCIP_CALL( SCIPsetIntParam(scip,
"branching/inference/priority", INT_MAX/4) );
415 if( SCIPfindHeur(scip,
"feaspump") != NULL )
417 SCIP_CALL( SCIPsetIntParam(scip,
"heuristics/feaspump/freq", 0) );
418 SCIP_CALL( SCIPsetIntParam(scip,
"heuristics/feaspump/maxsols", -1) );
423 if( SCIPversion() <= 2.01 )
425 SCIP_CALL( SCIPsetBoolParam(scip,
"heuristics/feaspump2/stage3", TRUE) );
429 SCIP_CALL( SCIPsetBoolParam(scip,
"heuristics/feaspump/stage3", TRUE) );
434 SCIP_CALL( SCIPsetLongintParam(scip,
"constraints/rowcuts/maxcuttingrounds", 0) );
440 SCIP_CALL( SCIPsetLongintParam(scip,
"limits/stallnodes", 500) );
441 SCIP_CALL( SCIPsetLongintParam(scip,
"limits/nodes", 5000) );
442 SCIP_CALL( SCIPsetRealParam (scip,
"limits/gap", .05) );
449 nSol =
milp_ -> getColSolution ();
456 SCIP_CALL( SCIPcreateSol(scip, &scipSol, NULL ));
457 SCIP_CALL(SCIPsetSolVals(scip, scipSol, nvars, vars,(
double*) sol));
464 SCIP_CALL( SCIPsetLongintParam(scip,
"limits/stallnodes", 500) );
465 SCIP_CALL( SCIPsetLongintParam(scip,
"limits/nodes", 5000) );
466 SCIP_CALL( SCIPsetRealParam (scip,
"limits/gap", .05) );
472 nSol =
milp_ -> getColSolution ();
474 for (
int j = 0; j <
problem_ -> nVars (); ++
j)
476 (
problem_ -> Var (j) -> Multiplicity () <= 0) ? 0. :
480 SCIP_CALL( SCIPcreateSol(scip, &scipSol, NULL ));
481 SCIP_CALL(SCIPsetSolVals(scip, scipSol, nvars, vars, (
double*) sol));
487 printf(
"Invalid MILP method in feasibility pump: %d\n", currentmilpmethod);
494 SCIP_CALL(SCIPtransformProb(scip));
497 SCIP_CONSHDLR* conshdlr_bounddisjunction = SCIPfindConshdlr(scip,
"bounddisjunction");
498 int nbdconss= SCIPconshdlrGetNConss(conshdlr_bounddisjunction);
499 SCIP_CONS** bdconss = SCIPconshdlrGetConss(conshdlr_bounddisjunction);
501 for(
int i=0; i < nbdconss; i++)
503 SCIP_CONS* checkcons = bdconss[i];
504 SCIP_VAR** checkvars = SCIPgetVarsBounddisjunction(scip, checkcons);
505 SCIP_Real* checkbounds = SCIPgetBoundsBounddisjunction(scip,checkcons);
506 SCIP_BOUNDTYPE* checkboundtypes =SCIPgetBoundtypesBounddisjunction(scip, checkcons);
507 int checknvars = SCIPgetNVarsBounddisjunction(scip, checkcons);
509 for(
int j=i+1; j < nbdconss; j++)
511 SCIP_CONS* tmpcons =SCIPconshdlrGetConss(conshdlr_bounddisjunction)[
j];
512 SCIP_VAR **tmpvars = SCIPgetVarsBounddisjunction(scip,tmpcons);
513 SCIP_Real *tmpbounds =SCIPgetBoundsBounddisjunction(scip, tmpcons);
514 SCIP_BOUNDTYPE *tmpboundtypes =SCIPgetBoundtypesBounddisjunction(scip, tmpcons);
515 int tmpnvars = SCIPgetNVarsBounddisjunction(scip, tmpcons);
518 if( checknvars != tmpnvars )
521 for(k=0; k < tmpnvars; k++)
522 if(tmpvars[k] != checkvars[k] || tmpbounds[k] !=checkbounds[k] || tmpboundtypes[k] != checkboundtypes[k])
526 problem_ -> Jnlst () -> Printf (Ipopt::J_WARNING,
J_NLPHEURISTIC,
"ZZZ identical bounddisjunction constraints\n");
535 SCIP_CALL( SCIPwriteOrigProblem(scip,
"debug.lp", NULL, FALSE) );
536 SCIP_CALL( SCIPwriteParams(scip,
"debug.set", FALSE,TRUE) );
542 SCIP_RETCODE retcode = SCIPsolve (scip);
546 if (SCIPgetStatus (scip) == SCIP_STATUS_INFEASIBLE) {
549 SCIP_CALL( SCIPwriteOrigProblem(scip,
"debug.lp", NULL, FALSE) );
550 SCIP_CALL( SCIPwriteParams(scip,
"debug.set", FALSE, TRUE));
552 printf (
"SCIP found that the problem is infeasible, exiting\n");
559 SCIP_CALL( SCIPprintStatistics(scip, NULL) );
563 problem_ -> Jnlst () -> Printf (Ipopt::J_ERROR,
J_NLPHEURISTIC,
"[FeasPump-SCIP] %5d %5d %7.2f\n", SCIPgetNVars(scip), SCIPgetNConss(scip), SCIPgetSolvingTime(scip));
565 if (retcode != SCIP_OKAY) {
566 problem_ -> Jnlst () -> Printf (Ipopt::J_WARNING,
J_NLPHEURISTIC,
"Couenne FP: SCIPsolve did not succeed\n");
570 nscipsols = SCIPgetNSols(scip);
577 SCIP_Real cutoffbound;
584 bestsol = SCIPgetBestSol(scip);
585 assert(bestsol != NULL);
588 scipsols = SCIPgetSols(scip);
589 assert(scipsols != NULL);
595 SCIP_CALL( SCIPgetSolVals(scip, bestsol,
problem_ -> nVars (), vars, sol) );
596 obj = SCIPgetSolOrigObj(scip, bestsol);
601 cutoffbound = obj > 0 ? 2*obj : obj / 2.0;
605 for(
int i=1; i<nscipsols && nstoredsols < 10 &&
606 (objval = SCIPgetSolOrigObj(scip,scipsols[i])) <= cutoffbound; i++){
611 SCIP_CALL( SCIPgetSolVals(scip, scipsols[i],
problem_ -> nVars (), vars, tmpsol) );
618 &&
pool_ -> Set (). find (couennesol) ==
pool_ -> Set() .
end ()
621 pool_ -> Set (). insert (couennesol);
631 if(
milpMethod_ == 0 && *nsuciter >= 3 && currentmilpmethod < 4 )
638 else if(
milpMethod_ == 0 && currentmilpmethod > 1 )
645 SCIP_CALL( SCIPfreeTransform(scip) );
652 }
while (solveagain);
659 for (
int i=0; i<nvars; i++) {
660 SCIP_CALL( SCIPreleaseVar(scip, &vars[i]) );
664 SCIPfreeMemoryArray(scip, &vars);
667 SCIPfreeMemoryArray(scip, &tabuvars );
668 SCIPfreeMemoryArray(scip, &tabubounds );
669 SCIPfreeMemoryArray(scip, &tabuboundtypes);
674 SCIP_CALL( SCIPfree(&scip) );
676 BMScheckEmptyMemory();
int nVars() const
Total number of variables.
CouenneCutGenerator * couenneCG_
CouenneCutGenerator for linearization cuts.
enum fpCutPlane milpCuttingPlane_
Separate convexification cuts during or after MILP.
CouenneFPpool * pool_
Pool of solutions.
int milpMethod_
Which SCIP MILP method to use.
Class containing a solution with infeasibility evaluation.
constraint handler for rowcuts constraints enables separation of convexification cuts during SCIP sol...
std::set< CouenneFPsolution, compareSol > tabuPool_
Solutions to avoid.
double CouNumber
main number type in Couenne
const Ipopt::EJournalCategory J_NLPHEURISTIC(Ipopt::J_USER5)
CouenneProblem * problem_
Couenne representation of the problem.
OsiSolverInterface * milp_
MILP relaxation of the MINLP (used to find integer, non-NLP-feasible solutions)
void fint fint fint real fint real * x
bool isInteger(CouNumber x)
is this number integer?