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

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

BonCouenne?.cpp: stabilizing pointers for PrintInfo?() added by Francois, removing warnings. Merging Recorded Best Sol data from art_cutoff option.

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