BCP_lp_fathom.cpp
Go to the documentation of this file.
1 // Copyright (C) 2000, International Business Machines
2 // Corporation and others. All Rights Reserved.
3 #include <numeric>
4 
5 #include "CoinHelperFunctions.hpp"
6 #include "CoinSort.hpp"
7 
8 #include "BCP_matrix.hpp"
9 #include "BCP_lp_node.hpp"
10 #include "BCP_lp_pool.hpp"
11 #include "BCP_lp.hpp"
12 #include "BCP_lp_user.hpp"
13 #include "BCP_lp_result.hpp"
14 #include "BCP_lp_functions.hpp"
15 
16 //#############################################################################
17 
18 void
20 {
22  // Here we don't have col/row_indices to compress, we are from fathom and
23  // we do want to force deletion.
25  BCP_lp_delete_cols_and_rows(p, 0, 0, 0, true, true);
26  }
27  BCP_lp_send_node_description(p, 0, msgtag);
29 }
30 
31 //#############################################################################
32 
33 // the primal is infeas when this function is called. Still, we must first try
34 // to achive TDF, before trying to restore feasibility.
35 
36 bool BCP_lp_fathom(BCP_lp_prob& p, const bool from_repricing)
37 {
38  BCP_lp_result& lpres = *p.lp_result;
39 
40  int i, j;
41  int added_size = 0;
42  int vars_to_add_size = 0;
43  const int max_var = p.param(BCP_lp_par::MaxVarsAddedPerIteration);
44 
45  switch (p.node->colgen) {
47  BCP_lp_perform_fathom(p, "LP: Pruning node\n",
48  lpres.termcode() & BCP_ProvenPrimalInf ?
51  return true;
52 
54  BCP_lp_perform_fathom(p, "LP: Sending node for next phase\n",
55  lpres.termcode() & BCP_ProvenPrimalInf ?
58  return true;
59 
61  BCP_lp_check_ub(p);
63  printf("LP: Generating columns before fathoming/resolving\n");
64  BCP_vec<BCP_col*> cols_to_add;
65  BCP_vec<BCP_var*> vars_to_add;
66  if (lpres.termcode() & BCP_ProvenPrimalInf) { //############ infeasible
67  // *FIXME* : change the hardcoded 10 into a parameter
68  std::vector<double*> dual_rays = p.lp_solver->getDualRays(10);
69  if (dual_rays.size() > 0) {
70  BCP_restore_feasibility(p, dual_rays, vars_to_add, cols_to_add);
71  for (i = dual_rays.size() - 1; i >= 0; --i) {
72  delete[] dual_rays[i];
73  }
74  } else {
75  throw BCP_fatal_error("\
76 BCP_lp_fathom(): infeasible but can't get a dual ray!\n");
77  }
78  vars_to_add_size = vars_to_add.size();
79  if (vars_to_add_size == 0) {
80  // Nothing helps...
82 LP: Fathoming node (discovered not restorable inf.)\n",
84  return true;
85  } else {
86  // Great, we can fix infeasibility:
87  for (i = 0; i < vars_to_add_size; ++i) {
88  vars_to_add[i]->set_bcpind(-BCP_lp_next_var_index(p));
89  }
90  BCP_lp_add_cols_to_lp(cols_to_add, p.lp_solver);
91  purge_ptr_vector(cols_to_add);
92  p.node->vars.append(vars_to_add);
95  printf("LP: %i variables added while restoring feasibility\n",
96  static_cast<int>(vars_to_add.size()));
97  // need not delete the entries in vars_to_add one-by-one; those
98  // pointers are appended to p.node->variables
99  // Here we don't have col/row_indices to compress, we say we
100  // are not from fathom ('cos we do add columns, i.e., we are
101  // not going to fathom the node after the call returns) and we
102  // don't want to force deletion.
103  BCP_lp_delete_cols_and_rows(p, 0, 0, 0, false, false);
104  return false;
105  }
106  } else { //########################################### over upper bound
107  BCP_price_vars(p, true /*from fathom*/, vars_to_add, cols_to_add);
108  if (vars_to_add.size() == 0) {
109  // we can fathom!
111 LP: Fathoming node (discovered tdf & high cost)\n",
113  return true;
114  }
115  // keep only the best so many to add
116  if (max_var < vars_to_add_size) {
117  // reorder the generated variables (and the corresponding
118  // columns) based on the reduced costs of the columns
119  const double * duals = p.lp_result->pi();
120  BCP_vec<double> rc(vars_to_add_size, 0.0);
121  for (i = 0; i < vars_to_add_size; ++i) {
122  rc[i] = (cols_to_add[i]->Objective() -
123  cols_to_add[i]->dotProduct(duals));
124  }
125  BCP_vec<int> perm;
126  perm.reserve(vars_to_add_size);
127  for (i = 0; i < vars_to_add_size; ++i)
128  perm.unchecked_push_back(i);
129  CoinSort_2(rc.begin(), rc.end(), perm.begin());
130  const double rc_cutoff = rc[max_var];
131  CoinSort_2(perm.begin(), perm.end(), rc.begin());
132  for (i = 0, j = 0; i < vars_to_add_size; ++i) {
133  if (rc[i] <= rc_cutoff) {
134  perm[j++] = i;
135  }
136  }
137  perm.erase(perm.entry(j), perm.end());
138  // those in perm are to be kept
139  keep_ptr_vector_by_index(vars_to_add, perm.begin(),perm.end());
140  keep_ptr_vector_by_index(cols_to_add, perm.begin(),perm.end());
141  // cols_to_add.keep_by_index(perm); // this was wrong
142  }
143 
144  // Just add the given colums and go back to resolve
145  added_size = vars_to_add.size();
146  for (i = 0; i < added_size; ++i){
147  vars_to_add[i]->set_bcpind(-BCP_lp_next_var_index(p));
148  }
149  BCP_lp_add_cols_to_lp(cols_to_add, p.lp_solver);
150  purge_ptr_vector(cols_to_add);
151  p.node->vars.append(vars_to_add);
152  p.local_cut_pool->rows_are_valid(false);
154  printf("LP: %i variables added in price-out (not TDF :-( )\n",
155  static_cast<int>(vars_to_add.size()));
156  // need not delete the entries in vars_to_add one-by-one; those
157  // pointers are appended to p.node->variables.
158  // Here we don't have col/row_indices to compress, we say we are
159  // not from fathom ('cos we do add columns, i.e., we are not going
160  // to fathom the node after the call returns) and we don't want
161  // to force deletion.
162  BCP_lp_delete_cols_and_rows(p, 0, 0, 0, false, false);
163  return false;
164  }
165  break;
166  }
167 
168  return true; // fake return
169 }
170 
171 //#############################################################################
172 
173 void
174 BCP_price_vars(BCP_lp_prob& p, const bool from_fathom,
175  BCP_vec<BCP_var*>& vars_to_add, BCP_vec<BCP_col*>& cols_to_add)
176 {
177  const BCP_lp_result& lpres = *p.lp_result;
178 
179  bool generated_algo_var = false;
180  const size_t to_add = vars_to_add.size();
182  vars_to_add.append(p.new_vars);
183  cols_to_add.append(p.new_cols);
184  p.new_vars.clear();
185  p.new_cols.clear();
186  } else {
187  p.user->generate_vars_in_lp(lpres, p.node->vars, p.node->cuts,
188  from_fathom, vars_to_add, cols_to_add);
189  }
190  if (vars_to_add.size() > to_add) {
191  generated_algo_var = true;
192  if (cols_to_add.size() > to_add) {
193  if (cols_to_add.size() != vars_to_add.size()) {
194  throw BCP_fatal_error("\
195 LP: uneven new_vars/new_cols sizes in BCP_price_vars().\n");
196  }
197  } else {
198  // expand the generated vars
199  BCP_vec<BCP_var*> new_vars(vars_to_add.begin() + to_add,
200  vars_to_add.end());
201  BCP_vec<BCP_col*> new_cols;
202  p.user->vars_to_cols(p.node->cuts, new_vars, new_cols,
203  lpres, BCP_Object_FromGenerator, false);
204  cols_to_add.insert(cols_to_add.end(),
205  new_cols.begin(), new_cols.end());
206  }
207  }
208 }
209 
210 //#############################################################################
211 
212 void
214  const std::vector<double*> dual_rays,
215  BCP_vec<BCP_var*>& vars_to_add,
216  BCP_vec<BCP_col*>& cols_to_add)
217 {
218  // Now try to restore feasibility with algo vars
219  // now we want to pass only the uncut dual rays, so collect them
220  const size_t to_add = vars_to_add.size();
221  p.user->restore_feasibility(*p.lp_result, dual_rays,
222  p.node->vars, p.node->cuts,
223  vars_to_add, cols_to_add);
224  if (vars_to_add.size() > to_add) {
225  if (cols_to_add.size() > to_add) {
226  if (cols_to_add.size() != vars_to_add.size()) {
227  throw BCP_fatal_error("\
228 LP: uneven new_vars/new_cols sizes in BCP_restore_feasibility().\n");
229  }
230  } else {
231  // expand the generated vars
232  BCP_vec<BCP_var*> new_vars(vars_to_add.begin() + to_add,
233  vars_to_add.end());
234  BCP_vec<BCP_col*> new_cols;
235  p.user->vars_to_cols(p.node->cuts, new_vars, new_cols,
237  false);
238  cols_to_add.insert(cols_to_add.end(),
239  new_cols.begin(), new_cols.end());
240  }
241  }
242 }
int BCP_lp_send_node_description(BCP_lp_prob &p, BCP_presolved_lp_brobj *brobj, BCP_message_tag msgtag)
BCP_message_tag
This enumerative constant describes the message tags different processes of BCP understand.
BCP_lp_node * node
Description he current search tree node.
Definition: BCP_lp.hpp:168
void print(const bool ifprint, const char *format,...) const
A method to print a message with the process id.
Definition: BCP_lp_user.cpp:38
void clear()
Delete every entry.
char param(BCP_lp_par::chr_params key) const
Definition: BCP_lp.hpp:275
int BCP_lp_next_var_index(BCP_lp_prob &p)
Do not generate columns, but send back the node to the Tree Manager for processing in the next phase...
Definition: BCP_enum.hpp:70
bool BCP_lp_fathom(BCP_lp_prob &p, const bool from_repricing)
BCP_var_set vars
void BCP_lp_add_cols_to_lp(const BCP_vec< BCP_col * > &cols, OsiSolverInterface *lp)
The lower bound corresponding to the node is above the upper bound.
virtual void generate_vars_in_lp(const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, const bool before_fathom, BCP_vec< BCP_var * > &new_vars, BCP_vec< BCP_col * > &new_cols)
Generate variables within the LP process.
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.
void BCP_price_vars(BCP_lp_prob &p, const bool from_fathom, BCP_vec< BCP_var * > &vars_to_add, BCP_vec< BCP_col * > &cols_to_add)
Print the number of variables generated before resolving the Lp ir fathoming a node.
void BCP_lp_perform_fathom(BCP_lp_prob &p, const char *msg, BCP_message_tag msgtag)
void BCP_restore_feasibility(BCP_lp_prob &p, const std::vector< double * > dual_rays, BCP_vec< BCP_var * > &vars_to_add, BCP_vec< BCP_col * > &cols_to_add)
static char * j
Definition: OSdtoa.cpp:3622
BCP_vec< BCP_var * > new_vars
Definition: BCP_lp.hpp:247
Attempt column generation.
Definition: BCP_enum.hpp:73
BCP_cut_set cuts
virtual void restore_feasibility(const BCP_lp_result &lpres, const std::vector< double * > dual_rays, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, BCP_vec< BCP_var * > &vars_to_add, BCP_vec< BCP_col * > &cols_to_add)
Restoring feasibility.
Whether to send back the description of fathomed search tree nodes to the Tree Manager.
virtual void vars_to_cols(const BCP_vec< BCP_cut * > &cuts, BCP_vec< BCP_var * > &vars, BCP_vec< BCP_col * > &cols, const BCP_lp_result &lpres, BCP_object_origin origin, bool allow_multiple)
Convert a set of variables into corresponding columns for the current LP relaxation.
BCP_lp_cut_pool * local_cut_pool
Definition: BCP_lp.hpp:193
void erase(iterator pos)
Erase the entry pointed to by pos.
BCP_lp_user * user
A class that holds the methods about how to pack things.
Definition: BCP_lp.hpp:131
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
The maximum number of variables that can be added per iteration.
void insert(iterator position, const void *first, const size_t num)
Insert num entries starting from memory location first into the vector from position pos...
The lower bound corresponding to the node is above the upper bound.
Print information related to fathoming.
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
void BCP_lp_check_ub(BCP_lp_prob &p)
void BCP_lp_clean_up_node(BCP_lp_prob &p)
Definition: BCP_lp_misc.cpp:59
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
iterator end()
Return an iterator to the end of the object.
Definition: BCP_vector.hpp:104
BCP_column_generation colgen
Do fathom the node.
Definition: BCP_enum.hpp:67
const double * pi() const
void keep_ptr_vector_by_index(BCP_vec< T * > &pvec, typename BCP_vec< int >::const_iterator first, typename BCP_vec< int >::const_iterator last)
This function keeps only the entries indexed by [first,last) from the vector of pointers pvec...
Definition: BCP_vector.hpp:316
void unchecked_push_back(const_reference x)
Append x to the end of the vector.
void purge_ptr_vector(BCP_vec< T * > &pvec, typename BCP_vec< T * >::iterator first, typename BCP_vec< T * >::iterator last)
This function purges the entries [first,last) from the vector of pointers pvec.
Definition: BCP_vector.hpp:266
void append(const BCP_vec< BCP_var * > &x)
Append the variables in the vector x to the end of the variable set.
Definition: BCP_var.hpp:342
int termcode() const
This class holds the results after solving an LP relaxation.
iterator entry(const int i)
Return an iterator to the i-th entry.
Definition: BCP_vector.hpp:109
void BCP_lp_delete_cols_and_rows(BCP_lp_prob &p, BCP_lp_branching_object *can, const int added_colnum, const int added_rownum, const bool from_fathom, const bool force_delete)
void append(const BCP_vec< T > &x)
Append the entries in x to the end of the vector.
Definition: BCP_vector.hpp:169
BCP_vec< BCP_col * > new_cols
Definition: BCP_lp.hpp:248
The node is infeasible.