コード例 #1
0
//-------------------------------------------------------------------------------
// Generate three cycle cuts
//------------------------------------------------------------------- 
void CglOddHole::generateCuts(const OsiSolverInterface & si, OsiCuts & cs,
			      const CglTreeInfo info)
{
  // Get basic problem information
  int nRows=si.getNumRows(); 
  int nCols=si.getNumCols(); 
  
  const CoinPackedMatrix * rowCopy = si.getMatrixByRow();

  // Could do cliques and extra OSL cliques
  // For moment just easy ones
  
  // If no information exists then get a list of suitable rows
  // If it does then suitable rows are subset of information
  
  CglOddHole temp;
  int * checkRow = new int[nRows];
  int i;
  if (!suitableRows_) {
    for (i=0;i<nRows;i++) {
      checkRow[i]=1;
    }
  } else {
    // initialize and extend rows to current size
    memset(checkRow,0,nRows*sizeof(int));
    memcpy(checkRow,suitableRows_,CoinMin(nRows,numberRows_)*sizeof(int));
  }
  temp.createRowList(si,checkRow);
  // now cut down further by only allowing rows with fractional solution
  double * solution = new double[nCols];
  memcpy(solution,si.getColSolution(),nCols*sizeof(double));
  const int * column = rowCopy->getIndices();
  const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
  const int * rowLength = rowCopy->getVectorLengths(); 
  const double * collower = si.getColLower();
  const double * colupper = si.getColUpper();
  int * suitable = temp.suitableRows_;

  // At present I am using new and delete as easier to see arrays in debugger
  int * fixed = new int[nCols]; // mark fixed columns 

  for (i=0;i<nCols;i++) {
    if (si.isBinary(i) ) {
      fixed[i]=0;
      if (colupper[i]-collower[i]<epsilon_) {
	solution[i]=0.0;
	fixed[i]=2;
      } else if (solution[i]<epsilon_) {
	solution[i]=0.0;
	fixed[i]=-1;
      } else if (solution[i]>onetol_) {
	solution[i]=1.0;
	fixed[i]=+1;
      }
    } else {
      //mark as fixed even if not (can not intersect any interesting rows)
      solution[i]=0.0;
      fixed[i]=3;
    }
  }
  // first do packed
  const double * rowlower = si.getRowLower();
  const double * rowupper = si.getRowUpper();
  for (i=0;i<nRows;i++) {
    if (suitable[i]) {
      int k;
      double sum=0.0;
      if (rowupper[i]>1.001) suitable[i]=-1;
      for (k=rowStart[i]; k<rowStart[i]+rowLength[i];k++) {
	int icol=column[k];
	if (!fixed[icol]) sum += solution[icol];
      }
      if (sum<0.9) suitable[i]=-1; //say no good
    }
  }
#ifdef CGL_DEBUG
  const OsiRowCutDebugger * debugger = si.getRowCutDebugger();
  if (debugger&&!debugger->onOptimalPath(si))
    debugger = NULL;
#else
  const OsiRowCutDebugger * debugger = NULL;
#endif
  temp.generateCuts(debugger, *rowCopy,solution,
		    si.getReducedCost(),cs,suitable,fixed,info,true);
  // now cover
  //if no >= then skip
  bool doCover=false;
  int nsuitable=0;
  for (i=0;i<nRows;i++) {
    suitable[i]=abs(suitable[i]);
    if (suitable[i]) {
      int k;
      double sum=0.0;
      if (rowlower[i]<0.999) sum=2.0;
      if (rowupper[i]>1.001) doCover=true;
      for (k=rowStart[i]; k<rowStart[i]+rowLength[i];k++) {
	int icol=column[k];
	if (!fixed[icol]) sum += solution[icol];
	if (fixed[icol]==1) sum=2.0; //don't use if any at 1
      }
      if (sum>1.1) {
	suitable[i]=-1; //say no good
      } else {
	nsuitable++;
      }
    }
  }
  if (doCover&&nsuitable) 
    temp.generateCuts(debugger, *rowCopy,solution,si.getReducedCost(),
		      cs,suitable,fixed,info,false);
  delete [] checkRow;
  delete [] solution;
  delete [] fixed;
    
}
コード例 #2
0
//--------------------------------------------------------------------------
// test cut debugger methods.
void
OsiRowCutDebuggerUnitTest(const OsiSolverInterface * baseSiP, const std::string & mpsDir)
{
  
  CoinRelFltEq eq;
  
  // Test default constructor
  {
    OsiRowCutDebugger r;
    OSIUNITTEST_ASSERT_ERROR(r.integerVariable_ == NULL, {}, "osirowcutdebugger", "default constructor");
    OSIUNITTEST_ASSERT_ERROR(r.knownSolution_   == NULL, {}, "osirowcutdebugger", "default constructor");
    OSIUNITTEST_ASSERT_ERROR(r.numberColumns_   == 0,    {}, "osirowcutdebugger", "default constructor");
  }
  
  {
    // Get non trivial instance
    OsiSolverInterface * imP = baseSiP->clone();
    std::string fn = mpsDir+"exmip1";
    imP->readMps(fn.c_str(),"mps");
    OSIUNITTEST_ASSERT_ERROR(imP->getNumRows() == 5, {}, "osirowcutdebugger", "read exmip1");
    
    /*
      Activate the debugger. The garbled name here is deliberate; the
      debugger should isolate the portion of the string between '/' and
      '.' (in normal use, this would be the base file name, stripped of
      the prefix and extension).
    */
    imP->activateRowCutDebugger("ab cd /x/ /exmip1.asc");
    
    int i;
    
    // return debugger
    const OsiRowCutDebugger * debugger = imP->getRowCutDebugger();
    OSIUNITTEST_ASSERT_ERROR(debugger != NULL, {}, "osirowcutdebugger", "return debugger");
    OSIUNITTEST_ASSERT_ERROR(debugger->numberColumns_ == 8, {}, "osirowcutdebugger", "return debugger");
    
    const bool type[]={0,0,1,1,0,0,0,0};
    const double values[]= {2.5, 0, 1, 1, 0.5, 3, 0, 0.26315789473684253};
    CoinPackedVector objCoefs(8,imP->getObjCoefficients());
   
    bool type_ok = true;
#if 0
    for (i=0;i<8;i++)
      type_ok &= type[i] == debugger->integerVariable_[i];
    OSIUNITTEST_ASSERT_ERROR(type_ok, {}, "osirowcutdebugger", "???");
#endif
    
    double objValue = objCoefs.dotProduct(values);
    double debuggerObjValue = objCoefs.dotProduct(debugger->knownSolution_);
    OSIUNITTEST_ASSERT_ERROR(eq(objValue, debuggerObjValue), {}, "osirowcutdebugger", "objective value");
    
    OsiRowCutDebugger rhs;
    {
      OsiRowCutDebugger rC1(*debugger);

      OSIUNITTEST_ASSERT_ERROR(rC1.numberColumns_ == 8, {}, "osirowcutdebugger", "copy constructor");
      type_ok = true;
      for (i=0;i<8;i++)
      	type_ok &= type[i] == rC1.integerVariable_[i];
      OSIUNITTEST_ASSERT_ERROR(type_ok, {}, "osirowcutdebugger", "copy constructor");
      OSIUNITTEST_ASSERT_ERROR(eq(objValue,objCoefs.dotProduct(rC1.knownSolution_)), {}, "osirowcutdebugger", "copy constructor");
      
      rhs = rC1;
      OSIUNITTEST_ASSERT_ERROR(rhs.numberColumns_ == 8, {}, "osirowcutdebugger", "assignment operator");
      type_ok = true;
      for (i=0;i<8;i++)
      	type_ok &= type[i] == rhs.integerVariable_[i];
      OSIUNITTEST_ASSERT_ERROR(type_ok, {}, "osirowcutdebugger", "assignment operator");
      OSIUNITTEST_ASSERT_ERROR(eq(objValue,objCoefs.dotProduct(rhs.knownSolution_)), {}, "osirowcutdebugger", "assignment operator");
    }
    // Test that rhs has correct values even though lhs has gone out of scope
    OSIUNITTEST_ASSERT_ERROR(rhs.numberColumns_ == 8, {}, "osirowcutdebugger", "assignment operator");
    type_ok = true;
    for (i=0;i<8;i++)
    	type_ok &= type[i] == rhs.integerVariable_[i];
    OSIUNITTEST_ASSERT_ERROR(type_ok, {}, "osirowcutdebugger", "assignment operator");
    OSIUNITTEST_ASSERT_ERROR(eq(objValue,objCoefs.dotProduct(rhs.knownSolution_)), {}, "osirowcutdebugger", "assignment operator");

    OsiRowCut cut[2];
    
    const int ne = 3;
    int inx[ne] = { 0, 2, 3 };
    double el[ne] = { 1., 1., 1. };
    cut[0].setRow(ne,inx,el);
    cut[0].setUb(5.);
    
    el[1]=5;
    cut[1].setRow(ne,inx,el);
    cut[1].setUb(5);
    OsiCuts cs; 
    cs.insert(cut[0]);
    cs.insert(cut[1]);
    OSIUNITTEST_ASSERT_ERROR(!debugger->invalidCut(cut[0]), {}, "osirowcutdebugger", "recognize (in)valid cut");
    OSIUNITTEST_ASSERT_ERROR( debugger->invalidCut(cut[1]), {}, "osirowcutdebugger", "recognize (in)valid cut");
    OSIUNITTEST_ASSERT_ERROR(debugger->validateCuts(cs,0,2) == 1, {}, "osirowcutdebugger", "recognize (in)valid cut");
    OSIUNITTEST_ASSERT_ERROR(debugger->validateCuts(cs,0,1) == 0, {}, "osirowcutdebugger", "recognize (in)valid cut");
    delete imP;
  }
}
コード例 #3
0
ファイル: CglAllDifferent.cpp プロジェクト: Alihina/ogdf
//-------------------------------------------------------------------
// Generate cuts
//-------------------------------------------------------------------
void CglAllDifferent::generateCuts(const OsiSolverInterface & si, OsiCuts & cs,
			      const CglTreeInfo ) const
{
#ifndef NDEBUG
  int nCols=si.getNumCols();
#endif
  int i;
  const double * lower = si.getColLower();
  const double * upper = si.getColUpper();
#ifdef CGL_DEBUG
  const OsiRowCutDebugger * debugger = si.getRowCutDebugger();
  if (debugger&&debugger->onOptimalPath(si)) {
    printf("On optimal path %d\n",nPath);
    nPath++;
    int nCols=si.getNumCols();
    const double * solution = si.getColSolution();
    const double * optimal = debugger->optimalSolution();
    const double * objective = si.getObjCoefficients();
    double objval1=0.0,objval2=0.0;
    for (i=0;i<nCols;i++) {
#if CGL_DEBUG>1
      printf("%d %g %g %g %g\n",i,lower[i],solution[i],upper[i],optimal[i]);
#endif
      objval1 += solution[i]*objective[i];
      objval2 += optimal[i]*objective[i];
      assert(optimal[i]>=lower[i]&&optimal[i]<=upper[i]);
    }
    printf("current obj %g, integer %g\n",objval1,objval2);
  }
#endif
  int * lo = new int[numberDifferent_];
  int * up = new int[numberDifferent_];
  for (i=0;i<numberDifferent_;i++) {
    int iColumn = originalWhich_[i];
    assert (iColumn<nCols);
    lo[i]  = static_cast<int> (lower[iColumn]);
    assert (floor(lower[iColumn]+0.5)==lower[iColumn]);
    up[i]  = static_cast<int> (upper[iColumn]);
    assert (floor(upper[iColumn]+0.5)==upper[iColumn]);
    assert (up[i]>=lo[i]);
  }
  // We are going to assume we can just have one big 2d array!
  // Could save by going to bits
  // also could skip sets where all are fixed
  // could do some of above by separate first pass
  // once a variable fixed - can take out of list
  // so need to redo complete stuff (including temp which_) every big pass
  int offset = COIN_INT_MAX;
  int maxValue = -COIN_INT_MAX;
  int numberLook=0;
  // copies
  //int * which = new int [numberTotal];
  //int * start = new int [numberSets_+1];
  for (i=0;i<numberSets_;i++) {
    for (int j=start_[i];j<start_[i+1];j++) {
      int k=which_[j];
      offset = CoinMin(offset,lo[k]);
      maxValue = CoinMax(maxValue,up[k]);
    }
    numberLook++;
    int gap = maxValue-offset+1;
    double size = static_cast<double> (gap) * numberDifferent_;
    if (size>1.0e7) {
      if (logLevel_)
        printf("Only looking at %d sets\n",numberLook);
      break;
    }
  }
  // Which sets a variable is in
  int * back = new int [start_[numberSets_]];
  int * backStart = new int[numberDifferent_+1];
  memset(backStart,0,(numberDifferent_+1)*sizeof(int));
  int numberTotal = start_[numberLook];
  for (i=0;i<numberTotal;i++) {
    int k=which_[i];
    // note +1
    backStart[k+1]++;
  }
  int n=0;
  for (i=0;i<numberDifferent_;i++) {
    int nThis = backStart[i+1];
    backStart[i+1]=n;
    n+= nThis;
  }
  // at end all backStart correct!
  for (i=0;i<numberLook;i++) {
    for (int j=start_[i];j<start_[i+1];j++) {
      int k=which_[j];
      // note +1
      int iPut = backStart[k+1];
      back[iPut]=i;
      backStart[k+1]=iPut+1;
    }
  }
  // value is possible for variable k if possible[k*gap+value] is nonzero
  int gap = maxValue-offset+1;
  char * possible = new char[gap*numberDifferent_];
  memset(possible,0,gap*numberDifferent_);
  // initialize
  int numberFixed=0;
  int * alreadyFixed = new int[numberDifferent_];
  for (i=0;i<numberDifferent_;i++) {
    alreadyFixed[i]=-1;
    int startV = i*gap + lo[i] - offset;
    int n = up[i]-lo[i]+1;
    memset(possible+startV,1,n);
  }
  for (i=0;i<numberDifferent_;i++) {
    int n = up[i]-lo[i]+1;
    if (n==1) {
      int fixedAt = lo[i]-offset;
      numberFixed++;
      alreadyFixed[i]=fixedAt;
      // take out of all others
      for (int j=backStart[i];j<backStart[i+1];j++) {
        int iSet = back[j];
        for (int jj=start_[iSet];jj<start_[iSet+1];jj++) {
          int k=which_[jj];
          if (k!=i) {
            // impossible
            possible[k*gap+fixedAt]=0;
          }
        }
      }
    }
  }
  bool finished=false;
  //int numberTightened=0;
  bool infeasible=false;
  // space to see which values possible
  int * check = new int[gap];
  unsigned int * bitmap = new unsigned int[numberDifferent_];
  int * stack = new int[numberDifferent_+1];
  int * first = new int[numberDifferent_+1];
  // just for valgrind etc
  memset(stack,0,(numberDifferent_+1)*sizeof(int));
  memset(first,0,(numberDifferent_+1)*sizeof(int));
  // do one set at a time
  while (!finished) {
    finished=true;
    int fixed=numberFixed;
    for (i=0;i<numberLook;i++) {
      memset(check,0,gap*sizeof(int));
      for (int j=start_[i];j<start_[i+1];j++) {
        int k=which_[j];
        if (alreadyFixed[k]>=0) {
          if (check[alreadyFixed[k]]==0) {
            check[alreadyFixed[k]]=1;
            continue;
          } else {
            // infeasible
            infeasible=true;
            i=numberLook;
            break;
          }
        }
        char * allowed = possible + k*gap;
        int n=0;
        for (int jj=0;jj<gap;jj++) {
          if (allowed[jj]) {
            n++;
            check[jj]++;
          }
        }
        if (n<2) {
          if (n==1) {
            // fix
            int fixedAt = -1;
            for (int jj=0;jj<gap;jj++) {
              if (allowed[jj]) {
                fixedAt=jj;
                break;
              }
            }
            numberFixed++;
            alreadyFixed[k]=fixedAt;
            check[fixedAt]=1;
            // take out of all others
            for (int j=backStart[k];j<backStart[k+1];j++) {
              int iSet = back[j];
              for (int jj=start_[iSet];jj<start_[iSet+1];jj++) {
                int kk=which_[jj];
                if (kk!=k) {
                  // impossible
                  possible[kk*gap+fixedAt]=0;
                }
              }
            }
          } else {
            // infeasible
            infeasible=true;
            j=numberTotal;
            i=numberLook;
            break;
          }
        }
      }
      // now check set
      // If number covered < number in set infeasible
      if (gap<30&&!infeasible) {
        int n=start_[i+1]-start_[i];
        memset(bitmap,0,n*sizeof(unsigned int));
        int j;
        int * which = which_+start_[i];
        unsigned int covered=0;
        bool good=true;
        for (j=0;j<n;j++) {
          int k=which[j];
          char * allowed = possible + k*gap;
          int jj;
          for (jj=0;jj<gap;jj++)
            if (allowed[jj])
              break;
          assert (jj<gap);
          first[j]=jj;
          unsigned int iBit = 1<<jj;
          if ((covered&iBit)==0) {
            stack[j]=jj;
            covered |= iBit;
          } else {
            // can't
            jj++;
            for (;jj<gap;jj++) {
              iBit  = iBit << 1;
              if (allowed[jj]&&(covered&iBit)==0)
                break;
            }
            if (jj<gap) {
              stack[j]=jj;
              covered |= iBit;
            } else {
              good = false;
              break;
            }
          }
        }
        int nStack=j;
        // just do first for rest
        for (;j<n;j++) {
          int k=which[j];
          char * allowed = possible + k*gap;
          int jj;
          for (jj=0;jj<gap;jj++)
            if (allowed[jj])
              break;
          assert (jj<gap);
          first[j]=jj;
        }
        int kLook=0;
        while (nStack) {
          nStack--;
          if (good) {
#if 0
            printf("con %d = ",i);
            for (j=0;j<n;j++)
              printf("%d ",stack[j]+1);
            printf("\n");
#endif
            // bug - kLook >= 0
            kLook=0;
            for (j=kLook;j<n;j++) {
              int iBit = 1 << stack[j];
              bitmap[j] |= iBit;
            }
          }
          kLook=nStack;
          int jj=stack[nStack];
          unsigned int iBit = 1<<jj;
          covered &= ~iBit;
          {
            unsigned int kBit=0;
            for (int k=0;k<nStack;k++) {
              int kk=stack[k];
              kBit |= 1<<kk;
            }
            assert (covered==kBit);
          }
          jj++;
          stack[nStack]=jj;
          while (nStack<n) {
            int k=which[nStack];
            char * allowed = possible + k*gap;
            for (;jj<gap;jj++) {
              iBit  = 1 << jj;
              if (allowed[jj]&&(covered&iBit)==0)
                break;
            }
            if (jj<gap) {
              stack[nStack]=jj;
              covered |= iBit;
              nStack++;
              stack[nStack]=first[nStack];
              jj = first[nStack];
              good=true;
            } else {
              good = false;
              break;
            }
          }
        }
        int nnFix=0;
        // Now see if we can fix any
        for (j=0;j<n;j++) {
          int k=which[j];
          unsigned int mapped = bitmap[j];
          char * allowed = possible + k*gap;
          unsigned int iBit=1;
          for (int jj=0;jj<gap;jj++) {
            if ((mapped&iBit)==0) {
              if (allowed[jj]) {
                if (!nnFix)
                  printf("for con %d x ",i);
                nnFix++;
                printf("%d not %d ",j,jj+1);
                allowed[jj]=0;
                finished=false;
              }
            }
            iBit  = iBit << 1;
          }
        }
        if (nnFix)
          printf("\n");
      }
    }
    if (numberFixed>fixed)
      finished=false; // try again
  }
  // Could try two sets
  if (infeasible) {
    // create infeasible cut
    OsiRowCut rc;
    rc.setLb(COIN_DBL_MAX);
    rc.setUb(0.0);
    cs.insert(rc);
  } else {
    // check to see if can tighten bounds
    CoinPackedVector lbs;
    CoinPackedVector ubs;
    int nTightened=0;
    for (i=0;i<numberDifferent_;i++) {
      int iColumn = originalWhich_[i];
      char * allowed = possible+i*gap;
      int firstLo=-1;
      int lastUp=-1;
      for (int jj=0;jj<gap;jj++) {
        if (allowed[jj]) {
          if (firstLo<0)
            firstLo=jj;
          lastUp = jj;
        }
      }
      if (firstLo+offset>lo[i]) {
        lbs.insert(iColumn,static_cast<double> (firstLo+offset));
        nTightened++;
      }
      if (lastUp+offset<up[i]) {
        ubs.insert(iColumn,static_cast<double> (lastUp+offset));
        nTightened++;
      }
    }
    if (nTightened) {
      OsiColCut cc;
      cc.setUbs(ubs);
      cc.setLbs(lbs);
      cc.setEffectiveness(100.0);
      cs.insert(cc);
    }
  }
  //delete [] which;
  //delete [] start;
  delete [] first;
  delete [] stack;
  delete [] bitmap;
  delete [] check;
  delete [] alreadyFixed;
  delete [] back;
  delete [] backStart;
  delete [] possible;
  delete [] lo;
  delete [] up;
}