aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
regress_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
/**
23
* @file
24
* @brief Class used to compute the operation between two decision diagrams
25
*
26
* @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27
* @author Pierre-Henri WUILLEMIN(@LIP6) and Jean-Christophe MAGNAN and Christophe
28
* GONZALES(@AMU)
29
*/
30
31
#
include
<
agrum
/
tools
/
multidim
/
utils
/
FunctionGraphUtilities
/
internalNode
.
h
>
32
#
include
<
agrum
/
tools
/
multidim
/
utils
/
FunctionGraphUtilities
/
operators
/
regress
.
h
>
33
34
#
define
ALLOCATE
(
x
)
SmallObjectAllocator
::
instance
(
)
.
allocate
(
x
)
35
#
define
DEALLOCATE
(
x
,
y
)
SmallObjectAllocator
::
instance
(
)
.
deallocate
(
x
,
y
)
36
37
namespace
gum
{
38
39
template
<
typename
GUM_SCALAR,
40
template
<
typename
>
41
class
COMBINEOPERATOR,
42
template
<
typename
>
43
class
PROJECTOPERATOR,
44
template
<
typename
>
45
class
TerminalNodePolicy >
46
INLINE Regress<
GUM_SCALAR
,
COMBINEOPERATOR
,
PROJECTOPERATOR
,
TerminalNodePolicy
>::
Regress
(
47
const
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>*
DG1
,
48
const
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>*
DG2
,
49
const
Set
<
const
DiscreteVariable
* >*
primedVars
,
50
const
DiscreteVariable
*
targetVar
,
51
const
GUM_SCALAR
neutral
) :
52
_DG1_
(
DG1
),
53
_DG2_
(
DG2
),
_neutral_
(
neutral
),
_combine_
(),
_project_
(),
54
_DG1InstantiationNeeded_
(
DG1
->
realSize
(),
true
,
false
),
55
_DG2InstantiationNeeded_
(
DG2
->
realSize
(),
true
,
false
) {
56
GUM_CONSTRUCTOR
(
Regress
);
57
_rd_
=
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>::
getReducedAndOrderedInstance
();
58
_nbVar_
= 0;
59
_default_
=
nullptr
;
60
_primedVars_
=
primedVars
;
61
_targetVar_
=
targetVar
;
62
}
63
64
template
<
typename
GUM_SCALAR
,
65
template
<
typename
>
66
class
COMBINEOPERATOR
,
67
template
<
typename
>
68
class
PROJECTOPERATOR
,
69
template
<
typename
>
70
class
TerminalNodePolicy
>
71
INLINE
Regress
<
GUM_SCALAR
,
COMBINEOPERATOR
,
PROJECTOPERATOR
,
TerminalNodePolicy
>::~
Regress
() {
72
GUM_DESTRUCTOR
(
Regress
);
73
74
for
(
auto
instIter
=
_DG1InstantiationNeeded_
.
beginSafe
();
75
instIter
!=
_DG1InstantiationNeeded_
.
endSafe
();
76
++
instIter
)
77
DEALLOCATE
(
instIter
.
val
(),
sizeof
(
short
int
) *
_nbVar_
);
78
79
for
(
auto
instIter
=
_DG2InstantiationNeeded_
.
beginSafe
();
80
instIter
!=
_DG2InstantiationNeeded_
.
endSafe
();
81
++
instIter
)
82
DEALLOCATE
(
instIter
.
val
(),
sizeof
(
short
int
) *
_nbVar_
);
83
84
if
(
_nbVar_
!= 0)
DEALLOCATE
(
_default_
,
sizeof
(
short
int
) *
_nbVar_
);
85
}
86
87
88
// This function is the main function. To be call every time an operation
89
// between the two given Function Graphs is required
90
template
<
typename
GUM_SCALAR
,
91
template
<
typename
>
92
class
COMBINEOPERATOR
,
93
template
<
typename
>
94
class
PROJECTOPERATOR
,
95
template
<
typename
>
96
class
TerminalNodePolicy
>
97
INLINE
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>*
98
Regress
<
GUM_SCALAR
,
COMBINEOPERATOR
,
PROJECTOPERATOR
,
TerminalNodePolicy
>::
compute
() {
99
_establishVarOrder_
();
100
_findRetrogradeVariables_
(
_DG1_
,
_DG1InstantiationNeeded_
);
101
_findRetrogradeVariables_
(
_DG2_
,
_DG2InstantiationNeeded_
);
102
103
Idx
*
varInst
=
nullptr
;
104
if
(
_nbVar_
!= 0) {
105
varInst
=
static_cast
<
Idx
* >(
ALLOCATE
(
sizeof
(
Idx
) *
_nbVar_
));
106
for
(
Idx
i
= 0;
i
<
_nbVar_
;
i
++)
107
varInst
[
i
] = (
Idx
)0;
108
}
109
110
O4DGContext
conti
(
varInst
,
_nbVar_
);
111
conti
.
setDG1Node
(
_DG1_
->
root
());
112
conti
.
setDG2Node
(
_DG2_
->
root
());
113
114
NodeId
root
=
_compute_
(
conti
, (
Idx
)0 - 1);
115
_rd_
->
manager
()->
setRootNode
(
root
);
116
117
if
(
_nbVar_
!= 0)
DEALLOCATE
(
varInst
,
sizeof
(
Idx
) *
_nbVar_
);
118
119
_rd_
->
erase
(*
_targetVar_
);
120
121
return
_rd_
;
122
}
123
124
// This function computes an efficient order for the final decision diagrams.
125
// Its main criterion to do so is the number of
126
// re-exploration to be done
127
template
<
typename
GUM_SCALAR
,
128
template
<
typename
>
129
class
COMBINEOPERATOR
,
130
template
<
typename
>
131
class
PROJECTOPERATOR
,
132
template
<
typename
>
133
class
TerminalNodePolicy
>
134
INLINE
void
Regress
<
GUM_SCALAR
,
COMBINEOPERATOR
,
PROJECTOPERATOR
,
TerminalNodePolicy
>::
135
_establishVarOrder_
() {
136
SequenceIteratorSafe
<
const
DiscreteVariable
* >
fite
=
_DG1_
->
variablesSequence
().
beginSafe
();
137
SequenceIteratorSafe
<
const
DiscreteVariable
* >
site
=
_DG2_
->
variablesSequence
().
beginSafe
();
138
139
while
(
fite
!=
_DG1_
->
variablesSequence
().
endSafe
()
140
&&
site
!=
_DG2_
->
variablesSequence
().
endSafe
()) {
141
// Test : if var from first order is already in final order
142
// we move onto the next one
143
if
(
_rd_
->
variablesSequence
().
exists
(*
fite
)) {
144
++
fite
;
145
continue
;
146
}
147
148
// Test : if var from second order is already in final order
149
// we move onto the next one
150
if
(
_rd_
->
variablesSequence
().
exists
(*
site
)) {
151
++
site
;
152
continue
;
153
}
154
155
// Test : is current var of the first order present in the second order.
156
// if not we add it to final order
157
if
(!
_DG2_
->
variablesSequence
().
exists
(*
fite
) && !
_primedVars_
->
exists
(*
fite
)) {
158
_rd_
->
add
(**
fite
);
159
++
fite
;
160
continue
;
161
}
162
163
// Test : is current var of the second order present in the first order.
164
// if not we add it to final order
165
if
(!
_DG1_
->
variablesSequence
().
exists
(*
site
) && !
_primedVars_
->
exists
(*
site
)) {
166
_rd_
->
add
(**
site
);
167
++
site
;
168
continue
;
169
}
170
171
// Test : is current var of the second order present in the first order.
172
// if not we add it to final order
173
if
(*
fite
== *
site
) {
174
_rd_
->
add
(**
fite
);
175
++
fite
;
176
++
site
;
177
continue
;
178
}
179
180
// Test : if chosing first order var cost less in terms or re exploration,
181
// we chose it
182
_rd_
->
add
(**
fite
);
183
++
fite
;
184
}
185
186
// Whenever an iterator has finished its sequence,
187
// the other may still be in the middle of its one.
188
// Hence, this part ensures that any variables remaining
189
// will be added to the final sequence if needed.
190
if
(
fite
==
_DG1_
->
variablesSequence
().
endSafe
()) {
191
for
(;
site
!=
_DG2_
->
variablesSequence
().
endSafe
(); ++
site
)
192
if
(!
_rd_
->
variablesSequence
().
exists
(*
site
))
_rd_
->
add
(**
site
);
193
}
else
{
194
for
(;
fite
!=
_DG1_
->
variablesSequence
().
endSafe
(); ++
fite
)
195
if
(!
_rd_
->
variablesSequence
().
exists
(*
fite
))
_rd_
->
add
(**
fite
);
196
}
197
198
// Various initialization needed now that we have a bigger picture
199
_nbVar_
=
_rd_
->
variablesSequence
().
size
();
200
201
if
(
_nbVar_
!= 0) {
202
_default_
=
static_cast
<
short
int
* >(
ALLOCATE
(
sizeof
(
short
int
) *
_nbVar_
));
203
for
(
Idx
i
= 0;
i
<
_nbVar_
;
i
++)
204
_default_
[
i
] = (
short
int
)0;
205
}
206
}
207
208
// This function computes for every nodes if any retrograde variable is
209
// present below
210
template
<
typename
GUM_SCALAR
,
211
template
<
typename
>
212
class
COMBINEOPERATOR
,
213
template
<
typename
>
214
class
PROJECTOPERATOR
,
215
template
<
typename
>
216
class
TerminalNodePolicy
>
217
INLINE
void
Regress
<
GUM_SCALAR
,
COMBINEOPERATOR
,
PROJECTOPERATOR
,
TerminalNodePolicy
>::
218
_findRetrogradeVariables_
(
const
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>*
dg
,
219
HashTable
<
NodeId
,
short
int
* >&
dgInstNeed
) {
220
HashTable
<
NodeId
,
short
int
* >
nodesVarDescendant
;
221
Size
tableSize
=
Size
(
_nbVar_
*
sizeof
(
short
int
));
222
223
for
(
auto
varIter
=
dg
->
variablesSequence
().
rbeginSafe
();
224
varIter
!=
dg
->
variablesSequence
().
rendSafe
();
225
--
varIter
) {
226
Idx
varPos
=
_rd_
->
variablesSequence
().
pos
(*
varIter
);
227
228
const
Link
<
NodeId
>*
nodeIter
=
dg
->
varNodeListe
(*
varIter
)->
list
();
229
while
(
nodeIter
!=
nullptr
) {
230
short
int
*
instantiationNeeded
=
static_cast
<
short
int
* >(
ALLOCATE
(
tableSize
));
231
dgInstNeed
.
insert
(
nodeIter
->
element
(),
instantiationNeeded
);
232
short
int
*
varDescendant
=
static_cast
<
short
int
* >(
ALLOCATE
(
tableSize
));
233
nodesVarDescendant
.
insert
(
nodeIter
->
element
(),
varDescendant
);
234
for
(
Idx
j
= 0;
j
<
_nbVar_
;
j
++) {
235
instantiationNeeded
[
j
] = (
short
int
)0;
236
varDescendant
[
j
] = (
short
int
)0;
237
}
238
239
240
varDescendant
[
varPos
] = (
short
int
)1;
241
for
(
Idx
modality
= 0;
modality
<
dg
->
node
(
nodeIter
->
element
())->
nbSons
(); ++
modality
) {
242
if
(!
dg
->
isTerminalNode
(
dg
->
node
(
nodeIter
->
element
())->
son
(
modality
))) {
243
short
int
*
sonVarDescendant
244
=
nodesVarDescendant
[
dg
->
node
(
nodeIter
->
element
())->
son
(
modality
)];
245
for
(
Idx
varIdx
= 0;
varIdx
<
_nbVar_
;
varIdx
++) {
246
varDescendant
[
varIdx
] +=
sonVarDescendant
[
varIdx
];
247
if
(
varDescendant
[
varIdx
] &&
varIdx
<
varPos
)
248
instantiationNeeded
[
varIdx
] = (
short
int
)1;
249
}
250
}
251
}
252
nodeIter
=
nodeIter
->
nextLink
();
253
}
254
}
255
256
for
(
auto
varIter
=
dg
->
variablesSequence
().
beginSafe
();
257
varIter
!=
dg
->
variablesSequence
().
endSafe
();
258
++
varIter
) {
259
const
Link
<
NodeId
>*
nodeIter
=
dg
->
varNodeListe
(*
varIter
)->
list
();
260
while
(
nodeIter
!=
nullptr
) {
261
for
(
Idx
modality
= 0;
modality
<
dg
->
node
(
nodeIter
->
element
())->
nbSons
(); ++
modality
) {
262
NodeId
sonId
=
dg
->
node
(
nodeIter
->
element
())->
son
(
modality
);
263
if
(!
dg
->
isTerminalNode
(
sonId
)) {
264
for
(
Idx
varIdx
= 0;
varIdx
<
_nbVar_
; ++
varIdx
) {
265
if
(
dgInstNeed
[
nodeIter
->
element
()][
varIdx
] &&
nodesVarDescendant
[
sonId
][
varIdx
]) {
266
dgInstNeed
[
sonId
][
varIdx
] = (
short
int
)1;
267
}
268
}
269
}
270
}
271
nodeIter
=
nodeIter
->
nextLink
();
272
}
273
}
274
275
for
(
HashTableIterator
<
NodeId
,
short
int
* >
it
=
nodesVarDescendant
.
begin
();
276
it
!=
nodesVarDescendant
.
end
();
277
++
it
) {
278
DEALLOCATE
(
it
.
val
(),
tableSize
);
279
}
280
281
nodesVarDescendant
.
clear
();
282
}
283
284
// A key is used for prunning uneccesary operations since once a node has been
285
// visited in a given context, there's no use to revisit him,
286
// the result will be the same node, so we just have to do an association
287
// context - node.
288
// The context consists in :
289
// _ Leader node we are visiting.
290
// _ Follower node we are visiting.
291
// _ For all retrograde variables, if it has been instanciated
292
// before, current modality instanciated, meaning :
293
// _ 0 means the variable hasn't be instanciated yet,
294
// _ From 1 to domainSize + 1 means that current modality
295
// index of variable is value - 1,
296
// _ domainSize + 2 means variable is on default mode.
297
// A key - node association is made each time we create a node in resulting
298
// diagram.
299
// Since GUM_MULTI_DIM_DECISION_DIAGRAM_RECUR_FUNCTION is a corner step in
300
// algorithm ( meaning each time we explore a node we go trought
301
// this function ), check only have to be at the beginning of that function.
302
template
<
typename
GUM_SCALAR
,
303
template
<
typename
>
304
class
COMBINEOPERATOR
,
305
template
<
typename
>
306
class
PROJECTOPERATOR
,
307
template
<
typename
>
308
class
TerminalNodePolicy
>
309
INLINE
NodeId
310
Regress
<
GUM_SCALAR
,
COMBINEOPERATOR
,
PROJECTOPERATOR
,
TerminalNodePolicy
>::
_compute_
(
311
O4DGContext
&
currentSituation
,
312
Idx
lastInstVarPos
) {
313
NodeId
newNode
= 0;
314
315
// If both current nodes are terminal,
316
// we only have to compute the resulting value
317
if
(
_DG1_
->
isTerminalNode
(
currentSituation
.
DG1Node
())
318
&&
_DG2_
->
isTerminalNode
(
currentSituation
.
DG2Node
())) {
319
// We have to compute new valueand we insert a new node in diagram with
320
// this value, ...
321
GUM_SCALAR
newVal
=
_neutral_
;
322
GUM_SCALAR
tempVal
=
_combine_
(
_DG1_
->
nodeValue
(
currentSituation
.
DG1Node
()),
323
_DG2_
->
nodeValue
(
currentSituation
.
DG2Node
()));
324
for
(
Idx
targetModa
= 0;
targetModa
<
_targetVar_
->
domainSize
(); ++
targetModa
)
325
newVal
=
_project_
(
newVal
,
tempVal
);
326
return
_rd_
->
manager
()->
addTerminalNode
(
newVal
);
327
}
328
329
// If not,
330
// we'll have to do some exploration
331
332
// First we ensure that we hadn't already visit this pair of node under hte
333
// same circumstances
334
short
int
*
dg1NeededVar
=
_DG1InstantiationNeeded_
.
exists
(
currentSituation
.
DG1Node
())
335
?
_DG1InstantiationNeeded_
[
currentSituation
.
DG1Node
()]
336
:
_default_
;
337
Idx
dg1CurrentVarPos
338
=
_DG1_
->
isTerminalNode
(
currentSituation
.
DG1Node
())
339
?
_nbVar_
340
:
_rd_
->
variablesSequence
().
pos
(
_DG1_
->
node
(
currentSituation
.
DG1Node
())->
nodeVar
());
341
short
int
*
dg2NeededVar
=
_DG2InstantiationNeeded_
.
exists
(
currentSituation
.
DG2Node
())
342
?
_DG2InstantiationNeeded_
[
currentSituation
.
DG2Node
()]
343
:
_default_
;
344
Idx
dg2CurrentVarPos
345
=
_DG2_
->
isTerminalNode
(
currentSituation
.
DG2Node
())
346
?
_nbVar_
347
:
_rd_
->
variablesSequence
().
pos
(
_DG2_
->
node
(
currentSituation
.
DG2Node
())->
nodeVar
());
348
349
short
int
*
instNeeded
=
static_cast
<
short
int
* >(
ALLOCATE
(
sizeof
(
short
int
) *
_nbVar_
));
350
351
for
(
Idx
i
= 0;
i
<
_nbVar_
;
i
++) {
352
instNeeded
[
i
] =
dg1NeededVar
[
i
] +
dg2NeededVar
[
i
];
353
}
354
355
double
curSitKey
=
currentSituation
.
key
(
instNeeded
);
356
357
if
(
_explorationTable_
.
exists
(
curSitKey
)) {
358
DEALLOCATE
(
instNeeded
,
sizeof
(
short
int
) *
_nbVar_
);
359
360
return
_explorationTable_
[
curSitKey
];
361
}
362
363
// ====================================================
364
365
NodeId
origDG1
=
currentSituation
.
DG1Node
(),
origDG2
=
currentSituation
.
DG2Node
();
366
367
const
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>*
leaddg
=
nullptr
;
368
NodeId
leadNodeId
= 0;
369
Idx
leadVarPos
=
_rd_
->
variablesSequence
().
size
();
370
typedef
void
(
O4DGContext
::*
SetNodeFunction
)(
const
NodeId
&);
371
SetNodeFunction
leadFunction
=
nullptr
;
372
373
bool
sameVar
=
false
;
374
375
if
(!
_DG1_
->
isTerminalNode
(
currentSituation
.
DG1Node
())) {
376
if
(
currentSituation
.
varModality
(
dg1CurrentVarPos
) != 0) {
377
// If var associated to current node has already been instanciated, we
378
// have to jump it
379
currentSituation
.
setDG1Node
(
_DG1_
->
node
(
currentSituation
.
DG1Node
())
380
->
son
(
currentSituation
.
varModality
(
dg1CurrentVarPos
) - 1));
381
382
newNode
=
_compute_
(
currentSituation
,
lastInstVarPos
);
383
_explorationTable_
.
insert
(
curSitKey
,
newNode
);
384
currentSituation
.
setDG1Node
(
origDG1
);
385
currentSituation
.
setDG2Node
(
origDG2
);
386
387
DEALLOCATE
(
instNeeded
,
sizeof
(
short
int
) *
_nbVar_
);
388
389
return
newNode
;
390
}
391
392
leaddg
=
_DG1_
;
393
leadNodeId
=
currentSituation
.
DG1Node
();
394
leadVarPos
=
dg1CurrentVarPos
;
395
leadFunction
= &
O4DGContext
::
setDG1Node
;
396
}
397
398
if
(!
_DG2_
->
isTerminalNode
(
currentSituation
.
DG2Node
())) {
399
if
(
currentSituation
.
varModality
(
dg2CurrentVarPos
) != 0) {
400
// If var associated to current node has already been instanciated, we
401
// have to jump it
402
currentSituation
.
setDG2Node
(
_DG2_
->
node
(
currentSituation
.
DG2Node
())
403
->
son
(
currentSituation
.
varModality
(
dg2CurrentVarPos
) - 1));
404
405
newNode
=
_compute_
(
currentSituation
,
lastInstVarPos
);
406
_explorationTable_
.
insert
(
curSitKey
,
newNode
);
407
currentSituation
.
setDG1Node
(
origDG1
);
408
currentSituation
.
setDG2Node
(
origDG2
);
409
410
DEALLOCATE
(
instNeeded
,
sizeof
(
short
int
) *
_nbVar_
);
411
412
return
newNode
;
413
}
414
415
if
(
leadVarPos
==
dg2CurrentVarPos
) {
sameVar
=
true
; }
416
417
if
(
leadVarPos
>
dg2CurrentVarPos
) {
418
leaddg
=
_DG2_
;
419
leadNodeId
=
currentSituation
.
DG2Node
();
420
leadVarPos
=
dg2CurrentVarPos
;
421
leadFunction
= &
O4DGContext
::
setDG2Node
;
422
}
423
}
424
425
// ====================================================
426
// Anticipated Exploration
427
428
// Before exploring nodes, we have to ensure that every anticipated
429
// exploration is done
430
for
(
Idx
varPos
=
lastInstVarPos
+ 1;
varPos
<
leadVarPos
; ++
varPos
) {
431
if
(
instNeeded
[
varPos
]) {
432
const
DiscreteVariable
*
curVar
=
_rd_
->
variablesSequence
().
atPos
(
varPos
);
433
NodeId
*
sonsIds
=
static_cast
<
NodeId
* >(
ALLOCATE
(
sizeof
(
NodeId
) *
curVar
->
domainSize
()));
434
435
for
(
Idx
modality
= 0;
modality
<
curVar
->
domainSize
();
modality
++) {
436
currentSituation
.
chgVarModality
(
varPos
,
modality
+ 1);
437
438
sonsIds
[
modality
] =
_compute_
(
currentSituation
,
varPos
);
439
}
440
441
newNode
=
_rd_
->
manager
()->
addInternalNode
(
curVar
,
sonsIds
);
442
443
_explorationTable_
.
insert
(
curSitKey
,
newNode
);
444
currentSituation
.
chgVarModality
(
varPos
, 0);
445
currentSituation
.
setDG1Node
(
origDG1
);
446
currentSituation
.
setDG2Node
(
origDG2
);
447
448
DEALLOCATE
(
instNeeded
,
sizeof
(
short
int
) *
_nbVar_
);
449
450
return
newNode
;
451
}
452
}
453
454
// ====================================================
455
// Terminal Exploration
456
if
(
sameVar
&&
_DG1_
->
node
(
origDG1
)->
nodeVar
() ==
_targetVar_
) {
457
GUM_SCALAR
newVal
=
_neutral_
;
458
for
(
Idx
targetModa
= 0;
targetModa
<
_targetVar_
->
domainSize
(); ++
targetModa
)
459
newVal
=
_project_
(
newVal
,
460
_combine_
(
_DG1_
->
nodeValue
(
_DG1_
->
node
(
origDG1
)->
son
(
targetModa
)),
461
_DG2_
->
nodeValue
(
_DG2_
->
node
(
origDG2
)->
son
(
targetModa
))));
462
newNode
=
_rd_
->
manager
()->
addTerminalNode
(
newVal
);
463
_explorationTable_
.
insert
(
curSitKey
,
newNode
);
464
DEALLOCATE
(
instNeeded
,
sizeof
(
short
int
) *
_nbVar_
);
465
return
newNode
;
466
}
467
if
(
_DG1_
->
isTerminalNode
(
origDG1
)) {
468
if
(
_DG2_
->
node
(
origDG2
)->
nodeVar
() ==
_targetVar_
) {
469
GUM_SCALAR
newVal
=
_neutral_
;
470
for
(
Idx
targetModa
= 0;
targetModa
<
_targetVar_
->
domainSize
(); ++
targetModa
)
471
newVal
=
_project_
(
newVal
,
472
_combine_
(
_DG1_
->
nodeValue
(
origDG1
),
473
_DG2_
->
nodeValue
(
_DG2_
->
node
(
origDG2
)->
son
(
targetModa
))));
474
newNode
=
_rd_
->
manager
()->
addTerminalNode
(
newVal
);
475
_explorationTable_
.
insert
(
curSitKey
,
newNode
);
476
DEALLOCATE
(
instNeeded
,
sizeof
(
short
int
) *
_nbVar_
);
477
return
newNode
;
478
}
479
}
else
{
480
if
(
_DG1_
->
node
(
origDG1
)->
nodeVar
() ==
_targetVar_
&&
_DG2_
->
isTerminalNode
(
origDG2
)) {
481
GUM_SCALAR
newVal
=
_neutral_
;
482
for
(
Idx
targetModa
= 0;
targetModa
<
_targetVar_
->
domainSize
(); ++
targetModa
)
483
newVal
=
_project_
(
newVal
,
484
_combine_
(
_DG1_
->
nodeValue
(
_DG1_
->
node
(
origDG1
)->
son
(
targetModa
)),
485
_DG2_
->
nodeValue
(
origDG2
)));
486
newNode
=
_rd_
->
manager
()->
addTerminalNode
(
newVal
);
487
_explorationTable_
.
insert
(
curSitKey
,
newNode
);
488
DEALLOCATE
(
instNeeded
,
sizeof
(
short
int
) *
_nbVar_
);
489
return
newNode
;
490
}
491
}
492
493
// ====================================================
494
// Normal Exploration
495
496
// If only one of the current node is terminal,
497
// we have to pursue deeper on the other diagram
498
if
(
sameVar
) {
499
// If so - meaning it's the same variable - we have to go
500
// down on both
501
const
InternalNode
*
dg1Node
=
_DG1_
->
node
(
origDG1
);
502
const
InternalNode
*
dg2Node
=
_DG2_
->
node
(
origDG2
);
503
504
const
DiscreteVariable
*
curVar
=
dg1Node
->
nodeVar
();
505
Idx
varPos
=
_rd_
->
variablesSequence
().
pos
(
curVar
);
506
NodeId
*
sonsIds
=
static_cast
<
NodeId
* >(
ALLOCATE
(
sizeof
(
NodeId
) *
curVar
->
domainSize
()));
507
508
for
(
Idx
modality
= 0;
modality
<
curVar
->
domainSize
();
modality
++) {
509
currentSituation
.
chgVarModality
(
varPos
,
modality
+ 1);
510
currentSituation
.
setDG1Node
(
dg1Node
->
son
(
modality
));
511
currentSituation
.
setDG2Node
(
dg2Node
->
son
(
modality
));
512
513
sonsIds
[
modality
] =
_compute_
(
currentSituation
,
varPos
);
514
}
515
516
newNode
=
_rd_
->
manager
()->
addInternalNode
(
curVar
,
sonsIds
);
517
518
_explorationTable_
.
insert
(
curSitKey
,
newNode
);
519
currentSituation
.
chgVarModality
(
varPos
, 0);
520
currentSituation
.
setDG1Node
(
origDG1
);
521
currentSituation
.
setDG2Node
(
origDG2
);
522
523
DEALLOCATE
(
instNeeded
,
sizeof
(
short
int
) *
_nbVar_
);
524
525
return
newNode
;
526
}
527
// ====================================================
528
else
{
529
const
InternalNode
*
leaddgNode
=
leaddg
->
node
(
leadNodeId
);
530
531
const
DiscreteVariable
*
curVar
=
leaddgNode
->
nodeVar
();
532
NodeId
*
sonsIds
=
static_cast
<
NodeId
* >(
ALLOCATE
(
sizeof
(
NodeId
) *
curVar
->
domainSize
()));
533
534
for
(
Idx
modality
= 0;
modality
<
curVar
->
domainSize
();
modality
++) {
535
currentSituation
.
chgVarModality
(
leadVarPos
,
modality
+ 1);
536
(
currentSituation
.*
leadFunction
)(
leaddgNode
->
son
(
modality
));
537
538
sonsIds
[
modality
] =
_compute_
(
currentSituation
,
leadVarPos
);
539
}
540
541
newNode
=
_rd_
->
manager
()->
addInternalNode
(
curVar
,
sonsIds
);
542
543
_explorationTable_
.
insert
(
curSitKey
,
newNode
);
544
currentSituation
.
chgVarModality
(
leadVarPos
, 0);
545
currentSituation
.
setDG1Node
(
origDG1
);
546
currentSituation
.
setDG2Node
(
origDG2
);
547
548
DEALLOCATE
(
instNeeded
,
sizeof
(
short
int
) *
_nbVar_
);
549
550
return
newNode
;
551
}
552
}
553
554
}
// namespace gum
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643
DEALLOCATE
#define DEALLOCATE(x, y)
Definition:
internalNode.cpp:34
ALLOCATE
#define ALLOCATE(x)
Definition:
internalNode.cpp:33