3 #include "CoinTime.hpp"
44 bool success = machines.
size() == 0 ?
53 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
58 if (machines.
size() == 0) {
63 p.slaves.all->add_procs(p.slaves.cg->procs().begin(),
64 p.slaves.cg->procs().end());
71 if (machines.
size() == 0) {
76 p.slaves.all->add_procs(p.slaves.vg->procs().begin(),
77 p.slaves.vg->procs().end());
84 if (machines.
size() == 0) {
89 p.slaves.all->add_procs(p.slaves.cp->procs().begin(),
90 p.slaves.cp->procs().end());
97 if (machines.
size() == 0) {
102 p.slaves.all->add_procs(p.slaves.vp->procs().begin(),
103 p.slaves.vp->procs().end());
118 template <
typename T>
void
122 int num,
const int* pids)
135 const double wallclockInit = CoinWallclockTime(-1);
151 template <
typename T>
void
155 const std::vector<int>& pids)
164 int num,
const int* pids)
175 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
186 procs ? *procs : p.slaves.cg->procs());
190 procs ? *procs : p.slaves.vg->procs());
202 const std::vector<int>& pids)
213 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
230 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
244 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
257 int * pids =
new int[branchNum];
275 std::map<int, BCP_tm_node_to_send*>::iterator index__node;
284 static int msg_count = 0;
340 const bool betterval =
342 const bool bettersol =
353 if (allval || allsol || ((betterval || bettersol) && better)) {
355 printf(
"TM: Solution found at %.3f sec.\n",
365 sprintf(bdstr,
"infinity");
370 printf(
"TM %.3f: Sol from proc: %i val: %f (prev best: %s) tree size/procd: %i/%i cand list ins/size: %i/%i\n",
373 tree_size, tree_proc,
374 cand_list_ins, cand_list_size);
375 if (allsol || (bettersol && better)) {
427 throw BCP_fatal_error(
"TM: node data from TMS for node not waiting.\n");
429 node_to_send = index__node->second;
440 throw BCP_fatal_error(
"TM: var list from TMS for node not waiting.\n");
442 node_to_send = index__node->second;
453 throw BCP_fatal_error(
"TM: cut list from TMS for node not waiting.\n");
455 node_to_send = index__node->second;
472 Unexpected BCP_Msg_LpStatistics message in BCP_tm_prob::process_message.\n");
488 Unknown message in BCP_tm_prob::process_message.\n");
496 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
498 msg_count % test_frequency == 0) {
502 if (slaves.lp->procs().size() == 0)
511 TM: Time has ran out.\n\
512 TM: Best lower bound in this phase: %f\n", lb);
519 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
526 if (dead_process_i == p.slaves.all->procs().end())
530 int dead_pid = *dead_process_i;
531 bool continue_testing =
true;
534 if (continue_testing) {
535 printf(
"TM: Removing dead LP (pid: %i).\n", dead_pid);
537 continue_testing =
false;
540 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
542 if (continue_testing && p.slaves.cg) {
543 i = p.slaves.cg->index_of_proc(dead_process);
545 printf(
"TM: CG #%i is dead. Removing the LP/CG/VG/triplet.\n", i);
547 continue_testing =
false;
551 if (continue_testing && p.slaves.vg) {
552 i = p.slaves.vg->index_of_proc(dead_process);
554 printf(
"TM: VG #%i is dead. Removing the LP/CG/VG/triplet.\n", i);
556 continue_testing =
false;
561 p.slaves.all->delete_proc(dead_pid);
572 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
573 if (node->
cp != -1) {
579 TM: non-existing CP was assigned to a just pruned node.\n");
581 if (--proc->second == 0)
582 p.slaves.cp->set_proc_free(proc->first);
584 if (node->
vp != -1) {
590 TM: non-existing VP was assigned to a just pruned node.\n");
592 if (--proc->second == 0)
593 p.slaves.vp->set_proc_free(proc->first);
604 printf(
"For now we can't remove dead processes...\n");
606 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
609 if (node->
lp != dead_pid)
613 if (node->
cp != -1) {
620 if (node->
vp != -1) {
629 node->
lp = node->
cg = node->
vg = -1;
634 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
637 proc = p.slaves.cg->procs()[index];
638 p.slaves.cg->delete_proc(index);
639 p.slaves.all->delete_proc(p.slaves.all->index_of_proc(proc));
642 proc = p.slaves.vg->procs()[index];
643 p.slaves.vg->delete_proc(index);
644 p.slaves.all->delete_proc(p.slaves.all->index_of_proc(proc));
648 p.slaves.lp->delete_proc(dead_pid);
649 p.slaves.all->delete_proc(dead_pid);
653 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
693 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
695 p.slaves.cg->set_proc_free(node->
cg);
697 p.slaves.vg->set_proc_free(node->
vg);
700 node->
lp = node->
cg = node->
vg = -1;
711 int sender = buf.
sender();
716 for (i = 0; i < lp_num; ++i)
722 for (i = 0; i < cg_num; ++i)
728 for (i = 0; i < vg_num; ++i)
734 for (i = 0; i < cp_num; ++i)
740 for (i = 0; i < vp_num; ++i)
745 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
747 if (p.slaves.cg->size() > 0) {
748 if (cg_num != lp_num) {
750 BCP: config change: CG's are running thus the number of new CG's must be\
751 the same as the number of new LP's. Not changing anything.\n");
758 BCP: config change: CG's are not running thus no new CG's can be started.\
759 Not changing anything.\n");
764 if (p.slaves.vg->size() > 0) {
765 if (vg_num != lp_num) {
767 BCP: config change: VG's are running thus the number of new VG's must be\
768 the same as the number of new LP's. Not changing anything.\n");
775 BCP: config change: VG's are not running thus no new VG's can be started.\
776 Not changing anything.\n");
787 BCP_proc_array* new_lps =
789 p.slaves.lp->add_procs(new_lps->procs().begin(),
790 new_lps->procs().end());
793 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
796 BCP_proc_array* new_cgs =
798 p.slaves.cg->add_procs(new_cgs->procs().begin(),
799 new_cgs->procs().end());
804 BCP_proc_array* new_vgs =
806 p.slaves.vg->add_procs(new_vgs->procs().begin(),
807 new_vgs->procs().end());
812 BCP_proc_array* new_cps =
814 p.slaves.cp->add_procs(new_cps->procs().begin(),
815 new_cps->procs().end());
820 BCP_proc_array* new_vps =
822 p.slaves.vp->add_procs(new_vps->procs().begin(),
823 new_vps->procs().end());
BCP_buffer msg_buf
members to measure how long it took to process the root node.
virtual void display_feasible_solution(const BCP_solution *sol)
Display a feasible solution.
void BCP_tm_notify_about_new_phase(BCP_tm_prob &p)
virtual void send(const int target, const BCP_message_tag tag)=0
Send an empty message (message tag only) to the process given by the frist argument.
virtual bool start_processes(const BCP_string &exe, const int proc_num, const bool debug, int *ids)=0
Spawn proc_num processes, all with the same executable.
Invoke the user-written "display_feasible_solution" function if a better integral feasible solution i...
BCP_buffer & pack(const T &value)
Pack a single object of type T.
BCP_parameter_set< BCP_vg_par > vg
int next_cut_index_set_start
BCP_parameter_set< BCP_cg_par > cg
void BCP_tm_notify_process_type(BCP_tm_prob &p, BCP_process_t ptype, int num, const int *pids)
Used to indicate that there is no message in the buffer of a process.
BCP_buffer & unpack(T &value)
Unpack a single object of type T.
virtual double objective_value() const =0
The method returning the objective value of the solution.
virtual void pack_module_data(BCP_buffer &buf, BCP_process_t ptype)
Pack the initial information (info that the user wants to send over) for the process specified by the...
std::map< int, BCP_tm_node * > active_nodes
A map from the process ids to the nodes (what they work on)
virtual void change_candidate_heap(CoinSearchTreeManager &candidates, const bool new_solution)
Request a list of process ids the LP can use to do distributed strong branching.
void BCP_tm_unpack_priced_root(BCP_tm_prob &p, BCP_buffer &buf)
The message contains the statistics the LP process collected.
Request an index set for variables to be genarated.
BCP_tm_node_status status
BCP_process_t
This enumerative constant describes the various process types.
Request an index set for cuts to be generated.
BCP_vec< std::pair< int, int > > leaves_per_cp
static void BCP_tm_change_config(BCP_tm_prob &p, BCP_buffer &buf)
BCP_tm_node * BCP_tm_unpack_node_no_branching_info(BCP_tm_prob &p, BCP_buffer &buf)
The TM sends the description of the core formulation to the slave process.
The lower bound corresponding to the node is above the upper bound.
int sender() const
Return a const pointer to the process id of the sender of the message in the buffer.
The number of Variable Generator processes that should be spawned.
The TM sends the process type to the process (LP, Cut Generator, etc.)
CoinSearchTreeManager candidate_list
Print the time (and the solution value and solution if the above paramters are set appropriately) whe...
BCP_vec< BCP_tm_node * > next_phase_nodes
a vector of nodes to be processed in the next phase
This class is a very simple impelementation of a constant length string.
virtual BCP_warmstart * unpack_warmstart(BCP_buffer &buf, bool report_if_default=false)
Unpack warmstarting information.
void add_free_ids(int numIds, const int *ids)
Pass in a list of freeIds_ to add.
virtual BCP_solution * unpack_feasible_solution(BCP_buffer &buf)
Unpack a MIP feasible solution that was packed by the BCP_lp_user::pack_feasible_solution() method...
void BCP_tm_stop_processes(BCP_tm_prob &p)
Warmstarting information for the LP solver.
Indicates whether message passing is serial (all processes are on the same processor) or not...
void push_back(const_reference x)
Append x to the end of the vector.
virtual void process_message()
void BCP_tm_start_processes(BCP_tm_prob &p)
void BCP_tm_remove_vg(BCP_tm_prob &p, const int index)
void BCP_tm_remove_lp(BCP_tm_prob &p, const int index)
This is the class serves as a holder for a set of parameters.
Invoke the user-written "display_feasible_solution" function if any* feasible solution is found...
Maximum allowed running time.
int request_sb_ids(int numIds, int *ids)
Request for a number of id's to do some strong branching.
void fint fint fint real fint real real real real real real real real real * e
void BCP_tm_unpack_node_with_branching_info(BCP_tm_prob &p, BCP_buffer &buf)
virtual void pack_warmstart(const BCP_warmstart *ws, BCP_buffer &buf, bool report_if_default=false)
Pack warmstarting information.
BCP_vec< BCP_tm_node * > nodes_to_free
Print the value of the integer solution when a solution better than the current best solution is foun...
void fint fint fint real fint real real real real real real real real real fint real fint * lp
The number of Cut Generator processes that should be spawned.
int next_var_index_set_start
An LP process (that is used as a strong branching node) indicates that it's finished.
BCP_vec< std::pair< int, int > > leaves_per_vp
The node is discarded (fathomed).
void pack(BCP_buffer &buf) const
Pack the contents of the core description into the buffer.
The TM sends the appropriate parameters to the slave process.
The warmstart information at the end of the root.
bool receive_cuts(BCP_buffer &buf)
return true if has everything to send the thing off to the LP.
void release_sb_id(int id)
Gives back to scheduler an id used for strong branching.
virtual void process_message(BCP_buffer &buf)
Process a message that has been sent by another process' user part to this process' user part...
The TM sends the initial user packed information to the slave process.
TM warns an LP process that the second phase will start.
void BCP_tm_free_procs_of_node(BCP_tm_prob &p, BCP_tm_node *node)
void BCP_tm_idle_processes(BCP_tm_prob &p)
void clear()
Completely clear the buffer.
BCP_message_tag msgtag() const
Return the message tag of the message in the buffer.
void fint fint fint real fint real real real real real real real real real fint real fint fint fint real * ws
The lower bound corresponding to the node is above the upper bound.
In addition to the node description, branching information is sent as well so that the children of th...
bool root_pricing_unpacked
Set to true if the result of root pricing is already unpacked.
Currently there isn't any error handling in BCP.
double true_lower_bound(const BCP_tm_node *node) const
Return the worst true lower bound in the search tree.
BCP_message_environment * msg_env
A class that holds the methods about how to pack things.
BCP_user_pack * packer
A class that holds the methods about how to pack things.
Indicates whether to debug Cut Pool processes or not.
static bool abort_on_error
size_t size() const
Return the current number of entries.
iterator end()
Return an iterator to the end of the object.
Send index set for cuts to be generated in the future.
std::vector< int > lp_procs
members to measure how long it took to process the root node.
void BCP_tm_notify_processes(BCP_tm_prob &p)
Print the value of any integer feasible solution found.
This class describes the message buffer used for all processes of BCP.
static std::map< int, BCP_tm_node_to_send * > waiting
void BCP_tm_broadcast_ub(BCP_tm_prob &p)
void BCP_tm_initialize_process_type(BCP_tm_prob &p, BCP_process_t ptype, BCP_parameter_set< T > &par, int num, const int *pids)
bool receive_vars(BCP_buffer &buf)
return true if has everything to send the thing off to the LP.
BCP_scheduler lp_scheduler
members to measure how long it took to process the root node.
BCP_parameter_set< BCP_lp_par > lp
BCP_tm_user * user
A class that holds the methods about how to pack things.
Used by the user to send a message to the user portion of the other process.
Any process to TM: a process has died.
Send index set for variables to be generated in the future.
Indicates whether to debug Cut Generator processes or not.
The number of Variable Pool processes that should be spawned.
BCP_slave_params slave_pars
virtual bool replace_solution(const BCP_solution *old_sol, const BCP_solution *new_sol)
Decide whether to replace old_sol with new_sol.
std::map< int, int > ts_space
Any process to TM or TM to any process: a new upper bound found.
Send a list of process ids the LP can use to do distributed strong branching.
virtual bool alive(const int pid)=0
Test if the process given by the argument is alive or not.
bool receive_node_desc(BCP_buffer &buf)
return true if has everything to send the thing off to the LP.
void BCP_tm_provide_SB_processes(BCP_tm_prob &p)
Indicates whether to debug Variable Pool processes or not.
void release_node_id(int id)
Give back an id to scheduler used for processing a node.
void BCP_tm_modify_pool_counters(BCP_tm_prob &p, BCP_tm_node *node)
void pack(BCP_buffer &buf)
Pack the parameter set into the buffer.
BCP_vec< std::pair< int, int > >::iterator BCP_tm_identify_process(BCP_vec< std::pair< int, int > > &proclist, int proc)
The name of the executable that's running (and that should be spawned on the other processors...
Indicates whether to debug Variable Generator processes or not.
char param(BCP_tm_par::chr_params key) const
BCP_parameter_set< BCP_ts_par > ts
The number of Cut Pool processes that should be spawned.
Indicates whether to debug LP processes or not.
The message contains a new MIP feasible solution.
void BCP_tm_remove_cg(BCP_tm_prob &p, const int index)
virtual void multicast(int num, const int *targets, const BCP_message_tag tag)=0
Send an empty message (message tag only) to all the processes in the process array.
bool BCP_tm_test_machine(BCP_tm_prob &p)
This is the abstract base class for a solution to a Mixed Integer Programming problem.
void BCP_tm_rebroadcast_root_warmstart(BCP_tm_prob &p)
The number of LP processes that should be spawned.