Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_graph_utils.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
44# ifndef TPL_GRAPH_UTILS_H
45# define TPL_GRAPH_UTILS_H
46
47# include <ah-graph-concepts.H>
48
49
50# include <cassert>
51# include <cstddef>
52# include <limits>
53# include <memory>
54# include <tuple>
55# include <utility>
56# include <vector>
57# include <tpl_agraph.H>
58# include <tpl_dynListQueue.H>
59# include <ah-errors.H>
60
61using namespace Aleph;
62
63namespace Aleph {
64
77 template <AlephGraph GT> inline static bool
78 __depth_first_traversal(const GT & g, typename GT::Node * node,
79 typename GT::Arc * arc,
80 bool (*visit)(const GT & g, typename GT::Node *,
81 typename GT::Arc *),
82 size_t & count);
83
107 template <AlephGraph GT> inline size_t
109 bool (*visit)(const GT & g, typename GT::Node *,
110 typename GT::Arc *))
111 {
114 size_t counter = 0;
115
117
118 return counter;
119 }
120
122 template <AlephGraph GT> inline
123 size_t depth_first_traversal(const GT & g,
124 bool (*visit)(const GT &, typename GT::Node *,
125 typename GT::Arc *))
126 {
128 }
129
134 template <class GT>
136 {
138 bool operator () (const GT &, typename GT::Node *, typename GT::Arc *)
139 {
140 return false;
141 }
142 };
143
164 template <AlephGraph GT,
168 {
169 Operation * op_ptr = nullptr;
170 SA sa;
171 size_t count = 0;
172 const GT * g_ptr = nullptr;
173
174 private:
175
176 bool __dft(typename GT::Node * node, typename GT::Arc * arc = nullptr)
177 {
178 if (IS_NODE_VISITED(node, Depth_First))
179 return false;
180
181 NODE_BITS(node).set_bit(Depth_First, true);
182 count++;
183
184 if ((*op_ptr)(*g_ptr, node, arc))
185 return true;
186
187 if (count == g_ptr->get_num_nodes())
188 return true;
189
190 // Recursively traverse arcs incident to `node`.
191 for (Node_Arc_Iterator<GT, SA> it(node, sa); it.has_curr(); it.next_ne())
192 {
193 auto arc = it.get_current_arc_ne();
194 if (IS_ARC_VISITED(arc, Depth_First))
195 continue;
196
197 ARC_BITS(arc).set_bit(Depth_First, true);
198 if (__dft (it.get_tgt_node_ne(), arc))
199 return true;
200 }
201
202 return false;
203 }
204
205 size_t dft(const GT & g, typename GT::Node * start_node, Operation & __op)
206 {
207 op_ptr = &__op;
208 g_ptr = &g;
209
212
213 count = 0;
214
216
217 return count;
218 }
219
220 public:
221
223 Depth_First_Traversal(SA __sa = SA()) : sa(__sa) { /* empty */ }
224
239 size_t operator () (const GT & g, Operation op = Operation())
240 {
241 return dft(g, g.get_first_node(), op);
242 }
243
259 size_t operator () (const GT & g, typename GT::Node * sn,
260 Operation op = Operation())
261 {
262 return dft(g, sn, op);
263 }
264 };
265
266
267 template <AlephGraph GT> inline static bool
268 __depth_first_traversal(const GT & g, typename GT::Node * node,
269 typename GT::Arc * arc,
270 bool (*visit)(const GT & g, typename GT::Node *,
271 typename GT::Arc *),
272 size_t & count)
273 {
274 if (IS_NODE_VISITED(node, Depth_First))
275 return false;
276
277 NODE_BITS(node).set_bit(Depth_First, true); // mark node visited
278 count++;
279
280 if (visit != nullptr) // invoke callback if provided
281 if ((*visit)(g, node, arc))
282 return true;
283
284 if (count == g.get_num_nodes()) // all nodes discovered?
285 return true;
286
287 for (auto it = g.get_arc_it(node); it.has_curr(); it.next_ne())
288 {
289 auto arc = it.get_current_arc_ne();
290 if (IS_ARC_VISITED(arc, Depth_First))
291 continue;
292
293 ARC_BITS(arc).set_bit(Depth_First, true); // mark arc visited
294 if (__depth_first_traversal(g, it.get_tgt_node_ne(), arc, visit, count))
295 return true;
296 }
297
298 return false; // keep exploring
299 }
300
301
327 template <AlephGraph GT> inline size_t
328 breadth_first_traversal(const GT & g, typename GT::Node * start,
329 bool (*visit)(const GT &, typename GT::Node *,
330 typename GT::Arc *) )
331 {
335
336 for (auto it = g.get_arc_it(start); it.has_curr(); it.next_ne())
337 q.put(it.get_current_arc_ne());
338
339 NODE_BITS(start).set_bit(Breadth_First, true);
340 size_t node_counter = 1;
341
342 if (visit != nullptr)
343 if ((*visit)(g, start, nullptr))
344 return 1;
345
346 while (not q.is_empty() and node_counter < g.get_num_nodes())
347 {
348 auto arc = q.get();
349 ARC_BITS(arc).set_bit(Breadth_First, true);
350
351 auto src = g.get_src_node(arc);
352 auto tgt = g.get_tgt_node(arc);
355 continue;
356
357 auto visit_node = IS_NODE_VISITED(src, Breadth_First) ? tgt : src;
358 if (visit != nullptr)
359 if ((*visit)(g, visit_node, arc))
360 break;
361
362 NODE_BITS(visit_node).set_bit(Breadth_First, true);
363 node_counter++;
364
365 for (auto it = g.get_arc_it(visit_node); it.has_curr(); it.next_ne())
366 {
367 auto curr_arc = it.get_current_arc_ne();
369 continue;
370
373 continue; // both endpoints already visited
374
375 q.put(curr_arc);
376 }
377 }
378
379 return node_counter;
380 }
381
383 template <AlephGraph GT> inline size_t
385 bool (*visit)(const GT &, typename GT::Node *,
386 typename GT::Arc *))
387 {
389 }
390
391
413 template <AlephGraph GT,
417 {
418 SA sa;
419 size_t count = 0;
420
421 size_t bft(const GT & g, typename GT::Node * start, Operation & op)
422 {
425 DynListQueue<typename GT::Arc*> q; // pending arcs queue
426
427 for (Node_Arc_Iterator<GT, SA> it(start, sa); it.has_curr(); it.next_ne())
428 q.put(it.get_current_arc_ne());
429
430 NODE_BITS(start).set_bit(Breadth_First, true);
431 count = 1;
432
433 if (op (g, start, nullptr))
434 return 1;
435
436 while (not q.is_empty() and count < g.get_num_nodes())
437 {
438 auto arc = q.get();
439 ARC_BITS(arc).set_bit(Breadth_First, true);
440
441 auto src = g.get_src_node(arc);
442 auto tgt = g.get_tgt_node(arc);
443
446 continue;
447
448 auto curr = IS_NODE_VISITED(src, Breadth_First) ? tgt : src;
449 if (op (g, curr, arc))
450 break;
451
452 NODE_BITS(curr).set_bit(Breadth_First, true);
453 count++;
454
455 for (Node_Arc_Iterator<GT, SA> it(curr, sa); it.has_curr(); it.next_ne())
456 {
457 auto curr_arc = it.get_current_arc_ne();
459 continue;
460
463 continue;
464
465 q.put(curr_arc);
466 }
467 }
468
469 return count;
470 }
471
472 public:
473
475 Breadth_First_Traversal(SA __sa = SA()) : sa(__sa) { /* empty */ }
476
491 size_t operator () (const GT & g, Operation op)
492 {
493 return bft (g, g.get_first_node(), op);
494 }
495
511 size_t operator () (const GT & g, typename GT::Node * p,
512 Operation && op = Operation())
513 {
514 return bft(g, p, op);
515 }
516
527 size_t operator () (const GT & g, typename GT::Node * p, Operation & op)
528 {
529 return bft(g, p, op);
530 }
531 };
532
555 template <AlephGraph GT> inline
556 Path<GT> find_path_breadth_first(const GT & g, typename GT::Node * start,
557 typename GT::Node * end)
558 {
559 ah_invalid_argument_if(start == nullptr or end == nullptr)
560 << "find_path_breadth_first(): start and end must be non-null";
561
562 if (start == end)
563 return Path<GT>(g, start);
564
565 g.reset_nodes();
566 g.reset_arcs();
567
569
570 for (auto it = g.get_arc_it(start); it.has_curr(); it.next_ne())
571 q.put(it.get_current_arc_ne());
572
573 NODE_BITS(start).set_bit(Find_Path, true);
574
575 bool path_found = false;
576
577 while (not q.is_empty())
578 {
579 auto arc = q.get();
580 auto src = g.get_src_node(arc);
581 auto tgt = g.get_tgt_node(arc);
582
584 continue;
585
586 if (IS_NODE_VISITED(tgt, Find_Path))
587 std::swap(src, tgt);
588
589 ARC_BITS(arc).set_bit(Find_Path, true);
590 NODE_BITS(tgt).set_bit(Find_Path, true);
591 NODE_COOKIE(tgt) = src;
592
593 if (tgt == end)
594 {
595 path_found = true;
596 break;
597 }
598
599 for (auto it = g.get_arc_it(tgt); it.has_curr(); it.next_ne())
600 {
601 auto a = it.get_current_arc_ne();
603 continue;
604
607 continue;
608
609 q.put(a);
610 }
611 }
612
613 if (not path_found)
614 return Path<GT>(g);
615
616 q.empty(); // free queue memory for eventually saving the required for path
617
618 Path<GT> path(g, end);
619 auto p = end;
620 while (p != start)
621 {
622 p = (typename GT::Node *) NODE_COOKIE(p);
623 path.insert(p);
624 }
625
626 return path;
627 }
628
629
642 template <AlephGraph GT> inline
643 bool test_connectivity(const GT & g)
644 {
646 << "test_connectivity() does not work on digraphs";
647
648 const auto num_nodes = g.get_num_nodes();
649 if (num_nodes == 0)
650 return false;
651
652 if (g.get_num_arcs() + 1 < num_nodes)
653 return false;
654
655 return depth_first_traversal<GT>(g, nullptr) == num_nodes;
656 }
657
658
660 template <AlephGraph GT> inline static
661 bool __test_cycle(const GT & g, typename GT::Node *, typename GT::Node *);
662
663
680 template <AlephGraph GT> inline
681 bool test_for_cycle(const GT & g, typename GT::Node * src)
682 {
683 ah_invalid_argument_if(src == nullptr)
684 << "test_for_cycle(): src must be non-null";
685
688 for (auto it = g.get_arc_it(src); it.has_curr(); it.next_ne())
689 {
690 auto arc = it.get_curr();
691 if (IS_ARC_VISITED(arc, Test_Cycle))
692 continue;
693
694 ARC_BITS(arc).set_bit(Test_Cycle, true);
695 if (__test_cycle(g, src, it.get_tgt_node_ne()))
696 return true;
697 }
698
699 return false;
700 }
701
702
703 template <AlephGraph GT> inline static bool
704 __test_cycle(const GT & g, typename GT::Node * src, typename GT::Node * curr)
705 {
706 if (src == curr)
707 return true; // detected cycle
708
709 if (IS_NODE_VISITED(curr, Test_Cycle))
710 return false;
711
712 NODE_BITS(curr).set_bit(Test_Cycle, true);
713
714 for (auto it = g.get_arc_it(curr); it.has_curr(); it.next_ne())
715 {
716 auto arc = it.get_curr();
717 if (IS_ARC_VISITED(arc, Test_Cycle))
718 continue;
719
720 ARC_BITS(arc).set_bit(Test_Cycle, true);
721 if (__test_cycle(g, src, it.get_tgt_node_ne()))
722 return true;
723 }
724
725 return false;
726 }
727
729 template <AlephGraph GT> inline static
730 bool __is_graph_acyclique(const GT & g, typename GT::Node * curr_node)
731 {
733 return false;
734
735 NODE_BITS(curr_node).set_bit(Test_Cycle, true);
736
737 for (auto it = g.get_arc_it(curr_node); it.has_curr(); it.next_ne())
738 {
739 auto arc = it.get_current_arc_ne();
740 if (IS_ARC_VISITED(arc, Test_Cycle))
741 continue;
742
743 ARC_BITS(arc).set_bit(Test_Cycle, true);
744
745 if (not __is_graph_acyclique(g, it.get_tgt_node_ne()))
746 return false;
747 }
748 // All outgoing arcs explored without detecting a back edge.
749 return true;
750 }
751
752
771 template <AlephGraph GT> inline
772 bool is_graph_acyclique(const GT & g, typename GT::Node * start_node)
773 {
775 << "is_graph_acyclique() does not work for digraphs";
776
777 const auto num_nodes = g.get_num_nodes();
778 if (num_nodes == 0)
779 return true;
780
782 << "is_graph_acyclique(): start_node must be non-null";
783
784 if (num_nodes == 1)
785 return true;
786
787 if (g.get_num_arcs() >= num_nodes)
788 return false;
789
792
794 }
795
811 template <AlephGraph GT> inline
812 bool is_graph_acyclique(const GT & g)
813 {
815 << "is_graph_acyclique() does not work for digraphs";
816
817 const auto num_nodes = g.get_num_nodes();
818 if (num_nodes == 0)
819 return true;
820
821 if (num_nodes == 1)
822 return true;
823
824 if (g.get_num_arcs() >= num_nodes)
825 return false;
826
829
830 for (auto it = g.get_node_it(); it.has_curr(); it.next_ne())
831 {
832 auto current_node = it.get_current_node_ne();
833 if (IS_NODE_VISITED(current_node, Test_Cycle))
834 continue;
835
836 if (not __is_graph_acyclique(g, current_node))
837 return false;
838 }
839
840 return true;
841 }
842
843
852 template <AlephGraph GT>
853 inline bool has_cycle(const GT & g)
854 {
855 return not is_graph_acyclique(g);
856 }
857
858
874 template <AlephGraph GT> inline
875 bool test_for_path(const GT & g, typename GT::Node * start_node,
876 typename GT::Node * end_node)
877 {
878 ah_invalid_argument_if(start_node == nullptr or end_node == nullptr)
879 << "test_for_path(): start_node and end_node must be non-null";
880
881 if (start_node == end_node)
882 return true;
883
886
887 for (auto it = g.get_arc_it(start_node); it.has_curr(); it.next_ne())
888 {
889 auto arc = it.get_current_arc_ne();
890 ARC_BITS(arc).set_bit(Find_Path, true);
891 if (__test_for_path(g, it.get_tgt_node_ne(), end_node))
892 return true;
893 }
894
895 return false;
896 }
897
898
900 template <AlephGraph GT> inline static
901 bool __test_for_path(const GT & g, typename GT::Node * curr_node,
902 typename GT::Node * end_node)
903 {
904 if (curr_node == end_node)
905 return true;
906
908 return false;
909
910 NODE_BITS(curr_node).set_bit(Find_Path, true);
911
912 for (auto it = g.get_arc_it(curr_node); it.has_curr(); it.next_ne())
913 {
914 auto arc = it.get_current_arc_ne();
915 if (IS_ARC_VISITED(arc, Find_Path))
916 continue;
917
918 ARC_BITS(arc).set_bit(Find_Path, true);
919 if (__test_for_path(g, it.get_tgt_node_ne(), end_node))
920 return true;
921 }
922
923 return false;
924 }
925
927 template <AlephGraph GT> inline
929
931 template <AlephGraph GT> inline
932 void build_subgraph(const GT & g, GT & sg,
933 typename GT::Node * g_src, size_t & node_count);
934
935
954 template <AlephGraph GT> inline
956 {
957 g.reset_nodes();
958 g.reset_arcs();
959
960 DynList<GT> list;
961 size_t count = 0; // visited node counter
962 for (auto it = g.get_node_it(); count < g.get_num_nodes() and it.has_curr();
963 it.next_ne())
964 {
965 auto curr = it.get_current_node_ne();
966 if (IS_NODE_VISITED(curr, Build_Subtree))
967 continue;
968
969 list.append(GT());
970 GT & subgraph = list.get_last();
971 build_subgraph(g, subgraph, curr, count);
972 }
973
974 return list;
975 }
976
977
998 template <AlephGraph GT> inline
999 void build_subgraph(const GT & g, GT & sg,
1000 typename GT::Node * g_src, size_t & node_count)
1001 {
1003 return;
1004
1005 NODE_BITS(g_src).set_bit(Build_Subtree, true);
1006 ++node_count;
1007
1009 if (sg_src == nullptr) // not mapped yet
1010 {
1011 sg_src = sg.insert_node(g_src->get_info());
1013 }
1014
1015 for (auto it = g.get_arc_it(g_src);
1016 node_count < g.get_num_nodes() and it.has_curr(); it.next_ne())
1017 {
1018 auto arc = it.get_current_arc_ne();
1019 if (IS_ARC_VISITED(arc, Build_Subtree))
1020 continue;
1021
1022 ARC_BITS(arc).set_bit(Build_Subtree, true);
1023 auto g_tgt = it.get_tgt_node_ne();
1025 if (sg_tgt == nullptr) // sg_tgt mapped in sg?
1026 {
1027 sg_tgt = sg.insert_node(g_tgt->get_info());
1029 }
1030
1031 auto sg_arc = sg.insert_arc(sg_src, sg_tgt, arc->get_info());
1032 GT::map_arcs(arc, sg_arc);
1033
1034 build_subgraph(g, sg, g_tgt, node_count);
1035 }
1036 }
1037
1038
1040 template <AlephGraph GT> inline static
1041 bool __find_depth_first_spanning_tree(const GT & g,
1042 typename GT::Node * gnode,
1043 typename GT::Arc * garc,
1044 GT & tree,
1045 typename GT::Node * tnode);
1046
1066 template <AlephGraph GT> inline
1068 {
1069 g.reset_nodes();
1070 g.reset_arcs();
1071
1072 GT tree;
1073
1075
1076 auto tnode = tree.insert_node(gnode->get_info());
1078
1079 for (auto it = g.get_arc_it(gnode); it.has_curr(); it.next_ne())
1080 {
1081 auto arc = it.get_current_arc_ne();
1082 if (IS_ARC_VISITED(arc, Spanning_Tree))
1083 continue;
1084
1085 auto arc_tgt_node = it.get_tgt_node_ne();
1087 continue;
1088
1090 return tree;
1091 }
1092
1093 return tree;
1094 }
1095
1097 template <AlephGraph GT> inline
1099 {
1101 }
1102
1103
1104 template <AlephGraph GT> inline static
1106 typename GT::Arc * garc,
1107 GT & tree, typename GT::Node * tnode)
1108 {
1109 NODE_BITS(gnode).set_bit(Spanning_Tree, true);
1110 ARC_BITS(garc).set_bit(Spanning_Tree, true);
1111
1112 auto tree_tgt_node = tree.insert_node(gnode->get_info());
1114
1115 auto tarc = tree.insert_arc(tnode, tree_tgt_node, garc->get_info());
1117
1119 if (tree.get_num_nodes() == g.get_num_nodes())
1120 return true;
1121
1122 assert(tree.get_num_nodes() > tree.get_num_arcs()); // tree invariant
1123
1124 for (auto it = g.get_arc_it(gnode); it.has_curr(); it.next_ne())
1125 {
1126 auto arc = it.get_current_arc_ne();
1127 if (IS_ARC_VISITED(arc, Spanning_Tree))
1128 continue;
1129
1130 auto arc_tgt_node = it.get_tgt_node_ne();
1132 continue;
1133
1135 return true; // spanning tree completed
1136 }
1137
1138 return false;
1139 }
1140
1159 template <AlephGraph GT> inline
1161 {
1164
1165 GT tree;
1166
1167 std::unique_ptr<typename GT::Node> tp_auto(new typename GT::Node(gp));
1168 tree.insert_node(tp_auto.get());
1169 GT::map_nodes(gp, tp_auto.release());
1170 NODE_BITS(gp).set_bit(Spanning_Tree, true);
1171
1173 for (auto it = g.get_arc_it(gp); it.has_curr(); it.next_ne())
1174 q.put(it.get_curr());
1175
1176 while (not q.is_empty())
1177 {
1178 auto garc = q.get();
1179 ARC_BITS(garc).set_bit(Spanning_Tree, true);
1180 auto gsrc = g.get_src_node(garc);
1181 auto gtgt = g.get_tgt_node(garc);
1182
1185 continue;
1186
1187 if (IS_NODE_VISITED(gtgt, Spanning_Tree)) // gtgt visited?
1188 std::swap(gsrc, gtgt); // make gsrc the visited endpoint
1189
1190 auto tsrc = mapped_node<GT>(gsrc);
1191 NODE_BITS(gtgt).set_bit(Spanning_Tree, true);
1192
1193 // Create and map the new tree node.
1194 std::unique_ptr<typename GT::Node> ttgt_auto(new typename GT::Node(gtgt));
1195 tree.insert_node(ttgt_auto.get());
1196 auto ttgt = ttgt_auto.release();
1198
1199 // Insert and map the new tree arc.
1200 auto tarc = tree.insert_arc(tsrc, ttgt, garc->get_info());
1202 if (tree.get_num_nodes() == g.get_num_nodes())
1203 break;
1204
1205 // Enqueue arcs incident to the newly visited node.
1206 for (auto it = g.get_arc_it(gtgt); it.has_curr(); it.next_ne())
1207 {
1208 auto current_arc = it.get_current_arc_ne();
1209 if (IS_ARC_VISITED(current_arc, Spanning_Tree))
1210 continue;
1211
1212 if (IS_NODE_VISITED(g.get_src_node(current_arc),Spanning_Tree) and
1214 continue;
1215 q.put(current_arc);
1216 }
1217 }
1218
1219 return tree;
1220 }
1221
1240 template <AlephGraph GT>
1242 {
1243 using Node = typename GT::Node;
1244 using Arc = typename GT::Arc;
1245
1246 GT ret;
1248 arcs.for_each([&table, &ret] (Arc * ga)
1249 {
1250 if (ga == nullptr)
1251 return;
1252
1253 Node * gsrc = (Node*) ga->src_node;
1254 Node * gtgt = (Node*) ga->tgt_node;
1255
1256 Node * tsrc;
1257 auto * pair_ptr = table.search(gsrc);
1258 if (pair_ptr)
1259 tsrc = pair_ptr->second;
1260 else
1261 {
1262 tsrc = ret.insert_node(gsrc->get_info());
1263 table.insert(gsrc, tsrc);
1265 }
1266
1267 Node * ttgt;
1268 pair_ptr = table.search(gtgt);
1269 if (pair_ptr)
1270 ttgt = pair_ptr->second;
1271 else
1272 {
1273 ttgt = ret.insert_node(gtgt->get_info());
1274 table.insert(gtgt, ttgt);
1276 }
1277
1278 Arc * ta = ret.insert_arc(tsrc, ttgt);
1279 *ta = *ga;
1280 ARC_COOKIE(ta) = ga;
1281 });
1282
1283 return ret;
1284 }
1285
1287 template <AlephGraph GT> inline static
1288 long & df(typename GT::Node * p)
1289 {
1290 return NODE_COUNTER(p);
1291 }
1292
1295 template <AlephGraph GT> inline static
1296 long & low(typename GT::Node * p)
1297 {
1298 return reinterpret_cast<long&>(NODE_COOKIE(p));
1299 }
1300
1302 template <AlephGraph GT> inline static
1303 void __compute_cut_nodes(const GT & g, DynList<typename GT::Node *> & list,
1304 typename GT::Node * p, typename GT::Arc * a,
1305 long & curr_df);
1306
1332 template <AlephGraph GT>
1334 compute_cut_nodes(const GT & g, typename GT::Node * start)
1335 {
1337
1339 << "compute_cut_nodes() does not work on digraphs";
1340
1341 if (g.get_num_nodes() == 0)
1342 return list;
1343
1344 ah_invalid_argument_if(start == nullptr)
1345 << "compute_cut_nodes(): start must be non-null";
1346
1347 using Node = typename GT::Node;
1348
1349 std::vector<Node*> nodes;
1350 nodes.reserve(g.get_num_nodes());
1351 for (auto it = g.get_node_it(); it.has_curr(); it.next_ne())
1352 nodes.push_back(it.get_curr());
1353
1354 std::vector<long> low_values(nodes.size(), -1);
1355
1356 for (size_t i = 0; i < nodes.size(); ++i)
1357 {
1358 auto p = nodes[i];
1359 NODE_COUNTER(p) = 0;
1360 NODE_BITS(p).reset();
1361 NODE_COOKIE(p) = &low_values[i];
1362 }
1363
1364 struct Cookie_Guard
1365 {
1366 std::vector<Node*> & nodes;
1367
1369 {
1370 for (auto p : nodes)
1371 NODE_COOKIE(p) = nullptr;
1372 }
1374
1375 g.reset_arcs();
1376 long current_df = 0;
1377 NODE_BITS(start).set_bit(Depth_First, true);
1378 low<GT>(start) = df<GT>(start) = current_df++;
1379 int call_counter = 0;
1380
1381 // Traverse arcs incident to `start`.
1382 for (auto it = g.get_arc_it(start);
1383 it.has_curr() and current_df < g.get_num_nodes(); it.next_ne())
1384 {
1385 auto tgt = it.get_tgt_node_ne();
1386 if (IS_NODE_VISITED(tgt, Depth_First))
1387 continue;
1388
1389 auto arc = it.get_current_arc_ne();
1390 if (IS_ARC_VISITED(arc, Depth_First))
1391 continue;
1392
1393 ARC_BITS(arc).set_bit(Depth_First, true);
1394 __compute_cut_nodes(g, list, tgt, arc, current_df);
1395 ++call_counter;
1396 }
1397
1398 // Root is an articulation point iff it has more than one DFS child.
1399 if (call_counter > 1)
1400 {
1401 NODE_BITS(start).set_bit(Cut, true);
1402 list.append(start);
1403 }
1404
1405 return list;
1406 }
1407
1409 template <AlephGraph GT>
1411 {
1412 return compute_cut_nodes(g, g.get_node());
1413 }
1414
1416 template <AlephGraph GT> inline static
1418 typename GT::Node * p, typename GT::Arc * a,
1419 long & curr_df)
1420 {
1421 NODE_BITS(p).set_bit(Depth_First, true);
1422 low<GT>(p) = df<GT>(p) = curr_df++;
1423
1424 bool p_is_cut_node = false;
1425 for (auto it = g.get_arc_it(p); it.has_curr(); it.next_ne())
1426 {
1427 auto arc = it.get_current_arc_ne();
1428 if (arc == a)
1429 continue; // parent arc
1430
1431 auto tgt = it.get_tgt_node_ne();
1432 if (IS_NODE_VISITED(tgt, Depth_First))
1433 {
1434 if (not IS_ARC_VISITED(arc, Depth_First))
1435 if (df<GT>(tgt) < low<GT>(p))
1436 low<GT>(p) = df<GT>(tgt);
1437
1438 continue;
1439 }
1440
1441 if (IS_ARC_VISITED(arc, Depth_First))
1442 continue;
1443
1444 ARC_BITS(arc).set_bit(Depth_First, true);
1445
1446 __compute_cut_nodes(g, list, tgt, arc, curr_df);
1447
1448 if (low<GT>(tgt) < low<GT>(p))
1449 low<GT>(p) = low<GT>(tgt);
1450
1451 if (low<GT>(tgt) >= df<GT>(p) and df<GT>(tgt) != 0)
1452 p_is_cut_node = true;
1453 }
1454
1455 if (p_is_cut_node)
1456 {
1457 NODE_BITS(p).set_bit(Cut, true);
1458 list.append(p);
1459 }
1460 }
1461
1466 const long Cross_Arc = -1;
1467
1469 template <AlephGraph GT> inline static
1470 bool is_a_cross_arc(typename GT::Arc * a)
1471 {
1472 return ARC_COUNTER(a) == Cross_Arc;
1473 }
1474
1476 template <AlephGraph GT> inline static
1477 bool is_a_cut_node(typename GT::Node * p)
1478 {
1479 return NODE_BITS(p).get_bit(Cut);
1480 }
1481
1483 template <AlephGraph GT> inline static
1484 bool is_an_cut_arc(typename GT::Arc * a)
1485 {
1486 return ARC_BITS(a).get_bit(Cut);
1487 }
1488
1490 template <AlephGraph GT> inline static
1491 bool is_node_painted(typename GT::Node * p)
1492 {
1493 return NODE_COUNTER(p) > 0;
1494 }
1495
1497 template <AlephGraph GT> inline static
1498 bool is_arc_painted(typename GT::Arc * arc)
1499 {
1500 return ARC_COUNTER(arc) > 0;
1501 }
1502
1504 template <AlephGraph GT> inline static
1505 void paint_node(typename GT::Node * p, const long & color)
1506 {
1507 NODE_COUNTER(p) = color;
1508 }
1509
1511 template <AlephGraph GT> inline static
1512 void paint_arc(typename GT::Arc * a, const long & color)
1513 {
1514 ARC_COUNTER(a) = color;
1515 }
1516
1518 template <AlephGraph GT> inline static
1519 const long & get_color(typename GT::Node * p)
1520 {
1521 return NODE_COUNTER(p);
1522 }
1523
1525 template <AlephGraph GT> inline static
1526 const long & get_color(typename GT::Arc * a)
1527 {
1528 return ARC_COUNTER(a);
1529 }
1530
1532 template <AlephGraph GT> inline static
1533 void __paint_subgraph(const GT & g, typename GT::Node * p, long current_color)
1534 {
1536
1537 if (is_node_painted <GT> (p))
1538 return;
1539
1541
1542 for (auto it = g.get_arc_it(p); it.has_curr(); it.next_ne())
1543 {
1544 auto arc = it.get_current_arc_ne();
1545 if (is_arc_painted <GT> (arc))
1546 continue;
1547
1548 auto tgt = it.get_tgt_node_ne();
1549 if (is_a_cut_node <GT> (tgt))
1550 continue;
1551
1553
1555 }
1556 }
1557
1559 template <AlephGraph GT> inline static
1560 void
1561 __paint_from_cut_node(const GT & g, typename GT::Node * p, long & current_color)
1562 {
1564
1565 // Paint each adjacent non-cut block with a new color.
1566 for (auto it = g.get_arc_it(p); it.has_curr(); it.next_ne())
1567 {
1568 auto arc = it.get_current_arc_ne();
1569
1571
1572 auto tgt_node = it.get_tgt_node_ne();
1573 if (is_a_cut_node <GT> (tgt_node)) // cut-to-cut arc
1574 {
1575 ARC_BITS(arc).set_bit(Cut, true);
1576 continue;
1577 }
1578 else
1579 {
1581 if (is_node_painted <GT> (tgt_node))
1582 continue;
1583 }
1584
1585 __paint_subgraph(g, tgt_node, current_color);
1586
1587 ++current_color;
1588
1590 }
1591 }
1592
1628 template <AlephGraph GT> inline long
1630 {
1633 long current_color = 1;
1634
1635 for (auto it = cut_node_list.get_it(); it.has_curr(); it.next_ne())
1636 __paint_from_cut_node(g, it.get_curr(), current_color);
1637
1638 return current_color;
1639 }
1640
1642 template <AlephGraph GT> inline static
1643 void __map_subgraph(const GT & g, GT & sg, typename GT::Node * gsrc,
1644 const long color)
1645 {
1647
1648 auto tsrc = mapped_node<GT>(gsrc); // image of gsrc in sg
1649
1650 // Traverse arcs and copy those with the requested color.
1651 for (auto it = g.get_arc_it(gsrc); it.has_curr(); it.next_ne())
1652 {
1653 auto garc = it.get_current_arc_ne();
1655 continue;
1656
1657 ARC_BITS(garc).set_bit(Build_Subtree, true);
1658
1659 auto gtgt = it.get_tgt_node_ne();
1660
1662
1663 typename GT::Node * ttgt = nullptr; // image of gtgt in sg
1666 else
1667 { // gtgt not in sg yet: copy & map it
1668 std::unique_ptr<typename GT::Node> ttgt_auto(new typename GT::Node(gtgt));
1669 sg.insert_node(ttgt_auto.get());
1671 NODE_BITS(gtgt).set_bit(Build_Subtree, true);
1672 ttgt = ttgt_auto.release();
1673 }
1674
1675 auto tarc = sg.insert_arc(tsrc, ttgt, garc->get_info());
1677
1678 __map_subgraph(g, sg, gtgt, color);
1679 }
1680 }
1681
1701 template <AlephGraph GT>
1702 GT map_subgraph(const GT & g, const long color)
1703 {
1706
1707 typename GT::Node * first = nullptr;
1708 for (auto it = g.get_node_it(); it.has_curr(); it.next_ne())
1709 if (get_color <GT> (it.get_current_node_ne()) == color)
1710 {
1711 first = it.get_current_node_ne();
1712 break;
1713 }
1714
1715 ah_domain_error_if(first == nullptr)
1716 << "Color does not exist in the graph";
1717
1718 GT sg;
1719 std::unique_ptr<typename GT::Node> auto_tsrc(new typename GT::Node(first));
1720 sg.insert_node(auto_tsrc.get());
1721 GT::map_nodes(first, auto_tsrc.release());
1722 NODE_BITS(first).set_bit(Build_Subtree, true);
1723
1724 __map_subgraph(g, sg, first, color);
1725
1726 return sg;
1727 }
1728
1749 template <AlephGraph GT>
1750 std::tuple<GT, DynList<typename GT::Arc*>>
1752 {
1753 GT cut_graph;
1755
1756 for (auto it = cut_node_list.get_it(); it.has_curr(); it.next_ne())
1757 {
1758 auto gp = it.get_curr();
1759
1761
1762 std::unique_ptr<typename GT::Node> tp_auto(new typename GT::Node(gp));
1763 cut_graph.insert_node(tp_auto.get());
1764 GT::map_nodes(gp, tp_auto.release());
1765 }
1766
1767 // cut_graph contains cut-to-cut arcs; cross_arc_list collects cut-to-noncut arcs.
1768 for (auto it = g.get_arc_it(); it.has_curr(); it.next_ne())
1769 {
1770 auto garc = it.get_current_arc_ne();
1772 {
1773 cross_arc_list.append(garc);
1774 continue;
1775 }
1776
1778 continue;
1779
1780 auto src = mapped_node<GT>(g.get_src_node(garc));
1781 auto tgt = mapped_node<GT>(g.get_tgt_node(garc));
1782
1783 assert(src != nullptr and tgt != nullptr);
1784
1785 auto arc = cut_graph.insert_arc(src, tgt, garc->get_info());
1786 GT::map_arcs(garc, arc);
1787 }
1788
1789 return { cut_graph, cross_arc_list };
1790 }
1791
1792
1802 template <class GT, class Distance>
1804 {
1806
1808
1809 bool operator () (typename GT::Arc * a1, typename GT::Arc * a2) const
1810 {
1811 return dist(a1) < dist(a2);
1812 }
1813 };
1814
1815
1833 template <AlephGraph GT>
1835 {
1837 << "invert_digraph() requires a digraph (or a graph temporarily treated as a digraph)";
1838
1839 g.reset_nodes();
1840 g.reset_arcs();
1841 GT gi;
1842
1843 // Copy all nodes first so isolated vertices are preserved.
1844 for (auto it = g.get_node_it(); it.has_curr(); it.next_ne())
1845 {
1846 auto gp = it.get_curr();
1847 auto ip = gi.insert_node(gp->get_info());
1849 }
1850
1851 for (auto it = g.get_arc_it(); it.has_curr(); it.next_ne())
1852 {
1853 auto arc = it.get_curr();
1854
1855 auto ssrc = g.get_src_node(arc);
1856 auto stgt = g.get_tgt_node(arc);
1857
1858 auto rsrc = mapped_node<GT>(ssrc);
1859 auto rtgt = mapped_node<GT>(stgt);
1860
1861 assert(rsrc != nullptr and rtgt != nullptr);
1862
1863 typename GT::Arc * ai = gi.insert_arc(rtgt, rsrc, arc->get_info());
1864 GT::map_arcs(arc, ai);
1865 }
1866
1867 assert(g.get_num_arcs() == gi.get_num_arcs() and
1868 g.get_num_nodes() == gi.get_num_nodes());
1869
1870 return gi;
1871 }
1872
1873
1883 template <AlephGraph GT, ArcFilter<GT> SA = Dft_Show_Arc<GT>>
1885 {
1886 SA sa;
1887
1888 public:
1889
1891 Invert_Digraph(SA __sa) : sa(__sa) { /* empty */ }
1892
1900 GT operator () (const GT & g) const
1901 {
1903 << "Invert_Digraph requires a digraph (or a graph temporarily treated as a digraph)";
1904
1905 g.reset_nodes();
1906 g.reset_arcs();
1907 GT gi;
1908
1909 // Copy all nodes first so isolated vertices are preserved.
1910 for (auto it = g.get_node_it(); it.has_curr(); it.next_ne())
1911 {
1912 auto gp = it.get_curr();
1913 auto ip = gi.insert_node(gp->get_info());
1915 }
1916
1917 for (Arc_Iterator<GT, SA> it(g, sa); it.has_curr(); it.next_ne())
1918 {
1919 auto arc = it.get_curr();
1920
1921 auto ssrc = g.get_src_node(arc);
1922 auto stgt = g.get_tgt_node(arc);
1923
1924 auto rsrc = mapped_node<GT>(ssrc);
1925 auto rtgt = mapped_node<GT>(stgt);
1926
1927 assert(rsrc != nullptr and rtgt != nullptr);
1928
1929 typename GT::Arc * ai = gi.insert_arc(rtgt, rsrc, arc->get_info());
1930 GT::map_arcs(arc, ai);
1931 }
1932
1933 assert(g.get_num_nodes() == gi.get_num_nodes());
1934
1935 return gi;
1936 }
1937 };
1938
1947 template <class GT>
1949 {
1950 public:
1951
1952 typedef typename GT::Arc_Type Distance_Type;
1953
1955
1957
1958 Distance_Type & operator () (typename GT::Arc * a) const
1959 {
1960 return a->get_info();
1961 }
1962
1963 Distance_Type & operator () (typename GT::Arc * a, typename GT::Node*) const
1964 {
1965 return a->get_info();
1966 }
1967
1968 static void set_zero(typename GT::Arc * a) { a->get_info() = 0; }
1969 };
1970
1971 template <class GT>
1973 std::numeric_limits<typename Dft_Dist<GT>::Distance_Type>::max();
1974
1975 template <class GT>
1977 typename Dft_Dist<GT>::Distance_Type{};
1978
1979
1991 template <AlephGraph GT, ArcFilter<GT> SA = Dft_Show_Arc<GT>>
1992 typename GT::Arc *
1994 typename GT::Node *src, typename GT::Node *tgt,
1995 SA sa = SA()) noexcept
1996 {
1997 assert(src != nullptr and tgt != nullptr);
1998
1999 // For efficiency, iterate over the node with fewer arcs
2000 if (not g.is_digraph() and tgt->num_arcs < src->num_arcs)
2001 std::swap(tgt, src);
2002
2003 typename GT::Arc * first_match = nullptr;
2004 for (Node_Arc_Iterator<GT, SA> it(src, sa); it.has_curr(); it.next_ne())
2005 {
2006 if (it.get_tgt_node_ne() != tgt)
2007 continue;
2008
2009 auto arc = it.get_current_arc_ne();
2010 // Prefer arc marked as spanning tree
2012 return arc;
2013
2014 // Keep first match as fallback
2015 if (first_match == nullptr)
2016 first_match = arc;
2017 }
2018
2019 return first_match; // Return first match if no spanning tree arc found
2020 }
2021
2022 template <AlephGraph GT, ArcDistance<GT> Distance = Dft_Dist<GT>>
2024 get_min_path(typename GT::Node * s, typename GT::Node * end, Path<GT> & path)
2025 {
2026 using Distance_Type = typename Distance::Distance_Type;
2027
2028 ah_invalid_argument_if(s == nullptr or end == nullptr)
2029 << "get_min_path(): s and end must be non-null";
2030
2031 Distance_Type dist{};
2032 path.empty();
2033
2034 if (s == end)
2035 {
2036 path.init(end);
2037 return dist;
2038 }
2039
2040 // Build path from end to start following cookies, collecting arcs
2041 Distance distance;
2043
2044 auto curr = end;
2045 while (curr != s)
2046 {
2047 auto prev = static_cast<typename GT::Node *>(NODE_COOKIE(curr));
2048 ah_domain_error_if(prev == nullptr)
2049 << "get_min_path(): broken cookie chain (nullptr)";
2050
2051 // Find the spanning tree arc between prev and curr
2052 auto arc = search_spanning_tree_arc<GT>(path.get_graph(), prev, curr);
2053 ah_domain_error_if(arc == nullptr)
2054 << "get_min_path(): no arc connecting nodes in path";
2055
2056 node_arc_list.insert(std::make_pair(curr, arc));
2057 dist += distance(arc);
2058 curr = prev;
2059 }
2060
2061 // Now build path from start to end
2062 path.init(s);
2063 for (auto it = node_arc_list.get_it(); it.has_curr(); it.next())
2064 {
2065 auto & [node, arc] = it.get_curr();
2066 (void)node; // suppress warning
2067 path.append(arc);
2068 }
2069
2070 return dist;
2071 }
2072
2089 template <AlephGraph GT,
2093 {
2095 SA sa;
2097
2098 public:
2099
2101 : dist(__dist), sa(__sa)
2102 {
2103 // empty
2104 }
2105
2108 {
2109 sum = typename Distance::Distance_Type{};
2110
2111 // Traverse all arcs and sum their weights
2112 for (Arc_Iterator <GT, SA> it(g, sa); it.has_curr(); it.next_ne())
2113 sum += dist(it.get_current_arc_ne());
2114
2115 return sum;
2116 }
2117
2120 {
2121 return total_cost (g);
2122 }
2123
2126 {
2127 sum = typename Distance::Distance_Type{};
2128 }
2129
2132 {
2133 return sum;
2134 }
2135
2136 bool operator () (typename GT::Arc * a)
2137 {
2138 if (not sa(a))
2139 return true; // skip but keep traversing
2140
2141 sum += dist(a);
2142 return true; // keep traversing
2143 }
2144 };
2145
2146
2147
2148} // end namespace Aleph
2149
2150# endif // TPL_GRAPH_UTILS_H
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_unless(C)
Throws std::domain_error if condition does NOT hold.
Definition ah-errors.H:543
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:527
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
Definition ah-errors.H:644
C++20 concepts for the protocol shared by graph algorithms.
WeightedDigraph::Node Node
WeightedDigraph::Arc Arc
List_Graph< Graph_Node< Node_Info >, Graph_Arc< Arc_Info > > GT
int num_nodes
Definition btreepic.C:410
Stateful breadth-first traversal functor.
Breadth_First_Traversal(SA __sa=SA())
Construct a traversal functor using the arc filter __sa.
size_t operator()(const GT &g, Operation op)
Traverse starting from the first node of the graph.
size_t bft(const GT &g, typename GT::Node *start, Operation &op)
RAII guard that clears graph cookies on destruction.
~Cookie_Guard()
Destructor - clears cookies if guard is still active.
Stateful depth-first traversal functor.
bool __dft(typename GT::Node *node, typename GT::Arc *arc=nullptr)
Depth_First_Traversal(SA __sa=SA())
Construct a traversal functor using the arc filter __sa.
size_t operator()(const GT &g, Operation op=Operation())
Traverse starting from the first node of the graph.
size_t dft(const GT &g, typename GT::Node *start_node, Operation &__op)
Default distance accessor for arc weights.
static const Distance_Type Max_Distance
Distance_Type & operator()(typename GT::Arc *a) const
GT::Arc_Type Distance_Type
static const Distance_Type Zero_Distance
static void set_zero(typename GT::Arc *a)
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.
Doubly-linked list (defined in tpl_dynList.H).
Definition htlist.H:1155
T & append(const T &item)
Definition htlist.H:1271
T & get_last() const
Return the last item of the list.
Definition htlist.H:1363
Generic key-value map implemented on top of a binary search tree.
Pair * search(const Key &key) const noexcept
Collect all keys.
Pair * insert(const Key &key, const Data &data)
Insert a key-value pair.
void next_ne() noexcept
Advances the iterator to the next filtered element (noexcept version).
Functor for computing the transposed digraph, filtering arcs.
Invert_Digraph(SA __sa)
Construct a functor using the arc filter __sa.
GT operator()(const GT &g) const
Compute the transposed graph.
Node * get_first_node() const
Return any node in the graph.
Definition tpl_graph.H:577
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Definition tpl_graph.H:525
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Definition tpl_graph.H:605
typename Arc::Arc_Type Arc_Type
The type of data stored in the arc.
Definition tpl_graph.H:440
Path on a graph.
Definition tpl_graph.H:2772
void insert(Arc *arc)
Insert an arc as the first of a path.
Definition tpl_graph.H:3118
void empty()
Clean the path: all the nodes and arc are removed.
Definition tpl_graph.H:2922
void init(Node *start_node)
Set the first node of a path.
Definition tpl_graph.H:2870
void append(Arc *arc)
Append an arc to the path.
Definition tpl_graph.H:2975
const GT & get_graph() const noexcept
Get a constant reference to the graph.
Definition tpl_graph.H:2844
Compute the total cost (sum of arc weights) of a graph.
Distance::Distance_Type total_cost(GT &g)
Compute the total cost.
Distance::Distance_Type sum
Distance::Distance_Type operator()(GT &g)
Total_Cost(Distance __dist=Distance(), SA __sa=SA())
Distance::Distance_Type value() const noexcept
Return the accumulated value (after using operator()(Arc*)).
void reset() noexcept
Reset the internal accumulator used by operator()(Arc*).
void for_each(Operation &operation)
Traverse all the container and performs an operation on each element.
Definition ah-dry.H:796
ArcInfo & get_info() noexcept
Return a modifiable reference to the arc data.
Definition graph-dry.H:637
size_t num_arcs
data associated to the node. Access it with get_info()
Definition graph-dry.H:496
void reset_bit_nodes(int bit) const noexcept
Reset bit to zero for all the nodes of graph.
Definition graph-dry.H:1088
void reset_arcs() const
Reset all the arcs of graph (the control bits, the state, the counter and the cookie)
Definition graph-dry.H:975
auto get_arc_it() const noexcept
Obtains an iterator to the arc of graph.
Definition graph-dry.H:2908
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:779
Node * get_node() const
Return any node in the graph.
Definition graph-dry.H:756
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:737
void set_bit(Node *node, int bit, int value) const noexcept
Set the control bit of node to value
Definition graph-dry.H:867
bool is_digraph() const noexcept
Return true if the graph this is directed.
Definition graph-dry.H:699
static void map_arcs(A1 *p, A2 *q) noexcept
Map the arcs through their cookies.
Definition graph-dry.H:1074
void reset_counter_nodes() const noexcept
Reset all the counters to zero for all the nodes of graph.
Definition graph-dry.H:1112
void reset_bit_arcs(int bit) const noexcept
Reset bit to zero for all the arcs of graph.
Definition graph-dry.H:1094
constexpr size_t get_num_arcs() const noexcept
Definition graph-dry.H:826
void reset_counter_arcs() const noexcept
Reset all the counters to zero for all the arcs of graph.
Definition graph-dry.H:1118
void reset_nodes() const
Reset all the nodes of graph (the control bits, the state, the counter and the cookie)
Definition graph-dry.H:968
auto get_node_it() const noexcept
Obtains an iterator to the nodes of graph.
Definition graph-dry.H:2886
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:785
static void map_nodes(N1 *p, N2 *q) noexcept
Map the nodes through their cookies.
Definition graph-dry.H:1043
__gmp_expr< typename __gmp_resolve_expr< T, V >::value_type, __gmp_binary_expr< __gmp_expr< T, U >, __gmp_expr< V, W >, __gmp_max_function > > max(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4121
DynArray< Graph::Node * > nodes
Definition graphpic.C:406
DynArray< Graph::Arc * > arcs
Definition graphpic.C:408
size_t depth_first_traversal(const GT &g, typename GT::Node *start_node, bool(*visit)(const GT &g, typename GT::Node *, typename GT::Arc *))
Depth-first traversal starting from a given node.
GT build_spanning_tree(const DynArray< typename GT::Arc * > &arcs)
Build a graph from a list of arcs (typically a spanning tree).
#define ARC_COOKIE(p)
Return the arc cookie
bool has_cycle(const GT &g)
Return true if an undirected graph has at least one cycle.
#define NODE_COUNTER(p)
Get the counter of a node.
DynList< GT > inconnected_components(const GT &g)
Forward declaration for inconnected_components().
bool test_for_cycle(const GT &g, typename GT::Node *src)
Search for a cycle reachable from a given node.
GT find_breadth_first_spanning_tree(GT &g, typename GT::Node *gp)
Build a breadth-first spanning tree (mapped to the original graph).
#define ARC_COUNTER(p)
Return the counter of arc p.
#define IS_NODE_VISITED(p, bit)
Determine whether the control bit is set or not to one.
GT invert_digraph(const GT &g)
Compute the transpose (arc-reversed) digraph.
DynList< typename GT::Node * > compute_cut_nodes(const GT &g, typename GT::Node *start)
Compute articulation points (cut vertices) of an undirected graph.
bool test_connectivity(const GT &g)
Connectivity test for undirected graphs.
#define ARC_BITS(p)
Return the control bits of arc p.
#define NODE_COOKIE(p)
Return the node cookie
long paint_subgraphs(const GT &g, const DynList< typename GT::Node * > &cut_node_list)
Paint connected blocks around articulation points.
Path< GT > find_path_breadth_first(const GT &g, typename GT::Node *start, typename GT::Node *end)
Breadth-first search of a (shortest-by-edges) path between two nodes.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
bool test_for_path(const GT &g, typename GT::Node *start_node, typename GT::Node *end_node)
Return true if there is a path between two nodes.
size_t breadth_first_traversal(const GT &g, typename GT::Node *start, bool(*visit)(const GT &, typename GT::Node *, typename GT::Arc *))
Breadth-first traversal starting from a given node.
void build_subgraph(const GT &g, GT &sg, typename GT::Node *g_src, size_t &node_count)
Forward declaration for build_subgraph().
#define IS_ARC_VISITED(p, bit)
Determine whether the bit field is or not set to one.
GT find_depth_first_spanning_tree(const GT &g, typename GT::Node *gnode)
Build a depth-first spanning tree (mapped to the original graph).
bool is_graph_acyclique(const GT &g, typename GT::Node *start_node)
Return true if an undirected graph is acyclic.
std::tuple< GT, DynList< typename GT::Arc * > > map_cut_graph(const GT &g, const DynList< typename GT::Node * > &cut_node_list)
Extract the cut graph and cross-arc list.
#define NODE_BITS(p)
Get the control bits of a node.
GT map_subgraph(const GT &g, const long color)
Extract a mapped subgraph containing a given color.
@ Depth_First
Definition aleph-graph.H:73
@ Build_Subtree
Definition aleph-graph.H:80
@ Breadth_First
Definition aleph-graph.H:74
@ Test_Cycle
Definition aleph-graph.H:75
@ Spanning_Tree
Definition aleph-graph.H:79
@ Find_Path
Definition aleph-graph.H:76
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
static bool __test_cycle(const GT &g, typename GT::Node *, typename GT::Node *)
Internal helper used by test_for_cycle().
const long Cross_Arc
Special marker for arcs connecting a cut node to a non-cut block.
static void paint_arc(typename GT::Arc *a, const long &color)
Set the arc color (stored in ARC_COUNTER).
GT::Arc * search_spanning_tree_arc(const GT &g, typename GT::Node *src, typename GT::Node *tgt, SA sa=SA()) noexcept
Helper to find the spanning tree arc between two nodes in a multigraph.
static long & low(typename GT::Node *p)
Internal helper: low-link value stored directly in NODE_COOKIE(p).
static bool is_node_painted(typename GT::Node *p)
Return true if the node has a positive color.
static const long & get_color(typename GT::Node *p)
Return the node color (stored in NODE_COUNTER).
and
Check uniqueness with explicit hash + equality functors.
static void __paint_subgraph(const GT &g, typename GT::Node *p, long current_color)
Internal DFS that paints a non-cut block with current_color.
static bool __test_for_path(const GT &g, typename GT::Node *curr_node, typename GT::Node *end_node)
Internal recursive DFS used by test_for_path().
static void paint_node(typename GT::Node *p, const long &color)
Set the node color (stored in NODE_COUNTER).
static bool is_a_cross_arc(typename GT::Arc *a)
Return true if the arc is marked as a cross-arc by paint_subgraphs().
Distance::Distance_Type get_min_path(typename GT::Node *s, typename GT::Node *end, Path< GT > &path)
static bool is_arc_painted(typename GT::Arc *arc)
Return true if the arc has a positive color.
static long & df(typename GT::Node *p)
Internal helper: DFS discovery time stored in NODE_COUNTER(p).
static bool is_an_cut_arc(typename GT::Arc *a)
Return true if the arc is marked as a cut-arc (between cut nodes).
static void __paint_from_cut_node(const GT &g, typename GT::Node *p, long &current_color)
Internal step that paints all blocks adjacent to a cut node.
static bool __is_graph_acyclique(const GT &g, typename GT::Node *curr_node)
Internal DFS used by is_graph_acyclique().
static void __map_subgraph(const GT &g, GT &sg, typename GT::Node *gsrc, const long color)
Internal recursive step used by map_subgraph().
static void __compute_cut_nodes(const GT &g, DynList< typename GT::Node * > &list, typename GT::Node *p, typename GT::Arc *a, long &curr_df)
Internal DFS step used by compute_cut_nodes().
static bool __depth_first_traversal(const GT &g, typename GT::Node *node, typename GT::Arc *arc, bool(*visit)(const GT &g, typename GT::Node *, typename GT::Arc *), size_t &count)
Internal recursive DFS used by depth_first_traversal().
static bool is_a_cut_node(typename GT::Node *p)
Return true if the node is marked as an articulation point.
static bool __find_depth_first_spanning_tree(const GT &g, typename GT::Node *gnode, typename GT::Arc *garc, GT &tree, typename GT::Node *tnode)
Internal recursive DFS used by find_depth_first_spanning_tree().
static long & color(typename GT::Node *p)
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
Filtered iterator on all the arcs of a graph.
Definition tpl_graph.H:1165
Default visit operation for traversals (never stops).
bool operator()(const GT &, typename GT::Node *, typename GT::Arc *)
Always continues the traversal (never stops early).
Default filter for filtered iterators on arcs.
Definition tpl_graph.H:1001
Comparison functor for arc weights/distances.
Distance_Compare(Distance __dist=Distance())
bool operator()(typename GT::Arc *a1, typename GT::Arc *a2) const
Filtered iterator of adjacent arcs of a node.
Definition tpl_graph.H:1120
Distance accessor.
static long counter
Definition test-splice.C:40
Array-based graph implementation.
Dynamic queue implementation based on linked lists.