Aleph-w  1.5a.2
Biblioteca general de algoritmos y estructuras de datos
 Todo Clases Archivos Funciones Variables 'typedefs' Enumeraciones Amigas Grupos Páginas
tpl_cut_nodes.H
1 # ifndef TPL_CUT_NODES_H
2 # define TPL_CUT_NODES_H
3 
4 # include <tpl_graph_utils.H>
5 
6 namespace Aleph {
7 
8 
67  template <class GT, class SA = Dft_Show_Arc<GT> >
69 {
70  SA & sa;
71  GT * gptr;
73  long curr_df;
74  long curr_color;
75 
76  enum State { Init, Cut_Nodes_Computed, Painted } state;
77 
78  void cut_nodes(typename GT::Node * p, typename GT::Arc * a)
79  {
80  NODE_BITS(p).set_bit(Depth_First, true); // pinte p visitado
81  low <GT> (p) = df <GT> (p) = curr_df++; // asígnele df
82 
83  // recorrer arcos de p mientras no se abarque a g
84  bool p_is_cut_node = false;
85  for (Node_Arc_Iterator <GT, SA> i(p, sa); i.has_curr(); i.next())
86  {
87  typename GT::Arc * arc = i.get_current_arc();
88  if (arc == a)
89  continue; // a es el padre de arc ==> ignorarlo
90 
91  typename GT::Node * tgt = i.get_tgt_node();
92  if (IS_NODE_VISITED(tgt, Depth_First))
93  {
94  if (not IS_ARC_VISITED(arc, Depth_First)) // no abarcador?
95  if (df<GT>(tgt) < low<GT>(p)) // sí, verificar valor low
96  low<GT>(p) = df<GT>(tgt); // actualizar low(p)
97 
98  continue;
99  }
100 
101  if (IS_ARC_VISITED(arc, Depth_First))
102  continue;
103 
104  ARC_BITS(arc).set_bit(Depth_First, true); // marque arco
105 
106  cut_nodes(tgt, arc);
107 
108  if (low<GT>(tgt) < low<GT>(p))
109  low<GT>(p) = low<GT>(tgt); // actualizar low(p)
110 
111  if (low<GT>(tgt) >= df<GT>(p) and df<GT>(tgt) != 0) // ¿de corte?
112  p_is_cut_node = true;
113  }
114 
115  // aquí, p ya fue explorado recursivamente
116  if (p_is_cut_node)
117  {
118  NODE_BITS(p).set_bit(Cut, true);
119  list_ptr->append(p);
120  }
121  }
122 
123 public:
124 
138  void cut_nodes(typename GT::Node * start,
140  {
141  curr_df = 0; // contador global de visitas
142  list_ptr = &list;
143 
144  list_ptr->empty();
145 
147 
148  gptr->reset_arcs();
149 
150  NODE_BITS(start).set_bit(Depth_First, true); // marcar start
151  df <GT> (start) = curr_df++;
152 
153  int call_counter = 0; // contador de llamadas recursivas
154 
155  // Recorra los arcos de start mientras g no haya sido abarcado
156  for (Node_Arc_Iterator<GT, SA> it(start, sa);
157  it.has_curr() and curr_df < gptr->get_num_nodes(); it.next())
158  {
159  typename GT::Node * tgt = it.get_tgt_node();
160  if (IS_NODE_VISITED(tgt, Depth_First))
161  continue;
162 
163  typename GT::Arc * arc = it.get_current_arc();
164  if (IS_ARC_VISITED(arc, Depth_First))
165  continue;
166 
167  ARC_BITS(arc).set_bit(Depth_First, true);
168  cut_nodes(tgt, arc);
169  ++call_counter;
170  }
171 
172  if (call_counter > 1) // ¿es la raíz un punto de articulación?
173  { // sí == métala en la lista
174  NODE_BITS(start).set_bit(Cut, true);
175  list_ptr->append(start);
176  }
177 
178  state = Cut_Nodes_Computed;
179  }
180 
181 private:
182 
183  void paint_subgraph(typename GT::Node * p)
184  {
185  I(not is_a_cut_node <GT> (p));
186 
187  if (is_node_painted <GT> (p))
188  return;
189 
190  paint_node <GT> (p, curr_color);
191 
192  for (Node_Arc_Iterator<GT, SA> it(p, sa); it.has_curr(); it.next())
193  {
194  typename GT::Arc * arc = it.get_current_arc();
195  if (is_arc_painted <GT> (arc))
196  continue;
197 
198  typename GT::Node * tgt = it.get_tgt_node();
199  if (is_a_cut_node <GT> (tgt))
200  continue;
201 
202  paint_arc<GT>(arc, curr_color);
203 
204  paint_subgraph(tgt);
205  }
206  }
207 
208  void paint_from_cut_node(typename GT::Node * p)
209  {
210  I(is_a_cut_node <GT> (p));
211 
212  // pintar recursivamente con dif colores bloques conectados a p
213  for (Node_Arc_Iterator<GT, SA> it(p, sa); it.has_curr(); it.next())
214  {
215  typename GT::Arc * arc = it.get_current_arc();
216 
217  I(not is_arc_painted <GT> (arc));
218 
219  typename GT::Node * tgt_node = it.get_tgt_node();
220  if (is_a_cut_node <GT> (tgt_node)) // ¿ es un arco de corte?
221  {
222  ARC_BITS(arc).set_bit(Cut, true); // marque como de corte
223  continue; // avance a próximo arco
224  }
225  else
226  {
227  paint_arc <GT> (arc, Cross_Arc); // marque como de cruce
228  if (is_node_painted <GT> (tgt_node))
229  continue;
230  }
231 
232  // pintar recursivamente nodo conectado a arc
233  paint_subgraph(tgt_node);
234 
235  curr_color++; // cambiar color (sig arco en otro bloque)
236 
237  I(not is_arc_painted <GT> (arc));
238  }
239  }
240 
241  typename GT::Node * create_and_map_node(typename GT::Node * gp,
242  const long & color,
243  GT & sg)
244  {
245  I(get_color<GT>(gp) == color);
246  I(not IS_NODE_VISITED(gp, Build_Subtree));
247 
248  unique_ptr<typename GT::Node> tp_auto(new typename GT::Node(gp));
249  sg.insert_node(tp_auto.get());
250  GT::map_nodes(gp, tp_auto.get());
251  NODE_BITS(gp).set_bit(Build_Subtree, true);
252 
253  return tp_auto.release();
254  }
255 
256  void map_subgraph(GT & sg, typename GT::Node * gsrc, const long & color)
257  {
258  I(get_color <GT> (gsrc) == color);
259 
260  typename GT::Node * tsrc = mapped_node<GT>(gsrc); // gsrc en sg
261 
262  // recorrer arcos de gsrc y añadir a sg los del color de interés
263  for (Node_Arc_Iterator <GT, SA> i(gsrc, sa); i.has_curr(); i.next())
264  {
265  typename GT::Arc * garc = i.get_current_arc();
266  if (get_color<GT>(garc) != color or IS_ARC_VISITED(garc, Build_Subtree))
267  continue; // arco es de otro color o ya está visitado
268 
269  ARC_BITS(garc).set_bit(Build_Subtree, true);
270 
271  typename GT::Node * gtgt = i.get_tgt_node();
272 
273  I(get_color <GT> (gtgt) == color);
274 
275  typename GT::Node * ttgt = NULL; // imagen gtgt en sg
276  if (IS_NODE_VISITED(gtgt, Build_Subtree)) // ¿gtgt en sg?
277  ttgt = mapped_node<GT> (gtgt);
278  else
279  ttgt = create_and_map_node(gtgt, color, sg);
280 
281  typename GT::Arc * tarc = sg.insert_arc(tsrc, ttgt, garc->get_info());
282  GT::map_arcs(garc, tarc);
283 
284  map_subgraph(sg, gtgt, color);
285  }
286  }
287 
288 public:
289 
297  Compute_Cut_Nodes(GT & g, SA && __sa = SA())
298  : sa(__sa), gptr(&g), state(Init)
299  {
300  /* empty */
301  }
302 
303  Compute_Cut_Nodes(GT & g, SA & __sa)
304  : sa(__sa), gptr(&g)
305  {
306  /* empty */
307  }
308 
311  {
312  cut_nodes(gptr->get_first_node(), list);
313  }
314 
316  void operator () (typename GT::Node * start,
318  {
319  cut_nodes(start, list);
320  }
321 
343  {
344  if (state != Cut_Nodes_Computed)
345  throw std::logic_error("Cut nodos has not been computed or the class is"
346  " another phase");
347 
348  gptr->reset_counter_nodes();
349  gptr->reset_counter_arcs();
350  curr_color = 1;
351 
352  // Recorrer cada nodo de corte y pintar sus bloques
353  for (typename DynDlist<typename GT::Node*>::Iterator i(*list_ptr);
354  i.has_curr(); i.next())
355  paint_from_cut_node(i.get_curr());
356 
357  state = Painted;
358 
359  return curr_color;
360  }
361 
373  void map_subgraph(GT & sg, const long & color)
374  {
375  if (state != Painted)
376  throw std::logic_error("Graph is not painted");
377 
378  clear_graph(sg);
379 
380  typename GT::Node * first = NULL; // busque primer nodo con color
381 
382  for (typename GT::Node_Iterator it(*gptr); it.has_current(); it.next())
383  if (get_color <GT> (it.get_current_node()) == color)
384  first = it.get_current_node();
385 
386  if (first == NULL) // Encontró el color?
387  throw std::domain_error("Color does not exist in the graph");
388 
389  // cree first, insértelo en sg y mapéelo
390  create_and_map_node(first, color, sg);
391  try
392  {
393  map_subgraph (sg, first, color); // mapee first
394  }
395  catch (...)
396  {
397  clear_graph(sg);
398  }
399  }
400 
420  void map_cut_graph(GT & cut_graph,
421  DynDlist<typename GT::Arc*> & cross_arc_list)
422  {
423  if (state != Painted)
424  throw std::logic_error("Graph is not painted");
425 
426  clear_graph(cut_graph);
427 
428  // recorra lista de nodos de corte e insértelos en cut_graph
429  for (typename DynDlist<typename GT::Node*>::Iterator it(*list_ptr);
430  it.has_curr(); it.next())
431  {
432  typename GT::Node * gp = it.get_current();
433 
434  I(is_a_cut_node <GT> (gp));
435 
436  unique_ptr<typename GT::Node> tp_auto(new typename GT::Node(gp));
437  cut_graph.insert_node(tp_auto.get());
438  GT::map_nodes(gp, tp_auto.release());
439  }
440 
441  // recorra arcos de g ==> cut_graph = {arcos no corte} U
442  // cross_arc_list = {arcos de cruce}
443  for (Arc_Iterator <GT, SA> it(*gptr, sa); it.has_curr(); it.next())
444  {
445  typename GT::Arc * garc = it.get_current_arc();
446  if (is_a_cross_arc <GT> (garc))
447  {
448  cross_arc_list.append(garc);
449  continue;
450  }
451 
452  if (not is_an_cut_arc <GT> (garc))
453  continue;
454 
455  typename GT::Node * src = mapped_node<GT>(gptr->get_src_node(garc));
456  typename GT::Node * tgt = mapped_node<GT>(gptr->get_tgt_node(garc));
457 
458  I(src != NULL and tgt != NULL);
459 
460  typename GT::Arc * arc =
461  cut_graph.insert_arc(src, tgt, garc->get_info());
462  GT::map_arcs(garc, arc);
463  }
464  }
465 
488  void compute_blocks(DynDlist<GT> & block_list,
489  GT & cut_graph,
490  DynDlist<typename GT::Arc*> & cross_arc_list)
491  {
492  if (state < Cut_Nodes_Computed)
493  throw std::logic_error("Cut nodes have not been computed");
494 
495  if (state == Cut_Nodes_Computed)
496  paint_subgraphs();
497 
498  const long & num_colors = curr_color;
499 
500  DynArray<GT*> blocks; // bloques en un arreglo para rápido
501  // acceso. Que esté o no vacío indica si ha
502  // sido o no procesado.
503  blocks.reserve(num_colors);
504 
505  // crear lista de componentes vacíos ordenador por color i
506  for (int i = 0; i < num_colors; ++i)
507  blocks.access(i) = &block_list.append(GT());
508 
509  // Recorrer los nodos y copiar y mapear según color
510  for (typename GT::Node_Iterator it(*gptr); it.has_curr(); it.next())
511  {
512  typename GT::Node * p = it.get_curr();
513  if (IS_NODE_VISITED(p, Build_Subtree))
514  continue;
515 
516  if (is_a_cut_node <GT> (p))
517  continue;
518 
519  const long color = get_color<GT>(p);
520 
521  GT & sg = *blocks.access(color - 1);
522 
523  create_and_map_node(p, color, sg);
524 
525  map_subgraph(sg, p, color);
526  }
527 
528  map_cut_graph(cut_graph, cross_arc_list);
529  }
530 };
531 
532 } // end namespace Aleph
533 
534 # endif // TPL_CUT_NODES_H
long paint_subgraphs()
Definition: tpl_cut_nodes.H:342
void reserve(const size_t l, const size_t r)
Definition: tpl_dynArray.H:960
Definition: tpl_graph.H:751
Definition: tpl_graph.H:1389
#define IS_NODE_VISITED(p, bit)
Definition: aleph-graph.H:242
void map_subgraph(GT &sg, const long &color)
Definition: tpl_cut_nodes.H:373
void operator()(DynDlist< typename GT::Node * > &list)
Definition: tpl_cut_nodes.H:310
void clear_graph(GT &g)
Definition: tpl_graph.H:2486
#define IS_ARC_VISITED(p, bit)
Definition: aleph-graph.H:275
void empty()
Vacía todos los elementos de la lista.
Definition: tpl_dynDlist.H:45
void next()
Adelanta el iterador una posición.
Definition: filter_iterator.H:143
Definition: tpl_cut_nodes.H:68
void map_cut_graph(GT &cut_graph, DynDlist< typename GT::Arc * > &cross_arc_list)
Definition: tpl_cut_nodes.H:420
#define NODE_BITS(p)
Definition: aleph-graph.H:221
Compute_Cut_Nodes(GT &g, SA &&__sa=SA())
Definition: tpl_cut_nodes.H:297
void compute_blocks(DynDlist< GT > &block_list, GT &cut_graph, DynDlist< typename GT::Arc * > &cross_arc_list)
Definition: tpl_cut_nodes.H:488
#define ARC_BITS(p)
Definition: aleph-graph.H:266
Definition: tpl_dynArray.H:70
void cut_nodes(typename GT::Node *start, DynDlist< typename GT::Node * > &list)
Definition: tpl_cut_nodes.H:138
T & access(const size_t i)
Definition: tpl_dynArray.H:793
Definition: tpl_graph.H:694
Definition: List.H:23
T & append(const T &item)
Definition: tpl_dynDlist.H:106

Leandro Rabindranath León