35 mc_cycle_cut->
pack(buf);
41 mc_dense_cut->
pack(buf);
44 throw BCP_fatal_error(
"MC_packer::pack_cut_algo() : unknown cut type!\n");
59 MC_packer::unpack_cut_algo() : unknown cut type!\n");
73 const int argnum,
const char *
const * arglist)
82 const int grid =
static_cast<int>(sqrt(mc.
num_nodes + 1.0));
83 const int num_grid_nodes = grid * grid;
84 const bool has_extra_node = (mc.
num_nodes != num_grid_nodes);
85 const double granularity = has_extra_node ? .99 : 1.99;
119 int * first_on_chain = component;
120 int * last_on_chain =
new int[
n];
121 int * next_on_chain =
new int[
n];
122 int * size_of_chain =
new int[
n];
124 CoinIotaN(first_on_chain, n, 0);
125 CoinIotaN(last_on_chain, n, 0);
126 CoinFillN(next_on_chain, n, -1);
127 CoinFillN(size_of_chain, n, 1);
133 for (
int k = 0;
k <
m; ++
k) {
134 const int i = edges[
k].
tail;
135 const int j = edges[
k].
head;
136 const int label_i = first_on_chain[i];
137 const int label_j = first_on_chain[
j];
138 if (label_i == label_j)
140 if (size_of_chain[label_i] > size_of_chain[label_j]) {
148 for (
int l = label_s; l != -1; l = next_on_chain[l]) {
149 first_on_chain[l] = label_l;
151 next_on_chain[last_on_chain[label_l]] = label_s;
152 last_on_chain[label_l] = last_on_chain[label_s];
153 size_of_chain[label_l] += size_of_chain[label_s];
156 delete[] last_on_chain;
157 delete[] next_on_chain;
158 delete[] size_of_chain;
167 const int num_nodes,
const int * nodes)
169 const int * nodes_end = nodes + num_nodes;
173 for (i = 0; i < num_nodes; ++i) {
175 for (j = mc.
nodes[nodes[i]].
degree - 1; j >= 0; --j) {
176 if (std::find(nodes, nodes_end, adj_list[j].neighbor) == nodes_end)
182 swstruct.
nodes =
new int[num_nodes + outedges];
184 CoinDisjointCopyN(nodes, num_nodes, swstruct.
nodes);
186 for (i = 0; i < num_nodes; ++i) {
188 for (j = mc.
nodes[nodes[i]].
degree - 1; j >= 0; --j) {
189 if (std::find(nodes, nodes_end, adj_list[j].neighbor) == nodes_end)
202 return ((ip0.first < ip1.first) ||
203 ((ip0.first == ip1.first) && (ip0.second < ip1.second)));
223 file.getline(line, 999);
224 int len = strlen(line);
225 if (strncmp(line,
"DESC: ggrid", CoinMin(len, 11)) == 0) {
228 printf(
"Ising problem detected.\n");
229 file.getline(line, 999);
233 while (strncmp(line,
"DESC:", CoinMin(len, 5)) == 0) {
234 file.getline(line, 999);
245 std::map<intpair, int> edge_map;
249 for (i = 0, k = 0; i <
m; ++i) {
250 file.getline(line, 999);
251 sscanf(line,
"%i%i%lf", &ip.first, &ip.second, &cost);
252 if (ip.first < 0 || ip.first >= n || ip.second < 0 || ip.second >= n ||
253 (ip.first == ip.second)) {
255 sprintf(errmsg,
" bad endnodes %i %i\n", ip.first, ip.second);
258 if (ip.first > ip.second)
259 std::swap(ip.first, ip.second);
260 const std::map<intpair, int>::const_iterator em = edge_map.find(ip);
261 if (em != edge_map.end()) {
262 printf(
"Warning: edge (%i,%i) appears once again.\n",
263 ip.first, ip.second);
264 printf(
" Collapsing the parallel edges.\n");
281 for (i = 0, k = 0; i < mc.
num_edges; ++i) {
283 printf(
"Warning: Discarded edge (%i,%i) as it has final cost 0.\n",
294 int * components =
new int[mc.
num_nodes];
297 mc.
edges, components);
299 printf(
"There are %i components in the graph. Adding 0 cost edges.\n",
302 seen.insert(components[0]);
304 if (seen.find(components[i]) == seen.end()) {
309 seen.insert(components[i]);
319 mc.
edges[i].
cost = floor(c / rescale + 0.5);
334 const int grid =
static_cast<int>(sqrt(mc.
num_nodes + 1.0));
335 const int num_grid_nodes = grid * grid;
336 const int num_grid_edges = 2 * num_grid_nodes;
337 const int vertical = num_grid_nodes;
342 for (i = 0; i < grid; ++i) {
343 for (j = 0; j < grid; ++
j) {
345 cycle[0] = i*grid +
j;
347 cycle[1] = vertical + i*grid + ((j+1) % grid);
349 cycle[2] = ((i+1) % grid) * grid +
j;
351 cycle[3] = vertical + i*grid +
j;
357 const bool has_extra_node = (mc.
num_nodes != num_grid_nodes);
358 if (has_extra_node) {
362 for (i = 0; i < grid; ++i) {
363 for (j = 0; j < grid; ++
j) {
365 triangle[0] = i*grid +
j;
366 triangle[1] = num_grid_edges + i*grid +
j;
367 triangle[2] = num_grid_edges + i*grid + ((j+1) % grid);
368 if (triangle[1] > triangle[2])
369 std::swap(triangle[1], triangle[2]);
372 triangle[0] = vertical + i*grid +
j;
373 triangle[1] = num_grid_edges + i*grid +
j;
374 triangle[2] = num_grid_edges + ((i+1) % grid) * grid +
j;
375 if (triangle[1] > triangle[2])
376 std::swap(triangle[1], triangle[2]);
396 for (i = 0; i < grid; ++i) {
397 for (j = 0; j < grid; ++
j) {
402 nodes[0] = ((i+grid-1)%grid) * grid +
j;
403 nodes[1] = i * grid +
j;
404 nodes[2] = ((i+1)%grid) * grid +
j;
406 if (next_struct->
num_neighbors != 8 + (has_extra_node ? 3 : 0))
413 nodes[0] = i * grid + ((j+grid-1)%grid);
414 nodes[1] = i * grid +
j;
415 nodes[2] = i * grid + ((j+1)%grid);
417 if (next_struct->
num_neighbors != 8 + (has_extra_node ? 3 : 0))
424 nodes[0] = ((i+grid-1)%grid) * grid +
j;
425 nodes[1] = i * grid +
j;
426 nodes[2] = i * grid + ((j+1)%grid);
428 if (next_struct->
num_neighbors != 8 + (has_extra_node ? 3 : 0))
436 nodes[0] = i * grid + ((j+1)%grid);
437 nodes[1] = i * grid +
j;
438 nodes[2] = ((i+1)%grid) * grid +
j;
440 if (next_struct->
num_neighbors != 8 + (has_extra_node ? 3 : 0))
448 nodes[0] = ((i+1)%grid) * grid +
j;
449 nodes[1] = i * grid +
j;
450 nodes[2] = i * grid + ((j+grid-1)%grid);
452 if (next_struct->
num_neighbors != 8 + (has_extra_node ? 3 : 0))
459 nodes[0] = i * grid + ((j+grid-1)%grid);
460 nodes[1] = i * grid +
j;
461 nodes[2] = ((i+grid-1)%grid) * grid +
j;
463 if (next_struct->
num_neighbors != 8 + (has_extra_node ? 3 : 0))
483 for (i = 0; i < grid; ++i) {
484 for (j = 0; j < grid; ++
j) {
486 nodes[0] = i * grid +
j;
487 nodes[1] = i * grid + ((j-1+grid)%grid);
488 nodes[2] = ((i-1+grid)%grid) * grid +
j;
489 nodes[3] = i * grid + ((j+1)%grid);
491 if (next_struct->
num_neighbors != 10 + (has_extra_node ? 4 : 0))
497 nodes[0] = i * grid +
j;
498 nodes[1] = ((i-1+grid)%grid) * grid +
j;
499 nodes[2] = i * grid + ((j+1)%grid);
500 nodes[3] = ((i+1)%grid) * grid +
j;
502 if (next_struct->
num_neighbors != 10 + (has_extra_node ? 4 : 0))
508 nodes[0] = i * grid +
j;
509 nodes[1] = i * grid + ((j+1)%grid);
510 nodes[2] = ((i+1)%grid) * grid +
j;
511 nodes[3] = i * grid + ((j-1+grid)%grid);
513 if (next_struct->
num_neighbors != 10 + (has_extra_node ? 4 : 0))
519 nodes[0] = i * grid +
j;
520 nodes[1] = ((i+1)%grid) * grid +
j;
521 nodes[2] = i * grid + ((j-1+grid)%grid);
522 nodes[3] = ((i-1+grid)%grid) * grid +
j;
524 if (next_struct->
num_neighbors != 10 + (has_extra_node ? 4 : 0))
539 for (i = 0; i < grid; ++i) {
540 for (j = 0; j < grid; ++
j) {
543 nodes[0] = i * grid +
j;
544 nodes[1] = i * grid + ((j+1)%grid);
545 nodes[2] = ((i-1+grid)%grid) * grid + ((j+1)%grid);
546 nodes[3] = ((i-1+grid)%grid) * grid + ((j+2)%grid);
548 if (next_struct->
num_neighbors != 10 + (has_extra_node ? 4 : 0))
554 nodes[0] = i * grid +
j;
555 nodes[1] = i * grid + ((j+1)%grid);
556 nodes[2] = ((i+1)%grid) * grid + ((j+1)%grid);
557 nodes[3] = ((i+1)%grid) * grid + ((j+2)%grid);
559 if (next_struct->
num_neighbors != 10 + (has_extra_node ? 4 : 0))
565 nodes[0] = i * grid +
j;
566 nodes[1] = ((i+1)%grid) * grid +
j;
567 nodes[2] = ((i+1)%grid) * grid + ((j+1)%grid);
568 nodes[3] = ((i+2)%grid) * grid + ((j+1)%grid);
570 if (next_struct->
num_neighbors != 10 + (has_extra_node ? 4 : 0))
576 nodes[0] = i * grid +
j;
577 nodes[1] = ((i+1)%grid) * grid +
j;
578 nodes[2] = ((i+1)%grid) * grid + ((j-1+grid)%grid);
579 nodes[3] = ((i+2)%grid) * grid + ((j-1+grid)%grid);
581 if (next_struct->
num_neighbors != 10 + (has_extra_node ? 4 : 0))
596 for (i = 0; i < grid; ++i) {
597 for (j = 0; j < grid; ++
j) {
601 nodes[0] = i * grid +
j;
602 nodes[1] = i * grid + ((j+1)%grid);
603 nodes[2] = ((i+1)%grid) * grid + ((j+1)%grid);
604 nodes[3] = ((i+1)%grid) * grid +
j;
606 if (next_struct->
num_neighbors != 8 + (has_extra_node ? 4 : 0))
624 for (i = 0; i < grid; ++i) {
625 for (j = 0; j < grid; ++
j) {
628 nodes[0] = i * grid +
j;
629 nodes[1] = i * grid + ((j+1)%grid);
630 nodes[2] = i * grid + ((j+2)%grid);
631 nodes[3] = ((i+1)%grid) * grid +
j;
632 nodes[4] = ((i+1)%grid) * grid + ((j+1)%grid);
633 nodes[5] = ((i+1)%grid) * grid + ((j+2)%grid);
635 if (next_struct->
num_neighbors != 10 + (has_extra_node ? 6 : 0))
642 nodes[0] = i * grid +
j;
643 nodes[1] = i * grid + ((j+1)%grid);
644 nodes[2] = ((i+1)%grid) * grid +
j;
645 nodes[3] = ((i+1)%grid) * grid + ((j+1)%grid);
646 nodes[4] = ((i+2)%grid) * grid +
j;
647 nodes[5] = ((i+2)%grid) * grid + ((j+1)%grid);
649 if (next_struct->
num_neighbors != 10 + (has_extra_node ? 6 : 0))
664 solfile.getline(line, 999);
665 sscanf(line,
"%i", s+i);
669 printf(
"\nMC: value of input solution: %.0f\n\n", mc.
feas_sol->
cost);
BCP_tm_user * tm_init(BCP_tm_prob &p, const int argnum, const char *const *arglist)
The minimum difference between the objective value of any two feasible solution (with different objec...
BCP_buffer & unpack(T &value)
Unpack a single object of type T.
This is the class from which the user should derive her own algorithmic cuts.
char entry(const chr_params key) const
BCP_parameter_set< MC_lp_par > lp_par
static bool operator<(const intpair &ip0, const intpair &ip1)
The BCP_lp_user class is the base class from which the user can derive a problem specific class to be...
USER_initialize * BCP_user_init()
void pack(BCP_buffer &buf) const
MC_switch_structure ** switch_structures
BCP_lp_user * lp_init(BCP_lp_prob &p)
int MC_components(const int n, const int m, const MC_graph_edge *edges, int *component)
void fint fint fint real fint real real real real real real real real real fint real fint * lp
This class is an abstract base class for the initializer class the user has to provide.
BCP_parameter_set< MC_tm_par > tm_par
BCP_user_pack * packer_init(BCP_user_class *p)
void read_from_file(const char *paramfile)
Simply invoke reading from a stream.
void pack(BCP_buffer &buf) const
void set_entry(const chr_params key, const char val)
virtual void pack_cut_algo(const BCP_cut_algo *cut, BCP_buffer &buf)
Pack an algorithmic cut.
virtual BCP_cut_algo * unpack_cut_algo(BCP_buffer &buf)
Unpack an algorithmic cut.
void fint fint fint fint fint fint fint fint fint fint real real real real real real real real * s
BCP_parameter_set< BCP_tm_par > par
static void MC_fill_structure(const MC_problem &mc, MC_switch_structure &swstruct, const int num_nodes, const int *nodes)
Currently there isn't any error handling in BCP.
std::pair< int, int > intpair
void MC_read_parameters(MC_tm &tm, const char *paramfile)
This class describes the message buffer used for all processes of BCP.
BCP_parameter_set< BCP_lp_par > lp
MC_adjacency_entry * adj_list
int * num_switch_structures
BCP_slave_params slave_pars
The BCP_tm_user class is the base class from which the user can derive a problem specific class to be...
void MC_readproblem(MC_tm &tm)