11 #include "CoinTime.hpp"
12 #include "OsiClpSolverInterface.hpp"
19 using namespace Ipopt;
20 using namespace Couenne;
22 #define COEFF_BOUNDS 1.e10
24 #define MIN_NUM_COEFF 1.e-9
25 #define MAX_NUM_COEFF 1.e+9
26 #define MAX_NUM_RATIO 1.e+6
31 const int *start,
const int *len,
32 const int *ind,
const double *el);
41 void addSubMatr (
int *start,
int *len,
int *ind,
double *el,
42 CoinPackedMatrix &Astd, CoinPackedVector &rstd,
43 int &cur,
int &curCol,
int dispM,
int dispVec,
int nrows);
47 int CouenneDisjCuts::generateDisjCuts (std::vector <std::pair <OsiCuts *, OsiCuts *> > &disjunctions,
48 OsiSolverInterface &si,
50 const CglTreeInfo &
info)
const {
92 CoinPackedMatrix Astd;
93 CoinPackedVector rstd;
94 OsiSI2MatrVec (Astd, rstd, si);
97 n = si. getNumCols (),
98 m = Astd. getMajorDim (), nC = 1 + n + 2 *
m,
99 nnz = Astd. getNumElements (), nnzC = 2 * (n + 1 + nnz + 2*
m);
101 if (jnlst_ -> ProduceOutput (J_DETAILED,
J_DISJCUTS))
102 printf (
"canonical form has %d cols, %d rows, %d nonzeros --> cglp has %d,%d,%d\n",
103 n, m, nnz, nC, 2*n + 3, nnzC);
106 *elements =
new double [nnzC];
109 *indices =
new int [nnzC],
110 *start =
new int [nC + 1],
111 *length =
new int [nC],
116 for (
int i=0, i2 = n; i<
n;) {
117 start [curCol] = cur;
118 length [curCol++] = 2;
119 indices [cur] = i++; elements [cur++] = -1.;
120 indices [cur] = i2++; elements [cur++] = -1.;
124 start [curCol] = cur;
125 length [curCol++] = 2;
126 indices [cur] = 2*
n; elements [cur++] = -1.;
127 indices [cur] = 2*n+1; elements [cur++] = -1.;
131 indices + cur, elements + cur,
136 if (jnlst_ -> ProduceOutput (J_MATRIX,
J_DISJCUTS)) {
137 printf (
"with third column\n");
138 printMatrix (curCol, 2*n+3, cur, start, length, indices, elements);
143 indices + cur, elements + cur,
148 if (jnlst_ -> ProduceOutput (J_MATRIX,
J_DISJCUTS)) {
149 printf (
"with 4th column\n");
150 printMatrix (curCol, 2*n+3, cur, start, length, indices, elements);
153 CoinPackedMatrix *baseA =
new CoinPackedMatrix;
155 baseA -> assignMatrix (
true,
167 OsiClpSolverInterface cglp;
169 cglp. messageHandler () -> setLogLevel (0);
172 N = baseA -> getMajorDim (),
173 M = baseA -> getMinorDim ();
175 assert (M == 2 * n + 3);
179 *collb =
new double [N],
180 *colub =
new double [N],
181 *obj =
new double [N],
182 *rowrhs =
new double [M],
183 *rowrng =
new double [M];
187 CoinFillN (collb + n+1, N - (n+1), 0.);
189 CoinFillN (colub + n+1, N - (n+1), 1.);
192 CoinCopyN (si.getColSolution (),
n, obj);
194 CoinFillN (obj + (n+1), N-(n+1), 0.);
197 CoinFillN (rowrhs, M-1, 0.);
201 CoinFillN (rowrng, M, COIN_DBL_MAX);
204 char *rowsen =
new char [M];
205 CoinFillN (rowsen, M,
'E');
206 rowsen [M-3] = rowsen [M-2] =
'L';
208 cglp.assignProblem (baseA,
217 cglp. setObjSense (-1);
225 for (std::vector <std::pair <OsiCuts *, OsiCuts *> >::iterator disjI = disjunctions.begin ();
226 (disjI != disjunctions.end ()) && (CoinCpuTime () < cpuTime_); ++disjI) {
229 *left = disjI -> first,
230 *right = disjI -> second;
233 ncolLeft = OsiCuts2MatrVec (&cglp, left, 0, 2*n),
234 ncolRight = OsiCuts2MatrVec (&cglp, right, n, 2*n+1);
241 if (jnlst_ -> ProduceOutput (J_MOREMATRIX,
J_DISJCUTS)) {
242 printf (
"current CGLP:\n");
247 if (first) {cglp.initialSolve (); first =
false;}
248 else cglp.resolve ();
250 if (cglp. isProvenOptimal () && (cglp.getObjValue () >
COUENNE_EPS)) {
252 const double *AlphaBeta = cglp. getColSolution ();
254 int *colInd = NULL, nnzCut = 0;
255 double *colCoe = NULL;
258 double mincoeff = COIN_DBL_MAX, maxcoeff = 0.;
260 for (
register int i=n+1; i--;) {
261 double value = fabs (AlphaBeta [i]);
262 if (value == 0.)
continue;
263 if (value > maxcoeff) maxcoeff = value;
264 if (value < mincoeff) mincoeff = value;
278 double *nzcoeff =
new double [nnzCut];
279 int *indices =
new int [nnzCut];
282 for (
int i = nnzCut = 0; i<
n; i++)
284 indices [nnzCut] = i;
285 nzcoeff [nnzCut++] = AlphaBeta [i];
288 OsiRowCut *cut =
new OsiRowCut;
289 cut -> setRow (nnzCut, indices, nzcoeff);
290 cut -> setUb (AlphaBeta [n]);
311 if (addPreviousCut_) {
313 colInd =
new int [2 * (nnzCut + 2)];
314 colCoe =
new double [2 * (nnzCut + 2)];
317 CoinCopyN (nzcoeff, nnzCut, colCoe);
318 CoinCopyN (indices, nnzCut, colInd);
319 colInd [nnzCut] = 2*
n; colCoe [nnzCut] = AlphaBeta [
n];
320 colInd [nnzCut+1] = 2*n+2; colCoe [nnzCut+1] = 1;
323 CoinCopyN (nzcoeff, nnzCut, colCoe + nnzCut + 2);
325 colInd [2*nnzCut + 2] = 2*n+1; colCoe [2*nnzCut+2] = AlphaBeta [
n];
326 colInd [2*nnzCut + 3] = 2*n+2; colCoe [2*nnzCut+3] = 1.;
329 double lb [2] = {0., 0.};
330 double ub [2] = {1., 1.};
331 double obj [2] = {0., 0.};
335 start [2] = 2 * (start [1] = nnzCut + 2);
352 if (jnlst_ -> ProduceOutput (J_DETAILED,
J_DISJCUTS)) {
353 printf (
"====== disjunctive cut: ");
363 int *delIndices =
new int [ncolLeft + ncolRight];
364 for (
register int nc = ncolLeft + ncolRight,
j = N + nc; nc--;)
366 delIndices -= (ncolLeft + ncolRight);
367 cglp.deleteCols (ncolLeft + ncolRight, delIndices);
368 delete [] delIndices;
void printLPMatrix(const OsiSolverInterface &si)
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
const Ipopt::EJournalCategory J_DISJCUTS(Ipopt::J_USER6)
void printMatrix(int nrows, int ncols, int nel, const int *start, const int *len, const int *ind, const double *el)
void CoinCopyDisp(register const int *src, register int num, register int *dst, register int displacement)
a CoinCopyN with a += on each element
void addSubMatr(int *start, int *len, int *ind, double *el, CoinPackedMatrix &Astd, CoinPackedVector &rstd, int &cur, int &curCol, int dispM, int dispVec, int nrows)
int nnz
ATTENTION: Filter expect the jacobian to be ordered by row.