aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
leafAggregator.cpp
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 Sources for Leaf Aggregator class
25
*
26
* @author Pierre-Henri WUILLEMIN(@LIP6) and Jean-Christophe MAGNAN and Christophe
27
* GONZALES(@AMU)
28
*/
29
// =======================================================
30
#
include
<
agrum
/
tools
/
core
/
math
/
math_utils
.
h
>
31
#
include
<
agrum
/
FMDP
/
learning
/
datastructure
/
leaves
/
leafAggregator
.
h
>
32
// =======================================================
33
34
namespace
gum
{
35
36
// ############################################################################
37
// Constructors / Destructors
38
// ############################################################################
39
40
// ============================================================================
41
// Default constructor.
42
// ============================================================================
43
LeafAggregator
::
LeafAggregator
(
NodeGraphPart
*
idSource
,
double
similarityThreshold
) :
44
_leavesCpt_
(
idSource
),
_similarityThreshold_
(
similarityThreshold
) {
45
GUM_CONSTRUCTOR
(
LeafAggregator
);
46
_initialContext_
=
new
FusionContext
<
true
>(
nullptr
);
47
_needsUpdate_
=
false
;
48
}
49
50
// ============================================================================
51
// Default constructor.
52
// ============================================================================
53
LeafAggregator
::~
LeafAggregator
() {
54
_removeContext_
(0);
55
56
delete
_initialContext_
;
57
58
for
(
HashTableIteratorSafe
<
AbstractLeaf
*,
Set
<
LeafPair
* >* >
leafIter
59
=
_leaf2Pair_
.
beginSafe
();
60
leafIter
!=
_leaf2Pair_
.
endSafe
();
61
++
leafIter
) {
62
for
(
SetIteratorSafe
<
LeafPair
* >
pairIter
=
leafIter
.
val
()->
beginSafe
();
63
pairIter
!=
leafIter
.
val
()->
endSafe
();
64
++
pairIter
) {
65
LeafPair
*
curPair
= *
pairIter
;
66
_leaf2Pair_
[
curPair
->
otherLeaf
(
leafIter
.
key
())]->
erase
(*
pairIter
);
67
leafIter
.
val
()->
erase
(
curPair
);
68
delete
curPair
;
69
}
70
delete
leafIter
.
val
();
71
}
72
73
74
GUM_DESTRUCTOR
(
LeafAggregator
);
75
}
76
77
// ############################################################################
78
//
79
// ############################################################################
80
81
// ============================================================================
82
//
83
// ============================================================================
84
void
LeafAggregator
::
addLeaf
(
AbstractLeaf
*
l
) {
85
Set
<
LeafPair
* >*
leafPairSet
=
new
Set
<
LeafPair
* >();
86
Set
<
LeafPair
* >
bag
;
87
88
// ****************************************************************************************
89
// Création et ajout des pairs de base (Feuille de base + nouvelle Feuille)
90
for
(
HashTableConstIteratorSafe
<
AbstractLeaf
*,
Set
<
LeafPair
* >* >
leafIter
91
=
_leaf2Pair_
.
cbeginSafe
();
92
leafIter
!=
_leaf2Pair_
.
cendSafe
();
93
++
leafIter
) {
94
// Création de la pair et ajout dans les listes de pair des feuilles de
95
// base
96
LeafPair
*
p
=
new
LeafPair
(
l
,
leafIter
.
key
());
97
p
->
updateLikelyhood
();
98
leafPairSet
->
insert
(
p
);
99
(
leafIter
.
val
())->
insert
(
p
);
100
101
// Ajout de la nouvelle pair au tas initial
102
_addInitialPair_
(
p
);
103
104
bag
.
insert
(
p
);
105
}
106
107
// ****************************************************************************************
108
// Enregistrement de la nouvelle Feuille en tant que feuille de base
109
_leaf2Pair_
.
insert
(
l
,
leafPairSet
);
110
111
// ****************************************************************************************
112
// Ajout de la feuille aux FusionContext
113
114
for
(
SequenceIteratorSafe
<
FusionContext
<
false
>* >
fusIter
=
_fusionSeq_
.
beginSafe
();
115
fusIter
!=
_fusionSeq_
.
endSafe
();
116
++
fusIter
) {
117
// Ajout de la nouvelle pair composée de la feuille de FusIter et de la
118
// nouvelle feuille aux FusionContext suivant
119
for
(
SetIteratorSafe
<
LeafPair
* >
pairIter
=
bag
.
beginSafe
();
pairIter
!=
bag
.
endSafe
();
120
++
pairIter
) {
121
if
((*
fusIter
)->
leaf
()->
contains
((*
pairIter
)->
secondLeaf
()->
id
())) {
122
bag
>> *
pairIter
;
123
continue
;
124
}
125
126
if
((*
fusIter
)->
addPair
(*
pairIter
))
_removeContext_
(
fusIter
.
pos
() + 1);
127
}
128
129
if
((*
fusIter
)->
associateLeaf
(
l
))
_removeContext_
(
fusIter
.
pos
() + 1);
130
131
bag
<< (*
fusIter
)->
leafAssociatedPair
(
l
);
132
}
133
134
_needsUpdate_
=
true
;
135
}
136
137
138
// ============================================================================
139
//
140
// ============================================================================
141
bool
LeafAggregator
::
updateLeaf
(
AbstractLeaf
*
l
) {
142
// ***********************************************************************************
143
// First we update every base pair linked to that leaf
144
Set
<
LeafPair
* >
bag
(*(
_leaf2Pair_
[
l
]));
145
for
(
SetIteratorSafe
<
LeafPair
* >
pairIter
=
bag
.
beginSafe
();
pairIter
!=
bag
.
endSafe
();
146
++
pairIter
) {
147
(*
pairIter
)->
updateLikelyhood
();
148
_updateInitialPair_
(*
pairIter
);
149
}
150
151
// **********************************************************************************
152
// The we have top update FusionContext pairs associated to that leaf
153
AbstractLeaf
*
curLeaf
=
l
;
154
for
(
SequenceIteratorSafe
<
FusionContext
<
false
>* >
fusIter
=
_fusionSeq_
.
beginSafe
();
155
fusIter
!=
_fusionSeq_
.
endSafe
();
156
++
fusIter
) {
157
if
((*
fusIter
)->
leaf
()->
contains
(
curLeaf
->
id
())) {
158
bag
.
clear
();
159
if
((*
fusIter
)->
updateAllAssociatedLeaves
())
_removeContext_
(
fusIter
.
pos
() + 1);
160
bag
= (*
fusIter
)->
associatedPairs
();
161
curLeaf
= (*
fusIter
)->
leaf
();
162
continue
;
163
}
164
165
for
(
SetIteratorSafe
<
LeafPair
* >
pairIter
=
bag
.
beginSafe
();
pairIter
!=
bag
.
endSafe
();
166
++
pairIter
) {
167
if
((*
fusIter
)->
leaf
()->
contains
((*
pairIter
)->
secondLeaf
()->
id
())
168
|| (*
fusIter
)->
leaf
()->
contains
((*
pairIter
)->
firstLeaf
()->
id
())) {
169
bag
>> *
pairIter
;
170
continue
;
171
}
172
173
if
((*
fusIter
)->
updatePair
(*
pairIter
))
_removeContext_
(
fusIter
.
pos
() + 1);
174
}
175
if
((*
fusIter
)->
updateAssociatedLeaf
(
curLeaf
))
_removeContext_
(
fusIter
.
pos
() + 1);
176
bag
<< (*
fusIter
)->
leafAssociatedPair
(
curLeaf
);
177
}
178
179
return
_needsUpdate_
;
180
}
181
182
183
// ============================================================================
184
//
185
// ============================================================================
186
void
LeafAggregator
::
removeLeaf
(
AbstractLeaf
*
l
) {
187
// ***********************************************************************************
188
// First we update every base pair linked to that leaf
189
Set
<
LeafPair
* >
bag
(*(
_leaf2Pair_
[
l
]));
190
for
(
SetIteratorSafe
<
LeafPair
* >
pairIter
=
bag
.
beginSafe
();
pairIter
!=
bag
.
endSafe
();
191
++
pairIter
) {
192
_removeInitialPair_
(*
pairIter
);
193
(*
_leaf2Pair_
[(*
pairIter
)->
otherLeaf
(
l
)]) >> *
pairIter
;
194
}
195
196
// **********************************************************************************
197
// The we have top update FusionContext pairs associated to that leaf
198
Set
<
LeafPair
* >
toBeDeleted
;
199
for
(
SequenceIteratorSafe
<
FusionContext
<
false
>* >
fusIter
=
_fusionSeq_
.
beginSafe
();
200
fusIter
!=
_fusionSeq_
.
endSafe
();
201
++
fusIter
) {
202
for
(
SetIteratorSafe
<
LeafPair
* >
pairIter
=
bag
.
beginSafe
();
pairIter
!=
bag
.
endSafe
();
203
++
pairIter
) {
204
if
((*
fusIter
)->
leaf
()->
contains
((*
pairIter
)->
secondLeaf
()->
id
())
205
|| (*
fusIter
)->
leaf
()->
contains
((*
pairIter
)->
firstLeaf
()->
id
())) {
206
bag
>> *
pairIter
;
207
continue
;
208
}
209
210
if
((*
fusIter
)->
removePair
(*
pairIter
)) {
_removeContext_
(
fusIter
.
pos
() + 1); }
211
}
212
213
bag
<< (*
fusIter
)->
leafAssociatedPair
(
l
);
214
toBeDeleted
<< (*
fusIter
)->
leafAssociatedPair
(
l
);
215
216
if
((*
fusIter
)->
deassociateLeaf
(
l
)) {
_removeContext_
(
fusIter
.
pos
() + 1); }
217
}
218
219
for
(
SetIteratorSafe
<
LeafPair
* >
pairIter
=
toBeDeleted
.
beginSafe
();
220
pairIter
!=
toBeDeleted
.
endSafe
();
221
++
pairIter
)
222
delete
*
pairIter
;
223
224
for
(
SetIteratorSafe
<
LeafPair
* >
pairIter
=
_leaf2Pair_
[
l
]->
beginSafe
();
225
pairIter
!=
_leaf2Pair_
[
l
]->
endSafe
();
226
++
pairIter
)
227
delete
*
pairIter
;
228
delete
_leaf2Pair_
[
l
];
229
_leaf2Pair_
.
erase
(
l
);
230
231
_needsUpdate_
=
true
;
232
}
233
234
235
// ============================================================================
236
//
237
// ============================================================================
238
void
LeafAggregator
::
update
() {
239
LeafPair
*
nextPair
=
_initialContext_
->
top
();
240
pair_iterator
pb
=
_initialContext_
->
beginPairs
();
241
pair_iterator
pe
=
_initialContext_
->
endPairs
();
242
if
(!
_fusionSeq_
.
empty
()) {
243
nextPair
=
_fusionSeq_
.
back
()->
top
();
244
pb
=
_fusionSeq_
.
back
()->
beginPairs
();
245
pe
=
_fusionSeq_
.
back
()->
endPairs
();
246
}
247
248
249
while
(
nextPair
&&
nextPair
->
likelyhood
() <
_similarityThreshold_
) {
250
AbstractLeaf
*
newLeaf
=
nextPair
->
convert2Leaf
(
_leavesCpt_
->
addNode
());
251
FusionContext
<
false
>*
newContext
=
new
FusionContext
<
false
>(
newLeaf
);
252
253
for
(
pair_iterator
pairIter
=
pb
;
pairIter
!=
pe
; ++
pairIter
) {
254
if
(!
newLeaf
->
contains
(
pairIter
.
key
()->
firstLeaf
()->
id
())
255
&& !
newLeaf
->
contains
(
pairIter
.
key
()->
secondLeaf
()->
id
()))
256
newContext
->
addPair
(
pairIter
.
key
());
257
if
(!
newLeaf
->
contains
(
pairIter
.
key
()->
firstLeaf
()->
id
())
258
&& !
newContext
->
containsAssociatedLeaf
(
pairIter
.
key
()->
firstLeaf
()))
259
newContext
->
associateLeaf
(
pairIter
.
key
()->
firstLeaf
());
260
if
(!
newLeaf
->
contains
(
pairIter
.
key
()->
secondLeaf
()->
id
())
261
&& !
newContext
->
containsAssociatedLeaf
(
pairIter
.
key
()->
secondLeaf
()))
262
newContext
->
associateLeaf
(
pairIter
.
key
()->
secondLeaf
());
263
}
264
265
_fusionSeq_
.
insert
(
newContext
);
266
nextPair
=
_fusionSeq_
.
back
()->
top
();
267
pb
=
_fusionSeq_
.
back
()->
beginPairs
();
268
pe
=
_fusionSeq_
.
back
()->
endPairs
();
269
}
270
_needsUpdate_
=
false
;
271
}
272
273
274
HashTable
<
NodeId
,
AbstractLeaf
* >
LeafAggregator
::
leavesMap
() {
275
HashTable
<
NodeId
,
AbstractLeaf
* >
retMap
;
276
for
(
SequenceIteratorSafe
<
FusionContext
<
false
>* >
fusIter
=
_fusionSeq_
.
rbeginSafe
();
277
fusIter
!=
_fusionSeq_
.
rendSafe
();
278
--
fusIter
) {
279
bool
alreadyIn
=
false
;
280
for
(
HashTableIteratorSafe
<
NodeId
,
AbstractLeaf
* >
mapIter
=
retMap
.
beginSafe
();
281
mapIter
!=
retMap
.
endSafe
();
282
++
mapIter
)
283
if
(
mapIter
.
val
()->
contains
((*
fusIter
)->
leaf
()->
id
())) {
284
alreadyIn
=
true
;
285
break
;
286
}
287
if
(!
alreadyIn
)
retMap
.
insert
((*
fusIter
)->
leaf
()->
id
(), (*
fusIter
)->
leaf
());
288
}
289
290
for
(
HashTableIteratorSafe
<
AbstractLeaf
*,
Set
<
LeafPair
* >* >
leafIter
291
=
_leaf2Pair_
.
beginSafe
();
292
leafIter
!=
_leaf2Pair_
.
endSafe
();
293
++
leafIter
) {
294
for
(
HashTableIteratorSafe
<
NodeId
,
AbstractLeaf
* >
mapIter
=
retMap
.
beginSafe
();
295
mapIter
!=
retMap
.
endSafe
();
296
++
mapIter
)
297
if
(
mapIter
.
val
()->
contains
(
leafIter
.
key
()->
id
())) {
298
retMap
.
insert
(
leafIter
.
key
()->
id
(),
mapIter
.
val
());
299
break
;
300
}
301
if
(!
retMap
.
exists
(
leafIter
.
key
()->
id
()))
retMap
.
insert
(
leafIter
.
key
()->
id
(),
leafIter
.
key
());
302
}
303
304
return
retMap
;
305
}
306
307
308
std
::
string
LeafAggregator
::
toString
() {
309
std
::
stringstream
ss
;
310
ss
<<
"################\nTas Initial : "
<<
std
::
endl
311
<<
_initialContext_
->
toString
() <<
std
::
endl
;
312
313
for
(
auto
fusIter
=
_fusionSeq_
.
beginSafe
();
fusIter
!=
_fusionSeq_
.
endSafe
(); ++
fusIter
) {
314
ss
<<
"################\nTas "
<<
fusIter
.
pos
() <<
" : "
<<
std
::
endl
315
<< (*
fusIter
)->
toString
();
316
}
317
318
return
ss
.
str
();
319
}
320
321
// ############################################################################
322
//
323
// ############################################################################
324
325
// ============================================================================
326
//
327
// ============================================================================
328
void
LeafAggregator
::
_removeContext_
(
Idx
startingPos
) {
329
for
(
Idx
i
=
_fusionSeq_
.
size
() - 1; !
_fusionSeq_
.
empty
() &&
i
>=
startingPos
; --
i
) {
330
_leavesCpt_
->
eraseNode
(
_fusionSeq_
.
atPos
(
i
)->
leaf
()->
id
());
331
delete
_fusionSeq_
.
atPos
(
i
);
332
_fusionSeq_
.
erase
(
_fusionSeq_
.
atPos
(
i
));
333
}
334
335
_needsUpdate_
=
true
;
336
}
337
338
339
// ============================================================================
340
//
341
// ============================================================================
342
void
LeafAggregator
::
_addInitialPair_
(
LeafPair
*
p
) {
343
bool
res
=
_initialContext_
->
addPair
(
p
);
344
if
(
res
)
_removeContext_
(0);
345
}
346
347
348
// ============================================================================
349
//
350
// ============================================================================
351
void
LeafAggregator
::
_updateInitialPair_
(
LeafPair
*
p
) {
352
bool
res
=
_initialContext_
->
updatePair
(
p
);
353
if
(
res
)
_removeContext_
(0);
354
}
355
356
// ============================================================================
357
//
358
// ============================================================================
359
void
LeafAggregator
::
_removeInitialPair_
(
LeafPair
*
p
) {
360
bool
res
=
_initialContext_
->
removePair
(
p
);
361
if
(
res
)
_removeContext_
(0);
362
}
363
364
}
// namespace gum
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643