aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
treeOperator_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
* @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 TreeOperator<
GUM_SCALAR
,
COMBINEOPERATOR
,
TerminalNodePolicy
>::
TreeOperator
(
45
const
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>*
dt1
,
46
const
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>*
dt2
) :
47
_dt1_
(
dt1
),
48
_dt2_
(
dt2
),
_combine_
() {
49
GUM_CONSTRUCTOR
(
TreeOperator
);
50
51
_rd_
=
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>::
getTreeInstance
();
52
}
53
54
template
<
typename
GUM_SCALAR
,
55
template
<
typename
>
56
class
COMBINEOPERATOR
,
57
template
<
typename
>
58
class
TerminalNodePolicy
>
59
INLINE
TreeOperator
<
GUM_SCALAR
,
COMBINEOPERATOR
,
TerminalNodePolicy
>::
TreeOperator
(
60
const
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>*
dt1
,
61
const
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>*
dt2
,
62
const
HashTable
<
const
DiscreteVariable
*,
Idx
>
givenContext
) :
63
_dt1_
(
dt1
),
64
_dt2_
(
dt2
),
_combine_
(),
_context_
(
givenContext
) {
65
GUM_CONSTRUCTOR
(
TreeOperator
);
66
67
_rd_
=
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>::
getTreeInstance
();
68
}
69
70
template
<
typename
GUM_SCALAR
,
71
template
<
typename
>
72
class
COMBINEOPERATOR
,
73
template
<
typename
>
74
class
TerminalNodePolicy
>
75
INLINE
TreeOperator
<
GUM_SCALAR
,
COMBINEOPERATOR
,
TerminalNodePolicy
>::~
TreeOperator
() {
76
GUM_DESTRUCTOR
(
TreeOperator
);
77
}
78
79
// This function is the main function. To be call every time an operation
80
// between the two given Function Graphs is required
81
template
<
typename
GUM_SCALAR
,
82
template
<
typename
>
83
class
COMBINEOPERATOR
,
84
template
<
typename
>
85
class
TerminalNodePolicy
>
86
INLINE
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>*
87
TreeOperator
<
GUM_SCALAR
,
COMBINEOPERATOR
,
TerminalNodePolicy
>::
compute
() {
88
_rd_
->
manager
()->
setRootNode
(
_xPloreDT1_
(
_dt1_
->
root
()));
89
90
return
_rd_
;
91
}
92
93
// Main recursion function, called every time we move on a node to determine
94
// what we have to do
95
template
<
typename
GUM_SCALAR
,
96
template
<
typename
>
97
class
COMBINEOPERATOR
,
98
template
<
typename
>
99
class
TerminalNodePolicy
>
100
INLINE
NodeId
TreeOperator
<
GUM_SCALAR
,
COMBINEOPERATOR
,
TerminalNodePolicy
>::
_xPloreDT1_
(
101
NodeId
currentNodeId
) {
102
if
(
_dt1_
->
isTerminalNode
(
currentNodeId
)) {
103
_curDT1Leaf_
=
currentNodeId
;
104
return
_xPloreDT2_
(
_dt2_
->
root
());
105
}
106
107
const
InternalNode
*
currentNode
=
_dt1_
->
node
(
currentNodeId
);
108
109
if
(!
_rd_
->
variablesSequence
().
exists
(
currentNode
->
nodeVar
()))
110
_rd_
->
add
(*(
currentNode
->
nodeVar
()));
111
112
NodeId
*
sonsMap
113
=
static_cast
<
NodeId
* >(
ALLOCATE
(
sizeof
(
NodeId
) *
currentNode
->
nodeVar
()->
domainSize
()));
114
for
(
Idx
moda
= 0;
moda
<
currentNode
->
nodeVar
()->
domainSize
(); ++
moda
) {
115
_context_
.
insert
(
currentNode
->
nodeVar
(),
moda
);
116
sonsMap
[
moda
] =
_xPloreDT1_
(
currentNode
->
son
(
moda
));
117
_context_
.
erase
(
currentNode
->
nodeVar
());
118
}
119
return
_checkRedundancy_
(
currentNode
->
nodeVar
(),
sonsMap
);
120
}
121
122
template
<
typename
GUM_SCALAR
,
123
template
<
typename
>
124
class
COMBINEOPERATOR
,
125
template
<
typename
>
126
class
TerminalNodePolicy
>
127
INLINE
NodeId
TreeOperator
<
GUM_SCALAR
,
COMBINEOPERATOR
,
TerminalNodePolicy
>::
_xPloreDT2_
(
128
NodeId
currentNodeId
) {
129
if
(
_dt2_
->
isTerminalNode
(
currentNodeId
))
130
return
_rd_
->
manager
()->
addTerminalNode
(
131
_combine_
(
_dt1_
->
nodeValue
(
_curDT1Leaf_
),
_dt2_
->
nodeValue
(
currentNodeId
)));
132
133
const
InternalNode
*
currentNode
=
_dt2_
->
node
(
currentNodeId
);
134
135
if
(!
_rd_
->
variablesSequence
().
exists
(
currentNode
->
nodeVar
()))
136
_rd_
->
add
(*(
currentNode
->
nodeVar
()));
137
138
if
(
_context_
.
exists
(
currentNode
->
nodeVar
()))
139
return
_xPloreDT2_
(
currentNode
->
son
(
_context_
[
currentNode
->
nodeVar
()]));
140
141
NodeId
*
sonsMap
142
=
static_cast
<
NodeId
* >(
ALLOCATE
(
sizeof
(
NodeId
) *
currentNode
->
nodeVar
()->
domainSize
()));
143
for
(
Idx
moda
= 0;
moda
<
currentNode
->
nodeVar
()->
domainSize
(); ++
moda
) {
144
_context_
.
insert
(
currentNode
->
nodeVar
(),
moda
);
145
sonsMap
[
moda
] =
_xPloreDT2_
(
currentNode
->
son
(
moda
));
146
_context_
.
erase
(
currentNode
->
nodeVar
());
147
}
148
return
_checkRedundancy_
(
currentNode
->
nodeVar
(),
sonsMap
);
149
}
150
151
template
<
typename
GUM_SCALAR
,
152
template
<
typename
>
153
class
COMBINEOPERATOR
,
154
template
<
typename
>
155
class
TerminalNodePolicy
>
156
INLINE
NodeId
TreeOperator
<
GUM_SCALAR
,
COMBINEOPERATOR
,
TerminalNodePolicy
>::
_checkRedundancy_
(
157
const
DiscreteVariable
*
var
,
158
NodeId
*
sonsMap
) {
159
bool
diff
=
false
;
160
for
(
Idx
moda
= 1;
moda
<
var
->
domainSize
() && !
diff
; ++
moda
)
161
if
(
sonsMap
[0] !=
sonsMap
[
moda
])
diff
=
true
;
162
163
if
(!
diff
) {
164
NodeId
zero
=
sonsMap
[0];
165
DEALLOCATE
(
sonsMap
,
sizeof
(
NodeId
) *
var
->
domainSize
());
166
return
zero
;
167
}
168
169
return
_rd_
->
manager
()->
addInternalNode
(
var
,
sonsMap
);
170
}
171
172
}
// 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