int main(int argc, const char *argv[]) { #if COIN_BIG_INDEX<2 ClpSimplex model; int status; int maxIts = 0; int maxFactor = 100; 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); } if (argc > 2) { maxFactor = atoi(argv[2]); printf("max factor %d\n", maxFactor); } if (argc > 3) { maxIts = atoi(argv[3]); printf("max its %d\n", maxIts); } // For now scaling off model.scaling(0); if (maxIts) { // Do partial dantzig ClpPrimalColumnSteepest dantzig(5); model.setPrimalColumnPivotAlgorithm(dantzig); //model.messageHandler()->setLogLevel(63); model.setFactorizationFrequency(maxFactor); model.setMaximumIterations(maxIts); model.primal(); if (!model.status()) exit(1); } // find gub int numberRows = model.numberRows(); int * gubStart = new int[numberRows+1]; int * gubEnd = new int[numberRows]; int * which = new int[numberRows]; int * whichGub = new int[numberRows]; int numberColumns = model.numberColumns(); int * mark = new int[numberColumns]; int iRow, iColumn; // delete variables fixed to zero const double * columnLower = model.columnLower(); const double * columnUpper = model.columnUpper(); int numberDelete = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] == 0.0 && columnLower[iColumn] == 0.0) mark[numberDelete++] = iColumn; } if (numberDelete) { model.deleteColumns(numberDelete, mark); numberColumns -= numberDelete; columnLower = model.columnLower(); columnUpper = model.columnUpper(); #if 0 CoinMpsIO writer; writer.setMpsData(*model.matrix(), COIN_DBL_MAX, model.getColLower(), model.getColUpper(), model.getObjCoefficients(), (const char*) 0 /*integrality*/, model.getRowLower(), model.getRowUpper(), NULL, NULL); writer.writeMps("cza.mps", 0, 0, 1); #endif } double * lower = new double[numberRows]; double * upper = new double[numberRows]; const double * rowLower = model.rowLower(); const double * rowUpper = model.rowUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) mark[iColumn] = -1; 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(); int putGub = numberRows; int putNonGub = numberRows; int * rowIsGub = new int [numberRows]; for (iRow = numberRows - 1; iRow >= 0; iRow--) { bool gubRow = true; int first = numberColumns + 1; int last = -1; for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { if (element[j] != 1.0) { gubRow = false; break; } else { int iColumn = column[j]; if (mark[iColumn] >= 0) { gubRow = false; break; } else { last = CoinMax(last, iColumn); first = CoinMin(first, iColumn); } } } if (last - first + 1 != rowLength[iRow] || !gubRow) { which[--putNonGub] = iRow; rowIsGub[iRow] = 0; } else { for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; mark[iColumn] = iRow; } rowIsGub[iRow] = -1; putGub--; gubStart[putGub] = first; gubEnd[putGub] = last + 1; lower[putGub] = rowLower[iRow]; upper[putGub] = rowUpper[iRow]; whichGub[putGub] = iRow; } } int numberNonGub = numberRows - putNonGub; int numberGub = numberRows - putGub; if (numberGub > 0) { printf("** %d gub rows\n", numberGub); int numberNormal = 0; const int * row = matrix->getIndices(); const int * columnLength = matrix->getVectorLengths(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const double * elementByColumn = matrix->getElements(); int numberElements = 0; bool doLower = false; bool doUpper = false; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (mark[iColumn] < 0) { mark[numberNormal++] = iColumn; } else { numberElements += columnLength[iColumn]; if (columnLower[iColumn] != 0.0) doLower = true; if (columnUpper[iColumn] < 1.0e20) doUpper = true; } } if (!numberNormal) { printf("Putting back one gub row to make non-empty\n"); for (iColumn = gubStart[putGub]; iColumn < gubEnd[putGub]; iColumn++) mark[numberNormal++] = iColumn; putGub++; numberGub--; } ClpSimplex model2(&model, numberNonGub, which + putNonGub, numberNormal, mark); int numberGubColumns = numberColumns - numberNormal; // sort gubs so monotonic int * which = new int[numberGub]; int i; for (i = 0; i < numberGub; i++) which[i] = i; CoinSort_2(gubStart + putGub, gubStart + putGub + numberGub, which); int * temp1 = new int [numberGub]; for (i = 0; i < numberGub; i++) { int k = which[i]; temp1[i] = gubEnd[putGub+k]; } memcpy(gubEnd + putGub, temp1, numberGub * sizeof(int)); delete [] temp1; double * temp2 = new double [numberGub]; for (i = 0; i < numberGub; i++) { int k = which[i]; temp2[i] = lower[putGub+k]; } memcpy(lower + putGub, temp2, numberGub * sizeof(double)); for (i = 0; i < numberGub; i++) { int k = which[i]; temp2[i] = upper[putGub+k]; } memcpy(upper + putGub, temp2, numberGub * sizeof(double)); delete [] temp2; delete [] which; numberElements -= numberGubColumns; int * start2 = new int[numberGubColumns+1]; int * row2 = new int[numberElements]; double * element2 = new double[numberElements]; double * cost2 = new double [numberGubColumns]; double * lowerColumn2 = NULL; if (doLower) { lowerColumn2 = new double [numberGubColumns]; CoinFillN(lowerColumn2, numberGubColumns, 0.0); } double * upperColumn2 = NULL; if (doUpper) { upperColumn2 = new double [numberGubColumns]; CoinFillN(upperColumn2, numberGubColumns, COIN_DBL_MAX); } numberElements = 0; int numberNonGubRows = 0; for (iRow = 0; iRow < numberRows; iRow++) { if (!rowIsGub[iRow]) rowIsGub[iRow] = numberNonGubRows++; } numberColumns = 0; gubStart[0] = 0; start2[0] = 0; const double * cost = model.objective(); for (int iSet = 0; iSet < numberGub; iSet++) { int iStart = gubStart[iSet+putGub]; int iEnd = gubEnd[iSet+putGub]; for (int k = iStart; k < iEnd; k++) { cost2[numberColumns] = cost[k]; if (columnLower[k]) lowerColumn2[numberColumns] = columnLower[k]; if (columnUpper[k] < 1.0e20) upperColumn2[numberColumns] = columnUpper[k]; for (int j = columnStart[k]; j < columnStart[k] + columnLength[k]; j++) { int iRow = rowIsGub[row[j]]; if (iRow >= 0) { row2[numberElements] = iRow; element2[numberElements++] = elementByColumn[j]; } } start2[++numberColumns] = numberElements; } gubStart[iSet+1] = numberColumns; } model2.replaceMatrix(new ClpGubDynamicMatrix(&model2, numberGub, numberColumns, gubStart, lower + putGub, upper + putGub, start2, row2, element2, cost2, lowerColumn2, upperColumn2)); delete [] rowIsGub; delete [] start2; delete [] row2; delete [] element2; delete [] cost2; delete [] lowerColumn2; delete [] upperColumn2; // For now scaling off model2.scaling(0); // Do partial dantzig ClpPrimalColumnSteepest dantzig(5); model2.setPrimalColumnPivotAlgorithm(dantzig); //model2.messageHandler()->setLogLevel(63); model2.setFactorizationFrequency(maxFactor); model2.setMaximumIterations(4000000); double time1 = CoinCpuTime(); model2.primal(); { ClpGubDynamicMatrix * gubMatrix = dynamic_cast< ClpGubDynamicMatrix*>(model2.clpMatrix()); assert(gubMatrix); const double * solution = model2.primalColumnSolution(); int numberGubColumns = gubMatrix->numberGubColumns(); int firstOdd = gubMatrix->firstDynamic(); int lastOdd = gubMatrix->firstAvailable(); int numberTotalColumns = firstOdd + numberGubColumns; int numberRows = model2.numberRows(); char * status = new char [numberTotalColumns]; double * gubSolution = new double [numberTotalColumns]; int numberSets = gubMatrix->numberSets(); const int * id = gubMatrix->id(); int i; const double * lowerColumn = gubMatrix->lowerColumn(); const double * upperColumn = gubMatrix->upperColumn(); for (i = 0; i < numberGubColumns; i++) { if (gubMatrix->getDynamicStatus(i) == ClpGubDynamicMatrix::atUpperBound) { gubSolution[i+firstOdd] = upperColumn[i]; status[i+firstOdd] = 2; } else if (gubMatrix->getDynamicStatus(i) == ClpGubDynamicMatrix::atLowerBound && lowerColumn) { gubSolution[i+firstOdd] = lowerColumn[i]; status[i+firstOdd] = 1; } else { gubSolution[i+firstOdd] = 0.0; status[i+firstOdd] = 1; } } for (i = 0; i < firstOdd; i++) { ClpSimplex::Status thisStatus = model2.getStatus(i); if (thisStatus == ClpSimplex::basic) status[i] = 0; else if (thisStatus == ClpSimplex::atLowerBound) status[i] = 1; else if (thisStatus == ClpSimplex::atUpperBound) status[i] = 2; else if (thisStatus == ClpSimplex::isFixed) status[i] = 3; else abort(); gubSolution[i] = solution[i]; } for (i = firstOdd; i < lastOdd; i++) { int iBig = id[i-firstOdd] + firstOdd; ClpSimplex::Status thisStatus = model2.getStatus(i); if (thisStatus == ClpSimplex::basic) status[iBig] = 0; else if (thisStatus == ClpSimplex::atLowerBound) status[iBig] = 1; else if (thisStatus == ClpSimplex::atUpperBound) status[iBig] = 2; else if (thisStatus == ClpSimplex::isFixed) status[iBig] = 3; else abort(); gubSolution[iBig] = solution[i]; } char * rowStatus = new char[numberRows]; for (i = 0; i < numberRows; i++) { ClpSimplex::Status thisStatus = model2.getRowStatus(i); if (thisStatus == ClpSimplex::basic) rowStatus[i] = 0; else if (thisStatus == ClpSimplex::atLowerBound) rowStatus[i] = 1; else if (thisStatus == ClpSimplex::atUpperBound) rowStatus[i] = 2; else if (thisStatus == ClpSimplex::isFixed) rowStatus[i] = 3; else abort(); } char * setStatus = new char[numberSets]; int * keyVariable = new int[numberSets]; memcpy(keyVariable, gubMatrix->keyVariable(), numberSets * sizeof(int)); for (i = 0; i < numberSets; i++) { int iKey = keyVariable[i]; if (iKey > lastOdd) iKey = numberTotalColumns + i; else iKey = id[iKey-firstOdd] + firstOdd; keyVariable[i] = iKey; ClpSimplex::Status thisStatus = gubMatrix->getStatus(i); if (thisStatus == ClpSimplex::basic) setStatus[i] = 0; else if (thisStatus == ClpSimplex::atLowerBound) setStatus[i] = 1; else if (thisStatus == ClpSimplex::atUpperBound) setStatus[i] = 2; else if (thisStatus == ClpSimplex::isFixed) setStatus[i] = 3; else abort(); } FILE * fp = fopen("xx.sol", "w"); fwrite(gubSolution, sizeof(double), numberTotalColumns, fp); fwrite(status, sizeof(char), numberTotalColumns, fp); const double * rowsol = model2.primalRowSolution(); int originalNumberRows = model.numberRows(); double * rowsol2 = new double[originalNumberRows]; memset(rowsol2, 0, originalNumberRows * sizeof(double)); model.times(1.0, gubSolution, rowsol2); for (i = 0; i < numberRows; i++) assert(fabs(rowsol[i] - rowsol2[i]) < 1.0e-3); //for (;i<originalNumberRows;i++) //printf("%d %g\n",i,rowsol2[i]); delete [] rowsol2; fwrite(rowsol, sizeof(double), numberRows, fp); fwrite(rowStatus, sizeof(char), numberRows, fp); fwrite(setStatus, sizeof(char), numberSets, fp); fwrite(keyVariable, sizeof(int), numberSets, fp); fclose(fp); delete [] status; delete [] gubSolution; delete [] setStatus; delete [] keyVariable; // ** if going to rstart as dynamic need id_ // also copy coding in useEf.. from ClpGubMatrix (i.e. test for basis) } printf("obj offset is %g\n", model2.objectiveOffset()); printf("Primal took %g seconds\n", CoinCpuTime() - time1); //model2.primal(1); } delete [] mark; delete [] gubStart; delete [] gubEnd; delete [] which; delete [] whichGub; delete [] lower; delete [] upper; #else printf("testGub2 not available with COIN_BIG_INDEX=2\n"); #endif return 0; }
CbcBranchingObject * CbcGeneralDepth::createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int /*way*/) { int numberDo = numberNodes_; if (whichSolution_ >= 0 && (model_->moreSpecialOptions()&33554432)==0) numberDo--; assert (numberDo > 0); // create object CbcGeneralBranchingObject * branch = new CbcGeneralBranchingObject(model_); // skip solution branch->numberSubProblems_ = numberDo; // If parentBranch_ back in then will have to be 2* branch->numberSubLeft_ = numberDo; branch->setNumberBranches(numberDo); CbcSubProblem * sub = new CbcSubProblem[numberDo]; int iProb = 0; branch->subProblems_ = sub; branch->numberRows_ = model_->solver()->getNumRows(); int iNode; //OsiSolverInterface * solver = model_->solver(); OsiClpSolverInterface * clpSolver = dynamic_cast<OsiClpSolverInterface *> (solver); assert (clpSolver); ClpSimplex * simplex = clpSolver->getModelPtr(); int numberColumns = simplex->numberColumns(); if ((model_->moreSpecialOptions()&33554432)==0) { double * lowerBefore = CoinCopyOfArray(simplex->getColLower(), numberColumns); double * upperBefore = CoinCopyOfArray(simplex->getColUpper(), numberColumns); ClpNodeStuff * info = nodeInfo_; double * weight = new double[numberNodes_]; int * whichNode = new int [numberNodes_]; // Sort for (iNode = 0; iNode < numberNodes_; iNode++) { if (iNode != whichSolution_) { double objectiveValue = info->nodeInfo_[iNode]->objectiveValue(); double sumInfeasibilities = info->nodeInfo_[iNode]->sumInfeasibilities(); int numberInfeasibilities = info->nodeInfo_[iNode]->numberInfeasibilities(); double thisWeight = 0.0; #if 1 // just closest thisWeight = 1.0e9 * numberInfeasibilities; thisWeight += sumInfeasibilities; thisWeight += 1.0e-7 * objectiveValue; // Try estimate thisWeight = info->nodeInfo_[iNode]->estimatedSolution(); #else thisWeight = 1.0e-3 * numberInfeasibilities; thisWeight += 1.0e-5 * sumInfeasibilities; thisWeight += objectiveValue; #endif whichNode[iProb] = iNode; weight[iProb++] = thisWeight; } } assert (iProb == numberDo); CoinSort_2(weight, weight + numberDo, whichNode); for (iProb = 0; iProb < numberDo; iProb++) { iNode = whichNode[iProb]; ClpNode * node = info->nodeInfo_[iNode]; // move bounds node->applyNode(simplex, 3); // create subproblem sub[iProb] = CbcSubProblem(clpSolver, lowerBefore, upperBefore, node->statusArray(), node->depth()); sub[iProb].objectiveValue_ = node->objectiveValue(); sub[iProb].sumInfeasibilities_ = node->sumInfeasibilities(); sub[iProb].numberInfeasibilities_ = node->numberInfeasibilities(); #ifdef CHECK_PATH if (simplex->numberColumns() == numberColumns_Z) { bool onOptimal = true; const double * columnLower = simplex->columnLower(); const double * columnUpper = simplex->columnUpper(); for (int i = 0; i < numberColumns_Z; i++) { if (iNode == gotGoodNode_Z) printf("good %d %d %g %g\n", iNode, i, columnLower[i], columnUpper[i]); if (columnUpper[i] < debuggerSolution_Z[i] || columnLower[i] > debuggerSolution_Z[i] && simplex->isInteger(i)) { onOptimal = false; break; } } if (onOptimal) { printf("adding to node %x as %d - objs\n", this, iProb); for (int j = 0; j <= iProb; j++) printf("%d %g\n", j, sub[j].objectiveValue_); } } #endif } delete [] weight; delete [] whichNode; const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); // restore bounds for ( int j = 0; j < numberColumns; j++) { if (lowerBefore[j] != lower[j]) solver->setColLower(j, lowerBefore[j]); if (upperBefore[j] != upper[j]) solver->setColUpper(j, upperBefore[j]); } delete [] upperBefore; delete [] lowerBefore; } else { // from diving CbcSubProblem ** nodes = reinterpret_cast<CbcSubProblem **> (model_->temporaryPointer()); assert (nodes); int adjustDepth=info->depth_; assert (numberDo); numberNodes_=0; for (iProb = 0; iProb < numberDo; iProb++) { if ((nodes[iProb]->problemStatus_&2)==0) { // create subproblem (and swap way and/or make inactive) sub[numberNodes_].takeOver(*nodes[iProb],true); // but adjust depth sub[numberNodes_].depth_+=adjustDepth; numberNodes_++; } delete nodes[iProb]; } branch->numberSubProblems_ = numberNodes_; branch->numberSubLeft_ = numberNodes_; branch->setNumberBranches(numberNodes_); if (!numberNodes_) { // infeasible delete branch; branch=NULL; } delete [] nodes; } return branch; }
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; }
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[]) { // 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 when reading an mps file 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) { fprintf(stderr, "Bad readMps %s\n", argv[1]); fprintf(stdout, "Bad readMps %s\n", argv[1]); exit(1); } #ifdef STYLE1 if (argc < 3 || !strstr(argv[2], "primal")) { // Use the dual algorithm unless user said "primal" model.initialDualSolve(); } else { model.initialPrimalSolve(); } #else ClpSolve solvectl; if (argc < 3 || (!strstr(argv[2], "primal") && !strstr(argv[2], "barrier"))) { // Use the dual algorithm unless user said "primal" or "barrier" std::cout << std::endl << " Solve using Dual: " << std::endl; solvectl.setSolveType(ClpSolve::useDual); solvectl.setPresolveType(ClpSolve::presolveOn); model.initialSolve(solvectl); } else if (strstr(argv[2], "barrier")) { // Use the barrier algorithm if user said "barrier" std::cout << std::endl << " Solve using Barrier: " << std::endl; solvectl.setSolveType(ClpSolve::useBarrier); solvectl.setPresolveType(ClpSolve::presolveOn); model.initialSolve(solvectl); } else { std::cout << std::endl << " Solve using Primal: " << std::endl; solvectl.setSolveType(ClpSolve::usePrimal); solvectl.setPresolveType(ClpSolve::presolveOn); model.initialSolve(solvectl); } #endif std::string modelName; model.getStrParam(ClpProbName, modelName); std::cout << "Model " << modelName << " has " << model.numberRows() << " rows and " << model.numberColumns() << " columns" << std::endl; // remove this to print solution exit(0); /* 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. This version just does non-zero columns */ #if 0 int numberRows = model.numberRows(); // Alternatively getRowActivity() double * rowPrimal = model.primalRowSolution(); // Alternatively getRowPrice() double * rowDual = model.dualRowSolution(); // Alternatively getRowLower() double * rowLower = model.rowLower(); // Alternatively getRowUpper() double * rowUpper = model.rowUpper(); // Alternatively getRowObjCoefficients() double * rowObjective = model.rowObjective(); // If we have not kept names (parameter to readMps) this will be 0 assert(model.lengthNames()); // Row names const std::vector<std::string> * rowNames = model.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; } #endif std::cout << "--------------------------------------" << std::endl; // Columns 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(); // If we have not kept names (parameter to readMps) this will be 0 assert(model.lengthNames()); // Column names const std::vector<std::string> * columnNames = model.columnNames(); int iColumn; std::cout << " Primal Dual Lower Upper Cost" << std::endl; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value; value = columnPrimal[iColumn]; if (fabs(value) > 1.0e-8) { std::cout << std::setw(6) << iColumn << " " << std::setw(8) << (*columnNames)[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; return 0; }
int main (int argc, const char *argv[]) { ClpSimplex model; int status; int maxFactor = 100; if (argc < 2) { status = model.readMps("../../Data/Netlib/czprob.mps"); if (status) { printf("Unable to read matrix - trying gzipped version\n"); status = model.readMps("../../Data/Netlib/czprob.mps.gz"); } } else { status = model.readMps(argv[1]); } if (status) { printf("errors on input\n"); exit(77); } if (argc > 2) { maxFactor = atoi(argv[2]); printf("max factor %d\n", maxFactor); } if (argc > 3) { printf("Using ClpDynamicMatrix\n"); } else { printf("Using ClpDynamicExampleMatrix\n"); } // find gub int numberRows = model.numberRows(); int * gubStart = new int[numberRows+1]; int * gubEnd = new int[numberRows]; int * which = new int[numberRows]; int * whichGub = new int[numberRows]; int numberColumns = model.numberColumns(); int * mark = new int[numberColumns]; int iRow, iColumn; // delete variables fixed to zero const double * columnLower = model.columnLower(); const double * columnUpper = model.columnUpper(); int numberDelete = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] == 0.0 && columnLower[iColumn] == 0.0) mark[numberDelete++] = iColumn; } if (numberDelete) { model.deleteColumns(numberDelete, mark); numberColumns -= numberDelete; columnLower = model.columnLower(); columnUpper = model.columnUpper(); } double * lower = new double[numberRows]; double * upper = new double[numberRows]; const double * rowLower = model.rowLower(); const double * rowUpper = model.rowUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) mark[iColumn] = -1; 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(); int putGub = numberRows; int putNonGub = numberRows; int * rowIsGub = new int [numberRows]; for (iRow = numberRows - 1; iRow >= 0; iRow--) { bool gubRow = true; int first = numberColumns + 1; int last = -1; for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { if (element[j] != 1.0) { gubRow = false; break; } else { int iColumn = column[j]; if (mark[iColumn] >= 0) { gubRow = false; break; } else { last = CoinMax(last, iColumn); first = CoinMin(first, iColumn); } } } if (last - first + 1 != rowLength[iRow] || !gubRow) { which[--putNonGub] = iRow; rowIsGub[iRow] = 0; } else { for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; mark[iColumn] = iRow; } rowIsGub[iRow] = -1; putGub--; gubStart[putGub] = first; gubEnd[putGub] = last + 1; lower[putGub] = rowLower[iRow]; upper[putGub] = rowUpper[iRow]; whichGub[putGub] = iRow; } } int numberNonGub = numberRows - putNonGub; int numberGub = numberRows - putGub; if (numberGub > 0) { printf("** %d gub rows\n", numberGub); int numberNormal = 0; const int * row = matrix->getIndices(); const int * columnLength = matrix->getVectorLengths(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const double * elementByColumn = matrix->getElements(); int numberElements = 0; bool doLower = false; bool doUpper = false; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (mark[iColumn] < 0) { mark[numberNormal++] = iColumn; } else { numberElements += columnLength[iColumn]; if (columnLower[iColumn] != 0.0) doLower = true; if (columnUpper[iColumn] < 1.0e20) doUpper = true; } } if (!numberNormal) { printf("Putting back one gub row to make non-empty\n"); for (iColumn = gubStart[putGub]; iColumn < gubEnd[putGub]; iColumn++) mark[numberNormal++] = iColumn; putGub++; numberGub--; } ClpSimplex model2(&model, numberNonGub, which + putNonGub, numberNormal, mark); // and copy for restart test ClpSimplex model3 = model2; int numberGubColumns = numberColumns - numberNormal; // sort gubs so monotonic int * which = new int[numberGub]; int i; for (i = 0; i < numberGub; i++) which[i] = i; CoinSort_2(gubStart + putGub, gubStart + putGub + numberGub, which); // move to bottom if we want to use later memmove(gubStart, gubStart + putGub, numberGub * sizeof(int)); int * temp1 = new int [numberGub]; for (i = 0; i < numberGub; i++) { int k = which[i]; temp1[i] = gubEnd[putGub+k]; } memcpy(gubEnd, temp1, numberGub * sizeof(int)); delete [] temp1; double * temp2 = new double [numberGub]; for (i = 0; i < numberGub; i++) { int k = which[i]; temp2[i] = lower[putGub+k]; } memcpy(lower, temp2, numberGub * sizeof(double)); for (i = 0; i < numberGub; i++) { int k = which[i]; temp2[i] = upper[putGub+k]; } memcpy(upper, temp2, numberGub * sizeof(double)); delete [] temp2; delete [] which; numberElements -= numberGubColumns; int * start2 = new int[numberGubColumns+1]; int * row2 = new int[numberElements]; double * element2 = new double[numberElements]; double * cost2 = new double [numberGubColumns]; double * lowerColumn2 = NULL; if (doLower) { lowerColumn2 = new double [numberGubColumns]; CoinFillN(lowerColumn2, numberGubColumns, 0.0); } double * upperColumn2 = NULL; if (doUpper) { upperColumn2 = new double [numberGubColumns]; CoinFillN(upperColumn2, numberGubColumns, COIN_DBL_MAX); } numberElements = 0; int numberNonGubRows = 0; for (iRow = 0; iRow < numberRows; iRow++) { if (!rowIsGub[iRow]) rowIsGub[iRow] = numberNonGubRows++; } numberColumns = 0; int iStart = gubStart[0]; gubStart[0] = 0; start2[0] = 0; const double * cost = model.objective(); for (int iSet = 0; iSet < numberGub; iSet++) { int iEnd = gubEnd[iSet]; for (int k = iStart; k < iEnd; k++) { cost2[numberColumns] = cost[k]; if (columnLower[k]) lowerColumn2[numberColumns] = columnLower[k]; if (columnUpper[k] < 1.0e20) upperColumn2[numberColumns] = columnUpper[k]; for (int j = columnStart[k]; j < columnStart[k] + columnLength[k]; j++) { int iRow = rowIsGub[row[j]]; if (iRow >= 0) { row2[numberElements] = iRow; element2[numberElements++] = elementByColumn[j]; } } start2[++numberColumns] = numberElements; } if (iSet < numberGub - 1) iStart = gubStart[iSet+1]; gubStart[iSet+1] = numberColumns; } printf("** Before adding matrix there are %d rows and %d columns\n", model2.numberRows(), model2.numberColumns()); if (argc > 3) { ClpDynamicMatrix * newMatrix = new ClpDynamicMatrix(&model2, numberGub, numberColumns, gubStart, lower, upper, start2, row2, element2, cost2, lowerColumn2, upperColumn2); model2.replaceMatrix(newMatrix); newMatrix->switchOffCheck(); newMatrix->setRefreshFrequency(1000); } else { ClpDynamicExampleMatrix * newMatrix = new ClpDynamicExampleMatrix(&model2, numberGub, numberColumns, gubStart, lower, upper, start2, row2, element2, cost2, lowerColumn2, upperColumn2); model2.replaceMatrix(newMatrix); newMatrix->switchOffCheck(); newMatrix->setRefreshFrequency(1000); } printf("** While after adding matrix there are %d rows and %d columns\n", model2.numberRows(), model2.numberColumns()); model2.setSpecialOptions(4); // exactly to bound // For now scaling off model2.scaling(0); ClpPrimalColumnSteepest steepest(5); model2.setPrimalColumnPivotAlgorithm(steepest); //model2.messageHandler()->setLogLevel(63); model2.setFactorizationFrequency(maxFactor); model2.setMaximumIterations(4000000); double time1 = CoinCpuTime(); model2.primal(); // can't use values pass model2.primal(0); // test proper restart if (argc > 3) { ClpDynamicMatrix * oldMatrix = dynamic_cast< ClpDynamicMatrix*>(model2.clpMatrix()); assert (oldMatrix); ClpDynamicMatrix * newMatrix = new ClpDynamicMatrix(&model3, numberGub, numberColumns, gubStart, lower, upper, start2, row2, element2, cost2, lowerColumn2, upperColumn2, oldMatrix->gubRowStatus(), oldMatrix->dynamicStatus()); model3.replaceMatrix(newMatrix); // and ordinary status (but only NON gub rows) memcpy(model3.statusArray(), model2.statusArray(), (newMatrix->numberStaticRows() + model3.numberColumns())*sizeof(unsigned char)); newMatrix->switchOffCheck(); newMatrix->setRefreshFrequency(1000); } else { ClpDynamicExampleMatrix * oldMatrix = dynamic_cast< ClpDynamicExampleMatrix*>(model2.clpMatrix()); assert (oldMatrix); ClpDynamicExampleMatrix * newMatrix = new ClpDynamicExampleMatrix(&model3, numberGub, numberColumns, gubStart, lower, upper, start2, row2, element2, cost2, lowerColumn2, upperColumn2, oldMatrix->gubRowStatus(), oldMatrix->dynamicStatus(), oldMatrix->numberGubColumns(), oldMatrix->idGen()); model3.replaceMatrix(newMatrix); // and ordinary status (but only NON gub rows) memcpy(model3.statusArray(), model2.statusArray(), (newMatrix->numberStaticRows() + model3.numberColumns())*sizeof(unsigned char)); newMatrix->switchOffCheck(); newMatrix->setRefreshFrequency(1000); } model3.setSpecialOptions(4); // exactly to bound // For now scaling off model3.scaling(0); model3.setPrimalColumnPivotAlgorithm(steepest); model3.messageHandler()->setLogLevel(63); model3.setFactorizationFrequency(maxFactor); model3.setMaximumIterations(4000000); delete [] rowIsGub; delete [] start2; delete [] row2; delete [] element2; delete [] cost2; delete [] lowerColumn2; delete [] upperColumn2; model3.primal(); // this code expects non gub first in original matrix // and only works at present for ClpDynamicMatrix ClpDynamicMatrix * gubMatrix = dynamic_cast< ClpDynamicMatrix*>(model2.clpMatrix()); assert (gubMatrix); ClpDynamicExampleMatrix * gubMatrix2 = dynamic_cast< ClpDynamicExampleMatrix*>(model2.clpMatrix()); if (!gubMatrix2) { const double * solution = model2.primalColumnSolution(); const double * cost = model.objective(); int numberGubColumns = gubMatrix->numberGubColumns(); int firstOdd = gubMatrix->firstDynamic(); int lastOdd = gubMatrix->firstAvailable(); int numberTotalColumns = firstOdd + numberGubColumns; int originalNumberRows = model.numberRows(); int numberStaticRows = gubMatrix->numberStaticRows(); char * status = new char [numberTotalColumns]; double * gubSolution = new double [numberTotalColumns]; int numberSets = gubMatrix->numberSets(); const int * id = gubMatrix->id(); int i; const float * columnLower = gubMatrix->columnLower(); const float * columnUpper = gubMatrix->columnUpper(); for (i = 0; i < numberGubColumns; i++) { if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::atUpperBound) { gubSolution[i+firstOdd] = columnUpper[i]; status[i+firstOdd] = 2; } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::atLowerBound && columnLower) { gubSolution[i+firstOdd] = columnLower[i]; status[i+firstOdd] = 1; } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::soloKey) { int iSet = gubMatrix->whichSet(i); gubSolution[i+firstOdd] = gubMatrix->keyValue(iSet); status[i+firstOdd] = 0; } else { gubSolution[i+firstOdd] = 0.0; status[i+firstOdd] = 1; } } for (i = 0; i < firstOdd; i++) { ClpSimplex::Status thisStatus = model2.getStatus(i); if (thisStatus == ClpSimplex::basic) status[i] = 0; else if (thisStatus == ClpSimplex::atLowerBound) status[i] = 1; else if (thisStatus == ClpSimplex::atUpperBound) status[i] = 2; else if (thisStatus == ClpSimplex::isFixed) status[i] = 3; else abort(); gubSolution[i] = solution[i]; } for (i = firstOdd; i < lastOdd; i++) { int iBig = id[i-firstOdd] + firstOdd; ClpSimplex::Status thisStatus = model2.getStatus(i); if (thisStatus == ClpSimplex::basic) status[iBig] = 0; else if (thisStatus == ClpSimplex::atLowerBound) status[iBig] = 1; else if (thisStatus == ClpSimplex::atUpperBound) status[iBig] = 2; else if (thisStatus == ClpSimplex::isFixed) status[iBig] = 3; else abort(); gubSolution[iBig] = solution[i]; } char * rowStatus = new char[originalNumberRows]; for (i = 0; i < numberStaticRows; i++) { ClpSimplex::Status thisStatus = model2.getRowStatus(i); if (thisStatus == ClpSimplex::basic) rowStatus[i] = 0; else if (thisStatus == ClpSimplex::atLowerBound) rowStatus[i] = 1; else if (thisStatus == ClpSimplex::atUpperBound) rowStatus[i] = 2; else if (thisStatus == ClpSimplex::isFixed) rowStatus[i] = 3; else abort(); } double objValue = 0.0; for (i = 0; i < numberTotalColumns; i++) objValue += cost[i] * gubSolution[i]; printf("objective value is %g\n", objValue); for (i = 0; i < numberSets; i++) { ClpSimplex::Status thisStatus = gubMatrix->getStatus(i); if (thisStatus == ClpSimplex::basic) rowStatus[numberStaticRows+i] = 0; else if (thisStatus == ClpSimplex::atLowerBound) rowStatus[numberStaticRows+i] = 1; else if (thisStatus == ClpSimplex::atUpperBound) rowStatus[numberStaticRows+i] = 2; else if (thisStatus == ClpSimplex::isFixed) rowStatus[numberStaticRows+i] = 3; else abort(); } // Coding below may not work if gub rows not at end FILE * fp = fopen ("xx.sol", "w"); fwrite(gubSolution, sizeof(double), numberTotalColumns, fp); fwrite(status, sizeof(char), numberTotalColumns, fp); const double * rowsol = model2.primalRowSolution(); double * rowsol2 = new double[originalNumberRows]; memset(rowsol2, 0, originalNumberRows * sizeof(double)); model.times(1.0, gubSolution, rowsol2); for (i = 0; i < numberStaticRows; i++) assert (fabs(rowsol[i] - rowsol2[i]) < 1.0e-3); for (; i < originalNumberRows; i++) assert (rowsol2[i] > lower[i-numberStaticRows] - 1.0e-3 && rowsol2[i] < upper[i-numberStaticRows] + 1.0e-3); //for (;i<originalNumberRows;i++) //printf("%d %g\n",i,rowsol2[i]); fwrite(rowsol2, sizeof(double), originalNumberRows, fp); delete [] rowsol2; fwrite(rowStatus, sizeof(char), originalNumberRows, fp); fclose(fp); delete [] status; delete [] gubSolution; // ** if going to rstart as dynamic need id_ // also copy coding in useEf.. from ClpGubMatrix (i.e. test for basis) } printf("obj offset is %g\n", model2.objectiveOffset()); printf("Primal took %g seconds\n", CoinCpuTime() - time1); } delete [] mark; delete [] gubStart; delete [] gubEnd; delete [] which; delete [] whichGub; delete [] lower; delete [] upper; 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; }
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; 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); } { // check if we need to change bounds to rows int numberColumns = model.numberColumns(); const double * columnLower = model.columnLower(); const double * columnUpper = model.columnUpper(); int iColumn; CoinBuild build; double one = 1.0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] < 1.0e20 && columnLower[iColumn] > -1.0e20) { if (fabs(columnLower[iColumn]) < fabs(columnUpper[iColumn])) { double value = columnUpper[iColumn]; model.setColumnUpper(iColumn, COIN_DBL_MAX); build.addRow(1, &iColumn, &one, -COIN_DBL_MAX, value); } else { double value = columnLower[iColumn]; model.setColumnLower(iColumn, -COIN_DBL_MAX); build.addRow(1, &iColumn, &one, value, COIN_DBL_MAX); } } } if (build.numberRows()) model.addRows(build); } int numberColumns = model.numberColumns(); const double * columnLower = model.columnLower(); const double * columnUpper = model.columnUpper(); int numberRows = model.numberRows(); double * rowLower = CoinCopyOfArray(model.rowLower(), numberRows); double * rowUpper = CoinCopyOfArray(model.rowUpper(), numberRows); const double * objective = model.objective(); CoinPackedMatrix * matrix = model.matrix(); // get transpose CoinPackedMatrix rowCopy = *matrix; int iRow, iColumn; int numberExtraRows = 0; for (iRow = 0; iRow < numberRows; iRow++) { if (rowLower[iRow] <= -1.0e20) { } else if (rowUpper[iRow] >= 1.0e20) { } else { if (rowUpper[iRow] != rowLower[iRow]) numberExtraRows++; } } const int * row = matrix->getIndices(); const int * columnLength = matrix->getVectorLengths(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const double * elementByColumn = matrix->getElements(); double objOffset = 0.0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double offset = 0.0; if (columnUpper[iColumn] >= 1.0e20) { if (columnLower[iColumn] > -1.0e20) offset = columnLower[iColumn]; } else if (columnLower[iColumn] <= -1.0e20) { offset = columnUpper[iColumn]; } else { // taken care of before abort(); } if (offset) { objOffset += offset * objective[iColumn]; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (rowLower[iRow] > -1.0e20) rowLower[iRow] -= offset * elementByColumn[j]; if (rowUpper[iRow] < 1.0e20) rowUpper[iRow] -= offset * elementByColumn[j]; } } } int * which = new int[numberRows+numberExtraRows]; rowCopy.reverseOrdering(); rowCopy.transpose(); double * fromRowsLower = new double[numberRows+numberExtraRows]; double * fromRowsUpper = new double[numberRows+numberExtraRows]; double * newObjective = new double[numberRows+numberExtraRows]; double * fromColumnsLower = new double[numberColumns]; double * fromColumnsUpper = new double[numberColumns]; for (iColumn = 0; iColumn < numberColumns; iColumn++) { // Offset is already in if (columnUpper[iColumn] >= 1.0e20) { if (columnLower[iColumn] > -1.0e20) { fromColumnsLower[iColumn] = -COIN_DBL_MAX; fromColumnsUpper[iColumn] = objective[iColumn]; } else { // free fromColumnsLower[iColumn] = objective[iColumn]; fromColumnsUpper[iColumn] = objective[iColumn]; } } else if (columnLower[iColumn] <= -1.0e20) { fromColumnsLower[iColumn] = objective[iColumn]; fromColumnsUpper[iColumn] = COIN_DBL_MAX; } else { abort(); } } int kRow = 0; for (iRow = 0; iRow < numberRows; iRow++) { if (rowLower[iRow] <= -1.0e20) { assert(rowUpper[iRow] < 1.0e20); newObjective[kRow] = -rowUpper[iRow]; fromRowsLower[kRow] = -COIN_DBL_MAX; fromRowsUpper[kRow] = 0.0; which[kRow] = iRow; kRow++; } else if (rowUpper[iRow] >= 1.0e20) { newObjective[kRow] = -rowLower[iRow]; fromRowsLower[kRow] = 0.0; fromRowsUpper[kRow] = COIN_DBL_MAX; which[kRow] = iRow; kRow++; } else { if (rowUpper[iRow] == rowLower[iRow]) { newObjective[kRow] = -rowLower[iRow]; fromRowsLower[kRow] = -COIN_DBL_MAX;; fromRowsUpper[kRow] = COIN_DBL_MAX; which[kRow] = iRow; kRow++; } else { // range newObjective[kRow] = -rowUpper[iRow]; fromRowsLower[kRow] = -COIN_DBL_MAX; fromRowsUpper[kRow] = 0.0; which[kRow] = iRow; kRow++; newObjective[kRow] = -rowLower[iRow]; fromRowsLower[kRow] = 0.0; fromRowsUpper[kRow] = COIN_DBL_MAX; which[kRow] = iRow; kRow++; } } } if (numberExtraRows) { CoinPackedMatrix newCopy; newCopy.submatrixOfWithDuplicates(rowCopy, kRow, which); rowCopy = newCopy; } ClpSimplex modelDual; modelDual.loadProblem(rowCopy, fromRowsLower, fromRowsUpper, newObjective, fromColumnsLower, fromColumnsUpper); modelDual.setObjectiveOffset(objOffset); delete [] fromRowsLower; delete [] fromRowsUpper; delete [] fromColumnsLower; delete [] fromColumnsUpper; delete [] newObjective; delete [] which; delete [] rowLower; delete [] rowUpper; modelDual.writeMps("dual.mps"); return 0; }