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