Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineWeightedDirectionalSymmetryCalculator.cs @ 17607

Last change on this file since 17607 was 17181, checked in by swagner, 5 years ago

#2875: Merged r17180 from trunk to stable

File size: 6.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using HeuristicLab.Common;
25
26
27namespace HeuristicLab.Problems.DataAnalysis {
28  public class OnlineWeightedDirectionalSymmetryCalculator : DeepCloneable, IOnlineTimeSeriesCalculator {
29    private int n;
30    private double correctSum;
31    private double incorrectSum;
32
33    public double WeightedDirectionalSymmetry {
34      get {
35        if (n <= 1) return 0.0;
36        return incorrectSum / correctSum;
37      }
38    }
39
40    public OnlineWeightedDirectionalSymmetryCalculator() {
41      Reset();
42    }
43
44    protected OnlineWeightedDirectionalSymmetryCalculator(OnlineWeightedDirectionalSymmetryCalculator original, Cloner cloner)
45      : base(original, cloner) {
46      n = original.n;
47      correctSum = original.correctSum;
48      incorrectSum = original.incorrectSum;
49      errorState = original.errorState;
50    }
51
52    public override IDeepCloneable Clone(Cloner cloner) {
53      return new OnlineWeightedDirectionalSymmetryCalculator(this, cloner);
54    }
55
56    public double Value {
57      get { return WeightedDirectionalSymmetry; }
58    }
59
60    private OnlineCalculatorError errorState;
61    public OnlineCalculatorError ErrorState {
62      get { return errorState; }
63    }
64
65    public void Add(double startValue, IEnumerable<double> actualContinuation, IEnumerable<double> predictedContinuation) {
66      if (double.IsNaN(startValue) || (errorState & OnlineCalculatorError.InvalidValueAdded) > 0) {
67        errorState = errorState | OnlineCalculatorError.InvalidValueAdded;
68      } else {
69        var actualEnumerator = actualContinuation.GetEnumerator();
70        var predictedEnumerator = predictedContinuation.GetEnumerator();
71        while (actualEnumerator.MoveNext() & predictedEnumerator.MoveNext() & errorState != OnlineCalculatorError.InvalidValueAdded) {
72          double actual = actualEnumerator.Current;
73          double predicted = predictedEnumerator.Current;
74          if (double.IsNaN(actual) || double.IsNaN(predicted)) {
75            errorState = errorState | OnlineCalculatorError.InvalidValueAdded;
76          } else {
77            double err = Math.Abs(actual - predicted);
78            // count as correct only if the trend (positive/negative/no change) is predicted correctly
79            if ((actual - startValue) * (predicted - startValue) > 0.0 ||
80              (actual - startValue).IsAlmost(predicted - startValue)) {
81              correctSum += err;
82            } else {
83              incorrectSum += err;
84            }
85            n++;
86          }
87        }
88        // check if both enumerators are at the end to make sure both enumerations have the same length
89        if (actualEnumerator.MoveNext() || predictedEnumerator.MoveNext()) {
90          errorState = errorState | OnlineCalculatorError.InvalidValueAdded;
91        } else {
92          errorState = errorState & (~OnlineCalculatorError.InsufficientElementsAdded); // n >= 1
93        }
94      }
95    }
96
97    public void Reset() {
98      n = 0;
99      correctSum = 0;
100      incorrectSum = 0;
101      errorState = OnlineCalculatorError.InsufficientElementsAdded;
102    }
103
104    public static double Calculate(double startValue, IEnumerable<double> actualContinuation, IEnumerable<double> predictedContinuation, out OnlineCalculatorError errorState) {
105      OnlineWeightedDirectionalSymmetryCalculator calculator = new OnlineWeightedDirectionalSymmetryCalculator();
106      calculator.Add(startValue, actualContinuation, predictedContinuation);
107      errorState = calculator.ErrorState;
108      return calculator.WeightedDirectionalSymmetry;
109    }
110
111    public static double Calculate(IEnumerable<double> startValues, IEnumerable<IEnumerable<double>> actualContinuations, IEnumerable<IEnumerable<double>> predictedContinuations, out OnlineCalculatorError errorState) {
112      IEnumerator<double> startValueEnumerator = startValues.GetEnumerator();
113      IEnumerator<IEnumerable<double>> actualContinuationsEnumerator = actualContinuations.GetEnumerator();
114      IEnumerator<IEnumerable<double>> predictedContinuationsEnumerator = predictedContinuations.GetEnumerator();
115      OnlineWeightedDirectionalSymmetryCalculator calculator = new OnlineWeightedDirectionalSymmetryCalculator();
116
117      // always move forward all enumerators (do not use short-circuit evaluation!)
118      while (startValueEnumerator.MoveNext() & actualContinuationsEnumerator.MoveNext() & predictedContinuationsEnumerator.MoveNext()) {
119        calculator.Add(startValueEnumerator.Current, actualContinuationsEnumerator.Current, predictedContinuationsEnumerator.Current);
120        if (calculator.ErrorState != OnlineCalculatorError.None) break;
121      }
122
123      // check if all enumerators are at the end to make sure both enumerations have the same length
124      if (calculator.ErrorState == OnlineCalculatorError.None &&
125          (startValueEnumerator.MoveNext() || actualContinuationsEnumerator.MoveNext() || predictedContinuationsEnumerator.MoveNext())) {
126        throw new ArgumentException("Number of elements in startValues, actualContinuations and estimatedValues predictedContinuations doesn't match.");
127      } else {
128        errorState = calculator.ErrorState;
129        return calculator.WeightedDirectionalSymmetry;
130      }
131    }
132  }
133}
Note: See TracBrowser for help on using the repository browser.