1 /**
2  *
3  *   Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(_at_LIP6) & Christophe GONZALES(_at_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 the classes to account for structure changes in a graph
24  *
25  * The classes included in this file shall be used by learning algorithms to
26  * notify scores, structural constraints, etc, how the learnt graph has been
27  * modified.
28  *
29  * @author Christophe GONZALES(_at_AMU) and Pierre-Henri WUILLEMIN(_at_LIP6)
30  */
31 #ifndef GUM_LEARNING_GRAPH_CHANGE_H
32 #define GUM_LEARNING_GRAPH_CHANGE_H
33 
34 #include <iostream>
35 #include <string>
36 
37 #include <agrum/agrum.h>
38 #include <agrum/tools/core/hashFunc.h>
39 #include <agrum/tools/graphs/parts/nodeGraphPart.h>
40 
41 namespace gum {
42 
43   namespace learning {
44 
45     /// the type of modification that can be applied to the graph
46     enum GraphChangeType
47     {
48       ARC_ADDITION,
49       ARC_DELETION,
50       ARC_REVERSAL,
51       EDGE_ADDITION,
52       EDGE_DELETION
53     };
54 
55     /* =========================================================================
56      */
57     /* ===                        GRAPH CHANGE CLASS                         ===
58      */
59     /* =========================================================================
60      */
61     /** @class GraphChange
62      * @brief
63      * @ingroup learning_group
64      */
65     class GraphChange {
66       public:
67       // ##########################################################################
68       /// @name Constructors / Destructors
69       // ##########################################################################
70       /// @{
71 
72       /// default constructor
73       GraphChange(GraphChangeType type, NodeId node1, NodeId node2) noexcept;
74 
75       /// copy constructor
76       GraphChange(const GraphChange& from) noexcept;
77 
78       /// move constructor
79       GraphChange(GraphChange&& from) noexcept;
80 
81       /// destructor
82       ~GraphChange() noexcept;
83 
84       /// @}
85 
86       // ##########################################################################
87       /// @name Operators
88       // ##########################################################################
89       /// @{
90 
91       /// copy constructor
92       GraphChange& operator=(const GraphChange& from) noexcept;
93 
94       /// move operator
95       GraphChange& operator=(GraphChange&& from) noexcept;
96 
97       /// returns whether two graph changes are identical or not
98       bool operator==(const GraphChange& from) const noexcept;
99 
100       /// returns whether two graph changes are different or not
101       bool operator!=(const GraphChange& from) const noexcept;
102 
103       /// @}
104 
105       // ##########################################################################
106       /// @name Accessors/Modifiers
107       // ##########################################################################
108       /// @{
109 
110       /// returns the type of the operation
111       GraphChangeType type() const noexcept;
112 
113       /// returns the first node involved in the modification
114       NodeId node1() const noexcept;
115 
116       /// returns the second node involved in the modification
117       NodeId node2() const noexcept;
118 
119       /// put the content of the graph change into a string
120       virtual std::string toString() const;
121 
122       /// @}
123 
124       private:
125       /// the type of modification
126       GraphChangeType _type_;
127 
128       /// the first node in the edge or arc to be modified
129       NodeId _node1_;
130 
131       /// the second node in the edge or arc to be modified
132       NodeId _node2_;
133     };
134 
135     /* =========================================================================
136      */
137     /* ===                        ARC ADDITION CLASS                         ===
138      */
139     /* =========================================================================
140      */
141     /** @class ArcAddition
142      * @brief The class for notifying learning algorithms of new arc additions
143      * @ingroup learning_group
144      *
145      * This class is convenient to know at compile time which graph change we
146      * are dealing with. Thus, this enables to perform faster code (we can avoid
147      * using a switch on GraphChanges to determine which change corresponds to
148      * this class.
149      */
150     class ArcAddition: public GraphChange {
151       public:
152       // ##########################################################################
153       /// @name Constructors / Destructors
154       // ##########################################################################
155       /// @{
156 
157       /// default constructor
158       ArcAddition(NodeId node1, NodeId node2) noexcept;
159 
160       /// copy constructor
161       ArcAddition(const ArcAddition& from) noexcept;
162 
163       /// move constructor
164       ArcAddition(ArcAddition&& from) noexcept;
165 
166       /// destructor
167       ~ArcAddition() noexcept;
168 
169       /// @}
170 
171       // ##########################################################################
172       /// @name Operators
173       // ##########################################################################
174       /// @{
175 
176       /// copy constructor
177       ArcAddition& operator=(const ArcAddition& from) noexcept;
178 
179       /// move operator
180       ArcAddition& operator=(ArcAddition&& from) noexcept;
181 
182       /// returns whether two arc additions are identical or not
183       bool operator==(const ArcAddition& from) const noexcept;
184 
185       /// returns whether two arc additions are different or not
186       bool operator!=(const ArcAddition& from) const noexcept;
187 
188       /// @}
189 
190       // ##########################################################################
191       /// @name Accessors / Modifiers
192       // ##########################################################################
193       /// @{
194 
195       /// put the content of the ArcAddition into a string
196       virtual std::string toString() const final;
197 
198       /// @}
199     };
200 
201     /* =========================================================================
202      */
203     /* ===                        ARC DELETION CLASS                         ===
204      */
205     /* =========================================================================
206      */
207     /** @class ArcDeletion
208      * @brief The class for notifying learning algorithms of arc removals
209      * @ingroup learning_group
210      *
211      * This class is convenient to know at compile time which graph change we
212      * are dealing with. Thus, this enables to perform faster code (we can avoid
213      * using a switch on GraphChanges to determine which change corresponds to
214      * this class.
215      */
216     class ArcDeletion: public GraphChange {
217       public:
218       // ##########################################################################
219       /// @name Constructors / Destructors
220       // ##########################################################################
221       /// @{
222 
223       /// default constructor
224       ArcDeletion(NodeId node1, NodeId node2) noexcept;
225 
226       /// copy constructor
227       ArcDeletion(const ArcDeletion& from) noexcept;
228 
229       /// move constructor
230       ArcDeletion(ArcDeletion&& from) noexcept;
231 
232       /// destructor
233       ~ArcDeletion() noexcept;
234 
235       /// @}
236 
237       // ##########################################################################
238       /// @name Operators
239       // ##########################################################################
240       /// @{
241 
242       /// copy constructor
243       ArcDeletion& operator=(const ArcDeletion& from) noexcept;
244 
245       /// move operator
246       ArcDeletion& operator=(ArcDeletion&& from) noexcept;
247 
248       /// returns whether two arc deletions are identical or not
249       bool operator==(const ArcDeletion& from) const noexcept;
250 
251       /// returns whether two arc deletions are different or not
252       bool operator!=(const ArcDeletion& from) const noexcept;
253 
254       /// @}
255 
256       // ##########################################################################
257       /// @name Accessors / Modifiers
258       // ##########################################################################
259       /// @{
260 
261       /// put the content of the ArcDeletion into a string
262       virtual std::string toString() const final;
263 
264       /// @}
265     };
266 
267     /* =========================================================================
268      */
269     /* ===                        ARC REVERSAL CLASS                         ===
270      */
271     /* =========================================================================
272      */
273     /** @class ArcReversal
274      * @brief The class for notifying learning algorithms of arc reversals
275      * @ingroup learning_group
276      *
277      * This class is convenient to know at compile time which graph change we
278      * are dealing with. Thus, this enables to perform faster code (we can avoid
279      * using a switch on GraphChanges to determine which change corresponds to
280      * this class.
281      */
282     class ArcReversal: public GraphChange {
283       public:
284       // ##########################################################################
285       /// @name Constructors / Destructors
286       // ##########################################################################
287       /// @{
288 
289       /// default constructor
290       ArcReversal(NodeId node1, NodeId node2) noexcept;
291 
292       /// copy constructor
293       ArcReversal(const ArcReversal& from) noexcept;
294 
295       /// move constructor
296       ArcReversal(ArcReversal&& from) noexcept;
297 
298       /// destructor
299       ~ArcReversal() noexcept;
300 
301       /// @}
302 
303       // ##########################################################################
304       /// @name Operators
305       // ##########################################################################
306       /// @{
307 
308       /// copy constructor
309       ArcReversal& operator=(const ArcReversal& from) noexcept;
310 
311       /// move operator
312       ArcReversal& operator=(ArcReversal&& from) noexcept;
313 
314       /// returns whether two arc reversals are identical or not
315       bool operator==(const ArcReversal& from) const noexcept;
316 
317       /// returns whether two arc reversals are different or not
318       bool operator!=(const ArcReversal& from) const noexcept;
319 
320       /// @}
321 
322       // ##########################################################################
323       /// @name Accessors / Modifiers
324       // ##########################################################################
325       /// @{
326 
327       /// put the content of the ArcReversal into a string
328       virtual std::string toString() const final;
329 
330       /// @}
331     };
332 
333     /* =========================================================================
334      */
335     /* ===                        EDGE ADDITION CLASS                        ===
336      */
337     /* =========================================================================
338      */
339     /** @class EdgeAddition
340      * @brief The class for notifying learning algorithms of new edge additions
341      * @ingroup learning_group
342      *
343      * This class is convenient to know at compile time which graph change we
344      * are dealing with. Thus, this enables to perform faster code (we can avoid
345      * using a switch on GraphChanges to determine which change corresponds to
346      * this class.
347      */
348     class EdgeAddition: public GraphChange {
349       public:
350       // ##########################################################################
351       /// @name Constructors / Destructors
352       // ##########################################################################
353       /// @{
354 
355       /// default constructor
356       EdgeAddition(NodeId node1, NodeId node2) noexcept;
357 
358       /// copy constructor
359       EdgeAddition(const EdgeAddition& from) noexcept;
360 
361       /// move constructor
362       EdgeAddition(EdgeAddition&& from) noexcept;
363 
364       /// destructor
365       ~EdgeAddition() noexcept;
366 
367       /// @}
368 
369       // ##########################################################################
370       /// @name Operators
371       // ##########################################################################
372       /// @{
373 
374       /// copy constructor
375       EdgeAddition& operator=(const EdgeAddition& from) noexcept;
376 
377       /// move operator
378       EdgeAddition& operator=(EdgeAddition&& from) noexcept;
379 
380       /// returns whether two edge additions are identical or not
381       bool operator==(const EdgeAddition& from) const noexcept;
382 
383       /// returns whether two edge additions are different or not
384       bool operator!=(const EdgeAddition& from) const noexcept;
385 
386       /// @}
387 
388       // ##########################################################################
389       /// @name Accessors / Modifiers
390       // ##########################################################################
391       /// @{
392 
393       /// put the content of the EdgeAddition into a string
394       virtual std::string toString() const final;
395 
396       /// @}
397     };
398 
399     /* =========================================================================
400      */
401     /* ===                        EDGE DELETION CLASS                        ===
402      */
403     /* =========================================================================
404      */
405     /** @class EdgeDeletion
406      * @brief The class for notifying learning algorithms of edge removals
407      * @ingroup learning_group
408      *
409      * This class is convenient to know at compile time which graph change we
410      * are dealing with. Thus, this enables to perform faster code (we can avoid
411      * using a switch on GraphChanges to determine which change corresponds to
412      * this class.
413      */
414     class EdgeDeletion: public GraphChange {
415       public:
416       // ##########################################################################
417       /// @name Constructors / Destructors
418       // ##########################################################################
419       /// @{
420 
421       /// default constructor
422       EdgeDeletion(NodeId node1, NodeId node2) noexcept;
423 
424       /// copy constructor
425       EdgeDeletion(const EdgeDeletion& from) noexcept;
426 
427       /// move constructor
428       EdgeDeletion(EdgeDeletion&& from) noexcept;
429 
430       /// destructor
431       ~EdgeDeletion() noexcept;
432 
433       /// @}
434 
435       // ##########################################################################
436       /// @name Operators
437       // ##########################################################################
438       /// @{
439 
440       /// copy constructor
441       EdgeDeletion& operator=(const EdgeDeletion& from) noexcept;
442 
443       /// move operator
444       EdgeDeletion& operator=(EdgeDeletion&& from) noexcept;
445 
446       /// returns whether two edge deletions are identical or not
447       bool operator==(const EdgeDeletion& from) const noexcept;
448 
449       /// returns whether two edge deletions are different or not
450       bool operator!=(const EdgeDeletion& from) const noexcept;
451 
452       /// @}
453 
454       // ##########################################################################
455       /// @name Accessors / Modifiers
456       // ##########################################################################
457       /// @{
458 
459       /// put the content of the EdgeDeletion into a string
460       virtual std::string toString() const final;
461 
462       /// @}
463     };
464 
465     /// a \c << operator for GraphChanges
466     std::ostream& operator<<(std::ostream& stream, const GraphChange& change);
467 
468     /// a \c << operator for ArcAddition
469     std::ostream& operator<<(std::ostream& stream, const ArcAddition& change);
470 
471     /// a \c << operator for ArcDeletion
472     std::ostream& operator<<(std::ostream& stream, const ArcDeletion& change);
473 
474     /// a \c << operator for ArcReversal
475     std::ostream& operator<<(std::ostream& stream, const ArcReversal& change);
476 
477     /// a \c << operator for EdgeAddition
478     std::ostream& operator<<(std::ostream& stream, const EdgeAddition& change);
479 
480     /// a \c << operator for EdgeDeletion
481     std::ostream& operator<<(std::ostream& stream, const EdgeDeletion& change);
482 
483   } /* namespace learning */
484 
485   /// the hash function for Graph Changes
486   template <>
487   class HashFunc< learning::GraphChange >: public HashFuncBase< learning::GraphChange > {
488     public:
489     /**
490      * @brief Returns the value of a key as a Size.
491      * @param key The value to return as a Size.
492      * @return Returns the value of a key as a Size.
493      */
494     static Size castToSize(const learning::GraphChange& key);
495 
496     /// computes the hashed value of a key
497     virtual Size operator()(const learning::GraphChange& key) const override final;
498   };
499 
500   /// the hash function for Arc Additions
501   template <>
502   class HashFunc< learning::ArcAddition >: public HashFuncBase< learning::ArcAddition > {
503     public:
504     /**
505      * @brief Returns the value of a key as a Size.
506      * @param key The value to return as a Size.
507      * @return Returns the value of a key as a Size.
508      */
509     static Size castToSize(const learning::ArcAddition& key);
510 
511     /// computes the hashed value of a key
512     virtual Size operator()(const learning::ArcAddition& key) const override final;
513   };
514 
515   /// the hash function for Arc Deletions
516   template <>
517   class HashFunc< learning::ArcDeletion >: public HashFuncBase< learning::ArcDeletion > {
518     public:
519     /**
520      * @brief Returns the value of a key as a Size.
521      * @param key The value to return as a Size.
522      * @return Returns the value of a key as a Size.
523      */
524     static Size castToSize(const learning::ArcDeletion& key);
525 
526     /// computes the hashed value of a key
527     virtual Size operator()(const learning::ArcDeletion& key) const override final;
528   };
529 
530   /// the hash function for Arc Reversals
531   template <>
532   class HashFunc< learning::ArcReversal >: public HashFuncBase< learning::ArcReversal > {
533     public:
534     /**
535      * @brief Returns the value of a key as a Size.
536      * @param key The value to return as a Size.
537      * @return Returns the value of a key as a Size.
538      */
539     static Size castToSize(const learning::ArcReversal& key);
540 
541     /// computes the hashed value of a key
542     virtual Size operator()(const learning::ArcReversal& key) const override final;
543   };
544 
545   /// the hash function for Edge Additions
546   template <>
547   class HashFunc< learning::EdgeAddition >: public HashFuncBase< learning::EdgeAddition > {
548     /**
549      * @brief Returns the value of a key as a Size.
550      * @param key The value to return as a Size.
551      * @return Returns the value of a key as a Size.
552      */
553     static Size castToSize(const learning::EdgeAddition& key);
554 
555     /// computes the hashed value of a key
556     virtual Size operator()(const learning::EdgeAddition& key) const override final;
557   };
558 
559   /// the hash function for Edge Deletions
560   template <>
561   class HashFunc< learning::EdgeDeletion >: public HashFuncBase< learning::EdgeDeletion > {
562     public:
563     /**
564      * @brief Returns the value of a key as a Size.
565      * @param key The value to return as a Size.
566      * @return Returns the value of a key as a Size.
567      */
568     static Size castToSize(const learning::EdgeDeletion& key);
569 
570     /// computes the hashed value of a key
571     virtual Size operator()(const learning::EdgeDeletion& key) const override final;
572   };
573 
574 } /* namespace gum */
575 
576 #ifndef GUM_NO_INLINE
577 #  include <agrum/BN/learning/structureUtils/graphChange_inl.h>
578 #endif   // GUM_NOINLINE
579 
580 #endif /* GUM_LEARNING_GRAPH_CHANGE_H */
581