CoinWarmStartBasis *CoinPrePostsolveMatrix::getStatus ()

{ int n = ncols_ ;
  int m = nrows_ ;
  CoinWarmStartBasis *wsb = new CoinWarmStartBasis() ;
  wsb->setSize(n,m) ;
  for (int j = 0 ; j < n ; j++)
  { CoinWarmStartBasis::Status statj = 
	CoinWarmStartBasis::Status(getColumnStatus(j)) ;
    wsb->setStructStatus(j,statj) ; }
  for (int i = 0 ; i < m ; i++)
  { CoinWarmStartBasis::Status stati =
	CoinWarmStartBasis::Status(getRowStatus(i)) ;
    wsb->setArtifStatus(i,stati) ; }
  
  return (wsb) ; }
Beispiel #2
0
//--------------------------------------------------------------------------
// ** At present this does not use any solver
void
CglGomoryUnitTest(
  const OsiSolverInterface * baseSiP,
  const std::string mpsDir )
{
  CoinRelFltEq eq(0.000001);

  // Test default constructor
  {
    CglGomory aGenerator;
    assert (aGenerator.getLimit()==50);
    assert (aGenerator.getAway()==0.05);
  }
  
  // Test copy & assignment etc
  {
    CglGomory rhs;
    {
      CglGomory bGenerator;
      bGenerator.setLimit(99);
      bGenerator.setAway(0.2);
      CglGomory cGenerator(bGenerator);
      rhs=bGenerator;
      assert (rhs.getLimit()==99);
      assert (rhs.getAway()==0.2);
    }
  }

  // Test explicit form - all integer (pg 125 Wolsey)
  if (1) {
    OsiCuts osicuts;
    CglGomory test1;
    int i;
    int nOldCuts=0,nRowCuts;
 
    // matrix data
    //deliberate hiccup of 2 between 0 and 1
    CoinBigIndex start[5]={0,4,7,8,9};
    int length[5]={2,3,1,1,1};
    int rows[11]={0,2,-1,-1,0,1,2,0,1,2};
    double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0,1,1,1};
    CoinPackedMatrix matrix(true,3,5,8,elements,rows,start,length);
    
    // rim data (objective not used just yet)
    double rowLower[5]={14.0,3.0,3.0,1.0e10,1.0e10};
    double rowUpper[5]={14.0,3.0,3.0,-1.0e10,-1.0e10};
    double colLower[7]={0.0,0.0,0.0,0.0,0.0,0.0,0.0};
    double colUpper[7]={100.0,100.0,100.0,100.0,100.0,100.0,100.0};
  
    // integer
    char intVar[7]={2,2,2,2,2,2,2};

    // basis 1
    int rowBasis1[3]={-1,-1,-1};
    int colBasis1[5]={1,1,-1,-1,1};
    CoinWarmStartBasis warm;
    warm.setSize(5,3);
    for (i=0;i<3;i++) {
      if (rowBasis1[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<5;i++) {
      if (colBasis1[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 1
    double colsol1[5]={20.0/7.0,3.0,0.0,0.0,23.0/7.0};
    test1.generateCuts(NULL, osicuts, matrix,
		       /*objective,*/ colsol1,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts==2);
    // cuts always <=
    int testCut=0; // test first cut as stronger
    double rhs=-6.0;
    double testCut1[5]={0.0,0.0,-1.0,-2.0,0.0};
    double * cut = testCut1;
    double * colsol = colsol1;
    for (i=nOldCuts; i<nRowCuts; i++){
      OsiRowCut rcut;
      CoinPackedVector rpv;
      rcut = osicuts.rowCut(i);
      rpv = rcut.row();
      const int n = rpv.getNumElements();
      const int * indices = rpv.getIndices();
      double* elements = rpv.getElements();
      double sum2=0.0;
      int k=0;
      for (k=0; k<n; k++){
	int column=indices[k];
	sum2 += colsol[column]*elements[k];
      }

      double ub=rcut.ub();

#ifdef CGL_DEBUG
      double lb=rcut.lb();
      if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
	std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
	for (k=0; k<n; k++){
	  int column=indices[k];
	  std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
	    colsol[column]<<") ";
	}
	std::cout <<std::endl;
      }
#endif

      if (i-nOldCuts==testCut) {
	assert( eq(rhs,ub));
	assert(n==2);
	for (k=0; k<n; k++){
	  int column=indices[k];
	  assert (eq(cut[column],elements[k]));
	}
	// add cut
	// explicit slack
	matrix.setDimensions(-1,6);
	rpv.insert(5,1.0*7.0); // to get cut in book
	rowLower[3]=ub;
	rowUpper[3]=ub;
	matrix.appendRow(rpv);
      }
    }
    nOldCuts=nRowCuts;
    // basis 2
    int rowBasis2[4]={-1,-1,-1,-1};
    int colBasis2[6]={1,1,1,1,-1,-1};
    warm.setSize(6,4);
    for (i=0;i<4;i++) {
      if (rowBasis2[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<6;i++) {
      if (colBasis2[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 2
    double colsol2[6]={2.0,0.5,1.0,2.5,0.0,0.0};
    test1.generateCuts(NULL, osicuts, matrix,
		       /*objective,*/ colsol2,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts-nOldCuts==2);
    // cuts always <=
    testCut=0; // test first cut as stronger
    rhs=-1.0;
    double testCut2[6]={0.0,0.0,0.0,0.0,-1.0,0.0};
    cut = testCut2;
    colsol = colsol2;
    for (i=nOldCuts; i<nRowCuts; i++){
      OsiRowCut rcut;
      CoinPackedVector rpv;
      rcut = osicuts.rowCut(i);
      rpv = rcut.row();
      const int n = rpv.getNumElements();
      const int * indices = rpv.getIndices();
      double* elements = rpv.getElements();
      double sum2=0.0;
      int k=0;
      for (k=0; k<n; k++){
	int column=indices[k];
	sum2 += colsol[column]*elements[k];
      }

      double ub=rcut.ub();

#ifdef CGL_DEBUG
      double lb=rcut.lb();
      if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
	std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
	for (k=0; k<n; k++){
	  int column=indices[k];
	  std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
	    colsol[column]<<") ";
	}
	std::cout <<std::endl;
      }
#endif

      if (i-nOldCuts==testCut) {
	assert( eq(rhs,ub));
	assert(n==1);
	for (k=0; k<n; k++){
	  int column=indices[k];
	  assert (eq(cut[column],elements[k]));
	}
	// add cut
	// explicit slack
	matrix.setDimensions(-1,7);
	rpv.insert(6,1.0);
	rowLower[4]=ub;
	rowUpper[4]=ub;
	matrix.appendRow(rpv);
      }
    }
    nOldCuts=nRowCuts;
    // basis 3
    int rowBasis3[5]={-1,-1,-1,-1,-1};
    int colBasis3[7]={1,1,1,1,1,-1,-1};
    warm.setSize(7,5);
    for (i=0;i<5;i++) {
      if (rowBasis3[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<7;i++) {
      if (colBasis3[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 3
    double colsol3[7]={2.0,1.0,2.0,2.0,1.0,0.0,0.0};
    test1.generateCuts(NULL, osicuts, matrix,
		       /*objective,*/ colsol3,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts==nOldCuts);
    
  }
  // Test explicit form - this time with x4 flipped
  if (1) {
    OsiCuts osicuts;
    CglGomory test1;
    int i;
    int nOldCuts=0,nRowCuts;
 
    // matrix data
    //deliberate hiccup of 2 between 0 and 1
    CoinBigIndex start[5]={0,4,7,8,9};
    int length[5]={2,3,1,1,1};
    int rows[11]={0,2,-1,-1,0,1,2,0,1,2};
    double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0,1,-1,1};
    CoinPackedMatrix matrix(true,3,5,8,elements,rows,start,length);
    
    // rim data (objective not used just yet)
    double rowLower[5]={14.0,-5.0,3.0,1.0e10,1.0e10};
    double rowUpper[5]={14.0,-5.0,3.0,-1.0e10,-1.0e10};
    double colLower[7]={0.0,0.0,0.0,0.0,0.0,0.0,0.0};
    double colUpper[7]={100.0,100.0,100.0,8.0,100.0,100.0,100.0};
  
    // integer
    char intVar[7]={2,2,2,2,2,2,2};

    // basis 1
    int rowBasis1[3]={-1,-1,-1};
    int colBasis1[5]={1,1,-1,-1,1};
    CoinWarmStartBasis warm;
    warm.setSize(5,3);
    for (i=0;i<3;i++) {
      if (rowBasis1[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<5;i++) {
      if (colBasis1[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 1
    double colsol1[5]={20.0/7.0,3.0,0.0,8.0,23.0/7.0};
    test1.generateCuts(NULL, osicuts, matrix,
		       /*objective,*/ colsol1,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts==2);
    // cuts always <=
    int testCut=0; // test first cut as stronger
    double rhs=10.0;
    double testCut1[5]={0.0,0.0,-1.0,2.0,0.0};
    double * cut = testCut1;
    double * colsol = colsol1;
    for (i=nOldCuts; i<nRowCuts; i++){
      OsiRowCut rcut;
      CoinPackedVector rpv;
      rcut = osicuts.rowCut(i);
      rpv = rcut.row();
      const int n = rpv.getNumElements();
      const int * indices = rpv.getIndices();
      double* elements = rpv.getElements();
      double sum2=0.0;
      int k=0;
      for (k=0; k<n; k++){
	int column=indices[k];
	sum2 += colsol[column]*elements[k];
      }

      double ub=rcut.ub();

#ifdef CGL_DEBUG
      double lb=rcut.lb();
      if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
	std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
	for (k=0; k<n; k++){
	  int column=indices[k];
	  std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
	    colsol[column]<<") ";
	}
	std::cout <<std::endl;
      }
#endif

      if (i-nOldCuts==testCut) {
	assert( eq(rhs,ub));
	assert(n==2);
	for (k=0; k<n; k++){
	  int column=indices[k];
	  assert (eq(cut[column],elements[k]));
	}
	// add cut
	// explicit slack
	matrix.setDimensions(-1,6);
	rpv.insert(5,1.0*7.0); // to get cut in book
	rowLower[3]=ub;
	rowUpper[3]=ub;
	matrix.appendRow(rpv);
      }
    }
    nOldCuts=nRowCuts;
    // basis 2
    int rowBasis2[4]={-1,-1,-1,-1};
    int colBasis2[6]={1,1,1,1,-1,-1};
    warm.setSize(6,4);
    for (i=0;i<4;i++) {
      if (rowBasis2[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<6;i++) {
      if (colBasis2[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 2
    double colsol2[6]={2.0,0.5,1.0,5.5,0.0,0.0};
    test1.generateCuts(NULL, osicuts, matrix,
		       /*objective,*/ colsol2,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts-nOldCuts==2);
    // cuts always <=
    testCut=0; // test first cut as stronger
    rhs=-1.0;
    double testCut2[6]={0.0,0.0,0.0,0.0,-1.0,0.0};
    cut = testCut2;
    colsol = colsol2;
    for (i=nOldCuts; i<nRowCuts; i++){
      OsiRowCut rcut;
      CoinPackedVector rpv;
      rcut = osicuts.rowCut(i);
      rpv = rcut.row();
      const int n = rpv.getNumElements();
      const int * indices = rpv.getIndices();
      double* elements = rpv.getElements();
      double sum2=0.0;
      int k=0;
      for (k=0; k<n; k++){
	int column=indices[k];
	sum2 += colsol[column]*elements[k];
      }

      double ub=rcut.ub();

#ifdef CGL_DEBUG
      double lb=rcut.lb();
      if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
	std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
	for (k=0; k<n; k++){
	  int column=indices[k];
	  std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
	    colsol[column]<<") ";
	}
	std::cout <<std::endl;
      }
#endif

      if (i-nOldCuts==testCut) {
	assert( eq(rhs,ub));
	assert(n==1);
	for (k=0; k<n; k++){
	  int column=indices[k];
	  assert (eq(cut[column],elements[k]));
	}
	// add cut
	// explicit slack
	matrix.setDimensions(-1,7);
	rpv.insert(6,1.0);
	rowLower[4]=ub;
	rowUpper[4]=ub;
	matrix.appendRow(rpv);
      }
    }
    nOldCuts=nRowCuts;
    // basis 3
    int rowBasis3[5]={-1,-1,-1,-1,-1};
    int colBasis3[7]={1,1,1,1,1,-1,-1};
    warm.setSize(7,5);
    for (i=0;i<5;i++) {
      if (rowBasis3[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<7;i++) {
      if (colBasis3[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 3
    double colsol3[7]={2.0,1.0,2.0,6.0,1.0,0.0,0.0};
    test1.generateCuts(NULL, osicuts, matrix,
		       /*objective,*/ colsol3,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts==nOldCuts);
    
  }
  // Test with slacks 
  if (1) {
    OsiCuts osicuts;
    CglGomory test1;
    int i;
    int nOldCuts=0,nRowCuts;
 
    // matrix data
    //deliberate hiccup of 2 between 0 and 1
    CoinBigIndex start[5]={0,4};
    int length[5]={2,3};
    int rows[11]={0,2,-1,-1,0,1,2};
    double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0};
    CoinPackedMatrix matrix(true,3,2,5,elements,rows,start,length);
    
    // rim data (objective not used just yet)
    double rowLower[5]={-1.0e10,-1.0e10,-1.0e10,1.0e10,1.0e10};
    double rowUpper[5]={14.0,3.0,3.0,-1.0e10,-1.0e10};
    double colLower[2]={0.0,0.0};
    double colUpper[2]={100.0,100.0};
  
    // integer
    char intVar[2]={2,2};

    // basis 1
    int rowBasis1[3]={-1,-1,1};
    int colBasis1[2]={1,1};
    CoinWarmStartBasis warm;
    warm.setSize(2,3);
    for (i=0;i<3;i++) {
      if (rowBasis1[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<2;i++) {
      if (colBasis1[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 1
    double colsol1[2]={20.0/7.0,3.0};
    test1.generateCuts(NULL, osicuts, matrix,
		       /* objective,*/ colsol1,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts==1);
    // cuts always <=
    int testCut=0; // test first cut as stronger
    double rhs=2.0;
    double testCut1[2]={1.0,0.0};
    double * cut = testCut1;
    double * colsol = colsol1;
    for (i=nOldCuts; i<nRowCuts; i++){
      OsiRowCut rcut;
      CoinPackedVector rpv;
      rcut = osicuts.rowCut(i);
      rpv = rcut.row();
      const int n = rpv.getNumElements();
      const int * indices = rpv.getIndices();
      double* elements = rpv.getElements();
      double sum2=0.0;
      int k=0;
      for (k=0; k<n; k++){
	int column=indices[k];
	sum2 += colsol[column]*elements[k];
      }

      double ub=rcut.ub();

#ifdef CGL_DEBUG
      double lb=rcut.lb();
      if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
	std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
	for (k=0; k<n; k++){
	  int column=indices[k];
	  std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
	    colsol[column]<<") ";
	}
	std::cout <<std::endl;
      }
#endif

      if (i-nOldCuts==testCut) {
	assert( eq(rhs,ub));
	assert(n==1);
	for (k=0; k<n; k++){
	  int column=indices[k];
	  assert (eq(cut[column],elements[k]));
	}
	// add cut
	rowLower[3]=-1.0e100;
	rowUpper[3]=ub;
	matrix.appendRow(rpv);
      }
    }
    nOldCuts=nRowCuts;
    // basis 2
    int rowBasis2[4]={1,1,-1,-1};
    int colBasis2[2]={1,1};
    warm.setSize(2,4);
    for (i=0;i<4;i++) {
      if (rowBasis2[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<2;i++) {
      if (colBasis2[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 2
    double colsol2[2]={2.0,0.5};
    test1.generateCuts(NULL, osicuts, matrix,
		       /*objective,*/ colsol2,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts-nOldCuts==1);
    // cuts always <=
    testCut=0; // test first cut as stronger
    rhs=1.0;
    double testCut2[2]={1.0,-1.0};
    cut = testCut2;
    colsol = colsol2;
    for (i=nOldCuts; i<nRowCuts; i++){
      OsiRowCut rcut;
      CoinPackedVector rpv;
      rcut = osicuts.rowCut(i);
      rpv = rcut.row();
      const int n = rpv.getNumElements();
      const int * indices = rpv.getIndices();
      double* elements = rpv.getElements();
      double sum2=0.0;
      int k=0;
      for (k=0; k<n; k++){
	int column=indices[k];
	sum2 += colsol[column]*elements[k];
      }

      double ub=rcut.ub();

#ifdef CGL_DEBUG
      double lb=rcut.lb();
      if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
	std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
	for (k=0; k<n; k++){
	  int column=indices[k];
	  std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
	    colsol[column]<<") ";
	}
	std::cout <<std::endl;
      }
#endif

      if (i-nOldCuts==testCut) {
	assert( eq(rhs,ub));
	assert(n==2);
	for (k=0; k<n; k++){
	  int column=indices[k];
	  assert (eq(cut[column],elements[k]));
	}
	// add cut
	rowLower[4]=-1.0e100;
	rowUpper[4]=ub;
	matrix.appendRow(rpv);
      }
    }
    nOldCuts=nRowCuts;
    // basis 3
    int rowBasis3[5]={1,1,1,-1,-1};
    int colBasis3[2]={1,1};
    warm.setSize(2,5);
    for (i=0;i<5;i++) {
      if (rowBasis3[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<2;i++) {
      if (colBasis3[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 3
    double colsol3[2]={2.0,1.0};
    test1.generateCuts(NULL, osicuts, matrix,
		       /*objective,*/ colsol3,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts==nOldCuts);
    
  }
  // swap some rows to G
  if (1) {
    OsiCuts osicuts;
    CglGomory test1;
    int i;
    int nOldCuts=0,nRowCuts;
 
    // matrix data
    //deliberate hiccup of 2 between 0 and 1
    CoinBigIndex start[5]={0,4};
    int length[5]={2,3};
    int rows[11]={0,2,-1,-1,0,1,2};
    double elements[11]={-7.0,-2.0,1.0e10,1.0e10,+2.0,1.0,+2.0};
    CoinPackedMatrix matrix(true,3,2,5,elements,rows,start,length);
    
    // rim data (objective not used just yet)
    double rowUpper[5]={1.0e10,3.0,1.0e10,-1.0e10,-1.0e10};
    double rowLower[5]={-14.0,-1.0e10,-3.0,1.0e10,1.0e10};
    double colLower[2]={0.0,0.0};
    double colUpper[2]={100.0,100.0};
  
    // integer
    char intVar[2]={2,2};

    // basis 1
    int rowBasis1[3]={-1,-1,1};
    int colBasis1[2]={1,1};
    CoinWarmStartBasis warm;
    warm.setSize(2,3);
    for (i=0;i<3;i++) {
      if (rowBasis1[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<2;i++) {
      if (colBasis1[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 1
    double colsol1[2]={20.0/7.0,3.0};
    test1.generateCuts(NULL, osicuts, matrix,
		 /*objective,*/ colsol1,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts==1);
    // cuts always <=
    int testCut=0; // test first cut as stronger
    double rhs=2.0;
    double testCut1[2]={1.0,0.0};
    double * cut = testCut1;
    double * colsol = colsol1;
    for (i=nOldCuts; i<nRowCuts; i++){
      OsiRowCut rcut;
      CoinPackedVector rpv;
      rcut = osicuts.rowCut(i);
      rpv = rcut.row();
      const int n = rpv.getNumElements();
      const int * indices = rpv.getIndices();
      double* elements = rpv.getElements();
      double sum2=0.0;
      int k=0;
      for (k=0; k<n; k++){
	int column=indices[k];
	sum2 += colsol[column]*elements[k];
      }

      double ub=rcut.ub();

#ifdef CGL_DEBUG
      double lb=rcut.lb();
      if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
	std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
	for (k=0; k<n; k++){
	  int column=indices[k];
	  std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
	    colsol[column]<<") ";
	}
	std::cout <<std::endl;
      }
#endif

      if (i-nOldCuts==testCut) {
	assert( eq(rhs,ub));
	assert(n==1);
	for (k=0; k<n; k++){
	  int column=indices[k];
	  assert (eq(cut[column],elements[k]));
	}
	// add cut
	rowLower[3]=-1.0e100;
	rowUpper[3]=ub;
	matrix.appendRow(rpv);
      }
    }
    nOldCuts=nRowCuts;
    // basis 2
    int rowBasis2[4]={1,1,-1,-1};
    int colBasis2[2]={1,1};
    warm.setSize(2,4);
    for (i=0;i<4;i++) {
      if (rowBasis2[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<2;i++) {
      if (colBasis2[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 2
    double colsol2[2]={2.0,0.5};
    test1.generateCuts(NULL, osicuts, matrix,
		 /*objective,*/ colsol2,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts-nOldCuts==1);
    // cuts always <=
    testCut=0; // test first cut as stronger
    rhs=1.0;
    double testCut2[2]={1.0,-1.0};
    cut = testCut2;
    colsol = colsol2;
    for (i=nOldCuts; i<nRowCuts; i++){
      OsiRowCut rcut;
      CoinPackedVector rpv;
      rcut = osicuts.rowCut(i);
      rpv = rcut.row();
      const int n = rpv.getNumElements();
      const int * indices = rpv.getIndices();
      double* elements = rpv.getElements();
      double sum2=0.0;
      int k=0;
      for (k=0; k<n; k++){
	int column=indices[k];
	sum2 += colsol[column]*elements[k];
      }

      double ub=rcut.ub();

#ifdef CGL_DEBUG
      double lb=rcut.lb();
      if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
	std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
	for (k=0; k<n; k++){
	  int column=indices[k];
	  std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
	    colsol[column]<<") ";
	}
	std::cout <<std::endl;
      }
#endif

      if (i-nOldCuts==testCut) {
	assert( eq(rhs,ub));
	assert(n==2);
	for (k=0; k<n; k++){
	  int column=indices[k];
	  assert (eq(cut[column],elements[k]));
	}
	// add cut
	rowLower[4]=-1.0e100;
	rowUpper[4]=ub;
	matrix.appendRow(rpv);
      }
    }
    nOldCuts=nRowCuts;
    // basis 3
    int rowBasis3[5]={1,1,1,-1,-1};
    int colBasis3[2]={1,1};
    warm.setSize(2,5);
    for (i=0;i<5;i++) {
      if (rowBasis3[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<2;i++) {
      if (colBasis3[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 3
    double colsol3[2]={2.0,1.0};
    test1.generateCuts(NULL, osicuts, matrix,
		 /*objective,*/ colsol3,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts==nOldCuts);
    
  }


  // NOW mixed integer gomory cuts

  // Test explicit form - (pg 130 Wolsey)
  // Some arrays left same size as previously although not used in full
  if (1) {
    OsiCuts osicuts;
    CglGomory test1;
    int i;
    int nOldCuts=0,nRowCuts;
 
    // matrix data
    //deliberate hiccup of 2 between 0 and 1
    CoinBigIndex start[5]={0,4,7,8,9};
    int length[5]={2,3,1,1,1};
    int rows[11]={0,2,-1,-1,0,1,2,0,1,2};
    double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0,1,1,1};
    CoinPackedMatrix matrix(true,3,5,8,elements,rows,start,length);
    
    // rim data (objective not used just yet)
    double rowLower[5]={14.0,3.0,3.0,1.0e10,1.0e10};
    double rowUpper[5]={14.0,3.0,3.0,-1.0e10,-1.0e10};
    double colLower[7]={0.0,0.0,0.0,0.0,0.0,0.0,0.0};
    double colUpper[7]={100.0,100.0,100.0,100.0,100.0,100.0,100.0};
  
    // integer
    char intVar[7]={2,0,0,0,0,0,0};

    // basis 1
    int rowBasis1[3]={-1,-1,-1};
    int colBasis1[5]={1,1,-1,-1,1};
    CoinWarmStartBasis warm;
    warm.setSize(5,3);
    for (i=0;i<3;i++) {
      if (rowBasis1[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<5;i++) {
      if (colBasis1[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 1
    double colsol1[5]={20.0/7.0,3.0,0.0,0.0,23.0/7.0};
    test1.generateCuts(NULL, osicuts, matrix,
		 /*objective,*/ colsol1,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts==1);
    // cuts always <=
    int testCut=0; // test first cut as stronger
    double rhs=-6.0/7.0;
    double testCut1[5]={0.0,0.0,-1.0/7.0,-2.0/7.0,0.0};
    double * cut = testCut1;
    double * colsol = colsol1;
    for (i=nOldCuts; i<nRowCuts; i++){
      OsiRowCut rcut;
      CoinPackedVector rpv;
      rcut = osicuts.rowCut(i);
      rpv = rcut.row();
      const int n = rpv.getNumElements();
      const int * indices = rpv.getIndices();
      double* elements = rpv.getElements();
      double sum2=0.0;
      int k=0;
      for (k=0; k<n; k++){
	int column=indices[k];
	sum2 += colsol[column]*elements[k];
      }

      double ub=rcut.ub();

#ifdef CGL_DEBUG
      double lb=rcut.lb();
      if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
	std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
	for (k=0; k<n; k++){
	  int column=indices[k];
	  std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
	    colsol[column]<<") ";
	}
	std::cout <<std::endl;
      }
#endif

      if (i-nOldCuts==testCut) {
	assert( eq(rhs,ub));
	assert(n==2);
	for (k=0; k<n; k++){
	  int column=indices[k];
	  assert (eq(cut[column],elements[k]));
	}
	// add cut
	// explicit slack
	matrix.setDimensions(-1,6);
	rpv.insert(5,1.0); // to get cut in book
	rowLower[3]=ub;
	rowUpper[3]=ub;
	matrix.appendRow(rpv);
      }
    }
    nOldCuts=nRowCuts;
    // basis 2
    int rowBasis2[4]={-1,-1,-1,-1};
    int colBasis2[6]={1,1,1,1,-1,-1};
    warm.setSize(6,4);
    for (i=0;i<4;i++) {
      if (rowBasis2[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<6;i++) {
      if (colBasis2[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 2
    double colsol2[6]={2.0,0.5,1.0,2.5,0.0,0.0};
    test1.generateCuts(NULL, osicuts, matrix,
		 /*objective,*/ colsol2,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts==nOldCuts);
    
  }
  // Test explicit form - this time with x4 flipped 
  if (1) {
    OsiCuts osicuts;
    CglGomory test1;
    int i;
    int nOldCuts=0,nRowCuts;
 
    // matrix data
    //deliberate hiccup of 2 between 0 and 1
    CoinBigIndex start[5]={0,4,7,8,9};
    int length[5]={2,3,1,1,1};
    int rows[11]={0,2,-1,-1,0,1,2,0,1,2};
    double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0,1,-1,1};
    CoinPackedMatrix matrix(true,3,5,8,elements,rows,start,length);
    
    // rim data (objective not used just yet)
    double rowLower[5]={14.0,-5.0,3.0,1.0e10,1.0e10};
    double rowUpper[5]={14.0,-5.0,3.0,-1.0e10,-1.0e10};
    double colLower[7]={0.0,0.0,0.0,0.0,0.0,0.0,0.0};
    double colUpper[7]={100.0,100.0,100.0,8.0,100.0,100.0,100.0};
  
    // integer
    char intVar[7]={2,0,0,0,0,0,0};

    // basis 1
    int rowBasis1[3]={-1,-1,-1};
    int colBasis1[5]={1,1,-1,-1,1};
    CoinWarmStartBasis warm;
    warm.setSize(5,3);
    for (i=0;i<3;i++) {
      if (rowBasis1[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<5;i++) {
      if (colBasis1[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 1
    double colsol1[5]={20.0/7.0,3.0,0.0,8.0,23.0/7.0};
    test1.generateCuts(NULL, osicuts, matrix,
		 /*objective,*/ colsol1,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts==1);
    // cuts always <=
    int testCut=0; 
    double rhs=10.0/7.0;
    double testCut1[5]={0.0,0.0,-1.0/7.0,2.0/7.0,0.0};
    double * cut = testCut1;
    double * colsol = colsol1;
    for (i=nOldCuts; i<nRowCuts; i++){
      OsiRowCut rcut;
      CoinPackedVector rpv;
      rcut = osicuts.rowCut(i);
      rpv = rcut.row();
      const int n = rpv.getNumElements();
      const int * indices = rpv.getIndices();
      double* elements = rpv.getElements();
      double sum2=0.0;
      int k=0;
      for (k=0; k<n; k++){
	int column=indices[k];
	sum2 += colsol[column]*elements[k];
      }

      double ub=rcut.ub();

#ifdef CGL_DEBUG
      double lb=rcut.lb();
      if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
	std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
	for (k=0; k<n; k++){
	  int column=indices[k];
	  std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
	    colsol[column]<<") ";
	}
	std::cout <<std::endl;
      }
#endif

      if (i-nOldCuts==testCut) {
	assert( eq(rhs,ub));
	assert(n==2);
	for (k=0; k<n; k++){
	  int column=indices[k];
	  assert (eq(cut[column],elements[k]));
	}
	// add cut
	// explicit slack
	matrix.setDimensions(-1,6);
	rpv.insert(5,1.0); // to get cut in book
	rowLower[3]=ub;
	rowUpper[3]=ub;
	matrix.appendRow(rpv);
      }
    }
    nOldCuts=nRowCuts;
    // basis 2
    int rowBasis2[4]={-1,-1,-1,-1};
    int colBasis2[6]={1,1,1,1,-1,-1};
    warm.setSize(6,4);
    for (i=0;i<4;i++) {
      if (rowBasis2[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<6;i++) {
      if (colBasis2[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 2
    double colsol2[6]={2.0,0.5,1.0,5.5,0.0,0.0};
    test1.generateCuts(NULL, osicuts, matrix,
		 /*objective,*/ colsol2,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts==nOldCuts);
    
  }
  // Test with slacks 
  if (1) {
    OsiCuts osicuts;
    CglGomory test1;
    int i;
    int nOldCuts=0,nRowCuts;
 
    // matrix data
    //deliberate hiccup of 2 between 0 and 1
    CoinBigIndex start[5]={0,4};
    int length[5]={2,3};
    int rows[11]={0,2,-1,-1,0,1,2};
    double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0};
    CoinPackedMatrix matrix(true,3,2,5,elements,rows,start,length);
    
    // rim data (objective not used just yet)
    double rowLower[5]={-1.0e10,-1.0e10,-1.0e10,1.0e10,1.0e10};
    double rowUpper[5]={14.0,3.0,3.0,-1.0e10,-1.0e10};
    double colLower[2]={0.0,0.0};
    double colUpper[2]={100.0,100.0};
  
    // integer
    char intVar[2]={2,0};

    // basis 1
    int rowBasis1[3]={-1,-1,1};
    int colBasis1[2]={1,1};
    CoinWarmStartBasis warm;
    warm.setSize(2,3);
    for (i=0;i<3;i++) {
      if (rowBasis1[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<2;i++) {
      if (colBasis1[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 1
    double colsol1[2]={20.0/7.0,3.0};
    test1.generateCuts(NULL, osicuts, matrix,
		 /*objective,*/ colsol1,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts==1);
    // cuts always <=
    int testCut=0; // test first cut as stronger
    double rhs=2.0;
    double testCut1[2]={1.0,0.0};
    double * cut = testCut1;
    double * colsol = colsol1;
    for (i=nOldCuts; i<nRowCuts; i++){
      OsiRowCut rcut;
      CoinPackedVector rpv;
      rcut = osicuts.rowCut(i);
      rpv = rcut.row();
      const int n = rpv.getNumElements();
      const int * indices = rpv.getIndices();
      double* elements = rpv.getElements();
      double sum2=0.0;
      int k=0;
      for (k=0; k<n; k++){
	int column=indices[k];
	sum2 += colsol[column]*elements[k];
      }

      double ub=rcut.ub();

#ifdef CGL_DEBUG
      double lb=rcut.lb();
      if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
	std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
	for (k=0; k<n; k++){
	  int column=indices[k];
	  std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
	    colsol[column]<<") ";
	}
	std::cout <<std::endl;
      }
#endif

      if (i-nOldCuts==testCut) {
	assert( eq(rhs,ub));
	assert(n==1);
	for (k=0; k<n; k++){
	  int column=indices[k];
	  assert (eq(cut[column],elements[k]));
	}
	// add cut
	rowLower[3]=-1.0e100;
	rowUpper[3]=ub;
	matrix.appendRow(rpv);
      }
    }
    nOldCuts=nRowCuts;
    // basis 2
    int rowBasis2[4]={1,1,-1,-1};
    int colBasis2[2]={1,1};
    warm.setSize(2,4);
    for (i=0;i<4;i++) {
      if (rowBasis2[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<2;i++) {
      if (colBasis2[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 2
    double colsol2[2]={2.0,0.5};
    test1.generateCuts(NULL, osicuts, matrix,
		       /*objective,*/ colsol2,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts==nOldCuts);
    
  }
  // swap some rows to G
  if (1) {
    OsiCuts osicuts;
    CglGomory test1;
    int i;
    int nOldCuts=0,nRowCuts;
 
    // matrix data
    //deliberate hiccup of 2 between 0 and 1
    CoinBigIndex start[5]={0,4};
    int length[5]={2,3};
    int rows[11]={0,2,-1,-1,0,1,2};
    double elements[11]={-7.0,-2.0,1.0e10,1.0e10,+2.0,1.0,+2.0};
    CoinPackedMatrix matrix(true,3,2,5,elements,rows,start,length);
    
    // rim data (objective not used just yet)
    double rowUpper[5]={1.0e10,3.0,1.0e10,-1.0e10,-1.0e10};
    double rowLower[5]={-14.0,-1.0e10,-3.0,1.0e10,1.0e10};
    double colLower[2]={0.0,0.0};
    double colUpper[2]={100.0,100.0};
  
    // integer
    char intVar[2]={2,0};

    // basis 1
    int rowBasis1[3]={-1,-1,1};
    int colBasis1[2]={1,1};
    CoinWarmStartBasis warm;
    warm.setSize(2,3);
    for (i=0;i<3;i++) {
      if (rowBasis1[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<2;i++) {
      if (colBasis1[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 1
    double colsol1[2]={20.0/7.0,3.0};
    test1.generateCuts(NULL, osicuts, matrix,
		       /*objective,*/ colsol1,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts==1);
    // cuts always <=
    int testCut=0; // test first cut as stronger
    double rhs=2.0;
    double testCut1[2]={1.0,0.0};
    double * cut = testCut1;
    double * colsol = colsol1;
    for (i=nOldCuts; i<nRowCuts; i++){
      OsiRowCut rcut;
      CoinPackedVector rpv;
      rcut = osicuts.rowCut(i);
      rpv = rcut.row();
      const int n = rpv.getNumElements();
      const int * indices = rpv.getIndices();
      double* elements = rpv.getElements();
      double sum2=0.0;
      int k=0;
      for (k=0; k<n; k++){
	int column=indices[k];
	sum2 += colsol[column]*elements[k];
      }

      double ub=rcut.ub();

#ifdef CGL_DEBUG
      double lb=rcut.lb();
      if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
	std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
	for (k=0; k<n; k++){
	  int column=indices[k];
	  std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
	    colsol[column]<<") ";
	}
	std::cout <<std::endl;
      }
#endif

      if (i-nOldCuts==testCut) {
	assert( eq(rhs,ub));
	assert(n==1);
	for (k=0; k<n; k++){
	  int column=indices[k];
	  assert (eq(cut[column],elements[k]));
	}
	// add cut
	rowLower[3]=-1.0e100;
	rowUpper[3]=ub;
	matrix.appendRow(rpv);
      }
    }
    nOldCuts=nRowCuts;
    // basis 2
    int rowBasis2[4]={1,1,-1,-1};
    int colBasis2[2]={1,1};
    warm.setSize(2,4);
    for (i=0;i<4;i++) {
      if (rowBasis2[i]<0) {
	warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setArtifStatus(i,CoinWarmStartBasis::basic);
      }
    }
    for (i=0;i<2;i++) {
      if (colBasis2[i]<0) {
	warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
      } else {
	warm.setStructStatus(i,CoinWarmStartBasis::basic);
      }
    }

    // solution 2
    double colsol2[2]={2.0,0.5};
    test1.generateCuts(NULL, osicuts, matrix,
		 /*objective,*/ colsol2,
		 colLower, colUpper,
		 rowLower, rowUpper, intVar, &warm);
    nRowCuts = osicuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
    assert (nRowCuts==nOldCuts);
    
  }

  // Miplib3 problem p0033
  if (1) {
    // Setup
    OsiSolverInterface  * siP = baseSiP->clone();
    std::string fn(mpsDir+"p0033");
    siP->readMps(fn.c_str(),"mps");
    siP->activateRowCutDebugger("p0033");
    CglGomory test;

    // Solve the LP relaxation of the model and
    // print out ofv for sake of comparison 
    siP->initialSolve();
    double lpRelaxBefore=siP->getObjValue();
    std::cout<<"Initial LP value: "<<lpRelaxBefore<<std::endl;
    assert( eq(lpRelaxBefore, 2520.5717391304347) );

    // Fails with OsiCpx, OsiXpr:
    /**********
    double mycs[] = {0, 1, 0, 0, -2.0837010502455788e-19, 1, 0, 0, 1,
		       0.021739130434782594, 0.35652173913043478, 
		       -6.7220534694101275e-18, 5.3125906451789717e-18, 
		       1, 0, 1.9298798670241979e-17, 0, 0, 0,
		       7.8875708048320448e-18, 0.5, 0, 
		       0.85999999999999999, 1, 1, 0.57999999999999996,
		       1, 0, 1, 0, 0.25, 0, 0.67500000000000004};
    siP->setColSolution(mycs);
    ****/

    OsiCuts cuts;    
    
    // Test generateCuts method
    test.generateCuts(*siP,cuts);
    int nRowCuts = cuts.sizeRowCuts();
    std::cout<<"There are "<<nRowCuts<<" Gomory cuts"<<std::endl;
    assert(cuts.sizeRowCuts() > 0);
    OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cuts);
    
    siP->resolve();
    double lpRelaxAfter=siP->getObjValue(); 
    std::cout<<"LP value with cuts: "<<lpRelaxAfter<<std::endl;
    //assert( eq(lpRelaxAfter, 2592.1908295194507) );
    assert( lpRelaxAfter> 2550.0 );
    assert( lpRelaxBefore < lpRelaxAfter );
    assert(lpRelaxAfter < 3089.1);
    
    delete siP;
  } 
}
Beispiel #3
0
void
OsiPresolve::postsolve(bool updateStatus)
{
  // Messages
  CoinMessages messages = CoinMessage(presolvedModel_->messages().language());
  if (!presolvedModel_->isProvenOptimal()) {
    presolvedModel_->messageHandler()->message(COIN_PRESOLVE_NONOPTIMAL,
					     messages)
					       <<CoinMessageEol;
  }

  // this is the size of the original problem
  const int ncols0  = ncols_;
  const int nrows0  = nrows_;
  const CoinBigIndex nelems0 = nelems_;

  // reality check
  assert(ncols0==originalModel_->getNumCols());
  assert(nrows0==originalModel_->getNumRows());

  // this is the reduced problem
  int ncols = presolvedModel_->getNumCols();
  int nrows = presolvedModel_->getNumRows();

  double *acts = new double [nrows0];
  double *sol = new double [ncols0];
  CoinZeroN(acts,nrows0);
  CoinZeroN(sol,ncols0);

  unsigned char * rowstat=NULL;
  unsigned char * colstat = NULL;
  CoinWarmStartBasis * presolvedBasis  =
    dynamic_cast<CoinWarmStartBasis*>(presolvedModel_->getWarmStart());
  if (!presolvedBasis)
    updateStatus=false;
  if (updateStatus) {
    colstat = new unsigned char[ncols0+nrows0];
#   ifdef ZEROFAULT
    memset(colstat,0,((ncols0+nrows0)*sizeof(char))) ;
#   endif
    rowstat = colstat + ncols0;
    int i;
    for (i=0;i<ncols;i++) {
      colstat[i] = presolvedBasis->getStructStatus(i);
    }
    for (i=0;i<nrows;i++) {
      rowstat[i] = presolvedBasis->getArtifStatus(i);
    }
  }
  delete presolvedBasis;

# if PRESOLVE_CONSISTENCY > 0
  if (updateStatus)
  { int basicCnt = 0 ;
    int i ;
    for (i = 0 ; i < ncols ; i++)
    { if (colstat[i] == CoinWarmStartBasis::basic) basicCnt++ ; }
    for (i = 0 ; i < nrows ; i++)
    { if (rowstat[i] == CoinWarmStartBasis::basic) basicCnt++ ; }

    assert (basicCnt == nrows) ;
  }
# endif

/*
  Postsolve back to the original problem.  The CoinPostsolveMatrix object
  assumes ownership of sol, acts, colstat, and rowstat.
*/
  CoinPostsolveMatrix prob(presolvedModel_, ncols0, nrows0, nelems0,
			   presolvedModel_->getObjSense(),
			   sol, acts, colstat, rowstat);

  postsolve(prob);


# if PRESOLVE_CONSISTENCY > 0
  if (updateStatus)
  { int basicCnt = 0 ;
    int i ;
    for (i = 0 ; i < ncols0 ; i++)
    { if (prob.getColumnStatus(i) == CoinWarmStartBasis::basic) basicCnt++ ; }
    for (i = 0 ; i < nrows0 ; i++)
    { if (prob.getRowStatus(i) == CoinWarmStartBasis::basic) basicCnt++ ; }

    assert (basicCnt == nrows0) ;
  }
# endif

  originalModel_->setColSolution(sol);
  if (updateStatus) {
    CoinWarmStartBasis *basis =
      dynamic_cast<CoinWarmStartBasis *>(presolvedModel_->getEmptyWarmStart());
    basis->setSize(ncols0,nrows0);
    int i;
    for (i=0;i<ncols0;i++) {
      CoinWarmStartBasis::Status status = static_cast<CoinWarmStartBasis::Status> (prob.getColumnStatus(i));
      /* FIXME: these asserts seem correct, but seem to reveal some bugs in CoinPresolve */
      // assert(status != CoinWarmStartBasis::atLowerBound || originalModel_->getColLower()[i] > -originalModel_->getInfinity());
      // assert(status != CoinWarmStartBasis::atUpperBound || originalModel_->getColUpper()[i] <  originalModel_->getInfinity());
      basis->setStructStatus(i,status);
    }
    for (i=0;i<nrows0;i++) {
      CoinWarmStartBasis::Status status = static_cast<CoinWarmStartBasis::Status> (prob.getRowStatus(i));
      /* FIXME: these asserts seem correct, but seem to reveal some bugs in CoinPresolve */
      // assert(status != CoinWarmStartBasis::atUpperBound || originalModel_->getRowLower()[i] > -originalModel_->getInfinity());
      // assert(status != CoinWarmStartBasis::atLowerBound || originalModel_->getRowUpper()[i] <  originalModel_->getInfinity());
      basis->setArtifStatus(i,status);
    }
    originalModel_->setWarmStart(basis);
    delete basis ;
  }

}
Beispiel #4
0
void OsiIF::_loadBasis(
	Array<LPVARSTAT::STATUS> &lpVarStat,
	Array<SlackStat::STATUS> &slackStat)
{
	int lps = lpVarStat.size();
	int sls = slackStat.size();

	CoinWarmStartBasis *ws = nullptr;
	ws = new CoinWarmStartBasis();
	ws->setSize(numCols_, numRows_);

	if (osiLP_->getNumCols() > lps) {
		Logger::ifout() << "OsiIF::_loadBasis: mismatch in number of columns: OSI " << osiLP_->getNumCols() << ", Abacus: " << lps << "\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcOsiIf);
	}
	for (int i = 0; i < numCols_; i++)
		ws->setStructStatus(i, lpVarStat2osi(lpVarStat[i]));

	if (osiLP_->getNumRows() > sls) {
		Logger::ifout() << "OsiIF::_loadBasis: mismatch in number of rows: OSI " << osiLP_->getNumCols() << ", Abacus: " << sls << "\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcOsiIf);
	}
	for (int i = 0; i < numRows_; i++)
		ws->setArtifStatus(i, slackStat2osi(slackStat[i]));

	lpSolverTime_.start();
	slackStatus_ = basisStatus_ = Missing;
	int status = 0;
	// FIXME loadBasis
	// better test whether the number of basic structurals is correct?
	if (ws->numberBasicStructurals() > 0) {
		status = osiLP_->setWarmStart(dynamic_cast<CoinWarmStart *> (ws));
		if (ws_ != nullptr) delete ws_;
		ws_ = dynamic_cast<CoinWarmStartBasis*> (osiLP_->getWarmStart());
		if (ws_ != nullptr) {
			delete[] cStat_;
			int nStructBytes = (int) ceil( ws_->getNumStructural() / 4.0);
			cStat_ = new char[nStructBytes];
			for(int i = 0; i < nStructBytes; i++) {
				cStat_[i] = ws_->getStructuralStatus()[i];
			}

			delete[] rStat_;
			int nArtBytes = (int) ceil( ws_->getNumArtificial() / 4.0 );
			rStat_ = new char[nArtBytes];
			for(int i = 0; i < nArtBytes; i++) {
				rStat_[i] = ws_->getArtificialStatus()[i];
			}

			basisStatus_ = Available;
		} else
			basisStatus_ = Missing;
	} else
		status = 2;
	lpSolverTime_.stop();

	delete ws;

	if (status == 0) {
		Logger::ifout()
			<< "OsiIF::_loadBasis(): loading the new basis has failed. Status "
			<< status << endl;
		// FIXME loadBasis
		return;
	} else
		return;
}