aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
inferenceEngine_tpl.h
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
/** @file
23
* @brief the class for computing G2 scores
24
*
25
* @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
26
*/
27
#
include
<
agrum
/
CN
/
inference
/
inferenceEngine
.
h
>
28
#
include
<
agrum
/
agrum
.
h
>
29
30
namespace
gum
{
31
namespace
credal
{
32
33
/*template< typename GUM_SCALAR >
34
InferenceEngine< GUM_SCALAR >::InferenceEngine () : ApproximationScheme() {
35
std::cout << "InferenceEngine construct ()" << std::endl;
36
GUM_CONSTRUCTOR ( InferenceEngine )
37
}*/
38
39
template
<
typename
GUM_SCALAR >
40
InferenceEngine< GUM_SCALAR >::InferenceEngine(
const
CredalNet< GUM_SCALAR >& credalNet) :
41
ApproximationScheme() {
42
credalNet_ = &credalNet;
43
44
dbnOpt_.setCNet(credalNet);
45
46
initMarginals_();
47
48
GUM_CONSTRUCTOR(InferenceEngine);
49
}
50
51
template
<
typename
GUM_SCALAR
>
52
InferenceEngine
<
GUM_SCALAR
>::~
InferenceEngine
() {
53
GUM_DESTRUCTOR
(
InferenceEngine
);
54
}
55
56
template
<
typename
GUM_SCALAR
>
57
const
CredalNet
<
GUM_SCALAR
>&
InferenceEngine
<
GUM_SCALAR
>::
credalNet
()
const
{
58
return
*
credalNet_
;
59
}
60
61
template
<
typename
GUM_SCALAR
>
62
void
InferenceEngine
<
GUM_SCALAR
>::
eraseAllEvidence
() {
63
evidence_
.
clear
();
64
query_
.
clear
();
65
/*
66
marginalMin_.clear();
67
marginalMax_.clear();
68
oldMarginalMin_.clear();
69
oldMarginalMax_.clear();
70
*/
71
initMarginals_
();
72
/*
73
expectationMin_.clear();
74
expectationMax_.clear();
75
*/
76
initExpectations_
();
77
78
// marginalSets_.clear();
79
initMarginalSets_
();
80
81
dynamicExpMin_
.
clear
();
82
dynamicExpMax_
.
clear
();
83
84
//_modal.clear();
85
86
//_t0.clear();
87
//_t1.clear();
88
}
89
90
/*
91
template< typename GUM_SCALAR >
92
void InferenceEngine< GUM_SCALAR >::setIterStop ( const int &iter_stop ) {
93
iterStop_ = iter_stop;
94
}*/
95
96
template
<
typename
GUM_SCALAR
>
97
void
InferenceEngine
<
GUM_SCALAR
>::
storeBNOpt
(
const
bool
value
) {
98
storeBNOpt_
=
value
;
99
}
100
101
template
<
typename
GUM_SCALAR
>
102
void
InferenceEngine
<
GUM_SCALAR
>::
storeVertices
(
const
bool
value
) {
103
storeVertices_
=
value
;
104
105
if
(
value
)
initMarginalSets_
();
106
}
107
108
template
<
typename
GUM_SCALAR
>
109
void
InferenceEngine
<
GUM_SCALAR
>::
setRepetitiveInd
(
const
bool
repetitive
) {
110
bool
oldValue
=
repetitiveInd_
;
111
repetitiveInd_
=
repetitive
;
112
113
// do not compute clusters more than once
114
if
(
repetitiveInd_
&& !
oldValue
)
repetitiveInit_
();
115
}
116
117
template
<
typename
GUM_SCALAR
>
118
bool
InferenceEngine
<
GUM_SCALAR
>::
repetitiveInd
()
const
{
119
return
repetitiveInd_
;
120
}
121
/*
122
template< typename GUM_SCALAR >
123
int InferenceEngine< GUM_SCALAR >::iterStop () const {
124
return iterStop_;
125
}*/
126
127
template
<
typename
GUM_SCALAR
>
128
bool
InferenceEngine
<
GUM_SCALAR
>::
storeVertices
()
const
{
129
return
storeVertices_
;
130
}
131
132
template
<
typename
GUM_SCALAR
>
133
bool
InferenceEngine
<
GUM_SCALAR
>::
storeBNOpt
()
const
{
134
return
storeBNOpt_
;
135
}
136
137
template
<
typename
GUM_SCALAR
>
138
VarMod2BNsMap
<
GUM_SCALAR
>*
InferenceEngine
<
GUM_SCALAR
>::
getVarMod2BNsMap
() {
139
return
&
dbnOpt_
;
140
}
141
142
template
<
typename
GUM_SCALAR
>
143
void
InferenceEngine
<
GUM_SCALAR
>::
insertModalsFile
(
const
std
::
string
&
path
) {
144
std
::
ifstream
mod_stream
(
path
.
c_str
(),
std
::
ios
::
in
);
145
146
if
(!
mod_stream
.
good
()) {
147
GUM_ERROR
(
OperationNotAllowed
,
148
"void InferenceEngine< GUM_SCALAR "
149
">::insertModals(const std::string & path) : "
150
"could not open input file : "
151
<<
path
);
152
}
153
154
if
(!
modal_
.
empty
())
modal_
.
clear
();
155
156
std
::
string
line
,
tmp
;
157
char
*
cstr
, *
p
;
158
159
while
(
mod_stream
.
good
()) {
160
getline
(
mod_stream
,
line
);
161
162
if
(
line
.
size
() == 0)
continue
;
163
164
cstr
=
new
char
[
line
.
size
() + 1];
165
strcpy
(
cstr
,
line
.
c_str
());
166
167
p
=
strtok
(
cstr
,
" "
);
168
tmp
=
p
;
169
170
std
::
vector
<
GUM_SCALAR
>
values
;
171
p
=
strtok
(
nullptr
,
" "
);
172
173
while
(
p
!=
nullptr
) {
174
values
.
push_back
(
GUM_SCALAR
(
atof
(
p
)));
175
p
=
strtok
(
nullptr
,
" "
);
176
}
// end of : line
177
178
modal_
.
insert
(
tmp
,
values
);
//[tmp] = values;
179
180
delete
[]
p
;
181
delete
[]
cstr
;
182
}
// end of : file
183
184
mod_stream
.
close
();
185
186
initExpectations_
();
187
}
188
189
template
<
typename
GUM_SCALAR
>
190
void
InferenceEngine
<
GUM_SCALAR
>::
insertModals
(
191
const
std
::
map
<
std
::
string
,
std
::
vector
<
GUM_SCALAR
> >&
modals
) {
192
if
(!
modal_
.
empty
())
modal_
.
clear
();
193
194
for
(
auto
it
=
modals
.
cbegin
(),
theEnd
=
modals
.
cend
();
it
!=
theEnd
; ++
it
) {
195
NodeId
id
;
196
197
try
{
198
id
=
credalNet_
->
current_bn
().
idFromName
(
it
->
first
);
199
}
catch
(
NotFound
&
err
) {
200
GUM_SHOWERROR
(
err
);
201
continue
;
202
}
203
204
// check that modals are net compatible
205
auto
dSize
=
credalNet_
->
current_bn
().
variable
(
id
).
domainSize
();
206
207
if
(
dSize
!=
it
->
second
.
size
())
continue
;
208
209
// GUM_ERROR(OperationNotAllowed, "void InferenceEngine< GUM_SCALAR
210
// >::insertModals( const std::map< std::string, std::vector< GUM_SCALAR
211
// > >
212
// &modals) : modalities does not respect variable cardinality : " <<
213
// credalNet_->current_bn().variable( id ).name() << " : " << dSize << "
214
// != "
215
// << it->second.size());
216
217
modal_
.
insert
(
it
->
first
,
it
->
second
);
//[ it->first ] = it->second;
218
}
219
220
//_modal = modals;
221
222
initExpectations_
();
223
}
224
225
template
<
typename
GUM_SCALAR
>
226
void
InferenceEngine
<
GUM_SCALAR
>::
insertEvidence
(
227
const
std
::
map
<
std
::
string
,
std
::
vector
<
GUM_SCALAR
> >&
eviMap
) {
228
if
(!
evidence_
.
empty
())
evidence_
.
clear
();
229
230
for
(
auto
it
=
eviMap
.
cbegin
(),
theEnd
=
eviMap
.
cend
();
it
!=
theEnd
; ++
it
) {
231
NodeId
id
;
232
233
try
{
234
id
=
credalNet_
->
current_bn
().
idFromName
(
it
->
first
);
235
}
catch
(
NotFound
&
err
) {
236
GUM_SHOWERROR
(
err
);
237
continue
;
238
}
239
240
evidence_
.
insert
(
id
,
it
->
second
);
241
}
242
}
243
244
// check that observed variables DO exists in the network (otherwise Lazy
245
// report
246
// an error and app crash)
247
template
<
typename
GUM_SCALAR
>
248
void
InferenceEngine
<
GUM_SCALAR
>::
insertEvidence
(
249
const
NodeProperty
<
std
::
vector
<
GUM_SCALAR
> >&
evidence
) {
250
if
(!
evidence_
.
empty
())
evidence_
.
clear
();
251
252
// use cbegin() to get const_iterator when available in aGrUM hashtables
253
for
(
const
auto
&
elt
:
evidence
) {
254
try
{
255
credalNet_
->
current_bn
().
variable
(
elt
.
first
);
256
}
catch
(
NotFound
&
err
) {
257
GUM_SHOWERROR
(
err
);
258
continue
;
259
}
260
261
evidence_
.
insert
(
elt
.
first
,
elt
.
second
);
262
}
263
}
264
265
template
<
typename
GUM_SCALAR
>
266
void
InferenceEngine
<
GUM_SCALAR
>::
insertEvidenceFile
(
const
std
::
string
&
path
) {
267
std
::
ifstream
evi_stream
(
path
.
c_str
(),
std
::
ios
::
in
);
268
269
if
(!
evi_stream
.
good
()) {
270
GUM_ERROR
(
IOError
,
271
"void InferenceEngine< GUM_SCALAR "
272
">::insertEvidence(const std::string & path) : could not "
273
"open input file : "
274
<<
path
);
275
}
276
277
if
(!
evidence_
.
empty
())
evidence_
.
clear
();
278
279
std
::
string
line
,
tmp
;
280
char
*
cstr
, *
p
;
281
282
while
(
evi_stream
.
good
() &&
std
::
strcmp
(
line
.
c_str
(),
"[EVIDENCE]"
) != 0) {
283
getline
(
evi_stream
,
line
);
284
}
285
286
while
(
evi_stream
.
good
()) {
287
getline
(
evi_stream
,
line
);
288
289
if
(
std
::
strcmp
(
line
.
c_str
(),
"[QUERY]"
) == 0)
break
;
290
291
if
(
line
.
size
() == 0)
continue
;
292
293
cstr
=
new
char
[
line
.
size
() + 1];
294
strcpy
(
cstr
,
line
.
c_str
());
295
296
p
=
strtok
(
cstr
,
" "
);
297
tmp
=
p
;
298
299
// if user input is wrong
300
NodeId
node
= -1;
301
302
try
{
303
node
=
credalNet_
->
current_bn
().
idFromName
(
tmp
);
304
}
catch
(
NotFound
&
err
) {
305
GUM_SHOWERROR
(
err
);
306
continue
;
307
}
308
309
std
::
vector
<
GUM_SCALAR
>
values
;
310
p
=
strtok
(
nullptr
,
" "
);
311
312
while
(
p
!=
nullptr
) {
313
values
.
push_back
(
GUM_SCALAR
(
atof
(
p
)));
314
p
=
strtok
(
nullptr
,
" "
);
315
}
// end of : line
316
317
evidence_
.
insert
(
node
,
values
);
318
319
delete
[]
p
;
320
delete
[]
cstr
;
321
}
// end of : file
322
323
evi_stream
.
close
();
324
}
325
326
template
<
typename
GUM_SCALAR
>
327
void
InferenceEngine
<
GUM_SCALAR
>::
insertQuery
(
328
const
NodeProperty
<
std
::
vector
<
bool
> >&
query
) {
329
if
(!
query_
.
empty
())
query_
.
clear
();
330
331
for
(
const
auto
&
elt
:
query
) {
332
try
{
333
credalNet_
->
current_bn
().
variable
(
elt
.
first
);
334
}
catch
(
NotFound
&
err
) {
335
GUM_SHOWERROR
(
err
);
336
continue
;
337
}
338
339
query_
.
insert
(
elt
.
first
,
elt
.
second
);
340
}
341
}
342
343
template
<
typename
GUM_SCALAR
>
344
void
InferenceEngine
<
GUM_SCALAR
>::
insertQueryFile
(
const
std
::
string
&
path
) {
345
std
::
ifstream
evi_stream
(
path
.
c_str
(),
std
::
ios
::
in
);
346
347
if
(!
evi_stream
.
good
()) {
348
GUM_ERROR
(
IOError
,
349
"void InferenceEngine< GUM_SCALAR >::insertQuery(const "
350
"std::string & path) : could not open input file : "
351
<<
path
);
352
}
353
354
if
(!
query_
.
empty
())
query_
.
clear
();
355
356
std
::
string
line
,
tmp
;
357
char
*
cstr
, *
p
;
358
359
while
(
evi_stream
.
good
() &&
std
::
strcmp
(
line
.
c_str
(),
"[QUERY]"
) != 0) {
360
getline
(
evi_stream
,
line
);
361
}
362
363
while
(
evi_stream
.
good
()) {
364
getline
(
evi_stream
,
line
);
365
366
if
(
std
::
strcmp
(
line
.
c_str
(),
"[EVIDENCE]"
) == 0)
break
;
367
368
if
(
line
.
size
() == 0)
continue
;
369
370
cstr
=
new
char
[
line
.
size
() + 1];
371
strcpy
(
cstr
,
line
.
c_str
());
372
373
p
=
strtok
(
cstr
,
" "
);
374
tmp
=
p
;
375
376
// if user input is wrong
377
NodeId
node
= -1;
378
379
try
{
380
node
=
credalNet_
->
current_bn
().
idFromName
(
tmp
);
381
}
catch
(
NotFound
&
err
) {
382
GUM_SHOWERROR
(
err
);
383
continue
;
384
}
385
386
auto
dSize
=
credalNet_
->
current_bn
().
variable
(
node
).
domainSize
();
387
388
p
=
strtok
(
nullptr
,
" "
);
389
390
if
(
p
==
nullptr
) {
391
query_
.
insert
(
node
,
std
::
vector
<
bool
>(
dSize
,
true
));
392
}
else
{
393
std
::
vector
<
bool
>
values
(
dSize
,
false
);
394
395
while
(
p
!=
nullptr
) {
396
if
((
Size
)
atoi
(
p
) >=
dSize
)
397
GUM_ERROR
(
OutOfBounds
,
398
"void InferenceEngine< GUM_SCALAR "
399
">::insertQuery(const std::string & path) : "
400
"query modality is higher or equal to "
401
"cardinality"
);
402
403
values
[
atoi
(
p
)] =
true
;
404
p
=
strtok
(
nullptr
,
" "
);
405
}
// end of : line
406
407
query_
.
insert
(
node
,
values
);
408
}
409
410
delete
[]
p
;
411
delete
[]
cstr
;
412
}
// end of : file
413
414
evi_stream
.
close
();
415
}
416
417
template
<
typename
GUM_SCALAR
>
418
INLINE
Potential
<
GUM_SCALAR
>
419
InferenceEngine
<
GUM_SCALAR
>::
marginalMin
(
const
std
::
string
&
varName
)
const
{
420
return
marginalMin
(
credalNet_
->
current_bn
().
idFromName
(
varName
));
421
}
422
423
template
<
typename
GUM_SCALAR
>
424
INLINE
Potential
<
GUM_SCALAR
>
425
InferenceEngine
<
GUM_SCALAR
>::
marginalMax
(
const
std
::
string
&
varName
)
const
{
426
return
marginalMax
(
credalNet_
->
current_bn
().
idFromName
(
varName
));
427
}
428
429
template
<
typename
GUM_SCALAR
>
430
gum
::
Potential
<
GUM_SCALAR
>
InferenceEngine
<
GUM_SCALAR
>::
marginalMin
(
const
NodeId
id
)
const
{
431
try
{
432
Potential
<
GUM_SCALAR
>
res
;
433
res
.
add
(
credalNet_
->
current_bn
().
variable
(
id
));
434
res
.
fillWith
(
marginalMin_
[
id
]);
435
return
res
;
436
}
catch
(
NotFound
&
err
) {
throw
(
err
); }
437
}
438
439
template
<
typename
GUM_SCALAR
>
440
gum
::
Potential
<
GUM_SCALAR
>
InferenceEngine
<
GUM_SCALAR
>::
marginalMax
(
const
NodeId
id
)
const
{
441
try
{
442
Potential
<
GUM_SCALAR
>
res
;
443
res
.
add
(
credalNet_
->
current_bn
().
variable
(
id
));
444
res
.
fillWith
(
marginalMax_
[
id
]);
445
return
res
;
446
}
catch
(
NotFound
&
err
) {
throw
(
err
); }
447
}
448
449
template
<
typename
GUM_SCALAR
>
450
const
GUM_SCALAR
&
451
InferenceEngine
<
GUM_SCALAR
>::
expectationMin
(
const
std
::
string
&
varName
)
const
{
452
try
{
453
return
expectationMin_
[
credalNet_
->
current_bn
().
idFromName
(
varName
)];
454
}
catch
(
NotFound
&
err
) {
throw
(
err
); }
455
}
456
457
template
<
typename
GUM_SCALAR
>
458
const
GUM_SCALAR
&
459
InferenceEngine
<
GUM_SCALAR
>::
expectationMax
(
const
std
::
string
&
varName
)
const
{
460
try
{
461
return
expectationMax_
[
credalNet_
->
current_bn
().
idFromName
(
varName
)];
462
}
catch
(
NotFound
&
err
) {
throw
(
err
); }
463
}
464
465
template
<
typename
GUM_SCALAR
>
466
const
GUM_SCALAR
&
InferenceEngine
<
GUM_SCALAR
>::
expectationMin
(
const
NodeId
id
)
const
{
467
try
{
468
return
expectationMin_
[
id
];
469
}
catch
(
NotFound
&
err
) {
throw
(
err
); }
470
}
471
472
template
<
typename
GUM_SCALAR
>
473
const
GUM_SCALAR
&
InferenceEngine
<
GUM_SCALAR
>::
expectationMax
(
const
NodeId
id
)
const
{
474
try
{
475
return
expectationMax_
[
id
];
476
}
catch
(
NotFound
&
err
) {
throw
(
err
); }
477
}
478
479
template
<
typename
GUM_SCALAR
>
480
const
std
::
vector
<
GUM_SCALAR
>&
481
InferenceEngine
<
GUM_SCALAR
>::
dynamicExpMin
(
const
std
::
string
&
varName
)
const
{
482
std
::
string
errTxt
=
"const std::vector< GUM_SCALAR > & InferenceEngine< "
483
"GUM_SCALAR >::dynamicExpMin ( const std::string & "
484
"varName ) const : "
;
485
486
if
(
dynamicExpMin_
.
empty
())
487
GUM_ERROR
(
OperationNotAllowed
,
errTxt
+
"_dynamicExpectations() needs to be called before"
)
488
489
if
(!
dynamicExpMin_
.
exists
(
varName
)
/*dynamicExpMin_.find(varName) == dynamicExpMin_.end()*/
)
490
GUM_ERROR
(
NotFound
,
errTxt
+
"variable name not found : "
<<
varName
)
491
492
return
dynamicExpMin_
[
varName
];
493
}
494
495
template
<
typename
GUM_SCALAR
>
496
const
std
::
vector
<
GUM_SCALAR
>&
497
InferenceEngine
<
GUM_SCALAR
>::
dynamicExpMax
(
const
std
::
string
&
varName
)
const
{
498
std
::
string
errTxt
=
"const std::vector< GUM_SCALAR > & InferenceEngine< "
499
"GUM_SCALAR >::dynamicExpMax ( const std::string & "
500
"varName ) const : "
;
501
502
if
(
dynamicExpMax_
.
empty
())
503
GUM_ERROR
(
OperationNotAllowed
,
errTxt
+
"_dynamicExpectations() needs to be called before"
)
504
505
if
(!
dynamicExpMax_
.
exists
(
varName
)
/*dynamicExpMin_.find(varName) == dynamicExpMin_.end()*/
)
506
GUM_ERROR
(
NotFound
,
errTxt
+
"variable name not found : "
<<
varName
)
507
508
return
dynamicExpMax_
[
varName
];
509
}
510
511
template
<
typename
GUM_SCALAR
>
512
const
std
::
vector
<
std
::
vector
<
GUM_SCALAR
> >&
513
InferenceEngine
<
GUM_SCALAR
>::
vertices
(
const
NodeId
id
)
const
{
514
return
marginalSets_
[
id
];
515
}
516
517
template
<
typename
GUM_SCALAR
>
518
void
InferenceEngine
<
GUM_SCALAR
>::
saveMarginals
(
const
std
::
string
&
path
)
const
{
519
std
::
ofstream
m_stream
(
path
.
c_str
(),
std
::
ios
::
out
|
std
::
ios
::
trunc
);
520
521
if
(!
m_stream
.
good
()) {
522
GUM_ERROR
(
IOError
,
523
"void InferenceEngine< GUM_SCALAR >::saveMarginals(const "
524
"std::string & path) const : could not open output file "
525
": "
526
<<
path
);
527
}
528
529
for
(
const
auto
&
elt
:
marginalMin_
) {
530
Size
esize
=
Size
(
elt
.
second
.
size
());
531
532
for
(
Size
mod
= 0;
mod
<
esize
;
mod
++) {
533
m_stream
<<
credalNet_
->
current_bn
().
variable
(
elt
.
first
).
name
() <<
" "
<<
mod
<<
" "
534
<< (
elt
.
second
)[
mod
] <<
" "
<<
marginalMax_
[
elt
.
first
][
mod
] <<
std
::
endl
;
535
}
536
}
537
538
m_stream
.
close
();
539
}
540
541
template
<
typename
GUM_SCALAR
>
542
void
InferenceEngine
<
GUM_SCALAR
>::
saveExpectations
(
const
std
::
string
&
path
)
const
{
543
if
(
dynamicExpMin_
.
empty
())
//_modal.empty())
544
return
;
545
546
// else not here, to keep the const (natural with a saving process)
547
// else if(dynamicExpMin_.empty() || dynamicExpMax_.empty())
548
//_dynamicExpectations(); // works with or without a dynamic network
549
550
std
::
ofstream
m_stream
(
path
.
c_str
(),
std
::
ios
::
out
|
std
::
ios
::
trunc
);
551
552
if
(!
m_stream
.
good
()) {
553
GUM_ERROR
(
IOError
,
554
"void InferenceEngine< GUM_SCALAR "
555
">::saveExpectations(const std::string & path) : could "
556
"not open output file : "
557
<<
path
);
558
}
559
560
for
(
const
auto
&
elt
:
dynamicExpMin_
) {
561
m_stream
<<
elt
.
first
;
// it->first;
562
563
// iterates over a vector
564
for
(
const
auto
&
elt2
:
elt
.
second
) {
565
m_stream
<<
" "
<<
elt2
;
566
}
567
568
m_stream
<<
std
::
endl
;
569
}
570
571
for
(
const
auto
&
elt
:
dynamicExpMax_
) {
572
m_stream
<<
elt
.
first
;
573
574
// iterates over a vector
575
for
(
const
auto
&
elt2
:
elt
.
second
) {
576
m_stream
<<
" "
<<
elt2
;
577
}
578
579
m_stream
<<
std
::
endl
;
580
}
581
582
m_stream
.
close
();
583
}
584
585
template
<
typename
GUM_SCALAR
>
586
std
::
string
InferenceEngine
<
GUM_SCALAR
>::
toString
()
const
{
587
std
::
stringstream
output
;
588
output
<<
std
::
endl
;
589
590
// use cbegin() when available
591
for
(
const
auto
&
elt
:
marginalMin_
) {
592
Size
esize
=
Size
(
elt
.
second
.
size
());
593
594
for
(
Size
mod
= 0;
mod
<
esize
;
mod
++) {
595
output
<<
"P("
<<
credalNet_
->
current_bn
().
variable
(
elt
.
first
).
name
() <<
"="
<<
mod
596
<<
"|e) = [ "
;
597
output
<<
marginalMin_
[
elt
.
first
][
mod
] <<
", "
<<
marginalMax_
[
elt
.
first
][
mod
] <<
" ]"
;
598
599
if
(!
query_
.
empty
())
600
if
(
query_
.
exists
(
elt
.
first
) &&
query_
[
elt
.
first
][
mod
])
output
<<
" QUERY"
;
601
602
output
<<
std
::
endl
;
603
}
604
605
output
<<
std
::
endl
;
606
}
607
608
return
output
.
str
();
609
}
610
611
template
<
typename
GUM_SCALAR
>
612
void
InferenceEngine
<
GUM_SCALAR
>::
saveVertices
(
const
std
::
string
&
path
)
const
{
613
std
::
ofstream
m_stream
(
path
.
c_str
(),
std
::
ios
::
out
|
std
::
ios
::
trunc
);
614
615
if
(!
m_stream
.
good
()) {
616
GUM_ERROR
(
IOError
,
617
"void InferenceEngine< GUM_SCALAR >::saveVertices(const "
618
"std::string & path) : could not open outpul file : "
619
<<
path
);
620
}
621
622
for
(
const
auto
&
elt
:
marginalSets_
) {
623
m_stream
<<
credalNet_
->
current_bn
().
variable
(
elt
.
first
).
name
() <<
std
::
endl
;
624
625
for
(
const
auto
&
elt2
:
elt
.
second
) {
626
m_stream
<<
"["
;
627
bool
first
=
true
;
628
629
for
(
const
auto
&
elt3
:
elt2
) {
630
if
(!
first
) {
631
m_stream
<<
","
;
632
first
=
false
;
633
}
634
635
m_stream
<<
elt3
;
636
}
637
638
m_stream
<<
"]\n"
;
639
}
640
}
641
642
m_stream
.
close
();
643
}
644
645
template
<
typename
GUM_SCALAR
>
646
void
InferenceEngine
<
GUM_SCALAR
>::
initMarginals_
() {
647
marginalMin_
.
clear
();
648
marginalMax_
.
clear
();
649
oldMarginalMin_
.
clear
();
650
oldMarginalMax_
.
clear
();
651
652
for
(
auto
node
:
credalNet_
->
current_bn
().
nodes
()) {
653
auto
dSize
=
credalNet_
->
current_bn
().
variable
(
node
).
domainSize
();
654
marginalMin_
.
insert
(
node
,
std
::
vector
<
GUM_SCALAR
>(
dSize
, 1));
655
oldMarginalMin_
.
insert
(
node
,
std
::
vector
<
GUM_SCALAR
>(
dSize
, 1));
656
657
marginalMax_
.
insert
(
node
,
std
::
vector
<
GUM_SCALAR
>(
dSize
, 0));
658
oldMarginalMax_
.
insert
(
node
,
std
::
vector
<
GUM_SCALAR
>(
dSize
, 0));
659
}
660
}
661
662
template
<
typename
GUM_SCALAR
>
663
void
InferenceEngine
<
GUM_SCALAR
>::
initMarginalSets_
() {
664
marginalSets_
.
clear
();
665
666
if
(!
storeVertices_
)
return
;
667
668
for
(
auto
node
:
credalNet_
->
current_bn
().
nodes
())
669
marginalSets_
.
insert
(
node
,
std
::
vector
<
std
::
vector
<
GUM_SCALAR
> >());
670
}
671
672
// since only monitored variables in modal_ will be alble to compute
673
// expectations, it is useless to initialize those for all variables
674
// modal_ variables will always be checked further, so it is not necessary
675
// to
676
// check it here, but doing so will use less memory
677
template
<
typename
GUM_SCALAR
>
678
void
InferenceEngine
<
GUM_SCALAR
>::
initExpectations_
() {
679
expectationMin_
.
clear
();
680
expectationMax_
.
clear
();
681
682
if
(
modal_
.
empty
())
return
;
683
684
for
(
auto
node
:
credalNet_
->
current_bn
().
nodes
()) {
685
std
::
string
var_name
,
time_step
;
686
687
var_name
=
credalNet_
->
current_bn
().
variable
(
node
).
name
();
688
auto
delim
=
var_name
.
find_first_of
(
"_"
);
689
var_name
=
var_name
.
substr
(0,
delim
);
690
691
if
(!
modal_
.
exists
(
var_name
))
continue
;
692
693
expectationMin_
.
insert
(
node
,
modal_
[
var_name
].
back
());
694
expectationMax_
.
insert
(
node
,
modal_
[
var_name
].
front
());
695
}
696
}
697
698
template
<
typename
GUM_SCALAR
>
699
void
InferenceEngine
<
GUM_SCALAR
>::
dynamicExpectations
() {
700
dynamicExpectations_
();
701
}
702
703
template
<
typename
GUM_SCALAR
>
704
void
InferenceEngine
<
GUM_SCALAR
>::
dynamicExpectations_
() {
705
// no modals, no expectations computed during inference
706
if
(
expectationMin_
.
empty
() ||
modal_
.
empty
())
return
;
707
708
// already called by the algorithm or the user
709
if
(
dynamicExpMax_
.
size
() > 0 &&
dynamicExpMin_
.
size
() > 0)
return
;
710
711
// typedef typename std::map< int, GUM_SCALAR > innerMap;
712
using
innerMap
=
typename
gum
::
HashTable
<
int
,
GUM_SCALAR
>;
713
714
// typedef typename std::map< std::string, innerMap > outerMap;
715
using
outerMap
=
typename
gum
::
HashTable
<
std
::
string
,
innerMap
>;
716
717
// typedef typename std::map< std::string, std::vector< GUM_SCALAR > >
718
// mod;
719
720
// si non dynamique, sauver directement expectationMin_ et Max (revient au
721
// meme
722
// mais plus rapide)
723
outerMap
expectationsMin
,
expectationsMax
;
724
725
for
(
const
auto
&
elt
:
expectationMin_
) {
726
std
::
string
var_name
,
time_step
;
727
728
var_name
=
credalNet_
->
current_bn
().
variable
(
elt
.
first
).
name
();
729
auto
delim
=
var_name
.
find_first_of
(
"_"
);
730
time_step
=
var_name
.
substr
(
delim
+ 1,
var_name
.
size
());
731
var_name
=
var_name
.
substr
(0,
delim
);
732
733
// to be sure (don't store not monitored variables' expectations)
734
// although it
735
// should be taken care of before this point
736
if
(!
modal_
.
exists
(
var_name
))
continue
;
737
738
expectationsMin
.
getWithDefault
(
var_name
,
innerMap
())
739
.
getWithDefault
(
atoi
(
time_step
.
c_str
()), 0)
740
=
elt
.
second
;
// we iterate with min iterators
741
expectationsMax
.
getWithDefault
(
var_name
,
innerMap
())
742
.
getWithDefault
(
atoi
(
time_step
.
c_str
()), 0)
743
=
expectationMax_
[
elt
.
first
];
744
}
745
746
for
(
const
auto
&
elt
:
expectationsMin
) {
747
typename
std
::
vector
<
GUM_SCALAR
>
dynExp
(
elt
.
second
.
size
());
748
749
for
(
const
auto
&
elt2
:
elt
.
second
)
750
dynExp
[
elt2
.
first
] =
elt2
.
second
;
751
752
dynamicExpMin_
.
insert
(
elt
.
first
,
dynExp
);
753
}
754
755
for
(
const
auto
&
elt
:
expectationsMax
) {
756
typename
std
::
vector
<
GUM_SCALAR
>
dynExp
(
elt
.
second
.
size
());
757
758
for
(
const
auto
&
elt2
:
elt
.
second
) {
759
dynExp
[
elt2
.
first
] =
elt2
.
second
;
760
}
761
762
dynamicExpMax_
.
insert
(
elt
.
first
,
dynExp
);
763
}
764
}
765
766
template
<
typename
GUM_SCALAR
>
767
void
InferenceEngine
<
GUM_SCALAR
>::
repetitiveInit_
() {
768
timeSteps_
= 0;
769
t0_
.
clear
();
770
t1_
.
clear
();
771
772
// t = 0 vars belongs to t0_ as keys
773
for
(
auto
node
:
credalNet_
->
current_bn
().
dag
().
nodes
()) {
774
std
::
string
var_name
=
credalNet_
->
current_bn
().
variable
(
node
).
name
();
775
auto
delim
=
var_name
.
find_first_of
(
"_"
);
776
777
if
(
delim
>
var_name
.
size
()) {
778
GUM_ERROR
(
InvalidArgument
,
779
"void InferenceEngine< GUM_SCALAR "
780
">::repetitiveInit_() : the network does not "
781
"appear to be dynamic"
);
782
}
783
784
std
::
string
time_step
=
var_name
.
substr
(
delim
+ 1, 1);
785
786
if
(
time_step
.
compare
(
"0"
) == 0)
t0_
.
insert
(
node
,
std
::
vector
<
NodeId
>());
787
}
788
789
// t = 1 vars belongs to either t0_ as member value or t1_ as keys
790
for
(
const
auto
&
node
:
credalNet_
->
current_bn
().
dag
().
nodes
()) {
791
std
::
string
var_name
=
credalNet_
->
current_bn
().
variable
(
node
).
name
();
792
auto
delim
=
var_name
.
find_first_of
(
"_"
);
793
std
::
string
time_step
=
var_name
.
substr
(
delim
+ 1,
var_name
.
size
());
794
var_name
=
var_name
.
substr
(0,
delim
);
795
delim
=
time_step
.
find_first_of
(
"_"
);
796
time_step
=
time_step
.
substr
(0,
delim
);
797
798
if
(
time_step
.
compare
(
"1"
) == 0) {
799
bool
found
=
false
;
800
801
for
(
const
auto
&
elt
:
t0_
) {
802
std
::
string
var_0_name
=
credalNet_
->
current_bn
().
variable
(
elt
.
first
).
name
();
803
delim
=
var_0_name
.
find_first_of
(
"_"
);
804
var_0_name
=
var_0_name
.
substr
(0,
delim
);
805
806
if
(
var_name
.
compare
(
var_0_name
) == 0) {
807
const
Potential
<
GUM_SCALAR
>*
potential
(&
credalNet_
->
current_bn
().
cpt
(
node
));
808
const
Potential
<
GUM_SCALAR
>*
potential2
(&
credalNet_
->
current_bn
().
cpt
(
elt
.
first
));
809
810
if
(
potential
->
domainSize
() ==
potential2
->
domainSize
())
811
t0_
[
elt
.
first
].
push_back
(
node
);
812
else
813
t1_
.
insert
(
node
,
std
::
vector
<
NodeId
>());
814
815
found
=
true
;
816
break
;
817
}
818
}
819
820
if
(!
found
) {
t1_
.
insert
(
node
,
std
::
vector
<
NodeId
>()); }
821
}
822
}
823
824
// t > 1 vars belongs to either t0_ or t1_ as member value
825
// remember timeSteps_
826
for
(
auto
node
:
credalNet_
->
current_bn
().
dag
().
nodes
()) {
827
std
::
string
var_name
=
credalNet_
->
current_bn
().
variable
(
node
).
name
();
828
auto
delim
=
var_name
.
find_first_of
(
"_"
);
829
std
::
string
time_step
=
var_name
.
substr
(
delim
+ 1,
var_name
.
size
());
830
var_name
=
var_name
.
substr
(0,
delim
);
831
delim
=
time_step
.
find_first_of
(
"_"
);
832
time_step
=
time_step
.
substr
(0,
delim
);
833
834
if
(
time_step
.
compare
(
"0"
) != 0 &&
time_step
.
compare
(
"1"
) != 0) {
835
// keep max time_step
836
if
(
atoi
(
time_step
.
c_str
()) >
timeSteps_
)
timeSteps_
=
atoi
(
time_step
.
c_str
());
837
838
std
::
string
var_0_name
;
839
bool
found
=
false
;
840
841
for
(
const
auto
&
elt
:
t0_
) {
842
std
::
string
var_0_name
=
credalNet_
->
current_bn
().
variable
(
elt
.
first
).
name
();
843
delim
=
var_0_name
.
find_first_of
(
"_"
);
844
var_0_name
=
var_0_name
.
substr
(0,
delim
);
845
846
if
(
var_name
.
compare
(
var_0_name
) == 0) {
847
const
Potential
<
GUM_SCALAR
>*
potential
(&
credalNet_
->
current_bn
().
cpt
(
node
));
848
const
Potential
<
GUM_SCALAR
>*
potential2
(&
credalNet_
->
current_bn
().
cpt
(
elt
.
first
));
849
850
if
(
potential
->
domainSize
() ==
potential2
->
domainSize
()) {
851
t0_
[
elt
.
first
].
push_back
(
node
);
852
found
=
true
;
853
break
;
854
}
855
}
856
}
857
858
if
(!
found
) {
859
for
(
const
auto
&
elt
:
t1_
) {
860
std
::
string
var_0_name
=
credalNet_
->
current_bn
().
variable
(
elt
.
first
).
name
();
861
auto
delim
=
var_0_name
.
find_first_of
(
"_"
);
862
var_0_name
=
var_0_name
.
substr
(0,
delim
);
863
864
if
(
var_name
.
compare
(
var_0_name
) == 0) {
865
const
Potential
<
GUM_SCALAR
>*
potential
(&
credalNet_
->
current_bn
().
cpt
(
node
));
866
const
Potential
<
GUM_SCALAR
>*
potential2
(&
credalNet_
->
current_bn
().
cpt
(
elt
.
first
));
867
868
if
(
potential
->
domainSize
() ==
potential2
->
domainSize
()) {
869
t1_
[
elt
.
first
].
push_back
(
node
);
870
break
;
871
}
872
}
873
}
874
}
875
}
876
}
877
}
878
879
template
<
typename
GUM_SCALAR
>
880
void
881
InferenceEngine
<
GUM_SCALAR
>::
updateExpectations_
(
const
NodeId
&
id
,
882
const
std
::
vector
<
GUM_SCALAR
>&
vertex
) {
883
std
::
string
var_name
=
credalNet_
->
current_bn
().
variable
(
id
).
name
();
884
auto
delim
=
var_name
.
find_first_of
(
"_"
);
885
886
var_name
=
var_name
.
substr
(0,
delim
);
887
888
if
(
modal_
.
exists
(
var_name
)
/*modal_.find(var_name) != modal_.end()*/
) {
889
GUM_SCALAR
exp
= 0;
890
auto
vsize
=
vertex
.
size
();
891
892
for
(
Size
mod
= 0;
mod
<
vsize
;
mod
++)
893
exp
+=
vertex
[
mod
] *
modal_
[
var_name
][
mod
];
894
895
if
(
exp
>
expectationMax_
[
id
])
expectationMax_
[
id
] =
exp
;
896
897
if
(
exp
<
expectationMin_
[
id
])
expectationMin_
[
id
] =
exp
;
898
}
899
}
900
901
template
<
typename
GUM_SCALAR
>
902
void
InferenceEngine
<
GUM_SCALAR
>::
updateCredalSets_
(
const
NodeId
&
id
,
903
const
std
::
vector
<
GUM_SCALAR
>&
vertex
,
904
const
bool
&
elimRedund
) {
905
auto
&
nodeCredalSet
=
marginalSets_
[
id
];
906
auto
dsize
=
vertex
.
size
();
907
908
bool
eq
=
true
;
909
910
for
(
auto
it
=
nodeCredalSet
.
cbegin
(),
itEnd
=
nodeCredalSet
.
cend
();
it
!=
itEnd
; ++
it
) {
911
eq
=
true
;
912
913
for
(
Size
i
= 0;
i
<
dsize
;
i
++) {
914
if
(
std
::
fabs
(
vertex
[
i
] - (*
it
)[
i
]) > 1e-6) {
915
eq
=
false
;
916
break
;
917
}
918
}
919
920
if
(
eq
)
break
;
921
}
922
923
if
(!
eq
||
nodeCredalSet
.
size
() == 0) {
924
nodeCredalSet
.
push_back
(
vertex
);
925
return
;
926
}
else
927
return
;
928
929
// because of next lambda return condition
930
if
(
nodeCredalSet
.
size
() == 1)
return
;
931
932
// check that the point and all previously added ones are not inside the
933
// actual
934
// polytope
935
auto
itEnd
936
=
std
::
remove_if
(
nodeCredalSet
.
begin
(),
937
nodeCredalSet
.
end
(),
938
[&](
const
std
::
vector
<
GUM_SCALAR
>&
v
) ->
bool
{
939
for
(
auto
jt
=
v
.
cbegin
(),
940
jtEnd
=
v
.
cend
(),
941
minIt
=
marginalMin_
[
id
].
cbegin
(),
942
minItEnd
=
marginalMin_
[
id
].
cend
(),
943
maxIt
=
marginalMax_
[
id
].
cbegin
(),
944
maxItEnd
=
marginalMax_
[
id
].
cend
();
945
jt
!=
jtEnd
&&
minIt
!=
minItEnd
&&
maxIt
!=
maxItEnd
;
946
++
jt
, ++
minIt
, ++
maxIt
) {
947
if
((
std
::
fabs
(*
jt
- *
minIt
) < 1e-6 ||
std
::
fabs
(*
jt
- *
maxIt
) < 1e-6)
948
&&
std
::
fabs
(*
minIt
- *
maxIt
) > 1e-6)
949
return
false
;
950
}
951
return
true
;
952
});
953
954
nodeCredalSet
.
erase
(
itEnd
,
nodeCredalSet
.
end
());
955
956
// we need at least 2 points to make a convex combination
957
if
(!
elimRedund
||
nodeCredalSet
.
size
() <= 2)
return
;
958
959
// there may be points not inside the polytope but on one of it's facet,
960
// meaning it's still a convex combination of vertices of this facet. Here
961
// we
962
// need lrs.
963
LRSWrapper
<
GUM_SCALAR
>
lrsWrapper
;
964
lrsWrapper
.
setUpV
((
unsigned
int
)
dsize
, (
unsigned
int
)(
nodeCredalSet
.
size
()));
965
966
for
(
const
auto
&
vtx
:
nodeCredalSet
)
967
lrsWrapper
.
fillV
(
vtx
);
968
969
lrsWrapper
.
elimRedundVrep
();
970
971
marginalSets_
[
id
] =
lrsWrapper
.
getOutput
();
972
}
973
974
template
<
typename
GUM_SCALAR
>
975
const
NodeProperty
<
std
::
vector
<
NodeId
> >&
976
InferenceEngine
<
GUM_SCALAR
>::
getT0Cluster
()
const
{
977
return
t0_
;
978
}
979
980
template
<
typename
GUM_SCALAR
>
981
const
NodeProperty
<
std
::
vector
<
NodeId
> >&
982
InferenceEngine
<
GUM_SCALAR
>::
getT1Cluster
()
const
{
983
return
t1_
;
984
}
985
986
template
<
typename
GUM_SCALAR
>
987
inline
const
GUM_SCALAR
InferenceEngine
<
GUM_SCALAR
>::
computeEpsilon_
() {
988
GUM_SCALAR
eps
= 0;
989
#
pragma
omp
parallel
990
{
991
GUM_SCALAR
tEps
= 0;
992
GUM_SCALAR
delta
;
993
994
/// int tId = getThreadNumber();
995
int
nsize
=
int
(
marginalMin_
.
size
());
996
997
#
pragma
omp
for
998
999
for
(
int
i
= 0;
i
<
nsize
;
i
++) {
1000
auto
dSize
=
marginalMin_
[
i
].
size
();
1001
1002
for
(
Size
j
= 0;
j
<
dSize
;
j
++) {
1003
// on min
1004
delta
=
marginalMin_
[
i
][
j
] -
oldMarginalMin_
[
i
][
j
];
1005
delta
= (
delta
< 0) ? (-
delta
) :
delta
;
1006
tEps
= (
tEps
<
delta
) ?
delta
:
tEps
;
1007
1008
// on max
1009
delta
=
marginalMax_
[
i
][
j
] -
oldMarginalMax_
[
i
][
j
];
1010
delta
= (
delta
< 0) ? (-
delta
) :
delta
;
1011
tEps
= (
tEps
<
delta
) ?
delta
:
tEps
;
1012
1013
oldMarginalMin_
[
i
][
j
] =
marginalMin_
[
i
][
j
];
1014
oldMarginalMax_
[
i
][
j
] =
marginalMax_
[
i
][
j
];
1015
}
1016
}
// end of : all variables
1017
1018
#
pragma
omp
critical
(
epsilon_max
)
1019
{
1020
#
pragma
omp
flush
(
eps
)
1021
eps
= (
eps
<
tEps
) ?
tEps
:
eps
;
1022
}
1023
}
1024
1025
return
eps
;
1026
}
1027
}
// namespace credal
1028
}
// namespace gum
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643
gum::credal
namespace for all credal networks entities
Definition:
LpInterface.cpp:37