aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
multiDimFunctionGraphProjector_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 projection of a function graph
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
/
multiDimFunctionGraphProjector
.
h
>
33
#
include
<
agrum
/
tools
/
variables
/
discreteVariable
.
h
>
34
35
namespace
gum
{
36
37
// CONSTRUCTOR
38
template
<
typename
GUM_SCALAR,
39
template
<
typename
>
40
class
FUNCTOR,
41
template
<
typename
>
42
class
TerminalNodePolicy >
43
MultiDimFunctionGraphProjector< GUM_SCALAR, FUNCTOR, TerminalNodePolicy >::
44
MultiDimFunctionGraphProjector(
45
const
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy >* src,
46
const
Set<
const
DiscreteVariable* >& delVars,
47
const
GUM_SCALAR neutral) :
48
_src_(src),
49
_delVars_(delVars), _function_(), _neutral_(neutral) {
50
GUM_CONSTRUCTOR(MultiDimFunctionGraphProjector);
51
_rd_ = MultiDimFunctionGraph< GUM_SCALAR >::getReducedAndOrderedInstance();
52
}
53
54
55
// DESTRUCTOR
56
template
<
typename
GUM_SCALAR
,
57
template
<
typename
>
58
class
FUNCTOR
,
59
template
<
typename
>
60
class
TerminalNodePolicy
>
61
MultiDimFunctionGraphProjector
<
GUM_SCALAR
,
FUNCTOR
,
TerminalNodePolicy
>::
62
~
MultiDimFunctionGraphProjector
() {
63
GUM_DESTRUCTOR
(
MultiDimFunctionGraphProjector
);
64
}
65
66
67
// This function is the main function. To be call every time an Projection
68
// between the two given Function Graphs is required
69
template
<
typename
GUM_SCALAR
,
70
template
<
typename
>
71
class
FUNCTOR
,
72
template
<
typename
>
73
class
TerminalNodePolicy
>
74
MultiDimFunctionGraph
<
GUM_SCALAR
,
TerminalNodePolicy
>*
75
MultiDimFunctionGraphProjector
<
GUM_SCALAR
,
FUNCTOR
,
TerminalNodePolicy
>::
project
() {
76
_rd_
->
copy
(*
_src_
);
77
78
for
(
SetIteratorSafe
<
const
DiscreteVariable
* >
varIter
=
_delVars_
.
beginSafe
();
79
varIter
!=
_delVars_
.
endSafe
();
80
++
varIter
) {
81
const
DiscreteVariable
*
curVar
= *
varIter
;
82
83
// Tout d'abord, on déplace la variable à projeter en fin de séquence afin
84
// de simplifier la projection
85
if
(
_rd_
->
variablesSequence
().
exists
(
curVar
))
86
_rd_
->
manager
()->
moveTo
(
curVar
,
_rd_
->
variablesSequence
().
size
() - 1);
87
88
// 1er cas spécial : le diagramme est un un simple noeud terminal
89
if
(
_rd_
->
isTerminalNode
(
_rd_
->
root
())) {
90
GUM_SCALAR
newVal
=
_neutral_
,
oldVal
=
_rd_
->
nodeValue
(
_rd_
->
root
());
91
for
(
Idx
curVarModality
= 0;
curVarModality
<
curVar
->
domainSize
(); ++
curVarModality
)
92
newVal
=
_function_
(
newVal
,
oldVal
);
93
94
NodeId
newSonId
=
_rd_
->
manager
()->
addTerminalNode
(
newVal
);
95
_rd_
->
manager
()->
setRootNode
(
newSonId
);
96
97
if
(
_rd_
->
variablesSequence
().
exists
(
curVar
))
_rd_
->
erase
(*
curVar
);
98
continue
;
99
}
100
101
// 2ème cas spécial : la racine du diagramme est associée à la variable
102
// projetée
103
if
(
_rd_
->
node
(
_rd_
->
root
())->
nodeVar
() ==
curVar
) {
104
const
InternalNode
*
curVarNode
=
_rd_
->
node
(
_rd_
->
root
());
105
GUM_SCALAR
newVal
=
_neutral_
;
106
for
(
Idx
curVarModality
= 0;
curVarModality
<
curVar
->
domainSize
(); ++
curVarModality
)
107
newVal
=
_function_
(
newVal
,
_rd_
->
nodeValue
(
curVarNode
->
son
(
curVarModality
)));
108
109
NodeId
newSonId
=
_rd_
->
manager
()->
addTerminalNode
(
newVal
);
110
111
_rd_
->
manager
()->
eraseNode
(
_rd_
->
root
(),
newSonId
,
false
);
112
113
if
(
_rd_
->
variablesSequence
().
exists
(
curVar
))
_rd_
->
erase
(*
curVar
);
114
continue
;
115
}
116
117
// Cas général
118
HashTable
<
NodeId
,
NodeId
>
visitedNode
(2 *
_rd_
->
realSize
(),
true
,
false
);
119
std
::
vector
<
NodeId
>
filo
;
120
filo
.
push_back
(
_rd_
->
root
());
121
122
while
(!
filo
.
empty
()) {
123
NodeId
curNodeId
=
filo
.
back
();
124
filo
.
pop_back
();
125
126
const
InternalNode
*
curNode
=
_rd_
->
node
(
curNodeId
);
127
128
for
(
Idx
modality
= 0;
modality
<
curNode
->
nodeVar
()->
domainSize
(); ++
modality
) {
129
NodeId
oldSonId
=
curNode
->
son
(
modality
);
130
131
if
(!
visitedNode
.
exists
(
oldSonId
)) {
132
NodeId
newSonId
=
oldSonId
;
133
134
if
(!
_rd_
->
isTerminalNode
(
oldSonId
)) {
135
if
(
_rd_
->
node
(
oldSonId
)->
nodeVar
() !=
curVar
) {
136
filo
.
push_back
(
oldSonId
);
137
}
else
{
138
const
InternalNode
*
curVarNode
=
_rd_
->
node
(
oldSonId
);
139
GUM_SCALAR
newVal
=
_neutral_
;
140
for
(
Idx
curVarModality
= 0;
curVarModality
<
curVar
->
domainSize
();
141
++
curVarModality
)
142
newVal
=
_function_
(
newVal
,
_rd_
->
nodeValue
(
curVarNode
->
son
(
curVarModality
)));
143
144
newSonId
=
_rd_
->
manager
()->
addTerminalNode
(
newVal
);
145
146
_rd_
->
manager
()->
eraseNode
(
oldSonId
,
newSonId
,
false
);
147
_rd_
->
manager
()->
setSon
(
curNodeId
,
modality
,
newSonId
);
148
}
149
150
}
else
{
151
GUM_SCALAR
newVal
=
_neutral_
,
oldVal
=
_rd_
->
nodeValue
(
oldSonId
);
152
for
(
Idx
curVarModality
= 0;
curVarModality
<
curVar
->
domainSize
(); ++
curVarModality
)
153
newVal
=
_function_
(
newVal
,
oldVal
);
154
155
newSonId
=
_rd_
->
manager
()->
addTerminalNode
(
newVal
);
156
_rd_
->
manager
()->
setSon
(
curNodeId
,
modality
,
newSonId
);
157
}
158
159
visitedNode
.
insert
(
oldSonId
,
newSonId
);
160
161
}
else
{
162
if
(
_rd_
->
node
(
curNodeId
)->
son
(
modality
) !=
visitedNode
[
oldSonId
])
163
_rd_
->
manager
()->
setSon
(
curNodeId
,
modality
,
visitedNode
[
oldSonId
]);
164
}
165
}
166
}
167
168
if
(
_rd_
->
variablesSequence
().
exists
(
curVar
))
_rd_
->
erase
(*
curVar
);
169
}
170
171
return
_rd_
;
172
}
173
174
}
// namespace gum
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643