OsiCuts2MatrVec.cpp
Go to the documentation of this file.
1 /* $Id: OsiCuts2MatrVec.cpp 694 2011-06-18 20:13:17Z stefan $
2  *
3  * Name: OsiCuts2MatrVec.cpp
4  * Author: Pietro Belotti
5  * Purpose: turn OsiCuts objects into coefficient matrix and rhs vector
6  *
7  * (C) Carnegie-Mellon University, 2008.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CouenneDisjCuts.hpp"
12 
13 #include "OsiSolverInterface.hpp"
14 
15 #include "CoinPackedVector.hpp"
16 #include "CoinPackedMatrix.hpp"
17 #include "CoinHelperFunctions.hpp"
18 
19 #include "CouenneCutGenerator.hpp"
20 
21 #include "CouennePrecisions.hpp"
22 #include "CouenneProblem.hpp"
23 #include "CouenneExprVar.hpp"
24 
25 using namespace Ipopt;
26 using namespace Couenne;
27 
28 // add CGLP columns to solver interface; return number of columns
29 // added (for later removal)
30 int CouenneDisjCuts::OsiCuts2MatrVec (OsiSolverInterface *cglp,
31  OsiCuts *cuts,
32  int displRow,
33  int displRhs) const {
34  int
35  ncols = 0,
36  nrcuts = cuts -> sizeRowCuts (),
37  nccuts = cuts -> sizeColCuts (),
38  ncgrow = cglp -> getNumRows () - 1,
39  nnzR = 0,
40  ncC = 0;
41 
42  if (!(nrcuts || nccuts))
43  return 0;
44 
45  // count nonzero in row cuts
46  for (int i=nrcuts; i--;) {
47 
48  OsiRowCut *cut = cuts -> rowCutPtr (i);
49 
50  if ((cut -> sense () == 'E') ||
51  (cut -> sense () == 'R')) {
52 
53  nnzR += 2 * cut -> row (). getNumElements ();
54  nrcuts++; // can increase as not used
55 
56  } else nnzR += cut -> row (). getNumElements ();
57  }
58 
59  // count bound constraints in column cuts
60  for (int i=nccuts; i--;) {
61  OsiColCut *cut = cuts -> colCutPtr (i);
62  ncC +=
63  cut -> lbs ().getNumElements () +
64  cut -> ubs ().getNumElements ();
65  }
66 
67  int
68  nnz = 2 * (nnzR + 2*nrcuts + 3*ncC),
69  *indices = new int [nnz],
70  *start = new int [nrcuts + ncC + 1],
71  curel = 0,
72  nCuts = 2*(nrcuts + ncC);
73 
74  double
75  *elements = new double [nnz], // for row cuts + col cuts
76  *collb = new double [nCuts], // lower bounds for new columns
77  *colub = new double [nCuts], // upper
78  *obj = new double [nCuts]; // objective coefficient (zero)
79 
80  // trivial, lower/upper bounds and objective coefficients
81  CoinFillN (collb, nCuts, 0.);
82  CoinFillN (colub, nCuts, 1.);
83  CoinFillN (obj, nCuts, 0.);
84 
85  // scan OsiColCuts ////////////////////////////////////////
86 
87  double *saveEl = elements;
88  int *saveInd = indices;
89 
90  for (int i = nccuts; i--;) {
91 
92  OsiColCut *cut = cuts -> colCutPtr (i);
93 
94  const CoinPackedVector
95  &lbs = cut -> lbs (),
96  &ubs = cut -> ubs ();
97 
98  // lower bounds
99  const int
100  *lind = lbs. getIndices (),
101  nlcc = lbs. getNumElements ();
102  const double *lele = lbs. getElements ();
103 
104  for (int j = nlcc; j--; lind++, lele++)
105 
106  if (couenneCG_ -> Problem () -> Var (*lind) -> Multiplicity () > 0) {
107  *start++ = curel;
108  *elements++ = -1.; *indices++ = displRow + *lind;
109  if (fabs (*lele) > COUENNE_EPS)
110  {*elements++ = -*lele; *indices++ = displRhs; curel++;}
111  *elements++ = 1.; *indices++ = ncgrow;
112  curel += 2;
113  }
114 
115  // upper bounds
116  const int
117  *uind = ubs. getIndices (),
118  nucc = ubs. getNumElements ();
119  const double *uele = ubs. getElements ();
120 
121  for (int j = nucc; j--; uind++, uele++)
122  if (couenneCG_ -> Problem () -> Var (*uind) -> Multiplicity () > 0) {
123  *start++ = curel;
124  *elements++ = 1.; *indices++ = displRow + *uind;
125  if (fabs (*uele) > COUENNE_EPS)
126  {*elements++ = *uele; *indices++ = displRhs; curel++;}
127  *elements++ = 1.; *indices++ = ncgrow;
128  curel += 2;
129  }
130 
131  ncols += nlcc + nucc;
132  }
133 
134  elements = saveEl;
135  indices = saveInd;
136 
137  //elements -= (3 * ncols);
138  //indices -= (3 * ncols);
139  start -= ncols;
140 
141  start [ncols] = curel; // may go
142 
143  if (jnlst_ -> ProduceOutput (J_MATRIX, J_DISJCUTS)) {
144  printf ("%d cuts, have %d cols and cur el is %d. Now for the %d row cuts\n",
145  nccuts, ncols, curel, nrcuts);
146 
147  printf ("matrix (.. %d) %d elements:\n", ncols, curel);
148 
149  printf ("start: "); for (int i=0; i<=ncols; i++) printf ("%d ", start [i]);
150 
151  printf ("\nElements:\n");
152  for (int i=0, j=0; i<ncols; i++) {
153  for (int k=0; k<start[i+1] - start[i]; k++, j++)
154  printf ("(%d %g) ", indices [j], elements [j]);
155  printf ("\n");
156  }
157  }
158 
159  // scan OsiRowCuts /////////////////////////////////////////////
160 
161  for (int i = cuts -> sizeRowCuts (); i--;) {
162 
163  OsiRowCut *cut = cuts -> rowCutPtr (i);
164 
165  const CoinPackedVector &row = cut -> row ();
166 
167  const double
168  rhs = cut -> rhs (),
169  rng = cut -> range (),
170  *rowEl = row. getElements ();
171 
172  const int
173  *rowIn = row. getIndices (),
174  rowNE = row. getNumElements ();
175 
176  switch (cut -> sense ()) {
177 
178  case 'L':
179 
180  start [ncols++] = curel;
181  CoinCopyDisp (rowIn, rowNE, indices + curel, displRow);
182  CoinCopyN (rowEl, rowNE, elements + curel);
183  curel += rowNE;
184  if (fabs (rhs) > COUENNE_EPS) {indices [curel] = displRhs; elements [curel++] = rhs;}
185  indices [curel] = ncgrow; elements [curel++] = 1.;
186 
187  break;
188 
189  case 'E':
190  case 'R':
191 
192  start [ncols++] = curel;
193  CoinCopyDisp (rowIn, rowNE, indices + curel, displRow);
194  CoinCopyN (rowEl, rowNE, elements + curel);
195  curel += rowNE;
196  if (fabs (rhs+rng) > COUENNE_EPS) {indices [curel] = displRhs; elements [curel++] = rhs + rng;}
197  // rng only used here, zero for 'E'
198  indices [curel] = ncgrow; elements [curel++] = 1.;
199 
200  start [ncols++] = curel;
201  CoinCopyDisp (rowIn, rowNE, indices + curel, displRow);
202  CoinInvN (rowEl, rowNE, elements + curel);
203  curel += rowNE;
204  if (fabs (rhs) > COUENNE_EPS) {indices [curel] = displRhs; elements [curel++] = -rhs;}
205  indices [curel] = ncgrow; elements [curel++] = 1.;
206 
207  break;
208 
209  case 'G':
210  start [ncols++] = curel;
211  CoinCopyDisp (rowIn, rowNE, indices + curel, displRow);
212  CoinInvN (rowEl, rowNE, elements + curel);
213  curel += rowNE;
214  if (fabs (rhs) > COUENNE_EPS) {indices [curel] = displRhs; elements [curel++] = -rhs;}
215  indices [curel] = ncgrow; elements [curel++] = 1.;
216 
217  break;
218 
219  default: printf ("Unknown type of cut:");
220  cut -> print ();
221  printf ("Aborting.\n");
222  exit (-1);
223  }
224  }
225 
226  start [ncols] = curel;
227 
228  // ncols=1;start[1]=3;
229  /* *start=0; start[1]=1;
230  *indices=0;
231  *elements=4.55;
232  *collb=-3;
233  *colub=+3;
234  *obj=4;*/
235 
236 
237  if (jnlst_ -> ProduceOutput (J_MATRIX, J_DISJCUTS)) {
238  printf ("===================\nmatrix (.. %d) %d elements:\n", ncols, curel);
239 
240  printf ("start: "); for (int i=0; i<=ncols; i++) printf ("%d ", start [i]);
241 
242  printf ("\nElements:\n");
243  for (int i=0, j=0; i<ncols; i++) {
244  for (int k=0; k<start[i+1] - start[i]; k++, j++)
245  printf ("(%d %g) ", indices [j], elements [j]);
246  printf ("\n");
247  }
248  }
249 
250  if (jnlst_ -> ProduceOutput (J_MATRIX, J_DISJCUTS)) {
251 
252  const CoinPackedMatrix *m = cglp->getMatrixByCol();
253 
254  printf ("before: size_ = %d, start [%d] = %d\n",
255  m -> getNumElements (),
256  m -> getSizeVectorLengths(),
257  m -> getVectorStarts () [m -> getSizeVectorLengths()]);
258  }
259 
260  cglp -> addCols (ncols, start,
261  indices, elements,
262  collb, colub,
263  obj);
264 
265  if (jnlst_ -> ProduceOutput (J_MATRIX, J_DISJCUTS)) {
266 
267  const CoinPackedMatrix *m = cglp->getMatrixByCol();
268  printf ("after: size_ = %d, start [%d] = %d\n",
269  m -> getNumElements (),
270  m -> getSizeVectorLengths(),
271  m -> getVectorStarts () [m -> getSizeVectorLengths()]);
272  }
273 
274  delete [] elements;
275  delete [] collb;
276  delete [] colub;
277  delete [] obj;
278 
279  delete [] indices;
280  delete [] start;
281 
282  return ncols;
283 }
void CoinInvN(register const double *orig, register int n, register double *inverted)
invert all contents
const Ipopt::EJournalCategory J_DISJCUTS(Ipopt::J_USER6)
static char * j
Definition: OSdtoa.cpp:3622
void fint fint * k
void CoinCopyDisp(register const int *src, register int num, register int *dst, register int displacement)
a CoinCopyN with a += on each element
#define COUENNE_EPS
void fint * m
int nnz
ATTENTION: Filter expect the jacobian to be ordered by row.