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
48# include <cassert>
49# include <cstddef>
50# include <limits>
51# include <memory>
52# include <tuple>
53# include <utility>
54# include <vector>
55# include <tpl_agraph.H>
56# include <tpl_dynListQueue.H>
57# include <ah-errors.H>
58
59using namespace Aleph;
60
61namespace Aleph {
62
75 template <class GT> inline static bool
76 __depth_first_traversal(const GT & g, typename GT::Node * node,
77 typename GT::Arc * arc,
78 bool (*visit)(const GT & g, typename GT::Node *,
79 typename GT::Arc *),
80 size_t & count);
81
105 template <class GT> inline size_t
107 bool (*visit)(const GT & g, typename GT::Node *,
108 typename GT::Arc *))
109 {
112 size_t counter = 0;
113
114 __depth_first_traversal(g, start_node, nullptr, visit, counter);
115
116 return counter;
117 }
118
120 template <class GT> inline
121 size_t depth_first_traversal(const GT & g,
122 bool (*visit)(const GT &, typename GT::Node *,
123 typename GT::Arc *))
124 {
126 }
127
132 template <class GT>
134 {
136 bool operator () (const GT &, typename GT::Node *, typename GT::Arc *)
137 {
138 return false;
139 }
140 };
141
162 template <class GT,
164 class SA = Dft_Show_Arc<GT>>
166 {
167 Operation * op_ptr = nullptr;
169 size_t count = 0;
170 const GT * g_ptr = nullptr;
171
172 private:
173
174 bool __dft(typename GT::Node * node, typename GT::Arc * arc = nullptr)
175 {
176 if (IS_NODE_VISITED(node, Depth_First))
177 return false;
178
179 NODE_BITS(node).set_bit(Depth_First, true);
180 count++;
181
182 if ((*op_ptr)(*g_ptr, node, arc))
183 return true;
184
185 if (count == g_ptr->get_num_nodes())
186 return true;
187
188 // Recursively traverse arcs incident to `node`.
189 for (Node_Arc_Iterator<GT, SA> it(node, sa); it.has_curr(); it.next_ne())
190 {
191 auto arc = it.get_current_arc_ne();
192 if (IS_ARC_VISITED(arc, Depth_First))
193 continue;
194
195 ARC_BITS(arc).set_bit(Depth_First, true);
196 if (__dft (it.get_tgt_node_ne(), arc))
197 return true;
198 }
199
200 return false;
201 }
202
203 size_t dft(const GT & g, typename GT::Node * start_node, Operation & __op)
204 {
205 op_ptr = &__op;
206 g_ptr = &g;
207
210
211 count = 0;
212
214
215 return count;
216 }
217
218 public:
219
221 Depth_First_Traversal(SA __sa = SA()) : sa(__sa) { /* empty */ }
222
237 size_t operator () (const GT & g, Operation op = Operation())
238 {
239 return dft(g, g.get_first_node(), op);
240 }
241
257 size_t operator () (const GT & g, typename GT::Node * sn,
258 Operation op = Operation())
259 {
260 return dft(g, sn, op);
261 }
262 };
263
264
265 template <class GT> inline static bool
266 __depth_first_traversal(const GT & g, typename GT::Node * node,
267 typename GT::Arc * arc,
268 bool (*visit)(const GT & g, typename GT::Node *,
269 typename GT::Arc *),
270 size_t & count)
271 {
272 if (IS_NODE_VISITED(node, Depth_First))
273 return false;
274
275 NODE_BITS(node).set_bit(Depth_First, true); // mark node visited
276 count++;
277
278 if (visit != nullptr) // invoke callback if provided
279 if ((*visit)(g, node, arc))
280 return true;
281
282 if (count == g.get_num_nodes()) // all nodes discovered?
283 return true;
284
285 for (auto it = g.get_arc_it(node); it.has_curr(); it.next_ne())
286 {
287 auto arc = it.get_current_arc_ne();
288 if (IS_ARC_VISITED(arc, Depth_First))
289 continue;
290
291 ARC_BITS(arc).set_bit(Depth_First, true); // mark arc visited
292 if (__depth_first_traversal(g, it.get_tgt_node_ne(), arc, visit, count))
293 return true;
294 }
295
296 return false; // keep exploring
297 }
298
299
325 template <class GT> inline size_t
326 breadth_first_traversal(const GT & g, typename GT::Node * start,
327 bool (*visit)(const GT &, typename GT::Node *,
328 typename GT::Arc *) )
329 {
333
334 for (auto it = g.get_arc_it(start); it.has_curr(); it.next_ne())
335 q.put(it.get_current_arc_ne());
336
337 NODE_BITS(start).set_bit(Breadth_First, true);
338 size_t node_counter = 1;
339
340 if (visit != nullptr)
341 if ((*visit)(g, start, nullptr))
342 return 1;
343
344 while (not q.is_empty() and node_counter < g.get_num_nodes())
345 {
346 auto arc = q.get();
347 ARC_BITS(arc).set_bit(Breadth_First, true);
348
349 auto src = g.get_src_node(arc);
350 auto tgt = g.get_tgt_node(arc);
353 continue;
354
355 auto visit_node = IS_NODE_VISITED(src, Breadth_First) ? tgt : src;
356 if (visit != nullptr)
357 if ((*visit)(g, visit_node, arc))
358 break;
359
360 NODE_BITS(visit_node).set_bit(Breadth_First, true);
361 node_counter++;
362
363 for (auto it = g.get_arc_it(visit_node); it.has_curr(); it.next_ne())
364 {
365 auto curr_arc = it.get_current_arc_ne();
367 continue;
368
371 continue; // both endpoints already visited
372
373 q.put(curr_arc);
374 }
375 }
376
377 return node_counter;
378 }
379
381 template <class GT> inline size_t
383 bool (*visit)(const GT &, typename GT::Node *,
384 typename GT::Arc *))
385 {
387 }
388
389
411 template <class GT,
413 class SA = Dft_Show_Arc<GT>>
415 {
417 size_t count = 0;
418
419 size_t bft(const GT & g, typename GT::Node * start, Operation & op)
420 {
423 DynListQueue<typename GT::Arc*> q; // pending arcs queue
424
425 for (Node_Arc_Iterator<GT, SA> it(start, sa); it.has_curr(); it.next_ne())
426 q.put(it.get_current_arc_ne());
427
428 NODE_BITS(start).set_bit(Breadth_First, true);
429 count = 1;
430
431 if (op (g, start, nullptr))
432 return 1;
433
434 while (not q.is_empty() and count < g.get_num_nodes())
435 {
436 auto arc = q.get();
437 ARC_BITS(arc).set_bit(Breadth_First, true);
438
439 auto src = g.get_src_node(arc);
440 auto tgt = g.get_tgt_node(arc);
441
444 continue;
445
446 auto curr = IS_NODE_VISITED(src, Breadth_First) ? tgt : src;
447 if (op (g, curr, arc))
448 break;
449
450 NODE_BITS(curr).set_bit(Breadth_First, true);
451 count++;
452
453 for (Node_Arc_Iterator<GT, SA> it(curr, sa); it.has_curr(); it.next_ne())
454 {
455 auto curr_arc = it.get_current_arc_ne();
457 continue;
458
461 continue;
462
463 q.put(curr_arc);
464 }
465 }
466
467 return count;
468 }
469
470 public:
471
473 Breadth_First_Traversal(SA __sa = SA()) : sa(__sa) { /* empty */ }
474
489 size_t operator () (const GT & g, Operation op)
490 {
491 return bft (g, g.get_first_node(), op);
492 }
493
509 size_t operator () (const GT & g, typename GT::Node * p,
510 Operation && op = Operation())
511 {
512 return bft(g, p, op);
513 }
514
525 size_t operator () (const GT & g, typename GT::Node * p, Operation & op)
526 {
527 return bft(g, p, op);
528 }
529 };
530
553 template <class GT> inline
554 Path<GT> find_path_breadth_first(const GT & g, typename GT::Node * start,
555 typename GT::Node * end)
556 {
557 ah_invalid_argument_if(start == nullptr or end == nullptr)
558 << "find_path_breadth_first(): start and end must be non-null";
559
560 if (start == end)
561 return Path<GT>(g, start);
562
563 g.reset_nodes();
564 g.reset_arcs();
565
567
568 for (auto it = g.get_arc_it(start); it.has_curr(); it.next_ne())
569 q.put(it.get_current_arc_ne());
570
571 NODE_BITS(start).set_bit(Find_Path, true);
572
573 bool path_found = false;
574
575 while (not q.is_empty())
576 {
577 auto arc = q.get();
578 auto src = g.get_src_node(arc);
579 auto tgt = g.get_tgt_node(arc);
580
582 continue;
583
584 if (IS_NODE_VISITED(tgt, Find_Path))
585 std::swap(src, tgt);
586
587 ARC_BITS(arc).set_bit(Find_Path, true);
588 NODE_BITS(tgt).set_bit(Find_Path, true);
589 NODE_COOKIE(tgt) = src;
590
591 if (tgt == end)
592 {
593 path_found = true;
594 break;
595 }
596
597 for (auto it = g.get_arc_it(tgt); it.has_curr(); it.next_ne())
598 {
599 auto a = it.get_current_arc_ne();
601 continue;
602
605 continue;
606
607 q.put(a);
608 }
609 }
610
611 if (not path_found)
612 return Path<GT>(g);
613
614 q.empty(); // free queue memory for eventually saving the required for path
615
616 Path<GT> path(g, end);
617 auto p = end;
618 while (p != start)
619 {
620 p = (typename GT::Node *) NODE_COOKIE(p);
621 path.insert(p);
622 }
623
624 return path;
625 }
626
627
640 template <class GT> inline
641 bool test_connectivity(const GT & g)
642 {
644 << "test_connectivity() does not work on digraphs";
645
646 const auto num_nodes = g.get_num_nodes();
647 if (num_nodes == 0)
648 return false;
649
650 if (g.get_num_arcs() + 1 < num_nodes)
651 return false;
652
653 return depth_first_traversal<GT>(g, nullptr) == num_nodes;
654 }
655
656
658 template <class GT> inline static
659 bool __test_cycle(const GT & g, typename GT::Node *, typename GT::Node *);
660
661
678 template <class GT> inline
679 bool test_for_cycle(const GT & g, typename GT::Node * src)
680 {
681 ah_invalid_argument_if(src == nullptr)
682 << "test_for_cycle(): src must be non-null";
683
686 for (auto it = g.get_arc_it(src); it.has_curr(); it.next_ne())
687 {
688 auto arc = it.get_curr();
689 if (IS_ARC_VISITED(arc, Test_Cycle))
690 continue;
691
692 ARC_BITS(arc).set_bit(Test_Cycle, true);
693 if (__test_cycle(g, src, it.get_tgt_node_ne()))
694 return true;
695 }
696
697 return false;
698 }
699
700
701 template <class GT> inline static bool
702 __test_cycle(const GT & g, typename GT::Node * src, typename GT::Node * curr)
703 {
704 if (src == curr)
705 return true; // detected cycle
706
707 if (IS_NODE_VISITED(curr, Test_Cycle))
708 return false;
709
710 NODE_BITS(curr).set_bit(Test_Cycle, true);
711
712 for (auto it = g.get_arc_it(curr); it.has_curr(); it.next_ne())
713 {
714 auto arc = it.get_curr();
715 if (IS_ARC_VISITED(arc, Test_Cycle))
716 continue;
717
718 ARC_BITS(arc).set_bit(Test_Cycle, true);
719 if (__test_cycle(g, src, it.get_tgt_node_ne()))
720 return true;
721 }
722
723 return false;
724 }
725
727 template <class GT> inline static
728 bool __is_graph_acyclique(const GT & g, typename GT::Node * curr_node)
729 {
731 return false;
732
733 NODE_BITS(curr_node).set_bit(Test_Cycle, true);
734
735 for (auto it = g.get_arc_it(curr_node); it.has_curr(); it.next_ne())
736 {
737 auto arc = it.get_current_arc_ne();
738 if (IS_ARC_VISITED(arc, Test_Cycle))
739 continue;
740
741 ARC_BITS(arc).set_bit(Test_Cycle, true);
742
743 if (not __is_graph_acyclique(g, it.get_tgt_node_ne()))
744 return false;
745 }
746 // All outgoing arcs explored without detecting a back edge.
747 return true;
748 }
749
750
769 template <class GT> inline
770 bool is_graph_acyclique(const GT & g, typename GT::Node * start_node)
771 {
773 << "is_graph_acyclique() does not work for digraphs";
774
775 const auto num_nodes = g.get_num_nodes();
776 if (num_nodes == 0)
777 return true;
778
780 << "is_graph_acyclique(): start_node must be non-null";
781
782 if (num_nodes == 1)
783 return true;
784
785 if (g.get_num_arcs() >= num_nodes)
786 return false;
787
790
792 }
793
809 template <class GT> inline
810 bool is_graph_acyclique(const GT & g)
811 {
813 << "is_graph_acyclique() does not work for digraphs";
814
815 const auto num_nodes = g.get_num_nodes();
816 if (num_nodes == 0)
817 return true;
818
819 if (num_nodes == 1)
820 return true;
821
822 if (g.get_num_arcs() >= num_nodes)
823 return false;
824
827
828 for (auto it = g.get_node_it(); it.has_curr(); it.next_ne())
829 {
830 auto current_node = it.get_current_node_ne();
831 if (IS_NODE_VISITED(current_node, Test_Cycle))
832 continue;
833
834 if (not __is_graph_acyclique(g, current_node))
835 return false;
836 }
837
838 return true;
839 }
840
841
850 template <class GT>
851 inline bool has_cycle(const GT & g)
852 {
853 return not is_graph_acyclique(g);
854 }
855
856
872 template <class GT> inline
873 bool test_for_path(const GT & g, typename GT::Node * start_node,
874 typename GT::Node * end_node)
875 {
876 ah_invalid_argument_if(start_node == nullptr or end_node == nullptr)
877 << "test_for_path(): start_node and end_node must be non-null";
878
879 if (start_node == end_node)
880 return true;
881
884
885 for (auto it = g.get_arc_it(start_node); it.has_curr(); it.next_ne())
886 {
887 auto arc = it.get_current_arc_ne();
888 ARC_BITS(arc).set_bit(Find_Path, true);
889 if (__test_for_path(g, it.get_tgt_node_ne(), end_node))
890 return true;
891 }
892
893 return false;
894 }
895
896
898 template <class GT> inline static
899 bool __test_for_path(const GT & g, typename GT::Node * curr_node,
900 typename GT::Node * end_node)
901 {
902 if (curr_node == end_node)
903 return true;
904
906 return false;
907
908 NODE_BITS(curr_node).set_bit(Find_Path, true);
909
910 for (auto it = g.get_arc_it(curr_node); it.has_curr(); it.next_ne())
911 {
912 auto arc = it.get_current_arc_ne();
913 if (IS_ARC_VISITED(arc, Find_Path))
914 continue;
915
916 ARC_BITS(arc).set_bit(Find_Path, true);
917 if (__test_for_path(g, it.get_tgt_node_ne(), end_node))
918 return true;
919 }
920
921 return false;
922 }
923
925 template <class GT> inline
927
929 template <class GT> inline
930 void build_subgraph(const GT & g, GT & sg,
931 typename GT::Node * g_src, size_t & node_count);
932
933
952 template <class GT> inline
954 {
955 g.reset_nodes();
956 g.reset_arcs();
957
958 DynList<GT> list;
959 size_t count = 0; // visited node counter
960 for (auto it = g.get_node_it(); count < g.get_num_nodes() and it.has_curr();
961 it.next_ne())
962 {
963 auto curr = it.get_current_node_ne();
964 if (IS_NODE_VISITED(curr, Build_Subtree))
965 continue;
966
967 list.append(GT());
968 GT & subgraph = list.get_last();
969 build_subgraph(g, subgraph, curr, count);
970 }
971
972 return list;
973 }
974
975
996 template <class GT> inline
997 void build_subgraph(const GT & g, GT & sg,
998 typename GT::Node * g_src, size_t & node_count)
999 {
1001 return;
1002
1003 NODE_BITS(g_src).set_bit(Build_Subtree, true);
1004 ++node_count;
1005
1007 if (sg_src == nullptr) // not mapped yet
1008 {
1009 sg_src = sg.insert_node(g_src->get_info());
1011 }
1012
1013 for (auto it = g.get_arc_it(g_src);
1014 node_count < g.get_num_nodes() and it.has_curr(); it.next_ne())
1015 {
1016 auto arc = it.get_current_arc_ne();
1017 if (IS_ARC_VISITED(arc, Build_Subtree))
1018 continue;
1019
1020 ARC_BITS(arc).set_bit(Build_Subtree, true);
1021 auto g_tgt = it.get_tgt_node_ne();
1023 if (sg_tgt == nullptr) // sg_tgt mapped in sg?
1024 {
1025 sg_tgt = sg.insert_node(g_tgt->get_info());
1027 }
1028
1029 auto sg_arc = sg.insert_arc(sg_src, sg_tgt, arc->get_info());
1030 GT::map_arcs(arc, sg_arc);
1031
1032 build_subgraph(g, sg, g_tgt, node_count);
1033 }
1034 }
1035
1036
1038 template <class GT> inline static
1039 bool __find_depth_first_spanning_tree(const GT & g,
1040 typename GT::Node * gnode,
1041 typename GT::Arc * garc,
1042 GT & tree,
1043 typename GT::Node * tnode);
1044
1064 template <class GT> inline
1066 {
1067 g.reset_nodes();
1068 g.reset_arcs();
1069
1070 GT tree;
1071
1073
1074 auto tnode = tree.insert_node(gnode->get_info());
1076
1077 for (auto it = g.get_arc_it(gnode); it.has_curr(); it.next_ne())
1078 {
1079 auto arc = it.get_current_arc_ne();
1080 if (IS_ARC_VISITED(arc, Spanning_Tree))
1081 continue;
1082
1083 auto arc_tgt_node = it.get_tgt_node_ne();
1085 continue;
1086
1088 return tree;
1089 }
1090
1091 return tree;
1092 }
1093
1095 template <class GT> inline
1097 {
1099 }
1100
1101
1102 template <class GT> inline static
1104 typename GT::Arc * garc,
1105 GT & tree, typename GT::Node * tnode)
1106 {
1107 NODE_BITS(gnode).set_bit(Spanning_Tree, true);
1108 ARC_BITS(garc).set_bit(Spanning_Tree, true);
1109
1110 auto tree_tgt_node = tree.insert_node(gnode->get_info());
1112
1113 auto tarc = tree.insert_arc(tnode, tree_tgt_node, garc->get_info());
1115
1117 if (tree.get_num_nodes() == g.get_num_nodes())
1118 return true;
1119
1120 assert(tree.get_num_nodes() > tree.get_num_arcs()); // tree invariant
1121
1122 for (auto it = g.get_arc_it(gnode); it.has_curr(); it.next_ne())
1123 {
1124 auto arc = it.get_current_arc_ne();
1125 if (IS_ARC_VISITED(arc, Spanning_Tree))
1126 continue;
1127
1128 auto arc_tgt_node = it.get_tgt_node_ne();
1130 continue;
1131
1133 return true; // spanning tree completed
1134 }
1135
1136 return false;
1137 }
1138
1157 template <class GT> inline
1159 {
1162
1163 GT tree;
1164
1165 std::unique_ptr<typename GT::Node> tp_auto(new typename GT::Node(gp));
1166 tree.insert_node(tp_auto.get());
1167 GT::map_nodes(gp, tp_auto.release());
1168 NODE_BITS(gp).set_bit(Spanning_Tree, true);
1169
1171 for (auto it = g.get_arc_it(gp); it.has_curr(); it.next_ne())
1172 q.put(it.get_curr());
1173
1174 while (not q.is_empty())
1175 {
1176 auto garc = q.get();
1177 ARC_BITS(garc).set_bit(Spanning_Tree, true);
1178 auto gsrc = g.get_src_node(garc);
1179 auto gtgt = g.get_tgt_node(garc);
1180
1183 continue;
1184
1185 if (IS_NODE_VISITED(gtgt, Spanning_Tree)) // gtgt visited?
1186 std::swap(gsrc, gtgt); // make gsrc the visited endpoint
1187
1188 auto tsrc = mapped_node<GT>(gsrc);
1189 NODE_BITS(gtgt).set_bit(Spanning_Tree, true);
1190
1191 // Create and map the new tree node.
1192 std::unique_ptr<typename GT::Node> ttgt_auto(new typename GT::Node(gtgt));
1193 tree.insert_node(ttgt_auto.get());
1194 auto ttgt = ttgt_auto.release();
1196
1197 // Insert and map the new tree arc.
1198 auto tarc = tree.insert_arc(tsrc, ttgt, garc->get_info());
1200 if (tree.get_num_nodes() == g.get_num_nodes())
1201 break;
1202
1203 // Enqueue arcs incident to the newly visited node.
1204 for (auto it = g.get_arc_it(gtgt); it.has_curr(); it.next_ne())
1205 {
1206 auto current_arc = it.get_current_arc_ne();
1207 if (IS_ARC_VISITED(current_arc, Spanning_Tree))
1208 continue;
1209
1210 if (IS_NODE_VISITED(g.get_src_node(current_arc),Spanning_Tree) and
1212 continue;
1213 q.put(current_arc);
1214 }
1215 }
1216
1217 return tree;
1218 }
1219
1238 template <class GT>
1240 {
1241 using Node = typename GT::Node;
1242 using Arc = typename GT::Arc;
1243
1244 GT ret;
1246 arcs.for_each([&table, &ret] (Arc * ga)
1247 {
1248 if (ga == nullptr)
1249 return;
1250
1251 Node * gsrc = (Node*) ga->src_node;
1252 Node * gtgt = (Node*) ga->tgt_node;
1253
1254 Node * tsrc;
1255 auto * pair_ptr = table.search(gsrc);
1256 if (pair_ptr)
1257 tsrc = pair_ptr->second;
1258 else
1259 {
1260 tsrc = ret.insert_node(gsrc->get_info());
1261 table.insert(gsrc, tsrc);
1263 }
1264
1265 Node * ttgt;
1266 pair_ptr = table.search(gtgt);
1267 if (pair_ptr)
1268 ttgt = pair_ptr->second;
1269 else
1270 {
1271 ttgt = ret.insert_node(gtgt->get_info());
1272 table.insert(gtgt, ttgt);
1274 }
1275
1276 Arc * ta = ret.insert_arc(tsrc, ttgt);
1277 *ta = *ga;
1278 ARC_COOKIE(ta) = ga;
1279 });
1280
1281 return ret;
1282 }
1283
1285 template <class GT> inline static
1286 long & df(typename GT::Node * p)
1287 {
1288 return NODE_COUNTER(p);
1289 }
1290
1293 template <class GT> inline static
1294 long & low(typename GT::Node * p)
1295 {
1296 return reinterpret_cast<long&>(NODE_COOKIE(p));
1297 }
1298
1300 template <class GT> inline static
1301 void __compute_cut_nodes(const GT & g, DynList<typename GT::Node *> & list,
1302 typename GT::Node * p, typename GT::Arc * a,
1303 long & curr_df);
1304
1330 template <class GT>
1332 compute_cut_nodes(const GT & g, typename GT::Node * start)
1333 {
1335
1337 << "compute_cut_nodes() does not work on digraphs";
1338
1339 if (g.get_num_nodes() == 0)
1340 return list;
1341
1342 ah_invalid_argument_if(start == nullptr)
1343 << "compute_cut_nodes(): start must be non-null";
1344
1345 using Node = typename GT::Node;
1346
1347 std::vector<Node*> nodes;
1348 nodes.reserve(g.get_num_nodes());
1349 for (auto it = g.get_node_it(); it.has_curr(); it.next_ne())
1350 nodes.push_back(it.get_curr());
1351
1352 std::vector<long> low_values(nodes.size(), -1);
1353
1354 for (size_t i = 0; i < nodes.size(); ++i)
1355 {
1356 auto p = nodes[i];
1357 NODE_COUNTER(p) = 0;
1358 NODE_BITS(p).reset();
1359 NODE_COOKIE(p) = &low_values[i];
1360 }
1361
1362 struct Cookie_Guard
1363 {
1364 std::vector<Node*> & nodes;
1365
1367 {
1368 for (auto p : nodes)
1369 NODE_COOKIE(p) = nullptr;
1370 }
1372
1373 g.reset_arcs();
1374 long current_df = 0;
1375 NODE_BITS(start).set_bit(Depth_First, true);
1376 low<GT>(start) = df<GT>(start) = current_df++;
1377 int call_counter = 0;
1378
1379 // Traverse arcs incident to `start`.
1380 for (auto it = g.get_arc_it(start);
1381 it.has_curr() and current_df < g.get_num_nodes(); it.next_ne())
1382 {
1383 auto tgt = it.get_tgt_node_ne();
1384 if (IS_NODE_VISITED(tgt, Depth_First))
1385 continue;
1386
1387 auto arc = it.get_current_arc_ne();
1388 if (IS_ARC_VISITED(arc, Depth_First))
1389 continue;
1390
1391 ARC_BITS(arc).set_bit(Depth_First, true);
1392 __compute_cut_nodes(g, list, tgt, arc, current_df);
1393 ++call_counter;
1394 }
1395
1396 // Root is an articulation point iff it has more than one DFS child.
1397 if (call_counter > 1)
1398 {
1399 NODE_BITS(start).set_bit(Cut, true);
1400 list.append(start);
1401 }
1402
1403 return list;
1404 }
1405
1407 template <class GT>
1409 {
1410 return compute_cut_nodes(g, g.get_node());
1411 }
1412
1414 template <class GT> inline static
1416 typename GT::Node * p, typename GT::Arc * a,
1417 long & curr_df)
1418 {
1419 NODE_BITS(p).set_bit(Depth_First, true);
1420 low<GT>(p) = df<GT>(p) = curr_df++;
1421
1422 bool p_is_cut_node = false;
1423 for (auto it = g.get_arc_it(p); it.has_curr(); it.next_ne())
1424 {
1425 auto arc = it.get_current_arc_ne();
1426 if (arc == a)
1427 continue; // parent arc
1428
1429 auto tgt = it.get_tgt_node_ne();
1430 if (IS_NODE_VISITED(tgt, Depth_First))
1431 {
1432 if (not IS_ARC_VISITED(arc, Depth_First))
1433 if (df<GT>(tgt) < low<GT>(p))
1434 low<GT>(p) = df<GT>(tgt);
1435
1436 continue;
1437 }
1438
1439 if (IS_ARC_VISITED(arc, Depth_First))
1440 continue;
1441
1442 ARC_BITS(arc).set_bit(Depth_First, true);
1443
1444 __compute_cut_nodes(g, list, tgt, arc, curr_df);
1445
1446 if (low<GT>(tgt) < low<GT>(p))
1447 low<GT>(p) = low<GT>(tgt);
1448
1449 if (low<GT>(tgt) >= df<GT>(p) and df<GT>(tgt) != 0)
1450 p_is_cut_node = true;
1451 }
1452
1453 if (p_is_cut_node)
1454 {
1455 NODE_BITS(p).set_bit(Cut, true);
1456 list.append(p);
1457 }
1458 }
1459
1464 const long Cross_Arc = -1;
1465
1467 template <class GT> inline static
1468 bool is_a_cross_arc(typename GT::Arc * a)
1469 {
1470 return ARC_COUNTER(a) == Cross_Arc;
1471 }
1472
1474 template <class GT> inline static
1475 bool is_a_cut_node(typename GT::Node * p)
1476 {
1477 return NODE_BITS(p).get_bit(Cut);
1478 }
1479
1481 template <class GT> inline static
1482 bool is_an_cut_arc(typename GT::Arc * a)
1483 {
1484 return ARC_BITS(a).get_bit(Cut);
1485 }
1486
1488 template <class GT> inline static
1489 bool is_node_painted(typename GT::Node * p)
1490 {
1491 return NODE_COUNTER(p) > 0;
1492 }
1493
1495 template <class GT> inline static
1496 bool is_arc_painted(typename GT::Arc * arc)
1497 {
1498 return ARC_COUNTER(arc) > 0;
1499 }
1500
1502 template <class GT> inline static
1503 void paint_node(typename GT::Node * p, const long & color)
1504 {
1505 NODE_COUNTER(p) = color;
1506 }
1507
1509 template <class GT> inline static
1510 void paint_arc(typename GT::Arc * a, const long & color)
1511 {
1512 ARC_COUNTER(a) = color;
1513 }
1514
1516 template <class GT> inline static
1517 const long & get_color(typename GT::Node * p)
1518 {
1519 return NODE_COUNTER(p);
1520 }
1521
1523 template <class GT> inline static
1524 const long & get_color(typename GT::Arc * a)
1525 {
1526 return ARC_COUNTER(a);
1527 }
1528
1530 template <class GT> inline static
1531 void __paint_subgraph(const GT & g, typename GT::Node * p, long current_color)
1532 {
1534
1535 if (is_node_painted <GT> (p))
1536 return;
1537
1539
1540 for (auto it = g.get_arc_it(p); it.has_curr(); it.next_ne())
1541 {
1542 auto arc = it.get_current_arc_ne();
1543 if (is_arc_painted <GT> (arc))
1544 continue;
1545
1546 auto tgt = it.get_tgt_node_ne();
1547 if (is_a_cut_node <GT> (tgt))
1548 continue;
1549
1551
1553 }
1554 }
1555
1557 template <class GT> inline static
1558 void
1559 __paint_from_cut_node(const GT & g, typename GT::Node * p, long & current_color)
1560 {
1562
1563 // Paint each adjacent non-cut block with a new color.
1564 for (auto it = g.get_arc_it(p); it.has_curr(); it.next_ne())
1565 {
1566 auto arc = it.get_current_arc_ne();
1567
1569
1570 auto tgt_node = it.get_tgt_node_ne();
1571 if (is_a_cut_node <GT> (tgt_node)) // cut-to-cut arc
1572 {
1573 ARC_BITS(arc).set_bit(Cut, true);
1574 continue;
1575 }
1576 else
1577 {
1579 if (is_node_painted <GT> (tgt_node))
1580 continue;
1581 }
1582
1583 __paint_subgraph(g, tgt_node, current_color);
1584
1585 ++current_color;
1586
1588 }
1589 }
1590
1626 template <class GT> inline long
1628 {
1631 long current_color = 1;
1632
1633 for (auto it = cut_node_list.get_it(); it.has_curr(); it.next_ne())
1634 __paint_from_cut_node(g, it.get_curr(), current_color);
1635
1636 return current_color;
1637 }
1638
1640 template <class GT> inline static
1641 void __map_subgraph(const GT & g, GT & sg, typename GT::Node * gsrc,
1642 const long color)
1643 {
1645
1646 auto tsrc = mapped_node<GT>(gsrc); // image of gsrc in sg
1647
1648 // Traverse arcs and copy those with the requested color.
1649 for (auto it = g.get_arc_it(gsrc); it.has_curr(); it.next_ne())
1650 {
1651 auto garc = it.get_current_arc_ne();
1653 continue;
1654
1655 ARC_BITS(garc).set_bit(Build_Subtree, true);
1656
1657 auto gtgt = it.get_tgt_node_ne();
1658
1660
1661 typename GT::Node * ttgt = nullptr; // image of gtgt in sg
1664 else
1665 { // gtgt not in sg yet: copy & map it
1666 std::unique_ptr<typename GT::Node> ttgt_auto(new typename GT::Node(gtgt));
1669 NODE_BITS(gtgt).set_bit(Build_Subtree, true);
1670 ttgt = ttgt_auto.release();
1671 }
1672
1673 auto tarc = sg.insert_arc(tsrc, ttgt, garc->get_info());
1675
1676 __map_subgraph(g, sg, gtgt, color);
1677 }
1678 }
1679
1699 template <class GT>
1700 GT map_subgraph(const GT & g, const long color)
1701 {
1704
1705 typename GT::Node * first = nullptr;
1706 for (auto it = g.get_node_it(); it.has_curr(); it.next_ne())
1707 if (get_color <GT> (it.get_current_node_ne()) == color)
1708 {
1709 first = it.get_current_node_ne();
1710 break;
1711 }
1712
1713 ah_domain_error_if(first == nullptr)
1714 << "Color does not exist in the graph";
1715
1716 GT sg;
1717 std::unique_ptr<typename GT::Node> auto_tsrc(new typename GT::Node(first));
1719 GT::map_nodes(first, auto_tsrc.release());
1720 NODE_BITS(first).set_bit(Build_Subtree, true);
1721
1722 __map_subgraph(g, sg, first, color);
1723
1724 return sg;
1725 }
1726
1747 template <class GT>
1748 std::tuple<GT, DynList<typename GT::Arc*>>
1750 {
1751 GT cut_graph;
1753
1754 for (auto it = cut_node_list.get_it(); it.has_curr(); it.next_ne())
1755 {
1756 auto gp = it.get_curr();
1757
1759
1760 std::unique_ptr<typename GT::Node> tp_auto(new typename GT::Node(gp));
1761 cut_graph.insert_node(tp_auto.get());
1762 GT::map_nodes(gp, tp_auto.release());
1763 }
1764
1765 // cut_graph contains cut-to-cut arcs; cross_arc_list collects cut-to-noncut arcs.
1766 for (auto it = g.get_arc_it(); it.has_curr(); it.next_ne())
1767 {
1768 auto garc = it.get_current_arc_ne();
1770 {
1772 continue;
1773 }
1774
1776 continue;
1777
1778 auto src = mapped_node<GT>(g.get_src_node(garc));
1779 auto tgt = mapped_node<GT>(g.get_tgt_node(garc));
1780
1781 assert(src != nullptr and tgt != nullptr);
1782
1783 auto arc = cut_graph.insert_arc(src, tgt, garc->get_info());
1784 GT::map_arcs(garc, arc);
1785 }
1786
1787 return { cut_graph, cross_arc_list };
1788 }
1789
1790
1800 template <class GT, class Distance>
1802 {
1804
1806
1807 bool operator () (typename GT::Arc * a1, typename GT::Arc * a2) const
1808 {
1809 return dist(a1) < dist(a2);
1810 }
1811 };
1812
1813
1831 template <class GT>
1833 {
1835 << "invert_digraph() requires a digraph (or a graph temporarily treated as a digraph)";
1836
1837 g.reset_nodes();
1838 g.reset_arcs();
1839 GT gi;
1840
1841 // Copy all nodes first so isolated vertices are preserved.
1842 for (auto it = g.get_node_it(); it.has_curr(); it.next_ne())
1843 {
1844 auto gp = it.get_curr();
1845 auto ip = gi.insert_node(gp->get_info());
1847 }
1848
1849 for (auto it = g.get_arc_it(); it.has_curr(); it.next_ne())
1850 {
1851 auto arc = it.get_curr();
1852
1853 auto ssrc = g.get_src_node(arc);
1854 auto stgt = g.get_tgt_node(arc);
1855
1856 auto rsrc = mapped_node<GT>(ssrc);
1857 auto rtgt = mapped_node<GT>(stgt);
1858
1859 assert(rsrc != nullptr and rtgt != nullptr);
1860
1861 typename GT::Arc * ai = gi.insert_arc(rtgt, rsrc, arc->get_info());
1862 GT::map_arcs(arc, ai);
1863 }
1864
1865 assert(g.get_num_arcs() == gi.get_num_arcs() and
1866 g.get_num_nodes() == gi.get_num_nodes());
1867
1868 return gi;
1869 }
1870
1871
1881 template <class GT, class SA = Dft_Show_Arc<GT>>
1883 {
1885
1886 public:
1887
1889 Invert_Digraph(SA __sa) : sa(__sa) { /* empty */ }
1890
1898 GT operator () (const GT & g) const
1899 {
1901 << "Invert_Digraph requires a digraph (or a graph temporarily treated as a digraph)";
1902
1903 g.reset_nodes();
1904 g.reset_arcs();
1905 GT gi;
1906
1907 // Copy all nodes first so isolated vertices are preserved.
1908 for (auto it = g.get_node_it(); it.has_curr(); it.next_ne())
1909 {
1910 auto gp = it.get_curr();
1911 auto ip = gi.insert_node(gp->get_info());
1913 }
1914
1915 for (Arc_Iterator<GT, SA> it(g, sa); it.has_curr(); it.next_ne())
1916 {
1917 auto arc = it.get_curr();
1918
1919 auto ssrc = g.get_src_node(arc);
1920 auto stgt = g.get_tgt_node(arc);
1921
1922 auto rsrc = mapped_node<GT>(ssrc);
1923 auto rtgt = mapped_node<GT>(stgt);
1924
1925 assert(rsrc != nullptr and rtgt != nullptr);
1926
1927 typename GT::Arc * ai = gi.insert_arc(rtgt, rsrc, arc->get_info());
1928 GT::map_arcs(arc, ai);
1929 }
1930
1931 assert(g.get_num_nodes() == gi.get_num_nodes());
1932
1933 return gi;
1934 }
1935 };
1936
1945 template <class GT>
1947 {
1948 public:
1949
1950 typedef typename GT::Arc_Type Distance_Type;
1951
1953
1955
1956 Distance_Type & operator () (typename GT::Arc * a) const
1957 {
1958 return a->get_info();
1959 }
1960
1961 Distance_Type & operator () (typename GT::Arc * a, typename GT::Node*) const
1962 {
1963 return a->get_info();
1964 }
1965
1966 static void set_zero(typename GT::Arc * a) { a->get_info() = 0; }
1967 };
1968
1969 template <class GT>
1971 std::numeric_limits<typename Dft_Dist<GT>::Distance_Type>::max();
1972
1973 template <class GT>
1975 typename Dft_Dist<GT>::Distance_Type{};
1976
1977
1989 template <class GT, class SA = Dft_Show_Arc<GT>>
1990 typename GT::Arc *
1992 typename GT::Node *src, typename GT::Node *tgt,
1993 SA sa = SA()) noexcept
1994 {
1995 assert(src != nullptr and tgt != nullptr);
1996
1997 // For efficiency, iterate over the node with fewer arcs
1998 if (not g.is_digraph() and tgt->num_arcs < src->num_arcs)
1999 std::swap(tgt, src);
2000
2001 typename GT::Arc * first_match = nullptr;
2002 for (Node_Arc_Iterator<GT, SA> it(src, sa); it.has_curr(); it.next_ne())
2003 {
2004 if (it.get_tgt_node_ne() != tgt)
2005 continue;
2006
2007 auto arc = it.get_current_arc_ne();
2008 // Prefer arc marked as spanning tree
2010 return arc;
2011
2012 // Keep first match as fallback
2013 if (first_match == nullptr)
2014 first_match = arc;
2015 }
2016
2017 return first_match; // Return first match if no spanning tree arc found
2018 }
2019
2020 template <class GT, class Distance = Dft_Dist<GT>>
2022 get_min_path(typename GT::Node * s, typename GT::Node * end, Path<GT> & path)
2023 {
2024 using Distance_Type = typename Distance::Distance_Type;
2025
2026 ah_invalid_argument_if(s == nullptr or end == nullptr)
2027 << "get_min_path(): s and end must be non-null";
2028
2029 Distance_Type dist{};
2030 path.empty();
2031
2032 if (s == end)
2033 {
2034 path.init(end);
2035 return dist;
2036 }
2037
2038 // Build path from end to start following cookies, collecting arcs
2039 Distance distance;
2041
2042 auto curr = end;
2043 while (curr != s)
2044 {
2045 auto prev = static_cast<typename GT::Node *>(NODE_COOKIE(curr));
2046 ah_domain_error_if(prev == nullptr)
2047 << "get_min_path(): broken cookie chain (nullptr)";
2048
2049 // Find the spanning tree arc between prev and curr
2050 auto arc = search_spanning_tree_arc<GT>(path.get_graph(), prev, curr);
2051 ah_domain_error_if(arc == nullptr)
2052 << "get_min_path(): no arc connecting nodes in path";
2053
2054 node_arc_list.insert(std::make_pair(curr, arc));
2055 dist += distance(arc);
2056 curr = prev;
2057 }
2058
2059 // Now build path from start to end
2060 path.init(s);
2061 for (auto it = node_arc_list.get_it(); it.has_curr(); it.next())
2062 {
2063 auto & [node, arc] = it.get_curr();
2064 (void)node; // suppress warning
2065 path.append(arc);
2066 }
2067
2068 return dist;
2069 }
2070
2087 template <class GT,
2088 class Distance = Dft_Dist<GT>,
2089 class SA = Dft_Show_Arc<GT>>
2091 {
2095
2096 public:
2097
2099 : dist(__dist), sa(__sa)
2100 {
2101 // empty
2102 }
2103
2106 {
2107 sum = typename Distance::Distance_Type{};
2108
2109 // Traverse all arcs and sum their weights
2110 for (Arc_Iterator <GT, SA> it(g, sa); it.has_curr(); it.next_ne())
2111 sum += dist(it.get_current_arc_ne());
2112
2113 return sum;
2114 }
2115
2118 {
2119 return total_cost (g);
2120 }
2121
2124 {
2125 sum = typename Distance::Distance_Type{};
2126 }
2127
2130 {
2131 return sum;
2132 }
2133
2134 bool operator () (typename GT::Arc * a)
2135 {
2136 if (not sa(a))
2137 return true; // skip but keep traversing
2138
2139 sum += dist(a);
2140 return true; // keep traversing
2141 }
2142 };
2143
2144
2145
2146} // end namespace Aleph
2147
2148# 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:538
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
Definition ah-errors.H:639
WeightedDigraph::Node Node
WeightedDigraph::Arc Arc
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.
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & insert(const T &item)
Insert a new item by copy.
Definition htlist.H:1502
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
T & get_last() const
Return the last item of the list.
Definition htlist.H:1663
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:576
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Definition tpl_graph.H:524
Graph_Arc< int > Arc
The node class type.
Definition tpl_graph.H:433
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Definition tpl_graph.H:604
typename Arc::Arc_Type Arc_Type
The type of data stored in the arc.
Definition tpl_graph.H:439
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
void init(Node *start_node)
Set the first node of a path.
Definition tpl_graph.H:2767
void append(Arc *arc)
Append an arc to the path.
Definition tpl_graph.H:2865
const GT & get_graph() const noexcept
Get a constant reference to the graph.
Definition tpl_graph.H:2741
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:685
ArcInfo & get_info() noexcept
Return a modifiable reference to the arc data.
Definition graph-dry.H:595
size_t num_arcs
data associated to the node. Access it with get_info()
Definition graph-dry.H:454
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
auto get_arc_it() const noexcept
Obtains an iterator to the arc of graph.
Definition graph-dry.H:2802
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_node() const
Return any node in the graph.
Definition graph-dry.H:708
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:695
void set_bit(Node *node, int bit, int value) const noexcept
Set the control bit of node to value
Definition graph-dry.H:819
bool is_digraph() const noexcept
Return true if the graph this is directed.
Definition graph-dry.H:657
static void map_arcs(A1 *p, A2 *q) noexcept
Map the arcs through their cookies.
Definition graph-dry.H:1026
void reset_counter_nodes() const noexcept
Reset all the counters to zero for all the nodes of graph.
Definition graph-dry.H:1064
void reset_bit_arcs(int bit) const noexcept
Reset bit to zero for all the arcs of graph.
Definition graph-dry.H:1046
constexpr size_t get_num_arcs() const noexcept
Definition graph-dry.H:778
void reset_counter_arcs() const noexcept
Reset all the counters to zero for all the arcs of graph.
Definition graph-dry.H:1070
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
auto get_node_it() const noexcept
Obtains an iterator to the nodes of graph.
Definition graph-dry.H:2780
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:737
static void map_nodes(N1 *p, N2 *q) noexcept
Map the nodes through their cookies.
Definition graph-dry.H:995
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:190
List_Graph< Graph_Node< int >, Graph_Arc< int > > GT
__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:4110
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.
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).
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)
DynList< T > maps(const C &c, Op op)
Classic map operation.
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:1164
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:1000
Comparison functor for arc weights/distances.
Distance_Compare(Distance __dist=Distance())
bool operator()(typename GT::Arc *a1, typename GT::Arc *a2) const
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
Distance accessor.
Array-based graph implementation.
Dynamic queue implementation based on linked lists.