16 #include "CoinHelperFunctions.hpp"
17 #include "CoinPackedMatrix.hpp"
18 #include "CglCutGenerator.hpp"
19 #include "CoinTime.hpp"
30 using namespace Ipopt;
37 t_chg_bounds *chg,
const CglTreeInfo &
info);
59 void CouenneTwoImplied::generateCuts (
const OsiSolverInterface &si,
61 const CglTreeInfo
info)
62 #if CGL_VERSION_MAJOR == 0 && CGL_VERSION_MINOR <= 57
74 double now = CoinCpuTime ();
78 if ((depthStopSeparate_ >= 0 &&
79 info.level > depthStopSeparate_)
81 (depthLevelling_ >= 0 &&
82 info.level >= depthLevelling_ &&
83 CoinDrand48 () > 1. / (2. + info.level - depthLevelling_)))
87 jnlst_ -> Printf (J_ERROR,
J_COUENNE,
"TwoImpl-BT: "); fflush (stdout);
98 problem_ -> domain () -> push (&si, &cs);
100 static int nBadColMatWarnings = 0;
102 std::set <std::pair <int, int> > pairs;
118 const CoinPackedMatrix *mat = si. getMatrixByRow ();
121 m = mat -> getMajorDim (),
122 n = mat -> getMinorDim ();
126 const CoinPackedMatrix *mat = si. getMatrixByCol ();
129 n = mat -> getMajorDim (),
130 m = mat -> getMinorDim ();
135 *rlb = si.getRowLower (),
136 *rub = si.getRowUpper ();
143 nnz = mat -> getNumElements (),
145 *sta =
new int [n+1],
146 nCuts = cs.sizeRowCuts ();
150 for (
int i=0, ii = cs. sizeRowCuts (); ii--; i++) {
152 const OsiRowCut *cut = cs. rowCutPtr (i);
153 const CoinPackedVector &rowCoe = cut -> row ();
155 nnzC += rowCoe.getNumElements ();
158 int *ind =
new int [nnz + nnzC];
159 double *A =
new double [nnz + nnzC];
164 *rA = mat -> getElements ();
167 *rInd = mat -> getIndices (),
168 *rSta = mat -> getVectorStarts ();
172 CoinZeroN (sta, n+1);
178 for (
int i=nnz; i--;)
179 ++ (sta [1 + *rInd++]);
183 for (
int i=0, ii = cs. sizeRowCuts (); ii--; i++) {
185 const OsiRowCut *cut = cs. rowCutPtr (i);
186 const CoinPackedVector &rowCoe = cut -> row ();
187 const int *indices = rowCoe.getIndices ();
188 int nnz = rowCoe.getNumElements ();
191 for (
int i=nnz; i--;)
192 ++ (sta [1 + *indices++]);
201 for (
int i=1; i<=
n; i++)
202 sta [i] += sta [i-1];
207 for (
int i=0; i<
m; i++) {
211 int rowStart = rSta [i];
213 for (
int j = rowStart, jj = rSta [i+1] - rowStart; jj--;
j++) {
215 int &curSta = sta [rInd [
j]];
218 A [curSta++] = rA [
j];
226 for (
int i=0, ii = cs. sizeRowCuts (); ii--; i++) {
228 const OsiRowCut *cut = cs. rowCutPtr (i);
231 const CoinPackedVector &rowCoe = cut -> row ();
232 const int *indices = rowCoe.getIndices ();
233 const double *elements = rowCoe.getElements ();
234 int nnz = rowCoe.getNumElements ();
237 for (
int j=nnz;
j--;) {
241 int &curSta = sta [*indices++];
244 A [curSta++] = *elements++;
260 *A = mat -> getElements ();
263 *ind = mat -> getIndices (),
264 *sta = mat -> getVectorStarts ();
272 for (
int i=0, ii=n; ii--; i++)
273 *isInteger++ = problem_ -> Var (i) ->
isInteger ();
299 *sa1 =
new double [
n],
300 *sa2 =
new double [
n];
302 CoinFillN (sa1, n, 0.);
303 CoinFillN (sa2, n, 0.);
305 for (
int i=0; i<
n; i++, sta++) {
309 for (
int jj = *(sta+1) - *sta,
j = *sta; jj--;
j++)
310 for (
int kk = jj,
k =
j+1;
kk--;
k++) {
312 if (CoinCpuTime () > problem_ -> getMaxCpuTime ())
322 if ((indj >= m + nCuts) || (indj < 0) ||
323 (indk >= m + nCuts) || (indk < 0)) {
325 if (nBadColMatWarnings++ < 1)
328 Couenne: warning, matrix by row has nonsense indices.\n\
329 This separator will now return without (column) cuts.\n\
330 NOTE: further such inconsistencies won't be reported.\n");
341 problem_ -> domain () -> pop ();
343 totalTime_ += CoinCpuTime () - now;
344 totalInitTime_ += CoinCpuTime () - now;
350 prod = A [
j] * A [
k],
351 rlbj, rubj, rlbk, rubk;
354 OsiRowCut *cut = cs.rowCutPtr (indj-m);
363 OsiRowCut *cut = cs.rowCutPtr (indk-m);
390 pairs.insert (std::pair <int, int> (indj, indk));
397 const CoinPackedMatrix *rowA = mat;
399 const CoinPackedMatrix *rowA = si. getMatrixByRow ();
403 *rA = rowA -> getElements ();
408 *clb = CoinCopyOfArray (problem_ -> Lb (), n),
409 *cub = CoinCopyOfArray (problem_ -> Ub (), n),
410 *oldLB = CoinCopyOfArray (problem_ -> Lb (), n),
411 *oldUB = CoinCopyOfArray (problem_ -> Ub (), n);
414 *rInd = rowA -> getIndices (),
415 *rSta = rowA -> getVectorStarts ();
460 for (std::set <std::pair <int, int> >:: iterator p = pairs.begin (); p != pairs.end (); ++p) {
462 if (CoinCpuTime () > problem_ -> getMaxCpuTime ())
472 double l1, u1, l2, u2;
474 const double *a1, *a2;
476 const int *ind1, *ind2;
483 const OsiRowCut *cut = cs.rowCutPtr (h-m);
484 const CoinPackedVector &rowCoe = cut -> row ();
488 n1 = rowCoe. getNumElements ();
489 ind1 = rowCoe. getIndices ();
490 a1 = rowCoe. getElements ();
496 n1 = rSta [h+1] - rSta [h];
497 ind1 = rInd + rSta [h];
505 OsiRowCut *cut = cs.rowCutPtr (k-m);
506 const CoinPackedVector &rowCoe = cut -> row ();
510 n2 = rowCoe. getNumElements ();
511 ind2 = rowCoe. getIndices ();
512 a2 = rowCoe. getElements ();
518 n2 = rSta [k+1] - rSta [
k];
519 ind2 = rInd + rSta [
k];
527 if ((h < m) && (k < m) && !firstCall_) {
529 bool new_bound =
false;
531 for (
int i=n1; i--;) {
535 if ((chg. lower () != t_chg_bounds::UNCHANGED) ||
536 (chg. upper () != t_chg_bounds::UNCHANGED))
542 for (
int i=n2; i--;) {
546 if ((chg. lower () != t_chg_bounds::UNCHANGED) ||
547 (chg. upper () != t_chg_bounds::UNCHANGED))
552 if (!new_bound)
continue;
557 for (
int i=n1; i--;) sa1 [ind1 [i]] = a1 [i];
558 for (
int i=n2; i--;) sa2 [ind2 [i]] = a2 [i];
569 result =
combine (problem_, n1, n2, ind1, ind2, sa1, sa2, a1, a2, clb, cub, l1, l2, u1, u2, isInteger, 1);
574 nCurTightened += result;
579 sa2 [ind2 [i]] = - a2 [i];
585 result =
combine (problem_, n1, n2, ind1, ind2, sa1, sa2, a1, a2, clb, cub, l1, l2, u1, u2, isInteger, -1);
590 nCurTightened += result;
594 for (
int i=n1; i--;) sa1 [ind1 [i]] = 0.;
595 for (
int i=n2; i--;) sa2 [ind2 [i]] = 0.;
601 int objInd = problem_ -> Obj (0) -> Body () -> Index ();
606 babInfo -> babPtr ()) {
609 UB = babInfo -> babPtr () -> model (). getObjValue(),
610 LB = babInfo -> babPtr () -> model (). getBestPossibleObjValue (),
611 primal0 = problem_ -> Ub (objInd),
612 dual0 = problem_ -> Lb (objInd);
619 problem_ -> Ub (objInd) = UB;
620 chg_bds [objInd].
setUpper (t_chg_bounds::CHANGED);
625 problem_ -> Lb (objInd) = LB;
626 chg_bds [objInd].
setLower (t_chg_bounds::CHANGED);
653 if (!(problem_ -> btCore (chg_bds))) {
664 for (
int i=0; i<
n; i++) {
666 if (problem_ -> Lb (i) > clb [i] +
COUENNE_EPS) clb [i] = problem_ -> Lb (i);
667 if (problem_ -> Ub (i) < cub [i] -
COUENNE_EPS) cub [i] = problem_ -> Ub (i);
672 ntightened += nCurTightened;
674 }
while (++ntrials < nMaxTrials_ && nCurTightened);
676 totalInitTime_ += CoinCpuTime () - now;
680 if (result >= 0 && ntightened) {
685 *indLB =
new int [
n],
686 *indUB =
new int [
n],
691 *valLB =
new double [
n],
692 *valUB =
new double [
n];
694 for (
int i=0; i<
n; i++) {
696 if (clb [i] > oldLB [i]) {
698 if (problem_ -> bestSol () &&
699 problem_ -> bestSol () [i] > oldLB [i] &&
700 problem_ -> bestSol () [i] < clb [i] - 1
e-12) {
703 "Warning, twoImplBounds new LB cuts optimal solution: LB x_%d = %g --> %g, opt %g (diff: %g)\n",
704 i, oldLB [i], clb [i], problem_ -> bestSol () [i], clb [i] - problem_ -> bestSol () [i]);
709 indLB [ntightenedL] = i;
710 valLB [ntightenedL++] = clb [i];
713 if (cub [i] < oldUB [i]) {
715 if (problem_ -> bestSol () &&
716 problem_ -> bestSol () [i] < oldUB [i] &&
717 problem_ -> bestSol () [i] > cub [i] + 1
e-12) {
720 "Warning, twoImplBounds new UB cuts optimal solution: UB x_%d = %g --> %g, opt %g (diff: %g)\n",
721 i, oldUB [i], cub [i], problem_ -> bestSol () [i], problem_ -> bestSol () [i] - cub [i]);
726 indUB [ntightenedU] = i;
727 valUB [ntightenedU++] = cub [i];
731 if (ntightenedL || ntightenedU) {
735 newBound.setLbs (ntightenedL, indLB, valLB);
736 newBound.setUbs (ntightenedU, indUB, valUB);
740 cs.insert (newBound);
748 ntightened = ntightenedL + ntightenedU;
766 problem_ -> domain () -> pop ();
777 totalTime_ += CoinCpuTime () - now;
780 jnlst_ -> Printf (J_ERROR,
J_COUENNE,
"%d improved bounds\n", ntightened);
void updateBranchInfo(const OsiSolverInterface &si, CouenneProblem *p, t_chg_bounds *chg, const CglTreeInfo &info)
get new bounds from parents' bounds + branching rules
bool isWiped(OsiCuts &cs)
Check whether the previous cut generators have added an infeasible cut.
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
status of lower/upper bound of a variable, to be checked/modified in bound tightening ...
void setLower(ChangeStatus lower)
int combine(CouenneProblem *p, int n1, int n2, const int *ind1, const int *ind2, double *sa1, double *sa2, const double *a1, const double *a2, double *clb, double *cub, double l1, double l2, double u1, double u2, bool *isInteger, int sign)
void fint fint fint real fint real real real real real real real real real * e
void setUpper(ChangeStatus upper)
double CouNumber
main number type in Couenne
int nnz
ATTENTION: Filter expect the jacobian to be ordered by row.
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...
Bonmin class for passing info between components of branch-and-cuts.
bool isInteger(CouNumber x)
is this number integer?