aGrUM 3.2.0
a C++ library for (probabilistic) graphical models
graphChange_inl.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#pragma once
42
43
52#include <agrum/BN/learning/structureUtils/graphChange.h> // to ease IDE parser
53#ifndef DOXYGEN_SHOULD_SKIP_THIS
54
55namespace gum {
56
57 namespace learning {
58
59 // Constructors, destructor and assignment operators are defined
60 // out-of-line in graphChange.cpp on purpose -- see the comment there.
61
63 INLINE GraphChangeType GraphChange::type() const noexcept { return type_; }
64
66 INLINE NodeId GraphChange::node1() const noexcept { return NodeId(nodes_[0]); }
67
69 INLINE NodeId GraphChange::node2() const noexcept { return NodeId(nodes_[1]); }
70
72 INLINE NodeId GraphChange::node3() const {
75 GUM_ERROR(InvalidNode, "GraphChange " << (int)(type_) << " does not involve a third node")
76 }
77 return NodeId(nodes_[2]);
78 }
79
81 INLINE bool GraphChange::operator==(const GraphChange& from) const noexcept {
82 // Here, we know that nodes_ and type_ are of the same type, which
83 // is 32bit long (and aligned accordingly). In addition, type_ is
84 // defined just after nodes_ in Class GraphChange. Hence, memcmping 4
85 // elements starting from pointer nodes_ will compare efficiently both
86 // the 3 elements of nodes_ and type_
87 return std::memcmp(nodes_, from.nodes_, 4 * sizeof(LearnNodeId)) == 0;
88 }
89
91 INLINE bool GraphChange::operator!=(const GraphChange& from) const noexcept {
92 return !operator==(from);
93 }
94
95 // ===========================================================================
96
97 // Constructors, destructor and assignment operators are defined
98 // out-of-line in graphChange.cpp on purpose -- see the comment there.
99
101 INLINE bool ArcAddition::operator==(const ArcAddition& from) const noexcept {
102 // compare nodes_[0] and nodes_[1] in this and from
103 return std::memcmp(nodes_, from.nodes_, 2 * sizeof(LearnNodeId)) == 0;
104 }
105
107 INLINE bool ArcAddition::operator!=(const ArcAddition& from) const noexcept {
108 return !operator==(from);
109 }
110
111 // ===========================================================================
112
113 // Constructors, destructor and assignment operators are defined
114 // out-of-line in graphChange.cpp on purpose -- see the comment there.
115
117 INLINE bool ArcDeletion::operator==(const ArcDeletion& from) const noexcept {
118 // compare nodes_[0] and nodes_[1] in this and from
119 return std::memcmp(nodes_, from.nodes_, 2 * sizeof(LearnNodeId)) == 0;
120 }
121
123 INLINE bool ArcDeletion::operator!=(const ArcDeletion& from) const noexcept {
124 return !operator==(from);
125 }
126
127 // ===========================================================================
128
129 // Constructors, destructor and assignment operators are defined
130 // out-of-line in graphChange.cpp on purpose -- see the comment there.
131
133 INLINE bool ArcReversal::operator==(const ArcReversal& from) const noexcept {
134 // compare nodes_[0] and nodes_[1] in this and from
135 return std::memcmp(nodes_, from.nodes_, 2 * sizeof(LearnNodeId)) == 0;
136 }
137
139 INLINE bool ArcReversal::operator!=(const ArcReversal& from) const noexcept {
140 return !operator==(from);
141 }
142
143 // ===========================================================================
144
145 // Constructors, destructor and assignment operators are defined
146 // out-of-line in graphChange.cpp on purpose -- see the comment there.
147
149 INLINE bool ArcTriangleDeletion1::operator==(const ArcTriangleDeletion1& from) const noexcept {
150 // compare nodes_[0], nodes_[1] and nodes_[2] in this and from
151 return std::memcmp(nodes_, from.nodes_, 3 * sizeof(LearnNodeId)) == 0;
152 }
153
155 INLINE bool ArcTriangleDeletion1::operator!=(const ArcTriangleDeletion1& from) const noexcept {
156 return !operator==(from);
157 }
158
160 INLINE NodeId ArcTriangleDeletion1::node3() const { return NodeId(nodes_[2]); }
161
162 // ===========================================================================
163
164 // Constructors, destructor and assignment operators are defined
165 // out-of-line in graphChange.cpp on purpose -- see the comment there.
166
168 INLINE bool ArcTriangleDeletion2::operator==(const ArcTriangleDeletion2& from) const noexcept {
169 // compare nodes_[0], nodes_[1] and nodes_[2] in this and from
170 return std::memcmp(nodes_, from.nodes_, 3 * sizeof(LearnNodeId)) == 0;
171 }
172
174 INLINE bool ArcTriangleDeletion2::operator!=(const ArcTriangleDeletion2& from) const noexcept {
175 return !operator==(from);
176 }
177
179 INLINE NodeId ArcTriangleDeletion2::node3() const { return NodeId(nodes_[2]); }
180
181 // ===========================================================================
182
183 // Constructors, destructor and assignment operators are defined
184 // out-of-line in graphChange.cpp on purpose -- see the comment there.
185
187 INLINE bool EdgeAddition::operator==(const EdgeAddition& from) const noexcept {
188 // compare nodes_[0] and nodes_[1] in this and from
189 return std::memcmp(nodes_, from.nodes_, 2 * sizeof(LearnNodeId)) == 0;
190 }
191
193 INLINE bool EdgeAddition::operator!=(const EdgeAddition& from) const noexcept {
194 return !operator==(from);
195 }
196
197 // ===========================================================================
198
199 // Constructors, destructor and assignment operators are defined
200 // out-of-line in graphChange.cpp on purpose -- see the comment there.
201
203 INLINE bool EdgeDeletion::operator==(const EdgeDeletion& from) const noexcept {
204 // compare nodes_[0] and nodes_[1] in this and from
205 return std::memcmp(nodes_, from.nodes_, 2 * sizeof(LearnNodeId)) == 0;
206 }
207
209 INLINE bool EdgeDeletion::operator!=(const EdgeDeletion& from) const noexcept {
210 return !operator==(from);
211 }
212
213
214 } /* namespace learning */
215
216 // ===========================================================================
217
218 // Returns the value of a key as a Size.
220 if constexpr (sizeof(learning::LearnNodeId) == sizeof(Size)) {
221 // here, we assume that it is very unlikely that many triangles share the same
222 // arc. Hence, to avoid slowing down the computations of the mapping of
223 // ArcAddition, ArcDeletion and ArcReversal while not speeding-up much that
224 // of ArcTriangleDeletion1 and ArcTriangleDeletion2, we never take into account
225 // node3 in our computations.
226 return Size(key.type()) * HashFuncConst::gold + Size(key.node1()) * HashFuncConst::pi
227 + Size(key.node2()) * HashFuncConst::sqrt3;
228 } else {
229 // here we not only take into account the 3 nodes but also the type of
230 // the change
231 const Size* const nodes = (const Size*)key.nodes_;
232 return nodes[0] * HashFuncConst::gold + nodes[1] * HashFuncConst::pi;
233 }
234 }
235
236 // computes the hashed value of a key
237 INLINE Size
239 return castToSize(key) >> this->right_shift_;
240 }
241
242 // Returns the value of a key as a Size.
244 if constexpr (sizeof(learning::LearnNodeId) == sizeof(Size)) {
245 return Size(key.node1()) * HashFuncConst::gold + Size(key.node2()) * HashFuncConst::pi;
246 } else {
247 // here we take into account both node1() and node2()
248 const Size* const nodes = (Size*)key.nodes_;
249 return nodes[0] * HashFuncConst::gold;
250 }
251 }
252
253 // computes the hashed value of a key
254 INLINE Size
256 return castToSize(key) >> this->right_shift_;
257 }
258
259 // Returns the value of a key as a Size.
261 if constexpr (sizeof(learning::LearnNodeId) == sizeof(Size)) {
262 return Size(key.node1()) * HashFuncConst::gold + Size(key.node2()) * HashFuncConst::pi;
263 } else {
264 // here we take into account both node1() and node2()
265 const Size* const nodes = (Size*)key.nodes_;
266 return nodes[0] * HashFuncConst::gold;
267 }
268 }
269
270 // computes the hashed value of a key
271 INLINE Size
273 return castToSize(key) >> this->right_shift_;
274 }
275
276 // Returns the value of a key as a Size.
278 if constexpr (sizeof(learning::LearnNodeId) == sizeof(Size)) {
279 return Size(key.node1()) * HashFuncConst::gold + Size(key.node2()) * HashFuncConst::pi;
280 } else {
281 // here we take into account both node1() and node2()
282 const Size* const nodes = (Size*)key.nodes_;
283 return nodes[0] * HashFuncConst::gold;
284 }
285 }
286
287 // computes the hashed value of a key
288 INLINE Size
290 return castToSize(key) >> this->right_shift_;
291 }
292
293 // Returns the value of a key as a Size.
296 if constexpr (sizeof(learning::LearnNodeId) == sizeof(Size)) {
297 return Size(key.node1()) * HashFuncConst::gold + Size(key.node2()) * HashFuncConst::pi
298 + Size(key.node3()) * HashFuncConst::sqrt3;
299 } else {
300 // here we not only take into account the 3 nodes but also the type of
301 // the change
302 const Size* const nodes = (const Size*)key.nodes_;
303 return nodes[0] * HashFuncConst::gold + nodes[1] * HashFuncConst::pi;
304 }
305 }
306
307 // computes the hashed value of a key
309 const learning::ArcTriangleDeletion1& key) const {
310 return castToSize(key) >> this->right_shift_;
311 }
312
313 // Returns the value of a key as a Size.
316 if constexpr (sizeof(learning::LearnNodeId) == sizeof(Size)) {
317 return Size(key.node1()) * HashFuncConst::gold + Size(key.node2()) * HashFuncConst::pi
318 + Size(key.node3()) * HashFuncConst::sqrt3;
319 } else {
320 // here we not only take into account the 3 nodes but also the type of
321 // the change
322 const Size* const nodes = (const Size*)key.nodes_;
323 return nodes[0] * HashFuncConst::gold + nodes[1] * HashFuncConst::pi;
324 }
325 }
326
327 // computes the hashed value of a key
329 const learning::ArcTriangleDeletion2& key) const {
330 return castToSize(key) >> this->right_shift_;
331 }
332
333 // Returns the value of a key as a Size.
335 if constexpr (sizeof(learning::LearnNodeId) == sizeof(Size)) {
336 return Size(key.node1()) * HashFuncConst::gold + Size(key.node2()) * HashFuncConst::pi;
337 } else {
338 // here we take into account both node1() and node2()
339 const Size* const nodes = (Size*)key.nodes_;
340 return nodes[0] * HashFuncConst::gold;
341 }
342 }
343
345 INLINE Size
347 return castToSize(key) >> this->right_shift_;
348 }
349
350 // Returns the value of a key as a Size.
352 if constexpr (sizeof(learning::LearnNodeId) == sizeof(Size)) {
353 return Size(key.node1()) * HashFuncConst::gold + Size(key.node2()) * HashFuncConst::pi;
354 } else {
355 // here we take into account both node1() and node2()
356 const Size* const nodes = (Size*)key.nodes_;
357 return nodes[0] * HashFuncConst::gold;
358 }
359 }
360
362 INLINE Size
364 return castToSize(key) >> this->right_shift_;
365 }
366
367} /* namespace gum */
368
369#endif /* DOXYGEN_SHOULD_SKIP_THIS */
static Size castToSize(const learning::ArcAddition &key)
Returns the value of a key as a Size.
Size operator()(const learning::ArcAddition &key) const final
computes the hashed value of a key
Size operator()(const learning::ArcDeletion &key) const final
computes the hashed value of a key
static Size castToSize(const learning::ArcDeletion &key)
Returns the value of a key as a Size.
Size operator()(const learning::ArcReversal &key) const final
computes the hashed value of a key
static Size castToSize(const learning::ArcReversal &key)
Returns the value of a key as a Size.
static Size castToSize(const learning::ArcTriangleDeletion1 &key)
Returns the value of a key as a Size.
Size operator()(const learning::ArcTriangleDeletion1 &key) const final
computes the hashed value of a key
static Size castToSize(const learning::ArcTriangleDeletion2 &key)
Returns the value of a key as a Size.
Size operator()(const learning::ArcTriangleDeletion2 &key) const final
computes the hashed value of a key
Size operator()(const learning::EdgeAddition &key) const final
computes the hashed value of a key
static Size castToSize(const learning::EdgeAddition &key)
Returns the value of a key as a Size.
static Size castToSize(const learning::EdgeDeletion &key)
Returns the value of a key as a Size.
Size operator()(const learning::EdgeDeletion &key) const final
computes the hashed value of a key
static Size castToSize(const learning::GraphChange &key)
Returns the value of a key as a Size.
Size operator()(const learning::GraphChange &key) const final
computes the hashed value of a key
The class for notifying learning algorithms of new arc additions.
bool operator!=(const ArcAddition &from) const noexcept
returns whether two arc additions are different or not
bool operator==(const ArcAddition &from) const noexcept
returns whether two arc additions are identical or not
The class for notifying learning algorithms of arc removals.
bool operator!=(const ArcDeletion &from) const noexcept
returns whether two arc deletions are different or not
bool operator==(const ArcDeletion &from) const noexcept
returns whether two arc deletions are identical or not
The class for notifying learning algorithms of arc reversals.
bool operator!=(const ArcReversal &from) const noexcept
returns whether two arc reversals are different or not
bool operator==(const ArcReversal &from) const noexcept
returns whether two arc reversals are identical or not
The graph change substituting a triangle node1->node2->node3 + node1->node3 into v-structure node2->n...
NodeId node3() const
returns the third node involved in the modification (if any)
bool operator!=(const ArcTriangleDeletion1 &from) const noexcept
returns whether two ArcTriangleDeletion1 are different or not
bool operator==(const ArcTriangleDeletion1 &from) const noexcept
returns whether two ArcTriangleDeletion1 are identical or not
The graph change substituting a triangle node1->node2->node3 + node1->node3 into v-structure node1->n...
bool operator==(const ArcTriangleDeletion2 &from) const noexcept
returns whether two ArcTriangleDeletion2 are identical or not
bool operator!=(const ArcTriangleDeletion2 &from) const noexcept
returns whether two ArcTriangleDeletion2 are different or not
NodeId node3() const
returns the third node involved in the modification (if any)
The class for notifying learning algorithms of new edge additions.
bool operator!=(const EdgeAddition &from) const noexcept
returns whether two edge additions are different or not
bool operator==(const EdgeAddition &from) const noexcept
returns whether two edge additions are identical or not
The class for notifying learning algorithms of edge removals.
bool operator!=(const EdgeDeletion &from) const noexcept
returns whether two edge deletions are different or not
bool operator==(const EdgeDeletion &from) const noexcept
returns whether two edge deletions are identical or not
bool operator==(const GraphChange &from) const noexcept
returns whether two graph changes are identical or not
GraphChangeType type_
the type of modification
NodeId node1() const noexcept
returns the first node involved in the modification
GraphChangeType type() const noexcept
returns the type of the operation
LearnNodeId nodes_[3]
the nodes involved in the edge or arc to be modified
NodeId node2() const noexcept
returns the second node involved in the modification
NodeId node3() const
returns the third node involved in the modification (if any)
bool operator!=(const GraphChange &from) const noexcept
returns whether two graph changes are different or not
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
the classes to account for structure changes in a graph
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition types.h:74
Size NodeId
Type for node ids.
include the inlined functions if necessary
Definition CSVParser.h:55
GraphChangeType
the type of modification that can be applied to the graph
Definition graphChange.h:74
uint32_t LearnNodeId
the internal type of the nodes involved in the arc/edge modifications
Definition graphChange.h:71
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
bool operator==(const HashTableIteratorSafe< Key, Val > &from) const noexcept
Checks whether two iterators are pointing toward equal elements.
static constexpr Size sqrt3
Definition hashFunc.h:105
static constexpr Size pi
Definition hashFunc.h:103
static constexpr Size gold
Definition hashFunc.h:101