1 /*++
2 Copyright (c) 2018 Microsoft Corporation
3 
4 Module Name:
5 
6     ema.h
7 
8 Abstract:
9 
10     Exponential moving average based on CaDiCal.
11     The exponential scheme used to adjust beta to alpha is
12     described in Biere & Froelich, POS (Pragmatics of SAT) 2016.
13 
14 Author:
15 
16     Nikolaj Bjorner (nbjorner) 2018-05-03
17 
18 Revision History:
19 
20 --*/
21 #pragma once
22 
23 class ema {
24     double m_alpha, m_beta, m_value;
25     unsigned m_period, m_wait;
invariant()26     bool invariant() const { return 0 <= m_alpha && m_alpha <= m_beta && m_beta <= 1; }
27  public:
ema()28     ema(): m_alpha(0), m_beta(1), m_value(0), m_period(0), m_wait(0) {
29         SASSERT(invariant());
30     }
31 
ema(double alpha)32     ema(double alpha):
33         m_alpha(alpha), m_beta(1), m_value(0),
34         m_period(0), m_wait(0) {
35         SASSERT(invariant());
36     }
37 
set_alpha(double alpha)38     void set_alpha(double alpha) {
39         m_alpha = alpha;
40         SASSERT(invariant());
41     }
42 
43     operator double () const { return m_value; }
44 
update(double x)45     void update(double x) {
46         SASSERT(invariant());
47         m_value += m_beta * (x - m_value);
48         if (m_beta <= m_alpha || m_wait--) return;
49         m_wait = m_period = 2*(m_period + 1) - 1;
50         m_beta *= 0.5;
51         if (m_beta < m_alpha) m_beta = m_alpha;
52     }
53 
set(double x)54     void set(double x) {
55         m_value = x;
56     }
57 };
58 
59