11 #include "CoinHelperFunctions.hpp"
12 #include "OsiClpSolverInterface.hpp"
13 #include "OsiCuts.hpp"
14 #include "CoinTime.hpp"
23 using namespace Ipopt;
24 using namespace Couenne;
28 void CouenneFixPoint::generateCuts (
const OsiSolverInterface &si,
30 const CglTreeInfo treeInfo)
31 #if CGL_VERSION_MAJOR == 0 && CGL_VERSION_MINOR <= 57
59 if (treeInfo.inTree &&
67 if ((levelStop_ < 0) &&
68 ((treeInfo.level > -2*levelStop_) ||
69 ((treeInfo.level > -levelStop_) &&
70 (treeInfo.level & 1))))
73 double startTime = CoinCpuTime ();
75 int nInitTightened = nTightened_;
77 if (treeInfo.inTree &&
78 treeInfo.level <= 0) {
80 problem_ -> Jnlst () -> Printf (J_ERROR,
J_COUENNE,
"Fixed Point FBBT: ");
86 double now = CoinCpuTime ();
88 problem_ -> domain () -> push (&si, &cs);
91 *oldLB = CoinCopyOfArray (problem_ -> Lb (), problem_ -> nVars ()),
92 *oldUB = CoinCopyOfArray (problem_ -> Ub (), problem_ -> nVars ());
94 perfIndicator_. setOldBounds (problem_ -> Lb (), problem_ -> Ub ());
115 OsiSolverInterface *fplp = NULL;
120 fplp =
new OsiClpSolverInterface;
142 const CoinPackedMatrix *A = si. getMatrixByRow ();
145 n = si. getNumCols (),
146 m = si. getNumRows (),
147 nCuts = cs.sizeRowCuts (),
148 *ind = A -> getIndices ();
151 *lb = problem_ -> Lb (),
152 *ub = problem_ -> Ub (),
153 *rlb = si. getRowLower (),
154 *rub = si. getRowUpper (),
155 *coe = A -> getElements ();
158 for (
int i=0; i<
n; i++)
159 printf (
"----------- x_%d in [%g,%g]\n", i, lb [i], ub [i]);
162 fplp -> messageHandler () -> setLogLevel (0);
165 for (
int i=0; i<
n; i++) {
166 bool isActive = problem_ -> Var (i) -> Multiplicity () > 0;
167 fplp -> addCol (0, NULL, NULL, lb [i], ub [i], isActive ? -1. : 0.);
170 for (
int i=0; i<
n; i++) {
171 bool isActive = problem_ -> Var (i) -> Multiplicity () > 0;
172 fplp -> addCol (0, NULL, NULL, lb [i], ub [i], isActive ? +1. : 0.);
175 if (extendedModel_) {
177 for (
int j=0;
j<
m;
j++) fplp -> addCol (0, NULL, NULL, rlb [
j], COIN_DBL_MAX, 0.);
178 for (
int j=0; j<
m; j++) fplp -> addCol (0, NULL, NULL, -COIN_DBL_MAX, rub [j], 0.);
183 for (
int j=0;
j<
m;
j++) {
185 const int nEl = A->getVectorLast(
j) - A->getVectorFirst(
j),
186 *rind = &ind [A->getVectorFirst (
j)];
187 const double *rcoe = &coe [A->getVectorFirst (
j)];
194 printf (
"row %4d, %4d elements: ",
j, nEl);
196 for (
int i=0; i<nEl; i++) {
197 printf (
"%+g x%d ", rcoe [i], rind [i]);
207 for (
int i = A->getVectorFirst(
j); i < A->getVectorLast(
j); i++)
208 createRow (-1, ind [i], n, fplp, rind, rcoe, rlb [
j], nEl, extendedModel_, j, m + nCuts);
211 for (
int i = A->getVectorFirst(j); i < A->getVectorLast(j); i++)
212 createRow (+1, ind [i], n, fplp, rind, rcoe, rub [j], nEl, extendedModel_, j, m + nCuts);
216 if (extendedModel_) {
217 createRow (-1, 2*n + j, n, fplp, rind, rcoe, rlb [j], nEl, extendedModel_, j, m + nCuts);
218 createRow (+1, 2*n + m + j, n, fplp, rind, rcoe, rub [j], nEl, extendedModel_, j, m + nCuts);
224 for (
int j = 0, jj = nCuts; jj--;
j++) {
228 OsiRowCut *cut = cs.rowCutPtr (
j);
230 const CoinPackedVector &row = cut -> row ();
233 nEl = row.getNumElements (),
234 *ind = row.getIndices ();
236 const double *coe = row.getElements ();
238 if (extendedModel_) {
239 fplp -> addCol (0, NULL, NULL, cut -> lb (), COIN_DBL_MAX, 0.);
240 fplp -> addCol (0, NULL, NULL, -COIN_DBL_MAX, cut -> ub (), 0.);
244 for (
int i=0; i<nEl; i++)
245 createRow (-1, ind [i], n, fplp, ind, coe, cut -> lb (), nEl, extendedModel_, m +
j, m + nCuts);
248 for (
int i=0; i<nEl; i++)
249 createRow (+1, ind [i], n, fplp, ind, coe, cut -> ub (), nEl, extendedModel_, m +
j, m + nCuts);
253 if (extendedModel_) {
254 createRow (-1, 2*n +
j, n, fplp, ind, coe, cut -> lb (), nEl, extendedModel_, m +
j, m + nCuts);
255 createRow (+1, 2*n + m + nCuts +
j, n, fplp, ind, coe, cut -> ub (), nEl, extendedModel_, m +
j, m + nCuts);
261 for (
int j=0;
j<
n;
j++) {
263 int ind [2] = {
j, n +
j};
264 double coe [2] = {1., -1.};
266 CoinPackedVector row (2, ind, coe);
267 fplp -> addRow (row, -COIN_DBL_MAX, 0.);
274 for (
int j=0;
j<
m;
j++) {
276 int ind [2] = {2*n +
j, 2*n + m + j};
277 double coe [2] = {1., -1.};
279 CoinPackedVector row (2, ind, coe);
280 fplp -> addRow (row, -COIN_DBL_MAX, 0.);
286 fplp -> setObjSense (-1.);
288 fplp -> initialSolve ();
294 if (fplp -> isProvenDualInfeasible ()) {
296 problem_ -> Jnlst () -> Printf (J_WARNING,
J_BOUNDTIGHTENING,
"FPLP unbounded: extra BT\n");
298 if (!(problem_ -> doFBBT ()) &&
299 !(problem_ -> btCore (NULL)))
304 for (
int i=0; i<
n; i++) {
305 fplp -> setColLower ( i, problem_ -> Lb (i));
306 fplp -> setColLower (n+i, problem_ -> Lb (i));
307 fplp -> setColUpper ( i, problem_ -> Ub (i));
308 fplp -> setColUpper (n+i, problem_ -> Ub (i));
315 *newLB = fplp -> getColSolution (),
318 double infeasBounds [] = {1,-1};
320 if (fplp -> isProvenOptimal ()) {
327 *indLB =
new int [
n],
328 *indUB =
new int [
n],
333 *valLB =
new double [
n],
334 *valUB =
new double [
n];
336 for (
int i=0; i<
n; i++) {
339 printf (
"x%d: [%g,%g] --> [%g,%g]\n", i,
340 oldLB [i], oldUB [i],
341 newLB [i], newUB [i]);
345 indLB [ntightenedL] = i;
346 valLB [ntightenedL++] = newLB [i];
353 indUB [ntightenedU] = i;
354 valUB [ntightenedU++] = newUB [i];
360 if (ntightenedL || ntightenedU) {
364 newBound.setLbs (ntightenedL, indLB, valLB);
365 newBound.setUbs (ntightenedU, indUB, valUB);
367 cs.insert (newBound);
375 CPUtime_ += CoinCpuTime () - now;
377 if (treeInfo.inTree &&
379 problem_ -> Jnlst () -> Printf (J_ERROR,
J_COUENNE,
"%d bounds tightened (%g seconds)\n",
380 nTightened_ - nInitTightened, CoinCpuTime () - now);
382 }
else if (fplp -> isProvenPrimalInfeasible ()) {
384 if (treeInfo.inTree &&
386 problem_ -> Jnlst () -> Printf (J_ERROR,
J_COUENNE,
" FPLP infeasible.\n");
390 newLB = infeasBounds;
391 newUB = infeasBounds + 1;
398 if (treeInfo.inTree &&
400 problem_ -> Jnlst () -> Printf (J_ERROR,
J_COUENNE,
" FPLP inconclusive, won't be used.\n");
408 perfIndicator_. update (newLB, newUB, treeInfo.level);
409 perfIndicator_. addToTimer (CoinCpuTime () - startTime);
413 problem_ -> domain () -> pop ();
436 void CouenneFixPoint::createRow (
int sign,
439 OsiSolverInterface *p,
553 printf (
"creating constraint from: ");
555 for (
int i=0; i<nEl; i++)
556 printf (
"%+g x%d ", coe [i], indices [i]);
558 printf (
"%c= %g for variable index %d: ", sign > 0 ?
'<' :
'>', rhs, indexVar);
566 int *iInd =
new int [nTerms];
567 double *elem =
new double [nTerms];
571 CoinCopyN (coe, nEl, elem);
575 iInd [nEl] = 2*nVars + indCon + ((sign > 0) ? nCon : 0);
580 for (
int k=0;
k<nEl;
k++) {
582 int curInd = indices [
k];
588 if (curInd == indexVar) {
589 if (((sign > 0) && (coe [
k] > 0.)) ||
590 ((sign < 0) && (coe [
k] < 0.)))
594 }
else if (((coe [
k] > 0.) && (sign < 0)) ||
595 ((coe [
k] < 0.) && (sign > 0)))
600 CoinPackedVector vec (nTerms, iInd, elem);
603 lb = sign > 0 ? -COIN_DBL_MAX : extMod ? 0. : rhs,
604 ub = sign < 0 ? +COIN_DBL_MAX : extMod ? 0. : rhs;
606 p -> addRow (vec, lb, ub);
612 for (
int i=0; i<nEl; i++)
613 printf (
"%+g x%d ", elem [i], iInd [i]);
615 printf (
"in [%g,%g]\n", lb, ub);
bool isWiped(OsiCuts &cs)
Check whether the previous cut generators have added an infeasible cut.
const Ipopt::EJournalCategory J_BOUNDTIGHTENING(Ipopt::J_USER2)
const Ipopt::EJournalCategory J_COUENNE(Ipopt::J_USER8)
void WipeMakeInfeas(OsiCuts &cs)
Add a fictitious cut 1<= x_0 <= -1 as a signal to the node solver that this node is deemed infeasible...