aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
structuralConstraintSetStatic.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 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,
108  ConstraintSet__< OTHER_CONSTRAINTS... > >::value,
109  typename ConstraintSet__< OTHER_CONSTRAINTS... >::minset,
110  typename ConcatConstraintSet__<
111  FIRST_CONSTRAINT,
112  typename ConstraintSet__< OTHER_CONSTRAINTS... >::minset >::type >::
113  type;
114  using set = StructuralConstraintSetStatic__< FIRST_CONSTRAINT,
115  OTHER_CONSTRAINTS... >;
116  };
117 
118  template < typename CONSTRAINT >
119  struct ConstraintSet__< CONSTRAINT > {
120  using minset = ConstraintSet__< CONSTRAINT >;
121  using set = StructuralConstraintSetStatic__< CONSTRAINT >;
122  };
123 
124  // ============================================================================
125  // a structure to concatenate ConstraintSets__ or simply constraints and
126  // produce as a result a new ConstraintSet__
127  template < typename SET1, typename SET2 >
128  struct ConcatConstraintSet__;
129 
130  template < typename CONSTRAINT1, typename CONSTRAINT2 >
131  struct ConcatConstraintSet__< CONSTRAINT1, ConstraintSet__< CONSTRAINT2 > > {
132  using type = ConstraintSet__< CONSTRAINT1, CONSTRAINT2 >;
133  };
134 
135  template < typename CONSTRAINT1, typename CONSTRAINT2 >
136  struct ConcatConstraintSet__< ConstraintSet__< CONSTRAINT1 >,
137  ConstraintSet__< CONSTRAINT2 > > {
138  using type = ConstraintSet__< CONSTRAINT1, CONSTRAINT2 >;
139  };
140 
141  template < typename CONSTRAINT1,
142  typename CONSTRAINT2,
143  typename... OTHER_CONSTRAINT2 >
144  struct ConcatConstraintSet__<
145  CONSTRAINT1,
146  ConstraintSet__< CONSTRAINT2, OTHER_CONSTRAINT2... > > {
147  using type
148  = ConstraintSet__< CONSTRAINT1, CONSTRAINT2, OTHER_CONSTRAINT2... >;
149  };
150 
151  template < typename CONSTRAINT1,
152  typename CONSTRAINT2,
153  typename... OTHER_CONSTRAINT1 >
154  struct ConcatConstraintSet__<
155  ConstraintSet__< CONSTRAINT1, OTHER_CONSTRAINT1... >,
156  ConstraintSet__< CONSTRAINT2 > > {
157  using type
158  = ConstraintSet__< CONSTRAINT1, OTHER_CONSTRAINT1..., CONSTRAINT2 >;
159  };
160 
161  template < typename CONSTRAINT1,
162  typename CONSTRAINT2,
163  typename... OTHER_CONSTR1,
164  typename... OTHER_CONSTR2 >
165  struct ConcatConstraintSet__<
166  ConstraintSet__< CONSTRAINT1, OTHER_CONSTR1... >,
167  ConstraintSet__< CONSTRAINT2, OTHER_CONSTR2... > > {
168  using type = ConstraintSet__< CONSTRAINT1,
169  OTHER_CONSTR1...,
170  CONSTRAINT2,
171  OTHER_CONSTR2... >;
172  };
173 
174  // ============================================================================
175  // a helper function to create minimum structural constraint sets and the
176  // methods actually used on all these constraints. This is a helper for
177  // the class that the user should use, i.e., StructuralConstraintSetStatic
178  template < typename CONSTRAINT1, typename... OTHER_CONSTRAINTS >
179  class StructuralConstraintSetStatic__:
180  public virtual CONSTRAINT1,
181  public virtual StructuralConstraintSetStatic__< OTHER_CONSTRAINTS... > {
182  public:
183  /// the type of the first constraint
184  using first_constraint = CONSTRAINT1;
185 
186  /// the type of the next constraints
187  using next_constraints
188  = StructuralConstraintSetStatic__< OTHER_CONSTRAINTS... >;
189 
190  // determines the set of all constraints in the set (included inherited
191  // ones)
192  using allConstraints = typename ConcatConstraintSet__<
193  typename std::conditional<
194  std::is_base_of< StructuralRoot__, CONSTRAINT1 >::value,
195  typename ConcatConstraintSet__<
196  CONSTRAINT1,
197  typename CONSTRAINT1::allConstraints >::type,
198  ConstraintSet__< CONSTRAINT1 > >::type,
199  typename next_constraints::allConstraints >::type;
200 
201  /** @brief determines the minimal set of constraints included in the set
202  * (removing duplicates)
203  *
204  * Assume that the class hierarchy is Z->Y->X, T->Y->X and that we have
205  *the
206  * set of constraints S = <Z,T>, then set of all structural constraints
207  * reachable from S is allConstraints = <Z,Y,X,T,Y,X>. minConstraints will
208  * reduce this set to <Z,T,Y,X>, i.e., it will remove all duplicates. */
209  using minConstraints = typename allConstraints::minset::set;
210 
211  // ##########################################################################
212  /// @name Constructors / Destructors
213  // ##########################################################################
214  /// @{
215 
216  /// default constructor
217  StructuralConstraintSetStatic__();
218 
219  /// copy constructor
220  StructuralConstraintSetStatic__(
221  const StructuralConstraintSetStatic__< CONSTRAINT1,
222  OTHER_CONSTRAINTS... >&);
223 
224  /// destructor
225  ~StructuralConstraintSetStatic__();
226 
227  /// @}
228 
229  // ##########################################################################
230  /// @name Operators
231  // ##########################################################################
232  /// @{
233 
234  /// copy operator
235  StructuralConstraintSetStatic__< CONSTRAINT1, OTHER_CONSTRAINTS... >&
236  operator=(const StructuralConstraintSetStatic__< CONSTRAINT1,
237  OTHER_CONSTRAINTS... >&);
238 
239  /// @}
240 
241  // ##########################################################################
242  /// @name Accessors / Modifiers
243  // ##########################################################################
244  /// @{
245 
246  /// sets a new graph from which we will perform checkings
247  void setGraph(const DiGraph& graph);
248 
249  /// notify the constraint of a modification of the graph
250  void modifyGraph(const ArcAddition& change);
251 
252  /// notify the constraint of a modification of the graph
253  void modifyGraph(const ArcDeletion& change);
254 
255  /// notify the constraint of a modification of the graph
256  void modifyGraph(const ArcReversal& change);
257 
258  /// notify the constraint of a modification of the graph
259  void modifyGraph(const GraphChange& change);
260 
261  /// indicates whether a change will always violate the constraint
262  bool isAlwaysInvalid(const GraphChange& change) const;
263 
264  /// checks whether the constraints enable to add arc (x,y)
265  bool checkArcAddition(NodeId x, NodeId y) const;
266 
267  /// checks whether the constraints enable to remove arc (x,y)
268  bool checkArcDeletion(NodeId x, NodeId y) const;
269 
270  /// checks whether the constraints enable to reverse arc (x,y)
271  bool checkArcReversal(NodeId x, NodeId y) const;
272 
273  /// checks whether the constraints enable to add an arc
274  bool checkModification(const ArcAddition& change) const;
275 
276  /// checks whether the constraints enable to remove an arc
277  bool checkModification(const ArcDeletion& change) const;
278 
279  /// checks whether the constraints enable to reverse an arc
280  bool checkModification(const ArcReversal& change) const;
281 
282  /// checks whether the constraints enable to perform a graph change
283  bool checkModification(const GraphChange& change) const;
284 
285  /// @}
286  };
287 
288  template < typename CONSTRAINT >
289  class StructuralConstraintSetStatic__< CONSTRAINT >:
290  public virtual CONSTRAINT,
291  public virtual StructuralRoot__ {
292  public:
293  /// the type of the first constraint
294  using first_constraint = CONSTRAINT;
295 
296  /// the type of the next constraints
297  using next_constraints = StructuralRoot__;
298 
299  // determines the set of all constraints in the set (included inherited
300  // ones)
301  /** this produces an ConstraintSet__. This typedef is to be used
302  * internally. */
303  using allConstraints = typename std::conditional<
304  std::is_base_of< StructuralRoot__, CONSTRAINT >::value,
305  typename ConcatConstraintSet__<
306  CONSTRAINT,
307  typename CONSTRAINT::allConstraints >::type,
308  ConstraintSet__< CONSTRAINT > >::type;
309 
310  /** @brief determines the minimal set of constraints included in the set
311  * (removing duplicates)
312  *
313  * Assume that the class hierarchy is Z->Y->X, T->Y->X and that we have
314  *the
315  * set of constraints S = <Z,T>, then set of all structural constraints
316  * reachable from S is allConstraints = <Z,Y,X,T,Y,X>. minConstraints will
317  * reduce this set to <Z,T,Y,X>, i.e., it will remove all duplicates. */
318  using minConstraints = typename allConstraints::minset::set;
319 
320  // ##########################################################################
321  /// @name Constructors / Destructors
322  // ##########################################################################
323  /// @{
324 
325  /// default constructor
326  StructuralConstraintSetStatic__();
327 
328  /// copy constructor
329  StructuralConstraintSetStatic__(
330  const StructuralConstraintSetStatic__< CONSTRAINT >&);
331 
332  /// destructor
333  ~StructuralConstraintSetStatic__();
334 
335  /// @}
336 
337  // ##########################################################################
338  /// @name Operators
339  // ##########################################################################
340  /// @{
341 
342  /// copy operator
343  StructuralConstraintSetStatic__< CONSTRAINT >&
344  operator=(const StructuralConstraintSetStatic__< CONSTRAINT >&);
345 
346  /// @}
347 
348  // ##########################################################################
349  /// @name Accessors / Modifiers
350  // ##########################################################################
351  /// @{
352 
353  /// sets a new graph from which we will perform checkings
354  void setGraph(const DiGraph& graph);
355 
356  /// notify the constraint of a modification of the graph
357  void modifyGraph(const ArcAddition& change);
358 
359  /// notify the constraint of a modification of the graph
360  void modifyGraph(const ArcDeletion& change);
361 
362  /// notify the constraint of a modification of the graph
363  void modifyGraph(const ArcReversal& change);
364 
365  /// notify the constraint of a modification of the graph
366  void modifyGraph(const GraphChange& change);
367 
368  /// indicates whether a change will always violate the constraint
369  bool isAlwaysInvalid(const GraphChange& change) const;
370 
371  /// checks whether the constraints enable to add arc (x,y)
372  bool checkArcAddition(NodeId x, NodeId y) const;
373 
374  /// checks whether the constraints enable to remove arc (x,y)
375  bool checkArcDeletion(NodeId x, NodeId y) const;
376 
377  /// checks whether the constraints enable to reverse arc (x,y)
378  bool checkArcReversal(NodeId x, NodeId y) const;
379 
380  /// checks whether the constraints enable to add an arc
381  bool checkModification(const ArcAddition& change) const;
382 
383  /// checks whether the constraints enable to remove an arc
384  bool checkModification(const ArcDeletion& change) const;
385 
386  /// checks whether the constraints enable to reverse an arc
387  bool checkModification(const ArcReversal& change) const;
388 
389  /// checks whether the constraints enable to perform a graph change
390  bool checkModification(const GraphChange& change) const;
391 
392  /// @}
393  };
394 
395 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
396 
397  /** @class StructuralConstraintSetStatic
398  * @brief the "meta-programming" class for storing structural constraints
399  * @ingroup learning_group
400  *
401  * In aGrUM, there are two ways to store sets of structural constraints: the
402  * first one is to put them into a StructuralConstraintSetDynamic. This
403  *class
404  * allows to add at runtime any constraint you wish. As such, it is very
405  * generic but, by not knowing at compile time the constraints that will be
406  * stored into the vector, calling its methods has a slight overhead. On the
407  * other hand, if you already know all the constraints you wish to apply,
408  *the
409  * StructuralConstraintSetStatic is better suited because it will compute at
410  * compile time how to call the constraint's methods in a most efficient
411  *way:
412  * if these methods are inlined, there will be no overhead at all when
413  *calling
414  * these methods.
415  *
416  * This class is intended to store structural constraints and help applying
417  * them during learning in a most efficient way. The idea is that it will
418  * compute at compile time the class hierarchy graph of the set of
419  *constraints
420  * and will determine the set of distinct structural constraints in the set.
421  * Then, each time we wish to apply a method, say a graph modification check
422  * to all the constraints, the class will apply the methods once on each
423  * distinct constraint, hence avoiding duplicates. */
424  template < typename CONSTRAINT1, typename... OTHER_CONSTRAINTS >
426  public virtual StructuralConstraintSetStatic__<
427  CONSTRAINT1,
428  OTHER_CONSTRAINTS... >::minConstraints {
429  public:
430  using constraints = typename StructuralConstraintSetStatic__<
431  CONSTRAINT1,
432  OTHER_CONSTRAINTS... >::minConstraints;
433 
434  // ##########################################################################
435  /// @name Constructors / Destructors
436  // ##########################################################################
437  /// @{
438 
439  /// default constructor
441 
442  /// copy constructor
444  const StructuralConstraintSetStatic< CONSTRAINT1,
445  OTHER_CONSTRAINTS... >&);
446 
447  /// destructor
449 
450  /// @}
451 
452  // ##########################################################################
453  /// @name Operators
454  // ##########################################################################
455  /// @{
456 
457  /// copy operator
458  StructuralConstraintSetStatic< CONSTRAINT1, OTHER_CONSTRAINTS... >&
459  operator=(const StructuralConstraintSetStatic< CONSTRAINT1,
460  OTHER_CONSTRAINTS... >&);
461 
462  /// @}
463 
464  // ##########################################################################
465  /// @name Accessors / Modifiers
466  // ##########################################################################
467  /// @{
468 
469  /// sets a new graph from which we will perform checkings
470  void setGraph(const DiGraph& graph);
471 
472  /// notify the constraint of a modification of the graph
473  void modifyGraph(const ArcAddition& change);
474 
475  /// notify the constraint of a modification of the graph
476  void modifyGraph(const ArcDeletion& change);
477 
478  /// notify the constraint of a modification of the graph
479  void modifyGraph(const ArcReversal& change);
480 
481  /// notify the constraint of a modification of the graph
482  void modifyGraph(const GraphChange& change);
483 
484  /// indicates whether a change will always violate the constraint
485  bool isAlwaysInvalid(const GraphChange& change) const;
486 
487  /// checks whether the constraints enable to add arc (x,y)
488  bool checkArcAddition(NodeId x, NodeId y) const;
489 
490  /// checks whether the constraints enable to remove arc (x,y)
491  bool checkArcDeletion(NodeId x, NodeId y) const;
492 
493  /// checks whether the constraints enable to reverse arc (x,y)
494  bool checkArcReversal(NodeId x, NodeId y) const;
495 
496  /// checks whether the constraints enable to add an arc
497  bool checkModification(const ArcAddition& change) const;
498 
499  /// checks whether the constraints enable to remove an arc
500  bool checkModification(const ArcDeletion& change) const;
501 
502  /// checks whether the constraints enable to reverse an arc
503  bool checkModification(const ArcReversal& change) const;
504 
505  /// checks whether the constraints enable to perform a graph change
506  bool checkModification(const GraphChange& change) const;
507 
508  /// @}
509  };
510 
511 #ifndef DOXYGEN_SHOULD_SKIP_THIS
512 
513  template < typename CONSTRAINT >
514  class StructuralConstraintSetStatic< CONSTRAINT >:
515  public virtual StructuralConstraintSetStatic__<
516  CONSTRAINT >::minConstraints {
517  public:
518  using constraints =
519  typename StructuralConstraintSetStatic__< CONSTRAINT >::minConstraints;
520 
521  // ##########################################################################
522  /// @name Constructors / Destructors
523  // ##########################################################################
524  /// @{
525 
526  /// default constructor
527  StructuralConstraintSetStatic();
528 
529  /// copy constructor
530  StructuralConstraintSetStatic(
531  const StructuralConstraintSetStatic< CONSTRAINT >&);
532 
533  /// destructor
534  ~StructuralConstraintSetStatic();
535 
536  /// @}
537 
538  // ##########################################################################
539  /// @name Operators
540  // ##########################################################################
541  /// @{
542 
543  /// copy operator
544  StructuralConstraintSetStatic< CONSTRAINT >&
545  operator=(const StructuralConstraintSetStatic< CONSTRAINT >&);
546 
547  /// @}
548 
549  // ##########################################################################
550  /// @name Accessors / Modifiers
551  // ##########################################################################
552  /// @{
553 
554  /// sets a new graph from which we will perform checkings
555  void setGraph(const DiGraph& graph);
556 
557  /// notify the constraint of a modification of the graph
558  void modifyGraph(const ArcAddition& change);
559 
560  /// notify the constraint of a modification of the graph
561  void modifyGraph(const ArcDeletion& change);
562 
563  /// notify the constraint of a modification of the graph
564  void modifyGraph(const ArcReversal& change);
565 
566  /// notify the constraint of a modification of the graph
567  void modifyGraph(const GraphChange& change);
568 
569  /// indicates whether a change will always violate the constraint
570  bool isAlwaysInvalid(const GraphChange& change) const;
571 
572  /// checks whether the constraints enable to add arc (x,y)
573  bool checkArcAddition(NodeId x, NodeId y) const;
574 
575  /// checks whether the constraints enable to remove arc (x,y)
576  bool checkArcDeletion(NodeId x, NodeId y) const;
577 
578  /// checks whether the constraints enable to reverse arc (x,y)
579  bool checkArcReversal(NodeId x, NodeId y) const;
580 
581  /// checks whether the constraints enable to add an arc
582  bool checkModification(const ArcAddition& change) const;
583 
584  /// checks whether the constraints enable to remove an arc
585  bool checkModification(const ArcDeletion& change) const;
586 
587  /// checks whether the constraints enable to reverse an arc
588  bool checkModification(const ArcReversal& change) const;
589 
590  /// checks whether the constraints enable to perform a graph change
591  bool checkModification(const GraphChange& change) const;
592 
593  /// @}
594  };
595 
596 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
597 
598  } /* namespace learning */
599 
600 } /* namespace gum */
601 
602 /// always include the templated function definitions
603 #include <agrum/BN/learning/constraints/structuralConstraintSetStatic_tpl.h>
604 
605 #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:669
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