#include <BCP_lp_user.hpp>
Public Member Functions | |
virtual OsiSolverInterface * | initialize_solver_interface () |
virtual void | initialize_new_search_tree_node (const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, const BCP_vec< BCP_obj_status > &var_status, const BCP_vec< BCP_obj_status > &cut_status, BCP_vec< int > &var_changed_pos, BCP_vec< double > &var_new_bd, BCP_vec< int > &cut_changed_pos, BCP_vec< double > &cut_new_bd) |
virtual void | modify_lp_parameters (OsiSolverInterface *lp, bool in_strong_branching) |
virtual double | compute_lower_bound (const double old_lower_bound, const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts) |
virtual BCP_solution * | generate_heuristic_solution (const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &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) |
virtual void | select_vars_to_delete (const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, const bool before_fathom, BCP_vec< int > &deletable) |
virtual void | select_cuts_to_delete (const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, const bool before_fathom, BCP_vec< int > &deletable) |
void | reduced_cost_fixing (const double *dj, const double *x, const double gap, BCP_vec< BCP_var * > &vars, int &newly_changed) |
virtual BCP_branching_object_relation | compare_branching_candidates (BCP_presolved_lp_brobj *new_solved, BCP_presolved_lp_brobj *old_solved) |
virtual void | set_actions_for_children (BCP_presolved_lp_brobj *best) |
virtual void | set_user_data_for_children (BCP_presolved_lp_brobj *best, const int selected) |
virtual void | set_user_data_for_children (BCP_presolved_lp_brobj *best) |
Methods to set and get the pointer to the BCP_lp_prob | |
object. It is unlikely that the users would want to muck around with these (especially with the set method!) but they are here to provide total control. | |
void | setLpProblemPointer (BCP_lp_prob *ptr) |
Set the pointer. | |
BCP_lp_prob * | getLpProblemPointer () |
Get the pointer. | |
Informational methods for the user. | |
double | upper_bound () const |
Return what is the best known upper bound (might be DBL_MAX). | |
int | current_phase () const |
Return the phase the algorithm is in. | |
int | current_level () const |
Return the level of the search tree node being processed. | |
int | current_index () const |
Return the internal index of the search tree node being processed. | |
int | current_iteration () const |
Return the iteration count within the search tree node being processed. | |
BCP_user_data * | get_user_data () |
Methods to get/set BCP parameters on the fly | |
char | get_param (const BCP_lp_par::chr_params key) const |
int | get_param (const BCP_lp_par::int_params key) const |
double | get_param (const BCP_lp_par::dbl_params key) const |
const BCP_string & | get_param (const BCP_lp_par::str_params key) const |
void | set_param (const BCP_lp_par::chr_params key, const bool val) |
void | set_param (const BCP_lp_par::chr_params key, const char val) |
void | set_param (const BCP_lp_par::int_params key, const int val) |
void | set_param (const BCP_lp_par::dbl_params key, const double val) |
void | set_param (const BCP_lp_par::str_params key, const char *val) |
A methods to send a solution to the Tree Manager. The user can | |
invoke this method at any time to send off a solution. | |
void | send_feasible_solution (const BCP_solution *sol) |
Constructor, Destructor | |
virtual | ~BCP_lp_user () |
Helper functions for selecting subset of entries from a double | |
vector. The indices (their position with respect to first ) of the variables satisfying the criteria are returned in the last argument. | |
void | select_nonzeros (const double *first, const double *last, const double etol, BCP_vec< int > &nonzeros) const |
void | select_zeros (const double *first, const double *last, const double etol, BCP_vec< int > &zeros) const |
void | select_positives (const double *first, const double *last, const double etol, BCP_vec< int > &positives) const |
void | select_fractions (const double *first, const double *last, const double etol, BCP_vec< int > &fractions) const |
Packing and unpacking methods | |
virtual void | unpack_module_data (BCP_buffer &buf) |
Methods that pack/unpack warmstart, var_algo and cut_algo objects. | |
The packing methods take an object and a buffer as an argument and the user is supposed to pack the object into the buffer.
The argument of the unpacking methods is just the buffer. The user is supposed to return a pointer to the unpacked object. | |
virtual void | pack_warmstart (const BCP_warmstart *ws, BCP_buffer &buf) |
virtual BCP_warmstart * | unpack_warmstart (BCP_buffer &buf) |
virtual void | pack_var_algo (const BCP_var_algo *var, BCP_buffer &buf) |
virtual BCP_var_algo * | unpack_var_algo (BCP_buffer &buf) |
virtual void | pack_cut_algo (const BCP_cut_algo *cut, BCP_buffer &buf) |
virtual BCP_cut_algo * | unpack_cut_algo (BCP_buffer &buf) |
virtual void | pack_user_data (const BCP_user_data *ud, BCP_buffer &buf) |
virtual BCP_user_data * | unpack_user_data (BCP_buffer &buf) |
MIP feasibility testing of LP solutions and heuristics | |
virtual BCP_solution * | test_feasibility (const BCP_lp_result &lp_result, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts) |
Helper functions for <code>test_feasibility</code>. If the | |
solution is feasible a pointer to a BCP_solution_generic object is returned. Note that the solutions generated by these helper functions DO NOT OWN the pointers in the _vars member of the solution. | |
BCP_solution_generic * | test_binary (const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const double etol) const |
BCP_solution_generic * | test_integral (const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const double etol) const |
BCP_solution_generic * | test_full (const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const double etol) const |
Packing of solutions | |
virtual void | pack_feasible_solution (BCP_buffer &buf, const BCP_solution *sol) |
virtual void | pack_primal_solution (BCP_buffer &buf, const BCP_lp_result &lp_result, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts) |
virtual void | pack_dual_solution (BCP_buffer &buf, const BCP_lp_result &lp_result, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts) |
Displaying of LP solutions | |
virtual void | display_lp_solution (const BCP_lp_result &lp_result, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, const bool final_lp_solution) |
Methods related to indexed variables. These methods must be | |
overridden if and only if BCP is supposed to track the indexed variables yet to be priced out, i.e., if the parameter MaintainIndexedVarPricingList is set to true. | |
virtual int | next_indexed_var (int prev_index) |
virtual BCP_var_indexed * | create_indexed_var (int index, const BCP_vec< BCP_cut * > &cuts, BCP_col &col) |
Converting cuts and variables into rows and columns | |
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) |
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) |
Generating cuts and variables | |
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) |
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) |
virtual BCP_object_compare_result | compare_cuts (const BCP_cut *c0, const BCP_cut *c1) |
virtual BCP_object_compare_result | compare_vars (const BCP_var *v0, const BCP_var *v1) |
Logical fixing | |
virtual void | logical_fixing (const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, const BCP_vec< BCP_obj_status > &var_status, const BCP_vec< BCP_obj_status > &cut_status, const int var_bound_changes_since_logical_fixing, BCP_vec< int > &changed_pos, BCP_vec< double > &new_bd) |
Branching related methods | |
virtual BCP_branching_decision | select_branching_candidates (const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, const BCP_lp_var_pool &local_var_pool, const BCP_lp_cut_pool &local_cut_pool, BCP_vec< BCP_lp_branching_object * > &cands) |
Helper functions for select_branching_candidates() | |
void | branch_close_to_half (const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const int to_be_selected, const double etol, BCP_vec< BCP_lp_branching_object * > &candidates) |
void | branch_close_to_one (const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const int to_be_selected, const double etol, BCP_vec< BCP_lp_branching_object * > &candidates) |
void | append_branching_vars (const double *x, const BCP_vec< BCP_var * > &vars, const BCP_vec< int > &select_pos, BCP_vec< BCP_lp_branching_object * > &candidates) |
Purging the slack pool | |
virtual void | purge_slack_pool (const BCP_vec< BCP_cut * > &slack_pool, BCP_vec< int > &to_be_purged) |
Private Attributes | |
bool | using_deprecated_set_user_data_for_children |
BCP_lp_prob * | p |
In that derived class the user can store data to be used in the methods she overrides. Also that is the object the user must return in the USER_initialize::lp_init() method.
There are two kind of methods in the class. The non-virtual methods are helper functions for the built-in defaults, but the user can use them as well. The virtual methods execute steps in the BCP algorithm where the user might want to override the default behavior.
The default implementations fall into three major categories.
Definition at line 72 of file BCP_lp_user.hpp.
|
Being virtual, the destructor invokes the destructor for the real type of the object being deleted. Definition at line 138 of file BCP_lp_user.hpp.
00138 {} |
|
This helper method creates branching variable candidates and appends them to Definition at line 1081 of file BCP_lp_user.cpp. References BCP_vec< T >::begin(), BCP_vec< T >::end(), and BCP_vec< T >::push_back(). Referenced by branch_close_to_half(), and branch_close_to_one().
01085 { 01086 BCP_vec<int>::const_iterator spi; 01087 BCP_vec<double> vbd(4, 0.0); 01088 BCP_vec<int> vpos(1, 0); 01089 01090 for (spi = select_pos.begin(); spi != select_pos.end(); ++spi) { 01091 const int pos = *spi; 01092 vpos[0] = pos; 01093 vbd[0] = vars[pos]->lb(); 01094 vbd[1] = floor(x[pos]); 01095 vbd[2] = ceil(x[pos]); 01096 vbd[3] = vars[pos]->ub(); 01097 cans.push_back 01098 (new BCP_lp_branching_object(2, 01099 0, 0, /* vars/cuts_to_add */ 01100 &vpos, 0, &vbd, 0, /* forced parts */ 01101 0, 0, 0, 0 /* implied parts */)); 01102 } 01103 } |
|
Select the "close-to-half" variables for strong branching. Variables that are at least Definition at line 906 of file BCP_lp_user.cpp. References append_branching_vars(), BCP_vec< T >::begin(), BCP_vec< T >::clear(), BCP_vec< T >::end(), BCP_vec< T >::entry(), BCP_vec< T >::erase(), BCP_vec< T >::index(), BCP_vec< T >::insert(), BCP_lp_prob::lp_solver, BCP_vec< T >::pop_back(), BCP_vec< T >::reserve(), BCP_vec< T >::size(), BCP_vec< T >::swap(), and BCP_lp_result::x(). Referenced by select_branching_candidates().
00911 { 00912 // order the variables based on their distance from a MIP feasible value 00913 const double etol5 = .5 - etol; 00914 BCP_vec<BCP_var*>::const_iterator vi = vars.begin(); 00915 const double * x = lpres.x(); 00916 const double * xi = x; 00917 const double * lastxi = x + vars.size(); 00918 00919 // choose 5 times the required ones (ordered primarily by closeness to half 00920 // and secondarily by cost) 00921 int to_select = 5*to_be_selected; 00922 00923 BCP_vec<int> select_pos(to_select + 1, -1); 00924 BCP_vec<double> select_val(to_select + 1, 1.0); 00925 BCP_vec<double> select_cost(to_select + 1, -1e20); 00926 00927 const double* objcoeff = p->lp_solver->getObjCoefficients(); 00928 00929 double val; 00930 int pos, i, k; 00931 00932 for (pos = 0, k = 0; k < to_select && xi != lastxi; ++pos, ++xi, ++vi){ 00933 // check if the next var violates MIP feasibility 00934 if ((*vi)->var_type() == BCP_ContinuousVar) 00935 continue; 00936 val = CoinAbs(*xi - .5 - floor(*xi)); 00937 if (val > etol5) 00938 continue; 00939 // if not, insert it into the list 00940 const double cost = CoinAbs(objcoeff[pos]); 00941 for (i = k - 1; i >= 0; --i) { 00942 if (select_val[i] < val || 00943 (select_val[i] == val && select_cost[i] >= cost)) 00944 break; 00945 select_pos[i+1] = select_pos[i]; 00946 select_val[i+1] = select_val[i]; 00947 select_cost[i+1] = select_cost[i]; 00948 } 00949 select_pos[i+1] = pos; 00950 select_val[i+1] = val; 00951 select_cost[i+1] = cost; 00952 ++k; 00953 } 00954 00955 for ( ; xi != lastxi; ++pos, ++xi, ++vi) { 00956 // check if the next var violates MIP feasibility 00957 if ((*vi)->var_type() == BCP_ContinuousVar) 00958 continue; 00959 val = CoinAbs(*xi - .5 - floor(*xi)); 00960 if (val > etol5) 00961 continue; 00962 // if not, insert it into the list 00963 const double cost = objcoeff[pos]; 00964 for (i = to_select - 1; i >= 0; --i) { 00965 if (select_val[i] < val || 00966 (select_val[i] == val && select_cost[i] >= cost)) 00967 break; 00968 select_pos[i+1] = select_pos[i]; 00969 select_val[i+1] = select_val[i]; 00970 select_cost[i+1] = select_cost[i]; 00971 } 00972 if (i != to_select - 1) { 00973 select_pos[i+1] = pos; 00974 select_val[i+1] = val; 00975 select_cost[i+1] = cost; 00976 } 00977 } 00978 00979 k = select_val.index(std::upper_bound(select_val.begin(), 00980 select_val.entry(k), 00981 2 * select_val[to_be_selected - 1])); 00982 00983 select_pos.erase(select_pos.entry(k), select_pos.end()); 00984 select_cost.erase(select_cost.entry(k), select_cost.end()); 00985 00986 // now reorder these and keep only as many as required. this time order by 00987 // cost alone. 00988 if (k > to_be_selected) { 00989 BCP_vec<double>::iterator di; 00990 BCP_vec<int> new_pos; 00991 new_pos.reserve(to_be_selected); 00992 BCP_vec<double>& new_cost = select_val; 00993 new_cost.clear(); 00994 for (pos = 0; pos < to_be_selected; ++pos) { 00995 const double val = select_cost[pos]; 00996 // insert the next into the list 00997 di = std::upper_bound(new_cost.begin(), new_cost.end(), val); 00998 new_pos.insert(new_pos.entry(new_cost.index(di)), select_pos[pos]); 00999 new_cost.insert(di, val); 01000 } 01001 for ( ; pos < k; ++pos) { 01002 const double val = select_cost[pos]; 01003 // insert the next into the list 01004 di = std::upper_bound(new_cost.begin(), new_cost.end(), val); 01005 if (di != new_cost.end()) { 01006 new_cost.pop_back(); 01007 new_pos.pop_back(); 01008 new_pos.insert(new_pos.entry(new_cost.index(di)), select_pos[pos]); 01009 new_cost.insert(di, val); 01010 } 01011 } 01012 select_pos.swap(new_pos); 01013 } 01014 01015 append_branching_vars(lpres.x(), vars, select_pos, cans); 01016 } |
|
Select the "close-to-one" variables for strong branching. Variables that are at least Definition at line 1019 of file BCP_lp_user.cpp. References append_branching_vars(), BCP_vec< T >::begin(), BCP_vec< T >::end(), BCP_vec< T >::entry(), BCP_vec< T >::index(), BCP_vec< T >::insert(), BCP_vec< T >::pop_back(), BCP_vec< T >::reserve(), BCP_vec< T >::size(), and BCP_lp_result::x(). Referenced by select_branching_candidates().
01024 { 01025 // order the variables based on their distance from a MIP feasible value 01026 BCP_vec<BCP_var*>::const_iterator vi = vars.begin(); 01027 const double * x = lpres.x(); 01028 const double * xi = x; 01029 const double * lastxi = x + vars.size(); 01030 01031 BCP_vec<int> select_pos; 01032 select_pos.reserve(to_be_selected); 01033 BCP_vec<double> select_val; 01034 select_val.reserve(to_be_selected); 01035 BCP_vec<double>::iterator spv; 01036 01037 double val; 01038 int pos; 01039 01040 for (pos = 0; 01041 select_pos.size() < static_cast<const size_t>(to_be_selected) && 01042 xi != lastxi; 01043 ++pos, ++xi, ++vi) { 01044 // check if the next var violates MIP feasibility 01045 if ((*vi)->var_type() == BCP_ContinuousVar) 01046 continue; 01047 if (*xi < etol) 01048 continue; 01049 val = 1 - *xi; 01050 if (val < etol) 01051 continue; 01052 // if not, insert it into the list 01053 spv = std::upper_bound(select_val.begin(), select_val.end(), val); 01054 select_pos.insert(select_pos.entry(select_val.index(spv)), pos); 01055 select_val.insert(spv, val); 01056 } 01057 01058 for ( ; xi != lastxi; ++pos, ++xi, ++vi) { 01059 // check if the next var violates MIP feasibility 01060 if ((*vi)->var_type() == BCP_ContinuousVar) 01061 continue; 01062 if (*xi < etol) 01063 continue; 01064 val = 1 - *xi; 01065 if (val < etol) 01066 continue; 01067 // if not, insert it into the list 01068 spv = std::upper_bound(select_val.begin(), select_val.end(), val); 01069 if (spv != select_val.end()) { 01070 select_pos.pop_back(); 01071 select_pos.insert(select_pos.entry(select_val.index(spv)), pos); 01072 select_val.pop_back(); 01073 select_val.insert(spv, val); 01074 } 01075 } 01076 01077 append_branching_vars(lpres.x(), vars, select_pos, cans); 01078 } |
|
Decide which branching object is preferred for branching.
Based on the member fields of the two presolved candidate branching objects decide which one should be preferred for really branching on it. Possible return values are: Definition at line 1107 of file BCP_lp_user.cpp. References BCP_vec< T >::begin(), BCP_vec< T >::end(), BCP_presolved_lp_brobj::fake_objective_values(), BCP_presolved_lp_brobj::fathomable(), BCP_presolved_lp_brobj::get_lower_bounds(), BCP_lp_prob::granularity(), BCP_presolved_lp_brobj::had_numerical_problems(), BCP_vec< T >::index(), BCP_lp_prob::lp_result, BCP_lp_result::objval(), BCP_lp_prob::param(), and BCP_lp_prob::ub().
01109 { 01110 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 01111 printf(" LP: Default compare_presolved_branching_objects() executed.\n"); 01112 } 01113 01114 // change the objvals according to the termcodes (in order to be able to 01115 // make decisions based on objval, no matter what the termcode is). 01116 new_presolved->fake_objective_values(p->lp_result->objval()); 01117 01118 // If using this branching object we can fathom all children, then choose 01119 // this object 01120 if (new_presolved->fathomable(p->ub() - p->granularity())) 01121 return(BCP_NewPresolvedIsBetter_BranchOnIt); 01122 01123 // If this is the first, keep it 01124 if (! old_presolved) 01125 return(BCP_NewPresolvedIsBetter); 01126 01127 // If something had gone wrong with at least one descendant in the new then 01128 // we prefer to keep the old. 01129 if (new_presolved->had_numerical_problems()) 01130 return(BCP_OldPresolvedIsBetter); 01131 01132 // OK, so all descendants finished just fine. Do whatever the parameter says 01133 01134 if (p->param(BCP_lp_par::BranchingObjectComparison) & BCP_Comparison_Objval){ 01135 const double objetol = 1e-7; 01136 01137 BCP_vec<double> new_obj; 01138 new_presolved->get_lower_bounds(new_obj); 01139 std::sort(new_obj.begin(), new_obj.end()); 01140 const int new_not_fathomed = 01141 new_obj.index(std::lower_bound(new_obj.begin(), new_obj.end(), 01142 DBL_MAX / 4)); 01143 01144 BCP_vec<double> old_obj; 01145 old_presolved->get_lower_bounds(old_obj); 01146 std::sort(old_obj.begin(), old_obj.end()); 01147 const int old_not_fathomed = 01148 old_obj.index(std::lower_bound(old_obj.begin(), old_obj.end(), 01149 DBL_MAX / 4)); 01150 01151 if (new_not_fathomed < old_not_fathomed) 01152 return BCP_NewPresolvedIsBetter; 01153 01154 if (new_not_fathomed > old_not_fathomed) 01155 return BCP_OldPresolvedIsBetter; 01156 01157 BCP_vec<double>::const_iterator new_first = new_obj.begin(); 01158 BCP_vec<double>::const_iterator new_last = new_obj.end(); 01159 BCP_vec<double>::const_iterator old_first = old_obj.begin(); 01160 BCP_vec<double>::const_iterator old_last = old_obj.end(); 01161 01162 switch(p->param(BCP_lp_par::BranchingObjectComparison)){ 01163 case BCP_LowestAverageObjval: 01164 case BCP_HighestAverageObjval: 01165 { 01166 double newavg = 0; 01167 for ( ; new_first != new_last; ++new_first) { 01168 if (*new_first < DBL_MAX / 4) 01169 newavg += *new_first; 01170 } 01171 newavg /= new_not_fathomed; 01172 double oldavg = 0; 01173 for ( ; old_first != old_last; ++old_first) { 01174 if (*old_first < DBL_MAX / 4) 01175 oldavg += *old_first; 01176 } 01177 oldavg /= old_not_fathomed; 01178 const bool high = (p->param(BCP_lp_par::BranchingObjectComparison) 01179 == BCP_HighestAverageObjval); 01180 return (high && newavg > oldavg) || (!high && newavg < oldavg) ? 01181 BCP_NewPresolvedIsBetter : BCP_OldPresolvedIsBetter; 01182 } 01183 01184 case BCP_LowestLowObjval: 01185 for ( ; new_first != new_last && old_first != old_last; 01186 ++new_first, ++old_first) { 01187 if (*new_first < *old_first - objetol) 01188 return BCP_NewPresolvedIsBetter; 01189 if (*new_first > *old_first + objetol) 01190 return BCP_OldPresolvedIsBetter; 01191 } 01192 return old_first == old_last ? 01193 BCP_OldPresolvedIsBetter : BCP_NewPresolvedIsBetter; 01194 01195 case BCP_HighestLowObjval: 01196 for ( ; new_first != new_last && old_first != old_last; 01197 ++new_first, ++old_first) { 01198 if (*new_first > *old_first + objetol) 01199 return BCP_NewPresolvedIsBetter; 01200 if (*new_first < *old_first - objetol) 01201 return BCP_OldPresolvedIsBetter; 01202 } 01203 return old_first == old_last ? 01204 BCP_OldPresolvedIsBetter : BCP_NewPresolvedIsBetter; 01205 01206 case BCP_LowestHighObjval: 01207 while (new_first != new_last && old_first != old_last) { 01208 --new_last; 01209 --old_last; 01210 if (*new_last < *old_last - objetol) 01211 return BCP_NewPresolvedIsBetter; 01212 if (*new_last > *old_last + objetol) 01213 return BCP_OldPresolvedIsBetter; 01214 } 01215 return old_first == old_last ? 01216 BCP_OldPresolvedIsBetter : BCP_NewPresolvedIsBetter; 01217 01218 case BCP_HighestHighObjval: 01219 while (new_first != new_last && old_first != old_last) { 01220 --new_last; 01221 --old_last; 01222 if (*new_last > *old_last + objetol) 01223 return BCP_NewPresolvedIsBetter; 01224 if (*new_last < *old_last - objetol) 01225 return BCP_OldPresolvedIsBetter; 01226 } 01227 return old_first == old_last ? 01228 BCP_OldPresolvedIsBetter : BCP_NewPresolvedIsBetter; 01229 default: 01230 throw BCP_fatal_error("Unknown branching object comparison rule.\n"); 01231 } 01232 } 01233 01234 // shouldn't ever get here 01235 throw BCP_fatal_error("No branching object comparison rule is chosen.\n"); 01236 01237 // fake return 01238 return BCP_NewPresolvedIsBetter; 01239 } |
|
Compare two generated cuts. Cuts are generated in different iterations, they come from the Cut Pool, etc. There is a very real possibility that the LP process receives several cuts that are either identical or one of them is better then another (cuts off everything the other cuts off). This routine is used to decide which one to keep if not both. Definition at line 704 of file BCP_lp_user.cpp. References BCP_lp_prob::param().
00705 { 00706 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00707 printf(" LP: Default compare_cuts() executed.\n"); 00708 } 00709 return BCP_DifferentObjs; 00710 } |
|
Compare two generated variables. Variables are generated in different iterations, they come from the Variable Pool, etc. There is a very real possibility that the LP process receives several variables that are either identical or one of them is better then another (e.g., almost identical but has much lower reduced cost). This routine is used to decide which one to keep if not both. Definition at line 713 of file BCP_lp_user.cpp. References BCP_lp_prob::param().
00714 { 00715 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00716 printf(" LP: Default compare_vars() executed.\n"); 00717 } 00718 return BCP_DifferentObjs; 00719 } |
|
Compute a true lower bound for the subproblem. In case column generation is done the lower bound for the subproblem might not be the same as the objective value of the current LP relaxation. Here the user has an option to return a true lower bound. Definition at line 245 of file BCP_lp_user.cpp. References BCP_lp_node::colgen, BCP_lp_prob::node, BCP_lp_result::objval(), BCP_lp_result::termcode(), and BCP_lp_prob::ub().
00249 { 00250 // If columns are to be generated then we can't say anything, just return 00251 // the current lower bound 00252 if (p->node->colgen != BCP_DoNotGenerateColumns_Fathom) 00253 return old_lower_bound; 00254 00255 // Otherwise we got the examine the termination code and the objective 00256 // value of the LP solution 00257 const int tc = lpres.termcode(); 00258 if (tc & BCP_ProvenOptimal) 00259 return lpres.objval(); 00260 00261 // The limit (the upper bound) on the dual objective is proven to be 00262 // reached, but the objval might not reflect this! (the LP solver may not 00263 // make the last iteration that pushes objval over the limit). So we return 00264 // a high value ourselves. 00265 if (tc & BCP_DualObjLimReached) 00266 return p->ub() + 1e-5; 00267 00268 // We can't say anything in any other case 00269 // (BCP_ProvenPrimalInf | BCP_ProvenDualInf | BCP_PrimalObjLimReached | 00270 // BCP_TimeLimit | BCP_Abandoned), not to mention that some of these are 00271 // impossible. Just return the current bound. 00272 return old_lower_bound; 00273 } |
|
Create the variable corresponding to the given Definition at line 618 of file BCP_lp_user.cpp. References BCP_lp_prob::param().
00621 { 00622 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00623 printf(" LP: Default create_indexed_var() executed.\n"); 00624 } 00625 throw BCP_fatal_error("create_indexed_var() missing.\n"); 00626 } |
|
Convert (and possibly lift) a set of cuts into corresponding rows for the current LP relaxation. Converting means computing for each cut the coefficients corresponding to each variable and creating BCP_row objects that can be added to the formulation. This method has different purposes depending on the value of the last argument. If multiple expansion is not allowed then the user must generate a unique row for each cut. This unique row must always be the same for any given cut. This kind of operation is needed so that an LP relaxation can be exactly recreated.
On the other hand if multiple expansion is allowed then the user has (almost) free reign over what she returns. She can delete some of the
Definition at line 647 of file BCP_lp_user.cpp. References BCP_lp_prob::param().
00654 { 00655 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00656 printf(" LP: Default cuts_to_rows() executed.\n"); 00657 } 00658 throw BCP_fatal_error("cuts_to_rows() missing.\n"); 00659 } |
|
Display the result of most recent LP optimization. This method is invoked every time an LP relaxation is optimized and the user can display (or not display) it.
Note that this method is invoked only if Default: display the solution if the appropriate verbosity code entry is set.
Definition at line 573 of file BCP_lp_user.cpp. References BCP_lp_prob::param(), select_nonzeros(), BCP_vec< T >::size(), and BCP_lp_result::x().
00577 { 00578 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00579 printf(" LP: Default display_lp_solution() executed.\n"); 00580 } 00581 00582 if (final_lp_solution) { 00583 if (! p->param(BCP_lp_par::LpVerb_FinalRelaxedSolution)) 00584 return; 00585 printf(" LP : Displaying LP solution (FinalRelaxedSolution) :\n"); 00586 } else { 00587 if (! p->param(BCP_lp_par::LpVerb_RelaxedSolution)) 00588 return; 00589 printf(" LP : Displaying LP solution (RelaxedSolution) :\n"); 00590 } 00591 00592 const double ietol = p->param(BCP_lp_par::IntegerTolerance); 00593 00594 printf(" LP : Displaying solution :\n"); 00595 BCP_vec<int> coll; 00596 const double * x = lpres.x(); 00597 select_nonzeros(x, x+vars.size(), ietol, coll); 00598 const int size = coll.size(); 00599 for (int i = 0; i < size; ++i) { 00600 const int ind = coll[i]; 00601 vars[ind]->display(x[ind]); 00602 } 00603 } |
|
Generate cuts within the LP process. Sometimes too much information would need to be transmitted for cut generation (e.g., the full tableau for Gomory cuts) or the cut generation is so fast that transmitting the info would take longer than generating the cuts. In such cases it might better to generate the cuts locally. This routine provides the opportunity.
Definition at line 679 of file BCP_lp_user.cpp. References BCP_lp_prob::param().
00684 { 00685 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00686 printf(" LP: Default generate_cuts_in_lp() executed.\n"); 00687 } 00688 } |
|
Try to generate a heuristic solution (or return one generated during cut/variable generation. Return a pointer to the generated solution or return a NULL pointer. Default: Return a NULL pointer Definition at line 442 of file BCP_lp_user.cpp. References BCP_lp_prob::param().
00445 { 00446 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00447 printf(" LP: Default generate_heuristic_solution() executed.\n"); 00448 } 00449 return NULL; 00450 } |
|
Generate variables within the LP process. Sometimes too much information would need to be transmitted for variable generation or the variable generation is so fast that transmitting the info would take longer than generating the variables. In such cases it might be better to generate the variables locally. This routine provides the opportunity. Default: empty method.
Definition at line 691 of file BCP_lp_user.cpp. References BCP_lp_prob::param().
00697 { 00698 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00699 printf(" LP: Default generate_vars_in_lp() executed.\n"); 00700 } 00701 } |
|
Return a pointer to the BCP_user_data structure the user (may have) stored in this node Definition at line 28 of file BCP_lp_user.cpp. References BCP_lp_prob::node, and BCP_lp_node::user_data.
|
|
Initializing a new search tree node. This method serves as hook for the user to do some preprocessing on a search tree node before the node is processed. Also, logical fixing results can be returned in the last four parameters. This might be very useful if the branching implies significant tightening.
Definition at line 217 of file BCP_lp_user.cpp. References BCP_lp_prob::param().
00225 { 00226 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00227 printf(" LP: Default initialize_new_search_tree_node() executed.\n"); 00228 } 00229 } |
|
Create LP solver environment. Create the LP solver class that will be used for solving the LP relaxations. The default implementation picks up which Definition at line 208 of file BCP_lp_user.cpp.
00209 { 00210 throw BCP_fatal_error("\ 00211 BCP_lp_user::initialize_solver_interface() invoked but not overridden!\n"); 00212 return 0; 00213 } |
|
This method provides an opportunity for the user to tighten the bounds of variables. The method is invoked after reduced cost fixing. The results are returned in the last two parameters.
Definition at line 773 of file BCP_lp_user.cpp. References BCP_lp_prob::param().
00781 { 00782 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00783 printf(" LP: Default logical_fixing() executed.\n"); 00784 } 00785 } |
|
Modify parameters of the LP solver before optimization. This method provides an opportunity for the user to change parameters of the LP solver before optimization in the LP solver starts. The second argument indicates whether the optimization is a "regular" optimization or it will take place in strong branching. Default: empty method. Definition at line 234 of file BCP_lp_user.cpp. References BCP_lp_prob::param().
00236 { 00237 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00238 printf(" LP: Default prepare_for_optimization() executed.\n"); 00239 } 00240 } |
|
Return the index of the indexed variable following Definition at line 609 of file BCP_lp_user.cpp. References BCP_lp_prob::param().
00610 { 00611 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00612 printf(" LP: Default next_indexed_var() executed.\n"); 00613 } 00614 return -1; 00615 } |
|
Pack an algorithmic cut Definition at line 175 of file BCP_lp_user.cpp.
00176 { 00177 throw BCP_fatal_error("\ 00178 BCP_lp_user::pack_cut_algo() invoked but not overridden!\n"); 00179 } |
|
Pack the information necessary for variable generation into the buffer. Note that the name of the method is pack_dual_solution because most likely that (or some part of that) will be needed for variable generation. However, if the user overrides the method she is free to pack anything (of course she'll have to unpack it in CG). This information will be sent to the Variable Generator (and possibly to the Variable Pool) where the user has to unpack it. If the user uses the built-in method here, then the built-in method will be used in the Variable Generator as well.
Default: The content of the message depends on the value of the
Definition at line 527 of file BCP_lp_user.cpp. References BCP_vec< T >::begin(), BCP_lp_result::dualTolerance(), BCP_vec< T >::end(), BCP_buffer::pack(), BCP_lp_prob::pack_cut(), BCP_lp_prob::param(), BCP_lp_result::pi(), BCP_vec< T >::reserve(), select_nonzeros(), BCP_buffer::set_msgtag(), BCP_vec< T >::size(), and BCP_vec< T >::unchecked_push_back().
00531 { 00532 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00533 printf(" LP: Default pack_for_vg() executed.\n"); 00534 } 00535 00536 BCP_vec<int> coll; 00537 00538 const double detol = lpres.dualTolerance(); 00539 const double * pi = lpres.pi(); 00540 const int cutnum = cuts.size(); 00541 00542 switch (p->param(BCP_lp_par::InfoForVG)){ 00543 case BCP_DualSolution_Nonzeros: 00544 select_nonzeros(pi, pi+cutnum, detol, coll); 00545 buf.set_msgtag(BCP_Msg_ForVG_DualNonzeros); 00546 break; 00547 case BCP_DualSolution_Full: 00548 coll.reserve(cutnum); 00549 for (int i = 0; i < cutnum; ++i) { 00550 coll.unchecked_push_back(i); 00551 } 00552 buf.set_msgtag(BCP_Msg_ForVG_DualFull); 00553 break; 00554 default: 00555 throw BCP_fatal_error("Incorrect msgtag in pack_lp_solution() !\n"); 00556 } 00557 00558 const int size = coll.size(); 00559 buf.pack(size); 00560 if (size > 0){ 00561 BCP_vec<int>::const_iterator pos = coll.begin() - 1; 00562 const BCP_vec<int>::const_iterator last_pos = coll.end(); 00563 while (++pos != last_pos) { 00564 buf.pack(pi[*pos]); 00565 p->pack_cut(BCP_ProcessType_Any, *cuts[*pos]); 00566 } 00567 } 00568 } |
|
Pack a MIP feasible solution into a buffer. The solution will be unpacked in the Tree Manager by the BCP_tm_user::unpack_feasible_solution() method.
Definition at line 454 of file BCP_lp_user.cpp. References BCP_solution_generic::_values, BCP_solution_generic::_vars, BCP_buffer::pack(), BCP_lp_prob::pack_var(), BCP_lp_prob::param(), and BCP_vec< T >::size().
00455 { 00456 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00457 printf(" LP: Default pack_feasible_solution() executed.\n"); 00458 } 00459 00460 const BCP_solution_generic* gensol = 00461 dynamic_cast<const BCP_solution_generic*>(sol); 00462 const BCP_vec<BCP_var*> solvars = gensol->_vars; 00463 const BCP_vec<double> values = gensol->_values; 00464 const int size = solvars.size(); 00465 buf.pack(size); 00466 for (int i = 0; i < size; ++i) { 00467 buf.pack(values[i]); 00468 p->pack_var(BCP_ProcessType_Any, *solvars[i]); 00469 } 00470 } |
|
Pack the information necessary for cut generation into the buffer. Note that the name of the method is pack_primal_solution because most likely that (or some part of that) will be needed for cut generation. However, if the user overrides the method she is free to pack anything (of course she'll have to unpack it in CG). This information will be sent to the Cut Generator (and possibly to the Cut Pool) where the user has to unpack it. If the user uses the built-in method here, then the built-in method will be used in the Cut Generator as well.
Default: The content of the message depends on the value of the
Definition at line 476 of file BCP_lp_user.cpp. References BCP_vec< T >::begin(), BCP_vec< T >::end(), BCP_buffer::pack(), BCP_lp_prob::pack_var(), BCP_lp_prob::param(), BCP_lp_result::primalTolerance(), BCP_vec< T >::reserve(), select_fractions(), select_nonzeros(), BCP_buffer::set_msgtag(), BCP_vec< T >::size(), BCP_vec< T >::unchecked_push_back(), and BCP_lp_result::x().
00480 { 00481 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00482 printf(" LP: Default pack_for_cg() executed.\n"); 00483 } 00484 00485 BCP_vec<int> coll; 00486 00487 const double petol = lpres.primalTolerance(); 00488 const double * x = lpres.x(); 00489 const int varnum = vars.size(); 00490 00491 switch (p->param(BCP_lp_par::InfoForCG)){ 00492 case BCP_PrimalSolution_Nonzeros: 00493 select_nonzeros(x, x + varnum, petol, coll); 00494 buf.set_msgtag(BCP_Msg_ForCG_PrimalNonzeros); 00495 break; 00496 case BCP_PrimalSolution_Fractions: 00497 select_fractions(x, x+varnum, petol, coll); 00498 buf.set_msgtag(BCP_Msg_ForCG_PrimalFractions); 00499 break; 00500 case BCP_PrimalSolution_Full: 00501 coll.reserve(varnum); 00502 for (int i = 0; i < varnum; ++i) { 00503 coll.unchecked_push_back(i); 00504 } 00505 buf.set_msgtag(BCP_Msg_ForCG_PrimalFull); 00506 break; 00507 default: 00508 throw BCP_fatal_error("Incorrect msgtag in pack_for_cg() !\n"); 00509 } 00510 00511 const int size = coll.size(); 00512 buf.pack(size); 00513 if (size > 0){ 00514 BCP_vec<int>::const_iterator pos = coll.begin() - 1; 00515 const BCP_vec<int>::const_iterator last_pos = coll.end(); 00516 while (++pos != last_pos) { 00517 buf.pack(x[*pos]); 00518 p->pack_var(BCP_ProcessType_Any, *vars[*pos]); 00519 } 00520 } 00521 } |
|
Pack an user data Definition at line 191 of file BCP_lp_user.cpp.
00192 { 00193 throw BCP_fatal_error("\ 00194 BCP_lp_user::pack_user_data() invoked but not overridden!\n"); 00195 } |
|
Pack an algorithmic variable Definition at line 159 of file BCP_lp_user.cpp.
00160 { 00161 throw BCP_fatal_error("\ 00162 BCP_lp_user::pack_var_algo() invoked but not overridden!\n"); 00163 } |
|
Pack warmstarting information Definition at line 137 of file BCP_lp_user.cpp. References BCP_lp_prob::param().
00138 { 00139 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00140 printf(" LP: Default BCP_lp_user::pack_warmstart() executed.\n"); 00141 } 00142 BCP_pack_warmstart(ws, buf); 00143 } |
|
Selectively purge the list of slack cuts.
When a cut becomes ineffective and is eventually purged from the LP formulation it is moved into
Default: Purges the slack cut pool according to the
Definition at line 1320 of file BCP_lp_user.cpp. References current_iteration(), BCP_lp_prob::param(), BCP_vec< T >::reserve(), BCP_vec< T >::size(), and BCP_vec< T >::unchecked_push_back().
01322 { 01323 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 01324 printf(" LP: Default purge_slack_pool() executed.\n"); 01325 } 01326 01327 switch (p->param(BCP_lp_par::SlackCutDiscardingStrategy)) { 01328 case BCP_DiscardSlackCutsAtNewNode: 01329 if (current_iteration() != 1) 01330 break; 01331 case BCP_DiscardSlackCutsAtNewIteration: 01332 { 01333 const int size = slack_pool.size(); 01334 if (size > 0) { 01335 to_be_purged.reserve(size); 01336 for (int i = 0; i < size; ++i) 01337 to_be_purged.unchecked_push_back(i); 01338 } 01339 } 01340 break; 01341 } 01342 } |
|
Reduced cost fixing. This is not exactly a helper function, but the user might want to invoke it... Definition at line 789 of file BCP_lp_user.cpp. References BCP_vec< T >::begin(), BCP_vec< T >::end(), BCP_var::is_fixed(), BCP_var::lb(), BCP_lp_prob::lp_solver, BCP_vec< T >::reserve(), BCP_var::set_lb(), BCP_var::set_ub(), BCP_vec< T >::size(), BCP_var::ub(), BCP_vec< T >::unchecked_push_back(), and BCP_var::var_type().
00792 { 00793 newly_changed = 0; 00794 const bool atZero = get_param(BCP_lp_par::DoReducedCostFixingAtZero); 00795 const bool atAny = get_param(BCP_lp_par::DoReducedCostFixingAtAnything); 00796 00797 if (! atZero && ! atAny) 00798 return; 00799 00800 double petol = 0.0; 00801 p->lp_solver->getDblParam(OsiPrimalTolerance, petol); 00802 00803 // If the gap is negative that means that we are above the limit, so 00804 // don't do anything. 00805 if (gap < 0) 00806 return; 00807 00808 const int varnum = vars.size(); 00809 BCP_vec<int> changed_indices; 00810 changed_indices.reserve(varnum); 00811 BCP_vec<double> changed_bounds; 00812 changed_bounds.reserve(2 * varnum); 00813 00814 // Note that when this function is called, we must have a dual 00815 // feasible dual solution. Therefore we can use the lagrangean 00816 // relaxation to fix variables. 00817 00818 // *FIXME* : If we knew that there are integral vars only, then 00819 // we could leave out the test for BCP_ContinuousVar... 00820 for (int i = 0; i < varnum; ++i) { 00821 BCP_var* var = vars[i]; 00822 if (! var->is_fixed() && var->var_type() != BCP_ContinuousVar){ 00823 if (dj[i] > 0) { 00824 const double lb = var->lb(); 00825 const double new_ub = lb + floor(gap / dj[i]); 00826 if (new_ub < var->ub() && (atAny || CoinAbs(x[i])<petol) ) { 00827 vars[i]->set_ub(new_ub); 00828 changed_indices.unchecked_push_back(i); 00829 changed_bounds.unchecked_push_back(lb); 00830 changed_bounds.unchecked_push_back(new_ub); 00831 } 00832 } else if (dj[i] < 0) { 00833 const double ub = var->ub(); 00834 const double new_lb = ub - floor(gap / (-dj[i])); 00835 if (new_lb > var->lb() && (atAny || CoinAbs(x[i])<petol) ) { 00836 vars[i]->set_lb(new_lb); 00837 changed_indices.unchecked_push_back(i); 00838 changed_bounds.unchecked_push_back(new_lb); 00839 changed_bounds.unchecked_push_back(ub); 00840 } 00841 } 00842 } 00843 } 00844 newly_changed = changed_indices.size(); 00845 if (newly_changed > 0) { 00846 p->lp_solver->setColSetBounds(changed_indices.begin(), 00847 changed_indices.end(), 00848 changed_bounds.begin()); 00849 } 00850 } |
|
Restoring feasibility. This method is invoked before fathoming a search tree node that has been found infeasible and the variable pricing did not generate any new variables. If the MaintainIndexedVarPricingList is set to true then BCP will take care of going through the indexed variables to see if any will restore feasibility and the user has to check only the algorithmic variables. Otherwise the user has to check all variables here. Definition at line 631 of file BCP_lp_user.cpp. References BCP_lp_prob::param().
00637 { 00638 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00639 printf(" LP: Default restore_feasibility() executed.\n"); 00640 } 00641 } |
|
Decide whether to branch or not and select a set of branching candidates if branching is decided upon. The return value indicates what should be done: branching, continuing with the same node or abandoning the node completely.
Default: Branch if both local pools are empty. If branching is done then several (based on the "Close-to-half" variables are those that should be integer and are at a fractional level. The measure of their fractionality is their distance from the closest integer. The most fractional variables will be selected, i.e., those that are close to half. If there are too many such variables then those with higher objective value have priority. "Close-to-on" is interpreted in a more literal sense. It should be used only if the integer variables are binary as it select those fractional variables which are away from 1 but are still close. If there are too many such variables then those with lower objective value have priority.
Definition at line 856 of file BCP_lp_user.cpp. References BCP_vec< T >::begin(), branch_close_to_half(), branch_close_to_one(), BCP_vec< T >::end(), BCP_lp_prob::param(), BCP_vec< T >::reserve(), BCP_vec< T >::size(), and BCP_vec< T >::unchecked_push_back().
00862 { 00863 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00864 printf(" LP: Default select_branching_candidates() executed.\n"); 00865 } 00866 00867 // *THINK* : this branching object selection is very primitive 00868 // *THINK* : should check for tail-off, could check for branching cuts, etc. 00869 if (local_var_pool.size() > 0 || local_cut_pool.size() > 0) 00870 return BCP_DoNotBranch; 00871 00872 if (p->param(BCP_lp_par::StrongBranch_CloseToHalfNum) > 0) 00873 branch_close_to_half(lpres, vars, 00874 p->param(BCP_lp_par::StrongBranch_CloseToHalfNum), 00875 p->param(BCP_lp_par::IntegerTolerance), 00876 cans); 00877 if (p->param(BCP_lp_par::StrongBranch_CloseToOneNum) > 0) 00878 branch_close_to_one(lpres, vars, 00879 p->param(BCP_lp_par::StrongBranch_CloseToOneNum), 00880 p->param(BCP_lp_par::IntegerTolerance), 00881 cans); 00882 // Get rid of duplicates in cans 00883 BCP_vec<int> brvars; 00884 brvars.reserve(cans.size()); 00885 for (size_t i = 0; i < cans.size(); ) { 00886 const int brvar = (*cans[i]->forced_var_pos)[0]; 00887 if (std::find(brvars.begin(), brvars.end(), brvar) == brvars.end()) { 00888 brvars.unchecked_push_back(brvar); 00889 ++i; 00890 } else { 00891 std::swap(cans[i], cans.back()); 00892 cans.pop_back(); 00893 } 00894 } 00895 00896 if (cans.size() == 0) { 00897 throw BCP_fatal_error("\ 00898 LP : No var/cut in pool but couldn't select branching object.\n"); 00899 } 00900 return BCP_DoBranch; 00901 } |
|
Select all fractional entries. Those are considered fractional that are further than Definition at line 113 of file BCP_lp_user.cpp. References BCP_vec< T >::reserve(), and BCP_vec< T >::unchecked_push_back(). Referenced by pack_primal_solution().
00115 { 00116 fractions.reserve(last - first); 00117 BCP_vec<double>::const_iterator current = first; 00118 for ( ; current != last; ++current) 00119 if (*current - floor(*current) >etol && ceil(*current) - *current >etol) 00120 fractions.unchecked_push_back(current - first); 00121 } |
|
Select all nonzero entries. Those are considered nonzero that have absolute value greater than Definition at line 83 of file BCP_lp_user.cpp. References BCP_vec< T >::reserve(), and BCP_vec< T >::unchecked_push_back(). Referenced by display_lp_solution(), pack_dual_solution(), and pack_primal_solution().
00085 { 00086 nonzeros.reserve(last - first); 00087 BCP_vec<double>::const_iterator current = first; 00088 for ( ; current != last; ++current) 00089 if (CoinAbs(*current) > etol) nonzeros.unchecked_push_back(current - first); 00090 } |
|
Select all positive entries. Those are considered positive that have value greater than Definition at line 103 of file BCP_lp_user.cpp. References BCP_vec< T >::reserve(), and BCP_vec< T >::unchecked_push_back().
00105 { 00106 positives.reserve(last - first); 00107 BCP_vec<double>::const_iterator current = first; 00108 for ( ; current != last; ++current) 00109 if (*current > etol) positives.unchecked_push_back(current - first); 00110 } |
|
Select all zero entries. Those are considered zero that have absolute value less than Definition at line 93 of file BCP_lp_user.cpp. References BCP_vec< T >::reserve(), and BCP_vec< T >::unchecked_push_back().
00095 { 00096 zeros.reserve(last - first); 00097 BCP_vec<double>::const_iterator current = first; 00098 for ( ; current != last; ++current) 00099 if (CoinAbs(*current) <= etol) zeros.unchecked_push_back(current - first); 00100 } |
|
Decide what to do with the children of the selected branching object. Fill out the
Default: Every action is THINK*: Should those children be sent back for processing in the next phase? Definition at line 1243 of file BCP_lp_user.cpp. References BCP_presolved_lp_brobj::action(), BCP_presolved_lp_brobj::candidate(), BCP_lp_branching_object::child_num, BCP_lp_node::dive, BCP_presolved_lp_brobj::lpres(), BCP_lp_prob::node, BCP_lp_result::objval(), BCP_lp_prob::over_ub(), and BCP_lp_prob::param().
01244 { 01245 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 01246 printf(" LP: Default set_actions_for_children() executed.\n"); 01247 } 01248 01249 // by default every action is set to BCP_ReturnChild 01250 if (p->node->dive == BCP_DoNotDive) 01251 return; 01252 01253 BCP_vec<BCP_child_action>& action = best->action(); 01254 int i, ind; 01255 01256 switch (p->param(BCP_lp_par::ChildPreference)){ 01257 case BCP_PreferChild_LowBound: 01258 // NOTE: if the lowest objval child is fathomed then everything is 01259 for (ind = 0, i = best->candidate()->child_num - 1; i > 0; --i){ 01260 if (best->lpres(i).objval() < best->lpres(ind).objval()) 01261 ind = i; 01262 } 01263 break; 01264 01265 case BCP_PreferChild_HighBound: 01266 // NOTE: this selects the highest objval child NOT FATHOMED, thus if 01267 // the highest objval child is fathomed then everything is 01268 for (ind = 0, i = best->candidate()->child_num - 1; i > 0; --i) { 01269 if (! p->over_ub(best->lpres(i).objval()) && 01270 best->lpres(i).objval() < best->lpres(ind).objval()) 01271 ind = i; 01272 } 01273 break; 01274 default: 01275 // *THINK* : fractional branching 01276 throw BCP_fatal_error("LP : Unrecognized child preference.\n"); 01277 } 01278 // mark the ind-th to be kept (if not over ub) 01279 if (! p->over_ub(best->lpres(ind).objval())) 01280 action[ind] = BCP_KeepChild; 01281 } |
|
Deprecated version of the previos method (it does not pass the index of the selected branching candidate). Definition at line 1309 of file BCP_lp_user.cpp. References BCP_lp_prob::param().
01310 { 01311 using_deprecated_set_user_data_for_children = false; 01312 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 01313 printf(" LP: Default set_user_data_for_children() executed.\n"); 01314 } 01315 } |
|
For each child create a user data object and put it into the appropriate entry in Definition at line 1286 of file BCP_lp_user.cpp.
01288 { 01289 using_deprecated_set_user_data_for_children = true; 01290 set_user_data_for_children(best); 01291 if (using_deprecated_set_user_data_for_children) { 01292 printf("\ 01293 *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***\n\ 01294 You have overridden\n\ 01295 BCP_lp_user::set_user_data_for_children(BCP_presolved_lp_brobj* best)\n\ 01296 which is a deprecated virtual function. Please override\n\ 01297 BCP_lp_user::set_user_data_for_children(BCP_presolved_lp_brobj* best,\n\ 01298 const int selected)\n\ 01299 instead. The old version will go away, your code will still compile, but it\n\ 01300 will not do what you intend it to be doing.\n\ 01301 *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***\n"\ 01302 ); 01303 } 01304 } |
|
Test whether all variables are 0/1. Definition at line 305 of file BCP_lp_user.cpp. References BCP_solution_generic::_objective, BCP_solution_generic::add_entry(), BCP_lp_prob::param(), BCP_vec< T >::size(), BCP_lp_result::termcode(), and BCP_lp_result::x(). Referenced by test_feasibility().
00308 { 00309 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00310 printf(" LP: Default test_binary() executed.\n"); 00311 } 00312 // Do anything only if the termination code is sensible 00313 const int tc = lpres.termcode(); 00314 if (! (tc & BCP_ProvenOptimal)) 00315 return 0; 00316 00317 const double * x = lpres.x(); 00318 const int varnum = vars.size(); 00319 int i; 00320 00321 for (i = 0 ; i < varnum; ++i) { 00322 const double xi = x[i]; 00323 if ( (xi > etol && xi < 1 - etol) || (xi < -etol) || (xi > 1 + etol) ) 00324 return(NULL); 00325 } 00326 00327 // This solution does not own the pointers to the variables 00328 BCP_solution_generic* sol = new BCP_solution_generic(false); 00329 double obj = 0; 00330 for (i = 0 ; i < varnum; ++i) { 00331 if (x[i] > 1 - etol) { 00332 sol->add_entry(vars[i], 1.0); 00333 obj += vars[i]->obj(); 00334 } 00335 } 00336 sol->_objective = obj; 00337 return sol; 00338 } |
|
Evaluate and return MIP feasibility of the current solution. If the solution is MIP feasible, return a solution object otherwise return a NULL pointer. The useris also welcome to heuristically generate a solution and return a pointer to that solution (although the user will have another chance (after cuts and variables are generated) to return/create heuristically generated solutions. (After all, it's quite possible that solutions are generated during cut/variable generation.)
Default: test feasibility based on the
Definition at line 278 of file BCP_lp_user.cpp. References BCP_lp_prob::param(), test_binary(), test_full(), and test_integral().
00281 { 00282 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00283 printf(" LP: Default test_feasibility() executed.\n"); 00284 } 00285 00286 const double etol = p->param(BCP_lp_par::IntegerTolerance); 00287 BCP_feasibility_test test = 00288 static_cast<BCP_feasibility_test>(p->param(BCP_lp_par::FeasibilityTest)); 00289 00290 BCP_solution* sol = NULL; 00291 switch (test){ 00292 case BCP_Binary_Feasible: sol = test_binary(lpres, vars, etol); break; 00293 case BCP_Integral_Feasible: sol = test_integral(lpres, vars, etol); break; 00294 case BCP_FullTest_Feasible: sol = test_full(lpres, vars, etol); break; 00295 default: 00296 throw BCP_fatal_error("LP: unknown test_feasibility() rule.\n"); 00297 } 00298 00299 return sol; 00300 } |
|
Test whether all variables are within their lower and upper bounds and that the integer variables are really integer. Definition at line 383 of file BCP_lp_user.cpp. References BCP_solution_generic::_objective, BCP_solution_generic::add_entry(), BCP_var::lb(), BCP_lp_prob::param(), BCP_vec< T >::size(), BCP_lp_result::termcode(), BCP_var::ub(), BCP_var::var_type(), and BCP_lp_result::x(). Referenced by test_feasibility().
00386 { 00387 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00388 printf(" LP: Default test_full() executed.\n"); 00389 } 00390 // Do anything only if the termination code is sensible 00391 const int tc = lpres.termcode(); 00392 if (! (tc & BCP_ProvenOptimal)) 00393 return 0; 00394 00395 const double * x = lpres.x(); 00396 const int varnum = vars.size(); 00397 const double etol1 = 1 - etol; 00398 int i; 00399 register double val; 00400 00401 for (i = 0 ; i < varnum; ++i) { 00402 val = x[i]; 00403 const BCP_var* vari = vars[i]; 00404 if (val < vari->lb() - etol || val > vari->ub() + etol) 00405 return(NULL); 00406 switch (vari->var_type()){ 00407 case BCP_BinaryVar: 00408 if (val > etol && val < etol1) 00409 return(NULL); 00410 break; 00411 case BCP_IntegerVar: 00412 val = val - floor(val); 00413 if (val > etol && val < etol1) 00414 return(NULL); 00415 break; 00416 case BCP_ContinuousVar: 00417 break; 00418 } 00419 } 00420 00421 // This solution does not own the pointers to the variables 00422 BCP_solution_generic* sol = new BCP_solution_generic(false); 00423 double obj = 0; 00424 for (i = 0 ; i < varnum; ++i) { 00425 val = x[i]; 00426 // round the integer vars 00427 if (vars[i]->var_type() == BCP_BinaryVar || 00428 vars[i]->var_type() == BCP_IntegerVar) 00429 val = floor(x[i] + 0.5); 00430 if (val < -etol || val > etol) { 00431 sol->add_entry(vars[i], val); 00432 obj += val * vars[i]->obj(); 00433 } 00434 } 00435 sol->_objective = obj; 00436 return sol; 00437 } |
|
Test whether all variables are integer and are within their lower and upper bounds. Definition at line 341 of file BCP_lp_user.cpp. References BCP_solution_generic::_objective, BCP_solution_generic::add_entry(), BCP_var::lb(), BCP_lp_prob::param(), BCP_vec< T >::size(), BCP_lp_result::termcode(), BCP_var::ub(), and BCP_lp_result::x(). Referenced by test_feasibility().
00344 { 00345 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00346 printf(" LP: Default test_integral() executed.\n"); 00347 } 00348 // Do anything only if the termination code is sensible 00349 const int tc = lpres.termcode(); 00350 if (! (tc & BCP_ProvenOptimal)) 00351 return 0; 00352 00353 const double * x = lpres.x(); 00354 const int varnum = vars.size(); 00355 int i; 00356 register double val; 00357 00358 for (i = 0 ; i < varnum; ++i) { 00359 val = x[i]; 00360 const BCP_var* vari = vars[i]; 00361 if (val < vari->lb() - etol || val > vari->ub() + etol) 00362 return(NULL); 00363 val = val - floor(val); 00364 if (val > etol && val < 1 - etol) 00365 return(NULL); 00366 } 00367 00368 // This solution does not own the pointers to the variables 00369 BCP_solution_generic* sol = new BCP_solution_generic(false); 00370 double obj = 0; 00371 for (i = 0 ; i < varnum; ++i) { 00372 val = floor(x[i] + 0.5); 00373 if (val < -etol || val > etol) { // could test != 0.0 00374 sol->add_entry(vars[i], val); 00375 obj += val * vars[i]->obj(); 00376 } 00377 } 00378 sol->_objective = obj; 00379 return sol; 00380 } |
|
Unpack an algorithmic cut Definition at line 183 of file BCP_lp_user.cpp.
00184 { 00185 throw BCP_fatal_error("\ 00186 BCP_lp_user::unpack_cut_algo() invoked but not overridden!\n"); 00187 } |
|
Unpack the initial information sent to the LP process by the Tree Manager. This information was packed by the method BCP_tm_user::pack_module_data() invoked with Default: empty method. Definition at line 127 of file BCP_lp_user.cpp. References BCP_lp_prob::param().
00128 { 00129 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00130 printf(" LP: Default unpack_module_data() executed.\n"); 00131 } 00132 } |
|
Unpack an user data Definition at line 199 of file BCP_lp_user.cpp.
00200 { 00201 throw BCP_fatal_error("\ 00202 BCP_lp_user::unpack_user_data() invoked but not overridden!\n"); 00203 } |
|
Unpack an algorithmic variable Definition at line 167 of file BCP_lp_user.cpp.
00168 { 00169 throw BCP_fatal_error("\ 00170 BCP_lp_user::unpack_var_algo() invoked but not overridden!\n"); 00171 } |
|
Unpack warmstarting information Definition at line 148 of file BCP_lp_user.cpp. References BCP_lp_prob::param().
00149 { 00150 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00151 printf(" LP: Default BCP_lp_user::unpack_warmstart() executed.\n"); 00152 } 00153 return BCP_unpack_warmstart(buf); 00154 } |
|
Convert a set of variables into corresponding columns for the current LP relaxation. Converting means to compute for each variable the coefficients corresponding to each cut and create BCP_col objects that can be added to the formulation. See the documentation of cuts_to_rows() above for the use of this method (just reverse the role of cuts and variables.)
Definition at line 662 of file BCP_lp_user.cpp. References BCP_lp_prob::param().
00669 { 00670 if (p->param(BCP_lp_par::ReportWhenDefaultIsExecuted)) { 00671 printf(" LP: Default vars_to_cols() executed.\n"); 00672 } 00673 throw BCP_fatal_error("vars_to_cols() missing.\n"); 00674 } |