aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
structuralConstraintSetStatic.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 the "meta-programming" class for storing several structural
24  *constraints
25  *
26  * In aGrUM, there are two ways to store sets of structural constraints: the
27  * first one is to put them into a StructuralConstraintSetDynamic. This class
28  * allows to add at runtime any constraint you wish. As such, it is very generic
29  * but, by not knowing at compile time the constraints that will be stored into
30  * the vector, calling its methods has a slight overhead. On the other hand, if
31  * you already know all the constraints you wish to apply, the
32  * StructuralConstraintSetStatic is better suited because it will compute at
33  * compile time how to call the constraint's methods in a most efficient way: if
34  * these methods are inlined, there will be no overhead at all when calling
35  *these
36  * methods. This file defines the StructuralConstraintSetStatic class.
37  *
38  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
39  */
40 #ifndef GUM_LEARNING_STRUCTURAL_CONSTRAINT_SET_STATIC_H
41 #define GUM_LEARNING_STRUCTURAL_CONSTRAINT_SET_STATIC_H
42 
43 #include <type_traits>
44 
45 #include <agrum/agrum.h>
46 #include <agrum/tools/graphs/diGraph.h>
47 #include <agrum/BN/learning/structureUtils/graphChange.h>
48 
49 namespace gum {
50 
51  namespace learning {
52 
53 #ifndef DOXYGEN_SHOULD_SKIP_THIS
54 
55  // a class that indicates the we inherit from a
56  // StructuralConstraintSetStatic
57  struct _StructuralRoot_ {};
58 
59  // a temporary structure used to help computing the minimal set of
60  // constraints
61  template < typename FIRST_CONSTRAINT, typename... OTHER_CONSTRAINTS >
62  struct _ConstraintSet_;
63 
64  // a structure to concatenate _ConstraintSets_ or simply constraints and
65  // produce as a result a new _ConstraintSet_
66  template < typename SET1, typename SET2 >
67  struct _ConcatConstraintSet_;
68 
69  // a helper function to create minimum structural constraint sets and the
70  // methods actually used on all these constraints. This is a helper for
71  // the class that the user should use, i.e., StructuralConstraintSetStatic
72  template < typename FIRST_CONSTRAINT, typename... OTHER_CONSTRAINTS >
73  class _StructuralConstraintSetStatic_;
74 
75  // ============================================================================
76  // checks whether a given structural constraint belongs to a given set of
77  // structural constraints
78  template < typename CONSTRAINT, typename SET >
79  struct _IsInConstraintSet_;
80 
81  template < typename CONSTRAINT, typename SET >
82  struct _IsInConstraintSet_< CONSTRAINT, _ConstraintSet_< SET > > {
83  constexpr static bool value = std::is_same< CONSTRAINT, SET >::value;
84  };
85 
86  template < typename CONSTRAINT, typename SET1, typename... SETS >
87  struct _IsInConstraintSet_< CONSTRAINT, _ConstraintSet_< SET1, SETS... > > {
88  constexpr static bool value
89  = std::is_same< CONSTRAINT, SET1 >::value
90  || _IsInConstraintSet_< CONSTRAINT, _ConstraintSet_< SETS... > >::value;
91  };
92 
93  // ============================================================================
94  // a temporary structure used to help computing the minimal set of
95  // constraints
96  // (removing all duplicates) belonging to a given set of structural
97  // constraints. For instance, if we have the following structural hierarchy:
98  // Z->Y->X, T->Y->X and we have the set of constraints S = <Z,T>, the set
99  // of
100  // all structural constraints reachable from S is S' = <Z,Y,X,T,Y,X>. The
101  // goal
102  // of the following class is to transform S' into S'' = <Z,T,Y,X>, i.e., the
103  // set S' without any duplicates.
104  template < typename FIRST_CONSTRAINT, typename... OTHER_CONSTRAINTS >
105  struct _ConstraintSet_: public _ConstraintSet_< OTHER_CONSTRAINTS... > {
106  using minset = typename std::conditional<
107  _IsInConstraintSet_< FIRST_CONSTRAINT, _ConstraintSet_< OTHER_CONSTRAINTS... > >::value,
108  typename _ConstraintSet_< OTHER_CONSTRAINTS... >::minset,
109  typename _ConcatConstraintSet_<
110  FIRST_CONSTRAINT,
111  typename _ConstraintSet_< OTHER_CONSTRAINTS... >::minset >::type >::type;
112  using set = _StructuralConstraintSetStatic_< FIRST_CONSTRAINT, OTHER_CONSTRAINTS... >;
113  };
114 
115  template < typename CONSTRAINT >
116  struct _ConstraintSet_< CONSTRAINT > {
117  using minset = _ConstraintSet_< CONSTRAINT >;
118  using set = _StructuralConstraintSetStatic_< CONSTRAINT >;
119  };
120 
121  // ============================================================================
122  // a structure to concatenate _ConstraintSets_ or simply constraints and
123  // produce as a result a new _ConstraintSet_
124  template < typename SET1, typename SET2 >
125  struct _ConcatConstraintSet_;
126 
127  template < typename CONSTRAINT1, typename CONSTRAINT2 >
128  struct _ConcatConstraintSet_< CONSTRAINT1, _ConstraintSet_< CONSTRAINT2 > > {
129  using type = _ConstraintSet_< CONSTRAINT1, CONSTRAINT2 >;
130  };
131 
132  template < typename CONSTRAINT1, typename CONSTRAINT2 >
133  struct _ConcatConstraintSet_< _ConstraintSet_< CONSTRAINT1 >, _ConstraintSet_< CONSTRAINT2 > > {
134  using type = _ConstraintSet_< CONSTRAINT1, CONSTRAINT2 >;
135  };
136 
137  template < typename CONSTRAINT1, typename CONSTRAINT2, typename... OTHER_CONSTRAINT2 >
138  struct _ConcatConstraintSet_< CONSTRAINT1,
139  _ConstraintSet_< CONSTRAINT2, OTHER_CONSTRAINT2... > > {
140  using type = _ConstraintSet_< CONSTRAINT1, CONSTRAINT2, OTHER_CONSTRAINT2... >;
141  };
142 
143  template < typename CONSTRAINT1, typename CONSTRAINT2, typename... OTHER_CONSTRAINT1 >
144  struct _ConcatConstraintSet_< _ConstraintSet_< CONSTRAINT1, OTHER_CONSTRAINT1... >,
145  _ConstraintSet_< CONSTRAINT2 > > {
146  using type = _ConstraintSet_< CONSTRAINT1, OTHER_CONSTRAINT1..., CONSTRAINT2 >;
147  };
148 
149  template < typename CONSTRAINT1,
150  typename CONSTRAINT2,
151  typename... OTHER_CONSTR1,
152  typename... OTHER_CONSTR2 >
153  struct _ConcatConstraintSet_< _ConstraintSet_< CONSTRAINT1, OTHER_CONSTR1... >,
154  _ConstraintSet_< CONSTRAINT2, OTHER_CONSTR2... > > {
155  using type = _ConstraintSet_< CONSTRAINT1, OTHER_CONSTR1..., CONSTRAINT2, OTHER_CONSTR2... >;
156  };
157 
158  // ============================================================================
159  // a helper function to create minimum structural constraint sets and the
160  // methods actually used on all these constraints. This is a helper for
161  // the class that the user should use, i.e., StructuralConstraintSetStatic
162  template < typename CONSTRAINT1, typename... OTHER_CONSTRAINTS >
163  class _StructuralConstraintSetStatic_:
164  public virtual CONSTRAINT1,
165  public virtual _StructuralConstraintSetStatic_< OTHER_CONSTRAINTS... > {
166  public:
167  /// the type of the first constraint
168  using first_constraint = CONSTRAINT1;
169 
170  /// the type of the next constraints
171  using next_constraints = _StructuralConstraintSetStatic_< OTHER_CONSTRAINTS... >;
172 
173  // determines the set of all constraints in the set (included inherited
174  // ones)
175  using allConstraints = typename _ConcatConstraintSet_<
176  typename std::conditional<
177  std::is_base_of< _StructuralRoot_, CONSTRAINT1 >::value,
178  typename _ConcatConstraintSet_< CONSTRAINT1,
179  typename CONSTRAINT1::allConstraints >::type,
180  _ConstraintSet_< CONSTRAINT1 > >::type,
181  typename next_constraints::allConstraints >::type;
182 
183  /** @brief determines the minimal set of constraints included in the set
184  * (removing duplicates)
185  *
186  * Assume that the class hierarchy is Z->Y->X, T->Y->X and that we have
187  *the
188  * set of constraints S = <Z,T>, then set of all structural constraints
189  * reachable from S is allConstraints = <Z,Y,X,T,Y,X>. minConstraints will
190  * reduce this set to <Z,T,Y,X>, i.e., it will remove all duplicates. */
191  using minConstraints = typename allConstraints::minset::set;
192 
193  // ##########################################################################
194  /// @name Constructors / Destructors
195  // ##########################################################################
196  /// @{
197 
198  /// default constructor
199  _StructuralConstraintSetStatic_();
200 
201  /// copy constructor
202  _StructuralConstraintSetStatic_(
203  const _StructuralConstraintSetStatic_< CONSTRAINT1, OTHER_CONSTRAINTS... >&);
204 
205  /// destructor
206  ~_StructuralConstraintSetStatic_();
207 
208  /// @}
209 
210  // ##########################################################################
211  /// @name Operators
212  // ##########################################################################
213  /// @{
214 
215  /// copy operator
216  _StructuralConstraintSetStatic_< CONSTRAINT1, OTHER_CONSTRAINTS... >&
217  operator=(const _StructuralConstraintSetStatic_< CONSTRAINT1, OTHER_CONSTRAINTS... >&);
218 
219  /// @}
220 
221  // ##########################################################################
222  /// @name Accessors / Modifiers
223  // ##########################################################################
224  /// @{
225 
226  /// sets a new graph from which we will perform checkings
227  void setGraph(const DiGraph& graph);
228 
229  /// notify the constraint of a modification of the graph
230  void modifyGraph(const ArcAddition& change);
231 
232  /// notify the constraint of a modification of the graph
233  void modifyGraph(const ArcDeletion& change);
234 
235  /// notify the constraint of a modification of the graph
236  void modifyGraph(const ArcReversal& change);
237 
238  /// notify the constraint of a modification of the graph
239  void modifyGraph(const GraphChange& change);
240 
241  /// indicates whether a change will always violate the constraint
242  bool isAlwaysInvalid(const GraphChange& change) const;
243 
244  /// checks whether the constraints enable to add arc (x,y)
245  bool checkArcAddition(NodeId x, NodeId y) const;
246 
247  /// checks whether the constraints enable to remove arc (x,y)
248  bool checkArcDeletion(NodeId x, NodeId y) const;
249 
250  /// checks whether the constraints enable to reverse arc (x,y)
251  bool checkArcReversal(NodeId x, NodeId y) const;
252 
253  /// checks whether the constraints enable to add an arc
254  bool checkModification(const ArcAddition& change) const;
255 
256  /// checks whether the constraints enable to remove an arc
257  bool checkModification(const ArcDeletion& change) const;
258 
259  /// checks whether the constraints enable to reverse an arc
260  bool checkModification(const ArcReversal& change) const;
261 
262  /// checks whether the constraints enable to perform a graph change
263  bool checkModification(const GraphChange& change) const;
264 
265  /// @}
266  };
267 
268  template < typename CONSTRAINT >
269  class _StructuralConstraintSetStatic_< CONSTRAINT >:
270  public virtual CONSTRAINT,
271  public virtual _StructuralRoot_ {
272  public:
273  /// the type of the first constraint
274  using first_constraint = CONSTRAINT;
275 
276  /// the type of the next constraints
277  using next_constraints = _StructuralRoot_;
278 
279  // determines the set of all constraints in the set (included inherited
280  // ones)
281  /** this produces an _ConstraintSet_. This typedef is to be used
282  * internally. */
283  using allConstraints = typename std::conditional<
284  std::is_base_of< _StructuralRoot_, CONSTRAINT >::value,
285  typename _ConcatConstraintSet_< CONSTRAINT, typename CONSTRAINT::allConstraints >::type,
286  _ConstraintSet_< CONSTRAINT > >::type;
287 
288  /** @brief determines the minimal set of constraints included in the set
289  * (removing duplicates)
290  *
291  * Assume that the class hierarchy is Z->Y->X, T->Y->X and that we have
292  *the
293  * set of constraints S = <Z,T>, then set of all structural constraints
294  * reachable from S is allConstraints = <Z,Y,X,T,Y,X>. minConstraints will
295  * reduce this set to <Z,T,Y,X>, i.e., it will remove all duplicates. */
296  using minConstraints = typename allConstraints::minset::set;
297 
298  // ##########################################################################
299  /// @name Constructors / Destructors
300  // ##########################################################################
301  /// @{
302 
303  /// default constructor
304  _StructuralConstraintSetStatic_();
305 
306  /// copy constructor
307  _StructuralConstraintSetStatic_(const _StructuralConstraintSetStatic_< CONSTRAINT >&);
308 
309  /// destructor
310  ~_StructuralConstraintSetStatic_();
311 
312  /// @}
313 
314  // ##########################################################################
315  /// @name Operators
316  // ##########################################################################
317  /// @{
318 
319  /// copy operator
320  _StructuralConstraintSetStatic_< CONSTRAINT >&
321  operator=(const _StructuralConstraintSetStatic_< CONSTRAINT >&);
322 
323  /// @}
324 
325  // ##########################################################################
326  /// @name Accessors / Modifiers
327  // ##########################################################################
328  /// @{
329 
330  /// sets a new graph from which we will perform checkings
331  void setGraph(const DiGraph& graph);
332 
333  /// notify the constraint of a modification of the graph
334  void modifyGraph(const ArcAddition& change);
335 
336  /// notify the constraint of a modification of the graph
337  void modifyGraph(const ArcDeletion& change);
338 
339  /// notify the constraint of a modification of the graph
340  void modifyGraph(const ArcReversal& change);
341 
342  /// notify the constraint of a modification of the graph
343  void modifyGraph(const GraphChange& change);
344 
345  /// indicates whether a change will always violate the constraint
346  bool isAlwaysInvalid(const GraphChange& change) const;
347 
348  /// checks whether the constraints enable to add arc (x,y)
349  bool checkArcAddition(NodeId x, NodeId y) const;
350 
351  /// checks whether the constraints enable to remove arc (x,y)
352  bool checkArcDeletion(NodeId x, NodeId y) const;
353 
354  /// checks whether the constraints enable to reverse arc (x,y)
355  bool checkArcReversal(NodeId x, NodeId y) const;
356 
357  /// checks whether the constraints enable to add an arc
358  bool checkModification(const ArcAddition& change) const;
359 
360  /// checks whether the constraints enable to remove an arc
361  bool checkModification(const ArcDeletion& change) const;
362 
363  /// checks whether the constraints enable to reverse an arc
364  bool checkModification(const ArcReversal& change) const;
365 
366  /// checks whether the constraints enable to perform a graph change
367  bool checkModification(const GraphChange& change) const;
368 
369  /// @}
370  };
371 
372 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
373 
374  /** @class StructuralConstraintSetStatic
375  * @brief the "meta-programming" class for storing structural constraints
376  * @ingroup learning_group
377  *
378  * In aGrUM, there are two ways to store sets of structural constraints: the
379  * first one is to put them into a StructuralConstraintSetDynamic. This
380  *class
381  * allows to add at runtime any constraint you wish. As such, it is very
382  * generic but, by not knowing at compile time the constraints that will be
383  * stored into the vector, calling its methods has a slight overhead. On the
384  * other hand, if you already know all the constraints you wish to apply,
385  *the
386  * StructuralConstraintSetStatic is better suited because it will compute at
387  * compile time how to call the constraint's methods in a most efficient
388  *way:
389  * if these methods are inlined, there will be no overhead at all when
390  *calling
391  * these methods.
392  *
393  * This class is intended to store structural constraints and help applying
394  * them during learning in a most efficient way. The idea is that it will
395  * compute at compile time the class hierarchy graph of the set of
396  *constraints
397  * and will determine the set of distinct structural constraints in the set.
398  * Then, each time we wish to apply a method, say a graph modification check
399  * to all the constraints, the class will apply the methods once on each
400  * distinct constraint, hence avoiding duplicates. */
401  template < typename CONSTRAINT1, typename... OTHER_CONSTRAINTS >
403  public virtual _StructuralConstraintSetStatic_< CONSTRAINT1,
404  OTHER_CONSTRAINTS... >::minConstraints {
405  public:
406  using constraints =
407  typename _StructuralConstraintSetStatic_< CONSTRAINT1,
408  OTHER_CONSTRAINTS... >::minConstraints;
409 
410  // ##########################################################################
411  /// @name Constructors / Destructors
412  // ##########################################################################
413  /// @{
414 
415  /// default constructor
417 
418  /// copy constructor
420  const StructuralConstraintSetStatic< CONSTRAINT1, OTHER_CONSTRAINTS... >&);
421 
422  /// destructor
424 
425  /// @}
426 
427  // ##########################################################################
428  /// @name Operators
429  // ##########################################################################
430  /// @{
431 
432  /// copy operator
433  StructuralConstraintSetStatic< CONSTRAINT1, OTHER_CONSTRAINTS... >&
434  operator=(const StructuralConstraintSetStatic< CONSTRAINT1, OTHER_CONSTRAINTS... >&);
435 
436  /// @}
437 
438  // ##########################################################################
439  /// @name Accessors / Modifiers
440  // ##########################################################################
441  /// @{
442 
443  /// sets a new graph from which we will perform checkings
444  void setGraph(const DiGraph& graph);
445 
446  /// notify the constraint of a modification of the graph
447  void modifyGraph(const ArcAddition& change);
448 
449  /// notify the constraint of a modification of the graph
450  void modifyGraph(const ArcDeletion& change);
451 
452  /// notify the constraint of a modification of the graph
453  void modifyGraph(const ArcReversal& change);
454 
455  /// notify the constraint of a modification of the graph
456  void modifyGraph(const GraphChange& change);
457 
458  /// indicates whether a change will always violate the constraint
459  bool isAlwaysInvalid(const GraphChange& change) const;
460 
461  /// checks whether the constraints enable to add arc (x,y)
462  bool checkArcAddition(NodeId x, NodeId y) const;
463 
464  /// checks whether the constraints enable to remove arc (x,y)
465  bool checkArcDeletion(NodeId x, NodeId y) const;
466 
467  /// checks whether the constraints enable to reverse arc (x,y)
468  bool checkArcReversal(NodeId x, NodeId y) const;
469 
470  /// checks whether the constraints enable to add an arc
471  bool checkModification(const ArcAddition& change) const;
472 
473  /// checks whether the constraints enable to remove an arc
474  bool checkModification(const ArcDeletion& change) const;
475 
476  /// checks whether the constraints enable to reverse an arc
477  bool checkModification(const ArcReversal& change) const;
478 
479  /// checks whether the constraints enable to perform a graph change
480  bool checkModification(const GraphChange& change) const;
481 
482  /// @}
483  };
484 
485 #ifndef DOXYGEN_SHOULD_SKIP_THIS
486 
487  template < typename CONSTRAINT >
488  class StructuralConstraintSetStatic< CONSTRAINT >:
489  public virtual _StructuralConstraintSetStatic_< CONSTRAINT >::minConstraints {
490  public:
491  using constraints = typename _StructuralConstraintSetStatic_< CONSTRAINT >::minConstraints;
492 
493  // ##########################################################################
494  /// @name Constructors / Destructors
495  // ##########################################################################
496  /// @{
497 
498  /// default constructor
499  StructuralConstraintSetStatic();
500 
501  /// copy constructor
502  StructuralConstraintSetStatic(const StructuralConstraintSetStatic< CONSTRAINT >&);
503 
504  /// destructor
505  ~StructuralConstraintSetStatic();
506 
507  /// @}
508 
509  // ##########################################################################
510  /// @name Operators
511  // ##########################################################################
512  /// @{
513 
514  /// copy operator
515  StructuralConstraintSetStatic< CONSTRAINT >&
516  operator=(const StructuralConstraintSetStatic< CONSTRAINT >&);
517 
518  /// @}
519 
520  // ##########################################################################
521  /// @name Accessors / Modifiers
522  // ##########################################################################
523  /// @{
524 
525  /// sets a new graph from which we will perform checkings
526  void setGraph(const DiGraph& graph);
527 
528  /// notify the constraint of a modification of the graph
529  void modifyGraph(const ArcAddition& change);
530 
531  /// notify the constraint of a modification of the graph
532  void modifyGraph(const ArcDeletion& change);
533 
534  /// notify the constraint of a modification of the graph
535  void modifyGraph(const ArcReversal& change);
536 
537  /// notify the constraint of a modification of the graph
538  void modifyGraph(const GraphChange& change);
539 
540  /// indicates whether a change will always violate the constraint
541  bool isAlwaysInvalid(const GraphChange& change) const;
542 
543  /// checks whether the constraints enable to add arc (x,y)
544  bool checkArcAddition(NodeId x, NodeId y) const;
545 
546  /// checks whether the constraints enable to remove arc (x,y)
547  bool checkArcDeletion(NodeId x, NodeId y) const;
548 
549  /// checks whether the constraints enable to reverse arc (x,y)
550  bool checkArcReversal(NodeId x, NodeId y) const;
551 
552  /// checks whether the constraints enable to add an arc
553  bool checkModification(const ArcAddition& change) const;
554 
555  /// checks whether the constraints enable to remove an arc
556  bool checkModification(const ArcDeletion& change) const;
557 
558  /// checks whether the constraints enable to reverse an arc
559  bool checkModification(const ArcReversal& change) const;
560 
561  /// checks whether the constraints enable to perform a graph change
562  bool checkModification(const GraphChange& change) const;
563 
564  /// @}
565  };
566 
567 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
568 
569  } /* namespace learning */
570 
571 } /* namespace gum */
572 
573 /// always include the templated function definitions
574 #include <agrum/BN/learning/constraints/structuralConstraintSetStatic_tpl.h>
575 
576 #endif /* GUM_LEARNING_STRUCTURAL_CONSTRAINT_SET_STATIC_H */
bool isAlwaysInvalid(const GraphChange &change) const
indicates whether a change will always violate the constraint
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
StructuralConstraintSetStatic()
default constructor
StructuralConstraintSetStatic(const StructuralConstraintSetStatic< CONSTRAINT1, OTHER_CONSTRAINTS... > &)
copy constructor
bool checkArcDeletion(NodeId x, NodeId y) const
checks whether the constraints enable to remove arc (x,y)
the "meta-programming" class for storing structural constraintsIn aGrUM, there are two ways to store ...
void setGraph(const DiGraph &graph)
sets a new graph from which we will perform checkings
bool checkArcReversal(NodeId x, NodeId y) const
checks whether the constraints enable to reverse arc (x,y)
StructuralConstraintSetStatic< CONSTRAINT1, OTHER_CONSTRAINTS... > & operator=(const StructuralConstraintSetStatic< CONSTRAINT1, OTHER_CONSTRAINTS... > &)
copy operator
bool checkModification(const GraphChange &change) const
checks whether the constraints enable to perform a graph change
Database(const std::string &filename, const BayesNet< GUM_SCALAR > &bn, const std::vector< std::string > &missing_symbols)
bool checkArcAddition(NodeId x, NodeId y) const
checks whether the constraints enable to add arc (x,y)
void modifyGraph(const GraphChange &change)
notify the constraint of a modification of the graph