15 #include "CoinTime.hpp"
16 #include "CoinHelperFunctions.hpp"
31 #define SPARSIFY_MAX_CARD 10000
32 #define SPARSIFY_NEW_NZ_THRESHOLD 0.70
36 using namespace Couenne;
41 const CglTreeInfo
info)
42 #if CGL_VERSION_MAJOR == 0 && CGL_VERSION_MINOR <= 57
49 if ((info . level + info . pass > 4))
return;
51 problem_ -> domain () -> push (&si, &cs);
53 for (std::vector <CouenneExprMatrix *>::const_iterator
54 minor = minors_. begin ();
55 minor != minors_.
end (); ++minor)
57 genCutSingle (*minor, si, cs, info);
59 problem_ -> domain () -> pop ();
65 const OsiSolverInterface &si,
67 const CglTreeInfo info)
const {
69 printf (
"Generating cut on minor -> ");
73 std::vector <expression *> &varInd = minor -> varIndices ();
76 n = (
int) (minor -> size ()),
80 **indA =
new int * [
n],
81 *indMap =
new int [
problem_ -> nVars ()],
86 *A =
new double [n *
n];
89 for (std::vector <expression *>::const_iterator
90 i = varInd . begin ();
91 i != varInd .
end (); ++i)
92 indMap [(*i) -> Index ()] = compressed_index++;
96 for (
int i=0; i<
n; ++i)
97 CoinFillN (indA [i] =
new int [n], n, -2);
103 CoinFillN (A, n * n, 0.);
106 printf (
"Components\n\n");
112 i = minor -> getRows () . begin ();
113 i != minor -> getRows () .
end (); ++i, ++indI) {
116 printf (
"row %d [var %d]: ", indI, i -> first); fflush (stdout);
120 majInd = (i -> first ==
problem_ -> nVars ()) ? n-1 : indMap [i -> first],
123 for (std::set <CouenneScalar *, CouenneSparseVector::compare_scalars>::const_iterator
124 j = i -> second -> getElements () . begin ();
125 j != i -> second -> getElements () .
end (); ++
j, ++indJ) {
128 printf (
"[r%d,v%d,%d,%g,", indJ,
130 (*j) -> getElem () -> Index (),
131 (*((*j) -> getElem ())) ());
132 (*j) -> getElem () -> print (); printf (
"] ");
136 int minInd = ((*j) -> getIndex () ==
problem_ -> nVars ()) ? (n-1) : (indMap [(*j) -> getIndex ()]);
140 A [majInd * n + minInd] = (*Elem) ();
143 indA [majInd] [minInd] = Elem -> Index ();
156 for (
int i=0; i<n-1; ++i)
157 for (
int j=i;
j<n-1; ++
j)
158 if (indA [i] [
j] == -2)
165 for (
int i=0; i<
n; ++i) {
166 for (
int j=0; j<
n; ++
j)
167 printf (
"[%4d,%7.2g] ", indA [i][j], A [i * n + j]);
173 *Acopy =
useSparsity_ ? CoinCopyOfArray (A, n * n) : NULL,
181 -COIN_DBL_MAX,
onlyNegEV_ ? 0. : COIN_DBL_MAX,
189 **work_ev =
new double * [
m];
191 for (
int i=0; i < nVecs; i++) {
198 work_ev [i] = z + (i*
n);
201 double scaling_factor = sqrt (n);
203 for (
int j=0; j<
n; j++)
204 work_ev [i] [j] *= scaling_factor;
210 for (
int i=0; i<nVecs; i++)
211 genSDPcut (si, cs, minor, work_ev [i], work_ev [i], indA);
215 card_sparse_v_mat = 0,
218 double **sparse_v_mat = NULL;
224 sparse_v_mat[i] =
new double [n];
227 card_sparse_v_mat = 0;
229 sparsify2 (n, A, sparse_v_mat, &card_sparse_v_mat, min_nz, &wise_evdec_num);
231 for (
int k=0;
k < card_sparse_v_mat;
k++)
232 genSDPcut (si, cs, minor, sparse_v_mat [
k], sparse_v_mat [k], indA);
236 for (
int i=0; i<nVecs; ++i) {
238 card_sparse_v_mat = 0;
239 double *v = work_ev[i];
243 for (
int k=0; k < card_sparse_v_mat; k++) {
245 genSDPcut (si, cs, minor, sparse_v_mat [k], sparse_v_mat [k], indA);
253 for (
int i=0; i<
n; ++i)
260 delete [] sparse_v_mat[i];
262 delete [] sparse_v_mat;
277 double *v1,
double *v2,
281 n = (
int) (XX -> size ()),
285 *inverse =
new int [nvars];
288 *coeff =
new double [N],
289 *xtraC =
new double [nvars],
292 std::vector <expression *> &varIndices = XX -> varIndices ();
294 CoinFillN (xtraC, nvars, 0.);
295 CoinFillN (inverse, nvars, -1);
303 printf (
"Solution: (");
304 for (
int i=0; i<
n; i++) {
306 printf (
"%g", v1 [i]);
313 bool numerics_flag =
false;
316 for (
int i=0; (i<
n) && !numerics_flag; i++)
318 for (
int j=i;
j<
n;
j++) {
320 double coeff0 = v1 [i] * v2 [
j] + v1 [
j] * v2 [i];
322 if (fabs (coeff0) < 1
e-21)
continue;
324 int index = indA [i] [
j];
327 printf (
"{%d,%g} ", index, coeff0);
341 if (index == -1) printf (
"found constant: %g\n", (i==
j) ? coeff0 / 2 : coeff0);
345 rhs -= ((i==
j) ? coeff0 / 2 : coeff0);
347 else if (index < -1) {
350 *Xi = XX -> varIndices () [i],
351 *Xj = XX -> varIndices () [
j];
360 Xi -> getBounds (
li, ui);
361 Xj -> getBounds (lj, uj);
364 printf (
"expression: x%d [%g,%g] * x%d [%g,%g]\n",
365 Xi -> Index (),
li, ui,
366 Xj -> Index (), lj, uj);
382 numerics_flag =
true;
386 xtraC [varIndices [i] -> Index ()] += coeff0 / 2 * (
li + ui);
388 printf (
"adding %g=%g*(%g+%g) (sq) to xtrac[%d=varInd[%d]]\n",
389 coeff0 / 2 * (
li + ui), coeff0,
li, ui, varIndices [i] -> Index (), i);
391 rhs += coeff0 / 2 * (
li * ui);
411 Xij . getBounds (
L,
U);
414 rhsMll = lj * valXi +
li * valXj - lj *
li,
415 rhsMuu = uj * valXi + ui * valXj - uj * ui;
419 if (
L >= CoinMax (rhsMll, rhsMuu))
423 else if (rhsMuu > rhsMll) {
427 numerics_flag =
true;
431 xtraC [varIndices [i] -> Index ()] += coeff0 * uj;
432 xtraC [varIndices [
j] -> Index ()] += coeff0 * ui;
433 rhs += coeff0 * uj * ui;
436 printf (
"adding (%g,%g) = %g*(%g,%g) (rhsMuu) to xtrac[%d=varInd[%d]] and xtrac[%d=varInd[%d]]\n",
437 coeff0 * uj, coeff0 * ui, coeff0, uj, ui, varIndices [i] -> Index (), i, varIndices [
j] -> Index (),
j);
444 numerics_flag =
true;
448 xtraC [varIndices [i] -> Index ()] += coeff0 * lj;
449 xtraC [varIndices [
j] -> Index ()] += coeff0 *
li;
450 rhs += coeff0 * lj *
li;
453 printf (
"adding (%g,%g) = %g*(%g,%g) (rhsMll) to xtrac[%d=varInd[%d]] and xtrac[%d=varInd[%d]]\n",
454 coeff0 * lj, coeff0 * li, coeff0, lj, li, varIndices [i] -> Index (), i, varIndices [
j] -> Index (),
j);
461 rhsMlu = lj * valXi + ui * valXj - lj * ui,
462 rhsMul = uj * valXi + li * valXj - uj *
li;
464 if (
U <= CoinMin (rhsMlu, rhsMul))
468 else if (rhsMul < rhsMlu) {
473 numerics_flag =
true;
477 xtraC [varIndices [i] -> Index ()] += coeff0 * uj;
478 xtraC [varIndices [
j] -> Index ()] += coeff0 *
li;
479 rhs += coeff0 * uj *
li;
482 printf (
"adding (%g,%g) = %g*(%g,%g) (rhsMul) to xtrac[%d=varInd[%d]] and xtrac[%d=varInd[%d]]\n",
483 coeff0 * uj, coeff0 * li, coeff0, uj, li, varIndices [i] -> Index (), i, varIndices [
j] -> Index (),
j);
491 numerics_flag =
true;
495 xtraC [varIndices [i] -> Index ()] += coeff0 * lj;
496 xtraC [varIndices [
j] -> Index ()] += coeff0 * ui;
497 rhs += coeff0 * lj * ui;
500 printf (
"adding (%g,%g) = %g*(%g,%g) (rhsMlu) to xtrac[%d=varInd[%d]] and xtrac[%d=varInd[%d]]\n",
501 coeff0 * lj, coeff0 * ui, coeff0, lj, ui, varIndices [i] -> Index (), i, varIndices [
j] -> Index (),
j);
512 printf (
"normal term: %g x_%d [terms:%d]\n", (i==
j) ? (0.5 * coeff0) : (coeff0), index, nterms);
515 if (inverse [index] >= 0)
516 coeff [inverse [index]] += (i==
j) ? (0.5 * coeff0) : (coeff0);
519 coeff [nterms] = (i==
j) ? (0.5 * coeff0) : (coeff0);
523 inverse [index] = nterms;
524 ind [nterms++] = index;
528 printf (
"%d terms so far\n", nterms);
533 for (std::vector <expression *>::iterator
534 i = varIndices . begin ();
535 i != varIndices .
end (); ++i) {
537 int varInd = (*i) -> Index ();
539 if ((inverse [varInd] >= 0) &&
540 (fabs (xtraC [varInd]) > 1
e-15)) {
542 printf (
"now adding %g to coeff [inv [%d] = %d]\n", xtraC [varInd], varInd, inverse [varInd]);
544 coeff [inverse [varInd]] += xtraC [varInd];
547 coeff [nterms] = xtraC [varInd];
548 inverse [varInd] = nterms;
549 ind [nterms++] = varInd;
556 if (!numerics_flag) {
558 OsiRowCut *cut =
new OsiRowCut;
559 cut -> setRow (nterms, ind, coeff);
565 printf (
"SDP: separating ");
570 cs.insertIfNotDuplicate (*cut, treatAsSame);
572 double violation = 0.;
574 if (
problem_ -> bestSol () && ((violation = cut -> violated (
problem_ -> bestSol ())) > 0.)) {
576 printf (
"Cut violates optimal solution by %g\n", violation);
CouenneProblem * problem_
pointer to problem info
void sparsify(bool sparsify_new, const int evidx, const double eigen_val, const double *v, const int n, const double *sol, double **sparse_v_mat, int *card_v_mat, int *evdec_num) const
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
void genSDPcut(const OsiSolverInterface &si, OsiCuts &cs, CouenneExprMatrix *XX, double *v1, double *v2, int **) const
void char char int double int double double int int double int double double int double int int int int *int dsyevx_interface(int n, double *A, int &m, double *&w, double *&z, double tolerance, double lb_ev, double ub_ev, int firstidx, int lastidx)
void fint fint fint real fint real real real real real real real real real * e
#define SPARSIFY_MAX_CARD
bool useSparsity_
Sparsify eigenvalues before writing inequality (default: no)
void genCutSingle(CouenneExprMatrix *const &, const OsiSolverInterface &, OsiCuts &, const CglTreeInfo=CglTreeInfo()) const
expression clone (points to another expression)
#define SPARSIFY_NEW_NZ_THRESHOLD
void sparsify2(const int n, const double *A, double **sparse_v_mat, int *card_v_mat, int min_nz, int *evdec_num) const
int numEigVec_
number of eigenvectors to be used (default: n)
void additionalSDPcuts(const OsiSolverInterface &si, OsiCuts &cs, CouenneExprMatrix *minor, int np, const double *A, const double *vector, int **) const
void fint fint fint real fint real real real real real real real real * w
bool onlyNegEV_
only use negative eigenvalues (default: yes)
virtual void generateCuts(const OsiSolverInterface &, OsiCuts &, const CglTreeInfo=CglTreeInfo()) const
The main CglCutGenerator.
class for multiplications,