aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
edgeGraphPart.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 // GUM_NO_INLINE
54
55namespace gum {
56
58 EdgeGraphPart::EdgeGraphPart(Size edges_size, bool edges_resize_policy) :
59 _edges_(edges_size, edges_resize_policy) {
60 GUM_CONSTRUCTOR(EdgeGraphPart);
61 }
62
64 GUM_CONS_CPY(EdgeGraphPart)
65
66 // copy the set of neighbours
67 _neighbours_.resize(s._neighbours_.capacity());
68
69 for (const auto& [key, nodeset]: s._neighbours_) {
70 NodeSet* newneigh = new NodeSet(*nodeset);
71 _neighbours_.insert(key, newneigh);
72 }
73
74 // send signals to indicate that there are new edges
75 if (onEdgeAdded.hasListener())
76 for (const auto& edge: _edges_)
77 GUM_EMIT2(onEdgeAdded, edge.first(), edge.second());
78 }
79
81 GUM_DESTRUCTOR(EdgeGraphPart)
82 // be sure to deallocate all the neighbours sets
84 }
85
87
89 for (const auto& elt: _neighbours_)
90 delete elt.second;
91
92 _neighbours_.clear();
93
94 if (onEdgeDeleted.hasListener()) {
95 EdgeSet tmp = _edges_;
96 _edges_.clear();
97
98 for (const auto& edge: tmp)
99 GUM_EMIT2(onEdgeDeleted, edge.first(), edge.second());
100 } else {
101 _edges_.clear();
102 }
103 }
104
106 // avoid self assignment
107 if (this != &s) {
108 clearEdges();
109
110 _edges_ = s._edges_;
111
112 // copy the set of neighbours
113 _neighbours_.resize(s._neighbours_.capacity());
114
115 for (const auto& [key, nodeset]: s._neighbours_) {
116 NodeSet* newneigh = new NodeSet(*nodeset);
117 _neighbours_.insert(key, newneigh);
118 }
119
120 if (onEdgeAdded.hasListener())
121 for (const auto& edge: _edges_)
122 GUM_EMIT2(onEdgeAdded, edge.first(), edge.second());
123 }
124
125 return *this;
126 }
127
128 std::string EdgeGraphPart::toString() const {
129 std::stringstream s;
130 bool first = true;
131 s << "{";
132
133 for (const auto& edge: _edges_) {
134 if (first) first = false;
135 else s << ",";
136
137 s << edge;
138 }
139
140 s << "}";
141
142 return s.str();
143 }
144
145 std::vector< NodeId > EdgeGraphPart::undirectedPath(NodeId n1, NodeId n2) const {
146 // not recursive version => use a FIFO for simulating the recursion
147 List< NodeId > nodeFIFO;
148 nodeFIFO.pushBack(n2);
149
150 // mark[node] = predecessor if visited, else mark[node] does not exist
152 mark.insert(n2, n2);
153
154 NodeId current;
155
156 while (!nodeFIFO.empty()) {
157 current = nodeFIFO.front();
158 nodeFIFO.popFront();
159
160 // check the neighbour
161 for (const auto new_one: neighbours(current)) {
162 if (mark.exists(new_one)) // if this node is already marked, stop
163 continue;
164
165 mark.insert(new_one, current);
166
167 if (new_one == n1) {
168 std::vector< NodeId > v;
169
170 for (current = n1; current != n2; current = mark[current])
171 v.push_back(current);
172
173 v.push_back(n2);
174
175 return v;
176 }
177
178 nodeFIFO.pushBack(new_one);
179 }
180 }
181
182 GUM_ERROR(NotFound, "no path found")
183 }
184
186 NodeSet visited;
187 NodeSet temp;
188
189 temp.insert(n1);
190 while (!temp.empty()) {
191 NodeId current = *(temp.begin());
192 if (current == n2) return true;
193 temp.erase(current);
194 visited.insert(current);
195 for (auto next: neighbours(current)) {
196 if (!temp.contains(next) && !visited.contains(next)) temp.insert(next);
197 }
198 }
199 return false;
200 }
201
202 bool EdgeGraphPart::hasUndirectedPath(NodeId n1, const NodeId n2, const NodeSet& except) const {
203 NodeSet visited;
204 NodeSet temp;
205
206 if (except.contains(n2)) return false;
207
208 temp.insert(n1);
209 while (!temp.empty()) {
210 NodeId current = *(temp.begin());
211 if (current == n2) return true;
212 temp.erase(current);
213 visited.insert(current);
214 for (auto next: neighbours(current)) {
215 if (!temp.contains(next) && !visited.contains(next) && !except.contains(next))
216 temp.insert(next);
217 }
218 }
219 return false;
220 }
221
223 const NodeSet& n2,
224 const NodeSet& except) const {
225 NodeSet visited;
226 NodeSet temp;
227
228 for (auto n: n1)
229 temp.insert(n);
230
231 while (!temp.empty()) {
232 NodeId current = *(temp.begin());
233 if (n2.contains(current)) return true;
234 temp.erase(current);
235 visited.insert(current);
236 for (auto next: neighbours(current)) {
237 if (!temp.contains(next) && !visited.contains(next) && !except.contains(next))
238 temp.insert(next);
239 }
240 }
241 return false;
242 }
243
244 std::ostream& operator<<(std::ostream& stream, const EdgeGraphPart& set) {
245 stream << set.toString();
246 return stream;
247 }
248
249} /* namespace gum */
Classes for undirected edge sets.
std::vector< NodeId > undirectedPath(NodeId node1, NodeId node2) const
returns a possible path from node1 to node2 in the edge set
EdgeGraphPart & operator=(const EdgeGraphPart &s)
copy operator
bool hasUndirectedPath(NodeId n1, NodeId n2) const
return true if n1 and n2 are connected (by an undirected path) in the graph.
virtual ~EdgeGraphPart()
destructor
EdgeGraphPart(Size edges_size=HashTableConst::default_size, bool edges_resize_policy=true)
default constructor
EdgeSet _edges_
the set of all the edges contained within the EdgeGraphPart
Signaler2< NodeId, NodeId > onEdgeDeleted
NodeProperty< NodeSet * > _neighbours_
for each node, the set of its adjacent edges
Signaler2< NodeId, NodeId > onEdgeAdded
virtual std::string toString() const
to friendly display the content of the EdgeGraphPart
virtual void clearEdges()
removes all the edges from the EdgeGraphPart
const NodeSet & neighbours(NodeId id) const
returns the set of node neighbours to a given node
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.
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
Inline implementation of classes for undirected edge sets.
#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
Set< Edge > EdgeSet
Some typdefs and define for shortcuts ...
Size NodeId
Type for node ids.
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