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