int main(int argc, const char *argv[]) { ClpInterior 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); } // ** note this does not have presolve #ifdef WSSMP_BARRIER ClpCholeskyWssmp * cholesky = new ClpCholeskyWssmp(); #else ClpCholeskyDense * cholesky = new ClpCholeskyDense(); #endif model.setCholesky(cholesky); model.primalDual(); // Do crossover ClpSimplex model2(model); // make sure no status left model2.createStatus(); model2.primal(1); return 0; }
int main(int argc, const char *argv[]) { // Get model in some way ClpInterior model; // Open graph and parameter files //FILE *fpin = fopen("./g.graph","r"); //FILE *fpp = fopen("./gparm","r"); FILE *fpin = fopen("./g.tiny", "r"); FILE *fpp = fopen("./gparm.tiny", "r"); assert(fpin); assert(fpp); myPdco stuff(model, fpin, fpp); Info info; Outfo outfo; Options options; /* * Set the input parameters for LSQR. */ options.gamma = stuff.getD1(); options.delta = stuff.getD2(); options.MaxIter = 40; options.FeaTol = 5.0e-4; options.OptTol = 5.0e-4; options.StepTol = 0.99; // options.x0min = 10.0/num_cols; options.x0min = 0.01; options.z0min = 0.01; options.mu0 = 1.0e-6; options.LSmethod = 3; // 1=Cholesky 2=QR 3=LSQR options.LSproblem = 1; // See below options.LSQRMaxIter = 999; options.LSQRatol1 = 1.0e-3; // Initial atol options.LSQRatol2 = 1.0e-6; // Smallest atol (unless atol1 is smaller) options.LSQRconlim = 1.0e12; info.atolmin = options.LSQRatol2; info.LSdamp = 0.0; // These are already set? model.xsize_ = 50.0 / (model.numberColumns()); model.xsize_ = CoinMin(1.0, model.xsize_); /* * Solve the test problem */ model.pdco(&stuff, options, info, outfo); /* * Examine the results. * Print the residual norms RNORM and ARNORM given by LSQR, and then compute */ 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[]) { /* Read quadratic model in two stages to test loadQuadraticObjective. And is also possible to just read into ClpSimplex/Interior which sets it all up in one go. But this is only if it is in QUADOBJ format. If no arguments does share2qp using ClpInterior (also creates quad.mps which is in QUADOBJ format) If one argument uses simplex e.g. testit quad.mps If > one uses barrier via ClpSimplex input and then ClpInterior borrow */ if (argc < 2) { CoinMpsIO m; #if defined(SAMPLEDIR) int status = m.readMps(SAMPLEDIR "/share2qp", "mps"); #else fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); #endif if (status) { printf("errors on input\n"); exit(77); } ClpInterior model; model.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); // get quadratic part int * start = NULL; int * column = NULL; double * element = NULL; m.readQuadraticMps(NULL, start, column, element, 2); int j; for (j = 0; j < 79; j++) { if (start[j] < start[j+1]) { int i; printf("Column %d ", j); for (i = start[j]; i < start[j+1]; i++) { printf("( %d, %g) ", column[i], element[i]); } printf("\n"); } } model.loadQuadraticObjective(model.numberColumns(), start, column, element); // share2qp is in old style qp format - convert to new so other options can use model.writeMps("quad.mps"); ClpCholeskyBase * cholesky = new ClpCholeskyBase(); cholesky->setKKT(true); model.setCholesky(cholesky); model.primalDual(); double *primal; double *dual; primal = model.primalColumnSolution(); dual = model.dualRowSolution(); int i; int numberColumns = model.numberColumns(); int numberRows = model.numberRows(); for (i = 0; i < numberColumns; i++) { if (fabs(primal[i]) > 1.0e-8) printf("%d primal %g\n", i, primal[i]); } for (i = 0; i < numberRows; i++) { if (fabs(dual[i]) > 1.0e-8) printf("%d dual %g\n", i, dual[i]); } } else { // Could read into ClpInterior ClpSimplex model; if (model.readMps(argv[1])) { printf("errors on input\n"); exit(77); } model.writeMps("quad"); if (argc < 3) { // simplex - just primal as dual does not work // also I need to fix scaling of duals on output // (Was okay in first place - can't mix and match scaling techniques) // model.scaling(0); model.primal(); } else { // barrier ClpInterior barrier; barrier.borrowModel(model); ClpCholeskyBase * cholesky = new ClpCholeskyBase(); cholesky->setKKT(true); barrier.setCholesky(cholesky); barrier.primalDual(); barrier.returnModel(model); } // Just check if share2qp (quad.mps here) // this is because I am not checking if variables at ub if (model.numberColumns() == 79) { double *primal; double *dual; primal = model.primalColumnSolution(); dual = model.dualRowSolution(); // Check duals by hand const ClpQuadraticObjective * quadraticObj = (dynamic_cast<const ClpQuadraticObjective*>(model.objectiveAsObject())); assert(quadraticObj); CoinPackedMatrix * quad = quadraticObj->quadraticObjective(); const int * columnQuadratic = quad->getIndices(); const CoinBigIndex * columnQuadraticStart = quad->getVectorStarts(); const int * columnQuadraticLength = quad->getVectorLengths(); const double * quadraticElement = quad->getElements(); int numberColumns = model.numberColumns(); int numberRows = model.numberRows(); double * gradient = new double [numberColumns]; // move linear objective memcpy(gradient, quadraticObj->linearObjective(), numberColumns * sizeof(double)); int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double valueI = primal[iColumn]; CoinBigIndex j; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; double valueJ = primal[jColumn]; double elementValue = quadraticElement[j]; if (iColumn != jColumn) { double gradientI = valueJ * elementValue; double gradientJ = valueI * elementValue; gradient[iColumn] += gradientI; gradient[jColumn] += gradientJ; } else { double gradientI = valueI * elementValue; gradient[iColumn] += gradientI; } } if (fabs(primal[iColumn]) > 1.0e-8) printf("%d primal %g\n", iColumn, primal[iColumn]); } for (int i = 0; i < numberRows; i++) { if (fabs(dual[i]) > 1.0e-8) printf("%d dual %g\n", i, dual[i]); } // Now use duals to get reduced costs // Can't use this as will try and use scaling // model.transposeTimes(-1.0,dual,gradient); // So ... CoinPackedMatrix * matrix = model.matrix(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); const double * element = matrix->getElements(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { double dj = gradient[iColumn]; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int jRow = row[j]; dj -= element[j] * dual[jRow]; } if (model.getColumnStatus(iColumn) == ClpSimplex::basic) { assert(fabs(dj) < 1.0e-5); } else { assert(dj > -1.0e-5); } } delete [] gradient; } } return 0; }