BM_tm.cpp
Go to the documentation of this file.
1 // (C) Copyright International Business Machines Corporation 2006, 2007
2 // All Rights Reserved.
3 // This code is published under the Eclipse Public License.
4 //
5 // Authors :
6 // Laszlo Ladanyi, International Business Machines Corporation
7 // Pierre Bonami, Carnegie Mellon University
8 
9 #include "OsiClpSolverInterface.hpp"
10 
11 #include "BCP_problem_core.hpp"
12 #include "BCP_tm.hpp"
13 #include "BCP_lp.hpp"
14 
15 // #include "BonIpoptSolver.hpp"
16 // #ifdef COIN_HAS_FILTERSQP
17 // # include "BonFilterSolver.hpp"
18 // #endif
19 // #include "BonOACutGenerator2.hpp"
20 // #include "BonEcpCuts.hpp"
21 // #include "BonOaNlpOptim.hpp"
22 #include "BonAmplSetup.hpp"
23 
24 #include "BM.hpp"
25 
26 //#############################################################################
27 
28 void
30 {
31  if (par.entry(BM_par::IpoptParamfile).length() != 0) {
32  FILE* ipopt = fopen(par.entry(BM_par::IpoptParamfile).c_str(), "r");
33  if (!ipopt) {
34  throw BCP_fatal_error("Non-existent IpoptParamfile\n");
35  }
36  fseek(ipopt, 0, SEEK_END);
37  int len = ftell(ipopt) + 1;
38  fseek(ipopt, 0, SEEK_SET);
39  char* ipopt_content = new char[len+1];
40  len = fread(ipopt_content, 1, len, ipopt);
41  ipopt_file_content.assign(ipopt_content, len);
42  delete[] ipopt_content;
43  }
44 
45  FILE* nl = fopen(par.entry(BM_par::NL_filename).c_str(), "r");
46  if (!nl) {
47  throw BCP_fatal_error("Non-existent NL_filename\n");
48  }
49  fseek(nl, 0, SEEK_END);
50  int len = ftell(nl) + 1;
51  fseek(nl, 0, SEEK_SET);
52  char* nl_content = new char[len+1];
53  len = fread(nl_content, 1, len, nl);
54  nl_file_content.assign(nl_content, len);
55  delete[] nl_content;
56 }
57 
58 /****************************************************************************/
59 
60 void
63  BCP_lp_relax*& matrix)
64 {
65  char* argv_[3];
66  char** argv = argv_;
67  argv[0] = NULL;
68  argv[1] = strdup(par.entry(BM_par::NL_filename).c_str());
69  argv[2] = NULL;
70 
71  /* Get the basic options. */
74  bonmin.initialize(argv);
75 
76  free(argv[1]);
77 
79 #if defined(BM_DISREGARD_SOS)
80  const Bonmin::TMINLP::SosInfo * sos = nlp.model()->sosConstraints();
81  if (sos->num > 0) {
82  printf("There are SOS constraints... disregarding them...\n");
83  }
84 #endif
85 
86  OsiSolverInterface& clp = *bonmin.continuousSolver();
87 
88  const int numCols = clp.getNumCols();
89  const int numRows = clp.getNumRows();
90 
91  const double* clb = clp.getColLower();
92  const double* cub = clp.getColUpper();
93 
94  double* obj = new double[numCols];
95  if (bonmin.getAlgorithm() == Bonmin::B_BB /* pure B&B */) {
96  std::cout<<"Doing branch and bound"<<std::endl;
97  CoinFillN(obj, numCols, 0.0);
98  matrix = NULL;
99  } else {
100  std::cout<<"Doing hybrid"<<std::endl;
101  CoinDisjointCopyN(clp.getObjCoefficients(), numCols, obj);
102  cuts.reserve(numRows);
103  const double* rlb = clp.getRowLower();
104  const double* rub = clp.getRowUpper();
105  for (int i = 0; i < numRows; ++i) {
106  cuts.push_back(new BCP_cut_core(rlb[i], rub[i]));
107  }
108  matrix = new BCP_lp_relax(true /*column major ordered*/);
109  matrix->copyOf(*clp.getMatrixByCol(), obj, clb, cub, rlb, rub);
110  }
111 
112  vars.reserve(numCols);
113  for (int i = 0; i < numCols; ++i) {
115  if (clp.isBinary(i)) type = BCP_BinaryVar;
116  if (clp.isInteger(i)) type = BCP_IntegerVar;
117  vars.push_back(new BCP_var_core(type, obj[i], clb[i], cub[i]));
118  }
119  delete[] obj;
120 
121  /* Initialize pseudocosts */
122  int nObj = 0;
123  for (int i = 0; i < numCols; ++i) {
124  if (nlp.isInteger(i)) {
125  ++nObj;
126  }
127  }
128 #if ! defined(BM_DISREGARD_SOS)
129  const Bonmin::TMINLP::SosInfo * sos = nlp.model()->sosConstraints();
130  nObj += sos->num;
131 #endif
132  pseudoCosts_.initialize(nObj);
133 }
134 
135 /****************************************************************************/
136 void
138  BCP_vec<BCP_cut*>& added_cuts,
139  BCP_user_data*& user_data)
140 {
141  BM_node* data = new BM_node;
142  data->numNlpFailed_ = 0;
143  user_data = data;
144 }
145 
146 void
148  bool write_file, bool write_screen)
149 {
150  const BCP_solution_generic* bg =
151  dynamic_cast<const BCP_solution_generic*>(sol);
152 
153  /* Parse again the input file so that we have a nice and clean ampl
154  setup */
155  char* argv_[3];
156  char** argv = argv_;
157  argv[0] = NULL;
158  argv[1] = strdup(par.entry(BM_par::NL_filename).c_str());
159  argv[2] = NULL;
161  bonmin.initialize(argv);
162 
163  Bonmin::OsiTMINLPInterface& nlpSolver = *bonmin.nonlinearSolver();
164  free(argv[1]);
165  OsiSolverInterface& clp = *bonmin.continuousSolver();
166 
167  const int numCols = clp.getNumCols();
168 
169  int i;
170 
171  /* Create a dense vector with the value of each variable. Round the
172  integer vars (they were tested to be near enough to integrality) so
173  in the printouts we won't have 9.99999991234, etc.) */
174  double* dsol = new double[numCols];
175  for (i = 0; i < numCols; ++i) {
176  dsol[i] = 0.0;
177  }
178  const BCP_vec<BCP_var*>& vars = bg->_vars;
179  const BCP_vec<double>& values = bg->_values;;
180  const int size = vars.size();
181  for (i = 0; i < size; ++i) {
182  const int ind = vars[i]->bcpind();
183  const double v = values[i];
184  const BCP_var_t type = vars[i]->var_type();
185  dsol[ind] = (type == BCP_ContinuousVar) ? v : floor(v+0.5);
186  }
187 
188  if (write_screen) {
189  /* Display the solution on the screen */
190  printf("bonmin: feasible solution found. Objective value: %f\n",
191  bg->objective_value());
192  for (i = 0; i < size; ++i) {
193  printf(" index: %5i value: %f\n",
194  vars[i]->bcpind(), dsol[vars[i]->bcpind()]);
195  }
196  printf("\n");
197  }
198 
199  if (write_file) {
200  /* create the AMPL solfile */
201  nlpSolver.model()->finalize_solution(Bonmin::TMINLP::SUCCESS, nlpSolver.getNumCols(),
202  dsol, bg->objective_value());
203  }
204  delete[] dsol;
205 }
206 
207 //#############################################################################
208 
209 void
211 {
212  int msgtag;
213  buf.unpack(msgtag);
214  if (msgtag == BM_PseudoCostUpdate) {
216  }
217 }
218 
219 /****************************************************************************/
220 
221 void
223 {
224  bool write_screen = false;
227  printf("TM: Running time: %.3f\n", CoinWallclockTime() - p->start_time);
228  printf("TM: search tree size: %i ( processed %i ) max depth: %i\n",
229  int(p->search_tree.size()), int(p->search_tree.processed()),
230  p->search_tree.maxdepth());
231  lp_stat.display();
232 
233  if (! p->feas_sol) {
234  printf("TM: No feasible solution is found\n");
235  } else {
236  printf("TM: The best solution found has value %f\n",
237  p->feas_sol->objective_value());
239  write_screen = true;
240  }
241  }
242  }
243  if (p->feas_sol) {
244  write_AMPL_solution(p->feas_sol, true, write_screen);
245  }
246 }
247 
248 /****************************************************************************/
249 
250 void
252 {
253  // For now, we want to write also the AMPL solution file...(?)
254  // This needs to be changed though
255  write_AMPL_solution(sol, true, true);
256 }
257 
259  static const std::string compName;
260  static inline const char* name() { return "BMSearchTreeCompareBest"; }
261  inline bool operator()(const CoinTreeSiblings* x,
262  const CoinTreeSiblings* y) const {
263  double allowable_gap = 1e-8;
264  const double xq = x->currentNode()->getQuality();
265  const double yq = y->currentNode()->getQuality();
266  const int xd = x->currentNode()->getDepth();
267  const int yd = y->currentNode()->getDepth();
268  return ((xq < yq-allowable_gap) ||
269  (xq <= yq+allowable_gap && xd > yd));
270  }
271 };
272 
273 const std::string
274 BMSearchTreeCompareBest::compName("BMSearchTreeCompareBest");
275 
276 void
278  BCP_column_generation& colgen,
279  CoinSearchTreeBase*& candidates)
280 {
284  case BCP_BestFirstSearch:
285  candidates = new CoinSearchTree<BMSearchTreeCompareBest>;
286  printf("Creating candidate list with BMSearchTreeCompareBest\n");
287  break;
289  candidates = new CoinSearchTree<CoinSearchTreeCompareBreadth>;
290  printf("Creating candidate list with CoinSearchTreeCompareBreadth\n");
291  break;
293  candidates = new CoinSearchTree<CoinSearchTreeCompareDepth>;
294  printf("Creating candidate list with CoinSearchTreeCompareDepth\n");
295  break;
297  candidates = new CoinSearchTree<CoinSearchTreeComparePreferred>;
298  printf("Creating candidate list with CoinSearchTreeComparePreferred\n");
299  break;
300  }
301 }
302 
303 //#############################################################################
304 
305 void
307 {
308  double* upTotalChange = pseudoCosts_.upTotalChange();
309  double* downTotalChange = pseudoCosts_.downTotalChange();
310  int* upNumber = pseudoCosts_.upNumber();
311  int* downNumber = pseudoCosts_.downNumber();
312  int objInd;
313  int branch;
314  double pcChange;
315  while (true) {
316  buf.unpack(objInd);
317  if (objInd == -1) {
318  break;
319  }
320  buf.unpack(branch);
321  buf.unpack(pcChange);
322  if (branch == 0) {
323  downTotalChange[objInd] += pcChange;
324  ++downNumber[objInd];
325  } else {
326  upTotalChange[objInd] += pcChange;
327  ++upNumber[objInd];
328  }
329  }
330 }
331 
332 //-----------------------------------------------------------------------------
333 
334 void
336 {
337  buf.pack(pseudoCosts_.upTotalChange(), pseudoCosts_.numberObjects());
338  buf.pack(pseudoCosts_.upNumber(), pseudoCosts_.numberObjects());
339  buf.pack(pseudoCosts_.downTotalChange(), pseudoCosts_.numberObjects());
340  buf.pack(pseudoCosts_.downNumber(), pseudoCosts_.numberObjects());
341 }
Binary (0-1) variable.
Definition: BCP_enum.hpp:163
BCP_tree search_tree
Definition: BCP_tm.hpp:239
double * values
void initialize(char **&argv)
initialize bonmin with ampl model using the command line arguments.
virtual void display_feasible_solution(const BCP_solution *sol)
Print a feasible solution.
Definition: BM_tm.cpp:251
BCP_buffer & pack(const T &value)
Pack a single object of type T.
Definition: BCP_buffer.hpp:177
Definition: BM.hpp:26
virtual void create_root(BCP_vec< BCP_var * > &added_vars, BCP_vec< BCP_cut * > &added_cuts, BCP_user_data *&user_data)
Create the set of extra variables and cuts that should be added to the formulation in the root node...
Definition: BM_tm.cpp:137
BCP_buffer & unpack(T &value)
Unpack a single object of type T.
Definition: BCP_buffer.hpp:186
virtual double objective_value() const =0
The method returning the objective value of the solution.
int num
Number of SOS constraints.
Definition: BonTMINLP.hpp:75
BCP_vec< BCP_var * > _vars
Vector of variables that are at nonzero level in the solution.
double start_time
Definition: BCP_tm.hpp:203
virtual void process_message(BCP_buffer &buf)
Process a message that has been sent by another process&#39; user part to this process&#39; user part...
Definition: BM_tm.cpp:210
This is class provides an Osi interface for a Mixed Integer Linear Program expressed as a TMINLP (so ...
void pack_pseudo_costs(BCP_buffer &buf)
Definition: BM_tm.cpp:335
virtual bool isInteger(int columnNumber) const
Return true if column is integer.
virtual const SosInfo * sosConstraints() const =0
void write_AMPL_solution(const BCP_solution *sol, bool write_file, bool write_screen)
auxilliary method for handling output for AMPL
Definition: BM_tm.cpp:147
char entry(const chr_params key) const
static const std::string compName
Definition: BM_tm.cpp:259
size_t size() const
int processed() const
Core cuts are the cuts that always stay in the LP formulation.
Definition: BCP_cut.hpp:195
Class to store sos constraints for model.
Definition: BonTMINLP.hpp:72
BCP_solution * feas_sol
Definition: BCP_tm.hpp:163
void reserve(const size_t n)
Reallocate the object to make space for n entries.
NO OLD DOC.
Definition: BCP_lp.hpp:56
BCP_vec< double > _values
Values of these variables in the solution.
virtual int getNumCols() const
Get number of columns.
Core variables are the variables that always stay in the LP formulation.
Definition: BCP_var.hpp:230
void push_back(const_reference x)
Append x to the end of the vector.
BCP_string & assign(const char *source, const int len)
Definition: BCP_string.hpp:48
void copyOf(const CoinPackedMatrix &m, const double *OBJ, const double *CLB, const double *CUB, const double *RLB, const double *RUB)
Set up the LP relaxation by making a copy of the arguments.
Definition: BCP_matrix.cpp:69
void fint fint fint real fint real real real real real real real real real * e
Bonmin::Algorithm getAlgorithm()
Get the algorithm used.
BCP_tm_prob * p
Definition: BCP_tm_user.hpp:60
int numNlpFailed_
A counter for how many times in a row did the NLP code fail.
Definition: BM.hpp:32
virtual void finalize_solution(TMINLP::SolverReturn status, Ipopt::Index n, const Ipopt::Number *x, Ipopt::Number obj_value)=0
This method is called when the algorithm is complete so the TNLP can store/write the solution...
Which search tree enumeration strategy should be used.
static const char * name()
Definition: BM_tm.cpp:260
void fint fint fint * phase
int maxdepth() const
NO OLD DOC.
Definition: BCP_tm.hpp:136
virtual void init_new_phase(int phase, BCP_column_generation &colgen, CoinSearchTreeBase *&candidates)
Do whatever initialization is necessary before the phase-th phase.
Definition: BM_tm.cpp:277
Continuous variable.
Definition: BCP_enum.hpp:167
Currently there isn&#39;t any error handling in BCP.
Definition: BCP_error.hpp:20
virtual void display_final_information(const BCP_lp_statistics &lp_stat)
Output the final solution.
Definition: BM_tm.cpp:222
BCP_string ipopt_file_content
Definition: BM.hpp:175
void display() const
Print out the statistics.
Definition: BCP_lp.cpp:39
size_t size() const
Return the current number of entries.
Definition: BCP_vector.hpp:116
Invoke &quot;display_feasible_solution&quot; user routine for the best feasible solution after the entire tree ...
bool operator()(const CoinTreeSiblings *x, const CoinTreeSiblings *y) const
Definition: BM_tm.cpp:261
virtual double objective_value() const
Return the objective value of the solution.
Do fathom the node.
Definition: BCP_enum.hpp:67
This class describes the message buffer used for all processes of BCP.
Definition: BCP_buffer.hpp:39
BCP_parameter_set< BM_par > par
Definition: BM.hpp:177
OsiTMINLPInterface * nonlinearSolver()
Pointer to the non-linear solver used.
BCP_tm_prob * getTmProblemPointer() const
Get the pointer.
Definition: BCP_tm_user.hpp:71
OsiSolverInterface * continuousSolver()
Pointer to the continuous solver to use for relaxations.
Print statistics: running time, tree size, best solution value.
BCP_column_generation
This enumerative constant describes what to do when a search tree node becomes fathomable for the cur...
Definition: BCP_enum.hpp:65
void receive_pseudo_cost_update(BCP_buffer &buf)
Definition: BM_tm.cpp:306
This class holds a MIP feasible primal solution.
virtual void readOptionsFile()
Get the options from default text file (bonmin.opt) if don&#39;t already have them.
char param(BCP_tm_par::chr_params key) const
Definition: BCP_tm.hpp:298
General integer variable.
Definition: BCP_enum.hpp:165
An object of type BCP_lp_relax holds the description of an lp relaxation.
Definition: BCP_matrix.hpp:267
OsiPseudoCosts pseudoCosts_
Definition: BM.hpp:178
virtual void initialize_core(BCP_vec< BCP_var_core * > &vars, BCP_vec< BCP_cut_core * > &cuts, BCP_lp_relax *&matrix)
Pass the core constraints and core variables to bcp.
Definition: BM_tm.cpp:61
BCP_var_t
This enumerative constant describes the integrality type of a variable.
Definition: BCP_enum.hpp:161
void readIpopt()
Definition: BM_tm.cpp:29
void fint fint fint real fint real * x
This is the abstract base class for a solution to a Mixed Integer Programming problem.
BCP_string nl_file_content
Definition: BM.hpp:176