BCP_cg_main.cpp
Go to the documentation of this file.
1 // Copyright (C) 2000, International Business Machines
2 // Corporation and others. All Rights Reserved.
3 #include <cstdio>
4 #include <cerrno>
5 #ifdef _MSC_VER
6 #include <process.h>
7 #endif
8 
9 #include "BcpConfig.h"
10 #include "BCP_os.hpp"
11 
12 #include "BCP_USER.hpp"
13 #include "BCP_error.hpp"
14 #include "BCP_buffer.hpp"
15 #include "BCP_message.hpp"
16 #include "BCP_problem_core.hpp"
17 #include "BCP_main_fun.hpp"
18 #include "BCP_cg_user.hpp"
19 #include "BCP_cg.hpp"
20 
21 //#############################################################################
22 
24  USER_initialize* user_init,
25  int my_id, int parent, double ub)
26 {
27  BCP_cg_prob p(my_id, parent);
28  p.upper_bound = ub;
29  p.msg_env = msg_env;
30 
31  // wait for the message with the parameters and unpack it
32  p.msg_buf.clear();
33  msg_env->receive(parent, BCP_Msg_ProcessParameters, p.msg_buf, -1);
34  p.par.unpack(p.msg_buf);
35 
36  // Let us be nice
37  setpriority(PRIO_PROCESS, 0, p.par.entry(BCP_cg_par::NiceLevel));
38 
39  FILE* logfile = 0;
40 
42  if (! (p.par.entry(BCP_cg_par::LogFileName) == "")) {
43  int len = log.length();
44  char *logname = new char[len + 300];
45  memcpy(logname, log.c_str(), len);
46  memcpy(logname + len, "-cg-", 4);
47  len += 4;
48  gethostname(logname + len, 255);
49  len = strlen(logname);
50  logname[len++] = '-';
51  sprintf(logname + len, "%i", static_cast<int>(GETPID));
52  logfile = freopen(logname, "a", stdout);
53  if (logfile == 0) {
54  fprintf(stderr, "Error while redirecting stdout: %i\n", errno);
55  abort();
56  }
57  setvbuf(logfile, NULL, _IOLBF, 0); // make it line buffered
58  delete[] logname;
59  } else {
60  setvbuf(stdout, NULL, _IOLBF, 0); // make it line buffered
61  }
62 
63  // now create the user universe
64  p.user = user_init->cg_init(p);
66  p.packer = user_init->packer_init(p.user);
67  p.packer->user_class = p.user;
68 
69  // wait for the core description and process it
70  p.msg_buf.clear();
72  p.core->unpack(p.msg_buf);
73 
74  // wait for the user info
75  p.msg_buf.clear();
76  msg_env->receive(parent, BCP_Msg_InitialUserInfo, p.msg_buf, -1);
78 
79  // ok, we're all geared up to generate cuts
80  // wait for messages and process them...
81  BCP_message_tag msgtag;
83  while (true) {
84  p.msg_buf.clear();
86  msgtag = p.msg_buf.msgtag();
87  if (msgtag == BCP_Msg_NoMessage) {
88  // test if the TM is still alive
89  if (! p.msg_env->alive(parent))
90  throw BCP_fatal_error("CG: The TM has died -- CG exiting\n");
91  } if (msgtag == BCP_Msg_ProcessType) {
92  p.msg_buf.unpack(ptype);
93  break;
94  } else {
95  if (BCP_cg_process_message(p, p.msg_buf)) {
96  // BCP_Msg_FinishedBCP arrived
97  break;
98  }
99  }
100  }
101  if (logfile)
102  fclose(logfile);
103 
104  return ptype;
105 }
106 
107 //#############################################################################
108 
109 bool
111 {
112  p.process_message();
113  return (p.msg_buf.msgtag() == BCP_Msg_FinishedBCP);
114 }
115 
116 void
118 {
119  while (true) {
120  const BCP_message_tag msgtag = msg_buf.msgtag();
121  switch (msgtag) {
125  case BCP_Msg_ForCG_User:
127  sender = msg_buf.sender();
129  break;
130 
131  case BCP_Msg_UpperBound:
132  double new_ub;
133  msg_buf.unpack(new_ub);
134  if (new_ub < upper_bound)
135  upper_bound = new_ub;
136  break;
137 
139  phase++;
140  break;
141 
142  case BCP_Msg_FinishedBCP:
143  return;
144 
145  default:
146  // a bogus message
147  printf("Unknown message type arrived to CG: %i\n", msg_buf.msgtag());
148  }
149  msg_buf.clear();
150 
151  if (probe_messages()) {
152  // if there's something interesting in the queue that overrides
153  // the pervious message then just continue to get the next message
154  continue;
155  }
156  // if there's nothing interesting then msgtag has the message tag of
157  // the last unpacked message. We got to do something only if the
158  // message is an lp solution, everything else has already been taken
159  // care of.
160  if (msgtag == BCP_Msg_ForCG_PrimalNonzeros ||
161  msgtag == BCP_Msg_ForCG_PrimalFractions ||
162  msgtag == BCP_Msg_ForCG_PrimalFull ||
163  msgtag == BCP_Msg_ForCG_User) {
165  // upon return send a no more cuts message
166  double timing = 0.0; // *FIXME*
167  msg_buf.clear();
170  }
171  break;
172  }
173 }
BCP_message_tag
This enumerative constant describes the message tags different processes of BCP understand.
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.
BCP_buffer & pack(const T &value)
Pack a single object of type T.
Definition: BCP_buffer.hpp:177
BCP has finished.
int node_index
The index of search tree node where the solution was generated.
Definition: BCP_cg.hpp:95
BCP_vec< double > x
The primal values corresponding to the variables above.
Definition: BCP_cg.hpp:85
Used when receiving, message with any message tag will be received.
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.
Definition: BCP_buffer.hpp:186
int sender
The process id of the LP process that sent the solution.
Definition: BCP_cg.hpp:87
virtual void receive(const int source, const BCP_message_tag tag, BCP_buffer &buf, const double timeout)=0
Blocking receive with timeout.
BCP_problem_core * core
The description of the core of the problem.
Definition: BCP_cg.hpp:67
const int BCP_AnyProcess
Definition: BCP_message.hpp:21
This is an abstract base class that describes the message passing environment.
Definition: BCP_message.hpp:30
BCP_process_t
This enumerative constant describes the various process types.
All primal variables.
char entry(const chr_params key) const
const char * c_str() const
Definition: BCP_string.hpp:19
virtual BCP_user_pack * packer_init(BCP_user_class *p)
Definition: BCP_USER.hpp:225
The TM sends the description of the core formulation to the slave process.
int sender() const
Return a const pointer to the process id of the sender of the message in the buffer.
Definition: BCP_buffer.hpp:93
This class is the central class of the Cut Generator process.
Definition: BCP_cg.hpp:32
The TM sends the process type to the process (LP, Cut Generator, etc.)
void unpack(BCP_buffer &buf)
Unpack the contents of the core description from the buffer.
#define setpriority(x, y, z)
Definition: BCP_os.hpp:13
This class is a very simple impelementation of a constant length string.
Definition: BCP_string.hpp:13
bool BCP_cg_process_message(BCP_cg_prob &p, BCP_buffer &buf)
Only primal variables currently at nonzero level.
The user packed everything.
BCP_process_t BCP_cg_main(BCP_message_environment *msg_env, USER_initialize *user_init, int my_id, int parent, double ub)
Definition: BCP_cg_main.cpp:23
bool probe_messages()
Test if there is a message in the message queue waiting to be processed.
Definition: BCP_cg.cpp:30
virtual void unpack_primal_solution(BCP_buffer &buf)
Unpack the LP solution arriving from the LP process.
Definition: BCP_cg_user.cpp:79
BCP_vec< BCP_var * > vars
Cuts are to be generated for the LP solution given by these variables and their values (next member)...
Definition: BCP_cg.hpp:83
int phase
The phase the algorithm is in.
Definition: BCP_cg.hpp:91
This class is an abstract base class for the initializer class the user has to provide.
Definition: BCP_USER.hpp:160
#define GETPID
Definition: BCP_os.hpp:31
int length() const
Definition: BCP_string.hpp:16
BCP_user_class * user_class
A pointer ot the usr class of the process from which the methods of this class are invoked from...
Definition: BCP_USER.hpp:55
#define gethostname(x, y)
Definition: BCP_os.hpp:25
The TM sends the appropriate parameters to the slave process.
fint timing
Definition: readASLfg.cpp:18
The TM sends the initial user packed information to the slave process.
TM warns an LP process that the second phase will start.
void clear()
Completely clear the buffer.
Definition: BCP_buffer.hpp:168
BCP_message_tag msgtag() const
Return the message tag of the message in the buffer.
Definition: BCP_buffer.hpp:90
No more (violated) cuts could be found.
BCP_buffer msg_buf
The message buffer of the Cut Generator process.
Definition: BCP_cg.hpp:61
double upper_bound
The proc id of the tree manager.
Definition: BCP_cg.hpp:73
The file where the output from this process should be logged.
Currently there isn&#39;t any error handling in BCP.
Definition: BCP_error.hpp:20
Only primal variables currently at fractional level.
virtual BCP_cg_user * cg_init(BCP_cg_prob &p)
Definition: BCP_USER.hpp:210
virtual void unpack_module_data(BCP_buffer &buf)
Unpack the initial information sent to the Cut Generator process by the Tree Manager.
Definition: BCP_cg_user.cpp:69
virtual void generate_cuts(BCP_vec< BCP_var * > &vars, BCP_vec< double > &x)
Perform the actual cut generation.
int node_iteration
The iteration within the search tree node where the solution was generated.
Definition: BCP_cg.hpp:98
This class describes the message buffer used for all processes of BCP.
Definition: BCP_buffer.hpp:39
BCP_user_pack * packer
A class that holds the methods about how to pack things.
Definition: BCP_cg.hpp:53
void unpack(BCP_buffer &buf)
Unpack the parameter set from the buffer.
virtual void process_message()
BCP_message_environment * msg_env
The message passing environment.
Definition: BCP_cg.hpp:58
Any process to TM or TM to any process: a new upper bound found.
virtual bool alive(const int pid)=0
Test if the process given by the argument is alive or not.
The &quot;nice&quot; level the process should run at.
int node_level
The level of search tree node where the solution was generated.
Definition: BCP_cg.hpp:93
BCP_parameter_set< BCP_cg_par > par
The parameters controlling the Cut Generator process.
Definition: BCP_cg.hpp:64
void setCgProblemPointer(BCP_cg_prob *ptr)
Set the pointer.
Definition: BCP_cg_user.hpp:61
BCP_cg_user * user
The user object holding the user&#39;s data.
Definition: BCP_cg.hpp:50
CouExpr & log(CouExpr &e)