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; }
static int solve(EKKModel * model, int startup, int algorithm, int presolve) { // values pass or not if (startup) startup = 1; // if scaled then be careful bool scaled = ekk_scaling(model) == 1; if (scaled) ekk_scaleRim(model, 1); void * compressInfo = NULL; ClpSimplex * clp; if (!presolve || !presolveInfo) { // no presolve or osl presolve - compact columns compressInfo = ekk_compressModel(model); clp = clpmodel(model, startup);; } else { // pick up clp model clp = presolveInfo->model(); } // don't scale if alreday scaled if (scaled) clp->scaling(false); if (clp->numberRows() > 10000) clp->factorization()->maximumPivots(100 + clp->numberRows() / 100); if (algorithm > 0) clp->primal(startup); else clp->dual(); int numberIterations = clp->numberIterations(); if (presolve && presolveInfo) { // very wasteful - create a clp copy of osl model ClpSimplex * clpOriginal = clpmodel(model, 0); presolveInfo->setOriginalModel(clpOriginal); // do postsolve presolveInfo->postsolve(true); delete clp; delete presolveInfo; presolveInfo = NULL; clp = clpOriginal; if (presolve == 3 || (presolve == 2 && clp->status())) { printf("Resolving from postsolved model\n"); clp->primal(1); numberIterations += clp->numberIterations(); } } // put back solution double * rowDual = (double *) ekk_rowduals(model); int numberRows = ekk_getInumrows(model); int numberColumns = ekk_getInumcols(model); int * rowStatus = (int *) ekk_rowstat(model); double * rowSolution = (double *) ekk_rowacts(model); int i; int * columnStatus = (int *) ekk_colstat(model); double * columnSolution = (double *) ekk_colsol(model); memcpy(rowSolution, clp->primalRowSolution(), numberRows * sizeof(double)); memcpy(rowDual, clp->dualRowSolution(), numberRows * sizeof(double)); for (i = 0; i < numberRows; i++) { if (clp->getRowStatus(i) == ClpSimplex::basic) rowStatus[i] = 0x80000000; else rowStatus[i] = 0; } double * columnDual = (double *) ekk_colrcosts(model); memcpy(columnSolution, clp->primalColumnSolution(), numberColumns * sizeof(double)); memcpy(columnDual, clp->dualColumnSolution(), numberColumns * sizeof(double)); for (i = 0; i < numberColumns; i++) { if (clp->getColumnStatus(i) == ClpSimplex::basic) columnStatus[i] = 0x80000000; else columnStatus[i] = 0; } ekk_setIprobstat(model, clp->status()); ekk_setRobjvalue(model, clp->objectiveValue()); ekk_setInumpinf(model, clp->numberPrimalInfeasibilities()); ekk_setInumdinf(model, clp->numberDualInfeasibilities()); ekk_setIiternum(model, numberIterations); ekk_setRsumpinf(model, clp->sumPrimalInfeasibilities()); ekk_setRsumdinf(model, clp->sumDualInfeasibilities()); delete clp; if (compressInfo) ekk_decompressModel(model, compressInfo); if (scaled) ekk_scaleRim(model, 2); return 0; }
// To define the function sciclp as a C function and allow this function to be loaded easily in scilab extern "C" int sciclp(char * fname) { ClpSimplex * modelSimplex = NULL; ClpInterior * modelInterior = NULL; ClpModel * modelBase = NULL; ClpCholeskyBase * cholesky = NULL; DerivedHandler * printer = NULL; ClpSolve modelSolve; // YC: we can set some parameters via CbcSolve CoinPackedMatrix A_matrix, Q_matrix; #ifdef HANDLE_CTRLC MyClpEventHandler SciClpEventHandler; SciClpEventHandler.setInCbc(false); #endif int Log = 0; int ncols = 0, nrows = 0, i, j, nz = 0, writemps = 0; int count = 0, status = 0, type; char * writemps_filename = NULL; SciSparse S_A, S_Q; if (Rhs<LASTPARAM) { Scierror(999,"%s: 12 inputs required in call to %s. Bug in clp.sci ?...\n", fname, fname); return 0; } /* Get pointers to input */ int n_a, m_a, * a_addr = NULL; int n_c, m_c, * c_addr = NULL; int n_lhs, m_lhs, * lhs_addr = NULL; int n_rhs, m_rhs, * rhs_addr = NULL; int n_upper, m_upper, * upper_addr = NULL; int n_lower, m_lower, * lower_addr = NULL; int * vtype_addr = NULL; int * ctype_addr = NULL; int n_q, m_q, * q_addr = NULL; double * c = NULL, * lhs = NULL, * rhs = NULL, * lower = NULL, * upper = NULL, * a = NULL; double * q = NULL; char * ctype = NULL, * vtype = NULL; SciErr _SciErr; _SciErr = getVarAddressFromPosition(pvApiCtx, C_IN, &c_addr); SCICOINOR_ERROR; _SciErr = getMatrixOfDouble(pvApiCtx, c_addr, &n_c, &m_c, &c); SCICOINOR_ERROR; _SciErr = getVarAddressFromPosition(pvApiCtx, LHS_IN, &lhs_addr); SCICOINOR_ERROR; _SciErr = getMatrixOfDouble(pvApiCtx, lhs_addr, &n_lhs, &m_lhs, &lhs); SCICOINOR_ERROR; _SciErr = getVarAddressFromPosition(pvApiCtx, RHS_IN, &rhs_addr); SCICOINOR_ERROR; _SciErr = getMatrixOfDouble(pvApiCtx, rhs_addr, &n_rhs, &m_rhs, &rhs); SCICOINOR_ERROR; _SciErr = getVarAddressFromPosition(pvApiCtx, LOWER_IN, &lower_addr); SCICOINOR_ERROR; _SciErr = getMatrixOfDouble(pvApiCtx, lower_addr, &n_lower, &m_lower, &lower); SCICOINOR_ERROR; _SciErr = getVarAddressFromPosition(pvApiCtx, UPPER_IN, &upper_addr); SCICOINOR_ERROR; _SciErr = getMatrixOfDouble(pvApiCtx, upper_addr, &n_upper, &m_upper, &upper); SCICOINOR_ERROR; _SciErr = getVarAddressFromPosition(pvApiCtx, CTYPE_IN, &ctype_addr); SCICOINOR_ERROR; getAllocatedSingleString(pvApiCtx, ctype_addr, &ctype); _SciErr = getVarAddressFromPosition(pvApiCtx, VTYPE_IN, &vtype_addr); SCICOINOR_ERROR; getAllocatedSingleString(pvApiCtx, vtype_addr, &vtype); ncols = n_c * m_c; /* Length of c == number of columns */ nrows = n_rhs * m_rhs; /* length of b == number of rows */ if (nrows==0) nrows = n_lhs * m_lhs; #ifdef DEBUG sciprint("DEBUG: c size: m = %d n = %d\n", m_c, n_c); sciprint("DEBUG: lhs size: m = %d n = %d\n", m_lhs, n_lhs); sciprint("DEBUG: rhs size: m = %d n = %d\n", m_rhs, n_rhs); sciprint("DEBUG: lower size: m = %d n = %d\n", m_lower, n_lower); sciprint("DEBUG: upper size: m = %d n = %d\n", m_upper, n_upper); sciprint("DEBUG: ctype size: m = %d n = %d\n", m_ctype, n_ctype); sciprint("DEBUG: vtype size: m = %d n = %d\n", m_vtype, n_vtype); sciprint("DEBUG: nrows = %d\n", nrows); sciprint("DEBUG: ncols = %d\n", ncols); sciprint("c :"); for(i=0;i<ncols; i++) sciprint("%f ",*(c+i)); sciprint("\n"); sciprint("lhs :"); for(i=0;i<nrows; i++) sciprint("%f ",*(lhs+i)); sciprint("\n"); sciprint("rhs :"); for(i=0;i<nrows; i++) sciprint("%f ",*(rhs+i)); sciprint("\n"); sciprint("lb :"); for(i=0;i<ncols; i++) sciprint("%f ",*(lower+i)); sciprint("\n"); sciprint("ub :"); for(i=0;i<ncols; i++) sciprint("%f ",*(upper+i)); sciprint("\n"); sciprint("ctype = %s\n", ctype); sciprint("vtype = %s\n", vtype); #endif ////////////////// // The A matrix // ////////////////// _SciErr = getVarAddressFromPosition(pvApiCtx, A_IN, &a_addr); SCICOINOR_ERROR; _SciErr = getVarType(pvApiCtx, a_addr, &type); SCICOINOR_ERROR; if(type!=sci_sparse) { #ifdef DEBUG sciprint("DEBUG: A_IN is not sparse\n"); #endif _SciErr = getMatrixOfDouble(pvApiCtx, a_addr, &m_a, &n_a, &a); SCICOINOR_ERROR; A_matrix.setDimensions(nrows,ncols); if (a==NULL) { Scierror(999,"%s: invalid value of matrix a\n",fname); freeAllocatedSingleString(ctype); freeAllocatedSingleString(vtype); return 0; } for(i=0; i<m_a; i++) { for(j=0; j<n_a; j++) { if (*(a+i+j*m_a) != 0) A_matrix.modifyCoefficient(i,j,*(a+i+j*m_a)); #ifdef DEBUG sciprint("%f ",*(a+i+j*m_a)); #endif } #ifdef DEBUG sciprint("\n"); #endif } } else { #ifdef DEBUG sciprint("DEBUG: A_IN is sparse\n"); #endif getAllocatedSparseMatrix(pvApiCtx, a_addr, &S_A.m, &S_A.n, &S_A.nel, &S_A.mnel, &S_A.icol, &S_A.R); A_matrix.setDimensions(nrows,ncols); #ifdef DEBUG sciprint("A = [%d,%d]\n", m_a, n_a); #endif nz = S_A.nel; count = 0; for(i=0;i<S_A.m;i++) { if (S_A.mnel[i]!=0) { #ifdef DEBUG sciprint("mnel[%d] = %d - ",i, S_A.mnel[i]); #endif for(j=0;j<S_A.mnel[i];j++) { count++; A_matrix.modifyCoefficient(i,S_A.icol[count-1]-1,S_A.R[count-1]); #ifdef DEBUG sciprint("[%d] = %f ", S_A.icol[count-1]-1, S_A.R[count-1]); #endif } #ifdef DEBUG sciprint("\n"); #endif } } freeAllocatedSparseMatrix(S_A.mnel, S_A.icol, S_A.R); } ///////////////// // Get options // ///////////////// #ifdef DEBUG sciprint("DEBUG: get options\n"); #endif // Default settings int * param_in_addr = NULL; int solverchoice = 1, loglevel = 0, fact_freq = 200, perturb = 0; int presolve = 0, red_grad = 1, maximumbarrieriterations = 200; int tmp_int, tmp_res; double tmp_double; char * tmp_char; initPList(pvApiCtx, PARAM_IN, ¶m_in_addr); if (!checkPList(pvApiCtx, param_in_addr)) { Scierror(999, "%s: argument n° %d is not a plist\n", fname, PARAM_IN); return 0; } // solver option getIntInPList(pvApiCtx, param_in_addr, "solver", &tmp_int, &tmp_res, 1, Log, CHECK_NONE); if (tmp_res!=-1) solverchoice = tmp_int; // Load the matrix in the solver switch(solverchoice) { case 6: modelInterior = new ClpInterior; modelBase = (ClpModel *)modelInterior; break; default: modelSimplex = new ClpSimplex; modelBase = (ClpModel *)modelSimplex; break; } // maxnumiterations option getIntInPList(pvApiCtx, param_in_addr, "maxnumiterations", &tmp_int, &tmp_res, 1000, Log, CHECK_NONE); if (tmp_res!=-1) modelBase->setMaximumIterations(tmp_int); // maxnumseconds option getDoubleInPList(pvApiCtx, param_in_addr, "maxnumseconds", &tmp_double, &tmp_res, 3600, Log, CHECK_NONE); if (tmp_res!=-1) modelBase->setMaximumSeconds(tmp_double); // primaltolerance option getDoubleInPList(pvApiCtx, param_in_addr, "primaltolerance", &tmp_double, &tmp_res, 1e-7, Log, CHECK_NONE); if (tmp_res!=-1) modelBase->setPrimalTolerance(tmp_double); // dualtolerance option getDoubleInPList(pvApiCtx, param_in_addr, "dualtolerance", &tmp_double, &tmp_res, 1e-7, Log, CHECK_NONE); if (tmp_res!=-1) modelBase->setDualTolerance(tmp_double); // verbose option getIntInPList(pvApiCtx, param_in_addr, "verbose", &tmp_int, &tmp_res, 0, Log, CHECK_NONE); if (tmp_res!=-1) { /////////////////////////////// // Enable printing in Scilab // // and set parameters of clp // /////////////////////////////// loglevel = tmp_int; printer = new DerivedHandler(); // assumed open printer->setLogLevel(loglevel); } // optim_dir option getIntInPList(pvApiCtx, param_in_addr, "optim_dir", &tmp_int, &tmp_res, 1, Log, CHECK_NONE); if (tmp_res!=-1) modelBase->setOptimizationDirection(tmp_int); // writemps option getStringInPList(pvApiCtx, param_in_addr, "writemps", &tmp_char, &tmp_res, "test.mps", Log, CHECK_NONE); if (tmp_res!=-1) { writemps_filename = tmp_char; writemps = 1; #ifdef DEBUG sciprint("DEBUG: writemps_filename = %s\n", writemps_filename); #endif } // perturb option getIntInPList(pvApiCtx, param_in_addr, "perturb", &tmp_int, &tmp_res, 0, Log, CHECK_NONE); if (tmp_res!=-1) perturb = tmp_int; // scaling option // Sets or unsets scaling: // - 0 -off // - 1 equilibrium (default) // - 2 geometric // - 3 auto // - 4 auto-but-as-initialSolve-in-bab. getIntInPList(pvApiCtx, param_in_addr, "scaling", &tmp_int, &tmp_res, 1, Log, CHECK_NONE); if (tmp_res!=-1) modelBase->scaling(tmp_int); // factorization frequency option getIntInPList(pvApiCtx, param_in_addr, "fact_freq", &tmp_int, &tmp_res, 200, Log, CHECK_NONE); if (tmp_res!=-1) fact_freq = tmp_int; // presolve option getIntInPList(pvApiCtx, param_in_addr, "presolve", &tmp_int, &tmp_res, 0, Log, CHECK_NONE); if (tmp_res!=-1) presolve = tmp_int; // reduced gradient phase option getIntInPList(pvApiCtx, param_in_addr, "red_grad", &tmp_int, &tmp_res, 1, Log, CHECK_NONE); if (tmp_res!=-1) red_grad = tmp_int; // maxnumiterationshotstart getIntInPList(pvApiCtx, param_in_addr, "maxnumiterationshotstart", &tmp_int, &tmp_res, 1000, Log, CHECK_NONE); if (tmp_res!=-1) modelBase->setIntParam(ClpMaxNumIterationHotStart, tmp_int); // dualobjectivelimit getDoubleInPList(pvApiCtx, param_in_addr, "dualobjectivelimit", &tmp_double, &tmp_res, 1e-7, Log, CHECK_NONE); if (tmp_res!=-1) modelBase->setDblParam(ClpDualObjectiveLimit, tmp_double); // primalobjectivelimit getDoubleInPList(pvApiCtx, param_in_addr, "primalobjectivelimit", &tmp_double, &tmp_res, 1e-7, Log, CHECK_NONE); if (tmp_res!=-1) modelBase->setDblParam(ClpPrimalObjectiveLimit, tmp_double); // obj offset getDoubleInPList(pvApiCtx, param_in_addr, "objoffset", &tmp_double, &tmp_res, 0.0, Log, CHECK_NONE); if (tmp_res!=-1) modelBase->setDblParam(ClpObjOffset, tmp_double); // presolvetolerance getDoubleInPList(pvApiCtx, param_in_addr, "presolvetolerance", &tmp_double, &tmp_res, 1e-7, Log, CHECK_NONE); if (tmp_res!=-1) modelBase->setDblParam(ClpPresolveTolerance, tmp_double); // maximumBarrierIterations getIntInPList(pvApiCtx, param_in_addr, "maxnumbarrieriterations", &tmp_int, &tmp_res, 200, Log, CHECK_NONE); if (tmp_res!=-1) maximumbarrieriterations = tmp_int; ///////////////////////////////////// // Set the bounds on the variables // ///////////////////////////////////// modelBase->loadProblem(A_matrix,lhs,rhs,c,lower,upper); for(i=0;i<ncols; i++) { modelBase->setColUpper(i, *(upper+i)); modelBase->setColLower(i, *(lower+i)); modelBase->setObjectiveCoefficient(i,*(c+i)); if ((*(vtype+i)=='I')||(*(vtype+i)=='i')) { modelBase->setInteger(i); } else { modelBase->setContinuous(i); } } ///////////////////////////////////////// // Set the boundary of the constraints // ///////////////////////////////////////// // 'L' - smaller than - <= // 'E' - equality - = // 'G' - greater than - >= // 'R' - Range - <= + >= // 'N' - Free - no constraints #ifdef DEBUG sciprint("DEBUG: dealing with btype\n"); #endif for(i=0;i<nrows; i++) { switch(*(ctype+i)) { case 'l': case 'L': modelBase->setRowUpper(i, *(rhs+i)); modelBase->setRowLower(i, -COIN_DBL_MAX); break; case 'e': case 'E': modelBase->setRowUpper(i, *(rhs+i)); modelBase->setRowLower(i, *(rhs+i)); break; case 'n': case 'N': modelBase->setRowUpper(i, COIN_DBL_MAX); modelBase->setRowLower(i, -COIN_DBL_MAX); break; case 'r': case 'R': modelBase->setRowUpper(i, *(rhs+i)); modelBase->setRowLower(i, *(lhs+i)); break; case 'g': case 'G': default: modelBase->setRowUpper(i, COIN_DBL_MAX); modelBase->setRowLower(i, *(lhs+i)); break; } #ifdef DEBUG sciprint("row lower[%d] = %f row upper[%d] = %f\n", i, modelBase->getRowLower()[i], i, modelBase->getRowUpper()[i]); #endif } /////////////////////////////////// // Affect names to rows and cols // /////////////////////////////////// modelBase->setIntParam(ClpNameDiscipline,0); //////////////////////// // Any quadratic part // //////////////////////// #ifdef DEBUG sciprint("DEBUG: dealing with Q\n"); #endif _SciErr = getVarAddressFromPosition(pvApiCtx, Q_IN, &q_addr); SCICOINOR_ERROR; _SciErr = getVarType(pvApiCtx, q_addr, &type); SCICOINOR_ERROR; if(type!=sci_sparse) { _SciErr = getMatrixOfDouble(pvApiCtx, q_addr, &m_q, &n_q, &q); SCICOINOR_ERROR; if (n_q * m_q !=0) { #ifdef DEBUG sciprint("DEBUG: Q_IN is not sparse\n"); sciprint("DEBUG: Q size: n = %d m= %d\n", n_q, m_q); #endif Q_matrix.setDimensions(nrows,ncols); nz = n_q * m_q; if (q==NULL) { Scierror(999,"%s: invalid value of matrix q\n",fname); freeAllocatedSingleString(ctype); freeAllocatedSingleString(vtype); if (writemps_filename) FREE(writemps_filename); return 0; } for(i=0; i<m_q; i++) { for(j=0; j<n_q; j++) { if (*(q+i+j*m_q)!=0) Q_matrix.modifyCoefficient(i,j,*(q+i+j*m_q)); } } modelBase->loadQuadraticObjective(Q_matrix); } } else { getAllocatedSparseMatrix(pvApiCtx, q_addr, &S_Q.m, &S_Q.n, &S_Q.nel, &S_Q.mnel, &S_Q.icol, &S_Q.R); if (S_Q.n * S_Q.m!=0) { #ifdef DEBUG sciprint("DEBUG: Q_IN is sparse\n"); sciprint("DEBUG: Q size: n = %d m= %d\n", S_Q.n, S_Q.m); #endif Q_matrix.setDimensions(nrows,ncols); nz = S_Q.nel; count = 0; for(i=0;i<S_Q.m;i++) { if (S_Q.mnel[i]!=0) { for(j=0;j<S_Q.mnel[i];j++) { count++; Q_matrix.modifyCoefficient(i,S_Q.icol[count-1]-1,S_Q.R[count-1]); } } } modelBase->loadQuadraticObjective(Q_matrix); } freeAllocatedSparseMatrix(S_Q.mnel, S_Q.icol, S_Q.R); } // Solver specific part switch(solverchoice) { case 6: modelInterior->setMaximumBarrierIterations(maximumbarrieriterations); break; default: modelSimplex->setFactorizationFrequency(fact_freq); modelSimplex->setPerturbation(perturb); break; } /////////////////////////// // Pre / Post resolution // /////////////////////////// #ifdef HANDLE_CTRLC /////////////////////////////////////////////////////////// // Pass in the event handler, to handle ctrl+c in scilab // /////////////////////////////////////////////////////////// if (modelSimplex) { modelSimplex->passInEventHandler(&SciClpEventHandler); modelSimplex->passInMessageHandler(printer); } #endif #ifdef DEBUG sciprint("DEBUG: presolve\n"); #endif // If the solver is not ClpInterior we can set the presolve option if (presolve && solverchoice!=6) { TRYCATCH(modelSimplex->initialSolve(modelSolve)); switch(presolve) { case 2: TRYCATCH(modelSimplex->initialDualSolve()); break; case 3: TRYCATCH(modelSimplex->initialPrimalSolve()); break; case 4: TRYCATCH(modelSimplex->initialBarrierSolve()); break; case 5: TRYCATCH(modelSimplex->initialBarrierNoCrossSolve()); break; default: TRYCATCH(modelSimplex->initialSolve()); break; } } //////////////////////////////////////////// // If needed, write the problem in a file // //////////////////////////////////////////// #ifdef DEBUG sciprint("DEBUG: dealing with writemps\n"); #endif if (writemps) { modelBase->writeMps(writemps_filename); if (loglevel) sciprint("sciclp: writing %s mps file\n",writemps_filename); } //////////////// // Resolution // //////////////// #ifdef DEBUG sciprint("DEBUG: resolution\n"); sciprint("model number columns = %d\n", modelBase->numberColumns()); sciprint("model number rows = %d\n", modelBase->numberRows()); #endif if ((solverchoice>=1)&&(solverchoice<=5)) { TRYCATCH(modelSimplex->initialSolve()) } #ifdef HANDLE_CTRLC /////////////////////////////////////////////////////////// // Pass in the event handler, to handle ctrl+c in scilab // /////////////////////////////////////////////////////////// if (modelSimplex) { modelSimplex->passInEventHandler(&SciClpEventHandler); modelSimplex->passInMessageHandler(printer); } if (modelInterior) { modelInterior->passInEventHandler(&SciClpEventHandler); modelInterior->passInMessageHandler(printer); } #endif switch (solverchoice) { case 2: TRYCATCH(status = modelSimplex->dual()); break; case 3: TRYCATCH(status = modelSimplex->barrier(false)); break; case 4: TRYCATCH(status = modelSimplex->barrier(true)); break; case 5: TRYCATCH(status = modelSimplex->reducedGradient(red_grad)); break; case 6: cholesky = new ClpCholeskyBase(); cholesky->setKKT(true); modelInterior->setCholesky(cholesky); TRYCATCH(status = modelInterior->primalDual()); break; case 7: TRYCATCH(status = modelInterior->pdco()); break; default: TRYCATCH(status = modelSimplex->primal()); break; } #ifdef DEBUG if (status && loglevel) sciprint("Optimization failed\n"); #endif int clp_status = 0; clp_status = (int)(pow(2.0,0.0)*modelBase->isAbandoned()); clp_status += (int)(pow(2.0,1.0)*modelBase->isProvenOptimal()); clp_status += (int)(pow(2.0,2.0)*modelBase->isProvenPrimalInfeasible()); clp_status += (int)(pow(2.0,3.0)*modelBase->isProvenDualInfeasible()); clp_status += (int)(pow(2.0,4.0)*modelBase->isPrimalObjectiveLimitReached()); clp_status += (int)(pow(2.0,5.0)*modelBase->isDualObjectiveLimitReached()); clp_status += (int)(pow(2.0,6.0)*modelBase->isIterationLimitReached()); ////////////////////////////// // Allocate for return data // ////////////////////////////// #ifdef DEBUG sciprint("DEBUG: allocating data\n"); #endif int m_xmin = ncols, n_xmin = 1; int m_lambda = 1, n_lambda = nrows; int * extra_addr = NULL; char * ListLabels [] = {"lambda","secondary_status","clp_status"}; _SciErr = createMatrixOfDouble(pvApiCtx, XMIN_OUT, m_xmin, n_xmin, (double *)modelBase->primalColumnSolution()); SCICOINOR_ERROR; createScalarDouble(pvApiCtx, FMIN_OUT, modelBase->getObjValue()); createScalarDouble(pvApiCtx, STATUS_OUT, (double)modelBase->status()); _SciErr = createPList(pvApiCtx, EXTRA_OUT, &extra_addr, (char **)ListLabels, 3); SCICOINOR_ERROR; _SciErr = createColVectorOfDoubleInPList(pvApiCtx, EXTRA_OUT, extra_addr, "lambda", m_lambda*n_lambda, (double *)modelBase->dualRowSolution()); SCICOINOR_ERROR; _SciErr = createIntInPList(pvApiCtx, EXTRA_OUT, extra_addr, "secondary_status", modelBase->secondaryStatus()); SCICOINOR_ERROR; _SciErr = createIntInPList(pvApiCtx, EXTRA_OUT, extra_addr, "clp_status", clp_status); SCICOINOR_ERROR; #ifdef DEBUG sciprint("DEBUG: getting solution\n"); #endif // // status of problem: // -1 - unknown e.g. before solve or if postSolve says not optimal // 0 - optimal // 1 - primal infeasible // 2 - dual infeasible // 3 - stopped on iterations or time // 4 - stopped due to errors // 5 - stopped by event handler (virtual int ClpEventHandler::event()) // // Secondary status of problem - may get extended // - 0 - none // - 1 - primal infeasible because dual limit reached OR probably primal infeasible but can't prove it (main status 4) // - 2 - scaled problem optimal - unscaled problem has primal infeasibilities // - 3 - scaled problem optimal - unscaled problem has dual infeasibilities // - 4 - scaled problem optimal - unscaled problem has primal and dual infeasibilities // - 5 - giving up in primal with flagged variables // - 6 - failed due to empty problem check // - 7 - postSolve says not optimal // - 8 - failed due to bad element check // - 9 - status was 3 and stopped on time // - 100 up - translation of enum from ClpEventHandler. ///////////////////////////////// // Copy solutions if available // ///////////////////////////////// #ifdef DEBUG sciprint("DEBUG: returning data\n"); #endif LhsVar(1) = XMIN_OUT; LhsVar(2) = FMIN_OUT; LhsVar(3) = STATUS_OUT; LhsVar(4) = EXTRA_OUT; ////////////////////////////// // Delete allocated objects // ////////////////////////////// if (modelSimplex) delete modelSimplex; if (modelInterior) delete modelInterior; if (printer) delete printer; freeAllocatedSingleString(ctype); freeAllocatedSingleString(vtype); if (writemps_filename) FREE(writemps_filename); return 0; }
int main(int argc, const char *argv[]) { int numberColumns; int numberRows; FILE * fp; if (argc > 1) { fp = fopen(argv[1], "r"); if (!fp) { fprintf(stderr, "Unable to open file %s\n", argv[1]); exit(1); } } else { fp = fopen("input.130", "r"); if (!fp) { fprintf(stderr, "Unable to open file input.l30 in Samples directory\n"); exit(1); } } int problem; char temp[100]; // read and skip fscanf(fp, "%s", temp); assert(!strcmp(temp, "BEGIN")); fscanf(fp, "%*s %*s %d %d %*s %*s %d %*s", &problem, &numberRows, &numberColumns); // scan down to SUPPLY while (fgets(temp, 100, fp)) { if (!strncmp(temp, "SUPPLY", 6)) break; } if (strncmp(temp, "SUPPLY", 6)) { fprintf(stderr, "Unable to find SUPPLY\n"); exit(2); } // get space for rhs double * lower = new double[numberRows]; double * upper = new double[numberRows]; int i; for (i = 0; i < numberRows; i++) { lower[i] = 0.0; upper[i] = 0.0; } // ***** Remember to convert to C notation while (fgets(temp, 100, fp)) { int row; int value; if (!strncmp(temp, "ARCS", 4)) break; sscanf(temp, "%d %d", &row, &value); upper[row-1] = -value; lower[row-1] = -value; } if (strncmp(temp, "ARCS", 4)) { fprintf(stderr, "Unable to find ARCS\n"); exit(2); } // number of columns may be underestimate int * head = new int[2*numberColumns]; int * tail = new int[2*numberColumns]; int * ub = new int[2*numberColumns]; int * cost = new int[2*numberColumns]; // ***** Remember to convert to C notation numberColumns = 0; while (fgets(temp, 100, fp)) { int iHead; int iTail; int iUb; int iCost; if (!strncmp(temp, "DEMAND", 6)) break; sscanf(temp, "%d %d %d %d", &iHead, &iTail, &iCost, &iUb); iHead--; iTail--; head[numberColumns] = iHead; tail[numberColumns] = iTail; ub[numberColumns] = iUb; cost[numberColumns] = iCost; numberColumns++; } if (strncmp(temp, "DEMAND", 6)) { fprintf(stderr, "Unable to find DEMAND\n"); exit(2); } // ***** Remember to convert to C notation while (fgets(temp, 100, fp)) { int row; int value; if (!strncmp(temp, "END", 3)) break; sscanf(temp, "%d %d", &row, &value); upper[row-1] = value; lower[row-1] = value; } if (strncmp(temp, "END", 3)) { fprintf(stderr, "Unable to find END\n"); exit(2); } printf("Problem %d has %d rows and %d columns\n", problem, numberRows, numberColumns); fclose(fp); ClpSimplex model; // now build model - we have rhs so build columns - two elements // per column double * objective = new double[numberColumns]; double * lowerColumn = new double[numberColumns]; double * upperColumn = new double[numberColumns]; double * element = new double [2*numberColumns]; int * start = new int[numberColumns+1]; int * row = new int[2*numberColumns]; start[numberColumns] = 2 * numberColumns; for (i = 0; i < numberColumns; i++) { start[i] = 2 * i; element[2*i] = -1.0; element[2*i+1] = 1.0; row[2*i] = head[i]; row[2*i+1] = tail[i]; lowerColumn[i] = 0.0; upperColumn[i] = ub[i]; objective[i] = cost[i]; } // Create Packed Matrix CoinPackedMatrix matrix; int * lengths = NULL; matrix.assignMatrix(true, numberRows, numberColumns, 2 * numberColumns, element, row, start, lengths); ClpNetworkMatrix network(matrix); // load model model.loadProblem(network, lowerColumn, upperColumn, objective, lower, upper); delete [] lower; delete [] upper; delete [] head; delete [] tail; delete [] ub; delete [] cost; delete [] objective; delete [] lowerColumn; delete [] upperColumn; delete [] element; delete [] start; delete [] row; /* The confusing flow below is in to exercise both dual and primal when ClpNetworkMatrix storage used. For practical use just one call e.g. model.dual(); would be used. If network then factorization scheme is changed to be much faster. Still not as fast as a real network code, but more flexible */ model.factorization()->maximumPivots(200 + model.numberRows() / 100); model.factorization()->maximumPivots(1000); //model.factorization()->maximumPivots(1); if (model.numberRows() < 50) model.messageHandler()->setLogLevel(63); model.dual(); model.setOptimizationDirection(-1); //model.messageHandler()->setLogLevel(63); model.primal(); model.setOptimizationDirection(1); model.primal(); 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 if (argc < 2) { #if defined(SAMPLEDIR) status = model.readMps(SAMPLEDIR "/p0033.mps", true); #else fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); #endif } else status = model.readMps(argv[1], true); /* This driver is similar to minimum.cpp, but it sets all parameter values to their defaults. The purpose of this is to give a list of most of the methods that the end user will need. There are also some more methods as for OsiSolverInterface e.g. some loadProblem methods and deleteRows and deleteColumns. Often two methods do the same thing, one having a name I like while the other adheres to OsiSolverInterface standards */ // Use exact devex ( a variant of steepest edge) ClpPrimalColumnSteepest primalSteepest; model.setPrimalColumnPivotAlgorithm(primalSteepest); int integerValue; double value; // Infeasibility cost value = model.infeasibilityCost(); std::cout << "Default value of infeasibility cost is " << value << std::endl; model.setInfeasibilityCost(value); if (!status) { model.primal(); } // Number of rows and columns - also getNumRows, getNumCols std::string modelName; model.getStrParam(ClpProbName, modelName); std::cout << "Model " << modelName << " has " << model.numberRows() << " rows and " << model.numberColumns() << " columns" << std::endl; /* Some parameters as in OsiSolverParameters. ObjectiveLimits are not active yet. dualTolerance, setDualTolerance, primalTolerance and setPrimalTolerance may be used as well */ model.getDblParam(ClpDualObjectiveLimit, value); std::cout << "Value of ClpDualObjectiveLimit is " << value << std::endl; model.getDblParam(ClpPrimalObjectiveLimit, value); std::cout << "Value of ClpPrimalObjectiveLimit is " << value << std::endl; model.getDblParam(ClpDualTolerance, value); std::cout << "Value of ClpDualTolerance is " << value << std::endl; model.getDblParam(ClpPrimalTolerance, value); std::cout << "Value of ClpPrimalTolerance is " << value << std::endl; model.getDblParam(ClpObjOffset, value); std::cout << "Value of ClpObjOffset is " << value << std::endl; // setDblParam(ClpPrimalTolerance) is same as this model.getDblParam(ClpPrimalTolerance, value); model.setPrimalTolerance(value); model.setDualTolerance(model.dualTolerance()) ; // Other Param stuff // Can also use maximumIterations model.getIntParam(ClpMaxNumIteration, integerValue); std::cout << "Value of ClpMaxNumIteration is " << integerValue << std::endl; model.setMaximumIterations(integerValue); // Not sure this works yet model.getIntParam(ClpMaxNumIterationHotStart, integerValue); std::cout << "Value of ClpMaxNumIterationHotStart is " << integerValue << std::endl; // Can also use getIterationCount and getObjValue /* Status of problem: 0 - optimal 1 - primal infeasible 2 - dual infeasible 3 - stopped on iterations etc 4 - stopped due to errors */ std::cout << "Model status is " << model.status() << " after " << model.numberIterations() << " iterations - objective is " << model.objectiveValue() << std::endl; assert(!model.isAbandoned()); assert(model.isProvenOptimal()); assert(!model.isProvenPrimalInfeasible()); assert(!model.isProvenDualInfeasible()); assert(!model.isPrimalObjectiveLimitReached()); assert(!model.isDualObjectiveLimitReached()); assert(!model.isIterationLimitReached()); // Things to help you determine if optimal assert(model.primalFeasible()); assert(!model.numberPrimalInfeasibilities()); assert(model.sumPrimalInfeasibilities() < 1.0e-7); assert(model.dualFeasible()); assert(!model.numberDualInfeasibilities()); assert(model.sumDualInfeasibilities() < 1.0e-7); // Save warm start and set to all slack unsigned char * basis1 = model.statusCopy(); model.createStatus(); // Now create another model and do hot start ClpSimplex model2 = model; model2.copyinStatus(basis1); delete [] basis1; // Check model has not got basis (should iterate) model.dual(); // Can use getObjSense model2.setOptimizationDirection(model.optimizationDirection()); // Can use scalingFlag() to check if scaling on // But set up scaling model2.scaling(); // Could play with sparse factorization on/off model2.setSparseFactorization(model.sparseFactorization()); // Sets row pivot choice algorithm in dual ClpDualRowSteepest dualSteepest; model2.setDualRowPivotAlgorithm(dualSteepest); // Dual bound (i.e. dual infeasibility cost) value = model.dualBound(); std::cout << "Default value of dual bound is " << value << std::endl; model.setDualBound(value); // Do some deafult message handling // To see real use - see OsiOslSolverInterfaceTest.cpp CoinMessageHandler handler; model2.passInMessageHandler(& handler); model2.newLanguage(CoinMessages::us_en); //Increase level of detail model2.setLogLevel(4); // solve model2.dual(); // flip direction twice and solve model2.setOptimizationDirection(-1); model2.dual(); model2.setOptimizationDirection(1); //Decrease level of detail model2.setLogLevel(1); model2.dual(); /* Now for getting at information. This will not deal with: ClpMatrixBase * rowCopy() and ClpMatrixbase * clpMatrix() nor with double * infeasibilityRay() and double * unboundedRay() (NULL returned if none/wrong) Up to user to use delete [] on these arrays. */ /* Now to print out solution. The methods used return modifiable arrays while the alternative names return const pointers - which is of course much more virtuous */ int numberRows = model2.numberRows(); // Alternatively getRowActivity() double * rowPrimal = model2.primalRowSolution(); // Alternatively getRowPrice() double * rowDual = model2.dualRowSolution(); // Alternatively getRowLower() double * rowLower = model2.rowLower(); // Alternatively getRowUpper() double * rowUpper = model2.rowUpper(); // Alternatively getRowObjCoefficients() double * rowObjective = model2.rowObjective(); // If we have not kept names (parameter to readMps) this will be 0 assert(model2.lengthNames()); // Row names const std::vector<std::string> * rowNames = model2.rowNames(); int iRow; std::cout << " Primal Dual Lower Upper (Cost)" << std::endl; for (iRow = 0; iRow < numberRows; iRow++) { double value; std::cout << std::setw(6) << iRow << " " << std::setw(8) << (*rowNames)[iRow]; value = rowPrimal[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = rowDual[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = rowLower[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = rowUpper[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; if (rowObjective) { value = rowObjective[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; } std::cout << std::endl; } std::cout << "--------------------------------------" << std::endl; // Columns int numberColumns = model2.numberColumns(); // Alternatively getColSolution() double * columnPrimal = model2.primalColumnSolution(); // Alternatively getReducedCost() double * columnDual = model2.dualColumnSolution(); // Alternatively getColLower() double * columnLower = model2.columnLower(); // Alternatively getColUpper() double * columnUpper = model2.columnUpper(); // Alternatively getObjCoefficients() double * columnObjective = model2.objective(); // If we have not kept names (parameter to readMps) this will be 0 assert(model2.lengthNames()); // Column names const std::vector<std::string> * columnNames = model2.columnNames(); int iColumn; std::cout << " Primal Dual Lower Upper Cost" << std::endl; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value; std::cout << std::setw(6) << iColumn << " " << std::setw(8) << (*columnNames)[iColumn]; value = columnPrimal[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnDual[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnLower[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnUpper[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnObjective[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; std::cout << std::endl; } std::cout << "--------------------------------------" << std::endl; std::cout << std::resetiosflags(std::ios::fixed | std::ios::showpoint | std::ios::scientific); // Now matrix CoinPackedMatrix * matrix = model2.matrix(); const double * element = matrix->getElements(); const int * row = matrix->getIndices(); const int * start = matrix->getVectorStarts(); const int * length = matrix->getVectorLengths(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { std::cout << "Column " << iColumn; int j; for (j = start[iColumn]; j < start[iColumn] + length[iColumn]; j++) std::cout << " ( " << row[j] << ", " << element[j] << ")"; std::cout << std::endl; } return 0; }
//----------------------------------------------------------------------------- void CbcSolverLongThin::resolve() { int * whichRow = NULL; int * whichColumn = NULL; // problem may be small enough to do nested search const double * colLower = modelPtr_->columnLower(); const double * colUpper = modelPtr_->columnUpper(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int numberRows=modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); int i; int nFix=0; int nNewRow=0; int nNewCol=0; int sizeDynamic = COIN_INT_MAX; int smallOriginalNumberRows=0; if (algorithm_==0) { for (i=0;i<numberIntegers;i++) { int iColumn=integerVariable[i]; if (colLower[iColumn]==colUpper[iColumn]) nFix++; } } else { whichRow = new int[numberRows]; whichColumn = new int [numberColumns]; // more sophisticated OsiCuts cs; tryCut->generateCuts(*this,cs); int numberCuts = cs.sizeColCuts(); if (numberCuts) { for ( i = 0 ; i < numberCuts ; i++) { const OsiColCut *thisCut = cs.colCutPtr(i) ; const CoinPackedVector & ubs = thisCut->ubs() ; int n = ubs.getNumElements() ; const int * which = ubs.getIndices() ; const double * values = ubs.getElements() ; for (int j = 0;j<n;j++) { int iColumn = which[j] ; this->setColUpper(iColumn,values[j]) ; } } } #if 1 const int * duplicate = tryCut->duplicate(); sizeDynamic = tryCut->sizeDynamic(); int nOrig = tryCut->numberOriginalRows(); for (i=0;i<nOrig;i++) { if (duplicate[i]==-1) whichRow[nNewRow++]=i; else modelPtr_->setRowStatus(i,ClpSimplex::basic); } smallOriginalNumberRows=nNewRow; for (;i<numberRows;i++) { whichRow[nNewRow++]=i; } #else for (i=0;i<numberRows;i++) whichRow[i]=i; nNewRow=numberRows; #endif for (i=0;i<numberIntegers;i++) { int iColumn=integerVariable[i]; if (colLower[iColumn]==colUpper[iColumn]) nFix++; bool choose; if (algorithm_==1) choose = true; else choose = (node_[i]>count_-memory_&&node_[i]>0); if ((choose&&colUpper[i]) ||(modelPtr_->getStatus(i)!=ClpSimplex::atLowerBound&& modelPtr_->getStatus(i)!=ClpSimplex::isFixed) ||colLower[i]>0.0) whichColumn[nNewCol++]=i; } } if (nestedSearch_<1.0&&model_&&model_->phase()==2) { if (((double) sizeDynamic)*((double) nNewCol)<1000000000&&sizeDynamic<10000000) { // could do Dynamic Programming // back to original number of rows nNewRow = smallOriginalNumberRows; // and get rid of any basics int nNewCol=0; for (i=0;i<numberColumns;i++) { if (colUpper[i]||colLower[i]>0.0) whichColumn[nNewCol++]=i; } ClpSimplex temp(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); int returnCode; double * rowLower2 = temp.rowLower(); double * rowUpper2 = temp.rowUpper(); int numberColumns2 = temp.numberColumns(); double * colLower2 = temp.columnLower(); double * colUpper2 = temp.columnUpper(); const CoinPackedMatrix * matrix = temp.matrix(); const double * element = matrix->getElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); double offset=0.0; const double * objective = temp.objective(); bool feasible=true; for (i=0;i<numberColumns2;i++) { double value = colLower2[i]; if (value) { offset += value*objective[i]; colLower2[i]=0.0; colUpper2[i] -= value; for (int j=columnStart[i]; j<columnStart[i]+columnLength[i];j++) { int iRow=row[j]; rowLower2[iRow] -= value*element[j]; rowUpper2[iRow] -= value*element[j]; if (rowUpper2[iRow]<-1.0e-8) { feasible=false; printf("odd - problem is infeasible\n"); } } } } temp.setObjectiveOffset(-offset); OsiClpSolverInterface temp2(&temp); double * solutionDP = NULL; if (feasible) { for (i=0;i<numberColumns2;i++) temp2.setInteger(i); CbcModel modelSmall(temp2); modelSmall.messageHandler()->setLogLevel(0); CbcFathomDynamicProgramming fathom1(modelSmall); // Set maximum space allowed fathom1.setMaximumSize(100000000); temp2.writeMps("small"); returnCode=fathom1.fathom(solutionDP); if (returnCode!=1) { printf("probably not enough memory\n"); abort(); } } if (solutionDP) { double objValue = 0.0; double * solution = modelPtr_->primalColumnSolution(); const double * objective = modelPtr_->objective(); for (i=0;i<numberColumns;i++) solution[i]=colLower[i]; for (i=0;i<nNewCol;i++) { int iColumn = whichColumn[i]; solution[iColumn]+=solutionDP[i]; } for (i=0;i<numberColumns;i++) objValue += solution[i]*objective[i]; if (objValue<model_->getCutoff()) { printf("good solution %g by dynamic programming\n",objValue); returnCode = 0; // paranoid check double * rowLower = modelPtr_->rowLower(); double * rowUpper = modelPtr_->rowUpper(); // Column copy const CoinPackedMatrix * matrix2 = modelPtr_->matrix(); element = matrix2->getElements(); row = matrix2->getIndices(); columnStart = matrix2->getVectorStarts(); columnLength = matrix2->getVectorLengths(); double * rowActivity = new double [numberRows]; memset(rowActivity,0,numberRows*sizeof(double)); for (i=0;i<numberColumns;i++) { int j; double value = solution[i]; assert (value>=colLower[i]&&value<=colUpper[i]); if (value) { printf("%d has value %g\n",i,value); for (j=columnStart[i]; j<columnStart[i]+columnLength[i];j++) { int iRow=row[j]; rowActivity[iRow] += value*element[j]; } } } // check was feasible bool feasible=true; for (i=0;i<numberRows;i++) { if(rowActivity[i]<rowLower[i]) { if (rowActivity[i]<rowLower[i]-1.0e-8) feasible = false; } else if(rowActivity[i]>rowUpper[i]) { if (rowActivity[i]>rowUpper[i]+1.0e-8) feasible = false; } } if (!feasible) { printf("** Bad solution by dynamic programming\n"); abort(); } delete [] rowActivity; model_->setBestSolution(CBC_TREE_SOL,objValue,solution); } else { returnCode=2; } } else { returnCode=2; } temp2.releaseClp(); modelPtr_->setProblemStatus(1); delete [] whichRow; delete [] whichColumn; return; } if (nFix>nestedSearch_*numberIntegers) { // Do nested search // back to original number of rows nNewRow = smallOriginalNumberRows; // and get rid of any basics int nNewCol=0; for (i=0;i<numberColumns;i++) { if (colUpper[i]||colLower[i]>0.0) whichColumn[nNewCol++]=i; } #if 0 // We clone from continuous solver so set some stuff OsiSolverInterface * solver = model_->continuousSolver(); CbcSolverLongThin * osiclp = dynamic_cast< CbcSolverLongThin*> (solver); assert (osiclp); // up special options if (osiclp->specialOptions()==3) osiclp->setSpecialOptions(7); double saveNested = osiclp->getNested(); int saveAlgorithm = osiclp->getAlgorithm(); osiclp->setNested(1.0); osiclp->setAlgorithm(0); int numberObjects = model_->numberObjects(); if (numberObjects>model_->numberIntegers()) { // for now only integers //assert (numberObjects == model_->numberIntegers()+1); model_->setNumberObjects(model_->numberIntegers()); // try follow on //model_->setNumberObjects(model_->numberIntegers()+1); } double saveMaxTime = model_->getDblParam(CbcModel::CbcMaximumSeconds); model_->setDblParam(CbcModel::CbcMaximumSeconds,1.0e5); // up special options #if 1 int returnCode= model_->subBranchAndBound(colLower,colUpper,2000); #else CbcModel * model3 = model_->cleanModel(colLower,colUpper); // integer presolve int returnCode=0; CbcModel * model2 = model3->integerPresolve(false); if (!model2||!model2->getNumRows()) { delete model2; delete model3; returnCode= 2; } else { if (handler_->logLevel()>1) printf("Reduced model has %d rows and %d columns\n", model2->getNumRows(),model2->getNumCols()); if (true) { OsiSolverInterface * solver = model2->solver(); OsiSolverInterface * osiclp = dynamic_cast< OsiSolverInterface*> (solver); assert (osiclp); int * priority = new int [numberColumns+1]; int n=0; int iColumn; for ( iColumn=0;iColumn<numberColumns;iColumn++) { if (solver->isInteger(iColumn)) { priority[n++]=10000; } } priority[n]=1; CbcObject * newObject =new CbcFollowOn2(model2); model2->addObjects(1,&newObject); delete newObject; model2->passInPriorities(priority,false); delete [] priority; } returnCode= model_->subBranchAndBound(model3,model2,4000); } #endif model_->setDblParam(CbcModel::CbcMaximumSeconds,saveMaxTime); model_->setNumberObjects(numberObjects); osiclp->setNested(saveNested); osiclp->setAlgorithm(saveAlgorithm); #else // start again very simply ClpSimplex temp(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); int returnCode; OsiClpSolverInterface temp2(&temp); temp2.setupForRepeatedUse(2); int numberColumns2 = temp.numberColumns(); const double * colUpper2 = temp2.getColUpper(); const double * colLower2 = temp2.getColLower(); const double * solution2 = temp.getColSolution(); double * cleanSolution2 = new double [numberColumns2]; for (i=0;i<numberColumns2;i++) { temp2.setInteger(i); double value = solution2[i]; value = CoinMin(CoinMax(value,colLower2[i]),colUpper2[i]); cleanSolution2[i] = value; } temp2.setColSolution(cleanSolution2); delete [] cleanSolution2; CbcModel modelSmall(temp2); modelSmall.setNumberStrong(0); CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(3); generator1.setMaxProbe(100); generator1.setMaxLook(50); generator1.setRowCuts(3); CglGomory generator2; // try larger limit generator2.setLimit(300); CglKnapsackCover generator3; CglOddHole generator4; generator4.setMinimumViolation(0.005); generator4.setMinimumViolationPer(0.00002); // try larger limit generator4.setMaximumEntries(200); CglClique generator5; generator5.setStarCliqueReport(false); generator5.setRowCliqueReport(false); CglMixedIntegerRounding mixedGen; CglFlowCover flowGen; // Add in generators modelSmall.addCutGenerator(&generator1,-1,"Probing",true,false,false,-1); modelSmall.addCutGenerator(&generator2,-99,"Gomory",true,false,false,-99); modelSmall.addCutGenerator(&generator3,-99,"Knapsack",true,false,false,-99); modelSmall.addCutGenerator(&generator4,-99,"OddHole",true,false,false,-99); modelSmall.addCutGenerator(&generator5,-99,"Clique",true,false,false,-99); modelSmall.addCutGenerator(&flowGen,-99,"FlowCover",true,false,false,-99); modelSmall.addCutGenerator(&mixedGen,-99,"MixedIntegerRounding",true,false,false,-100); #if 1 const CoinPackedMatrix * matrix = temp2.getMatrixByCol(); const int * columnLength = matrix->getVectorLengths(); int * priority = new int [numberColumns2+1]; // do pseudo costs and priorities - take a reasonable guess CbcObject ** objects = new CbcObject * [numberColumns2+1]; int n=0; const double * objective = modelSmall.getObjCoefficients(); for (i=0;i<numberColumns2;i++) { CbcSimpleIntegerPseudoCost * newObject = new CbcSimpleIntegerPseudoCost(&modelSmall,n,i,objective[i],0.5*objective[i]); newObject->setMethod(3); objects[n]= newObject; priority[n++]=10000-columnLength[i]; } priority[n]=1; objects[n++]=new CbcFollowOn2(&modelSmall); modelSmall.addObjects(n,objects); for (i=0;i<n;i++) delete objects[i]; delete [] objects; modelSmall.passInPriorities(priority,false); delete [] priority; #endif modelSmall.setCutoff(model_->getCutoff()); //if (!onPathX&&modelSmall.getCutoff()>480.5) //modelSmall.setCutoff(480.5); //printf("cutoff %g\n",model_->getCutoff()); modelSmall.messageHandler()->setLogLevel(1); modelSmall.solver()->messageHandler()->setLogLevel(0); modelSmall.messagesPointer()->setDetailMessage(3,9); modelSmall.messagesPointer()->setDetailMessage(3,6); modelSmall.messagesPointer()->setDetailMessage(3,4); modelSmall.messagesPointer()->setDetailMessage(3,13); modelSmall.messagesPointer()->setDetailMessage(3,14); modelSmall.messagesPointer()->setDetailMessage(3,1); modelSmall.messagesPointer()->setDetailMessage(3,3007); modelSmall.branchAndBound(); temp2.releaseClp(); if (modelSmall.bestSolution()) { double objValue = 0.0; const double * solution2 = modelSmall.bestSolution(); double * solution = modelPtr_->primalColumnSolution(); const double * objective = modelPtr_->objective(); for (i=0;i<numberColumns;i++) solution[i]=colLower[i]; for (i=0;i<nNewCol;i++) { int iColumn = whichColumn[i]; solution[iColumn]=solution2[i]; } for (i=0;i<numberColumns;i++) objValue += solution[i]*objective[i]; assert (objValue<model_->getCutoff()); if (objValue<model_->getCutoff()) { //printf("good solution \n"); model_->setBestSolution(CBC_TREE_SOL,objValue,solution); returnCode = 0; } else { returnCode=2; } } else { returnCode=2; } #endif if (returnCode!=0&&returnCode!=2) { printf("pretending entire search done\n"); returnCode=0; } if (returnCode==0||returnCode==2) { modelPtr_->setProblemStatus(1); delete [] whichRow; delete [] whichColumn; return; } } } if ((count_<100&&algorithm_==2)||!algorithm_) { delete [] whichRow; delete [] whichColumn; assert(!modelPtr_->specialOptions()); int saveOptions = modelPtr_->specialOptions(); int startFinishOptions; bool takeHint; OsiHintStrength strength; bool gotHint = (getHintParam(OsiDoInBranchAndCut,takeHint,strength)); assert (gotHint); if (strength!=OsiHintIgnore&&takeHint) { // could do something - think about it //printf("thin hint %d %c\n",strength,takeHint ? 'T' :'F'); } if((specialOptions_&1)==0) { startFinishOptions=0; modelPtr_->setSpecialOptions(saveOptions|(64|1024)); } else { startFinishOptions=1+2+4; if((specialOptions_&4)==0) modelPtr_->setSpecialOptions(saveOptions|(64|128|512|1024|4096)); else modelPtr_->setSpecialOptions(saveOptions|(64|128|512|1024|2048|4096)); } //printf("thin options %d size %d\n",modelPtr_->specialOptions(),modelPtr_->numberColumns()); setBasis(basis_,modelPtr_); //modelPtr_->setLogLevel(1); modelPtr_->dual(0,0); basis_ = getBasis(modelPtr_); modelPtr_->setSpecialOptions(saveOptions); if (modelPtr_->status()==0) { count_++; double * solution = modelPtr_->primalColumnSolution(); int i; for (i=0;i<numberColumns;i++) { if (solution[i]>1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) { node_[i]=CoinMax(count_,node_[i]); howMany_[i]++; } } } else { if (!algorithm_==2) printf("infeasible early on\n"); } } else { // use counts int i; const double * lower = modelPtr_->columnLower(); const double * upper = modelPtr_->columnUpper(); setBasis(basis_,modelPtr_); ClpSimplex * temp = new ClpSimplex(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); //temp->setLogLevel(2); //printf("small has %d rows and %d columns\n",nNewRow,nNewCol); temp->setSpecialOptions(128+512); temp->setDualObjectiveLimit(1.0e50); temp->dual(); if (temp->status()) { // In some cases we know that it must be infeasible if (believeInfeasible_||algorithm_==1) { modelPtr_->setProblemStatus(1); printf("assuming infeasible!\n"); //modelPtr_->writeMps("infeas.mps"); //temp->writeMps("infeas2.mps"); //abort(); delete temp; delete [] whichRow; delete [] whichColumn; return; } } double * solution = modelPtr_->primalColumnSolution(); if (!temp->status()) { const double * solution2 = temp->primalColumnSolution(); memset(solution,0,numberColumns*sizeof(double)); for (i=0;i<nNewCol;i++) { int iColumn = whichColumn[i]; solution[iColumn]=solution2[i]; modelPtr_->setStatus(iColumn,temp->getStatus(i)); } double * rowSolution = modelPtr_->primalRowSolution(); const double * rowSolution2 = temp->primalRowSolution(); double * dual = modelPtr_->dualRowSolution(); const double * dual2 = temp->dualRowSolution(); memset(dual,0,numberRows*sizeof(double)); for (i=0;i<nNewRow;i++) { int iRow=whichRow[i]; modelPtr_->setRowStatus(iRow,temp->getRowStatus(i)); rowSolution[iRow]=rowSolution2[i]; dual[iRow]=dual2[i]; } // See if optimal double * dj = modelPtr_->dualColumnSolution(); // get reduced cost for large problem // this assumes minimization memcpy(dj,modelPtr_->objective(),numberColumns*sizeof(double)); modelPtr_->transposeTimes(-1.0,dual,dj); modelPtr_->setObjectiveValue(temp->objectiveValue()); modelPtr_->setProblemStatus(0); int nBad=0; for (i=0;i<numberColumns;i++) { if (modelPtr_->getStatus(i)==ClpSimplex::atLowerBound &&upper[i]>lower[i]&&dj[i]<-1.0e-5) nBad++; } //modelPtr_->writeMps("bada.mps"); //temp->writeMps("badb.mps"); if (nBad) { assert (algorithm_==2); //printf("%d bad\n",nBad); timesBad_++; modelPtr_->primal(); } } else { // infeasible - do all modelPtr_->setSpecialOptions(64+128+512); setBasis(basis_,modelPtr_); //modelPtr_->setLogLevel(1); modelPtr_->dual(0,0); basis_ = getBasis(modelPtr_); modelPtr_->setSpecialOptions(0); if (modelPtr_->status()) { printf("really infeasible!\n"); delete temp; delete [] whichRow; delete [] whichColumn; return; } else { printf("initially infeasible\n"); } } delete temp; delete [] whichRow; delete [] whichColumn; basis_ = getBasis(modelPtr_); modelPtr_->setSpecialOptions(0); count_++; if ((count_%100)==0&&algorithm_==2) printf("count %d, bad %d\n",count_,timesBad_); for (i=0;i<numberColumns;i++) { if (solution[i]>1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) { node_[i]=CoinMax(count_,node_[i]); howMany_[i]++; } } if (modelPtr_->objectiveValue()>=modelPtr_->dualObjectiveLimit()) modelPtr_->setProblemStatus(1); } }
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; }
//----------------------------------------------------------------------------- void CbcSolver2::resolve() { int numberColumns = modelPtr_->numberColumns(); if ((count_<10&&algorithm_==2)||!algorithm_) { OsiClpSolverInterface::resolve(); if (modelPtr_->status()==0) { count_++; double * solution = modelPtr_->primalColumnSolution(); int i; for (i=0;i<numberColumns;i++) { if (solution[i]>1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) { node_[i]=CoinMax(count_,node_[i]); howMany_[i]++; } } } else { if (!algorithm_==2) printf("infeasible early on\n"); } } else { // use counts int numberRows=modelPtr_->numberRows(); int * whichRow = new int[numberRows]; int * whichColumn = new int [numberColumns]; int i; const double * lower = modelPtr_->columnLower(); const double * upper = modelPtr_->columnUpper(); const double * rowUpper = modelPtr_->rowUpper(); bool equality=false; for (i=0;i<numberRows;i++) { if (rowUpper[i]==1.0) { equality=true; break; } } setBasis(basis_,modelPtr_); int nNewCol=0; // Column copy //const double * element = modelPtr_->matrix()->getElements(); const int * row = modelPtr_->matrix()->getIndices(); const CoinBigIndex * columnStart = modelPtr_->matrix()->getVectorStarts(); const int * columnLength = modelPtr_->matrix()->getVectorLengths(); int * rowActivity = new int[numberRows]; memset(rowActivity,0,numberRows*sizeof(int)); int * rowActivity2 = new int[numberRows]; memset(rowActivity2,0,numberRows*sizeof(int)); char * mark = new char[numberColumns]; memset(mark,0,numberColumns); // Get rows which are satisfied for (i=0;i<numberColumns;i++) { if (lower[i]>0.0) { CoinBigIndex j; for (j=columnStart[i]; j<columnStart[i]+columnLength[i];j++) { int iRow=row[j]; rowActivity2[iRow] ++; } } else if (!upper[i]) { mark[i]=2; // no good } } // If equality - check not infeasible if (equality) { bool feasible=true; for (i=0;i<numberRows;i++) { if (rowActivity2[i]>1) { feasible=false; break; } } if (!feasible) { delete [] rowActivity; delete [] rowActivity2; modelPtr_->setProblemStatus(1); delete [] whichRow; delete [] whichColumn; delete [] mark; printf("infeasible by inspection (over)\n"); return; } } int nNoGood=0; for (i=0;i<numberColumns;i++) { if (mark[i]==2) { nNoGood++; continue; } bool choose; if (algorithm_==1) choose = true; else choose = (node_[i]>count_-memory_&&node_[i]>0); bool any; if (equality) { // See if forced to be zero CoinBigIndex j; any=true; for (j=columnStart[i]; j<columnStart[i]+columnLength[i];j++) { int iRow=row[j]; if (rowActivity2[iRow]) any=false; // can't be in } } else { // See if not useful CoinBigIndex j; any=false; for (j=columnStart[i]; j<columnStart[i]+columnLength[i];j++) { int iRow=row[j]; if (!rowActivity2[iRow]) any=true; // useful } } if (!any&&!lower[i]) { choose=false; // and say can't be useful mark[i]=2; nNoGood++; } if (strategy_&&modelPtr_->getColumnStatus(i)==ClpSimplex::basic) choose=true; if (choose||lower[i]>0.0) { mark[i]=1; whichColumn[nNewCol++]=i; CoinBigIndex j; double value = upper[i]; if (value) { for (j=columnStart[i]; j<columnStart[i]+columnLength[i];j++) { int iRow=row[j]; rowActivity[iRow] ++; } } } } // If equality add in slacks CoinModel build; if (equality) { int row=0; for (i=0;i<numberRows;i++) { // put in all rows if wanted if(strategy_) rowActivity2[i]=0; if (!rowActivity2[i]) { double element=1.0; build.addColumn(1,&row,&element,0.0,1.0,1.0e8); // large cost row++; } } } int nOK=0; int nNewRow=0; for (i=0;i<numberRows;i++) { if (rowActivity[i]) nOK++; if (!rowActivity2[i]) whichRow[nNewRow++]=i; // not satisfied else modelPtr_->setRowStatus(i,ClpSimplex::basic); // make slack basic } if (nOK<numberRows) { for (i=0;i<numberColumns;i++) { if (!mark[i]) { CoinBigIndex j; int good=0; for (j=columnStart[i]; j<columnStart[i]+columnLength[i];j++) { int iRow=row[j]; if (!rowActivity[iRow]) { rowActivity[iRow] ++; good++; } } if (good) { nOK+=good; whichColumn[nNewCol++]=i; } } } } delete [] rowActivity; delete [] rowActivity2; if (nOK<numberRows) { modelPtr_->setProblemStatus(1); delete [] whichRow; delete [] whichColumn; delete [] mark; printf("infeasible by inspection\n"); return; } bool allIn=false; if (nNewCol+nNoGood+numberRows>numberColumns) { // add in all allIn=true; for (i=0;i<numberColumns;i++) { if (!mark[i]) { whichColumn[nNewCol++]=i; } } } ClpSimplex * temp = new ClpSimplex(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); if (equality) temp->addColumns(build); temp->setLogLevel(1); printf("small has %d rows and %d columns (%d impossible to help) %s\n", nNewRow,nNewCol,nNoGood,allIn ? "all in" : ""); temp->setSpecialOptions(128+512); temp->setDualObjectiveLimit(1.0e50); temp->dual(); assert (!temp->status()); double * solution = modelPtr_->primalColumnSolution(); const double * solution2 = temp->primalColumnSolution(); memset(solution,0,numberColumns*sizeof(double)); for (i=0;i<nNewCol;i++) { int iColumn = whichColumn[i]; solution[iColumn]=solution2[i]; modelPtr_->setStatus(iColumn,temp->getStatus(i)); } double * rowSolution = modelPtr_->primalRowSolution(); const double * rowSolution2 = temp->primalRowSolution(); double * dual = modelPtr_->dualRowSolution(); const double * dual2 = temp->dualRowSolution(); memset(dual,0,numberRows*sizeof(double)); for (i=0;i<nNewRow;i++) { int iRow=whichRow[i]; modelPtr_->setRowStatus(iRow,temp->getRowStatus(i)); rowSolution[iRow]=rowSolution2[i]; dual[iRow]=dual2[i]; } // See if optimal double * dj = modelPtr_->dualColumnSolution(); // get reduced cost for large problem // this assumes minimization memcpy(dj,modelPtr_->objective(),numberColumns*sizeof(double)); modelPtr_->transposeTimes(-1.0,dual,dj); modelPtr_->setObjectiveValue(temp->objectiveValue()); modelPtr_->setProblemStatus(0); int nBad=0; for (i=0;i<numberColumns;i++) { if (modelPtr_->getStatus(i)==ClpSimplex::atLowerBound &&upper[i]>lower[i]&&dj[i]<-1.0e-5) nBad++; } //modelPtr_->writeMps("bada.mps"); //temp->writeMps("badb.mps"); delete temp; if (nBad&&!allIn) { assert (algorithm_==2); //printf("%d bad\n",nBad); timesBad_++; // just non mark==2 int nAdded=0; for (i=0;i<numberColumns;i++) { if (!mark[i]) { whichColumn[nNewCol++]=i; nAdded++; } } assert (nAdded); { temp = new ClpSimplex(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); if (equality) temp->addColumns(build); temp->setLogLevel(2); temp->setSpecialOptions(128+512); temp->setDualObjectiveLimit(1.0e50); temp->primal(1); assert (!temp->status()); double * solution = modelPtr_->primalColumnSolution(); const double * solution2 = temp->primalColumnSolution(); memset(solution,0,numberColumns*sizeof(double)); for (i=0;i<nNewCol;i++) { int iColumn = whichColumn[i]; solution[iColumn]=solution2[i]; modelPtr_->setStatus(iColumn,temp->getStatus(i)); } double * rowSolution = modelPtr_->primalRowSolution(); const double * rowSolution2 = temp->primalRowSolution(); double * dual = modelPtr_->dualRowSolution(); const double * dual2 = temp->dualRowSolution(); memset(dual,0,numberRows*sizeof(double)); for (i=0;i<nNewRow;i++) { int iRow=whichRow[i]; modelPtr_->setRowStatus(iRow,temp->getRowStatus(i)); rowSolution[iRow]=rowSolution2[i]; dual[iRow]=dual2[i]; } modelPtr_->setObjectiveValue(temp->objectiveValue()); modelPtr_->setProblemStatus(0); iterationsBad_ += temp->numberIterations(); printf("clean %d\n",temp->numberIterations()); delete temp; } } delete [] mark; delete [] whichRow; delete [] whichColumn; basis_ = getBasis(modelPtr_); modelPtr_->setSpecialOptions(0); count_++; if ((count_%100)==0&&algorithm_==2) printf("count %d, bad %d - iterations %d\n",count_,timesBad_,iterationsBad_); for (i=0;i<numberColumns;i++) { if (solution[i]>1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) { node_[i]=CoinMax(count_,node_[i]); howMany_[i]++; } } if (modelPtr_->objectiveValue()>=modelPtr_->dualObjectiveLimit()) modelPtr_->setProblemStatus(1); } }
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; }