aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
nodeGraphPart.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 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&),
438  Size size = 0) const;
439 
440  /// a method to create a hashMap with key:NodeId and value:VAL
441  /** for all nodes, the value stored is a. This method is a wrapper of the
442  * same
443  * method in HashTable.
444  * @see HashTable::map.
445  * @param a the default value assigned to each edge in the returned Property
446  * @param size an optional parameter enabling to fine-tune the returned
447  * Property. Roughly speaking, it is a good practice to have a size equal to
448  * half the number of nodes. If you do not specify this parameter, the
449  * method
450  * will assign it for you. */
451  template < typename VAL >
452  NodeProperty< VAL > nodesProperty(const VAL& a, Size size = 0) const;
453 
454  /** @brief a method to create a list of VAL from a set of nodes
455  * (using for every nodee, say x, the VAL f(x))
456  * @param f a function assigning a VAL to any node */
457  template < typename VAL >
458  List< VAL > listMapNodes(VAL (*f)(const NodeId&)) const;
459 
460  /// @}
461 
462  private:
463  friend class NodeGraphPartIterator;
465 
466  /// to enable testunits to use check__
467 
468  friend class gum_tests::NodeGraphPartTestSuite;
469 
470  /// updating endIterator (always at max__+1)
472 
473  /// code for clearing nodes (called twice)
474  void clearNodes__();
475 
476  /// to delete hole.
477  /// @warning the hole is assumed to be existing.
478  void eraseHole__(NodeId id);
479 
480  /// to add a hole.
481  /// @warning id is assumed not to be already a hole
482  void addHole__(NodeId id);
483 
484  // ############################################################################
485  /// @name Introspection
486  // ############################################################################
487  /// @{
488 
489  /// @return true if id is part of holes__
490  bool inHoles__(NodeId id) const;
491 
492  /// @return the size of holes__
493  Size sizeHoles__() const;
494 
495  /// @}
496 
497  /** @brief the set of nodes not contained in the NodeGraphPart in the
498  * interval 1..max__
499  * @warning holes__ may be nullptr. */
501 
502  /// value for holes__ configuration
504 
505  /// value for holes__ configuration
507 
508  /// the end iterator (used to speed-up parsings of the NodeGraphPart)
510 
511  /** @brief the id below which NodeIds may belong to the NodeGraphPart */
513  };
514 
515  /// for friendly displaying the content of node set
516  std::ostream& operator<<(std::ostream&, const NodeGraphPart&);
517 
518 } /* namespace gum */
519 
520 #ifndef GUM_NO_INLINE
521 # include <agrum/tools/graphs/parts/nodeGraphPart_inl.h>
522 #endif // GUM_NOINLINE
523 
524 #include <agrum/tools/graphs/parts/nodeGraphPart_tpl.h>
525 
526 #endif // GUM_NODE_GRAPH_PART_H
NodeGraphPart & operator=(const NodeGraphPart &p)
copy operator
void clearNodes__()
code for clearing nodes (called twice)
bool holes_resize_policy__
value for holes__ configuration
NodeGraphPartIterator(const NodeGraphPartIterator &it) noexcept
copy constructor
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
node_iterator_safe beginSafe() const
a begin iterator to parse the set of nodes contained in the NodeGraphPart
NodeGraphPartIterator NodeConstIterator
NodeGraphPartIterator & operator=(const NodeGraphPartIterator &it) noexcept
copy assignment operator
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669
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
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
void addHole__(NodeId id)
to add a hole.
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
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
NodeGraphPart(Size holes_size=HashTableConst::default_size, bool holes_resize_policy=true)
default constructor
NodeSet * holes__
the set of nodes not contained in the NodeGraphPart in the interval 1..max__
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
NodeGraphPartIteratorSafe endIteratorSafe__
the end iterator (used to speed-up parsings of the NodeGraphPart)
NodeId pos_
the nodeid on which the iterator points currently
Size sizeHoles__() const
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 boundVal__
the id below which NodeIds may belong to the NodeGraphPart
void updateEndIteratorSafe__()
updating endIterator (always at max__+1)
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
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
bool inHoles__(NodeId id) const
Signaler1< NodeId > onNodeDeleted
friend class NodeGraphPartIteratorSafe
NodeGraphPartIterator(const NodeGraphPart &nodes) noexcept
Default constructor.
Safe iterator on the node set of a graph.
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
void eraseHole__(NodeId id)
to delete hole.
const NodeGraphPart * nodes_
the nodegraphpart on which points the iterator
Size holes_size__
value for holes__ configuration
virtual void eraseNode(const NodeId id)
erase the node with the given id