generateCuts.cpp
Go to the documentation of this file.
1 /* $Id: generateCuts.cpp 1071 2014-03-13 01:35:13Z pbelotti $
2  *
3  * Name: generateCuts.cpp
4  * Author: Pietro Belotti
5  * Purpose: the generateCuts() method of the convexification class CouenneCutGenerator
6  *
7  * (C) Carnegie-Mellon University, 2006-11.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "BonCbc.hpp"
12 #include "BonBabInfos.hpp"
13 #include "CglCutGenerator.hpp"
14 
15 #include "CouenneCutGenerator.hpp"
16 #include "CouenneProblem.hpp"
17 #include "CouenneProblemElem.hpp"
18 #include "CouenneExprVar.hpp"
19 #include "CouenneInfeasCut.hpp"
20 
21 #include "CouenneRecordBestSol.hpp"
22 
23 //#define FM_PRINT_INFO
24 
25 #ifdef COIN_HAS_NTY
26 #include "Nauty.h"
27 #endif
28 
29 using namespace Ipopt;
30 
31 namespace Couenne {
32 
33 #define Couenne_large_bound2 9.99e12
34 
35 // checks bad cuts against known optimum
36 bool isOptimumCut (const CouNumber *opt, OsiCuts &cs, CouenneProblem *p);
37 
38 // set and lift bound for auxiliary variable associated with objective
39 // function
40 void fictitiousBound (OsiCuts &cs,
41  CouenneProblem *p,
42  bool action) { // true before convexifying, false afterwards
43 
44  // fictitious bound for initial unbounded lp relaxations
45  const CouNumber large_tol = (Couenne_large_bound2 / 1e6);
46 
47  // set trivial dual bound to objective function, if there is none
48 
49  int ind_obj = p -> Obj (0) -> Body () -> Index ();
50 
51  if (ind_obj < 0) return;
52 
53  // we have a single variable objective function
54 
55  //int sense = -1; //(p -> Obj (0) -> Sense () == MINIMIZE) ? -1 : 1;
56 
57  if (action)
58  //if (sense<0)
59  {if (p -> Lb (ind_obj) < - Couenne_large_bound2) p -> Lb (ind_obj) = - Couenne_large_bound2;}
60  //else {if (p -> Ub (ind_obj) > large_bound2) p -> Ub (ind_obj) = large_bound2;}
61  else
62  //if (sense>0) {if (fabs (p->Ub(ind_obj)-large_bound2)<large_tol) p->Ub(ind_obj)=COUENNE_INFINITY;}
63  //else
64  {if (fabs (p->Lb(ind_obj)+Couenne_large_bound2)<large_tol) p->Lb(ind_obj) =-COUENNE_INFINITY;}
65 }
66 
67 
68 // translate changed bound sparse array into a dense one
69 void sparse2dense (int ncols, t_chg_bounds *chg_bds, int *&changed, int &nchanged) {
70 
71  // convert sparse chg_bds in something handier
72 
73  changed = (int *) realloc (changed, ncols * sizeof (int));
74  nchanged = 0;
75 
76  for (register int i=ncols, j=0; i--; j++, chg_bds++)
77  if (chg_bds -> lower() != t_chg_bounds::UNCHANGED ||
78  chg_bds -> upper() != t_chg_bounds::UNCHANGED ) {
79  *changed++ = j;
80  nchanged++;
81  }
82 
83  changed -= nchanged;
84  //changed = (int *) realloc (changed, nchanged * sizeof (int));
85 }
86 
87 
89 void updateBranchInfo (const OsiSolverInterface &si, CouenneProblem *p,
90  t_chg_bounds *chg, const CglTreeInfo &info);
91 
93 
94 void CouenneCutGenerator::generateCuts (const OsiSolverInterface &si,
95  OsiCuts &cs,
96  const CglTreeInfo info)
97 #if CGL_VERSION_MAJOR == 0 && CGL_VERSION_MINOR <= 57
98  const
99 #endif
100  {
101 
102  // if si.lb(objInd) > cutoff,
103  // return infeasCut
104 
105  int indObj = problem_ -> Obj (0) -> Body () -> Index ();
106 
107  if ((indObj >= 0) &&
108  (si.getColLower () [indObj] > problem_ -> getCutOff () + COUENNE_EPS)) {
109 
110  WipeMakeInfeas (cs);
111  return;
112  }
113 
114  // check if out of time or if an infeasibility cut (iis of type 0)
115  // was added as a result of, e.g., pruning on BT. If so, no need to
116  // run this.
117 
118  if (isWiped (cs) ||
119  (CoinCpuTime () > problem_ -> getMaxCpuTime ()))
120  return;
121 
122 #ifdef FM_TRACE_OPTSOL
123  double currCutOff = problem_->getCutOff();
124  double bestVal = 1e50;
125  CouenneRecordBestSol *rs = problem_->getRecordBestSol();
126  if(rs->getHasSol()) {
127  bestVal = rs->getVal();
128  }
129  if(currCutOff > bestVal) {
130  //problem_ -> setCutOff (bestVal - 1e-6); // FIXME: don't add numerical constants
131  problem_ -> setCutOff (bestVal);
132 
133  if ((indObj >= 0) && (si. getColUpper () [indObj] > bestVal)) {
134  OsiColCut *objCut = new OsiColCut;
135  objCut->setUbs(1, &indObj, &bestVal);
136  cs.insert(objCut);
137  delete objCut;
138  }
139  }
140 #endif
141 
142 #ifdef FM_PRINT_INFO
143  if((BabPtr_ != NULL) && (info.level >= 0) && (info.pass == 0) &&
144  (BabPtr_->model().getNodeCount() > lastPrintLine)) {
145  printLineInfo();
146  lastPrintLine += 1;
147  }
148 #endif
149 
150  const int infeasible = 1;
151 
152  int nInitCuts = cs.sizeRowCuts ();
153 
154  CouNumber
155  *&realOpt = problem_ -> bestSol (),
156  *saveOptimum = realOpt;
157 
158  if (!firstcall_ && realOpt) {
159 
160  // have a debug optimal solution. Check if current bounds
161  // contain it, otherwise pretend it does not exist
162 
163  CouNumber *opt = realOpt;
164 
165  const CouNumber
166  *sol = si.getColSolution (),
167  *lb = si.getColLower (),
168  *ub = si.getColUpper ();
169 
170  int objind = problem_ -> Obj (0) -> Body () -> Index ();
171 
172  for (int j=0, i=problem_ -> nVars (); i--; j++, opt++, lb++, ub++)
173  if ((j != objind) &&
174  ((*opt < *lb - COUENNE_EPS * (1 + CoinMin (fabs (*opt), fabs (*lb)))) ||
175  (*opt > *ub + COUENNE_EPS * (1 + CoinMin (fabs (*opt), fabs (*ub)))))) {
176 
177  jnlst_ -> Printf (J_VECTOR, J_CONVEXIFYING,
178  "out of bounds, ignore x%d = %g [%g,%g] opt = %g\n",
179  problem_ -> nVars () - i - 1, *sol, *lb, *ub, *opt);
180 
181  // optimal point is not in current bounding box,
182  // pretend realOpt is NULL until we return from this procedure
183  realOpt = NULL;
184  break;
185  }
186  }
187 
188  /*static int count = 0;
189  char fname [20];
190  sprintf (fname, "relax_%d", count++);
191  si.writeLp (fname);
192  printf ("writing %s\n", fname);*/
193 
194  jnlst_ -> Printf (J_DETAILED, J_CONVEXIFYING,
195  "generateCuts: level = %d, pass = %d, intree = %d\n",
196  info.level, info.pass, info.inTree);
197 
198  Bonmin::BabInfo * babInfo = dynamic_cast <Bonmin::BabInfo *> (si.getAuxiliaryInfo ());
199 
200  if (babInfo)
201  babInfo -> setFeasibleNode ();
202 
203  double now = CoinCpuTime ();
204  int ncols = problem_ -> nVars ();
205 
206  // This vector contains variables whose bounds have changed due to
207  // branching, reduced cost fixing, or bound tightening below. To be
208  // used with malloc/realloc/free
209 
210  t_chg_bounds *chg_bds = new t_chg_bounds [ncols];
211 
212  /*for (int i=0; i < ncols; i++)
213  if (problem_ -> Var (i) -> Multiplicity () <= 0) {
214  chg_bds [i].setLower (t_chg_bounds::UNCHANGED);
215  chg_bds [i].setUpper (t_chg_bounds::UNCHANGED);
216  }*/
217 
218  problem_ -> installCutOff (); // install upper bound
219 
220  if (firstcall_) {
221 
222  // First convexification //////////////////////////////////////
223 
224  // OsiSolverInterface is empty yet, no information can be obtained
225  // on variables or bounds -- and none is needed since our
226  // constructor populated *problem_ with variables and bounds. We
227  // only need to update the auxiliary variables and bounds with
228  // their current value.
229 
230  for (int i=0; i < ncols; i++)
231  if (problem_ -> Var (i) -> Multiplicity () > 0) {
232  chg_bds [i].setLower (t_chg_bounds::CHANGED);
233  chg_bds [i].setUpper (t_chg_bounds::CHANGED);
234  }
235 
236  // start with FBBT, should take advantage of cutoff found by NLP
237  // run AFTER initial FBBT...
238  if (problem_ -> doFBBT () &&
239  (! (problem_ -> boundTightening (chg_bds, info, babInfo))))
240  jnlst_ -> Printf (J_STRONGWARNING, J_CONVEXIFYING,
241  "Couenne: WARNING, first convexification is infeasible\n");
242 
243  // For each auxiliary variable replacing the original (nonlinear)
244  // constraints, check if corresponding bounds are violated, and
245  // add cut to cs
246 
247  int nnlc = problem_ -> nCons ();
248 
249  for (int i=0; i<nnlc; i++) {
250 
251  if (CoinCpuTime () > problem_ -> getMaxCpuTime ())
252  break;
253 
254  // for each constraint
255  CouenneConstraint *con = problem_ -> Con (i);
256 
257  // (which has an aux as its body)
258  int objindex = con -> Body () -> Index ();
259 
260  if ((objindex >= 0) &&
261  ((con -> Body () -> Type () == AUX) ||
262  (con -> Body () -> Type () == VAR))) {
263 
264  // get the auxiliary that is at the lhs
265  exprVar *conaux = problem_ -> Var (objindex);
266 
267  if (conaux &&
268  (conaux -> Type () == AUX) &&
269  (conaux -> Image ()) &&
270  (conaux -> Image () -> Linearity () <= LINEAR)) {
271 
272  // reduce density of problem by adding w >= l rather than
273  // ax + b >= l for any linear auxiliary defined as w := ax+b
274 
275  double
276  lb = (*(con -> Lb ())) (),
277  ub = (*(con -> Ub ())) ();
278 
279  OsiColCut newBound;
280  if (lb > -COUENNE_INFINITY) newBound.setLbs (1, &objindex, &lb);
281  if (ub < COUENNE_INFINITY) newBound.setUbs (1, &objindex, &ub);
282 
283  cs.insert (newBound);
284 
285  // the auxiliary w of constraint w <= b is associated with a
286  // linear expression w = ax: add constraint ax <= b
287  /*conaux -> Image () -> generateCuts (conaux, si, cs, this, chg_bds,
288  conaux -> Index (),
289  (*(con -> Lb ())) (),
290  (*(con -> Ub ())) ());*/
291 
292  // take it from the list of the variables to be linearized
293  //
294  // DO NOT decrease multiplicity. Even if it is a linear
295  // term, its bounds can still be used in implied bounds
296  //
297  // Are we sure? That will happen only if its multiplicity is
298  // nonzero, for otherwise this aux is only used here, and is
299  // useless elsewhere
300  //
301  //conaux -> decreaseMult (); // !!!
302  }
303 
304  // also, add constraint w <= b
305 
306  // not now, do it later
307 
308 // // if there exists violation, add constraint
309 // CouNumber l = con -> Lb () -> Value (),
310 // u = con -> Ub () -> Value ();
311 
312 // // tighten bounds in Couenne's problem representation
313 // problem_ -> Lb (index) = CoinMax (l, problem_ -> Lb (index));
314 // problem_ -> Ub (index) = CoinMin (u, problem_ -> Ub (index));
315 
316  } else { // body is more than just a variable, but it should be
317  // linear. If so, generate equivalent linear cut
318 
319  assert (false); // TODO
320  }
321  }
322 
323  if (jnlst_ -> ProduceOutput (J_ITERSUMMARY, J_CONVEXIFYING)) {
324  if (cs.sizeRowCuts ()) {
325  jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne: %d constraint row cuts\n",
326  cs.sizeRowCuts ());
327  for (int i=0; i<cs.sizeRowCuts (); i++)
328  cs.rowCutPtr (i) -> print ();
329  }
330  if (cs.sizeColCuts ()) {
331  jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne: %d constraint col cuts\n",
332  cs.sizeColCuts ());
333  for (int i=0; i<cs.sizeColCuts (); i++)
334  cs.colCutPtr (i) -> print ();
335  }
336  }
337  } else {
338 
339  // use new optimum as lower bound for variable associated w/objective
340 
341  // transmit solution from OsiSolverInterface to problem
342  problem_ -> domain () -> push (&si, &cs);
343 
344  if (indObj >= 0) {
345 
346  // Use current value of objvalue's x as a lower bound for bound
347  // tightening
348  double lp_bound = problem_ -> domain () -> x (indObj);
349 
350  //if (problem_ -> Obj (0) -> Sense () == MINIMIZE)
351  {if (lp_bound > problem_ -> Lb (indObj)) problem_ -> Lb (indObj) = lp_bound;}
352  //else {if (lp_bound < problem_ -> Ub (indObj)) problem_ -> Ub (indObj) = lp_bound;}
353  }
354 
355  updateBranchInfo (si, problem_, chg_bds, info); // info.depth >= 0 || info.pass >= 0
356  }
357 
358  // restore constraint bounds before tightening and cut generation
359  for (int i = problem_ -> nCons (); i--;) {
360 
361  // for each constraint
362  CouenneConstraint *con = problem_ -> Con (i);
363 
364  // (which has an aux as its body)
365  int objindex = con -> Body () -> Index ();
366 
367  if ((objindex >= 0) &&
368  ((con -> Body () -> Type () == AUX) ||
369  (con -> Body () -> Type () == VAR))) {
370 
371  // if there exists violation, add constraint
372  CouNumber
373  l = con -> Lb () -> Value (),
374  u = con -> Ub () -> Value ();
375 
376  // tighten bounds in Couenne's problem representation
377  problem_ -> Lb (objindex) = CoinMax (l, problem_ -> Lb (objindex));
378  problem_ -> Ub (objindex) = CoinMin (u, problem_ -> Ub (objindex));
379  }
380  }
381 
382  problem_ -> installCutOff (); // install upper bound
383 
384  fictitiousBound (cs, problem_, false); // install finite lower bound, if currently -inf
385 
386  int *changed = NULL, nchanged;
387 
388  // Bound tightening ///////////////////////////////////////////
389 
390  // do bound tightening only at first pass of cutting plane in a node
391  // of BB tree (info.pass == 0) or if first call (creation of RLT,
392  // info.pass == -1)
393 
394  try {
395 
396  // Before bound tightening, compute symmetry group. After bound
397  // tightening is done, we can apply further tightening using orbit
398  // information.
399 
400 // #ifdef COIN_HAS_NTY
401 // // ChangeBounds (psi -> getColLower (),
402 // // psi -> getColUpper (),
403 // // psi -> getNumCols ());
404 
405 // if (problem_ -> orbitalBranching ()){
406 
407 // problem_ -> ChangeBounds (problem_ -> Lb (),
408 // problem_ -> Ub (),
409 // problem_ -> nVars ());
410 
411 // problem_ -> Compute_Symmetry ();
412 // }
413 // #endif
414 
415  // Bound tightening ////////////////////////////////////
416 
417  //bool is_feas = p -> btCore (chg_bds);
418 
419  // Reduced Cost BT -- to be done first to use rcost correctly
420  if (!firstcall_ && // have a linearization already
421  problem_ -> doRCBT () && // authorized to do reduced cost tightening
422  problem_ -> redCostBT (&si, chg_bds) && // some variables were tightened with reduced cost
423  !(problem_ -> btCore (chg_bds))) // in this case, do another round of FBBT
424  throw infeasible;
425 
426  // FBBT
427  if (problem_ -> doFBBT () &&
428  //(info.pass <= 0) && // do it in subsequent rounds too
429  (! (problem_ -> boundTightening (chg_bds, info, babInfo))))
430  throw infeasible;
431 
432  // OBBT
433  if (!firstcall_ && // no obbt if first call (there is no LP to work with)
434  problem_ -> obbt (this, si, cs, info, babInfo, chg_bds) < 0)
435  throw infeasible;
436 
437  // Bound tightening done /////////////////////////////
438 
439  if ((problem_ -> doFBBT () ||
440  problem_ -> doOBBT () ||
441  problem_ -> doABT ()) &&
442  (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING))) {
443 
444  jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== after bt =============\n");
445  for (int i = 0; i < problem_ -> nVars (); i++)
446  if (problem_ -> Var (i) -> Multiplicity () > 0)
447  jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
448  problem_ -> X (i), problem_ -> Lb (i), problem_ -> Ub (i));
449  jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
450  }
451 
452  // Use orbit info to tighten bounds
453 
454 #ifdef COIN_HAS_NTY
455 
456  // TODO: when independent bound tightener, can get original bounds
457  // through si.getCol{Low,Upp}er()
458 
459  if (problem_ -> orbitalBranching () && !firstcall_) {
460 
461  CouNumber
462  *lb = problem_ -> Lb (),
463  *ub = problem_ -> Ub ();
464 
465  std::vector<std::vector<int> > *new_orbits = problem_ -> getNtyInfo () -> getOrbits();
466 
467  for (int i=0, ii = problem_ -> getNtyInfo () -> getNumOrbits (); ii--; i++){
468 
469  CouNumber
470  ll = -COUENNE_INFINITY,
471  uu = COUENNE_INFINITY;
472 
473  std::vector <int> orbit = (*new_orbits)[i];
474 
475  if (orbit.size () <= 1)
476  continue; // not much to do when only one variable in this orbit
477 
478  if (jnlst_ -> ProduceOutput (J_VECTOR, J_BOUNDTIGHTENING)) {
479  printf ("orbit bounds: "); fflush (stdout);
480  for(int j = 0; j < orbit.size (); j++) {
481  printf ("x_%d [%g,%g] ", orbit[j], lb [orbit [j]], ub [orbit [j]]);
482  fflush (stdout);
483  }
484  }
485 
486  for (int j = 0; j < orbit.size (); j++) {
487 
488  int indOrb = orbit [j];
489 
490  if (indOrb < problem_ -> nVars ()) {
491 
492  if (lb [indOrb] > ll) ll = lb [indOrb];
493  if (ub [indOrb] < uu) uu = ub [indOrb];
494  }
495  }
496 
497  jnlst_ -> Printf (J_VECTOR, J_BOUNDTIGHTENING,
498  " --> new common bounds: [%g,%g]\n", ll, uu);
499 
500  for(int j = 0; j < orbit.size (); j++) {
501 
502  int indOrb = orbit [j];
503 
504  if (indOrb < problem_ -> nVars ()){
505 
506  lb [indOrb] = ll;
507  ub [indOrb] = uu;
508  }
509  }
510  }
511 
512  delete new_orbits;
513  }
514 
515 #endif
516 
517  // Generate convexification cuts //////////////////////////////
518 
519  sparse2dense (ncols, chg_bds, changed, nchanged);
520 
521  double *nlpSol = NULL;
522 
523  //--------------------------------------------
524 
525  if (true) {
526 
527  if (babInfo)
528  nlpSol = const_cast <double *> (babInfo -> nlpSolution ());
529 
530  // Aggressive Bound Tightening ////////////////////////////////
531 
532  int logAbtLev = problem_ -> logAbtLev ();
533 
534  if (problem_ -> doABT () && // flag is checked, AND
535  ((logAbtLev != 0) || // (parameter is nonzero OR
536  (info.level == 0)) && // we are at root node), AND
537  (info.pass == 0) && // at first round of cuts, AND
538  ((logAbtLev < 0) || // (logAbtLev = -1, OR
539  (info.level <= logAbtLev) || // depth is lower than COU_OBBT_CUTOFF_LEVEL, OR
540  (CoinDrand48 () < // probability inversely proportional to the level)
541  pow (2., (double) logAbtLev - (info.level + 1))))) {
542 
543  jnlst_ -> Printf(J_VECTOR, J_BOUNDTIGHTENING," performing ABT\n");
544  if (! (problem_ -> aggressiveBT (nlp_, chg_bds, info, babInfo)))
545  throw infeasible;
546 
547  sparse2dense (ncols, chg_bds, changed, nchanged);
548  }
549 
550  // obtain solution just found by nlp solver
551 
552  // Auxiliaries should be correct. solution should be the one found
553  // at the node even if not as good as the best known.
554 
555  // save violation flag and disregard it while adding cut at NLP
556  // point (which are not violated by the current, NLP, solution)
557  bool save_av = addviolated_;
558  addviolated_ = false;
559 
560  // save values
561  problem_ -> domain () -> push
562  (problem_ -> nVars (),
563  problem_ -> domain () -> x (),
564  problem_ -> domain () -> lb (),
565  problem_ -> domain () -> ub (), false);
566 
567  // fill originals with nlp values
568  if (nlpSol) {
569  CoinCopyN (nlpSol, problem_ -> nOrigVars (), problem_ -> domain () -> x ());
570  //problem_ -> initAuxs ();
571 
572  problem_ -> getAuxs (problem_ -> domain () -> x ());
573  }
574 
575  if (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING)) {
576  jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== genrowcuts on NLP =============\n");
577  for (int i = 0; i < problem_ -> nVars (); i++)
578  if (problem_ -> Var (i) -> Multiplicity () > 0)
579  jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
580  problem_ -> X (i),
581  problem_ -> Lb (i),
582  problem_ -> Ub (i));
583  jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
584  }
585 
586  problem_ -> domain () -> current () -> isNlp () = true;
587  genRowCuts (si, cs, nchanged, changed, chg_bds); // add cuts
588 
589  problem_ -> domain () -> pop (); // restore point
590 
591  addviolated_ = save_av; // restore previous value
592 
593  // if (!firstcall_) // keep solution if called from extractLinearRelaxation()
594  if (babInfo)
595  babInfo -> setHasNlpSolution (false); // reset it after use //AW HERE
596 
597  } else {
598 
599  if (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING)) {
600  jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== genrowcuts on LP =============\n");
601  for (int i = 0; i < problem_ -> nVars (); i++)
602  if (problem_ -> Var (i) -> Multiplicity () > 0)
603  jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
604  problem_ -> X (i),
605  problem_ -> Lb (i),
606  problem_ -> Ub (i));
607  jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
608  }
609 
610  genRowCuts (si, cs, nchanged, changed, chg_bds);
611  }
612 
613  // change tightened bounds through OsiCuts
614  if (nchanged)
615  genColCuts (si, cs, nchanged, changed);
616 
617  if (firstcall_ && (cs.sizeRowCuts () >= 1))
618  jnlst_->Printf(J_ITERSUMMARY, J_CONVEXIFYING,
619  "Couenne: %d initial row cuts\n", cs.sizeRowCuts ());
620 
621  if (realOpt && // this is a good time to check if we have cut the optimal solution
622  isOptimumCut (realOpt, cs, problem_))
623  jnlst_->Printf(J_ITERSUMMARY, J_CONVEXIFYING,
624  "Warning: Optimal solution was cut\n");
625  }
626 
627  catch (int exception) {
628 
629  if ((exception == infeasible) && (!firstcall_)) {
630 
631  jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,
632  "Couenne: Infeasible node\n");
633 
634  WipeMakeInfeas (cs);
635  }
636 
637  if (babInfo) // set infeasibility to true in order to skip NLP heuristic
638  babInfo -> setInfeasibleNode ();
639  }
640 
641  delete [] chg_bds;
642 
643  if (changed)
644  free (changed);
645 
646  if (firstcall_) {
647 
648  jnlst_ -> Printf (J_SUMMARY, J_CONVEXIFYING,
649  "Couenne: %d cuts (%d row, %d col) for linearization\n",
650  cs.sizeRowCuts () + cs.sizeColCuts (),
651  cs.sizeRowCuts (), cs.sizeColCuts ());
652 
653  fictitiousBound (cs, problem_, true);
654  firstcall_ = false;
655  ntotalcuts_ = nrootcuts_ = cs.sizeRowCuts ();
656 
657  } else {
658 
659  problem_ -> domain () -> pop ();
660 
661  ntotalcuts_ += (cs.sizeRowCuts () - nInitCuts);
662 
663  if (saveOptimum)
664  realOpt = saveOptimum; // restore debug optimum
665  }
666 
667  septime_ += CoinCpuTime () - now;
668 
669  if (jnlst_ -> ProduceOutput (J_ITERSUMMARY, J_CONVEXIFYING)) {
670 
671  if (cs.sizeColCuts ()) {
672  jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne col cuts:\n");
673  for (int i=0; i<cs.sizeColCuts (); i++)
674  cs.colCutPtr (i) -> print ();
675  }
676  }
677 
678  if (!(info.inTree))
679  rootTime_ = CoinCpuTime ();
680 }
681 
682 }
void updateBranchInfo(const OsiSolverInterface &si, CouenneProblem *p, t_chg_bounds *chg, const CglTreeInfo &info)
get new bounds from parents&#39; bounds + branching rules
bool isWiped(OsiCuts &cs)
Check whether the previous cut generators have added an infeasible cut.
void fint fint fint real fint real real real real real real real real real fint real fint fint fint real fint fint fint fint * info
status of lower/upper bound of a variable, to be checked/modified in bound tightening ...
void setLower(ChangeStatus lower)
void sparse2dense(int ncols, t_chg_bounds *chg_bds, int *&changed, int &nchanged)
translate sparse to dense vector (should be replaced)
CouNumber & Lb(int i) const
lower bound on
const Ipopt::EJournalCategory J_CONVEXIFYING(Ipopt::J_USER3)
static char * j
Definition: OSdtoa.cpp:3622
void setUpper(ChangeStatus upper)
Class to represent nonlinear constraints.
const Ipopt::EJournalCategory J_BOUNDTIGHTENING(Ipopt::J_USER2)
Class for MINLP problems with symbolic information.
bool isOptimumCut(const CouNumber *opt, OsiCuts &cs, CouenneProblem *p)
#define COUENNE_EPS
#define Couenne_large_bound2
static const int infeasible
Definition: Couenne.cpp:68
double CouNumber
main number type in Couenne
fint ll
#define COUENNE_INFINITY
void fictitiousBound(OsiCuts &cs, CouenneProblem *p, bool action)
variable-type operator
void WipeMakeInfeas(OsiCuts &cs)
Add a fictitious cut 1&lt;= x_0 &lt;= -1 as a signal to the node solver that this node is deemed infeasible...
Bonmin class for passing info between components of branch-and-cuts.
Definition: BonBabInfos.hpp:19
void fint fint fint real fint real * x