Looking at the formula, I think the solution would be this:
public static double smooth(double a, double... d) {
double soma = 0.0;
double potencia = 1.0;
for (int i = d.length - 1; i >= 0; i--) {
soma += a * potencia * d[i];
potencia *= 1.0 - a;
}
return soma;
}
I performed a test:
System.out.println(smooth(0.05, 10, 40, 50, 20, 35));
That is the result:
7.078253125000002
To find the term a
(supposing it is between 0.0 and 1.0), we search through iterations, the global maximum of the function, knowing that there are no local maxima:
public static double bestSmooth(double... d) {
double v1 = 0.0;
double v5 = 1.0;
while (true) {
double v3 = (v1 + v5) / 2;
if (v3 == v1 || v3 == v5) return v3;
double s1 = smooth(v1, d);
double s3 = smooth(v3, d);
double s5 = smooth(v5, d);
if (s5 >= s3 && s5 >= s1) {
v1 = v3;
} else if (s1 >= s3 && s1 >= s5) {
v5 = v3;
} else {
double v2 = (v1 + v3) / 2;
double v4 = (v3 + v5) / 2;
double s2 = smooth(v2, d);
double s4 = smooth(v4, d);
if (s4 >= s3 && s4 >= s5) {
v1 = v3;
v3 = v4;
} else if (s2 >= s3 && s2 >= s1) {
v5 = v3;
v3 = v2;
} else if (s3 >= s2 && s3 >= s4) {
v1 = v2;
v5 = v4;
}
}
}
}
To find the term a
on the basis of soma
and in the d
, there is no way to reverse the formula of smooth
directly, then we need to find the corresponding value iteratively:
private static boolean ordered(double a, double b, double c) {
return (a <= b && b <= c) || (c <= b && b <= a);
}
public static double smoothRatio(double total, double... d) {
double minA = 0.0;
double maxA = bestSmooth(d);
double smoothMin = smooth(minA, d);
double smoothMax = smooth(maxA, d);
if (!ordered(smoothMin, total, smoothMax)) throw new IllegalArgumentException();
while (true) {
if (total == smoothMin) return minA;
if (total == smoothMax) return maxA;
double mid = minA + (maxA - minA) / 2;
if (mid == minA) return minA;
if (mid == maxA) return maxA;
double smoothMid = smooth(mid, d);
if (ordered(smoothMid, total, smoothMax)) {
minA = mid;
smoothMin = smoothMid;
} else if (ordered(smoothMid, total, smoothMin)) {
maxA = mid;
smoothMax = smoothMid;
}
}
}
I performed a test:
System.out.println(smoothRatio(7.078253125000002, 10, 40, 50, 20, 35));
And I got that answer:
0.05
Complete examples of tests (the last three are in the figure):
public static void main(String[] args) {
testar(0.05, 10, 40, 50, 20, 35);
testar(0.34, 22, 18);
testar(0.25, 260, 350, 430, 280, 640, 650, 240, 430, 320, 585, 385, 450, 760, 690, 400);
testar(null, 128, 180, 96, 108, 130, 150, 165, 139, 140, 165, 290, 190, 210, 240, 235);
testar(null, 36, 48, 26, 31, 57, 42, 26, 23, 18, 25, 18, 36, 41, 18, 22);
}
private static void testar(Double a, double... d) {
System.out.println("Valores: " + java.util.Arrays.toString(d));
if (a != null) {
double r = smooth(a, d);
System.out.println("Taxa: " + a + " - resultado: " + r);
double b = smoothRatio(r, d);
System.out.println("Taxa (prova real): " + b);
}
double p = bestSmooth(d);
System.out.println("Melhor taxa: " + p + " - resultado: " + smooth(p, d));
System.out.println();
}
Here’s the way out:
Valores: [10.0, 40.0, 50.0, 20.0, 35.0]
Taxa: 0.05 - resultado: 7.078253125000002
Taxa (prova real): 0.05
Melhor taxa: 1.0 - resultado: 35.0
Valores: [22.0, 18.0]
Taxa: 0.34 - resultado: 11.056799999999999
Taxa (prova real): 0.33999999999999997
Melhor taxa: 0.9090909212827682 - resultado: 18.18181818181818
Valores: [260.0, 350.0, 430.0, 280.0, 640.0, 650.0, 240.0, 430.0, 320.0, 585.0, 385.0, 450.0, 760.0, 690.0, 400.0]
Taxa: 0.25 - resultado: 514.275442045182
Taxa (prova real): 0.24999999999999967
Melhor taxa: 0.3844731971623787 - resultado: 529.8357007856109
Valores: [128.0, 180.0, 96.0, 108.0, 130.0, 150.0, 165.0, 139.0, 140.0, 165.0, 290.0, 190.0, 210.0, 240.0, 235.0]
Melhor taxa: 0.9200836578384042 - resultado: 235.20144008802336
Valores: [36.0, 48.0, 26.0, 31.0, 57.0, 42.0, 26.0, 23.0, 18.0, 25.0, 18.0, 36.0, 41.0, 18.0, 22.0]
Melhor taxa: 0.21615071594715118 - resultado: 26.222890515272397
In these last three examples (as in the figure), the first of them (line 3 of the spreadsheet, marked with C) gives the answer 514.275442045182 (which is the same value as cells Q3-S3, if rounded) using a rate of 0.25 (cell U3). If you used an ideal rate of 0.3844731971623787, the answer would be as high as possible for these data: 529.8357007856109
For the other examples, you don’t have a value of a
. Different values of a
produce different results. Probably the value of a
what matters most is the one that produces the best result, which is calculated by means of the function bestSmooth
. Thus, in the case of your line 5 of the spreadsheet (marked with B), the best possible result is 235.20144008802336 at an ideal rate of 0.9200836578384042. In the case of your worksheet line 7 (marked with A), the best possible result is 26.222890515272397 at an ideal rate of 0.21615071594715118.
In real life, not always the best result or optimal rate is achievable, but the closer the actual rate gets to the optimal rate provided by the function bestSmooth
, the higher the expected value.
See here working on ideone.
Dt is a finite sequence?
– Victor Stafusa
What do these variables mean?
– user28595
It is a time sequence where each month has its quantity sold of a given product. A is the exponential factor or alpha Df is the quantity in a given month i is an exponential. The formula works as follows given an alpha I calculate the amount sold of a product in the following month. What I want to calculate now is the alpha
– user2509556