aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
arcGraphPart.cpp
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2025 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-2025 *
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
49
50#ifdef GUM_NO_INLINE
52#endif // GU%_NO_INLINE
54
55namespace gum {
56
58 ArcGraphPart::ArcGraphPart(Size arcs_size, bool arcs_resize_policy) :
59 _arcs_(arcs_size, arcs_resize_policy) {
60 GUM_CONSTRUCTOR(ArcGraphPart);
61 }
62
64 GUM_CONS_CPY(ArcGraphPart);
65
66 // copy the sets of parents
67 const NodeProperty< NodeSet* >& pars = s._parents_;
68 _parents_.resize(pars.capacity());
69
70 for (const auto& [key, nodeset]: pars) {
71 NodeSet* newpar = new NodeSet(*nodeset);
72 _parents_.insert(key, newpar);
73 }
74
75 // copy the sets of children
77 _children_.resize(children.capacity());
78
79 for (const auto& [key, nodeset]: children) {
80 NodeSet* newchildren = new NodeSet(*nodeset);
81 _children_.insert(key, newchildren);
82 }
83
84 // send signals to indicate that there are new arcs
85 if (onArcAdded.hasListener()) {
86 for (const auto& arc: _arcs_) {
87 GUM_EMIT2(onArcAdded, arc.tail(), arc.head());
88 }
89 }
90 }
91
93 GUM_DESTRUCTOR(ArcGraphPart);
94 // be sure to deallocate all the parents and children sets
95 clearArcs();
96 }
97
99 for (const auto& elt: _parents_)
100 delete elt.second;
101
102 _parents_.clear();
103
104 for (const auto& elt: _children_)
105 delete elt.second;
106
107 _children_.clear();
108
109 // we need this copy only if at least one onArcDeleted listener exists
110 if (onArcDeleted.hasListener()) {
111 ArcSet tmp = _arcs_;
112 _arcs_.clear();
113
114 for (const auto& arc: tmp)
115 GUM_EMIT2(onArcDeleted, arc.tail(), arc.head());
116 } else {
117 _arcs_.clear();
118 }
119 }
120
122 // avoid self assignment
123 if (this != &s) {
124 // copy the arcs
125 clearArcs();
126 _arcs_ = s._arcs_;
127
128 // copy the sets of parents
129 _parents_.resize(s._parents_.capacity());
130
131 for (const auto& [key, nodeset]: s._parents_) {
132 NodeSet* newpar = new NodeSet(*nodeset);
133 _parents_.insert(key, newpar);
134 }
135
136 // copy the sets of children
137 _children_.resize(s._children_.capacity());
138
139 for (const auto& [key, nodeset]: s._children_) {
140 NodeSet* newchildren = new NodeSet(*nodeset);
141 _children_.insert(key, newchildren);
142 }
143
144 if (onArcAdded.hasListener()) {
145 for (const auto& arc: _arcs_) {
146 GUM_EMIT2(onArcAdded, arc.tail(), arc.head());
147 }
148 }
149 }
150
151 return *this;
152 }
153
154 std::string ArcGraphPart::toString() const {
155 std::stringstream s;
156 bool first = true;
157 s << "{";
158
159 for (const auto& arc: _arcs_) {
160 if (first) {
161 first = false;
162 } else {
163 s << ",";
164 }
165
166 s << arc;
167 }
168
169 s << "}";
170
171 return s.str();
172 }
173
175 NodeSet res;
176 NodeSet tmp;
177 for (auto next: children(id))
178 tmp.insert(next);
179
180 while (!tmp.empty()) {
181 auto current = *(tmp.begin());
182 tmp.erase(current);
183 res.insert(current);
184 for (auto next: children(current)) {
185 if (!tmp.contains(next) && !res.contains(next)) { tmp.insert(next); }
186 }
187 }
188 return res;
189 }
190
192 NodeSet res;
193 NodeSet tmp;
194 for (auto next: parents(id))
195 tmp.insert(next);
196
197 while (!tmp.empty()) {
198 auto current = *(tmp.begin());
199 tmp.erase(current);
200 res.insert(current);
201 for (auto next: parents(current)) {
202 if (!tmp.contains(next) && !res.contains(next)) { tmp.insert(next); }
203 }
204 }
205 return res;
206 }
207
208 std::vector< NodeId > ArcGraphPart::directedPath(NodeId n1, NodeId n2) const {
209 // not recursive version => use a FIFO for simulating the recursion
210 List< NodeId > nodeFIFO;
211 nodeFIFO.pushBack(n2);
212
213 // mark[node] = successor if visited, else mark[node] does not exist
215 mark.insert(n2, n2);
216
217 NodeId current;
218
219 while (!nodeFIFO.empty()) {
220 current = nodeFIFO.front();
221 nodeFIFO.popFront();
222
223 // check the parents
224
225 for (const auto new_one: parents(current)) {
226 if (mark.exists(new_one)) // if this node is already marked, do not
227 continue; // check it again
228
229 mark.insert(new_one, current);
230
231 if (new_one == n1) {
232 std::vector< NodeId > v;
233
234 for (current = n1; current != n2; current = mark[current])
235 v.push_back(current);
236
237 v.push_back(n2);
238
239 return v;
240 }
241
242 nodeFIFO.pushBack(new_one);
243 }
244 }
245
246 GUM_ERROR(NotFound, "no path found")
247 }
248
249 std::vector< NodeId > ArcGraphPart::directedUnorientedPath(NodeId n1, NodeId n2) const {
250 // not recursive version => use a FIFO for simulating the recursion
251 List< NodeId > nodeFIFO;
252 nodeFIFO.pushBack(n2);
253
254 // mark[node] = successor if visited, else mark[node] does not exist
256 mark.insert(n2, n2);
257
258 NodeId current;
259
260 while (!nodeFIFO.empty()) {
261 current = nodeFIFO.front();
262 nodeFIFO.popFront();
263
264 // check the parents
265 for (const auto new_one: parents(current)) {
266 if (mark.exists(new_one)) // the node has already been visited
267 continue;
268
269 mark.insert(new_one, current);
270
271 if (new_one == n1) {
272 std::vector< NodeId > v;
273
274 for (current = n1; current != n2; current = mark[current])
275 v.push_back(current);
276
277 v.push_back(n2);
278
279 return v;
280 }
281
282 nodeFIFO.pushBack(new_one);
283 }
284
285 // check the children
286 for (const auto new_one: children(current)) {
287 if (mark.exists(new_one)) // the node has already been visited
288 continue;
289
290 mark.insert(new_one, current);
291
292 if (new_one == n1) {
293 std::vector< NodeId > v;
294
295 for (current = n1; current != n2; current = mark[current])
296 v.push_back(current);
297
298 v.push_back(n2);
299
300 return v;
301 }
302
303 nodeFIFO.pushBack(new_one);
304 }
305 }
306
307 GUM_ERROR(NotFound, "no path found")
308 }
309
310 std::ostream& operator<<(std::ostream& stream, const ArcGraphPart& set) {
311 stream << set.toString();
312 return stream;
313 }
314
315} /* namespace gum */
Inline implementation of classes for directed edge sets.
Classes for directed edge sets.
virtual ~ArcGraphPart()
destructor
const NodeSet & parents(NodeId id) const
returns the set of nodes with arc ingoing to a given node
Signaler2< NodeId, NodeId > onArcAdded
Set< Arc > _arcs_
the set of all the arcs contained within the ArcGraphPart
ArcGraphPart & operator=(const ArcGraphPart &s)
copy operator
std::vector< NodeId > directedUnorientedPath(NodeId node1, NodeId node2) const
returns an unoriented (directed) path from node1 to node2 in the arc set
void clearArcs()
removes all the arcs from the ArcGraphPart
NodeProperty< NodeSet * > _children_
for each arc, the set of its children
NodeSet descendants(NodeId id) const
returns the set of nodes with directed path outgoing from a given node
NodeProperty< NodeSet * > _parents_
for each arc, the sets of its parents
NodeSet children(const NodeSet &ids) const
returns the set of children of a set of nodes
NodeSet ancestors(NodeId id) const
returns the set of nodes with directed path ingoing to a given node
ArcGraphPart(Size arcs_size=HashTableConst::default_size, bool arcs_resize_policy=true)
default constructor
std::vector< NodeId > directedPath(NodeId node1, NodeId node2) const
returns a directed path from node1 to node2 belonging to the set of arcs
Signaler2< NodeId, NodeId > onArcDeleted
std::string toString() const
to friendly display the content of the ArcGraphPart
bool exists(const Key &key) const
Checks whether there exists an element with a given key in the hashtable.
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
Size capacity() const noexcept
Returns the number of slots in the 'nodes' vector of the hashtable.
Generic doubly linked lists.
Definition list.h:379
Val & front() const
Returns a reference to first element of a list, if any.
Definition list_tpl.h:1703
bool empty() const noexcept
Returns a boolean indicating whether the chained list is empty.
Definition list_tpl.h:1831
void popFront()
Removes the first element of a List, if any.
Definition list_tpl.h:1825
Val & pushBack(const Val &val)
Inserts a new element (a copy) at the end of the chained list.
Definition list_tpl.h:1488
Exception : the element we looked for cannot be found.
iterator begin() const
The usual unsafe begin iterator to parse the set.
Definition set_tpl.h:438
bool contains(const Key &k) const
Indicates whether a given elements belong to the set.
Definition set_tpl.h:497
void insert(const Key &k)
Inserts a new element into the set.
Definition set_tpl.h:539
bool empty() const noexcept
Indicates whether the set is the empty set.
Definition set_tpl.h:642
void erase(const Key &k)
Erases an element from the set.
Definition set_tpl.h:582
#define GUM_ERROR(type, msg)
Definition exceptions.h:72
some utils for topology : NodeId, Edge, Arc and consorts ...
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition types.h:74
Size NodeId
Type for node ids.
Set< Arc > ArcSet
Some typdefs and define for shortcuts ...
HashTable< NodeId, VAL > NodeProperty
Property on graph elements.
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
std::ostream & operator<<(std::ostream &stream, const AVLTree< Val, Cmp > &tree)
display the content of a tree
Definition AVLTree.h:913
#define GUM_EMIT2(signal, arg1, arg2)
Definition signaler2.h:61