Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ratio_cut_partition.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ratio_cut_partition.cpp
1 /* This software is distributed under the GNU Lesser General Public License */
2 //==========================================================================
3 //
4 // ratio_cut_partition.cpp
5 //
6 //==========================================================================
7 // $Id: ratio_cut_partition.cpp,v 1.9 2001/11/07 13:58:11 pick Exp $
8 
9 #include <GTL/debug.h>
10 #include <GTL/dfs.h>
12 
13 #include <iostream>
14 #include <queue>
15 
16 #include <cstdlib>
17 #include <cassert>
18 #include <cmath>
19 #include <ctime>
20 
21 #ifdef __GTL_MSVCC
22 # ifdef _DEBUG
23 # ifndef SEARCH_MEMORY_LEAKS_ENABLED
24 # error SEARCH NOT ENABLED
25 # endif
26 # define new DEBUG_NEW
27 # undef THIS_FILE
28  static char THIS_FILE[] = __FILE__;
29 # endif // _DEBUG
30 #endif // __GTL_MSVCC
31 
33 
34 
37 
38 
42 
43 
45 {
46  set_vars_executed = false;
48  enable_nodesAB_storing = false;
49 }
50 
51 
53 {
54 }
55 
56 
58  const node_map<int>& node_weight, const edge_map<int>& edge_weight)
59 {
60  this->node_weight = node_weight;
61  this->edge_weight = edge_weight;
62  set_vars_executed = true;
63  provided_st = false;
64  provided_fix = false;
65  this->fixed.init(G, UNFIXED);
66  provided_initial_part = false;
67  side.init(G);
68 }
69 
70 
72  const node_map<int>& node_weight, const edge_map<int>& edge_weight,
73  const node source_node, const node target_node)
74 {
75  this->node_weight = node_weight;
76  this->edge_weight = edge_weight;
77  this->source_node = source_node;
78  this->target_node = target_node;
79  set_vars_executed = true;
80  provided_st = true;
81  provided_fix = false;
82  this->fixed.init(G, UNFIXED);
83  provided_initial_part = false;
84  side.init(G);
85 }
86 
87 
89  const node_map<int>& node_weight, const edge_map<int>& edge_weight,
90  const node source_node, const node target_node,
91  const node_map<side_type>& init_side)
92 {
93  this->node_weight = node_weight;
94  this->edge_weight = edge_weight;
95  this->source_node = source_node;
96  this->target_node = target_node;
97  this->side = init_side;
98  set_vars_executed = true;
99  provided_st = true;
100  provided_fix = false;
101  this->fixed.init(G, UNFIXED);
102  provided_initial_part = true;
103 }
104 
105 
107  const node_map<int>& node_weight, const edge_map<int>& edge_weight,
108  const node source_node, const node target_node,
109  const node_map<fix_type>& fixed)
110 {
111  this->node_weight = node_weight;
112  this->edge_weight = edge_weight;
113  this->source_node = source_node;
114  this->target_node = target_node;
115  this->fixed = fixed;
116  set_vars_executed = true;
117  provided_st = true;
118  provided_fix = true;
119  provided_initial_part = false;
120  side.init(G);
121 }
122 
123 
125  const node_map<int>& node_weight, const edge_map<int>& edge_weight,
126  const node source_node, const node target_node,
127  const node_map<side_type>& init_side, const node_map<fix_type>& fixed)
128 {
129  this->node_weight = node_weight;
130  this->edge_weight = edge_weight;
131  this->source_node = source_node;
132  this->target_node = target_node;
133  this->side = init_side;
134  this->fixed = fixed;
135  set_vars_executed = true;
136  provided_st = true;
137  provided_fix = true;
138  provided_initial_part = true;
139 }
140 
141 
143 {
145 }
146 
147 
149 {
151 }
152 
153 
155 {
156  if ((!set_vars_executed) || (!G.is_undirected()))
157  {
158  return GTL_ERROR;
159  }
160 
161  graph::edge_iterator edge_it = G.edges_begin();
162  graph::edge_iterator edges_end = G.edges_end();
163  while (edge_it != edges_end)
164  {
165  if (edge_weight[*edge_it] < 0)
166  {
167  return GTL_ERROR;
168  }
169  ++edge_it;
170  }
171  int real_node_weights = 0;
172  graph::node_iterator node_it = G.nodes_begin();
173  graph::node_iterator nodes_end = G.nodes_end();
174  while (node_it != nodes_end)
175  {
176  if (node_weight[*node_it] > 0)
177  {
178  ++real_node_weights;
179  }
180  if (node_weight[*node_it] < 0)
181  {
182  return GTL_ERROR;
183  }
184  ++node_it;
185  }
186  if ((G.number_of_nodes() >= 2) && (real_node_weights < 2))
187  {
188  return GTL_ERROR;
189  }
190 
191  if ((provided_st) && (source_node == target_node) &&
192  (G.number_of_nodes() > 1))
193  {
194  return GTL_ERROR;
195  }
196 
197  if ((provided_initial_part) && ((side[source_node] != A) ||
198  (side[target_node] != B)))
199  {
200  return GTL_ERROR;
201  }
202 
203  if ((provided_fix) && ((fixed[source_node] == FIXB) ||
204  (fixed[target_node] == FIXA)))
205  {
206  return GTL_ERROR;
207  }
208 
209  if ((provided_st) && (node_weight[source_node] == 0 ||
210  node_weight[target_node] == 0))
211  {
212  return GTL_ERROR;
213  }
214 
215  return GTL_OK;
216 }
217 
218 
220 {
221  cur_cutsize = 0;
222  cur_cutratio = 0.0;
223  if (G.number_of_nodes() == 0)
224  {
225  return GTL_OK; // nothing to do
226  }
227  if (G.number_of_nodes() == 1)
228  {
229  side[*G.nodes_begin()] = A;
230  return GTL_OK;
231  }
232 
233  list<edge> artificial_edges;
234  if (!G.is_connected())
235  {
236  make_connected(G, artificial_edges);
237  }
238 
239  if (provided_fix)
240  {
241  divide_up(G);
242  }
243 
244  if (!provided_st)
245  {
248  }
249 
251  {
252  init_variables(G);
255  clean_step(G);
256  }
257  else
258  {
259  initialization(G);
260  }
262  group_swapping(G);
263 
265  {
267  }
269  {
270  compute_nodesAB(G);
271  }
272  restore(G, artificial_edges);
273 
274  return GTL_OK;
275 }
276 
277 
279 {
280  return cur_cutsize;
281 }
282 
283 
285 {
286  return cur_cutratio;
287 }
288 
289 
292 {
293  return side[n];
294 }
295 
296 
297 ratio_cut_partition::side_type ratio_cut_partition::operator []
298 (const node& n) const
299 {
300  return side[n];
301 }
302 
303 
305 {
306  int nwA = 0;
307  graph::node_iterator node_it = G.nodes_begin();
308  graph::node_iterator nodes_end = G.nodes_end();
309  while (node_it != nodes_end)
310  {
311  if (side[*node_it] == A)
312  {
313  nwA += node_weight[*node_it];
314  }
315  ++node_it;
316  }
317  return nwA;
318 }
319 
320 
322 {
323  int nwB = 0;
324  graph::node_iterator node_it = G.nodes_begin();
325  graph::node_iterator nodes_end = G.nodes_end();
326  while (node_it != nodes_end)
327  {
328  if (side[*node_it] == B)
329  {
330  nwB += node_weight[*node_it];
331  }
332  ++node_it;
333  }
334  return nwB;
335 }
336 
337 
340 {
341  return cut_edges.begin();
342 }
343 
344 
347 {
348  return cut_edges.end();
349 }
350 
351 
354 {
355  return nodesA.begin();
356 }
357 
358 
361 {
362  return nodesA.end();
363 }
364 
365 
368 {
369  return nodesB.begin();
370 }
371 
372 
375 {
376  return nodesB.end();
377 }
378 
379 
381 {
382  set_vars_executed = false;
383  cut_edges.clear();
384  nodesA.clear();
385  nodesB.clear();
386 }
387 
388 
390 {
391  graph::node_iterator node_it = G.nodes_begin();
392  graph::node_iterator nodes_end = G.nodes_end();
393  while (node_it != nodes_end)
394  {
395  if (fixed[*node_it] == FIXA)
396  {
397  side[*node_it] = A;
398  }
399  else if (fixed[*node_it] == FIXB)
400  {
401  side[*node_it] = B;
402  }
403  ++node_it;
404  }
405 }
406 
407 
409  list<edge>& artificial_edges)
410 {
411  dfs conn;
412  conn.scan_whole_graph(true);
413  conn.check(G);
414  conn.run(G);
415 
416  // connect dfs roots with zero edges
417  dfs::roots_iterator root_it = conn.roots_begin();
418  dfs::roots_iterator rootes_end = conn.roots_end();
419  while (root_it != rootes_end)
420  {
421  node edge_start = **root_it;
422  ++root_it;
423  if (root_it != rootes_end)
424  {
425  edge ne = G.new_edge(edge_start, **root_it);
426  edge_weight[ne] = 0; // this edge has no cut costs
427  artificial_edges.push_back(ne);
428  }
429  }
430 }
431 
432 
433 void ratio_cut_partition::restore(graph& G, list<edge>& artificial_edges)
434 {
435  list<edge>::iterator edge_it = artificial_edges.begin();
436  list<edge>::iterator edges_end = artificial_edges.end();
437  while (edge_it != edges_end)
438  {
439  G.del_edge(*edge_it);
440  ++edge_it;
441  }
442 }
443 
444 
446 {
447  int cutsize_A2B, cutsize_B2A;
448  double cutratio_A2B, cutratio_B2A;
449  node_map<side_type> side_B2A(G);
450 
451  init_variables(G);
452 
453  // start with moves from B to A
454  graph::node_iterator node_it = G.nodes_begin();
455  graph::node_iterator nodes_end = G.nodes_end();
456  while (node_it != nodes_end)
457  {
458  if (fixed[*node_it] == UNFIXED)
459  {
460  side[*node_it] = B;
461  }
462  ++node_it;
463  }
464  side[source_node] = A;
465  side[target_node] = B;
467  if (fixed[target_node] == UNFIXED)
468  {
470  erase(position_in_bucket[target_node]);
472  }
473  left_shift_op(G);
474  clean_step(G);
475  cutsize_B2A = cur_cutsize;
476  cutratio_B2A = cur_cutratio;
477  copy_side_node_map(G, side_B2A, side);
478 
479  // continue with moves from A to B
480  node_it = G.nodes_begin();
481  while (node_it != nodes_end)
482  {
483  if (fixed[*node_it] == UNFIXED)
484  {
485  side[*node_it] = A;
486  }
487  ++node_it;
488  }
489  side[source_node] = A;
490  side[target_node] = B;
492  if (fixed[source_node] == UNFIXED)
493  {
495  erase(position_in_bucket[source_node]);
497  }
498  right_shift_op(G);
499  clean_step(G);
500  cutsize_A2B = cur_cutsize;
501  cutratio_A2B = cur_cutratio;
502 
503  if (cutratio_B2A < cutratio_A2B)
504  {
505  copy_side_node_map(G, side, side_B2A);
506  cur_cutsize = cutsize_B2A;
507  cur_cutratio = cutratio_B2A;
509  }
510  else
511  {
512  // copy_side_node_map(...) not necessary
513  cur_cutsize = cutsize_A2B;
514  cur_cutratio = cutratio_A2B;
516  }
517 }
518 
519 
521 {
522  aside.init(G);
523  bside.init(G);
524  unlockedA.init(G);
525  unlockedB.init(G);
526  cur_cutsize = 0;
527  graph::edge_iterator edge_it = G.edges_begin();
528  graph::edge_iterator edges_end = G.edges_end();
529  while (edge_it != edges_end)
530  {
531  if ((side[(*edge_it).source()] == A) &&
532  (side[(*edge_it).target()] == A))
533  {
534  aside[*edge_it] = 2;
535  bside[*edge_it] = 0;
536  unlockedA[*edge_it].push_back((*edge_it).source());
537  unlockedA[*edge_it].push_back((*edge_it).target());
538  }
539  else if ((side[(*edge_it).source()] == B) &&
540  (side[(*edge_it).target()] == B))
541  {
542  aside[*edge_it] = 0;
543  bside[*edge_it] = 2;
544  unlockedB[*edge_it].push_back((*edge_it).source());
545  unlockedB[*edge_it].push_back((*edge_it).target());
546  }
547  else if ((side[(*edge_it).source()] == A) &&
548  (side[(*edge_it).target()] == B))
549  {
550  aside[*edge_it] = 1;
551  bside[*edge_it] = 1;
552  cur_cutsize += edge_weight[*edge_it];
553  unlockedA[*edge_it].push_back((*edge_it).source());
554  unlockedB[*edge_it].push_back((*edge_it).target());
555  }
556  else if ((side[(*edge_it).source()] == B) &&
557  (side[(*edge_it).target()] == A))
558  {
559  aside[*edge_it] = 1;
560  bside[*edge_it] = 1;
561  cur_cutsize += edge_weight[*edge_it];
562  unlockedA[*edge_it].push_back((*edge_it).target());
563  unlockedB[*edge_it].push_back((*edge_it).source());
564  }
565  ++edge_it;
566  }
567 
568  bucketA.resize(2 * max_vertex_degree * max_edge_weight + 1);
569  bucketB.resize(2 * max_vertex_degree * max_edge_weight + 1);
570 
573 }
574 
575 
577 {
580  nodes_on_sideA = 0;
581  nodes_on_sideB = 0;
582  bucketA_empty = true;
583  bucketB_empty = true;
584  bool first_A_node = true;
585  bool first_B_node = true;
586  int index;
587  // position_in_bucket.init(G);
588  gain_value.init(G);
589 
590  graph::node_iterator node_it = G.nodes_begin();
591  graph::node_iterator nodes_end = G.nodes_end();
592  while (node_it != nodes_end)
593  {
594  if (side[*node_it] == A)
595  {
596  node_weight_on_sideA += node_weight[*node_it];
597  ++nodes_on_sideA;
598  gain_value[*node_it] = inital_gain_of_node_on_sideA(*node_it);
599  if (fixed[*node_it] == UNFIXED)
600  {
601  if (first_A_node)
602  {
603  bucketA_empty = false;
604  max_gainA = gain_value[*node_it];
605  first_A_node = false;
606  }
607  else
608  {
609  if (max_gainA < gain_value[*node_it])
610  {
611  max_gainA = gain_value[*node_it];
612  }
613  }
614  index = range_up(gain_value[*node_it]);
615  position_in_bucket[*node_it] = bucketA[index].insert(
616  bucketA[index].begin(), *node_it);
617  }
618  }
619  else // side[*node_it] == B
620  {
621  node_weight_on_sideB += node_weight[*node_it];
622  ++nodes_on_sideB;
623  gain_value[*node_it] = inital_gain_of_node_on_sideB(*node_it);
624  if (fixed[*node_it] == UNFIXED)
625  {
626  if (first_B_node)
627  {
628  bucketB_empty = false;
629  max_gainB = gain_value[*node_it];
630  first_B_node = false;
631  }
632  else
633  {
634  if (max_gainB < gain_value[*node_it])
635  {
636  max_gainB = gain_value[*node_it];
637  }
638  }
639  index = range_up(gain_value[*node_it]);
640  position_in_bucket[*node_it] = bucketB[index].insert(
641  bucketB[index].begin(), *node_it);
642  }
643  }
644  ++node_it;
645  }
646 }
647 
648 
650 {
651  int node_gain = 0;
652  node::adj_edges_iterator adj_edge_it = cur_node.adj_edges_begin();
653  node::adj_edges_iterator adj_edges_end = cur_node.adj_edges_end();
654  while (adj_edge_it != adj_edges_end)
655  {
656  if (aside[*adj_edge_it] == 1)
657  {
658  node_gain += edge_weight[*adj_edge_it];
659  }
660  if (bside[*adj_edge_it] == 0)
661  {
662  node_gain -= edge_weight[*adj_edge_it];
663  }
664  ++adj_edge_it;
665  }
666  return node_gain;
667 }
668 
669 
671 {
672  int node_gain = 0;
673  node::adj_edges_iterator adj_edge_it = cur_node.adj_edges_begin();
674  node::adj_edges_iterator adj_edges_end = cur_node.adj_edges_end();
675  while (adj_edge_it != adj_edges_end)
676  {
677  if (bside[*adj_edge_it] == 1)
678  {
679  node_gain += edge_weight[*adj_edge_it];
680  }
681  if (aside[*adj_edge_it] == 0)
682  {
683  node_gain -= edge_weight[*adj_edge_it];
684  }
685  ++adj_edge_it;
686  }
687  return node_gain;
688 }
689 
690 
692 {
694  bool first_edge_found = true;
695  max_edge_weight = 0;
696  graph::edge_iterator edge_it = G.edges_begin();
697  graph::edge_iterator edges_end = G.edges_end();
698  while (edge_it != edges_end)
699  {
700  if (first_edge_found)
701  {
702  max_edge_weight = edge_weight[*edge_it];
703  first_edge_found = false;
704  }
705  else if (edge_weight[*edge_it] > max_edge_weight)
706  {
707  max_edge_weight = edge_weight[*edge_it];
708  }
709  ++edge_it;
710  }
711 }
712 
713 
715 {
716  max_vertex_degree = 0;
717  graph::node_iterator node_it = G.nodes_begin();
718  graph::node_iterator nodes_end = G.nodes_end();
719  while (node_it != nodes_end)
720  {
721  if (max_vertex_degree < (*node_it).degree())
722  {
723  max_vertex_degree = (*node_it).degree();
724  }
725  ++node_it;
726  }
727 }
728 
729 
731 {
732  srand((unsigned)time(NULL));
733  rand(); // necessary, otherwise the next rand() returns always 0 ?-)
734  int node_id = (int)floor((((double)rand() / (double)RAND_MAX) *
735  (double)(G.number_of_nodes() - 1)) + 0.5);
736  graph::node_iterator node_it = G.nodes_begin();
737  for (int i = 1; i <= node_id; i++)
738  {
739  ++node_it;
740  }
741  source_node = *node_it;
742  if (node_weight[source_node] == 0)
743  {
744  node_it = G.nodes_begin();
745  while (node_weight[*node_it] == 0)
746  {
747  ++node_it;
748  }
749  source_node = *node_it;
750  }
751 }
752 
753 
755 {
756  node cur_node, next;
757  node_map<bool> visited(G, false);
758  queue<node> next_nodes;
759  next_nodes.push(source_node);
760  visited[source_node] = true;
761 
762  while (!next_nodes.empty())
763  {
764  cur_node = next_nodes.front();
765  next_nodes.pop();
766 
767  node::adj_edges_iterator adj_edge_it = cur_node.adj_edges_begin();
768  node::adj_edges_iterator adj_edges_end = cur_node.adj_edges_end();
769  while (adj_edge_it != adj_edges_end)
770  {
771  if ((*adj_edge_it).target() != cur_node)
772  {
773  next = (*adj_edge_it).target();
774  }
775  else
776  {
777  next = (*adj_edge_it).source();
778  }
779  if (!visited[next])
780  {
781  next_nodes.push(next);
782  visited[next] = true;
783  }
784  ++adj_edge_it;
785  }
786  }
787  target_node = cur_node;
788  if (node_weight[target_node] == 0)
789  {
790  graph::node_iterator node_it = G.nodes_begin();
791  while ((node_weight[*node_it] == 0) || (*node_it == source_node))
792  {
793  ++node_it;
794  }
795  target_node = *node_it;
796  }
797 }
798 
799 
801 {
802  int step_number = 0;
803  int best_tentative_move = 0;
805  vector<node> tentative_moves(G.number_of_nodes() + 1);
806  vector<double> tentative_cutratio(G.number_of_nodes() + 1);
807  node moved_node;
808  tentative_cutratio[0] = cur_cutratio;
809  int best_cutsize = cur_cutsize;
810 
811  while (move_vertex_A2B(G, moved_node))
812  {
813  ++step_number;
814  tentative_cutratio[step_number] = cur_cutratio;
815  tentative_moves[step_number] = moved_node;
816  if (tentative_cutratio[best_tentative_move] > cur_cutratio)
817  {
818  best_tentative_move = step_number;
819  best_cutsize = cur_cutsize;
821  }
822  else if (tentative_cutratio[best_tentative_move] == cur_cutratio)
823  {
824  if (node_weight_on_sideA * node_weight_on_sideB > best_bal)
825  {
826  best_tentative_move = step_number;
827  best_cutsize = cur_cutsize;
829  }
830  }
831  }
832 
833  for (int i = 1; i <= best_tentative_move; i++)
834  {
835  if (side[tentative_moves[i]] == A)
836  {
837  side[tentative_moves[i]] = B;
838  }
839  else // side[tentative_moves[i]] == B
840  {
841  side[tentative_moves[i]] = A;
842  }
843  }
844  cur_cutratio = tentative_cutratio[best_tentative_move];
845  cur_cutsize = best_cutsize;
846 }
847 
848 
850 {
851  int step_number = 0;
852  int best_tentative_move = 0;
854  vector<node> tentative_moves(G.number_of_nodes() + 1);
855  vector<double> tentative_cutratio(G.number_of_nodes() + 1);
856  node moved_node;
857  tentative_cutratio[0] = cur_cutratio;
858  int best_cutsize = cur_cutsize;
859 
860  while (move_vertex_B2A(G, moved_node))
861  {
862  ++step_number;
863  tentative_cutratio[step_number] = cur_cutratio;
864  tentative_moves[step_number] = moved_node;
865  if (tentative_cutratio[best_tentative_move] > cur_cutratio)
866  {
867  best_tentative_move = step_number;
868  best_cutsize = cur_cutsize;
869  }
870  else if (tentative_cutratio[best_tentative_move] == cur_cutratio)
871  {
872  if (node_weight_on_sideA * node_weight_on_sideB > best_bal)
873  {
874  best_tentative_move = step_number;
875  best_cutsize = cur_cutsize;
877  }
878  }
879  }
880 
881  for (int i = 1; i <= best_tentative_move; i++)
882  {
883  if (side[tentative_moves[i]] == A)
884  {
885  side[tentative_moves[i]] = B;
886  }
887  else // side[tentative_moves[i]] == B
888  {
889  side[tentative_moves[i]] = A;
890  }
891  }
892  cur_cutratio = tentative_cutratio[best_tentative_move];
893  cur_cutsize = best_cutsize;
894 }
895 
896 
898 {
899  if (!bucketA_empty)
900  {
901  node cons_nodeA =
903  bucketA[range_up(max_gainA)].erase(position_in_bucket[cons_nodeA]);
904  update_data_structure_A2B(cons_nodeA, true);
905  moved_node = cons_nodeA;
906  }
907  else
908  {
909  return false; // no more vertices can be moved
910  }
912  return true;
913 }
914 
915 
917 {
918  if (!bucketB_empty)
919  {
920  node cons_nodeB =
922  bucketB[range_up(max_gainB)].erase(position_in_bucket[cons_nodeB]);
923  update_data_structure_B2A(cons_nodeB, true);
924  moved_node = cons_nodeB;
925  }
926  else
927  {
928  return false; // no more vertices can be moved
929  }
931  return true;
932 }
933 
934 
936 {
937  node cons_node = node_list.front();
938  double ratio, best_ratio;
939  if (side[cons_node] == A)
940  {
941  best_ratio = ratio_of_node_A2B(cons_node);
942  }
943  else // side[cons_node] == B
944  {
945  best_ratio = ratio_of_node_B2A(cons_node);
946  }
947 
948  list<node>::iterator node_it = node_list.begin();
949  list<node>::iterator nodes_end = node_list.end();
950  while (node_it != nodes_end)
951  {
952  if (side[cons_node] == A)
953  {
954  ratio = ratio_of_node_A2B(*node_it);
955  }
956  else // side[cons_node] == B
957  {
958  ratio = ratio_of_node_B2A(*node_it);
959  }
960  if (ratio > best_ratio) // choose node with highest ratio
961  {
962  best_ratio = ratio;
963  cons_node = *node_it;
964  }
965  ++node_it;
966  }
967  return cons_node;
968 }
969 
970 
972 {
973  double number_of_nodes = (double)(nodes_on_sideA + nodes_on_sideB);
974  return ((double)cur_cutsize + number_of_nodes) / (double)
976 }
977 
978 
980 {
981  return (double)gain_value[cur_node] /
982  ((double)((node_weight_on_sideB + node_weight[cur_node]) *
983  (node_weight_on_sideA - node_weight[cur_node])));
984 }
985 
986 
988 {
989  return (double)gain_value[cur_node] /
990  ((double)((node_weight_on_sideA + node_weight[cur_node]) *
991  (node_weight_on_sideB - node_weight[cur_node])));
992 }
993 
994 
995 inline int ratio_cut_partition::range_up(const int gain_value) const
996 {
997  return gain_value + (max_vertex_degree * max_edge_weight);
998 }
999 
1000 
1001 inline int ratio_cut_partition::range_down(const int index) const
1002 {
1003  return index - (max_vertex_degree * max_edge_weight);
1004 }
1005 
1006 
1008  const bool init_mode)
1009 {
1010  node_weight_on_sideA -= node_weight[cur_node];
1011  node_weight_on_sideB += node_weight[cur_node];
1012  --nodes_on_sideA;
1013  ++nodes_on_sideB;
1014  cur_cutsize -= gain_value[cur_node];
1015  cur_cutratio = cutratio();
1016 
1017  // updating gain values
1018  node::adj_edges_iterator adj_edge_it = cur_node.adj_edges_begin();
1019  node::adj_edges_iterator adj_edges_end = cur_node.adj_edges_end();
1020  while (adj_edge_it != adj_edges_end)
1021  {
1022  // delete cur_node from side A
1023  unlockedA[*adj_edge_it].remove(cur_node);
1024  --aside[*adj_edge_it];
1025  if (aside[*adj_edge_it] == 0)
1026  {
1027  list<node>::iterator node_it = unlockedB[*adj_edge_it].begin();
1028  list<node>::iterator nodes_end = unlockedB[*adj_edge_it].end();
1029  while (node_it != nodes_end)
1030  {
1031  update_bucketB(*node_it, gain_value[*node_it],
1032  gain_value[*node_it] - edge_weight[*adj_edge_it],
1033  init_mode);
1034  gain_value[*node_it] -= edge_weight[*adj_edge_it];
1035  ++node_it;
1036  }
1037  }
1038  else if (aside[*adj_edge_it] == 1)
1039  {
1040  list<node>::iterator node_it = unlockedA[*adj_edge_it].begin();
1041  list<node>::iterator nodes_end = unlockedA[*adj_edge_it].end();
1042  while (node_it != nodes_end)
1043  {
1044  update_bucketA(*node_it, gain_value[*node_it],
1045  gain_value[*node_it] + edge_weight[*adj_edge_it],
1046  init_mode);
1047  gain_value[*node_it] += edge_weight[*adj_edge_it];
1048  ++node_it;
1049  }
1050  }
1051  // add cur_node to side B
1052  ++bside[*adj_edge_it];
1053  if (bside[*adj_edge_it] == 1)
1054  {
1055  list<node>::iterator node_it = unlockedA[*adj_edge_it].begin();
1056  list<node>::iterator nodes_end = unlockedA[*adj_edge_it].end();
1057  while (node_it != nodes_end)
1058  {
1059  update_bucketA(*node_it, gain_value[*node_it],
1060  gain_value[*node_it] + edge_weight[*adj_edge_it],
1061  init_mode);
1062  gain_value[*node_it] += edge_weight[*adj_edge_it];
1063  ++node_it;
1064  }
1065  }
1066  else if (bside[*adj_edge_it] == 2)
1067  {
1068  list<node>::iterator node_it = unlockedB[*adj_edge_it].begin();
1069  list<node>::iterator nodes_end = unlockedB[*adj_edge_it].end();
1070  while (node_it != nodes_end)
1071  {
1072  update_bucketB(*node_it, gain_value[*node_it],
1073  gain_value[*node_it] - edge_weight[*adj_edge_it],
1074  init_mode);
1075  gain_value[*node_it] -= edge_weight[*adj_edge_it];
1076  ++node_it;
1077  }
1078  }
1079  ++adj_edge_it;
1080  }
1081 }
1082 
1083 
1085  const bool init_mode)
1086 {
1087  node_weight_on_sideA += node_weight[cur_node];
1088  node_weight_on_sideB -= node_weight[cur_node];
1089  ++nodes_on_sideA;
1090  --nodes_on_sideB;
1091  cur_cutsize -= gain_value[cur_node];
1092  cur_cutratio = cutratio();
1093 
1094  // updating gain values
1095  node::adj_edges_iterator adj_edge_it = cur_node.adj_edges_begin();
1096  node::adj_edges_iterator adj_edges_end = cur_node.adj_edges_end();
1097  while (adj_edge_it != adj_edges_end)
1098  {
1099  // delete cur_node from side B
1100  unlockedB[*adj_edge_it].remove(cur_node);
1101  bside[*adj_edge_it] -= 1;
1102  if (bside[*adj_edge_it] == 0)
1103  {
1104  list<node>::iterator node_it = unlockedA[*adj_edge_it].begin();
1105  list<node>::iterator nodes_end = unlockedA[*adj_edge_it].end();
1106  while (node_it != nodes_end)
1107  {
1108  update_bucketA(*node_it, gain_value[*node_it],
1109  gain_value[*node_it] - edge_weight[*adj_edge_it],
1110  init_mode);
1111  gain_value[*node_it] -= edge_weight[*adj_edge_it];
1112  ++node_it;
1113  }
1114  }
1115  else if (bside[*adj_edge_it] == 1)
1116  {
1117  list<node>::iterator node_it = unlockedB[*adj_edge_it].begin();
1118  list<node>::iterator nodes_end = unlockedB[*adj_edge_it].end();
1119  while (node_it != nodes_end)
1120  {
1121  update_bucketB(*node_it, gain_value[*node_it],
1122  gain_value[*node_it] + edge_weight[*adj_edge_it],
1123  init_mode);
1124  gain_value[*node_it] += edge_weight[*adj_edge_it];
1125  ++node_it;
1126  }
1127  }
1128  // add cur_node to side A
1129  aside[*adj_edge_it] += 1;
1130  if (aside[*adj_edge_it] == 1)
1131  {
1132  list<node>::iterator node_it = unlockedB[*adj_edge_it].begin();
1133  list<node>::iterator nodes_end = unlockedB[*adj_edge_it].end();
1134  while (node_it != nodes_end)
1135  {
1136  update_bucketB(*node_it, gain_value[*node_it],
1137  gain_value[*node_it] + edge_weight[*adj_edge_it],
1138  init_mode);
1139  gain_value[*node_it] += edge_weight[*adj_edge_it];
1140  ++node_it;
1141  }
1142  }
1143  else if (aside[*adj_edge_it] == 2)
1144  {
1145  list<node>::iterator node_it = unlockedA[*adj_edge_it].begin();
1146  list<node>::iterator nodes_end = unlockedA[*adj_edge_it].end();
1147  while (node_it != nodes_end)
1148  {
1149  update_bucketA(*node_it, gain_value[*node_it],
1150  gain_value[*node_it] - edge_weight[*adj_edge_it],
1151  init_mode);
1152  gain_value[*node_it] -= edge_weight[*adj_edge_it];
1153  ++node_it;
1154  }
1155  }
1156  ++adj_edge_it;
1157  }
1158 }
1159 
1160 
1162  const int old_gain, const int new_gain, const bool init_mode)
1163 {
1164  if ((init_mode) && (cur_node == source_node))
1165  {
1166  return; // this one needs no update with init_mode
1167  }
1168  if (fixed[cur_node] != UNFIXED)
1169  {
1170  return; // fixed nodes need no update
1171  }
1172  bucketA[range_up(old_gain)].erase(position_in_bucket[cur_node]);
1173  bucketA[range_up(new_gain)].push_front(cur_node);
1174  position_in_bucket[cur_node] = bucketA[range_up(new_gain)].begin();
1175  if (max_gainA < new_gain)
1176  {
1177  max_gainA = new_gain;
1178  }
1179 }
1180 
1181 
1183  const int old_gain, const int new_gain, const bool init_mode)
1184 {
1185  if ((init_mode) && (cur_node == target_node))
1186  {
1187  return; // this one needs no update with init_mode
1188  }
1189  if (fixed[cur_node] != UNFIXED)
1190  {
1191  return; // fixed nodes need no update
1192  }
1193  bucketB[range_up(old_gain)].erase(position_in_bucket[cur_node]);
1194  bucketB[range_up(new_gain)].push_front(cur_node);
1195  position_in_bucket[cur_node] = bucketB[range_up(new_gain)].begin();
1196  if (max_gainB < new_gain)
1197  {
1198  max_gainB = new_gain;
1199  }
1200 }
1201 
1202 
1204 {
1205  if ((side == A) && (!bucketA_empty))
1206  {
1207  while (bucketA[range_up(max_gainA)].begin() ==
1209  {
1210  --max_gainA;
1211  if (range_up(max_gainA) < 0)
1212  {
1213  bucketA_empty = true;
1214  return;
1215  }
1216  }
1217  bucketA_empty = false;
1218  }
1219  if ((side == B) && (!bucketB_empty))
1220  {
1221  while (bucketB[range_up(max_gainB)].begin() ==
1223  {
1224  --max_gainB;
1225  if (range_up(max_gainB) < 0)
1226  {
1227  bucketB_empty = true;
1228  return;
1229  }
1230  }
1231  bucketB_empty = false;
1232  }
1233 }
1234 
1235 
1237 {
1238  // clean unlocked* lists
1239  graph::edge_iterator edge_it = G.edges_begin();
1240  graph::edge_iterator edges_end = G.edges_end();
1241  while (edge_it != edges_end)
1242  {
1243  unlockedA[*edge_it].clear();
1244  unlockedB[*edge_it].clear();
1245  ++edge_it;
1246  }
1247 
1248  // clean buckets
1249  for (int i = 0; i <= 2 * max_vertex_degree * max_edge_weight; i++)
1250  {
1251  bucketA[i].clear();
1252  bucketB[i].clear();
1253  }
1254  bucketA.clear();
1255  bucketB.clear();
1256 }
1257 
1258 
1261 {
1262  graph::node_iterator node_it = G.nodes_begin();
1263  graph::node_iterator nodes_end = G.nodes_end();
1264  while (node_it != nodes_end)
1265  {
1266  dest[*node_it] = source[*node_it];
1267  ++node_it;
1268  }
1269 }
1270 
1271 
1273 {
1274  bool continue_loop = true;
1275  int old_cutsize = cur_cutsize;
1276  double old_cutratio = cur_cutratio;
1277 
1278  while (continue_loop)
1279  {
1280  if (direction == LEFT_SHIFT)
1281  {
1283  if (fixed[source_node] == UNFIXED)
1284  {
1286  erase(position_in_bucket[source_node]);
1287  update_max_gain(A);
1288  }
1289  right_shift_op(G);
1290  clean_step(G);
1291  if (cur_cutratio < old_cutratio)
1292  {
1293  continue_loop = true;
1295  old_cutsize = cur_cutsize;
1296  old_cutratio = cur_cutratio;
1297  }
1298  else
1299  {
1300  continue_loop = false;
1301  }
1302  }
1303  else // direction == RIGHT_SHIFT
1304  {
1306  if (fixed[target_node] == UNFIXED)
1307  {
1309  erase(position_in_bucket[target_node]);
1310  update_max_gain(B);
1311  }
1312  left_shift_op(G);
1313  clean_step(G);
1314  if (cur_cutratio < old_cutratio)
1315  {
1316  continue_loop = true;
1318  old_cutsize = cur_cutsize;
1319  old_cutratio = cur_cutratio;
1320  }
1321  else
1322  {
1323  continue_loop = false;
1324  }
1325  }
1326  }
1327 }
1328 
1329 
1331 {
1332  bool improved_cutratio;
1333 
1334  do
1335  {
1337  improved_cutratio = move_manager(G);
1338  clean_step(G);
1339  }
1340  while (improved_cutratio);
1341 }
1342 
1343 
1345 {
1346  int step_number = 0;
1347  int best_tentative_move = 0;
1348  int best_bal = node_weight_on_sideA * node_weight_on_sideB;
1349  vector<node> tentative_moves(G.number_of_nodes() + 1);
1350  vector<double> tentative_cutratio(G.number_of_nodes() + 1);
1351  node moved_node;
1352  tentative_cutratio[0] = cur_cutratio;
1353  int best_cutsize = cur_cutsize;
1354 
1355  while (move_vertex(G, moved_node))
1356  {
1357  ++step_number;
1358  tentative_moves[step_number] = moved_node;
1359  tentative_cutratio[step_number] = cur_cutratio;
1360  if (tentative_cutratio[best_tentative_move] > cur_cutratio)
1361  {
1362  best_tentative_move = step_number;
1363  best_cutsize = cur_cutsize;
1365  }
1366  else if (tentative_cutratio[best_tentative_move] == cur_cutratio)
1367  {
1368  if (node_weight_on_sideA * node_weight_on_sideB > best_bal)
1369  {
1370  best_tentative_move = step_number;
1371  best_cutsize = cur_cutsize;
1373  }
1374  }
1375  }
1376 
1377  for (int i = 1; i <= best_tentative_move; i++)
1378  {
1379  if (side[tentative_moves[i]] == A)
1380  {
1381  side[tentative_moves[i]] = B;
1382  }
1383  else // side[tentative_moves[i]] == B
1384  {
1385  side[tentative_moves[i]] = A;
1386  }
1387  }
1388  cur_cutratio = tentative_cutratio[best_tentative_move];
1389  cur_cutsize = best_cutsize;
1390  if (best_tentative_move > 0) // cutratio improved
1391  {
1392  return true;
1393  }
1394  return false; // best_move == 0 --> cutratio not improved
1395 }
1396 
1397 
1398 bool ratio_cut_partition::move_vertex(const graph &G, node& moved_node)
1399 {
1400  bool consA_ok = false, consB_ok = false;
1401  node cons_nodeA, cons_nodeB;
1402 
1403  if (!bucketA_empty)
1404  {
1405  cons_nodeA =
1407  consA_ok = true;
1408  if (node_weight_on_sideA - node_weight[cons_nodeA] == 0)
1409  {
1410  node temp_node = cons_nodeA;
1411  bucketA[range_up(gain_value[cons_nodeA])].
1412  erase(position_in_bucket[cons_nodeA]);
1413  update_max_gain(A);
1414  if (!bucketA_empty) // nodes with smaller weight available?
1415  {
1416  cons_nodeA = compute_highest_ratio_node
1418  }
1419  else
1420  {
1421  consA_ok = false;
1422  }
1423  bucketA_empty = false;
1424  bucketA[range_up(gain_value[temp_node])].push_front(temp_node);
1425  position_in_bucket[temp_node] =
1426  bucketA[range_up(gain_value[temp_node])].begin();
1427  max_gainA = gain_value[temp_node];
1428  }
1429  }
1430  if (!bucketB_empty)
1431  {
1432  cons_nodeB =
1434  consB_ok = true;
1435  if (node_weight_on_sideB - node_weight[cons_nodeB] == 0)
1436  {
1437  node temp_node = cons_nodeB;
1438  bucketB[range_up(gain_value[cons_nodeB])].
1439  erase(position_in_bucket[cons_nodeB]);
1440  update_max_gain(B);
1441  if (!bucketB_empty) // nodes with smaller weight available?
1442  {
1443  cons_nodeB = compute_highest_ratio_node
1445  }
1446  else
1447  {
1448  consB_ok = false;
1449  }
1450  bucketB_empty = false;
1451  bucketB[range_up(gain_value[temp_node])].push_front(temp_node);
1452  position_in_bucket[temp_node] =
1453  bucketB[range_up(gain_value[temp_node])].begin();
1454  max_gainB = gain_value[temp_node];
1455  }
1456  }
1457 
1458  if (consA_ok && consB_ok)
1459  {
1460  double ratio_A2B = ratio_of_node_A2B(cons_nodeA);
1461  double ratio_B2A = ratio_of_node_B2A(cons_nodeB);
1462  if (ratio_A2B > ratio_B2A)
1463  {
1464  moved_node = cons_nodeA;
1466  erase(position_in_bucket[cons_nodeA]);
1467  update_data_structure_A2B(cons_nodeA, false);
1468  }
1469  else // ratio_A2B <= ratio_B2A
1470  {
1471  moved_node = cons_nodeB;
1473  erase(position_in_bucket[cons_nodeB]);
1474  update_data_structure_B2A(cons_nodeB, false);
1475  }
1476  }
1477  else if (consA_ok)
1478  {
1479  moved_node = cons_nodeA;
1480  bucketA[range_up(max_gainA)].erase(position_in_bucket[cons_nodeA]);
1481  update_data_structure_A2B(cons_nodeA, false);
1482  }
1483  else if (consB_ok)
1484  {
1485  moved_node = cons_nodeB;
1486  bucketB[range_up(max_gainB)].erase(position_in_bucket[cons_nodeB]);
1487  update_data_structure_B2A(cons_nodeB, false);
1488  }
1489  else
1490  {
1491  return false; // no more vertices can be moved
1492  }
1493  update_max_gain(A);
1494  update_max_gain(B);
1495  return true;
1496 }
1497 
1498 
1500 {
1501  cut_edges.clear();
1502  graph::edge_iterator edge_it = G.edges_begin();
1503  graph::edge_iterator edges_end = G.edges_end();
1504  while (edge_it != edges_end)
1505  {
1506  if (side[(*edge_it).source()] != side[(*edge_it).target()])
1507  {
1508  cut_edges.push_back(*edge_it);
1509  }
1510  ++edge_it;
1511  }
1512 }
1513 
1514 
1516 {
1517  nodesA.clear();
1518  nodesB.clear();
1519  graph::node_iterator node_it = G.nodes_begin();
1520  graph::node_iterator nodes_end = G.nodes_end();
1521  while (node_it != nodes_end)
1522  {
1523  if (side[*node_it] == A)
1524  {
1525  nodesA.push_back(*node_it);
1526  }
1527  else // side[*node_it] == B
1528  {
1529  nodesB.push_back(*node_it);
1530  }
1531  ++node_it;
1532  }
1533 }
1534 
1535 
1536 #ifdef _DEBUG
1537 void ratio_cut_partition::print_bucketA()
1538 {
1540  GTL_debug::os() << endl << "bucketA:" << endl;
1541  for (int i = 0; i <= 2 * max_vertex_degree * max_edge_weight; i++)
1542  {
1543  GTL_debug::os() << range_down(i) << ": ";
1544  list<node>::iterator node_it = bucketA[i].begin();
1545  list<node>::iterator nodes_end = bucketA[i].end();
1546  while (node_it != nodes_end)
1547  {
1548  GTL_debug::os() << *node_it << " ";
1549  ++node_it;
1550  }
1551  GTL_debug::os() << endl;
1552  }
1553  GTL_debug::os() << endl;
1555 }
1556 
1557 
1558 void ratio_cut_partition::print_bucketB()
1559 {
1561  GTL_debug::os() << endl << "bucketB:" << endl;
1562  for (int i = 0; i <= 2 * max_vertex_degree * max_edge_weight; i++)
1563  {
1564  GTL_debug::os() << range_down(i) << ": ";
1565  list<node>::iterator node_it = bucketB[i].begin();
1566  list<node>::iterator nodes_end = bucketB[i].end();
1567  while (node_it != nodes_end)
1568  {
1569  GTL_debug::os() << *node_it << " ";
1570  ++node_it;
1571  }
1572  GTL_debug::os() << endl;
1573  }
1574  GTL_debug::os() << endl;
1576 }
1577 #endif // _DEBUG
1578 
1579 
1581 
1582 //--------------------------------------------------------------------------
1583 // end of file
1584 //--------------------------------------------------------------------------