diff --git a/src/Microsoft.ML.TimeSeries/Deseasonality.cs b/src/Microsoft.ML.TimeSeries/Deseasonality.cs
new file mode 100644
index 0000000000..b56613141c
--- /dev/null
+++ b/src/Microsoft.ML.TimeSeries/Deseasonality.cs
@@ -0,0 +1,132 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+
+namespace Microsoft.ML.TimeSeries
+{
+ internal interface IDeseasonality
+ {
+ ///
+ /// Remove the seasonality component from the given time-series.
+ ///
+ /// An array representing the input time-series.
+ /// The period value of the time-series.
+ /// The de-seasonalized time-series.
+ public abstract void Deseasonality(ref double[] values, int period, ref double[] results);
+ }
+
+ internal sealed class MeanDeseasonality : IDeseasonality
+ {
+ private double[] _circularComponent;
+
+ public void Deseasonality(ref double[] values, int period, ref double[] results)
+ {
+ Array.Resize(ref _circularComponent, period);
+
+ var length = values.Length;
+
+ // Initialize the circular component to 0.
+ for (int i = 0; i < period; ++i)
+ {
+ _circularComponent[i] = 0;
+ }
+
+ // Sum up values that locate at the same position in one period.
+ for (int i = 0; i < length; ++i)
+ {
+ var indexInPeriod = i % period;
+ _circularComponent[indexInPeriod] += values[i];
+ }
+
+ // Calculate the mean value as circular component.
+ var cnt = (length - 1) / period;
+ var rest = (length - 1) % period;
+ for (int i = 0; i < period; ++i)
+ {
+ var lastCircle = i <= rest ? 1 : 0;
+ _circularComponent[i] = _circularComponent[i] / (cnt + lastCircle);
+ }
+
+ // Substract the circular component from the original series.
+ for (int i = 0; i < length; ++i)
+ {
+ var indexInPeriod = i % period;
+ results[i] -= _circularComponent[indexInPeriod];
+ }
+ }
+ }
+
+ internal sealed class MedianDeseasonality : IDeseasonality
+ {
+ private List[] _subSeries;
+ private double[] _circularComponent;
+
+ public void Deseasonality(ref double[] values, int period, ref double[] results)
+ {
+ Array.Resize(ref _circularComponent, period);
+ Array.Resize(ref _subSeries, period);
+
+ var length = values.Length;
+
+ for (int i = 0; i < period; ++i)
+ {
+ _subSeries[i] = new List();
+ }
+
+ // Split the original series into #period subseries.
+ for (int i = 0; i < length; ++i)
+ {
+ var indexInPeriod = i % period;
+ _subSeries[indexInPeriod].Add(values[i]);
+ }
+
+ // Calculate the median value as circular component.
+ for (int i = 0; i < period; ++i)
+ {
+ _circularComponent[i] = MathUtility.QuickMedian(_subSeries[i]);
+ }
+
+ // Substract the circular component from the original series.
+ for (int i = 0; i < length; ++i)
+ {
+ var indexInPeriod = i % period;
+ results[i] -= _circularComponent[indexInPeriod];
+ }
+ }
+ }
+
+ ///
+ /// This class takes the residual component of stl decompose as the deseasonality result.
+ ///
+ internal sealed class StlDeseasonality : IDeseasonality
+ {
+ private readonly InnerStl _stl;
+
+ public StlDeseasonality()
+ {
+ _stl = new InnerStl(true);
+ }
+
+ public void Deseasonality(ref double[] values, int period, ref double[] results)
+ {
+ bool success = _stl.Decomposition(values, period);
+ if (success)
+ {
+ for (int i = 0; i < _stl.Residual.Count; ++i)
+ {
+ results[i] = _stl.Residual[i];
+ }
+ }
+ else
+ {
+ for (int i = 0; i < values.Length; ++i)
+ {
+ results[i] = values[i];
+ }
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.ML.TimeSeries/ExtensionsCatalog.cs b/src/Microsoft.ML.TimeSeries/ExtensionsCatalog.cs
index 161f8bc27b..151e51bea6 100644
--- a/src/Microsoft.ML.TimeSeries/ExtensionsCatalog.cs
+++ b/src/Microsoft.ML.TimeSeries/ExtensionsCatalog.cs
@@ -176,7 +176,36 @@ public static SrCnnAnomalyEstimator DetectAnomalyBySrCnn(this TransformsCatalog
///
public static IDataView DetectEntireAnomalyBySrCnn(this AnomalyDetectionCatalog catalog, IDataView input, string outputColumnName, string inputColumnName,
double threshold = 0.3, int batchSize = 1024, double sensitivity = 99, SrCnnDetectMode detectMode = SrCnnDetectMode.AnomalyOnly)
- => new SrCnnEntireAnomalyDetector(CatalogUtils.GetEnvironment(catalog), input, inputColumnName, outputColumnName, threshold, batchSize, sensitivity, detectMode);
+ {
+ var options = new SrCnnEntireAnomalyDetectorOptions()
+ {
+ Threshold = threshold,
+ BatchSize = batchSize,
+ Sensitivity = sensitivity,
+ DetectMode = detectMode,
+ };
+
+ return DetectEntireAnomalyBySrCnn(catalog, input, outputColumnName, inputColumnName, options);
+ }
+
+ ///
+ /// Create , which detects timeseries anomalies for entire input using SRCNN algorithm.
+ ///
+ /// The AnomalyDetectionCatalog.
+ /// Input DataView.
+ /// Name of the column resulting from data processing of .
+ /// The column data is a vector of . The length of this vector varies depending on .
+ /// Name of column to process. The column data must be .
+ /// Defines the settings of the load operation.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static IDataView DetectEntireAnomalyBySrCnn(this AnomalyDetectionCatalog catalog, IDataView input, string outputColumnName, string inputColumnName, SrCnnEntireAnomalyDetectorOptions options)
+ => new SrCnnEntireAnomalyDetector(CatalogUtils.GetEnvironment(catalog), input, outputColumnName, inputColumnName, options);
///
/// Create , which localizes root causes using decision tree algorithm.
diff --git a/src/Microsoft.ML.TimeSeries/STL/FastLoess.cs b/src/Microsoft.ML.TimeSeries/STL/FastLoess.cs
new file mode 100644
index 0000000000..6ed4dde87f
--- /dev/null
+++ b/src/Microsoft.ML.TimeSeries/STL/FastLoess.cs
@@ -0,0 +1,104 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using Microsoft.ML.Runtime;
+
+namespace Microsoft.ML.TimeSeries
+{
+ ///
+ /// This is the fast version of Loess. There are several alternatives to improve the performance. This one is an approximation approach.
+ /// The smoothing is conducted on a sample set, and then the values on the left points are assigned directly.
+ ///
+ internal class FastLoess
+ {
+ ///
+ /// This class is a sampling based method, so here specifies the sample size.
+ ///
+ private const int _sampleSize = 100;
+
+ ///
+ /// The minimum length of a valid time series. A time series with length equals 2 is so trivial and meaningless less than 2.
+ ///
+ public const int MinTimeSeriesLength = 3;
+
+ private readonly IReadOnlyList _x;
+ private readonly IReadOnlyList _y;
+ private readonly int _length;
+
+ private readonly Loess _smoother;
+
+ ///
+ /// Initializes a new instance of the class.
+ /// The fast version of the Loess method. when the time series is too long, the sampling will be conducted first to improve the performance.
+ ///
+ /// The input x-axis values
+ /// The input y-axis values
+ /// If the regression is considered to take temporal information into account. In general, this is true if we are regressing a time series, and false if we are regressing scatter plot data
+ /// This method will provide default smoothing ratio if user did not specify
+ public FastLoess(IReadOnlyList xValues, IReadOnlyList yValues, bool isTemporal = true, int r = -1)
+ {
+ Contracts.CheckValue(xValues, nameof(xValues));
+ Contracts.CheckValue(yValues, nameof(yValues));
+ Y = new List();
+
+ if (yValues.Count < MinTimeSeriesLength)
+ throw Contracts.Except("input data structure cannot be 0-length: lowess");
+
+ _x = xValues;
+ _y = yValues;
+ _length = _y.Count;
+
+ if (_length <= FastLoess._sampleSize)
+ {
+ if (r == -1)
+ _smoother = new Loess(_x, _y, isTemporal);
+ else
+ _smoother = new Loess(_x, _y, isTemporal, r);
+ }
+ else
+ {
+ // Conduct sampling based strategy, to boost the performance.
+ double step = _length * 1.0 / FastLoess._sampleSize;
+ var sampleX = new double[FastLoess._sampleSize];
+ var sampleY = new double[FastLoess._sampleSize];
+ for (int i = 0; i < FastLoess._sampleSize; i++)
+ {
+ int index = (int)(i * step);
+ sampleX[i] = _x[index];
+ sampleY[i] = _y[index];
+ }
+ if (r == -1)
+ _smoother = new Loess(sampleX, sampleY, isTemporal);
+ else
+ _smoother = new Loess(sampleX, sampleY, isTemporal, r);
+ }
+ }
+
+ ///
+ /// The estimated y values.
+ ///
+ public List Y { get; }
+
+ ///
+ /// Assign the smoothing values to all the data points, not only on the sample size.
+ ///
+ public void Estimate()
+ {
+ for (int i = 0; i < _length; i++)
+ {
+ double yValue = _smoother.EstimateY(_x[i]);
+ Y.Add(yValue);
+ }
+ }
+
+ ///
+ /// Estimate a y value by giving an x value, even if the x value is not one of the input points.
+ ///
+ public double EstimateY(double xValue)
+ {
+ return _smoother.EstimateY(xValue);
+ }
+ }
+}
diff --git a/src/Microsoft.ML.TimeSeries/STL/InnerStl.cs b/src/Microsoft.ML.TimeSeries/STL/InnerStl.cs
new file mode 100644
index 0000000000..0093f0ff41
--- /dev/null
+++ b/src/Microsoft.ML.TimeSeries/STL/InnerStl.cs
@@ -0,0 +1,325 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using Microsoft.ML.Runtime;
+
+namespace Microsoft.ML.TimeSeries
+{
+ internal class InnerStl
+ {
+ private readonly bool _isTemporal;
+ private double[] _seasonalComponent;
+ private double[] _trendComponent;
+ private double[] _residual;
+
+ // Arrays for intermediate results
+ private List[] _cycleSubSeries;
+ private List[] _smoothedSubseries;
+
+ private double[] _s;
+ private double[] _t;
+ private double[] _detrendedY;
+ private double[] _c;
+ private double[] _deseasonSeries;
+
+ ///
+ /// The smoothing parameter for the seasonal component.
+ /// This parameter should be odd, and at least 7.
+ ///
+ private const int Ns = 9;
+
+ ///
+ /// The number of passes through the inner loop. This parameter is set to 2, which works for many cases.
+ ///
+ private const int Ni = 2;
+
+ ///
+ /// The number of robustness iterations of the outer loop. This parameter is not used in this implementation as we simplify the implementation.
+ /// Keep this parameter here as it is listed as one of the six parameters described in the original paper.
+ ///
+ private const int No = 10;
+
+ ///
+ /// The smoothing parameter for the low-pass filter.
+ /// This parameter should be the least odd integer greater than or equal to np.
+ /// It will preventing the trend and seasonal components from competing for the same variation in the data.
+ ///
+ private int Nl(int np)
+ {
+ if (np % 2 == 0)
+ return np + 1;
+ return np;
+ }
+
+ ///
+ /// The smoothing parameter for the trend component.
+ /// In order to avoid the trend ans seasonal components compete for variation in the data, the nt should be chosen
+ /// S.t., satisty the following inequality.
+ ///
+ private int Nt(int np)
+ {
+ double value = 1.5 * np / (1.0 - 1.5 / Ns);
+ int result = (int)value + 1;
+ if (result % 2 == 0)
+ result++;
+ return result;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ /// For a time series, only with y values. assume the x-values are 0, 1, 2, ...
+ /// Since this method supports decompose seasonal signal, which requires the equal-space of the input x-axis values.
+ /// Otherwise, the smoothing on seasonal component will be very complicated.
+ ///
+ /// If the regression is considered to take temporal information into account. In general, this is true if we are regressing a time series, and false if we are regressing scatter plot data
+ public InnerStl(bool isTemporal)
+ {
+ _isTemporal = isTemporal;
+ }
+
+ ///
+ /// The seasonal component
+ ///
+ public IReadOnlyList SeasonalComponent
+ {
+ get { return _seasonalComponent; }
+ }
+
+ ///
+ /// The trend component
+ ///
+ public IReadOnlyList TrendComponent
+ {
+ get { return _trendComponent; }
+ }
+
+ ///
+ /// The left component after seasonal and trend are eliminated.
+ ///
+ public IReadOnlyList Residual
+ {
+ get { return _residual; }
+ }
+
+ ///
+ /// The core for the robust trend-seasonal decomposition. See the ref: http://www.wessa.net/download/stl.pdf,
+ /// See section 2 and 3. especially section 2.
+ ///
+ /// Return true if the process goes successfully. Otherwise, return false.
+ public bool Decomposition(IReadOnlyList yValues, int np)
+ {
+ Contracts.CheckValue(yValues, nameof(yValues));
+ Contracts.CheckParam(np > 0, nameof(np));
+
+ if (yValues.Count == 0)
+ throw Contracts.Except("input data structure cannot be 0-length: innerSTL");
+
+ int length = yValues.Count;
+ Array.Resize(ref _seasonalComponent, length);
+ Array.Resize(ref _trendComponent, length);
+ Array.Resize(ref _residual, length);
+
+ Array.Resize(ref _s, length);
+ Array.Resize(ref _t, length);
+ Array.Resize(ref _detrendedY, length);
+ Array.Resize(ref _c, length + np * 2);
+ Array.Resize(ref _deseasonSeries, length);
+
+ Array.Resize(ref _cycleSubSeries, np);
+ Array.Resize(ref _smoothedSubseries, np);
+
+ for (int i = 0; i < length; ++i)
+ {
+ _t[i] = 0;
+ }
+
+ for (int iter = 0; iter < Ni; iter++)
+ {
+ // step1: detrending
+ Detrending(yValues, _t, _detrendedY);
+
+ // step2: cycle-subseries smoothing
+ bool success = CycleSubseriesSmooth(_detrendedY, np, _c);
+ if (!success)
+ {
+ return false;
+ }
+
+ // step3: low-pass filtering of smoothed cycle-subseries
+ var lowPass = LowPassFiltering(_c, np);
+
+ // step4: detrending of smoothed cycle-subseries
+ SmoothedCycleSubseriesDetrending(_c, lowPass, _s);
+
+ // step5: deseasonalizing
+ Deseasonalizing(yValues, _s, _deseasonSeries);
+
+ // step6: trend smoothing
+ TrendSmooth(_deseasonSeries, np, _t);
+ }
+
+ for (int i = 0; i < _s.Length; i++)
+ {
+ _seasonalComponent[i] = _s[i];
+ _trendComponent[i] = _t[i];
+ _residual[i] = yValues[i] - _s[i] - _t[i];
+ }
+
+ return true;
+ }
+
+ private void Detrending(IReadOnlyList y, IReadOnlyList t, double[] detrendedY)
+ {
+ for (int i = 0; i < y.Count; i++)
+ detrendedY[i] = y[i] - t[i];
+ }
+
+ private bool CycleSubseriesSmooth(double[] detrendedY, int np, double[] c)
+ {
+ for (int i = 0; i < np; i++)
+ {
+ _cycleSubSeries[i] = new List();
+ _smoothedSubseries[i] = new List();
+ }
+
+ // obtain all the subseries
+ for (int i = 0; i < detrendedY.Length; i++)
+ {
+ int cycleIndex = i % np;
+ _cycleSubSeries[cycleIndex].Add(detrendedY[i]);
+ }
+
+ // smoothing on each subseries
+ for (int i = 0; i < _cycleSubSeries.Length; i++)
+ {
+ List virtualXValues = VirtualXValuesProvider.GetXValues(_cycleSubSeries[i].Count);
+
+ FastLoess model = new FastLoess(virtualXValues, _cycleSubSeries[i], _isTemporal, Ns);
+ model.Estimate();
+
+ // add a prior point
+ _smoothedSubseries[i].Add(model.EstimateY(-1.0));
+ _smoothedSubseries[i].AddRange(model.Y);
+
+ // add a after point
+ _smoothedSubseries[i].Add(model.EstimateY(_cycleSubSeries[i].Count * 1.0));
+ }
+
+ // c is the smoothed series, with _length + 2Np points.
+ int index = 0;
+ for (int i = 0; i < _smoothedSubseries[0].Count; i++)
+ {
+ for (int j = 0; j < _smoothedSubseries.Length; j++)
+ {
+ if (_smoothedSubseries[j].Count <= i)
+ break;
+ if (_smoothedSubseries[j][i].Equals(double.NaN))
+ {
+ return false;
+ }
+ c[index] = (_smoothedSubseries[j][i]);
+ ++index;
+ }
+ }
+
+ return true;
+ }
+
+ private FastLoess LowPassFiltering(double[] c, int np)
+ {
+ List c1 = MovingAverage(c, np);
+ List c2 = MovingAverage(c1, np);
+ List c3 = MovingAverage(c2, 3);
+ List virtualC3XValues = VirtualXValuesProvider.GetXValues(c3.Count);
+ FastLoess lowPass = new FastLoess(virtualC3XValues, c3, _isTemporal, Nl(np));
+ lowPass.Estimate();
+
+ return lowPass;
+ }
+
+ private void SmoothedCycleSubseriesDetrending(double[] c, FastLoess lowPass, double[] s)
+ {
+ for (int i = 0; i < s.Length; i++)
+ {
+ s[i] = c[i] - lowPass.Y[i];
+ }
+ }
+
+ private void Deseasonalizing(IReadOnlyList y, double[] s, double[] deseasonSeries)
+ {
+ for (int i = 0; i < y.Count; i++)
+ {
+ deseasonSeries[i] = y[i] - s[i];
+ }
+ }
+
+ private void TrendSmooth(double[] deseasonSeries, int np, double[] t)
+ {
+ List virtualDeseasonSeries = VirtualXValuesProvider.GetXValues(deseasonSeries.Length);
+ FastLoess trender = new FastLoess(virtualDeseasonSeries, deseasonSeries, _isTemporal, Nt(np));
+ trender.Estimate();
+ for (int i = 0; i < deseasonSeries.Length; i++)
+ {
+ t[i] = trender.Y[i];
+ }
+ }
+
+ ///
+ /// This class provides the virtual x values for multi object usage.
+ /// The cache mechanism is used for performance consideration.
+ ///
+ internal class VirtualXValuesProvider
+ {
+ private static Dictionary> _xValuesPool;
+
+ static VirtualXValuesProvider()
+ {
+ _xValuesPool = new Dictionary>();
+ }
+
+ ///
+ /// Get a list of virtual x-axis values. the values are from 0 to length - 1.
+ ///
+ /// Specify the length you want to create the x values.
+ /// If the input is cached, return the cached output directly. Otherwise, create a new list and return
+ internal static List GetXValues(int length)
+ {
+ lock (_xValuesPool)
+ {
+ List xValues;
+ if (_xValuesPool.TryGetValue(length, out xValues))
+ return xValues;
+
+ var newXValues = new List(length);
+ for (int i = 0; i < length; i++)
+ newXValues.Add(i);
+
+ _xValuesPool.Add(length, newXValues);
+ return newXValues;
+ }
+ }
+ }
+
+ private static List MovingAverage(IReadOnlyList s, int length)
+ {
+ List results = new List(s.Count);
+ double partialSum = 0;
+ for (int i = 0; i < length; ++i)
+ {
+ partialSum += s[i];
+ }
+
+ for (int i = length; i < s.Count; ++i)
+ {
+ results.Add(partialSum / length);
+ partialSum = partialSum - s[i - length] + s[i];
+ }
+ results.Add(partialSum / length);
+
+ return results;
+ }
+ }
+}
diff --git a/src/Microsoft.ML.TimeSeries/STL/LeastSquares.cs b/src/Microsoft.ML.TimeSeries/STL/LeastSquares.cs
new file mode 100644
index 0000000000..a2895ec509
--- /dev/null
+++ b/src/Microsoft.ML.TimeSeries/STL/LeastSquares.cs
@@ -0,0 +1,99 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using Microsoft.ML.Runtime;
+
+namespace Microsoft.ML.TimeSeries
+{
+ ///
+ /// This class is used to calculate the least squares of the scatterplots.
+ /// Please check http://en.wikipedia.org/wiki/Least_squares for more details.
+ ///
+ internal class LeastSquares
+ {
+ private readonly IReadOnlyList _x;
+ private readonly IReadOnlyList _y;
+ private readonly int _length;
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Constructing the least square algorithm. the input will be consumed directly without any copy, due to memory usage concern.
+ ///
+ /// The corresponding x-axis value
+ /// The corresponding y-axis value
+ public LeastSquares(IReadOnlyList x, IReadOnlyList y)
+ {
+ Contracts.CheckValue(x, nameof(x));
+ Contracts.CheckValue(y, nameof(y));
+
+ if (x.Count == 0 || y.Count == 0)
+ throw Contracts.Except("input data structure cannot be 0-length");
+ if (x.Count != y.Count)
+ throw Contracts.Except("the x-axis length should be equal to y-axis length!");
+ _x = x;
+ _y = y;
+ _length = _x.Count;
+ }
+
+ ///
+ /// y=b0+b1x, while the penalty is weighted
+ ///
+ /// The weighted least squares. Note that the weight should be non-negative, and equal length to data
+ public AbstractPolynomialModel RegressionDegreeOneWeighted(IReadOnlyList weights)
+ {
+ Contracts.CheckValue(weights, nameof(weights));
+
+ Contracts.CheckParam(weights.Count == _length, nameof(weights));
+ if (weights.Count != _length)
+ throw Contracts.Except("The length of the weight vector is not equal to the length of the data points.");
+
+ // This part unfolds the matrix calculation of [sqrt(W), sqrt(W) .* X]^T * [sqrt(W), sqrt(W) .* X]
+ double sum00 = 0;
+ double sum01 = 0;
+ double sum10 = 0;
+ double sum11 = 0;
+ double temp;
+ for (int k = 0; k < _length; k++)
+ {
+ temp = weights[k];
+ sum00 += temp;
+ temp *= _x[k];
+ sum01 += temp;
+ sum10 += temp;
+ temp *= _x[k];
+ sum11 += temp;
+ }
+
+ // calculate the reverse of a 2X2 matrix is simple, because suppose the matrix is [a,b;c,d], then its reverse is
+ // [x1,x2;x3,x4] where x1 = d/K, x2 = -c/K, x3 = -b/K, x4 = a/K, where K = ad-bc.
+ double a = sum00;
+ double b = sum01;
+ double c = sum10;
+ double d = sum11;
+ double divider = a * d - b * c;
+ double reverseS00 = d / divider;
+ double reverseS01 = -c / divider;
+ double reverseS10 = -b / divider;
+ double reverseS11 = a / divider;
+
+ // This part unfolds the matrix calculation of [sqrt(W), sqrt(W) .* X]^T * [sqrt(W) .* Y]
+ double fy0 = 0;
+ double fy1 = 0;
+ for (int i = 0; i < _length; i++)
+ {
+ temp = weights[i] * _y[i];
+ fy0 += temp;
+ fy1 += temp * _x[i];
+ }
+
+ double b0 = reverseS00 * fy0 + reverseS01 * fy1;
+ double b1 = reverseS10 * fy0 + reverseS11 * fy1;
+
+ double[] results = new double[2] { b0, b1 };
+
+ return new LinearModel(results);
+ }
+ }
+}
diff --git a/src/Microsoft.ML.TimeSeries/STL/LocalRegression.cs b/src/Microsoft.ML.TimeSeries/STL/LocalRegression.cs
new file mode 100644
index 0000000000..e10819257a
--- /dev/null
+++ b/src/Microsoft.ML.TimeSeries/STL/LocalRegression.cs
@@ -0,0 +1,260 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using Microsoft.ML.Internal.CpuMath.Core;
+
+namespace Microsoft.ML.TimeSeries
+{
+ ///
+ /// This class is used to maintain the neighbors of a given particular point.
+ ///
+ internal class LocalRegression
+ {
+ private const double NumericalThreshold = 1.0e-10;
+ private readonly IReadOnlyList _x;
+ private readonly IReadOnlyList _y;
+ private readonly int _length;
+
+ ///
+ /// The model is learned by several iterations of local weighted regression.
+ ///
+ private AbstractPolynomialModel _model;
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Construct the neighborhood information of a given point. note that the input series will not be copies again, due to
+ /// memory usage concern.
+ ///
+ /// The complete values of x-axis
+ /// The complete values of y-axis
+ /// The index of the current point
+ /// Number of neighbors, usually should be less then n. if it is equal/larger than n, the weight has slight change.
+ /// If the regression is considered to take temporal information into account. In general, this is true if we are regressing a time series, and false if we are regressing scatter plot data
+ public LocalRegression(IReadOnlyList x, IReadOnlyList y, int selfIndex, int r, bool isTemporal = true)
+ {
+ Contracts.CheckValue(x, nameof(x));
+ Contracts.CheckValue(y, nameof(y));
+
+ if (x.Count <= 1 || x.Count != y.Count)
+ throw Contracts.Except("cannot accomplish neighbors obtaining");
+
+ _model = null;
+
+ _x = x;
+ _y = y;
+ _length = _x.Count;
+ SelfIndex = selfIndex;
+
+ int startIndex = selfIndex;
+ int endIndex = selfIndex;
+ double selfValue = _x[SelfIndex];
+
+ // The farthest neighbor is contained in the list. This is the normal case.
+ if (r < _length)
+ {
+ int left = r;
+ while (left > 0)
+ {
+ if (startIndex == 0)
+ {
+ endIndex += left;
+ break;
+ }
+ if (endIndex == _length - 1)
+ {
+ startIndex -= left;
+ break;
+ }
+ double startV = _x[startIndex];
+ double endV = _x[endIndex];
+
+ // the left point is closer to the current
+ // bug fix: avoid potential inconsistent index assignment due to numerical precision.
+ double distanceDiff = (selfValue - startV) - (endV - selfValue);
+
+ if (distanceDiff < NumericalThreshold)
+ {
+ startIndex--;
+ }
+ else
+ {
+ endIndex++;
+ }
+ left--;
+ }
+ StartIndex = startIndex;
+ EndIndex = endIndex;
+
+ var neighborsCount = EndIndex - StartIndex + 1;
+ NeighborsX = new double[neighborsCount];
+ NeighborsY = new double[neighborsCount];
+ Weights = new double[neighborsCount];
+
+ double leftRange = selfValue - _x[startIndex];
+ double rightRange = _x[endIndex] - selfValue;
+ double range = Math.Max(leftRange, rightRange);
+
+ if (isTemporal)
+ {
+ for (int i = StartIndex; i <= EndIndex; i++)
+ {
+ NeighborsX[i - StartIndex] = _x[i];
+ NeighborsY[i - StartIndex] = _y[i];
+ Weights[i - StartIndex] = WeightMethod.Tricube((_x[i] - selfValue) / range);
+ }
+ }
+ else
+ {
+ for (int i = StartIndex; i <= EndIndex; i++)
+ {
+ NeighborsX[i - StartIndex] = _x[i];
+ NeighborsY[i - StartIndex] = _y[i];
+
+ // since we do not consider the local/temporal information, all the neighbors share same weight for further weighted regression
+ Weights[i - StartIndex] = 1.0;
+ }
+ }
+ }
+ else
+ {
+ // when the r is equal/larger than n
+ StartIndex = 0;
+ EndIndex = _length - 1;
+
+ double leftRange = selfValue - _x[StartIndex];
+ double rightRange = _x[EndIndex] - selfValue;
+ double range = Math.Max(leftRange, rightRange);
+
+ var neighborsCount = EndIndex - StartIndex + 1;
+ NeighborsX = new double[neighborsCount];
+ NeighborsY = new double[neighborsCount];
+ Weights = new double[neighborsCount];
+
+ // this is the slight modification of the weighting calculation
+ range = range * r / (_length - 1);
+
+ if (isTemporal)
+ {
+ for (int i = StartIndex; i <= EndIndex; i++)
+ {
+ NeighborsX[i - StartIndex] = _x[i];
+ NeighborsY[i - StartIndex] = _y[i];
+ Weights[i - StartIndex] = WeightMethod.Tricube((_x[i] - selfValue) / range);
+ }
+ }
+ else
+ {
+ for (int i = StartIndex; i <= EndIndex; i++)
+ {
+ NeighborsX[i - StartIndex] = _x[i];
+ NeighborsY[i - StartIndex] = _y[i];
+
+ // since we do not consider the local/temporal information, all the neighbors share same weight for further weighted regression
+ Weights[i - StartIndex] = 1.0;
+ }
+ }
+ }
+ }
+
+ ///
+ /// The values of the y-axis of the neighbors (include the self point)
+ ///
+ public double[] NeighborsY { get; private set; }
+
+ ///
+ /// The values of the x-axis of the neighbors (include the self point)
+ ///
+ public double[] NeighborsX { get; private set; }
+
+ ///
+ /// The weights for each neighbor. This is used for weighted least squares.
+ ///
+ public double[] Weights { get; private set; }
+
+ ///
+ /// The start index of the neighbors (inclusive)
+ ///
+ public int StartIndex { get; private set; }
+
+ ///
+ /// The end index of the neighbors (inclusive)
+ ///
+ public int EndIndex { get; private set; }
+
+ ///
+ /// The index of the self point. The index is on the complete series, not only on the neighbor series.
+ ///
+ public int SelfIndex { get; private set; }
+
+ private void Estimate()
+ {
+ for (int iter = 0; iter < LoessConfiguration.T; iter++)
+ {
+ _model = Regression();
+
+ // calculate the errors
+ var errors = new double[NeighborsX.Length];
+ var absErrors = new double[NeighborsX.Length];
+ for (int i = 0; i < NeighborsX.Length; i++)
+ {
+ double error = NeighborsY[i] - _model.Y(NeighborsX[i]);
+ errors[i] = error;
+ absErrors[i] = Math.Abs(error);
+ }
+
+ Array.Sort(absErrors);
+
+ double median = absErrors[absErrors.Length / 2];
+ if (median == 0) // a very subtle bug! sometimes, when the input data is very clean, so that the median could be 0!
+ median = double.Epsilon;
+
+ // calculate the gain for new weights. the outliers will get much less weight
+ var deltas = new double[errors.Length];
+ for (int i = 0; i < errors.Length; i++)
+ {
+ deltas[i] = WeightMethod.BisquareWeight(errors[i] / 6.0 / median);
+ }
+
+ // update new weights.
+ for (int i = 0; i < Weights.Length; i++)
+ {
+ Weights[i] *= deltas[i];
+ }
+ }
+ }
+
+ ///
+ /// Get the best estimated y for the current value.
+ ///
+ public double Y()
+ {
+ if (_model == null)
+ {
+ Estimate();
+ }
+ return _model.Y(_x[SelfIndex]);
+ }
+
+ ///
+ /// Get the best estimated y for any given x-value, event not one of the observed point
+ ///
+ /// Any given x value
+ public double Y(double xValue)
+ {
+ if (_model == null)
+ {
+ Estimate();
+ }
+ return _model.Y(xValue);
+ }
+
+ private AbstractPolynomialModel Regression()
+ {
+ LeastSquares ls = new LeastSquares(NeighborsX, NeighborsY);
+ return ls.RegressionDegreeOneWeighted(Weights);
+ }
+ }
+}
diff --git a/src/Microsoft.ML.TimeSeries/STL/Loess.cs b/src/Microsoft.ML.TimeSeries/STL/Loess.cs
new file mode 100644
index 0000000000..798a5f0cdb
--- /dev/null
+++ b/src/Microsoft.ML.TimeSeries/STL/Loess.cs
@@ -0,0 +1,179 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using Microsoft.ML.Runtime;
+
+namespace Microsoft.ML.TimeSeries
+{
+ ///
+ /// Loess is short for Robust Locally Weighted Regression and Smoothing Scatterplots.
+ ///
+ internal class Loess
+ {
+ ///
+ /// The minimum length of a valid time series. A time series with length equals 2 is so trivial and meaningless less than 2.
+ ///
+ public const int MinTimeSeriesLength = 3;
+
+ private const double NumericalThreshold = 1.0e-10;
+
+ ///
+ /// The ratio to determine the local region
+ ///
+ private readonly int _r;
+
+ private readonly bool _isTemporal;
+
+ ///
+ /// Key is the index of the given point, value is the corresponding neighbors of the given point.
+ ///
+ private readonly Dictionary _neighbors;
+
+ private IReadOnlyList _x;
+ private IReadOnlyList _y;
+ private readonly int _length;
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Construct the least square algorithm specified with the number of neighbors
+ ///
+ /// The corresponding x-axis value
+ /// The corresponding y-axis value
+ /// If the regression is considered to take temporal information into account. In general, this is true if we are regressing a time series, and false if we are regressing scatter plot data
+ /// The smoothing range, if it is not specified, the algorithm will estimate the value of r by ratio.
+ public Loess(IReadOnlyList xValues, IReadOnlyList yValues, bool isTemporal, int? r = null)
+ {
+ Contracts.CheckValue(xValues, nameof(xValues));
+ Contracts.CheckValue(yValues, nameof(yValues));
+
+ if (xValues.Count < MinTimeSeriesLength || yValues.Count < MinTimeSeriesLength)
+ throw Contracts.Except("input data structure cannot be 0-length: lowess");
+
+ if (xValues.Count != yValues.Count)
+ throw Contracts.Except("the x-axis length should be equal to y-axis length!: lowess");
+
+ _neighbors = new Dictionary();
+
+ _length = xValues.Count;
+ _isTemporal = isTemporal;
+
+ if (r == null)
+ {
+ _r = (int)(_length * LoessConfiguration.F);
+ }
+ else
+ {
+ _r = (int)r;
+ }
+
+ if (_r >= _length)
+ _r = _length - 1;
+ else if (_r < LoessConfiguration.MinimumNeighborCount) // the neighbors should be at least 2, or the matrix operations would encounter issues.
+ _r = LoessConfiguration.MinimumNeighborCount;
+
+ Init(xValues, yValues);
+ }
+
+ ///
+ /// Initialize the signal with basic checking
+ ///
+ /// The input x-axis values
+ /// The input y-axis values
+ private void Init(IReadOnlyList xValues, IReadOnlyList yValues)
+ {
+ _x = xValues;
+ _y = yValues;
+ for (int i = 0; i < _length; i++)
+ {
+ LocalRegression neighbor = new LocalRegression(_x, _y, i, _r, _isTemporal);
+ _neighbors.Add(i, neighbor);
+ }
+ }
+
+ ///
+ /// Estimate a y value by giving an x value, even if the x value is not one of the input points.
+ /// When the x value is not one of the input points, find the closed one from input points, and use its model.
+ ///
+ /// find the index with value closest to the input x value.
+ public double EstimateY(double xValue)
+ {
+ // find the closest point in x to the xValue
+ int start = 0;
+ int end = _length - 1;
+ while (end - start > 1)
+ {
+ int mid = (start + end) / 2;
+ if (_x[mid] > xValue)
+ {
+ end = mid;
+ }
+ else
+ {
+ start = mid;
+ }
+ }
+ double distanceDiff = (_x[end] - xValue) - (xValue - _x[start]);
+
+ int index = distanceDiff > -NumericalThreshold ? start : end;
+ return _neighbors[index].Y(xValue);
+ }
+ }
+
+ ///
+ /// This class is used to define a set of weight functions. These functions are useful for various purposes for smoothing,
+ /// i.e., the weighted least squares.
+ ///
+ internal class WeightMethod
+ {
+ ///
+ /// This is used for robust weight, It is one iteration step of loess.
+ ///
+ public static double BisquareWeight(double value)
+ {
+ double abs = Math.Abs(value);
+ if (abs >= 1)
+ return 0;
+ double temp = 1 - abs * abs;
+ return temp * temp;
+ }
+
+ ///
+ /// A famous weight function, since it enhances a chi-squared distributional approximation f an estimated of the error variance.
+ /// Tricube should provide an adequate smooth in almost all situations.
+ ///
+ public static double Tricube(double value)
+ {
+ double abs = Math.Abs(value);
+ if (abs >= 1)
+ return 0;
+ double temp = 1 - abs * abs * abs;
+ return temp * temp * temp;
+ }
+ }
+
+ ///
+ /// This class is used to store the parameters which are needed for lowess algorithm.
+ /// The name of these constansts are compliant with the original terms in paper.
+ ///
+ internal class LoessConfiguration
+ {
+ ///
+ /// Minumum number of neighbor counts, to apply underlying regression analysis.
+ /// This number should be even, so that neighbors on left/right side of a given data point is balanced. Unbalanced neighbors would make the local-weighted regression biased noticeably at corner cases.
+ ///
+ public const int MinimumNeighborCount = 4;
+
+ ///
+ /// (0, 1], a smooth range ratio. Let fn be the number of neighbors of a specific point.
+ ///
+ public const double F = 0.3;
+
+ ///
+ /// The number of iterations for robust regression.
+ ///
+ public const int T = 2;
+ }
+}
diff --git a/src/Microsoft.ML.TimeSeries/STL/MathsTools.cs b/src/Microsoft.ML.TimeSeries/STL/MathsTools.cs
new file mode 100644
index 0000000000..17f5547284
--- /dev/null
+++ b/src/Microsoft.ML.TimeSeries/STL/MathsTools.cs
@@ -0,0 +1,125 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+
+namespace Microsoft.ML.TimeSeries
+{
+ internal class MathUtility
+ {
+ ///
+ /// Use quick-sort like method to obtain the median value.
+ /// The complexity in expectation is O(n), which is faster than using quickSort.
+ ///
+ /// The input list of values. Note that this list will be modified after calling this method
+ /// Returns the median value
+ public static double QuickMedian(List values)
+ {
+ if (values == null || values.Count == 0)
+ return double.NaN;
+
+ // here the third parameter is start from 1. so we need to plus 1 to compliant.
+ return QuickSelect(values, values.Count / 2 + 1);
+ }
+
+ ///
+ /// Use quick-sort like method to obtain the median value.
+ /// The complexity in expectation is O(n), which is faster than using quickSort.
+ ///
+ /// The list of values
+ /// The k smallest value in the list
+ public static double QuickSelect(IReadOnlyList values, int k)
+ {
+ var nums = values;
+ double[] left = new double[values.Count];
+ double[] right = new double[values.Count];
+ int numsCount = nums.Count;
+
+ while (true)
+ {
+ if (numsCount == 1)
+ return nums[0];
+
+ int idx = FindMedianIndex(nums, 0, numsCount - 1);
+ double key = nums[idx];
+
+ int leftIdx = 0;
+ int rightIdx = 0;
+ for (int i = 0; i < numsCount; i++)
+ {
+ if (i == idx)
+ continue;
+
+ if (nums[i] < key)
+ left[leftIdx++] = nums[i];
+ else
+ right[rightIdx++] = nums[i];
+ }
+
+ if (leftIdx == k - 1)
+ return key;
+
+ if (leftIdx >= k)
+ {
+ nums = left;
+ numsCount = leftIdx;
+ }
+ else
+ {
+ nums = right;
+ k = k - leftIdx - 1;
+ numsCount = rightIdx;
+ }
+ }
+ }
+
+ public static int FindMedianIndex(IReadOnlyList values, int start, int end)
+ {
+ // Use the middle value among first/middle/end as the guard value, to make sure the average performance good.
+ // According to unit test, this fix will improve the average performance 10%. and works normally when input list is ordered.
+ double first = values[start];
+ double last = values[end];
+ int midIndex = (start + end) / 2;
+ int medianIndex = -1;
+ double middleValue = values[midIndex];
+ if (first < last)
+ {
+ if (middleValue > last)
+ {
+ // last is the middle value
+ medianIndex = end;
+ }
+ else if (middleValue > first)
+ {
+ // middleValue is the middle value
+ medianIndex = midIndex;
+ }
+ else
+ {
+ // first is the middle value
+ medianIndex = start;
+ }
+ }
+ else
+ {
+ if (middleValue > first)
+ {
+ // first is the middle value
+ medianIndex = start;
+ }
+ else if (middleValue < last)
+ {
+ // last is the middle value
+ medianIndex = end;
+ }
+ else
+ {
+ // middleValue is the middle value
+ medianIndex = midIndex;
+ }
+ }
+ return medianIndex;
+ }
+ }
+}
diff --git a/src/Microsoft.ML.TimeSeries/STL/PolynomialModel.cs b/src/Microsoft.ML.TimeSeries/STL/PolynomialModel.cs
new file mode 100644
index 0000000000..437916205f
--- /dev/null
+++ b/src/Microsoft.ML.TimeSeries/STL/PolynomialModel.cs
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using Microsoft.ML.Runtime;
+
+namespace Microsoft.ML.TimeSeries
+{
+ internal abstract class AbstractPolynomialModel
+ {
+ protected IReadOnlyList Coeffs;
+
+ public AbstractPolynomialModel(IReadOnlyList coeffs)
+ {
+ Contracts.CheckValue(coeffs, nameof(coeffs));
+ Coeffs = coeffs;
+ }
+
+ public abstract double Y(double x);
+ }
+
+ ///
+ /// A general polynomial model
+ ///
+ internal sealed class PolynomialModel : AbstractPolynomialModel
+ {
+ public PolynomialModel(IReadOnlyList coeffs)
+ : base(coeffs)
+ {
+ }
+
+ ///
+ /// This function calculates the y value by given the x value, under this model
+ ///
+ /// The specific x value
+ public override double Y(double x)
+ {
+ double result = Coeffs[0];
+ double p = 1.0;
+ for (int i = 1; i < Coeffs.Count; i++)
+ {
+ p *= x;
+ result += Coeffs[i] * p;
+ }
+ return result;
+ }
+ }
+
+ ///
+ /// This class calculates f(x) = b0 + b1 * x
+ ///
+ internal sealed class LinearModel : AbstractPolynomialModel
+ {
+ ///
+ /// Store the coefficients in member variables for better performance.
+ ///
+ private readonly double _b0;
+ private readonly double _b1;
+
+ public LinearModel(IReadOnlyList coeffs)
+ : base(coeffs)
+ {
+ Contracts.CheckParam(coeffs.Count == 2, nameof(coeffs), "must contain exact 2 elements.");
+
+ _b0 = coeffs[0];
+ _b1 = coeffs[1];
+ }
+
+ public override double Y(double x)
+ {
+ return _b0 + (_b1 * x);
+ }
+ }
+}
diff --git a/src/Microsoft.ML.TimeSeries/SrCnnAnomalyDetectionBase.cs b/src/Microsoft.ML.TimeSeries/SrCnnAnomalyDetectionBase.cs
index 566b5b6cd2..c18a309539 100644
--- a/src/Microsoft.ML.TimeSeries/SrCnnAnomalyDetectionBase.cs
+++ b/src/Microsoft.ML.TimeSeries/SrCnnAnomalyDetectionBase.cs
@@ -174,13 +174,13 @@ private protected override sealed void SpectralResidual(Single input, FixedSizeQ
// Step 1: Get backadd wave
List backAddList = BackAdd(data);
- // Step 2: FFT transformation
+ // Step 2: FftTransform transformation
int length = backAddList.Count;
float[] fftRe = new float[length];
float[] fftIm = new float[length];
FftUtils.ComputeForwardFft(backAddList.ToArray(), Enumerable.Repeat(0.0f, length).ToArray(), fftRe, fftIm, length);
- // Step 3: Calculate mags of FFT
+ // Step 3: Calculate mags of FftTransform
List magList = new List();
for (int i = 0; i < length; ++i)
{
diff --git a/src/Microsoft.ML.TimeSeries/SrCnnEntireAnomalyDetector.cs b/src/Microsoft.ML.TimeSeries/SrCnnEntireAnomalyDetector.cs
index 1636179a19..5f296d806c 100644
--- a/src/Microsoft.ML.TimeSeries/SrCnnEntireAnomalyDetector.cs
+++ b/src/Microsoft.ML.TimeSeries/SrCnnEntireAnomalyDetector.cs
@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Microsoft.ML.CommandLine;
using Microsoft.ML.Data;
using Microsoft.ML.Data.DataView;
using Microsoft.ML.Runtime;
@@ -33,6 +34,63 @@ public enum SrCnnDetectMode
AnomalyAndExpectedValue = 2
}
+ ///
+ /// The Deseasonality modes of SrCnn models. The de-seasonality mode is envoked when the period of the series is greater than 0.
+ ///
+ public enum SrCnnDeseasonalityMode
+ {
+ ///
+ /// In this mode, the stl decompose algorithm is used to de-seasonality.
+ ///
+ Stl = 0,
+
+ ///
+ /// In this mode, the mean value of points in the same position in a period is substracted to de-seasonality.
+ ///
+ Mean = 1,
+
+ ///
+ /// In this mode, the median value of points in the same position in a period is substracted to de-seasonality.
+ ///
+ Median = 2
+ }
+ public sealed class SrCnnEntireAnomalyDetectorOptions
+ {
+ [Argument(ArgumentType.AtMostOnce, HelpText = "The threshold to determine anomaly, score larger than the threshold is considered as anomaly.",
+ SortOrder = 3, ShortName = "thr")]
+ public double Threshold = Defaults.Threshold;
+
+ [Argument(ArgumentType.AtMostOnce, HelpText = "The number of data points to be detected in each batch. It should be at least 12. Set this parameter to -1 to detect anomaly on the entire series.",
+ SortOrder = 4, ShortName = "bsz")]
+ public int BatchSize = Defaults.BatchSize;
+
+ [Argument(ArgumentType.AtMostOnce, HelpText = "This parameter is used in AnomalyAndMargin mode the determine the range of the boundaries.",
+ SortOrder = 4, ShortName = "sen")]
+ public double Sensitivity = Defaults.Sensitivity;
+
+ [Argument(ArgumentType.AtMostOnce, HelpText = "Specify the detect mode as one of AnomalyOnly, AnomalyAndExpectedValue and AnomalyAndMargin.",
+ SortOrder = 5, ShortName = "dtmd")]
+ public SrCnnDetectMode DetectMode = Defaults.DetectMode;
+
+ [Argument(ArgumentType.AtMostOnce, HelpText = "If there is circular pattern in the series, set this value to the number of points in one cycle.",
+ SortOrder = 5, ShortName = "prd")]
+ public int Period = Defaults.Period;
+
+ [Argument(ArgumentType.AtMostOnce, HelpText = "Specify the deseasonality mode as one of stl, mean and median.",
+ SortOrder = 6, ShortName = "dsmd")]
+ public SrCnnDeseasonalityMode DeseasonalityMode = Defaults.DeseasonalityMode;
+
+ internal static class Defaults
+ {
+ public const double Threshold = 0.3;
+ public const int BatchSize = 2000;
+ public const double Sensitivity = 55;
+ public const SrCnnDetectMode DetectMode = SrCnnDetectMode.AnomalyOnly;
+ public const int Period = 0;
+ public const SrCnnDeseasonalityMode DeseasonalityMode = SrCnnDeseasonalityMode.Stl;
+ }
+ }
+
///
/// Detect timeseries anomalies for entire input using Spectral Residual(SR) algorithm.
///
@@ -72,19 +130,17 @@ public enum SrCnnDetectMode
/// ]]>
///
///
- ///
+ ///
+ ///
internal sealed class SrCnnEntireAnomalyDetector : BatchDataViewMapperBase
{
private const int MinBatchSize = 12;
private static readonly int[] _outputLengthArray = {3, 7, 4};
- private readonly int _batchSize;
+ private readonly SrCnnEntireAnomalyDetectorOptions _options;
private readonly string _inputColumnName;
private readonly int _outputLength;
private readonly Bindings _bindings;
- private readonly double _threshold;
- private readonly double _sensitivity;
- private readonly SrCnnDetectMode _detectMode;
private class Bindings : ColumnBindingsBase
{
@@ -127,29 +183,42 @@ public Func GetDependencies(Func predicate)
}
}
- public SrCnnEntireAnomalyDetector(IHostEnvironment env, IDataView input, string inputColumnName, string outputColumnName, double threshold, int batchSize, double sensitivity, SrCnnDetectMode detectMode)
+ public SrCnnEntireAnomalyDetector(IHostEnvironment env, IDataView input, string outputColumnName, string inputColumnName, SrCnnEntireAnomalyDetectorOptions options)
: base(env, nameof(SrCnnEntireAnomalyDetector), input)
{
+ Host.CheckValue(outputColumnName, nameof(outputColumnName));
+
Host.CheckValue(inputColumnName, nameof(inputColumnName));
_inputColumnName = inputColumnName;
- Host.CheckUserArg(batchSize == -1 || batchSize >= MinBatchSize, nameof(batchSize), "BatchSize must be -1 or no less than 12.");
- _batchSize = batchSize;
+ Host.CheckValue(options, nameof(options));
+ CheckOptionArguments(options);
- Host.CheckUserArg(threshold >= 0 && threshold <= 1, nameof(threshold), "Must be in [0,1].");
- Host.CheckUserArg(detectMode == SrCnnDetectMode.AnomalyOnly
- || detectMode == SrCnnDetectMode.AnomalyAndExpectedValue
- || detectMode == SrCnnDetectMode.AnomalyAndMargin, nameof(detectMode), "Invalid detectMode");
-
- Host.CheckUserArg(sensitivity >= 0 && sensitivity <= 100, nameof(sensitivity), "Must be in [0,100].");
- _outputLength = _outputLengthArray[(int)detectMode];
- _threshold = threshold;
- _sensitivity = sensitivity;
- _detectMode = detectMode;
+ _options = options;
+ _outputLength = _outputLengthArray[(int)options.DetectMode];
_bindings = new Bindings(input.Schema, inputColumnName, outputColumnName, new VectorDataViewType(NumberDataViewType.Double, _outputLength));
}
+ private void CheckOptionArguments(SrCnnEntireAnomalyDetectorOptions options)
+ {
+ Host.CheckUserArg(options.Period >= 0, nameof(options.Period), "Must be an integer equal to or greater than 0.");
+
+ Host.CheckUserArg(options.BatchSize == -1 || options.BatchSize >= MinBatchSize, nameof(options.BatchSize), "Must be -1 or no less than 12.");
+ Host.CheckUserArg(options.BatchSize >= 4 * options.Period || options.BatchSize == -1 || options.Period == 0, nameof(options.BatchSize), "Must be at least four times the length of one period.");
+
+ Host.CheckUserArg(options.Threshold >= 0 && options.Threshold <= 1, nameof(options.Threshold), "Must be in [0,1].");
+ Host.CheckUserArg(options.DetectMode == SrCnnDetectMode.AnomalyOnly
+ || options.DetectMode == SrCnnDetectMode.AnomalyAndExpectedValue
+ || options.DetectMode == SrCnnDetectMode.AnomalyAndMargin, nameof(options.DetectMode), "Invalid detectMode");
+
+ Host.CheckUserArg(options.DeseasonalityMode == SrCnnDeseasonalityMode.Stl
+ || options.DeseasonalityMode == SrCnnDeseasonalityMode.Mean
+ || options.DeseasonalityMode == SrCnnDeseasonalityMode.Median, nameof(options.DeseasonalityMode), "Invalid detectMode");
+
+ Host.CheckUserArg(options.Sensitivity >= 0 && options.Sensitivity <= 100, nameof(options.Sensitivity), "Must be in [0,100].");
+ }
+
protected override ColumnBindingsBase SchemaBindings => _bindings;
protected override Delegate[] CreateGetters(DataViewRowCursor input, Batch currentBatch, bool[] active)
@@ -159,16 +228,17 @@ protected override Delegate[] CreateGetters(DataViewRowCursor input, Batch curre
return new[] { currentBatch.CreateGetter(input, _inputColumnName) };
}
- protected override Batch CreateBatch(DataViewRowCursor input) => new Batch(_batchSize, _outputLength, _threshold, _sensitivity, _detectMode);
+ protected override Batch CreateBatch(DataViewRowCursor input)
+ => new Batch(_options.BatchSize, _outputLength, _options.Threshold, _options.Sensitivity, _options.DetectMode, _options.Period, _options.DeseasonalityMode);
protected override Func GetIsNewBatchDelegate(DataViewRowCursor input)
{
- return () => _batchSize == -1 ? input.Position == 0 : input.Position % _batchSize == 0;
+ return () => _options.BatchSize == -1 ? input.Position == 0 : input.Position % _options.BatchSize == 0;
}
protected override Func GetLastInBatchDelegate(DataViewRowCursor input)
{
- return () => _batchSize == -1 ? input.Position == -1 : (input.Position + 1) % _batchSize == 0;
+ return () => _options.BatchSize == -1 ? input.Position == -1 : (input.Position + 1) % _options.BatchSize == 0;
}
protected override ValueGetter GetLookAheadGetter(DataViewRowCursor input)
@@ -202,7 +272,7 @@ internal sealed class Batch
private double[][] _results;
private int _bLen;
- public Batch(int batchSize, int outputLength, double threshold, double sensitivity, SrCnnDetectMode detectMode)
+ public Batch(int batchSize, int outputLength, double threshold, double sensitivity, SrCnnDetectMode detectMode, int period, SrCnnDeseasonalityMode deseasonalityMode)
{
_batchSize = batchSize;
_outputLength = outputLength;
@@ -216,7 +286,7 @@ public Batch(int batchSize, int outputLength, double threshold, double sensitivi
_previousBatch = new List(batchSize);
_batch = new List(batchSize);
}
- _modeler = new SrCnnEntireModeler(threshold, sensitivity, detectMode);
+ _modeler = new SrCnnEntireModeler(threshold, sensitivity, detectMode, period, deseasonalityMode);
}
public void AddValue(double value)
@@ -312,6 +382,8 @@ internal sealed class SrCnnEntireModeler
private readonly double _threshold;
private readonly double _sensitivity;
private readonly SrCnnDetectMode _detectMode;
+ private readonly int _period;
+ private readonly IDeseasonality _deseasonalityFunction;
//used in all modes
private readonly double[] _predictArray;
@@ -329,6 +401,7 @@ internal sealed class SrCnnEntireModeler
private double[] _cumSumList;
private double[] _cumSumShift;
private double[] _zeroArray;
+ private double[] _seriesToDetect;
//used in AnomalyAndExpectedValue and AnomalyAndMargin
private double[] _deAnomalyData;
//used in AnomalyAndMargin mode
@@ -337,12 +410,27 @@ internal sealed class SrCnnEntireModeler
private double[] _trends;
private double[] _curWindow;
- public SrCnnEntireModeler(double threshold, double sensitivity, SrCnnDetectMode detectMode)
+ public SrCnnEntireModeler(double threshold, double sensitivity, SrCnnDetectMode detectMode, int period, SrCnnDeseasonalityMode deseasonalityMode)
{
_threshold = threshold;
_sensitivity = sensitivity;
_detectMode = detectMode;
+ _period = period;
_predictArray = new double[_lookaheadWindowSize + 1];
+
+ switch (deseasonalityMode)
+ {
+ case SrCnnDeseasonalityMode.Stl:
+ _deseasonalityFunction = new StlDeseasonality();
+ break;
+ case SrCnnDeseasonalityMode.Mean:
+ _deseasonalityFunction = new MeanDeseasonality();
+ break;
+ default:
+ Contracts.Assert(deseasonalityMode == SrCnnDeseasonalityMode.Median);
+ _deseasonalityFunction = new MedianDeseasonality();
+ break;
+ }
}
public void Train(double[] values, ref double[][] results)
@@ -359,27 +447,42 @@ public void Train(double[] values, ref double[][] results)
{
Array.Resize(ref results, values.Length);
}
- SpectralResidual(values, results, _threshold);
- //Optional Steps
- if (_detectMode == SrCnnDetectMode.AnomalyAndMargin)
+
+ Array.Resize(ref _seriesToDetect, values.Length);
+ for (int i = 0; i < values.Length; ++i)
{
- GetMargin(values, results, _sensitivity);
+ _seriesToDetect[i] = values[i];
}
- else if (_detectMode == SrCnnDetectMode.AnomalyAndExpectedValue)
+
+ if (_period > 0)
{
- GetExpectedValue(values, results);
+ _deseasonalityFunction.Deseasonality(ref values, _period, ref _seriesToDetect);
}
- }
- private void AllocateDoubleArray(ref double[] arr, int length)
- {
- if (arr == null)
+ SpectralResidual(_seriesToDetect, results, _threshold);
+
+ //Optional Steps
+ if (_detectMode == SrCnnDetectMode.AnomalyAndMargin)
{
- arr = new double[length];
+ if (_period > 0)
+ {
+ GetMarginPeriod(values, results, _seriesToDetect, _sensitivity);
+ }
+ else
+ {
+ GetMargin(values, results, _sensitivity);
+ }
}
- else if (arr.Length != length)
+ else if (_detectMode == SrCnnDetectMode.AnomalyAndExpectedValue)
{
- Array.Resize(ref arr, length);
+ if (_period > 0)
+ {
+ GetExpectedValuePeriod(values, results, _seriesToDetect);
+ }
+ else
+ {
+ GetExpectedValue(values, results);
+ }
}
}
@@ -390,18 +493,18 @@ private void SpectralResidual(double[] values, double[][] results, double thresh
// Step 2: FFT transformation
int length = _backAddArray.Length;
- AllocateDoubleArray(ref _fftRe, length);
- AllocateDoubleArray(ref _fftIm, length);
+ Array.Resize(ref _fftRe, length);
+ Array.Resize(ref _fftIm, length);
- AllocateDoubleArray(ref _zeroArray, length);
+ Array.Resize(ref _zeroArray, length);
FftUtils.ComputeForwardFft(_backAddArray, _zeroArray, _fftRe, _fftIm, length);
// Step 3: Calculate mags of FFT
- AllocateDoubleArray(ref _magList, length);
- AllocateDoubleArray(ref _magLogList, length);
+ Array.Resize(ref _magList, length);
+ Array.Resize(ref _magLogList, length);
for (int i = 0; i < length; ++i)
{
- _magList[i] = Math.Sqrt((Math.Pow(_fftRe[i], 2) + Math.Pow(_fftIm[i], 2)));
+ _magList[i] = Math.Sqrt(_fftRe[i] * _fftRe[i] + _fftIm[i] * _fftIm[i]);
if (_magList[i] > _eps)
{
_magLogList[i] = Math.Log(_magList[i]);
@@ -414,15 +517,15 @@ private void SpectralResidual(double[] values, double[][] results, double thresh
// Step 4: Calculate spectral
AverageFilter(_magLogList, _averagingWindowSize);
- AllocateDoubleArray(ref _spectralList, length);
+ Array.Resize(ref _spectralList, length);
for (int i = 0; i < length; ++i)
{
_spectralList[i] = Math.Exp(_magLogList[i] - _cumSumList[i]);
}
// Step 5: IFFT transformation
- AllocateDoubleArray(ref _transRe, length);
- AllocateDoubleArray(ref _transIm, length);
+ Array.Resize(ref _transRe, length);
+ Array.Resize(ref _transIm, length);
for (int i = 0; i < length; ++i)
{
if (_magLogList[i] != 0)
@@ -437,15 +540,15 @@ private void SpectralResidual(double[] values, double[][] results, double thresh
}
}
- AllocateDoubleArray(ref _ifftRe, length);
- AllocateDoubleArray(ref _ifftIm, length);
+ Array.Resize(ref _ifftRe, length);
+ Array.Resize(ref _ifftIm, length);
FftUtils.ComputeBackwardFft(_transRe, _transIm, _ifftRe, _ifftIm, length);
// Step 6: Calculate mag and ave_mag of IFFT
- AllocateDoubleArray(ref _ifftMagList, length);
+ Array.Resize(ref _ifftMagList, length);
for (int i = 0; i < length; ++i)
{
- _ifftMagList[i] = Math.Sqrt((Math.Pow(_ifftRe[i], 2) + Math.Pow(_ifftIm[i], 2)));
+ _ifftMagList[i] = Math.Sqrt(_ifftRe[i] * _ifftRe[i] + _ifftIm[i] * _ifftIm[i]);
}
AverageFilter(_ifftMagList, Math.Min(_ifftMagList.Length, _judgementWindowSize));
@@ -473,7 +576,7 @@ private void BackAdd(double[] data)
_predictArray[j++] = data[i];
}
var predictedValue = PredictNext(_predictArray);
- AllocateDoubleArray(ref _backAddArray, data.Length + _backAddWindowSize);
+ Array.Resize(ref _backAddArray, data.Length + _backAddWindowSize);
for (int i = 0; i < data.Length; ++i)
{
_backAddArray[i] = data[i];
@@ -500,8 +603,8 @@ private void AverageFilter(double[] data, int n)
double cumsum = 0.0f;
int length = data.Length;
- AllocateDoubleArray(ref _cumSumList, length);
- AllocateDoubleArray(ref _cumSumShift, length);
+ Array.Resize(ref _cumSumList, length);
+ Array.Resize(ref _cumSumShift, length);
for (int i = 0; i < length; ++i)
{
@@ -541,6 +644,102 @@ private void GetExpectedValue(double[] values, double[][] results)
}
}
+ private void GetExpectedValuePeriod(double[] values, double[][] results, IReadOnlyList residual)
+ {
+ //Step 8: Calculate Expected Value
+ for (int i = 0; i < values.Length; ++i)
+ {
+ results[i][3] = values[i] - residual[i];
+ }
+ }
+
+ private void GetMarginPeriod(double[] values, double[][] results, IReadOnlyList residual, double sensitivity)
+ {
+ //Step 8: Calculated Expected Value
+ GetExpectedValuePeriod(values, results, residual);
+
+ //Step 9: Calculate Boundary Unit
+ CalculateBoundaryUnit(values, results.Select(x => x[0] > 0).ToArray());
+
+ for (int i = 0; i < results.Length; ++i)
+ {
+ //Step 10: Calculate UpperBound and LowerBound
+ var margin = CalculateMargin(_units[i], sensitivity);
+ results[i][4] = _units[i];
+ results[i][5] = results[i][3] + margin;
+ results[i][6] = results[i][3] - margin;
+
+ // update anomaly result according to the boundary
+ results[i][0] = results[i][0] > 0 && (values[i] < results[i][6] || results[i][5] < values[i]) ? 1 : 0;
+ }
+
+ List> segments = new List>();
+ int start = -1;
+ int cursor = -1;
+ for(int i = 0; i < values.Length; ++i)
+ {
+ // this is a outlier
+ if (results[i][6] > values[i] || values[i] > results[i][5])
+ {
+ if (cursor + 1 == i)
+ {
+ cursor = i;
+ }
+ else
+ {
+ if (start > -1)
+ {
+ segments.Add(new Tuple(start, cursor));
+ }
+ start = i;
+ cursor = i;
+ }
+ }
+ }
+
+ if (start > -1)
+ {
+ segments.Add(new Tuple(start, Math.Max(start, cursor)));
+ }
+
+ List anomalyIndex = new List();
+ for (int i = 0; i < values.Length; ++i)
+ {
+ if(results[i][0] > 0)
+ {
+ anomalyIndex.Add(i);
+ }
+ }
+
+ // more than one anomaly, update anomaly results
+ if (anomalyIndex.Count > 1)
+ {
+ cursor = 0;
+ for(int i = 0; i < anomalyIndex.Count - 1; ++i)
+ {
+ while (cursor < segments.Count && anomalyIndex[i] >= segments[cursor].Item2)
+ {
+ ++cursor;
+ }
+
+ if (cursor < segments.Count && segments[cursor].Item1 <= anomalyIndex[i] && anomalyIndex[i+1] <= segments[cursor].Item2)
+ {
+ for (int j = anomalyIndex[i]; j < anomalyIndex[i+1]; ++j)
+ {
+ results[j][0] = 1;
+ }
+ }
+ }
+ }
+
+ //Step 11: Update Anomaly Score
+ for (int i = 0; i < results.Length; ++i)
+ {
+ results[i][1] = CalculateAnomalyScore(values[i], _ifftRe[i], _units[i], results[i][0] > 0);
+ }
+
+ }
+
private void GetMargin(double[] values, double[][] results, double sensitivity)
{
//Step 8: Calculate Expected Value
@@ -558,8 +757,10 @@ private void GetMargin(double[] values, double[][] results, double sensitivity)
results[i][4] = _units[i];
results[i][5] = _ifftRe[i] + margin;
results[i][6] = _ifftRe[i] - margin;
+
//Step 11: Update Anomaly Score
results[i][1] = CalculateAnomalyScore(values[i], _ifftRe[i], _units[i], results[i][0] > 0);
+
//Step 12: Update IsAnomaly
results[i][0] = results[i][0] > 0 && (values[i] < results[i][6] || values[i] > results[i][5]) ? 1 : 0;
}
@@ -579,7 +780,7 @@ private int[] GetAnomalyIndex(double[] scores)
private void GetDeanomalyData(double[] data, int[] anomalyIdxList)
{
- AllocateDoubleArray(ref _deAnomalyData, data.Length);
+ Array.Resize(ref _deAnomalyData, data.Length);
Array.Copy(data, _deAnomalyData, data.Length);
int minPointsToFit = 4;
foreach (var idx in anomalyIdxList)
@@ -624,11 +825,11 @@ private double CalculateInterpolate(List> values, int idx)
var n = values.Count;
double sumX = values.Sum(item => item.Item1);
double sumY = values.Sum(item => item.Item2);
- double sumXX = values.Sum(item => Math.Pow(item.Item1, 2));
+ double sumXX = values.Sum(item => item.Item1 * item.Item1);
double sumXY = values.Sum(item => item.Item1 * item.Item2);
- var a = ((double)n * sumXY - sumX * sumY) / ((double)n * sumXX - sumX * sumX);
- var b = (sumXX * sumY - sumX * sumXY) / ((double)n * sumXX - sumX * sumX);
+ var a = ((n * sumXY) - (sumX * sumY)) / ((n * sumXX) - (sumX * sumX));
+ var b = ((sumXX * sumY) - (sumX * sumXY)) / ((n * sumXX) - (sumX * sumX));
return a * (double)idx + b;
}
@@ -636,9 +837,9 @@ private double CalculateInterpolate(List> values, int idx)
private void CalculateExpectedValueByFft(double[] data)
{
int length = data.Length;
- AllocateDoubleArray(ref _fftRe, length);
- AllocateDoubleArray(ref _fftIm, length);
- AllocateDoubleArray(ref _zeroArray, length);
+ Array.Resize(ref _fftRe, length);
+ Array.Resize(ref _fftIm, length);
+ Array.Resize(ref _zeroArray, length);
FftUtils.ComputeForwardFft(data, _zeroArray, _fftRe, _fftIm, length);
for (int i = 0; i < length; ++i)
@@ -650,8 +851,8 @@ private void CalculateExpectedValueByFft(double[] data)
}
}
- AllocateDoubleArray(ref _ifftRe, length);
- AllocateDoubleArray(ref _ifftIm, length);
+ Array.Resize(ref _ifftRe, length);
+ Array.Resize(ref _ifftIm, length);
FftUtils.ComputeBackwardFft(_fftRe, _fftIm, _ifftRe, _ifftIm, length);
}
@@ -682,7 +883,7 @@ private void CalculateBoundaryUnit(double[] data, bool[] isAnomalys)
trendFraction = 1.0;
}
- AllocateDoubleArray(ref _units, _trends.Length);
+ Array.Resize(ref _units, _trends.Length);
for (int i = 0; i < _units.Length; ++i)
{
_units[i] = Math.Max(1, averageTrendPart + Math.Abs(_trends[i]) * trendFraction);
@@ -697,11 +898,11 @@ private void MedianFilter(double[] data, int window, bool needTwoEnd = false)
{
int wLen = window / 2 * 2 + 1;
int tLen = data.Length;
- AllocateDoubleArray(ref _val, tLen);
+ Array.Resize(ref _val, tLen);
Array.Copy(data, _val, tLen);
- AllocateDoubleArray(ref _trends, tLen);
+ Array.Resize(ref _trends, tLen);
Array.Copy(data, _trends, tLen);
- AllocateDoubleArray(ref _curWindow, wLen);
+ Array.Resize(ref _curWindow, wLen);
if (tLen < wLen)
return;
diff --git a/src/Microsoft.ML.TimeSeries/SrCnnTransformBase.cs b/src/Microsoft.ML.TimeSeries/SrCnnTransformBase.cs
index c76973bef2..fda4001b69 100644
--- a/src/Microsoft.ML.TimeSeries/SrCnnTransformBase.cs
+++ b/src/Microsoft.ML.TimeSeries/SrCnnTransformBase.cs
@@ -26,7 +26,7 @@ internal abstract class SrCnnArgumentBase
SortOrder = 3)]
public int WindowSize = 24;
- [Argument(ArgumentType.AtMostOnce, HelpText = "The size of the initial window for computingd. The default value is set to 0, which means there is no initial window considered.", ShortName = "iwnd",
+ [Argument(ArgumentType.AtMostOnce, HelpText = "The size of the initial window for computing. The default value is set to 0, which means there is no initial window considered.", ShortName = "iwnd",
SortOrder = 4)]
public int InitialWindowSize = 0;
diff --git a/test/Microsoft.ML.TimeSeries.Tests/TimeSeriesDirectApi.cs b/test/Microsoft.ML.TimeSeries.Tests/TimeSeriesDirectApi.cs
index d25b614d37..1cd4278934 100644
--- a/test/Microsoft.ML.TimeSeries.Tests/TimeSeriesDirectApi.cs
+++ b/test/Microsoft.ML.TimeSeries.Tests/TimeSeriesDirectApi.cs
@@ -616,8 +616,7 @@ public void TestSrCnnBatchAnomalyDetector(
var outputDataView = ml.AnomalyDetection.DetectEntireAnomalyBySrCnn(dataView, outputColumnName, inputColumnName,
threshold: 0.35, batchSize: batchSize, sensitivity: 90.0, mode);
- // Getting the data of the newly created column as an IEnumerable of
- // SrCnnAnomalyDetection.
+ // Getting the data of the newly created column as an IEnumerable of SrCnnAnomalyDetection.
var predictionColumn = ml.Data.CreateEnumerable(
outputDataView, reuseRowObject: false);
@@ -661,6 +660,98 @@ public void TestSrCnnBatchAnomalyDetector(
}
}
+ [Theory, CombinatorialData]
+ public void TestSrCnnAnomalyDetectorWithSeasonalData(
+ [CombinatorialValues(SrCnnDeseasonalityMode.Stl, SrCnnDeseasonalityMode.Mean, SrCnnDeseasonalityMode.Median)] SrCnnDeseasonalityMode mode)
+ {
+ var ml = new MLContext(1);
+ IDataView dataView;
+ var dataPath = GetDataPath("Timeseries", "period_no_anomaly.csv");
+
+ // Load data from file into the dataView
+ dataView = ml.Data.LoadFromTextFile(dataPath, hasHeader: true);
+
+ // Setup the detection arguments
+ string outputColumnName = nameof(SrCnnAnomalyDetection.Prediction);
+ string inputColumnName = nameof(TimeSeriesDataDouble.Value);
+
+ // Do batch anomaly detection
+ var options = new SrCnnEntireAnomalyDetectorOptions()
+ {
+ Threshold = 0.3,
+ BatchSize = -1,
+ Sensitivity = 53.0,
+ DetectMode = SrCnnDetectMode.AnomalyAndMargin,
+ Period = 288,
+ DeseasonalityMode = mode
+ };
+
+ var outputDataView = ml.AnomalyDetection.DetectEntireAnomalyBySrCnn(dataView, outputColumnName, inputColumnName, options);
+
+ // Getting the data of the newly created column as an IEnumerable of SrCnnAnomalyDetection.
+ var predictionColumn = ml.Data.CreateEnumerable(
+ outputDataView, reuseRowObject: false);
+
+ foreach (var prediction in predictionColumn)
+ {
+ Assert.Equal(7, prediction.Prediction.Length);
+ Assert.Equal(0, prediction.Prediction[0]);
+ }
+ }
+
+ [Theory, CombinatorialData]
+ public void TestSrCnnAnomalyDetectorWithSeasonalAnomalyData(
+ [CombinatorialValues(SrCnnDeseasonalityMode.Stl, SrCnnDeseasonalityMode.Mean, SrCnnDeseasonalityMode.Median)] SrCnnDeseasonalityMode mode
+ )
+ {
+ var ml = new MLContext(1);
+ IDataView dataView;
+ var dataPath = GetDataPath("Timeseries", "period_anomaly.csv");
+
+ // Load data from file into the dataView
+ dataView = ml.Data.LoadFromTextFile(dataPath, hasHeader: true);
+
+ // Setup the detection arguments
+ string outputColumnName = nameof(SrCnnAnomalyDetection.Prediction);
+ string inputColumnName = nameof(TimeSeriesDataDouble.Value);
+
+ // Do batch anomaly detection
+ var options = new SrCnnEntireAnomalyDetectorOptions()
+ {
+ Threshold = 0.23,
+ BatchSize = -1,
+ Sensitivity = 53.0,
+ DetectMode = SrCnnDetectMode.AnomalyAndMargin,
+ Period = 288,
+ DeseasonalityMode = mode
+ };
+
+ var outputDataView = ml.AnomalyDetection.DetectEntireAnomalyBySrCnn(dataView, outputColumnName, inputColumnName, options);
+
+ // Getting the data of the newly created column as an IEnumerable of SrCnnAnomalyDetection.
+ var predictionColumn = ml.Data.CreateEnumerable(
+ outputDataView, reuseRowObject: false);
+
+ var anomalyStartIndex = 2988;
+ var anomalyEndIndex = 3095;
+
+ int k = 0;
+ foreach (var prediction in predictionColumn)
+ {
+ Assert.Equal(7, prediction.Prediction.Length);
+ if (anomalyStartIndex <= k && k <= anomalyEndIndex)
+ {
+ Assert.Equal(1, prediction.Prediction[0]);
+ }
+ else
+ {
+ Assert.Equal(0, prediction.Prediction[0]);
+ }
+
+ ++k;
+ }
+ }
+
[Fact]
public void RootCauseLocalization()
{
diff --git a/test/data/Timeseries/period_anomaly.csv b/test/data/Timeseries/period_anomaly.csv
new file mode 100644
index 0000000000..52183ce307
--- /dev/null
+++ b/test/data/Timeseries/period_anomaly.csv
@@ -0,0 +1,4033 @@
+Value
+18.09048623
+20.35984259
+21.10546985
+21.15158525
+18.13714054
+21.62566053
+21.67380669
+20.24556149
+19.9283328
+18.17946985
+20.24781657
+19.63751633
+21.09122563
+19.61553427
+20.73432333
+18.40563259
+18.53180908
+18.55884076
+18.182102
+20.16531544
+21.1758709
+20.44164481
+20.29981954
+20.72249571
+19.35858129
+19.44781629
+19.25708039
+20.84843573
+18.64656134
+18.05210112
+20.38478579
+21.76952546
+20.43763167
+21.13168661
+20.69116284
+19.98974661
+20.87356961
+21.2964165
+18.89892658
+19.34452192
+18.89490293
+19.80869182
+21.5402582
+19.3808284
+19.49786756
+21.44146894
+20.06149732
+20.141796
+21.44320481
+19.96210695
+20.72623014
+18.34257866
+18.71452685
+19.6175048
+19.97935627
+21.8629348
+21.88260653
+21.40478835
+19.26239534
+21.85611316
+20.75736346
+19.57176051
+20.80669967
+18.06609092
+18.58461873
+21.31874285
+20.58229455
+19.45677881
+20.00266656
+21.6205686
+20.52631244
+19.59259714
+18.48130663
+19.17498721
+21.91336093
+19.74945225
+19.88735786
+19.99439213
+21.53641609
+20.41571314
+20.77470815
+19.55765417
+18.11635047
+21.72389166
+21.79651072
+21.79661221
+21.77474835
+21.26096776
+20.7383842
+21.37803967
+20.40218496
+18.53747846
+19.56487266
+21.88517965
+19.40455125
+21.47131165
+18.37284588
+19.33673537
+19.4038133
+18.20641017
+18.47637732
+18.77266084
+21.35126236
+18.25360796
+19.19480361
+18.04070001
+20.78251098
+20.48121236
+69.97175876
+66.29160587
+64.03244237
+70.9963549
+72.23120307
+63.08498037
+67.82088022
+64.58253327
+63.48625331
+71.18682426
+68.51811832
+64.14012052
+74.65120017
+84.84246498
+83.01150684
+83.49677345
+76.97938775
+79.52148874
+75.68743533
+71.04608986
+76.0645957
+79.05858129
+74.29647908
+83.00019292
+73.97109693
+77.40682104
+73.55447171
+78.00645026
+72.19877339
+75.90262558
+77.9412935
+79.17274194
+80.21494689
+75.94145893
+79.88644939
+79.6632095
+76.9663782
+85.18086544
+80.63338172
+77.22353592
+87.05282729
+85.41917245
+87.6161393
+82.9760511
+77.95790461
+76.40197814
+82.5139498
+87.58783364
+82.0077547
+86.08517365
+77.24711114
+78.49241782
+86.47964374
+84.08968086
+87.68151651
+84.37597226
+79.15724902
+80.47776902
+86.3875099
+80.80694945
+76.08270584
+78.96612645
+80.25720329
+73.54398706
+83.89617558
+73.74612295
+78.47491644
+84.86988511
+79.47731069
+85.46814565
+77.46638259
+87.31798924
+75.35077153
+72.61152924
+85.95799948
+84.03443672
+75.71101456
+87.75502326
+80.03571372
+87.21620976
+80.07969157
+79.54922971
+79.18545641
+77.35726178
+80.53906932
+79.24072245
+72.58781066
+76.16681749
+75.40982001
+85.87880475
+81.581763
+84.21876791
+87.30904897
+82.30447034
+87.72159144
+76.98807701
+74.98024612
+78.45292808
+79.5327601
+86.32575154
+80.95901594
+76.67486655
+83.88211632
+80.09328024
+74.59408248
+81.22908541
+86.58227934
+85.48192905
+32.55557757
+31.21332632
+29.35665837
+31.805747
+33.61330195
+31.10574583
+30.30685386
+34.76082353
+34.05794994
+32.88495765
+29.6754077
+29.72741087
+20.62242264
+22.92100781
+20.67772019
+23.93496854
+24.60848186
+21.80123867
+22.1924397
+23.34826767
+24.35844413
+24.16553878
+20.41801027
+20.91744053
+21.52282987
+21.25370592
+18.97766313
+20.48845628
+21.63021647
+19.32812544
+22.00079389
+18.64897217
+21.63587081
+20.95439396
+19.72305629
+21.38493946
+21.23088455
+21.83992669
+19.56455991
+20.84363841
+20.50843529
+20.19730819
+21.66516184
+18.09913002
+19.22026292
+20.24984383
+18.80299623
+21.73529712
+20.61014723
+19.93064704
+21.27921548
+19.82255616
+20.25403727
+18.02829454
+19.4814864
+18.57297484
+20.77868312
+19.93522729
+19.22546897
+19.89040582
+18.84213655
+21.70451299
+18.21938798
+21.46578878
+20.04928388
+20.47971733
+19.21411088
+21.87098889
+19.13107629
+20.35942024
+21.97788576
+21.52851026
+20.1453193
+21.96149809
+20.80547945
+18.83480166
+19.62238484
+19.33797334
+19.37605483
+21.04182576
+20.33705171
+18.15237085
+21.50979393
+19.18718456
+21.98829951
+21.81676292
+21.76212287
+21.24451042
+18.88245333
+20.13053098
+18.89721051
+19.03870182
+20.44380708
+18.16333418
+21.87783427
+21.67469269
+19.52307029
+20.06168979
+19.86447768
+21.52879911
+20.75440751
+19.11244499
+19.78736502
+19.7158639
+21.83734067
+18.70124364
+18.35830535
+21.52247533
+21.58674396
+21.48695635
+20.04390766
+20.63897771
+20.25345219
+18.2777913
+20.38333959
+18.05445659
+19.29994964
+21.7291703
+19.21618108
+21.75930657
+19.00053583
+19.25824896
+20.51362999
+21.04650789
+20.00555107
+21.52846275
+18.16096169
+21.68877935
+18.7852312
+21.53695498
+19.60345272
+21.33102822
+20.6866622
+18.70376653
+21.67219028
+18.98206956
+18.97656047
+21.25671559
+18.42349302
+18.88814363
+20.01471029
+21.32190811
+18.5899359
+20.19067294
+20.84496237
+21.4423809
+21.74226224
+21.13855966
+20.61131359
+19.73448034
+18.44844062
+20.83894877
+21.97094922
+20.94704238
+18.06684438
+19.98503991
+20.45858653
+20.7586968
+20.87890334
+20.23243376
+18.89344133
+21.76880265
+20.78666587
+18.94736015
+19.28928733
+21.68771068
+21.54994075
+19.62058575
+18.15322889
+18.19398948
+19.13567316
+20.51648888
+20.33677854
+20.53531115
+20.86913189
+18.07612901
+18.42034238
+19.43793381
+18.61943999
+18.30128017
+69.91711579
+72.28857609
+71.43572254
+72.31174099
+70.255649
+71.20069638
+64.89619133
+74.70490929
+63.6910529
+64.11711669
+65.12933691
+74.46452105
+85.17823891
+82.176751
+79.60297393
+77.91137117
+84.90403553
+80.6360659
+84.50221159
+74.75286841
+75.02018478
+83.1053257
+72.16574837
+84.52080041
+79.63887214
+86.30168633
+76.92435251
+82.95461041
+79.24764594
+81.53668494
+79.58954013
+86.94900678
+82.57524425
+75.56497688
+86.03550177
+76.24424896
+77.85214677
+73.54561839
+86.29578496
+76.48589902
+76.05131067
+86.62013253
+84.78656368
+74.16815403
+84.20802103
+86.50459933
+73.16827208
+85.10119579
+80.73933874
+82.68730947
+79.86649686
+83.14488979
+72.52815485
+84.18309878
+72.51609113
+79.26576921
+74.39758018
+85.15674591
+77.00009009
+79.24647299
+78.85622658
+84.35598217
+79.69448424
+84.61927144
+73.17261997
+75.06190034
+80.82066842
+87.14922983
+73.19261213
+72.68585837
+74.50123457
+82.25450166
+78.38313418
+85.20802007
+73.15022817
+75.14190402
+76.7996852
+82.02689392
+82.9619666
+73.98654243
+87.10003918
+77.45596258
+83.40989947
+80.38655178
+75.56398473
+85.53948893
+85.09164507
+78.33699926
+81.41756505
+76.12506497
+83.03746663
+76.94428127
+85.50509558
+75.47801675
+72.23671607
+76.29598218
+75.05681096
+80.13255226
+75.25922377
+84.21100559
+75.86190108
+83.31145889
+81.25550357
+87.779964
+87.99838184
+85.91238434
+84.15970159
+78.1832726
+33.6209646
+34.92271673
+28.94961092
+32.24264789
+30.19518335
+32.37040221
+31.78525527
+32.48491268
+32.32615201
+34.94467834
+32.33398489
+34.21587879
+21.5927937
+22.12268987
+22.26745115
+21.40870046
+21.86145917
+22.84133734
+22.75923993
+23.01122908
+21.73614307
+21.57492391
+22.90004686
+20.75521949
+19.46841697
+18.60455499
+18.72941383
+19.42889768
+18.51199171
+19.43720155
+21.11478277
+18.68229437
+20.22087319
+22.17209333
+21.6731024
+19.68307177
+21.80337813
+19.41131515
+18.37785424
+22.08170965
+21.58319449
+19.95907699
+20.76470048
+20.78419984
+18.86806294
+18.89043542
+19.97373871
+21.75019471
+18.05729347
+21.15030736
+18.24760803
+19.93200482
+20.57122075
+20.76695421
+18.25142161
+19.6933019
+20.35487097
+18.28171576
+18.55817698
+20.67442436
+20.0904094
+18.65089493
+20.14482441
+21.65492644
+18.06581831
+20.57448463
+18.2981143
+18.02925872
+18.60618966
+19.69540732
+21.21344819
+19.1308144
+20.50269285
+19.64462655
+18.93732717
+20.05698846
+21.18985796
+21.32996948
+21.38607813
+19.35423125
+21.17382426
+18.84871382
+20.95370041
+21.79353771
+18.05497534
+19.76145572
+20.59108395
+20.80710308
+18.70435103
+21.8887331
+20.46106147
+18.6573624
+18.08209005
+21.1330568
+18.31881896
+18.56420368
+20.29932011
+20.41402201
+20.74754847
+19.57405605
+21.09559468
+21.8974344
+19.08437977
+20.81211447
+21.71387461
+20.74514705
+20.72443799
+18.89509028
+20.1405208
+20.25009137
+20.80051825
+21.9872858
+18.13457529
+18.26093065
+18.31180028
+20.97191654
+18.54541518
+20.4898075
+19.29867551
+19.82927982
+18.86265264
+21.46442625
+20.3446013
+21.77825305
+20.298385
+18.49563212
+18.68348174
+21.95629591
+20.90226079
+18.197115
+20.81512402
+19.64869219
+19.22883355
+18.61624317
+21.35961582
+18.25536552
+19.15934185
+19.22553158
+18.64362114
+20.03273953
+18.04681051
+19.20390206
+21.73451778
+19.24211828
+19.44183755
+19.89266019
+20.2467735
+21.23483458
+18.76128489
+21.48698551
+21.03019743
+20.89060134
+18.34721829
+18.08656276
+20.3760508
+21.45253585
+20.33776586
+18.85293946
+18.36207959
+20.79838581
+20.88708111
+18.6901268
+18.11276126
+19.63313405
+20.33087481
+20.82400964
+21.23978004
+20.44214971
+18.44352243
+20.73032669
+21.93670657
+21.62233834
+21.48667564
+19.20868061
+21.00315271
+21.40441378
+20.71330482
+19.00224703
+21.81533589
+19.80327765
+62.9653556
+62.69297937
+70.00625823
+67.15285119
+62.4849807
+71.26895818
+72.07082227
+71.06565258
+63.95074794
+70.5809462
+61.34583012
+65.3495251
+76.02971017
+82.80303265
+75.89892067
+70.0149018
+75.30841631
+77.58330201
+84.56855429
+84.44485239
+72.64716507
+72.71347433
+72.3756802
+82.08406839
+71.66377453
+73.59062616
+80.12370998
+75.50522711
+73.03683711
+77.29149991
+75.92899775
+79.69660289
+87.14173108
+73.54494094
+77.49584551
+86.39028972
+85.92673273
+78.21436655
+83.08343233
+73.31762536
+83.3005761
+87.4606448
+80.50309067
+79.87987262
+74.9071014
+82.04204245
+81.3492601
+82.33201184
+72.39995243
+80.76018872
+81.49939295
+75.30240525
+75.31524572
+76.40115002
+83.36753246
+81.68064895
+85.51167461
+76.71212182
+86.57230662
+83.87916276
+78.31642735
+73.52066389
+76.10808524
+87.30410068
+76.96211966
+77.274706
+75.02982129
+84.90553396
+76.40663999
+77.28042234
+78.62579552
+78.93586337
+78.58069826
+80.05913055
+85.03138976
+85.10774361
+84.77219632
+73.61729069
+84.79404682
+73.92331871
+73.99486996
+87.16496755
+85.10954846
+80.83779142
+85.99935815
+87.82966565
+81.77011607
+81.80621792
+84.07067105
+75.71407787
+74.67385441
+84.15313043
+77.51832788
+74.16098331
+77.0378957
+77.73804063
+87.44360897
+83.16732344
+80.49367017
+87.50193662
+86.45020265
+80.19198291
+86.49084095
+78.4688444
+75.68670158
+75.72282175
+82.59701667
+80.0170944
+33.01727908
+33.1908798
+28.94286083
+29.1458478
+32.20913127
+30.02262129
+32.84820981
+32.33398252
+32.54886004
+30.73570853
+32.89499212
+34.10874632
+24.63135786
+23.91622954
+22.6575932
+21.02656342
+23.21287625
+24.36068762
+21.10916094
+21.30685921
+20.82755713
+23.46051168
+21.98139433
+20.44087534
+22.0157949
+20.71622387
+19.78816198
+19.84095403
+19.62086876
+20.29764654
+19.81252252
+20.67638781
+21.60032641
+21.19459316
+19.6380952
+20.59772294
+21.46303501
+18.36053445
+18.40109233
+20.32175869
+20.65513147
+18.93611115
+21.08158868
+20.68386171
+21.79728417
+18.76546068
+21.1063234
+18.42257826
+20.28062035
+20.22697983
+19.57231157
+21.39880773
+18.03477935
+20.09999509
+18.88672806
+20.9941295
+18.18971508
+21.34669191
+21.37286717
+21.35194224
+18.61384728
+20.52556622
+18.06093647
+21.3959576
+20.89591202
+20.12847885
+20.92638282
+18.38082483
+20.11848533
+19.16878567
+21.89468082
+21.43258607
+20.93310278
+21.73499054
+19.38737322
+21.6035196
+19.30095293
+20.93118688
+20.94566765
+18.07339951
+19.44423879
+18.07773069
+21.98836807
+18.48878705
+20.17124358
+21.16222496
+18.80505441
+19.94021067
+20.42971504
+18.64081902
+21.11422184
+19.19734583
+18.84409231
+20.23315499
+19.64125451
+21.68114378
+21.52025079
+19.93340265
+19.4370551
+19.30207193
+19.07025449
+20.17819141
+21.21991442
+19.24302643
+18.76037636
+19.90193522
+18.27613767
+20.80511602
+20.07343307
+19.98549923
+19.20178152
+21.61869375
+18.36194517
+21.47929604
+19.50682081
+21.52249406
+20.91504583
+18.41668291
+21.32614515
+20.72870733
+18.12920765
+18.53481073
+20.54251222
+20.65040201
+20.98660573
+20.8809816
+20.63807982
+21.06495561
+20.30034282
+19.04316554
+21.64950645
+18.07285612
+19.46624688
+20.91548117
+19.70862416
+18.09933763
+18.26392361
+20.59454948
+21.8594584
+20.20745454
+20.02703127
+19.27330085
+19.0267627
+18.08393993
+19.09181947
+19.79644176
+18.79179913
+18.34939195
+20.87091147
+21.57848108
+21.74708828
+20.47199491
+18.21109833
+20.96345052
+18.44038122
+20.67899247
+21.11746334
+20.90345884
+21.80753522
+20.95258514
+20.77283911
+19.04697269
+21.69907475
+18.71817548
+21.61958645
+19.25065017
+18.52065438
+21.30673211
+18.00998181
+21.32835327
+19.04924737
+21.53888509
+20.76591673
+20.66473333
+19.46127825
+18.2376119
+21.32029239
+18.68361518
+19.48903457
+20.40141874
+67.75865084
+63.90178464
+63.11238245
+62.8761493
+72.93690719
+61.62920987
+74.48739393
+63.89999019
+62.70038324
+69.04681451
+62.28780903
+69.39336438
+83.04172553
+70.58337729
+82.25396074
+75.96228988
+72.31529464
+72.57301737
+84.09922572
+71.55660127
+83.29246886
+78.28667652
+70.4461519
+77.04866978
+84.56871708
+83.11752913
+79.34159557
+85.24623329
+73.48228117
+86.03970251
+85.02980098
+82.83243464
+84.57568665
+80.21684182
+82.30578327
+80.48375172
+77.59363226
+81.00445063
+76.02810199
+78.94961337
+76.40061563
+73.87744519
+77.05720995
+85.52903734
+78.00357558
+83.86729671
+74.71340187
+78.6961577
+73.81997606
+74.20012471
+81.85933112
+81.70009635
+75.39585117
+79.57166932
+85.79230358
+74.76927521
+72.29001476
+82.41213859
+72.8384859
+87.65800085
+81.75000035
+79.52252438
+78.87609441
+81.16523442
+73.44646539
+86.87613469
+82.0063366
+74.94005867
+80.9974088
+74.12854575
+72.277374
+82.08433153
+82.37494266
+81.33836447
+74.93501189
+81.65409385
+72.90347517
+81.74702891
+80.86349601
+82.48328545
+86.32678095
+85.60490787
+87.68962524
+87.61901538
+84.35695313
+87.30254633
+85.87637729
+83.64115861
+73.20600752
+72.78465847
+85.40142911
+79.83434044
+85.03354369
+77.00654448
+78.36224728
+83.20282779
+86.64519452
+73.4041554
+85.78361737
+84.68817108
+77.04859875
+77.683436
+72.7433557
+72.25182203
+79.63206744
+73.52860609
+75.10400019
+85.54824234
+32.45457547
+32.85524129
+29.99986196
+34.103429
+34.35506395
+32.14929043
+34.64036309
+34.20689663
+33.4804683
+33.49807943
+29.47451257
+30.53334478
+20.45947442
+20.19889071
+20.86922556
+24.10458126
+21.23463462
+24.50628841
+22.83586243
+21.22291686
+22.38714477
+21.14154365
+24.56820019
+23.95574581
+18.53947386
+22.31409036
+21.38548242
+18.76943338
+21.17893195
+21.0818115
+19.32815847
+21.53859742
+18.7886168
+20.43676722
+18.47264523
+22.39994849
+21.1070845
+18.72485822
+19.45965625
+18.73173226
+21.16758886
+18.32311607
+21.46416238
+21.87327547
+20.80590298
+18.94235069
+19.53367407
+20.00452246
+20.43810084
+20.69450002
+20.23626704
+19.42388472
+21.58437023
+18.34316077
+19.88409463
+21.12251751
+18.2610044
+20.84132934
+21.29927417
+20.66314278
+18.0552135
+18.72414245
+19.37217106
+18.93839561
+21.85480388
+20.61033208
+19.1915679
+21.72296
+20.96640157
+19.14210342
+19.51927326
+18.80132459
+21.88429599
+20.06918598
+21.58422675
+19.38599908
+21.44336641
+18.21554739
+21.92836127
+21.64813747
+19.45281178
+21.09888866
+21.00903171
+21.60501919
+19.22901992
+19.86208002
+21.45999845
+21.11431782
+19.57386688
+21.38290093
+18.18781616
+21.12818521
+18.82706344
+19.14448363
+19.97285937
+19.798938
+20.08228043
+20.17910238
+19.32611076
+18.70091005
+21.07392492
+19.5999046
+20.02336345
+20.57878687
+21.63855169
+20.83021132
+18.1818369
+21.35424145
+21.95742006
+19.8899401
+21.87836135
+20.18931497
+19.83846398
+19.32561906
+20.6302195
+18.91928168
+18.41973687
+18.10894841
+19.16952045
+19.58308333
+20.20830679
+19.1709993
+21.93623829
+19.16698067
+19.76390155
+18.41310466
+19.04250605
+18.19332856
+20.23803453
+21.00425873
+18.78283926
+19.47164375
+18.06646491
+21.35808822
+21.1198541
+18.25301612
+19.45947044
+21.82114646
+19.56810822
+20.10483471
+19.42097144
+20.38452555
+21.9126275
+21.99001001
+21.09885991
+19.61724439
+19.9777288
+19.42692531
+21.94229852
+20.83104122
+19.79572578
+18.04846108
+20.08193366
+21.93571281
+20.09224364
+18.72970674
+18.08837499
+19.41881503
+21.67291222
+21.98621643
+21.7814719
+20.91767997
+20.23257091
+20.36274459
+20.15596804
+20.82819722
+19.67549291
+20.67681602
+18.48644846
+19.06278123
+21.34401216
+21.61499572
+20.15603295
+18.12654247
+21.70789428
+20.80825703
+19.6561117
+20.39351577
+19.71909934
+19.86135691
+73.26061417
+63.39074576
+62.60990024
+61.23711093
+65.47040511
+63.20482722
+64.19180273
+61.35285016
+64.28985764
+65.72487751
+61.62931795
+69.46749609
+78.66778141
+71.34599528
+79.07455175
+85.33910882
+84.49815815
+69.88145382
+82.18427139
+75.32795389
+70.82786927
+74.43365948
+74.83335073
+77.96075059
+82.08187623
+83.48098046
+75.47884199
+76.68543915
+76.47250267
+77.33696715
+87.46653394
+83.94041029
+87.07424836
+82.59123829
+78.02932924
+77.7664915
+79.72151756
+78.57551263
+85.15091607
+79.34470417
+76.63775397
+84.29648698
+85.56792168
+78.63239106
+82.58571523
+72.8533435
+80.37487191
+72.63243457
+72.44966136
+81.78716398
+76.83492131
+83.86046326
+86.31660001
+74.21244352
+83.57230325
+80.21306422
+73.77619746
+82.40569959
+81.7318485
+80.23100981
+86.81937174
+80.33341895
+87.84402513
+80.14381393
+73.85008764
+79.5237227
+74.91366417
+81.55022117
+83.08612648
+79.4911487
+73.55971645
+79.49444646
+73.30256372
+82.91321931
+84.645079
+87.39724621
+74.38011966
+80.51795239
+81.07981951
+86.75879165
+82.0356387
+74.32744078
+78.98086296
+82.47540868
+83.20439116
+85.80901922
+74.88797013
+87.22450688
+72.94609054
+87.74002569
+85.7241089
+82.564206
+83.75976719
+73.16293162
+72.66353829
+73.62811138
+73.39772885
+80.75806872
+75.44707482
+85.76325726
+79.13194758
+83.1281357
+82.44593783
+77.11761901
+75.89065203
+77.47927081
+84.74650144
+81.38039832
+30.4226416
+34.0342107
+29.15045447
+33.27476721
+31.61023909
+33.48025204
+34.73574552
+33.60021178
+31.6285722
+29.76623865
+33.96063972
+31.74850928
+20.49739808
+23.3813669
+21.46749563
+20.37901815
+24.20432322
+22.32429167
+21.41870434
+23.3694105
+24.12884133
+20.16137459
+23.24157651
+23.59621109
+19.29186251
+20.43749897
+18.79771482
+21.49068726
+21.90317959
+18.87513232
+21.77622094
+21.59235116
+19.85295672
+21.25942566
+18.43219689
+22.24864293
+20.29850025
+20.57966591
+20.75779906
+20.3426543
+21.52990536
+20.53691355
+21.7348689
+20.42690721
+18.77417519
+21.75819057
+20.82599719
+20.89678132
+21.96299124
+18.31835496
+19.73329621
+18.97457969
+20.54140669
+21.24762488
+21.88623346
+19.83741007
+21.16517199
+21.68900784
+20.75320569
+18.98914229
+20.43533943
+21.88400911
+21.95442975
+20.57338863
+21.55208824
+18.80500732
+18.98795941
+21.81573827
+18.54450136
+18.76802852
+19.68597338
+20.36224595
+20.41526888
+19.16790403
+21.68245559
+21.66039963
+19.56827221
+19.73716708
+20.80998847
+20.65198359
+19.52918806
+19.65697701
+19.39215577
+18.94154003
+19.83255345
+20.74573653
+20.96786682
+21.11549459
+19.49892805
+21.05854398
+18.02606526
+19.90819975
+21.1756176
+20.52017888
+19.8962525
+20.57856803
+21.62778401
+20.2655272
+21.19914477
+21.9229709
+20.82227281
+20.29330306
+18.14994379
+19.49791159
+20.26177093
+21.18882629
+19.75241916
+21.8402331
+19.08717501
+20.97826878
+19.67612567
+19.94395398
+21.21000814
+19.18486105
+18.38724823
+20.08102234
+20.11517845
+21.18867109
+21.87327682
+18.22120275
+20.3667579
+20.72511412
+21.9432054
+21.77036086
+20.84980306
+20.08715765
+18.64609569
+19.53670622
+20.3404893
+20.90080159
+20.54159823
+20.85649121
+19.71661002
+20.91050916
+18.57496502
+18.65034525
+18.65132858
+21.56345983
+18.30413625
+21.20603349
+18.93428359
+19.87371976
+21.66382638
+20.34374892
+18.84047074
+19.13636024
+21.6817865
+19.7085757
+20.34794193
+19.83972879
+19.51375235
+18.89311651
+20.744766
+20.87296811
+19.09954037
+21.15604337
+21.4181408
+21.68270039
+18.64484966
+19.21569473
+21.44141339
+18.79416081
+18.01387384
+21.48330924
+19.30579777
+19.6579901
+19.7853361
+21.3930984
+19.35156858
+21.56911954
+20.46775655
+20.1091469
+19.30245803
+18.97484679
+20.49623377
+19.78757664
+21.64206404
+19.96655486
+20.04717967
+19.66689312
+71.93397676
+66.97781309
+64.8630512
+72.92361989
+69.31686381
+69.24453899
+69.50718202
+70.97622058
+65.45772465
+61.66028344
+72.22406699
+62.95310873
+81.04264232
+71.11753343
+75.66477771
+70.8181646
+77.94475631
+79.97666719
+72.50064235
+75.60766064
+84.2773169
+76.7058791
+82.29547619
+84.22990724
+87.063996
+85.8549134
+76.61601435
+86.87675918
+84.48833392
+84.88244048
+71.80931114
+86.74421488
+83.94274692
+83.78175506
+72.86456932
+75.26677008
+87.29131122
+79.9148202
+78.27168942
+85.33652621
+73.30936969
+78.57666697
+77.91759894
+77.50450505
+76.83076821
+75.27076587
+74.67685296
+82.14780207
+86.68950698
+80.12239233
+76.74916862
+74.52867199
+85.26182609
+87.52286237
+77.56786567
+76.63680956
+81.60429751
+84.38500643
+79.26741611
+82.06147092
+83.46077878
+87.36528287
+74.63701454
+87.95389791
+78.27074931
+83.56719087
+81.15473443
+79.78286811
+83.16521378
+78.32830166
+74.01420685
+79.81846266
+80.34988256
+75.22971224
+86.96907479
+75.63888421
+78.54688745
+74.47815999
+80.57197284
+76.92146328
+79.82759397
+75.59314496
+72.85970259
+84.46681553
+82.25722261
+77.45168098
+72.7597679
+85.84903617
+74.71657662
+86.89170866
+79.65737312
+77.44603866
+83.8679906
+86.02926532
+77.93126739
+78.51734928
+78.9305012
+86.75713567
+83.08099196
+75.9623087
+74.95996638
+75.68585355
+76.21699296
+75.6829068
+82.53607146
+73.85490781
+78.19770581
+82.00082568
+30.66149795
+29.21775045
+29.32366748
+29.60618168
+34.1493888
+33.0103201
+29.21293782
+31.30283482
+30.58293923
+32.49945047
+32.14595191
+31.87918763
+21.56901424
+20.77734184
+23.48584491
+24.101757
+24.38979474
+20.42261187
+23.47478974
+23.41473421
+24.40304973
+21.29305622
+23.4849608
+20.40472465
+21.01758222
+19.86907245
+21.58145281
+21.96809409
+19.92630675
+20.58480039
+18.91288681
+20.13965069
+19.90983817
+19.18207346
+22.09578418
+19.03856756
+20.64156358
+21.66406126
+21.75178406
+21.27458895
+18.7943464
+21.37182027
+19.19796925
+21.7937021
+20.93636114
+21.24254733
+18.42816239
+20.42864949
+21.30500168
+21.46694991
+18.13191676
+21.77752329
+18.19080135
+20.47771446
+20.79349271
+18.44707336
+18.20951182
+21.15994267
+19.55743962
+18.44614136
+21.05471299
+21.40076044
+20.35345187
+18.64852706
+18.06435758
+20.80720414
+20.2044372
+20.60714438
+21.2568192
+19.74070059
+18.5016135
+21.76411105
+20.18104851
+20.46117648
+21.73364572
+21.72633463
+20.28837843
+19.1904457
+21.98845454
+20.72326836
+19.63374671
+20.23934721
+19.6633362
+21.55322061
+19.9299975
+21.2941135
+21.36070519
+21.29732935
+20.88875445
+21.41951087
+19.54891832
+18.45865282
+21.36981682
+19.99267366
+18.50950413
+18.46125009
+18.63696958
+21.00389304
+20.84342669
+18.81527472
+21.38769367
+19.12517918
+21.17194233
+19.95522363
+20.92619473
+19.52555065
+19.38856239
+21.3654384
+18.14120902
+21.89894779
+20.59271823
+19.72993355
+20.51221812
+18.49096379
+20.05620982
+21.94038209
+18.94107775
+20.8891124
+19.7398855
+20.60983259
+18.81954891
+19.88185993
+21.92037086
+18.7811486
+20.54578011
+20.302391
+20.26020635
+20.46049316
+20.00895189
+18.067723
+21.60038725
+21.30791531
+18.69667072
+19.65309271
+21.08219592
+21.92024926
+21.80454819
+21.5974368
+18.63349559
+21.65790042
+21.51377965
+19.50779964
+19.57809038
+19.83963569
+20.62470252
+19.04334246
+18.09179372
+18.5649181
+19.76046363
+19.12801028
+21.05806624
+18.42676028
+21.6698609
+21.58130872
+21.63502727
+20.95843999
+18.42799989
+19.75255029
+18.52562149
+21.95079677
+19.33215369
+20.34132217
+21.11757222
+21.68246434
+21.0221909
+20.69801512
+19.86392713
+20.42160054
+18.37665524
+21.53569017
+20.17510924
+18.1605402
+21.6796085
+19.9572079
+21.47435657
+21.42755182
+21.26300635
+18.24561208
+18.98826658
+21.50219149
+73.42627836
+67.42973653
+67.18456396
+63.58191262
+74.37038673
+64.09868326
+63.79674027
+70.18591399
+64.50268252
+73.96729391
+61.34833514
+61.27824437
+77.67568796
+77.41472938
+72.37540962
+77.51494362
+76.22898035
+83.65791423
+69.98362084
+84.99170737
+79.5305757
+72.19661028
+70.56571541
+78.19139982
+75.3036932
+76.3577367
+75.46658195
+81.90834048
+80.37132461
+72.80810523
+79.94187798
+84.15108203
+72.85931877
+85.71840868
+80.76538895
+86.68673156
+74.28101517
+87.79156354
+82.20959582
+80.9826113
+80.14818062
+72.29161581
+86.92978599
+82.20514687
+73.37786452
+72.24843244
+72.72516318
+81.65223182
+81.80460882
+79.97547795
+76.88979515
+80.48856181
+80.24156654
+72.2932944
+76.501143
+72.83348123
+86.38173943
+83.58350575
+87.91673764
+76.81629988
+86.05164289
+81.64494914
+79.24620251
+75.55754284
+83.81025156
+86.4621016
+75.76129765
+74.80265466
+83.13555994
+87.62736429
+83.99524965
+76.54961727
+78.71853108
+78.14833194
+85.63269821
+84.34112278
+81.42282529
+76.39861233
+87.00698117
+82.45225205
+87.52678608
+81.28109222
+85.1382668
+85.00886998
+77.39711183
+87.42416371
+72.35092457
+84.29921269
+87.44874547
+77.4223826
+82.36961125
+80.99541649
+84.18395532
+85.8586819
+81.64855634
+85.05431008
+76.99653965
+75.65736389
+78.89065274
+82.84375378
+74.99592238
+82.88560325
+78.30546831
+84.72917185
+72.5893452
+82.68769045
+82.39712575
+87.05493419
+33.36554594
+33.89632563
+34.58937586
+33.12032592
+30.65697738
+34.36654572
+33.58449352
+31.51639461
+33.3473803
+34.35320222
+35.04416691
+34.89504293
+21.61746748
+22.04918663
+20.65072286
+21.26899724
+24.11324569
+21.77660648
+22.94007465
+23.1435247
+23.66259385
+20.97894298
+21.52556166
+22.16854559
+19.92638875
+22.45797956
+21.85191727
+20.3967967
+22.03348403
+19.85598624
+21.65075255
+19.34817502
+21.59543084
+20.3016329
+18.87231699
+19.55128278
+19.70322212
+21.09795802
+18.37973208
+20.73725123
+20.96420197
+20.71464072
+21.14368336
+18.80249526
+20.44608575
+21.86904972
+20.54126409
+20.543483
+20.96586649
+19.35137642
+20.82187342
+21.68573366
+18.06090372
+21.50107339
+18.89259281
+19.84272383
+21.42994421
+21.31609232
+21.5884149
+21.78255836
+19.79242724
+20.62941533
+19.56566965
+19.40659222
+19.73016911
+20.97633122
+20.00960409
+21.26031989
+20.98490223
+18.08538557
+20.52489265
+19.75007578
+19.82651596
+21.27349222
+20.19043194
+21.54248729
+20.85122237
+20.21136004
+21.0181519
+18.1533962
+18.10833462
+18.33339731
+19.7502613
+18.94180058
+21.93704518
+20.16916056
+20.64966298
+19.11528055
+19.28718763
+19.34184766
+20.79494282
+19.89482483
+20.07073461
+20.36801193
+21.07524663
+18.36147899
+21.10749565
+20.25294028
+20.67638178
+19.31020706
+19.63754735
+18.92466328
+21.91719999
+19.98801189
+21.98430766
+19.95914391
+18.87900506
+20.02980959
+18.15838229
+21.61907921
+21.274201
+20.90328208
+20.43930686
+20.31933693
+21.98691286
+19.11198974
+21.11873746
+20.32561908
+21.90352218
+21.31121273
+21.99410045
+20.35329998
+18.81817583
+20.01474814
+20.84444454
+21.09744154
+18.00203996
+20.02010835
+18.94093832
+21.49964733
+18.61162178
+20.665825
+19.06424876
+19.42616857
+21.76223704
+18.9617925
+18.38001105
+18.27713961
+20.01846044
+20.56684593
+19.30917457
+20.76103897
+18.24413487
+21.42933858
+21.26626884
+21.94198509
+21.74601992
+19.42478866
+19.59710154
+20.98385939
+18.53633109
+19.25605884
+18.47416375
+19.8195458
+20.20801712
+18.84464188
+18.10652675
+20.87742333
+18.08002066
+21.89361044
+18.88642903
+20.65560037
+19.73900691
+18.23869544
+19.88873443
+20.06704254
+21.41873283
+20.92939628
+18.3172099
+18.83665073
+19.24755074
+18.46563075
+19.82759628
+21.93723676
+20.05845117
+20.96752867
+20.73175119
+21.39964574
+18.86289396
+21.01530505
+73.18643127
+63.53253359
+65.91651019
+74.39338399
+71.81871471
+65.04323532
+68.86960807
+66.69883527
+67.8635264
+66.0302602
+64.99890185
+70.37677736
+81.92296897
+83.40381455
+72.25072109
+82.61071773
+73.7945088
+76.47226077
+83.830406
+76.89389589
+72.89842605
+72.32116153
+77.18070806
+81.67667602
+87.42755061
+84.09094683
+85.5159982
+83.46152587
+85.80899984
+72.78137251
+86.35763215
+77.87244347
+86.22535261
+72.77245505
+82.94322399
+83.26839386
+87.84503354
+84.20052231
+78.02743388
+80.81887765
+77.77137723
+75.04613477
+75.884866
+75.46150595
+80.68410803
+86.39477187
+86.49970167
+72.78876898
+73.2608036
+75.90368366
+76.06269181
+73.50058243
+78.19664176
+81.38406942
+81.23109507
+80.67550813
+77.4001703
+83.28329818
+85.20328936
+77.52177857
+73.36504406
+76.73760044
+74.19433697
+79.4739247
+74.49138666
+79.40170466
+75.53242055
+83.81567434
+72.43761468
+80.87205882
+74.70822623
+72.01241307
+85.9063767
+82.74365026
+73.58237876
+82.62436468
+81.78557217
+79.57294309
+78.70737398
+86.19228875
+75.92163946
+78.37220853
+77.26510485
+84.33840681
+86.66327851
+85.59634283
+84.76310014
+87.78847057
+83.15415315
+84.01669935
+87.7246722
+72.11171411
+82.14461631
+83.82338357
+86.68506642
+86.14134348
+85.47133808
+87.13262689
+80.59803606
+72.11069384
+72.17684266
+80.7141939
+78.9643255
+79.21989043
+78.40644569
+86.68357966
+77.74669576
+85.69959816
+34.57832804
+31.99680518
+31.66039736
+33.6705254
+33.33101125
+30.90261881
+29.45630235
+30.49504951
+29.63857675
+30.68628067
+30.47565217
+32.8813468
+24.43614087
+23.23213065
+24.31138801
+23.67291122
+23.42089046
+22.01499628
+21.61507819
+23.95132131
+24.21616036
+22.18443235
+20.20060157
+23.71053784
+19.59964174
+18.47250047
+21.72923288
+20.55132827
+21.23862296
+22.17856924
+20.64864776
+20.49308268
+19.62255181
+19.68207371
+21.69463604
+20.27122355
+18.74364449
+18.46632996
+19.98716048
+19.95514718
+20.71277946
+19.97971436
+18.6630575
+20.12736131
+21.73096792
+18.72722688
+20.8586618
+20.47323911
+21.01449747
+18.62025939
+21.7873171
+20.50353021
+21.40881729
+19.00465402
+20.97777089
+21.14440196
+19.60854723
+19.55456818
+20.65099099
+18.3912694
+20.94651756
+18.17503597
+18.76596358
+20.66054109
+18.39682618
+21.89157074
+21.47770776
+20.50914633
+21.28031486
+21.55445785
+19.04155787
+21.4017547
+18.77917513
+19.65336906
+20.23303853
+20.85556385
+18.12056527
+19.16203765
+20.43407639
+19.42947472
+21.10010022
+20.60660864
+18.93760581
+18.58371592
+20.51618797
+19.80186931
+18.67582816
+19.30549682
+19.21218699
+18.43252789
+20.18763608
+21.05459454
+20.30186756
+21.30516546
+18.51027419
+19.74244743
+20.43766041
+20.70400624
+20.78314523
+20.91586171
+20.60571925
+18.37691236
+20.78122271
+20.89913063
+21.97391974
+20.77344975
+20.74732158
+20.05925316
+21.47169163
+21.98733905
+21.11617948
+20.45000151
+18.31581931
+20.90695653
+20.83424627
+21.10227259
+18.49822155
+20.61493
+19.18289562
+21.04108497
+18.96149582
+20.73591471
+19.17997179
+18.03597717
+20.53343165
+18.45307633
+20.63716589
+21.70243779
+21.87698374
+18.94369235
+21.23701291
+19.41421311
+21.60182829
+21.14995827
+18.29568687
+19.62854798
+19.3492713
+21.14072408
+19.64114284
+20.73835359
+20.40974102
+21.90255488
+21.75113983
+19.71079806
+20.89431285
+21.31784038
+21.59554302
+18.27253706
+19.2083152
+19.28092016
+19.7377838
+18.677059
+19.98482352
+20.65285731
+19.98945568
+20.66317238
+18.26576653
+21.50394933
+21.75627677
+20.4716297
+21.52556399
+18.52578407
+21.18979568
+18.47659277
+19.63204093
+19.29527414
+20.3423673
+19.20605814
+20.54925452
+19.46954916
+21.44316152
+20.53553536
+18.86119319
+19.34451769
+21.38968355
+19.545919
+20.14319626
+20.59576774
+19.3912386
+19.17591452
+67.66346668
+64.12238122
+65.06526398
+62.04426738
+65.33399575
+65.56157567
+74.28093106
+69.22031203
+71.90840099
+61.81713064
+62.64889903
+72.27770267
+79.51748901
+72.80404111
+76.1224247
+78.2001972
+82.93282455
+70.77759411
+79.10112993
+80.9683975
+85.01688163
+82.36712442
+74.12704791
+80.85266909
+83.70717148
+83.17371339
+84.61157126
+85.94092154
+73.13342864
+73.23416439
+84.23394542
+75.58173187
+72.49904277
+77.94914889
+84.60732241
+73.58089014
+82.65017218
+71.97138436
+73.6672922
+77.52046921
+73.24963133
+85.43178537
+85.7221379
+83.98822429
+75.78861849
+80.27550686
+74.85707999
+76.40865465
+80.23682321
+83.74011848
+73.49682661
+76.72872785
+86.80510335
+78.84704525
+87.00102952
+87.84132169
+80.40725484
+76.59031807
+84.63211235
+74.53108002
+76.02910018
+84.55401976
+78.93454576
+75.22099621
+82.41405585
+83.72017102
+73.99758778
+76.42801544
+75.53680215
+78.07392633
+84.211076
+83.41532551
+82.5995896
+72.09987657
+74.27357998
+75.57203529
+76.35056056
+74.34211098
+78.5642946
+73.20218661
+83.99954864
+84.6027204
+81.18748763
+73.43457305
+86.24116513
+87.45000536
+75.23767251
+83.27407722
+85.47085399
+80.63734154
+77.17302142
+79.6567865
+80.19614604
+78.41004216
+86.87731309
+83.90196868
+75.86079715
+81.36888375
+83.01899454
+74.24247424
+77.73478203
+86.48873929
+81.07473847
+75.47193496
+73.96452837
+80.29159946
+80.76294056
+77.35060152
+32.83465628
+29.23957638
+29.72888833
+32.29614625
+29.19561484
+34.43780948
+29.70973107
+33.11308084
+31.30369602
+31.35863556
+33.69528651
+31.99655152
+23.41093519
+22.42325547
+22.81621468
+23.56800024
+22.88074191
+22.91795443
+23.69570247
+24.4119076
+21.84768717
+22.74548362
+20.54650262
+21.76744019
+20.11975339
+21.85313179
+20.53485503
+21.42644761
+18.50985409
+20.33456173
+22.12379689
+19.35078954
+18.56111465
+20.20724193
+21.31735248
+20.29348228
+19.93514479
+20.77848037
+19.10883945
+21.1083954
+18.70179386
+19.67700078
+20.72302774
+21.41578066
+21.26772163
+20.98699871
+19.52968014
+18.57796546
+18.8854495
+21.47993621
+21.44989762
+21.82717739
+18.3215264
+20.16657768
+20.61450311
+20.86263842
+20.59520536
+21.10028239
+19.45654667
+18.7357001
+18.82194661
+18.05137996
+19.40501253
+18.37050266
+19.28965767
+20.51677877
+21.58205518
+21.36252262
+19.0143469
+18.53989154
+18.77589337
+21.88814832
+20.19789792
+18.73000889
+21.36298462
+19.58076498
+21.59688861
+19.04270851
+19.57288704
+20.01979105
+21.57046134
+21.47502973
+20.29742028
+18.88710204
+19.61342789
+21.90253226
+20.4310929
+21.12439102
+19.79945878
+20.1280291
+19.71581645
+20.81168399
+21.40588406
+20.02945417
+19.92346983
+19.36114587
+18.70838678
+21.75699089
+19.26431887
+21.20276585
+20.86138809
+21.1636704
+21.74707253
+20.49348304
+21.59180137
+18.67078929
+20.5068503
+21.08910245
+19.08656452
+20.96301521
+21.11390732
+21.32475182
+19.25153165
+20.72642636
+19.21701313
+20.95616155
+19.85189466
+20.3901775
+19.66335993
+18.64793171
+18.71211812
+18.31027563
+20.47229072
+21.39455359
+18.08334731
+18.26495801
+19.82986797
+20.95088294
+18.63083058
+19.08660528
+18.92802481
+19.59620487
+18.89999471
+19.41039471
+20.91417039
+20.44403699
+18.32472682
+20.55098267
+19.90830869
+21.7382623
+19.15721727
+20.90466568
+20.92344329
+18.88600312
+21.6128945
+19.9647328
+20.71553347
+18.58342224
+19.03121567
+20.34442847
+19.27610907
+19.99877167
+19.4960208
+20.56221519
+19.94858145
+18.01843974
+20.59872335
+19.68848623
+19.36679336
+18.37658701
+18.88147876
+18.89508917
+21.741478
+19.7300519
+18.16826339
+18.55526673
+18.3161307
+20.35547756
+18.74648597
+19.99423056
+19.48024825
+21.21550551
+19.28195855
+19.83306193
+20.88514219
+19.73340483
+21.17286214
+20.64673742
+19.64211646
+20.0159277
+74.353967
+70.19791635
+73.50793507
+63.63111565
+67.77201172
+73.55779871
+65.58752404
+74.36023309
+62.52025387
+73.47632792
+67.25488486
+62.20292065
+83.49017512
+73.7501121
+70.18532195
+71.94772628
+80.06946079
+85.01563431
+71.56989241
+77.00943371
+72.64347927
+81.40296701
+71.67227412
+73.56234394
+74.69164051
+80.35527459
+85.4551198
+79.69637856
+72.49430387
+80.52813755
+84.25177397
+73.66981216
+72.72439915
+74.55489489
+83.43375688
+80.97808539
+80.55273505
+75.9004883
+77.22300658
+87.34921521
+75.75898362
+86.32261518
+81.19095787
+73.88397617
+79.38162565
+87.07216734
+78.60261311
+85.71120801
+76.08459443
+81.11528209
+85.48111254
+86.71019962
+79.75402831
+82.21527323
+72.03039065
+76.03332054
+76.44104341
+73.47824917
+76.45676618
+77.11943942
+87.49605662
+82.6936686
+78.8122981
+87.80465655
+74.44814344
+79.6129975
+82.34904237
+72.88579147
+83.46797507
+73.59434495
+74.2409532
+74.55145356
+86.86140335
+82.93097258
+82.48604814
+80.88711942
+76.6841598
+81.9334487
+78.56164132
+74.32594487
+83.03275952
+74.07260358
+75.04997681
+85.08237219
+82.56171502
+82.09570084
+78.69109346
+78.34033788
+83.0440423
+83.83992764
+80.16325732
+87.50813989
+87.29102534
+78.59872093
+85.12979262
+80.69213054
+80.18806341
+72.879397
+81.18356419
+86.40921371
+84.48210915
+84.58104184
+74.55883599
+77.7351613
+75.73124959
+77.05461493
+81.27259829
+77.83651112
+32.38845981
+31.60640192
+30.63433369
+29.41057633
+34.5077595
+28.872784
+28.81057039
+34.09149899
+35.17958326
+33.45345167
+28.89774702
+30.25081164
+24.51376435
+23.78254575
+22.69926206
+21.22113481
+20.22437741
+20.25345829
+22.90167301
+20.25780569
+24.61146169
+20.98155842
+23.3439677
+20.85466641
+20.64422241
+18.76218361
+21.57272417
+20.82783655
+18.78493855
+21.90780877
+20.672588
+22.20684184
+22.18648907
+22.20239964
+18.75060796
+18.92744277
+22.05618714
+20.04616517
+19.04382987
+21.17983546
+19.14861511
+21.00922524
+21.45161895
+21.23851131
+19.1878529
+19.70058532
+19.74733838
+20.06092406
+18.68741411
+19.82889768
+20.06237336
+20.14615774
+21.30003013
+20.08860455
+18.94130189
+20.67234136
+21.20959825
+19.29599304
+20.60098168
+18.60559622
+19.37142382
+21.64105
+21.64938854
+20.30519616
+20.81340125
+21.42017354
+21.83840491
+19.96337799
+20.25019023
+19.66634148
+18.29143903
+19.6949946
+21.16250936
+21.21954199
+21.56950846
+18.20586682
+20.10861836
+18.42969795
+18.80296873
+21.60086601
+19.98716503
+21.03417968
+18.25753642
+19.66730602
+20.69696112
+18.53362593
+19.30327152
+18.25819122
+20.60535976
+21.88356504
+21.30818196
+21.89849247
+21.38241918
+21.42078322
+20.30870878
+20.07300925
+19.62501707
+21.27237958
+18.72827045
+18.22489966
+21.79157529
+18.01511274
+21.90731729
+20.91541348
+19.31399568
+20.79127937
+21.27150063
+18.98144822
+21.08358273
+21.2174785
+18.99741852
+18.16770542
+18.81648914
+18.80258564
+18.26096182
+20.90402954
+19.5198997
+21.53754467
+19.00868442
+19.81292866
+20.55606972
+21.5098598
+20.09848441
+19.49409851
+21.46806031
+19.2409857
+18.3176948
+19.78016843
+21.14037323
+18.12312333
+20.34352898
+20.37785619
+21.71416705
+19.14585927
+19.11534645
+19.76193461
+19.42765961
+20.94538345
+20.56700831
+21.03568415
+21.28016716
+21.69192453
+19.72374693
+21.93878956
+18.86264325
+20.85746065
+20.13603727
+21.26760238
+19.90708208
+21.13575454
+21.72067486
+20.92917706
+21.10437714
+18.26870173
+18.81983065
+21.89721496
+20.77274802
+20.24579607
+19.46790549
+18.177556
+19.47654363
+19.99565149
+18.84583804
+18.69254717
+20.03366621
+20.34361694
+18.95967168
+20.3495579
+21.60135986
+19.89269303
+21.42956068
+21.70908578
+18.36957612
+18.38324632
+19.90417673
+20.35240978
+19.70353386
+19.30580308
+20.56397646
+18.00832605
+39.37012762
+34.07096944
+39.00311113
+33.18490616
+34.11422771
+34.09109065
+39.57230091
+32.43312393
+37.00539511
+38.66174338
+37.24037031
+35.01168349
+42.7931454
+42.28520272
+38.68220657
+39.77489538
+42.86535043
+42.98327324
+38.80661448
+41.92322422
+37.64752498
+38.19501292
+36.57220356
+36.92000721
+41.08996647
+39.92590793
+37.69765867
+39.06638382
+38.82952581
+43.72328611
+42.65721259
+38.94731574
+43.1380873
+38.5861188
+41.17783925
+43.55826717
+39.09093313
+41.40592846
+38.33669658
+38.09999413
+40.56077873
+43.79904949
+39.59337073
+43.46629489
+43.28025624
+37.99967682
+39.18318361
+41.11350269
+40.13794398
+36.76178541
+43.94255231
+42.01450861
+39.49523206
+40.93879714
+36.69471044
+39.95601924
+43.43970786
+43.16590002
+38.69285492
+40.24450276
+41.57773766
+38.71883509
+36.51786514
+40.04225186
+40.81177987
+36.04557931
+36.76342652
+37.65712008
+38.78317719
+40.32711927
+38.34951613
+38.20824781
+42.95451984
+37.1601673
+39.9634253
+43.62231855
+40.99984359
+41.73737672
+39.44964345
+36.15922592
+41.16877947
+41.0551315
+36.88318504
+39.69702365
+43.3225761
+37.64063048
+39.68873924
+39.68877468
+42.48603736
+42.59655244
+42.0741015
+38.92358345
+36.57624858
+38.79581416
+41.43827657
+41.62191932
+43.71999048
+39.62911971
+41.05947415
+40.31351665
+37.20493896
+39.68960962
+40.35867091
+43.60598569
+38.93230247
+43.8407816
+40.33839027
+37.93974423
+22.51998714
+22.2801337
+23.77407575
+21.70524501
+23.73621533
+26.34434027
+24.8165105
+25.24697123
+22.17122398
+23.8708821
+22.97386892
+25.89166592
+19.4741763
+20.62833023
+21.16627809
+20.85841053
+22.17381264
+19.68284481
+20.28994662
+22.01507024
+20.91677666
+20.39280792
+18.84248049
+21.85408293
+22.06383805
+20.64499714
+21.59757411
+20.22804291
+19.07813758
+18.20223049
+20.77850173
+20.13221479
+21.29741964
+20.94495942
+22.12742386
+20.20158025
+19.74023306
+19.17759388
+19.93929706
+21.52587227
+18.1988305
+21.94665873
+22.00838593
+20.42391155
+19.35709868
+18.92242337
+19.13653111
+18.22954237
+19.90681197
+18.23513046
+20.8805765
+19.49395389
+18.80347411
+20.18587164
+21.90204364
+20.78717396
+19.97337683
+21.11441164
+20.95660985
+21.57384326
+18.81988019
+21.43688218
+19.20533341
+21.76538861
+19.12548455
+21.70878345
+21.85656159
+18.58315468
+21.899401
+18.34406582
+18.8754791
+19.77794083
+21.97438946
+19.9542522
+20.20163777
+20.7776998
+21.87317423
+21.1334056
+18.89661602
+19.21196372
+18.39051296
+20.57780946
+18.72296123
+19.02961955
+21.55245462
+19.3070227
+20.26658687
+19.59026404
+18.29612515
+19.45145532
+19.63227281
+21.58280441
+19.29780261
+19.51696448
+21.13158707
+21.0358266
+21.19314111
+21.81508296
+21.18222999
+19.63043281
+21.28603407
+20.03469853
+19.11085613
+19.21166827
+18.89536955
+18.57997183
+18.73796165
+18.2527122
+21.55380346
+21.72403124
+20.34708157
+21.36195823
+18.73428441
+21.6066953
+20.02544624
+18.26865997
+18.56525098
+19.23590584
+18.17423032
+19.23717351
+18.23972173
+18.94411042
+19.06267902
+21.97747591
+18.9421867
+18.9567458
+20.74715587
+21.43742991
+19.54822165
+21.50247208
+19.36056808
+18.78806352
+19.3185553
+20.4374255
+19.46857264
+20.69157522
+18.94774352
+20.80397158
+19.38975345
+19.82347349
+20.23098056
+20.74490001
+18.95485477
+21.34378215
+20.887371
+18.93639168
+21.89989825
+20.65918796
+19.80970755
+18.6301093
+20.13288401
+18.65910355
+19.71796671
+19.63485009
+20.87975858
+18.76953272
+21.28748542
+19.30452931
+19.77595451
+21.0893639
+20.5015696
+19.23210141
+19.5448117
+19.22314726
+20.37908067
+19.33049813
+20.90279078
+20.31914863
+18.58282645
+19.24107447
+18.88578977
+19.56125285
+20.06393634
+20.02705143
+21.01809471
+18.75668745
+21.78589132
+19.37138043
+19.20099539
+20.74071431
+72.15502615
+66.347216
+71.35711886
+73.218809
+71.62852985
+61.6650722
+72.45221719
+71.73294104
+70.30234724
+71.5363049
+74.52018538
+67.06313527
+70.88330461
+76.99301233
+70.56065033
+74.40676633
+78.94837437
+74.6453473
+80.47733422
+82.59722781
+76.36521606
+83.810141
+71.07910021
+82.87855631
+84.74562731
+76.68899093
+76.31876634
+76.42023058
+84.4724056
+84.79461707
+76.81190599
+80.99255689
+73.77759408
+79.02345705
+87.4528015
+74.09417781
+87.05640904
+85.08584986
+87.45036789
+74.78341226
+75.32579629
+72.18315106
+83.49491473
+82.20674848
+74.75922816
+84.55672947
+76.69498354
+74.07093719
+78.7421
+73.43788825
+76.19360764
+77.92262781
+85.60927563
+84.66045647
+79.0650884
+83.57313856
+81.07893056
+77.43488085
+83.59392214
+82.91608183
+81.90157961
+81.88335775
+82.92373135
+78.14897687
+85.90108959
+74.59334488
+86.13803259
+77.47279062
+73.99695383
+81.59652162
+78.01204195
+85.04391333
+78.89181013
+82.69620652
+76.93138928
+75.35051463
+78.20803369
+81.70814095
+82.51035572
+81.25052663
+87.80804853
+83.05664563
+86.90347976
+73.8862218
+72.98182675
+76.97576744
+74.18528058
+80.41374206
+80.30354587
+81.20059876
+83.92348496
+87.54110712
+86.05197384
+73.89373396
+77.41607038
+76.0930223
+74.82904899
+80.71556703
+80.85219939
+75.6358882
+83.39032398
+83.72659664
+72.33565214
+78.33209318
+86.24221714
+80.32506689
+77.56201504
+76.05878922
+30.3574631
+29.43850976
+34.03024255
+29.35460176
+30.67068061
+29.09231914
+33.80086756
+29.05140999
+30.77312116
+32.46909693
+31.42118667
+30.60652895
+21.39284587
+23.73409927
+24.52342052
+21.7192228
+20.33537079
+20.32381357
+23.56127481
+22.63461556
+23.67049381
+23.28478533
+24.22562712
+24.1284915
+21.66098875
+20.37837456
+19.69408553
+20.50878148
+20.48848506
+20.9316884
+19.19425541
+21.11741878
+20.30223714
+20.97235874
+19.41342112
+20.21128124
+18.93124067
+21.60442643
+20.04761298
+18.99064526
+18.25202595
+20.80232879
+18.94909999
+22.06372869
+20.23144849
+19.2478563
+20.72973709
+19.19256387
+21.30152702
+19.25140782
+21.97406579
+20.44018289
+21.39816712
+18.30882148
+19.41181513
+20.97006028
+20.64003149
+18.79499837
+19.44345953
+19.07206524
+20.45740775
+19.38199354
+19.23991032
+18.83312719
+19.63987861
+18.7856165
+21.8544736
+18.6215819
+21.65737628
+19.71767746
+19.51521017
+18.92891286
+20.54302534
+20.74211206
+19.87028385
+18.22282758
+21.6740406
+21.92131653
+19.72417366
+20.45464323
+19.80119451
+19.2875186
+18.30927517
+19.82427092
+21.27353823
+18.06812584
+20.32843073
+21.52308843
+18.87019772
+18.73302346
+21.0891065
+19.02034572
+18.76793707
+19.511957
+19.57000805
+21.49640425
+20.47377389
+19.62384583
+20.13755186
+21.81586093
+18.45285871
+18.83086209
+21.85011483
+21.82929939
+18.70866169
+18.58043527
+19.68434054
+18.19887317
+20.61961413
+18.30998409
+18.23211851
+19.94074774
+21.83114654
+19.70718374
+19.42592463
+21.99182686
+20.12787584
+19.50096563
+19.54344325
+18.77983798
+20.04889223
+19.75542011
+19.08318119
+18.64216035
+19.24495547
+20.03473331
+18.23333309
+18.61497611
+21.79062907
+20.1714214
+18.25379721
+20.77235104
+18.24721148
+20.95549691
+20.99985089
+20.6043159
+20.92881818
+18.35186312
+20.90712221
+18.54675328
+19.35802363
+21.77098101
+20.01150191
+21.86970573
+18.35568984
+19.9102264
+18.24960928
+20.52084105
+18.31482801
+18.70147121
+19.03532124
+20.99497541
+18.65584848
+21.38652821
+18.52761576
+18.1409778
+19.58018168
+21.91776657
+18.44136891
+18.40687378
+21.00466604
+19.24864678
+20.86912647
+18.80004236
+19.84028798
+19.06115951
+19.80611286
+21.07638837
+21.04803976
+20.06308915
+21.71348737
+19.05513641
+18.9612454
+20.4552256
+20.48518814
+18.18616016
+20.43111085
+19.49774463
+20.9897701
+21.23242266
+68.70929195
+61.22318843
+69.85457502
+71.3847854
+64.58617242
+67.51918562
+74.33388208
+65.25437153
+64.23488421
+64.06762515
+68.79969135
+74.11710458
+79.28687081
+74.54757483
+79.75060296
+79.53755246
+79.10427811
+72.31429473
+79.68847673
+76.5161523
+70.12854875
+78.21714484
+85.19341989
+75.26795845
+86.92425381
+73.09805612
+83.21688664
+73.38630424
+75.91888231
+80.64665265
+80.99556825
+83.89696079
+81.35391262
+81.00884826
+86.0780635
+78.7591646
+75.51352736
+74.49911102
+78.30583365
+83.30395923
+72.59347892
+73.97597636
+73.60937798
+81.26636565
+75.79477141
+74.57055867
+81.38655032
+84.0799415
+77.29592319
+81.23177339
+73.55233381
+86.94218535
+77.37176528
+87.93898067
+87.63636632
+84.44090451
+72.30371647
+80.67623178
+73.37176928
+86.30149109
+84.6301176
+87.55324327
+81.73020401
+80.35090784
+80.29972712
+78.1794212
+79.49522512
+82.16265733
+86.92298922
+81.53023577
+85.70974081
+85.80035997
+80.30055192
+77.55876969
+82.23239253
+79.13327778
+73.30235017
+78.04419638
+87.90431032
+72.77549127
+83.14587238
+85.45819887
+82.37882361
+81.11519299
+83.3207107
+78.86933237
+73.46164675
+87.39778026
+78.9166608
+82.64606911
+80.50081243
+72.87462923
+87.24377811
+84.68043303
+74.38542349
+87.70621362
+83.79038978
+79.55711586
+81.7818895
+73.70775861
+80.96655307
+73.17854905
+80.71765312
+80.84309998
+85.99098754
+83.6008879
+75.99280909
+86.21478517
+32.46874682
+32.68082239
+29.88147503
+34.28974443
+34.75817006
+33.75993367
+34.82080901
+30.73471349
+34.31115609
+31.92890998
+29.84906437
+33.08031748
+23.22485754
+21.44542065
+20.28316901
+21.05531457
+21.95100221
+20.91068069
+21.02925301
+21.91342897
+24.46880269
+23.58380966
+21.59247165
+24.42318489
+21.07656901
+20.2975215
+20.35015737
+20.1144091
+19.38633521
+20.01564522
+20.59426334
+20.59479978
+21.55207409
+19.90163578
+21.36800447
+20.79986392
+21.952249
+19.63493713
+21.70856916
+21.38472647
+20.64930024
+20.71702449
+18.42662497
+21.90554268
+18.51619738
+20.35014726
+19.41302051
+19.81406102
+20.46035514
+21.65617549
+19.84930554
+21.97199109
+20.39080465
+18.66011229
+18.77804681
+20.884474
+18.2190647
+19.94049081
+18.61072559
+19.75181809
+21.00370162
+19.83906008
+18.65738596
+19.01135096
+19.47389662
+18.28175416
+20.34125531
+20.43405775
+18.25211144
+19.61301026
+19.65977668
+19.33899065
+20.23095896
+19.38382996
+19.66563712
+21.19009419
+18.64843742
+20.47645878
+20.02237761
+19.22028655
+20.91013863
+20.20475344
+19.90944611
+20.67067726
+21.20916123
+21.89067516
+20.51740147
+21.49775994
+18.00436616
+20.12094277
+18.8585902
+18.37676983
+20.12788407
+20.98730602
+19.64909009
+20.6804298
+19.95887702
+19.74834346
+19.16102656
+19.53037406
+19.39918252
+20.58474874
+18.46407405
+18.37054547
+20.64005198
+20.18519228
+19.72080039
+18.60977154
+19.64410845
+21.15892705
+21.55848494
+20.81030628
+18.2396487
+20.68163911
+18.96394236
+19.26100497
+18.78349283
+21.10302316
+20.59440849
+20.44734022
+20.67189044
+18.94708905
+19.77857766
+20.53301489
+20.54637611
+21.16740745
+19.14841587
+21.08134449
+19.76073792
+20.68069077
+19.82287752
+21.79444068
+18.71720906
+20.70002035
+20.30614
+18.69092416
+18.26402534
+21.19657756
+18.62980533
+18.74602673
+21.9137369
+20.86904341
+19.00194737
+20.36379584
+20.13644735
+21.37789307
+20.91728299
+21.3268845
+18.84602635
+20.56087682
+18.16096343
+18.27576245
+20.85410813
+18.09768041
+20.31906004
+21.36162039
+19.51976723
+18.17936175
+20.8553898
+21.71874581
+20.86868557
+20.31378897
+18.92011532
+18.0615025
+20.77868843
+18.9241047
+21.43265071
+19.86545648
+20.12254233
+21.01574618
+21.11772243
+20.57060333
+21.75372726
+21.92919375
+21.78754178
+21.29671674
+20.82250088
+20.65330343
+18.41500071
+19.08593739
+61.27735984
+63.06877424
+67.17352089
+63.19289709
+73.46262244
+72.15750892
+62.173922
+64.58522653
+72.33937763
+72.12142732
+74.05812748
+74.76664956
+84.99171138
+76.20534154
+73.72509745
+81.61052616
+74.4847153
+82.35533359
+78.12697742
+82.16175131
+74.12165573
+77.72458394
+78.59364928
+84.47703721
+75.80796786
+86.46508976
+84.36847619
+83.19213904
+84.08238476
+81.19667993
+75.44984849
+74.58172798
+85.3462942
+83.10061706
+74.95880091
+81.35044489
+79.06575081
+74.44903654
+80.41310209
+76.41250031
+73.4516581
+79.37596718
+81.34400675
+72.66320196
+78.33936381
+76.03124361
+72.40342096
+73.92178807
+74.20673265
+74.90800573
+84.83367617
+79.01290221
+74.33553107
+73.58708633
+76.74862325
+84.74790392
+77.81267804
+74.54046376
+78.4470271
+80.86557252
+72.46986822
+82.03833079
+78.31785261
+72.15215053
+82.77825684
+83.39419906
+82.05749767
+77.46716488
+80.46981493
+78.19076996
+83.20595361
+81.33337879
+73.30808206
+82.28870695
+82.99501787
+77.93048675
+86.01174677
+85.48740899
+74.80194628
+86.46743084
+79.05319903
+83.57919207
+85.02473587
+80.08102995
+78.38548053
+86.64705554
+75.69351152
+76.11137511
+77.78577568
+85.7512878
+87.02044515
+75.52093844
+85.82175758
+76.13110118
+87.53009189
+81.55836968
+72.11335579
+72.54605061
+74.35972394
+75.00114172
+84.2818736
+75.56422501
+87.50623232
+82.17776136
+83.08024825
+75.48503532
+86.28326789
+82.68500141
+34.3321894
+34.92147232
+29.60409657
+29.41815263
+33.94180357
+34.34320018
+32.53606685
+31.14239753
+32.97682334
+30.75624416
+30.32566261
+31.92412321
+21.12836799
+22.32699094
+24.4455958
+23.92223117
+24.37850518
+23.7723525
+21.749283
+23.79796136
+24.2946612
+24.40271899
+23.2207251
+21.10692141
+18.59473039
+19.03493191
+22.38687991
+20.32474835
+21.93402245
+20.33682061
+21.13870857
+18.5308804
+19.45544657
+20.21895873
+21.01506452
+19.13455056
+21.15928519
+19.55101535
+21.37183578
+18.48015732
+20.81847763
+19.26534519
+21.283204
+19.70280333
+20.76057319
+21.84155968
+18.16930252
+18.13108053
+21.10135487
+20.60533435
+19.19032391
+19.99676528
+18.18518369
+18.7878014
+19.71689555
+21.35666039
+19.93779064
+20.36498164
+21.51565037
+19.25374151
+20.80679142
+21.45078679
+18.81407441
+19.42964243
+21.92344919
+21.93708537
+18.89654716
+18.26929038
+19.08735051
+19.59468929
+19.76781709
+20.47915647
diff --git a/test/data/Timeseries/period_no_anomaly.csv b/test/data/Timeseries/period_no_anomaly.csv
new file mode 100644
index 0000000000..ef5a04acdd
--- /dev/null
+++ b/test/data/Timeseries/period_no_anomaly.csv
@@ -0,0 +1,4033 @@
+Value
+18.32491854
+21.97032718
+18.62480603
+21.95368398
+21.90911973
+21.17527242
+20.63769185
+20.3112282
+21.46440618
+19.15775809
+19.87072485
+20.47755988
+19.6447619
+19.70994582
+19.32113867
+20.25692727
+21.40229811
+18.80611351
+21.73773216
+20.75635062
+21.29309285
+20.22476277
+21.11806681
+18.06480159
+21.2735217
+18.16055544
+21.55965351
+21.96785099
+19.17626985
+18.84127423
+21.06145346
+19.01210536
+21.46224953
+18.41137037
+18.50382079
+21.91660622
+20.69535559
+21.3875489
+19.29731751
+20.705935
+20.37696731
+20.41260048
+20.73012984
+20.30143669
+19.71624948
+19.10369078
+21.07432532
+18.90508972
+20.76941722
+18.93333129
+20.50132068
+20.98831307
+18.87485556
+18.2397732
+18.52389497
+20.42398787
+21.39778562
+18.17998728
+20.93660504
+19.36527458
+19.91411348
+21.7154382
+19.32788602
+19.86134774
+18.05472966
+18.32639488
+19.03436636
+18.11140896
+20.5255013
+19.70559343
+20.19258081
+18.69858874
+19.18372812
+20.6552979
+21.86121089
+18.20166709
+21.56153728
+20.30752481
+20.25567827
+20.00111414
+18.27757634
+18.35950741
+20.40364802
+19.36383429
+21.66907227
+19.62636215
+18.57312583
+20.85887533
+19.17341369
+20.10188123
+20.79133114
+21.60105644
+21.16876478
+20.70544427
+20.71853273
+21.78369858
+19.18329639
+18.00444838
+19.08781824
+18.87156552
+20.64733834
+20.5348464
+20.37384553
+18.06497377
+20.91511222
+19.29412165
+20.66022396
+20.22631371
+65.86114059
+63.03023723
+62.48409701
+72.50864933
+73.69020657
+70.03711744
+62.60670396
+66.66757015
+71.11357312
+71.80556402
+62.80777326
+61.20041778
+80.89236695
+75.37437265
+73.78955027
+70.04016873
+78.22544679
+83.04985941
+84.70244315
+78.62036163
+77.82443981
+71.1600751
+78.35850588
+75.73727531
+81.22387951
+77.75030384
+75.38971726
+73.07832774
+76.57646294
+73.10503944
+74.38136911
+87.27059427
+78.63102297
+80.02688857
+85.46202908
+87.40152779
+81.22584307
+84.89758164
+77.13837912
+76.79963304
+78.34912762
+82.66080406
+82.81556895
+76.95137836
+74.04240116
+82.0197981
+73.96434994
+81.15837308
+83.07481131
+83.18981359
+84.03538044
+85.94511896
+79.98014403
+83.66390288
+81.88710614
+74.96824234
+72.39365567
+76.53428953
+79.06955805
+81.85404542
+85.59524052
+75.13632475
+74.00524422
+87.41148321
+73.72517397
+79.65203364
+81.36511395
+80.65811896
+73.37299244
+72.90893083
+73.68419783
+81.36549721
+80.70874339
+75.73912557
+82.20359711
+85.12026287
+72.66456577
+79.96931138
+83.02816952
+76.03626088
+76.92359601
+81.81742099
+86.36613557
+84.95797512
+81.32992735
+83.68338681
+77.83701008
+82.25529052
+79.4587529
+75.03883411
+83.22765258
+80.90327886
+77.73779605
+86.5812608
+72.334807
+77.05222248
+72.91007437
+84.2644047
+83.2336873
+77.30160582
+82.81057464
+78.33496554
+84.10002837
+79.26690817
+78.59644546
+86.95564526
+76.01403641
+73.92712905
+32.54106968
+35.00365288
+31.21816497
+29.19702968
+30.97154776
+32.03795644
+29.83630151
+33.01184786
+35.18558933
+31.69112656
+31.0702568
+31.36450065
+20.67585375
+24.11706441
+22.01841773
+21.89498816
+23.11541115
+22.14030851
+23.06408468
+20.43527826
+23.80547927
+24.37345637
+23.06646766
+24.43645402
+19.05226653
+20.38749647
+20.89700013
+20.81479306
+20.07638721
+19.8167935
+18.95147097
+20.03657684
+19.09825847
+21.43996155
+19.28737128
+18.67188327
+20.30646993
+20.47874729
+21.59079292
+20.40540445
+19.4749566
+21.3138653
+20.25788888
+18.40504328
+20.36066652
+21.73590808
+19.67925966
+19.27739262
+18.59170874
+18.62364363
+19.75002777
+20.4022867
+18.34005117
+21.77916229
+21.04071417
+20.3660283
+21.33421588
+18.33833494
+19.92646656
+20.54007206
+21.31870403
+21.13793594
+19.11194579
+21.76769927
+18.50093486
+21.50466258
+21.88796268
+18.71220615
+20.8922748
+18.16462901
+19.62545866
+20.0689857
+20.3225809
+21.74374899
+20.68900275
+19.9251118
+21.23870015
+21.80213128
+18.08826459
+21.93008509
+18.34452856
+21.25754712
+19.12133901
+18.52871863
+19.75942256
+20.57582632
+19.52380738
+18.21826163
+20.39784456
+21.6096131
+19.53286146
+18.86533111
+19.77030938
+18.19345084
+21.28195034
+21.30536324
+20.35200185
+19.41241156
+21.19913346
+20.2187481
+21.30372923
+20.52583517
+21.13762189
+20.39425197
+19.65656427
+21.83178344
+20.1644553
+20.42035807
+18.88195056
+20.50260316
+20.2864306
+18.73935359
+18.23834839
+20.41743728
+21.05476908
+20.09360548
+18.9070905
+20.66608791
+18.32042291
+19.76733482
+18.65346703
+18.7378362
+18.8091758
+19.54682823
+18.20460082
+19.59117376
+20.04682979
+19.93317714
+19.5311364
+21.35658643
+18.58130677
+20.02278698
+18.24816567
+18.28462272
+20.2954634
+20.2640737
+21.51213405
+20.2314947
+21.83916408
+18.19477939
+18.39203074
+18.17626345
+18.7411074
+20.16508044
+20.58228873
+18.18234063
+21.78388356
+21.36866151
+19.18644993
+18.30875012
+18.67954829
+18.50777766
+18.49313512
+20.07424675
+18.98338977
+19.43255887
+21.95802133
+20.737257
+21.79592267
+18.57022622
+19.5285579
+20.21892721
+18.30703225
+18.01674977
+20.68173734
+20.56727807
+19.64315524
+19.9585763
+19.661772
+18.09602018
+19.34148642
+18.70832902
+18.39369676
+21.82688174
+20.3974389
+20.91462514
+19.26145497
+19.57258852
+18.94769598
+18.38786268
+63.63483027
+72.04619102
+70.41462295
+68.63823271
+67.66122227
+73.74510626
+62.18919529
+65.01617106
+65.95915481
+71.84099105
+74.69819883
+64.473119
+83.40924983
+82.73126524
+73.32668281
+76.03764164
+76.19812293
+85.02198478
+72.64744231
+82.24293171
+75.02667092
+81.18310777
+76.35857079
+78.81614352
+84.80985764
+84.35744915
+85.34759431
+72.51615394
+82.574372
+73.79435924
+78.18117851
+80.29275015
+77.97316877
+79.83190409
+87.41675442
+73.71849616
+82.70792797
+78.24201224
+74.03920299
+74.45034047
+87.08374366
+85.9703356
+86.40885616
+87.75908698
+75.24264658
+77.59380496
+82.60825547
+79.64515163
+78.67534592
+77.70632599
+81.48092999
+81.19000458
+74.56542535
+79.52874592
+80.83614309
+81.10512112
+75.34362828
+83.85621195
+72.38580875
+77.65866713
+84.47934717
+81.01839767
+76.17494235
+83.11526019
+81.07436335
+84.73583024
+83.75638248
+81.75780219
+79.80701188
+74.12735573
+76.17767158
+78.7018137
+81.58800534
+80.21855558
+76.61021695
+72.10273753
+79.93906013
+76.56928074
+83.75292878
+72.38244537
+81.35646395
+87.06275199
+74.78983028
+79.54562821
+73.46261082
+82.01075314
+80.80835174
+78.51769763
+80.34187809
+86.34502875
+75.14056457
+72.36089325
+85.78647344
+81.23371735
+86.25036969
+81.550967
+84.96254481
+78.87474353
+83.99772665
+86.60863021
+81.15393626
+74.89253365
+76.30073254
+75.17828436
+75.94968328
+76.90261766
+80.88210953
+81.40783481
+31.52959233
+32.73868671
+29.32207389
+29.36183908
+29.89970281
+32.11568982
+30.16956015
+30.6130143
+31.36199613
+33.99593667
+28.88871212
+32.95601812
+23.15656559
+23.73797659
+24.33873183
+20.25021645
+20.84894986
+24.13004607
+22.21416194
+22.68936482
+23.1303606
+23.20221712
+24.33419567
+24.62633204
+21.3817647
+19.60845784
+22.03546558
+18.63360864
+19.37850694
+22.10769163
+19.48136021
+19.33578651
+18.99776097
+21.9509215
+20.48023838
+21.19636231
+19.04725556
+21.13311601
+21.14101423
+19.34279393
+19.73701559
+18.92918712
+22.01139401
+20.68120583
+21.84251871
+19.30576713
+21.22897591
+21.16453901
+20.78655856
+21.88354394
+19.59301259
+18.54065124
+20.70669479
+20.93731974
+20.31973052
+18.84534574
+20.03704087
+19.26723775
+19.72878757
+20.60063193
+20.98488729
+18.93253311
+19.62506873
+19.080309
+18.798135
+21.13760652
+21.64116508
+19.48466908
+21.00914868
+21.59212605
+21.38860266
+18.73484995
+21.82516753
+19.50670576
+19.35696264
+18.24972531
+19.94469462
+18.43605446
+18.99415928
+19.26777049
+21.23530529
+21.5019546
+19.20986527
+21.43479249
+21.42892375
+21.0586038
+18.58678046
+20.76129139
+21.78009626
+20.73016192
+19.3264674
+20.00231727
+20.58290017
+20.04228163
+18.47981177
+19.24825618
+21.20958412
+21.44567218
+18.54920013
+21.80954701
+19.31529047
+20.64925495
+21.00730058
+21.24778494
+21.78299881
+19.25167819
+21.43402582
+18.52674761
+20.82016363
+20.96791092
+20.71089296
+19.00925894
+21.49217259
+18.67543385
+18.21453917
+20.86985996
+19.90190286
+21.39639208
+19.53358856
+18.67311435
+21.34576877
+20.19563853
+18.75678317
+20.88153599
+20.04445455
+20.41725193
+19.84359335
+21.31483594
+21.31825086
+20.83755529
+18.42160551
+21.35541545
+20.68405192
+20.78809666
+19.45193136
+21.51711822
+20.9014864
+18.45036187
+19.63111214
+21.54552145
+18.18878681
+21.84566648
+20.71665027
+20.52550391
+19.08223703
+18.99516716
+21.76823288
+19.19308982
+21.10202119
+19.57248719
+18.55701628
+18.04286119
+20.17702935
+21.90311527
+19.47654478
+19.42876934
+19.37636647
+20.08217535
+19.76265953
+21.51965851
+20.02208317
+20.03103135
+18.55348638
+21.93095816
+18.99989156
+18.29345627
+20.652585
+20.38146548
+19.66058262
+19.68876894
+21.14025568
+18.78285056
+21.28101328
+20.59498846
+19.6758791
+19.83211447
+19.02658883
+21.00845733
+20.05149897
+19.28341817
+69.30628157
+74.74198855
+67.119567
+73.72140305
+65.89222902
+61.94436481
+63.97769265
+66.89425395
+64.18703503
+61.20308772
+73.64402091
+72.67675999
+81.36037543
+72.44448252
+71.7080427
+70.88922571
+81.07693301
+84.25509955
+76.52191594
+71.68906323
+77.79233658
+75.2538712
+75.65728283
+79.48305129
+82.99849287
+73.32703964
+72.13402703
+87.38182913
+75.26931166
+72.42412067
+74.58777723
+72.18758559
+77.79936047
+84.32939798
+76.99515173
+78.6322929
+82.71001711
+80.04613436
+85.68019122
+85.75354292
+72.07198084
+84.34740241
+79.27649152
+87.71606292
+79.63603516
+87.68498672
+83.97222205
+75.88650494
+80.59497223
+87.85308043
+85.69991681
+73.54021641
+83.28195948
+77.51066635
+72.09440938
+78.43686614
+75.73788929
+85.08148387
+77.37871439
+85.21992141
+72.00611056
+76.921414
+75.85500221
+75.7334424
+73.08747755
+74.99038862
+80.88491046
+76.6580974
+78.67453996
+78.02612465
+86.01035011
+86.48063271
+79.88654463
+77.28175329
+73.70810366
+87.25360843
+72.96293067
+76.76166752
+76.76832224
+77.12568016
+74.62787306
+84.5297714
+73.95925578
+82.15771782
+73.98139438
+73.12842979
+86.55070588
+75.04191618
+85.139839
+80.71393897
+73.24556368
+87.28700347
+75.95123285
+85.75416088
+74.70081667
+85.66292164
+72.21163328
+80.18845651
+84.3110489
+86.95669489
+86.54720095
+85.11396523
+86.21102849
+75.1874861
+76.54691934
+76.62346698
+78.03283293
+78.29310066
+32.28514788
+29.82322476
+33.22397227
+29.87242012
+30.78596837
+32.02140269
+33.89721309
+33.53259665
+32.93141356
+29.79694315
+32.30108401
+29.35965197
+21.85058583
+22.01255285
+20.33835413
+21.38746551
+24.44130827
+24.43227274
+21.73842401
+20.35308737
+20.96234418
+21.91713451
+24.40605171
+20.79257066
+21.55936064
+18.87716345
+22.45123077
+19.99510094
+21.60736041
+19.83525284
+21.00293147
+19.21849765
+19.03010187
+22.27431045
+22.19068298
+22.06707251
+20.60014207
+21.33499154
+18.36387321
+19.43198407
+19.34723555
+20.64118563
+19.51706544
+18.68327841
+20.48372042
+21.3595718
+19.6222307
+18.61801437
+18.80478806
+18.96812515
+19.21802197
+20.59092861
+20.42336956
+20.80427238
+19.46867994
+21.31643475
+18.83441433
+19.8952441
+21.22411048
+18.73860639
+18.44299283
+21.53887054
+19.37543802
+20.73946171
+18.10486988
+20.76417351
+19.26810401
+18.22646222
+20.44317538
+18.9668562
+19.55098203
+18.32584113
+18.588653
+19.19190894
+18.359038
+21.64330506
+18.02418817
+19.93544088
+18.49298983
+19.23071636
+21.70423824
+18.64677821
+21.86332928
+18.82317751
+20.96626443
+20.18670906
+21.53791491
+20.21597302
+20.13823688
+18.781832
+18.66491745
+21.6659566
+19.3113528
+19.48832902
+21.03929463
+19.35529393
+21.80824979
+20.95171108
+20.38971697
+21.52358064
+18.19842363
+19.02825077
+19.86014534
+18.90791416
+20.97562075
+21.67683212
+19.69508048
+19.3685304
+21.84620293
+19.77940973
+19.9561936
+19.40659949
+21.63819389
+20.27582193
+21.04869835
+21.24722687
+19.36739617
+19.73477733
+21.3938871
+19.45302141
+21.17574053
+21.76396929
+20.49284149
+20.96650915
+21.22038925
+21.3801586
+19.58021335
+18.20505384
+19.60750508
+20.69502492
+19.80140154
+20.9958526
+19.42792972
+20.53897656
+18.74567922
+20.99747775
+20.18278388
+18.81625755
+19.16764469
+20.99443483
+19.93040494
+18.86412576
+21.86908476
+20.86050008
+21.82853933
+19.70842018
+19.90040136
+21.59182086
+20.10019736
+20.82911565
+19.00869151
+19.78690587
+18.49379946
+18.82392014
+18.00377366
+18.15706021
+21.90913529
+18.96941478
+20.65324284
+21.3563988
+20.20264184
+18.612578
+20.91246575
+20.40100564
+20.92500236
+21.07898649
+21.90164147
+20.29425312
+19.36656445
+20.59385823
+18.27376284
+21.58958927
+18.47752405
+19.31137135
+21.26298152
+20.38924951
+19.57454208
+19.89374264
+21.41818957
+19.36001754
+73.02723571
+62.39862826
+71.76445875
+72.72664781
+63.67272008
+67.05271284
+63.45079694
+70.80981615
+68.48072965
+69.84039752
+63.87222275
+64.07974372
+70.48403849
+74.83848815
+78.52723714
+83.15514987
+80.19071398
+76.59735094
+84.63242418
+81.00268551
+84.27616395
+78.02816535
+73.85819434
+70.65987017
+83.11565348
+73.49720288
+76.38333564
+80.03641732
+80.54448141
+81.11967516
+74.21212477
+77.60734369
+81.38385699
+86.99199922
+83.14024561
+86.24109015
+84.09435846
+81.36971054
+74.98228706
+82.56777007
+81.87570417
+81.54153932
+79.74077
+80.36195546
+77.25825914
+80.21263228
+75.07070142
+84.78093101
+74.95443789
+73.34185437
+78.96098124
+82.51311113
+78.98450837
+76.40972338
+80.91131556
+77.53342488
+86.90502083
+86.74149928
+80.01874001
+77.22760483
+83.79009651
+72.5839229
+79.59248347
+77.37746001
+86.72441119
+72.18858322
+80.84115745
+83.84659247
+79.75645931
+73.36292689
+87.55517939
+80.28431307
+81.82619437
+75.78502898
+79.7352039
+78.86563475
+73.19763077
+73.69785815
+85.39874048
+75.8363912
+75.1186112
+80.07781447
+84.29914482
+72.99044358
+81.22877075
+73.90722518
+72.58323745
+72.84376337
+85.34646187
+73.88741787
+72.7222822
+79.0062465
+85.50373138
+76.19838772
+78.74725069
+72.63862105
+79.18522582
+81.24177809
+81.1344817
+77.31879738
+77.0485013
+73.7059496
+77.86874323
+73.59188644
+84.26550276
+87.46035518
+87.5211577
+85.84110463
+32.64506349
+33.28553407
+30.62531126
+32.83692438
+31.71615103
+31.88490485
+33.64976353
+30.6042716
+30.83544759
+34.7177008
+29.15982989
+31.90805338
+24.24934626
+22.89442502
+22.60790245
+21.27885276
+21.697873
+23.97717559
+22.66529599
+22.4660438
+20.60611599
+20.23180503
+24.4773083
+21.84889683
+20.90276045
+18.75851271
+21.23003586
+22.25179297
+20.78992463
+18.94856813
+20.81473113
+21.57095793
+20.09668189
+22.03581515
+21.08900512
+22.1153233
+20.5923925
+18.61407257
+19.33111288
+18.89745421
+21.73915541
+21.1425999
+20.80498027
+19.29604378
+18.8261127
+21.12672816
+19.99213557
+18.99389332
+20.48613573
+18.17877028
+19.3232135
+19.89330723
+18.60968149
+21.95967897
+18.85447238
+18.53919307
+18.83220106
+21.09647772
+19.72093657
+20.28111495
+18.08750876
+18.14120768
+19.78710059
+21.27070416
+21.54509138
+18.35034886
+20.15732187
+21.6570761
+19.55564498
+21.32235643
+18.53834129
+21.74575234
+21.00569327
+21.76533757
+20.70646893
+19.45361573
+21.75272469
+19.10226711
+19.32869009
+20.80323367
+21.0612652
+21.71761394
+18.81920964
+21.19199214
+20.95418421
+18.25517823
+19.54889256
+19.13106183
+19.2179617
+21.93178752
+20.57110965
+20.87070463
+21.90647055
+19.50880713
+21.20736067
+19.73812385
+21.47813469
+18.72263017
+21.79074471
+18.87508683
+19.30488203
+21.02476894
+19.57502057
+20.43284551
+19.778294
+20.96947975
+18.91332501
+18.23383195
+19.19971759
+19.89723466
+18.67208021
+19.41918916
+19.59993207
+18.22956737
+20.33322899
+21.53737371
+18.60697165
+20.39123205
+20.65895682
+19.67733872
+20.80439035
+19.64292617
+20.01854915
+18.02941218
+20.76688046
+20.64537072
+18.15360351
+19.47300043
+21.91612736
+19.68294625
+20.00778162
+21.63972063
+20.8690475
+20.32828052
+21.19121873
+21.45746507
+19.82755229
+19.90043346
+19.54420374
+21.86682456
+20.78866502
+18.33289226
+21.45183849
+19.92223976
+18.27501563
+20.19886902
+19.66865712
+21.51099762
+18.81597841
+21.30585844
+20.23075476
+18.21844121
+21.88738121
+20.05046098
+19.16350742
+19.87762737
+21.43143113
+19.2196125
+18.77070559
+18.51628499
+19.19143759
+21.12019235
+19.88650546
+18.90992641
+18.66474
+19.33091791
+21.75969749
+19.37210685
+21.9524963
+19.94092182
+18.71665567
+21.56456037
+19.84142149
+20.83868537
+21.93484633
+18.2007014
+18.38677824
+20.88182697
+19.12730001
+18.73720559
+61.73532157
+61.49711528
+71.7330042
+63.02829461
+67.56100038
+69.44019669
+67.02558449
+61.56865047
+71.85562044
+61.34297985
+71.56170256
+73.34894112
+76.55767557
+78.15161918
+77.24278225
+75.88051776
+83.61282879
+83.71384809
+75.05186998
+79.38588258
+84.22560536
+84.7711479
+77.73904431
+76.86784098
+76.0003544
+86.81789827
+73.8393187
+80.78960958
+76.06167945
+76.00534785
+78.00862041
+87.45280285
+72.44218414
+80.76912908
+72.8812276
+74.02549928
+78.93816746
+80.07116127
+76.04930972
+76.97083812
+73.30340256
+76.75929472
+87.35997711
+87.01077973
+77.26522298
+81.03630258
+86.44966203
+72.01242243
+84.9505441
+87.15299111
+73.44358106
+74.56526302
+87.35097158
+80.58129814
+72.20981164
+76.10384267
+79.180091
+83.06660181
+83.71047071
+87.90564179
+76.59650238
+80.60765228
+80.52931117
+78.48655662
+74.70300439
+87.63509832
+85.64896364
+79.96948973
+81.64800747
+75.63254632
+80.6967195
+83.11553239
+80.24190212
+87.84371942
+81.7806814
+77.93483122
+84.35362264
+74.7266828
+78.15150276
+77.55059871
+78.908156
+84.50766593
+79.74600295
+84.70341804
+81.2236665
+77.47296221
+84.95949678
+75.81248917
+75.58998254
+80.07189305
+76.17344168
+72.14525404
+82.37260228
+80.1773472
+79.12813311
+87.47132829
+81.13915579
+85.81487229
+74.23117527
+81.10727226
+85.88764105
+81.32966089
+83.48819479
+77.95266715
+73.47916406
+79.32637426
+78.31164018
+85.87292994
+30.36156411
+34.98709234
+34.93207726
+30.38483668
+31.02752656
+34.53155011
+34.9863755
+31.63800418
+30.85437517
+32.16699551
+33.20171655
+30.55023103
+23.45939854
+20.39142384
+20.38083821
+21.89056772
+21.74355871
+21.57403562
+22.35976731
+21.59688526
+21.02131432
+21.5464224
+24.5275698
+22.0017869
+20.25354329
+20.79352803
+22.45976352
+19.4215986
+21.22253127
+21.36467305
+20.91960056
+18.79481665
+21.20446859
+18.69453171
+20.87380004
+21.46132424
+18.93433014
+21.46904712
+18.20839797
+21.47785261
+19.93655447
+18.9609294
+18.62408107
+21.91793211
+18.37845748
+18.88659623
+19.48436753
+20.57924785
+20.19857637
+18.52033643
+19.17730448
+18.97320388
+18.87227141
+19.66343613
+20.83610928
+18.88792674
+19.48540356
+19.58245082
+21.9268557
+21.83961134
+21.20462083
+18.97027728
+18.27565751
+19.27131593
+19.07083909
+20.02754775
+21.11496493
+21.43740695
+21.3835612
+19.44243447
+20.75292117
+19.25503304
+18.24362217
+20.80626106
+18.03931021
+19.63673035
+19.31751708
+20.77351015
+21.06498189
+19.21637854
+21.24650806
+19.17566704
+19.78530544
+20.90807411
+20.77168092
+21.94947389
+18.9006441
+20.64927165
+20.43872763
+21.66039382
+18.62544857
+21.00719265
+20.27307447
+19.09866348
+19.89773966
+19.33510639
+20.31725361
+21.55600244
+20.27721994
+20.52688967
+20.07499139
+18.20466203
+18.93143423
+19.96800692
+19.24094114
+18.72705439
+20.01653137
+19.29123917
+19.03243057
+19.85594167
+18.53313703
+21.71098293
+21.47080839
+20.83048234
+18.42485531
+21.10350902
+21.23182931
+21.07105847
+18.45586355
+20.57563183
+21.33729918
+20.3094136
+20.5856295
+19.83345392
+20.11482928
+18.13750743
+20.55585209
+18.32578885
+19.74005838
+19.17062039
+20.1817118
+18.53366534
+20.76657361
+21.18004615
+18.6534178
+18.41725235
+18.58206193
+21.50851025
+20.11275705
+19.86904398
+18.42684728
+20.59822403
+21.47199837
+21.31274348
+20.50421884
+18.30111487
+18.44958811
+18.19723595
+19.02991687
+18.54264587
+19.04019216
+19.54023222
+21.77193114
+20.44150424
+21.33989514
+20.841406
+18.45001252
+20.94368163
+19.10039553
+20.55643139
+19.36384789
+21.99068905
+19.05420592
+19.11652188
+21.72268902
+18.09857762
+20.78675595
+20.90130556
+21.34551431
+21.89775724
+21.90240768
+18.26110703
+21.28735729
+20.58523973
+20.58936854
+18.51339971
+20.60074867
+21.92993032
+21.64727428
+19.75652264
+61.74329244
+66.12719146
+72.43890824
+70.74038778
+67.44707372
+61.94938088
+67.0057683
+67.57873918
+73.82835525
+69.91877101
+65.43847967
+68.3443284
+70.86517838
+84.93425902
+75.42812968
+77.25650135
+75.35400728
+80.43258205
+80.1178431
+80.94180226
+74.00158292
+74.73917483
+71.78389911
+80.01351476
+72.20093351
+81.07353986
+85.39964335
+85.73579449
+78.70949654
+78.87276586
+72.79211789
+82.23584696
+84.62930982
+75.45899399
+78.26836922
+84.90890081
+85.93068677
+75.79981063
+80.7121592
+74.98979454
+73.54170415
+86.47403451
+85.02596632
+84.05956576
+72.69292479
+85.39706109
+78.91389477
+77.38534799
+80.72424331
+73.44402109
+84.08615927
+81.29944468
+74.96744504
+74.99371238
+74.92999091
+72.89453931
+81.38523804
+85.4250639
+72.26262423
+72.76660614
+81.16042854
+85.10784559
+77.22411531
+77.59010588
+81.53762997
+76.38373963
+72.42225742
+83.75963563
+82.00646211
+81.28819396
+83.86292045
+82.79971882
+75.29338899
+77.63895141
+74.0170517
+74.07700107
+82.81833688
+85.73677863
+87.40288227
+82.05276617
+74.9449017
+73.6896981
+85.00479949
+81.25932352
+81.8924031
+84.50323117
+83.2522758
+85.35116817
+72.89928252
+83.96016898
+85.61347974
+76.57801365
+82.24699847
+77.02644513
+87.32736939
+72.53463789
+81.27665429
+74.66402808
+83.39549126
+74.81421581
+75.7661031
+79.90990229
+86.63732593
+75.38740101
+74.3078118
+84.143597
+80.00988179
+86.58852855
+29.73832746
+32.93393219
+30.29042072
+29.80326102
+33.17394189
+32.59957531
+33.63088928
+30.78055458
+31.66701252
+31.3950127
+35.09816583
+30.67038743
+21.48078005
+21.74837478
+22.68938024
+21.29040473
+24.2604976
+21.35027016
+24.17325315
+20.62356715
+23.10139964
+24.22329379
+20.91599634
+24.49810344
+20.28701
+22.30564882
+21.20425464
+19.66729958
+19.20328691
+19.67609851
+18.81299908
+19.02128296
+18.86068894
+20.16437651
+21.69068877
+19.01110681
+18.61018384
+20.67246958
+18.8789178
+18.47871422
+18.75699776
+21.79906117
+21.38805721
+19.50945624
+20.72227478
+20.24581834
+20.80789779
+20.83019185
+20.53463039
+19.08270729
+18.17345546
+19.84129649
+21.58459687
+20.29745589
+21.35004054
+21.9875852
+18.67237309
+20.78704697
+20.71704357
+21.94086481
+21.94661588
+20.75069781
+18.97810226
+21.19829264
+18.43165473
+21.12685279
+21.64493953
+19.53508359
+20.52648151
+19.72435728
+19.75485242
+19.24517792
+21.04851848
+21.74470626
+21.76300344
+18.69912514
+21.4989746
+20.94972577
+19.0113496
+18.26913845
+19.07198907
+21.64883295
+20.5327147
+20.88421864
+19.0286094
+20.87755262
+18.11248603
+19.50128538
+20.50701339
+18.58438626
+21.2920143
+18.9401252
+20.60912445
+19.62078857
+20.38417438
+18.42980221
+18.0676512
+21.63825771
+19.07852004
+21.27870801
+21.9974012
+18.84572503
+19.06068296
+20.65143915
+21.86179454
+21.66325739
+20.01150208
+21.18044113
+18.54298341
+21.90975274
+21.85741294
+18.65491583
+19.1976925
+18.40061999
+19.0868704
+21.26382316
+19.51326243
+18.35358787
+19.3689021
+21.92553334
+20.51873438
+19.66464379
+18.66615405
+21.94470719
+21.28339604
+19.12590921
+18.28027478
+18.22650223
+18.4815126
+20.32307433
+21.71505368
+19.98697371
+21.37178193
+19.78354648
+20.83433418
+20.92749095
+18.69585482
+19.44486424
+20.54920863
+18.28278643
+19.44616075
+20.13919787
+21.98489797
+19.89813425
+21.26422703
+19.72826914
+21.18556289
+20.38165921
+21.54638177
+19.64377021
+20.41721768
+20.52007472
+19.66953177
+18.57724817
+18.37423763
+18.0666862
+21.49413706
+18.94589965
+18.846027
+20.9441416
+19.28006445
+20.02417877
+18.65004426
+21.83898289
+21.4063256
+21.45515849
+19.62709499
+21.04944485
+18.57550462
+18.03447601
+18.07989173
+20.34640695
+19.82157962
+20.0720614
+18.02985256
+19.69074648
+20.87227264
+19.77077481
+20.92887683
+18.93207586
+72.25873126
+69.20266487
+64.06637815
+64.41939847
+69.74121432
+72.48717847
+66.85253784
+64.71288584
+72.99135785
+70.30204877
+67.29396263
+67.83544266
+73.01006038
+79.56797682
+75.40768376
+85.29241314
+77.29244816
+77.38094461
+78.62201974
+84.06805317
+82.26869691
+76.84153868
+80.99421261
+78.93837494
+79.39860554
+74.62659005
+78.94644233
+75.47749881
+86.11764955
+76.90230996
+86.71280689
+80.04571133
+81.6120818
+80.20292483
+73.62566933
+77.54506067
+73.49803419
+81.86890399
+79.05500714
+84.34642223
+75.43689466
+74.54349727
+78.40711412
+86.72117569
+83.26670894
+78.60833466
+80.18002309
+73.25939129
+87.73215357
+82.64267787
+76.54808914
+81.3534048
+73.73401744
+87.43239789
+74.77860863
+82.34871665
+75.90904886
+83.46094669
+84.40887888
+82.75484973
+81.82806343
+86.27536409
+73.25451099
+77.29092611
+75.96895299
+87.8040086
+78.22648142
+83.71778454
+82.95162075
+75.38968092
+75.82032333
+76.49688099
+78.5772821
+75.74847386
+72.31372951
+86.06946263
+87.44891778
+77.46438253
+77.41536688
+72.11277672
+82.88321533
+85.20622034
+74.34501909
+74.55394587
+84.64116949
+81.8604948
+72.7176293
+81.96059448
+76.94253584
+77.89945292
+84.31554081
+84.97479993
+78.40555549
+87.15427964
+78.50325276
+84.34921461
+79.74200561
+86.36048406
+86.52414667
+73.39864074
+86.9838599
+85.20852474
+84.66093892
+75.21455255
+84.88187475
+85.60209088
+76.62637593
+87.23612776
+29.11909935
+29.75941351
+32.24051309
+32.48506558
+32.92895421
+28.90859688
+34.94634065
+29.08535821
+29.71559079
+28.88968737
+32.42788775
+34.76650138
+23.14344203
+23.84550415
+20.21949868
+22.5882273
+22.21884092
+22.39537516
+20.48351395
+23.22626914
+22.41442623
+23.58786555
+22.33410082
+20.82922859
+21.08726023
+19.13809431
+22.00532787
+20.94332386
+19.07590688
+22.37373642
+20.55522469
+18.73059183
+20.99950732
+19.46910249
+21.72392812
+21.78179895
+22.02098516
+20.10351397
+19.91496264
+21.1147691
+18.61882602
+20.28456278
+20.2818783
+18.44601033
+19.76636159
+21.51592221
+21.52745258
+18.48525598
+18.38051189
+19.06907065
+21.51970334
+18.53338532
+20.90003199
+18.42233095
+20.51222425
+19.44291649
+21.17596527
+18.95293916
+20.57654184
+18.96091515
+20.85864522
+21.49883912
+18.51076058
+21.4705043
+20.37821288
+18.51199558
+19.71395177
+18.64702071
+20.80538542
+21.03951135
+18.42672333
+20.02840412
+21.25850022
+21.74465217
+20.05407147
+21.80111689
+20.14275588
+19.57676198
+21.39281251
+19.97193084
+19.88761004
+19.96124996
+21.38714001
+21.32776617
+19.61407997
+19.33319944
+19.9677121
+20.29109004
+18.95334884
+21.17582034
+19.94593106
+19.33618219
+18.42728397
+18.95538064
+21.79712469
+19.22039875
+18.67543716
+19.84269117
+19.22835097
+18.140637
+19.29258087
+20.1764345
+20.20684949
+19.42623568
+19.78921103
+21.86207167
+19.50939391
+19.03290725
+18.97386818
+19.83105845
+21.03808059
+18.82395274
+20.83718451
+18.08459929
+19.67573191
+21.10346026
+19.35493182
+20.25494841
+18.81991693
+20.96798156
+18.20911641
+21.41017058
+18.79278555
+21.49759213
+19.41011697
+20.8907343
+19.27690119
+21.62364668
+18.5065485
+18.71407916
+19.9721205
+18.32775376
+18.78392074
+21.77506553
+21.90595864
+19.50503732
+21.69314408
+20.1792987
+19.07896986
+20.80959488
+20.63560723
+21.95650128
+19.06018915
+20.68823801
+18.20809502
+18.45458415
+18.0156735
+21.99784272
+21.20909479
+21.14689206
+20.0389043
+19.20026833
+18.60505714
+19.13869896
+19.50388489
+21.02524039
+20.15864716
+18.30993451
+18.07211604
+18.40932872
+19.64199485
+21.73277167
+20.54960992
+21.2073036
+19.86549838
+19.44666433
+18.43360149
+21.50373209
+21.13264012
+18.67247239
+20.04904226
+19.94949923
+20.50036621
+21.78474758
+20.31908577
+20.16086907
+18.20129173
+18.2516299
+18.74938717
+18.12988309
+71.30959938
+71.03729213
+63.05036479
+72.57067305
+63.30509007
+65.29598798
+64.58608583
+66.26337654
+64.66342722
+67.8497326
+66.74074719
+74.61734507
+70.70797695
+72.04665496
+70.65985787
+79.55305535
+70.68598399
+82.82154472
+77.78528755
+78.01915833
+78.55594676
+72.49102872
+72.9081535
+74.78804485
+81.006967
+74.90971311
+73.41813979
+86.99673896
+71.91759878
+84.33409953
+84.10091102
+76.29489327
+73.7250057
+73.884078
+82.65995244
+81.79119602
+84.42250207
+86.89529912
+82.97115281
+74.40423224
+75.80400777
+85.37252957
+75.25847854
+73.07256464
+83.15257789
+78.34629318
+86.61657607
+82.30519624
+73.42907644
+87.14478531
+76.11864336
+77.37682495
+78.41734194
+72.80211204
+79.92506014
+73.95534231
+78.3967055
+77.59272988
+84.34519363
+84.83036401
+74.4510323
+77.86108149
+77.96990784
+74.41899482
+84.77118687
+83.3116541
+75.04250637
+77.8638129
+73.68934314
+82.04736709
+73.93840158
+87.7707335
+84.49010208
+78.24306565
+81.25624285
+86.58063788
+80.86481218
+74.79125778
+78.05850432
+85.48949713
+82.3066181
+82.410799
+85.86831943
+86.30274041
+86.71651465
+73.51744594
+80.70586108
+83.84799135
+84.11066803
+81.70730235
+74.668454
+84.75856613
+83.52162097
+73.37803146
+79.42080471
+74.78349481
+77.39960301
+72.28926972
+78.40524779
+80.79799971
+81.91329003
+82.6158138
+85.38062822
+75.44737754
+73.92768077
+85.62456187
+74.50577643
+87.59612766
+34.1922381
+32.00560413
+35.08109038
+29.42320542
+30.73961497
+32.88462994
+31.040038
+34.74157766
+29.22000135
+32.31622952
+32.58153786
+32.97745366
+21.30538351
+21.7932564
+23.93968746
+21.03334245
+23.86436665
+22.68069505
+23.57459876
+23.35695972
+21.08965034
+22.70827981
+24.04739841
+22.09587953
+22.39115553
+20.28427281
+19.01684974
+20.02712421
+22.33017279
+19.74157636
+21.9877298
+22.04160253
+19.86636377
+18.77302314
+21.39978894
+19.70795414
+21.23312654
+19.86551832
+20.03678404
+21.21297344
+19.62319465
+19.86741738
+19.59838468
+19.56281495
+20.20028443
+21.33712668
+19.54041915
+20.19348452
+20.70276488
+19.09607242
+19.1284369
+21.7545168
+20.91419666
+20.32824309
+20.61064745
+18.13459027
+20.49206537
+20.057272
+20.20237439
+19.45635549
+18.32941416
+18.77696142
+21.80716502
+19.63856813
+19.87054703
+18.21433564
+18.15374977
+20.87273258
+20.15624791
+20.03867062
+18.97614084
+20.98303089
+18.67294632
+18.75973897
+19.84284869
+19.14511945
+18.98985192
+20.58095058
+20.60388698
+21.29806828
+19.67083427
+18.29234036
+19.09466554
+21.92002185
+20.3850343
+20.83894834
+18.02943132
+20.07282293
+18.15011463
+20.27692085
+21.6830834
+21.87367652
+20.1622107
+19.83281922
+21.78006838
+20.69443933
+18.25959712
+19.86290231
+18.96098007
+19.87921729
+19.82186229
+20.32857921
+19.42708196
+18.6570818
+20.01487774
+21.32081154
+20.65604891
+19.35347146
+21.74209209
+21.64883029
+18.8373936
+18.15767034
+20.96523483
+21.31044105
+21.87145826
+21.55934558
+20.40213907
+20.12020936
+18.11136421
+18.98662579
+19.83845901
+20.5140156
+20.22900733
+20.97054396
+19.11906772
+20.25981043
+18.35256897
+19.65466209
+21.00064333
+20.77360341
+21.96257095
+19.1115645
+19.9927572
+19.31812166
+19.76241246
+21.42780052
+20.7368363
+21.52976477
+18.81404443
+21.49344447
+18.2390491
+21.55439712
+19.31629512
+19.25835053
+20.04835431
+21.76276075
+18.19112546
+19.4089239
+21.42628795
+19.58421791
+18.79662759
+19.69917673
+19.54221001
+21.66166481
+21.0477375
+20.02046222
+21.95348227
+19.86111013
+18.23295132
+19.04909729
+19.74428192
+18.6276105
+21.79026051
+21.06739559
+19.0731488
+20.36321813
+20.88579663
+21.76511572
+21.5265414
+20.0607689
+21.09861048
+20.24857902
+20.21081556
+18.45896783
+18.50455063
+20.11813446
+19.07544618
+18.08414761
+20.89135682
+18.12994639
+69.29576504
+68.5330356
+74.37587979
+67.7852987
+62.06497953
+68.70295636
+72.63890792
+74.75715027
+67.05266716
+65.5560629
+73.53048484
+63.80089296
+79.39145676
+76.13668786
+70.4775983
+75.22991712
+73.95634667
+80.48813471
+84.56522852
+74.00009235
+82.43395138
+70.69918436
+78.19163808
+70.93493699
+86.42286069
+83.75605077
+82.03203539
+84.67124805
+81.86615483
+86.97809169
+82.9227872
+86.27377053
+79.79246561
+73.42979242
+79.96813848
+73.58578546
+81.38211979
+79.6242251
+81.86285292
+72.07415879
+75.02730693
+79.76545337
+87.10340732
+78.04397935
+78.69540447
+83.33501526
+81.5626913
+76.69067902
+78.55420479
+75.46508081
+87.43535382
+74.07236847
+77.9306807
+72.39604433
+75.53034024
+84.4672612
+75.2007512
+73.263427
+79.57214898
+72.14218947
+73.35273737
+84.91793766
+84.33952503
+86.6380623
+85.66813471
+82.92682833
+72.83382953
+84.52152066
+85.52406762
+84.78124464
+80.13181805
+75.72279455
+85.52445857
+83.63380206
+87.69133695
+74.49036645
+75.60990747
+75.38804667
+84.67982335
+74.98979683
+73.06585584
+87.97612833
+72.39638037
+85.36308547
+77.84572
+85.46568326
+80.87377258
+86.42593373
+86.81892109
+72.14543238
+73.20645426
+76.00559374
+82.70888786
+86.21218962
+79.35891885
+81.71141297
+75.01596884
+84.87943675
+87.47721619
+76.29755363
+79.91718454
+73.37782959
+80.94615542
+80.04450433
+74.31095521
+79.07302905
+77.34564473
+80.34926315
+32.5481815
+28.85436616
+33.67043183
+33.36328506
+31.14422689
+29.13878439
+33.6315618
+34.91311432
+30.33696439
+30.8705516
+29.97639674
+32.49238495
+20.8536883
+21.75574767
+23.28261703
+22.66931836
+21.89135109
+22.04271701
+22.67825551
+20.18627287
+20.51172309
+24.10803482
+20.50889675
+23.32647883
+22.20047605
+19.54071981
+19.94953269
+20.76230183
+22.04347968
+22.29004502
+21.46125081
+18.78679432
+21.17285517
+20.1126038
+20.35999105
+18.63331158
+18.8543169
+21.26363224
+19.91095129
+19.29884083
+19.62984941
+21.52040247
+21.0967768
+19.18089
+18.55866335
+19.09923121
+21.78710427
+20.42392181
+20.15324939
+20.40514454
+19.4827986
+21.24880736
+20.11243441
+18.48471991
+18.5340361
+20.16677812
+21.76715729
+19.25187255
+21.4987837
+21.07659646
+18.99489609
+18.1488469
+18.41092328
+20.91799122
+18.8022883
+19.48882482
+20.01063797
+20.90588583
+18.45646785
+19.62923371
+19.94412017
+20.16717961
+21.27344257
+18.68671278
+21.23132581
+20.77151371
+20.22348326
+20.79811148
+19.64807096
+18.55359034
+20.66306096
+20.09868923
+20.5574992
+19.35199512
+21.62746631
+20.34947947
+18.34160994
+19.79921596
+21.02542422
+21.17653825
+19.97838821
+21.57899028
+19.07067375
+19.64239479
+21.59438764
+21.58502687
+20.74285108
+21.43592219
+18.35509307
+21.4599799
+19.28247963
+18.71332605
+18.95747935
+19.67187403
+19.00476802
+19.28227034
+18.53991394
+19.18470706
+20.28913526
+19.76741483
+19.38687504
+20.98580852
+21.57403989
+21.02715689
+19.32800281
+20.97776867
+18.60792073
+18.52127195
+19.38250815
+21.23080948
+18.98539299
+18.25301364
+18.52683814
+21.43497987
+20.53513314
+19.01280465
+20.2211833
+20.11031849
+20.62174391
+18.93275022
+21.45761195
+19.23747425
+20.77652662
+18.06449859
+19.49062852
+19.40683927
+20.17393771
+18.29094505
+21.16052549
+18.87112321
+20.70815126
+21.21284849
+20.24750783
+20.96353283
+20.64744125
+19.42211919
+21.23543416
+19.17880548
+20.28485167
+20.98159096
+19.51582364
+19.21107043
+19.83738404
+21.27185398
+21.71968705
+20.18033365
+20.64586482
+21.61309449
+18.39418741
+18.92831431
+20.83560003
+21.29497785
+21.42811611
+19.66042871
+18.35735961
+19.75112591
+18.92293836
+19.16478582
+21.08907023
+18.30210834
+21.31032487
+19.71067634
+20.38425572
+18.35860892
+19.34943631
+18.35880368
+21.84617489
+21.2290466
+19.83853102
+18.89441019
+73.89498943
+65.8865137
+63.38938827
+68.85903568
+74.03532804
+61.25209195
+64.43849787
+73.96288791
+63.52676915
+62.74011094
+68.95454613
+72.921076
+77.24474437
+85.27563726
+80.38074478
+70.98964256
+85.24875468
+76.17051855
+74.30048733
+78.49828493
+74.56285383
+71.18182051
+69.86216788
+76.81753364
+84.87747587
+80.67010071
+87.45939288
+76.13000905
+76.02835735
+74.10865542
+74.17726731
+76.10360762
+84.17732808
+85.973156
+87.07578635
+75.26233466
+85.99743982
+77.15937893
+73.71688217
+85.81729433
+82.07907693
+74.5461315
+78.78264736
+76.50420777
+83.68816664
+79.1595541
+87.72308495
+72.78846861
+77.661601
+79.69127218
+80.03092484
+77.03647996
+83.6477637
+85.97531415
+86.99862415
+84.86112247
+85.58873693
+80.78933072
+85.19376021
+76.83761709
+78.37189816
+77.06690883
+79.47438241
+76.56559853
+87.38158856
+77.00181778
+73.56518131
+80.42521406
+72.9100854
+73.76514976
+75.50660574
+79.42579138
+78.93125717
+84.79425576
+83.83078968
+78.82033602
+77.33852486
+77.06276074
+84.38311131
+72.8324593
+72.20445322
+84.72789688
+79.63357753
+74.09338691
+75.76890948
+86.91989636
+85.75188297
+83.35640076
+79.71545063
+80.32502379
+87.60374437
+87.45215919
+75.44415988
+84.9775099
+75.15573836
+75.41645485
+82.81745674
+78.47998744
+86.90467714
+73.42412756
+80.18437946
+86.6963112
+86.46578536
+74.5044388
+77.8661733
+81.90591095
+74.55028953
+87.48832116
+34.65438905
+29.86847541
+29.57538927
+29.34660866
+34.6204328
+30.03918662
+31.4642175
+31.67264266
+32.63366442
+29.25910058
+30.25124934
+34.7615318
+24.22967595
+23.6601808
+20.24691647
+21.62498914
+22.97325387
+21.39285098
+24.23494706
+22.99982353
+20.48214097
+24.23234371
+24.45079329
+20.50815051
+20.61254727
+19.67457986
+20.04106862
+19.16785116
+20.79978308
+22.35588316
+20.49258512
+18.7716179
+20.97152521
+19.82555315
+21.93786931
+20.21244145
+18.86146091
+18.85449167
+21.17621694
+19.15384963
+21.17006441
+18.91390223
+19.37932181
+19.95728519
+21.87729271
+21.83121489
+18.9178594
+19.52615392
+18.61545124
+20.05917865
+19.86137883
+21.62377956
+21.74087272
+19.55302245
+19.98612004
+21.60566653
+21.24720898
+18.03191928
+19.29874728
+19.70599657
+18.92249756
+18.80189573
+18.15462304
+20.57742901
+19.05369877
+18.21288491
+18.92755063
+21.21172768
+21.41006667
+19.93609197
+19.66805822
+21.91562176
+18.80225864
+18.86143713
+19.16746871
+18.69102927
+19.51746239
+21.64333691
+20.46139136
+19.64778619
+21.73764318
+18.19385693
+18.84110471
+20.26355442
+20.46221049
+18.15823003
+19.61215503
+20.59661586
+20.79228219
+20.55255961
+19.2822529
+18.37408049
+19.70844979
+18.51501775
+21.79049463
+19.90068346
+19.2690367
+21.06521628
+19.99179437
+19.2401361
+21.24787097
+21.4686086
+20.69203267
+18.18785769
+20.26529152
+21.05317965
+18.54601205
+18.91468301
+21.52998042
+18.08048689
+21.01090855
+19.89509317
+19.78708864
+18.02838613
+21.27759292
+19.4392996
+20.16306253
+20.70920275
+20.81051831
+21.82392024
+20.12535981
+19.5988782
+21.81481451
+20.56844094
+19.19260143
+18.50585698
+21.37021801
+19.44872641
+20.64187889
+19.88326568
+18.79571912
+20.40674643
+18.24273228
+19.65336984
+20.18645976
+19.7441879
+20.9946887
+21.31169982
+21.0849723
+18.15525179
+18.77651508
+20.14643004
+21.73928816
+21.3398271
+21.37013803
+19.21283278
+19.71779159
+19.88282379
+18.62948633
+18.12427252
+21.7876116
+18.96285034
+18.95979561
+18.33351622
+21.71403101
+20.31894846
+20.66814743
+21.64630755
+19.38248068
+20.48602924
+18.15519782
+18.74709011
+21.32498322
+21.06707343
+19.40257077
+19.50724251
+20.13421773
+18.00096402
+18.96497734
+18.83292723
+19.00193179
+21.22362337
+19.11869543
+18.76608529
+20.01705384
+21.46258015
+18.96539882
+18.31414497
+19.42561894
+20.9906073
+68.68939141
+72.30838983
+74.25045321
+71.98020968
+69.41172187
+67.9094456
+61.74493957
+74.58677891
+66.41534327
+63.27030371
+70.26724043
+65.06632073
+78.93127876
+78.94663793
+76.75772682
+82.81656091
+73.9522888
+76.80277782
+78.18498184
+80.13945567
+82.00724312
+75.96740903
+79.86664857
+72.17748199
+86.40083539
+77.66016726
+83.1703087
+71.89150457
+74.83129632
+79.31456078
+85.53572725
+79.9534659
+86.35666015
+79.26230584
+79.36810243
+73.47245292
+84.74068891
+75.86030486
+86.29012727
+86.4692997
+86.98845024
+80.2272994
+82.73410036
+84.35490658
+74.00731842
+81.51737674
+72.4617079
+79.86510407
+74.45960831
+74.90878439
+77.82207928
+78.90005411
+81.95108581
+73.17328889
+80.039854
+74.9040208
+81.16411874
+82.17874616
+80.88793034
+83.79261311
+77.36603416
+84.23766186
+78.92048494
+79.74312412
+82.36568029
+72.29026404
+82.45994928
+81.89343131
+76.95385991
+73.36918667
+73.45144136
+86.76741492
+83.02767207
+74.0329311
+77.70682472
+81.4789457
+85.36832774
+72.69787695
+75.78540256
+86.23515598
+72.1459562
+75.22166351
+87.34354831
+81.81364413
+76.18659559
+73.07171721
+72.45092234
+75.91577552
+86.10360779
+78.65446745
+83.52517354
+86.69239412
+78.52849661
+75.06029382
+80.27373277
+86.52917286
+84.86995804
+73.05324944
+83.0811329
+81.1503292
+86.5193776
+73.95967427
+80.54454688
+86.07137004
+78.56035042
+79.71188807
+73.12734276
+76.45026889
+30.87683663
+34.84877698
+30.60906523
+31.74955381
+33.09634196
+29.83796785
+31.91322515
+33.52664342
+34.34786677
+32.80805306
+33.08193615
+29.60820854
+24.39707737
+20.75393073
+23.63053346
+21.34637595
+24.34249595
+23.38541745
+23.53708414
+21.14138394
+22.14481788
+22.92780185
+23.60948051
+20.62573687
+22.37384807
+22.0783436
+19.53934759
+21.80202569
+20.55505454
+20.3235591
+19.71992186
+20.81164708
+21.42162557
+20.11518094
+21.00928156
+21.29638547
+20.94454076
+18.2952621
+21.54189833
+19.92821167
+19.14110267
+19.05809986
+20.02773027
+21.65075327
+19.60705455
+21.09969767
+18.4755338
+19.99976705
+21.98783263
+21.10198968
+18.86020237
+20.02497142
+18.95267616
+19.65709641
+21.14061161
+21.10514075
+18.93055741
+21.7097146
+20.38982818
+19.53843606
+20.01158381
+20.42420571
+20.24344812
+19.9494497
+20.023575
+18.70923912
+21.25501179
+20.17091335
+18.52787611
+21.06867281
+21.73394803
+21.79341113
+19.47607093
+18.54206749
+20.07359851
+18.45043692
+21.73594967
+18.73431851
+19.01106344
+19.62654611
+19.53265787
+21.17865157
+19.82526728
+18.68307304
+19.06883958
+20.03645354
+18.58981567
+20.4466227
+20.26298923
+20.85880927
+21.75081846
+21.64901824
+21.78430247
+18.97886239
+18.52626123
+19.2091068
+21.58034069
+21.8882139
+21.4372998
+18.44007088
+21.78971199
+19.69343211
+18.03724116
+19.76957496
+18.18427668
+20.17551168
+19.35421611
+19.89373973
+20.45268144
+21.47520438
+20.64760631
+19.73619547
+21.27771141
+21.62232855
+18.47903987
+20.12773191
+19.13804784
+18.18824479
+20.67418678
+21.45108311
+18.65161062
+21.24965463
+21.41358293
+21.65736177
+19.06114036
+21.61581226
+19.28265102
+20.20935205
+18.20202988
+18.17552435
+20.88149285
+19.77791991
+19.0251695
+18.76165398
+20.67981396
+18.00160618
+21.22356468
+18.31699842
+18.76595846
+19.54494558
+19.93943496
+19.41998046
+19.28284866
+21.85566405
+20.56631873
+18.09373182
+19.72070363
+21.5000348
+19.20582475
+18.37822538
+21.03353909
+20.42405533
+20.28125003
+18.21430624
+18.56199604
+20.49019758
+18.83129537
+20.01628032
+20.17952674
+19.13402876
+21.79370062
+21.36985643
+20.88949403
+18.31197547
+18.42452008
+19.97112538
+18.6428534
+21.91306185
+18.63408094
+19.94987134
+19.45648423
+20.55754569
+18.51614564
+19.72126571
+19.09882013
+21.5510061
+18.16234285
+21.65490998
+21.33197655
+19.19028287
+71.9343529
+61.62450442
+74.34937148
+68.36169122
+65.32462195
+66.13113169
+62.10311281
+74.65515339
+61.73437045
+70.10673687
+67.22120862
+74.10526057
+73.65791597
+78.09798751
+77.32616836
+80.74848721
+70.8955188
+72.8476073
+73.17004601
+81.29609972
+72.77543257
+78.74059218
+73.18058409
+83.21241923
+86.55251747
+79.81411227
+77.17112049
+75.29045485
+72.35971705
+75.83822521
+81.97296584
+80.05464368
+86.58203249
+77.87039358
+82.6032026
+79.35018898
+80.10497799
+76.19284777
+79.18407737
+79.43712088
+83.20631281
+86.9457797
+77.17641747
+72.58799725
+79.84479314
+80.61452766
+74.60541476
+84.06643278
+87.73780361
+87.1114837
+75.13565973
+85.98517044
+83.25191293
+79.24252225
+80.63041996
+85.57306034
+79.66303532
+77.95260479
+79.87278582
+81.24657301
+75.02164125
+86.41037579
+82.78301741
+82.12836033
+73.58840721
+81.66286301
+73.9318217
+73.25564636
+80.43311336
+78.44080321
+81.41705612
+73.42403017
+78.89497161
+74.79586939
+87.79275856
+80.97762601
+82.99819298
+77.20595131
+73.51511688
+87.61309271
+76.5794094
+78.78017467
+82.39703173
+72.39446177
+84.96398296
+80.58509632
+76.45132821
+72.98558763
+74.59983142
+86.32037601
+82.97622827
+75.99828163
+73.04947198
+83.04968554
+81.15836779
+78.47216172
+77.81775331
+75.46899943
+82.71374834
+87.53065483
+74.81141521
+81.5538346
+78.78693064
+79.14698916
+76.06632727
+85.20212529
+79.76405904
+80.69446265
+30.75046394
+29.96356843
+29.34982085
+33.37035609
+30.05589363
+33.21647589
+31.29840325
+31.46095269
+31.80272987
+31.15332847
+29.4439622
+30.78163767
+23.13352867
+23.14271285
+21.44228372
+22.22125855
+21.02664243
+21.10246577
+20.26324984
+24.17742322
+21.1039647
+21.17935061
+21.41261324
+20.73078702
+21.05042052
+18.73978531
+18.98169291
+21.0729233
+19.82324966
+21.33175404
+20.71521151
+19.48066249
+21.09779103
+18.90825677
+20.62913668
+20.2225584
+19.16303746
+20.51401684
+21.58846392
+22.10119772
+20.52912007
+19.7129938
+18.99155233
+19.11972056
+20.0134254
+19.56256249
+21.75920328
+19.5666531
+19.51249238
+19.55289081
+21.36697345
+20.6229323
+20.4763138
+19.35513519
+21.29203745
+18.17088275
+21.50381254
+20.07024855
+19.61181021
+20.00785824
+20.6736307
+18.05452751
+21.49033278
+19.7907572
+19.37558548
+18.55654443
+19.761655
+19.98912826
+19.61835278
+20.71861758
+19.68736536
+21.84986468
+20.39711007
+21.22991174
+18.43742361
+19.58916517
+19.34739081
+20.27792955
+21.44445408
+18.31335287
+18.29029919
+21.40127083
+18.85140034
+20.67501302
+20.17151253
+21.33157438
+18.50035564
+18.51913186
+20.22727344
+21.78551461
+19.65999103
+19.3077684
+20.42675729
+21.7217944
+21.34771133
+21.98193444
+18.09027433
+18.45143258
+20.43787105
+21.28230576
+19.14097737
+18.95684435
+21.1479032
+18.22552742
+19.47753059
+20.02323689
+20.2413947
+20.91446063
+19.41938289
+20.45073738
+20.34150169
+20.1904644
+20.56193317
+19.03779668
+18.33859501
+18.47708669
+18.89832953
+20.00079174
+21.361771
+20.80517337
+21.15616242
+19.4039025
+19.61861497
+19.57472754
+18.76749274
+18.24486663
+20.36366437
+21.95686673
+18.66731882
+18.18673928
+21.11812673
+19.01034403
+21.31857522
+20.81574667
+21.78269415
+19.63570894
+20.64787936
+19.85941912
+20.52235479
+19.79839562
+18.75452899
+20.03158966
+20.11433681
+21.24241539
+20.94208282
+20.6551665
+18.45354838
+20.88246516
+20.00122063
+21.57639814
+21.67948374
+18.22062636
+21.28256624
+18.15078956
+19.4686785
+20.1691999
+18.59240319
+20.98525525
+18.03341882
+18.67439619
+20.32318732
+20.85755025
+21.66657241
+20.82198661
+20.68711708
+19.57736459
+18.0051377
+18.48063703
+20.13821818
+20.70051954
+19.66979314
+20.92271605
+20.08744918
+18.29670478
+18.768065
+21.35999289
+20.89965099
+21.57904795
+18.470229
+21.96089014
+64.04793131
+61.36020632
+74.76495197
+65.02260484
+70.28506455
+63.60287947
+69.09110804
+73.49487582
+65.55446388
+70.31545407
+63.75548881
+69.69721742
+75.06170946
+73.11795217
+74.70058543
+72.61561338
+83.83773799
+76.00434048
+73.64673481
+76.79928969
+74.81472131
+81.39338682
+84.91333303
+76.63828235
+85.26187519
+80.56748632
+74.06867602
+82.55166409
+79.73366224
+81.91524615
+85.71758861
+78.57267141
+85.90032892
+83.50664
+79.33877274
+81.16164485
+77.11664696
+87.63227173
+82.57840547
+72.61430778
+77.13327935
+81.8746633
+72.81385085
+72.29528848
+79.10534737
+77.23025522
+78.9179624
+76.11164925
+74.61757143
+83.0063674
+80.21388191
+75.18441879
+77.0949236
+81.44937398
+73.13811221
+74.34140193
+73.1543684
+84.97667802
+84.01837848
+84.03283419
+83.45719936
+82.70619669
+79.62804832
+82.27250135
+72.61029941
+81.93949748
+84.44198988
+80.00189349
+77.71648268
+76.43515869
+82.28088313
+83.08083111
+85.93465662
+77.47660154
+84.31554748
+80.98091576
+86.12455705
+80.44422146
+80.28130655
+81.24525334
+83.98823939
+87.43420828
+73.17631117
+72.85425423
+87.00063836
+80.47785549
+81.8382911
+79.71862457
+73.49837812
+84.28926822
+83.95543313
+76.98710533
+76.89968028
+85.40529812
+73.15757566
+86.09751707
+76.10655781
+81.48772467
+86.97587347
+82.84992821
+78.63084681
+83.03251546
+77.50364442
+76.43610531
+87.94689868
+84.01261144
+82.31548803
+77.68460446
+29.11462372
+28.99875844
+32.34675382
+33.67700295
+32.23922063
+34.1810179
+29.01392424
+31.14720731
+30.31724468
+31.66254092
+29.2632033
+34.9064358
+21.16018304
+24.2919375
+22.06800012
+24.57514677
+22.64218032
+24.3301299
+20.18396236
+23.51210856
+24.2056656
+20.785947
+20.59064269
+22.06208407
+22.25634853
+20.6536151
+20.59246143
+19.01005235
+18.43523362
+21.75033355
+18.79070518
+21.02824861
+22.17826873
+19.286638
+21.15695728
+18.75434915
+20.51301262
+18.74527433
+21.0443445
+19.29710877
+19.94886109
+20.49563118
+18.77478205
+21.06719067
+19.30277201
+20.74860493
+18.72257119
+20.85208244
+18.53052452
+19.72033934
+19.00705356
+21.01365475
+19.06642622
+21.54753501
+21.58798542
+18.80379959
+20.47502094
+18.36848739
+19.58493189
+20.87330606
+20.64165542
+20.50273845
+19.13383644
+19.51584612
+18.41531964
+20.88009949
+20.01939817
+20.83906286
+18.99942129
+19.30145808
+19.34057402
+18.10644541
+19.36419149
+21.21321829
+21.58919398
+20.07287326
+19.82200678
+18.12329847
+21.51681735
+18.05204085
+21.77900032
+19.95686499
+19.36773797
+21.69687374
+18.09756397
+20.32569958
+20.1957301
+18.8772816
+19.71554973
+20.60905602
+20.90852479
+18.00286743
+21.74741372
+18.65810149
+18.93432174
+19.05389378
+18.15128055
+18.49220849
+21.94539969
+19.26086695
+18.46120436
+18.42796504
+20.87783987
+21.41827466
+19.0278092
+18.08363805
+18.89236007
+18.22606276
+18.41357975
+19.72603248
+18.91967348
+20.06378351
+19.01397501
+21.7621492
+21.62377587
+20.26722442
+19.41769597
+19.52458753
+19.64740913
+20.91031729
+19.80655598
+21.42691979
+21.77637914
+19.34378461
+20.24277793
+18.38022615
+18.80187619
+19.65386307
+18.82481086
+21.50624196
+18.63314502
+19.82264329
+20.42279696
+20.76745563
+19.53227748
+21.47639627
+20.2732766
+19.75803112
+18.26896254
+19.85875787
+21.28294336
+20.45816407
+21.32864981
+19.97604668
+18.47384682
+18.05455938
+19.21287819
+20.79196189
+21.16103962
+19.18301134
+19.98261568
+19.68447562
+19.64209114
+18.92539485
+18.54548442
+18.78675423
+18.22132955
+18.79252297
+18.03680359
+20.5090336
+19.26550163
+21.89257885
+18.7748682
+19.38331428
+19.43136463
+18.03380598
+21.35683181
+18.12797784
+21.76071934
+21.5682974
+20.14208766
+20.1743823
+20.61511169
+19.54820005
+20.58888913
+18.17907355
+18.21619051
+19.82892168
+20.1984892
+21.55127056
+62.62338462
+72.38801181
+64.05664379
+66.55953762
+65.50579311
+66.64211171
+63.24673877
+68.04855301
+72.10233922
+67.20486254
+67.87234463
+72.74323916
+80.79802194
+77.45185242
+73.83943646
+83.57406311
+78.79535663
+73.27221091
+74.01673856
+82.30462554
+70.52513912
+85.23727074
+71.86305807
+82.19498351
+77.84650664
+79.39620618
+85.57386678
+78.13493956
+80.11630066
+72.35206183
+71.60533422
+75.46129718
+82.39199351
+73.49659686
+73.37727019
+78.10391751
+82.26655415
+83.29308009
+74.76538453
+73.18548227
+86.94189692
+76.07925733
+85.55075971
+85.71288417
+84.25912903
+74.6116961
+85.04664476
+84.20683934
+81.52799643
+77.37665771
+76.18184964
+73.93247934
+80.1368756
+81.34464661
+77.73076399
+79.5866397
+77.79755542
+82.23635545
+86.39940649
+74.60481474
+78.09879204
+74.25033348
+81.99516437
+83.65791238
+86.90643201
+76.45828065
+87.19919353
+73.00869816
+81.6443027
+72.91062363
+86.29624459
+80.47308202
+82.7087796
+85.30436388
+74.40425567
+72.61676786
+86.06127214
+77.03819207
+74.06295152
+79.49461664
+81.57211411
+72.4948337
+76.39759711
+72.52410175
+78.72521507
+86.32143473
+87.72227016
+82.19260305
+74.5860599
+86.49342417
+80.25981107
+74.45984603
+86.74746016
+84.1193433
+83.70712365
+83.34673123
+75.20540826
+75.37607812
+83.0126561
+75.515535
+79.01871681
+84.51199676
+84.54320783
+79.25215793
+84.6750065
+85.41791594
+82.47638035
+75.65478459
+30.55366953
+30.81497748
+29.54754062
+30.54821571
+30.14091725
+31.71409791
+34.61399366
+29.46866837
+33.4097083
+33.19860485
+29.41282122
+34.70445673
+22.70675422
+21.78948914
+23.54929156
+21.31299608
+23.26692279
+20.33790509
+23.9205467
+22.16780418
+23.01238299
+21.15114427
+23.19328896
+23.61963514
+20.37028097
+20.96220923
+20.30111074
+22.09419798
+20.47127192
+21.88004821
+21.71433777
+20.11342751
+19.37442585
+20.09531217
+21.81618611
+19.36438263
+20.19421451
+21.326264
+19.50709662
+20.66756892
+19.07364238
+18.5256159
+21.27918903
+18.48417465
+19.17713606
+21.52325574
+19.47892931
+21.99726382
+21.93997951
+19.09141425
+18.18135024
+20.84024057
+19.82295779
+18.42067826
+20.85008815
+18.14209934
+21.50140831
+18.57242253
+18.52701638
+18.72064376
+21.84525892
+20.77666579
+21.20955759
+19.59430132
+19.3489652
+18.94157211
+19.92641725
+20.21119474
+20.53104058
+19.03212748
+21.79880089
+18.68262037