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
48 if (!(problem_ -> fbbtReachedIterLimit ()))
56 if (treeInfo.inTree &&
61 double startTime = CoinCpuTime ();
63 int nInitTightened = nTightened_;
65 if (treeInfo.inTree &&
66 treeInfo.level <= 0) {
68 problem_ -> Jnlst () -> Printf (J_ERROR,
J_COUENNE,
"Fixed Point FBBT: ");
74 double now = CoinCpuTime ();
76 problem_ -> domain () -> push (&si, &cs);
79 *oldLB = CoinCopyOfArray (problem_ -> Lb (), problem_ -> nVars ()),
80 *oldUB = CoinCopyOfArray (problem_ -> Ub (), problem_ -> nVars ());
82 perfIndicator_. setOldBounds (problem_ -> Lb (), problem_ -> Ub ());
103 OsiSolverInterface *fplp = NULL;
108 fplp =
new OsiClpSolverInterface;
130 const CoinPackedMatrix *A = si. getMatrixByRow ();
133 n = si. getNumCols (),
134 m = si. getNumRows (),
135 nCuts = cs.sizeRowCuts (),
136 *ind = A -> getIndices ();
139 *lb = problem_ -> Lb (),
140 *ub = problem_ -> Ub (),
141 *rlb = si. getRowLower (),
142 *rub = si. getRowUpper (),
143 *coe = A -> getElements ();
146 for (
int i=0; i<
n; i++)
147 printf (
"----------- x_%d in [%g,%g]\n", i, lb [i], ub [i]);
150 fplp -> messageHandler () -> setLogLevel (0);
153 for (
int i=0; i<
n; i++) {
154 bool isActive = problem_ -> Var (i) -> Multiplicity () > 0;
155 fplp -> addCol (0, NULL, NULL, lb [i], ub [i], isActive ? -1. : 0.);
158 for (
int i=0; i<
n; i++) {
159 bool isActive = problem_ -> Var (i) -> Multiplicity () > 0;
160 fplp -> addCol (0, NULL, NULL, lb [i], ub [i], isActive ? +1. : 0.);
163 if (extendedModel_) {
165 for (
int j=0;
j<
m;
j++) fplp -> addCol (0, NULL, NULL, rlb [
j], COIN_DBL_MAX, 0.);
166 for (
int j=0; j<
m; j++) fplp -> addCol (0, NULL, NULL, -COIN_DBL_MAX, rub [j], 0.);
171 for (
int j=0;
j<
m;
j++) {
173 int nEl = A -> getVectorSize (
j);
180 printf (
"row %4d, %4d elements: ",
j, nEl);
182 for (
int i=0; i<nEl; i++) {
183 printf (
"%+g x%d ", coe [i], ind [i]);
193 for (
int i=0; i<nEl; i++)
194 createRow (-1, ind [i], n, fplp, ind, coe, rlb [
j], nEl, extendedModel_, j, m + nCuts);
197 for (
int i=0; i<nEl; i++)
198 createRow (+1, ind [i], n, fplp, ind, coe, rub [j], nEl, extendedModel_, j, m + nCuts);
202 if (extendedModel_) {
203 createRow (-1, 2*n + j, n, fplp, ind, coe, rlb [j], nEl, extendedModel_, j, m + nCuts);
204 createRow (+1, 2*n + m + j, n, fplp, ind, coe, rub [j], nEl, extendedModel_, j, m + nCuts);
213 for (
int j = 0, jj = nCuts; jj--;
j++) {
217 OsiRowCut *cut = cs.rowCutPtr (
j);
219 const CoinPackedVector &row = cut -> row ();
222 nEl = row.getNumElements (),
223 *ind = row.getIndices ();
225 const double *coe = row.getElements ();
227 if (extendedModel_) {
228 fplp -> addCol (0, NULL, NULL, cut -> lb (), COIN_DBL_MAX, 0.);
229 fplp -> addCol (0, NULL, NULL, -COIN_DBL_MAX, cut -> ub (), 0.);
233 for (
int i=0; i<nEl; i++)
234 createRow (-1, ind [i], n, fplp, ind, coe, cut -> lb (), nEl, extendedModel_, m +
j, m + nCuts);
237 for (
int i=0; i<nEl; i++)
238 createRow (+1, ind [i], n, fplp, ind, coe, cut -> ub (), nEl, extendedModel_, m +
j, m + nCuts);
242 if (extendedModel_) {
243 createRow (-1, 2*n +
j, n, fplp, ind, coe, cut -> lb (), nEl, extendedModel_, m +
j, m + nCuts);
244 createRow (+1, 2*n + m + nCuts +
j, n, fplp, ind, coe, cut -> ub (), nEl, extendedModel_, m +
j, m + nCuts);
255 for (
int j=0;
j<
m;
j++) {
257 int ind [2] = {2*n +
j, 2*n + m + j};
258 double coe [2] = {1., -1.};
260 CoinPackedVector row (2, ind, coe);
261 fplp -> addRow (row, -COIN_DBL_MAX, 0.);
267 fplp -> setObjSense (-1.);
273 fplp -> setIntParam (OsiMaxNumIteration, CoinMax (100, fplp -> getNumRows ()));
282 bool one_inf_bd =
false;
284 for (
int i=0; i<
n; ++i) {
292 one_norm += (oldUB [i] - oldLB [i]);
295 #define APPROX_USELESS .99
299 fplp -> setDblParam (OsiPrimalObjectiveLimit,
APPROX_USELESS * one_norm);
301 fplp -> initialSolve ();
309 if (fplp -> isProvenDualInfeasible () &&
310 !(fplp -> isProvenPrimalInfeasible ())) {
312 problem_ -> Jnlst () -> Printf (J_WARNING,
J_BOUNDTIGHTENING,
"FPLP unbounded: extra BT\n");
314 if (!(problem_ -> doFBBT ()) &&
315 !(problem_ -> btCore (NULL)))
320 for (
int i=0; i<
n; i++) {
321 fplp -> setColLower ( i, problem_ -> Lb (i));
322 fplp -> setColLower (n+i, problem_ -> Lb (i));
323 fplp -> setColUpper ( i, problem_ -> Ub (i));
324 fplp -> setColUpper (n+i, problem_ -> Ub (i));
333 *newLB = fplp -> getColSolution (),
336 double infeasBounds [] = {1,-1};
340 if (fplp -> isProvenOptimal ()) {
347 *indLB =
new int [
n],
348 *indUB =
new int [
n],
353 *valLB =
new double [
n],
354 *valUB =
new double [
n];
356 for (
int i=0; i<
n; i++) {
359 printf (
"x%d: [%g,%g] --> [%g,%g]\n", i,
360 oldLB [i], oldUB [i],
361 newLB [i], newUB [i]);
365 indLB [ntightenedL] = i;
366 valLB [ntightenedL++] = newLB [i];
373 indUB [ntightenedU] = i;
374 valUB [ntightenedU++] = newUB [i];
380 if (ntightenedL || ntightenedU) {
384 newBound.setLbs (ntightenedL, indLB, valLB);
385 newBound.setUbs (ntightenedU, indUB, valUB);
387 cs.insert (newBound);
395 CPUtime_ += CoinCpuTime () - now;
397 if (treeInfo.inTree &&
399 problem_ -> Jnlst () -> Printf (J_ERROR,
J_COUENNE,
"%d bounds tightened (%g seconds)\n",
400 nTightened_ - nInitTightened, CoinCpuTime () - now);
402 }
else if (fplp -> isProvenPrimalInfeasible ()) {
404 if (treeInfo.inTree &&
406 problem_ -> Jnlst () -> Printf (J_ERROR,
J_COUENNE,
" FPLP infeasible.\n");
410 newLB = infeasBounds;
411 newUB = infeasBounds + 1;
418 if (treeInfo.inTree &&
420 problem_ -> Jnlst () -> Printf (J_ERROR,
J_COUENNE,
" FPLP inconclusive, won't be used.\n");
430 perfIndicator_. update (newLB, newUB, treeInfo.level);
431 perfIndicator_. addToTimer (CoinCpuTime () - startTime);
433 problem_ -> domain () -> pop ();
456 void CouenneFixPoint::createRow (
int sign,
459 OsiSolverInterface *p,
573 printf (
"creating constraint from: ");
575 for (
int i=0; i<nEl; i++)
576 printf (
"%+g x%d ", coe [i], indices [i]);
578 printf (
"%c= %g for variable index %d: ", sign > 0 ?
'<' :
'>', rhs, indexVar);
586 int *iInd =
new int [nTerms];
587 double *elem =
new double [nTerms];
591 CoinCopyN (coe, nEl, elem);
595 iInd [nEl] = 2*nVars + indCon + ((sign > 0) ? nCon : 0);
600 for (
int k=0;
k<nEl;
k++) {
602 int curInd = indices [
k];
608 if (curInd == indexVar) {
609 if (((sign > 0) && (coe [
k] > 0.)) ||
610 ((sign < 0) && (coe [
k] < 0.)))
614 }
else if (((coe [
k] > 0.) && (sign < 0)) ||
615 ((coe [
k] < 0.) && (sign > 0)))
620 CoinPackedVector vec (nTerms, iInd, elem);
623 lb = sign > 0 ? -COIN_DBL_MAX : extMod ? 0. : rhs,
624 ub = sign < 0 ? +COIN_DBL_MAX : extMod ? 0. : rhs;
626 p -> addRow (vec, lb, ub);
632 for (
int i=0; i<nEl; i++)
633 printf (
"%+g x%d ", elem [i], iInd [i]);
635 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...