Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_find_path.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
52# ifndef TPL_FIND_PATH_H
53# define TPL_FIND_PATH_H
54
55# include <tpl_dynListStack.H>
56# include <tpl_dynListQueue.H>
57# include <tpl_graph_utils.H>
58# include <ah-errors.H>
59
60namespace Aleph
61{
62 template <class GT>
64 {
65 bool operator ()(typename GT::Node *) const noexcept { return false; }
66 };
67
91 template <class GT,
92 template <class, class> class Itor = Node_Arc_Iterator,
93 class SA = Dft_Show_Arc<GT>>
95 {
96 SA & sa;
97 GT *g_ptr = nullptr;
98
99 template <class Op>
100 bool find_path(typename GT::Node *curr, typename GT::Arc *arc,
101 Path<GT> & path, Op & op)
102 {
103 if (op(curr)) // goal node reached?
104 {
105 path.append(arc);
106 return true;
107 }
108
109 if (IS_NODE_VISITED(curr, Find_Path)) // ¿ha sido visitado?
110 return false; // sí ==> desde él no hay camino
111
112 path.append(arc); // añadir curr_arc al camino
113 NODE_BITS(curr).set_bit(Find_Path, true);
114
115 // buscar recursivamente a través de arcos de curr_node
116 for (Itor<GT, SA> i(curr, sa); i.has_curr(); i.next())
117 {
118 auto next_arc = i.get_curr();
120 continue;
121
122 ARC_BITS(next_arc).set_bit(Find_Path, true);
124 if (find_path(next_node, next_arc, path, op))
125 return true; // se encontró camino
126 }
127
128 path.remove_last_node();
129
130 return false;
131 }
132
133 template <class Op>
134 bool find(const GT & g, typename GT::Node *start, Path<GT> & path, Op & op)
135 {
136 g_ptr = const_cast<GT *>(&g);
137 path.set_graph(g, start);
138
139 if (op(start))
140 return true;
141
144
145 NODE_BITS(start).set_bit(Find_Path, true);
146
147 // explorar recursivamente cada arco de start
148 for (Itor<GT, SA> i(start, sa); i.has_curr(); i.next())
149 {
150 auto arc = i.get_curr();
151 ARC_BITS(arc).set_bit(Find_Path, true);
152
153 auto next_node = g.get_connected_node(arc, start);
155 continue;
156
157 if (find_path(next_node, arc, path, op))
158 return true;
159 }
160
161 path.remove_last_node();
162
163 return false;
164 }
165
166 template <class Op>
167 bool find(const GT & g, typename GT::Node *start, Path<GT> & path, Op && op)
168 {
169 return find(g, start, path, op);
170 }
171
172 public:
174 : sa(__sa)
175 { /* empty */
176 }
177
179 : sa(__sa)
180 { /* empty */
181 }
182
193 bool operator ()(const GT & g,
194 typename GT::Node *start, typename GT::Node *end,
195 Path<GT> & path)
196 {
197 return find(g, start, path, [end](auto p) { return p == end; });
198 }
199
210 typename GT::Node *start,
211 typename GT::Node *end)
212 {
213 Path<GT> ret(g);
214 find(g, start, ret, [end](auto p) { return p == end; });
215 return ret;
216 }
217
230 template <class Op>
231 Path<GT> operator ()(const GT & g, typename GT::Node *start, Op & op)
232 {
233 Path<GT> ret(g);
234 find<Op>(g, start, ret, op);
235 return ret;
236 }
237
238 template <class Op = Dft_Goal_Node<GT>>
239 Path<GT> operator ()(const GT & g, typename GT::Node *start, Op && op)
240 {
241 Path<GT> ret(g);
242 find<Op>(g, start, ret, op);
243 return ret;
244 }
245 };
246
247
271 template <class GT,
272 template <typename, class> class Itor = Node_Arc_Iterator,
273 class SA = Dft_Show_Arc<GT>>
275 {
277
278 template <class Op>
279 bool find_path(const GT & g, typename GT::Node *start,
280 Path<GT> & path, Op & op)
281 {
282 if (not path.inside_graph(g))
283 ah_invalid_argument_if(true) << "Path does not belong to graph";
284
285 path.empty(); // limpiamos cualquier cosa que esté en path
286 g.reset_nodes();
287 g.reset_arcs();
288
290
291 for (Itor<GT, SA> i(start, sa); i.has_curr(); i.next())
292 q.put(i.get_current_arc());
293
294 NODE_BITS(start).set_bit(Find_Path, true); // márquelo visitado
295
296 typename GT::Node *end = nullptr;
297
298 while (not q.is_empty()) // mientras queden arcos por visitar
299 {
300 auto arc = q.get();
301 auto src = g.get_src_node(arc);
302 auto tgt = g.get_tgt_node(arc);
303
305 continue;
306
307 if (IS_NODE_VISITED(tgt, Find_Path))
308 std::swap(src, tgt);
309
310 ARC_BITS(arc).set_bit(Find_Path, true);
311 NODE_BITS(tgt).set_bit(Find_Path, true);
312 NODE_COOKIE(tgt) = src;
313
314 if (op(tgt)) // ¿se encontró un camino que satisfaga op?
315 {
316 end = tgt;
317 break;
318 }
319
320 for (Itor<GT, SA> i(tgt); i.has_curr(); i.next())
321 {
322 auto a = i.get_current_arc();
323 if (IS_ARC_VISITED(a, Find_Path)) // ¿arco visitado?
324 continue; // sí ==> avanzar al siguiente
325
326 // revise nodos del arco para ver si han sido visitados
329 continue; // nodos ya visitados ==> no meter arco
330
331 q.put(a);
332 }
333 }
334
335 if (not end)
336 return false;
337
338 q.empty();
339 path.insert(end);
340 auto p = end;
341 while (p != start)
342 {
343 p = (typename GT::Node *) NODE_COOKIE(p);
344 path.insert(p);
345 }
346
347 return true;
348 }
349
350 template <class Op>
351 bool find_path(const GT & g, typename GT::Node *start,
352 Path<GT> & path, Op && op)
353 {
354 return find_path(g, start, path, op);
355 }
356
357 public:
359 : sa(_sa)
360 { /* Empty */
361 }
362
364 : sa(_sa)
365 { /* Empty */
366 }
367
377 template <class Op>
378 Path<GT> operator ()(const GT & g, typename GT::Node *start, Op & op)
379 {
380 Path<GT> ret(g);
381 find_path(g, start, ret, op);
382 return ret;
383 }
384
385 template <class Op>
386 Path<GT> operator ()(const GT & g, typename GT::Node *start, Op && op)
387 {
388 Path<GT> ret(g);
389 find_path(g, start, ret, op);
390 return ret;
391 }
392
403 bool operator ()(const GT & g, typename GT::Node *start,
404 typename GT::Node *end, Path<GT> & path)
405 {
406 return find_path(g, start, path, [end](auto p) { return p == end; });
407 }
408
419 typename GT::Node *start, typename GT::Node *end)
420 {
421 Path<GT> ret(g);
422 find_path(g, start, ret, [end](auto p) { return p == end; });
423 return ret;
424 }
425 };
426
432 template <class GT,
433 template <typename, class> class Itor = Out_Iterator,
434 class SA = Dft_Show_Arc<GT>>
436 {
437 const GT & g;
439
440 template <template <typename T> class Q, class Op>
441 Path<GT> find(typename GT::Node *start, Op & op)
442 {
443 g.reset_nodes();
444 g.reset_arcs();
445
446 start->set_state(Processed);
447
449 for (Itor<GT, SA> it(start, sa); it.has_curr(); it.next())
450 {
451 auto a = it.get_curr();
452 g.get_tgt_node(a)->set_state(Processing);
453 a->set_state(Processing);
454 q.put(a);
455 }
456
457 typename GT::Node *end = nullptr, *curr = nullptr;
458 while (not q.is_empty())
459 {
460 auto arc = q.get();
461 assert(arc->state() == Processing);
462 arc->set_state(Processed);
463
464 curr = g.get_tgt_node(arc);
465 if (curr->state() == Processed)
466 continue;
467
468 curr->set_state(Processed);
469 NODE_COOKIE(curr) = g.get_src_node(arc);
470
471 if (op(curr))
472 {
473 end = curr;
474 break;
475 }
476
477 for (Itor<GT, SA> it(curr, sa); it.has_curr(); it.next())
478 {
479 auto a = it.get_curr();
481
482 auto tgt = g.get_tgt_node(a);
483 if (tgt->state() == Processed)
484 continue;
485
486 if (tgt->state() != Processed)
487 {
488 q.put(a);
489 tgt->set_state(Processing);
490 }
491 else
492 a->set_state(Processed);
493 }
494 } // end while
495
496 Path<GT> ret(g);
497 if (not end)
498 return ret;
499
500 assert(curr == end);
501
502 while (curr != start)
503 {
504 ret.insert(curr);
505 curr = (typename GT::Node *) NODE_COOKIE(curr);
506 }
507 ret.insert(start);
508
509 return ret;
510 }
511
512 public:
513 Directed_Find_Path(const GT & __g, SA & __sa) : g(__g), sa(__sa) {}
514
515 Directed_Find_Path(const GT & __g, SA && __sa = SA()) : g(__g), sa(__sa) {}
516
517 template <class Op>
518 Path<GT> dfs(typename GT::Node *start, Op & op)
519 {
520 return find<DynListStack, Op>(start, op);
521 }
522
523 template <class Op>
524 Path<GT> dfs(typename GT::Node *start, Op && op)
525 {
526 return find<DynListStack, Op>(start, op);
527 }
528
529 template <class Op>
530 Path<GT> bfs(typename GT::Node *start, Op & op)
531 {
532 return find<DynListQueue, Op>(start, op);
533 }
534
535 template <class Op>
536 Path<GT> bfs(typename GT::Node *start, Op && op)
537 {
538 return find<DynListQueue, Op>(start, op);
539 }
540
541 Path<GT> dfs(typename GT::Node *start, typename GT::Node *end)
542 {
543 return dfs(start, [end](auto p) { return p == end; });
544 }
545
546 Path<GT> bfs(typename GT::Node *start, typename GT::Node *end)
547 {
548 return bfs(start, [end](auto p) { return p == end; });
549 }
550 };
551} // namespace Aleph
552
553# endif // TPL_FIND_PATH_H
Exception handling system with formatted messages for Aleph-w.
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
Definition ah-errors.H:639
Búsqueda de caminos sobre grafos dirigidos definidos mediante una clase grafo (no digrafo).
Directed_Find_Path(const GT &__g, SA &__sa)
Path< GT > dfs(typename GT::Node *start, Op &&op)
Path< GT > dfs(typename GT::Node *start, Op &op)
Path< GT > bfs(typename GT::Node *start, typename GT::Node *end)
Path< GT > dfs(typename GT::Node *start, typename GT::Node *end)
Directed_Find_Path(const GT &__g, SA &&__sa=SA())
Path< GT > find(typename GT::Node *start, Op &op)
Path< GT > bfs(typename GT::Node *start, Op &&op)
Path< GT > bfs(typename GT::Node *start, Op &op)
Dynamic queue of elements of generic type T based on single linked list.
T & put(const T &data)
The type of element.
T get()
Remove the oldest item of the queue.
void empty() noexcept
Empty the queue.
bool is_empty() const noexcept
Return true if this is empty.
T & insert(const T &item)
Insert a new item by copy.
Definition htlist.H:1502
Busca en amplitud un camino entre un par de nodos.
Path< GT > operator()(const GT &g, typename GT::Node *start, Op &op)
Invoca a la búsqueda de camino en amplitud.
bool find_path(const GT &g, typename GT::Node *start, Path< GT > &path, Op &&op)
bool find_path(const GT &g, typename GT::Node *start, Path< GT > &path, Op &op)
Busca en profundidad un camino entre un par de nodos.
Find_Path_Depth_First(SA &&__sa=SA())
bool operator()(const GT &g, typename GT::Node *start, typename GT::Node *end, Path< GT > &path)
Invoca a la búsqueda de camino en profundidad.
bool find(const GT &g, typename GT::Node *start, Path< GT > &path, Op &&op)
bool find_path(typename GT::Node *curr, typename GT::Arc *arc, Path< GT > &path, Op &op)
bool find(const GT &g, typename GT::Node *start, Path< GT > &path, Op &op)
constexpr bool is_empty() const noexcept
Return true if list is empty.
Definition htlist.H:523
Filtered iterator for outcoming arcs of a node.
Definition tpl_graph.H:1750
Path on a graph.
Definition tpl_graph.H:2669
void insert(Arc *arc)
Insert an arc as the first of a path.
Definition tpl_graph.H:3008
void empty()
Clean the path: all the nodes and arc are removed.
Definition tpl_graph.H:2819
bool inside_graph(const GT &gr) const noexcept
Return true if this is on graph gr
Definition tpl_graph.H:2747
void set_graph(const GT &__g, Node *start_node=nullptr)
Set the graph of the path.
Definition tpl_graph.H:2797
void append(Arc *arc)
Append an arc to the path.
Definition tpl_graph.H:2865
Node * remove_last_node()
Remove the last node of path.
Definition tpl_graph.H:3170
void set_state(unsigned int s) noexcept
Set the state to value s
Definition graph-dry.H:503
void reset_bit_nodes(int bit) const noexcept
Reset bit to zero for all the nodes of graph.
Definition graph-dry.H:1040
void reset_arcs() const
Reset all the arcs of graph (the control bits, the state, the counter and the cookie)
Definition graph-dry.H:927
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:731
Node * get_connected_node(Arc *arc, Node *node) const noexcept
Return the adjacent node to node through arc.
Definition graph-dry.H:772
void reset_bit_arcs(int bit) const noexcept
Reset bit to zero for all the arcs of graph.
Definition graph-dry.H:1046
void reset_nodes() const
Reset all the nodes of graph (the control bits, the state, the counter and the cookie)
Definition graph-dry.H:920
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:737
List_Graph< Graph_Node< int >, Graph_Arc< int > > GT
const unsigned char Processed
The node or arc has already been processed.
Definition aleph-graph.C:39
const unsigned char Processing
The node are being processed; probably it is inside a queue, stack or heap.
Definition aleph-graph.C:38
#define IS_NODE_VISITED(p, bit)
Determine whether the control bit is set or not to one.
#define ARC_BITS(p)
Return the control bits of arc p.
#define NODE_COOKIE(p)
Return the node cookie
#define IS_ARC_VISITED(p, bit)
Determine whether the bit field is or not set to one.
#define NODE_BITS(p)
Get the control bits of a node.
@ Find_Path
Definition aleph-graph.H:76
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynList< T > maps(const C &c, Op op)
Classic map operation.
bool operator()(typename GT::Node *) const noexcept
Default filter for filtered iterators on arcs.
Definition tpl_graph.H:1000
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
Filtered iterator of adjacent arcs of a node.
Definition tpl_graph.H:1119
Dynamic queue implementation based on linked lists.
Dynamic stack implementation based on linked lists.
Utility algorithms and operations for graphs.