aGrUM 3.1.1
a C++ library for (probabilistic) graphical models
nodeGraphPart_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
50
51// to ease parsing by IDE
53
54namespace gum {
55
56 //=================NODEGRAPHPARTITERATOR============================
57
59 INLINE void NodeGraphPartIterator::validate_() noexcept {
60 valid_ = false;
61
62 if (pos_ > nodes_->bound()) { pos_ = nodes_->bound(); }
63
64 while (pos_ < nodes_->bound()) {
65 if (!nodes_->_inHoles_(pos_)) {
66 valid_ = true;
67 return;
68 }
69
70 ++pos_;
71 }
72 }
73
75 INLINE
77 nodes_(&nodes) {
78 GUM_CONSTRUCTOR(NodeGraphPartIterator);
79 }
80
83 nodes_(it.nodes_), pos_(it.pos_), valid_(it.valid_) {
84 GUM_CONS_CPY(NodeGraphPartIterator);
85 }
86
89 nodes_(it.nodes_), pos_(it.pos_), valid_(it.valid_) {
90 GUM_CONS_MOV(NodeGraphPartIterator);
91 }
92
95 GUM_DESTRUCTOR(NodeGraphPartIterator);
96 }
97
101 nodes_ = it.nodes_;
102 pos_ = it.pos_;
103 valid_ = it.valid_;
104 GUM_OP_CPY(NodeGraphPartIterator);
105
106 return *this;
107 }
108
112 nodes_ = it.nodes_;
113 pos_ = it.pos_;
114 valid_ = it.valid_;
115 GUM_OP_MOV(NodeGraphPartIterator);
116
117 return *this;
118 }
119
121 INLINE
123 return ((pos_ == it.pos_) && (valid_ == it.valid_) && (nodes_ == it.nodes_));
124 }
125
128 ++pos_;
129 validate_();
130 return *this;
131 }
132
135 if (!valid_) { GUM_ERROR(UndefinedIteratorValue, "This iterator is not valid !") }
136
137 return pos_;
138 }
139
140 // unsafe private method
141 INLINE void NodeGraphPartIterator::setPos_(NodeId id) noexcept {
142 pos_ = id;
143
144 if (pos_ >= nodes_->bound()) {
145 pos_ = nodes_->bound();
146 valid_ = false;
147 } else {
148 valid_ = nodes_->exists(pos_);
149 }
150 }
151
152 //=================NODEGRAPHPARTITERATORSAFE============================
153
155 INLINE
157 NodeGraphPartIterator(nodes) {
158 GUM_CONNECT(*const_cast< NodeGraphPart* >(&nodes),
159 onNodeDeleted,
160 *this,
162 GUM_CONSTRUCTOR(NodeGraphPartIteratorSafe);
163 }
164
166 INLINE
175
177 INLINE
186
191
195 // avoid self assignment
196 if (&it != this) {
198 Listener::operator=(it);
199 GUM_OP_CPY(NodeGraphPartIteratorSafe);
200 }
201
202 return *this;
203 }
204
208 // avoid self assignment
209 if (&it != this) {
211 Listener::operator=(std::move(it));
212 GUM_OP_MOV(NodeGraphPartIteratorSafe);
213 }
214
215 return *this;
216 }
217
218 //=================NODEGRAPHPART============================
219
221 // avoid self assignment
222 if (this != &p) { populateNodes(p); }
223
224 return *this;
225 }
226
228 if (this != &p) {
229 clearNodes();
230 _holes_ = p._holes_;
231 _holes_size_ = p._holes_size_;
232 _holes_resize_policy_ = p._holes_resize_policy_;
233 _boundVal_ = p._boundVal_;
234 _names_ = std::move(p._names_);
235 p._holes_ = nullptr;
236 p._boundVal_ = 0;
238 GUM_OP_MOV(NodeGraphPart);
239 }
240 return *this;
241 }
242
244 NodeId next = 0;
245
246 // return the first hole if holes exist
247 if (_holes_ && (!_holes_->empty())) next = *(_holes_->begin());
248 else // in other case
249 next = _boundVal_;
250
251 return next;
252 }
253
254 // _holes_ is assumed to be not nullptr and id is assumed to be in _holes_
256 _holes_->erase(id);
257
258 if (_holes_->empty()) {
259 delete _holes_;
260 _holes_ = nullptr;
261 }
262 }
263
264 // warning: do not try to use function addNodeWithId ( const NodeId id ) within
265 // function addNodeWithId(): as both functions are virtual, this may create
266 // bugs within the graphs hierarchy (i.e., virtual functions calling
267 // recursively
268 // each other along the hierarchy) that are not easy to debug.
270 NodeId newNode;
271
272 // fill the first hole if holes exist
273 if (_holes_ && (!_holes_->empty())) {
274 newNode = *(_holes_->begin());
275 _eraseHole_(newNode);
276 } else {
277 newNode = _boundVal_;
278 ++_boundVal_;
280 }
281
282 GUM_EMIT1(onNodeAdded, newNode);
283
284 return newNode;
285 }
286
287 INLINE std::vector< NodeId > NodeGraphPart::addNodes(Size N) {
288 std::vector< NodeId > v;
289 v.reserve(N);
290 for (Idx i = 0; i < N; i++)
291 v.push_back(this->addNode());
292 return v;
293 }
294
296 return (_holes_) ? (_boundVal_ - _holes_->size()) : _boundVal_;
297 }
298
299 INLINE Size NodeGraphPart::size() const { return sizeNodes(); }
300
301 INLINE bool NodeGraphPart::existsNode(const NodeId node) const {
302 if (node >= _boundVal_) return false;
303
304 return (!_inHoles_(node));
305 }
306
307 INLINE bool NodeGraphPart::exists(const NodeId node) const { return existsNode(node); }
308
309 INLINE void NodeGraphPart::eraseNode(const NodeId node) {
310 if (!existsNode(node)) return;
311
312 if (_names_ && _names_->existsFirst(node)) _names_->eraseFirst(node);
313
314 _addHole_(node);
315
317 }
318
319 INLINE bool NodeGraphPart::emptyNodes() const { return (sizeNodes() == 0); }
320
321 INLINE bool NodeGraphPart::empty() const { return emptyNodes(); }
322
323 INLINE NodeId NodeGraphPart::bound() const { return _boundVal_; }
324
326
327 // warning: clear is an alias for clearNodes but it should never be the case
328 // that the code of clear is just a call to clearNodes: as both methods are
329 // virtual, this could induce bugs within the graphs hierarchy (i.e., virtual
330 // functions calling recursively each other along the hierarchy) that are not
331 // easy to debug. Hence, the code of clearNodes should be duplicated here.
333
336 it.validate_(); // stop the iterator at the first not-in-holes
337 return it;
338 }
339
341
342 INLINE const NodeGraphPartIteratorSafe& NodeGraphPart::endSafe() const noexcept {
343 return _endIteratorSafe_;
344 }
345
347 NodeGraphPartIterator it(*this);
348 it.validate_(); // stop the iterator at the first not-in-holes
349 return it;
350 }
351
352 INLINE const NodeGraphPartIterator& NodeGraphPart::end() const noexcept {
353 return _endIteratorSafe_;
354 }
355
356 INLINE bool NodeGraphPart::operator==(const NodeGraphPart& p) const {
357 if (_boundVal_ != p._boundVal_) return false;
358
359 if (_holes_)
360 if (p._holes_) return (*_holes_ == *p._holes_);
361 else return false;
362 else if (p._holes_) return false;
363
364 return true;
365 }
366
368 NodeSet son(sizeNodes());
369
370 if (!empty()) {
371 for (NodeId n = 0; n < _boundVal_; ++n) {
372 if (!_inHoles_(n)) son.insert(n);
373 }
374 }
375
376 return son;
377 }
378
379 INLINE const NodeGraphPart& NodeGraphPart::nodes() const {
380 return *(static_cast< const NodeGraphPart* >(this));
381 }
382
383 INLINE bool NodeGraphPart::_inHoles_(NodeId id) const { return _holes_ && _holes_->contains(id); }
384
386 INLINE Size NodeGraphPart::_sizeHoles_() const { return _holes_ ? _holes_->size() : (Size)0; }
387
389 INLINE std::unique_ptr< Bijection< NodeId, std::string > > NodeGraphPart::_cloneNames_() const {
390 return _names_ ? std::make_unique< Bijection< NodeId, std::string > >(*_names_) : nullptr;
391 }
392
393} /* namespace gum */
Safe iterator on the node set of a graph.
~NodeGraphPartIteratorSafe() final
destructor
NodeGraphPartIteratorSafe & operator=(const NodeGraphPartIteratorSafe &it)
copy assignment operator
void whenNodeDeleted(const void *src, NodeId id)
called when a node is deleted in the iterated NodeGraphPart
NodeGraphPartIteratorSafe(const NodeGraphPart &nodes)
default constructor
Unsafe iterator on the node set of a graph.
bool operator==(const NodeGraphPartIterator &it) const noexcept
checks whether two iterators point toward the same node
void setPos_(NodeId id) noexcept
this function is used by NodeGraphPart to update
void validate_() noexcept
ensure that the nodeId is either end() either a valid NodeId
virtual ~NodeGraphPartIterator() noexcept
destructor
NodeGraphPartIterator(const NodeGraphPart &nodes) noexcept
Default constructor.
NodeGraphPartIterator & operator++() noexcept
increment the iterator
const NodeGraphPart * nodes_
the nodegraphpart on which points the iterator
NodeGraphPartIterator & operator=(const NodeGraphPartIterator &it) noexcept
copy assignment operator
NodeId pos_
the nodeid on which the iterator points currently
value_type operator*() const
dereferencing operator
NodeGraphPartIteratorSafe _endIteratorSafe_
the end iterator (used to speed-up parsings of the NodeGraphPart)
Size size() const
alias for sizeNodes
void populateNodes(const NodeGraphPart &s)
populateNodes clears *this and fills it with the same nodes as "s"
Signaler< NodeId > onNodeDeleted
void _clearNodes_()
code for clearing nodes (called twice)
virtual void clear()
alias for clearNodes
Size sizeNodes() const
returns the number of nodes in the NodeGraphPart
std::unique_ptr< Bijection< NodeId, std::string > > _names_
optional node names — null when no name has been set
NodeId bound() const
returns a number n such that all node ids are strictly lower than n
void _eraseHole_(NodeId id)
to delete hole.
const NodeGraphPart & nodes() const
return *this as a NodeGraphPart
friend class NodeGraphPartIterator
void _updateEndIteratorSafe_()
updating endIterator (always at max+1)
virtual void eraseNode(const NodeId id)
erase the node with the given id
Size _holes_size_
value for holes configuration
node_iterator_safe beginSafe() const
a begin iterator to parse the set of nodes contained in the NodeGraphPart
NodeGraphPart & operator=(const NodeGraphPart &p)
copy operator
NodeSet asNodeSet() const
returns a copy of the set of nodes represented by the NodeGraphPart
bool exists(const NodeId id) const
alias for existsNode
bool emptyNodes() const
indicates whether there exists nodes in the NodeGraphPart
const node_iterator_safe & endSafe() const noexcept
the end iterator to parse the set of nodes contained in the NodeGraphPart
bool empty() const
alias for emptyNodes
NodeId nextNodeId() const
returns a new node id, not yet used by any node
bool _holes_resize_policy_
value for holes configuration
std::unique_ptr< Bijection< NodeId, std::string > > _cloneNames_() const
clone the names bijection (returns nullptr when no name has been set)
NodeSet * _holes_
the set of nodes not contained in the NodeGraphPart in the interval 1.
Signaler< NodeId > onNodeAdded
virtual void clearNodes()
remove all the nodes from the NodeGraphPart
friend class NodeGraphPartIteratorSafe
virtual NodeId addNode()
insert a new node and return its id
node_iterator begin() const noexcept
a begin iterator to parse the set of nodes contained in the NodeGraphPart
NodeId _boundVal_
the id below which NodeIds may belong to the NodeGraphPart
NodeGraphPart(Size holes_size=HashTableConst::default_size, bool holes_resize_policy=true)
default constructor
const node_iterator & end() const noexcept
the end iterator to parse the set of nodes contained in the NodeGraphPart
void _addHole_(NodeId id)
to add a hole.
bool _inHoles_(NodeId id) const
bool existsNode(const NodeId id) const
returns true iff the NodeGraphPart contains the given nodeId
bool operator==(const NodeGraphPart &p) const
check whether two NodeGraphParts contain the same nodes
std::vector< NodeId > addNodes(Size n)
insert n nodes
void insert(const Key &k)
Inserts a new element into the set.
Definition set_tpl.h:510
Exception : generic error on iterator.
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition types.h:74
Size Idx
Type for indexes.
Definition types.h:79
Size NodeId
Type for node ids.
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
#define GUM_CONNECT(sender, signal, receiver, target)
Definition listener.h:117
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
STL namespace.
Base node set class for graphs.
#define GUM_EMIT1(signal, arg1)
Definition signaler.h:289