48 template < GUM_DiGraphable G >
50 if (g.empty())
return {};
53 std::vector< NodeId > border;
54 border.reserve(g.size() / 2);
56 for (
const auto node: g.nodes()) {
57 const auto& par = g.parents(node);
58 indegree.
insert(node, par.size());
59 if (par.empty()) border.push_back(node);
66 while (!border.empty()) {
67 const NodeId root = border.back();
74 for (
const auto child: g.children(root)) {
75 const Size deg = indegree[child];
78 if (deg == 1) border.push_back(child);
79 indegree[child] = deg - 1;
83 GUM_ASSERT(result.
size() == g.size());
87 template < GUM_UndiGraphable G >
90 for (
const auto node: g.nodes())
91 visited.
insert(node,
false);
93 for (
const auto node: g.nodes()) {
94 if (visited[node])
continue;
100 while (!frontier.
empty()) {
101 const auto [current, from] = frontier.
front();
104 for (
const auto next: g.neighbours(current)) {
105 if (next == from)
continue;
106 if (visited[next])
return true;
107 visited[next] =
true;
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
Exception : existence of a directed cycle in a graph.
Generic doubly linked lists.
Val & front() const
Returns a reference to first element of a list, if any.
Val & pushBack(const Val &val)
Inserts a new element (a copy) at the end of the chained list.
bool empty() const noexcept
Returns a boolean indicating whether the chained list is empty.
void popFront()
Removes the first element of a List, if any.
void insert(const Key &k)
bool exists(const Key &k) const
Size size() const noexcept
Generic cycle-detection algorithms for aGrUM graphs.
#define GUM_ERROR(type, msg)
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Size NodeId
Type for node ids.
HashTable< NodeId, VAL > NodeProperty
Property on graph elements.
bool hasUndirectedCycle(const G &g)
Returns true if g contains at least one undirected cycle.
Sequence< NodeId > topologicalOrder(const G &g)
Returns a topological ordering of the nodes of g (Kahn's algorithm).