aGrUM
0.20.2
a C++ library for (probabilistic) graphical models
treeOperator_tpl.h
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 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
* @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
29
*/
30
31
#
include
<
agrum
/
tools
/
multidim
/
utils
/
FunctionGraphUtilities
/
internalNode
.
h
>
32
#
include
<
agrum
/
tools
/
multidim
/
utils
/
FunctionGraphUtilities
/
operators
/
treeOperator
.
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
TerminalNodePolicy >
44
INLINE
45
TreeOperator<
GUM_SCALAR
,
COMBINEOPERATOR
,
TerminalNodePolicy
>::
TreeOperator
(
46
const
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>*
dt1
,
47
const
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>*
dt2
) :
48
dt1__
(
dt1
),
49
dt2__
(
dt2
),
combine__
() {
50
GUM_CONSTRUCTOR
(
TreeOperator
);
51
52
rd__
=
MultiDimFunctionGraph
<
GUM_SCALAR
,
53
TerminalNodePolicy
>::
getTreeInstance
();
54
}
55
56
template
<
typename
GUM_SCALAR
,
57
template
<
typename
>
58
class
COMBINEOPERATOR
,
59
template
<
typename
>
60
class
TerminalNodePolicy
>
61
INLINE
62
TreeOperator
<
GUM_SCALAR
,
COMBINEOPERATOR
,
TerminalNodePolicy
>::
TreeOperator
(
63
const
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>*
dt1
,
64
const
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>*
dt2
,
65
const
HashTable
<
const
DiscreteVariable
*,
Idx
>
givenContext
) :
66
dt1__
(
dt1
),
67
dt2__
(
dt2
),
combine__
(),
context__
(
givenContext
) {
68
GUM_CONSTRUCTOR
(
TreeOperator
);
69
70
rd__
=
MultiDimFunctionGraph
<
GUM_SCALAR
,
71
TerminalNodePolicy
>::
getTreeInstance
();
72
}
73
74
template
<
typename
GUM_SCALAR
,
75
template
<
typename
>
76
class
COMBINEOPERATOR
,
77
template
<
typename
>
78
class
TerminalNodePolicy
>
79
INLINE
TreeOperator
<
GUM_SCALAR
,
COMBINEOPERATOR
,
TerminalNodePolicy
>::
80
~
TreeOperator
() {
81
GUM_DESTRUCTOR
(
TreeOperator
);
82
}
83
84
// This function is the main function. To be call every time an operation
85
// between the two given Function Graphs is required
86
template
<
typename
GUM_SCALAR
,
87
template
<
typename
>
88
class
COMBINEOPERATOR
,
89
template
<
typename
>
90
class
TerminalNodePolicy
>
91
INLINE
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>*
92
TreeOperator
<
GUM_SCALAR
,
COMBINEOPERATOR
,
TerminalNodePolicy
>::
compute
() {
93
rd__
->
manager
()->
setRootNode
(
xPloreDT1__
(
dt1__
->
root
()));
94
95
return
rd__
;
96
}
97
98
// Main recursion function, called every time we move on a node to determine
99
// what we have to do
100
template
<
typename
GUM_SCALAR
,
101
template
<
typename
>
102
class
COMBINEOPERATOR
,
103
template
<
typename
>
104
class
TerminalNodePolicy
>
105
INLINE
NodeId
106
TreeOperator
<
GUM_SCALAR
,
COMBINEOPERATOR
,
TerminalNodePolicy
>::
xPloreDT1__
(
107
NodeId
currentNodeId
) {
108
if
(
dt1__
->
isTerminalNode
(
currentNodeId
)) {
109
curDT1Leaf__
=
currentNodeId
;
110
return
xPloreDT2__
(
dt2__
->
root
());
111
}
112
113
const
InternalNode
*
currentNode
=
dt1__
->
node
(
currentNodeId
);
114
115
if
(!
rd__
->
variablesSequence
().
exists
(
currentNode
->
nodeVar
()))
116
rd__
->
add
(*(
currentNode
->
nodeVar
()));
117
118
NodeId
*
sonsMap
=
static_cast
<
NodeId
* >(
119
ALLOCATE
(
sizeof
(
NodeId
) *
currentNode
->
nodeVar
()->
domainSize
()));
120
for
(
Idx
moda
= 0;
moda
<
currentNode
->
nodeVar
()->
domainSize
(); ++
moda
) {
121
context__
.
insert
(
currentNode
->
nodeVar
(),
moda
);
122
sonsMap
[
moda
] =
xPloreDT1__
(
currentNode
->
son
(
moda
));
123
context__
.
erase
(
currentNode
->
nodeVar
());
124
}
125
return
checkRedundancy__
(
currentNode
->
nodeVar
(),
sonsMap
);
126
}
127
128
template
<
typename
GUM_SCALAR
,
129
template
<
typename
>
130
class
COMBINEOPERATOR
,
131
template
<
typename
>
132
class
TerminalNodePolicy
>
133
INLINE
NodeId
134
TreeOperator
<
GUM_SCALAR
,
COMBINEOPERATOR
,
TerminalNodePolicy
>::
xPloreDT2__
(
135
NodeId
currentNodeId
) {
136
if
(
dt2__
->
isTerminalNode
(
currentNodeId
))
137
return
rd__
->
manager
()->
addTerminalNode
(
138
combine__
(
dt1__
->
nodeValue
(
curDT1Leaf__
),
139
dt2__
->
nodeValue
(
currentNodeId
)));
140
141
const
InternalNode
*
currentNode
=
dt2__
->
node
(
currentNodeId
);
142
143
if
(!
rd__
->
variablesSequence
().
exists
(
currentNode
->
nodeVar
()))
144
rd__
->
add
(*(
currentNode
->
nodeVar
()));
145
146
if
(
context__
.
exists
(
currentNode
->
nodeVar
()))
147
return
xPloreDT2__
(
currentNode
->
son
(
context__
[
currentNode
->
nodeVar
()]));
148
149
NodeId
*
sonsMap
=
static_cast
<
NodeId
* >(
150
ALLOCATE
(
sizeof
(
NodeId
) *
currentNode
->
nodeVar
()->
domainSize
()));
151
for
(
Idx
moda
= 0;
moda
<
currentNode
->
nodeVar
()->
domainSize
(); ++
moda
) {
152
context__
.
insert
(
currentNode
->
nodeVar
(),
moda
);
153
sonsMap
[
moda
] =
xPloreDT2__
(
currentNode
->
son
(
moda
));
154
context__
.
erase
(
currentNode
->
nodeVar
());
155
}
156
return
checkRedundancy__
(
currentNode
->
nodeVar
(),
sonsMap
);
157
}
158
159
template
<
typename
GUM_SCALAR
,
160
template
<
typename
>
161
class
COMBINEOPERATOR
,
162
template
<
typename
>
163
class
TerminalNodePolicy
>
164
INLINE
NodeId
TreeOperator
<
GUM_SCALAR
,
COMBINEOPERATOR
,
TerminalNodePolicy
>::
165
checkRedundancy__
(
const
DiscreteVariable
*
var
,
NodeId
*
sonsMap
) {
166
bool
diff
=
false
;
167
for
(
Idx
moda
= 1;
moda
<
var
->
domainSize
() && !
diff
; ++
moda
)
168
if
(
sonsMap
[0] !=
sonsMap
[
moda
])
diff
=
true
;
169
170
if
(!
diff
) {
171
NodeId
zero
=
sonsMap
[0];
172
DEALLOCATE
(
sonsMap
,
sizeof
(
NodeId
) *
var
->
domainSize
());
173
return
zero
;
174
}
175
176
return
rd__
->
manager
()->
addInternalNode
(
var
,
sonsMap
);
177
}
178
179
}
// namespace gum
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669
DEALLOCATE
#define DEALLOCATE(x, y)
Definition:
internalNode.cpp:34
ALLOCATE
#define ALLOCATE(x)
Definition:
internalNode.cpp:33