00001
00002
00003 #include <functional>
00004
00005 #include "BCP_message.hpp"
00006 #include "BCP_problem_core.hpp"
00007 #include "BCP_branch.hpp"
00008 #include "BCP_warmstart.hpp"
00009 #include "BCP_lp.hpp"
00010 #include "BCP_lp_user.hpp"
00011 #include "BCP_lp_branch.hpp"
00012 #include "BCP_lp_node.hpp"
00013 #include "BCP_lp_functions.hpp"
00014 #include "BCP_lp_functions.hpp"
00015 #include "BCP_vector.hpp"
00016
00017 #include "BCP_USER.hpp"
00018
00019
00020 static inline void BCP_lp_pack_core(BCP_lp_prob& p);
00021 static inline void BCP_lp_pack_noncore_vars(BCP_lp_prob& p,
00022 BCP_vec<int>& deleted_pos);
00023 static inline void BCP_lp_pack_noncore_cuts(BCP_lp_prob& p,
00024 BCP_vec<int>& deleted_pos);
00025 static inline void BCP_lp_pack_warmstart(BCP_lp_prob& p,
00026 BCP_vec<int>& del_vars,
00027 BCP_vec<int>& del_cuts);
00028 static inline void BCP_lp_pack_user_data(BCP_lp_prob& p);
00029
00030
00031
00032 static inline int BCP_lp_pack_branching_info(BCP_lp_prob& p,
00033 BCP_presolved_lp_brobj* brobj);
00034
00035
00036
00037 static inline void
00038 BCP_lp_pack_core(BCP_lp_prob& p)
00039 {
00040 if (p.core->varnum() + p.core->cutnum() > 0){
00041 const bool dumpcuts = p.param(BCP_lp_par::Lp_DumpNodeDescCuts);
00042 const bool dumpvars = p.param(BCP_lp_par::Lp_DumpNodeDescVars);
00043 if (dumpvars) {
00044 const int bvarnum = p.core->varnum();
00045 const BCP_vec<BCP_var*>& vars = p.node->vars;
00046 printf(" Core Vars (bvarnum %i)\n", bvarnum);
00047 for (int i = 0; i < bvarnum; ++i) {
00048 printf(" var %4i: bcpind %i, status %i, lb %f, ub %f\n",
00049 i, vars[i]->bcpind(), vars[i]->status(),
00050 vars[i]->lb(), vars[i]->ub());
00051 }
00052 }
00053 if (dumpcuts) {
00054 const int bcutnum = p.core->cutnum();
00055 const BCP_vec<BCP_cut*>& cuts = p.node->cuts;
00056 printf(" Core Cuts (bcutnum %i)\n", bcutnum);
00057 for (int i = 0; i < bcutnum; ++i) {
00058 printf(" cut %4i: bcpind %i, status %i, lb %f, ub %f\n",
00059 i, cuts[i]->bcpind(), cuts[i]->status(),
00060 cuts[i]->lb(), cuts[i]->ub());
00061 }
00062 }
00063 BCP_problem_core_change exp_bc(p.core->varnum(), p.node->vars,
00064 p.core->cutnum(), p.node->cuts);
00065 switch (p.node->tm_storage.core_change){
00066 case BCP_Storage_WrtCore:
00067 {
00068 BCP_problem_core_change wrtcore_bc(BCP_Storage_WrtCore,
00069 *p.core_as_change, exp_bc);
00070 wrtcore_bc.pack(p.msg_buf);
00071 }
00072 break;
00073
00074 case BCP_Storage_Explicit:
00075 exp_bc.pack(p.msg_buf);
00076 break;
00077
00078 case BCP_Storage_WrtParent:
00079 {
00080 BCP_problem_core_change wrtparent_bc(BCP_Storage_WrtParent,
00081 p.parent->core_as_change, exp_bc);
00082 BCP_problem_core_change wrtcore_bc(BCP_Storage_WrtCore,
00083 *p.core_as_change, exp_bc);
00084 if (exp_bc.pack_size() <= wrtparent_bc.pack_size()){
00085 if (exp_bc.pack_size() <= wrtcore_bc.pack_size()){
00086 exp_bc.pack(p.msg_buf);
00087 }else{
00088 wrtcore_bc.pack(p.msg_buf);
00089 }
00090 }else{
00091 if (wrtparent_bc.pack_size() < wrtcore_bc.pack_size()){
00092 wrtparent_bc.pack(p.msg_buf);
00093 }else{
00094 wrtcore_bc.pack(p.msg_buf);
00095 }
00096 }
00097 }
00098 break;
00099
00100 default:
00101 throw BCP_fatal_error("BCP_lp_pack_core() : Bad storage.\n");
00102 }
00103
00104
00105 p.parent->core_as_change.swap(exp_bc);
00106 }
00107 }
00108
00109
00110
00111 static inline void
00112 BCP_lp_pack_noncore_vars(BCP_lp_prob& p, BCP_vec<int>& deleted_pos)
00113 {
00114 const bool dumpvars = p.param(BCP_lp_par::Lp_DumpNodeDescVars);
00115 if (dumpvars) {
00116 const int bvarnum = p.core->varnum();
00117 const int varnum = p.node->vars.size();
00118 const BCP_vec<BCP_var*>& vars = p.node->vars;
00119 printf(" Extra Vars (extra varnum %i)\n", varnum - bvarnum);
00120 for (int i = bvarnum; i < varnum; ++i) {
00121 printf(" var %4i: bcpind %i, status %i, lb %f, ub %f\n",
00122 i, vars[i]->bcpind(), vars[i]->status(),
00123 vars[i]->lb(), vars[i]->ub());
00124 }
00125 }
00126
00127
00128
00129
00130 BCP_vec<BCP_var*> vars_to_tm;
00131
00132
00133 BCP_obj_set_change expl;
00134
00135 BCP_var** vars = &p.node->vars[p.core->varnum()];
00136 const int new_added_num = p.node->vars.size() - p.core->varnum();
00137 if (new_added_num > 0) {
00138 expl._new_objs.reserve(new_added_num);
00139 expl._change.reserve(new_added_num);
00140 for (int i = 0; i < new_added_num; ++i) {
00141 BCP_var* v = vars[i];
00142 const int bcpind = v->bcpind();
00143
00144
00145
00146 if (bcpind < 0) {
00147 vars_to_tm.push_back(v);
00148 expl._new_objs.unchecked_push_back(-bcpind);
00149 } else {
00150 expl._new_objs.unchecked_push_back(bcpind);
00151 }
00152 expl._change.unchecked_push_back(BCP_obj_change(v->lb(), v->ub(),
00153 v->status()));
00154 }
00155 }
00156
00157
00158
00159
00160
00161 int num = vars_to_tm.size();
00162 p.msg_buf.pack(num);
00163 for (int i = 0; i < num; ++i) {
00164 assert(vars_to_tm[i]->bcpind() < 0);
00165 p.pack_var(*vars_to_tm[i]);
00166 vars_to_tm[i]->set_bcpind_flip();
00167 }
00168
00169 if (p.param(BCP_lp_par::UseExplicitStorage)) {
00170 if (dumpvars) {
00171 expl.print();
00172 }
00173 expl.pack(p.msg_buf);
00174 return;
00175 }
00176
00177
00178
00179
00180 BCP_obj_set_change wrtp;
00181 wrtp._storage = BCP_Storage_WrtParent;
00182
00183 const BCP_vec<int>& old_added_bcpind = p.parent->var_set._new_objs;
00184 const BCP_vec<BCP_obj_change>& old_added_desc = p.parent->var_set._change;
00185 const int old_added_num = old_added_bcpind.size();
00186 wrtp._del_change_pos.reserve(old_added_num);
00187
00188 BCP_vec<int> chpos;
00189 chpos.reserve(new_added_num);
00190
00191 int i, j;
00192
00193
00194 for (i = 0, j = 0; i < new_added_num && j < old_added_num; ++j) {
00195 const BCP_var* const v = vars[i];
00196 const BCP_obj_change& old = old_added_desc[j];
00197 if (v->bcpind() == old_added_bcpind[j]) {
00198
00199 if (v->lb()!=old.lb || v->ub()!=old.ub || v->status()!=old.stat)
00200 chpos.unchecked_push_back(i);
00201 ++i;
00202 } else {
00203 wrtp._del_change_pos.unchecked_push_back(j);
00204 }
00205 }
00206
00207 for ( ; j < old_added_num; ++j) {
00208 wrtp._del_change_pos.unchecked_push_back(j);
00209 }
00210
00211 wrtp._deleted_num = wrtp._del_change_pos.size();
00212
00213
00214
00215 wrtp._new_objs.reserve(new_added_num - i);
00216 for ( ; i < new_added_num; ++i){
00217 const int bcpind = vars[i]->bcpind();
00218 wrtp._new_objs.unchecked_push_back(bcpind > 0 ? bcpind : -bcpind);
00219 chpos.unchecked_push_back(i);
00220 }
00221
00222 wrtp._del_change_pos.append(chpos);
00223
00224
00225 const int chnum = chpos.size();
00226 wrtp._change.reserve(chnum);
00227 for (i = 0; i < chnum; ++i) {
00228 const BCP_var* const var = vars[chpos[i]];
00229 wrtp._change.unchecked_push_back(BCP_obj_change(var->lb(), var->ub(),
00230 var->status()));
00231 }
00232
00233 deleted_pos.clear();
00234 deleted_pos.append(wrtp._del_change_pos.begin(),
00235 wrtp._del_change_pos.entry(wrtp.deleted_num()));
00236
00237
00238
00239 if ((p.node->tm_storage.var_change == BCP_Storage_WrtParent) &&
00240 (expl.pack_size() > wrtp.pack_size())) {
00241 if (dumpvars) {
00242 wrtp.print();
00243 }
00244 wrtp.pack(p.msg_buf);
00245 } else {
00246 if (dumpvars) {
00247 expl.print();
00248 }
00249 expl.pack(p.msg_buf);
00250 }
00251 }
00252
00253
00254
00255 static inline void
00256 BCP_lp_pack_noncore_cuts(BCP_lp_prob& p, BCP_vec<int>& deleted_pos)
00257 {
00258 const bool dumpcuts = p.param(BCP_lp_par::Lp_DumpNodeDescCuts);
00259 if (dumpcuts) {
00260 const int bcutnum = p.core->cutnum();
00261 const int cutnum = p.node->cuts.size();
00262 const BCP_vec<BCP_cut*>& cuts = p.node->cuts;
00263 printf(" Extra Cuts (extra cutnum %i)\n", cutnum - bcutnum);
00264 for (int i = bcutnum; i < cutnum; ++i) {
00265 printf(" cut %4i: bcpind %i, status %i, lb %f, ub %f\n",
00266 i, cuts[i]->bcpind(), cuts[i]->status(),
00267 cuts[i]->lb(), cuts[i]->ub());
00268 }
00269 }
00270
00271
00272
00273
00274 BCP_vec<BCP_cut*> cuts_to_tm;
00275
00276
00277 BCP_obj_set_change expl;
00278
00279 BCP_cut** cuts = &p.node->cuts[p.core->cutnum()];
00280 const int new_added_num = p.node->cuts.size() - p.core->cutnum();
00281 if (new_added_num > 0) {
00282 expl._new_objs.reserve(new_added_num);
00283 expl._change.reserve(new_added_num);
00284 for (int i = 0; i < new_added_num; ++i) {
00285 BCP_cut* c = cuts[i];
00286 const int bcpind = c->bcpind();
00287
00288
00289
00290 if (bcpind < 0) {
00291 cuts_to_tm.push_back(c);
00292 expl._new_objs.unchecked_push_back(-bcpind);
00293 } else {
00294 expl._new_objs.unchecked_push_back(bcpind);
00295 }
00296 expl._change.unchecked_push_back(BCP_obj_change(c->lb(), c->ub(),
00297 c->status()));
00298 }
00299 }
00300
00301
00302
00303
00304
00305 int num = cuts_to_tm.size();
00306 p.msg_buf.pack(num);
00307 for (int i = 0; i < num; ++i) {
00308 assert(cuts_to_tm[i]->bcpind() < 0);
00309 p.pack_cut(*cuts_to_tm[i]);
00310 cuts_to_tm[i]->set_bcpind_flip();
00311 }
00312
00313 if (p.param(BCP_lp_par::UseExplicitStorage)) {
00314 if (dumpcuts) {
00315 expl.print();
00316 }
00317 expl.pack(p.msg_buf);
00318 return;
00319 }
00320
00321
00322
00323
00324 BCP_obj_set_change wrtp;
00325 wrtp._storage = BCP_Storage_WrtParent;
00326
00327 const BCP_vec<int>& old_added_bcpind = p.parent->cut_set._new_objs;
00328 const BCP_vec<BCP_obj_change>& old_added_desc = p.parent->cut_set._change;
00329 const int old_added_num = old_added_bcpind.size();
00330 wrtp._del_change_pos.reserve(old_added_num);
00331
00332 BCP_vec<int> chpos;
00333 chpos.reserve(new_added_num);
00334
00335 int i, j;
00336
00337
00338 for (i = 0, j = 0; i < new_added_num && j < old_added_num; ++j) {
00339 const BCP_cut* const c = cuts[i];
00340 const BCP_obj_change& old = old_added_desc[j];
00341 if (c->bcpind() == old_added_bcpind[j]) {
00342
00343 if (c->lb()!=old.lb || c->ub()!=old.ub || c->status()!=old.stat)
00344 chpos.unchecked_push_back(i);
00345 ++i;
00346 } else {
00347 wrtp._del_change_pos.unchecked_push_back(j);
00348 }
00349 }
00350
00351 for ( ; j < old_added_num; ++j) {
00352 wrtp._del_change_pos.unchecked_push_back(j);
00353 }
00354
00355 wrtp._deleted_num = wrtp._del_change_pos.size();
00356
00357
00358
00359 wrtp._new_objs.reserve(new_added_num - i);
00360 for ( ; i < new_added_num; ++i){
00361 const int bcpind = cuts[i]->bcpind();
00362 wrtp._new_objs.unchecked_push_back(bcpind > 0 ? bcpind : -bcpind);
00363 chpos.unchecked_push_back(i);
00364 }
00365
00366 wrtp._del_change_pos.append(chpos);
00367
00368
00369 const int chnum = chpos.size();
00370 wrtp._change.reserve(chnum);
00371 for (i = 0; i < chnum; ++i) {
00372 const BCP_cut* const cut = cuts[chpos[i]];
00373 wrtp._change.unchecked_push_back(BCP_obj_change(cut->lb(), cut->ub(),
00374 cut->status()));
00375 }
00376
00377 deleted_pos.clear();
00378 deleted_pos.append(wrtp._del_change_pos.begin(),
00379 wrtp._del_change_pos.entry(wrtp.deleted_num()));
00380
00381
00382
00383 if ((p.node->tm_storage.cut_change == BCP_Storage_WrtParent) &&
00384 (expl.pack_size() > wrtp.pack_size())) {
00385 if (dumpcuts) {
00386 wrtp.print();
00387 }
00388 wrtp.pack(p.msg_buf);
00389 } else {
00390 if (dumpcuts) {
00391 expl.print();
00392 }
00393 expl.pack(p.msg_buf);
00394 }
00395 }
00396
00397
00398
00399 static inline void
00400 BCP_lp_pack_warmstart(BCP_lp_prob& p,
00401 BCP_vec<int>& del_vars, BCP_vec<int>& del_cuts)
00402 {
00403 bool has_data = p.node->warmstart != 0;
00404 p.msg_buf.pack(has_data);
00405
00406 if (has_data) {
00407 const bool def = p.param(BCP_lp_par::ReportWhenDefaultIsExecuted);
00408 if (p.node->tm_storage.warmstart != BCP_Storage_WrtParent) {
00409 p.packer->pack_warmstart(p.node->warmstart, p.msg_buf, def);
00410 } else {
00411 double petol = 0.0;
00412 double detol = 0.0;
00413 p.lp_solver->getDblParam(OsiPrimalTolerance, petol);
00414 p.lp_solver->getDblParam(OsiDualTolerance, detol);
00415
00416 BCP_warmstart* ws_change =
00417 p.node->warmstart->as_change(p.parent->warmstart,
00418 del_vars, del_cuts, petol, detol);
00419 p.packer->pack_warmstart(ws_change, p.msg_buf, def);
00420 delete ws_change;
00421 ws_change = 0;
00422 }
00423 }
00424 }
00425
00426
00427
00428 static inline void BCP_lp_pack_user_data(BCP_lp_prob& p)
00429 {
00430 bool has_data = p.node->user_data != 0;
00431 p.msg_buf.pack(has_data);
00432 if (has_data) {
00433 p.packer->pack_user_data(p.node->user_data, p.msg_buf);
00434 }
00435 }
00436
00437
00438
00439 static inline int
00440 BCP_lp_pack_branching_info(BCP_lp_prob& p, BCP_presolved_lp_brobj* lp_brobj)
00441 {
00442 const int child_num = lp_brobj->candidate()->child_num;
00443
00444
00445 BCP_vec<double> lpobj;
00446 lpobj.reserve(child_num);
00447 for (int i = 0; i < child_num; ++i) {
00448 lpobj.unchecked_push_back(lp_brobj->lpres(i).objval());
00449 }
00450
00451
00452 BCP_vec<double> qualities(lpobj);
00453
00454 const BCP_vec<BCP_child_action>& action = lp_brobj->action();
00455 const BCP_vec<BCP_user_data*>& user_data = lp_brobj->user_data();
00456
00457
00458 BCP_buffer& buf = p.msg_buf;
00459 buf.pack(p.node->dive).pack(action).pack(qualities).pack(lpobj);
00460
00461 for (int i = 0; i < child_num; ++i) {
00462 bool has_user_data = user_data[i] != 0;
00463 buf.pack(has_user_data);
00464 if (has_user_data) {
00465 p.packer->pack_user_data(user_data[i], buf);
00466 }
00467 }
00468
00469 BCP_internal_brobj int_brobj(*lp_brobj->candidate());
00470 int_brobj.pack(buf);
00471
00472 int keep = -1;
00473 if (p.node->dive != BCP_DoNotDive){
00474 for (int i = child_num - 1; i >= 0; --i)
00475 if (action[i] == BCP_KeepChild) {
00476 if (keep == -1)
00477 keep = i;
00478 else
00479 throw BCP_fatal_error("LP : Can't keep more than one child!\n");
00480 }
00481 }
00482 return keep;
00483 }
00484
00485
00486
00487
00488
00489
00490 int BCP_lp_send_node_description(BCP_lp_prob& p,
00491 BCP_presolved_lp_brobj* brobj,
00492 BCP_message_tag msgtag)
00493 {
00494 BCP_buffer& buf = p.msg_buf;
00495 BCP_lp_node& node = *p.node;
00496
00497
00498 buf.clear();
00499 buf.pack(node.index).pack(node.quality).pack(node.true_lower_bound);
00500
00501 const bool dumpcuts = p.param(BCP_lp_par::Lp_DumpNodeDescCuts);
00502 const bool dumpvars = p.param(BCP_lp_par::Lp_DumpNodeDescVars);
00503 if (dumpcuts || dumpvars) {
00504 printf("LP: FINISHED NODE %i DUMP START ===========================\n",
00505 node.index);
00506 }
00507
00508
00509 const bool send_desc = brobj || p.param(BCP_lp_par::SendFathomedNodeDesc);
00510 buf.pack(send_desc);
00511 if (send_desc) {
00512
00513 BCP_lp_pack_core(p);
00514
00515 BCP_vec<int> del_vars;
00516 BCP_lp_pack_noncore_vars(p, del_vars);
00517
00518 BCP_vec<int> del_cuts;
00519 BCP_lp_pack_noncore_cuts(p, del_cuts);
00520
00521
00522
00523 if (p.node->warmstart) {
00524 throw BCP_fatal_error("\
00525 LP: there is ws info in BCP_lp_send_node_description()!\n");
00526 }
00527
00528 CoinWarmStart* ws = NULL;
00529 switch (p.param(BCP_lp_par::WarmstartInfo)) {
00530 case BCP_WarmstartNone:
00531 break;
00532 case BCP_WarmstartRoot:
00533 if (node.index == 0) {
00534 ws = p.lp_solver->getWarmStart();
00535 if (ws) {
00536 BCP_warmstart* bws = BCP_lp_convert_CoinWarmStart(p, ws);
00537 if (bws) {
00538 const bool def = p.param(BCP_lp_par::ReportWhenDefaultIsExecuted);
00539 BCP_buffer wsbuf;
00540 p.packer->pack_warmstart(bws, wsbuf, def);
00541 p.msg_env->send(p.get_parent() ,
00542 BCP_Msg_WarmstartRoot, wsbuf);
00543 p.warmstartRoot = ws;
00544 delete bws;
00545 }
00546 }
00547 }
00548 break;
00549 case BCP_WarmstartParent:
00550 ws = p.lp_solver->getWarmStart();
00551 p.node->warmstart = BCP_lp_convert_CoinWarmStart(p, ws);
00552 BCP_lp_pack_warmstart(p, del_vars, del_cuts);
00553 }
00554 BCP_lp_pack_user_data(p);
00555 }
00556
00557 int keep = -1;
00558
00559 if (dumpcuts || dumpvars) {
00560 printf("LP: FINISHED NODE %i DUMP END ===========================\n",
00561 node.index);
00562 }
00563 if (brobj) {
00564
00565
00566 keep = BCP_lp_pack_branching_info(p, brobj);
00567
00568
00569
00570
00571
00572 p.node->dive = BCP_UnknownDivingStatus;
00573 p.msg_env->send(p.get_parent() ,
00574 BCP_Msg_NodeDescriptionWithBranchingInfo, buf);
00575 }else{
00576
00577 p.msg_env->send(p.get_parent() , msgtag, buf);
00578 }
00579
00580 if (keep == -1){
00581
00582
00583 return -1;
00584 }
00585
00586
00587
00588
00589
00590
00591 if (p.node->dive == BCP_UnknownDivingStatus) {
00592
00593 p.msg_buf.clear();
00594 p.msg_env->receive(p.get_parent() ,
00595 BCP_Msg_DivingInfo, buf, -1);
00596 BCP_lp_unpack_diving_info(p, p.msg_buf);
00597 }
00598
00599
00600
00601 if (p.node->index == -1) {
00602 keep = -1;
00603
00604
00605 brobj->keep_no_child();
00606 }
00607 return keep;
00608 }
00609
00610