// ******************** FlopCpp ********************************************** // File: MP_model.cpp // $Id$ // Author: Tim Helge Hultberg (thh@mat.ua.pt) // Copyright (C) 2003 Tim Helge Hultberg // All Rights Reserved. //**************************************************************************** #include #include #include #include #include #include "MP_model.hpp" #include "MP_variable.hpp" #include "MP_constraint.hpp" #include using namespace flopc; using namespace std; MP_model& MP_model::default_model = *new MP_model(0); MP_model* MP_model::current_model = &MP_model::default_model; MP_model &MP_model::getDefaultModel() { return default_model;} MP_model *MP_model::getCurrentModel() { return current_model;} void NormalMessenger::statistics(int bm, int m, int bn, int n, int nz) { cout<<"FlopCpp: Number of constraint blocks: " <& cfs) { cout<<"FlopCpp: Constraint "<& cfs) { cout<<"Objective "<M = this; lcl_c->offset = m; m += lcl_c->size(); } double MP_model::getInfinity() const { if (Solver==0) { return 9.9e+32; } else { return Solver->getInfinity(); } } void MP_model::add(MP_variable* v) { v->M = this; v->offset = n; n += v->size(); } void MP_model::addRow(const Constraint& lcl_c) { vector cfs; vector v; ObjectiveGenerateFunctor f(cfs); lcl_c.left->generate(MP_domain::getEmpty(),v,f,1.0); lcl_c.right->generate(MP_domain::getEmpty(),v,f,-1.0); CoinPackedVector newRow; double rhs = 0.0; for (unsigned int j=0; j=0) { newRow.insert(col,elm); } else if (col==-1) { rhs = elm; } } // NB no "assembly" of added row yet. Will be done.... double lcl_bl = -rhs; double lcl_bu = -rhs; double inf = Solver->getInfinity(); switch (lcl_c.sense) { case LE: lcl_bl = - inf; break; case GE: lcl_bu = inf; break; case EQ: // Nothing to do break; } Solver->addRow(newRow,lcl_bl,lcl_bu); } void MP_model::setObjective(const MP_expression& o) { Objective = o; } void MP_model::minimize_max(MP_set &s, const MP_expression &obj) { MP_variable v; MP_constraint lcl_c(s); add(lcl_c); lcl_c(s) = v() >= obj; minimize(v()); } class flopc::CoefLess { public: bool operator() (const Coef& a, const Coef& b) const { if (a.col < b.col) { return true; } else if (a.col == b.col && a.row < b.row) { return true; } else { return false; } } }; void MP_model::assemble(vector& v, vector& av) { std::sort(v.begin(),v.end(),CoefLess()); int c,r,s; double val; std::vector::const_iterator i = v.begin(); while (i!=v.end()) { c = i->col; r = i->row; val = i->val; s = i->stage; i++; while (i!=v.end() && c==i->col && r==i->row) { val += i->val; if (i->stage>s) { s = i->stage; } i++; } av.push_back(Coef(c,r,val,s)); } } void MP_model::maximize() { if (Solver!=0) { attach(Solver); solve(MP_model::MAXIMIZE); } else { cout<<"no solver specified"< coefs; vector cfs; typedef std::set::iterator varIt; typedef std::set::iterator conIt; Objective->insertVariables(Variables); for (conIt i=Constraints.begin(); i!=Constraints.end(); i++) { add(*i); (*i)->insertVariables(Variables); } for (varIt j=Variables.begin(); j!=Variables.end(); j++) { add(*j); } // Generate coefficient matrix and right hand side bool doAssemble = true; if (doAssemble == true) { GenerateFunctor f(cfs); for (conIt i=Constraints.begin(); i!=Constraints.end(); i++) { (*i)->coefficients(f); messenger->constraintDebug((*i)->getName(),cfs); assemble(cfs,coefs); cfs.erase(cfs.begin(),cfs.end()); } } else { GenerateFunctor f(coefs); for (conIt i=Constraints.begin(); i!=Constraints.end(); i++) { (*i)->coefficients(f); } } nz = static_cast(coefs.size()); messenger->statistics(static_cast(Constraints.size()),m,static_cast(Variables.size()),n,nz); Elm = new double[nz]; Rnr = new int[nz]; Cst = new int[n+2]; Clg = new int[n+1]; l = new double[n]; u = new double[n]; bl = new double[m]; bu = new double[m]; const double inf = Solver->getInfinity(); for (int j=0; joffset; int end = (*i)->offset+(*i)->size(); switch ((*i)->sense) { case LE: for (int k=begin; k v; if (doAssemble == true) { ObjectiveGenerateFunctor f(cfs); coefs.erase(coefs.begin(),coefs.end()); Objective->generate(MP_domain::getEmpty(), v, f, 1.0); messenger->objectiveDebug(cfs); assemble(cfs,coefs); } else { ObjectiveGenerateFunctor f(coefs); coefs.erase(coefs.begin(),coefs.end()); Objective->generate(MP_domain::getEmpty(), v, f, 1.0); } c = new double[n]; for (int j=0; jsize(); k++) { l[(*i)->offset+k] = (*i)->lowerLimit.v[k]; u[(*i)->offset+k] = (*i)->upperLimit.v[k]; } } CoinPackedMatrix A(true,m,n,Cst[n],Elm,Rnr,Cst,Clg); Solver->loadProblem(A, l, u, c, bl, bu); // Instead of the 2 lines above we should be able to use // the line below, but due to a bug in OsiGlpk it does not work // Solver->loadProblem(n, m, Cst, Rnr, Elm, l, u, c, bl, bu); delete [] Elm; delete [] Rnr; delete [] Cst; delete [] Clg; delete [] l; delete [] u; delete [] bl; delete [] bu; delete [] c; for (varIt i=Variables.begin(); i!=Variables.end(); i++) { int begin = (*i)->offset; int end = (*i)->offset+(*i)->size(); if ((*i)->type == discrete) { for (int k=begin; ksetInteger(k); } } } mSolverState = MP_model::ATTACHED; messenger->generationTime(time-CoinCpuTime()); } void MP_model::detach() { assert(Solver); mSolverState=MP_model::DETACHED; /// @todo strip all data out of the solver. delete Solver; Solver=NULL; } MP_model::MP_status MP_model::solve(const MP_model::MP_direction &dir) { assert(Solver); assert(mSolverState != MP_model::DETACHED && mSolverState != MP_model::SOLVER_ONLY); Solver->setObjSense(dir); bool isMIP = false; for (varIt i=Variables.begin(); i!=Variables.end(); i++) { if ((*i)->type == discrete) { isMIP = true; break; } } if (isMIP == true) { try { Solver->branchAndBound(); } catch (CoinError e) { cout<initialSolve(); } catch (CoinError e) { cout<initialSolve(); } catch (CoinError e) { cout<isProvenOptimal() == true) { cout<<"FlopCpp: Optimal obj. value = "<getObjValue()<getNumCols()<<" "<getNumElements()<getColSolution(); reducedCost = Solver->getReducedCost(); rowPrice = Solver->getRowPrice(); rowActivity = Solver->getRowActivity(); } else if (Solver->isProvenPrimalInfeasible() == true) { return mSolverState=MP_model::PRIMAL_INFEASIBLE; //cout<<"FlopCpp: Problem is primal infeasible."<isProvenDualInfeasible() == true) { return mSolverState=MP_model::DUAL_INFEASIBLE; //cout<<"FlopCpp: Problem is dual infeasible."<