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