/home/coin/SVN-release/OS-2.0.0/Bcp/src/Member/BCP_message_single.cpp

Go to the documentation of this file.
00001 // Copyright (C) 2000, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 
00004 #include <cstdio>
00005 
00006 #include "CoinTime.hpp"
00007 
00008 #include "BCP_math.hpp"
00009 
00010 #include "BCP_USER.hpp"
00011 
00012 #include "BCP_error.hpp"
00013 #include "BCP_buffer.hpp"
00014 #include "BCP_vector.hpp"
00015 #include "BCP_message_single.hpp"
00016 
00017 #include "BCP_problem_core.hpp"
00018 #include "BCP_node_change.hpp"
00019 
00020 #include "BCP_tm_functions.hpp"
00021 #include "BCP_tm_user.hpp"
00022 #include "BCP_lp_functions.hpp"
00023 #include "BCP_lp_user.hpp"
00024 #include "BCP_lp.hpp"
00025 
00026 #include "BCP_cg_user.hpp"
00027 #include "BCP_cg.hpp"
00028 
00029 #include "BCP_vg_user.hpp"
00030 #include "BCP_vg.hpp"
00031 
00032 #include "BCP_tm.hpp"
00033 
00034 std::map<int, BCP_process*> BCP_single_environment::processes;
00035 
00036 //#############################################################################
00037 
00038 void
00039 BCP_single_environment::set_arguments(const int argnum,
00040                                       const char* const * args)
00041 {
00042     int i;
00043     for (i = _argnum - 1; i >= 0; --i) {
00044         free(_arglist[i]);
00045     }
00046     _argnum = argnum;
00047     _arglist = new char*[argnum];
00048     for (i = _argnum - 1; i >= 0; --i) {
00049         _arglist[i] = strdup(args[i]);
00050     }
00051 }
00052 
00053 //#############################################################################
00054 
00055 BCP_single_environment::~BCP_single_environment()
00056 {
00057     for (int i = _argnum - 1; i >= 0; --i) {
00058         free(_arglist[i]);
00059     }
00060     delete[] _arglist;
00061 }
00062 
00063 //-----------------------------------------------------------------------------
00064 
00065 int
00066 BCP_single_environment::register_process(USER_initialize* user_init)
00067 {
00068     // OK, the TM invoked registration. Now this function takes over and
00069     // becomes the driver for ALL `virtual' processes.
00070     //--------------------------------------------------------------------------
00071     // We start as it is in tm_main.cpp
00072     int _tm_id(0);
00073     int _lp_id(1);
00074 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00075     int _cg_id(2);
00076     int _vg_id(3);
00077 #endif
00078     //     int _cp_id(4);
00079     //     int _vp_id(5);
00080     BCP_tm_prob* _tm_prob = new BCP_tm_prob();
00081     processes[0] = _tm_prob;
00082 
00083     _tm_prob->par.set_entry(BCP_tm_par::MessagePassingIsSerial,true);
00084     _tm_prob->slave_pars.lp.set_entry(BCP_lp_par::MessagePassingIsSerial,true);
00085     _tm_prob->slave_pars.cg.set_entry(BCP_cg_par::MessagePassingIsSerial,true);
00086     _tm_prob->slave_pars.vg.set_entry(BCP_vg_par::MessagePassingIsSerial,true);
00087     /*
00088       _tm_prob->slave_pars.cp.set_entry(BCP_cp_par::MessagePassingIsSerial,true);
00089       _tm_prob->slave_pars.vp.set_entry(BCP_vp_par::MessagePassingIsSerial,true);
00090     */
00091     BCP_tm_parse_command_line(*_tm_prob, _argnum, _arglist);
00092     
00093     _tm_prob->msg_env = this;
00094     _tm_prob->start_time = CoinWallclockTime();
00095     _my_id = _tm_id;
00096 
00097     // BCP_tm_user_init() returns a BCP_tm_user* and that will be part of p.
00098     // Also, it should take care of every I/O, heuristic startup, etc. the user
00099     // wants to do. Wreak havoc in p if (s)he wants.
00100     // BUT: once this function returns, the processes designated to be part of
00101     // BCP must be idle and waiting for a message. See the
00102     // BCP_slave_process_stub() function below. 
00103     _tm_prob->user = user_init->tm_init(*_tm_prob, _argnum, _arglist);
00104     _tm_prob->user->setTmProblemPointer(_tm_prob);
00105     _tm_prob->packer = user_init->packer_init(_tm_prob->user);
00106     _tm_prob->packer->user_class = _tm_prob->user;
00107 
00108     // Initialize the number of leaves assigned to CP's and VP's as 0
00109 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00110     if (_tm_prob->param(BCP_tm_par::CpProcessNum) > 0) {
00111        _tm_prob->leaves_per_cp.reserve(_tm_prob->slaves.cp->procs().size());
00112        for (int i = _tm_prob->slaves.cp->procs().size() - 1; i >= 0; --i)
00113             _tm_prob->leaves_per_cp.unchecked_push_back
00114                 (std::make_pair(_tm_prob->slaves.cp->procs()[i], 0));
00115     }
00116     if (_tm_prob->param(BCP_tm_par::VpProcessNum) > 0) {
00117         _tm_prob->leaves_per_vp.reserve(_tm_prob->slaves.vp->procs().size());
00118         for (int i = _tm_prob->slaves.vp->procs().size() - 1; i >= 0; --i)
00119             _tm_prob->leaves_per_vp.unchecked_push_back
00120                 (std::make_pair(_tm_prob->slaves.vp->procs()[i], 0));
00121     }
00122 #endif
00123 
00124     // Set the core (variables & cuts)
00125     _tm_prob->core = BCP_tm_create_core(*_tm_prob);
00126     _tm_prob->core_as_change = new BCP_problem_core_change;
00127     *_tm_prob->core_as_change = *_tm_prob->core;
00128 
00129     // Initialize the root of the search tree (can't invoke directly
00130     // p.user->create_root(), b/c the root might contain extra vars/cuts and
00131     // it's better if we take care of inserting them into the appropriate data
00132     // structures.
00133     BCP_tm_node* root = BCP_tm_create_root(*_tm_prob);
00134 
00135     _tm_prob->next_phase_nodes.push_back(root);
00136     _tm_prob->search_tree.insert(root);
00137 
00138     BCP_sanity_checks(*_tm_prob);
00139 
00140     // The TM is ready to roll
00141 
00142     //=========================================================================
00143     // Create the slave "processes"
00144     //=========================================================================
00145     // LP
00146     BCP_lp_prob* _lp_prob = new BCP_lp_prob(_lp_id, _tm_id);
00147     processes[_lp_id] = _lp_prob;
00148     _lp_prob->msg_env = new BCP_single_environment(_lp_id);
00149     _tm_prob->lp_procs.push_back(_lp_id);
00150     _tm_prob->lp_scheduler.add_free_ids(_tm_prob->lp_procs.size(),
00151                                         &_tm_prob->lp_procs[0]);
00152     _tm_prob->lp_scheduler.
00153       setParams(_tm_prob->param(BCP_tm_par::LPscheduler_OverEstimationStatic),
00154                 _tm_prob->param(BCP_tm_par::LPscheduler_SwitchToRateThreshold),
00155                 10.0, /* estimated root time */
00156                 _tm_prob->param(BCP_tm_par::LPscheduler_FactorTimeHorizon),
00157                 _tm_prob->param(BCP_tm_par::LPscheduler_OverEstimationRate),
00158                 _tm_prob->param(BCP_tm_par::LPscheduler_MaxNodeIdRatio),
00159                 _tm_prob->param(BCP_tm_par::LPscheduler_MaxNodeIdNum),
00160                 _tm_prob->param(BCP_tm_par::LPscheduler_MaxSbIdNum),
00161                 _tm_prob->param(BCP_tm_par::LPscheduler_MinSbIdNum));
00162 
00163     //-------------------------------------------------------------------------
00164     BCP_cg_prob* _cg_prob = 0;
00165     BCP_vg_prob* _vg_prob = 0;
00166 //     BCP_cp_prob* _cp_prob = 0;
00167 //     BCP_vp_prob* _vp_prob = 0;
00168     //-------------------------------------------------------------------------
00169     // CG
00170 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00171     if (_tm_prob->param(BCP_tm_par::CgProcessNum) > 0) {
00172         _cg_prob = new BCP_cg_prob(_cg_id, _tm_id);
00173         processes[_cg_id] = _cg_prob;
00174         _cg_prob->msg_env = new BCP_single_environment(_cg_id);
00175         _tm_prob->slaves.cg = new BCP_proc_array;
00176         _tm_prob->slaves.cg->add_proc(_cg_id);
00177         _tm_prob->slaves.all->add_proc(_cg_id);
00178     }
00179     //-------------------------------------------------------------------------
00180     // VG
00181     if (_tm_prob->param(BCP_tm_par::VgProcessNum) > 0) {
00182         _vg_prob = new BCP_vg_prob(_vg_id, _tm_id);
00183         processes[_vg_id] = _vg_prob;
00184         _vg_prob->msg_env = new BCP_single_environment(_vg_id);
00185         _tm_prob->slaves.vg = new BCP_proc_array;
00186         _tm_prob->slaves.vg->add_proc(_vg_id);
00187         _tm_prob->slaves.all->add_proc(_vg_id);
00188     }
00189     //-------------------------------------------------------------------------
00190     // CP
00191     if (_tm_prob->param(BCP_tm_par::CpProcessNum) > 0) {
00192         _cp_prob = new BCP_cp_prob(_cp_id, _tm_id);
00193         processes[_cp_id] = _cp_prob;
00194         _cp_prob->msg_env = new BCP_single_environment(_cp_id);
00195         _tm_prob->slaves.cp = new BCP_proc_array;
00196         _tm_prob->slaves.cp->add_proc(_cp_id);
00197         _tm_prob->slaves.all->add_proc(_cp_id);
00198     }
00199     //-------------------------------------------------------------------------
00200     // VP
00201     if (_tm_prob->param(BCP_tm_par::VpProcessNum) > 0) {
00202         _vp_prob = new BCP_vp_prob(_vp_id, _tm_id);
00203         processes[_vp_id] = _vp_prob;
00204         _vp_prob->msg_env = new BCP_single_environment(_vp_id);
00205         _tm_prob->slaves.vp = new BCP_proc_array;
00206         _tm_prob->slaves.vp->add_proc(_vp_id);
00207         _tm_prob->slaves.all->add_proc(_vp_id);
00208     }
00209 #endif
00210 
00211     //=========================================================================
00212     // distribute the core to the slave processes
00213     // LP
00214     _tm_prob->msg_buf.clear();
00215     _tm_prob->core->pack(_tm_prob->msg_buf);
00216     BCP_lp_process_core(*_lp_prob, _tm_prob->msg_buf);
00217 
00218     // CG
00219     if (_cg_prob) {
00220         _tm_prob->msg_buf.clear();
00221         _tm_prob->core->pack(_tm_prob->msg_buf);
00222         _cg_prob->core->unpack(_tm_prob->msg_buf);
00223     }
00224     // VG
00225     if (_vg_prob) {
00226         _tm_prob->msg_buf.clear();
00227         _tm_prob->core->pack(_tm_prob->msg_buf);
00228         _vg_prob->core->unpack(_tm_prob->msg_buf);
00229     }
00230     // CP
00231     // VP
00232 
00233     //=========================================================================
00234     // Initialize the slave "processes"
00235     //=========================================================================
00236     // LP (it already has the core)
00237     // copy over the parameter structure
00238     _lp_prob->par = _tm_prob->slave_pars.lp;
00239     // create the user universe
00240     _lp_prob->user = user_init->lp_init(*_lp_prob);
00241     _lp_prob->user->setLpProblemPointer(_lp_prob);
00242     _lp_prob->packer = user_init->packer_init(_lp_prob->user);
00243     _lp_prob->packer->user_class = _lp_prob->user;
00244 
00245     // copy over the user info
00246     _tm_prob->msg_buf.clear();
00247     _tm_prob->user->pack_module_data(_tm_prob->msg_buf, BCP_ProcessType_LP);
00248     _lp_prob->user->unpack_module_data(_tm_prob->msg_buf);
00249     _lp_prob->master_lp = _lp_prob->user->initialize_solver_interface();
00250 
00251     _lp_prob->upper_bound = std::min<double>(_tm_prob->ub(), BCP_DBL_MAX);
00252     //-------------------------------------------------------------------------
00253     if (_cg_prob) {
00254         // CG (it already has the core)
00255         // copy over the parameter structure
00256         _cg_prob->par = _tm_prob->slave_pars.cg;
00257         // create the user universe
00258         _cg_prob->user = user_init->cg_init(*_cg_prob);
00259         _cg_prob->user->setCgProblemPointer(_cg_prob);
00260         _cg_prob->packer = user_init->packer_init(_cg_prob->user);
00261         _cg_prob->packer->user_class = _cg_prob->user;
00262         // copy over the user info
00263         _tm_prob->msg_buf.clear();
00264         _tm_prob->user->pack_module_data(_tm_prob->msg_buf,
00265                                          BCP_ProcessType_CG);
00266         if (_cg_prob->user)
00267             _cg_prob->user->unpack_module_data(_tm_prob->msg_buf);
00268     }
00269     //-------------------------------------------------------------------------
00270     // VG
00271     if (_vg_prob) {
00272         // VG (it already has the core)
00273         // copy over the parameter structure
00274         _vg_prob->par = _tm_prob->slave_pars.vg;
00275         // create the user universe
00276         _vg_prob->user = user_init->vg_init(*_vg_prob);
00277         _vg_prob->user->setVgProblemPointer(_vg_prob);
00278         _vg_prob->packer = user_init->packer_init(_vg_prob->user);
00279         _vg_prob->packer->user_class = _vg_prob->user;
00280         // copy over the user info
00281         _tm_prob->msg_buf.clear();
00282         _tm_prob->user->pack_module_data(_tm_prob->msg_buf,
00283                                          BCP_ProcessType_VG);
00284         if (_vg_prob->user)
00285             _vg_prob->user->unpack_module_data(_tm_prob->msg_buf);
00286     }
00287     //-------------------------------------------------------------------------
00288     // CP
00289     // VP
00290 
00291     //=========================================================================
00292     // Back to TM
00293     bool something_died = false;
00294     try {
00295         for ( _tm_prob->phase = 0; true ; ++_tm_prob->phase) {
00296             // insert the nodes in next_phase_nodes into candidates, print out
00297             // some statistics about the previous phase (if there was one) and
00298             // do some other stuff, too.
00299             BCP_tm_tasks_before_new_phase(*_tm_prob);
00300             // do one phase 
00301             // While there are nodes waiting to be processed (or being
00302             // processed) we don't go to the next phase
00303             something_died = false;
00304             while (! _tm_prob->candidate_list.empty() ||
00305                    _tm_prob->lp_scheduler.numNodeIds() > 0){
00306                 // Fill up as many free LP processes as we can
00307                 if (BCP_tm_start_new_nodes(*_tm_prob) == BCP_NodeStart_Error) {
00308                     // Error indicates that something has died
00309                     something_died = true;
00310                     break;
00311                 }
00312                 // No need to process messages, they have all been processed
00313                 // (single environment!) Also all the "processes" are alive.
00314             }
00315             // If nothing is left for the next phase or if something has died
00316             // then quit the infinite loop.
00317             if (_tm_prob->next_phase_nodes.size() == 0 || something_died)
00318                 break;
00319         }
00320     }
00321     catch (BCP_fatal_error& err) {
00322         // there can be only one, a timeout
00323     }
00324 
00325     // everything is done
00326     BCP_tm_wrapup(_tm_prob, _lp_prob, _cg_prob, _vg_prob, true);
00327     // sleep(7200);
00328 
00329     delete _lp_prob;
00330 
00331     if (_cg_prob) {
00332         delete _cg_prob;
00333     }
00334     if (_vg_prob) {
00335         delete _vg_prob;
00336     }
00337       
00338     //    if (_cp_prob)
00339     //       delete _cp_prob;
00340     //    if (_vp_prob)
00341     //       delete _vp_prob;
00342       
00343     delete _tm_prob;
00344 
00345     return 0; //fake, just to quiet the compiler
00346 }
00347 
00348 //-----------------------------------------------------------------------------
00349 
00350 int
00351 BCP_single_environment::parent_process() {
00352     throw BCP_fatal_error("\
00353 BCP_single_environment::parent_process() invoked.\n");
00354     return 0; // to satisfy aCC on HP-UX
00355 }
00356 
00357 bool
00358 BCP_single_environment::alive(const int pid)
00359 {
00360     return true;
00361 }
00362 
00363 const int* 
00364 BCP_single_environment::alive(int num, const int* pids)
00365 {
00366   return NULL;
00367 }
00368 
00369 //-----------------------------------------------------------------------------
00370 
00371 void
00372 BCP_single_environment::send(const int target,
00373                              const BCP_message_tag tag)
00374 {
00375     BCP_process* target_process = processes[target];
00376     BCP_buffer& target_buf = target_process->get_message_buffer();
00377     target_buf.clear();
00378     target_buf._sender = _my_id;
00379     target_buf._msgtag = tag;
00380     target_process->process_message();
00381 }
00382 
00383 void
00384 BCP_single_environment::send(const int target,
00385                              const BCP_message_tag tag,
00386                              const BCP_buffer& buf)
00387 {
00388     BCP_process* target_process = processes[target];
00389     BCP_buffer& target_buf = target_process->get_message_buffer();
00390     target_buf = buf;
00391     target_buf._sender = _my_id;
00392     target_buf._msgtag = tag;
00393     target_process->process_message();
00394 }
00395    
00396 //-----------------------------------------------------------------------------
00397 
00398 void
00399 BCP_single_environment::multicast(int num, const int* targets,
00400                                   const BCP_message_tag tag)
00401 {
00402   for (int i = 0; i < num; ++i) {
00403     send(targets[i], tag);
00404   }
00405 }
00406 
00407 void
00408 BCP_single_environment::multicast(int num, const int* targets,
00409                                   const BCP_message_tag tag,
00410                                   const BCP_buffer& buf)
00411 {
00412   for (int i = 0; i < num; ++i) {
00413     send(targets[i], tag, buf);
00414   }
00415 }
00416 
00417 //-----------------------------------------------------------------------------
00418 
00419 void
00420 BCP_single_environment::receive(const int source,
00421                                 const BCP_message_tag tag,
00422                                 BCP_buffer& buf, const double timeout)
00423 {
00424     // In the single_environment this is not really needed. Report if it's
00425     // called with anything but:
00426     //   BCP_UpperBound, BCP_Msg_DivingInfo or BCP_Msg_PricedRoot.
00427     if (tag != BCP_Msg_UpperBound &&
00428         tag != BCP_Msg_DivingInfo)
00429         printf("BCP_single_environment::receive() is called with %i as tag.\n",
00430                tag);
00431 }
00432 
00433 //-----------------------------------------------------------------------------
00434 
00435 bool
00436 BCP_single_environment::probe(const int source,
00437                               const BCP_message_tag tag)
00438 {
00439     // In the single_environment this is not needed.
00440     return false;
00441 }
00442 
00443 //-----------------------------------------------------------------------------
00444 // These should never be invoked in a BCP_single_environment
00445 
00446 int
00447 BCP_single_environment::start_process(const BCP_string& exe,
00448                                       const bool debug)
00449 {
00450     throw BCP_fatal_error("start_process() called!\n");
00451     return 0; // to satisfy aCC on HP-UX
00452 }
00453 
00454 int
00455 BCP_single_environment::start_process(const BCP_string& exe,
00456                                       const BCP_string& machine,
00457                                       const bool debug)
00458 {
00459     throw BCP_fatal_error("start_process() called!\n");
00460     return 0; // to satisfy aCC on HP-UX
00461 }
00462 
00463 bool
00464 BCP_single_environment::start_processes(const BCP_string& exe,
00465                                         const int proc_num,
00466                                         const bool debug,
00467                                         int* ids)
00468 {
00469     throw BCP_fatal_error("start_processes() called!\n");
00470     return false; // to satisfy aCC on HP-UX
00471 }
00472 
00473 bool
00474 BCP_single_environment::start_processes(const BCP_string& exe,
00475                                         const int proc_num,
00476                                         const BCP_vec<BCP_string>& machines,
00477                                         const bool debug,
00478                                         int* ids)
00479 {
00480     throw BCP_fatal_error("start_processes() called!\n");
00481     return false; // to satisfy aCC on HP-UX
00482 }
00483 
00484 //-----------------------------------------------------------------------------
00485 
00486 // void BCP_single_environment::stop_process(const int process) {
00487 //    check_error( pvm_kill(BCP_is_single_id(process, "stop_process()")),
00488 //              "stop_process()");
00489 // }
00490 
00491 // void BCP_single_environment::stop_processes(const BCP_proc_array* processes){
00492 //    BCP_vec<int>::const_iterator first = processes.procs.begin();
00493 //    BCP_vec<int>::const_iterator last = pprocesses.procs.end();
00494 //    while (first != last)
00495 //       check_error( pvm_kill(BCP_is_single_id(*first, "stop_processes()")),
00496 //                 "stop_processes()");
00497 //       ++first;
00498 //    }
00499 // }

Generated on Mon Aug 3 03:02:15 2009 by  doxygen 1.4.7