00001
00002
00003 #include <functional>
00004
00005 #include "BCP_message.hpp"
00006 #include "BCP_lp_user.hpp"
00007 #include "BCP_lp_node.hpp"
00008 #include "BCP_lp_pool.hpp"
00009 #include "BCP_lp.hpp"
00010 #include "BCP_lp_functions.hpp"
00011
00012
00013
00014 void BCP_lp_check_ub(BCP_lp_prob& p)
00015 {
00016 while (true){
00017
00018 p.msg_buf.clear();
00019 p.msg_env->receive(BCP_AnyProcess, BCP_Msg_UpperBound, p.msg_buf, 0);
00020 if (p.msg_buf.msgtag() == BCP_Msg_NoMessage)
00021 break;
00022 BCP_lp_process_ub_message(p, p.msg_buf);
00023 }
00024 }
00025
00026
00027
00028 void
00029 BCP_lp_prob::process_message()
00030 {
00031 BCP_cut* cut;
00032 BCP_var* var;
00033 const BCP_proc_id * cpid = node->cp;
00034 const BCP_proc_id * vpid = node->vp;
00035 bool dont_send_to_pool;
00036
00037 int node_index;
00038 int node_itcnt;
00039
00040 switch (msg_buf.msgtag()){
00041 case BCP_Msg_InitialUserInfo:
00042 throw BCP_fatal_error("\
00043 LP: BCP_Msg_InitialUserInfo arrived in BCP_lp_prob::process_message().\n");
00044
00045 case BCP_Msg_CutIndexSet:
00046 msg_buf.unpack(next_cut_index).unpack(last_cut_index);
00047 break;
00048
00049 case BCP_Msg_VarIndexSet:
00050 msg_buf.unpack(next_var_index).unpack(last_var_index);
00051 break;
00052
00053 case BCP_Msg_CutDescription:
00054 cut = unpack_cut();
00055 if (param(BCP_lp_par::CompareNewCutsToOldOnes)){
00056
00057 BCP_lp_cut_pool::iterator oldcut = local_cut_pool->begin();
00058 BCP_lp_cut_pool::iterator lastoldcut = local_cut_pool->end();
00059 while (oldcut != lastoldcut){
00060 switch (user->compare_cuts((*oldcut)->cut(), cut)){
00061 case BCP_FirstObjIsBetter:
00062 case BCP_ObjsAreSame:
00063 delete cut; cut = 0;
00064 msg_buf.clear();
00065 return;
00066 case BCP_SecondObjIsBetter:
00067 case BCP_DifferentObjs:
00068 ++oldcut;
00069 break;
00070 }
00071 }
00072 }
00073
00074 dont_send_to_pool =
00075 (! cpid || (cpid && cpid->is_same_process(msg_buf.sender())));
00076 if (no_more_cuts_cnt >= 0){
00077 BCP_lp_cut_pool& cp = *local_cut_pool;
00078 const int old_cp_size = cp.size();
00079 BCP_vec<BCP_row*> rows;
00080 rows.reserve(1);
00081 BCP_vec<BCP_cut*> cuts(1, cut);
00082 user->cuts_to_rows(node->vars, cuts, rows, *lp_result,
00083 cpid && cpid->is_same_process(msg_buf.sender()) ?
00084 BCP_Object_FromPool : BCP_Object_FromGenerator,
00085 true);
00086 const int cutnum = cuts.size();
00087 for (int i = 0; i < cutnum; ++i) {
00088 cut = cuts[i];
00089 cut->set_bcpind(-BCP_lp_next_cut_index(*this));
00090 cut->dont_send_to_pool(dont_send_to_pool);
00091 cp.push_back(new BCP_lp_waiting_row(cut, rows[i]));
00092 }
00093
00094 cp.compute_violations(*lp_result, cp.entry(old_cp_size), cp.end());
00095 }else{
00096 local_cut_pool->push_back(new BCP_lp_waiting_row(cut));
00097 }
00098 break;
00099
00100 case BCP_Msg_NoMoreCuts:
00101
00102
00103 double cutgen_time;
00104 msg_buf.unpack(node_index).unpack(node_itcnt).unpack(cutgen_time);
00105 stat.time_cut_generation += cutgen_time;
00106 if (no_more_cuts_cnt >= 0 &&
00107 node->index == node_index && node->iteration_count == node_itcnt)
00108 no_more_cuts_cnt--;
00109 break;
00110
00111 case BCP_Msg_VarDescription:
00112 var = unpack_var();
00113 if (param(BCP_lp_par::CompareNewVarsToOldOnes)){
00114
00115 BCP_lp_var_pool::iterator oldvar = local_var_pool->begin();
00116 BCP_lp_var_pool::iterator lastoldvar = local_var_pool->end();
00117 while (oldvar != lastoldvar){
00118 switch (user->compare_vars((*oldvar)->var(), var)){
00119 case BCP_FirstObjIsBetter:
00120 case BCP_ObjsAreSame:
00121 delete var; var = 0;
00122 msg_buf.clear();
00123 return;
00124 case BCP_SecondObjIsBetter:
00125 case BCP_DifferentObjs:
00126 ++oldvar;
00127 break;
00128 }
00129 }
00130 }
00131
00132 dont_send_to_pool =
00133 (! vpid || (vpid && vpid->is_same_process(msg_buf.sender())));
00134 if (no_more_vars_cnt >= 0){
00135 BCP_lp_var_pool& vp = *local_var_pool;
00136 const int old_vp_size = vp.size();
00137 BCP_vec<BCP_col*> cols;
00138 cols.reserve(1);
00139 BCP_vec<BCP_var*> vars(1, var);
00140 user->vars_to_cols(node->cuts, vars, cols, *lp_result,
00141 vpid && vpid->is_same_process(msg_buf.sender()) ?
00142 BCP_Object_FromPool : BCP_Object_FromGenerator,
00143 true);
00144 const int varnum = vars.size();
00145 for (int i = 0; i < varnum; ++i) {
00146 var = vars[i];
00147 var->set_bcpind(-BCP_lp_next_var_index(*this));
00148 var->dont_send_to_pool(dont_send_to_pool);
00149 vp.push_back(new BCP_lp_waiting_col(var, cols[i]));
00150 }
00151
00152 vp.compute_red_costs(*lp_result, vp.entry(old_vp_size), vp.end());
00153 }else{
00154 local_var_pool->push_back(new BCP_lp_waiting_col(var));
00155 }
00156 break;
00157
00158 case BCP_Msg_NoMoreVars:
00159
00160
00161 double vargen_time;
00162 msg_buf.unpack(node_index).unpack(node_itcnt).unpack(vargen_time);
00163 stat.time_var_generation += vargen_time;
00164 if (no_more_vars_cnt >= 0 &&
00165 node->index == node_index && node->iteration_count == node_itcnt)
00166 no_more_vars_cnt--;
00167 break;
00168
00169 case BCP_Msg_UpperBound:
00170 BCP_lp_process_ub_message(*this, msg_buf);
00171 break;
00172
00173 #if 0
00174 case BCP_Msg_RootToPrice:
00175 BCP_lp_unpack_active_node(*this, msg_buf);
00176
00177 BCP_lp_create_lp(p);
00178 BCP_lp_repricing(p);
00179 lp_solver->unload_lp();
00180 break;
00181 #endif
00182
00183 case BCP_Msg_ActiveNodeData:
00184 BCP_lp_unpack_active_node(*this, msg_buf);
00185
00186 lp_solver = master_lp->clone();
00187 if (! param(BCP_lp_par::SolveLpToOptimality))
00188 lp_solver->setDblParam(OsiDualObjectiveLimit, ub() - granularity());
00189 BCP_lp_create_lp(*this);
00190 BCP_lp_main_loop(*this);
00191 delete lp_solver;
00192 lp_solver = NULL;
00193 break;
00194
00195 case BCP_Msg_DivingInfo:
00196 BCP_lp_unpack_diving_info(*this, msg_buf);
00197 break;
00198
00199 case BCP_Msg_NextPhaseStarts:
00200 msg_buf.clear();
00201
00202 stat.pack(msg_buf);
00203 msg_env->send(tree_manager, BCP_Msg_LpStatistics, msg_buf);
00204 phase++;
00205 break;
00206
00207 case BCP_Msg_FinishedBCP:
00208
00209
00210 stat.pack(msg_buf);
00211 msg_env->send(tree_manager, BCP_Msg_LpStatistics, msg_buf);
00212 return;
00213
00214
00215
00216
00217
00218
00219 default:
00220 printf("Unknown message type arrived to LP: %i\n", msg_buf.msgtag());
00221 break;
00222 }
00223
00224 msg_buf.clear();
00225 }
00226
00227
00228
00229 BCP_IndexType
00230 BCP_lp_next_var_index(BCP_lp_prob& p)
00231 {
00232 if (p.next_var_index == p.last_var_index) {
00233 BCP_buffer& buf = p.msg_buf;
00234
00235 buf.clear();
00236 p.msg_env->send(p.tree_manager, BCP_Msg_RequestVarIndexSet);
00237
00238
00239
00240 if (p.next_var_index == p.last_var_index) {
00241 p.msg_env->receive(p.tree_manager, BCP_Msg_VarIndexSet, buf, -1);
00242 p.process_message();
00243 }
00244 }
00245 const BCP_IndexType tmp = p.next_var_index++;
00246 return tmp;
00247 }
00248
00249
00250
00251 BCP_IndexType
00252 BCP_lp_next_cut_index(BCP_lp_prob& p)
00253 {
00254 if (p.next_cut_index == p.last_cut_index) {
00255 BCP_buffer& buf = p.msg_buf;
00256
00257 buf.clear();
00258 p.msg_env->send(p.tree_manager, BCP_Msg_RequestCutIndexSet);
00259
00260
00261
00262 if (p.next_cut_index == p.last_cut_index) {
00263 p.msg_env->receive(p.tree_manager, BCP_Msg_CutIndexSet, buf, -1);
00264 p.process_message();
00265 }
00266 }
00267 const BCP_IndexType tmp = p.next_cut_index++;
00268 return tmp;
00269 }
00270
00271
00272
00273 void BCP_lp_process_ub_message(BCP_lp_prob& p, BCP_buffer& buf)
00274 {
00275 double new_ub;
00276 buf.unpack(new_ub);
00277 if (! p.param(BCP_lp_par::SolveLpToOptimality) &&
00278 p.ub(new_ub) &&
00279 p.lp_solver)
00280 p.lp_solver->setDblParam(OsiDualObjectiveLimit, new_ub - p.granularity());
00281 }
00282
00283
00284
00285 void BCP_lp_send_cuts_to_cp(BCP_lp_prob& p, const int eff_cnt_limit)
00286 {
00287 if (! p.node->cp)
00288 return;
00289
00290 BCP_cut_set& cuts = p.node->cuts;
00291 BCP_cut_set::iterator cuti = cuts.entry(p.core->cutnum());
00292 const BCP_cut_set::const_iterator lastcuti = cuts.end();
00293 BCP_cut* cut;
00294 int cnt;
00295
00296
00297 for (cnt = 0; cuti != lastcuti; ++cuti) {
00298 cut = *cuti;
00299 if (cut->effective_count() >= eff_cnt_limit &&
00300 ! cut->dont_send_to_pool())
00301 ++cnt;
00302 }
00303
00304 if (cnt > 0){
00305 BCP_buffer& buf = p.msg_buf;
00306 buf.clear();
00307 buf.pack(cnt);
00308
00309 buf.pack(p.node->level);
00310
00311 cuti = cuts.entry(p.core->cutnum());
00312 for ( ; cuti != lastcuti; ++cuti) {
00313 cut = *cuti;
00314 if (cut->effective_count() >= eff_cnt_limit &&
00315 ! cut->dont_send_to_pool())
00316 p.pack_cut(BCP_ProcessType_CP, *cut);
00317 cut->dont_send_to_pool(true);
00318 }
00319
00320 p.msg_env->send(p.node->cp, BCP_Msg_CutsToCutPool, buf);
00321 if (p.param(BCP_lp_par::LpVerb_CutsToCutPoolCount))
00322 printf("LP: %i cuts sent to cutpool\n", cnt);
00323 }
00324 }
00325
00326
00327
00328 void BCP_lp_unpack_diving_info(BCP_lp_prob& p, BCP_buffer& buf)
00329 {
00330 buf.unpack(p.node->dive);
00331 if (p.node->dive != BCP_DoNotDive){
00332
00333 buf.unpack(p.node->index);
00334
00335 p.node->level++;
00336 p.node->iteration_count = 0;
00337 } else {
00338 p.node->index = -1;
00339 }
00340 }