aGrUM 2.3.2
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-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#pragma once
41
42
49
50// to ease parsing by IDE
52
53namespace gum {
54
55 //=================NODEGRAPHPARTITERATOR============================
56
58 INLINE void NodeGraphPartIterator::validate_() noexcept {
59 valid_ = false;
60
61 if (pos_ > nodes_->bound()) { pos_ = nodes_->bound(); }
62
63 while (pos_ < nodes_->bound()) {
64 if (!nodes_->_inHoles_(pos_)) {
65 valid_ = true;
66 return;
67 }
68
69 ++pos_;
70 }
71 }
72
74 INLINE
76 nodes_(&nodes) {
77 GUM_CONSTRUCTOR(NodeGraphPartIterator);
78 }
79
82 nodes_(it.nodes_), pos_(it.pos_), valid_(it.valid_) {
83 GUM_CONS_CPY(NodeGraphPartIterator);
84 }
85
88 nodes_(it.nodes_), pos_(it.pos_), valid_(it.valid_) {
89 GUM_CONS_MOV(NodeGraphPartIterator);
90 }
91
94 GUM_DESTRUCTOR(NodeGraphPartIterator);
95 }
96
100 nodes_ = it.nodes_;
101 pos_ = it.pos_;
102 valid_ = it.valid_;
103 GUM_OP_CPY(NodeGraphPartIterator);
104
105 return *this;
106 }
107
111 nodes_ = it.nodes_;
112 pos_ = it.pos_;
113 valid_ = it.valid_;
114 GUM_OP_MOV(NodeGraphPartIterator);
115
116 return *this;
117 }
118
120 INLINE
122 return ((pos_ == it.pos_) && (valid_ == it.valid_) && (nodes_ == it.nodes_));
123 }
124
126 INLINE
128 return !(operator==(it));
129 }
130
133 ++pos_;
134 validate_();
135 return *this;
136 }
137
140 if (!valid_) { GUM_ERROR(UndefinedIteratorValue, "This iterator is not valid !") }
141
142 return pos_;
143 }
144
145 // unsafe private method
146 INLINE void NodeGraphPartIterator::setPos_(NodeId id) noexcept {
147 pos_ = id;
148
149 if (pos_ >= nodes_->bound()) {
150 pos_ = nodes_->bound();
151 valid_ = false;
152 } else {
153 valid_ = nodes_->exists(pos_);
154 }
155 }
156
157 //=================NODEGRAPHPARTITERATORSAFE============================
158
160 INLINE
162 NodeGraphPartIterator(nodes) {
163 GUM_CONNECT(*const_cast< NodeGraphPart* >(&nodes),
164 onNodeDeleted,
165 *this,
167 GUM_CONSTRUCTOR(NodeGraphPartIteratorSafe);
168 }
169
171 INLINE
180
182 INLINE
191
196
200 // avoid self assignment
201 if (&it != this) {
203 Listener::operator=(it);
204 GUM_OP_CPY(NodeGraphPartIteratorSafe);
205 }
206
207 return *this;
208 }
209
213 // avoid self assignment
214 if (&it != this) {
216 Listener::operator=(std::move(it));
217 GUM_OP_MOV(NodeGraphPartIteratorSafe);
218 }
219
220 return *this;
221 }
222
223 //=================NODEGRAPHPART============================
224
226 // avoid self assignment
227 if (this != &p) { populateNodes(p); }
228
229 return *this;
230 }
231
233 NodeId next = 0;
234
235 // return the first hole if holes exist
236 if (_holes_ && (!_holes_->empty())) next = *(_holes_->begin());
237 else // in other case
238 next = _boundVal_;
239
240 return next;
241 }
242
243 // _holes_ is assumed to be not nullptr and id is assumed to be in _holes_
245 _holes_->erase(id);
246
247 if (_holes_->empty()) {
248 delete _holes_;
249 _holes_ = nullptr;
250 }
251 }
252
253 // warning: do not try to use function addNodeWithId ( const NodeId id ) within
254 // function addNodeWithId(): as both functions are virtual, this may create
255 // bugs within the graphs hierarchy (i.e., virtual functions calling
256 // recursively
257 // each other along the hierarchy) that are not easy to debug.
259 NodeId newNode;
260
261 // fill the first hole if holes exist
262 if (_holes_ && (!_holes_->empty())) {
263 newNode = *(_holes_->begin());
264 _eraseHole_(newNode);
265 } else {
266 newNode = _boundVal_;
267 ++_boundVal_;
269 }
270
271 GUM_EMIT1(onNodeAdded, newNode);
272
273 return newNode;
274 }
275
276 INLINE std::vector< NodeId > NodeGraphPart::addNodes(Size N) {
277 std::vector< NodeId > v;
278 v.reserve(N);
279 for (Idx i = 0; i < N; i++)
280 v.push_back(this->addNode());
281 return v;
282 }
283
285 return (_holes_) ? (_boundVal_ - _holes_->size()) : _boundVal_;
286 }
287
288 INLINE Size NodeGraphPart::size() const { return sizeNodes(); }
289
290 INLINE bool NodeGraphPart::existsNode(const NodeId node) const {
291 if (node >= _boundVal_) return false;
292
293 return (!_inHoles_(node));
294 }
295
296 INLINE bool NodeGraphPart::exists(const NodeId node) const { return existsNode(node); }
297
298 INLINE void NodeGraphPart::eraseNode(const NodeId node) {
299 if (!existsNode(node)) return;
300
301 _addHole_(node);
302
304 }
305
306 INLINE bool NodeGraphPart::emptyNodes() const { return (sizeNodes() == 0); }
307
308 INLINE bool NodeGraphPart::empty() const { return emptyNodes(); }
309
310 INLINE NodeId NodeGraphPart::bound() const { return _boundVal_; }
311
313
314 // warning: clear is an alias for clearNodes but it should never be the case
315 // that the code of clear is just a call to clearNodes: as both methods are
316 // virtual, this could induce bugs within the graphs hierarchy (i.e., virtual
317 // functions calling recursively each other along the hierarchy) that are not
318 // easy to debug. Hence, the code of clearNodes should be duplicated here.
320
323 it.validate_(); // stop the iterator at the first not-in-holes
324 return it;
325 }
326
328
329 INLINE const NodeGraphPartIteratorSafe& NodeGraphPart::endSafe() const noexcept {
330 return _endIteratorSafe_;
331 }
332
334 NodeGraphPartIterator it(*this);
335 it.validate_(); // stop the iterator at the first not-in-holes
336 return it;
337 }
338
339 INLINE const NodeGraphPartIterator& NodeGraphPart::end() const noexcept {
340 return _endIteratorSafe_;
341 }
342
343 INLINE bool NodeGraphPart::operator==(const NodeGraphPart& p) const {
344 if (_boundVal_ != p._boundVal_) return false;
345
346 if (_holes_)
347 if (p._holes_) return (*_holes_ == *p._holes_);
348 else return false;
349 else if (p._holes_) return false;
350
351 return true;
352 }
353
354 INLINE bool NodeGraphPart::operator!=(const NodeGraphPart& p) const { return !operator==(p); }
355
357 NodeSet son(sizeNodes());
358
359 if (!empty()) {
360 for (NodeId n = 0; n < _boundVal_; ++n) {
361 if (!_inHoles_(n)) son.insert(n);
362 }
363 }
364
365 return son;
366 }
367
368 INLINE const NodeGraphPart& NodeGraphPart::nodes() const {
369 return *(static_cast< const NodeGraphPart* >(this));
370 }
371
372 INLINE bool NodeGraphPart::_inHoles_(NodeId id) const { return _holes_ && _holes_->contains(id); }
373
375 INLINE Size NodeGraphPart::_sizeHoles_() const { return _holes_ ? _holes_->size() : (Size)0; }
376
377} /* namespace gum */
Safe iterator on the node set of a graph.
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
bool operator!=(const NodeGraphPartIterator &it) const noexcept
checks whether two iterators point toward different nodes
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)
Signaler1< NodeId > onNodeDeleted
Size size() const
alias for sizeNodes
void populateNodes(const NodeGraphPart &s)
populateNodes clears *this and fills it with the same nodes as "s"
Signaler1< NodeId > onNodeAdded
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
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
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
NodeSet * _holes_
the set of nodes not contained in the NodeGraphPart in the interval 1.
virtual void clearNodes()
remove all the nodes from the NodeGraphPart
friend class NodeGraphPartIteratorSafe
virtual NodeId addNode()
insert a new node and return its id
bool operator!=(const NodeGraphPart &p) const
check whether two NodeGraphParts contain different nodes
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:539
Exception : generic error on iterator.
#define GUM_ERROR(type, msg)
Definition exceptions.h:72
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
bool operator==(const HashTableIteratorSafe< Key, Val > &from) const noexcept
Checks whether two iterators are pointing toward equal elements.
STL namespace.
Base node set class for graphs.
#define GUM_EMIT1(signal, arg1)
Definition signaler1.h:61