FLOPC++
MP_model.cpp
Go to the documentation of this file.
1 // ******************** FlopCpp **********************************************
2 // File: MP_model.cpp
3 // $Id$
4 // Author: Tim Helge Hultberg (thh@mat.ua.pt)
5 // Copyright (C) 2003 Tim Helge Hultberg
6 // All Rights Reserved.
7 //****************************************************************************
8 
9 #include <iostream>
10 #include <sstream>
11 #include <algorithm>
12 
13 #include <CoinPackedMatrix.hpp>
14 #include <OsiSolverInterface.hpp>
15 #include "MP_model.hpp"
16 #include "MP_variable.hpp"
17 #include "MP_constraint.hpp"
18 #include <CoinTime.hpp>
19 
20 using namespace flopc;
21 using namespace std;
22 
25 MP_model &MP_model::getDefaultModel() { return default_model;}
26 MP_model *MP_model::getCurrentModel() { return current_model;}
27 
28 void NormalMessenger::statistics(int bm, int m, int bn, int n, int nz) {
29  cout<<"FlopCpp: Number of constraint blocks: " <<bm<<endl;
30  cout<<"FlopCpp: Number of individual constraints: " <<m<<endl;
31  cout<<"FlopCpp: Number of variable blocks: " <<bn<<endl;
32  cout<<"FlopCpp: Number of individual variables: " <<n<<endl;
33  cout<<"FlopCpp: Number of non-zeroes (including rhs): " <<nz<<endl;
34 }
35 
37  cout<<"FlopCpp: Generation time: "<<t<<endl;
38 }
39 
40 void VerboseMessenger::constraintDebug(string name, const vector<Coef>& cfs) {
41  cout<<"FlopCpp: Constraint "<<name<<endl;
42  for (unsigned int j=0; j<cfs.size(); j++) {
43  int col=cfs[j].col;
44  int row=cfs[j].row;
45  double elm=cfs[j].val;
46  int stage=cfs[j].stage;
47  cout<<row<<" "<<col<<" "<<elm<<" "<<stage<<endl;
48  }
49 }
50 
51 void VerboseMessenger::objectiveDebug(const vector<Coef>& cfs) {
52  cout<<"Objective "<<endl;
53  for (unsigned int j=0; j<cfs.size(); j++) {
54  int col=cfs[j].col;
55  int row=cfs[j].row;
56  double elm=cfs[j].val;
57  cout<<row<<" "<<col<<" "<<elm<<endl;
58  }
59 }
60 
61 MP_model::MP_model(OsiSolverInterface* s, Messenger* m) :
62  solution(0), messenger(m), Objective(0), Solver(s),
63  m(0), n(0), nz(0), bl(0),
64  mSolverState(((s==NULL)?(MP_model::DETACHED):(MP_model::SOLVER_ONLY))) {
66 }
67 
69  Constraints.insert(&lcl_c);
70  return *this;
71 }
72 
74  lcl_c->M = this;
75  lcl_c->offset = m;
76  m += lcl_c->size();
77 }
78 
79 double MP_model::getInfinity() const {
80  if (Solver==0) {
81  return 9.9e+32;
82  } else {
83  return Solver->getInfinity();
84  }
85 }
86 
88  v->M = this;
89  v->offset = n;
90  n += v->size();
91 }
92 
93 void MP_model::addRow(const Constraint& lcl_c) {
94  vector<Coef> cfs;
95  vector<Constant> v;
97  lcl_c.left->generate(MP_domain::getEmpty(),v,f,1.0);
98  lcl_c.right->generate(MP_domain::getEmpty(),v,f,-1.0);
99  CoinPackedVector newRow;
100  double rhs = 0.0;
101  for (unsigned int j=0; j<cfs.size(); j++) {
102  int col=cfs[j].col;
103  //int row=cfs[j].row;
104  double elm=cfs[j].val;
105  //cout<<row<<" "<<col<<" "<<elm<<endl;
106  if (col>=0) {
107  newRow.insert(col,elm);
108  } else if (col==-1) {
109  rhs = elm;
110  }
111  }
112  // NB no "assembly" of added row yet. Will be done....
113 
114  double lcl_bl = -rhs;
115  double lcl_bu = -rhs;
116 
117  double inf = Solver->getInfinity();
118  switch (lcl_c.sense) {
119  case LE:
120  lcl_bl = - inf;
121  break;
122  case GE:
123  lcl_bu = inf;
124  break;
125  case EQ:
126  // Nothing to do
127  break;
128  }
129 
130  Solver->addRow(newRow,lcl_bl,lcl_bu);
131 }
132 
134  Objective = o;
135 }
136 
138  MP_variable v;
139  MP_constraint lcl_c(s);
140  add(lcl_c);
141  lcl_c(s) = v() >= obj;
142  minimize(v());
143 }
144 
145 
147 public:
148  bool operator() (const Coef& a, const Coef& b) const {
149  if (a.col < b.col) {
150  return true;
151  } else if (a.col == b.col && a.row < b.row) {
152  return true;
153  } else {
154  return false;
155  }
156  }
157 };
158 
159 void MP_model::assemble(vector<Coef>& v, vector<Coef>& av) {
160  std::sort(v.begin(),v.end(),CoefLess());
161  int c,r,s;
162  double val;
163  std::vector<Coef>::const_iterator i = v.begin();
164  while (i!=v.end()) {
165  c = i->col;
166  r = i->row;
167  val = i->val;
168  s = i->stage;
169  i++;
170  while (i!=v.end() && c==i->col && r==i->row) {
171  val += i->val;
172  if (i->stage>s) {
173  s = i->stage;
174  }
175  i++;
176  }
177  av.push_back(Coef(c,r,val,s));
178  }
179 }
180 
182  if (Solver!=0) {
183  attach(Solver);
185  } else {
186  cout<<"no solver specified"<<endl;
187  }
188 }
189 
191  if (Solver!=0) {
192  Objective = obj;
193  attach(Solver);
195  } else {
196  cout<<"no solver specified"<<endl;
197  }
198 }
199 
201  if (Solver!=0) {
202  attach(Solver);
204  } else {
205  cout<<"no solver specified"<<endl;
206  }
207 }
208 
210  if (Solver!=0) {
211  Objective = obj;
212  attach(Solver);
214  } else {
215  cout<<"no solver specified"<<endl;
216  }
217 }
218 
219 void MP_model::attach(OsiSolverInterface *_solver) {
220  if (_solver==NULL) {
221  if (Solver==NULL) {
223  return;
224  }
225  } else { // use pre-attached solver.
226  if(Solver && Solver!=_solver) {
227  detach();
228  }
229  Solver=_solver;
230  }
231  double time = CoinCpuTime();
232  m=0;
233  n=0;
234  vector<Coef> coefs;
235  vector<Coef> cfs;
236 
237  typedef std::set<MP_variable* >::iterator varIt;
238  typedef std::set<MP_constraint* >::iterator conIt;
239 
240  Objective->insertVariables(Variables);
241  for (conIt i=Constraints.begin(); i!=Constraints.end(); i++) {
242  add(*i);
243  (*i)->insertVariables(Variables);
244  }
245  for (varIt j=Variables.begin(); j!=Variables.end(); j++) {
246  add(*j);
247  }
248 
249  // Generate coefficient matrix and right hand side
250  bool doAssemble = true;
251  if (doAssemble == true) {
252  GenerateFunctor f(cfs);
253  for (conIt i=Constraints.begin(); i!=Constraints.end(); i++) {
254  (*i)->coefficients(f);
255  messenger->constraintDebug((*i)->getName(),cfs);
256  assemble(cfs,coefs);
257  cfs.erase(cfs.begin(),cfs.end());
258  }
259  } else {
260  GenerateFunctor f(coefs);
261  for (conIt i=Constraints.begin(); i!=Constraints.end(); i++) {
262  (*i)->coefficients(f);
263  }
264  }
265  nz = static_cast<int>(coefs.size());
266 
267  messenger->statistics(static_cast<int>(Constraints.size()),m,static_cast<int>(Variables.size()),n,nz);
268 
269  Elm = new double[nz];
270  Rnr = new int[nz];
271  Cst = new int[n+2];
272  Clg = new int[n+1];
273  l = new double[n];
274  u = new double[n];
275  bl = new double[m];
276  bu = new double[m];
277 
278  const double inf = Solver->getInfinity();
279 
280  for (int j=0; j<n; j++) {
281  Clg[j] = 0;
282  }
283  Clg[n] = 0;
284 
285  // Treat right hand side as n'th column
286  for (int j=0; j<=n; j++) {
287  Clg[j] = 0;
288  }
289  for (int i=0; i<nz; i++) {
290  int col = coefs[i].col;
291  if (col == -1) {
292  col = n;
293  }
294  Clg[col]++;
295  }
296  Cst[0]=0;
297  for (int j=0; j<=n; j++) {
298  Cst[j+1]=Cst[j]+Clg[j];
299  }
300  for (int i=0; i<=n; i++) {
301  Clg[i]=0;
302  }
303  for (int i=0; i<nz; i++) {
304  int col = coefs[i].col;
305  if (col==-1) {
306  col = n;
307  }
308  int row = coefs[i].row;
309  double elm = coefs[i].val;
310  Elm[Cst[col]+Clg[col]] = elm;
311  Rnr[Cst[col]+Clg[col]] = row;
312  Clg[col]++;
313  }
314 
315  // Row bounds
316  for (int i=0; i<m; i++) {
317  bl[i] = 0;
318  bu[i] = 0;
319  }
320  for (int j=Cst[n]; j<Cst[n+1]; j++) {
321  bl[Rnr[j]] = -Elm[j];
322  bu[Rnr[j]] = -Elm[j];
323  }
324 
325  for (conIt i=Constraints.begin(); i!=Constraints.end(); i++) {
326  int begin = (*i)->offset;
327  int end = (*i)->offset+(*i)->size();
328  switch ((*i)->sense) {
329  case LE:
330  for (int k=begin; k<end; k++) {
331  bl[k] = - inf;
332  }
333  break;
334  case GE:
335  for (int k=begin; k<end; k++) {
336  bu[k] = inf;
337  }
338  break;
339  case EQ:
340  // Nothing to do
341  break;
342  }
343  }
344 
345  // Generate objective function coefficients
346  vector<Constant> v;
347  if (doAssemble == true) {
349  coefs.erase(coefs.begin(),coefs.end());
350  Objective->generate(MP_domain::getEmpty(), v, f, 1.0);
351 
353  assemble(cfs,coefs);
354  } else {
355  ObjectiveGenerateFunctor f(coefs);
356  coefs.erase(coefs.begin(),coefs.end());
357  Objective->generate(MP_domain::getEmpty(), v, f, 1.0);
358  }
359 
360  c = new double[n];
361  for (int j=0; j<n; j++) {
362  c[j] = 0.0;
363  }
364  for (size_t i=0; i<coefs.size(); i++) {
365  int col = coefs[i].col;
366  double elm = coefs[i].val;
367  c[col] = elm;
368  }
369 
370  // Column bounds
371  for (int j=0; j<n; j++) {
372  l[j] = 0.0;
373  u[j] = inf;
374  }
375 
376  for (varIt i=Variables.begin(); i!=Variables.end(); i++) {
377  for (int k=0; k<(*i)->size(); k++) {
378  l[(*i)->offset+k] = (*i)->lowerLimit.v[k];
379  u[(*i)->offset+k] = (*i)->upperLimit.v[k];
380  }
381  }
382 
383  CoinPackedMatrix A(true,m,n,Cst[n],Elm,Rnr,Cst,Clg);
384  Solver->loadProblem(A, l, u, c, bl, bu);
385 
386  // Instead of the 2 lines above we should be able to use
387  // the line below, but due to a bug in OsiGlpk it does not work
388  // Solver->loadProblem(n, m, Cst, Rnr, Elm, l, u, c, bl, bu);
389 
390  delete [] Elm;
391  delete [] Rnr;
392  delete [] Cst;
393  delete [] Clg;
394  delete [] l;
395  delete [] u;
396  delete [] bl;
397  delete [] bu;
398  delete [] c;
399 
400  for (varIt i=Variables.begin(); i!=Variables.end(); i++) {
401  int begin = (*i)->offset;
402  int end = (*i)->offset+(*i)->size();
403  if ((*i)->type == discrete) {
404  for (int k=begin; k<end; k++) {
405  Solver->setInteger(k);
406  }
407  }
408  }
410  messenger->generationTime(time-CoinCpuTime());
411 
412 }
414  assert(Solver);
417  delete Solver;
418  Solver=NULL;
419 }
420 
422  assert(Solver);
423  assert(mSolverState != MP_model::DETACHED &&
425  Solver->setObjSense(dir);
426  bool isMIP = false;
427  for (varIt i=Variables.begin(); i!=Variables.end(); i++) {
428  if ((*i)->type == discrete) {
429  isMIP = true;
430  break;
431  }
432  }
433  if (isMIP == true) {
434  try {
435  Solver->branchAndBound();
436  } catch (CoinError e) {
437  cout<<e.message()<<endl;
438  cout<<"Solving the LP relaxation instead."<<endl;
439  try {
440  Solver->initialSolve();
441  } catch (CoinError e) {
442  cout<<e.message()<<endl;
443  }
444  }
445  } else {
446  try {
447  Solver->initialSolve();
448  } catch (CoinError e) {
449  cout<<e.message()<<endl;
450  }
451  }
452 
453  if (Solver->isProvenOptimal() == true) {
454  cout<<"FlopCpp: Optimal obj. value = "<<Solver->getObjValue()<<endl;
455  cout<<"FlopCpp: Solver(m, n, nz) = "<<Solver->getNumRows()<<" "<<
456  Solver->getNumCols()<<" "<<Solver->getNumElements()<<endl;
457  solution = Solver->getColSolution();
458  reducedCost = Solver->getReducedCost();
459  rowPrice = Solver->getRowPrice();
460  rowActivity = Solver->getRowActivity();
461  } else if (Solver->isProvenPrimalInfeasible() == true) {
463  //cout<<"FlopCpp: Problem is primal infeasible."<<endl;
464  } else if (Solver->isProvenDualInfeasible() == true) {
466  //cout<<"FlopCpp: Problem is dual infeasible."<<endl;
467  } else {
469  //cout<<"FlopCpp: Solution process abandoned."<<endl;
470  }
472 }
473 
474 namespace flopc {
475  std::ostream &operator<<(std::ostream &os,
476  const MP_model::MP_status &condition) {
477  switch(condition) {
478  case MP_model::OPTIMAL:
479  os<<"OPTIMAL";
480  break;
482  os<<"PRIMAL_INFEASIBLE";
483  break;
485  os<<"DUAL_INFEASIBLE";
486  break;
487  case MP_model::ABANDONED:
488  os<<"ABANDONED";
489  break;
490  default:
491  os<<"UNKNOWN";
492  };
493  return os;
494  }
495 
496  std::ostream &operator<<(std::ostream &os,
497  const MP_model::MP_direction &direction) {
498  switch(direction) {
499  case MP_model::MINIMIZE:
500  os<<"MINIMIZE";
501  break;
502  case MP_model::MAXIMIZE:
503  os<<"MAXIMIZE";
504  break;
505  default:
506  os<<"UNKNOWN";
507  };
508  return os;
509  }
510 }
Symbolic representation of a linear expression.This is one of the main public interface classes...
Messenger * messenger
Definition: MP_model.hpp:246
MP_model(OsiSolverInterface *s, Messenger *m=new NormalMessenger)
Constructs an MP_model from an OsiSolverInterface *.
Definition: MP_model.cpp:61
std::ostream & operator<<(std::ostream &os, const MP_model::MP_status &condition)
allows print of result from call to solve();
Definition: MP_model.cpp:475
static void assemble(std::vector< Coef > &v, std::vector< Coef > &av)
Definition: MP_model.cpp:159
static MP_model * getCurrentModel()
Definition: MP_model.cpp:26
double getInfinity() const
Definition: MP_model.cpp:79
std::set< MP_constraint * >::iterator conIt
Definition: MP_model.hpp:240
MP_model & add(MP_constraint &c)
Adds a constrataint block to the model.
Definition: MP_model.cpp:68
std::set< MP_variable * >::iterator varIt
Definition: MP_model.hpp:239
Inteface for hooking up to internal flopc++ message handling.In more advanced use of FlopC++...
Definition: MP_model.hpp:35
virtual void statistics(int bm, int m, int bn, int n, int nz)
Definition: MP_model.cpp:28
const double * rowPrice
Definition: MP_model.hpp:213
virtual void constraintDebug(std::string name, const std::vector< Coef > &cfs)
Definition: MP_model.hpp:40
std::set< MP_variable * > Variables
Definition: MP_model.hpp:253
MP_expression right
virtual void generationTime(double t)
Definition: MP_model.hpp:43
Functor to facilitate generation of the objective function.
void setObjective(const MP_expression &o)
sets the &quot;current objective&quot; to the parameter o
Definition: MP_model.cpp:133
void addRow(const Constraint &c)
Adds a constraint to the MP_model.
Definition: MP_model.cpp:93
const double * rowActivity
Definition: MP_model.hpp:214
MP_expression Objective
Definition: MP_model.hpp:251
static MP_model * current_model
Definition: MP_model.hpp:242
double * Elm
Definition: MP_model.hpp:264
int size() const
MP_status mSolverState
Definition: MP_model.hpp:270
A solver is attached, but not yet solved.
Definition: MP_model.hpp:111
MP_status
Reflects the state of the solution from solve()
Definition: MP_model.hpp:97
This is the anchor point for all constructs in a FlopC++ model.The constructors take an OsiSolverInte...
Definition: MP_model.hpp:89
virtual void statistics(int bm, int m, int bn, int n, int nz)
Definition: MP_model.hpp:42
OsiSolverInterface * Solver
Definition: MP_model.hpp:256
if solve is called and solver finds model primal infeasible.
Definition: MP_model.hpp:101
MP_model::MP_status solve(const MP_model::MP_direction &dir)
Definition: MP_model.cpp:421
Internal representation of a Coefficient in a matrix.
static const MP_domain & getEmpty()
returns a reference to the &quot;empty&quot; set.
Definition: MP_domain.cpp:48
void minimize_max(MP_set &d, const MP_expression &obj)
Definition: MP_model.cpp:137
Symantic representation of a variable.This is one of the main public interface classes. It should be directly declared by clients of the FlopC++. The parametersof construction are MP_set s which specify the indexes over which the variable is defined.
Definition: MP_variable.hpp:75
if solve is called and solver finds the model dual infeasible.
Definition: MP_model.hpp:103
MP_expression left
Representation of a set for indexing into some other construct.This is one of the main public interfa...
Definition: MP_set.hpp:78
const double * reducedCost
Definition: MP_model.hpp:212
Functor to facilitate generation of coefficients.
virtual void objectiveDebug(const std::vector< Coef > &cfs)
Definition: MP_model.cpp:51
virtual void constraintDebug(std::string name, const std::vector< Coef > &cfs)
Definition: MP_model.cpp:40
const double * solution
Definition: MP_model.hpp:211
static MP_model & default_model
Definition: MP_model.hpp:241
static MP_model & getDefaultModel()
Definition: MP_model.cpp:25
No solver is attached.
Definition: MP_model.hpp:113
if the solve method is called and the optimal solution found.
Definition: MP_model.hpp:99
MP_direction
used when calling the solve() method.
Definition: MP_model.hpp:93
virtual void objectiveDebug(const std::vector< Coef > &cfs)
Definition: MP_model.hpp:41
void detach()
detaches an OsiSolverInterface object from the model. In essence, this will clean up any intermediate...
Definition: MP_model.cpp:413
void attach(OsiSolverInterface *solver=NULL)
attaches the symantic representation of a model and data to a particular OsiSolverInterface ...
Definition: MP_model.cpp:219
std::set< MP_constraint * > Constraints
Definition: MP_model.hpp:252
virtual void generationTime(double t)
Definition: MP_model.cpp:36
Semantic representation of a linear constraint.This is one of the main public interface classes...