aGrUM 3.0.0
a C++ library for (probabilistic) graphical models
reachability_tpl.h
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2026 by *
5 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
6 * - Christophe GONZALES(_at_AMU) *
7 * *
8 * The aGrUM/pyAgrum library is free software; you can redistribute it *
9 * and/or modify it under the terms of either : *
10 * *
11 * - the GNU Lesser General Public License as published by *
12 * the Free Software Foundation, either version 3 of the License, *
13 * or (at your option) any later version, *
14 * - the MIT license (MIT), *
15 * - or both in dual license, as here. *
16 * *
17 * (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18 * *
19 * This aGrUM/pyAgrum library is distributed in the hope that it will be *
20 * useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26 * OTHER DEALINGS IN THE SOFTWARE. *
27 * *
28 * See LICENCES for more details. *
29 * *
30 * SPDX-FileCopyrightText: Copyright 2005-2026 *
31 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
32 * - Christophe GONZALES(_at_AMU) *
33 * SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34 * *
35 * Contact : info_at_agrum_dot_org *
36 * homepage : http://agrum.gitlab.io *
37 * gitlab : https://gitlab.com/agrumery/agrum *
38 * *
39 ****************************************************************************/
40
41
48
49#pragma once
50
51// to ease IDE parser
53
54namespace gum::graph {
55
56 template < GUM_DiGraphable G >
57 NodeSet ancestors(const G& g, NodeId id) {
58 NodeSet res;
59 NodeSet frontier = g.parents(id);
60
61 while (!frontier.empty()) {
62 const NodeId current = *frontier.begin();
63 frontier.erase(current);
64 res.insert(current);
65 for (const auto p: g.parents(current))
66 if (!res.contains(p)) frontier.insert(p);
67 }
68
69 return res;
70 }
71
72 template < GUM_DiGraphable G >
73 NodeSet descendants(const G& g, NodeId id) {
74 NodeSet res;
75 NodeSet frontier = g.children(id);
76
77 while (!frontier.empty()) {
78 const NodeId current = *frontier.begin();
79 frontier.erase(current);
80 res.insert(current);
81 for (const auto c: g.children(current))
82 if (!res.contains(c)) frontier.insert(c);
83 }
84
85 return res;
86 }
87
88 template < GUM_DiGraphable G >
89 NodeSet family(const G& g, NodeId id) {
90 NodeSet res{id};
91 return res + g.parents(id);
92 }
93
94 template < GUM_DiGraphable G >
95 NodeSet family(const G& g, const NodeSet& ids) {
96 NodeSet res;
97 for (const auto node: ids)
98 res += family(g, node);
99 return res;
100 }
101
102 template < GUM_UndiGraphable G >
105 NodeId numCC = 0;
106
107 for (const auto node: g.nodes()) {
108 if (res.exists(node)) continue;
109
110 NodeSet frontier{node};
111 while (!frontier.empty()) {
112 const NodeId current = *frontier.begin();
113 frontier.erase(current);
114 res.insert(current, numCC);
115 for (const auto nei: g.neighbours(current))
116 if (!res.exists(nei)) frontier.insert(nei);
117 }
118 ++numCC;
119 }
120
121 return res;
122 }
123
124 template < GUM_NodeGraphable G >
127 NodeId numCC = 0;
128
129 for (const auto node: g.nodes()) {
130 if (res.exists(node)) continue;
131
132 NodeSet frontier{node};
133 while (!frontier.empty()) {
134 const NodeId current = *frontier.begin();
135 frontier.erase(current);
136 res.insert(current, numCC);
137
138 if constexpr (GUM_DiGraphable< G >) {
139 for (const auto n: g.parents(current))
140 if (!res.exists(n)) frontier.insert(n);
141 for (const auto n: g.children(current))
142 if (!res.exists(n)) frontier.insert(n);
143 }
144 if constexpr (GUM_UndiGraphable< G >) {
145 for (const auto n: g.neighbours(current))
146 if (!res.exists(n)) frontier.insert(n);
147 }
148 }
149 ++numCC;
150 }
151
152 return res;
153 }
154
155 template < GUM_UndiGraphable G >
156 bool areConnected(const G& g, const NodeSet& A, const NodeSet& B) {
157 if (A.empty() || B.empty()) return false;
158 if (!(A * B).empty()) return true;
159
160 NodeSet visited;
161 NodeSet frontier = A;
162 for (const auto s: A)
163 visited.insert(s);
164
165 while (!frontier.empty()) {
166 const NodeId u = *frontier.begin();
167 frontier.erase(u);
168 for (const auto v: g.neighbours(u)) {
169 if (visited.exists(v)) continue;
170 if (B.contains(v)) return true;
171 visited.insert(v);
172 frontier.insert(v);
173 }
174 }
175 return false;
176 }
177
178 template < GUM_MixedGraphable G >
179 NodeSet chainComponent(const G& g, NodeId node) {
180 NodeSet res;
181 NodeSet frontier{node};
182
183 while (!frontier.empty()) {
184 const NodeId n = *frontier.begin();
185 frontier.erase(n);
186 res.insert(n);
187 for (const auto nei: g.neighbours(n))
188 if (!res.contains(nei)) frontier.insert(nei);
189 }
190
191 return res;
192 }
193
194 template < GUM_MixedGraphable G >
195 NodeSet boundary(const G& g, NodeId node) {
196 return g.neighbours(node) + g.parents(node) + g.children(node);
197 }
198
199} // namespace gum::graph
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
bool exists(const Key &key) const
Checks whether there exists an element with a given key in the hashtable.
bool contains(const Key &k) const
Indicates whether a given elements belong to the set.
Definition set_tpl.h:468
bool exists(const Key &k) const
Indicates whether a given elements belong to the set.
Definition set_tpl.h:504
bool empty() const noexcept
Indicates whether the set is the empty set.
Definition set_tpl.h:613
iterator begin() const
The usual unsafe begin iterator to parse the set.
Definition set_tpl.h:409
void insert(const Key &k)
Inserts a new element into the set.
Definition set_tpl.h:510
void erase(const Key &k)
Erases an element from the set.
Definition set_tpl.h:553
Concept for directed graphs (arcs with parents/children).
Concept for undirected graphs (edges with neighbours).
Size NodeId
Type for node ids.
HashTable< NodeId, VAL > NodeProperty
Property on graph elements.
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
NodeSet descendants(const G &g, NodeId id)
Returns the set of all descendants of id (nodes reachable from id following arc direction).
NodeSet ancestors(const G &g, NodeId id)
Returns the set of all ancestors of id (nodes from which id is reachable following arc direction).
bool areConnected(const G &g, const NodeSet &A, const NodeSet &B)
Returns true iff some node in A can reach some node in B via undirected edges.
NodeSet boundary(const G &g, NodeId node)
Returns the boundary of node: neighbours ∪ parents ∪ children.
NodeProperty< NodeId > chainComponents(const G &g)
Returns a node-to-component-id mapping for the chain components of g (connected components of the edg...
NodeSet chainComponent(const G &g, NodeId node)
Returns the chain component of node in g.
NodeSet family(const G &g, NodeId id)
Returns the family of id : { id } ∪ parents(id).
NodeProperty< NodeId > connectedComponents(const G &g)
Returns a node-to-component-id mapping for the (weakly) connected components of g.
Generic node-reachability algorithms for aGrUM graphs.