ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
cadical_ema.cpp
Go to the documentation of this file.
1#include "global.h"
2
3#include "internal.hpp"
4
6
7namespace CaDiCaL {
8
9// Updating an exponential moving average is placed here since we want to
10// log both updates and phases of initialization, thus need 'LOG'.
11//
12// We now use initialization bias correction as in the ADAM method
13// [KingmaBa-ICLR'15] instead of our ad-hoc initialization method used
14// before. Our old variant used exponentially decreasing alphas:
15//
16// 1,
17// 1/2, 1/2,
18// 1/4, 1/4, 1/4, 1/4
19// 1/8, 1/8, 1/8, 1/8, 1/8, 1/8, 1/8, 1/8,
20// ...
21// 2^-n, ..., 2^-n 'n' times
22// alpha, alpha, ... now 'alpha' forever.
23//
24// where 2^-n is the smallest negative power of two above 'alpha'
25//
26// This old method is better than the initializations described in our
27// [BiereFroehlich-POS'15] paper and actually faster than the ADAM method,
28// but less precise. We consider this old method obsolete now but it
29// could still be useful for implementations relying on integers instead
30// of floating points because it only needs shifts and integer arithmetic.
31//
32// Our new method for unbiased initialization of the exponential averages
33// works as follows. First the biased moving average is computed as usual.
34// Note that (as already before) we use the simpler equation
35//
36// new_biased = old_biased + alpha * (y - old_biased);
37//
38// which in principle (and thus easy to remember) can be implemented as
39//
40// biased += alpha * (y - biased);
41//
42// The original formulation in the ADAM paper (with 'alpha = 1 - beta') is
43//
44// new_biased = beta * old_biased + (1 - beta) * y
45//
46// To show that these are equivalent (modulo floating point issues)
47// consider the following equivalent expressions:
48//
49// old_biased + alpha * (y - old_biased)
50// old_biased + alpha * y - alpha * old_biased
51// (1 - alpha) * old_biased + alpha * y
52// beta * old_biased + (1 - beta) * y
53//
54// The real new idea taken from the ADAM paper is however to fix the biased
55// moving average with a correction term '1.0 / (1.0 - pow (beta, updated))'
56// by multiplication to obtain an unbiased moving average (called simply
57// 'value' in our 'code'). In order to avoid computing 'pow' every time, we
58// use 'exp' which is multiplied in every update with 'beta'.
59
60void EMA::update (Internal *internal, double y, const char *name) {
61#ifdef LOGGING
62 updated++;
63 const double old_value = value;
64#endif
65 const double old_biased = biased;
66 const double delta = y - old_biased;
67 const double scaled_delta = alpha * delta;
68 const double new_biased = old_biased + scaled_delta;
69 LOG ("update %" PRIu64 " of biased %s EMA %g with %g (delta %g) "
70 "yields %g (scaled delta %g)",
71 updated, name, old_biased, y, delta, new_biased, scaled_delta);
72 biased = new_biased;
73 const double old_exp = exp;
74 double new_exp, div, new_value;
75 if (old_exp) {
76 new_exp = old_exp * beta;
77 CADICAL_assert (new_exp < 1);
78 exp = new_exp;
79 div = 1 - new_exp;
80 CADICAL_assert (div > 0);
81 new_value = new_biased / div;
82 } else {
83 new_value = new_biased;
84#ifdef LOGGING
85 new_exp = 0;
86 div = 1;
87#endif
88 }
89 value = new_value;
90 LOG ("update %" PRIu64 " of corrected %s EMA %g with %g (delta %g) "
91 "yields %g (exponent %g, divisor %g)",
92 updated, name, old_value, y, delta, new_value, new_exp, div);
93#ifndef LOGGING
94 (void) internal;
95 (void) name;
96#endif
97}
98
99} // namespace CaDiCaL
100
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define CADICAL_assert(ignore)
Definition global.h:14
#define LOG(...)
char * name
Definition main.h:24
double value
Definition ema.hpp:23
double alpha
Definition ema.hpp:25
double biased
Definition ema.hpp:24
double beta
Definition ema.hpp:26
void update(Internal *, double y, const char *name)
double exp
Definition ema.hpp:27