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; }
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; }
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; }