BCP_lp_generate_cuts.cpp
Go to the documentation of this file.
1 // Copyright (C) 2000, International Business Machines
2 // Corporation and others. All Rights Reserved.
3 #include "CoinTime.hpp"
4 
5 #include "BCP_lp_functions.hpp"
6 #include "BCP_enum.hpp"
7 #include "BCP_lp_result.hpp"
8 #include "BCP_lp_pool.hpp"
9 #include "BCP_lp_user.hpp"
10 #include "BCP_lp.hpp"
11 #include "BCP_lp_node.hpp"
12 
14  bool varset_changed, const bool from_repricing)
15 {
16  double time0 = CoinCpuTime();
17 
18  BCP_lp_result& lpres = *p.lp_result;
20  int prev_size = cp.size();
21 
22  if (prev_size > 0 && ! cp.rows_are_valid()){
23  // we must regenerate the rows from the constraints
24  // first delete the old rows then expand the cuts again
25 
26  // these will hold cuts and rows expanded from the cuts
27  BCP_vec<BCP_cut*> cuts;
28  BCP_vec<BCP_row*> rows;
29 
30  cuts.reserve(prev_size);
31  int i;
32  for (i = 0; i < prev_size; ++i) {
33  cp[i]->delete_row();
34  cuts.unchecked_push_back(cp[i]->cut());
35  }
36  // now expand
37  rows.reserve(prev_size);
38  p.user->cuts_to_rows(p.node->vars, cuts, rows,
39  lpres, BCP_Object_Leftover, false);
40  for (i = 0; i < prev_size; ++i) {
41  cp[i]->set_row(rows[i]);
42  }
43  rows.clear();
44  }
45  cp.rows_are_valid(true);
46 
48  printf("LP: Number of leftover cuts: %i\n", prev_size);
49 
50  // Generate cuts within the LP process
51  BCP_vec<BCP_cut*> new_cuts;
52  BCP_vec<BCP_row*> new_rows;
54  new_cuts = p.new_cuts;
55  new_rows = p.new_rows;
56  p.new_cuts.clear();
57  p.new_rows.clear();
58  } else {
59  p.user->generate_cuts_in_lp(lpres, p.node->vars, p.node->cuts,
60  new_cuts, new_rows);
61  }
62  if (new_cuts.size() > 0) {
63  const int new_size = new_cuts.size();
64  if (new_rows.size() != 0) {
65  if (static_cast<int>(new_rows.size()) != new_size) {
66  throw BCP_fatal_error("\
67 LP: uneven new_cuts/new_rows sizes in generate_cuts_in_lp().\n");
68  }
69  } else {
70  // expand the generated cuts
71  new_rows.reserve(new_size);
72  p.user->cuts_to_rows(p.node->vars, new_cuts, new_rows,
73  lpres, BCP_Object_FromGenerator, false);
74  }
75 
76  cp.reserve(cp.size() + new_size);
77  for (int i = 0; i < new_size; ++i) {
78  new_cuts[i]->set_bcpind(-BCP_lp_next_cut_index(p));
79  cp.unchecked_push_back(new BCP_lp_waiting_row(new_cuts[i],
80  new_rows[i]));
81  }
82  new_rows.clear();
83  new_cuts.clear();
85  printf("LP: Number of cuts generated in the LP process: %i\n",
86  new_size);
87  prev_size = cp.size();
88  }
89 
90  // Compute the violation for everything in the local cut pool and throw out
91  // the ones not violated
92  if (prev_size > 0) {
93  cp.compute_violations(lpres, cp.begin(), cp.end());
94  double petol = 0.0;
95  p.lp_solver->getDblParam(OsiPrimalTolerance, petol);
96  const int cnt = cp.remove_nonviolated(petol);
98  printf("LP: Non-violated (hence removed): %i\n", cnt);
99  prev_size = cp.size();
100  }
101 
103  // If the message passing environment is not really parallel (i.e.,
104  // while the CG/CP are working the LP stops and also the LP must
105  // immediately process any cuts sent back then this is the place to
106  // send the lp solution to the CG/CP.
107  // send the current solution to CG, and also to CP if we are either
108  // - at the beginning of a chain (but not in the root in the
109  // first phase)
110  // - or this is the cut_pool_check_freq-th iteration.
111  if (p.node->cg != -1 || p.node->cp != -1) {
112  const BCP_message_tag msgtag = BCP_lp_pack_for_cg(p);
113  if (p.node->cg != -1) {
114  ++p.no_more_cuts_cnt;
115  p.msg_env->send(p.node->cg, msgtag, p.msg_buf);
116  }
117  if (p.node->cp != -1) {
118  if (! (p.node->iteration_count %
120  || varset_changed) {
121  ++p.no_more_cuts_cnt;
122  p.msg_env->send(p.node->cp, msgtag, p.msg_buf);
123  }
124  }
125  }
126  }
127 
128  if (p.no_more_cuts_cnt > 0){
129  // Receive cuts if we have sent out the lp solution somewhere.
130  // set the timeout (all the times are in microseconds).
131  double first_cut_time_out = varset_changed ?
134  double all_cuts_time_out = varset_changed ?
137  double tout = cp.size() == 0 ? first_cut_time_out : all_cuts_time_out;
138  double tin = CoinCpuTime();
139 
140  while(true){
141  p.msg_buf.clear();
143  p.msg_buf, tout);
144  if (p.msg_buf.msgtag() == BCP_Msg_NoMessage){
145  // check that everyone is still alive
146  if (! p.msg_env->alive(p.get_parent() /*tree_manager*/))
147  throw BCP_fatal_error("\
148 LP: The TM has died -- LP exiting\n");
149  if (p.node->cg != -1 && ! p.msg_env->alive(p.node->cg))
150  throw BCP_fatal_error("\
151 LP: The CG has died -- LP exiting\n");
152  if (p.node->cp != -1 && ! p.msg_env->alive(p.node->cp))
153  throw BCP_fatal_error("\
154 LP: The CP has died -- LP exiting\n");
155  if (p.node->vg != -1 && ! p.msg_env->alive(p.node->vg))
156  throw BCP_fatal_error("\
157 LP: The VG has died -- LP exiting\n");
158  if (p.node->vp != -1 && ! p.msg_env->alive(p.node->vp))
159  throw BCP_fatal_error("\
160 LP: The VP has died -- LP exiting\n");
161  // now the message queue is empty and received_message has
162  // returned, i.e., we have waited enough
164  printf("LP: Receive cuts timed out after %f secs\n",
165  (prev_size != static_cast<int>(cp.size()) ?
166  all_cuts_time_out : first_cut_time_out));
167  break;
168  }
169  p.process_message();
170  // break out if no more cuts can come
171  if (p.no_more_cuts_cnt == 0)
172  break;
173 
174  // reset the timeout
175  tout = cp.size() == 0 ? first_cut_time_out : all_cuts_time_out;
176  if (tout >= 0){
177  // with this tout we'll read out the rest of the message queue
178  // even if cut generation times out.
179  tout = std::max<double>(0.0, tout - (CoinCpuTime() - tin));
180  }
181  }
182  }
183  // reset no_more_cuts_cnt to 0
184  p.no_more_cuts_cnt = 0;
185 
187  printf("LP: Number of cuts received from CG: %i\n",
188  static_cast<int>(cp.size() - prev_size));
189  printf("LP: Total number of cuts in local pool: %i\n",
190  static_cast<int>(cp.size()));
191  }
192 
193  if (cp.size() > 0) {
194  const int oldsize = cp.size();
195  double petol = 0.0;
196  p.lp_solver->getDblParam(OsiPrimalTolerance, petol);
197  const int cnt = cp.remove_nonviolated(petol);
198  if (cnt > 0) {
199  printf("\
200 LP: *WARNING*: There are nonviolated cuts in the local CP\n\
201  at the end of cut generation.\n\
202  Discarding %i cuts out of %i.\n", cnt, oldsize);
203  }
204  }
205 
206  p.stat.time_cut_generation += CoinCpuTime() - time0;
207 
208  return cp.size();
209 }
This and the following three parameters control how long the LP process waits for generated cuts...
BCP_message_tag
This enumerative constant describes the message tags different processes of BCP understand.
virtual void send(const int target, const BCP_message_tag tag)=0
Send an empty message (message tag only) to the process given by the frist argument.
Used when receiving, message with any message tag will be received.
BCP_lp_node * node
Description he current search tree node.
Definition: BCP_lp.hpp:168
Used to indicate that there is no message in the buffer of a process.
virtual void receive(const int source, const BCP_message_tag tag, BCP_buffer &buf, const double timeout)=0
Blocking receive with timeout.
void clear()
Delete every entry.
char param(BCP_lp_par::chr_params key) const
Definition: BCP_lp.hpp:275
const int BCP_AnyProcess
Definition: BCP_message.hpp:21
BCP_var_set vars
BCP_lp_statistics stat
Definition: BCP_lp.hpp:213
int remove_nonviolated(const double etol)
Definition: BCP_lp_pool.cpp:14
Indicates whether message passing is serial (all processes are on the same processor) or not...
virtual void process_message()
iterator begin()
Return an iterator to the beginning of the object.
Definition: BCP_vector.hpp:99
NO OLD DOC.
Definition: BCP_lp.hpp:102
void reserve(const size_t n)
Reallocate the object to make space for n entries.
BCP_cut_set cuts
Print the current number of cuts in the cut pool.
int no_more_cuts_cnt
Definition: BCP_lp.hpp:226
BCP_lp_cut_pool * local_cut_pool
Definition: BCP_lp.hpp:193
int BCP_lp_next_cut_index(BCP_lp_prob &p)
BCP_lp_user * user
A class that holds the methods about how to pack things.
Definition: BCP_lp.hpp:131
The object was left over in the local variable or cut pool of the LP process from the previous iterat...
Definition: BCP_enum.hpp:252
bool rows_are_valid() const
Definition: BCP_lp_pool.hpp:59
OsiSolverInterface * lp_solver
A class that holds the methods about how to pack things.
Definition: BCP_lp.hpp:137
BCP_lp_result * lp_result
Definition: BCP_lp.hpp:185
This parameter specifies the time to wait for cuts at iterations that are not the first at a search t...
void compute_violations(const BCP_lp_result &lpres, BCP_lp_cut_pool::iterator first, BCP_lp_cut_pool::iterator last)
Definition: BCP_lp_pool.hpp:62
int get_parent() const
Definition: BCP_process.hpp:25
int BCP_lp_generate_cuts(BCP_lp_prob &p, bool first_in_loop, const bool from_repricing)
This parameter specifies the time to wait for cuts at the first LP relaxation at a search tree node...
void clear()
Completely clear the buffer.
Definition: BCP_buffer.hpp:168
BCP_message_tag msgtag() const
Return the message tag of the message in the buffer.
Definition: BCP_buffer.hpp:90
bool user_has_lp_result_processing
Definition: BCP_lp.hpp:244
Currently there isn&#39;t any error handling in BCP.
Definition: BCP_error.hpp:20
virtual void cuts_to_rows(const BCP_vec< BCP_var * > &vars, BCP_vec< BCP_cut * > &cuts, BCP_vec< BCP_row * > &rows, const BCP_lp_result &lpres, BCP_object_origin origin, bool allow_multiple)
Convert (and possibly lift) a set of cuts into corresponding rows for the current LP relaxation...
The object was generated by a variable or cut generator.
Definition: BCP_enum.hpp:257
size_t size() const
Return the current number of entries.
Definition: BCP_vector.hpp:116
virtual void generate_cuts_in_lp(const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, BCP_vec< BCP_cut * > &new_cuts, BCP_vec< BCP_row * > &new_rows)
Generate cuts within the LP process.
iterator end()
Return an iterator to the end of the object.
Definition: BCP_vector.hpp:104
BCP_message_tag BCP_lp_pack_for_cg(BCP_lp_prob &p)
Definition: BCP_lp_misc.cpp:75
void unchecked_push_back(const_reference x)
Append x to the end of the vector.
This parameter specifies the time to wait for the first generated cut at iterations that are not the ...
BCP_vec< BCP_cut * > new_cuts
Definition: BCP_lp.hpp:245
The Cut Pool is queried for violated valid inequalities after the first LP relaxation is solved and t...
BCP_message_environment * msg_env
A class that holds the methods about how to pack things.
Definition: BCP_lp.hpp:139
This class holds the results after solving an LP relaxation.
BCP_vec< BCP_row * > new_rows
Definition: BCP_lp.hpp:246
virtual bool alive(const int pid)=0
Test if the process given by the argument is alive or not.
double time_cut_generation
Definition: BCP_lp.hpp:61
BCP_buffer msg_buf
Definition: BCP_lp.hpp:239
Print information if receiving cuts is timed out.