int main(int argc, const char *argv[]) { int status; CoinMpsIO m; if (argc < 2) status = m.readMps("model1.mps", ""); else status = m.readMps(argv[1], ""); if (status) { fprintf(stdout, "Bad readMps %s\n", argv[1]); exit(1); } // Load up model1 - so we can use known good solution ClpSimplex model1; model1.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); model1.dual(); // Get data arrays const CoinPackedMatrix * matrix1 = m.getMatrixByCol(); const int * start1 = matrix1->getVectorStarts(); const int * length1 = matrix1->getVectorLengths(); const int * row1 = matrix1->getIndices(); const double * element1 = matrix1->getElements(); const double * columnLower1 = m.getColLower(); const double * columnUpper1 = m.getColUpper(); const double * rowLower1 = m.getRowLower(); const double * rowUpper1 = m.getRowUpper(); const double * objective1 = m.getObjCoefficients(); int numberColumns = m.getNumCols(); int numberRows = m.getNumRows(); int numberElements = m.getNumElements(); // Get new arrays int numberColumns2 = (numberColumns + 1); int * start2 = new int[numberColumns2+1]; int * row2 = new int[numberElements]; double * element2 = new double[numberElements]; int * segstart = new int[numberColumns+1]; double * breakpt = new double[2*numberColumns]; double * slope = new double[2*numberColumns]; double * objective2 = new double[numberColumns2]; double * columnLower2 = new double[numberColumns2]; double * columnUpper2 = new double[numberColumns2]; double * rowLower2 = new double[numberRows]; double * rowUpper2 = new double[numberRows]; // We need to modify rhs memcpy(rowLower2, rowLower1, numberRows * sizeof(double)); memcpy(rowUpper2, rowUpper1, numberRows * sizeof(double)); double objectiveOffset = 0.0; // For new solution double * newSolution = new double [numberColumns]; const double * oldSolution = model1.primalColumnSolution(); int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) printf("%g ", oldSolution[iColumn]); printf("\n"); numberColumns2 = 0; numberElements = 0; start2[0] = 0; int segptr = 0; segstart[0] = 0; // Now check for duplicates for (iColumn = 0; iColumn < numberColumns; iColumn++) { // test if column identical to next column bool ifcopy = 1; if (iColumn < numberColumns - 1) { int joff = length1[iColumn]; for (int j = start1[iColumn]; j < start1[iColumn] + length1[iColumn]; j++) { if (row1[j] != row1[j+joff]) { ifcopy = 0; break; } if (element1[j] != element1[j+joff]) { ifcopy = 0; break; } } } else { ifcopy = 0; } //if (iColumn>47||iColumn<45) //ifcopy=0; if (ifcopy) { double lo1 = columnLower1[iColumn]; double up1 = columnUpper1[iColumn]; double obj1 = objective1[iColumn]; double sol1 = oldSolution[iColumn]; double lo2 = columnLower1[iColumn+1]; double up2 = columnUpper1[iColumn+1]; double obj2 = objective1[iColumn+1]; double sol2 = oldSolution[iColumn+1]; if (fabs(up1 - lo2) > 1.0e-8) { // try other way double temp; temp = lo1; lo1 = lo2; lo2 = temp; temp = up1; up1 = up2; up2 = temp; temp = obj1; obj1 = obj2; obj2 = temp; temp = sol1; sol1 = sol2; sol2 = temp; assert(fabs(up1 - lo2) < 1.0e-8); } // subtract out from rhs double fixed = up1; // do offset objectiveOffset += fixed * obj2; for (int j = start1[iColumn]; j < start1[iColumn] + length1[iColumn]; j++) { int iRow = row1[j]; double value = element1[j]; if (rowLower2[iRow] > -1.0e30) rowLower2[iRow] -= value * fixed; if (rowUpper2[iRow] < 1.0e30) rowUpper2[iRow] -= value * fixed; } newSolution[numberColumns2] = fixed; if (fabs(sol1 - fixed) > 1.0e-8) newSolution[numberColumns2] = sol1; if (fabs(sol2 - fixed) > 1.0e-8) newSolution[numberColumns2] = sol2; columnLower2[numberColumns2] = lo1; columnUpper2[numberColumns2] = up2; objective2[numberColumns2] = 0.0; breakpt[segptr] = lo1; slope[segptr++] = obj1; breakpt[segptr] = lo2; slope[segptr++] = obj2; for (int j = start1[iColumn]; j < start1[iColumn] + length1[iColumn]; j++) { row2[numberElements] = row1[j]; element2[numberElements++] = element1[j]; } start2[++numberColumns2] = numberElements; breakpt[segptr] = up2; slope[segptr++] = COIN_DBL_MAX; segstart[numberColumns2] = segptr; iColumn++; // skip next column } else { // normal column columnLower2[numberColumns2] = columnLower1[iColumn]; columnUpper2[numberColumns2] = columnUpper1[iColumn]; objective2[numberColumns2] = objective1[iColumn]; breakpt[segptr] = columnLower1[iColumn]; slope[segptr++] = objective1[iColumn]; for (int j = start1[iColumn]; j < start1[iColumn] + length1[iColumn]; j++) { row2[numberElements] = row1[j]; element2[numberElements++] = element1[j]; } newSolution[numberColumns2] = oldSolution[iColumn]; start2[++numberColumns2] = numberElements; breakpt[segptr] = columnUpper1[iColumn]; slope[segptr++] = COIN_DBL_MAX; segstart[numberColumns2] = segptr; } } // print new number of columns, elements printf("New number of columns = %d\n", numberColumns2); printf("New number of elements = %d\n", numberElements); printf("Objective offset is %g\n", objectiveOffset); ClpSimplex model; // load up model.loadProblem(numberColumns2, numberRows, start2, row2, element2, columnLower2, columnUpper2, objective2, rowLower2, rowUpper2); model.scaling(0); model.setDblParam(ClpObjOffset, -objectiveOffset); // Create nonlinear objective int returnCode = model.createPiecewiseLinearCosts(segstart, breakpt, slope); assert(!returnCode); // delete delete [] segstart; delete [] breakpt; delete [] slope; delete [] start2; delete [] row2 ; delete [] element2; delete [] objective2; delete [] columnLower2; delete [] columnUpper2; delete [] rowLower2; delete [] rowUpper2; // copy in solution - (should be optimal) model.allSlackBasis(); memcpy(model.primalColumnSolution(), newSolution, numberColumns2 * sizeof(double)); //memcpy(model.columnLower(),newSolution,numberColumns2*sizeof(double)); //memcpy(model.columnUpper(),newSolution,numberColumns2*sizeof(double)); delete [] newSolution; //model.setLogLevel(63); const double * solution = model.primalColumnSolution(); double * saveSol = new double[numberColumns2]; memcpy(saveSol, solution, numberColumns2 * sizeof(double)); for (iColumn = 0; iColumn < numberColumns2; iColumn++) printf("%g ", solution[iColumn]); printf("\n"); // solve model.primal(1); for (iColumn = 0; iColumn < numberColumns2; iColumn++) { if (fabs(solution[iColumn] - saveSol[iColumn]) > 1.0e-3) printf(" ** was %g ", saveSol[iColumn]); printf("%g ", solution[iColumn]); } printf("\n"); model.primal(1); for (iColumn = 0; iColumn < numberColumns2; iColumn++) { if (fabs(solution[iColumn] - saveSol[iColumn]) > 1.0e-3) printf(" ** was %g ", saveSol[iColumn]); printf("%g ", solution[iColumn]); } printf("\n"); model.primal(); for (iColumn = 0; iColumn < numberColumns2; iColumn++) { if (fabs(solution[iColumn] - saveSol[iColumn]) > 1.0e-3) printf(" ** was %g ", saveSol[iColumn]); printf("%g ", solution[iColumn]); } printf("\n"); model.allSlackBasis(); for (iColumn = 0; iColumn < numberColumns2; iColumn++) { if (fabs(solution[iColumn] - saveSol[iColumn]) > 1.0e-3) printf(" ** was %g ", saveSol[iColumn]); printf("%g ", solution[iColumn]); } printf("\n"); model.setLogLevel(63); model.primal(); for (iColumn = 0; iColumn < numberColumns2; iColumn++) { if (fabs(solution[iColumn] - saveSol[iColumn]) > 1.0e-3) printf(" ** was %g ", saveSol[iColumn]); printf("%g ", solution[iColumn]); } printf("\n"); return 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; }
/* Randomized Rounding Heuristic Returns 1 if solution, 0 if not */ int CbcHeuristicRandRound::solution(double & solutionValue, double * betterSolution) { // rlh: Todo: Memory Cleanup // std::cout << "Entering the Randomized Rounding Heuristic" << std::endl; setWhen(1); // setWhen(1) didn't have the effect I expected (e.g., run once). // Run only once. // // See if at root node bool atRoot = model_->getNodeCount() == 0; int passNumber = model_->getCurrentPassNumber(); // Just do once if (!atRoot || passNumber > 1) { // std::cout << "Leaving the Randomized Rounding Heuristic" << std::endl; return 0; } std::cout << "Entering the Randomized Rounding Heuristic" << std::endl; typedef struct { int numberSolutions; int maximumSolutions; int numberColumns; double ** solution; int * numberUnsatisfied; } clpSolution; double start = CoinCpuTime(); numCouldRun_++; // #ifdef HEURISTIC_INFORM printf("Entering heuristic %s - nRuns %d numCould %d when %d\n", heuristicName(),numRuns_,numCouldRun_,when_); #endif // Todo: Ask JJHF what "number of times // the heuristic could run" means. OsiSolverInterface * solver = model_->solver()->clone(); double primalTolerance ; solver->getDblParam(OsiPrimalTolerance, primalTolerance) ; OsiClpSolverInterface * clpSolver = dynamic_cast<OsiClpSolverInterface *> (solver); assert (clpSolver); ClpSimplex * simplex = clpSolver->getModelPtr(); // Initialize the structure holding the solutions for the Simplex iterations clpSolution solutions; // Set typeStruct field of ClpTrustedData struct to 1 to indicate // desired behavior for RandRound heuristic (which is what?) ClpTrustedData trustedSolutions; trustedSolutions.typeStruct = 1; trustedSolutions.data = &solutions; solutions.numberSolutions = 0; solutions.maximumSolutions = 0; solutions.numberColumns = simplex->numberColumns(); solutions.solution = NULL; solutions.numberUnsatisfied = NULL; simplex->setTrustedUserPointer(&trustedSolutions); // Solve from all slack to get some points simplex->allSlackBasis(); // Calling primal() invalidates pointers to some rim vectors, // like...row sense (!) simplex->primal(); // 1. Okay - so a workaround would be to copy the data I want BEFORE // calling primal. // 2. Another approach is to ask the simplex solvers NOT to mess up my // rims. // 3. See freeCachedResults() for what is getting // deleted. Everything else points into the structure. // ...or use collower and colupper rather than rowsense. // ..store address of where one of these // Store the basic problem information // -Get the number of columns, rows and rhs vector int numCols = clpSolver->getNumCols(); int numRows = clpSolver->getNumRows(); // Find the integer variables (use columnType(?)) // One if not continuous, that is binary or general integer) // columnType() = 0 continuous // = 1 binary // = 2 general integer bool * varClassInt = new bool[numCols]; const char* columnType = clpSolver->columnType(); int numGenInt = 0; for (int i = 0; i < numCols; i++) { if (clpSolver->isContinuous(i)) varClassInt[i] = 0; else varClassInt[i] = 1; if (columnType[i] == 2) numGenInt++; } // Heuristic is for problems with general integer variables. // If there are none, quit. if (numGenInt++ < 1) { delete [] varClassInt ; std::cout << "Leaving the Randomized Rounding Heuristic" << std::endl; return 0; } // -Get the rows sense const char * rowSense; rowSense = clpSolver->getRowSense(); // -Get the objective coefficients double *originalObjCoeff = CoinCopyOfArray(clpSolver->getObjCoefficients(), numCols); // -Get the matrix of the problem // rlh: look at using sparse representation double ** matrix = new double * [numRows]; for (int i = 0; i < numRows; i++) { matrix[i] = new double[numCols]; for (int j = 0; j < numCols; j++) matrix[i][j] = 0; } const CoinPackedMatrix* matrixByRow = clpSolver->getMatrixByRow(); const double * matrixElements = matrixByRow->getElements(); const int * matrixIndices = matrixByRow->getIndices(); const int * matrixStarts = matrixByRow->getVectorStarts(); for (int j = 0; j < numRows; j++) { for (int i = matrixStarts[j]; i < matrixStarts[j+1]; i++) { matrix[j][matrixIndices[i]] = matrixElements[i]; } } double * newObj = new double [numCols]; srand ( static_cast<unsigned int>(time(NULL) + 1)); int randNum; // Shuffle the rows: // Put the rows in a random order // so that the optimal solution is a different corner point than the // starting point. int * index = new int [numRows]; for (int i = 0; i < numRows; i++) index[i] = i; for (int i = 0; i < numRows; i++) { int temp = index[i]; int randNumTemp = i + intRand(numRows - i); index[i] = index[randNumTemp]; index[randNumTemp] = temp; } // Start finding corner points by iteratively doing the following: // - contruct a randomly tilted objective // - solve for (int i = 0; i < numRows; i++) { // TODO: that 10,000 could be a param in the member data if (solutions.numberSolutions > 10000) break; randNum = intRand(2); for (int j = 0; j < numCols; j++) { // for row i and column j vary the coefficient "a bit" if (randNum == 1) // if the element is zero, then set the new obj // coefficient to 0.1 (i.e., round up) if (fabs(matrix[index[i]][j]) < primalTolerance) newObj[j] = 0.1; else // if the element is nonzero, then increase the new obj // coefficient "a bit" newObj[j] = matrix[index[i]][j] * 1.1; else // if randnum is 2, then // if the element is zero, then set the new obj coeffient // to NEGATIVE 0.1 (i.e., round down) if (fabs(matrix[index[i]][j]) < primalTolerance) newObj[j] = -0.1; else // if the element is nonzero, then DEcrease the new obj coeffienct "a bit" newObj[j] = matrix[index[i]][j] * 0.9; } // Use the new "tilted" objective clpSolver->setObjective(newObj); // Based on the row sense, we decide whether to max or min if (rowSense[i] == 'L') clpSolver->setObjSense(-1); else clpSolver->setObjSense(1); // Solve with primal simplex simplex->primal(1); // rlh+ll: This was the original code. But we already have the // model pointer (it's in simplex). And, calling getModelPtr() // invalidates the cached data in the OsiClpSolverInterface // object, which means our precious rowsens is lost. So let's // not use the line below... /******* clpSolver->getModelPtr()->primal(1); */ printf("---------------------------------------------------------------- %d\n", i); } // Iteratively do this process until... // either you reach the max number of corner points (aka 10K) // or all the rows have been used as an objective. // Look at solutions int numberSolutions = solutions.numberSolutions; //const char * integerInfo = simplex->integerInformation(); //const double * columnLower = simplex->columnLower(); //const double * columnUpper = simplex->columnUpper(); printf("there are %d solutions\n", numberSolutions); // Up to here we have all the corner points // Now we need to do the random walks and roundings double ** cornerPoints = new double * [numberSolutions]; for (int j = 0; j < numberSolutions; j++) cornerPoints[j] = solutions.solution[j]; bool feasibility = 1; // rlh: use some COIN max instead of 1e30 (?) double bestObj = 1e30; std::vector< std::vector <double> > feasibles; int numFeasibles = 0; // Check the feasibility of the corner points int numCornerPoints = numberSolutions; const double * rhs = clpSolver->getRightHandSide(); // rlh: row sense hasn't changed. why a fresh copy? // Delete next line. rowSense = clpSolver->getRowSense(); for (int i = 0; i < numCornerPoints; i++) { //get the objective value for this this point double objValue = 0; for (int k = 0; k < numCols; k++) objValue += cornerPoints[i][k] * originalObjCoeff[k]; if (objValue < bestObj) { // check integer feasibility feasibility = 1; for (int j = 0; j < numCols; j++) { if (varClassInt[j]) { double closest = floor(cornerPoints[i][j] + 0.5); if (fabs(cornerPoints[i][j] - closest) > primalTolerance) { feasibility = 0; break; } } } // check all constraints satisfied if (feasibility) { for (int irow = 0; irow < numRows; irow++) { double lhs = 0; for (int j = 0; j < numCols; j++) { lhs += matrix[irow][j] * cornerPoints[i][j]; } if (rowSense[irow] == 'L' && lhs > rhs[irow] + primalTolerance) { feasibility = 0; break; } if (rowSense[irow] == 'G' && lhs < rhs[irow] - primalTolerance) { feasibility = 0; break; } if (rowSense[irow] == 'E' && (lhs - rhs[irow] > primalTolerance || lhs - rhs[irow] < -primalTolerance)) { feasibility = 0; break; } } } if (feasibility) { numFeasibles++; feasibles.push_back(std::vector <double> (numCols)); for (int k = 0; k < numCols; k++) feasibles[numFeasibles-1][k] = cornerPoints[i][k]; printf("obj: %f\n", objValue); if (objValue < bestObj) bestObj = objValue; } } } int numFeasibleCorners; numFeasibleCorners = numFeasibles; //find the center of gravity of the corner points as the first random point double * rp = new double[numCols]; for (int i = 0; i < numCols; i++) { rp[i] = 0; for (int j = 0; j < numCornerPoints; j++) { rp[i] += cornerPoints[j][i]; } rp[i] = rp[i] / numCornerPoints; } //------------------------------------------- //main loop: // -generate the next random point // -round the random point // -check the feasibility of the random point //------------------------------------------- srand ( static_cast<unsigned int>(time(NULL) + 1)); int numRandomPoints = 0; while (numRandomPoints < 50000) { numRandomPoints++; //generate the next random point int randomIndex = intRand(numCornerPoints); double random = CoinDrand48(); for (int i = 0; i < numCols; i++) { rp[i] = (random * (cornerPoints[randomIndex][i] - rp[i])) + rp[i]; } //CRISP ROUNDING //round the random point just generated double * roundRp = new double[numCols]; for (int i = 0; i < numCols; i++) { roundRp[i] = rp[i]; if (varClassInt[i]) { if (rp[i] >= 0) { if (fmod(rp[i], 1) > 0.5) roundRp[i] = floor(rp[i]) + 1; else roundRp[i] = floor(rp[i]); } else { if (fabs(fmod(rp[i], 1)) > 0.5) roundRp[i] = floor(rp[i]); else roundRp[i] = floor(rp[i]) + 1; } } } //SOFT ROUNDING // Look at original files for the "how to" on soft rounding; // Soft rounding omitted here. //Check the feasibility of the rounded random point // -Check the feasibility // -Get the rows sense rowSense = clpSolver->getRowSense(); rhs = clpSolver->getRightHandSide(); //get the objective value for this feasible point double objValue = 0; for (int i = 0; i < numCols; i++) objValue += roundRp[i] * originalObjCoeff[i]; if (objValue < bestObj) { feasibility = 1; for (int i = 0; i < numRows; i++) { double lhs = 0; for (int j = 0; j < numCols; j++) { lhs += matrix[i][j] * roundRp[j]; } if (rowSense[i] == 'L' && lhs > rhs[i] + primalTolerance) { feasibility = 0; break; } if (rowSense[i] == 'G' && lhs < rhs[i] - primalTolerance) { feasibility = 0; break; } if (rowSense[i] == 'E' && (lhs - rhs[i] > primalTolerance || lhs - rhs[i] < -primalTolerance)) { feasibility = 0; break; } } if (feasibility) { printf("Feasible Found.\n"); printf("%.2f\n", CoinCpuTime() - start); numFeasibles++; feasibles.push_back(std::vector <double> (numCols)); for (int i = 0; i < numCols; i++) feasibles[numFeasibles-1][i] = roundRp[i]; printf("obj: %f\n", objValue); if (objValue < bestObj) bestObj = objValue; } } delete [] roundRp; } printf("Number of Feasible Corners: %d\n", numFeasibleCorners); printf("Number of Feasibles Found: %d\n", numFeasibles); if (numFeasibles > 0) printf("Best Objective: %f\n", bestObj); printf("time: %.2f\n", CoinCpuTime() - start); if (numFeasibles == 0) { // cleanup delete [] varClassInt; for (int i = 0; i < numRows; i++) delete matrix[i]; delete [] matrix; delete [] newObj; delete [] index; for (int i = 0; i < numberSolutions; i++) delete cornerPoints[i]; delete [] cornerPoints; delete [] rp; return 0; } // We found something better solutionValue = bestObj; for (int k = 0; k < numCols; k++) { betterSolution[k] = feasibles[numFeasibles-1][k]; } delete [] varClassInt; for (int i = 0; i < numRows; i++) delete matrix[i]; delete [] matrix; delete [] newObj; delete [] index; for (int i = 0; i < numberSolutions; i++) delete cornerPoints[i]; delete [] cornerPoints; delete [] rp; std::cout << "Leaving the Randomized Rounding Heuristic" << std::endl; return 1; }
/* Comments needed Returns 1 if solution, 0 if not */ int CbcHeuristicPivotAndFix::solution(double & /*solutionValue*/, double * /*betterSolution*/) { numCouldRun_++; // Todo: Ask JJHF what this for. std::cout << "Entering Pivot-and-Fix Heuristic" << std::endl; #ifdef HEURISTIC_INFORM printf("Entering heuristic %s - nRuns %d numCould %d when %d\n", heuristicName(),numRuns_,numCouldRun_,when_); #endif #ifdef FORNOW std::cout << "Lucky you! You're in the Pivot-and-Fix Heuristic" << std::endl; // The struct should be moved to member data typedef struct { int numberSolutions; int maximumSolutions; int numberColumns; double ** solution; int * numberUnsatisfied; } clpSolution; double start = CoinCpuTime(); OsiClpSolverInterface * clpSolverOriginal = dynamic_cast<OsiClpSolverInterface *> (model_->solver()); assert (clpSolverOriginal); OsiClpSolverInterface *clpSolver(clpSolverOriginal); ClpSimplex * simplex = clpSolver->getModelPtr(); // Initialize the structure holding the solutions clpSolution solutions; // Set typeStruct field of ClpTrustedData struct to one. // This tells Clp it's "Mahdi!" ClpTrustedData trustedSolutions; trustedSolutions.typeStruct = 1; trustedSolutions.data = &solutions; solutions.numberSolutions = 0; solutions.maximumSolutions = 0; solutions.numberColumns = simplex->numberColumns(); solutions.solution = NULL; solutions.numberUnsatisfied = NULL; simplex->setTrustedUserPointer(&trustedSolutions); // Solve from all slack to get some points simplex->allSlackBasis(); simplex->primal(); // ------------------------------------------------- // Get the problem information // - get the number of cols and rows int numCols = clpSolver->getNumCols(); int numRows = clpSolver->getNumRows(); // - get the right hand side of the rows const double * rhs = clpSolver->getRightHandSide(); // - find the integer variables bool * varClassInt = new bool[numCols]; int numInt = 0; for (int i = 0; i < numCols; i++) { if (clpSolver->isContinuous(i)) varClassInt[i] = 0; else { varClassInt[i] = 1; numInt++; } } // -Get the rows sense const char * rowSense; rowSense = clpSolver->getRowSense(); // -Get the objective coefficients const double *objCoefficients = clpSolver->getObjCoefficients(); double *originalObjCoeff = new double [numCols]; for (int i = 0; i < numCols; i++) originalObjCoeff[i] = objCoefficients[i]; // -Get the matrix of the problem double ** matrix = new double * [numRows]; for (int i = 0; i < numRows; i++) { matrix[i] = new double[numCols]; for (int j = 0; j < numCols; j++) matrix[i][j] = 0; } const CoinPackedMatrix* matrixByRow = clpSolver->getMatrixByRow(); const double * matrixElements = matrixByRow->getElements(); const int * matrixIndices = matrixByRow->getIndices(); const int * matrixStarts = matrixByRow->getVectorStarts(); for (int j = 0; j < numRows; j++) { for (int i = matrixStarts[j]; i < matrixStarts[j+1]; i++) { matrix[j][matrixIndices[i]] = matrixElements[i]; } } // The newObj is the randomly perturbed constraint used to find new // corner points double * newObj = new double [numCols]; // Set the random seed srand ( time(NULL) + 1); int randNum; // We're going to add a new row to the LP formulation // after finding each new solution. // Adding a new row requires the new elements and the new indices. // The elements are original objective function coefficients. // The indicies are the (dense) columns indices stored in addRowIndex. // The rhs is the value of the new solution stored in solutionValue. int * addRowIndex = new int[numCols]; for (int i = 0; i < numCols; i++) addRowIndex[i] = i; // The number of feasible solutions found by the PF heuristic. // This controls the return code of the solution() method. int numFeasibles = 0; // Shuffle the rows int * index = new int [numRows]; for (int i = 0; i < numRows; i++) index[i] = i; for (int i = 0; i < numRows; i++) { int temp = index[i]; int randNumTemp = i + (rand() % (numRows - i)); index[i] = index[randNumTemp]; index[randNumTemp] = temp; } // In the clpSolution struct, we store a lot of column solutions. // For each perturb objective, we store the solution from each // iteration of the LP solve. // For each perturb objective, we look at the collection of // solutions to do something extremly intelligent :-) // We could (and should..and will :-) wipe out the block of // solutions when we're done with them. But for now, we just move on // and store the next block of solutions for the next (perturbed) // objective. // The variable startIndex tells us where the new block begins. int startIndex = 0; // At most "fixThreshold" number of integer variables can be unsatisfied // for calling smallBranchAndBound(). // The PF Heuristic only fixes fixThreshold number of variables to // their integer values. Not more. Not less. The reason is to give // the smallBB some opportunity to find better solutions. If we fix // everything it might be too many (leading the heuristic to come up // with infeasibility rather than a useful result). // (This is an important paramater. And it is dynamically set.) double fixThreshold; /* if(numInt > 400) fixThreshold = 17*sqrt(numInt); if(numInt<=400 && numInt>100) fixThreshold = 5*sqrt(numInt); if(numInt<=100) fixThreshold = 4*sqrt(numInt); */ // Initialize fixThreshold based on the number of integer // variables if (numInt <= 100) fixThreshold = .35 * numInt; if (numInt > 100 && numInt < 1000) fixThreshold = .85 * numInt; if (numInt >= 1000) fixThreshold = .1 * numInt; // Whenever the dynamic system for changing fixThreshold // kicks in, it changes the parameter by the // fixThresholdChange amount. // (The 25% should be member data and tuned. Another paper!) double fixThresholdChange = 0.25 * fixThreshold; // maxNode is the maximum number of nodes we allow smallBB to // search. It's initialized to 400 and changed dynamically. // The 400 should be member data, if we become virtuous. int maxNode = 400; // We control the decision to change maxNode through the boolean // variable changeMaxNode. The boolean variable is initialized to // true and gets set to false under a condition (and is never true // again.) // It's flipped off and stays off (in the current incarnation of PF) bool changeMaxNode = 1; // The sumReturnCode is used for the dynamic system that sets // fixThreshold and changeMaxNode. // // We track what's happening in sumReturnCode. There are 8 switches. // The first 5 switches corresponds to a return code for smallBB. // // We want to know how many times we consecutively get the same // return code. // // If "good" return codes are happening often enough, we're happy. // // If a "bad" returncodes happen consecutively, we want to // change something. // // The switch 5 is the number of times PF didn't call smallBB // becuase the number of integer variables that took integer values // was less than fixThreshold. // // The swicth 6 was added for a brilliant idea...to be announced // later (another paper!) // // The switch 7 is the one that changes the max node. Read the // code. (Todo: Verbalize the brilliant idea for the masses.) // int sumReturnCode[8]; /* sumReturnCode[0] ~ -1 --> problem too big for smallBB sumReturnCode[1] ~ 0 --> smallBB not finshed and no soln sumReturnCode[2] ~ 1 --> smallBB not finshed and there is a soln sumReturnCode[3] ~ 2 --> smallBB finished and no soln sumReturnCode[4] ~ 3 --> smallBB finished and there is a soln sumReturnCode[5] ~ didn't call smallBranchAndBound too few to fix sumReturnCode[6] ~ didn't call smallBranchAndBound too many unsatisfied sumReturnCode[7] ~ the same as sumReturnCode[1] but becomes zero just if the returnCode is not 0 */ for (int i = 0; i < 8; i++) sumReturnCode[i] = 0; int * colIndex = new int[numCols]; for (int i = 0; i < numCols; i++) colIndex[i] = i; double cutoff = COIN_DBL_MAX; bool didMiniBB; // Main loop for (int i = 0; i < numRows; i++) { // track the number of mini-bb for the dynamic threshold setting didMiniBB = 0; for (int k = startIndex; k < solutions.numberSolutions; k++) //if the point has 0 unsatisfied variables; make sure it is //feasible. Check integer feasiblity and constraints. if (solutions.numberUnsatisfied[k] == 0) { double feasibility = 1; //check integer feasibility for (int icol = 0; icol < numCols; icol++) { double closest = floor(solutions.solution[k][icol] + 0.5); if (varClassInt[icol] && (fabs(solutions.solution[k][icol] - closest) > 1e-6)) { feasibility = 0; break; } } //check if the solution satisfies the constraints for (int irow = 0; irow < numRows; irow++) { double lhs = 0; for (int j = 0; j < numCols; j++) lhs += matrix[irow][j] * solutions.solution[k][j]; if (rowSense[irow] == 'L' && lhs > rhs[irow] + 1e-6) { feasibility = 0; break; } if (rowSense[irow] == 'G' && lhs < rhs[irow] - 1e-6) { feasibility = 0; break; } if (rowSense[irow] == 'E' && (lhs - rhs[irow] > 1e-6 || lhs - rhs[irow] < -1e-6)) { feasibility = 0; break; } } //if feasible, find the objective value and set the cutoff // for the smallBB and add a new constraint to the LP // (and update the best solution found so far for the // return arguments) if (feasibility) { double objectiveValue = 0; for (int j = 0; j < numCols; j++) objectiveValue += solutions.solution[k][j] * originalObjCoeff[j]; cutoff = objectiveValue; clpSolver->addRow(numCols, addRowIndex, originalObjCoeff, -COIN_DBL_MAX, cutoff); // Todo: pick up the best solution in the block (not // the last). solutionValue = objectiveValue; for (int m = 0; m < numCols; m++) betterSolution[m] = solutions.solution[k][m]; numFeasibles++; } } // Go through the block of solution and decide if to call smallBB for (int k = startIndex; k < solutions.numberSolutions; k++) { if (solutions.numberUnsatisfied[k] <= fixThreshold) { // get new copy OsiSolverInterface * newSolver; newSolver = new OsiClpSolverInterface(*clpSolver); newSolver->setObjSense(1); newSolver->setObjective(originalObjCoeff); int numberColumns = newSolver->getNumCols(); int numFixed = 0; // Fix the first fixThreshold number of integer vars // that are satisfied for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) { if (newSolver->isInteger(iColumn)) { double value = solutions.solution[k][iColumn]; double intValue = floor(value + 0.5); if (fabs(value - intValue) < 1.0e-5) { newSolver->setColLower(iColumn, intValue); newSolver->setColUpper(iColumn, intValue); numFixed++; if (numFixed > numInt - fixThreshold) break; } } } COIN_DETAIL_PRINT(printf("numFixed: %d\n", numFixed)); COIN_DETAIL_PRINT(printf("fixThreshold: %f\n", fixThreshold)); COIN_DETAIL_PRINT(printf("numInt: %d\n", numInt)); double *newSolution = new double[numCols]; double newSolutionValue; // Call smallBB on the modified problem int returnCode = smallBranchAndBound(newSolver, maxNode, newSolution, newSolutionValue, cutoff, "mini"); // If smallBB found a solution, update the better // solution and solutionValue (we gave smallBB our // cutoff, so it only finds improving solutions) if (returnCode == 1 || returnCode == 3) { numFeasibles ++; solutionValue = newSolutionValue; for (int m = 0; m < numCols; m++) betterSolution[m] = newSolution[m]; COIN_DETAIL_PRINT(printf("cutoff: %f\n", newSolutionValue)); COIN_DETAIL_PRINT(printf("time: %.2lf\n", CoinCpuTime() - start)); } didMiniBB = 1; COIN_DETAIL_PRINT(printf("returnCode: %d\n", returnCode)); //Update sumReturnCode array for (int iRC = 0; iRC < 6; iRC++) { if (iRC == returnCode + 1) sumReturnCode[iRC]++; else sumReturnCode[iRC] = 0; } if (returnCode != 0) sumReturnCode[7] = 0; else sumReturnCode[7]++; if (returnCode == 1 || returnCode == 3) { cutoff = newSolutionValue; clpSolver->addRow(numCols, addRowIndex, originalObjCoeff, -COIN_DBL_MAX, cutoff); COIN_DETAIL_PRINT(printf("******************\n\n*****************\n")); } break; } } if (!didMiniBB && solutions.numberSolutions - startIndex > 0) { sumReturnCode[5]++; for (int iRC = 0; iRC < 5; iRC++) sumReturnCode[iRC] = 0; } //Change "fixThreshold" if needed // using the data we've recorded in sumReturnCode if (sumReturnCode[1] >= 3) fixThreshold -= fixThresholdChange; if (sumReturnCode[7] >= 3 && changeMaxNode) { maxNode *= 5; changeMaxNode = 0; } if (sumReturnCode[3] >= 3 && fixThreshold < 0.95 * numInt) fixThreshold += fixThresholdChange; if (sumReturnCode[5] >= 4) fixThreshold += fixThresholdChange; if (sumReturnCode[0] > 3) fixThreshold -= fixThresholdChange; startIndex = solutions.numberSolutions; //Check if the maximum iterations limit is reached // rlh: Ask John how this is working with the change to trustedUserPtr. if (solutions.numberSolutions > 20000) break; // The first time in this loop PF solves orig LP. //Generate the random objective function randNum = rand() % 10 + 1; randNum = fmod(randNum, 2); for (int j = 0; j < numCols; j++) { if (randNum == 1) if (fabs(matrix[index[i]][j]) < 1e-6) newObj[j] = 0.1; else newObj[j] = matrix[index[i]][j] * 1.1; else if (fabs(matrix[index[i]][j]) < 1e-6) newObj[j] = -0.1; else newObj[j] = matrix[index[i]][j] * 0.9; } clpSolver->setObjective(newObj); if (rowSense[i] == 'L') clpSolver->setObjSense(-1); else // Todo #1: We don't need to solve the LPs to optimality. // We just need corner points. // There's a problem in stopping Clp that needs to be looked // into. So for now, we solve optimality. clpSolver->setObjSense(1); // simplex->setMaximumIterations(100); clpSolver->getModelPtr()->primal(1); // simplex->setMaximumIterations(100000); #ifdef COIN_DETAIL printf("cutoff: %f\n", cutoff); printf("time: %.2f\n", CoinCpuTime() - start); for (int iRC = 0; iRC < 8; iRC++) printf("%d ", sumReturnCode[iRC]); printf("\nfixThreshold: %f\n", fixThreshold); printf("numInt: %d\n", numInt); printf("\n---------------------------------------------------------------- %d\n", i); #endif //temp: if (i > 3) break; } COIN_DETAIL_PRINT(printf("Best Feasible Found: %f\n", cutoff)); COIN_DETAIL_PRINT(printf("Total time: %.2f\n", CoinCpuTime() - start)); if (numFeasibles == 0) { return 0; } // We found something better std::cout << "See you soon! You're leaving the Pivot-and-Fix Heuristic" << std::endl; std::cout << std::endl; return 1; #endif return 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; }
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; }