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

Last change on this file since 858 was 858, checked in by pbelotti, 9 years ago

computing symmetry groups only when necessary

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