aGrUM
0.20.2
a C++ library for (probabilistic) graphical models
approximationScheme_inl.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 Inline implementatioh of gum::ApproximationSettings.
25
*
26
* ApproximationSettings provides as well 2 signals :
27
* - onProgress(int pourcent,double error)
28
* - onStop(std::string message)
29
* @see gum::ApproximationListener for dedicated listener.
30
*
31
* @author Pierre-Henri WUILLEMIN(@LIP6)
32
*/
33
34
#
include
<
agrum
/
agrum
.
h
>
35
// To help IDE parser
36
#
include
<
agrum
/
tools
/
core
/
approximations
/
approximationScheme
.
h
>
37
38
namespace
gum
{
39
40
// Given that we approximate f(t), stopping criterion on |f(t+1)-f(t)| If
41
// the criterion was disabled it will be enabled
42
INLINE
void
ApproximationScheme
::
setEpsilon
(
double
eps
) {
43
if
(
eps
< 0.) {
GUM_ERROR
(
OutOfLowerBound
,
"eps should be >=0"
); }
44
45
eps_
=
eps
;
46
enabled_eps_
=
true
;
47
}
48
49
// Get the value of epsilon
50
INLINE
double
ApproximationScheme
::
epsilon
()
const
{
return
eps_
; }
51
52
// Disable stopping criterion on epsilon
53
INLINE
void
ApproximationScheme
::
disableEpsilon
() {
enabled_eps_
=
false
; }
54
55
// Enable stopping criterion on epsilon
56
INLINE
void
ApproximationScheme
::
enableEpsilon
() {
enabled_eps_
=
true
; }
57
58
// @return true if stopping criterion on epsilon is enabled, false
59
// otherwise
60
INLINE
bool
ApproximationScheme
::
isEnabledEpsilon
()
const
{
61
return
enabled_eps_
;
62
}
63
64
// Given that we approximate f(t), stopping criterion on d/dt(|f(t+1)-f(t)|)
65
INLINE
void
ApproximationScheme
::
setMinEpsilonRate
(
double
rate
) {
66
if
(
rate
< 0) {
GUM_ERROR
(
OutOfLowerBound
,
"rate should be >=0"
); }
67
68
min_rate_eps_
=
rate
;
69
enabled_min_rate_eps_
=
true
;
70
}
71
72
// Get the value of the minimal epsilon rate
73
INLINE
double
ApproximationScheme
::
minEpsilonRate
()
const
{
74
return
min_rate_eps_
;
75
}
76
77
// Disable stopping criterion on epsilon rate
78
INLINE
void
ApproximationScheme
::
disableMinEpsilonRate
() {
79
enabled_min_rate_eps_
=
false
;
80
}
81
82
// Enable stopping criterion on epsilon rate
83
INLINE
void
ApproximationScheme
::
enableMinEpsilonRate
() {
84
enabled_min_rate_eps_
=
true
;
85
}
86
87
// @return true if stopping criterion on epsilon rate is enabled, false
88
// otherwise
89
INLINE
bool
ApproximationScheme
::
isEnabledMinEpsilonRate
()
const
{
90
return
enabled_min_rate_eps_
;
91
}
92
93
// stopping criterion on number of iterations
94
INLINE
void
ApproximationScheme
::
setMaxIter
(
Size
max
) {
95
if
(
max
< 1) {
GUM_ERROR
(
OutOfLowerBound
,
"max should be >=1"
); }
96
max_iter_
=
max
;
97
enabled_max_iter_
=
true
;
98
}
99
100
// @return the criterion on number of iterations
101
INLINE Size
ApproximationScheme
::
maxIter
()
const
{
return
max_iter_
; }
102
103
// Disable stopping criterion on max iterations
104
INLINE
void
ApproximationScheme
::
disableMaxIter
() {
enabled_max_iter_
=
false
; }
105
106
// Enable stopping criterion on max iterations
107
INLINE
void
ApproximationScheme
::
enableMaxIter
() {
enabled_max_iter_
=
true
; }
108
109
// @return true if stopping criterion on max iterations is enabled, false
110
// otherwise
111
INLINE
bool
ApproximationScheme
::
isEnabledMaxIter
()
const
{
112
return
enabled_max_iter_
;
113
}
114
115
// stopping criterion on timeout (in seconds)
116
// If the criterion was disabled it will be enabled
117
INLINE
void
ApproximationScheme
::
setMaxTime
(
double
timeout
) {
118
if
(
timeout
<= 0.) {
GUM_ERROR
(
OutOfLowerBound
,
"timeout should be >0."
); }
119
max_time_
=
timeout
;
120
enabled_max_time_
=
true
;
121
}
122
123
// returns the timeout (in seconds)
124
INLINE
double
ApproximationScheme
::
maxTime
()
const
{
return
max_time_
; }
125
126
// get the current running time in second (double)
127
INLINE
double
ApproximationScheme
::
currentTime
()
const
{
return
timer_
.
step
(); }
128
129
// Disable stopping criterion on timeout
130
INLINE
void
ApproximationScheme
::
disableMaxTime
() {
enabled_max_time_
=
false
; }
131
132
// Enable stopping criterion on timeout
133
INLINE
void
ApproximationScheme
::
enableMaxTime
() {
enabled_max_time_
=
true
; }
134
135
// @return true if stopping criterion on timeout is enabled, false
136
// otherwise
137
INLINE
bool
ApproximationScheme
::
isEnabledMaxTime
()
const
{
138
return
enabled_max_time_
;
139
}
140
141
// how many samples between 2 stopping isEnableds
142
INLINE
void
ApproximationScheme
::
setPeriodSize
(
Size
p
) {
143
if
(
p
< 1) {
GUM_ERROR
(
OutOfLowerBound
,
"p should be >=1"
); }
144
145
period_size_
=
p
;
146
}
147
148
INLINE
Size
ApproximationScheme
::
periodSize
()
const
{
return
period_size_
; }
149
150
// verbosity
151
INLINE
void
ApproximationScheme
::
setVerbosity
(
bool
v
) {
verbosity_
=
v
; }
152
153
INLINE
bool
ApproximationScheme
::
verbosity
()
const
{
return
verbosity_
; }
154
155
// history
156
INLINE
IApproximationSchemeConfiguration
::
ApproximationSchemeSTATE
157
ApproximationScheme
::
stateApproximationScheme
()
const
{
158
return
current_state_
;
159
}
160
161
// @throw OperationNotAllowed if scheme not performed
162
INLINE
Size
ApproximationScheme
::
nbrIterations
()
const
{
163
if
(
stateApproximationScheme
() ==
ApproximationSchemeSTATE
::
Undefined
) {
164
GUM_ERROR
(
OperationNotAllowed
,
165
"state of the approximation scheme is undefined"
);
166
}
167
168
return
current_step_
;
169
}
170
171
// @throw OperationNotAllowed if scheme not performed or verbosity=false
172
INLINE
const
std
::
vector
<
double
>&
ApproximationScheme
::
history
()
const
{
173
if
(
stateApproximationScheme
() ==
ApproximationSchemeSTATE
::
Undefined
) {
174
GUM_ERROR
(
OperationNotAllowed
,
175
"state of the approximation scheme is udefined"
);
176
}
177
178
if
(
verbosity
() ==
false
) {
179
GUM_ERROR
(
OperationNotAllowed
,
"No history when verbosity=false"
);
180
}
181
182
return
history_
;
183
}
184
185
// initialise the scheme
186
INLINE
void
ApproximationScheme
::
initApproximationScheme
() {
187
current_state_
=
ApproximationSchemeSTATE
::
Continue
;
188
current_step_
= 0;
189
current_epsilon_
=
current_rate_
= -1.0;
190
history_
.
clear
();
191
timer_
.
reset
();
192
}
193
194
// @return true if we are at the beginning of a period (compute error is
195
// mandatory)
196
INLINE
bool
ApproximationScheme
::
startOfPeriod
() {
197
if
(
current_step_
<
burn_in_
) {
return
false
; }
198
199
if
(
period_size_
== 1) {
return
true
; }
200
201
return
((
current_step_
-
burn_in_
) %
period_size_
== 0);
202
}
203
204
// update the scheme w.r.t the new error and incr steps
205
INLINE
void
ApproximationScheme
::
updateApproximationScheme
(
unsigned
int
incr
) {
206
current_step_
+=
incr
;
207
}
208
209
INLINE
Size
ApproximationScheme
::
remainingBurnIn
() {
210
if
(
burn_in_
>
current_step_
) {
211
return
burn_in_
-
current_step_
;
212
}
else
{
213
return
0;
214
}
215
}
216
217
// stop approximation scheme by user request.
218
INLINE
void
ApproximationScheme
::
stopApproximationScheme
() {
219
if
(
current_state_
==
ApproximationSchemeSTATE
::
Continue
) {
220
stopScheme_
(
ApproximationSchemeSTATE
::
Stopped
);
221
}
222
}
223
224
// update the scheme w.r.t the new error. Test the stopping criterions that
225
// are enabled
226
INLINE
bool
ApproximationScheme
::
continueApproximationScheme
(
double
error
) {
227
// For coherence, we fix the time used in the method
228
229
double
timer_step
=
timer_
.
step
();
230
231
if
(
enabled_max_time_
) {
232
if
(
timer_step
>
max_time_
) {
233
stopScheme_
(
ApproximationSchemeSTATE
::
TimeLimit
);
234
return
false
;
235
}
236
}
237
238
if
(!
startOfPeriod
()) {
return
true
; }
239
240
if
(
current_state_
!=
ApproximationSchemeSTATE
::
Continue
) {
241
GUM_ERROR
(
OperationNotAllowed
,
242
"state of the approximation scheme is not correct : "
243
+
messageApproximationScheme
());
244
}
245
246
if
(
verbosity
()) {
history_
.
push_back
(
error
); }
247
248
if
(
enabled_max_iter_
) {
249
if
(
current_step_
>
max_iter_
) {
250
stopScheme_
(
ApproximationSchemeSTATE
::
Limit
);
251
return
false
;
252
}
253
}
254
255
last_epsilon_
=
current_epsilon_
;
256
current_epsilon_
=
error
;
// eps rate isEnabled needs it so affectation was
257
// moved from eps isEnabled below
258
259
if
(
enabled_eps_
) {
260
if
(
current_epsilon_
<=
eps_
) {
261
stopScheme_
(
ApproximationSchemeSTATE
::
Epsilon
);
262
return
false
;
263
}
264
}
265
266
if
(
last_epsilon_
>= 0.) {
267
if
(
current_epsilon_
> .0) {
268
// ! current_epsilon_ can be 0. AND epsilon
269
// isEnabled can be disabled !
270
current_rate_
271
=
std
::
fabs
((
current_epsilon_
-
last_epsilon_
) /
current_epsilon_
);
272
}
273
// limit with current eps ---> 0 is | 1 - ( last_eps / 0 ) | --->
274
// infinity the else means a return false if we isEnabled the rate below,
275
// as we would have returned false if epsilon isEnabled was enabled
276
else
{
277
current_rate_
=
min_rate_eps_
;
278
}
279
280
if
(
enabled_min_rate_eps_
) {
281
if
(
current_rate_
<=
min_rate_eps_
) {
282
stopScheme_
(
ApproximationSchemeSTATE
::
Rate
);
283
return
false
;
284
}
285
}
286
}
287
288
if
(
stateApproximationScheme
() ==
ApproximationSchemeSTATE
::
Continue
) {
289
if
(
onProgress
.
hasListener
()) {
290
GUM_EMIT3
(
onProgress
,
current_step_
,
current_epsilon_
,
timer_step
);
291
}
292
293
return
true
;
294
}
else
{
295
return
false
;
296
}
297
}
298
299
INLINE
void
300
ApproximationScheme
::
stopScheme_
(
ApproximationSchemeSTATE
new_state
) {
301
if
(
new_state
==
ApproximationSchemeSTATE
::
Continue
) {
return
; }
302
303
if
(
new_state
==
ApproximationSchemeSTATE
::
Undefined
) {
return
; }
304
305
current_state_
=
new_state
;
306
timer_
.
pause
();
307
308
if
(
onStop
.
hasListener
()) {
GUM_EMIT1
(
onStop
,
messageApproximationScheme
()); }
309
}
310
311
}
// namespace gum
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669