source: trunk/Couenne/src/convex/generateCuts.cpp @ 945

Last change on this file since 945 was 945, checked in by stefan, 8 years ago

generateCuts in Cgl >= 0.58 will not be const anymore

  • Property svn:keywords set to Author Date Id Revision
File size: 20.6 KB
Line 
1/* $Id: generateCuts.cpp 945 2013-04-06 20:25:21Z stefan $
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
29using namespace Ipopt;
30
31namespace Couenne {
32
33#define Couenne_large_bound2 9.99e12
34
35// checks bad cuts against known optimum
36bool isOptimumCut (const CouNumber *opt, OsiCuts &cs, CouenneProblem *p);
37
38// set and lift bound for auxiliary variable associated with objective
39// function
40void 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
69void 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
88/// get new bounds from parents' bounds + branching rules
89void updateBranchInfo (const OsiSolverInterface &si, CouenneProblem *p, 
90                       t_chg_bounds *chg, const CglTreeInfo &info);
91
92/// a convexifier cut generator
93
94void 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    /*printf ("== BT ================\n");
418      for (int i = 0; i < problem_ -> nVars (); i++)
419      if (problem_ -> Var (i) -> Multiplicity () > 0)
420      printf ("%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
421      problem_ -> X  (i), problem_ -> Lb (i), problem_ -> Ub (i));
422      printf("=============================\n");*/
423
424    // Reduced Cost BT -- to be done first to use rcost correctly
425    if (!firstcall_  &&                         // have a linearization already
426        problem_ -> doRCBT () &&                // authorized to do reduced cost tightening
427        problem_ -> redCostBT (&si, chg_bds) && // some variables were tightened with reduced cost
428        !(problem_ -> btCore (chg_bds)))        // in this case, do another round of FBBT
429      throw infeasible;
430
431    // FBBT
432    if (problem_ -> doFBBT () && 
433        //(info.pass <= 0) && // do it in subsequent rounds too
434        (! (problem_ -> boundTightening (chg_bds, info, babInfo))))
435      throw infeasible;
436
437    // OBBT
438    if (!firstcall_ && // no obbt if first call (there is no LP to work with)
439        problem_ -> obbt (this, si, cs, info, babInfo, chg_bds) < 0)
440      throw infeasible;
441
442    // Bound tightening done /////////////////////////////
443
444    if ((problem_ -> doFBBT () ||
445         problem_ -> doOBBT () ||
446         problem_ -> doABT  ()) &&
447        (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING))) {
448
449      jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== after bt =============\n");
450      for (int i = 0; i < problem_ -> nVars (); i++)
451        if (problem_ -> Var (i) -> Multiplicity () > 0)
452          jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
453                         problem_ -> X  (i), problem_ -> Lb (i), problem_ -> Ub (i));
454      jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
455    }
456
457    // Use orbit info to tighten bounds
458
459#ifdef COIN_HAS_NTY
460
461    // TODO: when independent bound tightener, can get original bounds
462    // through si.getCol{Low,Upp}er()
463
464    if (problem_ -> orbitalBranching () && !firstcall_) {
465
466      CouNumber
467        *lb = problem_ -> Lb (),
468        *ub = problem_ -> Ub ();
469
470      std::vector<std::vector<int> > *new_orbits = problem_ -> getNtyInfo () -> getOrbits();
471
472      for (int i=0, ii = problem_ -> getNtyInfo () -> getNumOrbits (); ii--; i++){
473
474        CouNumber
475          ll = -COUENNE_INFINITY,
476          uu =  COUENNE_INFINITY; 
477       
478        std::vector <int> orbit = (*new_orbits)[i];
479
480        if (orbit.size () <= 1)
481          continue; // not much to do when only one variable in this orbit
482
483        if (jnlst_ -> ProduceOutput (J_VECTOR, J_BOUNDTIGHTENING)) {
484          printf ("orbit bounds: "); fflush (stdout);
485          for(int j = 0; j < orbit.size (); j++) {
486            printf ("x_%d [%g,%g] ", orbit[j], lb [orbit [j]], ub [orbit [j]]);
487            fflush (stdout);
488          }
489        }
490
491        for (int j = 0; j < orbit.size (); j++) {
492 
493          int indOrb = orbit [j];
494
495          if (indOrb < problem_ -> nVars ()) {
496
497            if (lb [indOrb] > ll) ll = lb [indOrb];
498            if (ub [indOrb] < uu) uu = ub [indOrb];
499          }
500        }
501
502        jnlst_ -> Printf (J_VECTOR, J_BOUNDTIGHTENING, 
503                          " --> new common bounds: [%g,%g]\n", ll, uu);
504
505        for(int j = 0; j < orbit.size (); j++) {
506
507          int indOrb = orbit [j];
508
509          if (indOrb < problem_ -> nVars ()){
510
511            lb [indOrb] = ll;
512            ub [indOrb] = uu;
513          }
514        }
515      }
516
517      delete new_orbits;
518    }
519
520#endif
521
522    // Generate convexification cuts //////////////////////////////
523
524    sparse2dense (ncols, chg_bds, changed, nchanged);
525
526    double *nlpSol = NULL;
527
528    //--------------------------------------------
529
530    if (true) {
531
532      if (babInfo) 
533        nlpSol = const_cast <double *> (babInfo -> nlpSolution ());
534
535      // Aggressive Bound Tightening ////////////////////////////////
536
537      int logAbtLev = problem_ -> logAbtLev ();
538
539      if (problem_ -> doABT () &&             // flag is checked, AND
540          ((logAbtLev != 0) ||                // (parameter is nonzero OR
541           (info.level == 0)) &&              //  we are at root node), AND
542          (info.pass == 0) &&                 // at first round of cuts, AND
543          ((logAbtLev < 0) ||                 // (logAbtLev = -1, OR
544           (info.level <= logAbtLev) ||       //  depth is lower than COU_OBBT_CUTOFF_LEVEL, OR
545           (CoinDrand48 () <                  //  probability inversely proportional to the level)
546            pow (2., (double) logAbtLev - (info.level + 1))))) {
547
548        jnlst_ -> Printf(J_VECTOR, J_BOUNDTIGHTENING,"  performing ABT\n");
549        if (! (problem_ -> aggressiveBT (nlp_, chg_bds, info, babInfo)))
550          throw infeasible;
551
552        sparse2dense (ncols, chg_bds, changed, nchanged);
553      }
554
555      // obtain solution just found by nlp solver
556
557      // Auxiliaries should be correct. solution should be the one found
558      // at the node even if not as good as the best known.
559
560      // save violation flag and disregard it while adding cut at NLP
561      // point (which are not violated by the current, NLP, solution)
562      bool save_av = addviolated_;
563      addviolated_ = false;
564
565      // save values
566      problem_ -> domain () -> push
567        (problem_ -> nVars (), 
568         problem_ -> domain () -> x  (), 
569         problem_ -> domain () -> lb (), 
570         problem_ -> domain () -> ub (), false);
571
572      // fill originals with nlp values
573      if (nlpSol) {
574        CoinCopyN (nlpSol, problem_ -> nOrigVars (), problem_ -> domain () -> x ());
575      //problem_ -> initAuxs ();
576
577      problem_ -> getAuxs (problem_ -> domain () -> x ());
578      }
579
580      if (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING)) {
581        jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== genrowcuts on NLP =============\n");
582        for (int i = 0; i < problem_ -> nVars (); i++)
583          if (problem_ -> Var (i) -> Multiplicity () > 0)
584            jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
585                           problem_ -> X  (i),
586                           problem_ -> Lb (i),
587                           problem_ -> Ub (i));
588        jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
589      }
590
591      problem_ -> domain () -> current () -> isNlp () = true;
592      genRowCuts (si, cs, nchanged, changed, chg_bds);  // add cuts
593
594      problem_ -> domain () -> pop (); // restore point
595
596      addviolated_ = save_av;     // restore previous value
597
598      //    if (!firstcall_) // keep solution if called from extractLinearRelaxation()
599      if (babInfo) 
600        babInfo -> setHasNlpSolution (false); // reset it after use //AW HERE
601
602    } else {
603
604      if (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING)) {
605        jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== genrowcuts on LP =============\n");
606        for (int i = 0; i < problem_ -> nVars (); i++)
607          if (problem_ -> Var (i) -> Multiplicity () > 0)
608            jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
609                           problem_ -> X  (i),
610                           problem_ -> Lb (i),
611                           problem_ -> Ub (i));
612        jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
613      }
614
615      genRowCuts (si, cs, nchanged, changed, chg_bds);
616    }
617
618    // change tightened bounds through OsiCuts
619    if (nchanged)
620      genColCuts (si, cs, nchanged, changed);
621
622    if (firstcall_ && (cs.sizeRowCuts () >= 1))
623      jnlst_->Printf(J_ITERSUMMARY, J_CONVEXIFYING,
624                     "Couenne: %d initial row cuts\n", cs.sizeRowCuts ());
625
626    if (realOpt && // this is a good time to check if we have cut the optimal solution
627        isOptimumCut (realOpt, cs, problem_))
628      jnlst_->Printf(J_ITERSUMMARY, J_CONVEXIFYING,
629                     "Warning: Optimal solution was cut\n");
630  }
631
632  catch (int exception) {
633
634    if ((exception == infeasible) && (!firstcall_)) {
635
636      jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,
637                        "Couenne: Infeasible node\n");
638
639      WipeMakeInfeas (cs);
640    }
641
642    if (babInfo) // set infeasibility to true in order to skip NLP heuristic
643      babInfo -> setInfeasibleNode ();
644  }
645
646  delete [] chg_bds;
647
648  if (changed) 
649    free (changed);
650
651  if (firstcall_) {
652
653    jnlst_ -> Printf (J_SUMMARY, J_CONVEXIFYING, 
654                      "Couenne: %d cuts (%d row, %d col) for linearization\n", 
655                      cs.sizeRowCuts () + cs.sizeColCuts (),
656                      cs.sizeRowCuts (),  cs.sizeColCuts ());
657
658    fictitiousBound (cs, problem_, true);
659    firstcall_  = false;
660    ntotalcuts_ = nrootcuts_ = cs.sizeRowCuts ();
661
662  } else { 
663
664    problem_ -> domain () -> pop ();
665
666    ntotalcuts_ += (cs.sizeRowCuts () - nInitCuts);
667
668    if (saveOptimum)
669      realOpt = saveOptimum; // restore debug optimum
670  }
671
672  septime_ += CoinCpuTime () - now;
673
674  if (jnlst_ -> ProduceOutput (J_ITERSUMMARY, J_CONVEXIFYING)) {
675
676    if (cs.sizeColCuts ()) {
677      jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne col cuts:\n");
678      for (int i=0; i<cs.sizeColCuts (); i++) 
679        cs.colCutPtr (i) -> print ();
680    }
681  }
682
683  if (!(info.inTree)) 
684    rootTime_ = CoinCpuTime ();
685}
686
687}
Note: See TracBrowser for help on using the repository browser.