// ******************** 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 using std::cout; using std::endl; #include #include #include #include "MP_model.hpp" #include "MP_variable.hpp" #include "MP_constraint.hpp" #include using namespace flopc; 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; if (constraint->left.isDefined() && constraint->right.isDefined()) { constraint->offset = m; m += constraint->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& constraint) { vector cfs; vector v; MP::GenerateFunctor f(0,cfs); constraint->left->generate(MP_domain::getEmpty(),v,f,1.0); constraint->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 local_bl = -rhs; double local_bu = -rhs; double inf = Solver->getInfinity(); switch (constraint->sense) { case LE: local_bl = - inf; break; case GE: local_bu = inf; break; case EQ: // Nothing to do break; } Solver->addRow(newRow,local_bl,local_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 constraint(s); add(constraint); constraint(s) = v() >= obj; minimize(v()); } void MP_model::assemble(vector& v, vector& av) { std::sort(v.begin(),v.end(),MP::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(MP::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 for (conIt i=Constraints.begin(); i!=Constraints.end(); i++) { (*i)->coefficients(cfs); messenger->constraintDebug((*i)->getName(),cfs); assemble(cfs,coefs); cfs.erase(cfs.begin(),cfs.end()); } nz = coefs.size(); messenger->statistics(Constraints.size(),m,Variables.size(),n,nz); if (nz>0) { Elm = new double[nz]; Rnr = new int[nz]; } Cst = new int[n+2]; Clg = new int[n+1]; if (n>0) { l = new double[n]; u = new double[n]; c = new double[n]; } if (m>0) { bl = new double[m]; bu = new double[m]; } const double inf = Solver->getInfinity(); for (int j=0; jleft.isDefined() && (*i)->right.isDefined() ) { int begin = (*i)->offset; int end = (*i)->offset+(*i)->size(); switch ((*i)->sense) { case LE: for (int k=begin; k v; MP::GenerateFunctor f(0,cfs); coefs.erase(coefs.begin(),coefs.end()); Objective->generate(MP_domain::getEmpty(), v, f, 1.0); messenger->objectiveDebug(cfs); assemble(cfs,coefs); for (int j=0; jsize(); k++) { l[(*i)->offset+k] = (*i)->lowerLimit.v[k]; u[(*i)->offset+k] = (*i)->upperLimit.v[k]; } } Solver->loadProblem(n, m, Cst, Rnr, Elm, l, u, c, bl, bu); if (nz>0) { delete [] Elm; delete [] Rnr; } delete [] Cst; delete [] Clg; if (n>0) { delete [] l; delete [] u; delete [] c; } if (m>0) { delete [] bl; delete [] bu; } 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(CoinCpuTime()-time); } void MP_model::detach() { assert(Solver); mSolverState = MP_model::DETACHED; delete Solver; Solver = 0; } 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()<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."<