Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
planarity.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file planarity.cpp
1 /* This software is distributed under the GNU Lesser General Public License */
2 //==========================================================================
3 //
4 // planarity.cpp
5 //
6 //==========================================================================
7 // $Id: planarity.cpp,v 1.28 2008/02/03 18:12:07 chris Exp $
8 
9 #include <GTL/planarity.h>
10 #include <GTL/pq_tree.h>
11 #include <GTL/biconnectivity.h>
12 #include <GTL/debug.h>
13 
14 #include <iostream>
15 #include <cstdio>
16 #include <fstream>
17 #include <sstream>
18 
19 #ifdef __GTL_MSVCC
20 # ifdef _Debug
21 # ifndef SEARCH_MEMORY_LEAKS_ENABLED
22 # error SEARCH NOT ENABLED
23 # endif
24 # define new DEBUG_NEW
25 # undef THIS_FILE
26  static char THIS_FILE[] = __FILE__;
27 # endif // _DEBUG
28 #endif // __GTL_MSVCC
29 
31 
32 //--------------------------------------------------------------------------
33 // Planarity Test
34 //--------------------------------------------------------------------------
35 
36 
38  algorithm (), emp (false), kup (false), bip (true)
39 {
40 #ifdef _DEBUG
42 #endif
43 };
44 
46 {
47 #ifdef _DEBUG
49 #endif
50 };
51 
52 
54 {
55  return algorithm::GTL_OK;
56 }
57 
59 {
60 
61  if (G.number_of_edges() == 0) return algorithm::GTL_OK;
62 
63  st_number st_;
64 
65  //
66  // The graph may have self loops. Make sure that we
67  // choose a normal edge for st.
68  //
69 
71  edge_it = G.edges_begin(),
72  edge_end = G.edges_end();
73 
74  edge st;
75 
76  while (edge_it != edge_end) {
77  if ((*edge_it).source() != (*edge_it).target()) {
78  st = *edge_it;
79  break;
80  }
81  ++edge_it;
82  }
83 
84  //
85  // G has only selfloops
86  //
87 
88  if (st == edge()) {
89  if (emp) {
90  em.init (G);
91  edge_it = G.edges_begin();
92  edge_end = G.edges_end();
93 
94  for (;edge_it != edge_end; ++edge_it) {
95  em.self.push_back (*edge_it);
96  }
97  }
98 
99  return algorithm::GTL_OK;
100  }
101 
102  st_.st_edge (st);
103  st_.s_node (st.source());
104  int res = st_.check(G);
105  assert (res == algorithm::GTL_OK);
106  res = st_.run(G);
107  assert (res == algorithm::GTL_OK);
108  int size = G.number_of_nodes();
109 
110  if (emp) {
111  em.init (G);
112  }
113 
114  list<pq_leaf*> neighbors;
115  st_number::iterator st_it = st_.begin();
116  node curr = *st_it;
120  node::in_edges_iterator i_end = curr.in_edges_end();
121  list<edge> self_loops;
122  node opp;
123  node_map<int> visited_from (G, 0);
124  pq_leaf* tmp_leaf;
125  vector< list<pq_leaf*> > leaves (size);
126 
127  for (; o_it != o_end; ++o_it) {
128  opp = curr.opposite (*o_it);
129 
130  if (opp != curr) {
131  if (visited_from[opp] == st_[curr] && emp) {
132  em.multi.push_back (*o_it);
133  } else {
134  visited_from[opp] = st_[curr];
135  tmp_leaf = new pq_leaf (st_[opp], st_[curr], *o_it, opp);
136  leaves[st_[opp]-1].push_back (tmp_leaf);
137  neighbors.push_back (tmp_leaf);
138  }
139 
140  } else if (emp) {
141  em.self.push_back (*o_it);
142  }
143  }
144 
145  for (; i_it != i_end; ++i_it) {
146  opp = curr.opposite (*i_it);
147 
148  if (opp != curr) {
149  if (visited_from[opp] == st_[curr] && emp) {
150  em.multi.push_back (*i_it);
151  } else {
152  visited_from[opp] = st_[curr];
153  tmp_leaf = new pq_leaf (st_[opp], st_[curr], *i_it, opp);
154  leaves[st_[opp]-1].push_back (tmp_leaf);
155  neighbors.push_back (tmp_leaf);
156  }
157  }
158  }
159 
161 
162  //
163  // There is a problem with node/edge maps of iterators with Visual C++
164  // which I donīt fully understand at the moment. Fortunatly the init for the
165  // maps below is only needed to allocate memory, which is done anyway, when
166  // values are assigned to it.
167  //
168 
169 #ifndef __GTL_MSVCC
170  dirs.init (G);
171 #endif
172  pq_tree PQ (st_[curr], curr, neighbors);
173  neighbors.erase (neighbors.begin(), neighbors.end());
174  ++st_it;
175  curr = *st_it;
176 
177  while (st_[curr] < size) {
178 
179 #ifdef _DEBUG
180  char filename[10] = "out";
181  char buffer[12];
182 #ifdef __GTL_MSVCC
183  _snprintf (buffer, 12, "%s%d.gml", filename, st_[curr]);
184 #else
185  snprintf (buffer, 12, "%s%d.gml", filename, st_[curr]);
186 #endif
187  ofstream os (buffer, ios::out | ios::trunc);
188  os << PQ << endl;
189  os.close();
190  bool ret_flag = PQ.integrity_check();
191  assert(ret_flag);
192 #endif
193 
194  if (!PQ.reduce (leaves[st_[curr]-1])) {
195 #ifdef _DEBUG
196  os.open ("fail.gml", ios::out | ios::trunc);
197  os << PQ << endl;
198  os.close ();
199 #endif
200  if (kup) {
201  examine_obstruction (G, st_, curr,
202  PQ.get_fail(), PQ.is_fail_root(), em, dirs, &PQ);
203  }
204 
205  PQ.reset();
206  return false;
207  }
208 
209 
210  //
211  // It seems to be not very comfortable to use in and out iterators to
212  // go through the adjacency of a node. For graphs without selfloops this
213  // could be replaced by using adj_iterator, but if there are selfloops
214  // they will occur in both the list of outgoing and the one of incoming
215  // edges, and thus two times in the adjacency.
216  //
217 
218  o_it = curr.out_edges_begin();
219  o_end = curr.out_edges_end();
220  i_it = curr.in_edges_begin();
221  i_end = curr.in_edges_end();
222 
223  for (; o_it != o_end; ++o_it) {
224  opp = curr.opposite (*o_it);
225 
226  if (st_[opp] > st_[curr]) {
227  if (visited_from[opp] == st_[curr] && emp) {
228  em.multi.push_back (*o_it);
229  } else {
230  visited_from[opp] = st_[curr];
231  tmp_leaf = new pq_leaf (st_[opp], st_[curr], *o_it, opp);
232  leaves[st_[opp]-1].push_back (tmp_leaf);
233  neighbors.push_back (tmp_leaf);
234  }
235 
236  } else if (st_[opp] == st_[curr] && emp) {
237  em.self.push_back (*o_it);
238  }
239  }
240 
241  for (; i_it != i_end; ++i_it) {
242  opp = curr.opposite (*i_it);
243 
244  if (st_[opp] > st_[curr]) {
245  if (visited_from[opp] == st_[curr] && emp) {
246  em.multi.push_back (*i_it);
247  } else {
248  visited_from[opp] = st_[curr];
249  tmp_leaf = new pq_leaf (st_[opp], st_[curr], *i_it, opp);
250  leaves[st_[opp]-1].push_back (tmp_leaf);
251  neighbors.push_back (tmp_leaf);
252  }
253  }
254  }
255 
256  if (emp) {
257  PQ.replace_pert (st_[curr], curr, neighbors, &em, &(dirs[curr]));
258 #ifdef _DEBUG
259  GTL_debug::os() << "Embedding of " << st_[curr] << ":: ";
260  planar_embedding::iterator adit, adend;
261  for (adit = em.adj_edges_begin (curr), adend = em.adj_edges_end (curr); adit != adend; ++adit) {
262  GTL_debug::os() << "[" << st_[curr.opposite (*adit)] << "]";
263  }
264  GTL_debug::os() << endl;
265  GTL_debug::os() << "Direction Indicators for: " << st_[curr] << ":: ";
266  list<direction_indicator>::iterator dit, dend;
267 
268  for (dit = dirs[curr].begin(), dend = dirs[curr].end(); dit != dend; ++dit) {
269  GTL_debug::os() << "[";
270  if ((*dit).direction)
271  GTL_debug::os() << ">> " << (*dit).id << " >>";
272  else
273  GTL_debug::os() << "<< " << (*dit).id << " <<";
274  GTL_debug::os() << "]";
275  }
276  GTL_debug::os() << endl;
277 #endif
278 
279  } else {
280  PQ.replace_pert (st_[curr], curr, neighbors);
281  }
282 
283  PQ.reset();
284 
285 
286  neighbors.erase (neighbors.begin(), neighbors.end());
287  ++st_it;
288  curr = *st_it;
289  }
290 
291  if (emp) {
292  PQ.get_frontier (em, dirs[curr]);
293 
294 
295  //
296  // get self_loops for last node
297  //
298 
299  o_it = curr.out_edges_begin();
300  o_end = curr.out_edges_end();
301 
302  for (; o_it != o_end; ++o_it) {
303  if ((*o_it).target() == (*o_it).source()) {
304  em.self.push_back (*o_it);
305  }
306  }
307 
308  //
309  // some adjcacency list of the embedding obtained so far have to be
310  // turned.
311  //
312 
313  correct_embedding(em, st_, dirs);
314 
315  node_map<int> mark;
316  mark.init (G, 0);
317  node_map<symlist<edge>::iterator > upward_begin;
318  upward_begin.init (G);
319  node tmp;
320 
321  forall_nodes (tmp, G) {
322  upward_begin[tmp] = em.adjacency(tmp).begin();
323  }
324 
325  extend_embedding(curr, em, mark, upward_begin);
326  }
327 
328  return true;
329 }
330 
331 
333 {
334  bool directed = false;
335 
336  if (G.is_directed()) {
337  G.make_undirected();
338  directed = true;
339  }
340 
341  biconnectivity biconn;
342 
343  if (bip) {
344  biconn.make_biconnected (true);
345  } else {
346  biconn.store_components (true);
347  }
348 
349  biconn.check (G);
350  biconn.run (G);
351 
352  if (emp) {
353  embedding.init (G);
354  }
355 
356  planar_embedding em;
357 
358  if (!biconn.is_biconnected() && !bip) {
360 
361  for (c_it = biconn.components_begin(), c_end = biconn.components_end();
362  c_it != c_end; ++c_it) {
363 
364  switch_to_component (G, c_it);
365 
366 #ifdef _DEBUG
367  GTL_debug::os() << "Component is: " << endl;
368  GTL_debug::os() << G << endl;
369 #endif
370  if (!run_on_biconnected (G, em)) {
371  if (directed) {
372  G.make_directed();
373  }
374 
375  G.restore_graph();
376  planar = false;
377  return algorithm::GTL_OK;
378  }
379 
380  if (emp) {
381  add_to_embedding (G, em);
382  }
383  }
384 
385  G.restore_graph();
386 
387  } else {
388 
389  //
390  // G is already biconnected
391  //
392 
393  GTL_debug::debug_message ("graph is biconnected\n");
394 
395  if (!run_on_biconnected (G, embedding)) {
396  if (directed) {
397  G.make_directed();
398  }
399 
400  planar = false;
401  return algorithm::GTL_OK;
402  }
403  }
404 
405  if (bip) {
406  list<edge>::iterator it, end;
407  it = biconn.additional_begin();
408  end = biconn.additional_end();
409 
410  for (; it != end; ++it) {
411 
412  if (emp) {
413  node s = (*it).source();
414  node t = (*it).target();
415  embedding.adj[s].erase (embedding.s_pos[*it]);
416  embedding.adj[t].erase (embedding.t_pos[*it]);
417  }
418 
419  G.del_edge (*it);
420  }
421  }
422 
423  if (directed) {
424  G.make_directed();
425  }
426 
427  planar = true;
428  return algorithm::GTL_OK;
429 }
430 
432 {
433  node n;
434  forall_nodes (n, G) {
437 
438  for (; it != end; ++it) {
439  embedding.pos (n, *it) = em.pos (n, *it);
440  }
441 
444  em.adj_edges_begin (n),
445  em.adj_edges_end (n));
446  }
447 
448  embedding.self.splice (
449  embedding.self.end(),
450  em.self, em.self.begin(), em.self.end());
451  embedding.multi.splice (
452  embedding.multi.end(),
453  em.multi, em.multi.begin(), em.multi.end());
454 }
455 
456 
458 {
459  ob_edges.erase (ob_edges.begin(), ob_edges.end());
460  ob_nodes.erase (ob_nodes.begin(), ob_nodes.end());
461 }
462 
463 
465  planar_embedding& em,
466  st_number& st_,
467  node_map<list<direction_indicator> >& dirs)
468 {
471  bool* turn = new bool[st_[*it]];
472 
473  for (int i = 0; i < st_[*it]; ++i) {
474  turn[i] = false;
475  }
476 
477  while (it != end) {
478  node curr = *it;
479 
480  if (turn[st_[curr] - 1]) {
481  em.adjacency(curr).reverse();
482  }
483 
484  list<direction_indicator>::iterator d_it = dirs[curr].begin();
485 
486  while (!dirs[curr].empty()) {
487 
488  if ((*d_it).direction && turn[st_[curr] - 1] ||
489  !(*d_it).direction && !turn[st_[curr] - 1]) {
490  turn[(*d_it).id - 1] = true;
491  }
492 
493  d_it = dirs[curr].erase (d_it);
494  }
495 
496  ++it;
497  }
498 
499  delete[] turn;
500 }
501 
502 
504  node n,
505  planar_embedding& em,
506  node_map<int>& mark,
507  node_map<symlist<edge>::iterator >& upward_begin)
508 {
509  mark[n] = 1;
510 
511  symlist<edge>::iterator it = upward_begin[n];
513  node other;
514 
515  for (; it != end; ++it) {
516  em.pos (n, *it) = it;
517  other = n.opposite (*it);
518  em.pos (other, *it) = em.push_front (other, *it);
519 
520  if (mark[other] == 0) {
521  extend_embedding (other, em, mark, upward_begin);
522  }
523  }
524 }
525 
528 {
529  //
530  // hide all nodes
531  //
532 
533  list<node> dummy;
534  G.induced_subgraph (dummy);
535 
536  //
537  // Restore nodes in this component.
538  //
539 
540  list<node>::iterator it = (*c_it).first.begin();
541  list<node>::iterator end = (*c_it).first.end();
542 
543  for (; it != end; ++it) {
544  G.restore_node (*it);
545  }
546 
547  //
548  // Restore edges in this component.
549  //
550 
551  list<edge>::iterator e_it = (*c_it).second.begin();
552  list<edge>::iterator e_end = (*c_it).second.end();
553 
554  for (; e_it != e_end; ++e_it) {
555  G.restore_edge (*e_it);
556  }
557 }
558 
560  st_number& st_,
561  node act,
562  pq_node* fail,
563  bool is_root,
564  planar_embedding& em,
565  node_map<list<direction_indicator> >& dirs,
566  pq_tree* PQ)
567 {
568  node_map<int> used (G, 0);
569  node_map<edge> to_father (G);
570 
571  //
572  // Create a dfs-tree of the so called bush form. This is basically a normal dfs
573  // applied to the induced subgraph of G consisting only of the nodes with st_number
574  // 1, ..., st_[act] - 1. The only difference is that edges are always directed from
575  // the lower numbered vertex to higher numbered one.
576  //
577 
578  dfs_bushform (st_.s_node(), used, st_, st_[act], to_father);
579 
580  if (fail->kind() == pq_node::Q_NODE) {
581 
582  //
583  // In case the reduction failed at a Q-Node we need to know the edges that
584  // form the boundary of the biconnected component, which this Q-Node represents.
585  // These can easily be obtained from the embedding we got so far.
586  //
587 
588  q_node* q_fail = fail->Q();
589 
590  pq_tree::sons_iterator s_it = q_fail->sons.begin();
591  pq_tree::sons_iterator s_end = q_fail->sons.end();
592  node greatest = fail->n;
593 
594  while (s_it != s_end) {
595  if ((*s_it)->kind() == pq_node::DIR) {
596  direction_indicator* dir = (*s_it)->D();
598 
599  if (++tmp == ++(dir->pos)) {
600  dir->direction = true;
601  } else {
602  dir->direction = false;
603  }
604 
605  dirs[act].push_back (*dir);
606 
607  //
608  // chris 2/3/2008:
609  //
610  // To avoid a memory leak, it is not sufficient to erase it from the
611  // PQ-tree (-node). The direction indicator object also has to be
612  // deleted. Since it is then not a member of the pertinent subtree any
613  // more, it must not be cleared by PQ->reset(). The instance in the
614  // dirs node map is a clone!
615  //
616 
617  // s_it = q_fail->sons.erase (s_it);
618  s_it = PQ->remove_dir_ind(q_fail, s_it);
619  } else {
620  if (st_[(*s_it)->up] > st_[greatest]) {
621  greatest = (*s_it)->up;
622  }
623 
624  ++s_it;
625  }
626  }
627 
628  correct_embedding (em, st_, dirs);
629  node_map<int> mark;
630  mark.init (G, 0);
631  node_map<symlist<edge>::iterator > upward_begin;
632  upward_begin.init (G);
633  node tmp;
634 
635  em.adjacency(fail->n).erase (
636  em.adjacency(fail->n).begin(),
637  em.adjacency(fail->n).end());
638 
639  forall_nodes (tmp, G) {
640  upward_begin[tmp] = em.adjacency(tmp).begin();
641  }
642 
643  //
644  // chris 2/3/2008:
645  //
646  // With the code of MR 11/27/2001 the component of the failing Q-node is not found
647  // correctly.
648  //
649 
650  extend_embedding(greatest, em, mark, upward_begin);
651 
652  /*
653  //
654  // MR 11/27/2001:
655  //
656  // This is important! We restricted building the embedding to the nodes in
657  // the biconnected component which the Q-node fail refers to. But the st-number
658  // obtained for the whole graph restricted to these nodes will not be a st-numbering
659  // for this biconnected component.
660  //
661 
662  st_number::reverse_iterator st_it, st_end;
663 
664  for (st_it = st_.rbegin(), st_end = st_.rend();
665  st_it != st_end;
666  ++st_it)
667  {
668  if (mark[*st_it] == 0) {
669  extend_embedding (*st_it, em, mark, upward_begin);
670  }
671  }
672  */
673 #ifdef _DEBUG
674  GTL_debug::os() << "Embedding so far (st_numbered): " << endl;
675  em.write_st (GTL_debug::os(), st_);
676 #endif
677 
678  attachment_cycle (fail->n, em);
679 
680  if (!q_fail->pert_cons) {
681 
682  //
683  // the reduction failed because there was more than one block
684  // of pertinent children. The reduction in this case assures that
685  // pert_begin and pert_end lie in different blocks and that
686  // --pert_end is empty and lies between these two blocks.
687  //
688  // This is one of the two cases that may apply when the reduction
689  // fails already in bubble up. The reduction takes care of this.
690  //
691 
692  GTL_debug::debug_message ("CASE C (non consecutive pertinent children)\n");
693  pq_tree::sons_iterator tmp = q_fail->pert_begin;
694  pq_leaf* leaves[3];
695  node nodes[3];
696  leaves[0] = search_full_leaf (*tmp);
697  nodes[0] = (*tmp)->up;
698 
699  tmp = q_fail->pert_end;
700  leaves[2] = search_full_leaf (*tmp);
701  nodes[2] = (*tmp)->up;
702 
703  --tmp;
704  while ((*tmp)->kind() == pq_node::DIR) {
705  --tmp;
706  }
707 
708  leaves[1] = search_empty_leaf (*tmp);
709  nodes[1] = (*tmp)->up;
710 
711  case_C (nodes, leaves, st_, to_father, G, q_fail);
712 
713  } else if (!(*(q_fail->pert_end))->is_endmost && !is_root) {
714 
715  GTL_debug::debug_message ("CASE D (non-root q-node with both endmost sons empty)\n");
716  pq_tree::sons_iterator tmp = q_fail->sons.begin();
717  pq_leaf* leaves[3];
718  node nodes[3];
719  leaves[0] = search_empty_leaf (*tmp);
720  nodes[0] = (*tmp)->up;
721 
722  tmp = --(q_fail->sons.end());
723  leaves[2] = search_empty_leaf (*tmp);
724  nodes[2] = (*tmp)->up;
725 
726  tmp = q_fail->pert_begin;
727  leaves[1] = search_full_leaf (*tmp);
728  nodes[1] = (*tmp)->up;
729 
730  case_D (nodes, leaves, st_, to_father, G, q_fail);
731 
732  } else if (q_fail->partial_count == 1) {
733  if (q_fail->partial_pos[0] == q_fail->pert_end) {
734  GTL_debug::debug_message ("CASE D (non-root q-node with partial child at end of pertinent children\n");
735  pq_tree::sons_iterator tmp = q_fail->sons.begin();
736  pq_leaf* leaves[3];
737  node nodes[3];
738  leaves[0] = search_empty_leaf (*tmp);
739  nodes[0] = (*tmp)->up;
740 
741  tmp = q_fail->pert_end;
742  leaves[2] = search_empty_leaf (*tmp);
743  nodes[2] = (*tmp)->up;
744 
745  tmp = q_fail->pert_begin;
746  leaves[1] = search_full_leaf (*tmp);
747  nodes[1] = (*tmp)->up;
748 
749  case_D (nodes, leaves, st_, to_father, G, q_fail);
750  } else {
751  GTL_debug::debug_message ("CASE C (q-node with partial children surrounded by pertinent children)\n");
752  pq_tree::sons_iterator tmp = q_fail->pert_begin;
753  pq_leaf* leaves[3];
754  node nodes[3];
755  leaves[0] = search_full_leaf (*tmp);
756  nodes[0] = (*tmp)->up;
757 
758  tmp = q_fail->pert_end;
759  leaves[2] = search_full_leaf (*tmp);
760  nodes[2] = (*tmp)->up;
761 
762  tmp = q_fail->partial_pos[0];
763  leaves[1] = search_empty_leaf (*tmp);
764  nodes[1] = (*tmp)->up;
765 
766 
767  case_C (nodes, leaves, st_, to_father, G, q_fail);
768  }
769 
770  } else if ((q_fail->partial_pos[0] == q_fail->pert_begin ||
771  q_fail->partial_pos[0] == q_fail->pert_end) &&
772  (q_fail->partial_pos[1] == q_fail->pert_begin ||
773  q_fail->partial_pos[1] == q_fail->pert_end)) {
774 
775  if (++(q_fail->sons.begin()) == --(q_fail->sons.end())) {
776 
777  //
778  // q_node with two children, which are both partial.
779  //
780 
781  pq_tree::sons_iterator tmp = q_fail->sons.begin();
782  pq_leaf* leaves[4];
783  node nodes[2];
784  leaves[0] = search_empty_leaf (*tmp);
785  nodes[0] = (*tmp)->up;
786  leaves[1] = search_full_leaf (*tmp);
787 
788  ++tmp;
789  leaves[2] = search_empty_leaf (*tmp);
790  nodes[1] = (*tmp)->up;
791  leaves[3] = search_full_leaf (*tmp);
792 
793  case_E (nodes, leaves, st_, to_father, G, q_fail);
794 
795  } else if (q_fail->partial_count == 2) {
796  GTL_debug::debug_message ("CASE D (non-root q_node with first and last pertinent children partial)\n");
797 
798  //
799  // sons.begin() is empty, pert_begin is partial, pert_end is partial
800  //
801 
802  pq_tree::sons_iterator tmp = q_fail->sons.begin();
803  pq_leaf* leaves[3];
804  node nodes[3];
805  leaves[0] = search_empty_leaf (*tmp);
806  nodes[0] = (*tmp)->up;
807 
808  tmp = q_fail->pert_end;
809  leaves[2] = search_empty_leaf (*tmp);
810  nodes[2] = (*tmp)->up;
811 
812  tmp = q_fail->pert_begin;
813 
814  if (tmp == q_fail->sons.begin()) {
815  ++tmp;
816  }
817 
818  leaves[1] = search_full_leaf (*tmp);
819  nodes[1] = (*tmp)->up;
820 
821  case_D (nodes, leaves, st_, to_father, G, q_fail);
822 
823  } else {
824  GTL_debug::debug_message ("CASE C (q_node with at least three partial children)\n");
825 
826  //
827  // There must be at least one other partial child among the pertinent.
828  //
829 
830  pq_tree::sons_iterator tmp = q_fail->pert_begin;
831  pq_leaf* leaves[3];
832  node nodes[3];
833  leaves[0] = search_full_leaf (*tmp);
834  nodes[0] = (*tmp)->up;
835 
836  tmp = q_fail->pert_end;
837  leaves[2] = search_full_leaf (*tmp);
838  nodes[2] = (*tmp)->up;
839 
840  tmp = q_fail->partial_pos[2];
841  leaves[1] = search_empty_leaf (*tmp);
842  nodes[1] = (*tmp)->up;
843 
844  case_C (nodes, leaves, st_, to_father, G, q_fail);
845  }
846 
847  } else {
848 
849  //
850  // At least one partial son is in between the pertinent sons.
851  //
852 
853  GTL_debug::debug_message ("CASE C (q_node with at least two partial children, at least one surrounded by pertinent)\n");
854  pq_tree::sons_iterator tmp = q_fail->pert_begin;
855  pq_leaf* leaves[3];
856  node nodes[3];
857  leaves[0] = search_full_leaf (*tmp);
858  nodes[0] = (*tmp)->up;
859 
860  tmp = q_fail->pert_end;
861  leaves[2] = search_full_leaf (*tmp);
862  nodes[2] = (*tmp)->up;
863 
864  tmp = q_fail->partial_pos[0];
865 
866  if (tmp == q_fail->pert_begin || tmp == q_fail->pert_end) {
867  tmp = q_fail->partial_pos[1];
868  }
869 
870  leaves[1] = search_empty_leaf (*tmp);
871  nodes[1] = (*tmp)->up;
872 
873  case_C (nodes, leaves, st_, to_father, G, q_fail);
874  }
875 
876  } else {
877 
878  //
879  // pert_root is a P-Node ==> at least two partial children.
880  //
881 
882  p_node* p_fail = fail->P();
883 
884  if (p_fail->partial_count == 2) {
885  GTL_debug::debug_message ("CASE B (non-root p-node with two partial children)\n");
886  case_B (p_fail, act, st_, to_father, G);
887 
888  } else {
889 
890  //
891  // We have at least three partial children
892  //
893 
894  GTL_debug::debug_message ("CASE A (p-node with at least three partial children)\n");
895  case_A (p_fail, act, st_, to_father, G);
896  }
897  }
898 }
899 
900 
901 
902 void planarity::case_A (p_node* p_fail,
903  node act,
904  st_number& st_,
905  node_map<edge> to_father,
906  graph& G)
907 {
908  node art = p_fail->n;
909  ob_nodes.push_back (art);
910  ob_nodes.push_back (act);
911  node_map<int> mark (G, 0);
912  mark[art] = 1;
913  pq_leaf* empty[3];
914  pq_tree::sons_iterator part_pos = p_fail->partial_sons.begin();
915  int i;
916 
917  for (i = 0; i < 3; ++i) {
918  q_node* q_part = (*part_pos)->Q();
919  empty[i] = run_through_partial (q_part, mark, to_father, art);
920  ++part_pos;
921  }
922 
923  node t_node = st_.s_node().opposite (st_.st_edge());
924  mark[t_node] = 1;
925  node tmp[3];
926 
927  for (i = 0; i < 3; ++i) {
928  tmp[i] = up_until_marked (empty[i]->n, mark, st_);
929  }
930 
931  assert (tmp[0] == t_node);
932  node tmp_node;
933 
934  //
935  // The three paths found meet at the nodes tmp[1] and tmp[2]; the one
936  // one with the higher st_number is the one we are looking for. Since the
937  // first path always ends at t and it may happen that the paths meet below
938  // t, we might have to delete some of the edges found in the first path.
939  //
940 
941  if (st_[tmp[1]] < st_[tmp[2]]) {
942  tmp_node = tmp[2];
943  ob_nodes.push_back (tmp[1]);
944  } else {
945  tmp_node = tmp[1];
946  ob_nodes.push_back (tmp[2]);
947  }
948 
949 
950  if (tmp_node != t_node) {
951  list<edge>::iterator it, end;
952  int max_st = st_[tmp_node];
953 
954  it = ob_edges.begin();
955  end = ob_edges.end();
956 
957  while (it != end) {
958  edge cur = *it;
959 
960  if (st_[cur.source()] > max_st || st_[cur.target()] > max_st) {
961  it = ob_edges.erase (it);
962  } else {
963  ++it;
964  }
965  }
966  }
967 }
968 
969 
970 
971 void planarity::case_B (p_node* p_fail,
972  node act,
973  st_number& st_,
974  node_map<edge> to_father,
975  graph& G)
976 {
977  //
978  // P-Node, which is not the root of the pertinent subtree, but has
979  // two partial children.
980  //
981 
982  node art = p_fail->n;
983  ob_nodes.push_back (art);
984  ob_nodes.push_back (act);
985  node_map<int> mark (G, 0);
986  node_map<int> below (G, 0);
987  mark[art] = 1;
988 
989  //
990  // mark edges leading to full leaves from full sons.
991  //
992 
994  for (it = p_fail->full_sons.begin(), end = p_fail->full_sons.end(); it != end; ++it) {
995  mark_all_neighbors_of_leaves (*it, below);
996  }
997 
998  //
999  // search paths from one full and one empty leaf to the articulation point
1000  // in TBk. mark edges leading to full leaves from pertinent sons of part.
1001  //
1002 
1003  pq_tree::sons_iterator part_pos = p_fail->partial_sons.begin();
1004  q_node* q_part = (*part_pos)->Q();
1005  pq_leaf* empty1 = run_through_partial (q_part, mark, to_father, art);
1006 
1007  for (it = q_part->pert_begin, end = ++(q_part->pert_end); it != end; ++it) {
1008  mark_all_neighbors_of_leaves (*it, below);
1009  }
1010 
1011  //
1012  // search paths from one full and one empty leaf to the articulation point
1013  // in TBk. mark edges leading to full leaves from pertinent sons of part.
1014  //
1015 
1016  ++part_pos;
1017  q_part = (*part_pos)->Q();
1018  pq_leaf* empty2 = run_through_partial (q_part, mark, to_father, art);
1019 
1020 
1021  for (it = q_part->pert_begin, end = ++(q_part->pert_end); it != end; ++it) {
1022  mark_all_neighbors_of_leaves (*it, below);
1023  }
1024 
1025  //
1026  // now that all the adjacent edges of act, that lead to art in TBk have been
1027  // marked search an unmarked adj. edge of act,
1028  //
1029 
1030  node::adj_edges_iterator a_it, a_end;
1031 
1032  for (a_it = act.adj_edges_begin(), a_end = act.adj_edges_end(); a_it != a_end; ++a_it) {
1033  if (below[act.opposite (*a_it)] == 0 && st_[act.opposite (*a_it)] < st_[act]) {
1034  break;
1035  }
1036  }
1037 
1038  assert (a_it != a_end);
1039  mark[st_.s_node()] = 1;
1040  mark[art] = 0;
1041  node tmp = up_until_marked (art, mark, to_father);
1042  assert (tmp == st_.s_node());
1043  tmp = up_until_marked (act.opposite (*a_it), mark, to_father);
1044  assert(tmp != art);
1045  ob_nodes.push_back (tmp);
1046  ob_edges.push_back (*a_it);
1047  ob_edges.push_back (st_.st_edge());
1048 
1049  //
1050  // search from empty1 and empty2 to t.
1051  //
1052 
1053  node t_node = st_.s_node().opposite (st_.st_edge());
1054  mark[t_node] = 1;
1055  tmp = up_until_marked (empty1->n, mark, st_);
1056  assert (tmp == t_node);
1057  tmp = up_until_marked (empty2->n, mark, st_);
1058  ob_nodes.push_back (tmp);
1059 }
1060 
1061 
1063  pq_leaf** leaves,
1064  st_number& st_,
1065  node_map<edge> to_father,
1066  graph& G,
1067  q_node* q_fail)
1068 {
1069  int i;
1070  node_map<int> mark (G, 0);
1071  node y_0 = q_fail->n;
1072 
1073  for (i = 0; i < 3; ++i) {
1074  mark[nodes[i]] = 1;
1075  edge tmp_edge = leaves[i]->e;
1076  node tmp_node = leaves[i]->n;
1077  ob_edges.push_back (tmp_edge);
1078  tmp_node = up_until_marked (tmp_node.opposite (tmp_edge), mark, to_father);
1079  assert (tmp_node == nodes[i]);
1080  ob_nodes.push_back (nodes[i]);
1081  }
1082 
1083  ob_nodes.push_back (y_0);
1084  mark[st_.s_node()] = 1;
1085  node tmp = up_until_marked (y_0, mark, to_father);
1086  assert (tmp == st_.s_node ());
1087 
1088  ob_nodes.push_back (leaves[2]->n);
1089  ob_edges.push_back (st_.st_edge());
1090 
1091  node t_node = st_.s_node().opposite (st_.st_edge());
1092  mark[t_node] = 1;
1093  tmp = up_until_marked (leaves[1]->n, mark, st_);
1094  assert (tmp == t_node);
1095  tmp = up_until_marked (leaves[2]->n, mark, st_);
1096  ob_nodes.push_back (tmp);
1097 }
1098 
1099 
1101  pq_leaf** leaves,
1102  st_number& st_,
1103  node_map<edge> to_father,
1104  graph& G,
1105  q_node* q_fail)
1106 {
1107  //
1108  // Mark all edges from leaves leading to this component.
1109  //
1110 
1111  node y_0 = q_fail->n;
1113  node_map<int> below (G, 0);
1114  node act = leaves[1]->n;
1115 
1116  for (it = q_fail->sons.begin(), end = q_fail->sons.end(); it != end; ++it) {
1117  mark_all_neighbors_of_leaves (*it, below);
1118  }
1119 
1120  node::adj_edges_iterator a_it, a_end;
1121 
1122  for (a_it = act.adj_edges_begin(), a_end = act.adj_edges_end(); a_it != a_end; ++a_it) {
1123  if (below[act.opposite (*a_it)] == 0 && st_[act.opposite (*a_it)] < st_[act]) {
1124  break;
1125  }
1126  }
1127 
1128 
1129  //
1130  // Since q_fail can't be the root of the pertinent subtree, there must
1131  // be at least one edge from act not leading to the component described by
1132  // q_fail.
1133  //
1134 
1135  assert (a_it != a_end);
1136 
1137  int i;
1138  node_map<int> mark (G, 0);
1139 
1140  for (i = 0; i < 3; ++i) {
1141  mark[nodes[i]] = 1;
1142  edge tmp_edge = leaves[i]->e;
1143  node tmp_node = leaves[i]->n;
1144  ob_edges.push_back (tmp_edge);
1145  tmp_node = up_until_marked (tmp_node.opposite (tmp_edge), mark, to_father);
1146  assert (tmp_node == nodes[i]);
1147  ob_nodes.push_back (nodes[i]);
1148  }
1149 
1150  ob_nodes.push_back (y_0);
1151  mark[st_.s_node()] = 1;
1152  node tmp = up_until_marked (y_0, mark, to_father);
1153  assert (tmp == st_.s_node ());
1154  ob_edges.push_back (*a_it);
1155  tmp = up_until_marked (act.opposite (*a_it), mark, to_father);
1156 
1157 
1158  //
1159  // The paths from y_0 and from act meet in tmp. If tmp != s_node we have
1160  // to delete some edges.
1161  //
1162 
1163  if (tmp != st_.s_node()) {
1164  list<edge>::iterator it, end;
1165  int min_st = st_[tmp];
1166  it = ob_edges.begin();
1167  end = ob_edges.end();
1168 
1169  while (it != end) {
1170  edge cur = *it;
1171 
1172  if (st_[cur.source()] < min_st || st_[cur.target()] < min_st) {
1173  it = ob_edges.erase (it);
1174  } else {
1175  ++it;
1176  }
1177  }
1178  }
1179 
1180  ob_nodes.push_back (act);
1181 
1182  node t_node = st_.s_node().opposite (st_.st_edge());
1183  mark[t_node] = 1;
1184  node tmp_nodes[3];
1185 
1186  for (i = 0; i < 3; ++i) {
1187  tmp_nodes[i] = up_until_marked (leaves[i]->n, mark, st_);
1188  }
1189 
1190  assert (tmp_nodes[0] == t_node);
1191 
1192  //
1193  // The three paths found meet at the nodes tmp[1] and tmp[2]; the one
1194  // one with the higher st_number is the one we are looking for. Since the
1195  // first path always ends at t and it may happen that the paths meet below
1196  // t, we might have to delete some of the edges found in the first path.
1197  //
1198 
1199  if (st_[tmp_nodes[1]] < st_[tmp_nodes[2]]) {
1200  tmp = tmp_nodes[2];
1201  ob_nodes.push_back (tmp_nodes[1]);
1202  } else {
1203  tmp = tmp_nodes[1];
1204  ob_nodes.push_back (tmp_nodes[2]);
1205  }
1206 
1207 
1208  if (tmp != t_node) {
1209  list<edge>::iterator it, end;
1210  int max_st = st_[tmp];
1211  it = ob_edges.begin();
1212  end = ob_edges.end();
1213 
1214  while (it != end) {
1215  edge cur = *it;
1216 
1217  if (st_[cur.source()] > max_st || st_[cur.target()] > max_st) {
1218  it = ob_edges.erase (it);
1219  } else {
1220  ++it;
1221  }
1222  }
1223  }
1224 }
1225 
1226 
1228  pq_leaf** leaves,
1229  st_number& st_,
1230  node_map<edge> to_father,
1231  graph& G,
1232  q_node* q_fail)
1233 {
1234 
1235  //
1236  // Mark all edges from the act node leading to this component.
1237  //
1238 
1239  node y_0 = q_fail->n;
1241  node_map<int> below (G, 0);
1242  node act = leaves[1]->n;
1243 
1244  for (it = q_fail->pert_begin, end = ++(q_fail->pert_end); it != end; ++it) {
1245  mark_all_neighbors_of_leaves (*it, below);
1246  }
1247 
1248  node::adj_edges_iterator a_it, a_end;
1249 
1250  for (a_it = act.adj_edges_begin(), a_end = act.adj_edges_end(); a_it != a_end; ++a_it) {
1251  if (below[act.opposite (*a_it)] == 0 && st_[act.opposite (*a_it)] < st_[act]) {
1252  break;
1253  }
1254  }
1255 
1256 
1257  //
1258  // Since q_fail can't be the root of the pertinent subtree, there must
1259  // be at least one edge from act not leading to the component described by
1260  // q_fail.
1261  //
1262 
1263  assert (a_it != a_end);
1264 
1265  //
1266  // The list ob_edges at the moment contains the boundary. we need to know the paths
1267  // from y_0 to nodes[0] ( = y_1), from nodes[0] to nodes[1] ( = y_2 ) and from nodes[1]
1268  // back to y_0, because some of them will be eventually deleted later.
1269  //
1270 
1271  list<edge>::iterator paths_begin[3];
1272  list<edge>::iterator l_it, l_end;
1273  node next = y_0;
1274 
1275  for (l_it = ob_edges.begin(), l_end = ob_edges.end(); l_it != l_end; ++l_it) {
1276  next = next.opposite (*l_it);
1277 
1278  if (next == nodes[1]) {
1279  node tmp = nodes[1];
1280  nodes[1] = nodes[0];
1281  nodes[0] = tmp;
1282  pq_leaf* tmp_leaf = leaves[2];
1283  leaves[2] = leaves[0];
1284  leaves[0] = tmp_leaf;
1285  tmp_leaf = leaves[3];
1286  leaves[3] = leaves[1];
1287  leaves[1] = tmp_leaf;
1288 
1289  paths_begin[0] = l_it;
1290  ++paths_begin[0];
1291  break;
1292  } else if (next == nodes[0]) {
1293  paths_begin[0] = l_it;
1294  ++paths_begin[0];
1295  break;
1296  }
1297  }
1298 
1299  assert (l_it != l_end);
1300  ++l_it;
1301  assert (l_it != l_end);
1302 
1303  for (; l_it != l_end; ++l_it) {
1304  next = next.opposite (*l_it);
1305 
1306  if (next == nodes[1]) {
1307  paths_begin[1] = l_it;
1308  ++paths_begin[1];
1309  break;
1310  }
1311  }
1312 
1313  assert (l_it != l_end);
1314 
1315  paths_begin[2] = --l_end;
1316 
1317  node y[3];
1318  int i;
1319  node_map<int> mark (G, 0);
1320  list<edge> from_act[3];
1321  list<edge>::iterator pos;
1322 
1323  for (i = 0; i < 2; ++i) {
1324  mark[nodes[i]] = 1;
1325  edge tmp_edge = leaves[2 * i]->e;
1326  node tmp_node = leaves[2 * i]->n;
1327  ob_edges.push_back (tmp_edge);
1328  tmp_node = up_until_marked (tmp_node.opposite (tmp_edge), mark, to_father);
1329  assert (tmp_node == nodes[i]);
1330  tmp_edge = leaves[2 * i + 1]->e;
1331  tmp_node = leaves[2 * i + 1]->n;
1332  pos = ob_edges.insert (ob_edges.end(), tmp_edge);
1333  y[i + 1] = up_until_marked (tmp_node.opposite (tmp_edge), mark, to_father);
1334  from_act[i + 1].splice (from_act[i + 1].begin(), ob_edges, pos, ob_edges.end());
1335  }
1336 
1337  mark[st_.s_node()] = 1;
1338  node tmp = up_until_marked (y_0, mark, to_father);
1339  assert (tmp == st_.s_node ());
1340  pos = ob_edges.insert (ob_edges.end(), *a_it);
1341  y[0] = up_until_marked (act.opposite (*a_it), mark, to_father);
1342  from_act[0].splice (from_act[0].begin(), ob_edges, pos, ob_edges.end());
1343 
1344  node t_node = st_.s_node().opposite (st_.st_edge());
1345  mark[t_node] = 1;
1346  node tmp_nodes[3];
1347  node_map<int> from_where (G, 0);
1348 
1349  for (i = 0; i < 2; ++i) {
1350  pos = --(ob_edges.end());
1351  tmp_nodes[i] = up_until_marked (leaves[2 * i]->n, mark, st_);
1352  for (l_it = ++pos, l_end = ob_edges.end(); l_it != l_end; ++l_it) {
1353  from_where[(*l_it).source()] = i + 1;
1354  from_where[(*l_it).target()] = i + 1;
1355  }
1356  }
1357 
1358  assert (tmp_nodes[0] == t_node);
1359 
1360  if (y_0 != y[0]) {
1361  ob_nodes.push_back (y_0);
1362  ob_nodes.push_back (y[0]);
1363  ob_nodes.push_back (y[1]);
1364  ob_nodes.push_back (y[2]);
1365  ob_nodes.push_back (act);
1366  ob_nodes.push_back (tmp_nodes[1]);
1367 
1368  l_it = paths_begin[0];
1369  l_end = paths_begin[1];
1370  ob_edges.erase (l_it, l_end);
1371 
1372  for (i = 0; i < 3; ++i) {
1373  ob_edges.splice (ob_edges.end(), from_act[i], from_act[i].begin(), from_act[i].end());
1374  }
1375 
1376  GTL_debug::debug_message ("CASE E(i)\n");
1377 
1378  } else if (nodes[0] != y[1]) {
1379  ob_nodes.push_back (y_0);
1380  ob_nodes.push_back (y[1]);
1381  ob_nodes.push_back (nodes[0]);
1382  ob_nodes.push_back (y[2]);
1383  ob_nodes.push_back (act);
1384  ob_nodes.push_back (tmp_nodes[1]);
1385  l_it = paths_begin[1];
1386  l_end = paths_begin[2];
1387  ++l_end;
1388  ob_edges.erase (l_it, l_end);
1389 
1390  for (i = 0; i < 3; ++i) {
1391  ob_edges.splice (ob_edges.end(), from_act[i], from_act[i].begin(), from_act[i].end());
1392  }
1393 
1394  GTL_debug::debug_message ("CASE E(ii)\n");
1395 
1396  } else if (nodes[1] != y[2]) {
1397  ob_nodes.push_back (y_0);
1398  ob_nodes.push_back (y[1]);
1399  ob_nodes.push_back (nodes[1]);
1400  ob_nodes.push_back (y[2]);
1401  ob_nodes.push_back (act);
1402  ob_nodes.push_back (tmp_nodes[1]);
1403  l_it = ob_edges.begin();
1404  l_end = paths_begin[0];
1405  ob_edges.erase (l_it, l_end);
1406 
1407  for (i = 0; i < 3; ++i) {
1408  ob_edges.splice (ob_edges.end(), from_act[i], from_act[i].begin(), from_act[i].end());
1409  }
1410 
1411  GTL_debug::debug_message ("CASE E(ii)\n");
1412 
1413  } else {
1414  tmp_nodes[2] = up_until_marked (leaves[1]->n, mark, st_);
1415  ob_nodes.push_back (y_0);
1416  ob_nodes.push_back (y[1]);
1417  ob_nodes.push_back (tmp_nodes[1]);
1418  ob_nodes.push_back (y[2]);
1419  ob_nodes.push_back (act);
1420 
1421  if (st_[tmp_nodes[1]] < st_[tmp_nodes[2]]) {
1422  ob_nodes.push_back (tmp_nodes[2]);
1423  l_it = paths_begin[0];
1424  l_end = paths_begin[1];
1425  ob_edges.erase (l_it, l_end);
1426 
1427  for (i = 1; i < 3; ++i) {
1428  ob_edges.splice (ob_edges.end(), from_act[i], from_act[i].begin(), from_act[i].end());
1429  }
1430 
1431  GTL_debug::debug_message ("CASE E(iii) (1)\n");
1432 
1433  } else if (st_[tmp_nodes[1]] > st_[tmp_nodes[2]]) {
1434  edge last_edge = *(--(ob_edges.end()));
1435  ob_nodes.push_back (tmp_nodes[2]);
1436  ob_edges.splice (ob_edges.end(), from_act[0], from_act[0].begin(), from_act[0].end());
1437  int from;
1438 
1439  if (from_where[last_edge.source()] > 0) {
1440  from = from_where[last_edge.source()];
1441  } else {
1442  from = from_where[last_edge.target()];
1443  }
1444 
1445  assert (from > 0);
1446 
1447  if (from == 1) {
1448  ob_edges.splice (ob_edges.end(), from_act[2], from_act[2].begin(), from_act[2].end());
1449 
1450  l_it = paths_begin[1];
1451  l_end = paths_begin[2];
1452  ++l_end;
1453  ob_edges.erase (l_it, l_end);
1454 
1455  } else {
1456  ob_edges.splice (ob_edges.end(), from_act[1], from_act[1].begin(), from_act[1].end());
1457 
1458  l_it = ob_edges.begin();
1459  l_end = paths_begin[0];
1460  ob_edges.erase (l_it, l_end);
1461  }
1462 
1463  GTL_debug::debug_message ("CASE E(iii) (2)\n");
1464 
1465  } else {
1466  for (i = 0; i < 3; ++i) {
1467  ob_edges.splice (ob_edges.end(), from_act[i], from_act[i].begin(), from_act[i].end());
1468  }
1469 
1470  GTL_debug::debug_message ("CASE E(iii) (3)\n");
1471  }
1472  }
1473 
1474  ob_edges.push_back (st_.st_edge());
1475 }
1476 
1477 
1479 {
1480  switch (n->kind()) {
1481  case pq_node::LEAF:
1482  return n->L();
1483 
1484  case pq_node::P_NODE:
1485  case pq_node::Q_NODE:
1486  return search_full_leaf (*(--(n->sons.end())));
1487 
1488  default:
1489  assert (false);
1490  return 0;
1491  }
1492 }
1493 
1494 
1496 {
1497  switch (n->kind()) {
1498  case pq_node::LEAF:
1499  return n->L();
1500 
1501  case pq_node::Q_NODE:
1502  case pq_node::P_NODE:
1503  return search_empty_leaf (*(n->sons.begin()));
1504 
1505  default:
1506  assert (false);
1507  return 0;
1508  }
1509 }
1510 
1511 
1512 
1514 {
1515  if (act->kind() == pq_node::LEAF) {
1516  mark[((pq_leaf*)act)->e.opposite(((pq_leaf*)act)->n)] = 1;
1517  } else {
1519 
1520  for (it = act->sons.begin(), end = act->sons.end(); it != end; ++it) {
1521  mark_all_neighbors_of_leaves (*it, mark);
1522  }
1523  }
1524 }
1525 
1526 
1528 {
1529  pq_leaf* tmp = search_full_leaf (part);
1530  edge tmp_edge = tmp->e;
1531  node tmp_node = tmp->n;
1532  ob_edges.push_back (tmp_edge);
1533  tmp_node = up_until_marked (tmp_node.opposite (tmp_edge), mark, to_father);
1534 
1535  tmp = search_empty_leaf (part);
1536  tmp_node = tmp->n;
1537  tmp_edge = tmp->e;
1538  ob_edges.push_back (tmp_edge);
1539  tmp_node = up_until_marked (tmp_node.opposite (tmp_edge), mark, to_father);
1540  assert (tmp_node != v);
1541  ob_nodes.push_back (tmp_node);
1542 
1543  return tmp->L();
1544 }
1545 
1546 
1548 {
1549  while (mark[act] == 0) {
1550  mark[act] = 1;
1551  edge next = to_father[act];
1552  ob_edges.push_back (next);
1553  act = act.opposite (next);
1554  }
1555 
1556  return act;
1557 }
1558 
1560 {
1561  while (mark[act] == 0) {
1562  mark[act] = 1;
1563  node opp;
1565 
1566  for (it = act.adj_edges_begin(), end = act.adj_edges_end(); it != end; ++it) {
1567  opp = act.opposite (*it);
1568  if (st_[opp] > st_[act]) {
1569  break;
1570  }
1571  }
1572 
1573  assert (it != end);
1574  ob_edges.push_back (*it);
1575  act = opp;
1576  }
1577 
1578  return act;
1579 }
1580 
1582 {
1583  edge act = em.adjacency(start).front();
1584  node next = start.opposite (act);
1585  ob_edges.push_back (act);
1586 
1587  while (next != start) {
1588  act = em.cyclic_next (next, act);
1589  next = next.opposite (act);
1590  ob_edges.push_back (act);
1591  }
1592 }
1593 
1594 
1596  node_map<int>& used,
1597  st_number& st_,
1598  int stop,
1599  node_map<edge>& to_father)
1600 {
1601  used[n] = 1;
1603 
1604  for (it = n.adj_edges_begin(), end = n.adj_edges_end(); it != end; ++it) {
1605  edge act = *it;
1606  node other = n.opposite(act);
1607 
1608  if (used[other] == 0 && st_[other] < stop) {
1609  to_father[other] = *it;
1610  dfs_bushform (other, used, st_, stop, to_father);
1611  }
1612  }
1613 }
1614 
1615 #ifdef _DEBUG
1616 
1617 void planarity::write_node(ostream& os, int id, int label, int mark) {
1618  os << "node [\n" << "id " << id << endl;
1619  os << "label \"" << label << "\"\n";
1620  os << "graphics [\n" << "x 100\n" << "y 100 \n";
1621  if (mark == 1) {
1622  os << "outline \"#ff0000\"\n";
1623  }
1624  os << "]\n";
1625  os << "]" << endl;
1626 }
1627 #endif
1628 
1629 #ifdef _DEBUG
1630 void planarity::write_bushform(graph& G, st_number& st_, int k, const char* name, const node_map<int>& mark,
1631  const node_map<edge>& to_father)
1632 {
1633  // create the bushform Bk for the k where the test failed
1634  st_number::iterator st_it, st_end;
1635  int id = 0;
1636  node_map<int> ids (G);
1637  ofstream os (name, ios::out | ios::trunc);
1638 
1639  os << "graph [\n" << "directed 1" << endl;
1640 
1641  for (st_it = st_.begin(), st_end = st_.end(); st_it != st_end && st_[*st_it] <= k; ++st_it) {
1642  write_node(os, id, st_[*st_it], mark[*st_it]);
1643  ids[*st_it] = id;
1644  id++;
1645  }
1646 
1647  for (st_it = st_.begin(), st_end = st_.end(); st_it != st_end && st_[*st_it] <= k; ++st_it) {
1648  node::adj_edges_iterator ait, aend;
1649 
1650  for (ait = (*st_it).adj_edges_begin(), aend = (*st_it).adj_edges_end(); ait != aend; ait++) {
1651  node other = (*ait).opposite(*st_it);
1652  int other_id;
1653  if (st_[*st_it] < st_[other]) {
1654  if(st_[other] > k) {
1655  write_node(os, id, st_[other], mark[other]);
1656  other_id = id;
1657  id++;
1658  } else {
1659  other_id = ids[other];
1660  }
1661 
1662  os << "edge [\n" << "source " << ids[*st_it] << "\ntarget " << other_id << endl;
1663  if (*ait == to_father[*st_it] || *ait == to_father[other]) {
1664  os << "graphics [\n" << "fill \"#0000ff\"" << endl;
1665  os << "width 4.0\n]" << endl;
1666  }
1667  os << "\n]" << endl;
1668  }
1669  }
1670  }
1671 
1672  os << "]" << endl;
1673 }
1674 
1675 #endif
1676 
1678 
1679 //--------------------------------------------------------------------------
1680 // end of file
1681 //--------------------------------------------------------------------------