CouenneFeasPump.cpp
Go to the documentation of this file.
1 /* $Id: CouenneFeasPump.cpp 1073 2014-04-11 01:38:17Z pbelotti $
2  *
3  * Name: CouenneFeasPump.cpp
4  * Authors: Pietro Belotti
5  * Timo Berthold, ZIB Berlin
6  * Purpose: Implement the Feasibility Pump heuristic class
7  * Created: August 5, 2009
8  *
9  * This file is licensed under the Eclipse Public License (EPL)
10  */
11 
12 #include "CbcModel.hpp"
13 #include "CoinTime.hpp"
14 #include "CoinHelperFunctions.hpp"
15 
16 #include "CouenneExprAux.hpp"
17 #include "CouenneFeasPump.hpp"
18 #include "CouenneProblem.hpp"
19 #include "CouenneProblemElem.hpp"
20 #include "CouenneCutGenerator.hpp"
21 #include "CouenneTNLP.hpp"
22 #include "CouenneFPpool.hpp"
23 #include "CouenneRecordBestSol.hpp"
24 
25 #ifdef COIN_HAS_SCIP
26 /* general SCIP includes */
27 #include "scip/scip.h"
28 #include "scip/cons_linear.h"
29 #include "scip/scipdefplugins.h"
30 #endif
31 
32 using namespace Ipopt;
33 using namespace Couenne;
34 
35 void printDist (CouenneProblem *p, const double *iSol, double *nSol);
36 void printCmpSol (CouenneProblem *p, const double *iSol, double *nSol, int direction);
37 
38 // Solve
39 int CouenneFeasPump::solution (double &objVal, double *newSolution) {
40 
41  const int depth = (model_ && (model_ -> currentNode ())) ? model_ -> currentNode () -> depth () : 0;
42 
43  double time0 = CoinCpuTime();
44 
45  match_ = NULL;
46 
47  if ((nCalls_ == 0) || // check upper limit on number of runs
48  //(problem_ -> nIntVars () <= 0) || // feas pump on NLP? Why not?
49  (CoinCpuTime () >= problem_ -> getMaxCpuTime ()) || // don't start if time is out
50  ((numberSolvePerLevel_ >= 0) && // stop FP after a certain level
51  (CoinDrand48 () > 1. / CoinMax // decided randomly and inversely proportional
52  (1., (double) ((CoinMax (0, depth - numberSolvePerLevel_ + 1)) * // to BB tree depth
53  (depth - numberSolvePerLevel_ + 1))))))
54  return 0;
55 
56  if (nCalls_ > 0) // only decrease it if positive. If -1, no limit on # calls
57  --nCalls_;
58 
59  problem_ -> Jnlst () -> Printf (J_WARNING, J_NLPHEURISTIC, "==================================================== FP: BEGIN\n");
60  problem_ -> Jnlst () -> Printf (J_ERROR, J_NLPHEURISTIC, "[FeasPump] Initializing\n");
61 
62  // Solve NLP once at the beginning ////////////////////////
63  //
64  // First, it possibly provides an NLP feasible point (the LP
65  // provides a neither NLP nor integer point)
66  //
67  // Second, we need it to compile the Lagrangian Hessian used as a
68  // distance
69 
70  if (!nlp_) // first call (in this run of FP). Create NLP
71  nlp_ = new CouenneTNLP (problem_);
72 
73  //problem_ -> domain () -> push (*(problem_ -> domain () -> current ()));
74  problem_ -> domain () -> push (model_ -> solver ());
75  // NOTE: FP should only get bounds from the current BB node
76 
77  // Initial Bound Tightening: since Cbc prefers (reasonably) to call
78  // a heuristic before any cut separator and because BT is instead
79  // quite fast, let's see if we can reduce bounds to get a tighter
80  // MILP relaxation.
81 
82  t_chg_bounds *chg_bds = new t_chg_bounds [problem_ -> nVars ()];
83 
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);
87  }
88 
89  bool is_still_feas = problem_ -> btCore (chg_bds);
90 
91  delete [] chg_bds;
92 
93  // Now that bounds are possibly reduced, put current point within
94  // bounds
95 
96  double
97  *lb = problem_ -> domain () -> lb (),
98  *ub = problem_ -> domain () -> ub (),
99  *sol = problem_ -> domain () -> x ();
100 
101  for (int i=problem_ -> nVars (); i--;)
102 
103  if (sol [i] < lb [i]) sol [i] = lb [i];
104  else if (sol [i] > ub [i]) sol [i] = ub [i];
105 
106  // fix integer coordinates of current (MINLP feasible!) solution
107  // and set it as initial (obviously NLP feasible) solution
108 
109  nlp_ -> setInitSol (sol);
110 
112 
113  if ((multHessNLP_ != 0.) ||
114  (multHessMILP_ != 0.))
115  nlp_ -> getSaveOptHessian () = true;
116 
117  if (problem_ -> Jnlst () -> ProduceOutput (J_ALL, J_NLPHEURISTIC)) {
118  printf ("initial: solving NLP:---------\n");
119  problem_ -> print ();
120  printf ("---------------------\n");
121  }
122 
123  problem_ -> Jnlst () -> Printf (J_WARNING, J_NLPHEURISTIC, "FP: Initial NLP... "); fflush (stdout);
124 
125  // Solve with original objective function // /|---------+
126  ApplicationReturnStatus status = app_ -> OptimizeTNLP (nlp_); // < | NLP |
127  // \|---------+
128 
129  problem_ -> Jnlst () -> Printf (J_WARNING, J_NLPHEURISTIC, "done\n"); fflush (stdout);
130 
131  if (nlp_ -> getSolution () && (problem_ -> Jnlst () -> ProduceOutput (J_ALL, J_NLPHEURISTIC))) { // check if non-NULL
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");
136  }
137  if ((problem_ -> nVars () - 1) % 5) printf ("\n");
138  }
139 
141 
142  //problem_ -> domain () -> pop ();
143 
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");
146 
147  if ((multHessNLP_ != 0.) ||
148  (multHessMILP_ != 0.))
149  nlp_ -> getSaveOptHessian () = false;
150 
151  // This FP works as follows:
152  //
153  // obtain current NLP solution xN or, if none available, current LP solution
154  //
155  // repeat {
156  //
157  // 1) compute MILP solution(s) {xI} H_1-closest to xN
158  // 2) insert them in pool
159  // 3) consider the most promising one xI in the whole pool
160  //
161  // if xI is MINLP-feasible (hack incumbent callback)
162  // update cutoff with min obj among MINLP-feasible
163  // run BT
164  // [else // a little out of the FP scheme
165  // apply linearization cuts to MILP]
166  //
167  // select subset of variables (cont or integer), fix them
168  //
169  // compute NLP solution xN that is H_2-closest to xI
170  //
171  // if MINLP feasible
172  // update cutoff with min obj among MINLP-feasible
173  // run BT
174  //
175  // } until exit condition satisfied
176  //
177  // fix integer variables
178  // resolve NLP
179 
180  CouNumber
181  *nSol = NULL, // solution of the nonlinear problem
182  *iSol = NULL, // solution of the IP problem
183  *best = NULL; // best solution found so far
184 
185  int
186  niter = 0, // iteration counter
187  nsuciter = 0, // counter for consecutive successful applications of one MILP solving method
188  retval = 0, // 1 if found a better solution
189  nSep = 0, // If separation short circuit, max # of consecutive separations
190  objInd = problem_ -> Obj (0) -> Body () -> Index ();
191 
192  if (nlp_ -> getSolution ())
193  nSol = CoinCopyOfArray (nlp_ -> getSolution (), problem_ -> nVars ());
194 
195  bool isNlpFeas = problem_ -> checkNLP0 (nSol,
196  nSol [objInd],
197  true,
198  false, // don't care about obj
199  true, // stop at first violation
200  true); // checkAll
201 
203  // _ _
204  // (_) | |
205  // _ __ ___ __ _ _ _ __ | | ___ ___ _ __
206  // | '_ ` _ \ / _` | | | | '_ \ | | / _ \ / _ \ | '_ `.
207  // | | | | | | | (_| | | | | | | | | | | (_) | | (_) | | |_) |
208  // |_| |_| |_| \__,_| |_| |_| |_| |_| \___/ \___/ | .__/
209  // | |
211 
212  // copy bounding box and current solution to the problem (better
213  // linearization cuts). Note that this push is pop()'d at the end
214  // of the main routine
215 
216  // use new bounds found in BT earlier
217 
218  //problem_ -> domain () -> push (model_ -> solver ());
219 
220  expression *originalObjective = problem_ -> Obj (0) -> Body ();
221 
222  double
223  save_mDN = multDistNLP_,
224  save_mHN = multHessNLP_,
225  save_mON = multObjFNLP_,
226  save_mDM = multDistMILP_,
227  save_mHM = multHessMILP_,
228  save_mOM = multObjFMILP_;
229 
230  if (!isNlpFeas) do { // only do this if NLP solution was not also MINLP
231 
232  if (CoinCpuTime () > problem_ -> getMaxCpuTime ())
233  break;
234 
235  if (niter) {
236  multDistNLP_ *= fabs (save_mDN); // update within loop
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);
242  }
243 
244  problem_ -> Jnlst () -> Printf (J_ERROR, J_NLPHEURISTIC, "[FeasPump] Iteration %d [%gs]\n", niter, CoinCpuTime() - time0);
245 
246  // INTEGER PART /////////////////////////////////////////////////////////
247 
248  // Solve IP using nSol as the initial point to minimize weighted
249  // l-1 distance from. If nSol==NULL, the MILP is created using the
250  // original milp's LP solution.
251 
252  bool bad_IP_sol = false;
253 
254  double z = solveMILP (nSol, iSol, niter, &nsuciter);
255 
256 #if 0
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] -
261  milp_ -> getColLower () [i]) < COUENNE_EPS)
262  printf ("%d ", i);
263  }
264 
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)
269  printf ("%d ", i);
270  problem_ -> domain () -> pop ();
271 
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)
276  printf ("%d ", i);
277  problem_ -> domain () -> pop ();
278  printf ("\n");
279 #endif
280 
281  // if no MILP solution was found, bail out
282 
283  bool try_again = false;
284 
285  if (!iSol || z >= COIN_DBL_MAX/2) {
286 
287  problem_ -> Jnlst () -> Printf (J_WARNING, J_NLPHEURISTIC, "FP: could not find IP solution\n");
288 
289  // find non-tabu solution in the solution pool
290  while (!pool_ -> Set (). empty ()) {
291 
292  // EXTRACT the closest (to nSol) IP solution from the pool
293  pool_ -> findClosestAndReplace (iSol, iSol, problem_ -> nVars ());
294 
295  CouenneFPsolution newSol (problem_, iSol);
296 
297  // we found a solution that is not in the tabu list
298  if (tabuPool_ . find (newSol) == tabuPool_ . end ()) {
299 
300  //tabuPool_ . insert (newSol);
301 
302  try_again = true;
303  break;
304  }
305  }
306 
307  if (!try_again) { // try moving around current solution
308 
309  bad_IP_sol = true;
310 
311  // SCIP could not find a MILP solution and we're somewhat
312  // locked. Round current solution and feed it to the NLP. This
313  // is better than just bailing out.
314 
315  int n = problem_ -> nVars ();
316 
317  if (!iSol)
318  iSol = new double [n];
319 
320  for (int i=0; i<n; i++)
321  iSol [i] = (problem_ -> Var (i) -> isInteger ()) ?
322  COUENNE_round (nSol [i]) :
323  nSol [i];
324  }
325 
326  // if (!try_again) { // nothing to do, bail out
327  // problem_ -> Jnlst () -> Printf (J_WARNING, J_NLPHEURISTIC, "FP: could not find from pool either, bailing out\n");
328  // break;
329  // }
330  }
331 
332  bool isChecked = false;
333 
334  // If a solution was found, but is in the tabu list, two choices:
335  //
336  // 1) the pool is empty: do a round of cuts and repeat;
337  //
338  // 2) the pool is nonempty: extract the best solution from the
339  // pool and use it instead
340 
341  problem_ -> Jnlst () -> Printf (J_WARNING, J_NLPHEURISTIC, "FP: %d solutions in pool, %d in tabu list\n", pool_ -> Set (). size (), tabuPool_ . size ());
342 
343  CouenneFPsolution checkedSol (problem_, iSol, false); // false is for not allocating space for this
344 
345  if (tabuPool_. find (checkedSol) == tabuPool_ . end ())
346 
347  tabuPool_. insert (CouenneFPsolution (problem_, iSol)); // only insertion to tabu pool: we check its feasibility now
348 
349  else {
350 
351  problem_ -> Jnlst () -> Printf (J_WARNING, J_NLPHEURISTIC, "FP: found solution is tabu\n");
352 
353  // Current solution was visited before. Replace it with another
354  // MILP solution from the pool, if any.
355 
356  if (tabuMgt_ == FP_TABU_NONE) break;
357 
358  else if ((tabuMgt_ == FP_TABU_POOL) && !(pool_ -> Set (). empty ())) {
359 
360  // try to find non-tabu solution in the solution pool
361 
362  do {
363 
364  // retrieve the top solution from the pool
365  pool_ -> findClosestAndReplace (iSol, nSol, problem_ -> nVars ());
366 
367  CouenneFPsolution newSol (problem_, iSol);
368 
369  // we found a solution that is not in the tabu list
370  if (tabuPool_. find (newSol) == tabuPool_ . end ()) {
371 
372  tabuPool_ . insert (newSol);
373  break;
374  }
375 
376  // the pool is empty -> just round
377  if (pool_ -> Set ().empty ())
378  {
379  int n = problem_ -> nVars ();
380 
381  if (!iSol)
382  iSol = new double [n];
383 
384  for (int i=0; i<n; i++)
385  iSol [i] = (problem_ -> Var (i) -> isInteger ()) ?
386  COUENNE_round (nSol [i]) :
387  nSol [i];
388 
389  // delete[] iSol;
390  // iSol = NULL;
391  }
392 
393  } while( !pool_ -> Set ().empty() );
394 
395  } else if (((tabuMgt_ == FP_TABU_CUT) ||
396  ((pool_ -> Set (). empty ()) && iSol))) {
397 
398  OsiCuts cs;
399 
400  problem_ -> domain () -> push (problem_ -> nVars (), iSol, milp_ -> getColLower (), milp_ -> getColUpper (), false); // don't copy vectors
401  couenneCG_ -> genRowCuts (*milp_, cs, 0, NULL); // remaining three arguments NULL by default
402  problem_ -> domain () -> pop ();
403 
404  if (cs.sizeRowCuts ()) {
405 
406  milp_ -> applyCuts (cs);
407 
408  if (nSep++ < nSepRounds_)
409  continue;
410 
411  } else break; // nothing left to do, just bail out
412 
413  } else if ((tabuMgt_ == FP_TABU_PERTURB) && iSol) {
414 
415  // perturb solution
416 
417  const CouNumber
418  *lb = milp_ -> getColLower (),
419  *ub = milp_ -> getColUpper ();
420 
421  double
422  downMoves = 0.,
423  upMoves = 0.;
424 
425  int startIndex = (int) floor (CoinDrand48 () * problem_ -> nOrigVars ());
426 
427  for (int ii = problem_ -> nOrigVars (); ii--; lb++, ub++) {
428 
429  if (problem_ -> Var (ii) -> Multiplicity () <= 0)
430  continue;
431 
432  // make perturbation start from pseudo-random points
433 
434  int i = (startIndex + ii) % problem_ -> nOrigVars ();
435 
436  if (problem_ -> Var (i) -> isInteger ()) {
437 
438  double
439  rnd = CoinDrand48 (),
440  down = 0.,
441  up = 1.;
442 
443  // if there is room on the left (resp. right) of the
444  // solution, consider moving down (resp. up). Make moves
445  // less likely as we don't want to perturb too many
446  // variables
447 
448 #define RND_DECR_EXPONENT .5
449 
450  if (iSol [i] >= lb [i] + 1.) down = 1. / pow (1. + (downMoves += 1.), RND_DECR_EXPONENT);
451  if (iSol [i] <= ub [i] - 1.) up = 1. - 1. / pow (1. + (upMoves += 1.), RND_DECR_EXPONENT);
452 
453  if (rnd < down) iSol [i] -= 1.;
454  else if (rnd > up) iSol [i] += 1.;
455  }
456  }
457  }
458  }
459 
460  if (!iSol)
461  break;
462 
463  problem_ -> Jnlst () -> Printf (J_WARNING, J_NLPHEURISTIC, "FP: checking IP solution for feasibility\n");
464 
465  isChecked = problem_ -> checkNLP0 (iSol, z, true,
466  false, // don't care about obj
467  true, // stop at first violation
468  true); // checkAll
469 
470  // Possible improvement: if IP-infeasible or if z does not improve
471  // the best solution found so far, then try the following:
472  //
473  // 1) Fix integer variables to IP solution's corresponding components
474  // 2) Solve restriction with original obj
475  // 3) While not found (MI)NLP solution or
476  // solution MINLP infeasible or
477  // z not better
478  // 4) Get solution x* from pool
479  // 5) Solve with original objective
480  // 6) Done
481  // 7) If found solution, set it, otherwise keep previously found (IP-feasible) one
482 
483  if ((!isChecked || // not MINLP feasible
484  z > problem_ -> getCutOff ())) { // not improving
485 
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 ());
487 
488  bool try_again;
489 
490  do {
491 
492  try_again = false;
493 
494  if (CoinCpuTime () > problem_ -> getMaxCpuTime ())
495  break;
496 
497  // Check if fixing integers to those in iSol yields an
498  // infeasible problem. If so, don't optimize
499  if (fixIntVariables (iSol)) {
500 
501  nlp_ -> setInitSol (iSol);
502 
503  if (problem_ -> Jnlst () -> ProduceOutput (J_ALL, J_NLPHEURISTIC)) {
504  printf ("----------------------- Solving NLP:\n");
505  problem_ -> print ();
506  printf ("-----------------------\n");
507  }
508 
509  status = app_ -> OptimizeTNLP (nlp_);
510 
511  if (nlp_ -> getSolution ()) { // check if non-NULL
512  if (nSol) CoinCopyN (nlp_ -> getSolution (), problem_ -> nVars (), nSol);
513  else nSol = CoinCopyOfArray (nlp_ -> getSolution (), problem_ -> nVars ());
514  }
515 
516  if (nlp_ -> getSolution () && (problem_ -> Jnlst () -> ProduceOutput (J_ALL, J_NLPHEURISTIC))) { // check if non-NULL
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");
521  }
522  }
523 
524  z = nlp_ -> getSolValue ();
525 
526  if (z < problem_ -> getCutOff ()) // don't waste time if not improving
527 
528  isChecked = problem_ -> checkNLP0 (nSol, z, true,
529  false, // don't care about obj
530  true, // stop at first violation
531  true); // checkAll
532 
533  if (isChecked && (z < problem_ -> getCutOff ()))
534  break;
535  }
536 
537  // ONLY do the following if we didn't get a good IP solution
538  // earlier (i.e. if we had to round)
539 
540  // find non-tabu solution in the solution pool
541  if (bad_IP_sol)
542  while (!pool_ -> Set (). empty ()) {
543 
544  // EXTRACT the closest (to nSol) IP solution from the pool
545  pool_ -> findClosestAndReplace (iSol, nSol, problem_ -> nVars ());
546 
547  CouenneFPsolution newSol (problem_, iSol);
548 
549  // we found a solution that is not in the tabu list
550  if (tabuPool_ . find (newSol) == tabuPool_ . end ()) {
551 
552  tabuPool_ . insert (newSol);
553  try_again = true;
554  break;
555  }
556  }
557 
558  } while (try_again);
559  }
560 
561  // Whatever the previous block yielded, we are now going to check
562  // if we have a new solution, and if so we save it.
563 
564  if (isChecked) {
565 
566  problem_ -> Jnlst () -> Printf (J_WARNING, J_NLPHEURISTIC, "FP: IP solution is MINLP feasible\n");
567 
568  // solution is MINLP feasible! Save it.
569 
570  retval = 1;
571  objVal = z;
572 
573  // Found a MINLP-feasible solution, but to keep diversity do NOT
574  // use the best available. Just use this.
575  //
576  // #ifdef FM_CHECKNLP2
577  // # ifdef FM_TRACE_OPTSOL
578  // problem_->getRecordBestSol()->update();
579  // best = problem_->getRecordBestSol()->getSol();
580  // objVal = problem_->getRecordBestSol()->getVal();
581  // # else /* not FM_TRACE_OPTSOL */
582  // best = problem_->getRecordBestSol()->getModSol(problem_->nVars());
583  // objVal = z;
584  // # endif /* not FM_TRACE_OPTSOL */
585  // #else /* not FM_CHECKNLP2 */
586  // # ifdef FM_TRACE_OPTSOL
587  // problem_->getRecordBestSol()->update(iSol, problem_->nVars(),
588  // z, problem_->getFeasTol());
589  // best = problem_->getRecordBestSol()->getSol();
590  // objVal = problem_->getRecordBestSol()->getVal();
591  // # else /* not FM_TRACE_OPTSOL */
592 
593  best = iSol;
594 
595  // objVal = z;
596  // # ifdef FM_TRACE_OPTSOL
597  // problem_->getRecordBestSol()->update();
598  // best = problem_->getRecordBestSol()->getSol();
599  // objVal = problem_->getRecordBestSol()->getVal();
600  // # endif /* not FM_TRACE_OPTSOL */
601  // #endif /* not FM_CHECKNLP2 */
602 
603  if (z < problem_ -> getCutOff ()) {
604 
605  problem_ -> setCutOff (objVal);
606 
607  t_chg_bounds *chg_bds = NULL;
608 
609  if (objInd >= 0) {
610  chg_bds = new t_chg_bounds [problem_ -> nVars ()];
611  chg_bds [objInd].setUpper (t_chg_bounds::CHANGED);
612  }
613 
614  // If, with new cutoff, bound tightening clears the whole
615  // feasible set, stop
616  bool is_still_feas = problem_ -> btCore (chg_bds);
617 
618  if (chg_bds)
619  delete [] chg_bds;
620 
621  // don't tighten MILP if BT says it's infeasible
622 
623  if (!is_still_feas)
624  break;
625 
626  // Update lb/ub on milp and nlp here
627  const CouNumber
628  *plb = problem_ -> Lb (),
629  *pub = problem_ -> Ub (),
630  *mlb = milp_ -> getColLower (),
631  *mub = milp_ -> getColUpper ();
632 
633  for (int i=problem_ -> nVars (), j=0; i--; ++j, ++plb, ++pub) {
634 
635  bool neglect = problem_ -> Var (j) -> Multiplicity () <= 0;
636 
637  // neglect'ed variables don't appear in the problem, so MILP can fix them to zero
638  if (*plb > *mlb++) milp_ -> setColLower (j, neglect ? 0. : *plb);
639  if (*pub < *mub++) milp_ -> setColUpper (j, neglect ? 0. : *pub);
640  }
641  }
642 
643  break;
644 
645  } else {
646 
647  problem_ -> Jnlst () -> Printf (J_WARNING, J_NLPHEURISTIC, "FP: IP solution NOT MINLP feasible\n");
648 
649  if (milpCuttingPlane_ == FP_CUT_EXTERNAL ||
650  milpCuttingPlane_ == FP_CUT_POST) {
651 
652  // Solution is IP- but not MINLP feasible: it might get cut by
653  // linearization cuts. If so, add a round of cuts and repeat.
654 
655  OsiCuts cs;
656 
657  problem_ -> domain () -> push (milp_);
658  couenneCG_ -> genRowCuts (*milp_, cs, 0, NULL); // remaining three arguments NULL by default
659  problem_ -> domain () -> pop ();
660 
661  if (cs.sizeRowCuts ()) {
662 
663  // the (integer, NLP infeasible) solution could be separated
664 
665  milp_ -> applyCuts (cs);
666 
667  // found linearization cut, now re-solve MILP (not quite a FP)
668  if (milpCuttingPlane_ == FP_CUT_EXTERNAL &&
669  nSep++ < nSepRounds_)
670  continue;
671  }
672  }
673  }
674 
675  //
676  // reset number of separation during non-separating iteration
677  //
678 
679  nSep = 0;
680 
681  // NONLINEAR PART ///////////////////////////////////////////////////////
682 
683  // fix some variables and solve the NLP to find a NLP (possibly
684  // non-MIP) feasible solution
685 
686  z = solveNLP (iSol, nSol);
687 
688  if ((nSol && iSol) &&
689  (problem_ -> Jnlst () -> ProduceOutput (J_WARNING, J_NLPHEURISTIC))) {
690 
691  double dist = 0.;
692  int nNonint = 0;
693 
694  for (int i = 0; i < problem_ -> nVars (); ++i) {
695 
696  exprVar *e = problem_ -> Var (i);
697 
698  if (e -> Multiplicity () <= 0)
699  continue;
700 
701  if (e -> isInteger () &&
702  (fabs (iSol [i] - ceil (iSol [i] - .5)) > COUENNE_EPS))
703  ++nNonint;
704 
705  dist +=
706  (iSol [i] - nSol [i]) *
707  (iSol [i] - nSol [i]);
708  }
709 
710  printf ("FP: after NLP, distance %g, %d nonintegers\n", sqrt (dist), nNonint);
711  }
712 
713  if (problem_ -> Jnlst () -> ProduceOutput (J_WARNING, J_NLPHEURISTIC)) {
714 
715  printDist (problem_, iSol, nSol);
716  printCmpSol (problem_, iSol, nSol, 0);
717  }
718 
719  if (z > COIN_DBL_MAX/2) // something went wrong in the NLP, bail out
720  break;
721 
722  // check if newly found NLP solution is also integer
723 
724  isChecked = false;
725 
726  if (nSol) {
727 
728  isChecked = problem_->checkNLP0 (nSol, z, true,
729  false, // do not care about obj
730  true, // stopAtFirstViol
731  true); // checkALL
732  }
733 
734  if (nSol && isChecked) {
735 
736  problem_ -> Jnlst () -> Printf (J_WARNING, J_NLPHEURISTIC, "FP: NLP solution is MINLP feasible\n");
737 
738  retval = 1;
739  objVal = z;
740 
741 #ifdef FM_TRACE_OPTSOL // - if ----------------------------
742 #ifdef FM_CHECKNLP2
743  problem_->getRecordBestSol()->update();
744 #else
745  problem_->getRecordBestSol()->update(nSol, problem_->nVars(), z, problem_->getFeasTol());
746 #endif
747  best = problem_->getRecordBestSol()->getSol();
748  objVal = problem_->getRecordBestSol()->getVal();
749 #else // - else --------------------------
750 #ifdef FM_CHECKNLP2
751  best = problem_->getRecordBestSol()->getModSol(problem_ -> nVars ());
752 #else
753  best = nSol;
754 #endif
755  objVal = z;
756 #endif // - endif -------------------------
757 
758  if (z < problem_ -> getCutOff ()) {
759 
760  problem_ -> setCutOff (objVal);
761 
762  t_chg_bounds *chg_bds = NULL;
763 
764  if (objInd >= 0) {
765 
766  chg_bds = new t_chg_bounds [problem_ -> nVars ()];
767  chg_bds [objInd].setUpper (t_chg_bounds::CHANGED);
768  }
769 
770  // if bound tightening clears the whole feasible set, stop
771  bool is_still_feas = problem_ -> btCore (chg_bds);
772 
773  if (chg_bds)
774  delete [] chg_bds;
775 
776  if (!is_still_feas)
777  break;
778  }
779  }
780 
781  // update weights for hessian, distance, and objective, for both
782  // MILP and NLP parts
783 
784  //multHessNLP_ *= save_multHessNLP_; // exponential reduction
785 
786  } while ((niter++ < maxIter_) &&
787  (retval == 0));
788 
789  problem_ -> Jnlst () -> Printf (J_WARNING, J_NLPHEURISTIC, "FP: out of the FP loop (feas=%d\n)", retval);
790 
791  // OUT OF THE LOOP ////////////////////////////////////////////////////////
792 
793  // If MINLP solution found,
794  //
795  // 1) restore original objective
796  // 2) fix integer variables
797  // 3) resolve NLP
798 
799  if (nlp_)
800  nlp_ -> setObjective (originalObjective);
801 
802  if (retval > 0) {
803 
804  problem_ -> Jnlst () -> Printf (J_WARNING, J_NLPHEURISTIC, "FP: fix integer variables and rerun NLP\n");
805 
806  if (!nlp_) // first call (in this run of FP). Create NLP
807  nlp_ = new CouenneTNLP (problem_);
808 
809  problem_ -> domain () -> push (*(problem_ -> domain () -> current ()));
810 
811  // fix integer coordinates of current (MINLP feasible!) solution
812  // and, if feasible, set it as initial (obviously NLP feasible)
813  // solution
814 
815  if (fixIntVariables (best)) {
816 
817  nlp_ -> setInitSol (best);
818 
820 
821  //app_ -> Options () -> SetStringValue ("fixed_variable_treatment", "make_parameter");
822 
823  // Solve with original objective function
824  status = app_ -> OptimizeTNLP (nlp_);
825 
827 
828  if ((status != Solve_Succeeded) &&
829  (status != Solved_To_Acceptable_Level))
830 
831  problem_ -> Jnlst () -> Printf (J_WARNING, J_NLPHEURISTIC,
832  "Feasibility Pump: error in final NLP problem (due to fixing integer variables?)\n");
833 
834  if (nlp_ -> getSolution () && (problem_ -> Jnlst () -> ProduceOutput (J_ALL, J_NLPHEURISTIC))) { // check if non-NULL
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");
839  }
840  }
841 
842  // if found a solution with the last NLP, check & save it
843 
844  double z = nlp_ -> getSolValue ();
845 
846  // check if newly found NLP solution is also integer (unlikely...)
847  bool isChecked = false;
848 
849  if (nSol) {
850 
851  problem_ -> Jnlst () -> Printf (J_WARNING, J_NLPHEURISTIC, "FP: found nlp solution, check it\n");
852 
853  isChecked = problem_ -> checkNLP0 (nSol, z, true,
854  false,
855  true,
856  true);
857  }
858 
859  if (nSol &&
860  isChecked &&
861  (z < problem_ -> getCutOff ())) {
862 
863  problem_ -> Jnlst () -> Printf (J_WARNING, J_NLPHEURISTIC, "FP: feasible solution is improving\n");
864 
865 #ifdef FM_TRACE_OPTSOL
866 
867 #ifdef FM_CHECKNLP2
868  problem_->getRecordBestSol()->update();
869 #else
870  problem_->getRecordBestSol()->update(nSol, problem_->nVars(), z, problem_->getFeasTol());
871 #endif
872  best = problem_->getRecordBestSol()->getSol();
873  objVal = problem_->getRecordBestSol()->getVal();
874 #else
875 
876 #ifdef FM_CHECKNLP2
877  best = problem_->getRecordBestSol()->getModSol(problem_ -> nVars ());
878 #else
879  best = nSol;
880 #endif
881  objVal = z;
882 #endif
883 
884  problem_ -> setCutOff (objVal);
885  }
886  }
887 
888  problem_ -> domain () -> pop ();
889 
890  if (problem_ -> Jnlst () -> ProduceOutput (J_WARNING, J_NLPHEURISTIC)) {
891  printf ("FP: returning MINLP feasible solution:\n");
892  printDist (problem_, best, nSol);
893  }
894 
895  CoinCopyN (best, problem_ -> nVars (), newSolution);
896  }
897 
898  // post-call fading update of coefficients
899 
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_;
906 
907  if (iSol) delete [] iSol;
908  if (nSol) delete [] nSol;
909 
910  // release bounding box
911  problem_ -> domain () -> pop ();
912 
913  // deleted at every call from Cbc, since it changes not only in
914  // terms of variable bounds but also in terms of linearization cuts
915  // added
916 
917  delete milp_;
918  delete postlp_;
919  milp_ = postlp_ = NULL;
920 
921  if (match_) {
922  delete [] match_;
923  match_ = NULL;
924  }
925 
926  problem_ -> Jnlst () -> Printf
927  (J_WARNING, J_NLPHEURISTIC, "FP: done ===================\n");
928 
929  if (!retval)
930  problem_ -> Jnlst () -> Printf
931  (J_ERROR, J_NLPHEURISTIC, "FP: No solution found\n");
932 
933  if (retval && (-2 == nCalls_)) {
934  problem_ -> bonBase () -> options () -> SetNumericValue ("time_limit", 0.001, "couenne.");
935  problem_ -> bonBase () -> setDoubleParameter (Bonmin::BabSetupBase::MaxTime, 0.001);
936  }
937 
938  return retval;
939 }
940 
941 // gather data on single solution for later printout
943  int n,
944  const double *v,
945  double &norm,
946  int &nInfI,
947  int &nInfN,
948  double &infI,
949  double &infN) {
950 
951  p -> domain () -> push (n, v, NULL, NULL); // don't care about bounds as not used
952 
953  norm = infI = infN = 0.;
954  nInfI = nInfN = 0;
955 
956  while (n--) {
957  norm += (*v * *v);
958  ++v;
959  }
960  v -= n;
961 
962  norm = sqrt (norm);
963 
964  for (std::vector <exprVar *>::iterator i = p -> Variables (). begin ();
965  i != p -> Variables (). end ();
966  ++i) {
967 
968  if ((*i) -> Multiplicity () <= 0)
969  continue;
970 
971  CouNumber
972  vval = (**i) ();
973 
974  if ((*i) -> isInteger ()) {
975 
976  double inf = CoinMax (vval - floor (vval + COUENNE_EPS),
977  ceil (vval - COUENNE_EPS) - vval);
978 
979  if (inf > COUENNE_EPS) {
980  ++nInfI;
981  infI += inf;
982  }
983  }
984 
985  if ((*i) -> Type () == AUX) {
986 
987  double
988  diff = 0.,
989  fval = (*((*i) -> Image ())) ();
990 
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);
993 
994  if (diff > COUENNE_EPS) {
995  ++nInfN;
996  infN += diff;
997  }
998  }
999  }
1000 
1001  p -> domain () -> pop ();
1002 }
1003 
1004 
1005 // print solutions and distances
1006 void printDist (CouenneProblem *p, const double *iSol, double *nSol) {
1007 
1008  int nInfII = -1, nInfNI = -1, nInfIN = -1, nInfNN = -1;
1009 
1010  double
1011  dist = -1.,
1012  normI = -1., normN = -1.,
1013  infII = -1., infNI = -1.,
1014  infIN = -1., infNN = -1.;
1015 
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);
1018 
1019  if (iSol && nSol) {
1020 
1021  dist = 0.;
1022 
1023  for (int i = p -> nVars (); i--;) {
1024 
1025  if (p -> Var (i) -> Multiplicity () <= 0)
1026  continue;
1027 
1028  dist +=
1029  (iSol [i] - nSol [i]) *
1030  (iSol [i] - nSol [i]);
1031  }
1032 
1033  dist = sqrt (dist);
1034  }
1035 
1036  printf ("FP: ");
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);
1039 }
1040 
1041 
1042 #define WRAP 3
1043 
1044 void printCmpSol (CouenneProblem *p, const double *iSol, double *nSol, int direction) {
1045 
1046  int n = p -> nVars ();
1047 
1048  printf ("i:%p n:%p\nFP # ",
1049  (void *) iSol, (void *) nSol);
1050 
1051  double
1052  distance = 0.,
1053  diff;
1054 
1055  char c =
1056  direction < 0 ? '<' :
1057  direction > 0 ? '>' : '-';
1058 
1059  for (int i=0; i<n; i++) {
1060 
1061  if (p -> Var (i) -> Multiplicity () <= 0)
1062  continue;
1063 
1064  if (i && !(i % WRAP))
1065  printf ("\nFP # ");
1066 
1067  double
1068  iS = iSol ? iSol [i] : 12345., // flag values, to be seen if something is wrong
1069  nS = nSol ? nSol [i] : 54321.;
1070 
1071  printf ("[%4d %+e -%c- %+e (%e)] ",
1072  i, iS, c, nS,
1073  (iSol && nSol) ? fabs (iS - nS) : 0.);
1074 
1075  if (iSol && nSol) {
1076  diff = iS - nS;
1077  distance += (diff*diff);
1078  }
1079  }
1080 
1081  if (iSol && nSol) {
1082 
1083  distance = sqrt (distance);
1084  printf ("\n### distance: %e\n", distance);
1085  }
1086 }
#define COUENNE_round(x)
static Bigint * diff(Bigint *a, Bigint *b)
Definition: OSdtoa.cpp:1120
status of lower/upper bound of a variable, to be checked/modified in bound tightening ...
#define RND_DECR_EXPONENT
static char * j
Definition: OSdtoa.cpp:3622
int up
Definition: OSdtoa.cpp:1817
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)
fint end
Class for MINLP problems with symbolic information.
#define COUENNE_EPS
static int
Definition: OSdtoa.cpp:2173
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)
#define WRAP
double CouNumber
main number type in Couenne
const Ipopt::EJournalCategory J_NLPHEURISTIC(Ipopt::J_USER5)
variable-type operator
Expression base class.
Class for handling NLPs using CouenneProblem.
Definition: CouenneTNLP.hpp:27
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.
Definition: OSInstance.h:83
void fint * n
real c
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?