Aleph-w  1.5a.2
Biblioteca general de algoritmos y estructuras de datos
 Todo Clases Archivos Funciones Variables 'typedefs' Enumeraciones Amigas Grupos Páginas
tpl_find_path.H
1 
2 # ifndef TPL_FIND_PATH_H
3 # define TPL_FIND_PATH_H
4 
5 # include <tpl_graph_utils.H>
6 
7 namespace Aleph {
8 
32  template <class GT, class SA = Dft_Show_Arc<GT> >
34 {
35  SA & sa;
36  typename GT::Node * end;
37  Path<GT> * path;
38 
39  bool find_path(typename GT::Node * curr, typename GT::Arc * arc)
40  {
41  if (curr == end) // ¿se alcanzó nodo final?
42  { // sí, terminar añadir el arco y terminar
43  path->append(arc);
44 
45  return true;
46  }
47 
48  if (IS_NODE_VISITED(curr, Find_Path)) // ¿ha sido visitado?
49  return false; // sí ==> desde él no hay camino
50 
51  path->append(arc); // añadir curr_arc al camino
52  NODE_BITS(curr).set_bit(Find_Path, true);
53 
54  // buscar recursivamente a través de arcos de curr_node
55  for (Node_Arc_Iterator<GT, SA> i(curr, sa); i.has_curr(); i.next())
56  {
57  typename GT::Arc * next_arc = i.get_current_arc();
58  if (IS_ARC_VISITED(next_arc, Find_Path))
59  continue;
60 
61  ARC_BITS(next_arc).set_bit(Find_Path, true);
62  typename GT::Node * next_node = i.get_tgt_node();
63  if (find_path(next_node, next_arc))
64  {
65  I(path->get_last_node() == end);
66 
67  return true; // se encontró camino
68  }
69  }
70 
71  path->remove_last_node();
72 
73  return false;
74  }
75 
76  bool find_path(GT & g, typename GT::Node * start,
77  typename GT::Node * end_node, Path<GT> & p)
78  {
79  if (not p.inside_graph(g))
80  throw std::invalid_argument("Path does not belong to graph");
81 
82  end = end_node;
83  path = &p;
84 
85  path->clear_path();
86  path->init(start);
87 
88  g.reset_bit_nodes(Find_Path);
89  g.reset_bit_arcs(Find_Path);
90 
91  NODE_BITS(start).set_bit(Find_Path, true);
92 
93  // explorar recursivamente cada arco de start_node
94  for (Node_Arc_Iterator<GT, SA> i(start, sa); i.has_curr(); i.next())
95  {
96  typename GT::Arc * arc = i.get_current_arc();
97  ARC_BITS(arc).set_bit(Find_Path, true);
98 
99  typename GT::Node * next_node = i.get_tgt_node();
100  if (IS_NODE_VISITED(next_node, Find_Path))
101  continue;
102 
103  if (find_path(next_node, arc))
104  return true;
105  }
106 
107  return false;
108  }
109 
110 public:
111 
112  Find_Path_Depth_First(SA && __sa = SA()) : sa(__sa) { /* empty */ }
113 
114  Find_Path_Depth_First(SA & __sa) : sa(__sa) { /* empty */ }
115 
126  bool operator () (GT & g, typename GT::Node * start_node,
127  typename GT::Node * end_node, Path<GT> & path)
128  {
129  return find_path(g, start_node, end_node, path);
130  }
131 };
132 
133 
157  template <class GT, class SA = Dft_Show_Arc<GT> >
159 {
160  SA & sa;
161 
162  bool find_path(GT & g, typename GT::Node * start,
163  typename GT::Node * end, Path<GT> & path)
164  {
165  if (not path.inside_graph(g))
166  throw std::invalid_argument("Path does not belong to graph");
167 
168  path.clear_path(); // limpiamos cualquier cosa que esté en path
169  g.reset_nodes();
170  g.reset_arcs();
171 
173 
174  for (Node_Arc_Iterator<GT, SA> i(start, sa); i.has_curr(); i.next())
175  q.put(i.get_current_arc());
176 
177  NODE_BITS(start).set_bit(Find_Path, true); // márquelo visitado
178 
179  bool path_found = false;
180 
181  while (not q.is_empty()) // mientras queden arcos por visitar
182  {
183  typename GT::Arc * arc = q.get();
184  typename GT::Node * src = g.get_src_node(arc);
185  typename GT::Node * tgt = g.get_tgt_node(arc);
186 
187  if (IS_NODE_VISITED(src, Find_Path) and IS_NODE_VISITED(tgt, Find_Path))
188  continue;
189 
190  if (IS_NODE_VISITED(tgt, Find_Path))
191  std::swap(src, tgt);
192 
193  ARC_BITS(arc).set_bit(Find_Path, true);
194  NODE_BITS(tgt).set_bit(Find_Path, true);
195  NODE_COOKIE(tgt) = src;
196 
197  if (tgt == end) // ¿se encontró un camino?
198  {
199  path_found = true;
200  break;
201  }
202 
203  for (Node_Arc_Iterator<GT,SA> i(tgt); i.has_curr(); i.next())
204  {
205  typename GT::Arc * a = i.get_current_arc();
206  if (IS_ARC_VISITED(a, Find_Path)) // ¿arco visitado?
207  continue; // sí ==> avanzar al siguiente
208 
209  // revise nodos del arco para ver si han sido visitados
210  if (IS_NODE_VISITED(g.get_src_node(a), Find_Path) and
211  IS_NODE_VISITED(g.get_tgt_node(a), Find_Path))
212  continue; // nodos ya visitados ==> no meter arco
213 
214  q.put(a);
215  }
216  }
217 
218  if (not path_found)
219  return false;
220 
221  q.empty();
222  path.insert(end);
223  typename GT::Node * p = end;
224  while (p != start)
225  {
226  p = (typename GT::Node *) NODE_COOKIE(p);
227  path.insert(p);
228  }
229 
230  return true;
231  }
232 
233 public:
234 
235  Find_Path_Breadth_First(SA & _sa) : sa(_sa) { /* Empty */ }
236 
237  Find_Path_Breadth_First(SA && _sa = SA()) : sa(_sa) { /* Empty */ }
238 
249  bool operator () (GT & g, typename GT::Node * start,
250  typename GT::Node * end, Path<GT> & path)
251  {
252  return find_path(g, start, end, path);
253  }
254 };
255 
256 
257 } // namespace Aleph
258 
259 # endif // TPL_FIND_PATH_H
#define NODE_COOKIE(p)
Definition: aleph-graph.H:248
bool operator()(GT &g, typename GT::Node *start_node, typename GT::Node *end_node, Path< GT > &path)
Definition: tpl_find_path.H:126
void insert(Arc *arc)
Definition: tpl_graph.H:1758
#define IS_NODE_VISITED(p, bit)
Definition: aleph-graph.H:242
bool operator()(GT &g, typename GT::Node *start, typename GT::Node *end, Path< GT > &path)
Definition: tpl_find_path.H:249
Definition: tpl_find_path.H:158
Definition: tpl_dynListQueue.H:22
bool inside_graph(GT &gr) const
retorna true si el camino this refiere al grafo gr
Definition: tpl_graph.H:1562
#define IS_ARC_VISITED(p, bit)
Definition: aleph-graph.H:275
Definition: tpl_graph.H:26
Definition: tpl_find_path.H:33
void next()
Adelanta el iterador una posición.
Definition: filter_iterator.H:143
#define NODE_BITS(p)
Definition: aleph-graph.H:221
void clear_path()
Limpia el camino (se eliminan todos sus nodos y arcos).
Definition: tpl_graph.H:1620
#define ARC_BITS(p)
Definition: aleph-graph.H:266
T get()
Definition: tpl_dynListQueue.H:107
Definition: tpl_graph.H:694
T & put(const T &data)
Definition: tpl_dynListQueue.H:86

Leandro Rabindranath León