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