CYCLUS
solver_factory.cc
Go to the documentation of this file.
1 #include "solver_factory.h"
2 
3 #include <iostream>
4 
5 #include "OsiClpSolverInterface.hpp"
7 #include "CbcSolver.hpp"
8 #include "CoinTime.hpp"
9 
10 #include "error.h"
11 
12 namespace cyclus {
13 
14 int CbcCallBack(CbcModel * model, int from) {
15  int ret = 0;
16  switch (from) {
17  case 1:
18  case 2:
19  if (!model->status() && model->secondaryStatus())
20  ret=1;
21  break;
22  case 3:
23  case 4:
24  case 5:
25  break;
26  }
27  return ret;
28 }
29 
30 ObjValueHandler::ObjValueHandler(double obj, double time, bool found)
31  : obj_(obj),
32  time_(time),
33  found_(found) { };
34 
36  : obj_(obj),
37  time_(0),
38  found_(false) { };
39 
41 
42 ObjValueHandler::ObjValueHandler(const ObjValueHandler& other): CbcEventHandler(other) {
43  obj_ = other.obj();
44  time_ = other.time();
45  found_ = other.found();
46 }
47 
49  if (this != &other) {
50  obj_ = other.obj();
51  time_ = other.time();
52  found_ = other.found();
53  CbcEventHandler::operator=(other);
54  }
55  return *this;
56 }
57 
58 CbcEventHandler* ObjValueHandler::clone() {
59  return new ObjValueHandler(*this);
60 }
61 
62 CbcEventHandler::CbcAction ObjValueHandler::event(CbcEvent e) {
63  if (!found_ && (e == solution || e == heuristicSolution)) {
64  const CbcModel* m = getModel();
65  double cbcobj = m->getObjValue();
66  if (cbcobj < obj_) {
67  time_ = CoinCpuTime() -
68  m->getDblParam(CbcModel::CbcStartSeconds);
69  found_ = true;
70  }
71  }
72  return noAction;
73 }
74 
75 // 10800 s = 3 hrs * 60 min/hr * 60 s/min
76 #define CYCLUS_SOLVER_TIMEOUT 10800
77 
79 SolverFactory::SolverFactory(std::string t) : t_(t), tmax_(CYCLUS_SOLVER_TIMEOUT) { }
80 SolverFactory::SolverFactory(std::string t, double tmax)
81  : t_(t),
82  tmax_(tmax) { }
83 
84 OsiSolverInterface* SolverFactory::get() {
85  if (t_ == "clp" || t_ == "cbc") {
86  OsiClpSolverInterface* s = new OsiClpSolverInterface();
87  s->getModelPtr()->setMaximumSeconds(tmax_);
88  return s;
89  } else {
90  throw ValueError("invalid SolverFactory type '" + t_ + "'");
91  }
92 }
93 
94 void ReportProg(OsiSolverInterface* si) {
95  const double* objs = si->getObjCoefficients();
96  const double* clbs = si->getColLower();
97  const double* cubs = si->getColUpper();
98  int ncol = si->getNumCols();
99  std::cout << "Column info\n";
100  for (int i = 0; i != ncol; i ++) {
101  std::cout << i
102  << " obj" << ": " << objs[i]
103  << " lb" << ": " << clbs[i]
104  << " ub" << ": " << cubs[i]
105  << " int" << ": " << std::boolalpha << si->isInteger(i) << '\n';
106  }
107 
108  const CoinPackedMatrix* m = si->getMatrixByRow();
109  const double* rlbs = si->getRowLower();
110  const double* rubs = si->getRowUpper();
111  int nrow = si->getNumRows();
112  std::cout << "Row info\n";
113  for (int i = 0; i != nrow; i ++) {
114  std::cout << i
115  << " lb" << ": " << rlbs[i]
116  << " ub" << ": " << rubs[i] << '\n';
117  }
118  std::cout << "matrix:\n";
119  m->dumpMatrix();
120 }
121 
122 void SolveProg(OsiSolverInterface* si, double greedy_obj, bool verbose) {
123  if (verbose)
124  ReportProg(si);
125 
126  if (HasInt(si)) {
127  const char *argv[] = {"exchng", "-log", "0", "-solve", "-quit"};
128  int argc = 5;
129  CbcModel model(*si);
130  ObjValueHandler handler(greedy_obj);
131  CbcMain0(model);
132  model.passInEventHandler(&handler);
133  CbcMain1(argc, argv, model, CbcCallBack);
134  si->setColSolution(model.getColSolution());
135  if (verbose) {
136  std::cout << "Greedy equivalent time: " << handler.time()
137  << " and obj " << handler.obj()
138  << " and found " << std::boolalpha << handler.found() << "\n";
139  }
140  } else {
141  // no ints, just solve 'initial lp relaxation'
142  si->initialSolve();
143  }
144 
145  if (verbose) {
146  const double* soln = si->getColSolution();
147  for (int i = 0; i != si->getNumCols(); i ++) {
148  std::cout << "soln " << i << ": " << soln[i]
149  << " integer: " << std::boolalpha << si->isInteger(i) << "\n";
150  }
151  }
152 }
153 
154 void SolveProg(OsiSolverInterface* si) {
155  SolveProg(si, si->getInfinity(), false);
156 }
157 
158 void SolveProg(OsiSolverInterface* si, bool verbose) {
159  SolveProg(si, si->getInfinity(), verbose);
160 }
161 
162 void SolveProg(OsiSolverInterface* si, double greedy_obj) {
163  SolveProg(si, greedy_obj, false);
164 }
165 
166 bool HasInt(OsiSolverInterface* si) {
167  int i = 0;
168  for (i = 0; i != si->getNumCols(); i++) {
169  if (si->isInteger(i)) {
170  return true;
171  }
172  }
173  return false;
174 }
175 
176 } // namespace cyclus
ObjValueHandler(double obj, double time, bool found)
An event handler that records the time that a better solution is found.
For values that are too big, too small, etc.
Definition: error.h:41
SolverFactory()
currently supported solver types are &#39;clp&#39; and &#39;cbc&#39;
virtual CbcEventHandler * clone()
virtual CbcEventHandler::CbcAction event(CbcEvent e)
ObjValueHandler & operator=(const ObjValueHandler &other)
int CbcCallBack(CbcModel *model, int from)
this is taken exactly from driver4.cpp in the Cbc examples
double time() const
OsiSolverInterface * get()
get the configured solver
bool HasInt(OsiSolverInterface *si)
taken directly from OsiSolverInterface.cpp on 2/17/14 from https://projects.coin-or.org/Osi/browser/trunk.
Definition: agent.cc:14
void ReportProg(OsiSolverInterface *si)
#define CYCLUS_SOLVER_TIMEOUT
void SolveProg(OsiSolverInterface *si, double greedy_obj, bool verbose)