00001
00002
00003 #if defined(_MSC_VER)
00004
00005 # pragma warning(disable:4786)
00006 #endif
00007 #include <cstdlib>
00008 #include <cstdio>
00009 #include <cmath>
00010 #include <cassert>
00011 #include <cfloat>
00012 #include <iostream>
00013
00014 #include "CoinHelperFunctions.hpp"
00015 #include "CglKnapsackCover.hpp"
00016 #include "CoinPackedVector.hpp"
00017 #include "CoinSort.hpp"
00018 #include "CoinPackedMatrix.hpp"
00019 #include "OsiRowCutDebugger.hpp"
00020
00021
00022
00023
00024
00025 void CglKnapsackCover::generateCuts(const OsiSolverInterface & si,
00026 OsiCuts & cs ) const
00027 {
00028
00029 int nRows=si.getNumRows();
00030 int nCols=si.getNumCols();
00031
00032
00033
00034
00035
00036
00037
00038 CoinPackedVector krow;
00039 double b=0.0;
00040 int * complement= new int[nCols];
00041
00042
00043
00044
00045
00046 double * xstar= new double[nCols];
00047
00048
00049 int * thisColumnIndex = new int [nCols];
00050 double * thisElement = new double[nCols];
00051 int * back = new int[nCols];
00052
00053 const double *colsol = si.getColSolution();
00054 int k;
00055
00056
00057
00058
00059 int * vub = new int [nRows];
00060
00061
00062 int * vubRow = new int [nCols];
00063 double * vubValue = new double [nRows];
00064
00065
00066 double * effectiveUpper = new double [nRows];
00067 double * effectiveLower = new double [nRows];
00068 const double * colUpper = si.getColUpper();
00069 const double * colLower = si.getColLower();
00070 for (k=0; k<nCols; k++){
00071 back[k]=-1;
00072 xstar[k]=colsol[k];
00073 complement[k]=0;
00074 vubRow[k]=-1;
00075 if (si.isBinary(k)) {
00076 if (si.isFreeBinary(k)) {
00077 vubRow[k]=-2;
00078 } else {
00079 vubRow[k]=-10;
00080 }
00081 } else if (colUpper[k]==colLower[k]) {
00082 vubRow[k]=-10;
00083 }
00084 }
00085
00086 int rowIndex;
00087 int numberVub=0;
00088
00089 const CoinPackedMatrix * matrixByRow = si.getMatrixByRow();
00090 const double * elementByRow = matrixByRow->getElements();
00091 const int * column = matrixByRow->getIndices();
00092 const int * rowStart = matrixByRow->getVectorStarts();
00093 const int * rowLength = matrixByRow->getVectorLengths();
00094 const double * rowUpper = si.getRowUpper();
00095 const double * rowLower = si.getRowLower();
00096
00097
00098
00099 for (rowIndex=0;rowIndex<nRows;rowIndex++) {
00100 int start = rowStart[rowIndex];
00101 int end = start + rowLength[rowIndex];
00102 double upRhs = rowUpper[rowIndex];
00103 double loRhs = rowLower[rowIndex];
00104 int numberContinuous=0;
00105 int numberBinary=0;
00106 int iCont=-1;
00107 double sum = 0.0;
00108 double valueContinuous=0.0;
00109 double valueBinary=0.0;
00110 int iBinary=-1;
00111 int j;
00112 for (j=start;j<end;j++) {
00113 int iColumn=column[j];
00114 if (colUpper[iColumn]>colLower[iColumn]) {
00115 sum += colsol[iColumn]*elementByRow[j];
00116 if (vubRow[iColumn]==-2) {
00117
00118 numberBinary++;
00119 valueBinary=elementByRow[j];
00120 iBinary=iColumn;
00121 } else if (vubRow[iColumn]==-1) {
00122
00123 if (colsol[iColumn]<colUpper[iColumn]-1.0e-6&&
00124 colsol[iColumn]>colLower[iColumn]+1.0e-6) {
00125
00126 iCont=iColumn;
00127 numberContinuous++;
00128 valueContinuous=elementByRow[j];
00129 } else {
00130
00131 numberContinuous ++;
00132 iCont=-1;
00133 }
00134 } else {
00135
00136 numberContinuous ++;
00137 iCont=-1;
00138 if (colsol[iColumn]<colUpper[iColumn]-1.0e-6&&
00139 colsol[iColumn]>colLower[iColumn]+1.0e-6) {
00140
00141 numberContinuous ++;
00142 iCont=-1;
00143 }
00144 }
00145 } else {
00146
00147 upRhs -= colLower[iColumn]*elementByRow[j];
00148 loRhs -= colLower[iColumn]*elementByRow[j];
00149 }
00150 }
00151
00152 effectiveUpper[rowIndex] = upRhs;
00153 effectiveLower[rowIndex] = loRhs;
00154 vubValue[rowIndex] = valueContinuous;
00155 bool possible = false;
00156 if (fabs(sum-upRhs)<1.0e-5) {
00157 possible=true;
00158 } else {
00159 effectiveUpper[rowIndex]=DBL_MAX;
00160 }
00161 if (fabs(sum-loRhs)<1.0e-5) {
00162 possible=true;
00163 } else {
00164 effectiveLower[rowIndex]=-DBL_MAX;
00165 }
00166 if (!numberBinary||numberBinary+numberContinuous>maxInKnapsack_)
00167 possible=false;
00168 if (possible) {
00169
00170 if(numberContinuous==1&&iCont>=0) {
00171
00172 if (numberBinary==1)
00173 #ifdef PRINT_DEBUG
00174 printf("vub (by row %d) %g <= 0-1 %g * %d + %g * %d <= %g\n",
00175 rowIndex,effectiveLower[rowIndex],valueBinary,iBinary,
00176 valueContinuous,iCont,effectiveUpper[rowIndex]);
00177 #endif
00178 vubRow[iCont]=rowIndex;
00179 vub[rowIndex]=iCont;
00180 numberVub++;
00181 } else if (numberBinary>1) {
00182
00183 vub[rowIndex]=-1;
00184 } else {
00185
00186 vub[rowIndex]=-2;
00187 }
00188 } else {
00189
00190 vub[rowIndex]=-2;
00191 }
00192 }
00193
00194 int numCheck = 0;
00195 int* toCheck = 0;
00196 if (!rowsToCheck_) {
00197 toCheck = new int[nRows];
00198 CoinIotaN(toCheck, nRows, 0);
00199 numCheck = nRows;
00200 } else {
00201 numCheck = numRowsToCheck_;
00202 toCheck = rowsToCheck_;
00203 }
00204
00205
00206 int ntry;
00207 if (numberVub)
00208 ntry=4;
00209 else
00210 ntry=2;
00211
00212 for (int ii=0; ii < numCheck; ++ii){
00213 rowIndex = toCheck[ii];
00214 if (rowIndex < 0 || rowIndex >= nRows)
00215 continue;
00216 if (vub[rowIndex]==-2)
00217 continue;
00218
00219 #ifdef PRINT_DEBUG
00220 std::cout << "CGL: Processing row " << rowIndex << std::endl;
00221 #endif
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00234
00235
00236
00238 #ifdef CGL_DEBUG
00239 assert(!krow.getNumElements());
00240 #endif
00241 double effectiveRhs[4];
00242 double rhs[4];
00243 double sign[]={0.0,0.0,-1.0,1.0};
00244 bool rowType[] = {false,true,false,true};
00245 effectiveRhs[0] = effectiveLower[rowIndex];
00246 rhs[0]=rowLower[rowIndex];
00247 effectiveRhs[2] = effectiveRhs[0];
00248 rhs[2]= effectiveRhs[0];
00249 effectiveRhs[1] = effectiveUpper[rowIndex];
00250 rhs[1]=rowUpper[rowIndex];
00251 effectiveRhs[3] = effectiveRhs[1];
00252 rhs[3]= effectiveRhs[1];
00253 int itry;
00254 #ifdef CGL_DEBUG
00255 int kcuts[4];
00256 memset(kcuts,0,4*sizeof(int));
00257 #endif
00258 for (itry=0;itry<ntry;itry++) {
00259 #ifdef CGL_DEBUG
00260 int nlast=cs.sizeRowCuts();
00261 #endif
00262
00263 if (fabs(effectiveRhs[itry])>1.0e20)
00264 continue;
00265 int length = rowLength[rowIndex];
00266 memcpy(thisColumnIndex,column+rowStart[rowIndex],length*sizeof(int));
00267 memcpy(thisElement,elementByRow+rowStart[rowIndex],
00268 length*sizeof(double));
00269 b=rhs[itry];
00270 if (itry>1) {
00271
00272 int i;
00273
00274 int length2=length;
00275 int numberReplaced=0;
00276 for (i=0;i<length;i++) {
00277 int iColumn = thisColumnIndex[i];
00278 back[thisColumnIndex[i]]=i;
00279 if (vubRow[iColumn]==-10) {
00280
00281 thisElement[i]=0.0;
00282 }
00283 }
00284 for (i=0;i<length;i++) {
00285 int iColumn = thisColumnIndex[i];
00286 int iRow = vubRow[iColumn];
00287 if (iRow>=0&&vub[iRow]==iColumn&&iRow!=rowIndex) {
00288 double useRhs=0.0;
00289 double vubCoefficient = vubValue[iRow];
00290 double thisCoefficient = thisElement[i];
00291 int replace = 0;
00292
00293 if (sign[itry]*thisCoefficient>0.0) {
00294
00295 if (effectiveLower[iRow]>-1.0e20&&vubCoefficient>0.0)
00296 replace=-1;
00297 else if (effectiveUpper[iRow]<1.0e20&&vubCoefficient<0.0)
00298 replace=1;
00299 } else {
00300
00301 if (effectiveLower[iRow]>-1.0e20&&vubCoefficient<0.0)
00302 replace=-1;
00303 else if (effectiveUpper[iRow]<1.0e20&&vubCoefficient>0.0)
00304 replace=1;
00305 }
00306 if (replace) {
00307 numberReplaced++;
00308 if (replace<0)
00309 useRhs = effectiveLower[iRow];
00310 else
00311 useRhs = effectiveUpper[iRow];
00312
00313
00314 thisElement[i]=0.0;
00315 double scale = thisCoefficient/vubCoefficient;
00316
00317 b -= scale*useRhs;
00318 int start = rowStart[iRow];
00319 int end = start+rowLength[iRow];
00320 int j;
00321 for (j=start;j<end;j++) {
00322 int iColumn = column[j];
00323 if (vubRow[iColumn]==-2) {
00324 double change = scale*elementByRow[j];
00325 int iBack = back[iColumn];
00326 if (iBack<0) {
00327
00328 back[iColumn]=length2;
00329 thisElement[length2]=-change;
00330 thisColumnIndex[length2++]=iColumn;
00331 } else {
00332
00333 thisElement[iBack] -= change;
00334 }
00335 }
00336 }
00337 }
00338 }
00339 }
00340 if (numberReplaced) {
00341 length=0;
00342 for (i=0;i<length2;i++) {
00343 int iColumn = thisColumnIndex[i];
00344 back[iColumn]=-1;
00345 if (thisElement[i]) {
00346 thisElement[length]=thisElement[i];
00347 thisColumnIndex[length++]=iColumn;
00348 }
00349 }
00350 if (length>maxInKnapsack_)
00351 continue;
00352 } else {
00353 for (i=0;i<length;i++) {
00354 int iColumn = thisColumnIndex[i];
00355 back[iColumn]=-1;
00356 }
00357 continue;
00358 }
00359 }
00360 if (!deriveAKnapsack(si, cs, krow, rowType[itry], b, complement,
00361 xstar, rowIndex,
00362 length,thisColumnIndex,thisElement)) {
00363
00364
00365
00366 for(k=0; k<krow.getNumElements(); k++) {
00367 if (complement[krow.getIndices()[k]]){
00368 xstar[krow.getIndices()[k]]= 1.0-xstar[krow.getIndices()[k]];
00369 complement[krow.getIndices()[k]]=0;
00370 }
00371 }
00372 krow.setVector(0,NULL,NULL);
00373 continue;
00374 }
00375 #ifdef PRINT_DEBUG
00376 {
00377
00378 int i;
00379 printf("rhs sense %c rhs %g\n",si.getRowSense()[rowIndex],
00380 si.getRightHandSide()[rowIndex]);
00381 const int * indices = si.getMatrixByRow()->getVector(rowIndex).getIndices();
00382 const double * elements = si.getMatrixByRow()->getVector(rowIndex).getElements();
00383
00384 for (i=0; i<si.getMatrixByRow()->getVector(rowIndex).getNumElements(); i++){
00385 printf("%d (s=%g) %g, ",indices[i],colsol[indices[i]],elements[i]);
00386 }
00387 printf("\n");
00388 }
00389 #endif
00390
00392
00393
00394
00395
00396
00397
00398
00399
00401
00403
00404
00406
00407 CoinPackedVector cover, remainder;
00408
00409
00410 if (findGreedyCover(rowIndex, krow, b, xstar, cover, remainder) == 1){
00411
00412
00413 if (!liftAndUncomplementAndAdd(rowUpper[rowIndex], krow, b,
00414 complement, rowIndex, cover,
00415 remainder, cs)) {
00416
00417
00418
00419 for(k=0; k<krow.getNumElements(); k++) {
00420 if (complement[krow.getIndices()[k]]){
00421 xstar[krow.getIndices()[k]]= 1.0-xstar[krow.getIndices()[k]];
00422 complement[krow.getIndices()[k]]=0;
00423 }
00424 }
00425 krow.setVector(0,NULL,NULL);
00426 continue;
00427 }
00428 }
00429
00430
00432
00433
00435
00436
00437 cover.setVector(0,NULL,NULL);
00438 remainder.setVector(0,NULL,NULL);
00439
00440 if (findPseudoJohnAndEllisCover(rowIndex, krow, b,
00441 xstar, cover, remainder) == 1){
00442
00443
00444 if (!liftAndUncomplementAndAdd(rowUpper[rowIndex], krow, b,
00445 complement, rowIndex, cover,
00446 remainder, cs)) {
00447
00448
00449
00450 for(k=0; k<krow.getNumElements(); k++) {
00451 if (complement[krow.getIndices()[k]]){
00452 xstar[krow.getIndices()[k]]= 1.0-xstar[krow.getIndices()[k]];
00453 complement[krow.getIndices()[k]]=0;
00454 }
00455 }
00456 krow.setVector(0,NULL,NULL);
00457 continue;
00458 }
00459
00460
00461 #if 0
00462
00463
00464 seqLiftAndUncomplementAndAdd(nCols, xstar, complement, rowIndex,
00465 krow.getNumElements(), b, cover, remainder,
00466 cs);
00467 #endif
00468 }
00469
00470
00471
00473
00474
00476 CoinPackedVector atOnes;
00477 CoinPackedVector fracCover;
00478
00479
00480 remainder.setVector(0,NULL,NULL);
00481
00482
00483 if (findJohnAndEllisCover(rowIndex, krow, b,
00484 xstar, fracCover, atOnes, remainder) == 1){
00485
00486
00487
00488
00489 liftUpDownAndUncomplementAndAdd(nCols, xstar, complement, rowIndex,
00490 krow.getNumElements(), b, fracCover,
00491 atOnes, remainder, cs);
00492 }
00493
00494
00496
00497
00498
00500
00501
00502
00503 cover.setVector(0,NULL,NULL);
00504 remainder.setVector(0,NULL,NULL);
00505
00506
00507
00508
00509
00510 if(krow.getNumElements()<=15){
00511 if (findExactMostViolatedMinCover(nCols, rowIndex, krow, b,
00512 xstar, cover, remainder) == 1){
00513
00514
00515 if (!liftAndUncomplementAndAdd(rowUpper[rowIndex], krow, b,
00516 complement, rowIndex, cover, remainder, cs)) {
00517
00518
00519
00520 for(k=0; k<krow.getNumElements(); k++) {
00521 if (complement[krow.getIndices()[k]]){
00522 xstar[krow.getIndices()[k]]= 1.0-xstar[krow.getIndices()[k]];
00523 complement[krow.getIndices()[k]]=0;
00524 }
00525 }
00526 krow.setVector(0,NULL,NULL);
00527 continue;
00528 }
00529 }
00530 }
00531 else {
00532 if (findLPMostViolatedMinCover(nCols, rowIndex, krow, b,
00533 xstar, cover, remainder) == 1){
00534
00535
00536 if (!liftAndUncomplementAndAdd(rowUpper[rowIndex], krow, b,
00537 complement, rowIndex, cover, remainder, cs)) {
00538
00539
00540
00541 for(k=0; k<krow.getNumElements(); k++) {
00542 if (complement[krow.getIndices()[k]]){
00543 xstar[krow.getIndices()[k]]= 1.0-xstar[krow.getIndices()[k]];
00544 complement[krow.getIndices()[k]]=0;
00545 }
00546 }
00547 krow.setVector(0,NULL,NULL);
00548 continue;
00549 }
00550 }
00551 }
00552
00553
00554
00555
00556
00557 int k;
00558 if (fabs(b-rowUpper[rowIndex]) > epsilon_) {
00559 for(k=0; k<krow.getNumElements(); k++) {
00560 if (complement[krow.getIndices()[k]]){
00561 xstar[krow.getIndices()[k]]= 1.0-xstar[krow.getIndices()[k]];
00562 complement[krow.getIndices()[k]]=0;
00563 }
00564 }
00565 }
00566 krow.setVector(0,NULL,NULL);
00567 #ifdef CGL_DEBUG
00568 int nnow = cs.sizeRowCuts();
00569 if (nnow>nlast) {
00570 const OsiRowCutDebugger * debugger = si.getRowCutDebugger();
00571 if (debugger&&debugger->onOptimalPath(si)) {
00572
00573 int k;
00574 for (k=nlast;k<nnow;k++) {
00575 OsiRowCut rc=cs.rowCut(k);
00576 if(debugger->invalidCut(rc)) {
00577 printf("itry %d, rhs %g, length %d\n",itry,rhs[itry],length);
00578 int i;
00579 for (i=0;i<length;i++) {
00580 int iColumn = thisColumnIndex[i];
00581 printf("column %d, coefficient %g, value %g, bounds %g %g\n",iColumn,
00582 thisElement[i],colsol[iColumn],colLower[iColumn],
00583 colUpper[iColumn]);
00584 }
00585 if (itry>1) {
00586 int length = rowLength[rowIndex];
00587 memcpy(thisColumnIndex,column+rowStart[rowIndex],
00588 length*sizeof(int));
00589 memcpy(thisElement,elementByRow+rowStart[rowIndex],
00590 length*sizeof(double));
00591 printf("Original row had rhs %g and length %d\n",
00592 (itry==2 ? rowLower[rowIndex] :rowUpper[rowIndex]),
00593 length);
00594 for (i=0;i<length;i++) {
00595 int iColumn = thisColumnIndex[i];
00596 printf("column %d, coefficient %g, value %g, bounds %g %g\n",iColumn,
00597 thisElement[i],colsol[iColumn],colLower[iColumn],
00598 colUpper[iColumn]);
00599 }
00600 }
00601 assert(!debugger->invalidCut(rc));
00602 }
00603 }
00604 }
00605 if (itry>1&&nnow-nlast>kcuts[itry-2]) {
00606 printf("itry %d gave %d cuts as against %d for itry %d\n",
00607 itry,nnow-nlast,kcuts[itry-2],itry-2);
00608 }
00609 kcuts[itry]=nnow-nlast;
00610 nlast=nnow;
00611 }
00612 #endif
00613 }
00614 }
00615
00616 if (toCheck != rowsToCheck_)
00617 delete[] toCheck;
00618 delete[] xstar;
00619 delete[] complement;
00620 delete [] thisColumnIndex;
00621 delete [] thisElement;
00622 delete [] back;
00623 delete [] vub;
00624 delete [] vubRow;
00625 delete [] vubValue;
00626 delete [] effectiveLower;
00627 delete [] effectiveUpper;
00628 }
00629
00630 void
00631 CglKnapsackCover::setTestedRowIndices(int num, const int* ind)
00632 {
00633 if (rowsToCheck_)
00634 delete[] rowsToCheck_;
00635 numRowsToCheck_ = num;
00636 if (num > 0) {
00637 rowsToCheck_ = new int[num];
00638 CoinCopyN(ind, num, rowsToCheck_);
00639 }
00640 }
00641
00642
00643
00644
00645 int
00646 CglKnapsackCover::liftAndUncomplementAndAdd(
00647 double rowub,
00648 CoinPackedVector & krow,
00649 double & b,
00650 int * complement,
00651 int row,
00652 CoinPackedVector & cover,
00653 CoinPackedVector & remainder,
00654 OsiCuts & cs ) const
00655 {
00656 CoinPackedVector cut;
00657 double cutRhs = cover.getNumElements() - 1.0;
00658 int goodCut=1;
00659
00660 if (remainder.getNumElements() > 0){
00661
00662 if (!liftCoverCut(
00663 b, krow.getNumElements(),
00664 cover, remainder,
00665 cut ))
00666 goodCut= 0;
00667 }
00668
00669
00670 else {
00671 cut.reserve(cover.getNumElements());
00672 cut.setConstant(cover.getNumElements(),cover.getIndices(),1.0);
00673 }
00674
00675
00676 int k;
00677 if (fabs(b-rowub)> epsilon_) {
00678 double * elements = cut.getElements();
00679 int * indices = cut.getIndices();
00680 for (k=0; k<cut.getNumElements(); k++){
00681 if (complement[indices[k]]) {
00682
00683
00684 elements[k] *= -1;
00685 cutRhs += elements[k];
00686 }
00687 }
00688 }
00689 if (goodCut) {
00690
00691 OsiRowCut rc;
00692 rc.setRow(cut);
00693 #ifdef CGL_DEBUG
00694 {
00695 double * elements = cut.getElements();
00696 int * indices = cut.getIndices();
00697 int n=cut.getNumElements();
00698 for (k=0; k<n; k++){
00699 assert(indices[k]>=0);
00700 assert(elements[k]);
00701 }
00702 }
00703 #endif
00704 rc.setLb(-DBL_MAX);
00705 rc.setUb(cutRhs);
00706
00707
00708
00709
00710 #ifdef PRINT_DEBUG
00711 {
00712 int k;
00713 printf("cutrhs %g %d elements\n",cutRhs,cut.getNumElements());
00714 double * elements = cut.getElements();
00715 int * indices = cut.getIndices();
00716 for (k=0; k<cut.getNumElements(); k++){
00717 printf("%d %g\n",indices[k],elements[k]);
00718 }
00719 }
00720 #endif
00721 cs.insert(rc);
00722
00723 return 1;
00724 } else {
00725 return 0;
00726 }
00727 }
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737 int
00738 CglKnapsackCover::deriveAKnapsack(
00739 const OsiSolverInterface & si,
00740 OsiCuts & cs,
00741 CoinPackedVector & krow,
00742 bool treatAsLRow,
00743 double & b,
00744 int * complement,
00745 double * xstar,
00746 int rowIndex,
00747 int numberElements,
00748 const int * index,
00749 const double * element) const
00750 {
00751 int i;
00752
00753 krow.clear();
00754
00755
00756
00757
00758
00759 CoinPackedVector leMatrixRow(numberElements,index,element);
00760
00761 double maxKrowElement = -DBL_MAX;
00762 double minKrowElement = DBL_MAX;
00763
00764
00765 if (treatAsLRow) {
00766
00767 } else {
00768
00769 b=-b;
00770 std::transform(leMatrixRow.getElements(),
00771 leMatrixRow.getElements() + leMatrixRow.getNumElements(),
00772 leMatrixRow.getElements(),
00773 std::negate<double>());
00774 }
00775
00776
00777
00778 int nBinUnsat =0;
00779 const double * colupper = si.getColUpper();
00780 const double * collower = si.getColLower();
00781
00782
00783
00784
00785
00786
00787
00788
00789 const int * indices = leMatrixRow.getIndices();
00790 const double * elements = leMatrixRow.getElements();
00791
00792 for (i=0; i<leMatrixRow.getNumElements(); i++){
00793
00794 if ( !si.isFreeBinary(indices[i]) ) {
00795
00796 if(elements[i]<-epsilon_){
00797
00798 if (colupper[indices[i]] < si.getInfinity()){
00799
00800 b=b-elements[i]*colupper[indices[i]];
00801 }
00802 else {
00803 return 0;
00804 }
00805 }
00806
00807 else if(elements[i]>epsilon_){
00808
00809 if (collower[indices[i]] > -si.getInfinity()){
00810
00811 b=b-elements[i]*collower[indices[i]];
00812 }
00813 else {
00814 return 0;
00815 }
00816 }
00817
00818
00819 }
00820
00821
00822
00823
00824 else{
00825 krow.insert(indices[i], elements[i]);
00826
00827
00828
00829 if(xstar[indices[i]] > epsilon_ && xstar[indices[i]] < onetol_)
00830 nBinUnsat++;
00831
00832
00833
00834
00835
00836 if (fabs(elements[i]) > maxKrowElement)
00837 maxKrowElement = fabs(elements[i]);
00838 if (fabs(elements[i]) < minKrowElement)
00839 minKrowElement = fabs(elements[i]);
00840 }
00841 }
00842
00843
00844
00845
00846
00847
00848
00849 if (krow.getNumElements() < 3 ||
00850 nBinUnsat == 0 ||
00851 maxKrowElement-minKrowElement < 1.0e-3*maxKrowElement ) {
00852 return 0;
00853 }
00854
00855
00856 if (krow.getNumElements()==2) {
00857 const int * indices = krow.getIndices();
00858 double * elements = krow.getElements();
00859 double sum=0.0;
00860 for(i=0; i<2; i++){
00861 int iColumn = indices[i];
00862 sum += elements[i]*xstar[iColumn];
00863 }
00864 if (sum<b-1.0e-4) {
00865 return 0;
00866 } else {
00867 printf("*** Doubleton Row is ");
00868 for(i=0; i<2; i++){
00869 int iColumn = indices[i];
00870 sum += elements[i]*xstar[iColumn];
00871 printf("%d (coeff = %g, value = %g} ",indices[i],
00872 elements[i],xstar[iColumn]);
00873 }
00874 printf("<= %g - go for it\n",b);
00875 }
00876 }
00877
00878
00879
00880
00881
00882
00883
00884 {
00885 const int s = krow.getNumElements();
00886 const int * indices = krow.getIndices();
00887 double * elements = krow.getElements();
00888 for(i=0; i<s; i++){
00889 if (elements[i] < -epsilon_) {
00890 complement[indices[i]]= 1;
00891 elements[i] *= -1;
00892 b+=elements[i];
00893 xstar[indices[i]]=1.0-xstar[indices[i]];
00894 }
00895 }
00896 }
00897
00898
00899
00900
00901
00902 if (b < 0 ){
00903 OsiColCut cc;
00904 int index = krow.getIndices()[0];
00905 const double fakeLb = colupper[index] + 1.0;;
00906 const double fakeUb = collower[index];
00907 assert( fakeUb < fakeLb );
00908 cc.setLbs( 1, &index, &fakeLb);
00909 cc.setUbs( 1, &index, &fakeLb);
00910 cc.setEffectiveness(DBL_MAX);
00911 cs.insert(cc);
00912 #ifdef PRINT_DEBUG
00913 printf("Cgl: Problem is infeasible\n");
00914 #endif
00915 }
00916
00917
00918
00919
00920
00921 int fixed = 0;
00922 CoinPackedVector fixedBnd;
00923 for(i=0; i<krow.getNumElements(); i++){
00924 if (krow.getElements()[i]> b){
00925 fixedBnd.insert(krow.getIndices()[i],complement[krow.getIndices()[i]]);
00926 #ifdef PRINT_DEBUG
00927 printf("Variable %i being fixed to %i due to row %i.\n",
00928 krow.getIndices()[i],complement[krow.getIndices()[i]],rowIndex);
00929 #endif
00930 fixed = 1;
00931 }
00932 }
00933
00934
00935
00936 if (fixed) {
00937 OsiColCut cc;
00938 cc.setLbs(fixedBnd);
00939 cc.setUbs(fixedBnd);
00940 cc.setEffectiveness(DBL_MAX);
00941 return 0;
00942 }
00943
00944 return 1;
00945 }
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956 int
00957 CglKnapsackCover::deriveAKnapsack(
00958 const OsiSolverInterface & si,
00959 OsiCuts & cs,
00960 CoinPackedVector & krow,
00961 double & b,
00962 int * complement,
00963 double * xstar,
00964 int rowIndex,
00965 const CoinPackedVectorBase & matrixRow ) const
00966 {
00967
00968 const char rowsense = si.getRowSense()[rowIndex];
00969
00970
00971 if (rowsense=='E' || rowsense=='N') {
00972 return 0;
00973 }
00974
00975 bool treatAsLRow = (rowsense=='L');
00976 const int * indices = matrixRow.getIndices();
00977 const double * elements = matrixRow.getElements();
00978 int numberElements = matrixRow.getNumElements();
00979 return deriveAKnapsack( si, cs, krow, treatAsLRow, b, complement,
00980 xstar, rowIndex, numberElements, indices,
00981 elements);
00982 }
00983
00984
00985
00986
00987
00988
00989
00990
00991 int
00992 CglKnapsackCover::findLPMostViolatedMinCover(
00993 int nCols,
00994 int row,
00995 CoinPackedVector & krow,
00996 double & b,
00997 double * xstar,
00998 CoinPackedVector & cover,
00999 CoinPackedVector & remainder) const
01000 {
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039 double elementSum = krow.sum();
01040
01041
01042
01043 if (elementSum < b + epsilon_) {
01044 return -1;
01045 }
01046
01047
01048
01049
01050 double * ratio= new double[nCols];
01051 memset(ratio, 0, (nCols*sizeof(double)));
01052
01053 int i;
01054 for (i=0; i<krow.getNumElements(); i++){
01055 if (fabs(krow.getElements()[i])> epsilon_ ){
01056 ratio[krow.getIndices()[i]]=
01057 (1.0-xstar[krow.getIndices()[i]]) / (krow.getElements()[i]);
01058 }
01059 else {
01060 ratio[krow.getIndices()[i]] = 0.0;
01061 }
01062 }
01063
01064
01065 CoinDecrSolutionOrdered dso(ratio);
01066 krow.sort(dso);
01067
01068
01069 int r = 0;
01070 double sum = krow.getElements()[0];
01071 while ( sum <= (elementSum - b - epsilon_ ) ){
01072 r++;
01073 sum += krow.getElements()[r];
01074 }
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094 int nCover;
01095
01096 double lpoofv=0.0;
01097 for (i=r+1; i<krow.getNumElements(); i++){
01098 lpoofv += (1-xstar[krow.getIndices()[i]]);
01099 }
01100 double ipofv = lpoofv + (1-xstar[krow.getIndices()[r]]);
01101
01102
01103 if (ipofv > 1.0 - epsilon_){
01104 delete [] ratio;
01105 return -1;
01106 }
01107 else {
01108
01109
01110 nCover = krow.getNumElements() - r;
01111 double coverSum =0.0;
01112 cover.reserve(nCover);
01113 remainder.reserve(r);
01114
01115 for (i=r; i<krow.getNumElements(); i++){
01116 cover.insert(krow.getIndices()[i],krow.getElements()[i]);
01117 coverSum += krow.getElements()[i];
01118 }
01119 for (i=0; i<r; i++){
01120 remainder.insert(krow.getIndices()[i],krow.getElements()[i]);
01121 }
01122
01123 #ifdef PRINT_DEBUG
01124 if (coverSum <= b){
01125 printf("The identified cover is NOT a cover\n");
01126 abort();
01127 }
01128 #endif
01129
01130
01131 cover.sortDecrElement();
01132
01133
01134
01135
01136
01137
01138 double oneLessCoverSum = coverSum - cover.getElements()[nCover-1];
01139 while (oneLessCoverSum > b){
01140
01141 remainder.insert(cover.getIndices()[nCover-1],
01142 cover.getElements()[nCover-1]);
01143 cover.truncate(nCover-1);
01144 nCover--;
01145 oneLessCoverSum -= cover.getElements()[nCover-1];
01146 }
01147
01148 if (nCover<2){
01149 #ifdef PRINT_DEBUG
01150 printf("nCover < 2...aborting\n");
01151 #endif
01152 abort();
01153 }
01154
01155 #ifdef PRINT_DEBUG
01156 printf("\
01157 Lp relax of most violated minimal cover: row %i has cover of size %i.\n",
01158 row,nCover);
01159
01160 for (i=0; i<cover.getNumElements(); i++){
01161 printf("index %i, element %g, xstar value % g \n",
01162 cover.getIndices()[i],cover.getElements()[i],
01163 xstar[cover.getIndices()[i]]);
01164
01165 }
01166 printf("The b = %g, and the cover sum is %g\n\n", b, cover.sum());
01167 #endif
01168
01169 #ifdef P0201
01170 double ppsum=0.0;
01171 for (i=0; i<nCover; i++){
01172 ppsum += p0201[krow.getIndices()[i]];
01173 }
01174
01175 if (ppsum > nCover-1){
01176 printf("\
01177 \nBad cover from lp relax of most violated cover..aborting\n");
01178 abort();
01179 }
01180 #endif
01181
01182
01183 delete [] ratio;
01184 return 1;
01185 }
01186 }
01187
01188
01189
01190
01191
01192
01193
01194
01195 int
01196 CglKnapsackCover::findExactMostViolatedMinCover(
01197 int nCols,
01198 int row,
01199 CoinPackedVector & krow,
01200 double b,
01201 double * xstar,
01202 CoinPackedVector & cover,
01203 CoinPackedVector & remainder) const
01204 {
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234 double elementSum = krow.sum();
01235
01236
01237
01238 if (elementSum < b + epsilon_) {
01239 #ifdef PRINT_DEBUG
01240 printf("Redundant/useless adjusted row\n");
01241 #endif
01242 return -1;
01243 }
01244
01245
01246
01247
01248 double * ratio= new double[nCols];
01249 memset(ratio, 0, (nCols*sizeof(double)));
01250
01251 int i;
01252 {
01253 const int * indices = krow.getIndices();
01254 const double * elements = krow.getElements();
01255 for (i=0; i<krow.getNumElements(); i++){
01256 if (fabs(elements[i])> epsilon_ ){
01257 ratio[indices[i]]= (1.0-xstar[indices[i]]) / elements[i];
01258 }
01259 else {
01260 ratio[indices[i]] = 0.0;
01261 }
01262 }
01263 }
01264
01265
01266 CoinDecrSolutionOrdered dso(ratio);
01267 krow.sort(dso);
01268
01269 #ifdef CGL_DEBUG
01270
01271 for ( i=1; i<krow.getNumElements(); i++ ) {
01272 double ratioim1 = ratio[krow.getIndices()[i-1]];
01273 double ratioi= ratio[krow.getIndices()[i]];
01274 assert( ratioim1 >= ratioi );
01275 }
01276 #endif
01277
01278
01279
01280
01281
01282
01283 double objConst = 0.0;
01284 double exactOptVal = -1.0;
01285 int * exactOptSol = new int[krow.getNumElements()];
01286 double * p = new double[krow.getNumElements()];
01287 double * w = new double[krow.getNumElements()];
01288 int kk;
01289 for (kk=0; kk<krow.getNumElements(); kk++){
01290 p[kk]=1.0-xstar[krow.getIndices()[kk]];
01291 w[kk]=krow.getElements()[kk];
01292 objConst+=p[kk];
01293 }
01294
01295
01296 exactSolveKnapsack(krow.getNumElements(), (elementSum-b-epsilon_), p, w,
01297 exactOptVal, exactOptSol);
01298
01299 if(objConst-exactOptVal < 1){
01300 cover.reserve(krow.getNumElements());
01301 remainder.reserve(krow.getNumElements());
01302
01303
01304
01305 double coverElementSum = 0;
01306 for(kk=0;kk<krow.getNumElements();kk++){
01307 if(exactOptSol[kk]==0){
01308 cover.insert(krow.getIndices()[kk],krow.getElements()[kk]);
01309 coverElementSum += krow.getElements()[kk];
01310 }
01311 else {
01312 remainder.insert(krow.getIndices()[kk],krow.getElements()[kk]);
01313 }
01314 }
01315
01316 cover.sortDecrElement();
01317
01318
01319
01320
01321
01322 double oneLessCoverElementSum =
01323 coverElementSum - cover.getElements()[cover.getNumElements()-1];
01324 while (oneLessCoverElementSum > b){
01325
01326 remainder.insert(cover.getIndices()[cover.getNumElements()-1],
01327 cover.getElements()[cover.getNumElements()-1]);
01328 cover.truncate(cover.getNumElements()-1);
01329 oneLessCoverElementSum -= cover.getElements()[cover.getNumElements()-1];
01330 }
01331
01332 #ifdef PRINT_DEBUG
01333 printf("Exact Most Violated Cover: row %i has cover of size %i.\n",
01334 row,cover.getNumElements());
01335
01336 for (i=0; i<cover.getNumElements(); i++){
01337 printf("index %i, element %g, xstar value % g \n",
01338 cover.getIndices()[i], cover.getElements()[i],
01339 xstar[cover.getIndices()[i]]);
01340
01341 }
01342 printf("The b = %g, and the cover sum is %g\n\n", b, cover.sum() );
01343 #endif
01344
01345
01346 delete [] exactOptSol;
01347 delete [] p;
01348 delete [] w;
01349 delete [] ratio;
01350
01351 return 1;
01352 }
01353
01354
01355 delete [] exactOptSol;
01356 delete [] p;
01357 delete [] w;
01358 delete [] ratio;
01359
01360 return 0;
01361
01362 }
01363
01364
01365
01366
01367
01368
01369 int
01370 CglKnapsackCover::findPseudoJohnAndEllisCover(
01371 int row,
01372 CoinPackedVector & krow,
01373 double & b,
01374 double * xstar,
01375 CoinPackedVector & cover,
01376 CoinPackedVector & remainder) const
01377
01378 {
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420 cover.reserve(krow.getNumElements());
01421 remainder.reserve(krow.getNumElements());
01422
01423 double unsatRhs = b;
01424
01425
01426 CoinPackedVector unsat;
01427 unsat.reserve(krow.getNumElements());
01428
01429
01430 CoinPackedVector atOne;
01431 atOne.reserve(krow.getNumElements());
01432
01433
01434
01435
01436
01437
01438
01439 int i;
01440 for (i=0; i<krow.getNumElements(); i++){
01441
01442 if (xstar[krow.getIndices()[i]] > onetol_){
01443 atOne.insert(krow.getIndices()[i],krow.getElements()[i]);
01444 unsatRhs -= krow.getElements()[i];
01445 }
01446 else if (xstar[krow.getIndices()[i]] >= epsilon_){
01447 unsat.insert(krow.getIndices()[i],krow.getElements()[i]) ;
01448 }
01449 else {
01450 remainder.insert(krow.getIndices()[i],krow.getElements()[i]);
01451 }
01452 }
01453
01454
01455 CoinDecrSolutionOrdered decrSol(xstar);
01456 unsat.sort(decrSol);
01457
01458 #ifdef CGL_DEBUG
01459
01460 for (i=1; i<unsat.getNumElements(); i++){
01461 double xstarim1= xstar[unsat.getIndices()[i-1]];
01462 double xstari= xstar[unsat.getIndices()[i]];
01463 assert( xstarim1 >= xstari );
01464 }
01465 #endif
01466
01467
01468 double bigCoef= 0.0;
01469
01470 int bigIndex = 0;
01471 for (i=0; i<unsat.getNumElements(); i++){
01472 if (unsat.getElements()[i]>bigCoef){
01473 bigCoef = unsat.getElements()[i];
01474 bigIndex = i;
01475 }
01476 }
01477
01478
01479 i=0;
01480 double margin = unsatRhs;
01481 int gotCover=0;
01482 int j;
01483
01484
01485
01486 while (i<unsat.getNumElements() && !gotCover){
01487 margin -= unsat.getElements()[i];
01488
01489
01490 if (i == bigIndex){
01491 bigCoef = 0.0;
01492 bigIndex = 0;
01493 for (j=i+1; j<unsat.getNumElements(); j++){
01494 double temp = unsat.getElements()[j];
01495 if (temp > bigCoef ){
01496 bigCoef = temp;
01497 bigIndex = j;
01498 }
01499 }
01500 }
01501
01502 if (bigCoef > margin+epsilon2_) gotCover = 1;
01503 i++;
01504 }
01505
01506
01507 if(gotCover){
01508 j=i;
01509 if (j<unsat.getNumElements()){
01510 while (unsat.getElements()[j]< margin) {
01511 j++;
01512 }
01513
01514 unsat.swap(i,j);
01515 i++;
01516 }
01517
01518
01519
01520 int nCover = i;
01521 double coverElementSum = 0.0;
01522 double coverXstarSum = 0.0;
01523 int k;
01524 for (k=0; k<nCover; k++){
01525 coverElementSum += unsat.getElements()[k];
01526 coverXstarSum += xstar[unsat.getIndices()[k]];
01527 }
01528
01529
01530
01531
01532
01533
01534 if (coverXstarSum > (nCover-1) && coverElementSum > unsatRhs+epsilon2_){
01535 for (i=nCover; i<unsat.getNumElements(); i++) {
01536 remainder.insert(unsat.getIndices()[i],unsat.getElements()[i]);
01537 }
01538 unsat.truncate(nCover);
01539 cover = unsat;
01540 cover.append(atOne);
01541
01542 for (k=nCover; k<cover.getNumElements(); k++){
01543 coverElementSum+=cover.getElements()[k];
01544 coverXstarSum+=xstar[cover.getIndices()[k]];
01545 }
01546
01547
01548 int size = cover.getNumElements() + remainder.getNumElements();
01549 int krowsize = krow.getNumElements();
01550 assert( size == krowsize );
01551
01552