44# ifndef TPL_GRAPH_UTILS_H
45# define TPL_GRAPH_UTILS_H
77 template <AlephGraph GT>
inline static bool
107 template <AlephGraph GT>
inline size_t
122 template <AlephGraph GT>
inline
164 template <AlephGraph
GT,
193 auto arc = it.get_current_arc_ne();
198 if (
__dft (it.get_tgt_node_ne(), arc))
262 return dft(g, sn, op);
267 template <AlephGraph GT>
inline static bool
280 if (
visit !=
nullptr)
281 if ((*
visit)(g, node, arc))
287 for (
auto it = g.
get_arc_it(node); it.has_curr(); it.next_ne())
289 auto arc = it.get_current_arc_ne();
327 template <AlephGraph GT>
inline size_t
336 for (
auto it = g.
get_arc_it(start); it.has_curr(); it.next_ne())
337 q.
put(it.get_current_arc_ne());
342 if (
visit !=
nullptr)
343 if ((*
visit)(g, start,
nullptr))
358 if (
visit !=
nullptr)
367 auto curr_arc = it.get_current_arc_ne();
383 template <AlephGraph GT>
inline size_t
413 template <AlephGraph
GT,
428 q.
put(it.get_current_arc_ne());
433 if (op (g, start,
nullptr))
449 if (op (g, curr, arc))
457 auto curr_arc = it.get_current_arc_ne();
514 return bft(g, p, op);
529 return bft(g, p, op);
555 template <AlephGraph GT>
inline
560 <<
"find_path_breadth_first(): start and end must be non-null";
570 for (
auto it = g.
get_arc_it(start); it.has_curr(); it.next_ne())
571 q.
put(it.get_current_arc_ne());
599 for (
auto it = g.
get_arc_it(tgt); it.has_curr(); it.next_ne())
601 auto a = it.get_current_arc_ne();
642 template <AlephGraph GT>
inline
646 <<
"test_connectivity() does not work on digraphs";
660 template <AlephGraph GT>
inline static
680 template <AlephGraph GT>
inline
684 <<
"test_for_cycle(): src must be non-null";
688 for (
auto it = g.
get_arc_it(src); it.has_curr(); it.next_ne())
690 auto arc = it.get_curr();
703 template <AlephGraph GT>
inline static bool
714 for (
auto it = g.
get_arc_it(curr); it.has_curr(); it.next_ne())
716 auto arc = it.get_curr();
729 template <AlephGraph GT>
inline static
739 auto arc = it.get_current_arc_ne();
771 template <AlephGraph GT>
inline
775 <<
"is_graph_acyclique() does not work for digraphs";
782 <<
"is_graph_acyclique(): start_node must be non-null";
811 template <AlephGraph GT>
inline
815 <<
"is_graph_acyclique() does not work for digraphs";
830 for (
auto it = g.
get_node_it(); it.has_curr(); it.next_ne())
832 auto current_node = it.get_current_node_ne();
852 template <AlephGraph GT>
874 template <AlephGraph GT>
inline
879 <<
"test_for_path(): start_node and end_node must be non-null";
889 auto arc = it.get_current_arc_ne();
900 template <AlephGraph GT>
inline static
914 auto arc = it.get_current_arc_ne();
927 template <AlephGraph GT>
inline
931 template <AlephGraph GT>
inline
954 template <AlephGraph GT>
inline
965 auto curr = it.get_current_node_ne();
998 template <AlephGraph GT>
inline
1018 auto arc = it.get_current_arc_ne();
1023 auto g_tgt = it.get_tgt_node_ne();
1040 template <AlephGraph GT>
inline static
1066 template <AlephGraph GT>
inline
1081 auto arc = it.get_current_arc_ne();
1097 template <AlephGraph GT>
inline
1104 template <AlephGraph GT>
inline static
1126 auto arc = it.get_current_arc_ne();
1159 template <AlephGraph GT>
inline
1173 for (
auto it = g.
get_arc_it(
gp); it.has_curr(); it.next_ne())
1174 q.
put(it.get_curr());
1208 auto current_arc = it.get_current_arc_ne();
1240 template <AlephGraph GT>
1287 template <AlephGraph GT>
inline static
1295 template <AlephGraph GT>
inline static
1302 template <AlephGraph GT>
inline static
1332 template <AlephGraph GT>
1339 <<
"compute_cut_nodes() does not work on digraphs";
1345 <<
"compute_cut_nodes(): start must be non-null";
1349 std::vector<Node*>
nodes;
1351 for (
auto it = g.
get_node_it(); it.has_curr(); it.next_ne())
1352 nodes.push_back(it.get_curr());
1356 for (
size_t i = 0; i <
nodes.size(); ++i)
1366 std::vector<Node*> &
nodes;
1370 for (
auto p :
nodes)
1385 auto tgt = it.get_tgt_node_ne();
1389 auto arc = it.get_current_arc_ne();
1409 template <AlephGraph GT>
1416 template <AlephGraph GT>
inline static
1425 for (
auto it = g.
get_arc_it(p); it.has_curr(); it.next_ne())
1427 auto arc = it.get_current_arc_ne();
1431 auto tgt = it.get_tgt_node_ne();
1469 template <AlephGraph GT>
inline static
1476 template <AlephGraph GT>
inline static
1483 template <AlephGraph GT>
inline static
1490 template <AlephGraph GT>
inline static
1497 template <AlephGraph GT>
inline static
1504 template <AlephGraph GT>
inline static
1511 template <AlephGraph GT>
inline static
1518 template <AlephGraph GT>
inline static
1525 template <AlephGraph GT>
inline static
1532 template <AlephGraph GT>
inline static
1542 for (
auto it = g.
get_arc_it(p); it.has_curr(); it.next_ne())
1544 auto arc = it.get_current_arc_ne();
1548 auto tgt = it.get_tgt_node_ne();
1559 template <AlephGraph GT>
inline static
1566 for (
auto it = g.
get_arc_it(p); it.has_curr(); it.next_ne())
1568 auto arc = it.get_current_arc_ne();
1572 auto tgt_node = it.get_tgt_node_ne();
1628 template <AlephGraph GT>
inline long
1635 for (
auto it =
cut_node_list.get_it(); it.has_curr(); it.next_ne())
1642 template <AlephGraph GT>
inline static
1653 auto garc = it.get_current_arc_ne();
1659 auto gtgt = it.get_tgt_node_ne();
1701 template <AlephGraph GT>
1707 typename GT::Node * first =
nullptr;
1708 for (
auto it = g.
get_node_it(); it.has_curr(); it.next_ne())
1711 first = it.get_current_node_ne();
1716 <<
"Color does not exist in the graph";
1749 template <AlephGraph GT>
1750 std::tuple<GT, DynList<typename GT::Arc*>>
1756 for (
auto it =
cut_node_list.get_it(); it.has_curr(); it.next_ne())
1758 auto gp = it.get_curr();
1768 for (
auto it = g.
get_arc_it(); it.has_curr(); it.next_ne())
1770 auto garc = it.get_current_arc_ne();
1783 assert(src !=
nullptr and tgt !=
nullptr);
1785 auto arc =
cut_graph.insert_arc(src, tgt,
garc->get_info());
1802 template <
class GT,
class Distance>
1833 template <AlephGraph GT>
1837 <<
"invert_digraph() requires a digraph (or a graph temporarily treated as a digraph)";
1844 for (
auto it = g.
get_node_it(); it.has_curr(); it.next_ne())
1846 auto gp = it.get_curr();
1851 for (
auto it = g.
get_arc_it(); it.has_curr(); it.next_ne())
1853 auto arc = it.get_curr();
1883 template <AlephGraph GT, ArcFilter<GT> SA = Dft_Show_Arc<GT>>
1903 <<
"Invert_Digraph requires a digraph (or a graph temporarily treated as a digraph)";
1910 for (
auto it = g.
get_node_it(); it.has_curr(); it.next_ne())
1912 auto gp = it.get_curr();
1919 auto arc = it.get_curr();
1973 std::numeric_limits<typename Dft_Dist<GT>::Distance_Type>
::max();
1991 template <AlephGraph GT, ArcFilter<GT> SA = Dft_Show_Arc<GT>>
1997 assert(src !=
nullptr and tgt !=
nullptr);
2001 std::swap(tgt, src);
2006 if (it.get_tgt_node_ne() != tgt)
2009 auto arc = it.get_current_arc_ne();
2022 template <AlephGraph GT, ArcDistance<GT> Distance = Dft_Dist<GT>>
2029 <<
"get_min_path(): s and end must be non-null";
2031 Distance_Type dist{};
2049 <<
"get_min_path(): broken cookie chain (nullptr)";
2054 <<
"get_min_path(): no arc connecting nodes in path";
2057 dist += distance(arc);
2063 for (
auto it =
node_arc_list.get_it(); it.has_curr(); it.next())
2065 auto & [node, arc] = it.get_curr();
2089 template <AlephGraph
GT,
2113 sum +=
dist(it.get_current_arc_ne());
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_unless(C)
Throws std::domain_error if condition does NOT hold.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
C++20 concepts for the protocol shared by graph algorithms.
WeightedDigraph::Node Node
List_Graph< Graph_Node< Node_Info >, Graph_Arc< Arc_Info > > GT
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).
T & append(const T &item)
T & get_last() const
Return the last item of the list.
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.
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Graph_Node< Node_Info > Node
The graph type.
Graph_Arc< Arc_Info > Arc
The node class type.
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
typename Arc::Arc_Type Arc_Type
The type of data stored in the arc.
void insert(Arc *arc)
Insert an arc as the first of a path.
void empty()
Clean the path: all the nodes and arc are removed.
void init(Node *start_node)
Set the first node of a path.
void append(Arc *arc)
Append an arc to the path.
const GT & get_graph() const noexcept
Get a constant reference to the graph.
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.
ArcInfo & get_info() noexcept
Return a modifiable reference to the arc data.
size_t num_arcs
data associated to the node. Access it with get_info()
void reset_bit_nodes(int bit) const noexcept
Reset bit to zero for all the nodes of graph.
void reset_arcs() const
Reset all the arcs of graph (the control bits, the state, the counter and the cookie)
auto get_arc_it() const noexcept
Obtains an iterator to the arc of graph.
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Node * get_node() const
Return any node in the graph.
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
void set_bit(Node *node, int bit, int value) const noexcept
Set the control bit of node to value
bool is_digraph() const noexcept
Return true if the graph this is directed.
static void map_arcs(A1 *p, A2 *q) noexcept
Map the arcs through their cookies.
void reset_counter_nodes() const noexcept
Reset all the counters to zero for all the nodes of graph.
void reset_bit_arcs(int bit) const noexcept
Reset bit to zero for all the arcs of graph.
constexpr size_t get_num_arcs() const noexcept
void reset_counter_arcs() const noexcept
Reset all the counters to zero for all the arcs of graph.
void reset_nodes() const
Reset all the nodes of graph (the control bits, the state, the counter and the cookie)
auto get_node_it() const noexcept
Obtains an iterator to the nodes of graph.
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
static void map_nodes(N1 *p, N2 *q) noexcept
Map the nodes through their cookies.
__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)
DynArray< Graph::Node * > nodes
DynArray< Graph::Arc * > arcs
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().
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.
Main namespace for Aleph-w library functions.
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 ¤t_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.
Filtered iterator on all the arcs of a graph.
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.
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.
Array-based graph implementation.
Dynamic queue implementation based on linked lists.