source: trunk/Couenne/src/bound_tightening/twoImpliedBT/TwoImpliedGenCuts.cpp @ 732

Last change on this file since 732 was 732, checked in by pbelotti, 10 years ago

fixed semiaux exprDiv convexification on fixed denominator. Renovated redcost BT, optimality based BT, and probing. New elimination of negative eigenvalue from FP HessLag?

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.3 KB
Line 
1/* $Id: TwoImpliedGenCuts.cpp 732 2011-07-03 20:06:50Z pbelotti $
2 *
3 * Name:    TwoImpliedGenCuts.cpp
4 * Author:  Pietro Belotti
5 * Purpose: bound reduction using two inequalities from the LP relaxation
6 *
7 * (C) Pietro Belotti, 2010.
8 * This file is licensed under the Eclipse Public License (EPL)
9 */
10
11#include <set>
12#include <stdlib.h>
13
14#include "BonCbc.hpp"
15#include "BonBabInfos.hpp"
16#include "CoinHelperFunctions.hpp"
17#include "CoinPackedMatrix.hpp"
18#include "CglCutGenerator.hpp"
19#include "CoinTime.hpp"
20
21#include "CouenneTypes.hpp"
22#include "CouenneProblemElem.hpp"
23#include "CouenneTwoImplied.hpp"
24#include "CouenneExprVar.hpp"
25#include "CouennePrecisions.hpp"
26#include "CouenneProblem.hpp"
27#include "CouenneInfeasCut.hpp"
28#include "CouenneJournalist.hpp"
29
30using namespace Ipopt;
31
32// necessary to make updateBranchInfo visible
33namespace Couenne {
34
35/// get new bounds from parents' bounds + branching rules
36void updateBranchInfo (const OsiSolverInterface &si, CouenneProblem *p, 
37                       t_chg_bounds *chg, const CglTreeInfo &info);
38
39// do single pair of inequalities. Return < 0 if infeasible
40
41int combine (CouenneProblem *p,
42             int n1, int n2, 
43             const int *ind1, // indices
44             const int *ind2, 
45             double *sa1, // coeff (sparse array)
46             double *sa2,
47             const double *a1,  // coeff
48             const double *a2, 
49             double *clb, // variable bounds
50             double *cub,
51             double l1, // constraint bounds
52             double l2, 
53             double u1, 
54             double u2, 
55             bool *isInteger,
56             int sign); // invert second constraint? -1: yes, +1: no
57
58/// the main CglCutGenerator
59void CouenneTwoImplied::generateCuts (const OsiSolverInterface &si, 
60                                      OsiCuts &cs, 
61                                      const CglTreeInfo info) const {
62
63  // don't perform this is cs has been added an infeasible cut (a
64  // result of some bound tightening procedure discovering an
65  // infeasible node)
66
67  if (isWiped (cs))
68    return;
69
70  double now = CoinCpuTime ();
71
72  // a more elaborate scheme to avoid heavy use of this heavy procedure
73
74  if ((depthStopSeparate_ >= 0 &&           // if -1, there is no limit on depth
75       info.level > depthStopSeparate_)     // otherwise, check if too deep for adding these cuts
76      ||
77      (depthLevelling_ >= 0 &&              // chance to run this procedure
78       info.level >= depthLevelling_ &&
79       CoinDrand48 () > 1. / (2. + info.level - depthLevelling_)))
80    return;
81
82  if (info.level <= 0)
83    jnlst_ -> Printf (J_ERROR, J_COUENNE, "TwoImpl-BT: "); fflush (stdout);
84
85  // printf ("probexecute = %g. Level = %d, depthlevelling = %d, depthStop = %d, cond = %d\n",
86  //      1. / (2. + info.level - depthLevelling_),
87  //      info.level,
88  //      depthLevelling_,
89  //      depthStopSeparate_,
90  //      (depthLevelling_ < 0 || info.level < depthLevelling_));
91
92  // Update CouenneProblem's bounds using si's getCol{Low,Upp}er() and
93  // cs's OsiColCuts
94  problem_ -> domain () -> push (&si, &cs);
95
96  static int nBadColMatWarnings = 0;
97
98  std::set <std::pair <int, int> > pairs;
99
100  /// In principle, "si. getMatrixByCol ()" should be sufficient.
101  /// However, there seems to be a bug (not sure where... Osi? Clp?
102  /// Or, most probably, Couenne?) that doesn't return good values
103  /// from A (and triggers Valgrind errors and segfaults on ex3_1_1
104  /// and others). While waiting for a fix, we'll use the row
105  /// representation.
106
107  /// Update: we should probably stick to #defining USE_ROW even when
108  /// this is solved, as cuts from cs should also be added.
109
110#define USE_ROW
111
112#ifdef USE_ROW
113
114  const CoinPackedMatrix *mat = si. getMatrixByRow ();
115
116  int 
117    m = mat -> getMajorDim (), // # rows
118    n = mat -> getMinorDim (); // # cols
119
120#else
121
122  const CoinPackedMatrix *mat = si. getMatrixByCol ();
123
124  int 
125    n = mat -> getMajorDim (), // # cols
126    m = mat -> getMinorDim (); // # rows
127
128#endif
129
130  const double
131    *rlb = si.getRowLower (),
132    *rub = si.getRowUpper ();
133
134#ifdef USE_ROW
135
136  /// These will be used
137
138  int 
139     nnz   = mat -> getNumElements (), // # nonzeros
140     nnzC  = 0,
141    *sta   = new int [n+1],
142     nCuts = cs.sizeRowCuts ();
143
144  // Count nonzeros in cs
145
146  for (int i=0, ii = cs. sizeRowCuts (); ii--; i++) {
147
148    const OsiRowCut        *cut     = cs. rowCutPtr (i);
149    const CoinPackedVector &rowCoe  = cut -> row ();
150
151    nnzC += rowCoe.getNumElements ();
152  }
153
154  int    *ind = new int    [nnz + nnzC];
155  double *A   = new double [nnz + nnzC];
156
157  /// these are the row-format originals
158  {
159    const double
160      *rA   = mat -> getElements ();
161
162    const int
163      *rInd = mat -> getIndices      (),
164      *rSta = mat -> getVectorStarts ();
165
166    // copy rA, rInd, rSta into A, ind, sta
167
168    CoinZeroN (sta, n+1);
169
170    /////////////////////////////////////////////////////////
171
172    // pre-fill starting positions with cardinalities of each column
173
174    for (int i=nnz; i--;)
175      ++ (sta [1 + *rInd++]);
176
177    // fill sta with nonzeros from cs's OsiRowCuts
178
179    for (int i=0, ii = cs. sizeRowCuts (); ii--; i++) {
180
181      const OsiRowCut        *cut     = cs. rowCutPtr (i);
182      const CoinPackedVector &rowCoe  = cut -> row ();
183      const int              *indices = rowCoe.getIndices     ();
184      int                     nnz     = rowCoe.getNumElements ();
185      // Note: nnz redeclared here (no scoping problems)
186
187      for (int i=nnz; i--;)
188        ++ (sta [1 + *indices++]);
189    }
190
191    rInd -= nnz;
192
193    ////////////////////////////////////////////////////////
194
195    // make sta cumulative
196
197    for (int i=1; i<=n; i++)
198      sta [i] += sta [i-1];
199
200    // use space marked by sta to fill appropriate
201    // indices/coefficients
202
203    for (int i=0; i<m; i++) {
204
205      // filling indices of row i
206
207      int rowStart = rSta [i];
208
209      for (int j = rowStart, jj = rSta [i+1] - rowStart; jj--; j++) {
210
211        int &curSta = sta [rInd [j]];
212
213        ind [curSta]   = i;
214        A   [curSta++] = rA [j];
215      }
216     
217      //printf ("\n");
218    }
219
220    // Add rowCuts from cs as well.
221
222    for (int i=0, ii = cs. sizeRowCuts (); ii--; i++) {
223
224      const OsiRowCut        *cut      = cs. rowCutPtr (i);
225      //printf ("[cut] %4d [%g,%g]: ", m+i, cut -> lb (), cut -> ub ());
226
227      const CoinPackedVector &rowCoe   = cut -> row ();
228      const int              *indices  = rowCoe.getIndices  ();
229      const double           *elements = rowCoe.getElements ();
230      int                     nnz      = rowCoe.getNumElements ();
231      // Note: nnz redeclared here (no scoping problems)
232
233      for (int j=nnz; j--;) {
234
235        //printf ("%+g x%d ", *elements, *indices);
236
237        int &curSta = sta [*indices++];
238
239        ind [curSta]   = m+i;
240        A   [curSta++] = *elements++;
241      }
242      //printf ("\n");
243    }
244
245    for (int i=n; --i;)
246      sta [i] = sta [i-1];
247
248    sta [0] = 0;
249
250    //printf ("%d + %d = %d nonzeros\n", nnz, nnzC, nnz + nnzC);
251  }
252
253#else
254
255  const double
256    *A   = mat -> getElements ();
257
258  const int
259    *ind = mat -> getIndices      (),
260    *sta = mat -> getVectorStarts ();
261
262#endif
263
264  /// Prepare vector for integrality test. Since many checks are done
265  /// within combine(), it is worth to prepare one here
266
267  bool *isInteger = new bool [n];
268  for (int i=0, ii=n; ii--; i++)
269    *isInteger++ = problem_ -> Var (i) -> isInteger ();
270  isInteger -= n;
271
272  // print out
273
274  // for (int i=0; i<n; i++) {
275
276  //   printf ("x%04d - %5d -> %5d, %5d elements:", i, sta [i], sta [i+1], sta [i+1] - sta [i]);
277  //   fflush (stdout);
278
279  //   for (int j=0; j<sta [i+1] - sta [i]; j++) {
280  //     printf ("(%d,%g) ", ind [sta [i] + j], A [sta [i] + j]);
281  //     fflush (stdout);
282  //   }
283  //   printf ("\n");
284  // }
285
286  // For every column i, compare pairs of rows j and k with nonzero
287  // coefficients.
288  //
289  // If the coefficients have the same sign and the inequalities are
290  // both >= or both <=, skip this pair -- no tightening can come from
291  // this pair (this doesn't mean that for another variable the
292  // opposite may happen).
293
294  double 
295    *sa1 = new double [n], // contains dense representation of a1 i.e. lots of zeros
296    *sa2 = new double [n]; //                                  a2
297
298  CoinFillN (sa1, n, 0.);
299  CoinFillN (sa2, n, 0.);
300
301  for (int i=0; i<n; i++, sta++) {
302
303    //printf ("x%d:\n", i);
304
305    for   (int jj = *(sta+1) - *sta, j = *sta; jj--; j++)
306      for (int kk = jj,              k = j+1;  kk--; k++) {
307
308        if (CoinCpuTime () > problem_ -> getMaxCpuTime ())
309          break;
310
311        register int 
312          indj = ind [j],
313          indk = ind [k];
314
315        //printf ("  checking pair %d, %d\n", indj, indk);
316
317        // should never happen, but if it does, just bail out
318        if ((indj >= m + nCuts) || (indj < 0) ||
319            (indk >= m + nCuts) || (indk < 0)) {
320
321          if (nBadColMatWarnings++ < 1)
322            //      jnlst_ -> Printf (J_STRONGWARNING, J_BOUNDTIGHTENING, "
323            printf ("\
324  Couenne: warning, matrix by row has nonsense indices.\n\
325  This separator will now return without (column) cuts.\n\
326  NOTE: further such inconsistencies won't be reported.\n");
327
328          delete [] sa1;
329          delete [] sa2;
330
331          delete [] sta;
332          delete [] ind;
333          delete [] A;
334
335          delete [] isInteger;
336
337          problem_ -> domain () -> pop ();
338
339          totalTime_     += CoinCpuTime () - now;
340          totalInitTime_ += CoinCpuTime () - now;
341
342          return; 
343        }
344
345        double 
346          prod = A [j] * A [k],
347          rlbj, rubj, rlbk, rubk;
348
349        if (indj>=m) {
350          OsiRowCut *cut = cs.rowCutPtr (indj-m);
351          rlbj = cut -> lb ();
352          rubj = cut -> ub ();
353        } else {
354          rlbj = rlb [indj];
355          rubj = rub [indj];
356        }
357
358        if (indk>=m) {
359          OsiRowCut *cut = cs.rowCutPtr (indk-m);
360          rlbk = cut -> lb ();
361          rubk = cut -> ub ();
362        } else {
363          rlbk = rlb [indk];
364          rubk = rub [indk];
365        }
366
367        if (prod > 0.) { // same sign -- skip unless finite lb1/ub2 OR
368                         // finite ub1/lb2. This is to avoid a situation
369                         // in which all coefficients in this pair
370                         // have the same sign
371
372          if (!(((rlbj > -COUENNE_INFINITY/10) && (rubk <  COUENNE_INFINITY/10)) || 
373                ((rubj <  COUENNE_INFINITY/10) && (rlbk > -COUENNE_INFINITY/10))))
374
375            continue;
376
377        } else
378
379        if ((prod < 0.) && // opposite sign -- multiply second
380                           // inequality by -1 and repeat
381            !(((rlbj > -COUENNE_INFINITY/10) && (rlbk > -COUENNE_INFINITY/10)) || 
382              ((rubj <  COUENNE_INFINITY/10) && (rubk <  COUENNE_INFINITY/10))))
383
384          continue;
385
386        pairs.insert (std::pair <int, int> (indj, indk));
387      }
388  }
389
390  // pairs (h,k) are done. Now for each pair set new bounds, if possible ///////////////////////////
391
392#ifdef USE_ROW
393  const CoinPackedMatrix *rowA = mat;
394#else
395  const CoinPackedMatrix *rowA = si. getMatrixByRow ();
396#endif
397
398  const double
399    *rA  = rowA -> getElements ();
400
401  // TODO: no need for copy, though we need it to compare to old problem's bounds
402
403  double
404    *clb = CoinCopyOfArray (problem_ -> Lb (), n),
405    *cub = CoinCopyOfArray (problem_ -> Ub (), n),
406    *oldLB = CoinCopyOfArray (problem_ -> Lb (), n),
407    *oldUB = CoinCopyOfArray (problem_ -> Ub (), n);
408
409  const int
410    *rInd = rowA -> getIndices      (),
411    *rSta = rowA -> getVectorStarts ();
412
413  int 
414    ntightened = 0,
415    ntrials    = 0,
416    nCurTightened;
417
418  // info about LP problem: upper bound, dual bound
419
420  Bonmin::BabInfo * babInfo = dynamic_cast <Bonmin::BabInfo *> (si.getAuxiliaryInfo ());
421
422  int result = 0;
423
424  // data structure for FBBT
425
426  t_chg_bounds *chg_bds = new t_chg_bounds [n];
427
428  // for (int i=0; i<n; i++)
429  //   if (problem_ -> Var (i) -> Multiplicity () <= 0) {
430  //     chg_bds [i].setLower (t_chg_bounds::UNCHANGED);
431  //     chg_bds [i].setUpper (t_chg_bounds::UNCHANGED);
432  //   }
433
434  // fills in chg_bds with changed bounds from previous BB node
435
436  updateBranchInfo (si, problem_, chg_bds, info);
437
438  // Comparing all pairs of inequalities is overkill if the comparison
439  // has been done in a previous iteration: a pair of inequalities of
440  // the old LP relaxation should be skipped unless some bounds have
441  // been changed in at least one of the variables (of either
442  // inequality). Moreover, all pairs of inequalities should be
443  // considered where the first is from the LP relaxation and the
444  // second is from the cuts added so far.
445
446  // Repeat the scan as long as there is tightening and the bounding
447  // box is nonempty.
448
449  do {
450
451    nCurTightened = 0;
452
453    // scan all pairs. All are potential pairs of inequalities that
454    // can give a better (combined) implied bound
455
456    for (std::set <std::pair <int, int> >:: iterator p = pairs.begin (); p != pairs.end (); ++p) {
457
458      if (CoinCpuTime () > problem_ -> getMaxCpuTime ())
459        break;
460
461      // indices of the two inequalities
462
463      int 
464        h = p -> first,
465        k = p -> second,
466        n1, n2;
467
468      double l1, u1, l2, u2;
469
470      const double *a1, *a2;
471
472      const int *ind1, *ind2;
473
474      // set indices/counters depending on whether h or k are cuts or
475      // inequalities
476
477      if (h>=m) {
478
479        const OsiRowCut *cut = cs.rowCutPtr (h-m);
480        const CoinPackedVector &rowCoe  = cut -> row ();
481
482        l1 = cut -> lb ();
483        u1 = cut -> ub ();
484        n1   = rowCoe. getNumElements ();
485        ind1 = rowCoe. getIndices     ();
486        a1   = rowCoe. getElements    ();
487
488      } else {
489
490        l1 = rlb [h];
491        u1 = rub [h];
492        n1 = rSta [h+1] - rSta [h];
493        ind1 = rInd + rSta [h];
494        a1 = rA + rSta [h];
495      }
496
497      ////////////////////////////////////////////////////////////////
498
499      if (k>=m) {
500
501        OsiRowCut *cut = cs.rowCutPtr (k-m);
502        const CoinPackedVector &rowCoe  = cut -> row ();
503
504        l2 = cut -> lb ();
505        u2 = cut -> ub ();
506        n2   = rowCoe. getNumElements ();
507        ind2 = rowCoe. getIndices     ();
508        a2   = rowCoe. getElements    ();
509
510      } else {
511
512        l2 = rlb [k];
513        u2 = rub [k];
514        n2 = rSta [k+1] - rSta [k];
515        ind2 = rInd + rSta [k];
516        a2 = rA + rSta [k];
517      }
518
519      // If both indices are from the LP relaxation, only check if
520      // there is at least one changed bound in the variables of one
521      // (or both) of them
522
523      if ((h < m) && (k < m) && !firstCall_) {
524
525        bool new_bound = false;
526
527        for (int i=n1; i--;) {
528
529          t_chg_bounds &chg = chg_bds [ind1 [i]];
530
531          if ((chg. lower () != t_chg_bounds::UNCHANGED) ||
532              (chg. upper () != t_chg_bounds::UNCHANGED))
533
534            new_bound = true;
535        }
536
537        if (!new_bound) 
538          for (int i=n2; i--;) {
539
540            t_chg_bounds &chg = chg_bds [ind2 [i]];
541
542            if ((chg. lower () != t_chg_bounds::UNCHANGED) ||
543                (chg. upper () != t_chg_bounds::UNCHANGED))
544
545              new_bound = true;
546          }
547
548        if (!new_bound) continue;
549      }
550
551      // fill in sa1 and sa2
552
553      for (int i=n1; i--;) sa1 [ind1 [i]] = a1 [i];
554      for (int i=n2; i--;) sa2 [ind2 [i]] = a2 [i];
555
556      // A few cases here on the inequalities' bounds, which may
557      // determine a change of sign in the second when combining the
558      // two: for example, if we have -inf < ax < b and c < dx < +inf,
559      // it makes sense to combine -inf < ax < b and -inf < - dx < -c
560      // as the upper bound will create a finite convex combination.
561
562      if ((u1 <   COUENNE_INFINITY && u2 <   COUENNE_INFINITY) ||
563          (l1 > - COUENNE_INFINITY && l2 > - COUENNE_INFINITY))
564
565        result = combine (problem_, n1, n2, ind1, ind2, sa1, sa2, a1, a2, clb, cub, l1, l2, u1, u2, isInteger, 1);
566
567      if (result < 0)
568        break;
569
570      nCurTightened += result;
571      result = 0;
572
573      // fill in sa2 with opposite values
574      for (int i=n2; i--;) 
575        sa2 [ind2 [i]] = - a2 [i];
576
577      if ((u1 <   COUENNE_INFINITY && l2 > - COUENNE_INFINITY) ||
578          (l1 > - COUENNE_INFINITY && u2 <   COUENNE_INFINITY))
579
580        // do NOT invert l2 and u2, this is done in combine
581        result = combine (problem_, n1, n2, ind1, ind2, sa1, sa2, a1, a2, clb, cub, l1, l2, u1, u2, isInteger, -1);
582
583      if (result < 0)
584        break;
585
586      nCurTightened += result;
587
588      // clean sa1 and sa2
589
590      for (int i=n1; i--;) sa1 [ind1 [i]] = 0.;
591      for (int i=n2; i--;) sa2 [ind2 [i]] = 0.;
592    }
593
594    if (result < 0) 
595      break;
596
597    int objInd = problem_ -> Obj (0) -> Body () -> Index ();
598
599    if (nCurTightened &&
600        (objInd >= 0) && 
601        babInfo && 
602        babInfo -> babPtr ()) {
603
604#ifdef DEBUG
605      printf ("FBBT\n");
606#endif
607
608      CouNumber
609        UB      = babInfo -> babPtr () -> model (). getObjValue(),
610        LB      = babInfo -> babPtr () -> model (). getBestPossibleObjValue (),
611        primal0 = problem_ -> Ub (objInd), 
612        dual0   = problem_ -> Lb (objInd);
613
614      // Do one round of BT
615
616      if ((UB < COUENNE_INFINITY) && 
617          (UB < primal0 - COUENNE_EPS)) { // update primal bound (MIP)
618
619        problem_ -> Ub (objInd) = UB;
620        chg_bds [objInd].setUpper (t_chg_bounds::CHANGED);
621      }
622
623      if ((LB > - COUENNE_INFINITY) && 
624          (LB > dual0 + COUENNE_EPS)) { // update dual bound
625        problem_ -> Lb (objInd) = LB;
626        chg_bds [objInd].setLower (t_chg_bounds::CHANGED);
627      }
628
629      // change chg_bds for all new bounds stored in cs
630
631      /*for (int i = cs. sizeColCuts (); i--;) {
632
633        const CoinPackedVector
634          &lbs = cs. colCutPtr (i) -> lbs (),
635          &ubs = cs. colCutPtr (i) -> ubs ();
636
637        // copy lbs
638
639        const int *indices = lbs. getIndices ();
640
641        for (int j = lbs. getNumElements (); j--; indices++)
642          chg_bds [*indices].setLower (t_chg_bounds::CHANGED);
643
644        // copy ubs
645
646        indices = ubs. getIndices ();
647
648        for (int j = ubs. getNumElements (); j--; indices++)
649          chg_bds [*indices].setUpper (t_chg_bounds::CHANGED);
650      }
651      */
652
653      if (!(problem_ -> btCore (chg_bds))) {
654
655        //problem infeasible, add IIS of size 2
656
657        result = -1;
658        break;
659
660      } else {
661
662        // update tightened bounds from problem to clb
663
664        for (int i=0; i<n; i++) {
665
666          if (problem_ -> Lb (i) > clb [i] + COUENNE_EPS) clb [i] = problem_ -> Lb (i);
667          if (problem_ -> Ub (i) < cub [i] - COUENNE_EPS) cub [i] = problem_ -> Ub (i);
668        }
669      }
670    }
671
672    ntightened += nCurTightened;
673
674  } while (++ntrials < nMaxTrials_ && nCurTightened);
675
676  totalInitTime_ += CoinCpuTime () - now;
677
678  // check if bounds improved, in that case create OsiColCuts
679
680  if (result >= 0 && ntightened) {
681
682    // check old and new bounds
683
684    int 
685      *indLB = new int [n],
686      *indUB = new int [n],
687      ntightenedL = 0,
688      ntightenedU = 0;
689
690    double 
691      *valLB = new double [n],
692      *valUB = new double [n];
693
694    for (int i=0; i<n; i++) {
695
696      if (clb [i] > oldLB [i]) {
697
698        if (problem_ -> bestSol () &&
699            problem_ -> bestSol () [i] > oldLB [i] &&
700            problem_ -> bestSol () [i] < clb   [i] - 1e-12) {
701
702          jnlst_ -> Printf (J_ERROR, J_COUENNE, 
703                            "Warning, twoImplBounds new LB cuts optimal solution: LB x_%d = %g --> %g, opt %g (diff: %g)\n",
704                            i, oldLB [i], clb [i], problem_ -> bestSol () [i], clb [i] - problem_ -> bestSol () [i]);
705
706        }
707
708        //printf ("L %4d: %g -> %g\n", i, oldLB [i], clb [i]);
709        indLB [ntightenedL]   = i;
710        valLB [ntightenedL++] = clb [i];
711      }
712
713      if (cub [i] < oldUB [i]) {
714
715        if (problem_ -> bestSol () &&
716            problem_ -> bestSol () [i] < oldUB [i] &&
717            problem_ -> bestSol () [i] > cub   [i] + 1e-12) {
718
719          jnlst_ -> Printf (J_ERROR, J_COUENNE, 
720                            "Warning, twoImplBounds new UB cuts optimal solution: UB x_%d = %g --> %g, opt %g (diff: %g)\n",
721                            i, oldUB [i], cub [i], problem_ -> bestSol () [i], problem_ -> bestSol () [i] - cub [i]);
722
723        }
724
725        //printf ("U %4d: %g -> %g\n", i, oldUB [i], cub [i]);
726        indUB [ntightenedU]   = i;
727        valUB [ntightenedU++] = cub [i];
728      }
729    }
730
731    if (ntightenedL || ntightenedU) {
732
733      OsiColCut newBound;
734
735      newBound.setLbs (ntightenedL, indLB, valLB);
736      newBound.setUbs (ntightenedU, indUB, valUB);
737
738      //newBound.print ();
739
740      cs.insert (newBound);
741    }
742
743    delete [] indLB;
744    delete [] indUB;
745    delete [] valLB;
746    delete [] valUB;
747
748    ntightened = ntightenedL + ntightenedU;
749  }
750
751  else 
752
753    if (result < 0)
754      WipeMakeInfeas (cs);
755
756  delete [] clb;
757  delete [] cub;
758  delete [] oldLB;
759  delete [] oldUB;
760  delete [] sa1;
761  delete [] sa2; 
762  delete [] chg_bds;
763
764  delete [] isInteger;
765
766  problem_ -> domain () -> pop ();
767
768#ifdef USE_ROW
769  delete [] A;
770  delete [] ind;
771  delete [] (sta-n);
772#endif
773
774  if (firstCall_)
775    firstCall_ = false;
776
777  totalTime_ += CoinCpuTime () - now;
778
779  if (info.level <= 0)
780    jnlst_ -> Printf (J_ERROR, J_COUENNE, "%d improved bounds\n", ntightened);
781}
782}
Note: See TracBrowser for help on using the repository browser.