aGrUM 3.0.0
a C++ library for (probabilistic) graphical models
gum::ExactBNdistance< GUM_SCALAR > Class Template Reference

ExactBNdistance computes exactly the KL divergence betweens 2 BNs. More...

#include <exactBNdistance.h>

Inheritance diagram for gum::ExactBNdistance< GUM_SCALAR >:
Collaboration diagram for gum::ExactBNdistance< GUM_SCALAR >:

Public Member Functions

 ExactBNdistance (const IBayesNet< GUM_SCALAR > &P, const IBayesNet< GUM_SCALAR > &Q)
 constructor must give 2 BNs
 ExactBNdistance (const BNdistance< GUM_SCALAR > &kl)
 copy constructor
 ~ExactBNdistance () override
 destructor
Complexity difficulty () const
 return KL::Complexity::Heavy,KL::Complexity::Difficult,KL::Complexity::Correct depending on the BNs p and q
Accessors to results. The first call do the computations. The

others do not.

double klPQ ()
Size errorPQ ()
double klQP ()
Size errorQP ()
double hellinger ()
double bhattacharya ()
double jsd ()
const IBayesNet< GUM_SCALAR > & p () const
const IBayesNet< GUM_SCALAR > & q () const

Protected Member Functions

void computeKL_ () final
void process_ ()

Protected Attributes

const IBayesNet< GUM_SCALAR > & p_
const IBayesNet< GUM_SCALAR > & q_
GUM_SCALAR klPQ_
GUM_SCALAR klQP_
Size errorPQ_
Size errorQP_
GUM_SCALAR hellinger_
GUM_SCALAR bhattacharya_
GUM_SCALAR jsd_

Private Member Functions

bool _checkCompatibility_ () const

Private Attributes

Complexity _difficulty_
bool _done_

Detailed Description

template<GUM_Numeric GUM_SCALAR>
class gum::ExactBNdistance< GUM_SCALAR >

ExactBNdistance computes exactly the KL divergence betweens 2 BNs.

ExactBNdistance should be used only if difficulty() gives an estimation ( KL_CORRECT ) of the needed time. KL.process() computes KL(P||Q) using klPQ() and KL(Q||P) using klQP(). The computations are made once. The second is for free :) ExactBNdistance allows as well to compute in the same time the Hellinger distance ( \(*\sqrt{\sum_i (\sqrt{p_i}-\sqrt{q_i})^2}\)) (Kokolakis and Nanopoulos, 2001).

It may happen that P*ln(P/Q) is not computable (Q=0 and P!=0). In such a case, KL keeps working but trace this error (errorPQ() and errorQP())? *

Warning
This ExactBNdistance should be use only if difficulty()==complexity::CORRECT or at most complexity::DIFFICULT ... snippets :
gum::KL base_kl(net1,net2);
if (base_kl.difficulty()!=KL::HEAVY) {
gum::ExactBNdistance kl(base_kl);
std::cout<<"KL net1||net2 :"<<kl.klPQ()<<std::endl;
} else {
gum::GibbsKL kl(base_kl);
std::cout<<"KL net1||net2 :"<<kl.klPQ()<<std::endl;
}
ExactBNdistance computes exactly the KL divergence betweens 2 BNs.

Definition at line 89 of file exactBNdistance.h.

Constructor & Destructor Documentation

◆ ExactBNdistance() [1/2]

template<GUM_Numeric GUM_SCALAR>
gum::ExactBNdistance< GUM_SCALAR >::ExactBNdistance ( const IBayesNet< GUM_SCALAR > & P,
const IBayesNet< GUM_SCALAR > & Q )

constructor must give 2 BNs

Exceptions
gum::OperationNotAllowedif the 2 BNs have not the same domainSize or compatible node sets.

Definition at line 59 of file exactBNdistance_tpl.h.

60 :
63 }
BNdistance(const IBayesNet< GUM_SCALAR > &P, const IBayesNet< GUM_SCALAR > &Q)
constructor must give 2 BNs
ExactBNdistance(const IBayesNet< GUM_SCALAR > &P, const IBayesNet< GUM_SCALAR > &Q)
constructor must give 2 BNs

References gum::BNdistance< GUM_SCALAR >::BNdistance(), and ExactBNdistance().

Referenced by ExactBNdistance(), ExactBNdistance(), and ~ExactBNdistance().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ExactBNdistance() [2/2]

template<GUM_Numeric GUM_SCALAR>
gum::ExactBNdistance< GUM_SCALAR >::ExactBNdistance ( const BNdistance< GUM_SCALAR > & kl)
explicit

copy constructor

Definition at line 66 of file exactBNdistance_tpl.h.

References gum::BNdistance< GUM_SCALAR >::BNdistance(), and ExactBNdistance().

Here is the call graph for this function:

◆ ~ExactBNdistance()

template<GUM_Numeric GUM_SCALAR>
gum::ExactBNdistance< GUM_SCALAR >::~ExactBNdistance ( )
override

destructor

Definition at line 72 of file exactBNdistance_tpl.h.

References ExactBNdistance().

Here is the call graph for this function:

Member Function Documentation

◆ _checkCompatibility_()

template<GUM_Numeric GUM_SCALAR>
bool gum::BNdistance< GUM_SCALAR >::_checkCompatibility_ ( ) const
privateinherited

Definition at line 145 of file BNdistance_tpl.h.

145 {
146 // should not be used
147 if (p_.size() != q_.size())
149 "BNdistance : the 2 BNs are not compatible (not the same size)")
150
151 for (auto node: p_.nodes()) {
152 const DiscreteVariable& vp = p_.variable(node);
153 if (!q_.exists(vp.name())) {
154 GUM_ERROR(OperationNotAllowed,
155 "BNdistance : the 2 BNs are not compatible (variable : " + vp.name() + ")");
156 }
157 const DiscreteVariable& vq = q_.variableFromName(vp.name());
158 if (vp != vq)
160 "BNdistance : the 2 BNs are not compatible "
161 "(not the same variable for the same name : "
162 + vp.toString() + "and " + vq.toString() + ")");
163 }
164
165 if (std::fabs(p_.log10DomainSize() - q_.log10DomainSize()) > 1e-14) {
167 "BNdistance : the 2 BNs are not compatible (not the same domainSize) : p="
168 << p_.log10DomainSize() << " q=" << q_.log10DomainSize() << " => "
169 << p_.log10DomainSize() - q_.log10DomainSize());
170 }
171
172 return true;
173 }
const IBayesNet< GUM_SCALAR > & q_
Definition BNdistance.h:157
const IBayesNet< GUM_SCALAR > & p_
Definition BNdistance.h:156
#define GUM_ERROR(type, msg)
Definition exceptions.h:76

References GUM_ERROR, gum::Variable::name(), p_, q_, and gum::DiscreteVariable::toString().

Referenced by BNdistance().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ bhattacharya()

template<GUM_Numeric GUM_SCALAR>
double gum::BNdistance< GUM_SCALAR >::bhattacharya ( )
inherited
Returns
Bhattacharya distance (
See also
http://en.wikipedia.org/wiki/Bhattacharya_distance)

Definition at line 110 of file BNdistance_tpl.h.

110 {
111 process_();
112 return bhattacharya_;
113 }
GUM_SCALAR bhattacharya_
Definition BNdistance.h:166

References bhattacharya_, and process_().

Here is the call graph for this function:

◆ computeKL_()

template<GUM_Numeric GUM_SCALAR>
void gum::ExactBNdistance< GUM_SCALAR >::computeKL_ ( )
finalprotectedvirtual

Reimplemented from gum::BNdistance< GUM_SCALAR >.

Definition at line 77 of file exactBNdistance_tpl.h.

77 {
79 errorPQ_ = errorQP_ = 0;
80
81 auto Ip = p_.completeInstantiation();
82 auto Iq = q_.completeInstantiation();
83
84 // map between p_ variables and q_ variables (using name of vars)
86
87 for (Idx ite = 0; ite < Ip.nbrDim(); ++ite) {
88 map.insert(&Ip.variable(ite), &q_.variableFromName(Ip.variable(ite).name()));
89 }
91 for (Ip.setFirst(); !Ip.end(); ++Ip) {
92 Iq.setValsFrom(map, Ip);
93 pp = p_.jointProbability(Ip);
94 pq = q_.jointProbability(Iq);
95 pmid = (pp + pq) / 2.0;
99
100
103
104 if (pp != (GUM_SCALAR)0.0) {
105 if (pq != (GUM_SCALAR)0.0) {
106 klPQ_ -= pp * (lpq - lpp); // log2(pq / pp);
107 } else {
108 errorPQ_++;
109 }
110 }
111
112 if (pq != (GUM_SCALAR)0.0) {
113 if (pp != (GUM_SCALAR)0.0) {
114 klQP_ -= pq * (lpp - lpq); // log2(pp / pq);
115 } else {
116 errorQP_++;
117 }
118 }
119 if (pmid != (GUM_SCALAR)0.0) {
120 jsd_ += pp * lpp + pq * lpq
121 - (pp + pq) * lpmid; // pp* log2(pp / pmid) + pq * log2(pq / pmid);
122 }
123 }
124 jsd_ /= 2.0;
127 }
GUM_SCALAR hellinger_
Definition BNdistance.h:165
GUM_SCALAR klPQ_
Definition BNdistance.h:159
GUM_SCALAR jsd_
Definition BNdistance.h:167
GUM_SCALAR klQP_
Definition BNdistance.h:160
#define GUM_LOG2_OR_0(x)
Definition math_utils.h:70

References gum::BNdistance< GUM_SCALAR >::bhattacharya_, gum::BNdistance< GUM_SCALAR >::errorPQ_, gum::BNdistance< GUM_SCALAR >::errorQP_, GUM_LOG2_OR_0, gum::BNdistance< GUM_SCALAR >::hellinger_, gum::HashTable< Key, Val >::insert(), gum::BNdistance< GUM_SCALAR >::jsd_, gum::BNdistance< GUM_SCALAR >::klPQ_, gum::BNdistance< GUM_SCALAR >::klQP_, gum::BNdistance< GUM_SCALAR >::p_, and gum::BNdistance< GUM_SCALAR >::q_.

Here is the call graph for this function:

◆ difficulty()

template<GUM_Numeric GUM_SCALAR>
Complexity gum::BNdistance< GUM_SCALAR >::difficulty ( ) const
inherited

return KL::Complexity::Heavy,KL::Complexity::Difficult,KL::Complexity::Correct depending on the BNs p and q

Definition at line 87 of file BNdistance_tpl.h.

87 {
88 return _difficulty_;
89 }
Complexity _difficulty_
Definition BNdistance.h:171

References _difficulty_.

◆ errorPQ()

template<GUM_Numeric GUM_SCALAR>
Size gum::BNdistance< GUM_SCALAR >::errorPQ ( )
inherited
Returns
the number of errors while processing divergence KL(P||Q)

Definition at line 122 of file BNdistance_tpl.h.

122 {
123 process_();
124 return errorPQ_;
125 }

References errorPQ_, and process_().

Here is the call graph for this function:

◆ errorQP()

template<GUM_Numeric GUM_SCALAR>
Size gum::BNdistance< GUM_SCALAR >::errorQP ( )
inherited
Returns
the number of errors while processing divergence KL(Q||P)

Definition at line 128 of file BNdistance_tpl.h.

128 {
129 process_();
130 return errorQP_;
131 }

References errorQP_, and process_().

Here is the call graph for this function:

◆ hellinger()

template<GUM_Numeric GUM_SCALAR>
double gum::BNdistance< GUM_SCALAR >::hellinger ( )
inherited
Returns
hellinger distance (
See also
http://en.wikipedia.org/wiki/Hellinger_distance)

Definition at line 104 of file BNdistance_tpl.h.

104 {
105 process_();
106 return hellinger_;
107 }

References hellinger_, and process_().

Here is the call graph for this function:

◆ jsd()

template<GUM_Numeric GUM_SCALAR>
double gum::BNdistance< GUM_SCALAR >::jsd ( )
inherited
Returns
Jensen-Shannon divergence(
See also
https://en.wikipedia.org/wiki/Jensen%E2%80%93Shannon_divergence)

Definition at line 116 of file BNdistance_tpl.h.

116 {
117 process_();
118 return jsd_;
119 }

References jsd_, and process_().

Here is the call graph for this function:

◆ klPQ()

template<GUM_Numeric GUM_SCALAR>
double gum::BNdistance< GUM_SCALAR >::klPQ ( )
inherited
Returns
divergence KL(P||Q)

Definition at line 92 of file BNdistance_tpl.h.

92 {
93 process_();
94 return klPQ_;
95 }

References klPQ_, and process_().

Here is the call graph for this function:

◆ klQP()

template<GUM_Numeric GUM_SCALAR>
double gum::BNdistance< GUM_SCALAR >::klQP ( )
inherited
Returns
divergence KL(Q||P)

Definition at line 98 of file BNdistance_tpl.h.

98 {
99 process_();
100 return klQP_;
101 }

References klQP_, and process_().

Here is the call graph for this function:

◆ p()

template<GUM_Numeric GUM_SCALAR>
const IBayesNet< GUM_SCALAR > & gum::BNdistance< GUM_SCALAR >::p ( ) const
inherited
Returns
p

Definition at line 134 of file BNdistance_tpl.h.

134 {
135 return p_;
136 }

References p_.

Referenced by gum::GibbsBNdistance< GUM_SCALAR >::GibbsBNdistance().

Here is the caller graph for this function:

◆ process_()

template<GUM_Numeric GUM_SCALAR>
void gum::BNdistance< GUM_SCALAR >::process_ ( )
protectedinherited

Definition at line 177 of file BNdistance_tpl.h.

177 {
178 if (!_done_) {
179 computeKL_();
180 _done_ = true;
181 }
182 }
virtual void computeKL_()

References _done_, and computeKL_().

Referenced by bhattacharya(), errorPQ(), errorQP(), hellinger(), jsd(), klPQ(), and klQP().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ q()

template<GUM_Numeric GUM_SCALAR>
const IBayesNet< GUM_SCALAR > & gum::BNdistance< GUM_SCALAR >::q ( ) const
inherited
Returns
q

Definition at line 139 of file BNdistance_tpl.h.

139 {
140 return q_;
141 }

References q_.

Member Data Documentation

◆ _difficulty_

template<GUM_Numeric GUM_SCALAR>
Complexity gum::BNdistance< GUM_SCALAR >::_difficulty_
privateinherited

Definition at line 171 of file BNdistance.h.

Referenced by BNdistance(), BNdistance(), and difficulty().

◆ _done_

template<GUM_Numeric GUM_SCALAR>
bool gum::BNdistance< GUM_SCALAR >::_done_
privateinherited

Definition at line 172 of file BNdistance.h.

Referenced by BNdistance(), BNdistance(), and process_().

◆ bhattacharya_

template<GUM_Numeric GUM_SCALAR>
GUM_SCALAR gum::BNdistance< GUM_SCALAR >::bhattacharya_
protectedinherited

◆ errorPQ_

template<GUM_Numeric GUM_SCALAR>
Size gum::BNdistance< GUM_SCALAR >::errorPQ_
protectedinherited

◆ errorQP_

template<GUM_Numeric GUM_SCALAR>
Size gum::BNdistance< GUM_SCALAR >::errorQP_
protectedinherited

◆ hellinger_

template<GUM_Numeric GUM_SCALAR>
GUM_SCALAR gum::BNdistance< GUM_SCALAR >::hellinger_
protectedinherited

◆ jsd_

template<GUM_Numeric GUM_SCALAR>
GUM_SCALAR gum::BNdistance< GUM_SCALAR >::jsd_
protectedinherited

◆ klPQ_

template<GUM_Numeric GUM_SCALAR>
GUM_SCALAR gum::BNdistance< GUM_SCALAR >::klPQ_
protectedinherited

◆ klQP_

template<GUM_Numeric GUM_SCALAR>
GUM_SCALAR gum::BNdistance< GUM_SCALAR >::klQP_
protectedinherited

◆ p_

template<GUM_Numeric GUM_SCALAR>
const IBayesNet< GUM_SCALAR >& gum::BNdistance< GUM_SCALAR >::p_
protectedinherited

◆ q_

template<GUM_Numeric GUM_SCALAR>
const IBayesNet< GUM_SCALAR >& gum::BNdistance< GUM_SCALAR >::q_
protectedinherited

The documentation for this class was generated from the following files: