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; }
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 the presolve variation of Sprint. This assumes we can get feasible easily */ int numberRows = model.numberRows(); int numberColumns = model.numberColumns(); // We will need arrays to choose variables. These are too big but .. double * weight = new double [numberRows+numberColumns]; int * sort = new int [numberRows+numberColumns]; double * columnLower = model.columnLower(); double * columnUpper = model.columnUpper(); double * saveLower = new double [numberColumns]; memcpy(saveLower, columnLower, numberColumns * sizeof(double)); double * saveUpper = new double [numberColumns]; memcpy(saveUpper, columnUpper, numberColumns * sizeof(double)); double * solution = model.primalColumnSolution(); // Fix in some magical way so remaining problem is easy #if 0 // This is from a real-world problem for (int iColumn = 0; iColumn < numberColumns; iColumn++) { char firstCharacter = model.columnName(iColumn)[0]; if (firstCharacter == 'F' || firstCharacter == 'P' || firstCharacter == 'L' || firstCharacter == 'T') { columnUpper[iColumn] = columnLower[iColumn]; } } #else double * obj = model.objective(); double * saveObj = new double [numberColumns]; memcpy(saveObj, obj, numberColumns * sizeof(double)); memset(obj, 0, numberColumns * sizeof(double)); model.dual(); memcpy(obj, saveObj, numberColumns * sizeof(double)); delete [] saveObj; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (solution[iColumn]<columnLower[iColumn]+1.0e-8) { columnUpper[iColumn] = columnLower[iColumn]; } } #endif // 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 = 3 * numberRows; // And we want number of rows to be this int smallNumberRows = numberRows / 4; for (iPass = 0; iPass < maxPass; iPass++) { printf("Start of pass %d\n", iPass); ClpSimplex * model2; ClpPresolve pinfo; int numberPasses = 1; // can change this model2 = pinfo.presolvedModel(model, 1.0e-8, false, numberPasses, false); if (!model2) { fprintf(stdout, "ClpPresolve says %s is infeasible with tolerance of %g\n", argv[1], 1.0e-8); // model was infeasible - maybe try again with looser tolerances model2 = pinfo.presolvedModel(model, 1.0e-7, false, numberPasses, false); if (!model2) { fprintf(stdout, "ClpPresolve says %s is infeasible with tolerance of %g\n", argv[1], 1.0e-7); exit(2); } } // change factorization frequency from 200 model2->setFactorizationFrequency(100 + model2->numberRows() / 50); model2->primal(); pinfo.postsolve(true); // adjust smallNumberColumns if necessary if (iPass) { double ratio = ((double) smallNumberRows) / ((double) model2->numberRows()); smallNumberColumns = (int)(smallNumberColumns * ratio); } delete model2; /* After this postsolve model should be optimal. We can use checkSolution and test feasibility */ model.checkSolution(); if (model.numberDualInfeasibilities() || model.numberPrimalInfeasibilities()) printf("%g dual %g(%d) Primal %g(%d)\n", model.objectiveValue(), model.sumDualInfeasibilities(), model.numberDualInfeasibilities(), model.sumPrimalInfeasibilities(), model.numberPrimalInfeasibilities()); // Put back true bounds memcpy(columnLower, saveLower, numberColumns * sizeof(double)); memcpy(columnUpper, saveUpper, numberColumns * sizeof(double)); if ((model.objectiveValue() > lastObjective - 1.0e-7 && iPass > 5) || iPass == maxPass - 1) { break; // finished } else { lastObjective = model.objectiveValue(); // now massage weight so all basic in plus good djs const double * djs = model.dualColumnSolution(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { double dj = djs[iColumn]; double value = solution[iColumn]; if (model.getStatus(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); // and fix others for (int iColumn = smallNumberColumns; iColumn < numberColumns; iColumn++) { int kColumn = sort[iColumn]; double value = solution[kColumn]; columnLower[kColumn] = value; columnUpper[kColumn] = value; } } } delete [] weight; delete [] sort; delete [] saveLower; delete [] saveUpper; model.primal(1); return 0; }