singleDisjunctions.cpp
Go to the documentation of this file.
1 /* $Id: singleDisjunctions.cpp 490 2011-01-14 16:07:12Z pbelotti $ */
2 /*
3  * Name: singleDisjunctions.cpp
4  * Author: Pietro Belotti
5  * Purpose: simpler methods on single disjunctions
6  *
7  * (C) Carnegie-Mellon University, 2008.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CouenneCutGenerator.hpp"
12 #include "CouenneProblem.hpp"
13 #include "CouenneDisjCuts.hpp"
14 
15 using namespace Couenne;
16 
18 OsiCuts *CouenneDisjCuts::getSingleDisjunction (OsiSolverInterface &si) const {
19 
20  int
21  ncols = si.getNumCols (), nNL = 0, nNU = 0,
22  *indNL = new int [ncols],
23  *indNU = new int [ncols];
24 
25  double
26  *oldL = couenneCG_ -> Problem () -> Lb (), *valNL = new double [ncols],
27  *oldU = couenneCG_ -> Problem () -> Ub (), *valNU = new double [ncols];
28 
29  const double
30  *newL = si.getColLower (),
31  *newU = si.getColUpper ();
32 
33  for (int i=0; i<ncols; i++) {
34  if (newL [i] > oldL [i] + COUENNE_EPS) {indNL [nNL] = i; valNL [nNL++] = newL [i];}
35  if (newU [i] < oldU [i] - COUENNE_EPS) {indNU [nNU] = i; valNU [nNU++] = newU [i];}
36  }
37 
38  OsiColCut cut;
39 
40  cut. setLbs (nNL, indNL, valNL);
41  cut. setUbs (nNU, indNU, valNU);
42 
43  OsiCuts *cuts = new OsiCuts;
44 
45  cuts -> insert (cut);
46 
47  delete [] indNL; delete [] valNL;
48  delete [] indNU; delete [] valNU;
49 
50  return cuts;
51 }
52 
53 
55 int CouenneDisjCuts::checkDisjSide (OsiSolverInterface &si, OsiCuts *cuts) const {
56 
57  int retval = COUENNE_FEASIBLE;
58 
59  const double
60  *lower = si.getColLower (),
61  *upper = si.getColUpper ();
62 
63  // check each colcut in cuts (there should be just one)
64 
65  for (int i = cuts -> sizeColCuts (); i--;) {
66 
67  // lower bounds
68 
69  const CoinPackedVector &lbs = cuts -> colCutPtr (i) -> lbs ();
70  const int *lindices = lbs.getIndices ();
71  const double *lvalues = lbs.getElements ();
72 
73  for (int j = lbs.getNumElements (); j--;) {
74  register double lb = *lvalues++;
75  register int ind = *lindices++;
76 
77  if (lb > upper [ind] + COUENNE_EPS) // fathom node
78  return COUENNE_INFEASIBLE;
79 
80  if (lb > lower [ind] + COUENNE_EPS)
81  retval = COUENNE_TIGHTENED;
82  }
83 
84  // upper bounds
85 
86  const CoinPackedVector &ubs = cuts -> colCutPtr (i) -> ubs ();
87  const int *uindices = ubs.getIndices ();
88  const double *uvalues = ubs.getElements ();
89 
90  for (int j = ubs.getNumElements (); j--;) {
91  register double ub = *uvalues++;
92  register int ind = *uindices++;
93 
94  if (ub < lower [ind] - COUENNE_EPS) // fathom node
95  return COUENNE_INFEASIBLE;
96 
97  if (ub < upper [ind] - COUENNE_EPS)
98  retval = COUENNE_TIGHTENED;
99  }
100  }
101 
102  return retval;
103 }
104 
105 
107 int CouenneDisjCuts::getBoxUnion (OsiSolverInterface &si,
108  OsiCuts *left, OsiCuts *right,
109  CoinPackedVector &lower, CoinPackedVector &upper) const {
110 
111  int retval = COUENNE_FEASIBLE;
112 
113  CoinPackedVector
114  lowerLeft, upperLeft,
115  lowerRight, upperRight;
116 
117  // merge all left lowers and uppers
118  for (int i = left -> sizeColCuts (); i--;) {
119  lowerLeft. append (left -> colCutPtr (i) -> lbs ());
120  upperLeft. append (left -> colCutPtr (i) -> ubs ());
121  }
122 
123  // merge all right lowers and uppers
124  for (int i = right -> sizeColCuts (); i--;) {
125  lowerRight. append (right -> colCutPtr (i) -> lbs ());
126  upperRight. append (right -> colCutPtr (i) -> ubs ());
127  }
128 
129  // sort all indexed vectors
130  lowerLeft. sortIncrIndex (); upperLeft. sortIncrIndex ();
131  lowerRight. sortIncrIndex (); upperRight. sortIncrIndex ();
132 
133  // now compare bounds one by one -- complexity linear in size of vectors
134 
135  mergeBoxes (-1, lowerLeft, lowerRight, lower);
136  mergeBoxes (+1, upperLeft, upperRight, upper);
137 
138  return retval;
139 }
140 
141 
143 void CouenneDisjCuts::mergeBoxes (int dir, // direction (negative for "<", positive for ">")
144  CoinPackedVector &left,
145  CoinPackedVector &right,
146  CoinPackedVector merged) const {
147  int
148  Ln = left. getNumElements (),
149  Rn = right. getNumElements ();
150 
151  if (!Ln || !Rn)
152  return;
153 
154  const int
155  *Li = left. getIndices (),
156  *Ri = right. getIndices ();
157 
158  const double
159  *Le = left. getElements (),
160  *Re = right. getElements ();
161 
162  for (;;) {
163 
164  for (;;) {
165 
166  register int diff = *Li - *Ri;
167 
168  if (diff < 0) {if (!--Ln) break; Li++; Le++;}
169  else if (diff > 0) {if (!--Rn) break; Ri++; Re++;}
170  else break;
171  }
172 
173  if (!Ln || !Rn) break; // !Ln, !Rn (==> exit), or Li==*Ri:
174  if (dir < 0) merged. insert (*Li, *Le<*Re ? *Le : *Re); // add min(*Le, *Re))
175  else merged. insert (*Li, *Le>*Re ? *Le : *Re); // add max(*Le, *Re))
176 
177  Li++; Ri++;
178  Le++; Re++;
179 
180  if (!--Ln || !--Rn) break;
181  }
182 }
static Bigint * diff(Bigint *a, Bigint *b)
Definition: OSdtoa.cpp:1120
CouenneCutGenerator * couenneCG_
pointer to symbolic repr. of constraint, variables, and bounds
static char * j
Definition: OSdtoa.cpp:3622
OsiCuts * getSingleDisjunction(OsiSolverInterface &si) const
create single osicolcut disjunction
#define COUENNE_EPS
int getBoxUnion(OsiSolverInterface &si, OsiCuts *left, OsiCuts *right, CoinPackedVector &lower, CoinPackedVector &upper) const
compute smallest box containing both left and right boxes.
int checkDisjSide(OsiSolverInterface &si, OsiCuts *cuts) const
check if (column!) cuts compatible with solver interface
void mergeBoxes(int dir, CoinPackedVector &left, CoinPackedVector &right, CoinPackedVector merged) const
utility to merge vectors into one