aGrUM
3.2.0
a C++ library for (probabilistic) graphical models
Toggle main menu visibility
informationTheory_tpl.h
Go to the documentation of this file.
1
/****************************************************************************
2
* This file is part of the aGrUM/pyAgrum library. *
3
* *
4
* Copyright (c) 2005-2026 by *
5
* - Pierre-Henri WUILLEMIN(_at_LIP6) *
6
* - Christophe GONZALES(_at_AMU) *
7
* *
8
* The aGrUM/pyAgrum library is free software; you can redistribute it *
9
* and/or modify it under the terms of either : *
10
* *
11
* - the GNU Lesser General Public License as published by *
12
* the Free Software Foundation, either version 3 of the License, *
13
* or (at your option) any later version, *
14
* - the MIT license (MIT), *
15
* - or both in dual license, as here. *
16
* *
17
* (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18
* *
19
* This aGrUM/pyAgrum library is distributed in the hope that it will be *
20
* useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26
* OTHER DEALINGS IN THE SOFTWARE. *
27
* *
28
* See LICENCES for more details. *
29
* *
30
* SPDX-FileCopyrightText: Copyright 2005-2026 *
31
* - Pierre-Henri WUILLEMIN(_at_LIP6) *
32
* - Christophe GONZALES(_at_AMU) *
33
* SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34
* *
35
* Contact : info_at_agrum_dot_org *
36
* homepage : http://agrum.gitlab.io *
37
* gitlab : https://gitlab.com/agrumery/agrum *
38
* *
39
****************************************************************************/
40
41
#pragma once
42
43
49
#include <utility>
50
51
#include <
agrum/base/core/exceptions.h
>
52
#include <
agrum/base/graphicalModels/algorithms/informationTheory.h
>
53
54
#include <
agrum/base/core/math/math_utils.h
>
55
56
#define INFORMATION_THEORY_TEMPLATE \
57
template < template < typename > class INFERENCE_ENGINE, \
58
typename GUM_SCALAR >
//@todo when CLANG-compliant for virtual class : requires
59
// JointTargettable< INFERENCE_ENGINE< GUM_SCALAR > >
60
61
namespace
gum
{
62
INFORMATION_THEORY_TEMPLATE
63
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::InformationTheory
(
64
INFERENCE_ENGINE< GUM_SCALAR >& engine,
65
gum::NodeSet
X,
66
gum::NodeSet
Y,
67
gum::NodeSet
Z) :
engine_
(engine),
X_
(
std
::move(X)),
Y_
(
std
::move(Y)),
Z_
(
std
::move(Z)) {
68
GUM_CONSTRUCTOR(
InformationTheory
)
69
if
((!(
X_
*
Y_
).empty()) || (!(
X_
*
Z_
).empty()) || (!(
Z_
*
Y_
).empty()))
70
GUM_ERROR
(
OperationNotAllowed
,
"The intersection between the set of variables must be empty"
)
71
makeInference_
();
72
}
73
74
INFORMATION_THEORY_TEMPLATE
75
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::InformationTheory
(
76
INFERENCE_ENGINE< GUM_SCALAR >& engine,
77
const
gum::NodeSet
& X,
78
const
gum::NodeSet
& Y) :
InformationTheory
(engine, X, Y,
NodeSet
()) {}
79
80
INFORMATION_THEORY_TEMPLATE
81
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::InformationTheory
(
82
INFERENCE_ENGINE< GUM_SCALAR >& engine,
83
const
std::vector< std::string >& Xnames,
84
const
std::vector< std::string >& Ynames) :
85
InformationTheory
< INFERENCE_ENGINE, GUM_SCALAR >(engine,
86
engine.model().nodeset(Xnames),
87
engine.model().nodeset(Ynames),
88
NodeSet
()) {}
89
90
INFORMATION_THEORY_TEMPLATE
91
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::InformationTheory
(
92
INFERENCE_ENGINE< GUM_SCALAR >& engine,
93
const
std::vector< std::string >& Xnames,
94
const
std::vector< std::string >& Ynames,
95
const
std::vector< std::string >& Znames) :
96
InformationTheory
< INFERENCE_ENGINE, GUM_SCALAR >(engine,
97
engine.model().nodeset(Xnames),
98
engine.model().nodeset(Ynames),
99
engine.model().nodeset(Znames)) {}
100
101
INFORMATION_THEORY_TEMPLATE
102
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::~InformationTheory
() {
103
GUM_DESTRUCTOR(
InformationTheory
);
104
}
105
106
INFORMATION_THEORY_TEMPLATE
107
void
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::makeInference_
() {
108
vX_
.clear();
109
for
(
const
auto
x:
X_
)
110
vX_
.insert(&
engine_
.model().variable(x));
111
112
vY_
.clear();
113
for
(
const
auto
y:
Y_
)
114
vY_
.insert(&
engine_
.model().variable(y));
115
116
vZ_
.clear();
117
for
(
const
auto
z:
Z_
)
118
vZ_
.insert(&
engine_
.model().variable(z));
119
120
const
NodeSet
joint_vars =
X_
+
Y_
+
Z_
;
121
if
(!
engine_
.isJointTarget(joint_vars)) {
122
// we check if it is not an implicit target : containng a node and some of its parent (could
123
// be better)
124
bool
implicit_target =
false
;
125
for
(
const
auto
node: joint_vars)
126
if
(
engine_
.model().family(node).isSupersetOrEqual(joint_vars)) {
127
implicit_target =
true
;
128
break
;
129
}
130
if
(!implicit_target) {
131
engine_
.eraseAllJointTargets();
132
engine_
.addJointTarget(joint_vars);
133
}
134
}
135
engine_
.makeInference();
136
137
if
(!
Z_
.empty()) {
138
pXYZ_
=
engine_
.jointPosterior(joint_vars);
139
pXZ_
=
pXYZ_
.sumIn(
vX_
+
vZ_
);
140
pYZ_
=
pXYZ_
.sumIn(
vY_
+
vZ_
);
141
pZ_
=
pXZ_
.sumIn(
vZ_
);
142
pXY_
=
pXYZ_
.sumIn(
vX_
+
vY_
);
143
}
else
{
144
pXY_
=
engine_
.jointPosterior(joint_vars);
145
}
146
pX_
=
pXY_
.sumIn(
vX_
);
147
pY_
=
pXY_
.sumIn(
vY_
);
148
}
149
150
INFORMATION_THEORY_TEMPLATE
151
GUM_SCALAR
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::entropyX
() {
return
pX_
.entropy(); }
152
153
INFORMATION_THEORY_TEMPLATE
154
GUM_SCALAR
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::entropyY
() {
return
pY_
.entropy(); }
155
156
INFORMATION_THEORY_TEMPLATE
157
GUM_SCALAR
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::entropyXY
() {
158
return
pXY_
.entropy();
159
}
160
161
INFORMATION_THEORY_TEMPLATE
162
GUM_SCALAR
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::entropyXgivenY
() {
163
return
-
pXY_
.expectedValue([
this
](
const
gum::Instantiation
& i) -> GUM_SCALAR {
164
// f(x,y)=log (p(x,y)/p(y))
165
const
auto
& pxy =
pXY_
[i];
166
if
(pxy == GUM_SCALAR(0.0))
return
GUM_SCALAR(0.0);
167
168
const
auto
& py =
pY_
[i];
169
if
(py == GUM_SCALAR(0.0))
return
GUM_SCALAR(0.0);
170
171
return
GUM_LOG2_OR_0
(pxy / py);
172
});
173
}
174
175
INFORMATION_THEORY_TEMPLATE
176
GUM_SCALAR
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::entropyYgivenX
() {
177
return
-
pXY_
.expectedValue([
this
](
const
gum::Instantiation
& i) -> GUM_SCALAR {
178
// f(x,y)=log (p(x,y)/p(x))
179
const
auto
& pxy =
pXY_
[i];
180
if
(pxy == GUM_SCALAR(0.0))
return
GUM_SCALAR(0.0);
181
182
const
auto
& px =
pX_
[i];
183
if
(px == GUM_SCALAR(0.0))
return
GUM_SCALAR(0.0);
184
185
return
GUM_LOG2_OR_0
(pxy / px);
186
});
187
}
188
189
INFORMATION_THEORY_TEMPLATE
190
GUM_SCALAR
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::entropyXgivenZ
() {
191
if
(
Z_
.empty())
GUM_ERROR
(
ArgumentError
,
"Z has not been specified."
)
192
return
-
pXZ_
.expectedValue([
this
](
const
gum::Instantiation
& i) -> GUM_SCALAR {
193
// f(x,z)=log (p(x,z)/p(z))
194
const
auto
& pxz =
pXZ_
[i];
195
if
(pxz == GUM_SCALAR(0.0))
return
GUM_SCALAR(0.0);
196
197
const
auto
& pz =
pZ_
[i];
198
if
(pz == GUM_SCALAR(0.0))
return
GUM_SCALAR(0.0);
199
200
return
GUM_LOG2_OR_0
(pxz / pz);
201
});
202
}
203
204
INFORMATION_THEORY_TEMPLATE
205
GUM_SCALAR
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::entropyYgivenZ
() {
206
if
(
Z_
.empty())
GUM_ERROR
(
ArgumentError
,
"Z has not been specified."
)
207
return
-
pYZ_
.expectedValue([
this
](
const
gum::Instantiation
& i) -> GUM_SCALAR {
208
// f(y,z)=log (p(y,z)/p(z))
209
const
auto
& pyz =
pYZ_
[i];
210
if
(pyz == GUM_SCALAR(0.0))
return
GUM_SCALAR(0.0);
211
212
const
auto
& pz =
pZ_
[i];
213
if
(pz == GUM_SCALAR(0.0))
return
GUM_SCALAR(0.0);
214
215
return
GUM_LOG2_OR_0
(pyz / pz);
216
});
217
}
218
219
INFORMATION_THEORY_TEMPLATE
220
GUM_SCALAR
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::mutualInformationXY
() {
221
return
pXY_
.expectedValue([
this
](
const
gum::Instantiation
& i) -> GUM_SCALAR {
222
// f(x,y)=log (p(x,y)/p(x)p(y))
223
const
auto
& pxy =
pXY_
[i];
224
if
(pxy == GUM_SCALAR(0.0))
return
GUM_SCALAR(0.0);
225
226
const
auto
& pxpy =
pY_
[i] *
pX_
[i];
227
if
(pxpy == GUM_SCALAR(0.0))
return
GUM_SCALAR(0.0);
228
229
return
GUM_LOG2_OR_0
(pxy / pxpy);
230
});
231
}
232
233
INFORMATION_THEORY_TEMPLATE
234
GUM_SCALAR
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::variationOfInformationXY
() {
235
return
-
pXY_
.expectedValue([
this
](
const
gum::Instantiation
& i) -> GUM_SCALAR {
236
// f(x,y)= -log(p(x)*p(y))
237
return
GUM_LOG2_OR_0
(
pY_
[i] *
pX_
[i]);
238
});
239
}
240
241
INFORMATION_THEORY_TEMPLATE
242
GUM_SCALAR
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::entropyXYgivenZ
() {
243
if
(
Z_
.empty())
GUM_ERROR
(
ArgumentError
,
"Z has not been specified."
)
244
return
pXYZ_
.expectedValue([
this
](
const
gum::Instantiation
& i) -> GUM_SCALAR {
245
// f(x,y,z)= -log(p(x,y,z)/p(z))
246
const
auto
& pxyz =
pXYZ_
[i];
247
if
(pxyz == GUM_SCALAR(0.0))
return
GUM_SCALAR(0.0);
248
249
const
auto
& pz =
pZ_
[i];
250
if
(pz == GUM_SCALAR(0.0))
return
GUM_SCALAR(0.0);
251
252
return
-
GUM_LOG2_OR_0
(pxyz / pz);
253
});
254
}
255
256
INFORMATION_THEORY_TEMPLATE
257
GUM_SCALAR
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::entropyXgivenYZ
() {
258
if
(
Z_
.empty())
GUM_ERROR
(
ArgumentError
,
"Z has not been specified."
)
259
return
pXYZ_
.expectedValue([
this
](
const
gum::Instantiation
& i) -> GUM_SCALAR {
260
// f(x,y,z)= -log(p(x,y,z)/p(y,z))
261
const
auto
& pxyz =
pXYZ_
[i];
262
if
(pxyz == GUM_SCALAR(0.0))
return
GUM_SCALAR(0.0);
263
264
const
auto
& pyz =
pYZ_
[i];
265
if
(pyz == GUM_SCALAR(0.0))
return
GUM_SCALAR(0.0);
266
267
return
-
GUM_LOG2_OR_0
(pxyz / pyz);
268
});
269
}
270
271
INFORMATION_THEORY_TEMPLATE
272
GUM_SCALAR
InformationTheory< INFERENCE_ENGINE, GUM_SCALAR >::mutualInformationXYgivenZ
() {
273
if
(
Z_
.empty())
GUM_ERROR
(
ArgumentError
,
"Z has not been specified."
)
274
return
pXYZ_
.expectedValue([
this
](
const
gum::Instantiation
& i) -> GUM_SCALAR {
275
// f(x,y)=log (p(x,y)/p(x)p(y))
276
const
auto
& pzpxyz =
pXYZ_
[i] *
pZ_
[i];
277
if
(pzpxyz == GUM_SCALAR(0.0))
return
GUM_SCALAR(0.0);
278
279
const
auto
& pxzpyz =
pXZ_
[i] *
pYZ_
[i];
280
if
(pxzpyz == GUM_SCALAR(0.0))
return
GUM_SCALAR(0.0);
281
282
return
GUM_LOG2_OR_0
(pzpxyz / pxzpyz);
283
});
284
}
285
286
#undef INFORMATION_THEORY_TEMPLATE
287
}
// namespace gum
ArgumentError
Exception base for argument error.
gum::InformationTheory::pY_
Tensor< GUM_SCALAR > pY_
Definition
informationTheory.h:131
gum::InformationTheory::pXYZ_
Tensor< GUM_SCALAR > pXYZ_
Definition
informationTheory.h:126
gum::InformationTheory::makeInference_
void makeInference_()
Definition
informationTheory_tpl.h:107
gum::InformationTheory::entropyYgivenZ
GUM_SCALAR entropyYgivenZ()
Definition
informationTheory_tpl.h:205
gum::InformationTheory::entropyY
GUM_SCALAR entropyY()
Definition
informationTheory_tpl.h:154
gum::InformationTheory::entropyXYgivenZ
GUM_SCALAR entropyXYgivenZ()
Definition
informationTheory_tpl.h:242
gum::InformationTheory::entropyXY
GUM_SCALAR entropyXY()
Definition
informationTheory_tpl.h:157
gum::InformationTheory::Z_
const NodeSet Z_
Definition
informationTheory.h:120
gum::InformationTheory::pX_
Tensor< GUM_SCALAR > pX_
Definition
informationTheory.h:130
gum::InformationTheory::entropyXgivenYZ
GUM_SCALAR entropyXgivenYZ()
Definition
informationTheory_tpl.h:257
gum::InformationTheory::vX_
VariableSet vX_
Definition
informationTheory.h:122
gum::InformationTheory::InformationTheory
InformationTheory(INFERENCE_ENGINE< GUM_SCALAR > &engine, NodeSet X, NodeSet Y, NodeSet Z)
Definition
informationTheory_tpl.h:63
gum::InformationTheory::entropyYgivenX
GUM_SCALAR entropyYgivenX()
Definition
informationTheory_tpl.h:176
gum::InformationTheory::mutualInformationXYgivenZ
GUM_SCALAR mutualInformationXYgivenZ()
Definition
informationTheory_tpl.h:272
gum::InformationTheory::pXZ_
Tensor< GUM_SCALAR > pXZ_
Definition
informationTheory.h:128
gum::InformationTheory::vY_
VariableSet vY_
Definition
informationTheory.h:123
gum::InformationTheory::vZ_
VariableSet vZ_
Definition
informationTheory.h:124
gum::InformationTheory::mutualInformationXY
GUM_SCALAR mutualInformationXY()
Definition
informationTheory_tpl.h:220
gum::InformationTheory::pYZ_
Tensor< GUM_SCALAR > pYZ_
Definition
informationTheory.h:129
gum::InformationTheory::entropyXgivenY
GUM_SCALAR entropyXgivenY()
Definition
informationTheory_tpl.h:162
gum::InformationTheory::variationOfInformationXY
GUM_SCALAR variationOfInformationXY()
Definition
informationTheory_tpl.h:234
gum::InformationTheory::X_
const NodeSet X_
Definition
informationTheory.h:118
gum::InformationTheory::pZ_
Tensor< GUM_SCALAR > pZ_
Definition
informationTheory.h:132
gum::InformationTheory::entropyXgivenZ
GUM_SCALAR entropyXgivenZ()
Definition
informationTheory_tpl.h:190
gum::InformationTheory::engine_
INFERENCE_ENGINE< GUM_SCALAR > & engine_
Definition
informationTheory.h:116
gum::InformationTheory::pXY_
Tensor< GUM_SCALAR > pXY_
Definition
informationTheory.h:127
gum::InformationTheory::~InformationTheory
~InformationTheory()
Definition
informationTheory_tpl.h:102
gum::InformationTheory::Y_
const NodeSet Y_
Definition
informationTheory.h:119
gum::InformationTheory::entropyX
GUM_SCALAR entropyX()
Definition
informationTheory_tpl.h:151
gum::Instantiation
Class for assigning/browsing values to tuples of discrete variables.
Definition
instantiation.h:102
OperationNotAllowed
Exception : operation not allowed.
exceptions.h
aGrUM's exceptions
GUM_ERROR
#define GUM_ERROR(type, msg)
Definition
exceptions.h:76
gum::NodeSet
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
Definition
graphElements.h:392
informationTheory.h
Class encapsulating computations of notions from Information Theory.
INFORMATION_THEORY_TEMPLATE
#define INFORMATION_THEORY_TEMPLATE
Definition
informationTheory_tpl.h:56
math_utils.h
Useful macros for maths.
GUM_LOG2_OR_0
#define GUM_LOG2_OR_0(x)
Definition
math_utils.h:70
gum
gum is the global namespace for all aGrUM entities
Definition
agrum.h:46
std
STL namespace.
aGrUM
3.2.0
© PHW&CG&others - 2022
DoXyGeN 1.18.0