TwoImpliedGenCuts.cpp
Go to the documentation of this file.
1 /* $Id: TwoImpliedGenCuts.cpp 945 2013-04-06 20:25:21Z stefan $
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 
30 using namespace Ipopt;
31 
32 // necessary to make updateBranchInfo visible
33 namespace Couenne {
34 
36 void 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 
41 int 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 
59 void CouenneTwoImplied::generateCuts (const OsiSolverInterface &si,
60  OsiCuts &cs,
61  const CglTreeInfo info)
62 #if CGL_VERSION_MAJOR == 0 && CGL_VERSION_MINOR <= 57
63  const
64 #endif
65  {
66 
67  // don't perform this is cs has been added an infeasible cut (a
68  // result of some bound tightening procedure discovering an
69  // infeasible node)
70 
71  if (isWiped (cs))
72  return;
73 
74  double now = CoinCpuTime ();
75 
76  // a more elaborate scheme to avoid heavy use of this heavy procedure
77 
78  if ((depthStopSeparate_ >= 0 && // if -1, there is no limit on depth
79  info.level > depthStopSeparate_) // otherwise, check if too deep for adding these cuts
80  ||
81  (depthLevelling_ >= 0 && // chance to run this procedure
82  info.level >= depthLevelling_ &&
83  CoinDrand48 () > 1. / (2. + info.level - depthLevelling_)))
84  return;
85 
86  if (info.level <= 0)
87  jnlst_ -> Printf (J_ERROR, J_COUENNE, "TwoImpl-BT: "); fflush (stdout);
88 
89  // printf ("probexecute = %g. Level = %d, depthlevelling = %d, depthStop = %d, cond = %d\n",
90  // 1. / (2. + info.level - depthLevelling_),
91  // info.level,
92  // depthLevelling_,
93  // depthStopSeparate_,
94  // (depthLevelling_ < 0 || info.level < depthLevelling_));
95 
96  // Update CouenneProblem's bounds using si's getCol{Low,Upp}er() and
97  // cs's OsiColCuts
98  problem_ -> domain () -> push (&si, &cs);
99 
100  static int nBadColMatWarnings = 0;
101 
102  std::set <std::pair <int, int> > pairs;
103 
110 
113 
114 #define USE_ROW
115 
116 #ifdef USE_ROW
117 
118  const CoinPackedMatrix *mat = si. getMatrixByRow ();
119 
120  int
121  m = mat -> getMajorDim (), // # rows
122  n = mat -> getMinorDim (); // # cols
123 
124 #else
125 
126  const CoinPackedMatrix *mat = si. getMatrixByCol ();
127 
128  int
129  n = mat -> getMajorDim (), // # cols
130  m = mat -> getMinorDim (); // # rows
131 
132 #endif
133 
134  const double
135  *rlb = si.getRowLower (),
136  *rub = si.getRowUpper ();
137 
138 #ifdef USE_ROW
139 
141 
142  int
143  nnz = mat -> getNumElements (), // # nonzeros
144  nnzC = 0,
145  *sta = new int [n+1],
146  nCuts = cs.sizeRowCuts ();
147 
148  // Count nonzeros in cs
149 
150  for (int i=0, ii = cs. sizeRowCuts (); ii--; i++) {
151 
152  const OsiRowCut *cut = cs. rowCutPtr (i);
153  const CoinPackedVector &rowCoe = cut -> row ();
154 
155  nnzC += rowCoe.getNumElements ();
156  }
157 
158  int *ind = new int [nnz + nnzC];
159  double *A = new double [nnz + nnzC];
160 
162  {
163  const double
164  *rA = mat -> getElements ();
165 
166  const int
167  *rInd = mat -> getIndices (),
168  *rSta = mat -> getVectorStarts ();
169 
170  // copy rA, rInd, rSta into A, ind, sta
171 
172  CoinZeroN (sta, n+1);
173 
175 
176  // pre-fill starting positions with cardinalities of each column
177 
178  for (int i=nnz; i--;)
179  ++ (sta [1 + *rInd++]);
180 
181  // fill sta with nonzeros from cs's OsiRowCuts
182 
183  for (int i=0, ii = cs. sizeRowCuts (); ii--; i++) {
184 
185  const OsiRowCut *cut = cs. rowCutPtr (i);
186  const CoinPackedVector &rowCoe = cut -> row ();
187  const int *indices = rowCoe.getIndices ();
188  int nnz = rowCoe.getNumElements ();
189  // Note: nnz redeclared here (no scoping problems)
190 
191  for (int i=nnz; i--;)
192  ++ (sta [1 + *indices++]);
193  }
194 
195  rInd -= nnz;
196 
198 
199  // make sta cumulative
200 
201  for (int i=1; i<=n; i++)
202  sta [i] += sta [i-1];
203 
204  // use space marked by sta to fill appropriate
205  // indices/coefficients
206 
207  for (int i=0; i<m; i++) {
208 
209  // filling indices of row i
210 
211  int rowStart = rSta [i];
212 
213  for (int j = rowStart, jj = rSta [i+1] - rowStart; jj--; j++) {
214 
215  int &curSta = sta [rInd [j]];
216 
217  ind [curSta] = i;
218  A [curSta++] = rA [j];
219  }
220 
221  //printf ("\n");
222  }
223 
224  // Add rowCuts from cs as well.
225 
226  for (int i=0, ii = cs. sizeRowCuts (); ii--; i++) {
227 
228  const OsiRowCut *cut = cs. rowCutPtr (i);
229  //printf ("[cut] %4d [%g,%g]: ", m+i, cut -> lb (), cut -> ub ());
230 
231  const CoinPackedVector &rowCoe = cut -> row ();
232  const int *indices = rowCoe.getIndices ();
233  const double *elements = rowCoe.getElements ();
234  int nnz = rowCoe.getNumElements ();
235  // Note: nnz redeclared here (no scoping problems)
236 
237  for (int j=nnz; j--;) {
238 
239  //printf ("%+g x%d ", *elements, *indices);
240 
241  int &curSta = sta [*indices++];
242 
243  ind [curSta] = m+i;
244  A [curSta++] = *elements++;
245  }
246  //printf ("\n");
247  }
248 
249  for (int i=n; --i;)
250  sta [i] = sta [i-1];
251 
252  sta [0] = 0;
253 
254  //printf ("%d + %d = %d nonzeros\n", nnz, nnzC, nnz + nnzC);
255  }
256 
257 #else
258 
259  const double
260  *A = mat -> getElements ();
261 
262  const int
263  *ind = mat -> getIndices (),
264  *sta = mat -> getVectorStarts ();
265 
266 #endif
267 
270 
271  bool *isInteger = new bool [n];
272  for (int i=0, ii=n; ii--; i++)
273  *isInteger++ = problem_ -> Var (i) -> isInteger ();
274  isInteger -= n;
275 
276  // print out
277 
278  // for (int i=0; i<n; i++) {
279 
280  // printf ("x%04d - %5d -> %5d, %5d elements:", i, sta [i], sta [i+1], sta [i+1] - sta [i]);
281  // fflush (stdout);
282 
283  // for (int j=0; j<sta [i+1] - sta [i]; j++) {
284  // printf ("(%d,%g) ", ind [sta [i] + j], A [sta [i] + j]);
285  // fflush (stdout);
286  // }
287  // printf ("\n");
288  // }
289 
290  // For every column i, compare pairs of rows j and k with nonzero
291  // coefficients.
292  //
293  // If the coefficients have the same sign and the inequalities are
294  // both >= or both <=, skip this pair -- no tightening can come from
295  // this pair (this doesn't mean that for another variable the
296  // opposite may happen).
297 
298  double
299  *sa1 = new double [n], // contains dense representation of a1 i.e. lots of zeros
300  *sa2 = new double [n]; // a2
301 
302  CoinFillN (sa1, n, 0.);
303  CoinFillN (sa2, n, 0.);
304 
305  for (int i=0; i<n; i++, sta++) {
306 
307  //printf ("x%d:\n", i);
308 
309  for (int jj = *(sta+1) - *sta, j = *sta; jj--; j++)
310  for (int kk = jj, k = j+1; kk--; k++) {
311 
312  if (CoinCpuTime () > problem_ -> getMaxCpuTime ())
313  break;
314 
315  register int
316  indj = ind [j],
317  indk = ind [k];
318 
319  //printf (" checking pair %d, %d\n", indj, indk);
320 
321  // should never happen, but if it does, just bail out
322  if ((indj >= m + nCuts) || (indj < 0) ||
323  (indk >= m + nCuts) || (indk < 0)) {
324 
325  if (nBadColMatWarnings++ < 1)
326  // jnlst_ -> Printf (J_STRONGWARNING, J_BOUNDTIGHTENING, "
327  printf ("\
328  Couenne: warning, matrix by row has nonsense indices.\n\
329  This separator will now return without (column) cuts.\n\
330  NOTE: further such inconsistencies won't be reported.\n");
331 
332  delete [] sa1;
333  delete [] sa2;
334 
335  delete [] sta;
336  delete [] ind;
337  delete [] A;
338 
339  delete [] isInteger;
340 
341  problem_ -> domain () -> pop ();
342 
343  totalTime_ += CoinCpuTime () - now;
344  totalInitTime_ += CoinCpuTime () - now;
345 
346  return;
347  }
348 
349  double
350  prod = A [j] * A [k],
351  rlbj, rubj, rlbk, rubk;
352 
353  if (indj>=m) {
354  OsiRowCut *cut = cs.rowCutPtr (indj-m);
355  rlbj = cut -> lb ();
356  rubj = cut -> ub ();
357  } else {
358  rlbj = rlb [indj];
359  rubj = rub [indj];
360  }
361 
362  if (indk>=m) {
363  OsiRowCut *cut = cs.rowCutPtr (indk-m);
364  rlbk = cut -> lb ();
365  rubk = cut -> ub ();
366  } else {
367  rlbk = rlb [indk];
368  rubk = rub [indk];
369  }
370 
371  if (prod > 0.) { // same sign -- skip unless finite lb1/ub2 OR
372  // finite ub1/lb2. This is to avoid a situation
373  // in which all coefficients in this pair
374  // have the same sign
375 
376  if (!(((rlbj > -COUENNE_INFINITY/10) && (rubk < COUENNE_INFINITY/10)) ||
377  ((rubj < COUENNE_INFINITY/10) && (rlbk > -COUENNE_INFINITY/10))))
378 
379  continue;
380 
381  } else
382 
383  if ((prod < 0.) && // opposite sign -- multiply second
384  // inequality by -1 and repeat
385  !(((rlbj > -COUENNE_INFINITY/10) && (rlbk > -COUENNE_INFINITY/10)) ||
386  ((rubj < COUENNE_INFINITY/10) && (rubk < COUENNE_INFINITY/10))))
387 
388  continue;
389 
390  pairs.insert (std::pair <int, int> (indj, indk));
391  }
392  }
393 
394  // pairs (h,k) are done. Now for each pair set new bounds, if possible ///////////////////////////
395 
396 #ifdef USE_ROW
397  const CoinPackedMatrix *rowA = mat;
398 #else
399  const CoinPackedMatrix *rowA = si. getMatrixByRow ();
400 #endif
401 
402  const double
403  *rA = rowA -> getElements ();
404 
405  // TODO: no need for copy, though we need it to compare to old problem's bounds
406 
407  double
408  *clb = CoinCopyOfArray (problem_ -> Lb (), n),
409  *cub = CoinCopyOfArray (problem_ -> Ub (), n),
410  *oldLB = CoinCopyOfArray (problem_ -> Lb (), n),
411  *oldUB = CoinCopyOfArray (problem_ -> Ub (), n);
412 
413  const int
414  *rInd = rowA -> getIndices (),
415  *rSta = rowA -> getVectorStarts ();
416 
417  int
418  ntightened = 0,
419  ntrials = 0,
420  nCurTightened;
421 
422  // info about LP problem: upper bound, dual bound
423 
424  Bonmin::BabInfo * babInfo = dynamic_cast <Bonmin::BabInfo *> (si.getAuxiliaryInfo ());
425 
426  int result = 0;
427 
428  // data structure for FBBT
429 
430  t_chg_bounds *chg_bds = new t_chg_bounds [n];
431 
432  // for (int i=0; i<n; i++)
433  // if (problem_ -> Var (i) -> Multiplicity () <= 0) {
434  // chg_bds [i].setLower (t_chg_bounds::UNCHANGED);
435  // chg_bds [i].setUpper (t_chg_bounds::UNCHANGED);
436  // }
437 
438  // fills in chg_bds with changed bounds from previous BB node
439 
440  updateBranchInfo (si, problem_, chg_bds, info);
441 
442  // Comparing all pairs of inequalities is overkill if the comparison
443  // has been done in a previous iteration: a pair of inequalities of
444  // the old LP relaxation should be skipped unless some bounds have
445  // been changed in at least one of the variables (of either
446  // inequality). Moreover, all pairs of inequalities should be
447  // considered where the first is from the LP relaxation and the
448  // second is from the cuts added so far.
449 
450  // Repeat the scan as long as there is tightening and the bounding
451  // box is nonempty.
452 
453  do {
454 
455  nCurTightened = 0;
456 
457  // scan all pairs. All are potential pairs of inequalities that
458  // can give a better (combined) implied bound
459 
460  for (std::set <std::pair <int, int> >:: iterator p = pairs.begin (); p != pairs.end (); ++p) {
461 
462  if (CoinCpuTime () > problem_ -> getMaxCpuTime ())
463  break;
464 
465  // indices of the two inequalities
466 
467  int
468  h = p -> first,
469  k = p -> second,
470  n1, n2;
471 
472  double l1, u1, l2, u2;
473 
474  const double *a1, *a2;
475 
476  const int *ind1, *ind2;
477 
478  // set indices/counters depending on whether h or k are cuts or
479  // inequalities
480 
481  if (h>=m) {
482 
483  const OsiRowCut *cut = cs.rowCutPtr (h-m);
484  const CoinPackedVector &rowCoe = cut -> row ();
485 
486  l1 = cut -> lb ();
487  u1 = cut -> ub ();
488  n1 = rowCoe. getNumElements ();
489  ind1 = rowCoe. getIndices ();
490  a1 = rowCoe. getElements ();
491 
492  } else {
493 
494  l1 = rlb [h];
495  u1 = rub [h];
496  n1 = rSta [h+1] - rSta [h];
497  ind1 = rInd + rSta [h];
498  a1 = rA + rSta [h];
499  }
500 
502 
503  if (k>=m) {
504 
505  OsiRowCut *cut = cs.rowCutPtr (k-m);
506  const CoinPackedVector &rowCoe = cut -> row ();
507 
508  l2 = cut -> lb ();
509  u2 = cut -> ub ();
510  n2 = rowCoe. getNumElements ();
511  ind2 = rowCoe. getIndices ();
512  a2 = rowCoe. getElements ();
513 
514  } else {
515 
516  l2 = rlb [k];
517  u2 = rub [k];
518  n2 = rSta [k+1] - rSta [k];
519  ind2 = rInd + rSta [k];
520  a2 = rA + rSta [k];
521  }
522 
523  // If both indices are from the LP relaxation, only check if
524  // there is at least one changed bound in the variables of one
525  // (or both) of them
526 
527  if ((h < m) && (k < m) && !firstCall_) {
528 
529  bool new_bound = false;
530 
531  for (int i=n1; i--;) {
532 
533  t_chg_bounds &chg = chg_bds [ind1 [i]];
534 
535  if ((chg. lower () != t_chg_bounds::UNCHANGED) ||
536  (chg. upper () != t_chg_bounds::UNCHANGED))
537 
538  new_bound = true;
539  }
540 
541  if (!new_bound)
542  for (int i=n2; i--;) {
543 
544  t_chg_bounds &chg = chg_bds [ind2 [i]];
545 
546  if ((chg. lower () != t_chg_bounds::UNCHANGED) ||
547  (chg. upper () != t_chg_bounds::UNCHANGED))
548 
549  new_bound = true;
550  }
551 
552  if (!new_bound) continue;
553  }
554 
555  // fill in sa1 and sa2
556 
557  for (int i=n1; i--;) sa1 [ind1 [i]] = a1 [i];
558  for (int i=n2; i--;) sa2 [ind2 [i]] = a2 [i];
559 
560  // A few cases here on the inequalities' bounds, which may
561  // determine a change of sign in the second when combining the
562  // two: for example, if we have -inf < ax < b and c < dx < +inf,
563  // it makes sense to combine -inf < ax < b and -inf < - dx < -c
564  // as the upper bound will create a finite convex combination.
565 
566  if ((u1 < COUENNE_INFINITY && u2 < COUENNE_INFINITY) ||
567  (l1 > - COUENNE_INFINITY && l2 > - COUENNE_INFINITY))
568 
569  result = combine (problem_, n1, n2, ind1, ind2, sa1, sa2, a1, a2, clb, cub, l1, l2, u1, u2, isInteger, 1);
570 
571  if (result < 0)
572  break;
573 
574  nCurTightened += result;
575  result = 0;
576 
577  // fill in sa2 with opposite values
578  for (int i=n2; i--;)
579  sa2 [ind2 [i]] = - a2 [i];
580 
581  if ((u1 < COUENNE_INFINITY && l2 > - COUENNE_INFINITY) ||
582  (l1 > - COUENNE_INFINITY && u2 < COUENNE_INFINITY))
583 
584  // do NOT invert l2 and u2, this is done in combine
585  result = combine (problem_, n1, n2, ind1, ind2, sa1, sa2, a1, a2, clb, cub, l1, l2, u1, u2, isInteger, -1);
586 
587  if (result < 0)
588  break;
589 
590  nCurTightened += result;
591 
592  // clean sa1 and sa2
593 
594  for (int i=n1; i--;) sa1 [ind1 [i]] = 0.;
595  for (int i=n2; i--;) sa2 [ind2 [i]] = 0.;
596  }
597 
598  if (result < 0)
599  break;
600 
601  int objInd = problem_ -> Obj (0) -> Body () -> Index ();
602 
603  if (nCurTightened &&
604  (objInd >= 0) &&
605  babInfo &&
606  babInfo -> babPtr ()) {
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 }
void updateBranchInfo(const OsiSolverInterface &si, CouenneProblem *p, t_chg_bounds *chg, const CglTreeInfo &info)
get new bounds from parents&#39; bounds + branching rules
bool isWiped(OsiCuts &cs)
Check whether the previous cut generators have added an infeasible cut.
fint kk
void fint fint fint real fint real real real real real real real real real fint real fint fint fint real fint fint fint fint * info
status of lower/upper bound of a variable, to be checked/modified in bound tightening ...
void setLower(ChangeStatus lower)
static char * j
Definition: OSdtoa.cpp:3622
int combine(CouenneProblem *p, int n1, int n2, const int *ind1, const int *ind2, double *sa1, double *sa2, const double *a1, const double *a2, double *clb, double *cub, double l1, double l2, double u1, double u2, bool *isInteger, int sign)
void fint fint fint real fint real real real real real real real real real * e
void setUpper(ChangeStatus upper)
void fint fint * k
#define COUENNE_EPS
double CouNumber
main number type in Couenne
#define COUENNE_INFINITY
void fint * m
int nnz
ATTENTION: Filter expect the jacobian to be ordered by row.
const Ipopt::EJournalCategory J_COUENNE(Ipopt::J_USER8)
void WipeMakeInfeas(OsiCuts &cs)
Add a fictitious cut 1&lt;= x_0 &lt;= -1 as a signal to the node solver that this node is deemed infeasible...
void fint * n
Bonmin class for passing info between components of branch-and-cuts.
Definition: BonBabInfos.hpp:19
bool isInteger(CouNumber x)
is this number integer?