/home/coin/SVN-release/OS-2.4.2/Bcp/src/LP/BCP_lp_msg_node_send.cpp

Go to the documentation of this file.
00001 // Copyright (C) 2000, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
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: // including BCP_Storage_NoData
00101          throw BCP_fatal_error("BCP_lp_pack_core() : Bad storage.\n");
00102       }
00103       // look ahead (the current node may become the parent) and replace the
00104       // parent's core to be exp_bc
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     // No matter whether we'll use an explicit description or WrtParent, all
00128     // vars with negative bcpind will have to be sent to the TM. These vars
00129     // will be collected in this vector.
00130     BCP_vec<BCP_var*> vars_to_tm;
00131     
00132     // First create an explicit description
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             // while we make the explicit description make sure that all extra
00144             // vars have positive bcpind. After all, they are being sent to
00145             // the TM right now.
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     // Whether we'll pack the Explicit or the WrtParent description, the new
00158     // vars need to be packed. Pack them first, so by the time the positive
00159     // bcpind in expl (or wrtp) arrives to the TM, the var already exists in
00160     // the TM.
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     // Now create a WrtParent description and see which one is shorter. Also,
00178     // we'll need the list of deleted variable positions when we set of the
00179     // warmstart information to be sent.
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     // first check how many entry has been deleted from oldvars
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             // added_bcpind ALWAYS has real indices, so this really separates
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     // append the remains of old_added to _del_change_pos
00207     for ( ; j < old_added_num; ++j) {
00208         wrtp._del_change_pos.unchecked_push_back(j);
00209     }
00210     // _deleted_num is the current length of _del_change_pos
00211     wrtp._deleted_num = wrtp._del_change_pos.size();
00212 
00213     // the rest are the set of really new vars, and also the position of those
00214     // vars must be appended to chpos.
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     // append chpos to _del_change_pos to get the final list
00222     wrtp._del_change_pos.append(chpos);
00223     
00224     // finally, create _change: just pick up things based on chpos
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     // if the TM storage is WrtParent then pack the shorter
00238     // FIXME: why only if TM storage is WrtParent ???
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     // No matter whether we'll use an explicit description or WrtParent, all
00272     // cuts with negative bcpind will have to be sent to the TM. These cuts
00273     // will be collected in this vector.
00274     BCP_vec<BCP_cut*> cuts_to_tm;
00275     
00276     // First create an explicit description
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             // while we make the explicit description make sure that all extra
00288             // cuts have positive bcpind. After all, they are being sent to
00289             // the TM right now.
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     // Whether we'll pack the Explicit or the WrtParent description, the new
00302     // cuts need to be packed. Pack them first, so by the time the positive
00303     // bcpind in expl (or wrtp) arrives to the TM, the cut already exists in
00304     // the TM.
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     // Now create a WrtParent description and see which one is shorter. Also,
00322     // we'll need the list of deleted cutiable positions when we set of the
00323     // warmstart information to be sent.
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     // first check how many entry has been deleted from oldcuts
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             // added_bcpind ALWAYS has real indices, so this really separates
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     // append the remains of old_added to _del_change_pos
00351     for ( ; j < old_added_num; ++j) {
00352         wrtp._del_change_pos.unchecked_push_back(j);
00353     }
00354     // _deleted_num is the current length of _del_change_pos
00355     wrtp._deleted_num = wrtp._del_change_pos.size();
00356 
00357     // the rest are the set of really new cuts, and also the position of those
00358     // cuts must be appended to chpos.
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     // append chpos to _del_change_pos to get the final list
00366     wrtp._del_change_pos.append(chpos);
00367     
00368     // finally, create _change: just pick up things based on chpos
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     // if the TM storage is WrtParent then pack the shorter
00382     // FIXME: why only if TM storage is WrtParent ???
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           // this return an explicit storage if that's shorter!
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    // collect the lower bounds on the children
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    // The qualities are the same (for now) as the lpobjs
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    // now pack all those stuff
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 // brobj is 0, msgtag is 'real' when invoked from fathom().
00488 // brobj is 'real', msgtag is BCP_Msg_NoMessage when invoked from branch()
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    // let's start with saying who this node is and what is the lb we got
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    // Send the node description only if this node is branched on (i.e., brobj
00508    // is non-null) or if we got to send the description of fathomed nodes, too.
00509    const bool send_desc = brobj || p.param(BCP_lp_par::SendFathomedNodeDesc);
00510    buf.pack(send_desc);
00511    if (send_desc) {
00512       // Pack the core (WrtCore, WrtParent or Explicit)
00513       BCP_lp_pack_core(p);  // BCP_problem_core_change
00514       // pack the algo var set change (or pack them explicitly)
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       // At this point there aren't supposed to be any ws info. It was deleted
00522       // when the lp formulation was created. Test this.
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       // If necessary, get and pack the warmstart info
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) { // we are in the root
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() /*tree_manager*/,
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       // we came here from branch()
00565       // pack the branching info, 'keep' will tell whether we wish to dive
00566       keep = BCP_lp_pack_branching_info(p, brobj);
00567       // In a single process environment (message driven) the reaction in the
00568       // TM to the send below will reset p.node->dive. In a multi-process
00569       // environment p.node->dive will remain Unknown. This will help later
00570       // (20 lines below) to decide whether we have to get the diving info or
00571       // not.
00572       p.node->dive = BCP_UnknownDivingStatus;
00573       p.msg_env->send(p.get_parent() /*tree_manager*/,
00574                       BCP_Msg_NodeDescriptionWithBranchingInfo, buf);
00575    }else{
00576       // we came from fathom()
00577       p.msg_env->send(p.get_parent() /*tree_manager*/, msgtag, buf);
00578    }
00579 
00580    if (keep == -1){
00581       // we don't wan't to dive (or we came from fathom()),
00582       // don't wait for the names of the ones not having global internal index
00583       return -1;
00584    }
00585 
00586    // We did want to dive
00587 
00588    // In the single process environment the diving info already came back
00589    // (when the TM processes the branching info) and p.node->dive is set.
00590    // Otherwise we got to receive the diving info here.
00591    if (p.node->dive == BCP_UnknownDivingStatus) {
00592       // We got to receive the diving information by hand
00593       p.msg_buf.clear();
00594       p.msg_env->receive(p.get_parent() /*tree_manager*/,
00595                          BCP_Msg_DivingInfo, buf, -1);
00596       BCP_lp_unpack_diving_info(p, p.msg_buf);
00597    }
00598 
00599    // BCP_lp_unpack_diving_info() sets p.node->index to the new index if
00600    // diving is to be done, or to -1 if diving is not allowed.
00601    if (p.node->index == -1) {
00602       keep = -1;
00603       // At this point brobj cannot be empty.
00604       // We must reset the child to be kept, too.
00605       brobj->keep_no_child();
00606    }
00607    return keep;
00608 }
00609 
00610 //#############################################################################

Generated on Wed Nov 30 03:03:49 2011 by  doxygen 1.4.7