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
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
54 
55  // Enable stopping criterion on epsilon
57 
58  // @return true if stopping criterion on epsilon is enabled, false
59  // otherwise
61  return enabled_eps_;
62  }
63 
64  // Given that we approximate f(t), stopping criterion on d/dt(|f(t+1)-f(t)|)
66  if (rate < 0) { GUM_ERROR(OutOfLowerBound, "rate should be >=0"); }
67 
69  enabled_min_rate_eps_ = true;
70  }
71 
72  // Get the value of the minimal epsilon rate
74  return min_rate_eps_;
75  }
76 
77  // Disable stopping criterion on epsilon rate
79  enabled_min_rate_eps_ = false;
80  }
81 
82  // Enable stopping criterion on epsilon rate
84  enabled_min_rate_eps_ = true;
85  }
86 
87  // @return true if stopping criterion on epsilon rate is enabled, false
88  // otherwise
90  return enabled_min_rate_eps_;
91  }
92 
93  // stopping criterion on number of iterations
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
105 
106  // Enable stopping criterion on max iterations
108 
109  // @return true if stopping criterion on max iterations is enabled, false
110  // otherwise
112  return enabled_max_iter_;
113  }
114 
115  // stopping criterion on timeout (in seconds)
116  // If the criterion was disabled it will be enabled
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
131 
132  // Enable stopping criterion on timeout
134 
135  // @return true if stopping criterion on timeout is enabled, false
136  // otherwise
138  return enabled_max_time_;
139  }
140 
141  // how many samples between 2 stopping isEnableds
143  if (p < 1) { GUM_ERROR(OutOfLowerBound, "p should be >=1"); }
144 
145  period_size_ = p;
146  }
147 
149 
150  // verbosity
152 
153  INLINE bool ApproximationScheme::verbosity() const { return verbosity_; }
154 
155  // history
158  return current_state_;
159  }
160 
161  // @throw OperationNotAllowed if scheme not performed
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 {
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
188  current_step_ = 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)
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
206  current_step_ += incr;
207  }
208 
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.
221  }
222  }
223 
224  // update the scheme w.r.t the new error. Test the stopping criterions that
225  // are enabled
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_) {
234  return false;
235  }
236  }
237 
238  if (!startOfPeriod()) { return true; }
239 
242  "state of the approximation scheme is not correct : "
244  }
245 
246  if (verbosity()) { history_.push_back(error); }
247 
248  if (enabled_max_iter_) {
249  if (current_step_ > max_iter_) {
251  return false;
252  }
253  }
254 
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_) {
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 !
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 {
278  }
279 
280  if (enabled_min_rate_eps_) {
281  if (current_rate_ <= min_rate_eps_) {
283  return false;
284  }
285  }
286  }
287 
289  if (onProgress.hasListener()) {
291  }
292 
293  return true;
294  } else {
295  return false;
296  }
297  }
298 
299  INLINE void
301  if (new_state == ApproximationSchemeSTATE::Continue) { return; }
302 
303  if (new_state == ApproximationSchemeSTATE::Undefined) { return; }
304 
306  timer_.pause();
307 
309  }
310 
311 } // namespace gum
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669