aGrUM
0.20.2
a C++ library for (probabilistic) graphical models
defaultEliminationSequenceStrategy.cpp
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
/** @file
23
* @brief An efficient unconstrained elimination sequence algorithm
24
*
25
* @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
26
*/
27
28
#
include
<
agrum
/
agrum
.
h
>
29
#
include
<
agrum
/
tools
/
core
/
math
/
math_utils
.
h
>
30
#
include
<
agrum
/
tools
/
graphs
/
algorithms
/
triangulations
/
eliminationStrategies
/
defaultEliminationSequenceStrategy
.
h
>
31
32
namespace
gum
{
33
34
/// default constructor (uses an empty graph)
35
DefaultEliminationSequenceStrategy
::
DefaultEliminationSequenceStrategy
(
36
double
theRatio
,
37
double
theThreshold
) :
38
simplicial_ratio__
(
theRatio
),
39
simplicial_threshold__
(
theThreshold
) {
40
// for debugging purposes
41
GUM_CONSTRUCTOR
(
DefaultEliminationSequenceStrategy
);
42
}
43
44
/// constructor for an a priori non empty graph
45
DefaultEliminationSequenceStrategy
::
DefaultEliminationSequenceStrategy
(
46
UndiGraph
*
graph
,
47
const
NodeProperty
<
Size
>*
domain_sizes
,
48
double
ratio
,
49
double
threshold
) :
50
simplicial_ratio__
(
ratio
),
51
simplicial_threshold__
(
threshold
) {
52
setGraph
(
graph
,
domain_sizes
);
53
54
// for debugging purposes
55
GUM_CONSTRUCTOR
(
DefaultEliminationSequenceStrategy
);
56
}
57
58
/// copy constructor
59
DefaultEliminationSequenceStrategy
::
DefaultEliminationSequenceStrategy
(
60
const
DefaultEliminationSequenceStrategy
&
from
) :
61
UnconstrainedEliminationSequenceStrategy
(
from
),
62
// no need to set log_weights__ because the copy of the simplicial set
63
// will set it properly
64
simplicial_set__
(
new
SimplicialSet
(*
from
.
simplicial_set__
,
65
graph_
,
66
&
log_domain_sizes_
,
67
&
log_weights__
,
68
false
)),
69
simplicial_ratio__
(
from
.
simplicial_ratio__
),
70
simplicial_threshold__
(
from
.
simplicial_threshold__
),
71
provide_fill_ins__
(
from
.
provide_fill_ins__
) {
72
// for debugging purposes
73
GUM_CONS_CPY
(
DefaultEliminationSequenceStrategy
);
74
}
75
76
/// move constructor
77
DefaultEliminationSequenceStrategy
::
DefaultEliminationSequenceStrategy
(
78
DefaultEliminationSequenceStrategy
&&
from
) :
79
UnconstrainedEliminationSequenceStrategy
(
std
::
move
(
from
)),
80
log_weights__
(
std
::
move
(
from
.
log_weights__
)),
81
simplicial_set__
(
from
.
simplicial_set__
),
82
simplicial_ratio__
(
from
.
simplicial_ratio__
),
83
simplicial_threshold__
(
from
.
simplicial_threshold__
),
84
provide_fill_ins__
(
from
.
provide_fill_ins__
) {
85
simplicial_set__
->
replaceLogWeights
(&
from
.
log_weights__
, &
log_weights__
);
86
from
.
simplicial_set__
=
nullptr
;
87
88
// for debugging purposes
89
GUM_CONS_MOV
(
DefaultEliminationSequenceStrategy
);
90
}
91
92
/// destructor
93
DefaultEliminationSequenceStrategy
::~
DefaultEliminationSequenceStrategy
() {
94
// for debugging purposes
95
GUM_DESTRUCTOR
(
DefaultEliminationSequenceStrategy
);
96
97
if
(
simplicial_set__
!=
nullptr
)
delete
simplicial_set__
;
98
}
99
100
/** @brief creates a new elimination sequence of the same type as the current
101
* object, but this sequence contains only an empty graph */
102
DefaultEliminationSequenceStrategy
*
103
DefaultEliminationSequenceStrategy
::
newFactory
()
const
{
104
return
new
DefaultEliminationSequenceStrategy
(
simplicial_ratio__
,
105
simplicial_threshold__
);
106
}
107
108
/// virtual copy constructor
109
DefaultEliminationSequenceStrategy
*
110
DefaultEliminationSequenceStrategy
::
copyFactory
()
const
{
111
return
new
DefaultEliminationSequenceStrategy
(*
this
);
112
}
113
114
/// create a new simplicial set suited for the current graph
115
void
DefaultEliminationSequenceStrategy
::
createSimplicialSet__
() {
116
// remove the old simplicial set, if any
117
if
(
simplicial_set__
!=
nullptr
) {
118
delete
simplicial_set__
;
119
simplicial_set__
=
nullptr
;
120
}
121
122
if
(
graph_
!=
nullptr
) {
123
// create a simplicial set suited for the graph
124
simplicial_set__
=
new
SimplicialSet
(
graph_
,
125
&
log_domain_sizes_
,
126
&
log_weights__
,
127
simplicial_ratio__
,
128
simplicial_threshold__
);
129
130
simplicial_set__
->
setFillIns
(
provide_fill_ins__
);
131
}
132
}
133
134
/// sets a new graph to be triangulated
135
bool
DefaultEliminationSequenceStrategy
::
setGraph
(
136
UndiGraph
*
graph
,
137
const
NodeProperty
<
Size
>*
domain_sizes
) {
138
if
(
UnconstrainedEliminationSequenceStrategy
::
setGraph
(
graph
,
domain_sizes
)) {
139
createSimplicialSet__
();
140
return
true
;
141
}
142
143
return
false
;
144
}
145
146
/// clears the sequence (to prepare, for instance, a new elimination sequence)
147
void
DefaultEliminationSequenceStrategy
::
clear
() {
148
UnconstrainedEliminationSequenceStrategy
::
clear
();
149
150
log_weights__
.
clear
();
151
if
(
simplicial_set__
!=
nullptr
) {
152
delete
simplicial_set__
;
153
simplicial_set__
=
nullptr
;
154
}
155
}
156
157
/// returns the new node to be eliminated within the triangulation algorithm
158
NodeId
DefaultEliminationSequenceStrategy
::
nextNodeToEliminate
() {
159
// if there is no simplicial set, send an exception
160
if
(
graph_
==
nullptr
) {
GUM_ERROR
(
NotFound
,
"the graph is empty"
); }
161
162
// select a node to be eliminated: try simplicial nodes, then almost
163
// simplicial nodes, then quasi-simplicial nodes
164
// note that if graph__ != 0, simplicial_set__ has been allocated
165
if
(
simplicial_set__
->
hasSimplicialNode
())
166
return
simplicial_set__
->
bestSimplicialNode
();
167
else
if
(
simplicial_set__
->
hasAlmostSimplicialNode
())
168
return
simplicial_set__
->
bestAlmostSimplicialNode
();
169
else
if
(
simplicial_set__
->
hasQuasiSimplicialNode
())
170
return
simplicial_set__
->
bestQuasiSimplicialNode
();
171
else
{
172
// here: select the node through Kjaerulff's heuristic
173
auto
iter_heuristic
=
log_weights__
.
cbegin
();
174
175
if
(
iter_heuristic
==
log_weights__
.
cend
())
176
GUM_ERROR
(
NotFound
,
"there exists no more node to eliminate"
);
177
178
double
min_weight
=
iter_heuristic
.
val
();
179
NodeId
removable_node
=
iter_heuristic
.
key
();
180
for
(++
iter_heuristic
;
iter_heuristic
!=
log_weights__
.
cend
();
181
++
iter_heuristic
) {
182
if
(
iter_heuristic
.
val
() <
min_weight
) {
183
removable_node
=
iter_heuristic
.
key
();
184
min_weight
=
iter_heuristic
.
val
();
185
}
186
}
187
188
return
removable_node
;
189
}
190
}
191
192
/** @brief if the elimination sequence is able to compute fill-ins, we
193
* indicate
194
* whether we want this feature to be activated */
195
void
DefaultEliminationSequenceStrategy
::
askFillIns
(
bool
do_it
) {
196
provide_fill_ins__
=
do_it
;
197
198
if
(
simplicial_set__
!=
nullptr
)
199
simplicial_set__
->
setFillIns
(
provide_fill_ins__
);
200
}
201
202
/** @brief indicates whether the new fill-ins generated by a new eliminated
203
* node, if needed, will be computed by the elimination sequence, or need be
204
* computed by the triangulation itself. */
205
bool
DefaultEliminationSequenceStrategy
::
providesFillIns
()
const
{
206
return
provide_fill_ins__
;
207
}
208
209
/** @brief indicates whether the elimination sequence updates by itself the
210
* graph after a node has been eliminated */
211
bool
DefaultEliminationSequenceStrategy
::
providesGraphUpdate
()
const
{
212
return
true
;
213
}
214
215
/// performs all the graph/fill-ins updates provided
216
void
DefaultEliminationSequenceStrategy
::
eliminationUpdate
(
const
NodeId
id
) {
217
if
(
simplicial_set__
!=
nullptr
) {
218
simplicial_set__
->
makeClique
(
id
);
219
simplicial_set__
->
eraseClique
(
id
);
220
}
221
}
222
223
/** @brief in case fill-ins are provided, this function returns the fill-ins
224
* generated after the last node elimination */
225
const
EdgeSet
&
DefaultEliminationSequenceStrategy
::
fillIns
() {
226
if
(!
provide_fill_ins__
|| (
simplicial_set__
==
nullptr
))
227
return
UnconstrainedEliminationSequenceStrategy
::
fillIns
();
228
else
229
return
simplicial_set__
->
fillIns
();
230
}
231
232
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669