Aleph-w  1.9
General library for algorithms and data structures
tpl_find_path.H
1 
2 /* Aleph-w
3 
4  / \ | | ___ _ __ | |__ __ __
5  / _ \ | |/ _ \ '_ \| '_ \ ____\ \ /\ / / Data structures & Algorithms
6  / ___ \| | __/ |_) | | | |_____\ V V / version 1.9b
7  /_/ \_\_|\___| .__/|_| |_| \_/\_/ https://github.com/lrleon/Aleph-w
8  |_|
9 
10  This file is part of Aleph-w library
11 
12  Copyright (c) 2002-2018 Leandro Rabindranath Leon & Alejandro Mujica
13 
14  This program is free software: you can redistribute it and/or modify
15  it under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  This program is distributed in the hope that it will be useful, but
20  WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  General Public License for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27 
28 # ifndef TPL_FIND_PATH_H
29 # define TPL_FIND_PATH_H
30 
31 # include <tpl_dynListStack.H>
32 # include <tpl_dynListQueue.H>
33 # include <tpl_graph_utils.H>
34 
35 namespace Aleph {
36 
37  template <class GT>
38 struct Dft_Goal_Node
39 {
40  bool operator () (typename GT::Node *) const noexcept { return false; }
41 };
42 
66  template <class GT,
67  template <class, class> class Itor = Node_Arc_Iterator,
68  class SA = Dft_Show_Arc<GT>>
70 {
71  SA & sa;
72  GT * g_ptr = nullptr;
73 
74  template <class Op>
75  bool find_path(typename GT::Node * curr, typename GT::Arc * arc,
76  Path<GT> & path, Op & op)
77  {
78  if (op(curr)) // goal node reached?
79  {
80  path.append(arc);
81  return true;
82  }
83 
84  if (IS_NODE_VISITED(curr, Find_Path)) // ¿ha sido visitado?
85  return false; // sí ==> desde él no hay camino
86 
87  path.append(arc); // añadir curr_arc al camino
88  NODE_BITS(curr).set_bit(Find_Path, true);
89 
90  // buscar recursivamente a través de arcos de curr_node
91  for (Itor<GT, SA> i(curr, sa); i.has_curr(); i.next())
92  {
93  auto next_arc = i.get_curr();
94  if (IS_ARC_VISITED(next_arc, Find_Path))
95  continue;
96 
97  ARC_BITS(next_arc).set_bit(Find_Path, true);
98  auto next_node = g_ptr->get_connected_node(next_arc, curr);
99  if (find_path(next_node, next_arc, path, op))
100  return true; // se encontró camino
101  }
102 
103  path.remove_last_node();
104 
105  return false;
106  }
107 
108  template <class Op>
109  bool find(const GT & g, typename GT::Node * start, Path<GT> & path, Op & op)
110  {
111  g_ptr = const_cast<GT*>(&g);
112  path.set_graph(g, start);
113 
114  if (op(start))
115  return true;
116 
117  g.reset_bit_nodes(Find_Path);
118  g.reset_bit_arcs(Find_Path);
119 
120  NODE_BITS(start).set_bit(Find_Path, true);
121 
122  // explorar recursivamente cada arco de start
123  for (Itor<GT, SA> i(start, sa); i.has_curr(); i.next())
124  {
125  auto arc = i.get_curr();
126  ARC_BITS(arc).set_bit(Find_Path, true);
127 
128  auto next_node = g.get_connected_node(arc, start);
129  if (IS_NODE_VISITED(next_node, Find_Path))
130  continue;
131 
132  if (find_path(next_node, arc, path, op))
133  return true;
134  }
135 
136  path.remove_last_node();
137 
138  return false;
139  }
140 
141  template <class Op>
142  bool find(const GT & g, typename GT::Node * start, Path<GT> & path, Op && op)
143  {
144  return find(g, start, path, op);
145  }
146 
147 public:
148 
149  Find_Path_Depth_First(SA && __sa = SA())
150  noexcept(std::is_nothrow_constructible<SA>::value and
151  std::is_nothrow_copy_assignable<SA>::value)
152  : sa(__sa) { /* empty */ }
153 
154  Find_Path_Depth_First(SA & __sa)
155  noexcept(std::is_nothrow_copy_assignable<SA>::value)
156  : sa(__sa) { /* empty */ }
157 
168  bool operator () (const GT & g,
169  typename GT::Node * start, typename GT::Node * end,
170  Path<GT> & path)
171  {
172  return find(g, start, path, [end] (auto p) { return p == end; });
173  }
174 
184  Path<GT> operator () (const GT & g,
185  typename GT::Node * start,
186  typename GT::Node * end)
187  {
188  Path<GT> ret(g);
189  find(g, start, ret, [end] (auto p) { return p == end; });
190  return ret;
191  }
192 
205  template <class Op>
206  Path<GT> operator () (const GT & g, typename GT::Node * start, Op & op)
207  {
208  Path<GT> ret(g);
209  find<Op>(g, start, ret, op);
210  return ret;
211  }
212 
213  template <class Op = Dft_Goal_Node<GT>>
214  Path<GT> operator () (const GT & g, typename GT::Node * start, Op && op)
215  {
216  Path<GT> ret(g);
217  find<Op>(g, start, ret, op);
218  return ret;
219  }
220 };
221 
222 
246  template <class GT,
247  template <typename, class> class Itor = Node_Arc_Iterator,
248  class SA = Dft_Show_Arc<GT> >
250 {
251  SA & sa;
252 
253  template <class Op>
254  bool find_path(const GT & g, typename GT::Node * start,
255  Path<GT> & path, Op & op)
256  {
257  if (not path.inside_graph(g))
258  throw std::invalid_argument("Path does not belong to graph");
259 
260  path.empty(); // limpiamos cualquier cosa que esté en path
261  g.reset_nodes();
262  g.reset_arcs();
263 
265 
266  for (Itor<GT, SA> i(start, sa); i.has_curr(); i.next())
267  q.put(i.get_current_arc());
268 
269  NODE_BITS(start).set_bit(Find_Path, true); // márquelo visitado
270 
271  typename GT::Node * end = nullptr;
272 
273  while (not q.is_empty()) // mientras queden arcos por visitar
274  {
275  auto arc = q.get();
276  auto src = g.get_src_node(arc);
277  auto tgt = g.get_tgt_node(arc);
278 
279  if (IS_NODE_VISITED(src, Find_Path) and IS_NODE_VISITED(tgt, Find_Path))
280  continue;
281 
282  if (IS_NODE_VISITED(tgt, Find_Path))
283  std::swap(src, tgt);
284 
285  ARC_BITS(arc).set_bit(Find_Path, true);
286  NODE_BITS(tgt).set_bit(Find_Path, true);
287  NODE_COOKIE(tgt) = src;
288 
289  if (op(tgt)) // ¿se encontró un camino que satisfaga op?
290  {
291  end = tgt;
292  break;
293  }
294 
295  for (Itor<GT,SA> i(tgt); i.has_curr(); i.next())
296  {
297  auto a = i.get_current_arc();
298  if (IS_ARC_VISITED(a, Find_Path)) // ¿arco visitado?
299  continue; // sí ==> avanzar al siguiente
300 
301  // revise nodos del arco para ver si han sido visitados
302  if (IS_NODE_VISITED(g.get_src_node(a), Find_Path) and
303  IS_NODE_VISITED(g.get_tgt_node(a), Find_Path))
304  continue; // nodos ya visitados ==> no meter arco
305 
306  q.put(a);
307  }
308  }
309 
310  if (not end)
311  return false;
312 
313  q.empty();
314  path.insert(end);
315  auto p = end;
316  while (p != start)
317  {
318  p = (typename GT::Node *) NODE_COOKIE(p);
319  path.insert(p);
320  }
321 
322  return true;
323  }
324 
325  template <class Op>
326  bool find_path(const GT & g, typename GT::Node * start,
327  Path<GT> & path, Op && op)
328  {
329  return find_path(g, start, path, op);
330  }
331 
332 public:
333 
334  Find_Path_Breadth_First(SA & _sa)
335  noexcept(std::is_nothrow_copy_assignable<SA>::value)
336  : sa(_sa) { /* Empty */ }
337 
338  Find_Path_Breadth_First(SA && _sa = SA())
339  noexcept(std::is_nothrow_constructible<SA>::value and
340  std::is_nothrow_copy_assignable<SA>::value)
341  : sa(_sa) { /* Empty */ }
342 
353  template <class Op>
354  Path<GT> operator () (const GT & g, typename GT::Node * start, Op & op)
355  {
356  Path<GT> ret(g);
357  find_path(g, start, ret, op);
358  return ret;
359  }
360 
361  template <class Op>
362  Path<GT> operator () (const GT & g, typename GT::Node * start, Op && op)
363  {
364  Path<GT> ret(g);
365  find_path(g, start, ret, op);
366  return ret;
367  }
368 
379  bool operator () (const GT & g, typename GT::Node * start,
380  typename GT::Node * end, Path<GT> & path)
381  {
382  return find_path(g, start, path, [end] (auto p) { return p == end; });
383  }
384 
394  Path<GT> operator () (const GT & g,
395  typename GT::Node * start, typename GT::Node * end)
396  {
397  Path<GT> ret(g);
398  find_path(g, start, ret, [end] (auto p) { return p == end; });
399  return ret;
400  }
401 };
402 
408  template <class GT,
409  template <typename, class> class Itor = Out_Iterator,
410  class SA = Dft_Show_Arc<GT>>
412 {
413  const GT & g;
414  SA & sa;
415 
416  template <template <typename T> class Q, class Op>
417  Path<GT> find(typename GT::Node * start, Op & op)
418  {
419  g.reset_nodes();
420  g.reset_arcs();
421 
422  start->set_state(Processed);
423 
424  Q<typename GT::Arc*> q;
425  for (Itor<GT, SA> it(start, sa); it.has_curr(); it.next())
426  {
427  auto a = it.get_curr();
428  it.get_node(a)->set_state(Processing);
429  a->set_state(Processing);
430  q.put(a);
431  }
432 
433  typename GT::Node * end = nullptr, * curr = nullptr;
434  while (not q.is_empty())
435  {
436  auto arc = q.get();
437  assert(arc->state() == Processing);
438  arc->set_state(Processed);
439 
440  curr = g.get_tgt_node(arc);
441  if (curr->state() == Processed)
442  continue;
443 
444  curr->set_state(Processed);
445  NODE_COOKIE(curr) = g.get_src_node(arc);
446 
447  if (op(curr))
448  {
449  end = curr;
450  break;
451  }
452 
453  for (Itor<GT, SA> it(curr, sa); it.has_curr(); it.next())
454  {
455  auto a = it.get_curr();
456  a->set_state(Processing);
457 
458  auto tgt = it.get_node(a);
459  if (tgt->state() == Processed)
460  continue;
461 
462  if (tgt->state() != Processed)
463  {
464  q.put(a);
465  tgt->set_state(Processing);
466  }
467  else
468  a->set_state(Processed);
469  }
470  } // end while
471 
472  Path<GT> ret(g);
473  if (not end)
474  return ret;
475 
476  assert(curr == end);
477 
478  while (curr != start)
479  {
480  ret.insert(curr);
481  curr = (typename GT::Node*) NODE_COOKIE(curr);
482  }
483  ret.insert(start);
484 
485  return ret;
486  }
487 
488 public:
489 
490  Directed_Find_Path(const GT & __g, SA & __sa) : g(__g), sa(__sa) {}
491 
492  Directed_Find_Path(const GT & __g, SA && __sa = SA()) : g(__g), sa(__sa) {}
493 
494  template <class Op>
495  Path<GT> dfs(typename GT::Node * start, Op & op)
496  {
497  return find<DynListStack, Op>(start, op);
498  }
499 
500  template <class Op>
501  Path<GT> dfs(typename GT::Node * start, Op && op)
502  {
503  return find<DynListStack, Op>(start, op);
504  }
505 
506  template <class Op>
507  Path<GT> bfs(typename GT::Node * start, Op & op)
508  {
509  return find<DynListQueue, Op>(start, op);
510  }
511 
512  template <class Op>
513  Path<GT> bfs(typename GT::Node * start, Op && op)
514  {
515  return find<DynListQueue, Op>(start, op);
516  }
517 
518  Path<GT> dfs(typename GT::Node * start, typename GT::Node * end)
519  {
520  return dfs(start, [end] (auto p) { return p == end; });
521  }
522 
523  Path<GT> bfs(typename GT::Node * start, typename GT::Node * end)
524  {
525  return bfs(start, [end] (auto p) { return p == end; });
526  }
527 };
528 
529 
530 
531 
532 } // namespace Aleph
533 
534 # endif // TPL_FIND_PATH_H
const unsigned char Processing
#define NODE_COOKIE(p)
Definition: aleph-graph.H:333
bool is_empty() const noexcept
rioReturn true if this is empty
Definition: tpl_dynListQueue.H:112
void insert(Arc *arc)
Definition: tpl_graph.H:2951
#define IS_NODE_VISITED(p, bit)
Definition: aleph-graph.H:327
Definition: tpl_find_path.H:249
Definition: tpl_dynListQueue.H:50
Node * remove_last_node() noexcept(noexcept(list.remove_last()))
Definition: tpl_graph.H:3105
const unsigned char Processed
#define IS_ARC_VISITED(p, bit)
Definition: aleph-graph.H:360
Definition: tpl_graph.H:53
Definition: tpl_find_path.H:69
Definition: ah-comb.H:35
Definition: tpl_find_path.H:411
Definition: tpl_graph.H:1063
Definition: tpl_graph.H:1796
#define NODE_BITS(p)
Definition: aleph-graph.H:305
void set_graph(const GT &__g, Node *start_node=nullptr)
Definition: tpl_graph.H:2745
#define ARC_BITS(p)
Definition: aleph-graph.H:351
void empty() noexcept
Empty the queue.
Definition: tpl_dynListQueue.H:185
void empty()
Clean the path: all the nodes and arc are removed.
Definition: tpl_graph.H:2761
T get()
Definition: tpl_dynListQueue.H:165
void append(Arc *arc)
Definition: tpl_graph.H:2808
Definition: tpl_graph.H:1177
bool inside_graph(const GT &gr) const noexcept
Return true if this is on graph gr
Definition: tpl_graph.H:2708
T & put(const T &data)
The type of element.
Definition: tpl_dynListQueue.H:125

Leandro Rabindranath León