aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
BNdistance.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 /**
23  * @file
24  * @brief algorithm for KL divergence between BNs
25  *
26  * @author Pierre-Henri WUILLEMIN(@LIP6)
27  *
28  */
29 #ifndef GUM_KL_H
30 #define GUM_KL_H
31 
32 #include <agrum/BN/IBayesNet.h>
33 #include <agrum/tools/core/sequence.h>
34 
35 namespace gum {
36 
37  /**
38  * @brief Complexity allows to characterize the awaited difficulty for an
39  * algorithm
40  * given a specific instance
41  * Therefore this is not a theoretical characterization but rather a pragmatic
42  * rate
43  * of that very instance.
44  */
45  enum class Complexity : char
46  {
47  Heavy,
48  Difficult,
49  Correct
50  };
51 
52  /**
53  * @class KL
54  *
55  * @brief KL is the base class for KL computation betweens 2 BNs.
56  *
57  * KL is not virtual because it may be instantiated but protected methods throw
58  *gum::OperationNotAllow : we do not know here how the computation is done.
59  * Since this computation may be very difficult, KL.Complexity() give an
60  *estimation
61  *( KL_Complexity::Heavy,KL_Complexity::Difficult,KL_Complexity::Correct ) of
62  *the
63  *needed time.
64  * KL.process() computes KL(P||Q) using klPQ() and KL(Q||P) using klQP(). The
65  *computations are made once. The second is for free :)
66  *
67  * It may happen that P*ln(P/Q) is not computable (Q=0 and P!=0). In such a
68  *case, KL
69  *keeps working but trace this error (errorPQ() and errorQP())?
70  */
71  template < typename GUM_SCALAR >
72  class BNdistance {
73 // difficulty is chosen w.r.t the log10DomainSize of the BN
74 #define GAP_COMPLEXITY_KL_HEAVY_DIFFICULT double(12.0)
75 #define GAP_COMPLEXITY_KL_DIFFICULT_CORRECT double(7.0)
76  public:
77  /** constructor must give 2 BNs
78  * @throw gum::OperationNotAllowed if the 2 BNs have not the same domainSize
79  * or
80  * compatible node sets.
81  */
82  BNdistance(const IBayesNet< GUM_SCALAR >& P, const IBayesNet< GUM_SCALAR >& Q);
83 
84  /** copy constructor
85  */
86  BNdistance(const BNdistance< GUM_SCALAR >& kl);
87 
88  /** destructor */
89  virtual ~BNdistance();
90 
91  /**
92  * return
93  * KL::Complexity::Heavy,KL::Complexity::Difficult,KL::Complexity::Correct
94  * depending on the BNs _p_ and _q_
95  */
96  Complexity difficulty() const;
97 
98  /// @name Accessors to results. The first call do the computations. The
99  /// others do
100  /// not.
101  /// @{
102 
103  /// @return divergence KL(P||Q)
104  double klPQ();
105 
106  /// @return the number of errors while processing divergence KL(P||Q)
107  Size errorPQ();
108 
109  /// @return divergence KL(Q||P)
110  double klQP();
111 
112  /// @return the number of errors while processing divergence KL(Q||P)
113  Size errorQP();
114 
115  /// @return hellinger distance (@see
116  /// http://en.wikipedia.org/wiki/Hellinger_distance)
117  double hellinger();
118 
119  /// @return Bhattacharya distance (@see
120  /// http://en.wikipedia.org/wiki/Bhattacharya_distance)
121  double bhattacharya();
122 
123  /// @return Jensen-Shannon divergence(@see
124  /// https://en.wikipedia.org/wiki/Jensen%E2%80%93Shannon_divergence)
125  double jsd();
126 
127  /// @return p
128  const IBayesNet< GUM_SCALAR >& p() const;
129 
130  /// @return q
131  const IBayesNet< GUM_SCALAR >& q() const;
132  /// @}
133 
134  protected:
135  // should be pure virtual but using BNdistance directly is a way to delay the
136  // choice between different computation scheme (@see ExactBNdistance)
137  virtual void computeKL_();
138 
139  void process_();
140 
143 
144  GUM_SCALAR klPQ_;
145  GUM_SCALAR klQP_;
146 
149 
150  GUM_SCALAR hellinger_;
151  GUM_SCALAR bhattacharya_;
152  GUM_SCALAR jsd_;
153 
154  private:
155  bool _checkCompatibility_() const;
157  bool _done_;
158  };
159 
160 
161 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
162 
163  extern template class BNdistance< double >;
164 
165 #endif
166 
167 } // namespace gum
168 
169 #include <agrum/BN/algorithms/divergence/BNdistance_tpl.h>
170 
171 #endif // GUM_KL_H
double bhattacharya()
Complexity difficulty() const
return KL::Complexity::Heavy,KL::Complexity::Difficult,KL::Complexity::Correct depending on the BNs p...
bool _checkCompatibility_() const
GUM_SCALAR klQP_
Definition: BNdistance.h:145
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
GUM_SCALAR klPQ_
Definition: BNdistance.h:144
BNdistance(const IBayesNet< GUM_SCALAR > &P, const IBayesNet< GUM_SCALAR > &Q)
constructor must give 2 BNs
const IBayesNet< GUM_SCALAR > & p() const
GUM_SCALAR hellinger_
Definition: BNdistance.h:150
Complexity _difficulty_
Definition: BNdistance.h:156
Complexity
Complexity allows to characterize the awaited difficulty for an algorithm given a specific instance T...
Definition: BNdistance.h:45
GUM_SCALAR bhattacharya_
Definition: BNdistance.h:151
const IBayesNet< GUM_SCALAR > & q() const
const IBayesNet< GUM_SCALAR > & p_
Definition: BNdistance.h:141
GUM_SCALAR jsd_
Definition: BNdistance.h:152
virtual ~BNdistance()
destructor
virtual void computeKL_()
const IBayesNet< GUM_SCALAR > & q_
Definition: BNdistance.h:142
double hellinger()
BNdistance(const BNdistance< GUM_SCALAR > &kl)
copy constructor