aGrUM  0.21.0
a C++ library for (probabilistic) graphical models
nodeGraphPart.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /** @file
23  * @brief Base node set class for graphs
24  *
25  * @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
26  */
27 #ifndef GUM_NODE_GRAPH_PART_H
28 #define GUM_NODE_GRAPH_PART_H
29 
30 #include <algorithm>
31 #include <utility>
32 
33 #include <agrum/agrum.h>
34 
35 #include <agrum/tools/graphs/graphElements.h>
36 
37 #include <agrum/tools/core/signal/listener.h>
38 #include <agrum/tools/core/signal/signaler.h>
39 
40 #ifndef DOXYGEN_SHOULD_SKIP_THIS
41 
42 namespace gum_tests {
43 
44  class NodeGraphPartTestSuite;
45 }
46 
47 #endif
48 
49 namespace gum {
50 
51  class NodeGraphPart;
52 
53  /**
54  * @class NodeGraphPartIterator
55  * @brief Unsafe iterator on the node set of a graph.
56  */
58  friend class NodeGraphPart;
59 
60  public:
61  /// types for STL compliance
62  /// @{
63  using iterator_category = std::forward_iterator_tag;
64  using value_type = NodeId;
66  using const_reference = const value_type&;
67  using pointer = value_type*;
68  using const_pointer = const value_type*;
69  using difference_type = std::ptrdiff_t;
70  /// @}
71 
72  // ############################################################################
73  /// @name Constructors / Destructors
74  // ############################################################################
75  /// @{
76 
77  /**
78  * @brief Default constructor.
79  */
80  NodeGraphPartIterator(const NodeGraphPart& nodes) noexcept;
81 
82  /// copy constructor
83  NodeGraphPartIterator(const NodeGraphPartIterator& it) noexcept;
84 
85  /// move constructor
87 
88  /// destructor
89  virtual ~NodeGraphPartIterator() noexcept;
90 
91  /// @}
92 
93  // ############################################################################
94  /// @name Operators
95  // ############################################################################
96  /// @{
97 
98  /// copy assignment operator
100 
101  /// move assignment operator
103 
104  /// checks whether two iterators point toward the same node
105  bool operator==(const NodeGraphPartIterator& it) const noexcept;
106 
107  /// checks whether two iterators point toward different nodes
108  bool operator!=(const NodeGraphPartIterator& it) const noexcept;
109 
110  /// increment the iterator
111  NodeGraphPartIterator& operator++() noexcept;
112 
113  /// dereferencing operator
114  value_type operator*() const;
115 
116  /// @}
117 
118  protected:
119  /// @brief this function is used by @ref NodeGraphPart to update
120  void setPos_(NodeId id) noexcept;
121 
122  /// ensure that the nodeId is either end() either a valid NodeId
123  void validate_() noexcept;
124 
125  /// the nodegraphpart on which points the iterator
127 
128  /// the nodeid on which the iterator points currently
130 
131  // is this iterator still valid ?
132  bool valid_{false};
133  };
134 
135  /**
136  * @class NodeGraphPartIteratorSafe
137  * @brief Safe iterator on the node set of a graph.
138  */
140  friend class NodeGraphPart;
141 
142  public:
143  /// types for STL compliance
144  /// @{
145  using iterator_category = std::forward_iterator_tag;
148  using const_reference = const value_type&;
149  using pointer = value_type*;
150  using const_pointer = const value_type*;
151  using difference_type = std::ptrdiff_t;
152  /// @}
153 
154  // ############################################################################
155  /// @name Constructors / Destructors
156  // ############################################################################
157  /// @{
158 
159  /// default constructor
161 
162  /// copy constructor
164 
165  /// move constructor
167 
168  /// destructor
170 
171  /// @}
172 
173  // ############################################################################
174  /// @name Operators
175  // ############################################################################
176  /// @{
177 
178  /// copy assignment operator
180 
181  /// move assignment operator
183 
184  /// @}
185 
186  // ############################################################################
187  /// @name Accessors / Modifiers
188  // ############################################################################
189  /// @{
190 
191  /// called when a node is deleted in the iterated NodeGraphPart
192  /**
193  * @param src the NodeGraphPart
194  * @param id id of deleted node
195  */
196  void whenNodeDeleted(const void* src, NodeId id);
197 
198  /// @}
199  };
200 
201  /**
202  * @class NodeGraphPart
203  * @brief Class for node sets in graph
204  *
205  * @ingroup graph_group
206  *
207  * NodeGraphPart represents the set of nodes of all the graphs. It is built to
208  * be as light as possible and it implements its own NodeId factory.
209  * The set of NodeId is 0 ... ( _bound_-1) minus the NodeIds in
210  * _holes_.
211  *
212  * @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
213  *
214  *
215  * @par Usage example:
216  * @code
217  * // create an empty node list
218  * NodeGraphPart nodes1;
219  *
220  * // add 2 elements
221  * NodeId id_a=nodes1.addNode( );
222  * NodeId id_b=nodes1.addNode( );
223  *
224  * // checks if there exists a node with ID = 6
225  * if ( !nodes1.exists( 6 ) ) std::cerr << "no node with ID 6" << std::endl;
226  *
227  * // check if the set of nodes is empty
228  * if ( !nodes1.empty() || ( nodes1.size() != 0 ) )
229  * std::cerr << "nodes1 is not empty" << std::endl;
230  *
231  * // copy a set of nodes
232  * NodeGraphPart nodes2 = nodes1, nodes3;
233  * nodes3 = nodes1;
234  *
235  * // remove elements from list3
236  * nodes3.eraseNode( id_a );
237  * nodes3.eraseNode( id_b );
238  *
239  * // remove all the elements from the list
240  * nodes1.clear();
241  *
242  * for ( NodeGraphPart::iterator it=nodes2.beginNodes();
243  * it!=nodes2.endNodes();++it ) {
244  * std::cerr<<*it<<" ";
245  * }
246  *
247  * std::cerr<<"list : "<<nodes2.listMapNodes(getDouble)<<std::endl;
248  *
249  * std::cerr<<"hashmap : "<<nodes2.hashMapNodes(getDouble)<<std::endl;
250  * @endcode
251  */
252 
254  public:
255  /// types for STL compliance
256  /// @{
257  using node_iterator = NodeGraphPartIterator;
258  using node_const_iterator = NodeGraphPartIterator;
259  using node_iterator_safe = NodeGraphPartIteratorSafe;
260  using node_const_iterator_safe = NodeGraphPartIteratorSafe;
261  /// @}
262 
263  // something strange with SWIG (with "using", these definitions cored dump
264  // the
265  // swig process)
270 
273 
274  // ############################################################################
275  /// @name Constructors / Destructors
276  // ############################################################################
277  /// @{
278 
279  /// default constructor
280  /** A NodeGrphPart does not store all its nodes. To be lighter in terms of
281  * memory consumption, it store its maximal NodeId and the set of NodeIds
282  * between 0 and this maximum that do not actually belong to the set of its
283  * nodes (the so-called set of holes). In practice, it turns out that the
284  * set of holes is most often very small.
285  * @param holes_size the size of the hash table used to store all holes
286  * @param holes_resize_policy the resizing policy of this hash table**/
287  explicit NodeGraphPart(Size holes_size = HashTableConst::default_size,
288  bool holes_resize_policy = true);
289 
290  /// copy constructor
291  /** @param s the NodeGraphPart to be copied */
292  NodeGraphPart(const NodeGraphPart& s);
293 
294  /// destructor
295  virtual ~NodeGraphPart();
296 
297  /// @}
298 
299  // ############################################################################
300  /// @name Operators
301  // ############################################################################
302  /// @{
303 
304  /// copy operator
305  /** @param p the NodeGraphPart to be copied */
307 
308  /// check whether two NodeGraphParts contain the same nodes
309  /** @param p the NodeGraphPart to be compared with "this" */
310  bool operator==(const NodeGraphPart& p) const;
311 
312  /// check whether two NodeGraphParts contain different nodes
313  /** @param p the NodeGraphPart to be compared with "this" */
314  bool operator!=(const NodeGraphPart& p) const;
315 
316  /// @}
317 
318  // ############################################################################
319  /// @name Accessors/Modifiers
320  // ############################################################################
321  /// @{
322 
323  /// populateNodes clears *this and fills it with the same nodes as "s"
324  /** populateNodes should basically be the preferred way to insert nodes with
325  * IDs not selected by the internal idFactory.
326  * @param s the NodeGraphPart to be copied */
327  void populateNodes(const NodeGraphPart& s);
328 
329  /// populateNodesFromProperty clears *this and fills it with the keys of "h"
330  /** populateNodes should basically be the preferred way to insert nodes with
331  * IDs not selected by the internal idFactory. */
332  template < typename T >
333  void populateNodesFromProperty(const NodeProperty< T >& h);
334 
335  /** returns a new node id, not yet used by any node
336  * @warning a code like @code id=nextNodeId();addNode(id); @endcode is
337  * basically not thread safe !!
338  * @return a node id not yet used by any node within the NodeGraphPart */
339  NodeId nextNodeId() const;
340 
341  /// insert a new node and return its id
342  /** @return the id chosen by the internal idFactory */
343  virtual NodeId addNode();
344 
345  /** insert n nodes
346  *
347  * @param n the number of nodes to add
348  * @return the vector of chosen ids
349  */
351 
352  /// try to insert a node with the given id
353  /** @warning This method should be carefully used. Please prefer
354  * @ref populateNodes or @ref populateNodesFromProperty when possible
355  * @throws DuplicateElement exception if the id already exists
356  */
357  virtual void addNodeWithId(const NodeId id);
358 
359  /// erase the node with the given id
360  /** If the NodeGraphPart does not contain the nodeId, then nothing is done.
361  * In
362  * particular, no exception is raised. However, the signal onNodeDeleted is
363  * fired only if a node is effectively removed. */
364  virtual void eraseNode(const NodeId id);
365 
366  /// returns true iff the NodeGraphPart contains the given nodeId
367  bool existsNode(const NodeId id) const;
368 
369  /// alias for @ref existsNode
370  bool exists(const NodeId id) const;
371 
372  /// indicates whether there exists nodes in the NodeGraphPart
373  bool emptyNodes() const;
374 
375  /// alias for @ref emptyNodes
376  bool empty() const;
377 
378  /// remove all the nodes from the NodeGraphPart
379  virtual void clearNodes();
380 
381  /// alias for @ref clearNodes
382  virtual void clear();
383 
384  /// returns the number of nodes in the NodeGraphPart
385  Size sizeNodes() const;
386 
387  /// alias for @ref sizeNodes
388  Size size() const;
389 
390  /// returns a number n such that all node ids are strictly lower than n
391  NodeId bound() const;
392 
393  /// returns a copy of the set of nodes represented by the NodeGraphPart
394  /** @warning this function is o(n) where n is the number of nodes. In space
395  * and
396  * in time. Usually, when you need to parse the nodes of a NodeGraphPart,
397  * prefer
398  * using @code for(const auto n : nodes()) @endcode rather than
399  * @code for(const auto n : asNodeSet()) @endcode as this is faster and
400  * consumes much less memory. */
401  NodeSet asNodeSet() const;
402 
403  /// return *this as a NodeGraphPart
404  const NodeGraphPart& nodes() const;
405 
406  /// a begin iterator to parse the set of nodes contained in the
407  /// NodeGraphPart
408  node_iterator_safe beginSafe() const;
409 
410  /// the end iterator to parse the set of nodes contained in the
411  /// NodeGraphPart
412  const node_iterator_safe& endSafe() const noexcept;
413 
414  /// a begin iterator to parse the set of nodes contained in the
415  /// NodeGraphPart
416  node_iterator begin() const noexcept;
417 
418  /// the end iterator to parse the set of nodes contained in the
419  /// NodeGraphPart
420  const node_iterator& end() const noexcept;
421 
422  virtual /// a function to display the set of nodes
423  std::string
424  toString() const;
425 
426  /// a method to create a HashTable with key:NodeId and value:VAL
427  /** VAL are computed from the nodes using for all node x, VAL f(x).
428  * This method is a wrapper of the same method in HashTable.
429  * @see HashTable::map.
430  * @param f a function assigning a VAL to any node
431  * @param size an optional parameter enabling to fine-tune the returned
432  * Property. Roughly speaking, it is a good practice to have a size equal to
433  * half the number of nodes. If you do not specify this parameter, the
434  * method
435  * will assign it for you. */
436  template < typename VAL >
437  NodeProperty< VAL > nodesProperty(VAL (*f)(const NodeId&), Size size = 0) const;
438 
439  /// a method to create a hashMap with key:NodeId and value:VAL
440  /** for all nodes, the value stored is a. This method is a wrapper of the
441  * same
442  * method in HashTable.
443  * @see HashTable::map.
444  * @param a the default value assigned to each edge in the returned Property
445  * @param size an optional parameter enabling to fine-tune the returned
446  * Property. Roughly speaking, it is a good practice to have a size equal to
447  * half the number of nodes. If you do not specify this parameter, the
448  * method
449  * will assign it for you. */
450  template < typename VAL >
451  NodeProperty< VAL > nodesProperty(const VAL& a, Size size = 0) const;
452 
453  /** @brief a method to create a list of VAL from a set of nodes
454  * (using for every nodee, say x, the VAL f(x))
455  * @param f a function assigning a VAL to any node */
456  template < typename VAL >
457  List< VAL > listMapNodes(VAL (*f)(const NodeId&)) const;
458 
459  /// @}
460 
461  private:
462  friend class NodeGraphPartIterator;
464 
465  /// to enable testunits to use _check_
466 
467  friend class gum_tests::NodeGraphPartTestSuite;
468 
469  /// updating endIterator (always at _max_+1)
471 
472  /// code for clearing nodes (called twice)
473  void _clearNodes_();
474 
475  /// to delete hole.
476  /// @warning the hole is assumed to be existing.
477  void _eraseHole_(NodeId id);
478 
479  /// to add a hole.
480  /// @warning id is assumed not to be already a hole
481  void _addHole_(NodeId id);
482 
483  // ############################################################################
484  /// @name Introspection
485  // ############################################################################
486  /// @{
487 
488  /// @return true if id is part of _holes_
489  bool _inHoles_(NodeId id) const;
490 
491  /// @return the size of _holes_
492  Size _sizeHoles_() const;
493 
494  /// @}
495 
496  /** @brief the set of nodes not contained in the NodeGraphPart in the
497  * interval 1.. _max_
498  * @warning _holes_ may be nullptr. */
500 
501  /// value for _holes_ configuration
503 
504  /// value for _holes_ configuration
506 
507  /// the end iterator (used to speed-up parsings of the NodeGraphPart)
509 
510  /** @brief the id below which NodeIds may belong to the NodeGraphPart */
512  };
513 
514  /// for friendly displaying the content of node set
515  std::ostream& operator<<(std::ostream&, const NodeGraphPart&);
516 
517 } /* namespace gum */
518 
519 #ifndef GUM_NO_INLINE
520 # include <agrum/tools/graphs/parts/nodeGraphPart_inl.h>
521 #endif // GUM_NOINLINE
522 
523 #include <agrum/tools/graphs/parts/nodeGraphPart_tpl.h>
524 
525 #endif // GUM_NODE_GRAPH_PART_H
NodeGraphPart & operator=(const NodeGraphPart &p)
copy operator
NodeGraphPartIterator(const NodeGraphPartIterator &it) noexcept
copy constructor
NodeSet * _holes_
the set of nodes not contained in the NodeGraphPart in the interval 1.
NodeProperty< VAL > nodesProperty(const VAL &a, Size size=0) const
a method to create a hashMap with key:NodeId and value:VAL
virtual void addNodeWithId(const NodeId id)
try to insert a node with the given id
NodeId _boundVal_
the id below which NodeIds may belong to the NodeGraphPart
node_iterator_safe beginSafe() const
a begin iterator to parse the set of nodes contained in the NodeGraphPart
void _updateEndIteratorSafe_()
updating endIterator (always at max+1)
NodeGraphPartIterator NodeConstIterator
NodeGraphPartIterator & operator=(const NodeGraphPartIterator &it) noexcept
copy assignment operator
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
NodeGraphPartIteratorSafe(NodeGraphPartIteratorSafe &&it)
move constructor
NodeGraphPartIteratorSafe & operator=(const NodeGraphPartIteratorSafe &it)
copy assignment operator
Size size() const
alias for sizeNodes
NodeGraphPartIterator(NodeGraphPartIterator &&it) noexcept
move constructor
NodeGraphPartIteratorSafe NodeIteratorSafe
List< VAL > listMapNodes(VAL(*f)(const NodeId &)) const
a method to create a list of VAL from a set of nodes (using for every nodee, say x, the VAL f(x))
void setPos_(NodeId id) noexcept
this function is used by NodeGraphPart to update
NodeProperty< VAL > nodesProperty(VAL(*f)(const NodeId &), Size size=0) const
a method to create a HashTable with key:NodeId and value:VAL
NodeGraphPart(const NodeGraphPart &s)
copy constructor
bool exists(const NodeId id) const
alias for existsNode
virtual NodeId addNode()
insert a new node and return its id
void _addHole_(NodeId id)
to add a hole.
bool operator!=(const NodeGraphPartIterator &it) const noexcept
checks whether two iterators point toward different nodes
bool operator==(const NodeGraphPart &p) const
check whether two NodeGraphParts contain the same nodes
virtual ~NodeGraphPart()
destructor
NodeGraphPartIteratorSafe NodeConstIteratorSafe
void validate_() noexcept
ensure that the nodeId is either end() either a valid NodeId
bool empty() const
alias for emptyNodes
bool emptyNodes() const
indicates whether there exists nodes in the NodeGraphPart
void _clearNodes_()
code for clearing nodes (called twice)
node_iterator begin() const noexcept
a begin iterator to parse the set of nodes contained in the NodeGraphPart
Unsafe iterator on the node set of a graph.
Definition: nodeGraphPart.h:57
NodeGraphPartIteratorSafe _endIteratorSafe_
the end iterator (used to speed-up parsings of the NodeGraphPart)
NodeGraphPart(Size holes_size=HashTableConst::default_size, bool holes_resize_policy=true)
default constructor
Size _holes_size_
value for holes configuration
Size _sizeHoles_() const
NodeGraphPartIteratorSafe(const NodeGraphPart &nodes)
default constructor
value_type operator*() const
dereferencing operator
Signaler1< NodeId > onNodeAdded
NodeSet asNodeSet() const
returns a copy of the set of nodes represented by the NodeGraphPart
void populateNodesFromProperty(const NodeProperty< T > &h)
populateNodesFromProperty clears *this and fills it with the keys of "h"
NodeGraphPartIterator & operator++() noexcept
increment the iterator
const NodeGraphPart & nodes() const
return *this as a NodeGraphPart
std::vector< NodeId > addNodes(Size n)
insert n nodes
virtual std::string toString() const
a function to display the set of nodes
NodeId pos_
the nodeid on which the iterator points currently
NodeGraphPartIterator NodeIterator
virtual void clear()
alias for clearNodes
bool existsNode(const NodeId id) const
returns true iff the NodeGraphPart contains the given nodeId
Size sizeNodes() const
returns the number of nodes in the NodeGraphPart
NodeGraphPartIteratorSafe & operator=(NodeGraphPartIteratorSafe &&it)
move assignment operator
bool operator==(const NodeGraphPartIterator &it) const noexcept
checks whether two iterators point toward the same node
NodeId bound() const
returns a number n such that all node ids are strictly lower than n
NodeGraphPartIterator & operator=(NodeGraphPartIterator &&it) noexcept
move assignment operator
bool _inHoles_(NodeId id) const
NodeGraphPartIteratorSafe(const NodeGraphPartIteratorSafe &it)
copy constructor
virtual void clearNodes()
remove all the nodes from the NodeGraphPart
const node_iterator_safe & endSafe() const noexcept
the end iterator to parse the set of nodes contained in the NodeGraphPart
NodeId nextNodeId() const
returns a new node id, not yet used by any node
bool operator!=(const NodeGraphPart &p) const
check whether two NodeGraphParts contain different nodes
void populateNodes(const NodeGraphPart &s)
populateNodes clears *this and fills it with the same nodes as "s"
virtual ~NodeGraphPartIterator() noexcept
destructor
Signaler1< NodeId > onNodeDeleted
friend class NodeGraphPartIteratorSafe
NodeGraphPartIterator(const NodeGraphPart &nodes) noexcept
Default constructor.
Safe iterator on the node set of a graph.
void _eraseHole_(NodeId id)
to delete hole.
const node_iterator & end() const noexcept
the end iterator to parse the set of nodes contained in the NodeGraphPart
void whenNodeDeleted(const void *src, NodeId id)
called when a node is deleted in the iterated NodeGraphPart
const NodeGraphPart * nodes_
the nodegraphpart on which points the iterator
bool _holes_resize_policy_
value for holes configuration
virtual void eraseNode(const NodeId id)
erase the node with the given id