aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
aggregatorDecomposition_tpl.h
Go to the documentation of this file.
1
/**
2
*
3
* Copyright 2005-2019 Pierre-Henri WUILLEMIN & Christophe GONZALES(@AMU)
4
* {prenom.nom}_at_lip6.fr
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 Inline implementation of AggregatorDecomposition.
25
*
26
* @author Gaspard Ducamp
27
*
28
*/
29
#
include
<
agrum
/
BN
/
inference
/
tools
/
aggregatorDecomposition
.
h
>
30
#
include
<
typeinfo
>
31
#
include
<
list
>
32
33
namespace
gum
{
34
35
template
<
typename
GUM_SCALAR >
36
INLINE AggregatorDecomposition<
GUM_SCALAR
>::
AggregatorDecomposition
() {
37
_arity_
= 2;
38
GUM_CONSTRUCTOR
(
AggregatorDecomposition
);
39
}
40
41
template
<
typename
GUM_SCALAR
>
42
AggregatorDecomposition
<
GUM_SCALAR
>::~
AggregatorDecomposition
() {
43
GUM_DESTRUCTOR
(
AggregatorDecomposition
);
44
}
45
46
template
<
typename
GUM_SCALAR
>
47
BayesNet
<
GUM_SCALAR
>&
48
AggregatorDecomposition
<
GUM_SCALAR
>::
getDecomposedAggregator
(
BayesNet
<
GUM_SCALAR
>&
bn
) {
49
for
(
NodeId
node
:
bn
.
nodes
().
asNodeSet
()) {
50
std
::
string
description
=
bn
.
cpt
(
node
).
toString
();
51
auto
p
=
dynamic_cast
<
const
gum
::
aggregator
::
MultiDimAggregator
<
GUM_SCALAR
>* >(
52
bn
.
cpt
(
node
).
content
());
53
if
(
p
!=
nullptr
&&
p
->
isDecomposable
()) {
decomposeAggregator_
(
bn
,
node
); }
54
}
55
return
bn
;
56
}
57
58
template
<
typename
GUM_SCALAR
>
59
NodeId
AggregatorDecomposition
<
GUM_SCALAR
>::
addAggregator_
(
BayesNet
<
GUM_SCALAR
>&
bn
,
60
std
::
string
aggType
,
61
const
DiscreteVariable
&
var
,
62
Idx
value
) {
63
if
(
toLower
(
aggType
) ==
"min"
) {
64
return
bn
.
addMIN
(
var
);
65
}
else
if
(
toLower
(
aggType
) ==
"max"
) {
66
return
bn
.
addMAX
(
var
);
67
}
else
if
(
toLower
(
aggType
) ==
"count"
) {
68
return
bn
.
addCOUNT
(
var
,
value
);
69
}
else
if
(
toLower
(
aggType
) ==
"exists"
) {
70
return
bn
.
addEXISTS
(
var
,
value
);
71
}
else
if
(
toLower
(
aggType
) ==
"or"
) {
72
return
bn
.
addOR
(
var
);
73
}
else
if
(
toLower
(
aggType
) ==
"and"
) {
74
return
bn
.
addAND
(
var
);
75
}
else
if
(
toLower
(
aggType
) ==
"forall"
) {
76
return
bn
.
addFORALL
(
var
);
77
}
else
if
(
toLower
(
aggType
) ==
"amplitude"
) {
78
return
bn
.
addAMPLITUDE
(
var
);
79
}
else
if
(
toLower
(
aggType
) ==
"median"
) {
80
return
bn
.
addMEDIAN
(
var
);
81
}
else
if
(
toLower
(
aggType
) ==
"sum"
) {
82
return
bn
.
addSUM
(
var
);
83
}
else
{
84
std
::
string
msg
=
"Unknown aggregate: "
;
85
msg
.
append
(
aggType
);
86
GUM_ERROR
(
NotFound
,
msg
)
87
}
88
}
89
90
template
<
typename
GUM_SCALAR
>
91
BayesNet
<
GUM_SCALAR
>&
92
AggregatorDecomposition
<
GUM_SCALAR
>::
decomposeAggregator_
(
BayesNet
<
GUM_SCALAR
>&
bn
,
93
NodeId
initialAggregator
) {
94
auto
p
=
static_cast
<
const
gum
::
aggregator
::
MultiDimAggregator
<
GUM_SCALAR
>* >(
95
bn
.
cpt
(
initialAggregator
).
content
());
96
auto
newAgg
=
bn
.
variable
(
initialAggregator
).
clone
();
97
98
Set
<
NodeId
>
parents
=
bn
.
parents
(
initialAggregator
);
99
100
std
::
list
<
NodeId
>
orderedParents
= {};
101
102
for
(
const
auto
&
elt
:
parents
) {
103
orderedParents
.
push_back
(
elt
);
104
}
105
106
orderedParents
.
sort
();
107
108
Set
<
NodeId
>
newAggs
=
Set
<
NodeId
>();
109
List
<
NodeId
>
newAggParents
;
110
111
gum
::
Size
arity
=
getMaximumArity
();
112
gum
::
Size
q
= 0;
113
gum
::
Size
i
= 0;
114
115
long
minVal
= 0;
116
long
maxVal
= 0;
117
118
int
j
= 1;
119
120
std
::
string
newName
121
=
std
::
string
(
bn
.
variable
(
initialAggregator
).
name
()) +
"_"
+
std
::
to_string
(
j
);
122
std
::
string
aggType
=
p
->
aggregatorName
();
123
124
for
(
auto
parent
:
parents
) {
125
bn
.
eraseArc
(
parent
,
initialAggregator
);
126
}
127
128
/*
129
* We are constructing the new aggregator with a clone of the former
130
*/
131
newAgg
->
setName
(
newName
);
132
newAgg
->
setDescription
(
aggType
);
133
134
// for(Set<NodeId>::iterator it = parents.begin(); it!= parents.end(); ++it){
135
for
(
auto
it
=
orderedParents
.
begin
();
it
!=
orderedParents
.
end
(); ++
it
) {
136
if
(
q
<
parents
.
size
() -
parents
.
size
() %
arity
) {
137
if
(
i
==
arity
) {
138
i
= 0;
139
j
++;
140
141
if
(
newAgg
->
varType
() ==
VarType
::
Labelized
) {
142
addAggregator_
(
bn
,
aggType
, *
newAgg
,
p
->
domainSize
());
143
}
else
if
(
newAgg
->
varType
() ==
VarType
::
Range
) {
144
static_cast
<
RangeVariable
* >(
newAgg
)->
setMinVal
(
minVal
);
145
static_cast
<
RangeVariable
* >(
newAgg
)->
setMaxVal
(
maxVal
);
146
addAggregator_
(
bn
,
aggType
, *
newAgg
, 0);
147
}
else
{
148
GUM_ERROR
(
OperationNotAllowed
,
"Decomposition is not available for type : "
+
aggType
)
149
}
150
151
/*
152
* Adding arcs in the new node from its parents and adding thoses into
153
* the temporary potential
154
*/
155
for
(
NodeId
node
:
newAggParents
) {
156
bn
.
addArc
(
node
,
bn
.
idFromName
(
newName
));
157
}
158
159
/*
160
* Adding the new aggregator in t
161
*/
162
newAggs
.
insert
(
bn
.
idFromName
(
newName
));
163
164
newAggParents
.
clear
();
165
166
minVal
= 0;
167
maxVal
= 0;
168
169
newName
=
std
::
string
(
bn
.
variable
(
initialAggregator
).
name
()) +
"_"
+
std
::
to_string
(
j
);
170
171
delete
(
newAgg
);
172
newAgg
=
bn
.
variable
(
initialAggregator
).
clone
();
173
newAgg
->
setName
(
newName
);
174
newAgg
->
setDescription
(
aggType
);
175
176
if
(
bn
.
variable
(*
it
).
varType
() ==
VarType
::
Range
) {
177
minVal
+=
static_cast
<
const
RangeVariable
& >(
bn
.
variable
(*
it
)).
minVal
();
178
maxVal
+=
static_cast
<
const
RangeVariable
& >(
bn
.
variable
(*
it
)).
maxVal
();
179
}
180
181
newAggParents
.
push_back
(*
it
);
182
i
++;
183
}
else
{
184
if
(
bn
.
variable
(*
it
).
varType
() ==
VarType
::
Range
) {
185
minVal
+=
static_cast
<
const
RangeVariable
& >(
bn
.
variable
(*
it
)).
minVal
();
186
maxVal
+=
static_cast
<
const
RangeVariable
& >(
bn
.
variable
(*
it
)).
maxVal
();
187
}
188
189
newAggParents
.
push_back
(*
it
);
190
i
++;
191
}
192
}
else
{
193
newAggs
.
insert
(*
it
);
194
}
195
q
++;
196
}
197
198
if
(
newAgg
->
varType
() ==
VarType
::
Labelized
) {
199
addAggregator_
(
bn
,
aggType
, *
newAgg
,
p
->
domainSize
());
200
}
else
if
(
newAgg
->
varType
() ==
VarType
::
Range
) {
201
static_cast
<
RangeVariable
* >(
newAgg
)->
setMinVal
(
minVal
);
202
static_cast
<
RangeVariable
* >(
newAgg
)->
setMaxVal
(
maxVal
);
203
addAggregator_
(
bn
,
aggType
, *
newAgg
, 0);
204
}
else
{
205
GUM_ERROR
(
OperationNotAllowed
,
"Decomposition is not available for type : "
+
aggType
)
206
}
207
208
newAggs
.
insert
(
bn
.
idFromName
(
newName
));
209
210
for
(
NodeId
node
:
newAggParents
) {
211
bn
.
addArc
(
node
,
bn
.
idFromName
(
newName
));
212
}
213
214
Set
<
NodeId
>
final
=
addDepthLayer_
(
bn
,
newAggs
,
initialAggregator
,
j
);
215
216
for
(
auto
agg
:
final
) {
217
bn
.
addArc
(
agg
,
initialAggregator
);
218
}
219
220
delete
(
newAgg
);
221
return
bn
;
222
}
223
224
template
<
typename
GUM_SCALAR
>
225
Set
<
NodeId
>
AggregatorDecomposition
<
GUM_SCALAR
>::
addDepthLayer_
(
BayesNet
<
GUM_SCALAR
>&
bn
,
226
Set
<
NodeId
>
nodes
,
227
NodeId
initialAggregator
,
228
int
&
j
) {
229
auto
p
=
static_cast
<
const
gum
::
aggregator
::
MultiDimAggregator
<
GUM_SCALAR
>* >(
230
bn
.
cpt
(
initialAggregator
).
content
());
231
232
gum
::
Size
arity
=
getMaximumArity
();
233
std
::
string
aggType
=
p
->
aggregatorName
();
234
235
if
(
nodes
.
size
() <=
arity
) {
236
return
nodes
;
237
}
else
{
238
auto
newAgg
=
bn
.
variable
(
initialAggregator
).
clone
();
239
240
Set
<
NodeId
>
newAggs
=
Set
<
NodeId
>();
241
242
List
<
NodeId
>
newAggParents
;
243
244
std
::
list
<
NodeId
>
orderedParents
= {};
245
246
for
(
const
auto
&
elt
:
nodes
) {
247
orderedParents
.
push_back
(
elt
);
248
}
249
250
orderedParents
.
sort
();
251
252
gum
::
Size
i
= 0;
253
gum
::
Size
q
= 0;
254
long
minVal
= 0;
255
long
maxVal
= 0;
256
257
j
++;
258
259
std
::
string
newName
260
=
std
::
string
(
bn
.
variable
(
initialAggregator
).
name
()) +
"_"
+
std
::
to_string
(
j
);
261
262
newAgg
->
setName
(
newName
);
263
newAgg
->
setDescription
(
aggType
);
264
265
// for(Set<NodeId>::iterator it = nodes.begin(); it!= nodes.end(); ++it){
266
for
(
auto
it
=
orderedParents
.
begin
();
it
!=
orderedParents
.
end
(); ++
it
) {
267
if
(
q
<
nodes
.
size
() -
nodes
.
size
() %
arity
) {
268
if
(
i
==
arity
) {
269
i
= 0;
270
j
++;
271
272
if
(
newAgg
->
varType
() ==
VarType
::
Labelized
) {
273
addAggregator_
(
bn
,
aggType
, *
newAgg
,
p
->
domainSize
());
274
}
else
if
(
newAgg
->
varType
() ==
VarType
::
Range
) {
275
static_cast
<
RangeVariable
* >(
newAgg
)->
setMinVal
(
minVal
);
276
static_cast
<
RangeVariable
* >(
newAgg
)->
setMaxVal
(
maxVal
);
277
addAggregator_
(
bn
,
aggType
, *
newAgg
, 0);
278
}
else
{
279
GUM_ERROR
(
OperationNotAllowed
,
"Decomposition is not available for type : "
+
aggType
)
280
}
281
282
for
(
NodeId
node
:
newAggParents
) {
283
bn
.
addArc
(
node
,
bn
.
idFromName
(
newName
));
284
}
285
286
newAggs
.
insert
(
bn
.
idFromName
(
newName
));
287
288
newAggParents
.
clear
();
289
290
minVal
= 0;
291
maxVal
= 0;
292
293
newName
=
std
::
string
(
bn
.
variable
(
initialAggregator
).
name
()) +
"_"
+
std
::
to_string
(
j
);
294
295
delete
(
newAgg
);
296
newAgg
=
bn
.
variable
(
initialAggregator
).
clone
();
297
newAgg
->
setName
(
newName
);
298
newAgg
->
setDescription
(
aggType
);
299
300
if
(
bn
.
variable
(*
it
).
varType
() ==
VarType
::
Range
) {
301
minVal
+=
static_cast
<
const
RangeVariable
& >(
bn
.
variable
(*
it
)).
minVal
();
302
maxVal
+=
static_cast
<
const
RangeVariable
& >(
bn
.
variable
(*
it
)).
maxVal
();
303
}
304
305
newAggParents
.
push_back
(*
it
);
306
i
++;
307
}
else
{
308
if
(
bn
.
variable
(*
it
).
varType
() ==
VarType
::
Range
) {
309
minVal
+=
static_cast
<
const
RangeVariable
& >(
bn
.
variable
(*
it
)).
minVal
();
310
maxVal
+=
static_cast
<
const
RangeVariable
& >(
bn
.
variable
(*
it
)).
maxVal
();
311
}
312
313
newAggParents
.
push_back
(*
it
);
314
i
++;
315
}
316
}
else
{
317
newAggs
.
insert
(*
it
);
318
}
319
q
++;
320
}
321
322
if
(
newAgg
->
varType
() ==
VarType
::
Labelized
) {
323
addAggregator_
(
bn
,
aggType
, *
newAgg
,
p
->
domainSize
());
324
}
else
if
(
newAgg
->
varType
() ==
VarType
::
Range
) {
325
static_cast
<
RangeVariable
* >(
newAgg
)->
setMinVal
(
minVal
);
326
static_cast
<
RangeVariable
* >(
newAgg
)->
setMaxVal
(
maxVal
);
327
addAggregator_
(
bn
,
aggType
, *
newAgg
, 0);
328
}
else
{
329
GUM_ERROR
(
OperationNotAllowed
,
"Decomposition is not available for type : "
+
aggType
)
330
}
331
332
newAggs
.
insert
(
bn
.
idFromName
(
newName
));
333
334
for
(
NodeId
node
:
newAggParents
) {
335
bn
.
addArc
(
node
,
bn
.
idFromName
(
newName
));
336
}
337
338
delete
(
newAgg
);
339
return
addDepthLayer_
(
bn
,
newAggs
,
initialAggregator
,
j
);
340
}
341
}
342
343
344
template
<
typename
GUM_SCALAR
>
345
INLINE
void
AggregatorDecomposition
<
GUM_SCALAR
>::
setMaximumArity
(
gum
::
Size
arity
) {
346
if
(
arity
< 2) {
GUM_ERROR
(
OperationNotAllowed
,
"Maximum arity should be at least 2"
) }
347
_arity_
=
arity
;
348
}
349
350
template
<
typename
GUM_SCALAR
>
351
gum
::
Size
AggregatorDecomposition
<
GUM_SCALAR
>::
getMaximumArity
() {
352
return
_arity_
;
353
}
354
355
template
<
typename
GUM_SCALAR
>
356
INLINE
std
::
string
AggregatorDecomposition
<
GUM_SCALAR
>::
name
()
const
{
357
return
"aggregator decomposition"
;
358
}
359
360
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643