Пример #1
0
/*
  Install the name information from a CoinModel object. CoinModel does not
  maintain a name for the objective function (in fact, it has no concept of
  objective function).
*/
void OsiSolverInterface::setRowColNames (CoinModel &mod)

{ int nameDiscipline,m,n ;
/*
  Determine how we're handling names. It's possible that the underlying solver
  has overridden getIntParam, but doesn't recognise OsiNameDiscipline. In that
  case, we want to default to auto names
*/
  bool recognisesOsiNames = getIntParam(OsiNameDiscipline,nameDiscipline) ;
  if (recognisesOsiNames == false)
  { nameDiscipline = 0 ; }
/*
  Whatever happens, we're about to clean out the current name vectors. Decide
  on an appropriate size and call reallocRowColNames to adjust capacity.
*/
  if (nameDiscipline == 0)
  { m = 0 ;
    n = 0 ; }
  else
  { m = mod.rowNames()->numberItems() ;
    n = mod.columnNames()->numberItems() ; }
  reallocRowColNames(rowNames_,m,colNames_,n) ;
/*
  If name discipline is auto, we're done already. Otherwise, load 'em
  up. As best I can see, there's no guarantee that we'll have names for all
  rows and columns, so we need to pay attention.
*/
  if (nameDiscipline != 0)
  { int maxRowNdx=-1, maxColNdx=-1 ;
    const char *const *names = mod.rowNames()->names() ;
    rowNames_.resize(m) ;
    for (int i = 0 ; i < m ; i++)
    { std::string nme = names[i] ;
      if (nme.length() == 0)
      { if (nameDiscipline == 2)
	{ nme = dfltRowColName('r',i) ; } }
      if (nme.length() > 0)
      { maxRowNdx = i ; }
      rowNames_[i] = nme ; }
    rowNames_.resize(maxRowNdx+1) ;
    names = mod.columnNames()->names() ;
    colNames_.resize(n) ;
    for (int j = 0 ; j < n ; j++)
    { std::string nme = names[j] ;
      if (nme.length() == 0)
      { if (nameDiscipline == 2)
	{ nme = dfltRowColName('c',j) ; } }
      if (nme.length() > 0)
      { maxColNdx = j ; }
      colNames_[j] = nme ; }
    colNames_.resize(maxColNdx+1) ; }
/*
  And we're done.
*/
  return ; }
Пример #2
0
    // nothing to inherit from GC really
    ColoredGraph solve(const Graph& gr) override {

        CoinModel coinModel;
        for (auto i = 0; i < gr.nodeCount(); ++i) {
            coinModel.addCol(0, nullptr, nullptr, 0, gr.nodeCount()-1, 1, nullptr, true);
        }
        OsiClpSolverInterface solver;
        solver.loadFromCoinModel(coinModel);

        CbcModel model(solver);
        model.setLogLevel(0);
        model.passInEventHandler(make_unique<GC_LP_EventHandler>(recoveryPath).get());

        if (use_heuristic) {
            GC_LP_Heuristic heuristic;
            model.addHeuristic(&heuristic);
        }

        AddRules(model, gr);

        if (use_parallel) {
            model.setNumberThreads(std::thread::hardware_concurrency());
        }

        if (max_seconds != 0) model.setMaximumSeconds(max_seconds);

        model.initialSolve();
        model.branchAndBound();

        if (model.maximumSecondsReached()) Println(cout, "max seconds reached");
        if (model.isSecondsLimitReached()) Println(cout, "seconds limit reached");

        seconds_passed_ = model.getCurrentSeconds();
        iterations_passed_ = model.getIterationCount();

        const double *solution = model.bestSolution();

        if (solution == nullptr) {
            vector<Color> colors(gr.nodeCount());
            iota(colors.begin(), colors.end(), 0);
            return {gr, colors};
        }
        return ColoredGraph(gr, {solution, solution+gr.nodeCount()});
    }
Пример #3
0
int main(int argc, const char *argv[])
{
     try {
          // Empty model
          ClpSimplex  model;

          // Objective - just nonzeros
          int objIndex[] = {0, 2};
          double objValue[] = {1.0, 4.0};
          // Upper bounds - as dense vector
          double upper[] = {2.0, COIN_DBL_MAX, 4.0};

          // Create space for 3 columns
          model.resize(0, 3);
          // Fill in
          int i;
          // Virtuous way
          // First objective
          for (i = 0; i < 2; i++)
               model.setObjectiveCoefficient(objIndex[i], objValue[i]);
          // Now bounds (lower will be zero by default but do again)
          for (i = 0; i < 3; i++) {
               model.setColumnLower(i, 0.0);
               model.setColumnUpper(i, upper[i]);
          }
          /*
            We could also have done in non-virtuous way e.g.
            double * objective = model.objective();
            and then set directly
          */
          // Faster to add rows all at once - but this is easier to show
          // Now add row 1 as >= 2.0
          int row1Index[] = {0, 2};
          double row1Value[] = {1.0, 1.0};
          model.addRow(2, row1Index, row1Value,
                       2.0, COIN_DBL_MAX);
          // Now add row 2 as == 1.0
          int row2Index[] = {0, 1, 2};
          double row2Value[] = {1.0, -5.0, 1.0};
          model.addRow(3, row2Index, row2Value,
                       1.0, 1.0);
          // solve
          model.dual();

          /*
            Adding one row at a time has a significant overhead so let's
            try a more complicated but faster way

            First time adding in 10000 rows one by one
          */
          model.allSlackBasis();
          ClpSimplex modelSave = model;
          double time1 = CoinCpuTime();
          int k;
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -5.0, 1.0};
               model.addRow(3, row2Index, row2Value,
                            1.0, 1.0);
          }
          printf("Time for 10000 addRow is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = modelSave;
          // Now use build
          CoinBuild buildObject;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -5.0, 1.0};
               buildObject.addRow(3, row2Index, row2Value,
                                  1.0, 1.0);
          }
          model.addRows(buildObject);
          printf("Time for 10000 addRow using CoinBuild is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = modelSave;
          int del[] = {0, 1, 2};
          model.deleteRows(2, del);
          // Now use build +-1
          CoinBuild buildObject2;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -1.0, 1.0};
               buildObject2.addRow(3, row2Index, row2Value,
                                   1.0, 1.0);
          }
          model.addRows(buildObject2, true);
          printf("Time for 10000 addRow using CoinBuild+-1 is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = modelSave;
          model.deleteRows(2, del);
          // Now use build +-1
          CoinModel modelObject2;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -1.0, 1.0};
               modelObject2.addRow(3, row2Index, row2Value,
                                   1.0, 1.0);
          }
          model.addRows(modelObject2, true);
          printf("Time for 10000 addRow using CoinModel+-1 is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = ClpSimplex();
          // Now use build +-1
          CoinModel modelObject3;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -1.0, 1.0};
               modelObject3.addRow(3, row2Index, row2Value,
                                   1.0, 1.0);
          }
          model.loadProblem(modelObject3, true);
          printf("Time for 10000 addRow using CoinModel load +-1 is %g\n", CoinCpuTime() - time1);
          model.writeMps("xx.mps");
          model.dual();
          model = modelSave;
          // Now use model
          CoinModel modelObject;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -5.0, 1.0};
               modelObject.addRow(3, row2Index, row2Value,
                                  1.0, 1.0);
          }
          model.addRows(modelObject);
          printf("Time for 10000 addRow using CoinModel is %g\n", CoinCpuTime() - time1);
          model.dual();
          model.writeMps("b.mps");
          // Method using least memory - but most complicated
          time1 = CoinCpuTime();
          // Assumes we know exact size of model and matrix
          // Empty model
          ClpSimplex  model2;
          {
               // Create space for 3 columns and 10000 rows
               int numberRows = 10000;
               int numberColumns = 3;
               // This is fully dense - but would not normally be so
               int numberElements = numberRows * numberColumns;
               // Arrays will be set to default values
               model2.resize(numberRows, numberColumns);
               double * elements = new double [numberElements];
               CoinBigIndex * starts = new CoinBigIndex [numberColumns+1];
               int * rows = new int [numberElements];;
               int * lengths = new int[numberColumns];
               // Now fill in - totally unsafe but ....
               // no need as defaults to 0.0 double * columnLower = model2.columnLower();
               double * columnUpper = model2.columnUpper();
               double * objective = model2.objective();
               double * rowLower = model2.rowLower();
               double * rowUpper = model2.rowUpper();
               // Columns - objective was packed
               for (k = 0; k < 2; k++) {
                    int iColumn = objIndex[k];
                    objective[iColumn] = objValue[k];
               }
               for (k = 0; k < numberColumns; k++)
                    columnUpper[k] = upper[k];
               // Rows
               for (k = 0; k < numberRows; k++) {
                    rowLower[k] = 1.0;
                    rowUpper[k] = 1.0;
               }
               // Now elements
               double row2Value[] = {1.0, -5.0, 1.0};
               CoinBigIndex put = 0;
               for (k = 0; k < numberColumns; k++) {
                    starts[k] = put;
                    lengths[k] = numberRows;
                    double value = row2Value[k];
                    for (int i = 0; i < numberRows; i++) {
                         rows[put] = i;
                         elements[put] = value;
                         put++;
                    }
               }
               starts[numberColumns] = put;
               // assign to matrix
               CoinPackedMatrix * matrix = new CoinPackedMatrix(true, 0.0, 0.0);
               matrix->assignMatrix(true, numberRows, numberColumns, numberElements,
                                    elements, rows, starts, lengths);
               ClpPackedMatrix * clpMatrix = new ClpPackedMatrix(matrix);
               model2.replaceMatrix(clpMatrix, true);
               printf("Time for 10000 addRow using hand written code is %g\n", CoinCpuTime() - time1);
               // If matrix is really big could switch off creation of row copy
               // model2.setSpecialOptions(256);
          }
          model2.dual();
          model2.writeMps("a.mps");
          // Print column solution
          int numberColumns = model.numberColumns();

          // Alternatively getColSolution()
          double * columnPrimal = model.primalColumnSolution();
          // Alternatively getReducedCost()
          double * columnDual = model.dualColumnSolution();
          // Alternatively getColLower()
          double * columnLower = model.columnLower();
          // Alternatively getColUpper()
          double * columnUpper = model.columnUpper();
          // Alternatively getObjCoefficients()
          double * columnObjective = model.objective();

          int iColumn;

          std::cout << "               Primal          Dual         Lower         Upper          Cost"
                    << std::endl;

          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
               double value;
               std::cout << std::setw(6) << iColumn << " ";
               value = columnPrimal[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnDual[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnLower[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnUpper[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnObjective[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value;

               std::cout << std::endl;
          }
          std::cout << "--------------------------------------" << std::endl;
          // Test CoinAssert
          std::cout << "If Clp compiled with -g below should give assert, if with -O1 or COIN_ASSERT CoinError" << std::endl;
          model = modelSave;
          model.deleteRows(2, del);
          // Deliberate error
          model.deleteColumns(1, del + 2);
          // Now use build +-1
          CoinBuild buildObject3;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int row2Index[] = {0, 1, 2};
               double row2Value[] = {1.0, -1.0, 1.0};
               buildObject3.addRow(3, row2Index, row2Value,
                                   1.0, 1.0);
          }
          model.addRows(buildObject3, true);
     } catch (CoinError e) {
          e.print();
          if (e.lineNumber() >= 0)
               std::cout << "This was from a CoinAssert" << std::endl;
     }
     return 0;
}
Пример #4
0
//--------------------------------------------------------------------------
// test solution methods.
void OsiCbcSolverInterfaceUnitTest(const std::string & mpsDir, const std::string & netlibDir)
{
  {    
    CoinRelFltEq eq;
    OsiCbcSolverInterface m;
    std::string fn = mpsDir+"exmip1";
    m.readMps(fn.c_str(),"mps");

    {
      OsiCbcSolverInterface im;    
      OSIUNITTEST_ASSERT_ERROR(im.getNumCols() == 0, {}, "cbc", "default constructor");
      OSIUNITTEST_ASSERT_ERROR(im.getModelPtr() != NULL, {}, "cbc", "default constructor");
    }
    
    // Test copy constructor and assignment operator
    {
      OsiCbcSolverInterface lhs;
      {      
        OsiCbcSolverInterface im(m);        
        
        OsiCbcSolverInterface imC1(im);
        OSIUNITTEST_ASSERT_ERROR(imC1.getModelPtr() != im.getModelPtr(), {}, "cbc", "copy constructor");
        OSIUNITTEST_ASSERT_ERROR(imC1.getNumCols()  == im.getNumCols(),  {}, "cbc", "copy constructor");
        OSIUNITTEST_ASSERT_ERROR(imC1.getNumRows()  == im.getNumRows(),  {}, "cbc", "copy constructor");
        
        OsiCbcSolverInterface imC2(im);
        OSIUNITTEST_ASSERT_ERROR(imC2.getModelPtr() != im.getModelPtr(), {}, "cbc", "copy constructor");
        OSIUNITTEST_ASSERT_ERROR(imC2.getNumCols()  == im.getNumCols(),  {}, "cbc", "copy constructor");
        OSIUNITTEST_ASSERT_ERROR(imC2.getNumRows()  == im.getNumRows(),  {}, "cbc", "copy constructor");

        OSIUNITTEST_ASSERT_ERROR(imC1.getModelPtr() != imC2.getModelPtr(), {}, "cbc", "copy constructor");
        
        lhs = imC2;
      }

      // Test that lhs has correct values even though rhs has gone out of scope
      OSIUNITTEST_ASSERT_ERROR(lhs.getModelPtr() != m.getModelPtr(), {}, "cbc", "assignment operator");
      OSIUNITTEST_ASSERT_ERROR(lhs.getNumCols()  == m.getNumCols(),  {}, "cbc", "copy constructor");
      OSIUNITTEST_ASSERT_ERROR(lhs.getNumRows()  == m.getNumRows(),  {}, "cbc", "copy constructor");
    }

    // Test clone
    {
      OsiCbcSolverInterface cbcSi(m);
      OsiSolverInterface * siPtr = &cbcSi;
      OsiSolverInterface * siClone = siPtr->clone();
      OsiCbcSolverInterface * cbcClone = dynamic_cast<OsiCbcSolverInterface*>(siClone);

      OSIUNITTEST_ASSERT_ERROR(cbcClone != NULL, {}, "cbc", "clone");
      OSIUNITTEST_ASSERT_ERROR(cbcClone->getModelPtr() != cbcSi.getModelPtr(), {}, "cbc", "clone");
      OSIUNITTEST_ASSERT_ERROR(cbcClone->getNumRows() == cbcSi.getNumRows(),   {}, "cbc", "clone");
      OSIUNITTEST_ASSERT_ERROR(cbcClone->getNumCols() == m.getNumCols(),       {}, "cbc", "clone");
      
      delete siClone;
    }
  
    // test infinity
    {
      OsiCbcSolverInterface si;
      OSIUNITTEST_ASSERT_ERROR(si.getInfinity() == OsiCbcInfinity, {}, "cbc", "infinity");
    }     
    
    // Test some catches
    if (!OsiCbcHasNDEBUG())
    {
      OsiCbcSolverInterface solver;
      try {
        solver.setObjCoeff(0,0.0);
        OSIUNITTEST_ADD_OUTCOME("cbc", "setObjCoeff on empty model", "should throw exception", OsiUnitTest::TestOutcome::ERROR, false);
      }
      catch (CoinError e) {
        if (OsiUnitTest::verbosity >= 1)
          std::cout<<"Correct throw from setObjCoeff on empty model"<<std::endl;
      }

      std::string fn = mpsDir+"exmip1";
      solver.readMps(fn.c_str(),"mps");
      OSIUNITTEST_CATCH_ERROR(solver.setObjCoeff(0,0.0), {}, "cbc", "setObjCoeff on nonempty model");

      try {
        int index[]={0,20};
        double value[]={0.0,0.0,0.0,0.0};
        solver.setColSetBounds(index,index+2,value);
        OSIUNITTEST_ADD_OUTCOME("cbc", "setColSetBounds on cols not in model", "should throw exception", OsiUnitTest::TestOutcome::ERROR, false);
      }
      catch (CoinError e) {
        if (OsiUnitTest::verbosity >= 1)
          std::cout<<"Correct throw from setObjCoeff on empty model"<<std::endl;
      }
    }
    
    {    
      OsiCbcSolverInterface cbcSi(m);
      int nc = cbcSi.getNumCols();
      int nr = cbcSi.getNumRows();
      const double * cl = cbcSi.getColLower();
      const double * cu = cbcSi.getColUpper();
      const double * rl = cbcSi.getRowLower();
      const double * ru = cbcSi.getRowUpper();
      OSIUNITTEST_ASSERT_ERROR(nc == 8, return, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(nr == 5, return, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cl[0],2.5), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cl[1],0.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cu[1],4.1), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cu[2],1.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(rl[0],2.5), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(rl[4],3.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(ru[1],2.1), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(ru[4],15.), {}, "cbc", "read and copy exmip1");
      
      const double * cs = cbcSi.getColSolution();
      OSIUNITTEST_ASSERT_ERROR(eq(cs[0],2.5), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cs[7],0.0), {}, "cbc", "read and copy exmip1");
      
      OSIUNITTEST_ASSERT_ERROR(!eq(cl[3],1.2345), {}, "cbc", "set col lower");
      cbcSi.setColLower( 3, 1.2345 );
      OSIUNITTEST_ASSERT_ERROR( eq(cbcSi.getColLower()[3],1.2345), {}, "cbc", "set col lower");
      
      OSIUNITTEST_ASSERT_ERROR(!eq(cbcSi.getColUpper()[4],10.2345), {}, "cbc", "set col upper");
      cbcSi.setColUpper( 4, 10.2345 );
      OSIUNITTEST_ASSERT_ERROR( eq(cbcSi.getColUpper()[4],10.2345), {}, "cbc", "set col upper");

      // LH: Objective will depend on how underlying solver constructs and maintains initial solution
      double objValue = cbcSi.getObjValue();
      OSIUNITTEST_ASSERT_ERROR(eq(objValue,3.5) || eq(objValue,10.5), {}, "cbc", "getObjValue() before solve");

      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[0], 1.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[1], 0.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[2], 0.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[3], 0.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[4], 2.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[5], 0.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[6], 0.0), {}, "cbc", "read and copy exmip1");
      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[7],-1.0), {}, "cbc", "read and copy exmip1");
    }
    
    // Test matrixByRow method
    { 
      const OsiCbcSolverInterface si(m);
      const CoinPackedMatrix * smP = si.getMatrixByRow();

      OSIUNITTEST_ASSERT_ERROR(smP->getMajorDim()    ==  5, return, "cbc", "getMatrixByRow: major dim");
      OSIUNITTEST_ASSERT_ERROR(smP->getMinorDim()    ==  8, return, "cbc", "getMatrixByRow: major dim");
      OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "cbc", "getMatrixByRow: num elements");
      OSIUNITTEST_ASSERT_ERROR(smP->getSizeVectorStarts() == 6, return, "cbc", "getMatrixByRow: num elements");

#ifdef OSICBC_TEST_MTX_STRUCTURE
      CoinRelFltEq eq;
      const double * ev = smP->getElements();
      OSIUNITTEST_ASSERT_ERROR(eq(ev[0],   3.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[1],   1.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[2],  -2.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[3],  -1.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[4],  -1.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[5],   2.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[6],   1.1), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[7],   1.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[8],   1.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[9],   2.8), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[10], -1.2), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[11],  5.6), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[12],  1.0), {}, "cbc", "getMatrixByRow: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[13],  1.9), {}, "cbc", "getMatrixByRow: elements");
      
      const int * mi = smP->getVectorStarts();
      OSIUNITTEST_ASSERT_ERROR(mi[0] ==  0, {}, "cbc", "getMatrixByRow: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[1] ==  5, {}, "cbc", "getMatrixByRow: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[2] ==  7, {}, "cbc", "getMatrixByRow: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[3] ==  9, {}, "cbc", "getMatrixByRow: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "cbc", "getMatrixByRow: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "cbc", "getMatrixByRow: vector starts");
      
      const int * ei = smP->getIndices();
      OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "cbc", "getMatrixByRow: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "cbc", "getMatrixByRow: indices");
#else	// OSICBC_TEST_MTX_STRUCTURE

      CoinPackedMatrix exmip1Mtx ;
      exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx()) ;
      OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*smP), {}, "cbc", "getMatrixByRow") ;
#endif	// OSICBC_TEST_MTX_STRUCTURE
    }

    // Test adding several cuts, and handling of a coefficient of infinity
    // in the constraint matrix.
    {
      OsiCbcSolverInterface fim;
      std::string fn = mpsDir+"exmip1";
      fim.readMps(fn.c_str(),"mps");
      // exmip1.mps has 2 integer variables with index 2 & 3
      fim.initialSolve();
      OsiRowCut cuts[3];
      
      
      // Generate one ineffective cut plus two trivial cuts
      int c;
      int nc = fim.getNumCols();
      int *inx = new int[nc];
      for (c=0;c<nc;c++) inx[c]=c;
      double *el = new double[nc];
      for (c=0;c<nc;c++) el[c]=1.0e-50+((double)c)*((double)c);
      
      cuts[0].setRow(nc,inx,el);
      cuts[0].setLb(-100.);
      cuts[0].setUb(500.);
      cuts[0].setEffectiveness(22);
      el[4]=0.0; // to get inf later
      
      for (c=2;c<4;c++) {
        el[0]=1.0;
        inx[0]=c;
        cuts[c-1].setRow(1,inx,el);
        cuts[c-1].setLb(1.);
        cuts[c-1].setUb(100.);
        cuts[c-1].setEffectiveness(c);
      }
      fim.writeMps("x1.mps");
      fim.applyRowCuts(3,cuts);
      fim.writeMps("x2.mps");
      // resolve - should get message about zero elements
      fim.resolve();
      fim.writeMps("x3.mps");
      // check integer solution
      const double * cs = fim.getColSolution();
      CoinRelFltEq eq;
      OSIUNITTEST_ASSERT_ERROR(eq(cs[2], 1.0), {}, "cbc", "add cuts");
      OSIUNITTEST_ASSERT_ERROR(eq(cs[3], 1.0), {}, "cbc", "add cuts");
      // check will find invalid matrix
      el[0]=1.0/el[4];
      inx[0]=0;
      cuts[0].setRow(nc,inx,el);
      cuts[0].setLb(-100.);
      cuts[0].setUb(500.);
      cuts[0].setEffectiveness(22);
      fim.applyRowCut(cuts[0]);
      // resolve - should get message about zero elements
      fim.resolve();
      OSIUNITTEST_ASSERT_WARNING(fim.isAbandoned(), {}, "cbc", "add cuts");
      delete[]el;
      delete[]inx;
    }

    // Test matrixByCol method
    {
      const OsiCbcSolverInterface si(m);
      const CoinPackedMatrix * smP = si.getMatrixByCol();

      OSIUNITTEST_ASSERT_ERROR(smP->getMajorDim()    ==  8, return, "cbc", "getMatrixByCol: major dim");
      OSIUNITTEST_ASSERT_ERROR(smP->getMinorDim()    ==  5, return, "cbc", "getMatrixByCol: minor dim");
      OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "cbc", "getMatrixByCol: number of elements");
      OSIUNITTEST_ASSERT_ERROR(smP->getSizeVectorStarts() == 9, return, "cbc", "getMatrixByCol: vector starts size");

#ifdef OSICBC_TEST_MTX_STRUCTURE
      CoinRelFltEq eq;
      const double * ev = smP->getElements();
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 5.6), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2], 1.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3], 2.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4], 1.1), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 1.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6],-2.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 2.8), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8],-1.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 1.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[10], 1.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[11],-1.2), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[12],-1.0), {}, "cbc", "getMatrixByCol: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "getMatrixByCol: elements");
      
      const CoinBigIndex * mi = smP->getVectorStarts();
      OSIUNITTEST_ASSERT_ERROR(mi[0] ==  0, {}, "cbc", "getMatrixByCol: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[1] ==  2, {}, "cbc", "getMatrixByCol: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[2] ==  4, {}, "cbc", "getMatrixByCol: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[3] ==  6, {}, "cbc", "getMatrixByCol: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[4] ==  8, {}, "cbc", "getMatrixByCol: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[5] == 10, {}, "cbc", "getMatrixByCol: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[6] == 11, {}, "cbc", "getMatrixByCol: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[7] == 12, {}, "cbc", "getMatrixByCol: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[8] == 14, {}, "cbc", "getMatrixByCol: vector starts");
      
      const int * ei = smP->getIndices();
      OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 4, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 0, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 1, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 1, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 2, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 0, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 3, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 0, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 4, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[10] == 2, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[11] == 3, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[12] == 0, {}, "cbc", "getMatrixByCol: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[13] == 4, {}, "cbc", "getMatrixByCol: indices");
#else // OSICBC_TEST_MTX_STRUCTURE

      CoinPackedMatrix &exmip1Mtx = BuildExmip1Mtx() ;
      OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*smP), {}, "cbc", "getMatrixByCol");
#endif	// OSICBC_TEST_MTX_STRUCTURE     
    }

    //--------------
    // Test rowsense, rhs, rowrange, matrixByRow, solver assignment
    {
      OsiCbcSolverInterface lhs;
      {
        OsiCbcSolverInterface siC1(m);

        const char   * siC1rs  = siC1.getRowSense();
        OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "cbc", "row sense");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "cbc", "row sense");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "cbc", "row sense");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "cbc", "row sense");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "cbc", "row sense");

        const double * siC1rhs = siC1.getRightHandSide();
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "cbc", "right hand side");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "cbc", "right hand side");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "cbc", "right hand side");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "cbc", "right hand side");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "cbc", "right hand side");

        const double * siC1rr  = siC1.getRowRange();
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "cbc", "row range");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "cbc", "row range");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "cbc", "row range");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "cbc", "row range");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "cbc", "row range");
        
        const CoinPackedMatrix * siC1mbr = siC1.getMatrixByRow();
        OSIUNITTEST_ASSERT_ERROR(siC1mbr != NULL, {}, "cbc", "matrix by row");
        OSIUNITTEST_ASSERT_ERROR(siC1mbr->getMajorDim()    ==  5, return, "cbc", "matrix by row: major dim");
        OSIUNITTEST_ASSERT_ERROR(siC1mbr->getMinorDim()    ==  8, return, "cbc", "matrix by row: major dim");
        OSIUNITTEST_ASSERT_ERROR(siC1mbr->getNumElements() == 14, return, "cbc", "matrix by row: num elements");
        OSIUNITTEST_ASSERT_ERROR(siC1mbr->getSizeVectorStarts() == 6, return, "cbc", "matrix by row: num elements");

#ifdef OSICBC_TEST_MTX_STRUCTURE
        const double * ev = siC1mbr->getElements();
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 1.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3],-1.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4],-1.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 2.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 1.1), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 2.8), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[10],-1.2), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "cbc", "matrix by row: elements");
        OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "matrix by row: elements");

        const CoinBigIndex * mi = siC1mbr->getVectorStarts();
        OSIUNITTEST_ASSERT_ERROR(mi[0] ==  0, {}, "cbc", "matrix by row: vector starts");
        OSIUNITTEST_ASSERT_ERROR(mi[1] ==  5, {}, "cbc", "matrix by row: vector starts");
        OSIUNITTEST_ASSERT_ERROR(mi[2] ==  7, {}, "cbc", "matrix by row: vector starts");
        OSIUNITTEST_ASSERT_ERROR(mi[3] ==  9, {}, "cbc", "matrix by row: vector starts");
        OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "cbc", "matrix by row: vector starts");
        OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "cbc", "matrix by row: vector starts");

        const int * ei = siC1mbr->getIndices();
        OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "cbc", "matrix by row: indices");
        OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "cbc", "matrix by row: indices");
#else	// OSICBC_TEST_MTX_STRUCTURE

        CoinPackedMatrix exmip1Mtx ;
        exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx()) ;
        OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*siC1mbr), {}, "cbc", "matrix by row");
#endif	// OSICBC_TEST_MTX_STRUCTURE

        OSIUNITTEST_ASSERT_WARNING(siC1rs  == siC1.getRowSense(), {}, "cbc", "row sense");
        OSIUNITTEST_ASSERT_WARNING(siC1rhs == siC1.getRightHandSide(), {}, "cbc", "right hand side");
        OSIUNITTEST_ASSERT_WARNING(siC1rr  == siC1.getRowRange(), {}, "cbc", "row range");

        // Change CBC Model by adding free row
        OsiRowCut rc;
        rc.setLb(-COIN_DBL_MAX);
        rc.setUb( COIN_DBL_MAX);
        OsiCuts cuts;
        cuts.insert(rc);
        siC1.applyCuts(cuts);

        siC1rs  = siC1.getRowSense();
        OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "cbc", "row sense after adding row");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "cbc", "row sense after adding row");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "cbc", "row sense after adding row");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "cbc", "row sense after adding row");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "cbc", "row sense after adding row");
        OSIUNITTEST_ASSERT_ERROR(siC1rs[5] == 'N', {}, "cbc", "row sense after adding row");

        siC1rhs = siC1.getRightHandSide();
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "cbc", "right hand side after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "cbc", "right hand side after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "cbc", "right hand side after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "cbc", "right hand side after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "cbc", "right hand side after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[5],0.0), {}, "cbc", "right hand side after adding row");

        siC1rr  = siC1.getRowRange();
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "cbc", "row range after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "cbc", "row range after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "cbc", "row range after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "cbc", "row range after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "cbc", "row range after adding row");
        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[5],0.0), {}, "cbc", "row range after adding row");

        lhs = siC1;
      }

      // Test that lhs has correct values even though siC1 has gone out of scope    
      const char * lhsrs  = lhs.getRowSense();
      OSIUNITTEST_ASSERT_ERROR(lhsrs[0] == 'G', {}, "cbc", "row sense after assignment");
      OSIUNITTEST_ASSERT_ERROR(lhsrs[1] == 'L', {}, "cbc", "row sense after assignment");
      OSIUNITTEST_ASSERT_ERROR(lhsrs[2] == 'E', {}, "cbc", "row sense after assignment");
      OSIUNITTEST_ASSERT_ERROR(lhsrs[3] == 'R', {}, "cbc", "row sense after assignment");
      OSIUNITTEST_ASSERT_ERROR(lhsrs[4] == 'R', {}, "cbc", "row sense after assignment");
      OSIUNITTEST_ASSERT_ERROR(lhsrs[5] == 'N', {}, "cbc", "row sense after assignment");
      
      const double * lhsrhs = lhs.getRightHandSide();
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[0],2.5), {}, "cbc", "right hand side after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[1],2.1), {}, "cbc", "right hand side after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[2],4.0), {}, "cbc", "right hand side after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[3],5.0), {}, "cbc", "right hand side after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[4],15.), {}, "cbc", "right hand side after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[5],0.0), {}, "cbc", "right hand side after assignment");
      
      const double *lhsrr = lhs.getRowRange();
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[0],0.0), {}, "cbc", "row range after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[1],0.0), {}, "cbc", "row range after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[2],0.0), {}, "cbc", "row range after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[3],5.0-1.8), {}, "cbc", "row range after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[4],15.0-3.0), {}, "cbc", "row range after assignment");
      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[5],0.0), {}, "cbc", "row range after assignment");
      
      const CoinPackedMatrix * lhsmbr = lhs.getMatrixByRow();
      OSIUNITTEST_ASSERT_ERROR(lhsmbr != NULL, {}, "cbc", "matrix by row after assignment");
      OSIUNITTEST_ASSERT_ERROR(lhsmbr->getMajorDim()    ==  6, return, "cbc", "matrix by row after assignment: major dim");
      OSIUNITTEST_ASSERT_ERROR(lhsmbr->getNumElements() == 14, return, "cbc", "matrix by row after assignment: num elements");


#ifdef OSICBC_TEST_MTX_STRUCTURE
      const double * ev = lhsmbr->getElements();
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 1.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3],-1.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4],-1.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 2.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 1.1), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 2.8), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[10],-1.2), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "cbc", "matrix by row after assignment: elements");
      OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "matrix by row after assignment: elements");
      
      const CoinBigIndex * mi = lhsmbr->getVectorStarts();
      OSIUNITTEST_ASSERT_ERROR(mi[0] ==  0, {}, "cbc", "matrix by row after assignment: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[1] ==  5, {}, "cbc", "matrix by row after assignment: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[2] ==  7, {}, "cbc", "matrix by row after assignment: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[3] ==  9, {}, "cbc", "matrix by row after assignment: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "cbc", "matrix by row after assignment: vector starts");
      OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "cbc", "matrix by row after assignment: vector starts");
      
      const int * ei = lhsmbr->getIndices();
      OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "cbc", "matrix by row after assignment: indices");
      OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "cbc", "matrix by row after assignment: indices");
#else	// OSICBC_TEST_MTX_STRUCTURE

/*
  This admittedly looks bogus, but it's the equivalent operation on the matrix
  for inserting a cut of the form -Inf <= +Inf (i.e., a cut with no
  coefficients).
*/
      CoinPackedMatrix exmip1Mtx ;
      exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx()) ;
      CoinPackedVector freeRow ;
      exmip1Mtx.appendRow(freeRow) ;
      OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*lhsmbr), {}, "cbc", "matrix by row after assignment");
#endif	// OSICBC_TEST_MTX_STRUCTURE
    }
  }

  // Test add/delete columns
  {    
    OsiCbcSolverInterface m;
    std::string fn = mpsDir+"p0033";
    m.readMps(fn.c_str(),"mps");
    double inf = m.getInfinity();

    CoinPackedVector c0;
    c0.insert(0, 4);
    c0.insert(1, 1);
    m.addCol(c0, 0, inf, 3);
    m.initialSolve();
    double objValue = m.getObjValue();
    CoinRelFltEq eq(1.0e-2);
    OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "cbc", "objvalue after adding col");

    // Try deleting first column that's nonbasic at lower bound (0).
    int * d = new int[1];
    CoinWarmStartBasis *cwsb = dynamic_cast<CoinWarmStartBasis *>(m.getWarmStart()) ;
    OSIUNITTEST_ASSERT_ERROR(cwsb != NULL, {}, "cbc", "get warmstart basis");
    CoinWarmStartBasis::Status stati ;
    int iCol ;
    for (iCol = 0 ;  iCol < cwsb->getNumStructural() ; iCol++)
    { stati = cwsb->getStructStatus(iCol) ;
      if (stati == CoinWarmStartBasis::atLowerBound) break ; }
    d[0]=iCol;
    m.deleteCols(1,d);
    delete [] d;
    delete cwsb;
    d=NULL;
    m.resolve();
    objValue = m.getObjValue();
    OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "clp", "objvalue after deleting first col");

    // Try deleting column we added. If basic, go to initialSolve as deleting
    // basic variable trashes basis required for warm start.
    iCol = m.getNumCols()-1;
    cwsb = dynamic_cast<CoinWarmStartBasis *>(m.getWarmStart()) ;
    stati =  cwsb->getStructStatus(iCol) ;
    delete cwsb;
    m.deleteCols(1,&iCol);
    if (stati == CoinWarmStartBasis::basic)
    { m.initialSolve() ; }
    else
    { m.resolve(); }
    objValue = m.getObjValue();
    OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "clp", "objvalue after deleting added col");
  }

  // Build a model
  {    
    OsiCbcSolverInterface model;
    std::string fn = mpsDir+"p0033";
    model.readMps(fn.c_str(),"mps");
    // Point to data
    int numberRows = model.getNumRows();
    const double * rowLower = model.getRowLower();
    const double * rowUpper = model.getRowUpper();
    int numberColumns = model.getNumCols();
    const double * columnLower = model.getColLower();
    const double * columnUpper = model.getColUpper();
    const double * columnObjective = model.getObjCoefficients();
    // get row copy
    CoinPackedMatrix rowCopy = *model.getMatrixByRow();
    const int * column = rowCopy.getIndices();
    const int * rowLength = rowCopy.getVectorLengths();
    const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
    const double * element = rowCopy.getElements();
    
    // solve
    model.initialSolve();
    // Now build new model
    CoinModel build;
    // Row bounds
    int iRow;
    for (iRow=0;iRow<numberRows;iRow++) {
      build.setRowBounds(iRow,rowLower[iRow],rowUpper[iRow]);
    }
    // Column bounds and objective
    int iColumn;
    for (iColumn=0;iColumn<numberColumns;iColumn++) {
      build.setColumnLower(iColumn,columnLower[iColumn]);
      build.setColumnUpper(iColumn,columnUpper[iColumn]);
      build.setObjective(iColumn,columnObjective[iColumn]);
    }
    // Adds elements one by one by row (backwards by row)
    for (iRow=numberRows-1;iRow>=0;iRow--) {
      int start = rowStart[iRow];
      for (int j=start;j<start+rowLength[iRow];j++) 
        build(iRow,column[j],element[j]);
    }
    // Now create Model
    OsiCbcSolverInterface model2;
    model2.loadFromCoinModel(build);
    model2.initialSolve();
    // Save - should be continuous
    model2.writeMps("continuous");
    int * whichInteger = new int[numberColumns];
    for (iColumn=0;iColumn<numberColumns;iColumn++) 
      whichInteger[iColumn]=iColumn;
    // mark as integer
    model2.setInteger(whichInteger,numberColumns);
    delete [] whichInteger;
    // save - should be integer
    model2.writeMps("integer");
    
    // Now do with strings attached
    // Save build to show how to go over rows
    CoinModel saveBuild = build;
    build = CoinModel();
    // Column bounds
    for (iColumn=0;iColumn<numberColumns;iColumn++) {
      build.setColumnLower(iColumn,columnLower[iColumn]);
      build.setColumnUpper(iColumn,columnUpper[iColumn]);
    }
    // Objective - half the columns as is and half with multiplier of "1.0+multiplier"
    // Pick up from saveBuild (for no reason at all)
    for (iColumn=0;iColumn<numberColumns;iColumn++) {
      double value = saveBuild.objective(iColumn);
      if (iColumn*2<numberColumns) {
        build.setObjective(iColumn,columnObjective[iColumn]);
      } else {
        // create as string
        char temp[100];
        sprintf(temp,"%g + abs(%g*multiplier)",value,value);
        build.setObjective(iColumn,temp);
      }
    }
    // It then adds rows one by one but for half the rows sets their values
    //      with multiplier of "1.0+1.5*multiplier"
    for (iRow=0;iRow<numberRows;iRow++) {
      if (iRow*2<numberRows) {
        // add row in simple way
        int start = rowStart[iRow];
        build.addRow(rowLength[iRow],column+start,element+start,
                     rowLower[iRow],rowUpper[iRow]);
      } else {
        // As we have to add one by one let's get from saveBuild
        CoinModelLink triple=saveBuild.firstInRow(iRow);
        while (triple.column()>=0) {
          int iColumn = triple.column();
          if (iColumn*2<numberColumns) {
            // just value as normal
            build(iRow,triple.column(),triple.value());
          } else {
            // create as string
            char temp[100];
            sprintf(temp,"%g + (1.5*%g*multiplier)",triple.value(), triple.value());
            build(iRow,iColumn,temp);
          }
          triple=saveBuild.next(triple);
        }
        // but remember to do rhs
        build.setRowLower(iRow,rowLower[iRow]);
        build.setRowUpper(iRow,rowUpper[iRow]);
      }
    }
    // If small switch on error printing
    if (numberColumns<50)
      build.setLogLevel(1);
    // should fail as we never set multiplier
    OSIUNITTEST_ASSERT_ERROR(model2.loadFromCoinModel(build) != 0, {}, "cbc", "build model with missing multipliers");
    build.associateElement("multiplier",0.0);
    OSIUNITTEST_ASSERT_ERROR(model2.loadFromCoinModel(build) == 0, {}, "cbc", "build model");
    model2.initialSolve();
    // It then loops with multiplier going from 0.0 to 2.0 in increments of 0.1
    for (double multiplier=0.0;multiplier<2.0;multiplier+= 0.1) {
      build.associateElement("multiplier",multiplier);
      OSIUNITTEST_ASSERT_ERROR(model2.loadFromCoinModel(build,true) == 0, {}, "cbc", "build model with increasing multiplier");
      model2.resolve();
    }
  }

  // branch and bound
  {    
    OsiCbcSolverInterface m;
    std::string fn = mpsDir+"p0033";
    m.readMps(fn.c_str(),"mps");
    m.initialSolve();
    //m.messageHandler()->setLogLevel(0);
    m.getModelPtr()->messageHandler()->setLogLevel(0);
    m.branchAndBound();
  }

  // branch and bound using CbcModel!!!!!!!
  {    
    OsiCbcSolverInterface mm;
    OsiCbcSolverInterface m(&mm);
    std::string fn = mpsDir+"p0033";
    m.readMps(fn.c_str(),"mps");
    m.initialSolve();
    m.branchAndBound();
  }

  // Do common solverInterface testing 
  {
    OsiCbcSolverInterface m;
    OsiSolverInterfaceCommonUnitTest(&m, mpsDir,netlibDir);
  }
  {
    OsiCbcSolverInterface mm;
    OsiCbcSolverInterface m(&mm);
    OsiSolverInterfaceCommonUnitTest(&m, mpsDir,netlibDir);
  }
}
Пример #5
0
//--------------------------------------------------------------------------
// Test building a model
void
CoinModelUnitTest(const std::string & mpsDir,
                  const std::string & netlibDir, const std::string & testModel)
{

    // Get a model
    CoinMpsIO m;
    std::string fn = mpsDir+"exmip1";
    int numErr = m.readMps(fn.c_str(),"mps");
    assert( numErr== 0 );

    int numberRows = m.getNumRows();
    int numberColumns = m.getNumCols();

    // Build by row from scratch
    {
        CoinPackedMatrix matrixByRow = * m.getMatrixByRow();
        const double * element = matrixByRow.getElements();
        const int * column = matrixByRow.getIndices();
        const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
        const int * rowLength = matrixByRow.getVectorLengths();
        const double * rowLower = m.getRowLower();
        const double * rowUpper = m.getRowUpper();
        const double * columnLower = m.getColLower();
        const double * columnUpper = m.getColUpper();
        const double * objective = m.getObjCoefficients();
        int i;
        CoinModel temp;
        for (i=0; i<numberRows; i++) {
            temp.addRow(rowLength[i],column+rowStart[i],
                        element+rowStart[i],rowLower[i],rowUpper[i],m.rowName(i));
        }
        // Now do column part
        for (i=0; i<numberColumns; i++) {
            temp.setColumnBounds(i,columnLower[i],columnUpper[i]);
            temp.setColumnObjective(i,objective[i]);
            if (m.isInteger(i))
                temp.setColumnIsInteger(i,true);;
        }
        // write out
        temp.writeMps("byRow.mps");
    }

    // Build by column from scratch and save
    CoinModel model;
    {
        CoinPackedMatrix matrixByColumn = * m.getMatrixByCol();
        const double * element = matrixByColumn.getElements();
        const int * row = matrixByColumn.getIndices();
        const CoinBigIndex * columnStart = matrixByColumn.getVectorStarts();
        const int * columnLength = matrixByColumn.getVectorLengths();
        const double * rowLower = m.getRowLower();
        const double * rowUpper = m.getRowUpper();
        const double * columnLower = m.getColLower();
        const double * columnUpper = m.getColUpper();
        const double * objective = m.getObjCoefficients();
        int i;
        for (i=0; i<numberColumns; i++) {
            model.addColumn(columnLength[i],row+columnStart[i],
                            element+columnStart[i],columnLower[i],columnUpper[i],
                            objective[i],m.columnName(i),m.isInteger(i));
        }
        // Now do row part
        for (i=0; i<numberRows; i++) {
            model.setRowBounds(i,rowLower[i],rowUpper[i]);
        }
        // write out
        model.writeMps("byColumn.mps");
    }

    // model was created by column - play around
    {
        CoinModel temp;
        int i;
        for (i=numberRows-1; i>=0; i--)
            temp.setRowLower(i,model.getRowLower(i));
        for (i=0; i<numberColumns; i++) {
            temp.setColumnUpper(i,model.getColumnUpper(i));
            temp.setColumnName(i,model.getColumnName(i));
        }
        for (i=numberColumns-1; i>=0; i--) {
            temp.setColumnLower(i,model.getColumnLower(i));
            temp.setColumnObjective(i,model.getColumnObjective(i));
            temp.setColumnIsInteger(i,model.getColumnIsInteger(i));
        }
        for (i=0; i<numberRows; i++) {
            temp.setRowUpper(i,model.getRowUpper(i));
            temp.setRowName(i,model.getRowName(i));
        }
        // Now elements
        for (i=0; i<numberRows; i++) {
            CoinModelLink triple=model.firstInRow(i);
            while (triple.column()>=0) {
                temp(i,triple.column(),triple.value());
                triple=model.next(triple);
            }
        }
        // and by column
        for (i=numberColumns-1; i>=0; i--) {
            CoinModelLink triple=model.lastInColumn(i);
            while (triple.row()>=0) {
                assert (triple.value()==temp(triple.row(),i));
                temp(triple.row(),i,triple.value());
                triple=model.previous(triple);
            }
        }
        // check equal
        model.setLogLevel(1);
        assert (!model.differentModel(temp,false));
    }
    // Try creating model with strings
    {
        CoinModel temp;
        int i;
        for (i=numberRows-1; i>=0; i--) {
            double value = model.getRowLower(i);
            if (value==-1.0)
                temp.setRowLower(i,"minusOne");
            else if (value==1.0)
                temp.setRowLower(i,"sqrt(plusOne)");
            else if (value==4.0)
                temp.setRowLower(i,"abs(4*plusOne)");
            else
                temp.setRowLower(i,value);
        }
        for (i=0; i<numberColumns; i++) {
            double value;
            value = model.getColumnUpper(i);
            if (value==-1.0)
                temp.setColumnUpper(i,"minusOne");
            else if (value==1.0)
                temp.setColumnUpper(i,"plusOne");
            else
                temp.setColumnUpper(i,value);
            temp.setColumnName(i,model.getColumnName(i));
        }
        for (i=numberColumns-1; i>=0; i--) {
            temp.setColumnLower(i,model.getColumnLower(i));
            temp.setColumnObjective(i,model.getColumnObjective(i));
            temp.setColumnIsInteger(i,model.getColumnIsInteger(i));
        }
        for (i=0; i<numberRows; i++) {
            double value = model.getRowUpper(i);
            if (value==-1.0)
                temp.setRowUpper(i,"minusOne");
            else if (value==1.0)
                temp.setRowUpper(i,"plusOne");
            else
                temp.setRowUpper(i,value);
            temp.setRowName(i,model.getRowName(i));
        }
        // Now elements
        for (i=0; i<numberRows; i++) {
            CoinModelLink triple=model.firstInRow(i);
            while (triple.column()>=0) {
                double value = triple.value();
                if (value==-1.0)
                    temp(i,triple.column(),"minusOne");
                else if (value==1.0)
                    temp(i,triple.column(),"plusOne");
                else if (value==-2.0)
                    temp(i,triple.column(),"minusOne-1.0");
                else if (value==2.0)
                    temp(i,triple.column(),"plusOne+1.0+minusOne+(2.0-plusOne)");
                else
                    temp(i,triple.column(),value);
                triple=model.next(triple);
            }
        }
        temp.associateElement("minusOne",-1.0);
        temp.associateElement("plusOne",1.0);
        temp.setProblemName("fromStrings");
        temp.writeMps("string.mps");

        // check equal
        model.setLogLevel(1);
        assert (!model.differentModel(temp,false));
    }
    // Test with various ways of generating
    {
        /*
          Get a model. Try first with netlibDir, fall back to mpsDir (sampleDir)
          if that fails.
        */
        CoinMpsIO m;
        std::string fn = netlibDir+testModel;
        double time1 = CoinCpuTime();
        int numErr = m.readMps(fn.c_str(),"");
        if (numErr != 0) {
            std::cout
                    << "Could not read " << testModel << " in " << netlibDir
                    << "; falling back to " << mpsDir << "." << std::endl ;
            fn = mpsDir+testModel ;
            numErr = m.readMps(fn.c_str(),"") ;
            if (numErr != 0) {
                std::cout << "Could not read " << testModel << "; skipping test." << std::endl ;
            }
        }
        if (numErr == 0) {
            std::cout
                    << "Time for readMps is "
                    << (CoinCpuTime()-time1) << " seconds." << std::endl ;
            int numberRows = m.getNumRows();
            int numberColumns = m.getNumCols();
            // Build model
            CoinModel model;
            CoinPackedMatrix matrixByRow = * m.getMatrixByRow();
            const double * element = matrixByRow.getElements();
            const int * column = matrixByRow.getIndices();
            const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
            const int * rowLength = matrixByRow.getVectorLengths();
            const double * rowLower = m.getRowLower();
            const double * rowUpper = m.getRowUpper();
            const double * columnLower = m.getColLower();
            const double * columnUpper = m.getColUpper();
            const double * objective = m.getObjCoefficients();
            int i;
            for (i=0; i<numberRows; i++) {
                model.addRow(rowLength[i],column+rowStart[i],
                             element+rowStart[i],rowLower[i],rowUpper[i],m.rowName(i));
            }
            // Now do column part
            for (i=0; i<numberColumns; i++) {
                model.setColumnBounds(i,columnLower[i],columnUpper[i]);
                model.setColumnObjective(i,objective[i]);
                model.setColumnName(i,m.columnName(i));
                if (m.isInteger(i))
                    model.setColumnIsInteger(i,true);;
            }
            // Test
            CoinSeedRandom(11111);
            time1 = 0.0;
            int nPass=50;
            for (i=0; i<nPass; i++) {
                double random = CoinDrand48();
                int iSeed = (int) (random*1000000);
                //iSeed = 776151;
                CoinSeedRandom(iSeed);
                std::cout << "before pass " << i << " with seed of " << iSeed << std::endl ;
                buildRandom(model,CoinDrand48(),time1,i);
                model.validateLinks();
            }
            std::cout
                    << "Time for " << nPass << " CoinModel passes is "
                    << time1 << " seconds\n" << std::endl ;
        }
    }
}
Пример #6
0
/* Build a model in some interesting way

   Nine blocks defined by 4 random numbers
   If next random number <0.4 addRow next possible
   If <0.8 addColumn if possible
   Otherwise do by element
   For each one use random <0.5 to add rim at same time
   At end fill in rim at random

*/
void buildRandom(CoinModel & baseModel, double random, double & timeIt, int iPass)
{
    CoinModel model;
    int numberRows = baseModel.numberRows();
    int numberColumns = baseModel.numberColumns();
    int numberElements = baseModel.numberElements();
    // Row numbers and column numbers
    int lastRow[4];
    int lastColumn[4];
    int i;
    lastRow[0]=0;
    lastColumn[0]=0;
    lastRow[3]=numberRows;
    lastColumn[3]=numberColumns;
    for ( i=1; i<3; i++) {
        int size;
        size = (int) ((0.25*random+0.2)*numberRows);
        random = CoinDrand48();
        lastRow[i]=lastRow[i-1]+size;
        size = (int) ((0.25*random+0.2)*numberColumns);
        random = CoinDrand48();
        lastColumn[i]=lastColumn[i-1]+size;
    }
    // whether block done 0 row first
    char block[9]= {0,0,0,0,0,0,0,0,0};
    // whether rowRim done
    char rowDone[3]= {0,0,0};
    // whether columnRim done
    char columnDone[3]= {0,0,0};
    // Save array for deleting elements
    CoinModelTriple * dTriple = new CoinModelTriple[numberElements];
    numberElements=0;
    double time1 = CoinCpuTime();
    for (int jBlock=0; jBlock<9; jBlock++) {
        int iType=-1;
        int iBlock=-1;
        if (random<0.4) {
            // trying addRow
            int j;
            for (j=0; j<3; j++) {
                int k;
                for (k=0; k<3; k++) {
                    if (block[3*j+k])
                        break; //already taken
                }
                if (k==3) {
                    // can do but decide which one
                    iBlock = 3*j + (int) (CoinDrand48()*0.3);
                    iType=0;
                    break;
                }
            }
        }
        if (iType==-1&&random<0.8) {
            // trying addRow
            int j;
            for (j=0; j<3; j++) {
                int k;
                for (k=0; k<3; k++) {
                    if (block[j+3*k])
                        break; //already taken
                }
                if (k==3) {
                    // can do but decide which one
                    iBlock = j + 3*((int) (CoinDrand48()*0.3));
                    iType=1;
                    break;
                }
            }
        }
        if (iType==-1) {
            iType=2;
            int j;
            for (j=0; j<9; j++) {
                if (!block[j]) {
                    iBlock=j;
                    break;
                }
            }
        }
        random=CoinDrand48();
        assert (iBlock>=0&&iBlock<9);
        assert (iType>=0);
        assert (!block[iBlock]);
        block[iBlock]=static_cast<char>(1+iType);
        int jRow = iBlock/3;
        int jColumn = iBlock%3;
        bool doRow = (CoinDrand48()<0.5)&&!rowDone[jRow];
        bool doColumn = (CoinDrand48()<0.5&&!columnDone[jColumn]);
        if (!iType) {
            // addRow
            int * column = new int[lastColumn[jColumn+1]-lastColumn[jColumn]];
            double * element = new double[lastColumn[jColumn+1]-lastColumn[jColumn]];
            for (i=lastRow[jRow]; i<lastRow[jRow+1]; i++) {
                int n=0;
                CoinModelLink triple=baseModel.firstInRow(i);
                while (triple.column()>=0) {
                    if (triple.column()>=lastColumn[jColumn]&&triple.column()<lastColumn[jColumn+1]) {
                        column[n]=triple.column();
                        element[n++]=triple.value();
                    }
                    triple=baseModel.next(triple);
                }
                assert (i>=model.numberRows());
                if (i>model.numberRows()) {
                    assert (i==lastRow[jRow]);
                    std::cout << "need to fill in rows" << std::endl ;
                    for (int k=0; k<jRow; k++) {
                        int start = CoinMax(lastRow[k],model.numberRows());
                        int end = lastRow[k+1];
                        bool doBounds = rowDone[k]!=0;
                        for (int j=start; j<end; j++) {
                            if (doBounds)
                                model.addRow(0,NULL,NULL,baseModel.rowLower(j),
                                             baseModel.rowUpper(j),baseModel.rowName(j));
                            else
                                model.addRow(0,NULL,NULL);
                        }
                    }
                }
                if (doRow)
                    model.addRow(n,column,element,baseModel.rowLower(i),
                                 baseModel.rowUpper(i),baseModel.rowName(i));
                else
                    model.addRow(n,column,element);
            }
            if (doRow) {
                rowDone[jRow]=1;
            }
            delete [] column;
            delete [] element;
        } else if (iType==1) {
            // addColumn
            int * row = new int[lastRow[jRow+1]-lastRow[jRow]];
            double * element = new double[lastRow[jRow+1]-lastRow[jRow]];
            for (i=lastColumn[jColumn]; i<lastColumn[jColumn+1]; i++) {
                int n=0;
                CoinModelLink triple=baseModel.firstInColumn(i);
                while (triple.row()>=0) {
                    if (triple.row()>=lastRow[jRow]&&triple.row()<lastRow[jRow+1]) {
                        row[n]=triple.row();
                        element[n++]=triple.value();
                    }
                    triple=baseModel.next(triple);
                }
                assert (i>=model.numberColumns());
                if (i>model.numberColumns()) {
                    assert (i==lastColumn[jColumn]);
                    std::cout << "need to fill in columns" << std::endl ;
                    for (int k=0; k<jColumn; k++) {
                        int start = CoinMax(lastColumn[k],model.numberColumns());
                        int end = lastColumn[k+1];
                        bool doBounds = columnDone[k]!=0;
                        for (int j=start; j<end; j++) {
                            if (doBounds)
                                model.addColumn(0,NULL,NULL,baseModel.columnLower(j),
                                                baseModel.columnUpper(j),baseModel.objective(j),
                                                baseModel.columnName(j),baseModel.isInteger(j));
                            else
                                model.addColumn(0,NULL,NULL);
                        }
                    }
                }
                if (doColumn)
                    model.addColumn(n,row,element,baseModel.columnLower(i),
                                    baseModel.columnUpper(i),baseModel.objective(i),
                                    baseModel.columnName(i),baseModel.isInteger(i));
                else
                    model.addColumn(n,row,element);
            }
            if (doColumn) {
                columnDone[jColumn]=1;
            }
            delete [] row;
            delete [] element;
        } else {
            // addElement
            // Which way round ?
            if (CoinDrand48()<0.5) {
                // rim first
                if (doRow) {
                    for (i=lastRow[jRow]; i<lastRow[jRow+1]; i++) {
                        model.setRowLower(i,baseModel.getRowLower(i));
                        model.setRowUpper(i,baseModel.getRowUpper(i));
                        model.setRowName(i,baseModel.getRowName(i));
                    }
                    rowDone[jRow]=1;
                }
                if (doColumn) {
                    for (i=lastColumn[jColumn]; i<lastColumn[jColumn+1]; i++) {
                        model.setColumnLower(i,baseModel.getColumnLower(i));
                        model.setColumnUpper(i,baseModel.getColumnUpper(i));
                        model.setColumnName(i,baseModel.getColumnName(i));
                        model.setColumnObjective(i,baseModel.getColumnObjective(i));
                        model.setColumnIsInteger(i,baseModel.getColumnIsInteger(i));
                    }
                    columnDone[jColumn]=1;
                }
                if (CoinDrand48()<0.3) {
                    // by row
                    for (i=lastRow[jRow]; i<lastRow[jRow+1]; i++) {
                        CoinModelLink triple=baseModel.firstInRow(i);
                        while (triple.column()>=0) {
                            int iColumn = triple.column();
                            if (iColumn>=lastColumn[jColumn]&&iColumn<lastColumn[jColumn+1])
                                model(i,triple.column(),triple.value());
                            triple=baseModel.next(triple);
                        }
                    }
                } else if (CoinDrand48()<0.6) {
                    // by column
                    for (i=lastColumn[jColumn]; i<lastColumn[jColumn+1]; i++) {
                        CoinModelLink triple=baseModel.firstInColumn(i);
                        while (triple.row()>=0) {
                            int iRow = triple.row();
                            if (iRow>=lastRow[jRow]&&iRow<lastRow[jRow+1])
                                model(triple.row(),i,triple.value());
                            triple=baseModel.next(triple);
                        }
                    }
                } else {
                    // scan through backwards
                    const CoinModelTriple * elements = baseModel.elements();
                    for (i=baseModel.numberElements()-1; i>=0; i--) {
                        int iRow = (int) rowInTriple(elements[i]);
                        int iColumn = elements[i].column;
                        if (iRow>=lastRow[jRow]&&iRow<lastRow[jRow+1]&&
                                iColumn>=lastColumn[jColumn]&&iColumn<lastColumn[jColumn+1])
                            model(iRow,iColumn,elements[i].value);
                    }
                }
            } else {
                // elements first
                if (CoinDrand48()<0.3) {
                    // by row
                    for (i=lastRow[jRow]; i<lastRow[jRow+1]; i++) {
                        CoinModelLink triple=baseModel.firstInRow(i);
                        while (triple.column()>=0) {
                            int iColumn = triple.column();
                            if (iColumn>=lastColumn[jColumn]&&iColumn<lastColumn[jColumn+1])
                                model(i,triple.column(),triple.value());
                            triple=baseModel.next(triple);
                        }
                    }
                } else if (CoinDrand48()<0.6) {
                    // by column
                    for (i=lastColumn[jColumn]; i<lastColumn[jColumn+1]; i++) {
                        CoinModelLink triple=baseModel.firstInColumn(i);
                        while (triple.row()>=0) {
                            int iRow = triple.row();
                            if (iRow>=lastRow[jRow]&&iRow<lastRow[jRow+1])
                                model(triple.row(),i,triple.value());
                            triple=baseModel.next(triple);
                        }
                    }
                } else {
                    // scan through backwards
                    const CoinModelTriple * elements = baseModel.elements();
                    for (i=baseModel.numberElements()-1; i>=0; i--) {
                        int iRow = (int) rowInTriple(elements[i]);
                        int iColumn = elements[i].column;
                        if (iRow>=lastRow[jRow]&&iRow<lastRow[jRow+1]&&
                                iColumn>=lastColumn[jColumn]&&iColumn<lastColumn[jColumn+1])
                            model(iRow,iColumn,elements[i].value);
                    }
                }
                if (doRow) {
                    for (i=lastRow[jRow]; i<lastRow[jRow+1]; i++) {
                        model.setRowLower(i,baseModel.getRowLower(i));
                        model.setRowUpper(i,baseModel.getRowUpper(i));
                        model.setRowName(i,baseModel.getRowName(i));
                    }
                    rowDone[jRow]=1;
                }
                if (doColumn) {
                    for (i=lastColumn[jColumn]; i<lastColumn[jColumn+1]; i++) {
                        model.setColumnLower(i,baseModel.getColumnLower(i));
                        model.setColumnUpper(i,baseModel.getColumnUpper(i));
                        model.setColumnName(i,baseModel.getColumnName(i));
                        model.setColumnObjective(i,baseModel.getColumnObjective(i));
                        model.setColumnIsInteger(i,baseModel.getColumnIsInteger(i));
                    }
                    columnDone[jColumn]=1;
                }
            }
        }
        // Mess up be deleting some elements
        if (CoinDrand48()<0.3&&iPass>10) {
            double random2=CoinDrand48();
            double randomDelete = 0.2 + 0.5*random2; // fraction to delete
            //model.validateLinks();
            if (random2<0.2) {
                // delete some rows
                for (int j=lastRow[jRow]; j<lastRow[jRow+1]; j++) {
                    //model.validateLinks();
                    if (CoinDrand48()<randomDelete) {
                        // save and delete
                        double rowLower = model.rowLower(j);
                        double rowUpper = model.rowUpper(j);
                        char * rowName = CoinStrdup(model.rowName(j));
                        CoinModelLink triple=model.firstInRow(j);
                        while (triple.column()>=0) {
                            int iColumn = triple.column();
                            assert (j==triple.row());
                            setRowInTriple(dTriple[numberElements],j);
                            dTriple[numberElements].column=iColumn;
                            dTriple[numberElements].value = triple.value();
                            numberElements++;
                            triple=model.next(triple);
                        }
                        model.deleteRow(j);
                        if (rowDone[jRow]) {
                            // put back rim
                            model.setRowLower(j,rowLower);
                            model.setRowUpper(j,rowUpper);
                            model.setRowName(j,rowName);
                        }
                        free(rowName);
                    }
                }
            } else if (random2<0.4) {
                // delete some columns
                for (int j=lastColumn[jColumn]; j<lastColumn[jColumn+1]; j++) {
                    //model.validateLinks();
                    if (CoinDrand48()<randomDelete) {
                        // save and delete
                        double columnLower = model.columnLower(j);
                        double columnUpper = model.columnUpper(j);
                        double objective = model.objective(j);
                        bool integer = model.isInteger(j)!=0;
                        char * columnName = CoinStrdup(model.columnName(j));
                        CoinModelLink triple=model.firstInColumn(j);
                        while (triple.column()>=0) {
                            int iRow = triple.row();
                            assert (j==triple.column());
                            dTriple[numberElements].column = j;
                            setRowInTriple(dTriple[numberElements],iRow);
                            dTriple[numberElements].value = triple.value();
                            numberElements++;
                            triple=model.next(triple);
                        }
                        model.deleteColumn(j);
                        if (columnDone[jColumn]) {
                            // put back rim
                            model.setColumnLower(j,columnLower);
                            model.setColumnUpper(j,columnUpper);
                            model.setObjective(j,objective);
                            model.setIsInteger(j,integer);
                            model.setColumnName(j,columnName);
                        }
                        free(columnName);
                    }
                }
            } else {
                // delete some elements
                //model.validateLinks();
                const CoinModelTriple * elements = baseModel.elements();
                for (i=0; i<model.numberElements(); i++) {
                    int iRow = (int) rowInTriple(elements[i]);
                    int iColumn = elements[i].column;
                    if (iRow>=lastRow[jRow]&&iRow<lastRow[jRow+1]&&
                            iColumn>=lastColumn[jColumn]&&iColumn<lastColumn[jColumn+1]) {
                        if (CoinDrand48()<randomDelete) {
                            dTriple[numberElements].column = iColumn;
                            setRowInTriple(dTriple[numberElements],iRow);
                            dTriple[numberElements].value = elements[i].value;
                            int position = model.deleteElement(iRow,iColumn);
                            if (position>=0)
                                numberElements++;
                        }
                    }
                }
            }
        }
    }
    // Do rim if necessary
    for (int k=0; k<3; k++) {
        if (!rowDone[k]) {
            for (i=lastRow[k]; i<lastRow[k+1]; i++) {
                model.setRowLower(i,baseModel.getRowLower(i));
                model.setRowUpper(i,baseModel.getRowUpper(i));
                model.setRowName(i,baseModel.getRowName(i));
            }
        }
        if (!columnDone[k]) {
            for (i=lastColumn[k]; i<lastColumn[k+1]; i++) {
                model.setColumnLower(i,baseModel.getColumnLower(i));
                model.setColumnUpper(i,baseModel.getColumnUpper(i));
                model.setColumnName(i,baseModel.getColumnName(i));
                model.setColumnObjective(i,baseModel.getColumnObjective(i));
                model.setColumnIsInteger(i,baseModel.getColumnIsInteger(i));
            }
        }
    }
    // Put back any elements
    for (i=0; i<numberElements; i++) {
        model(rowInTriple(dTriple[i]),dTriple[i].column,dTriple[i].value);
    }
    delete [] dTriple;
    timeIt +=  CoinCpuTime()-time1;
    model.setLogLevel(1);
    assert (!model.differentModel(baseModel,false));
}
Пример #7
0
int main(int argc, const char *argv[])
{
     // Empty model
     ClpSimplex  model;
     std::string mpsFileName;
     if (argc >= 2) mpsFileName = argv[1];
     else {
#if defined(NETLIBDIR)
          mpsFileName = NETLIBDIR "/25fv47.mps";
#else
          fprintf(stderr, "Do not know where to find netlib MPS files.\n");
          exit(1);
#endif
     }
     int status = model.readMps(mpsFileName.c_str(), true);

     if (status) {
          fprintf(stderr, "Bad readMps %s\n", mpsFileName.c_str());
          fprintf(stdout, "Bad readMps %s\n", mpsFileName.c_str());
          exit(1);
     }
     // Point to data
     int numberRows = model.numberRows();
     const double * rowLower = model.rowLower();
     const double * rowUpper = model.rowUpper();
     int numberColumns = model.numberColumns();
     const double * columnLower = model.columnLower();
     const double * columnUpper = model.columnUpper();
     const double * columnObjective = model.objective();
     CoinPackedMatrix * matrix = model.matrix();
     // get row copy
     CoinPackedMatrix rowCopy = *matrix;
     rowCopy.reverseOrdering();
     const int * column = rowCopy.getIndices();
     const int * rowLength = rowCopy.getVectorLengths();
     const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
     const double * element = rowCopy.getElements();
     //const int * row = matrix->getIndices();
     //const int * columnLength = matrix->getVectorLengths();
     //const CoinBigIndex * columnStart = matrix->getVectorStarts();
     //const double * elementByColumn = matrix->getElements();

     // solve
     model.dual();
     // Now build new model
     CoinModel build;
     double time1 = CoinCpuTime();
     // Row bounds
     int iRow;
     for (iRow = 0; iRow < numberRows; iRow++) {
          build.setRowBounds(iRow, rowLower[iRow], rowUpper[iRow]);
          // optional name
          build.setRowName(iRow, model.rowName(iRow).c_str());
     }
     // Column bounds and objective
     int iColumn;
     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
          build.setColumnLower(iColumn, columnLower[iColumn]);
          build.setColumnUpper(iColumn, columnUpper[iColumn]);
          build.setObjective(iColumn, columnObjective[iColumn]);
          // optional name
          build.setColumnName(iColumn, model.columnName(iColumn).c_str());
     }
     // Adds elements one by one by row (backwards by row)
     for (iRow = numberRows - 1; iRow >= 0; iRow--) {
          int start = rowStart[iRow];
          for (int j = start; j < start + rowLength[iRow]; j++)
               build(iRow, column[j], element[j]);
     }
     double time2 = CoinCpuTime();
     // Now create clpsimplex
     ClpSimplex model2;
     model2.loadProblem(build);
     double time3 = CoinCpuTime();
     printf("Time for build using CoinModel is %g (%g for loadproblem)\n", time3 - time1,
            time3 - time2);
     model2.dual();
     // Now do with strings attached
     // Save build to show how to go over rows
     CoinModel saveBuild = build;
     build = CoinModel();
     time1 = CoinCpuTime();
     // Column bounds
     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
          build.setColumnLower(iColumn, columnLower[iColumn]);
          build.setColumnUpper(iColumn, columnUpper[iColumn]);
     }
     // Objective - half the columns as is and half with multiplier of "1.0+multiplier"
     // Pick up from saveBuild (for no reason at all)
     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
          double value = saveBuild.objective(iColumn);
          if (iColumn * 2 < numberColumns) {
               build.setObjective(iColumn, columnObjective[iColumn]);
          } else {
               // create as string
               char temp[100];
               sprintf(temp, "%g + abs(%g*multiplier)", value, value);
               build.setObjective(iColumn, temp);
          }
     }
     // It then adds rows one by one but for half the rows sets their values
     //      with multiplier of "1.0+1.5*multiplier"
     for (iRow = 0; iRow < numberRows; iRow++) {
          if (iRow * 2 < numberRows) {
               // add row in simple way
               int start = rowStart[iRow];
               build.addRow(rowLength[iRow], column + start, element + start,
                            rowLower[iRow], rowUpper[iRow]);
          } else {
               // As we have to add one by one let's get from saveBuild
               CoinModelLink triple = saveBuild.firstInRow(iRow);
               while (triple.column() >= 0) {
                    int iColumn = triple.column();
                    if (iColumn * 2 < numberColumns) {
                         // just value as normal
                         build(iRow, triple.column(), triple.value());
                    } else {
                         // create as string
                         char temp[100];
                         sprintf(temp, "%g + (1.5*%g*multiplier)", triple.value(), triple.value());
                         build(iRow, iColumn, temp);
                    }
                    triple = saveBuild.next(triple);
               }
               // but remember to do rhs
               build.setRowLower(iRow, rowLower[iRow]);
               build.setRowUpper(iRow, rowUpper[iRow]);
          }
     }
     time2 = CoinCpuTime();
     // Now create ClpSimplex
     // If small switch on error printing
     if (numberColumns < 50)
          build.setLogLevel(1);
     int numberErrors = model2.loadProblem(build);
     // should fail as we never set multiplier
     assert(numberErrors);
     time3 = CoinCpuTime() - time2;
     // subtract out unsuccessful times
     time1 += time3;
     time2 += time3;
     build.associateElement("multiplier", 0.0);
     numberErrors = model2.loadProblem(build);
     assert(!numberErrors);
     time3 = CoinCpuTime();
     printf("Time for build using CoinModel is %g (%g for successful loadproblem)\n", time3 - time1,
            time3 - time2);
     build.writeMps("zero.mps");
     // It then loops with multiplier going from 0.0 to 2.0 in increments of 0.1
     for (double multiplier = 0.0; multiplier < 2.0; multiplier += 0.1) {
          build.associateElement("multiplier", multiplier);
          numberErrors = model2.loadProblem(build, true);
          assert(!numberErrors);
          model2.dual();
     }

     return 0;
}
Пример #8
0
int main(int argc, const char *argv[])
{
     {
          // Empty model
          ClpSimplex  model;

          // Bounds on rows - as dense vector
          double lower[] = {2.0, 1.0};
          double upper[] = {COIN_DBL_MAX, 1.0};

          // Create space for 2 rows
          model.resize(2, 0);
          // Fill in
          int i;
          // Now row bounds
          for (i = 0; i < 2; i++) {
               model.setRowLower(i, lower[i]);
               model.setRowUpper(i, upper[i]);
          }
          // Now add column 1
          int column1Index[] = {0, 1};
          double column1Value[] = {1.0, 1.0};
          model.addColumn(2, column1Index, column1Value,
                          0.0, 2, 1.0);
          // Now add column 2
          int column2Index[] = {1};
          double column2Value[] = { -5.0};
          model.addColumn(1, column2Index, column2Value,
                          0.0, COIN_DBL_MAX, 0.0);
          // Now add column 3
          int column3Index[] = {0, 1};
          double column3Value[] = {1.0, 1.0};
          model.addColumn(2, column3Index, column3Value,
                          0.0, 4.0, 4.0);
          // solve
          model.dual();

          /*
            Adding one column at a time has a significant overhead so let's
            try a more complicated but faster way

            First time adding in 10000 columns one by one

          */
          model.allSlackBasis();
          ClpSimplex modelSave = model;
          double time1 = CoinCpuTime();
          int k;
          for (k = 0; k < 10000; k++) {
               int column2Index[] = {0, 1};
               double column2Value[] = {1.0, -5.0};
               model.addColumn(2, column2Index, column2Value,
                               0.0, 1.0, 10000.0);
          }
          printf("Time for 10000 addColumn is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = modelSave;
          // Now use build
          CoinBuild buildObject;
          time1 = CoinCpuTime();
          for (k = 0; k < 100000; k++) {
               int column2Index[] = {0, 1};
               double column2Value[] = {1.0, -5.0};
               buildObject.addColumn(2, column2Index, column2Value,
                                     0.0, 1.0, 10000.0);
          }
          model.addColumns(buildObject);
          printf("Time for 100000 addColumn using CoinBuild is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = modelSave;
          // Now use build +-1
          int del[] = {0, 1, 2};
          model.deleteColumns(3, del);
          CoinBuild buildObject2;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int column2Index[] = {0, 1};
               double column2Value[] = {1.0, 1.0, -1.0};
               int bias = k & 1;
               buildObject2.addColumn(2, column2Index, column2Value + bias,
                                      0.0, 1.0, 10000.0);
          }
          model.addColumns(buildObject2, true);
          printf("Time for 10000 addColumn using CoinBuild+-1 is %g\n", CoinCpuTime() - time1);
          model.dual();
          model = modelSave;
          // Now use build +-1
          model.deleteColumns(3, del);
          CoinModel modelObject2;
          time1 = CoinCpuTime();
          for (k = 0; k < 10000; k++) {
               int column2Index[] = {0, 1};
               double column2Value[] = {1.0, 1.0, -1.0};
               int bias = k & 1;
               modelObject2.addColumn(2, column2Index, column2Value + bias,
                                      0.0, 1.0, 10000.0);
          }
          model.addColumns(modelObject2, true);
          printf("Time for 10000 addColumn using CoinModel+-1 is %g\n", CoinCpuTime() - time1);
          //model.writeMps("xx.mps");
          model.dual();
          model = modelSave;
          // Now use model
          CoinModel modelObject;
          time1 = CoinCpuTime();
          for (k = 0; k < 100000; k++) {
               int column2Index[] = {0, 1};
               double column2Value[] = {1.0, -5.0};
               modelObject.addColumn(2, column2Index, column2Value,
                                     0.0, 1.0, 10000.0);
          }
          model.addColumns(modelObject);
          printf("Time for 100000 addColumn using CoinModel is %g\n", CoinCpuTime() - time1);
          model.dual();
          // Print column solution Just first 3 columns
          int numberColumns = model.numberColumns();
          numberColumns = CoinMin(3, numberColumns);

          // Alternatively getColSolution()
          double * columnPrimal = model.primalColumnSolution();
          // Alternatively getReducedCost()
          double * columnDual = model.dualColumnSolution();
          // Alternatively getColLower()
          double * columnLower = model.columnLower();  // Alternatively getColUpper()
          double * columnUpper = model.columnUpper();
          // Alternatively getObjCoefficients()
          double * columnObjective = model.objective();

          int iColumn;

          std::cout << "               Primal          Dual         Lower         Upper          Cost"
                    << std::endl;

          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
               double value;
               std::cout << std::setw(6) << iColumn << " ";
               value = columnPrimal[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnDual[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnLower[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnUpper[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value;
               value = columnObjective[iColumn];
               if (fabs(value) < 1.0e5)
                    std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
               else
                    std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value;

               std::cout << std::endl;
          }
          std::cout << "--------------------------------------" << std::endl;
     }
     {
          // Now copy a model
          ClpSimplex  model;
          int status;
          if (argc < 2) {
#if defined(SAMPLEDIR)
               status = model.readMps(SAMPLEDIR "/p0033.mps", true);
#else
               fprintf(stderr, "Do not know where to find sample MPS files.\n");
               exit(1);
#endif
          } else
               status = model.readMps(argv[1]);
          if (status) {
               printf("errors on input\n");
               exit(77);
          }
          model.initialSolve();
          int numberRows = model.numberRows();
          int numberColumns = model.numberColumns();
          const double * rowLower = model.rowLower();
          const double * rowUpper = model.rowUpper();

          // Start off model2
          ClpSimplex model2;
          model2.addRows(numberRows, rowLower, rowUpper, NULL);

          // Build object
          CoinBuild buildObject;
          // Add columns
          const double * columnLower = model.columnLower();
          const double * columnUpper = model.columnUpper();
          const double * objective = model.objective();
          CoinPackedMatrix * matrix = model.matrix();
          const int * row = matrix->getIndices();
          const int * columnLength = matrix->getVectorLengths();
          const CoinBigIndex * columnStart = matrix->getVectorStarts();
          const double * elementByColumn = matrix->getElements();
          for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
               CoinBigIndex start = columnStart[iColumn];
               buildObject.addColumn(columnLength[iColumn], row + start, elementByColumn + start,
                                     columnLower[iColumn], columnUpper[iColumn],
                                     objective[iColumn]);
          }

          // add in
          model2.addColumns(buildObject);
          model2.initialSolve();
     }
     {
          // and again
          ClpSimplex  model;
          int status;
          if (argc < 2) {
#if defined(SAMPLEDIR)
               status = model.readMps(SAMPLEDIR "/p0033.mps", true);
#else
               fprintf(stderr, "Do not know where to find sample MPS files.\n");
               exit(1);
#endif
          } else
               status = model.readMps(argv[1]);
          if (status) {
               printf("errors on input\n");
               exit(77);
          }
          model.initialSolve();
          int numberRows = model.numberRows();
          int numberColumns = model.numberColumns();
          const double * rowLower = model.rowLower();
          const double * rowUpper = model.rowUpper();

          // Build object
          CoinModel buildObject;
          for (int iRow = 0; iRow < numberRows; iRow++)
               buildObject.setRowBounds(iRow, rowLower[iRow], rowUpper[iRow]);

          // Add columns
          const double * columnLower = model.columnLower();
          const double * columnUpper = model.columnUpper();
          const double * objective = model.objective();
          CoinPackedMatrix * matrix = model.matrix();
          const int * row = matrix->getIndices();
          const int * columnLength = matrix->getVectorLengths();
          const CoinBigIndex * columnStart = matrix->getVectorStarts();
          const double * elementByColumn = matrix->getElements();
          for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
               CoinBigIndex start = columnStart[iColumn];
               buildObject.addColumn(columnLength[iColumn], row + start, elementByColumn + start,
                                     columnLower[iColumn], columnUpper[iColumn],
                                     objective[iColumn]);
          }

          // add in
          ClpSimplex model2;
          model2.loadProblem(buildObject);
          model2.initialSolve();
     }
     return 0;
}
Пример #9
0
int main (int argc, const char *argv[])
{
  // Get data
  std::string fileName = "./sudoku_sample.csv";
  if (argc>=2) fileName = argv[1];
  FILE * fp = fopen(fileName.c_str(),"r");
  if (!fp) {
    printf("Unable to open file %s\n",fileName.c_str());
    exit(0);
  }
#define MAX_SIZE 16
  int valueOffset=1;
  double lo[MAX_SIZE*MAX_SIZE],up[MAX_SIZE*MAX_SIZE];
  char line[80];
  int row,column;
  /*************************************** 
     Read .csv file and see if 9 or 16 Su Doku
  ***************************************/
  int size=9;
  for (row=0;row<size;row++) {
    fgets(line,80,fp);
    // Get size of sudoku puzzle (9 or 16)
    if (!row) {
      int get=0;
      size=1;
      while (line[get]>=32) {
        if (line[get]==',')
          size++;
        get++;
      }
      assert (size==9||size==16);
      printf("Solving Su Doku of size %d\n",size);
      if (size==16)
        valueOffset=0;
    }
    int get=0;
    for (column=0;column<size;column++) {
      lo[size*row+column]=valueOffset;
      up[size*row+column]=valueOffset-1+size;
      if (line[get]!=','&&line[get]>=32) {
        // skip blanks
        if (line[get]==' ') {
          get++;
          continue;
        }
        int value = line[get]-'0';
        if (size==9) {
          assert (value>=1&&value<=9);
        } else {
          assert (size==16);
          if (value<0||value>9) {
            if (line[get]=='"') {
              get++;
              value = 10 + line[get]-'A';
              if (value<10||value>15) {
                value = 10 + line[get]-'a';
              }
              get++;
            } else {
              value = 10 + line[get]-'A';
              if (value<10||value>15) {
                value = 10 + line[get]-'a';
              }
          }
          }
          assert (value>=0&&value<=15);
        }
        lo[size*row+column]=value;
        up[size*row+column]=value;
        get++;
      }
      get++;
    }
  }
  int block_size = (int) sqrt ((double) size);
  /*************************************** 
     Now build rules for all different
     3*9 or 3*16 sets of variables
     Number variables by row*size+column
  ***************************************/
  int starts[3*MAX_SIZE+1];
  int which[3*MAX_SIZE*MAX_SIZE];
  int put=0;
  int set=0;
  starts[0]=0;
  // By row
  for (row=0;row<size;row++) {
    for (column=0;column<size;column++) 
      which[put++]=row*size+column;
    starts[set+1]=put;
    set++;
  }
  // By column
  for (column=0;column<size;column++) {
    for (row=0;row<size;row++) 
      which[put++]=row*size+column;
    starts[set+1]=put;
    set++;
  }
  // By box
  for (row=0;row<size;row+=block_size) {
    for (column=0;column<size;column+=block_size) {
      for (int row2=row;row2<row+block_size;row2++) {
        for (int column2=column;column2<column+block_size;column2++) 
          which[put++]=row2*size+column2;
      }
      starts[set+1]=put;
      set++;
    }
  }
  OsiClpSolverInterface solver1;

  /*************************************** 
     Create model
     Set variables to be general integer variables although
     priorities probably mean that it won't matter
  ***************************************/
  CoinModel build;
  // Columns
  char name[4];
  for (row=0;row<size;row++) {
    for (column=0;column<size;column++) {
      if (row<10) {
        if (column<10) 
          sprintf(name,"X%d%d",row,column);
        else
          sprintf(name,"X%d%c",row,'A'+(column-10));
      } else {
        if (column<10) 
          sprintf(name,"X%c%d",'A'+(row-10),column);
        else
          sprintf(name,"X%c%c",'A'+(row-10),'A'+(column-10));
      }
      double value = CoinDrand48()*100.0;
      build.addColumn(0,NULL,NULL,lo[size*row+column],
                      up[size*row+column], value, name,true);
    }
  }
  /*************************************** 
     Now add in extra variables for N way branching
  ***************************************/
  for (row=0;row<size;row++) {
    for (column=0;column<size;column++) {
      int iColumn = size*row+column;
      double value = lo[iColumn];
      if (value<up[iColumn]) {
        for (int i=0;i<size;i++)
          build.addColumn(0,NULL,NULL,0.0,1.0,0.0);
      } else {
        // fixed
        // obviously could do better  if we missed out variables
        int which = ((int) value) - valueOffset;
        for (int i=0;i<size;i++) {
          if (i!=which)
            build.addColumn(0,NULL,NULL,0.0,0.0,0.0);
          else
            build.addColumn(0,NULL,NULL,0.0,1.0,0.0);
        }
      }
    }
  }
  
  /*************************************** 
     Now rows
  ***************************************/
  double values[]={1.0,1.0,1.0,1.0,
                   1.0,1.0,1.0,1.0,
                   1.0,1.0,1.0,1.0,
                   1.0,1.0,1.0,1.0};
  int indices[MAX_SIZE+1];
  double rhs = size==9 ? 45.0 : 120.0;
  for (row=0;row<3*size;row++) {
    int iStart = starts[row];
    for (column=0;column<size;column++) 
      indices[column]=which[column+iStart];
    build.addRow(size,indices,values,rhs,rhs);
  }
  double values2[MAX_SIZE+1];
  values2[0]=-1.0;
  for (row=0;row<size;row++) 
    values2[row+1]=row+valueOffset;
  // Now add rows for extra variables
  for (row=0;row<size;row++) {
    for (column=0;column<size;column++) {
      int iColumn = row*size+column;
      int base = size*size + iColumn*size;
      indices[0]=iColumn;
      for (int i=0;i<size;i++)
        indices[i+1]=base+i;
      build.addRow(size+1,indices,values2,0.0,0.0);
    }
  }
  solver1.loadFromCoinModel(build);
  build.writeMps("xx.mps");
  
  double time1 = CoinCpuTime();
  solver1.initialSolve();
  CbcModel model(solver1);
  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
  model.solver()->setHintParam(OsiDoScale,false,OsiHintTry);
  /*************************************** 
    Add in All different cut generator and All different branching
    So we will have integers then cut branching then N way branching
    in reverse priority order
  ***************************************/
  
  // Cut generator
  CglAllDifferent allDifferent(3*size,starts,which);
  model.addCutGenerator(&allDifferent,-99,"allDifferent");
  model.cutGenerator(0)->setWhatDepth(5);
  CbcObject ** objects = new CbcObject * [4*size*size];
  int nObj=0;
  for (row=0;row<3*size;row++) {
    int iStart = starts[row];
    objects[row]= new CbcBranchAllDifferent(&model,size,which+iStart);
    objects[row]->setPriority(2000+nObj); // do after rest satisfied
    nObj++;
  }
  /*************************************** 
     Add in N way branching and while we are at it add in cuts
  ***************************************/
  CglStored stored;
  for (row=0;row<size;row++) {
    for (column=0;column<size;column++) {
      int iColumn = row*size+column;
      int base = size*size + iColumn*size;
      int i;
      for ( i=0;i<size;i++)
        indices[i]=base+i;
      CbcNWay * obj = new CbcNWay(&model,size,indices,nObj);
      int seq[200];
      int newUpper[200];
      memset(newUpper,0,sizeof(newUpper));
      for (i=0;i<size;i++) {
        int state=9999;
        int one=1;
        int nFix=1;
        // Fix real variable
        seq[0]=iColumn;
        newUpper[0]=valueOffset+i;
        int kColumn = base+i;
        int j;
        // same row
        for (j=0;j<size;j++) {
          int jColumn = row*size+j;
          int jjColumn = size*size+jColumn*size+i;
          if (jjColumn!=kColumn) {
            seq[nFix++]=jjColumn; // must be zero
          }
        }
        // same column
        for (j=0;j<size;j++) {
          int jColumn = j*size+column;
          int jjColumn = size*size+jColumn*size+i;
          if (jjColumn!=kColumn) {
            seq[nFix++]=jjColumn; // must be zero
          }
        }
        // same block
        int kRow = row/block_size;
        kRow *= block_size;
        int kCol = column/block_size;
        kCol *= block_size;
        for (j=kRow;j<kRow+block_size;j++) {
          for (int jc=kCol;jc<kCol+block_size;jc++) {
            int jColumn = j*size+jc;
            int jjColumn = size*size+jColumn*size+i;
            if (jjColumn!=kColumn) {
              seq[nFix++]=jjColumn; // must be zero
            }
          }
        }
        // seem to need following?
        const int * upperAddress = newUpper;
        const int * seqAddress = seq;
        CbcFixVariable fix(1,&state,&one,&upperAddress,&seqAddress,&nFix,&upperAddress,&seqAddress);
        obj->setConsequence(indices[i],fix);
        // Now do as cuts
        for (int kk=1;kk<nFix;kk++) {
          int jColumn = seq[kk];
          int cutInd[2];
          cutInd[0]=kColumn;
          if (jColumn>kColumn) {
            cutInd[1]=jColumn;
            stored.addCut(-COIN_DBL_MAX,1.0,2,cutInd,values);
          }
        }
      }
      objects[nObj]= obj;
      objects[nObj]->setPriority(nObj);
      nObj++;
    }
  }
  model.addObjects(nObj,objects);
  for (row=0;row<nObj;row++) 
    delete objects[row];
  delete [] objects;
  model.messageHandler()->setLogLevel(1);
  model.addCutGenerator(&stored,1,"stored");
  // Say we want timings
  int numberGenerators = model.numberCutGenerators();
  int iGenerator;
  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
    generator->setTiming(true);
  }
  // Set this to get all solutions (all ones in newspapers should only have one)
  //model.setCutoffIncrement(-1.0e6);
  /*************************************** 
     Do branch and bound
  ***************************************/
  // Do complete search
  model.branchAndBound();
  std::cout<<"took "<<CoinCpuTime()-time1<<" seconds, "
	   <<model.getNodeCount()<<" nodes with objective "
	   <<model.getObjValue()
	   <<(!model.status() ? " Finished" : " Not finished")
	   <<std::endl;


  /*************************************** 
     Print solution and check it is feasible
     We could modify output so could be imported by spreadsheet
  ***************************************/
  if (model.getMinimizationObjValue()<1.0e50) {
    
    const double * solution = model.bestSolution();
    int put=0;
    for (row=0;row<size;row++) {
      for (column=0;column<size;column++) {
        int value = (int) floor(solution[row*size+column]+0.5);
        assert (value>=lo[put]&&value<=up[put]);
        // save for later test
        lo[put++]=value;
        printf("%d ",value);
      }
      printf("\n");
    }
    // check valid
    bool valid=true;
    // By row
    for (row=0;row<size;row++) {
      put=0;
      for (column=0;column<size;column++) 
        which[put++]=row*size+column;
      assert (put==size);
      int i;
      for (i=0;i<put;i++) 
        which[i]=(int) lo[which[i]];
      std::sort(which,which+put);
      int last = valueOffset-1;
      for (i=0;i<put;i++) {
        int value=which[i];
        if (value!=last+1)
          valid=false;
        last=value;
      }
    }
    // By column
    for (column=0;column<size;column++) {
      put=0;
      for (row=0;row<size;row++) 
        which[put++]=row*size+column;
      assert (put==size);
      int i;
      for (i=0;i<put;i++) 
        which[i]=(int) lo[which[i]];
      std::sort(which,which+put);
      int last = valueOffset-1;
      for (i=0;i<put;i++) {
        int value=which[i];
        if (value!=last+1)
          valid=false;
        last=value;
      }
    }
    // By box
    for (row=0;row<size;row+=block_size) {
      for (column=0;column<size;column+=block_size) {
        put=0;
        for (int row2=row;row2<row+block_size;row2++) {
          for (int column2=column;column2<column+block_size;column2++) 
            which[put++]=row2*size+column2;
        }
        assert (put==size);
        int i;
        for (i=0;i<put;i++) 
          which[i]=(int) lo[which[i]];
        std::sort(which,which+put);
        int last = valueOffset-1;
        for (i=0;i<put;i++) {
          int value=which[i];
          if (value!=last+1)
          valid=false;
          last=value;
        }
      }
    }
    if (valid) {
      printf("solution is valid\n");
    } else {
      printf("solution is not valid\n");
      abort();
    }
  }
  return 0;
}    
Пример #10
0
int main (int argc, const char *argv[])
{

  OsiClpSolverInterface solver1;

  /*
    We are going to treat x1 and x2 as integer and x3 and x4 as a set.
    We define two new variables y1 == x1*x4 and y2 == x2*x3.
    We define a variable z == x1*x4/x2*x3 so y2*z == y1
    (we will treat y2 as a set)
    Then we have objective - minimize w1 + w2 where
    w1 - w2 = 1.0/6.931 - z

    The model would be a lot smaller if we had column generation.
  */
  // Create model 
  CoinModel build;
  // Keep values of all variables for reporting purposes even if not necessary
  /*
    z is first, then x then y1,y2 then w1,w2 
    then y1 stuff, y2 stuff and finally y2 -> z stuff.
    For rows same but 2 per y then rest of z stuff
  */
  int loInt=12;
  int hiInt=60;
  int ybaseA=5, ybaseB=9, ylen=hiInt-loInt+1;
  int base = ybaseB+2*2*ylen;
  int yylen = hiInt*hiInt-loInt*loInt+1;
  int zbase = 10;
  int i;
  // Do single variables
  double value[] ={1.0,1.0};
  int row[2];
  /* z - obviously we can't choose bounds too tight but we need bounds
     so choose 20% off as obviously feasible.
     fastest way to solve would be too run for a few seconds to get
     tighter bounds then re-formulate and solve.  */
  double loose=0.2;
  double loZ = (1-loose)*(1.0/6.931), hiZ = (1+loose)*(1.0/6.931);
  row[0]=0; // for reporting
  row[1]=zbase+1; // for real use
  build.addColumn(2,row,value,loZ, hiZ, 0.0);
  // x
  for (i=0;i<4;i++) {
    row[0]=i+1;
    build.addColumn(1,row,value,loInt, hiInt,0.0);
    // we don't need to say x2, x3 integer but won't hurt
    build.setInteger(i+1);
  }
  // y
  for (i=0;i<2;i++) {
    // y from x*x, and convexity
    row[0]=ybaseA+2*i;
    if (i==0)
      row[1]=zbase+2; // yb*z == ya
    else
      row[1]=zbase-1; // to feed into z
    build.addColumn(2,row,value,loInt*loInt, hiInt*hiInt,0.0);
    // we don't need to say integer but won't hurt
    build.setInteger(ybaseA+i);
  }
  // skip z convexity put w in final equation
  row[0]=zbase+1;
  build.addColumn(1,row,value,0.0,1.0,1.0);
  value[0]=-1.0;
  build.addColumn(1,row,value,0.0,1.0,1.0);
  // Do columns so we know where each is
  for (i=ybaseB;i<base+(2*yylen);i++)
    build.setColumnBounds(i,0.0,1.0);
  // Now do rows
  // z definition
  build.setRowBounds(0,0.0,0.0);
  for (i=0;i<yylen;i++) {
    // l
    build.setElement(0,base+2*i,-loZ);
    // u
    build.setElement(0,base+2*i+1,-hiZ);
  }
  // x
  for (i=0;i<2;i++) {
    int iVarRow = 1+i;
    int iSetRow = 4-i; // as it is x1*x4 and x2*x3
    build.setRowBounds(iVarRow,0.0,0.0);
    build.setRowBounds(iSetRow,0.0,0.0);
    int j;
    int base2 = ybaseB + 2*ylen*i;
    for (j=0;j<ylen;j++) {
      // l
      build.setElement(iVarRow,base2+2*j,-loInt);
      build.setElement(iSetRow,base2+2*j,-loInt-j);
      // u
      build.setElement(iVarRow,base2+2*j+1,-hiInt);
      build.setElement(iSetRow,base2+2*j+1,-loInt-j);
    }
  }
  // y
  for (i=0;i<2;i++) {
    int iRow = 5+2*i;
    int iConvex = iRow+1;
    build.setRowBounds(iRow,0.0,0.0);
    build.setRowBounds(iConvex,1.0,1.0);
    int j;
    int base2 = ybaseB + 2*ylen*i;
    for (j=0;j<ylen;j++) {
      // l
      build.setElement(iRow,base2+2*j,-loInt*(j+loInt));
      build.setElement(iConvex,base2+2*j,1.0);
      // u
      build.setElement(iRow,base2+2*j+1,-hiInt*(j+loInt));
      build.setElement(iConvex,base2+2*j+1,1.0);
    }
  }
  // row that feeds into z and convexity
  build.setRowBounds(zbase-1,0.0,0.0);
  build.setRowBounds(zbase,1.0,1.0);
  for (i=0;i<yylen;i++) {
    // l
    build.setElement(zbase-1,base+2*i,-(i+loInt*loInt));
    build.setElement(zbase,base+2*i,1.0);
    // u
    build.setElement(zbase-1,base+2*i+1,-(i+loInt*loInt));
    build.setElement(zbase,base+2*i+1,1.0);
  }
  // and real equation rhs
  build.setRowBounds(zbase+1,1.0/6.931,1.0/6.931);
  // z*y
  build.setRowBounds(zbase+2,0.0,0.0);
  for (i=0;i<yylen;i++) {
    // l
    build.setElement(zbase+2,base+2*i,-(i+loInt*loInt)*loZ);
    // u
    build.setElement(zbase+2,base+2*i+1,-(i+loInt*loInt)*hiZ);
  }
  // And finally two more rows to break symmetry
  build.setRowBounds(zbase+3,-COIN_DBL_MAX,0.0);
  build.setElement(zbase+3,1,1.0);
  build.setElement(zbase+3,4,-1.0);
  build.setRowBounds(zbase+4,-COIN_DBL_MAX,0.0);
  build.setElement(zbase+4,2,1.0);
  build.setElement(zbase+4,3,-1.0);
  solver1.loadFromCoinModel(build);
  // To make CbcBranchLink simpler assume that all variables with same i are consecutive
  
  double time1 = CoinCpuTime();
  solver1.initialSolve();
  solver1.writeMps("bad");
  CbcModel model(solver1);
  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
  model.solver()->setHintParam(OsiDoScale,false,OsiHintTry);

  CbcObject ** objects = new CbcObject * [3];
  /* Format is number in sets, number in each link, first variable in matrix)
      and then a weight for each in set to say where to branch.  
      In this case use NULL to say 0,1,2 ...
      Finally a set number as ID.
  */
  objects[0]=new CbcLink(&model,ylen,2,ybaseB,NULL,0);
  objects[0]->setPriority(10);
  objects[1]=new CbcLink(&model,ylen,2,ybaseB+2*ylen,NULL,0);
  objects[1]->setPriority(20);
  objects[2]=new CbcLink(&model,yylen,2,base,NULL,0);
  objects[2]->setPriority(1);
  model.addObjects(3,objects);
  for (i=0;i<3;i++)
    delete objects[i];
  delete [] objects;
  model.messageHandler()->setLogLevel(1);
  // Do complete search
  
  model.setDblParam(CbcModel::CbcMaximumSeconds,1200.0);
  model.setDblParam(CbcModel::CbcCutoffIncrement,1.0e-8);
  model.branchAndBound();

  std::cout<<"took "<<CoinCpuTime()-time1<<" seconds, "
	   <<model.getNodeCount()<<" nodes with objective "
	   <<model.getObjValue()
	   <<(!model.status() ? " Finished" : " Not finished")
	   <<std::endl;


  if (model.getMinimizationObjValue()<1.0e50) {
    
    const double * solution = model.bestSolution();
    int numberColumns = model.solver()->getNumCols();
    double x1=solution[1];
    double x2=solution[2];
    double x3=solution[3];
    double x4=solution[4];
    printf("Optimal solution %g %g %g %g\n",x1,x2,x3,x4);
    for (int iColumn=0;iColumn<numberColumns;iColumn++) {
      double value=solution[iColumn];
      if (fabs(value)>1.0e-7) 
	std::cout<<iColumn<<" "<<value<<std::endl;
    }
  }
  return 0;
}    
Пример #11
0
//-----------------------------------------------------------------------------
void CbcSolver2::resolve()
{
  int numberColumns = modelPtr_->numberColumns();
  if ((count_<10&&algorithm_==2)||!algorithm_) {
    OsiClpSolverInterface::resolve();
    if (modelPtr_->status()==0) {
      count_++;
      double * solution = modelPtr_->primalColumnSolution();
      int i;
      for (i=0;i<numberColumns;i++) {
	if (solution[i]>1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) {
	  node_[i]=CoinMax(count_,node_[i]);
	  howMany_[i]++;
	}
      }
    } else {
      if (!algorithm_==2)
	printf("infeasible early on\n");
    }
  } else {
    // use counts
    int numberRows=modelPtr_->numberRows();
    int * whichRow = new int[numberRows];
    int * whichColumn = new int [numberColumns];
    int i;
    const double * lower = modelPtr_->columnLower();
    const double * upper = modelPtr_->columnUpper();
    const double * rowUpper = modelPtr_->rowUpper();
    bool equality=false;
    for (i=0;i<numberRows;i++) {
      if (rowUpper[i]==1.0) {
        equality=true;
        break;
      }
    }
    setBasis(basis_,modelPtr_);
    int nNewCol=0;
    // Column copy
    //const double * element = modelPtr_->matrix()->getElements();
    const int * row = modelPtr_->matrix()->getIndices();
    const CoinBigIndex * columnStart = modelPtr_->matrix()->getVectorStarts();
    const int * columnLength = modelPtr_->matrix()->getVectorLengths();
    
    int * rowActivity = new int[numberRows];
    memset(rowActivity,0,numberRows*sizeof(int));
    int * rowActivity2 = new int[numberRows];
    memset(rowActivity2,0,numberRows*sizeof(int));
    char * mark = new char[numberColumns];
    memset(mark,0,numberColumns);
    // Get rows which are satisfied
    for (i=0;i<numberColumns;i++) {
      if (lower[i]>0.0) {
        CoinBigIndex j;
        for (j=columnStart[i];
             j<columnStart[i]+columnLength[i];j++) {
          int iRow=row[j];
          rowActivity2[iRow] ++;
        }
      } else if (!upper[i]) {
        mark[i]=2; // no good
      }
    }
    // If equality - check not infeasible
    if (equality) {
      bool feasible=true;
      for (i=0;i<numberRows;i++) {
        if (rowActivity2[i]>1) {
          feasible=false;
          break;
        }
      }
      if (!feasible) {
        delete [] rowActivity;
        delete [] rowActivity2;
        modelPtr_->setProblemStatus(1);
        delete [] whichRow;
        delete [] whichColumn;
        delete [] mark;
        printf("infeasible by inspection (over)\n");
        return;
      }
    }
    int nNoGood=0;
    for (i=0;i<numberColumns;i++) {
      if (mark[i]==2) {
        nNoGood++;
        continue;
      }
      bool choose;
      if (algorithm_==1)
        choose = true;
      else
        choose = (node_[i]>count_-memory_&&node_[i]>0);
      bool any;
      if (equality) {
        // See if forced to be zero
        CoinBigIndex j;
        any=true;
        for (j=columnStart[i];
             j<columnStart[i]+columnLength[i];j++) {
          int iRow=row[j];
          if (rowActivity2[iRow])
            any=false; // can't be in
        }
      } else {
        // See if not useful
        CoinBigIndex j;
        any=false;
        for (j=columnStart[i];
             j<columnStart[i]+columnLength[i];j++) {
          int iRow=row[j];
          if (!rowActivity2[iRow])
            any=true; // useful
        }
      }
      if (!any&&!lower[i]) {
        choose=false;
        // and say can't be useful
        mark[i]=2;
        nNoGood++;
      }
      if (strategy_&&modelPtr_->getColumnStatus(i)==ClpSimplex::basic)
        choose=true;
      if (choose||lower[i]>0.0) {
        mark[i]=1;
	whichColumn[nNewCol++]=i;
        CoinBigIndex j;
        double value = upper[i];
        if (value) {
          for (j=columnStart[i];
               j<columnStart[i]+columnLength[i];j++) {
            int iRow=row[j];
            rowActivity[iRow] ++;
          }
        }
      }
    }
    // If equality add in slacks
    CoinModel build;
    if (equality) {
      int row=0;
      for (i=0;i<numberRows;i++) {
        // put in all rows if wanted
        if(strategy_)
          rowActivity2[i]=0;
        if (!rowActivity2[i]) {
          double element=1.0;
          build.addColumn(1,&row,&element,0.0,1.0,1.0e8); // large cost
          row++;
        }
      }
    }
    int nOK=0;
    int nNewRow=0;
    for (i=0;i<numberRows;i++) {
      if (rowActivity[i])
        nOK++;
      if (!rowActivity2[i])
        whichRow[nNewRow++]=i; // not satisfied
      else
        modelPtr_->setRowStatus(i,ClpSimplex::basic); // make slack basic
    }
    if (nOK<numberRows) {
      for (i=0;i<numberColumns;i++) {
        if (!mark[i]) {
          CoinBigIndex j;
          int good=0;
          for (j=columnStart[i];
               j<columnStart[i]+columnLength[i];j++) {
            int iRow=row[j];
            if (!rowActivity[iRow]) {
              rowActivity[iRow] ++;
              good++;
            }
          }
          if (good) {
            nOK+=good;
            whichColumn[nNewCol++]=i;
          }
        }
      }
    }
    delete [] rowActivity;
    delete [] rowActivity2;
    if (nOK<numberRows) {
      modelPtr_->setProblemStatus(1);
      delete [] whichRow;
      delete [] whichColumn;
      delete [] mark;
      printf("infeasible by inspection\n");
      return;
    }
    bool allIn=false;
    if (nNewCol+nNoGood+numberRows>numberColumns) {
      // add in all
      allIn=true;
      for (i=0;i<numberColumns;i++) {
        if (!mark[i]) {
          whichColumn[nNewCol++]=i;
        }
      }
    }
    ClpSimplex *  temp = new ClpSimplex(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn);
    if (equality)
      temp->addColumns(build);
    temp->setLogLevel(1);
    printf("small has %d rows and %d columns (%d impossible to help) %s\n",
           nNewRow,nNewCol,nNoGood,allIn ? "all in" : "");
    temp->setSpecialOptions(128+512);
    temp->setDualObjectiveLimit(1.0e50);
    temp->dual();
    assert (!temp->status());
    double * solution = modelPtr_->primalColumnSolution();
    const double * solution2 = temp->primalColumnSolution();
    memset(solution,0,numberColumns*sizeof(double));
    for (i=0;i<nNewCol;i++) {
      int iColumn = whichColumn[i];
      solution[iColumn]=solution2[i];
      modelPtr_->setStatus(iColumn,temp->getStatus(i));
    }
    double * rowSolution = modelPtr_->primalRowSolution();
    const double * rowSolution2 = temp->primalRowSolution();
    double * dual = modelPtr_->dualRowSolution();
    const double * dual2 = temp->dualRowSolution();
    memset(dual,0,numberRows*sizeof(double));
    for (i=0;i<nNewRow;i++) {
      int iRow=whichRow[i];
      modelPtr_->setRowStatus(iRow,temp->getRowStatus(i));
      rowSolution[iRow]=rowSolution2[i];
      dual[iRow]=dual2[i];
    }
    // See if optimal
    double * dj = modelPtr_->dualColumnSolution();
    // get reduced cost for large problem
    // this assumes minimization
    memcpy(dj,modelPtr_->objective(),numberColumns*sizeof(double));
    modelPtr_->transposeTimes(-1.0,dual,dj);
    modelPtr_->setObjectiveValue(temp->objectiveValue());
    modelPtr_->setProblemStatus(0);
    int nBad=0;
    for (i=0;i<numberColumns;i++) {
      if (modelPtr_->getStatus(i)==ClpSimplex::atLowerBound
          &&upper[i]>lower[i]&&dj[i]<-1.0e-5)
        nBad++;
    }
    //modelPtr_->writeMps("bada.mps");
    //temp->writeMps("badb.mps");
    delete temp;
    if (nBad&&!allIn) {
      assert (algorithm_==2);
      //printf("%d bad\n",nBad);
      timesBad_++;
      // just non mark==2
      int nAdded=0;
      for (i=0;i<numberColumns;i++) {
        if (!mark[i]) {
          whichColumn[nNewCol++]=i;
          nAdded++;
        }
      }
      assert (nAdded);
      {
        temp = new ClpSimplex(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn);
        if (equality)
          temp->addColumns(build);
        temp->setLogLevel(2);
        temp->setSpecialOptions(128+512);
        temp->setDualObjectiveLimit(1.0e50);
        temp->primal(1);
        assert (!temp->status());
        double * solution = modelPtr_->primalColumnSolution();
        const double * solution2 = temp->primalColumnSolution();
        memset(solution,0,numberColumns*sizeof(double));
        for (i=0;i<nNewCol;i++) {
          int iColumn = whichColumn[i];
          solution[iColumn]=solution2[i];
          modelPtr_->setStatus(iColumn,temp->getStatus(i));
        }
        double * rowSolution = modelPtr_->primalRowSolution();
        const double * rowSolution2 = temp->primalRowSolution();
        double * dual = modelPtr_->dualRowSolution();
        const double * dual2 = temp->dualRowSolution();
        memset(dual,0,numberRows*sizeof(double));
        for (i=0;i<nNewRow;i++) {
          int iRow=whichRow[i];
          modelPtr_->setRowStatus(iRow,temp->getRowStatus(i));
          rowSolution[iRow]=rowSolution2[i];
          dual[iRow]=dual2[i];
        }
        modelPtr_->setObjectiveValue(temp->objectiveValue());
        modelPtr_->setProblemStatus(0);
        iterationsBad_ += temp->numberIterations();
        printf("clean %d\n",temp->numberIterations());
        delete temp;
      }
    }
    delete [] mark;
    delete [] whichRow;
    delete [] whichColumn;
    basis_ = getBasis(modelPtr_);
    modelPtr_->setSpecialOptions(0);
    count_++;
    if ((count_%100)==0&&algorithm_==2)
      printf("count %d, bad %d - iterations %d\n",count_,timesBad_,iterationsBad_);
    for (i=0;i<numberColumns;i++) {
      if (solution[i]>1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) {
	node_[i]=CoinMax(count_,node_[i]);
	howMany_[i]++;
      }
    }
    if (modelPtr_->objectiveValue()>=modelPtr_->dualObjectiveLimit())
      modelPtr_->setProblemStatus(1);
  }
}
OsiSolverInterface *
expandKnapsack(CoinModel & model, int * whichColumn, int * knapsackStart,
               int * knapsackRow, int &numberKnapsack,
               CglStored & stored, int logLevel,
               int fixedPriority, int SOSPriority, CoinModel & tightenedModel)
{
    int maxTotal = numberKnapsack;
    // load from coin model
    OsiSolverLink *si = new OsiSolverLink();
    OsiSolverInterface * finalModel = NULL;
    si->setDefaultMeshSize(0.001);
    // need some relative granularity
    si->setDefaultBound(100.0);
    si->setDefaultMeshSize(0.01);
    si->setDefaultBound(100000.0);
    si->setIntegerPriority(1000);
    si->setBiLinearPriority(10000);
    si->load(model, true, logLevel);
    // get priorities
    const int * priorities = model.priorities();
    int numberColumns = model.numberColumns();
    if (priorities) {
        OsiObject ** objects = si->objects();
        int numberObjects = si->numberObjects();
        for (int iObj = 0; iObj < numberObjects; iObj++) {
            int iColumn = objects[iObj]->columnNumber();
            if (iColumn >= 0 && iColumn < numberColumns) {
#ifndef NDEBUG
                OsiSimpleInteger * obj =
                    dynamic_cast <OsiSimpleInteger *>(objects[iObj]) ;
#endif
                assert (obj);
                int iPriority = priorities[iColumn];
                if (iPriority > 0)
                    objects[iObj]->setPriority(iPriority);
            }
        }
        if (fixedPriority > 0) {
            si->setFixedPriority(fixedPriority);
        }
        if (SOSPriority < 0)
            SOSPriority = 100000;
    }
    CoinModel coinModel = *si->coinModel();
    assert(coinModel.numberRows() > 0);
    tightenedModel = coinModel;
    int numberRows = coinModel.numberRows();
    // Mark variables
    int * whichKnapsack = new int [numberColumns];
    int iRow, iColumn;
    for (iColumn = 0; iColumn < numberColumns; iColumn++)
        whichKnapsack[iColumn] = -1;
    int kRow;
    bool badModel = false;
    // analyze
    if (logLevel > 1) {
        for (iRow = 0; iRow < numberRows; iRow++) {
            /* Just obvious one at first
            positive non unit coefficients
            all integer
            positive rowUpper
            for now - linear (but further down in code may use nonlinear)
            column bounds should be tight
            */
            //double lower = coinModel.getRowLower(iRow);
            double upper = coinModel.getRowUpper(iRow);
            if (upper < 1.0e10) {
                CoinModelLink triple = coinModel.firstInRow(iRow);
                bool possible = true;
                int n = 0;
                int n1 = 0;
                while (triple.column() >= 0) {
                    int iColumn = triple.column();
                    const char *  el = coinModel.getElementAsString(iRow, iColumn);
                    if (!strcmp("Numeric", el)) {
                        if (coinModel.columnLower(iColumn) == coinModel.columnUpper(iColumn)) {
                            triple = coinModel.next(triple);
                            continue; // fixed
                        }
                        double value = coinModel.getElement(iRow, iColumn);
                        if (value < 0.0) {
                            possible = false;
                        } else {
                            n++;
                            if (value == 1.0)
                                n1++;
                            if (coinModel.columnLower(iColumn) < 0.0)
                                possible = false;
                            if (!coinModel.isInteger(iColumn))
                                possible = false;
                            if (whichKnapsack[iColumn] >= 0)
                                possible = false;
                        }
                    } else {
                        possible = false; // non linear
                    }
                    triple = coinModel.next(triple);
                }
                if (n - n1 > 1 && possible) {
                    double lower = coinModel.getRowLower(iRow);
                    double upper = coinModel.getRowUpper(iRow);
                    CoinModelLink triple = coinModel.firstInRow(iRow);
                    while (triple.column() >= 0) {
                        int iColumn = triple.column();
                        lower -= coinModel.columnLower(iColumn) * triple.value();
                        upper -= coinModel.columnLower(iColumn) * triple.value();
                        triple = coinModel.next(triple);
                    }
                    printf("%d is possible %g <=", iRow, lower);
                    // print
                    triple = coinModel.firstInRow(iRow);
                    while (triple.column() >= 0) {
                        int iColumn = triple.column();
                        if (coinModel.columnLower(iColumn) != coinModel.columnUpper(iColumn))
                            printf(" (%d,el %g up %g)", iColumn, triple.value(),
                                   coinModel.columnUpper(iColumn) - coinModel.columnLower(iColumn));
                        triple = coinModel.next(triple);
                    }
                    printf(" <= %g\n", upper);
                }
            }
        }
    }
    numberKnapsack = 0;
    for (kRow = 0; kRow < numberRows; kRow++) {
        iRow = kRow;
        /* Just obvious one at first
           positive non unit coefficients
           all integer
           positive rowUpper
           for now - linear (but further down in code may use nonlinear)
           column bounds should be tight
        */
        //double lower = coinModel.getRowLower(iRow);
        double upper = coinModel.getRowUpper(iRow);
        if (upper < 1.0e10) {
            CoinModelLink triple = coinModel.firstInRow(iRow);
            bool possible = true;
            int n = 0;
            int n1 = 0;
            while (triple.column() >= 0) {
                int iColumn = triple.column();
                const char *  el = coinModel.getElementAsString(iRow, iColumn);
                if (!strcmp("Numeric", el)) {
                    if (coinModel.columnLower(iColumn) == coinModel.columnUpper(iColumn)) {
                        triple = coinModel.next(triple);
                        continue; // fixed
                    }
                    double value = coinModel.getElement(iRow, iColumn);
                    if (value < 0.0) {
                        possible = false;
                    } else {
                        n++;
                        if (value == 1.0)
                            n1++;
                        if (coinModel.columnLower(iColumn) < 0.0)
                            possible = false;
                        if (!coinModel.isInteger(iColumn))
                            possible = false;
                        if (whichKnapsack[iColumn] >= 0)
                            possible = false;
                    }
                } else {
                    possible = false; // non linear
                }
                triple = coinModel.next(triple);
            }
            if (n - n1 > 1 && possible) {
                // try
                CoinModelLink triple = coinModel.firstInRow(iRow);
                while (triple.column() >= 0) {
                    int iColumn = triple.column();
                    if (coinModel.columnLower(iColumn) != coinModel.columnUpper(iColumn))
                        whichKnapsack[iColumn] = numberKnapsack;
                    triple = coinModel.next(triple);
                }
                knapsackRow[numberKnapsack++] = iRow;
            }
        }
    }
    if (logLevel > 0)
        printf("%d out of %d candidate rows are possible\n", numberKnapsack, numberRows);
    // Check whether we can get rid of nonlinearities
    /* mark rows
       -2 in knapsack and other variables
       -1 not involved
       n only in knapsack n
    */
    int * markRow = new int [numberRows];
    for (iRow = 0; iRow < numberRows; iRow++)
        markRow[iRow] = -1;
    int canDo = 1; // OK and linear
    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
        CoinModelLink triple = coinModel.firstInColumn(iColumn);
        int iKnapsack = whichKnapsack[iColumn];
        bool linear = true;
        // See if quadratic objective
        const char * expr = coinModel.getColumnObjectiveAsString(iColumn);
        if (strcmp(expr, "Numeric")) {
            linear = false;
        }
        while (triple.row() >= 0) {
            int iRow = triple.row();
            if (iKnapsack >= 0) {
                if (markRow[iRow] == -1) {
                    markRow[iRow] = iKnapsack;
                } else if (markRow[iRow] != iKnapsack) {
                    markRow[iRow] = -2;
                }
            }
            const char * expr = coinModel.getElementAsString(iRow, iColumn);
            if (strcmp(expr, "Numeric")) {
                linear = false;
            }
            triple = coinModel.next(triple);
        }
        if (!linear) {
            if (whichKnapsack[iColumn] < 0) {
                canDo = 0;
                break;
            } else {
                canDo = 2;
            }
        }
    }
    int * markKnapsack = NULL;
    double * coefficient = NULL;
    double * linear = NULL;
    int * whichRow = NULL;
    int * lookupRow = NULL;
    badModel = (canDo == 0);
    if (numberKnapsack && canDo) {
        /* double check - OK if
           no nonlinear
           nonlinear only on columns in knapsack
           nonlinear only on columns in knapsack * ONE other - same for all in knapsack
           AND that is only row connected to knapsack
           (theoretically could split knapsack if two other and small numbers)
           also ONE could be ONE expression - not just a variable
        */
        int iKnapsack;
        markKnapsack = new int [numberKnapsack];
        coefficient = new double [numberKnapsack];
        linear = new double [numberColumns];
        for (iKnapsack = 0; iKnapsack < numberKnapsack; iKnapsack++)
            markKnapsack[iKnapsack] = -1;
        if (canDo == 2) {
            for (iRow = -1; iRow < numberRows; iRow++) {
                int numberOdd;
                CoinPackedMatrix * row = coinModel.quadraticRow(iRow, linear, numberOdd);
                if (row) {
                    // see if valid
                    const double * element = row->getElements();
                    const int * column = row->getIndices();
                    const CoinBigIndex * columnStart = row->getVectorStarts();
                    const int * columnLength = row->getVectorLengths();
                    int numberLook = row->getNumCols();
                    for (int i = 0; i < numberLook; i++) {
                        int iKnapsack = whichKnapsack[i];
                        if (iKnapsack < 0) {
                            // might be able to swap - but for now can't have knapsack in
                            for (int j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) {
                                int iColumn = column[j];
                                if (whichKnapsack[iColumn] >= 0) {
                                    canDo = 0; // no good
                                    badModel = true;
                                    break;
                                }
                            }
                        } else {
                            // OK if in same knapsack - or maybe just one
                            int marked = markKnapsack[iKnapsack];
                            for (int j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) {
                                int iColumn = column[j];
                                if (whichKnapsack[iColumn] != iKnapsack && whichKnapsack[iColumn] >= 0) {
                                    canDo = 0; // no good
                                    badModel = true;
                                    break;
                                } else if (marked == -1) {
                                    markKnapsack[iKnapsack] = iColumn;
                                    marked = iColumn;
                                    coefficient[iKnapsack] = element[j];
                                    coinModel.associateElement(coinModel.columnName(iColumn), 1.0);
                                } else if (marked != iColumn) {
                                    badModel = true;
                                    canDo = 0; // no good
                                    break;
                                } else {
                                    // could manage with different coefficients - but for now ...
                                    assert(coefficient[iKnapsack] == element[j]);
                                }
                            }
                        }
                    }
                    delete row;
                }
            }
        }
        if (canDo) {
            // for any rows which are cuts
            whichRow = new int [numberRows];
            lookupRow = new int [numberRows];
            bool someNonlinear = false;
            double maxCoefficient = 1.0;
            for (iKnapsack = 0; iKnapsack < numberKnapsack; iKnapsack++) {
                if (markKnapsack[iKnapsack] >= 0) {
                    someNonlinear = true;
                    int iColumn = markKnapsack[iKnapsack];
                    maxCoefficient = CoinMax(maxCoefficient, fabs(coefficient[iKnapsack] * coinModel.columnUpper(iColumn)));
                }
            }
            if (someNonlinear) {
                // associate all columns to stop possible error messages
                for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                    coinModel.associateElement(coinModel.columnName(iColumn), 1.0);
                }
            }
            ClpSimplex tempModel;
            tempModel.loadProblem(coinModel);
            // Create final model - first without knapsacks
            int nCol = 0;
            int nRow = 0;
            for (iRow = 0; iRow < numberRows; iRow++) {
                if (markRow[iRow] < 0) {
                    lookupRow[iRow] = nRow;
                    whichRow[nRow++] = iRow;
                } else {
                    lookupRow[iRow] = -1;
                }
            }
            for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                if (whichKnapsack[iColumn] < 0)
                    whichColumn[nCol++] = iColumn;
            }
            ClpSimplex finalModelX(&tempModel, nRow, whichRow, nCol, whichColumn, false, false, false);
            OsiClpSolverInterface finalModelY(&finalModelX, true);
            finalModel = finalModelY.clone();
            finalModelY.releaseClp();
            // Put back priorities
            const int * priorities = model.priorities();
            if (priorities) {
                finalModel->findIntegers(false);
                OsiObject ** objects = finalModel->objects();
                int numberObjects = finalModel->numberObjects();
                for (int iObj = 0; iObj < numberObjects; iObj++) {
                    int iColumn = objects[iObj]->columnNumber();
                    if (iColumn >= 0 && iColumn < nCol) {
#ifndef NDEBUG
                        OsiSimpleInteger * obj =
                            dynamic_cast <OsiSimpleInteger *>(objects[iObj]) ;
#endif
                        assert (obj);
                        int iPriority = priorities[whichColumn[iColumn]];
                        if (iPriority > 0)
                            objects[iObj]->setPriority(iPriority);
                    }
                }
            }
            for (iRow = 0; iRow < numberRows; iRow++) {
                whichRow[iRow] = iRow;
            }
            int numberOther = finalModel->getNumCols();
            int nLargest = 0;
            int nelLargest = 0;
            int nTotal = 0;
            for (iKnapsack = 0; iKnapsack < numberKnapsack; iKnapsack++) {
                iRow = knapsackRow[iKnapsack];
                int nCreate = maxTotal;
                int nelCreate = coinModel.expandKnapsack(iRow, nCreate, NULL, NULL, NULL, NULL);
                if (nelCreate < 0)
                    badModel = true;
                nTotal += nCreate;
                nLargest = CoinMax(nLargest, nCreate);
                nelLargest = CoinMax(nelLargest, nelCreate);
            }
            if (nTotal > maxTotal)
                badModel = true;
            if (!badModel) {
                // Now arrays for building
                nelLargest = CoinMax(nelLargest, nLargest) + 1;
                double * buildObj = new double [nLargest];
                double * buildElement = new double [nelLargest];
                int * buildStart = new int[nLargest+1];
                int * buildRow = new int[nelLargest];
                // alow for integers in knapsacks
                OsiObject ** object = new OsiObject * [numberKnapsack+nTotal];
                int nSOS = 0;
                int nObj = numberKnapsack;
                for (iKnapsack = 0; iKnapsack < numberKnapsack; iKnapsack++) {
                    knapsackStart[iKnapsack] = finalModel->getNumCols();
                    iRow = knapsackRow[iKnapsack];
                    int nCreate = 10000;
                    coinModel.expandKnapsack(iRow, nCreate, buildObj, buildStart, buildRow, buildElement);
                    // Redo row numbers
                    for (iColumn = 0; iColumn < nCreate; iColumn++) {
                        for (int j = buildStart[iColumn]; j < buildStart[iColumn+1]; j++) {
                            int jRow = buildRow[j];
                            jRow = lookupRow[jRow];
                            assert (jRow >= 0 && jRow < nRow);
                            buildRow[j] = jRow;
                        }
                    }
                    finalModel->addCols(nCreate, buildStart, buildRow, buildElement, NULL, NULL, buildObj);
                    int numberFinal = finalModel->getNumCols();
                    for (iColumn = numberOther; iColumn < numberFinal; iColumn++) {
                        if (markKnapsack[iKnapsack] < 0) {
                            finalModel->setColUpper(iColumn, maxCoefficient);
                            finalModel->setInteger(iColumn);
                        } else {
                            finalModel->setColUpper(iColumn, maxCoefficient + 1.0);
                            finalModel->setInteger(iColumn);
                        }
                        OsiSimpleInteger * sosObject = new OsiSimpleInteger(finalModel, iColumn);
                        sosObject->setPriority(1000000);
                        object[nObj++] = sosObject;
                        buildRow[iColumn-numberOther] = iColumn;
                        buildElement[iColumn-numberOther] = 1.0;
                    }
                    if (markKnapsack[iKnapsack] < 0) {
                        // convexity row
                        finalModel->addRow(numberFinal - numberOther, buildRow, buildElement, 1.0, 1.0);
                    } else {
                        int iColumn = markKnapsack[iKnapsack];
                        int n = numberFinal - numberOther;
                        buildRow[n] = iColumn;
                        buildElement[n++] = -fabs(coefficient[iKnapsack]);
                        // convexity row (sort of)
                        finalModel->addRow(n, buildRow, buildElement, 0.0, 0.0);
                        OsiSOS * sosObject = new OsiSOS(finalModel, n - 1, buildRow, NULL, 1);
                        sosObject->setPriority(iKnapsack + SOSPriority);
                        // Say not integral even if is (switch off heuristics)
                        sosObject->setIntegerValued(false);
                        object[nSOS++] = sosObject;
                    }
                    numberOther = numberFinal;
                }
                finalModel->addObjects(nObj, object);
                for (iKnapsack = 0; iKnapsack < nObj; iKnapsack++)
                    delete object[iKnapsack];
                delete [] object;
                // Can we move any rows to cuts
                const int * cutMarker = coinModel.cutMarker();
                if (cutMarker && 0) {
                    printf("AMPL CUTS OFF until global cuts fixed\n");
                    cutMarker = NULL;
                }
                if (cutMarker) {
                    // Row copy
                    const CoinPackedMatrix * matrixByRow = finalModel->getMatrixByRow();
                    const double * elementByRow = matrixByRow->getElements();
                    const int * column = matrixByRow->getIndices();
                    const CoinBigIndex * rowStart = matrixByRow->getVectorStarts();
                    const int * rowLength = matrixByRow->getVectorLengths();

                    const double * rowLower = finalModel->getRowLower();
                    const double * rowUpper = finalModel->getRowUpper();
                    int nDelete = 0;
                    for (iRow = 0; iRow < numberRows; iRow++) {
                        if (cutMarker[iRow] && lookupRow[iRow] >= 0) {
                            int jRow = lookupRow[iRow];
                            whichRow[nDelete++] = jRow;
                            int start = rowStart[jRow];
                            stored.addCut(rowLower[jRow], rowUpper[jRow],
                                          rowLength[jRow], column + start, elementByRow + start);
                        }
                    }
                    finalModel->deleteRows(nDelete, whichRow);
                }
                knapsackStart[numberKnapsack] = finalModel->getNumCols();
                delete [] buildObj;
                delete [] buildElement;
                delete [] buildStart;
                delete [] buildRow;
                finalModel->writeMps("full");
            }
        }
    }
    delete [] whichKnapsack;
    delete [] markRow;
    delete [] markKnapsack;
    delete [] coefficient;
    delete [] linear;
    delete [] whichRow;
    delete [] lookupRow;
    delete si;
    si = NULL;
    if (!badModel && finalModel) {
        finalModel->setDblParam(OsiObjOffset, coinModel.objectiveOffset());
        return finalModel;
    } else {
        delete finalModel;
        printf("can't make knapsacks - did you set fixedPriority (extra1)\n");
        return NULL;
    }
}