//------------------------------------------------------------------- // Generate Stored cuts //------------------------------------------------------------------- void CglStored::generateCuts(const OsiSolverInterface & si, OsiCuts & cs, const CglTreeInfo /*info*/) const { // Get basic problem information const double * solution = si.getColSolution(); int numberRowCuts = cuts_.sizeRowCuts(); for (int i=0;i<numberRowCuts;i++) { const OsiRowCut * rowCutPointer = cuts_.rowCutPtr(i); double violation = rowCutPointer->violated(solution); if (violation>=requiredViolation_) cs.insert(*rowCutPointer); } if (probingInfo_) { int number01 = probingInfo_->numberIntegers(); const cliqueEntry * entry = probingInfo_->fixEntries(); const int * toZero = probingInfo_->toZero(); const int * toOne = probingInfo_->toOne(); const int * integerVariable = probingInfo_->integerVariable(); const double * lower = si.getColLower(); const double * upper = si.getColUpper(); OsiRowCut cut; int column[2]; double element[2]; for (int i=0;i<number01;i++) { int iColumn=integerVariable[i]; if (upper[iColumn]==lower[iColumn]) continue; double value1 = solution[iColumn]; for (int j=toZero[i];j<toOne[i];j++) { int jColumn=sequenceInCliqueEntry(entry[j]); if (jColumn<number01) { jColumn=integerVariable[jColumn]; assert (jColumn>=0); double value2 = solution[jColumn]; if (oneFixesInCliqueEntry(entry[j])) { double violation = 1.0-value1-value2; if (violation>requiredViolation_) { //printf("XXX can do %d + %d >=1\n",iColumn,jColumn); cut.setLb(1.0); cut.setUb(COIN_DBL_MAX); column[0]=iColumn; element[0]=1.0; column[1]=jColumn; element[1]= 1.0; cut.setEffectiveness(violation); cut.setRow(2,column,element,false); cs.insert(cut); } } else { double violation = value2-value1; if (violation>requiredViolation_) { //printf("XXX can do %d >= %d\n",iColumn,jColumn); cut.setLb(0.0); cut.setUb(COIN_DBL_MAX); column[0]=iColumn; element[0]=1.0; column[1]=jColumn; element[1]= -1.0; cut.setEffectiveness(violation); cut.setRow(2,column,element,false); cs.insert(cut); } } } else { jColumn -= number01; // not 0-1 double value2 = solution[jColumn]; double lowerValue = lower[jColumn]; double upperValue = upper[jColumn]; if (oneFixesInCliqueEntry(entry[j])) { double violation = upperValue-value1*(upperValue-lowerValue)-value2; if (violation>requiredViolation_) { //printf("XXX can do %g*%d + %d >=%g\n",(upperValue-lowerValue),iColumn,jColumn,upperValue); cut.setLb(upperValue); cut.setUb(COIN_DBL_MAX); column[0]=iColumn; element[0]=upperValue-lowerValue; column[1]=jColumn; element[1]= 1.0; cut.setEffectiveness(violation); cut.setRow(2,column,element,false); cs.insert(cut); } } else { double violation = value2-value1*(upperValue-lowerValue)-lowerValue; if (violation>requiredViolation_) { //printf("XXX can do %g*%d >= %d -%g\n",(upperValue-lowerValue),iColumn,jColumn,lowerValue); cut.setLb(-lowerValue); cut.setUb(COIN_DBL_MAX); column[0]=iColumn; element[0]=upperValue-lowerValue; column[1]=jColumn; element[1]= -1.0; cut.setEffectiveness(violation); cut.setRow(2,column,element,false); cs.insert(cut); } } } } for (int j=toOne[i];j<toZero[i+1];j++) { int jColumn=sequenceInCliqueEntry(entry[j]); if (jColumn<number01) { jColumn=integerVariable[jColumn]; assert (jColumn>=0); double value2 = solution[jColumn]; if (oneFixesInCliqueEntry(entry[j])) { double violation = value1-value2; if (violation>requiredViolation_) { //printf("XXX can do %d <= %d\n",iColumn,jColumn); cut.setLb(-COIN_DBL_MAX); cut.setUb(0.0); column[0]=iColumn; element[0]=1.0; column[1]=jColumn; element[1]= -1.0; cut.setEffectiveness(violation); cut.setRow(2,column,element,false); cs.insert(cut); } } else { double violation = value1+value2-1.0; if (violation>requiredViolation_) { //printf("XXX can do %d + %d <=1\n",iColumn,jColumn); cut.setLb(-COIN_DBL_MAX); cut.setUb(1.0); column[0]=iColumn; element[0]=1.0; column[1]=jColumn; element[1]= 1.0; cut.setEffectiveness(violation); cut.setRow(2,column,element,false); cs.insert(cut); } } } else { jColumn -= number01; // not 0-1 double value2 = solution[jColumn]; double lowerValue = lower[jColumn]; double upperValue = upper[jColumn]; if (oneFixesInCliqueEntry(entry[j])) { double violation = lowerValue +(upperValue-lowerValue)*value1-value2; if (violation>requiredViolation_) { //printf("XXX can do %g*%d <= %d -%g\n",(upperValue-lowerValue),iColumn,jColumn,lowerValue); cut.setLb(-COIN_DBL_MAX); cut.setUb(-lowerValue); column[0]=iColumn; element[0]=upperValue-lowerValue; column[1]=jColumn; element[1]= -1.0; cut.setEffectiveness(violation); cut.setRow(2,column,element,false); cs.insert(cut); } } else { double violation = (upperValue-lowerValue)*value1+value2-upperValue; if (violation>requiredViolation_) { //printf("XXX can do %g*%d + %d <=%g\n",(upperValue-lowerValue),iColumn,jColumn,upperValue); cut.setLb(-COIN_DBL_MAX); cut.setUb(upperValue); column[0]=iColumn; element[0]=upperValue-lowerValue; column[1]=jColumn; element[1]= 1.0; cut.setEffectiveness(violation); cut.setRow(2,column,element,false); cs.insert(cut); } } } } } } }
static int outDupsEtc(int numberIntegers, int & numberCliques, int & numberMatrixCliques, int * & cliqueStart, char * & cliqueType, CliqueEntry *& entry, int numberLastTime, int printit) { bool allNew=false; int * whichP = new int [numberIntegers]; int iClique; assert (sizeof(int)==4); assert (sizeof(CliqueEntry)==4); // If lots then get rid of short ones #define KEEP_CLIQUES 10000 if (numberCliques-numberMatrixCliques>KEEP_CLIQUES) { int * sort = new int [numberCliques]; for (iClique=numberMatrixCliques;iClique<numberCliques;iClique++) { int j = cliqueStart[iClique]; int n = cliqueStart[iClique+1]-j; sort[iClique]=n; } std::sort(sort+numberMatrixCliques,sort+numberCliques); int allow = sort[numberCliques-KEEP_CLIQUES]; int nEqual=0; for (iClique=numberCliques-KEEP_CLIQUES;iClique<numberCliques;iClique++) { if (sort[iClique]>allow) break; else nEqual++; } delete [] sort; int j=cliqueStart[numberMatrixCliques]; int put=j; int nClique=numberMatrixCliques; for (iClique=numberMatrixCliques;iClique<numberCliques;iClique++) { int end = cliqueStart[iClique+1]; int n = end-j; bool copy=false; if (n>allow) { copy=true; } else if (n==allow&&nEqual) { copy=true; nEqual--; } if (copy) { cliqueType[nClique++]=cliqueType[iClique]; for (;j<end;j++) entry[put++]=entry[j]; } j = cliqueStart[iClique+1]; cliqueStart[nClique]=put; } numberCliques = nClique; } // sort for (iClique=0;iClique<numberCliques;iClique++) { int j = cliqueStart[iClique]; int n = cliqueStart[iClique+1]-j; for (int i=0;i<n;i++) whichP[i]=sequenceInCliqueEntry(entry[i+j]); CoinSort_2(whichP,whichP+n,(reinterpret_cast<int *>(entry))+j); } // lexicographic sort int * which = new int [numberCliques]; int * position = new int [numberCliques]; int * sort = new int [numberCliques]; int * value = new int [numberCliques]; for (iClique=0;iClique<numberCliques;iClique++) { which[iClique]=iClique; sort[iClique]=sequenceInCliqueEntry(entry[cliqueStart[iClique]]); value[iClique]=sort[iClique]; position[iClique]=0; } CoinSort_2(sort,sort+numberCliques,which); int lastDone=-1; int nDup=0; int nSave=0; while (lastDone<numberCliques-1) { int jClique=lastDone+1; int jFirst = jClique; int iFirst = which[jFirst]; int iValue = value[iFirst]; int iPos = position[iFirst]; jClique++; for (;jClique<numberCliques;jClique++) { int kClique = which[jClique]; int jValue = value[kClique]; if (jValue>iValue||position[kClique]<iPos) break; } if (jClique==jFirst+1) { // done that bit lastDone++; } else { // use next bit to sort and then repeat int jLast=jClique; for (jClique=jFirst;jClique<jLast;jClique++) { int kClique = which[jClique]; int iValue = value[kClique]; // put at end if finished if (iValue<numberIntegers) { int kPos=position[kClique]+1; position[kClique]=kPos; kPos += cliqueStart[kClique]; if (kPos==cliqueStart[kClique+1]) { iValue = numberIntegers; } else { iValue = sequenceInCliqueEntry(entry[kPos]); } value[kClique]=iValue; } sort[jClique]=iValue; } CoinSort_2(sort+jFirst,sort+jLast,which+jFirst); // if duplicate mark and move on int iLowest=numberCliques; for (jClique=jFirst;jClique<jLast;jClique++) { int kClique = which [jClique]; int iValue = value[kClique]; if (iValue<numberIntegers) break; iLowest = CoinMin(iLowest,kClique); } if (jClique>jFirst) { // mark all apart from lowest number as duplicate and move on lastDone =jClique-1; for (jClique=jFirst;jClique<=lastDone;jClique++) { int kClique = which [jClique]; if (kClique!=iLowest) { value[kClique]=-2; nDup++; nSave += cliqueStart[kClique+1]-cliqueStart[kClique]; } } } } } if (printit) printf("%d duplicates\n",nDup); // Now see if any subset int nOut=0; for (int jClique=0;jClique<numberCliques;jClique++) { if (value[jClique]!=-2) { position[jClique]=cliqueStart[jClique]; value[jClique]=sequenceInCliqueEntry(entry[cliqueStart[jClique]]); } } nSave=0; int startLooking=0; for (int jClique=0;jClique<numberCliques;jClique++) { int kClique = which[jClique]; if (value[kClique]==-2) { nOut++; nSave += cliqueStart[kClique+1]-cliqueStart[kClique]; if (jClique==startLooking) startLooking++; continue; } int kValue =value[kClique]; for (int iiClique=startLooking;iiClique<jClique;iiClique++) { int iClique = which[iiClique]; int iValue = value[iClique]; if (iValue==-2||iValue==numberIntegers) { if (iiClique==startLooking) startLooking++; continue; } else { if (kValue>static_cast<int> (sequenceInCliqueEntry(entry[cliqueStart[iClique+1]-1]))) { value[iClique]=numberIntegers; continue; } } if (iValue<kValue) { while (iValue<kValue) { int iPos=position[iClique]+1; position[iClique]=iPos; if (iPos==cliqueStart[iClique+1]) { iValue = numberIntegers; } else { iValue = sequenceInCliqueEntry(entry[iPos]); } value[iClique]=iValue; } } if (iValue>kValue) continue; // not a candidate // See if subset (remember duplicates have gone) if (cliqueStart[iClique+1]-position[iClique]> cliqueStart[kClique+1]-cliqueStart[kClique]) { // could be subset ? int offset = cliqueStart[iClique]-position[kClique]; int j; bool subset=true; // what about different fixes bool odd=false; for (j=cliqueStart[kClique]+1;j<cliqueStart[kClique+1];j++) { int kColumn = sequenceInCliqueEntry(entry[j]); int iColumn = sequenceInCliqueEntry(entry[j+offset]); if (iColumn>kColumn) { subset=false; } else { while (iColumn<kColumn) { offset++; if (j+offset<cliqueStart[iClique+1]) { iColumn = sequenceInCliqueEntry(entry[j+offset]); } else { subset=false; break; } } } if (!subset) break; } if (subset) { value[kClique]=-2; if (printit>1) printf("clique %d is subset of %d\n",kClique,iClique); nOut++; break; } } } } if (nOut) { if(printit) printf("Can get rid of %d cliques\n",nOut); // make new copy int nNewC=numberCliques-nOut; int size = cliqueStart[numberCliques]-nSave; int n=0; int * start = new int [nNewC+1]; char * type = new char [nNewC]; start[0]=0; CliqueEntry * entryC = new CliqueEntry [size]; int nel=0; allNew = true; for (int jClique=0;jClique<numberCliques;jClique++) { int kClique = which[jClique]; if (value[kClique]!=-2&&kClique<numberMatrixCliques) { if (kClique>=numberLastTime) allNew=false; int nn=cliqueStart[kClique+1]-cliqueStart[kClique]; memcpy(entryC+nel,entry+cliqueStart[kClique],nn*sizeof(CliqueEntry)); nel += nn; type[n++]=cliqueType[kClique]; start[n]=nel; } } int nM=n; for (int jClique=0;jClique<numberCliques;jClique++) { int kClique = which[jClique]; if (value[kClique]!=-2&&kClique>=numberMatrixCliques) { if (kClique>=numberLastTime) allNew=false; int nn=cliqueStart[kClique+1]-cliqueStart[kClique]; memcpy(entryC+nel,entry+cliqueStart[kClique],nn*sizeof(CliqueEntry)); nel += nn; type[n++]=cliqueType[kClique]; start[n]=nel; } } // move numberCliques=n; numberMatrixCliques=nM; delete [] cliqueStart; cliqueStart=start; delete [] entry; entry = entryC; delete [] cliqueType; cliqueType = type; if (printit>1) { for (int jClique=0;jClique<numberCliques;jClique++) { printf("%d [ ",jClique); for (int i=cliqueStart[jClique];i<cliqueStart[jClique+1];i++) printf("%d(%d) ",sequenceInCliqueEntry(entry[i]),oneFixesInCliqueEntry(entry[i])); printf("]\n"); } } if (printit) printf("%d matrix cliques and %d found by probing\n",numberMatrixCliques,numberCliques-numberMatrixCliques); } delete [] value; delete [] sort; delete [] which; delete [] position; delete [] whichP; if (!allNew) return nOut; else return -1; }
OsiSolverInterface * CglTreeProbingInfo::analyze(const OsiSolverInterface & si,int createSolver, int numberExtraCliques,const int * starts, const CliqueEntry * entries,const char * type) { if (!createSolver) return NULL; convert(); if (!numberIntegers_) return NULL; bool alwaysDo=false; if (numberExtraCliques<0) { alwaysDo=true; numberExtraCliques=0; } bool printit=false; int numberCliques=0; int numberEntries=0; int * cliqueStart = NULL; CliqueEntry * entry = NULL; char * cliqueType=NULL; int * whichP = new int [numberIntegers_]; int * whichM = new int [numberIntegers_]; int *whichClique=NULL; int numberRows=si.getNumRows(); int numberMatrixCliques=0; const CoinPackedMatrix * rowCopy = si.getMatrixByRow(); assert(numberRows&&si.getNumCols()); int iRow; const int * column = rowCopy->getIndices(); const double * elementByRow = rowCopy->getElements(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); const int * rowLength = rowCopy->getVectorLengths(); const double * lower = si.getColLower(); const double * upper = si.getColUpper(); const double * rowLower = si.getRowLower(); const double * rowUpper = si.getRowUpper(); for (int iPass=0;iPass<2;iPass++) { if (iPass) { int numberExtraEntries=0; if (numberExtraCliques) numberExtraEntries = starts[numberExtraCliques]; cliqueStart = new int [numberCliques+1+numberExtraCliques]; cliqueStart[0]=0; entry = new CliqueEntry [numberEntries+numberExtraEntries]; cliqueType = new char [numberCliques+numberExtraCliques]; whichClique = new int [numberEntries+numberExtraEntries]; numberCliques=0; numberEntries=0; } #if 1 for (iRow=0;iRow<numberRows;iRow++) { int numberP1=0, numberM1=0; int numberTotal=0; CoinBigIndex j; double upperValue=rowUpper[iRow]; double lowerValue=rowLower[iRow]; bool good=true; for (j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) { int iColumn = column[j]; double value = elementByRow[j]; if (upper[iColumn]-lower[iColumn]<1.0e-8) { // fixed upperValue -= lower[iColumn]*value; lowerValue -= lower[iColumn]*value; continue; } else if (backward_[iColumn]<0) { good = false; break; } else { iColumn = backward_[iColumn]; numberTotal++; } if (fabs(value)!=1.0) { good=false; } else if (value>0.0) { assert (numberP1<numberIntegers_); whichP[numberP1++]=iColumn;; } else { assert (numberM1<numberIntegers_); whichM[numberM1++]=iColumn; } } int iUpper = static_cast<int> (floor(upperValue+1.0e-5)); int iLower = static_cast<int> (ceil(lowerValue-1.0e-5)); int state=0; if (upperValue<1.0e6) { if (iUpper==1-numberM1) state=1; else if (iUpper==-numberM1) state=2; else if (iUpper<-numberM1) state=3; if (fabs(static_cast<double> (iUpper)-upperValue)>1.0e-9) state =-1; } if (!state&&lowerValue>-1.0e6) { if (-iLower==1-numberP1) state=-1; else if (-iLower==-numberP1) state=-2; else if (-iLower<-numberP1) state=-3; if (fabs(static_cast<double> (iLower)-lowerValue)>1.0e-9) state =-1; } if (numberP1+numberM1<2) state=-1; if (good&&state>0) { if (abs(state)==3) { // infeasible printf("FFF Infeasible\n");; //feasible=false; break; } else if (abs(state)==2) { // we can fix all //numberFixed += numberP1+numberM1; printf("FFF can fix %d\n",numberP1+numberM1); } else { for (j=0;j<numberP1;j++) { int iColumn = whichP[j]; if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,true); setSequenceInCliqueEntry(temp,iColumn); entry[numberEntries]=temp; } numberEntries++; } for (j=0;j<numberM1;j++) { int iColumn = whichM[j]; if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,false); setSequenceInCliqueEntry(temp,iColumn); entry[numberEntries]=temp; } numberEntries++; } if (iPass) { if (iLower!=iUpper) { // slack cliqueType[numberCliques]='S'; } else { cliqueType[numberCliques]='E'; } cliqueStart[numberCliques+1]=numberEntries; } numberCliques++; } } } #endif if (numberExtraCliques) { int numberExtraEntries = starts[numberExtraCliques]; memcpy(entry+numberEntries,entries,numberExtraEntries*sizeof(CliqueEntry)); for (int iClique=0;iClique<numberExtraCliques;iClique++) { cliqueType[numberCliques] = type[iClique]; numberCliques++; cliqueStart[numberCliques]=starts[iClique]+numberEntries; } numberEntries += numberExtraEntries; } numberMatrixCliques=numberCliques; //int size = toZero_[numberIntegers_]; //char * used = new char [size]; //memset(used,0,size); // find two cliques int nFix=0; for (int iColumn=0;iColumn<static_cast<int> (numberIntegers_);iColumn++) { int j; for ( j=toZero_[iColumn];j<toOne_[iColumn];j++) { int jColumn=sequenceInCliqueEntry(fixEntry_[j]); // just look at ones beore (this also skips non 0-1) if (jColumn<iColumn) { int k; for ( k=toZero_[jColumn];k<toOne_[jColumn];k++) { if (sequenceInCliqueEntry(fixEntry_[k])== (iColumn)) { if (oneFixesInCliqueEntry(fixEntry_[j])) { if (oneFixesInCliqueEntry(fixEntry_[k])) { if (printit&&!iPass) printf("%d to zero implies %d to one and %d to zero implies %d to one\n", iColumn,jColumn,jColumn,iColumn); //0-0 illegal if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,false); setSequenceInCliqueEntry(temp,iColumn); entry[numberEntries]=temp; } numberEntries++; if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,false); setSequenceInCliqueEntry(temp,jColumn); entry[numberEntries]=temp; } numberEntries++; if (iPass) { // slack cliqueType[numberCliques]='S'; cliqueStart[numberCliques+1]=numberEntries; } numberCliques++; } else { if (printit&&!iPass) printf("%d to zero implies %d to one and %d to zero implies %d to zero\n", iColumn,jColumn,jColumn,iColumn); nFix++; // jColumn is 1 } } else { if (oneFixesInCliqueEntry(fixEntry_[k])) { if (printit&&!iPass) printf("%d to zero implies %d to zero and %d to zero implies %d to one\n", iColumn,jColumn,jColumn,iColumn); nFix++; // iColumn is 1 } else { if (printit&&!iPass) printf("%d to zero implies %d to zero and %d to zero implies %d to zero\n", iColumn,jColumn,jColumn,iColumn); nFix++; // jColumn=iColumn } } } } for ( k=toOne_[jColumn];k<toZero_[jColumn+1];k++) { if (sequenceInCliqueEntry(fixEntry_[k])== (iColumn)) { if (oneFixesInCliqueEntry(fixEntry_[j])) { if (oneFixesInCliqueEntry(fixEntry_[k])) { if (printit&&!iPass) printf("%d to zero implies %d to one and %d to one implies %d to one\n", iColumn,jColumn,jColumn,iColumn); nFix++; //iColumn is 1 } else { if (printit&&!iPass) printf("%d to zero implies %d to one and %d to one implies %d to zero\n", iColumn,jColumn,jColumn,iColumn); nFix++; // iColumn+jcolumn=1 } } else { if (oneFixesInCliqueEntry(fixEntry_[k])) { if (printit&&!iPass) printf("%d to zero implies %d to zero and %d to one implies %d to one\n", iColumn,jColumn,jColumn,iColumn); // 0-1 illegal if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,false); setSequenceInCliqueEntry(temp,iColumn); entry[numberEntries]=temp; } numberEntries++; if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,true); setSequenceInCliqueEntry(temp,jColumn); entry[numberEntries]=temp; } numberEntries++; if (iPass) { // slack cliqueType[numberCliques]='S'; cliqueStart[numberCliques+1]=numberEntries; } numberCliques++; } else { if (printit&&!iPass) printf("%d to zero implies %d to zero and %d to one implies %d to zero\n", iColumn,jColumn,jColumn,iColumn); nFix++; // jColumn is 0 } } } } } } for ( j=toOne_[iColumn];j<toZero_[iColumn+1];j++) { int jColumn=sequenceInCliqueEntry(fixEntry_[j]); if (jColumn<iColumn) { int k; for ( k=toZero_[jColumn];k<toOne_[jColumn];k++) { if (sequenceInCliqueEntry(fixEntry_[k])== (iColumn)) { if (oneFixesInCliqueEntry(fixEntry_[j])) { if (oneFixesInCliqueEntry(fixEntry_[k])) { if (printit&&!iPass) printf("%d to one implies %d to one and %d to zero implies %d to one\n", iColumn,jColumn,jColumn,iColumn); nFix++; // jColumn is 1 } else { if (printit&&!iPass) printf("%d to one implies %d to one and %d to zero implies %d to zero\n", iColumn,jColumn,jColumn,iColumn); // 1-0 illegal if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,true); setSequenceInCliqueEntry(temp,iColumn); entry[numberEntries]=temp; } numberEntries++; if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,false); setSequenceInCliqueEntry(temp,jColumn); entry[numberEntries]=temp; } numberEntries++; if (iPass) { // slack cliqueType[numberCliques]='S'; cliqueStart[numberCliques+1]=numberEntries; } numberCliques++; } } else { if (oneFixesInCliqueEntry(fixEntry_[k])) { if (printit&&!iPass) printf("%d to one implies %d to zero and %d to zero implies %d to one\n", iColumn,jColumn,jColumn,iColumn); nFix++; // iColumn+jColumn=1 } else { if (printit&&!iPass) printf("%d to one implies %d to zero and %d to zero implies %d to zero\n", iColumn,jColumn,jColumn,iColumn); nFix++; // iColumn is 0 } } } } for ( k=toOne_[jColumn];k<toZero_[jColumn+1];k++) { if (sequenceInCliqueEntry(fixEntry_[k])== (iColumn)) { if (oneFixesInCliqueEntry(fixEntry_[j])) { if (oneFixesInCliqueEntry(fixEntry_[k])) { if (printit&&!iPass) printf("%d to one implies %d to one and %d to one implies %d to one\n", iColumn,jColumn,jColumn,iColumn); nFix++; // iColumn == jColumn } else { if (printit&&!iPass) printf("%d to one implies %d to one and %d to one implies %d to zero\n", iColumn,jColumn,jColumn,iColumn); nFix++; // iColumn is 0 } } else { if (oneFixesInCliqueEntry(fixEntry_[k])) { if (printit&&!iPass) printf("%d to one implies %d to zero and %d to one implies %d to one\n", iColumn,jColumn,jColumn,iColumn); nFix++; // jColumn is 0 } else { if (printit&&!iPass) printf("%d to one implies %d to zero and %d to one implies %d to zero\n", iColumn,jColumn,jColumn,iColumn); // 1-1 illegal if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,true); setSequenceInCliqueEntry(temp,iColumn); entry[numberEntries]=temp; } numberEntries++; if (iPass) { CliqueEntry temp; setOneFixesInCliqueEntry(temp,true); setSequenceInCliqueEntry(temp,jColumn); entry[numberEntries]=temp; } numberEntries++; if (iPass) { // slack cliqueType[numberCliques]='S'; cliqueStart[numberCliques+1]=numberEntries; } numberCliques++; } } } } } } } if (!iPass) printf("%d cliques and %d fixed (%d already from matrix))\n", numberCliques-numberMatrixCliques,nFix,numberMatrixCliques); } int iClique; outDupsEtc(numberIntegers_, numberCliques, numberMatrixCliques, cliqueStart, cliqueType, entry, -1, printit ? 2 : 1); printf("%d matrix cliques and %d found by probing\n",numberMatrixCliques,numberCliques-numberMatrixCliques); int * zeroStart = new int [numberIntegers_+1]; int * oneStart = new int [numberIntegers_]; int * zeroCount = new int [numberIntegers_]; int * oneCount = new int [numberIntegers_]; char * mark = new char [numberIntegers_]; memset(mark,0,numberIntegers_); int nStrengthen=-1; int iPass=0; while (nStrengthen&&iPass<20) { iPass++; int numberLastTime = numberCliques; int * count = new int [numberCliques]; int i,iColumn; for (i=0;i<numberCliques;i++) { count[i]=0; } int * whichCount = new int [numberCliques]; CoinZeroN(zeroCount,numberIntegers_); CoinZeroN(oneCount,numberIntegers_); for (iClique=0;iClique<numberCliques;iClique++) { for (int j=cliqueStart[iClique];j<cliqueStart[iClique+1];j++) { int iColumn = static_cast<int> (sequenceInCliqueEntry(entry[j])); if (oneFixesInCliqueEntry(entry[j])) { oneCount[iColumn]++; } else { zeroCount[iColumn]++; } } } int j; zeroStart[0]=0; cliqueStart[0]=0; for (j=0;j<numberIntegers_;j++) { int n; n=zeroCount[j]; zeroCount[j]=0; oneStart[j] = zeroStart[j]+n; n=oneCount[j]; oneCount[j]=0; zeroStart[j+1] = oneStart[j]+n; } for (iClique=0;iClique<numberCliques;iClique++) { for (int j=cliqueStart[iClique];j<cliqueStart[iClique+1];j++) { int iColumn = static_cast<int> (sequenceInCliqueEntry(entry[j])); if (oneFixesInCliqueEntry(entry[j])) { int k=oneCount[iColumn]; oneCount[iColumn]++; int put = oneStart[iColumn]+k; whichClique[put]=iClique; } else { int k=zeroCount[iColumn]; zeroCount[iColumn]++; int put = zeroStart[iColumn]+k; whichClique[put]=iClique; } } } nStrengthen=0; int numberEntries=cliqueStart[numberCliques]; int maximumEntries=numberEntries; int maximumCliques=numberCliques; for (iColumn=0;iColumn<numberIntegers_;iColumn++) { int i; int n; int nCount=0; n=0; for (i=zeroStart[iColumn];i<oneStart[iColumn];i++) { int jClique = whichClique[i]; //if (jClique<numberMatrixCliques) //continue; int j = cliqueStart[jClique]; //assert (cliqueStart[jClique+1]==j+2); for (;j<cliqueStart[jClique+1];j++) { CliqueEntry eJ = entry[j]; int jColumn = sequenceInCliqueEntry(eJ); if (jColumn>iColumn&&!mark[jColumn]) { mark[jColumn]=1; whichP[n++]=jColumn; assert (n<numberIntegers_); if (oneFixesInCliqueEntry(eJ)) { for (int k=oneStart[jColumn];k<zeroStart[jColumn+1];k++) { int jClique = whichClique[k]; if (!count[jClique]) whichCount[nCount++]=jClique; count[jClique]++; } } else { for (int k=zeroStart[jColumn];k<oneStart[jColumn];k++) { int jClique = whichClique[k]; if (!count[jClique]) whichCount[nCount++]=jClique; count[jClique]++; } } } } } std::sort(whichP,whichP+n); for (i=0;i<nCount;i++) { int jClique = whichCount[i]; int jCount = count[jClique]; count[jClique]=0; if (jCount==cliqueStart[jClique+1]-cliqueStart[jClique]) { printf("Zero can extend %d [ ",jClique); for (int i=cliqueStart[jClique];i<cliqueStart[jClique+1];i++) printf("%d(%d) ",sequenceInCliqueEntry(entry[i]),oneFixesInCliqueEntry(entry[i])); printf("] by %d(0)\n",iColumn); nStrengthen++; if (numberEntries+jCount+1>maximumEntries) { maximumEntries = CoinMax(numberEntries+jCount+1,(maximumEntries*12)/10+100); CliqueEntry * temp = new CliqueEntry [maximumEntries]; memcpy(temp,entry,numberEntries*sizeof(CliqueEntry)); delete [] entry; entry=temp; int * tempI = new int [maximumEntries]; memcpy(tempI,whichClique,numberEntries*sizeof(int)); delete [] whichClique; whichClique=tempI; } if (numberCliques==maximumCliques) { maximumCliques = (maximumCliques*12)/10+100; int * temp = new int [maximumCliques+1]; memcpy(temp,cliqueStart,(numberCliques+1)*sizeof(int)); delete [] cliqueStart; cliqueStart=temp; char * tempT = new char [maximumCliques]; memcpy(tempT,cliqueType,numberCliques); delete [] cliqueType; cliqueType=tempT; } CliqueEntry eI; eI.fixes=0; setSequenceInCliqueEntry(eI,iColumn); setOneFixesInCliqueEntry(eI,false); entry[numberEntries++]=eI; whichM[0]=iColumn; int n=1; for (int i=cliqueStart[jClique];i<cliqueStart[jClique+1];i++) { entry[numberEntries++]=entry[i]; whichM[n++]=sequenceInCliqueEntry(entry[i]); } CoinSort_2(whichM,whichM+n,(reinterpret_cast<int *>(entry))+numberEntries-n); cliqueType[numberCliques]='S'; numberCliques++; cliqueStart[numberCliques]=numberEntries; } } for (i=0;i<n;i++) mark[whichP[i]]=0; nCount=0; n=0; for (i=oneStart[iColumn];i<zeroStart[iColumn+1];i++) { int jClique = whichClique[i]; //if (jClique<numberMatrixCliques) //continue; int j = cliqueStart[jClique]; //assert (cliqueStart[jClique+1]==j+2); for (;j<cliqueStart[jClique+1];j++) { CliqueEntry eJ = entry[j]; int jColumn = sequenceInCliqueEntry(eJ); if (jColumn>iColumn&&!mark[jColumn]) { mark[jColumn]=1; whichP[n++]=jColumn; assert (n<numberIntegers_); if (oneFixesInCliqueEntry(eJ)) { for (int k=oneStart[jColumn];k<zeroStart[jColumn+1];k++) { int jClique = whichClique[k]; if (!count[jClique]) whichCount[nCount++]=jClique; count[jClique]++; } } else { for (int k=zeroStart[jColumn];k<oneStart[jColumn];k++) { int jClique = whichClique[k]; if (!count[jClique]) whichCount[nCount++]=jClique; count[jClique]++; } } } } } std::sort(whichP,whichP+n); for (i=0;i<nCount;i++) { int jClique = whichCount[i]; int jCount = count[jClique]; count[jClique]=0; if (jCount==cliqueStart[jClique+1]-cliqueStart[jClique]) { #if 1 if (printit) { printf("One can extend %d [ ",jClique); for (int i=cliqueStart[jClique];i<cliqueStart[jClique+1];i++) printf("%d(%d) ",sequenceInCliqueEntry(entry[i]),oneFixesInCliqueEntry(entry[i])); printf("] by %d(1)\n",iColumn); } #endif nStrengthen++; if (numberEntries+jCount+1>maximumEntries) { maximumEntries = CoinMax(numberEntries+jCount+1,(maximumEntries*12)/10+100); CliqueEntry * temp = new CliqueEntry [maximumEntries]; memcpy(temp,entry,numberEntries*sizeof(CliqueEntry)); delete [] entry; entry=temp; int * tempI = new int [maximumEntries]; memcpy(tempI,whichClique,numberEntries*sizeof(int)); delete [] whichClique; whichClique=tempI; } if (numberCliques==maximumCliques) { maximumCliques = (maximumCliques*12)/10+100; int * temp = new int [maximumCliques+1]; memcpy(temp,cliqueStart,(numberCliques+1)*sizeof(int)); delete [] cliqueStart; cliqueStart=temp; char * tempT = new char [maximumCliques]; memcpy(tempT,cliqueType,numberCliques); delete [] cliqueType; cliqueType=tempT; } CliqueEntry eI; eI.fixes=0; setSequenceInCliqueEntry(eI,iColumn); setOneFixesInCliqueEntry(eI,true); entry[numberEntries++]=eI; whichM[0]=iColumn; int n=1; for (int i=cliqueStart[jClique];i<cliqueStart[jClique+1];i++) { entry[numberEntries++]=entry[i]; whichM[n++]=sequenceInCliqueEntry(entry[i]); } CoinSort_2(whichM,whichM+n,(reinterpret_cast<int *>(entry))+numberEntries-n); cliqueType[numberCliques]='S'; numberCliques++; cliqueStart[numberCliques]=numberEntries; } } for (i=0;i<n;i++) mark[whichP[i]]=0; } if (nStrengthen) { int numberDeleted = outDupsEtc(numberIntegers_, numberCliques, numberMatrixCliques, cliqueStart, cliqueType, entry, numberLastTime,printit ? 2 : 1); if (numberDeleted<0||(iPass>1&&numberCliques-numberDeleted>5000)) nStrengthen=0; } delete [] count; delete [] whichCount; } #if 0 if (numberCliques>numberMatrixCliques) { // should keep as cliques and also use in branching ?? double * element = new double [numberIntegers_]; for (iClique=numberMatrixCliques;iClique<numberCliques;iClique++) { int n=0; double rhs=1.0; for (int i=cliqueStart[iClique];i<cliqueStart[iClique+1];i++) { CliqueEntry eI=entry[i]; int iColumn = integerVariable_[sequenceInCliqueEntry(eI)]; whichP[n]=iColumn; if (oneFixesInCliqueEntry(eI)) { element[n++]=1.0; } else { element[n++]=-1.0; rhs -= 1.0; } } stored->addCut(-COIN_DBL_MAX,rhs,n,whichP,element); } delete [] element; } #endif OsiSolverInterface * newSolver=NULL; if (numberCliques>numberMatrixCliques||alwaysDo) { newSolver = si.clone(); // Delete all rows int * start = new int [ CoinMax(numberRows,numberCliques+1)]; int i; for (i=0;i<numberRows;i++) start[i]=i; newSolver->deleteRows(numberRows,start); start[0]=0; int numberElements = cliqueStart[numberCliques]; int * column = new int [numberElements]; double * element = new double [numberElements]; double * lower = new double [numberCliques]; double * upper = new double [numberCliques]; numberElements=0; for (iClique=0;iClique<numberCliques;iClique++) { double rhs=1.0; for (int i=cliqueStart[iClique];i<cliqueStart[iClique+1];i++) { CliqueEntry eI=entry[i]; int iColumn = integerVariable_[sequenceInCliqueEntry(eI)]; column[numberElements]=iColumn; if (oneFixesInCliqueEntry(eI)) { element[numberElements++]=1.0; } else { element[numberElements++]=-1.0; rhs -= 1.0; } } start[iClique+1]=numberElements; assert (cliqueType[iClique]=='S'|| cliqueType[iClique]=='E'); if (cliqueType[iClique]=='S') lower[iClique]=-COIN_DBL_MAX; else lower[iClique] = rhs; upper[iClique]=rhs; } newSolver->addRows(numberCliques,start,column,element,lower,upper); delete [] start; delete [] column; delete [] element; delete [] lower; delete [] upper; } delete [] mark; delete [] whichP; delete [] whichM; delete [] cliqueStart; delete [] entry; delete [] cliqueType; delete [] zeroStart; delete [] oneStart; delete [] zeroCount; delete [] oneCount; delete [] whichClique; return newSolver; }
// Converts to ordered and takes out duplicates void CglTreeProbingInfo::convert() { if (numberEntries_>=0) { CoinSort_2( fixingEntry_, fixingEntry_+numberEntries_, fixEntry_); assert (!toZero_); toZero_ = new int [numberIntegers_+1]; toOne_ = new int [numberIntegers_]; toZero_[0]=0; int n=0; int put=0; for (int intVariable = 0;intVariable<numberIntegers_;intVariable++) { int last = n; for (;n<numberEntries_;n++) { int value = fixingEntry_[n]; int iVar = value>>1; int way = value &1; if (intVariable!=iVar||way) break; } if (n>last) { // sort assert (sizeof(int)==4); std::sort(reinterpret_cast<unsigned int *> (fixEntry_)+last, reinterpret_cast<unsigned int *> (fixEntry_)+n); CliqueEntry temp2; temp2.fixes=0; setSequenceInCliqueEntry(temp2,numberVariables_+1); for (int i=last;i<n;i++) { if (sequenceInCliqueEntry(temp2)!=sequenceInCliqueEntry(fixEntry_[i])||oneFixesInCliqueEntry(temp2)||oneFixesInCliqueEntry(fixEntry_[i])) { temp2 = fixEntry_[i]; fixEntry_[put++]=temp2; } } } toOne_[intVariable]=put; last = n; for (;n<numberEntries_;n++) { int value = fixingEntry_[n]; int iVar = value>>1; if (intVariable!=iVar) break; } if (n>last) { // sort assert (sizeof(int)==4); std::sort(reinterpret_cast<unsigned int *> (fixEntry_)+last, reinterpret_cast<unsigned int *> (fixEntry_)+n); CliqueEntry temp2; temp2.fixes=0; setSequenceInCliqueEntry(temp2,numberVariables_+1); for (int i=last;i<n;i++) { if (sequenceInCliqueEntry(temp2)!=sequenceInCliqueEntry(fixEntry_[i])||oneFixesInCliqueEntry(temp2)||oneFixesInCliqueEntry(fixEntry_[i])) { temp2 = fixEntry_[i]; fixEntry_[put++]=temp2; } } last=n; } toZero_[intVariable+1]=put; } delete [] fixingEntry_; fixingEntry_ = NULL; numberEntries_ = -2; }