Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-03 08:19:40

0001 /* This software is distributed under the GNU Lesser General Public License */
0002 //==========================================================================
0003 //
0004 //   planarity.cpp 
0005 //
0006 //==========================================================================
0007 // $Id: planarity.cpp,v 1.28 2008/02/03 18:12:07 chris Exp $
0008 
0009 #include <GTL/planarity.h>
0010 #include <GTL/pq_tree.h>
0011 #include <GTL/biconnectivity.h>
0012 #include <GTL/debug.h>
0013 
0014 #include <iostream>
0015 #include <cstdio>
0016 #include <fstream>
0017 #include <sstream>
0018 
0019 #ifdef __GTL_MSVCC
0020 #   ifdef _Debug
0021 #   ifndef SEARCH_MEMORY_LEAKS_ENABLED
0022 #   error SEARCH NOT ENABLED
0023 #   endif
0024 #   define new DEBUG_NEW
0025 #   undef THIS_FILE
0026     static char THIS_FILE[] = __FILE__;
0027 #   endif   // _DEBUG
0028 #endif  // __GTL_MSVCC
0029 
0030 __GTL_BEGIN_NAMESPACE
0031 
0032 //--------------------------------------------------------------------------
0033 //   Planarity Test
0034 //--------------------------------------------------------------------------
0035 
0036 
0037 planarity::planarity() : 
0038     algorithm (), emp (false), kup (false), bip (true) 
0039 {
0040 #ifdef _DEBUG  
0041     GTL_debug::init_debug();
0042 #endif
0043 };  
0044 
0045 planarity::~planarity()
0046 {
0047 #ifdef _DEBUG  
0048     GTL_debug::close_debug();
0049 #endif
0050 };  
0051 
0052 
0053 int planarity::check (graph& G) 
0054 {
0055     return algorithm::GTL_OK;
0056 }
0057 
0058 bool planarity::run_on_biconnected (graph& G, planar_embedding& em)
0059 {
0060 
0061     if (G.number_of_edges() == 0) return algorithm::GTL_OK;
0062     
0063     st_number st_;
0064     
0065     //
0066     // The graph may have self loops. Make sure that we 
0067     // choose a normal edge for st.
0068     //
0069 
0070     graph::edge_iterator 
0071     edge_it = G.edges_begin(), 
0072     edge_end = G.edges_end();
0073 
0074     edge st;
0075 
0076     while (edge_it != edge_end) {
0077     if ((*edge_it).source() != (*edge_it).target()) {
0078         st = *edge_it;
0079         break;
0080     }
0081     ++edge_it;
0082     }
0083 
0084     //
0085     // G has only selfloops
0086     //
0087 
0088     if (st == edge()) {
0089     if (emp) {
0090         em.init (G);
0091         edge_it = G.edges_begin();
0092         edge_end = G.edges_end();
0093     
0094         for (;edge_it != edge_end; ++edge_it) {
0095         em.self.push_back (*edge_it);
0096         }
0097     }
0098 
0099     return algorithm::GTL_OK;
0100     }
0101 
0102     st_.st_edge (st);
0103     st_.s_node (st.source());
0104     int res = st_.check(G);
0105     assert (res == algorithm::GTL_OK);
0106     res = st_.run(G);
0107     assert (res == algorithm::GTL_OK);
0108     int size = G.number_of_nodes();
0109 
0110     if (emp) {
0111     em.init (G);
0112     }
0113     
0114     list<pq_leaf*> neighbors;
0115     st_number::iterator st_it = st_.begin();
0116     node curr = *st_it;
0117     node::out_edges_iterator o_it = curr.out_edges_begin();
0118     node::out_edges_iterator o_end = curr.out_edges_end();
0119     node::in_edges_iterator i_it = curr.in_edges_begin();
0120     node::in_edges_iterator i_end = curr.in_edges_end();
0121     list<edge> self_loops;
0122     node opp;
0123     node_map<int> visited_from (G, 0);
0124     pq_leaf* tmp_leaf;
0125     vector< list<pq_leaf*> > leaves (size);
0126     
0127     for (; o_it != o_end; ++o_it) {
0128     opp = curr.opposite (*o_it);
0129 
0130     if (opp != curr) {
0131         if (visited_from[opp] == st_[curr] && emp) {
0132         em.multi.push_back (*o_it);
0133         } else {
0134         visited_from[opp] = st_[curr];
0135         tmp_leaf = new pq_leaf (st_[opp], st_[curr], *o_it, opp);
0136         leaves[st_[opp]-1].push_back (tmp_leaf);
0137         neighbors.push_back (tmp_leaf);
0138         }
0139 
0140     } else if (emp) {
0141         em.self.push_back (*o_it);
0142     }
0143     }
0144     
0145     for (; i_it != i_end; ++i_it) {
0146     opp = curr.opposite (*i_it);
0147 
0148     if (opp != curr) {
0149         if (visited_from[opp] == st_[curr] && emp) {
0150         em.multi.push_back (*i_it);
0151         } else {
0152         visited_from[opp] = st_[curr];
0153         tmp_leaf = new pq_leaf (st_[opp], st_[curr], *i_it, opp);
0154         leaves[st_[opp]-1].push_back (tmp_leaf);
0155         neighbors.push_back (tmp_leaf);
0156         }
0157     } 
0158     }
0159 
0160     node_map<list<direction_indicator> > dirs;
0161 
0162     //
0163     // There is a problem with node/edge maps of iterators with Visual C++
0164     // which I donīt fully understand at the moment. Fortunatly the init for the 
0165     // maps below is only needed to allocate memory, which is done anyway, when
0166     // values are assigned to it.
0167     //
0168 
0169 #ifndef __GTL_MSVCC
0170     dirs.init (G);
0171 #endif
0172     pq_tree PQ (st_[curr], curr, neighbors);
0173     neighbors.erase (neighbors.begin(), neighbors.end());
0174     ++st_it;
0175     curr = *st_it;
0176     
0177     while (st_[curr] < size) {
0178         
0179 #ifdef _DEBUG
0180     char filename[10] = "out";
0181     char buffer[12];
0182 #ifdef __GTL_MSVCC
0183     _snprintf (buffer, 12, "%s%d.gml", filename, st_[curr]);
0184 #else 
0185     snprintf (buffer, 12, "%s%d.gml", filename, st_[curr]);
0186 #endif
0187     ofstream os (buffer, ios::out | ios::trunc);
0188     os << PQ << endl;
0189     os.close();
0190     bool ret_flag = PQ.integrity_check();
0191     assert(ret_flag);
0192 #endif
0193         
0194     if (!PQ.reduce (leaves[st_[curr]-1])) {
0195 #ifdef _DEBUG
0196         os.open ("fail.gml", ios::out | ios::trunc);
0197         os << PQ << endl;
0198         os.close ();
0199 #endif          
0200         if (kup) {
0201         examine_obstruction (G, st_, curr, 
0202             PQ.get_fail(), PQ.is_fail_root(), em, dirs, &PQ);
0203         }
0204 
0205         PQ.reset();
0206         return false;
0207     }
0208 
0209     
0210     //
0211     // It seems to be not very comfortable to use in and out iterators to
0212     // go through the adjacency of a node. For graphs without selfloops this
0213     // could be replaced by using adj_iterator, but if there are selfloops 
0214     // they will occur in both the list of outgoing and the one of incoming 
0215     // edges, and thus two times in the adjacency.
0216     //
0217 
0218     o_it = curr.out_edges_begin();
0219     o_end = curr.out_edges_end();
0220     i_it = curr.in_edges_begin();
0221     i_end = curr.in_edges_end();
0222         
0223     for (; o_it != o_end; ++o_it) {
0224         opp = curr.opposite (*o_it);
0225             
0226         if (st_[opp] > st_[curr]) {
0227         if (visited_from[opp] == st_[curr] && emp) {
0228             em.multi.push_back (*o_it);
0229         } else {
0230             visited_from[opp] = st_[curr];
0231             tmp_leaf = new pq_leaf (st_[opp], st_[curr], *o_it, opp);
0232             leaves[st_[opp]-1].push_back (tmp_leaf);
0233             neighbors.push_back (tmp_leaf);
0234         }
0235 
0236         } else if (st_[opp] == st_[curr] && emp) {
0237         em.self.push_back (*o_it);
0238         }
0239     }
0240     
0241     for (; i_it != i_end; ++i_it) {
0242         opp = curr.opposite (*i_it);
0243             
0244         if (st_[opp] > st_[curr]) {
0245         if (visited_from[opp] == st_[curr] && emp) {
0246             em.multi.push_back (*i_it);
0247         } else {
0248             visited_from[opp] = st_[curr];
0249             tmp_leaf = new pq_leaf (st_[opp], st_[curr], *i_it, opp);
0250             leaves[st_[opp]-1].push_back (tmp_leaf);
0251             neighbors.push_back (tmp_leaf);
0252         }
0253         }
0254     }
0255         
0256     if (emp) {
0257         PQ.replace_pert (st_[curr], curr, neighbors, &em, &(dirs[curr]));
0258 #ifdef _DEBUG
0259         GTL_debug::os() << "Embedding of " << st_[curr] << ":: ";
0260         planar_embedding::iterator adit, adend;
0261         for (adit = em.adj_edges_begin (curr), adend = em.adj_edges_end (curr); adit != adend; ++adit) {
0262         GTL_debug::os() << "[" << st_[curr.opposite (*adit)] << "]";
0263         }
0264         GTL_debug::os() << endl;
0265         GTL_debug::os() << "Direction Indicators for: " << st_[curr] << ":: ";
0266         list<direction_indicator>::iterator dit, dend;
0267 
0268         for (dit = dirs[curr].begin(), dend = dirs[curr].end(); dit != dend; ++dit) {
0269         GTL_debug::os() << "[";
0270         if ((*dit).direction)
0271             GTL_debug::os() << ">> " << (*dit).id << " >>";
0272         else 
0273             GTL_debug::os() << "<< " << (*dit).id << " <<";
0274         GTL_debug::os() << "]";
0275         }
0276         GTL_debug::os() << endl;
0277 #endif
0278 
0279     } else {
0280         PQ.replace_pert (st_[curr], curr, neighbors);       
0281     }
0282 
0283     PQ.reset();
0284 
0285 
0286     neighbors.erase (neighbors.begin(), neighbors.end());
0287     ++st_it;
0288     curr = *st_it;
0289     }
0290     
0291     if (emp) {
0292     PQ.get_frontier (em, dirs[curr]);
0293     
0294 
0295     //
0296     // get self_loops for last node
0297     //
0298 
0299     o_it = curr.out_edges_begin();
0300     o_end = curr.out_edges_end();
0301     
0302     for (; o_it != o_end; ++o_it) {
0303         if ((*o_it).target() == (*o_it).source()) {
0304         em.self.push_back (*o_it);
0305         }
0306     }
0307     
0308     //
0309     // some adjcacency list of the embedding obtained so far have to be
0310     // turned.
0311     // 
0312 
0313     correct_embedding(em, st_, dirs);
0314         
0315     node_map<int> mark;
0316     mark.init (G, 0);   
0317     node_map<symlist<edge>::iterator > upward_begin;
0318     upward_begin.init (G);
0319     node tmp;
0320     
0321     forall_nodes (tmp, G) {
0322         upward_begin[tmp] = em.adjacency(tmp).begin();
0323     } 
0324 
0325     extend_embedding(curr, em, mark, upward_begin);
0326     }
0327 
0328     return true;
0329 }
0330 
0331 
0332 int planarity::run (graph& G) 
0333 {      
0334     bool directed = false;
0335     
0336     if (G.is_directed()) {
0337     G.make_undirected();
0338     directed = true;
0339     }
0340     
0341     biconnectivity biconn;
0342     
0343     if (bip) {
0344     biconn.make_biconnected (true);
0345     } else {
0346     biconn.store_components (true);
0347     }
0348 
0349     biconn.check (G);
0350     biconn.run (G);
0351     
0352     if (emp) {
0353     embedding.init (G);
0354     }
0355 
0356     planar_embedding em;
0357 
0358     if (!biconn.is_biconnected() && !bip) {
0359     biconnectivity::component_iterator c_it, c_end;
0360 
0361     for (c_it = biconn.components_begin(), c_end = biconn.components_end(); 
0362     c_it != c_end; ++c_it) {
0363         
0364         switch_to_component (G, c_it);
0365         
0366 #ifdef _DEBUG
0367         GTL_debug::os() << "Component is: " << endl;
0368         GTL_debug::os() << G << endl;
0369 #endif
0370         if (!run_on_biconnected (G, em)) {
0371         if (directed) {
0372             G.make_directed();
0373         }
0374         
0375         G.restore_graph();
0376         planar = false;
0377         return algorithm::GTL_OK;
0378         }
0379      
0380         if (emp) {
0381         add_to_embedding (G, em);
0382         }
0383     }
0384     
0385     G.restore_graph();
0386 
0387     } else {
0388 
0389     //
0390     // G is already biconnected
0391     //
0392     
0393     GTL_debug::debug_message ("graph is biconnected\n");
0394 
0395     if (!run_on_biconnected (G, embedding)) {
0396         if (directed) {
0397         G.make_directed();
0398         }
0399         
0400         planar = false;
0401         return algorithm::GTL_OK;
0402     }   
0403     }
0404 
0405     if (bip) {
0406     list<edge>::iterator it, end;
0407     it = biconn.additional_begin();
0408     end = biconn.additional_end();
0409     
0410     for (; it != end; ++it) {
0411 
0412         if (emp) {
0413         node s = (*it).source();
0414         node t = (*it).target();
0415         embedding.adj[s].erase (embedding.s_pos[*it]);
0416         embedding.adj[t].erase (embedding.t_pos[*it]);
0417         }
0418 
0419         G.del_edge (*it);
0420     }
0421     }
0422 
0423     if (directed) {
0424     G.make_directed();
0425     }
0426 
0427     planar = true;
0428     return algorithm::GTL_OK;
0429 }
0430 
0431 void planarity::add_to_embedding (graph& G, planar_embedding& em) 
0432 {
0433     node n;
0434     forall_nodes (n, G) {
0435     planar_embedding::iterator it = em.adj_edges_begin (n);
0436     planar_embedding::iterator end = em.adj_edges_end (n);
0437         
0438     for (; it != end; ++it) {
0439         embedding.pos (n, *it) = em.pos (n, *it);
0440     }
0441         
0442     embedding.adjacency(n).splice (
0443         embedding.adj_edges_end (n),
0444         em.adj_edges_begin (n),
0445         em.adj_edges_end (n));
0446     }
0447 
0448     embedding.self.splice (
0449     embedding.self.end(), 
0450     em.self, em.self.begin(), em.self.end());
0451     embedding.multi.splice (
0452     embedding.multi.end(), 
0453     em.multi, em.multi.begin(), em.multi.end());
0454 }
0455 
0456 
0457 void planarity::reset () 
0458 {
0459     ob_edges.erase (ob_edges.begin(), ob_edges.end());
0460     ob_nodes.erase (ob_nodes.begin(), ob_nodes.end());
0461 }
0462 
0463 
0464 void planarity::correct_embedding (
0465     planar_embedding& em, 
0466     st_number& st_, 
0467     node_map<list<direction_indicator> >& dirs) 
0468 {
0469     st_number::reverse_iterator it = st_.rbegin();
0470     st_number::reverse_iterator end = st_.rend();
0471     bool* turn = new bool[st_[*it]];
0472     
0473     for (int i = 0; i < st_[*it]; ++i) {
0474     turn[i] = false;
0475     } 
0476     
0477     while (it != end) {
0478     node curr = *it;
0479         
0480     if (turn[st_[curr] - 1]) {
0481         em.adjacency(curr).reverse();
0482     } 
0483         
0484     list<direction_indicator>::iterator d_it = dirs[curr].begin();
0485         
0486     while (!dirs[curr].empty()) {
0487             
0488         if ((*d_it).direction && turn[st_[curr] - 1] || 
0489         !(*d_it).direction && !turn[st_[curr] - 1]) {
0490         turn[(*d_it).id - 1] = true;
0491         }
0492         
0493         d_it = dirs[curr].erase (d_it);
0494     }
0495         
0496     ++it;
0497     }
0498     
0499     delete[] turn;
0500 }
0501 
0502 
0503 void planarity::extend_embedding (  
0504     node n, 
0505     planar_embedding& em, 
0506     node_map<int>& mark,
0507     node_map<symlist<edge>::iterator >& upward_begin)
0508 {
0509     mark[n] = 1;
0510     
0511     symlist<edge>::iterator it = upward_begin[n];
0512     symlist<edge>::iterator end = em.adjacency(n).end();
0513     node other;
0514 
0515     for (; it != end; ++it) {
0516     em.pos (n, *it) = it;
0517     other = n.opposite (*it);
0518     em.pos (other, *it) = em.push_front (other, *it);
0519 
0520     if (mark[other] == 0) {
0521         extend_embedding (other, em, mark, upward_begin);
0522     }
0523     }
0524 }
0525 
0526 void planarity::switch_to_component (graph& G, 
0527                      biconnectivity::component_iterator c_it)
0528 {
0529     //
0530     // hide all nodes 
0531     //
0532 
0533     list<node> dummy;
0534     G.induced_subgraph (dummy);
0535 
0536     //
0537     // Restore nodes in this component.
0538     // 
0539 
0540     list<node>::iterator it = (*c_it).first.begin();
0541     list<node>::iterator end = (*c_it).first.end();
0542 
0543     for (; it != end; ++it) {
0544     G.restore_node (*it);
0545     }
0546 
0547     //
0548     // Restore edges in this component.
0549     //
0550 
0551     list<edge>::iterator e_it = (*c_it).second.begin();
0552     list<edge>::iterator e_end = (*c_it).second.end();
0553   
0554     for (; e_it != e_end; ++e_it) {
0555     G.restore_edge (*e_it);
0556     }
0557 }
0558 
0559 void planarity::examine_obstruction (graph& G, 
0560                      st_number& st_, 
0561                      node act, 
0562                      pq_node* fail, 
0563                      bool is_root,
0564                      planar_embedding& em,
0565                      node_map<list<direction_indicator> >& dirs,
0566                      pq_tree* PQ)
0567 {
0568     node_map<int> used (G, 0);
0569     node_map<edge> to_father (G);
0570 
0571     //
0572     // Create a dfs-tree of the so called bush form. This is basically a normal dfs 
0573     // applied to the induced subgraph of G consisting only of the nodes with st_number 
0574     // 1, ..., st_[act] - 1. The only difference is that edges are always directed from 
0575     // the lower numbered vertex to higher numbered one.
0576     //
0577 
0578     dfs_bushform (st_.s_node(), used, st_, st_[act], to_father);
0579 
0580     if (fail->kind() == pq_node::Q_NODE) {
0581 
0582     //
0583     // In case the reduction failed at a Q-Node we need to know the edges that 
0584     // form the boundary of the biconnected component, which this Q-Node represents.
0585     // These can easily be obtained from the embedding we got so far.
0586     //
0587 
0588     q_node* q_fail = fail->Q();
0589 
0590     pq_tree::sons_iterator s_it = q_fail->sons.begin();
0591     pq_tree::sons_iterator s_end = q_fail->sons.end();
0592     node greatest = fail->n;
0593 
0594     while (s_it != s_end)  {
0595         if ((*s_it)->kind() == pq_node::DIR) {
0596         direction_indicator* dir = (*s_it)->D();
0597         pq_tree::sons_iterator tmp = s_it;
0598         
0599         if (++tmp == ++(dir->pos)) {
0600             dir->direction = true;
0601         } else {
0602             dir->direction = false;
0603         }
0604 
0605         dirs[act].push_back (*dir);
0606 
0607         //
0608         // chris 2/3/2008:
0609         //
0610         // To avoid a memory leak, it is not sufficient to erase it from the
0611         // PQ-tree (-node). The direction indicator object also has to be
0612         // deleted. Since it is then not a member of the pertinent subtree any
0613         // more, it must not be cleared by PQ->reset(). The instance in the
0614         // dirs node map is a clone!
0615         //
0616 
0617         // s_it = q_fail->sons.erase (s_it);
0618         s_it = PQ->remove_dir_ind(q_fail, s_it);
0619         } else {
0620         if (st_[(*s_it)->up] > st_[greatest]) {
0621             greatest = (*s_it)->up;
0622         }
0623 
0624         ++s_it;
0625         }
0626     }
0627     
0628     correct_embedding (em, st_, dirs);
0629     node_map<int> mark;
0630     mark.init (G, 0);   
0631     node_map<symlist<edge>::iterator > upward_begin;
0632     upward_begin.init (G);
0633     node tmp;
0634 
0635     em.adjacency(fail->n).erase (
0636         em.adjacency(fail->n).begin(), 
0637         em.adjacency(fail->n).end());
0638 
0639     forall_nodes (tmp, G) {
0640         upward_begin[tmp] = em.adjacency(tmp).begin();
0641     }
0642 
0643     //
0644     // chris 2/3/2008:
0645     //
0646     // With the code of MR 11/27/2001 the component of the failing Q-node is not found
0647     // correctly.
0648     //
0649 
0650     extend_embedding(greatest, em, mark, upward_begin);
0651     
0652     /*
0653     //
0654     // MR 11/27/2001:
0655     //
0656     // This is important! We restricted building the embedding to the nodes in
0657     // the biconnected component which the Q-node fail refers to. But the st-number 
0658     // obtained for the whole graph restricted to these nodes will not be a st-numbering 
0659     // for this biconnected component. 
0660     //
0661 
0662     st_number::reverse_iterator st_it, st_end;
0663 
0664     for (st_it = st_.rbegin(), st_end = st_.rend();
0665          st_it != st_end;
0666          ++st_it) 
0667     {
0668         if (mark[*st_it] == 0) {
0669         extend_embedding (*st_it, em, mark, upward_begin);
0670         }
0671     }
0672     */
0673 #ifdef _DEBUG
0674     GTL_debug::os() << "Embedding so far (st_numbered): " << endl;
0675     em.write_st (GTL_debug::os(), st_);
0676 #endif 
0677 
0678     attachment_cycle (fail->n, em);
0679 
0680     if (!q_fail->pert_cons) {
0681 
0682         //
0683         // the reduction failed because there was more than one block 
0684         // of pertinent children. The reduction in this case assures that 
0685         // pert_begin and pert_end lie in different blocks and that 
0686         // --pert_end is empty and lies between these two blocks.
0687         //
0688         // This is one of the two cases that may apply when the reduction 
0689         // fails already in bubble up. The reduction takes care of this.
0690         //
0691 
0692         GTL_debug::debug_message ("CASE C (non consecutive pertinent children)\n");
0693         pq_tree::sons_iterator tmp = q_fail->pert_begin;
0694         pq_leaf* leaves[3];
0695         node nodes[3];
0696         leaves[0] = search_full_leaf (*tmp);
0697         nodes[0] = (*tmp)->up;
0698 
0699         tmp = q_fail->pert_end;
0700         leaves[2] = search_full_leaf (*tmp);
0701         nodes[2] = (*tmp)->up;
0702         
0703         --tmp;
0704         while ((*tmp)->kind() == pq_node::DIR) {
0705         --tmp;
0706         }
0707 
0708         leaves[1] = search_empty_leaf (*tmp);
0709         nodes[1] = (*tmp)->up;
0710         
0711         case_C (nodes, leaves, st_, to_father, G, q_fail);
0712 
0713     } else if (!(*(q_fail->pert_end))->is_endmost && !is_root) {
0714 
0715         GTL_debug::debug_message ("CASE D (non-root q-node with both endmost sons empty)\n");
0716         pq_tree::sons_iterator tmp = q_fail->sons.begin();
0717         pq_leaf* leaves[3];
0718         node nodes[3];
0719         leaves[0] = search_empty_leaf (*tmp);
0720         nodes[0] = (*tmp)->up;
0721 
0722         tmp = --(q_fail->sons.end());
0723         leaves[2] = search_empty_leaf (*tmp);
0724         nodes[2] = (*tmp)->up;
0725         
0726         tmp = q_fail->pert_begin;
0727         leaves[1] = search_full_leaf (*tmp);
0728         nodes[1] = (*tmp)->up;
0729 
0730         case_D (nodes, leaves, st_, to_father, G, q_fail);         
0731 
0732     } else if (q_fail->partial_count == 1) {
0733         if (q_fail->partial_pos[0] == q_fail->pert_end) {       
0734         GTL_debug::debug_message ("CASE D (non-root q-node with partial child at end of pertinent children\n");
0735         pq_tree::sons_iterator tmp = q_fail->sons.begin();
0736         pq_leaf* leaves[3];
0737         node nodes[3];
0738         leaves[0] = search_empty_leaf (*tmp);
0739         nodes[0] = (*tmp)->up;
0740         
0741         tmp = q_fail->pert_end;
0742         leaves[2] = search_empty_leaf (*tmp);
0743         nodes[2] = (*tmp)->up;
0744         
0745         tmp = q_fail->pert_begin;
0746         leaves[1] = search_full_leaf (*tmp);
0747         nodes[1] = (*tmp)->up;
0748         
0749         case_D (nodes, leaves, st_, to_father, G, q_fail);      
0750         } else {
0751         GTL_debug::debug_message ("CASE C (q-node with partial children surrounded by pertinent children)\n");
0752         pq_tree::sons_iterator tmp = q_fail->pert_begin;
0753         pq_leaf* leaves[3];
0754         node nodes[3];
0755         leaves[0] = search_full_leaf (*tmp);
0756         nodes[0] = (*tmp)->up;
0757         
0758         tmp = q_fail->pert_end;
0759         leaves[2] = search_full_leaf (*tmp);
0760         nodes[2] = (*tmp)->up;
0761         
0762         tmp = q_fail->partial_pos[0];
0763         leaves[1] = search_empty_leaf (*tmp);
0764         nodes[1] = (*tmp)->up;
0765         
0766         
0767         case_C (nodes, leaves, st_, to_father, G, q_fail);
0768         }
0769         
0770     } else if ((q_fail->partial_pos[0] == q_fail->pert_begin ||
0771             q_fail->partial_pos[0] == q_fail->pert_end) && 
0772            (q_fail->partial_pos[1] == q_fail->pert_begin ||
0773             q_fail->partial_pos[1] == q_fail->pert_end)) {
0774 
0775         if (++(q_fail->sons.begin()) == --(q_fail->sons.end())) {
0776 
0777         //
0778         // q_node with two children, which are both partial.
0779         //
0780 
0781         pq_tree::sons_iterator tmp = q_fail->sons.begin();
0782         pq_leaf* leaves[4];
0783         node nodes[2];
0784         leaves[0] = search_empty_leaf (*tmp);
0785         nodes[0] = (*tmp)->up;
0786         leaves[1] = search_full_leaf (*tmp);
0787         
0788         ++tmp;
0789         leaves[2] = search_empty_leaf (*tmp);
0790         nodes[1] = (*tmp)->up;
0791         leaves[3] = search_full_leaf (*tmp);
0792 
0793         case_E (nodes, leaves, st_, to_father, G, q_fail);      
0794 
0795         } else if (q_fail->partial_count == 2) {
0796         GTL_debug::debug_message ("CASE D (non-root q_node with first and last pertinent children partial)\n");
0797 
0798         //
0799         // sons.begin() is empty, pert_begin is partial, pert_end is partial
0800         //
0801 
0802         pq_tree::sons_iterator tmp = q_fail->sons.begin();
0803         pq_leaf* leaves[3];
0804         node nodes[3];
0805         leaves[0] = search_empty_leaf (*tmp);
0806         nodes[0] = (*tmp)->up;
0807         
0808         tmp = q_fail->pert_end;
0809         leaves[2] = search_empty_leaf (*tmp);
0810         nodes[2] = (*tmp)->up;
0811         
0812         tmp = q_fail->pert_begin;
0813 
0814         if (tmp == q_fail->sons.begin()) {
0815             ++tmp;
0816         }
0817 
0818         leaves[1] = search_full_leaf (*tmp);
0819         nodes[1] = (*tmp)->up;
0820         
0821         case_D (nodes, leaves, st_, to_father, G, q_fail);      
0822 
0823         } else {
0824         GTL_debug::debug_message ("CASE C (q_node with at least three partial children)\n");
0825 
0826         //
0827         // There must be at least one other partial child among the pertinent.
0828         //
0829         
0830         pq_tree::sons_iterator tmp = q_fail->pert_begin;
0831         pq_leaf* leaves[3];
0832         node nodes[3];
0833         leaves[0] = search_full_leaf (*tmp);
0834         nodes[0] = (*tmp)->up;
0835         
0836         tmp = q_fail->pert_end;
0837         leaves[2] = search_full_leaf (*tmp);
0838         nodes[2] = (*tmp)->up;
0839         
0840         tmp = q_fail->partial_pos[2];
0841         leaves[1] = search_empty_leaf (*tmp);
0842         nodes[1] = (*tmp)->up;
0843                 
0844         case_C (nodes, leaves, st_, to_father, G, q_fail);
0845         }
0846 
0847     } else {
0848         
0849         //
0850         // At least one partial son is in between the pertinent sons.
0851         //
0852 
0853         GTL_debug::debug_message ("CASE C (q_node with at least two partial children, at least one surrounded by pertinent)\n");
0854         pq_tree::sons_iterator tmp = q_fail->pert_begin;
0855         pq_leaf* leaves[3];
0856         node nodes[3];
0857         leaves[0] = search_full_leaf (*tmp);
0858         nodes[0] = (*tmp)->up;
0859         
0860         tmp = q_fail->pert_end;
0861         leaves[2] = search_full_leaf (*tmp);
0862         nodes[2] = (*tmp)->up;
0863         
0864         tmp = q_fail->partial_pos[0];
0865         
0866         if (tmp == q_fail->pert_begin || tmp == q_fail->pert_end) {
0867         tmp = q_fail->partial_pos[1];
0868         }
0869         
0870         leaves[1] = search_empty_leaf (*tmp);
0871         nodes[1] = (*tmp)->up;
0872         
0873         case_C (nodes, leaves, st_, to_father, G, q_fail);
0874     }
0875 
0876     } else {
0877 
0878     //
0879     // pert_root is a P-Node ==> at least two partial children.
0880     //
0881 
0882     p_node* p_fail = fail->P();
0883 
0884     if (p_fail->partial_count == 2) {
0885         GTL_debug::debug_message ("CASE B (non-root p-node with two partial children)\n");
0886         case_B (p_fail, act, st_, to_father, G);
0887     
0888     } else {
0889 
0890         //
0891         // We have at least three partial children 
0892         //
0893 
0894         GTL_debug::debug_message ("CASE A (p-node with at least three partial children)\n");
0895         case_A (p_fail, act, st_, to_father, G);
0896     }   
0897     }   
0898 }
0899 
0900 
0901 
0902 void planarity::case_A (p_node* p_fail,
0903             node act,
0904             st_number& st_, 
0905             node_map<edge> to_father, 
0906             graph& G)
0907 {
0908     node art = p_fail->n;
0909     ob_nodes.push_back (art);
0910     ob_nodes.push_back (act);
0911     node_map<int> mark (G, 0);
0912     mark[art] = 1;
0913     pq_leaf* empty[3];
0914     pq_tree::sons_iterator part_pos = p_fail->partial_sons.begin();
0915     int i;
0916     
0917     for (i = 0; i < 3; ++i) {
0918     q_node* q_part = (*part_pos)->Q();
0919     empty[i] = run_through_partial (q_part, mark, to_father, art);
0920     ++part_pos;
0921     }
0922     
0923     node t_node = st_.s_node().opposite (st_.st_edge());
0924     mark[t_node] = 1;
0925     node tmp[3];
0926     
0927     for (i = 0; i < 3; ++i) {
0928     tmp[i] = up_until_marked (empty[i]->n, mark, st_);
0929     }
0930     
0931     assert (tmp[0] == t_node);
0932     node tmp_node;
0933     
0934     //
0935     // The three paths found meet at the nodes tmp[1] and tmp[2]; the one
0936     // one with the higher st_number is the one we are looking for. Since the
0937     // first path always ends at t and it may happen that the paths meet below 
0938     // t, we might have to delete some of the edges found in the first path.
0939     //
0940     
0941     if (st_[tmp[1]] < st_[tmp[2]]) {
0942     tmp_node = tmp[2];
0943     ob_nodes.push_back (tmp[1]);
0944     } else {
0945     tmp_node = tmp[1];
0946     ob_nodes.push_back (tmp[2]);
0947     }
0948     
0949     
0950     if (tmp_node != t_node) {
0951     list<edge>::iterator it, end;
0952     int max_st = st_[tmp_node];
0953     
0954     it = ob_edges.begin();
0955     end = ob_edges.end();
0956     
0957     while (it != end) {
0958         edge cur = *it;
0959         
0960         if (st_[cur.source()] > max_st || st_[cur.target()] > max_st) {
0961         it = ob_edges.erase (it);
0962         } else {
0963         ++it;
0964         }
0965     }
0966     }
0967 }
0968 
0969 
0970 
0971 void planarity::case_B (p_node* p_fail,
0972             node act,
0973             st_number& st_, 
0974             node_map<edge> to_father, 
0975             graph& G)
0976 {
0977     //
0978     // P-Node, which is not the root of the pertinent subtree, but has 
0979     // two partial children. 
0980     // 
0981 
0982     node art = p_fail->n;
0983     ob_nodes.push_back (art);
0984     ob_nodes.push_back (act);
0985     node_map<int> mark (G, 0);
0986     node_map<int> below (G, 0);
0987     mark[art] = 1;
0988     
0989     //
0990     // mark edges leading to full leaves from full sons.
0991     //
0992     
0993     pq_tree::sons_iterator it, end;
0994     for (it = p_fail->full_sons.begin(), end = p_fail->full_sons.end(); it != end; ++it) {
0995     mark_all_neighbors_of_leaves (*it, below);
0996     }
0997     
0998     //
0999     // 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 
1062 void planarity::case_C (node* nodes,
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 
1100 void planarity::case_D (node* nodes,
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;
1112     pq_tree::sons_iterator it, end;
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 
1227 void planarity::case_E (node* nodes,
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;
1240     pq_tree::sons_iterator it, end;
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 
1478 pq_leaf* planarity::search_full_leaf (pq_node* n) 
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 
1495 pq_leaf* planarity::search_empty_leaf (pq_node* n) 
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 
1513 void planarity::mark_all_neighbors_of_leaves (pq_node* act, node_map<int>& mark)
1514 {
1515     if (act->kind() == pq_node::LEAF) {
1516         mark[((pq_leaf*)act)->e.opposite(((pq_leaf*)act)->n)] = 1;
1517     } else {
1518         pq_tree::sons_iterator it, end;
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 
1527 pq_leaf* planarity::run_through_partial (q_node* part, node_map<int>& mark, node_map<edge>& to_father, node v) 
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 
1547 node planarity::up_until_marked (node act, node_map<int>& mark, node_map<edge>& to_father) 
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 
1559 node planarity::up_until_marked (node act, node_map<int>& mark, st_number& st_) 
1560 {
1561     while (mark[act] == 0) {
1562     mark[act] = 1;
1563     node opp;
1564     node::adj_edges_iterator it, end;
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 
1581 void planarity::attachment_cycle (node start, planar_embedding& em) 
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 
1595 void planarity::dfs_bushform (node n, 
1596                   node_map<int>& used, 
1597                   st_number& st_, 
1598                   int stop, 
1599                   node_map<edge>& to_father) 
1600 {    
1601     used[n] = 1;
1602     node::adj_edges_iterator it, end;
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 
1677 __GTL_END_NAMESPACE
1678 
1679 //--------------------------------------------------------------------------
1680 //   end of file
1681 //--------------------------------------------------------------------------