12 #include "CbcModel.hpp"
13 #include "CoinTime.hpp"
14 #include "CoinHelperFunctions.hpp"
27 #include "scip/scip.h"
28 #include "scip/cons_linear.h"
29 #include "scip/scipdefplugins.h"
32 using namespace Ipopt;
33 using namespace Couenne;
39 int CouenneFeasPump::solution (
double &objVal,
double *newSolution) {
41 const int depth = (model_ && (model_ -> currentNode ())) ? model_ -> currentNode () -> depth () : 0;
43 double time0 = CoinCpuTime();
49 (CoinCpuTime () >= problem_ -> getMaxCpuTime ()) ||
50 ((numberSolvePerLevel_ >= 0) &&
51 (CoinDrand48 () > 1. / CoinMax
52 (1., (
double) ((CoinMax (0, depth - numberSolvePerLevel_ + 1)) *
53 (depth - numberSolvePerLevel_ + 1))))))
59 problem_ -> Jnlst () -> Printf (J_WARNING,
J_NLPHEURISTIC,
"==================================================== FP: BEGIN\n");
60 problem_ -> Jnlst () -> Printf (J_ERROR,
J_NLPHEURISTIC,
"[FeasPump] Initializing\n");
74 problem_ -> domain () -> push (model_ -> solver ());
84 for (
int i=problem_ -> nVars (); i--;) {
85 chg_bds [i]. setLower (t_chg_bounds::CHANGED);
86 chg_bds [i]. setUpper (t_chg_bounds::CHANGED);
89 bool is_still_feas = problem_ -> btCore (chg_bds);
97 *lb = problem_ -> domain () -> lb (),
98 *ub = problem_ -> domain () -> ub (),
99 *sol = problem_ -> domain () ->
x ();
101 for (
int i=problem_ -> nVars (); i--;)
103 if (sol [i] < lb [i]) sol [i] = lb [i];
104 else if (sol [i] > ub [i]) sol [i] = ub [i];
109 nlp_ -> setInitSol (sol);
113 if ((multHessNLP_ != 0.) ||
114 (multHessMILP_ != 0.))
115 nlp_ -> getSaveOptHessian () =
true;
117 if (problem_ -> Jnlst () -> ProduceOutput (J_ALL,
J_NLPHEURISTIC)) {
118 printf (
"initial: solving NLP:---------\n");
119 problem_ -> print ();
120 printf (
"---------------------\n");
123 problem_ -> Jnlst () -> Printf (J_WARNING,
J_NLPHEURISTIC,
"FP: Initial NLP... "); fflush (stdout);
126 ApplicationReturnStatus status = app_ -> OptimizeTNLP (nlp_);
129 problem_ -> Jnlst () -> Printf (J_WARNING,
J_NLPHEURISTIC,
"done\n"); fflush (stdout);
131 if (nlp_ -> getSolution () && (problem_ -> Jnlst () -> ProduceOutput (J_ALL,
J_NLPHEURISTIC))) {
132 printf (
"######################## NLP solution (init):\n");
133 for (
int i=0; i< problem_ -> nVars ();) {
134 printf (
"%+e ", nlp_ -> getSolution () [i]);
135 if (!(++i % 15)) printf (
"\n");
137 if ((problem_ -> nVars () - 1) % 5) printf (
"\n");
144 if ((status != Solve_Succeeded) && (status != Solved_To_Acceptable_Level))
145 problem_ -> Jnlst () -> Printf (J_WARNING,
J_NLPHEURISTIC,
"Feasibility Pump: error in initial NLP problem\n");
147 if ((multHessNLP_ != 0.) ||
148 (multHessMILP_ != 0.))
149 nlp_ -> getSaveOptHessian () =
false;
190 objInd = problem_ -> Obj (0) -> Body () -> Index ();
192 if (nlp_ -> getSolution ())
193 nSol = CoinCopyOfArray (nlp_ -> getSolution (), problem_ -> nVars ());
195 bool isNlpFeas = problem_ -> checkNLP0 (nSol,
220 expression *originalObjective = problem_ -> Obj (0) -> Body ();
223 save_mDN = multDistNLP_,
224 save_mHN = multHessNLP_,
225 save_mON = multObjFNLP_,
226 save_mDM = multDistMILP_,
227 save_mHM = multHessMILP_,
228 save_mOM = multObjFMILP_;
232 if (CoinCpuTime () > problem_ -> getMaxCpuTime ())
236 multDistNLP_ *= fabs (save_mDN);
237 multHessNLP_ *= fabs (save_mHN);
238 multObjFNLP_ *= fabs (save_mON);
239 multDistMILP_ *= fabs (save_mDM);
240 multHessMILP_ *= fabs (save_mHM);
241 multObjFMILP_ *= fabs (save_mOM);
244 problem_ -> Jnlst () -> Printf (J_ERROR,
J_NLPHEURISTIC,
"[FeasPump] Iteration %d [%gs]\n", niter, CoinCpuTime() - time0);
252 bool bad_IP_sol =
false;
254 double z = solveMILP (nSol, iSol, niter, &nsuciter);
257 if (milp_ && milp_ -> getColLower ()) {
258 printf (
"fixed in milp_: ");
259 for (
int i=0; i<problem_ -> nVars (); ++i)
260 if (fabs (milp_ -> getColUpper () [i] -
265 problem_ -> domain () -> push (model_ -> solver ());
266 printf (
"\nfixed in model_: ");
267 for (
int i=0; i<problem_ -> nVars (); ++i)
268 if (fabs (problem_ -> Ub (i) - problem_ -> Lb (i)) <
COUENNE_EPS)
270 problem_ -> domain () -> pop ();
272 problem_ -> domain () -> push (*(problem_ -> domain () -> current ()));
273 printf (
"\nfixed in problem_: ");
274 for (
int i=0; i<problem_ -> nVars (); ++i)
275 if (fabs (problem_ -> Ub (i) - problem_ -> Lb (i)) <
COUENNE_EPS)
277 problem_ -> domain () -> pop ();
283 bool try_again =
false;
285 if (!iSol || z >= COIN_DBL_MAX/2) {
287 problem_ -> Jnlst () -> Printf (J_WARNING,
J_NLPHEURISTIC,
"FP: could not find IP solution\n");
290 while (!pool_ -> Set (). empty ()) {
293 pool_ -> findClosestAndReplace (iSol, iSol, problem_ -> nVars ());
298 if (tabuPool_ . find (newSol) == tabuPool_ .
end ()) {
315 int n = problem_ -> nVars ();
318 iSol =
new double [
n];
320 for (
int i=0; i<
n; i++)
321 iSol [i] = (problem_ -> Var (i) ->
isInteger ()) ?
332 bool isChecked =
false;
341 problem_ -> Jnlst () -> Printf (J_WARNING,
J_NLPHEURISTIC,
"FP: %d solutions in pool, %d in tabu list\n", pool_ -> Set (). size (), tabuPool_ . size ());
345 if (tabuPool_. find (checkedSol) == tabuPool_ .
end ())
351 problem_ -> Jnlst () -> Printf (J_WARNING,
J_NLPHEURISTIC,
"FP: found solution is tabu\n");
356 if (tabuMgt_ == FP_TABU_NONE)
break;
358 else if ((tabuMgt_ == FP_TABU_POOL) && !(pool_ -> Set (). empty ())) {
365 pool_ -> findClosestAndReplace (iSol, nSol, problem_ -> nVars ());
370 if (tabuPool_. find (newSol) == tabuPool_ .
end ()) {
372 tabuPool_ . insert (newSol);
377 if (pool_ -> Set ().empty ())
379 int n = problem_ -> nVars ();
382 iSol =
new double [
n];
384 for (
int i=0; i<
n; i++)
385 iSol [i] = (problem_ -> Var (i) ->
isInteger ()) ?
393 }
while( !pool_ -> Set ().empty() );
395 }
else if (((tabuMgt_ == FP_TABU_CUT) ||
396 ((pool_ -> Set (). empty ()) && iSol))) {
400 problem_ -> domain () -> push (problem_ -> nVars (), iSol, milp_ -> getColLower (), milp_ -> getColUpper (),
false);
401 couenneCG_ -> genRowCuts (*milp_, cs, 0, NULL);
402 problem_ -> domain () -> pop ();
404 if (cs.sizeRowCuts ()) {
406 milp_ -> applyCuts (cs);
408 if (nSep++ < nSepRounds_)
413 }
else if ((tabuMgt_ == FP_TABU_PERTURB) && iSol) {
418 *lb = milp_ -> getColLower (),
419 *ub = milp_ -> getColUpper ();
425 int startIndex = (
int) floor (CoinDrand48 () * problem_ -> nOrigVars ());
427 for (
int ii = problem_ -> nOrigVars (); ii--; lb++, ub++) {
429 if (problem_ -> Var (ii) -> Multiplicity () <= 0)
434 int i = (startIndex + ii) % problem_ -> nOrigVars ();
436 if (problem_ -> Var (i) ->
isInteger ()) {
439 rnd = CoinDrand48 (),
448 #define RND_DECR_EXPONENT .5
450 if (iSol [i] >= lb [i] + 1.) down = 1. / pow (1. + (downMoves += 1.),
RND_DECR_EXPONENT);
453 if (rnd < down) iSol [i] -= 1.;
454 else if (rnd >
up) iSol [i] += 1.;
463 problem_ -> Jnlst () -> Printf (J_WARNING,
J_NLPHEURISTIC,
"FP: checking IP solution for feasibility\n");
465 isChecked = problem_ -> checkNLP0 (iSol, z,
true,
484 z > problem_ -> getCutOff ())) {
486 problem_ -> Jnlst () -> Printf (J_WARNING,
J_NLPHEURISTIC,
"FP: infeasible/non-improving (feas==%d, z=%g, cutoff=%g), looping on pool\n", isChecked, z, problem_->getCutOff ());
494 if (CoinCpuTime () > problem_ -> getMaxCpuTime ())
499 if (fixIntVariables (iSol)) {
501 nlp_ -> setInitSol (iSol);
503 if (problem_ -> Jnlst () -> ProduceOutput (J_ALL,
J_NLPHEURISTIC)) {
504 printf (
"----------------------- Solving NLP:\n");
505 problem_ -> print ();
506 printf (
"-----------------------\n");
509 status = app_ -> OptimizeTNLP (nlp_);
511 if (nlp_ -> getSolution ()) {
512 if (nSol) CoinCopyN (nlp_ -> getSolution (), problem_ -> nVars (), nSol);
513 else nSol = CoinCopyOfArray (nlp_ -> getSolution (), problem_ -> nVars ());
516 if (nlp_ -> getSolution () && (problem_ -> Jnlst () -> ProduceOutput (J_ALL,
J_NLPHEURISTIC))) {
517 printf (
"######################## NLP solution (loop through pool):\n");
518 for (
int i=0; i< problem_ -> nVars ();) {
519 printf (
"%+e ", nlp_ -> getSolution () [i]);
520 if (!(++i % 15)) printf (
"\n");
524 z = nlp_ -> getSolValue ();
526 if (z < problem_ -> getCutOff ())
528 isChecked = problem_ -> checkNLP0 (nSol, z,
true,
533 if (isChecked && (z < problem_ -> getCutOff ()))
542 while (!pool_ -> Set (). empty ()) {
545 pool_ -> findClosestAndReplace (iSol, nSol, problem_ -> nVars ());
550 if (tabuPool_ . find (newSol) == tabuPool_ .
end ()) {
552 tabuPool_ . insert (newSol);
566 problem_ -> Jnlst () -> Printf (J_WARNING,
J_NLPHEURISTIC,
"FP: IP solution is MINLP feasible\n");
603 if (z < problem_ -> getCutOff ()) {
605 problem_ -> setCutOff (objVal);
611 chg_bds [objInd].
setUpper (t_chg_bounds::CHANGED);
616 bool is_still_feas = problem_ -> btCore (chg_bds);
628 *plb = problem_ -> Lb (),
629 *pub = problem_ -> Ub (),
630 *mlb = milp_ -> getColLower (),
631 *mub = milp_ -> getColUpper ();
633 for (
int i=problem_ -> nVars (),
j=0; i--; ++
j, ++plb, ++pub) {
635 bool neglect = problem_ -> Var (
j) -> Multiplicity () <= 0;
638 if (*plb > *mlb++) milp_ -> setColLower (
j, neglect ? 0. : *plb);
639 if (*pub < *mub++) milp_ -> setColUpper (
j, neglect ? 0. : *pub);
647 problem_ -> Jnlst () -> Printf (J_WARNING,
J_NLPHEURISTIC,
"FP: IP solution NOT MINLP feasible\n");
649 if (milpCuttingPlane_ == FP_CUT_EXTERNAL ||
650 milpCuttingPlane_ == FP_CUT_POST) {
657 problem_ -> domain () -> push (milp_);
658 couenneCG_ -> genRowCuts (*milp_, cs, 0, NULL);
659 problem_ -> domain () -> pop ();
661 if (cs.sizeRowCuts ()) {
665 milp_ -> applyCuts (cs);
668 if (milpCuttingPlane_ == FP_CUT_EXTERNAL &&
669 nSep++ < nSepRounds_)
686 z = solveNLP (iSol, nSol);
688 if ((nSol && iSol) &&
689 (problem_ -> Jnlst () -> ProduceOutput (J_WARNING,
J_NLPHEURISTIC))) {
694 for (
int i = 0; i < problem_ -> nVars (); ++i) {
698 if (e -> Multiplicity () <= 0)
702 (fabs (iSol [i] - ceil (iSol [i] - .5)) >
COUENNE_EPS))
706 (iSol [i] - nSol [i]) *
707 (iSol [i] - nSol [i]);
710 printf (
"FP: after NLP, distance %g, %d nonintegers\n", sqrt (dist), nNonint);
713 if (problem_ -> Jnlst () -> ProduceOutput (J_WARNING,
J_NLPHEURISTIC)) {
719 if (z > COIN_DBL_MAX/2)
728 isChecked = problem_->checkNLP0 (nSol, z,
true,
734 if (nSol && isChecked) {
736 problem_ -> Jnlst () -> Printf (J_WARNING,
J_NLPHEURISTIC,
"FP: NLP solution is MINLP feasible\n");
741 #ifdef FM_TRACE_OPTSOL // - if ----------------------------
743 problem_->getRecordBestSol()->update();
745 problem_->getRecordBestSol()->update(nSol, problem_->nVars(), z, problem_->getFeasTol());
747 best = problem_->getRecordBestSol()->getSol();
748 objVal = problem_->getRecordBestSol()->getVal();
749 #else // - else --------------------------
751 best = problem_->getRecordBestSol()->getModSol(problem_ -> nVars ());
756 #endif // - endif -------------------------
758 if (z < problem_ -> getCutOff ()) {
760 problem_ -> setCutOff (objVal);
767 chg_bds [objInd].
setUpper (t_chg_bounds::CHANGED);
771 bool is_still_feas = problem_ -> btCore (chg_bds);
786 }
while ((niter++ < maxIter_) &&
789 problem_ -> Jnlst () -> Printf (J_WARNING,
J_NLPHEURISTIC,
"FP: out of the FP loop (feas=%d\n)", retval);
800 nlp_ -> setObjective (originalObjective);
804 problem_ -> Jnlst () -> Printf (J_WARNING,
J_NLPHEURISTIC,
"FP: fix integer variables and rerun NLP\n");
809 problem_ -> domain () -> push (*(problem_ -> domain () -> current ()));
815 if (fixIntVariables (best)) {
817 nlp_ -> setInitSol (best);
824 status = app_ -> OptimizeTNLP (nlp_);
828 if ((status != Solve_Succeeded) &&
829 (status != Solved_To_Acceptable_Level))
832 "Feasibility Pump: error in final NLP problem (due to fixing integer variables?)\n");
834 if (nlp_ -> getSolution () && (problem_ -> Jnlst () -> ProduceOutput (J_ALL,
J_NLPHEURISTIC))) {
835 printf (
"######################## NLP solution (post):\n");
836 for (
int i=0; i< problem_ -> nVars ();) {
837 printf (
"%+e ", nlp_ -> getSolution () [i]);
838 if (!(++i % 15)) printf (
"\n");
844 double z = nlp_ -> getSolValue ();
847 bool isChecked =
false;
851 problem_ -> Jnlst () -> Printf (J_WARNING,
J_NLPHEURISTIC,
"FP: found nlp solution, check it\n");
853 isChecked = problem_ -> checkNLP0 (nSol, z,
true,
861 (z < problem_ -> getCutOff ())) {
863 problem_ -> Jnlst () -> Printf (J_WARNING,
J_NLPHEURISTIC,
"FP: feasible solution is improving\n");
865 #ifdef FM_TRACE_OPTSOL
868 problem_->getRecordBestSol()->update();
870 problem_->getRecordBestSol()->update(nSol, problem_->nVars(), z, problem_->getFeasTol());
872 best = problem_->getRecordBestSol()->getSol();
873 objVal = problem_->getRecordBestSol()->getVal();
877 best = problem_->getRecordBestSol()->getModSol(problem_ -> nVars ());
884 problem_ -> setCutOff (objVal);
888 problem_ -> domain () -> pop ();
890 if (problem_ -> Jnlst () -> ProduceOutput (J_WARNING,
J_NLPHEURISTIC)) {
891 printf (
"FP: returning MINLP feasible solution:\n");
895 CoinCopyN (best, problem_ -> nVars (), newSolution);
900 multDistNLP_ = save_mDN * fadeMult_;
901 multHessNLP_ = save_mHN * fadeMult_;
902 multObjFNLP_ = save_mON * fadeMult_;
903 multDistMILP_ = save_mDM * fadeMult_;
904 multHessMILP_ = save_mHM * fadeMult_;
905 multObjFMILP_ = save_mOM * fadeMult_;
907 if (iSol)
delete [] iSol;
908 if (nSol)
delete [] nSol;
911 problem_ -> domain () -> pop ();
919 milp_ = postlp_ = NULL;
926 problem_ -> Jnlst () -> Printf
930 problem_ -> Jnlst () -> Printf
933 if (retval && (-2 == nCalls_)) {
934 problem_ -> bonBase () -> options () -> SetNumericValue (
"time_limit", 0.001,
"couenne.");
951 p -> domain () -> push (n, v, NULL, NULL);
953 norm = infI = infN = 0.;
964 for (std::vector <exprVar *>::iterator i = p ->
Variables (). begin ();
968 if ((*i) -> Multiplicity () <= 0)
976 double inf = CoinMax (vval - floor (vval +
COUENNE_EPS),
985 if ((*i) -> Type () ==
AUX) {
989 fval = (*((*i) -> Image ())) ();
991 if ((*i) -> sign () != expression::AUX_GEQ) diff = CoinMax (diff, vval - fval);
992 else if ((*i) -> sign () != expression::AUX_LEQ) diff = CoinMax (diff, fval - vval);
1001 p -> domain () -> pop ();
1008 int nInfII = -1, nInfNI = -1, nInfIN = -1, nInfNN = -1;
1012 normI = -1., normN = -1.,
1013 infII = -1., infNI = -1.,
1014 infIN = -1., infNN = -1.;
1016 if (iSol)
compDistSingle (p, p -> nVars (), iSol, normI, nInfII, nInfNI, infII, infNI);
1017 if (nSol)
compDistSingle (p, p -> nVars (), nSol, normN, nInfIN, nInfNN, infIN, infNN);
1023 for (
int i = p -> nVars (); i--;) {
1025 if (p -> Var (i) -> Multiplicity () <= 0)
1029 (iSol [i] - nSol [i]) *
1030 (iSol [i] - nSol [i]);
1037 printf (
"IP norm i:%e n:%e dist %e #inf i:%4d n:%4d max inf i:%e n:%e ", normI, normN, dist, nInfII, nInfNI, infII, infNI);
1038 printf (
"NL #inf i:%4d n:%4d max inf i:%e n:%e\n", nInfIN, nInfNN, infIN, infNN);
1046 int n = p -> nVars ();
1048 printf (
"i:%p n:%p\nFP # ",
1049 (
void *) iSol, (
void *) nSol);
1056 direction < 0 ?
'<' :
1057 direction > 0 ?
'>' :
'-';
1059 for (
int i=0; i<
n; i++) {
1061 if (p -> Var (i) -> Multiplicity () <= 0)
1064 if (i && !(i %
WRAP))
1068 iS = iSol ? iSol [i] : 12345.,
1069 nS = nSol ? nSol [i] : 54321.;
1071 printf (
"[%4d %+e -%c- %+e (%e)] ",
1073 (iSol && nSol) ? fabs (iS - nS) : 0.);
1083 distance = sqrt (distance);
1084 printf (
"\n### distance: %e\n", distance);
static Bigint * diff(Bigint *a, Bigint *b)
status of lower/upper bound of a variable, to be checked/modified in bound tightening ...
#define RND_DECR_EXPONENT
Class containing a solution with infeasibility evaluation.
void fint fint fint real fint real real real real real real real real real * e
void setUpper(ChangeStatus upper)
Class for MINLP problems with symbolic information.
void compDistSingle(CouenneProblem *p, int n, const double *v, double &norm, int &nInfI, int &nInfN, double &infI, double &infN)
void printCmpSol(CouenneProblem *p, const double *iSol, double *nSol, int direction)
double CouNumber
main number type in Couenne
const Ipopt::EJournalCategory J_NLPHEURISTIC(Ipopt::J_USER5)
Class for handling NLPs using CouenneProblem.
double distance(const double *p1, const double *p2, int size, double k=2.)
compute Euclidean distance between two points (most likely LP solutions) l_2 norm by default...
The in-memory representation of the variables element.
void printDist(CouenneProblem *p, const double *iSol, double *nSol)
void fint fint fint real fint real * x
bool isInteger(CouNumber x)
is this number integer?