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 <cfloat>
00011 #include <iostream>
00012
00013 #include "CoinHelperFunctions.hpp"
00014 #include "CoinPackedVector.hpp"
00015 #include "CoinPackedMatrix.hpp"
00016 #include "OsiRowCutDebugger.hpp"
00017 #include "CglOddHole.hpp"
00018
00019
00020 typedef struct {double dj;double element; int sequence;}
00021 double_double_int_triple;
00022 class double_double_int_triple_compare {
00023 public:
00024 bool operator() (double_double_int_triple x , double_double_int_triple y) const
00025 {
00026 return ( x.dj < y.dj);
00027 }
00028 };
00029
00030
00031
00032 void CglOddHole::generateCuts(const OsiSolverInterface & si,
00033 OsiCuts & cs ) const
00034 {
00035
00036 int nRows=si.getNumRows();
00037 int nCols=si.getNumCols();
00038
00039 const CoinPackedMatrix * rowCopy = si.getMatrixByRow();
00040
00041
00042
00043
00044
00045
00046
00047 CglOddHole temp;
00048 int * checkRow = new int[nRows];
00049 int i;
00050 if (!suitableRows_) {
00051 for (i=0;i<nRows;i++) {
00052 checkRow[i]=1;
00053 }
00054 } else {
00055
00056 memset(checkRow,0,nRows*sizeof(int));
00057 memcpy(checkRow,suitableRows_,CoinMin(nRows,numberRows_)*sizeof(int));
00058 }
00059 temp.createRowList(si,checkRow);
00060
00061 double * solution = new double[nCols];
00062 memcpy(solution,si.getColSolution(),nCols*sizeof(double));
00063 const int * column = rowCopy->getIndices();
00064 const int * rowStart = rowCopy->getVectorStarts();
00065 const int * rowLength = rowCopy->getVectorLengths();
00066 const double * collower = si.getColLower();
00067 const double * colupper = si.getColUpper();
00068 int * suitable = temp.suitableRows_;
00069
00070
00071 int * fixed = new int[nCols];
00072
00073 for (i=0;i<nCols;i++) {
00074 if (si.isBinary(i) ) {
00075 fixed[i]=0;
00076 if (colupper[i]-collower[i]<epsilon_) {
00077 solution[i]=0.0;
00078 fixed[i]=2;
00079 } else if (solution[i]<epsilon_) {
00080 solution[i]=0.0;
00081 fixed[i]=-1;
00082 } else if (solution[i]>onetol_) {
00083 solution[i]=1.0;
00084 fixed[i]=+1;
00085 }
00086 } else {
00087
00088 solution[i]=0.0;
00089 fixed[i]=3;
00090 }
00091 }
00092
00093 const double * rowlower = si.getRowLower();
00094 const double * rowupper = si.getRowUpper();
00095 for (i=0;i<nRows;i++) {
00096 if (suitable[i]) {
00097 int k;
00098 double sum=0.0;
00099 if (rowupper[i]>1.001) suitable[i]=-1;
00100 for (k=rowStart[i]; k<rowStart[i]+rowLength[i];k++) {
00101 int icol=column[k];
00102 if (!fixed[icol]) sum += solution[icol];
00103 }
00104 if (sum<0.9) suitable[i]=-1;
00105 }
00106 }
00107 #ifdef CGL_DEBUG
00108 const OsiRowCutDebugger * debugger = si.getRowCutDebugger();
00109 if (debugger&&!debugger->onOptimalPath(si))
00110 debugger = NULL;
00111 #else
00112 const OsiRowCutDebugger * debugger = NULL;
00113 #endif
00114 temp.generateCuts(debugger, *rowCopy,solution,
00115 si.getReducedCost(),cs,suitable,fixed,true);
00116
00117
00118 bool doCover=false;
00119 int nsuitable=0;
00120 for (i=0;i<nRows;i++) {
00121 suitable[i]=abs(suitable[i]);
00122 if (suitable[i]) {
00123 int k;
00124 double sum=0.0;
00125 if (rowlower[i]<0.999) sum=2.0;
00126 if (rowupper[i]>1.001) doCover=true;
00127 for (k=rowStart[i]; k<rowStart[i]+rowLength[i];k++) {
00128 int icol=column[k];
00129 if (!fixed[icol]) sum += solution[icol];
00130 if (fixed[icol]==1) sum=2.0;
00131 }
00132 if (sum>1.1) {
00133 suitable[i]=-1;
00134 } else {
00135 nsuitable++;
00136 }
00137 }
00138 }
00139 if (doCover&&nsuitable)
00140 temp.generateCuts(debugger, *rowCopy,solution,si.getReducedCost(),
00141 cs,suitable,fixed,false);
00142 delete [] checkRow;
00143 delete [] solution;
00144 delete [] fixed;
00145
00146 }
00147 void CglOddHole::generateCuts(const OsiRowCutDebugger * debugger,
00148 const CoinPackedMatrix & rowCopy,
00149 const double * solution,
00150 const double * dj, OsiCuts & cs,
00151 const int * suitableRow,
00152 const int * fixedColumn,
00153 bool packed)
00154 {
00155 CoinPackedMatrix columnCopy = rowCopy;
00156 columnCopy.reverseOrdering();
00157
00158
00159 int nRows=columnCopy.getNumRows();
00160 int nCols=columnCopy.getNumCols();
00161
00162 const int * column = rowCopy.getIndices();
00163 const int * rowStart = rowCopy.getVectorStarts();
00164 const int * rowLength = rowCopy.getVectorLengths();
00165
00166 const int * row = columnCopy.getIndices();
00167 const int * columnStart = columnCopy.getVectorStarts();
00168 const int * columnLength = columnCopy.getVectorLengths();
00169
00170
00171
00172 int * mrow = new int[nRows];
00173
00174 int * lookup = new int[nCols];
00175
00176 int nSmall=0;
00177 int i;
00178
00179 int n=0;
00180 for (i=0;i<nRows;i++) {
00181 if (suitableRow[i]>0) {
00182 mrow[i]=n++;
00183 } else {
00184 mrow[i]=-1;
00185 }
00186 }
00187 for (i=0;i<nCols;i++) {
00188 if (!fixedColumn[i]) {
00189 lookup[i]=nSmall++;
00190 } else {
00191 lookup[i]=-1;
00192 }
00193 }
00194 int nSmall2=2*nSmall;
00195
00196 #define MAXELS 50000
00197 int maxels=MAXELS;
00198
00199
00200 double * cost = (double *) malloc(maxels*sizeof(double));
00201
00202 int * to= (int *) malloc(maxels*sizeof(int));
00203
00204 int * rowfound=(int *) malloc(maxels*sizeof(int));
00205
00206 int * starts=new int[2*nSmall+1];
00207 starts[0]=0;
00208
00209 int * mark =new int[nSmall2];
00210 memset(mark,0,nSmall2*sizeof(int));
00211 n=0;
00212 for (i=0;i<nCols;i++) {
00213 int icol=lookup[i];
00214 if (icol>=0) {
00215
00216 int k;
00217 double dd=1.0000001-solution[i];
00218 mark[icol]=1;
00219
00220 if (n+nCols>maxels) {
00221 maxels*=2;
00222 cost=(double *) realloc(cost,maxels*sizeof(int));
00223 to=(int *) realloc(to,maxels*sizeof(int));
00224 rowfound=(int *) realloc(rowfound,maxels*sizeof(int));
00225 }
00226
00227 for (k=columnStart[i];k<columnStart[i]+columnLength[i];k++) {
00228 int irow=row[k];
00229 int jrow=mrow[irow];
00230
00231 if (jrow>=0) {
00232 int j;
00233 for (j=rowStart[irow];j<rowStart[irow]+rowLength[irow];j++) {
00234 int jcol=column[j];
00235 int kcol=lookup[jcol];
00236 if (kcol>=0&&!mark[kcol]) {
00237 cost[n]=dd-solution[jcol];
00238 to[n]=kcol;
00239 rowfound[n++]=irow;
00240 mark[kcol]=1;
00241 }
00242 }
00243 }
00244 }
00245 starts[icol+1]=n;
00246
00247 mark[icol]=0;
00248 for (k=starts[icol];k<starts[icol+1];k++) {
00249 int ito=to[k];
00250 if (ito<0||ito>=nSmall) abort();
00251 mark[to[k]]=0;
00252 }
00253 }
00254 }
00255
00256 if (packed) {
00257 for (i=0;i<n;i++) {
00258 if (cost[i]<1.0e-10) {
00259 cost[i]=1.0e-10;
00260 }
00261 }
00262 } else {
00263 for (i=0;i<n;i++) {
00264 cost[i]=-cost[i];
00265 if (cost[i]<1.0e-10) {
00266 cost[i]=1.0e-10;
00267 }
00268 }
00269 }
00270
00271
00272 if (2*n>maxels) {
00273 maxels=2*n;
00274 cost=(double *) realloc(cost,maxels*sizeof(int));
00275 to=(int *) realloc(to,maxels*sizeof(int));
00276 rowfound=(int *) realloc(rowfound,maxels*sizeof(int));
00277 }
00278
00279
00280 for (i=0;i<nSmall;i++) {
00281 int k,j=i+nSmall;
00282 for (k=starts[i];k<starts[i+1];k++) {
00283 int ito=to[k];
00284 to[n]=ito;
00285 to[k]=ito+nSmall;
00286 cost[n]=cost[k];
00287 rowfound[n++]=rowfound[k];;
00288 }
00289 starts[j+1]=n;
00290 }
00291
00292 double * check = new double[nCols];
00293 CoinSeedRandom(13579);
00294 for (i=0;i<nCols;i++) {
00295 check[i]=CoinDrand48();
00296 }
00297
00298
00299
00300 typedef struct {
00301 double cost;
00302 int back;
00303 } Path;
00304 typedef struct {
00305 double cost;
00306 int node;
00307 } Item;
00308 Item * stack = new Item [nSmall2];
00309 Path * path = new Path [nSmall2];
00310
00311
00312
00313 int ncuts=0;
00314 int maxcuts=1000;
00315 double * hash = (double *) malloc(maxcuts*sizeof(double));
00316
00317 int * clean = new int[nSmall2];
00318 int * candidate = new int[CoinMax(nSmall2,nCols)];
00319 double * element = new double[nCols];
00320
00321 double_double_int_triple * sortit =
00322 new double_double_int_triple [nCols];
00323 memset(mark,0,nSmall2*sizeof(int));
00324 int * countcol = new int[nCols];
00325 memset(countcol,0,nCols*sizeof(int));
00326 int bias = packed ? 0 : 1;
00327
00328
00329 int icol;
00330 for (icol=0;icol<nSmall;icol++) {
00331 int j;
00332 int jcol=icol+nSmall;
00333 int istack=1;
00334 for (j=0;j<nSmall2;j++) {
00335 path[j].cost=1.0e70;
00336 path[j].back=nSmall2+1;
00337 }
00338 path[icol].cost=0.0;
00339 path[icol].back=-1;
00340 stack[0].cost=0.0;
00341 stack[0].node=icol;
00342 mark[icol]=1;
00343 while(istack) {
00344 Item thisItem=stack[--istack];
00345 double thisCost=thisItem.cost;
00346 int inode=thisItem.node;
00347 int k;
00348 mark[inode]=0;
00349
00350
00351 for (k=starts[inode];k<starts[inode+1];k++) {
00352 int jnode=to[k];
00353 if (!mark[jnode]&&thisCost+cost[k]<path[jnode].cost-1.0e-12) {
00354 path[jnode].cost=thisCost+cost[k];
00355 path[jnode].back=inode;
00356
00357 stack[istack].cost=path[jnode].cost;
00358 stack[istack++].node=jnode;
00359 mark[jnode]=1;
00360 #ifdef CGL_DEBUG
00361 assert (istack<=nSmall2);
00362 #endif
00363 }
00364 }
00365 }
00366 bool good=(path[jcol].cost<0.9999);
00367
00368 if (good) {
00369 int ii;
00370 int nrow2=0;
00371 int nclean=0;
00372 double sum=0;
00373 #ifdef CGL_DEBUG
00374 printf("** %d ",jcol-nSmall);
00375 #endif
00376 ii=1;
00377 candidate[0]=jcol;
00378 while(jcol!=icol) {
00379 int jjcol;
00380 jcol=path[jcol].back;
00381 if (jcol>=nSmall) {
00382 jjcol=jcol-nSmall;
00383 } else {
00384 jjcol=jcol;
00385 }
00386 #ifdef CGL_DEBUG
00387 printf(" %d",jjcol);
00388 #endif
00389 if (mark[jjcol]) {
00390
00391
00392
00393
00394 } else {
00395 mark[jjcol]=1;
00396 clean[nclean++]=jjcol;
00397 candidate[ii++]=jcol;
00398 #ifdef CGL_DEBUG
00399 assert (ii<=nSmall2);
00400 #endif
00401 }
00402 }
00403 #ifdef CGL_DEBUG
00404 printf("\n");
00405 #endif
00406 for (j=0;j<nclean;j++) {
00407 int k=clean[j];
00408 mark[k]=0;
00409 }
00410 if (good) {
00411 int k;
00412 for (k=ii-1;k>0;k--) {
00413 int jk,kk=candidate[k];
00414 int ix=0;
00415 for (jk=starts[kk];jk<starts[kk+1];jk++) {
00416 int ito=to[jk];
00417 if (ito==candidate[k-1]) {
00418 ix=1;
00419
00420 mrow[nrow2++]=rowfound[jk];
00421 break;
00422 }
00423 }
00424 if (!ix) {
00425 good=false;
00426 }
00427 }
00428 if ((nrow2&1)!=1) {
00429 good=false;
00430 }
00431 if (good) {
00432 int nincut=0;
00433 for (k=0;k<nrow2;k++) {
00434 int j,irow=mrow[k];
00435 for (j=rowStart[irow];j<rowStart[irow]+rowLength[irow];j++) {
00436 int icol=column[j];
00437 if (!countcol[icol]) candidate[nincut++]=icol;
00438 countcol[icol]++;
00439 }
00440 }
00441 #ifdef CGL_DEBUG
00442 printf("true constraint %d",nrow2);
00443 #endif
00444 nrow2=nrow2>>1;
00445 double rhs=nrow2;
00446 if (!packed) rhs++;
00447 ii=0;
00448 for (k=0;k<nincut;k++) {
00449 int jcol=candidate[k];
00450 if (countcol[jcol]) {
00451 #ifdef CGL_DEBUG
00452 printf(" %d %d",jcol,countcol[jcol]);
00453 #endif
00454 int ihalf=(countcol[jcol]+bias)>>1;
00455 if (ihalf) {
00456 element[ii]=ihalf;
00457 sum+=solution[jcol]*element[ii];
00458
00459 candidate[ii++]=jcol;
00460 }
00461 countcol[jcol]=0;
00462 }
00463 }
00464 #ifdef CGL_DEBUG
00465 printf("\n");
00466 #endif
00467 OsiRowCut rc;
00468 double violation=0.0;
00469 if (packed) {
00470 violation = sum-rhs;
00471 rc.setLb(-DBL_MAX);
00472 rc.setUb(rhs);
00473 } else {
00474
00475 violation = rhs-sum;
00476 rc.setUb(DBL_MAX);
00477 rc.setLb(rhs);
00478 }
00479 if (violation<minimumViolation_) {
00480 #ifdef CGL_DEBUG
00481 printf("why no cut\n");
00482 #endif
00483 good=false;
00484 } else {
00485 if (((double) ii) * minimumViolationPer_>violation||
00486 ii>maximumEntries_) {
00487 #ifdef CGL_DEBUG
00488 printf("why no cut\n");
00489 #endif
00490 if (packed) {
00491
00492
00493 nincut=ii;
00494 for (k=0;k<nincut;k++) {
00495 int jcol=candidate[k];
00496 double value = fabs(dj[jcol]);
00497 if (solution[jcol])
00498 value = -solution[jcol];
00499 sortit[k].dj=value;
00500 sortit[k].element=element[k];
00501 sortit[k].sequence=jcol;
00502 }
00503
00504 std::sort(sortit,sortit+nincut,double_double_int_triple_compare());
00505 nincut = min(nincut,maximumEntries_);
00506 sum=0.0;
00507 for (k=0;k<nincut;k++) {
00508 int jcol=sortit[k].sequence;
00509 candidate[k]=jcol;
00510 element[k]=sortit[k].element;
00511 sum+=solution[jcol]*element[k];
00512 }
00513 violation = sum-rhs;
00514 ii=nincut;
00515 if (violation<minimumViolation_) {
00516 good=false;
00517 }
00518 } else {
00519 good=false;
00520 }
00521 }
00522 }
00523 if (good) {
00524
00525 int j;
00526 #if 0
00527 double value=0.0;
00528 for (j=0;j<ii;j++) {
00529 int icol=candidate[j];
00530 value += check[icol]*element[j];
00531 }
00532 #else
00533 CoinPackedVector candidatePv(ii,candidate,element);
00534 candidatePv.sortIncrIndex();
00535 double value = candidatePv.dotProduct(check);
00536 #endif
00537
00538 for (j=0;j<ncuts;j++) {
00539 if (value==hash[j]) {
00540
00541 break;
00542 }
00543 }
00544 if (j==ncuts) {
00545
00546 if (ncuts==maxcuts) {
00547 maxcuts *= 2;
00548 hash = (double *) realloc(hash,maxcuts*sizeof(double));
00549 }
00550 hash[ncuts++]=value;
00551 rc.setRow(ii,candidate,element);
00552 #ifdef CGL_DEBUG
00553 printf("sum %g rhs %g %d\n",sum,rhs,ii);
00554 if (debugger)
00555 assert(!debugger->invalidCut(rc));
00556 #endif
00557 cs.insert(rc);
00558 }
00559 }
00560 }
00561
00562 }
00563 }
00564 }
00565 delete [] countcol;
00566 delete [] element;
00567 delete [] candidate;
00568 delete [] sortit;
00569 delete [] clean;
00570 delete [] path;
00571 delete [] stack;
00572 free(hash);
00573 delete [] check;
00574 delete [] mark;
00575 delete [] starts;
00576 delete [] lookup;
00577 delete [] mrow;
00578 free(rowfound);
00579 free(to);
00580 free(cost);
00581 }
00582
00583
00584
00585 void CglOddHole::createRowList( const OsiSolverInterface & si,
00586 const int * possible)
00587 {
00588
00589 int nRows=si.getNumRows();
00590
00591 const CoinPackedMatrix * rowCopy = si.getMatrixByRow();
00592
00593 const int * column = rowCopy->getIndices();
00594 const int * rowStart = rowCopy->getVectorStarts();
00595 const int * rowLength = rowCopy->getVectorLengths();
00596
00597 int rowIndex;
00598 delete [] suitableRows_;
00599 numberRows_=nRows;
00600
00601 const double * rowElements = rowCopy->getElements();
00602 const double * rowupper = si.getRowUpper();
00603 const double * rowlower = si.getRowLower();
00604 const double * collower = si.getColLower();
00605 const double * colupper = si.getColUpper();
00606
00607 suitableRows_=new int[nRows];
00608 if (possible) {
00609 memcpy(suitableRows_,possible,nRows*sizeof(int));
00610 } else {
00611 int i;
00612 for (i=0;i<nRows;i++) {
00613 suitableRows_[i]=1;
00614 }
00615 }
00616 for (rowIndex=0; rowIndex<nRows; rowIndex++){
00617 double rhs1=rowupper[rowIndex];
00618 double rhs2=rowlower[rowIndex];
00619 if (suitableRows_[rowIndex]) {
00620 int i;
00621 bool goodRow=true;
00622 for (i=rowStart[rowIndex];
00623 i<rowStart[rowIndex]+rowLength[rowIndex];i++) {
00624 int thisCol=column[i];
00625 if (colupper[thisCol]-collower[thisCol]>epsilon_) {
00626
00627 if (!si.isBinary(thisCol) ) {
00628 goodRow=false;
00629 break;
00630 }
00631 if (fabs(rowElements[i]-1.0)>epsilon_) {
00632 goodRow=false;
00633 break;
00634 }
00635 } else {
00636 rhs1 -= collower[thisCol]*rowElements[i];
00637 rhs2 -= collower[thisCol]*rowElements[i];
00638 }
00639 }
00640 if (fabs(rhs1-1.0)>epsilon_&&fabs(rhs2-1.0)>epsilon_) {
00641 goodRow=false;
00642 }
00643 if (goodRow) {
00644 suitableRows_[rowIndex]=1;
00645 } else {
00646 suitableRows_[rowIndex]=0;
00647 }
00648 }
00649 }
00650 }
00652 void CglOddHole::createRowList(int numberRows, const int * whichRow)
00653 {
00654 suitableRows_=new int [numberRows];
00655 numberRows_=numberRows;
00656 memcpy(suitableRows_,whichRow,numberRows*sizeof(int));
00657 }
00658
00659
00660
00661 void CglOddHole::createCliqueList(int numberCliques, const int * cliqueStart,
00662 const int * cliqueMember)
00663 {
00664 numberCliques_=numberCliques;
00665 startClique_=new int[numberCliques_+1];
00666 memcpy(startClique_,cliqueStart,(numberCliques_+1)*sizeof(int));
00667 int length=startClique_[numberCliques_];
00668 member_=new int[length];
00669 memcpy(member_,cliqueMember,length*sizeof(int));
00670 }
00671
00672 int CglOddHole::numberPossible()
00673 {
00674 int i,n=0;
00675 for (i=0;i<numberRows_;i++) {
00676 if (suitableRows_[i]) n++;
00677 }
00678 return n;
00679 }
00680
00681
00682
00683
00684
00685 CglOddHole::CglOddHole ()
00686 :
00687 CglCutGenerator(),
00688 epsilon_(1.0e-08),
00689 onetol_(1-epsilon_)
00690 {
00691
00692 numberRows_=0;
00693 suitableRows_=NULL;
00694 startClique_=NULL;
00695 numberCliques_=0;
00696 member_=NULL;
00697 minimumViolation_=0.001;
00698 minimumViolationPer_=0.0003;
00699 maximumEntries_=100;
00700 }
00701
00702
00703
00704
00705 CglOddHole::CglOddHole (
00706 const CglOddHole & source)
00707 :
00708 CglCutGenerator(source),
00709 epsilon_(source.epsilon_),
00710 onetol_(source.onetol_)
00711 {
00712
00713 numberRows_=source.numberRows_;
00714 suitableRows_=new int[numberRows_];
00715 memcpy(suitableRows_,source.suitableRows_,numberRows_*sizeof(int));
00716
00717 numberCliques_=source.numberCliques_;
00718 if (numberCliques_) {
00719 startClique_=new int[numberCliques_+1];
00720 memcpy(startClique_,source.startClique_,(numberCliques_+1)*sizeof(int));
00721 int length=startClique_[numberCliques_];
00722 member_=new int[length];
00723 memcpy(member_,source.member_,length*sizeof(int));
00724 } else {
00725 startClique_=NULL;
00726 member_=NULL;
00727 }
00728 minimumViolation_=source.minimumViolation_;
00729 minimumViolationPer_=source.minimumViolationPer_;
00730 maximumEntries_=source.maximumEntries_;
00731 }
00732
00733
00734
00735
00736 CglOddHole::~CglOddHole ()
00737 {
00738
00739 delete [] suitableRows_;
00740 delete [] startClique_;
00741 delete [] member_;
00742 }
00743
00744
00745
00746
00747 CglOddHole &
00748 CglOddHole::operator=(
00749 const CglOddHole& rhs)
00750 {
00751 if (this != &rhs) {
00752 CglCutGenerator::operator=(rhs);
00753 epsilon_=rhs.epsilon_;
00754 onetol_=rhs.onetol_;
00755 delete [] suitableRows_;
00756
00757 numberRows_=rhs.numberRows_;
00758 suitableRows_=new int[numberRows_];
00759 memcpy(suitableRows_,rhs.suitableRows_,numberRows_*sizeof(int));
00760 delete [] startClique_;
00761 delete [] member_;
00762
00763 numberCliques_=rhs.numberCliques_;
00764 if (numberCliques_) {
00765 startClique_=new int[numberCliques_+1];
00766 memcpy(startClique_,rhs.startClique_,(numberCliques_+1)*sizeof(int));
00767 int length=startClique_[numberCliques_];
00768 member_=new int[length];
00769 memcpy(member_,rhs.member_,length*sizeof(int));
00770 } else {
00771 startClique_=NULL;
00772 member_=NULL;
00773 }
00774 minimumViolation_=rhs.minimumViolation_;
00775 minimumViolationPer_=rhs.minimumViolationPer_;
00776 maximumEntries_=rhs.maximumEntries_;
00777 }
00778 return *this;
00779 }
00780
00781 double
00782 CglOddHole::getMinimumViolation() const
00783 {
00784 return minimumViolation_;
00785 }
00786 void
00787 CglOddHole::setMinimumViolation(double value)
00788 {
00789 if (value>1.0e-8&&value<=0.5)
00790 minimumViolation_=value;
00791 }
00792
00793 double
00794 CglOddHole::getMinimumViolationPer() const
00795 {
00796 return minimumViolationPer_;
00797 }
00798 void
00799 CglOddHole::setMinimumViolationPer(double value)
00800 {
00801 if (value>1.0e-8&&value<=0.25)
00802 minimumViolationPer_=value;
00803 }
00804
00805 int
00806 CglOddHole::getMaximumEntries() const
00807 {
00808 return maximumEntries_;
00809 }
00810 void
00811 CglOddHole::setMaximumEntries(int value)
00812 {
00813 if (value>2)
00814 maximumEntries_=value;
00815 }
00816
00817
00818 void
00819 CglOddHole::refreshSolver(OsiSolverInterface * solver)
00820 {
00821 }