Пример #1
0
int main (int argc, const char *argv[])
{
     ClpSimplex  model;
     int status;
     // Keep names
     if (argc < 2) {
          status = model.readMps("small.mps", true);
     } else {
          status = model.readMps(argv[1], true);
     }
     if (status)
          exit(10);
     /*
       This driver implements what I called Sprint.  Cplex calls it
       "sifting" which is just as silly.  When I thought of this trivial idea
       it reminded me of an LP code of the 60's called sprint which after
       every factorization took a subset of the matrix into memory (all
       64K words!) and then iterated very fast on that subset.  On the
       problems of those days it did not work very well, but it worked very
       well on aircrew scheduling problems where there were very large numbers
       of columns all with the same flavor.
     */

     /* The idea works best if you can get feasible easily.  To make it
        more general we can add in costed slacks */

     int originalNumberColumns = model.numberColumns();
     int numberRows = model.numberRows();

     // We will need arrays to choose variables.  These are too big but ..
     double * weight = new double [numberRows+originalNumberColumns];
     int * sort = new int [numberRows+originalNumberColumns];
     int numberSort = 0;
     // Say we are going to add slacks - if you can get a feasible
     // solution then do that at the comment - Add in your own coding here
     bool addSlacks = true;

     if (addSlacks) {
          // initial list will just be artificials
          // first we will set all variables as close to zero as possible
          int iColumn;
          const double * columnLower = model.columnLower();
          const double * columnUpper = model.columnUpper();
          double * columnSolution = model.primalColumnSolution();

          for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) {
               double value = 0.0;
               if (columnLower[iColumn] > 0.0)
                    value = columnLower[iColumn];
               else if (columnUpper[iColumn] < 0.0)
                    value = columnUpper[iColumn];
               columnSolution[iColumn] = value;
          }
          // now see what that does to row solution
          double * rowSolution = model.primalRowSolution();
          memset (rowSolution, 0, numberRows * sizeof(double));
          model.times(1.0, columnSolution, rowSolution);

          int * addStarts = new int [numberRows+1];
          int * addRow = new int[numberRows];
          double * addElement = new double[numberRows];
          const double * lower = model.rowLower();
          const double * upper = model.rowUpper();
          addStarts[0] = 0;
          int numberArtificials = 0;
          double * addCost = new double [numberRows];
          const double penalty = 1.0e8;
          int iRow;
          for (iRow = 0; iRow < numberRows; iRow++) {
               if (lower[iRow] > rowSolution[iRow]) {
                    addRow[numberArtificials] = iRow;
                    addElement[numberArtificials] = 1.0;
                    addCost[numberArtificials] = penalty;
                    numberArtificials++;
                    addStarts[numberArtificials] = numberArtificials;
               } else if (upper[iRow] < rowSolution[iRow]) {
                    addRow[numberArtificials] = iRow;
                    addElement[numberArtificials] = -1.0;
                    addCost[numberArtificials] = penalty;
                    numberArtificials++;
                    addStarts[numberArtificials] = numberArtificials;
               }
          }
          model.addColumns(numberArtificials, NULL, NULL, addCost,
                           addStarts, addRow, addElement);
          delete [] addStarts;
          delete [] addRow;
          delete [] addElement;
          delete [] addCost;
          // Set up initial list
          numberSort = numberArtificials;
          int i;
          for (i = 0; i < numberSort; i++)
               sort[i] = i + originalNumberColumns;
     } else {
          // Get initial list in some magical way
          // Add in your own coding here
          abort();
     }

     int numberColumns = model.numberColumns();
     const double * columnLower = model.columnLower();
     const double * columnUpper = model.columnUpper();
     double * fullSolution = model.primalColumnSolution();

     // Just do this number of passes
     int maxPass = 100;
     int iPass;
     double lastObjective = 1.0e31;

     // Just take this number of columns in small problem
     int smallNumberColumns = CoinMin(3 * numberRows, numberColumns);
     smallNumberColumns = CoinMax(smallNumberColumns, 3000);
     // We will be using all rows
     int * whichRows = new int [numberRows];
     for (int iRow = 0; iRow < numberRows; iRow++)
          whichRows[iRow] = iRow;
     double originalOffset;
     model.getDblParam(ClpObjOffset, originalOffset);

     for (iPass = 0; iPass < maxPass; iPass++) {
          printf("Start of pass %d\n", iPass);
          //printf("Bug until submodel new version\n");
          CoinSort_2(sort, sort + numberSort, weight);
          // Create small problem
          ClpSimplex small(&model, numberRows, whichRows, numberSort, sort);
          // now see what variables left out do to row solution
          double * rowSolution = model.primalRowSolution();
          memset (rowSolution, 0, numberRows * sizeof(double));
          int iRow, iColumn;
          // zero out ones in small problem
          for (iColumn = 0; iColumn < numberSort; iColumn++) {
               int kColumn = sort[iColumn];
               fullSolution[kColumn] = 0.0;
          }
          // Get objective offset
          double offset = 0.0;
          const double * objective = model.objective();
          for (iColumn = 0; iColumn < originalNumberColumns; iColumn++)
               offset += fullSolution[iColumn] * objective[iColumn];
          small.setDblParam(ClpObjOffset, originalOffset - offset);
          model.times(1.0, fullSolution, rowSolution);

          double * lower = small.rowLower();
          double * upper = small.rowUpper();
          for (iRow = 0; iRow < numberRows; iRow++) {
               if (lower[iRow] > -1.0e50)
                    lower[iRow] -= rowSolution[iRow];
               if (upper[iRow] < 1.0e50)
                    upper[iRow] -= rowSolution[iRow];
          }
          /* For some problems a useful variant is to presolve problem.
             In this case you need to adjust smallNumberColumns to get
             right size problem.  Also you can dispense with creating
             small problem and fix variables in large problem and do presolve
             on that. */
          // Solve
          small.primal();
          // move solution back
          const double * solution = small.primalColumnSolution();
          for (iColumn = 0; iColumn < numberSort; iColumn++) {
               int kColumn = sort[iColumn];
               model.setColumnStatus(kColumn, small.getColumnStatus(iColumn));
               fullSolution[kColumn] = solution[iColumn];
          }
          for (iRow = 0; iRow < numberRows; iRow++)
               model.setRowStatus(iRow, small.getRowStatus(iRow));
          memcpy(model.primalRowSolution(), small.primalRowSolution(),
                 numberRows * sizeof(double));
          if ((small.objectiveValue() > lastObjective - 1.0e-7 && iPass > 5) ||
                    !small.numberIterations() ||
                    iPass == maxPass - 1) {

               break; // finished
          } else {
               lastObjective = small.objectiveValue();
               // get reduced cost for large problem
               // this assumes minimization
               memcpy(weight, model.objective(), numberColumns * sizeof(double));
               model.transposeTimes(-1.0, small.dualRowSolution(), weight);
               // now massage weight so all basic in plus good djs
               for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                    double dj = weight[iColumn];
                    double value = fullSolution[iColumn];
                    if (model.getColumnStatus(iColumn) == ClpSimplex::basic)
                         dj = -1.0e50;
                    else if (dj < 0.0 && value < columnUpper[iColumn])
                         dj = dj;
                    else if (dj > 0.0 && value > columnLower[iColumn])
                         dj = -dj;
                    else if (columnUpper[iColumn] > columnLower[iColumn])
                         dj = fabs(dj);
                    else
                         dj = 1.0e50;
                    weight[iColumn] = dj;
                    sort[iColumn] = iColumn;
               }
               // sort
               CoinSort_2(weight, weight + numberColumns, sort);
               numberSort = smallNumberColumns;
          }
     }
     if (addSlacks) {
          int i;
          int numberArtificials = numberColumns - originalNumberColumns;
          for (i = 0; i < numberArtificials; i++)
               sort[i] = i + originalNumberColumns;
          model.deleteColumns(numberArtificials, sort);
     }
     delete [] weight;
     delete [] sort;
     delete [] whichRows;
     model.primal(1);
     return 0;
}
Пример #2
0
int main(int argc, const char *argv[])
{
     ClpSimplex  model;
     int status;
     // Keep names
     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], true);
     /*
       This driver is similar to minimum.cpp, but it
       sets all parameter values to their defaults.  The purpose of this
       is to give a list of most of the methods that the end user will need.

       There are also some more methods as for OsiSolverInterface e.g.
       some loadProblem methods and deleteRows and deleteColumns.

       Often two methods do the same thing, one having a name I like
       while the other adheres to OsiSolverInterface standards
     */

     // Use exact devex ( a variant of steepest edge)
     ClpPrimalColumnSteepest primalSteepest;
     model.setPrimalColumnPivotAlgorithm(primalSteepest);


     int integerValue;
     double value;

     // Infeasibility cost
     value = model.infeasibilityCost();
     std::cout << "Default value of infeasibility cost is " << value << std::endl;
     model.setInfeasibilityCost(value);

     if (!status) {
          model.primal();
     }
     // Number of rows and columns - also getNumRows, getNumCols
     std::string modelName;
     model.getStrParam(ClpProbName, modelName);
     std::cout << "Model " << modelName << " has " << model.numberRows() << " rows and " <<
               model.numberColumns() << " columns" << std::endl;

     /* Some parameters as in OsiSolverParameters.  ObjectiveLimits
        are not active yet.  dualTolerance, setDualTolerance,
        primalTolerance and setPrimalTolerance may be used as well */

     model.getDblParam(ClpDualObjectiveLimit, value);
     std::cout << "Value of ClpDualObjectiveLimit is " << value << std::endl;
     model.getDblParam(ClpPrimalObjectiveLimit, value);
     std::cout << "Value of ClpPrimalObjectiveLimit is " << value << std::endl;
     model.getDblParam(ClpDualTolerance, value);
     std::cout << "Value of ClpDualTolerance is " << value << std::endl;
     model.getDblParam(ClpPrimalTolerance, value);
     std::cout << "Value of ClpPrimalTolerance is " << value << std::endl;
     model.getDblParam(ClpObjOffset, value);
     std::cout << "Value of ClpObjOffset is " << value << std::endl;

     // setDblParam(ClpPrimalTolerance) is same as this
     model.getDblParam(ClpPrimalTolerance, value);
     model.setPrimalTolerance(value);

     model.setDualTolerance(model.dualTolerance()) ;

     // Other Param stuff

     // Can also use maximumIterations
     model.getIntParam(ClpMaxNumIteration, integerValue);
     std::cout << "Value of ClpMaxNumIteration is " << integerValue << std::endl;
     model.setMaximumIterations(integerValue);

     // Not sure this works yet
     model.getIntParam(ClpMaxNumIterationHotStart, integerValue);
     std::cout << "Value of ClpMaxNumIterationHotStart is "
               << integerValue << std::endl;

     // Can also use getIterationCount and getObjValue
     /* Status of problem:
         0 - optimal
         1 - primal infeasible
         2 - dual infeasible
         3 - stopped on iterations etc
         4 - stopped due to errors
     */
     std::cout << "Model status is " << model.status() << " after "
               << model.numberIterations() << " iterations - objective is "
               << model.objectiveValue() << std::endl;

     assert(!model.isAbandoned());
     assert(model.isProvenOptimal());
     assert(!model.isProvenPrimalInfeasible());
     assert(!model.isProvenDualInfeasible());
     assert(!model.isPrimalObjectiveLimitReached());
     assert(!model.isDualObjectiveLimitReached());
     assert(!model.isIterationLimitReached());


     // Things to help you determine if optimal
     assert(model.primalFeasible());
     assert(!model.numberPrimalInfeasibilities());
     assert(model.sumPrimalInfeasibilities() < 1.0e-7);
     assert(model.dualFeasible());
     assert(!model.numberDualInfeasibilities());
     assert(model.sumDualInfeasibilities() < 1.0e-7);

     // Save warm start and set to all slack
     unsigned char * basis1 = model.statusCopy();
     model.createStatus();

     // Now create another model and do hot start
     ClpSimplex model2 = model;
     model2.copyinStatus(basis1);
     delete [] basis1;

     // Check model has not got basis (should iterate)
     model.dual();

     // Can use getObjSense
     model2.setOptimizationDirection(model.optimizationDirection());

     // Can use scalingFlag() to check if scaling on
     // But set up scaling
     model2.scaling();

     // Could play with sparse factorization on/off
     model2.setSparseFactorization(model.sparseFactorization());

     // Sets row pivot choice algorithm in dual
     ClpDualRowSteepest dualSteepest;
     model2.setDualRowPivotAlgorithm(dualSteepest);

     // Dual bound (i.e. dual infeasibility cost)
     value = model.dualBound();
     std::cout << "Default value of dual bound is " << value << std::endl;
     model.setDualBound(value);

     // Do some deafult message handling
     // To see real use - see OsiOslSolverInterfaceTest.cpp
     CoinMessageHandler handler;
     model2.passInMessageHandler(& handler);
     model2.newLanguage(CoinMessages::us_en);

     //Increase level of detail
     model2.setLogLevel(4);

     // solve
     model2.dual();
     // flip direction twice and solve
     model2.setOptimizationDirection(-1);
     model2.dual();
     model2.setOptimizationDirection(1);
     //Decrease level of detail
     model2.setLogLevel(1);
     model2.dual();

     /*
       Now for getting at information.  This will not deal with:

       ClpMatrixBase * rowCopy() and ClpMatrixbase * clpMatrix()

       nor with

       double * infeasibilityRay() and double * unboundedRay()
       (NULL returned if none/wrong)
       Up to user to use delete [] on these arrays.

      */


     /*
       Now to print out solution.  The methods used return modifiable
       arrays while the alternative names return const pointers -
       which is of course much more virtuous

      */

     int numberRows = model2.numberRows();

     // Alternatively getRowActivity()
     double * rowPrimal = model2.primalRowSolution();
     // Alternatively getRowPrice()
     double * rowDual = model2.dualRowSolution();
     // Alternatively getRowLower()
     double * rowLower = model2.rowLower();
     // Alternatively getRowUpper()
     double * rowUpper = model2.rowUpper();
     // Alternatively getRowObjCoefficients()
     double * rowObjective = model2.rowObjective();

     // If we have not kept names (parameter to readMps) this will be 0
     assert(model2.lengthNames());

     // Row names
     const std::vector<std::string> * rowNames = model2.rowNames();


     int iRow;

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

     for (iRow = 0; iRow < numberRows; iRow++) {
          double value;
          std::cout << std::setw(6) << iRow << " " << std::setw(8) << (*rowNames)[iRow];
          value = rowPrimal[iRow];
          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 = rowDual[iRow];
          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 = rowLower[iRow];
          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 = rowUpper[iRow];
          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;
          if (rowObjective) {
               value = rowObjective[iRow];
               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;

     // Columns

     int numberColumns = model2.numberColumns();

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

     // If we have not kept names (parameter to readMps) this will be 0
     assert(model2.lengthNames());

     // Column names
     const std::vector<std::string> * columnNames = model2.columnNames();


     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 << " " << std::setw(8) << (*columnNames)[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;

     std::cout << std::resetiosflags(std::ios::fixed | std::ios::showpoint | std::ios::scientific);

     // Now matrix
     CoinPackedMatrix * matrix = model2.matrix();

     const double * element = matrix->getElements();
     const int * row = matrix->getIndices();
     const int * start = matrix->getVectorStarts();
     const int * length = matrix->getVectorLengths();

     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
          std::cout << "Column " << iColumn;
          int j;
          for (j = start[iColumn]; j < start[iColumn] + length[iColumn]; j++)
               std::cout << " ( " << row[j] << ", " << element[j] << ")";
          std::cout << std::endl;
     }
     return 0;
}
Пример #3
0
int main(int argc, const char *argv[])
{
     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], true);
     if( status != 0 )
     {
        printf("Error %d reading MPS file\n", status);
        return status;
     }
     /*
       This driver uses volume algorithm
       then does dual - after adjusting costs
       then solves real problem
     */

     // do volume for a bit
     VOL_problem volprob;
     const CoinPackedMatrix* mat = model.matrix();
     const int psize = mat->getNumCols();
     const int dsize = mat->getNumRows();
     char * sense = new char[dsize];
     double * rhs = new double[dsize];
     const double * rowLower = model.rowLower();
     const double * rowUpper = model.rowUpper();
     // Set the lb/ub on the duals
     volprob.dsize = dsize;
     volprob.psize = psize;
     volprob.dual_lb.allocate(dsize);
     volprob.dual_ub.allocate(dsize);
     volprob.dsol.allocate(dsize);
     int i;
     for (i = 0; i < dsize; ++i) {
          if (rowUpper[i] == rowLower[i]) {
               // 'E':
               volprob.dual_lb[i] = -1.0e31;
               volprob.dual_ub[i] = 1.0e31;
               rhs[i] = rowUpper[i];
               sense[i] = 'E';
          } else if (rowLower[i] < -0.99e10 && rowUpper[i] < 0.99e10) {
               // 'L':
               volprob.dual_lb[i] = -1.0e31;
               volprob.dual_ub[i] = 0.0;
               rhs[i] = rowUpper[i];
               sense[i] = 'L';
          } else if (rowLower[i] > -0.99e10 && rowUpper[i] > 0.99e10) {
               // 'G':
               volprob.dual_lb[i] = 0.0;
               volprob.dual_ub[i] = 1.0e31;
               rhs[i] = rowLower[i];
               sense[i] = 'G';
          } else {
               printf("Volume Algorithm can't work if there is a non ELG row\n");
               abort();
          }
     }
     // Can't use read_param as private
     // anyway I want automatic use - so maybe this is problem
#if 0
     FILE* infile = fopen("parameters", "r");
     if (!infile) {
          printf("Failure to open parameter file\n");
     } else {
          volprob.read_params("parameters");
     }
#endif
#if 0
     // should save and restore bounds
     model.tightenPrimalBounds();
#else
     double * colUpper = model.columnUpper();
     for (i = 0; i < psize; i++)
          colUpper[i] = 1.0;
#endif
     lpHook myHook(model.getColLower(), model.getColUpper(),
                   model.getObjCoefficients(),
                   rhs, sense, *mat);
     // move duals
     double * pi = model.dualRowSolution();
     memcpy(volprob.dsol.v, pi, dsize * sizeof(double));
     volprob.solve(myHook,  false /* not warmstart */);
     // For now stop as not doing any good
     exit(77);
     // create objectives
     int numberRows = model.numberRows();
     int numberColumns = model.numberColumns();
     memcpy(pi, volprob.dsol.v, numberRows * sizeof(double));
#define MODIFYCOSTS
#ifdef MODIFYCOSTS
     double * saveObj = new double[numberColumns];
     memcpy(saveObj, model.objective(), numberColumns * sizeof(double));
     memcpy(model.dualColumnSolution(), model.objective(),
            numberColumns * sizeof(double));
     model.clpMatrix()->transposeTimes(-1.0, pi, model.dualColumnSolution());
     memcpy(model.objective(), model.dualColumnSolution(),
            numberColumns * sizeof(double));
     const double * rowsol = model.primalRowSolution();
     //const double * rowLower = model.rowLower();
     //const double * rowUpper = model.rowUpper();
     double offset = 0.0;
     for (i = 0; i < numberRows; i++) {
          offset += pi[i] * rowsol[i];
     }
     double value2;
     model.getDblParam(ClpObjOffset, value2);
     printf("Offset %g %g\n", offset, value2);
     model.setRowObjective(pi);
     // zero out pi
     memset(pi, 0, numberRows * sizeof(double));
#endif
     // Could put some in basis - only partially tested
     model.allSlackBasis();
     model.factorization()->maximumPivots(1000);
     //model.setLogLevel(63);
     // solve
     model.dual(1);
     //model.primal(1);
#ifdef MODIFYCOSTS
     memcpy(model.objective(), saveObj, numberColumns * sizeof(double));
     // zero out pi
     memset(pi, 0, numberRows * sizeof(double));
     model.setRowObjective(pi);
     delete [] saveObj;
     model.primal();
#endif

     return 0;
}