using System; using System.Linq; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Operators; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using System.Collections.Generic; namespace HeuristicLab.Analysis.FitnessLandscape.Analysis { [Item("Ruggedness Calculator", "Calculates ruggedness descriptors froma given quality trail.")] [StorableClass] public class RuggednessCalculator : SingleSuccessorOperator { #region Parameters public LookupParameter QualityTrailParameter { get { return (LookupParameter)Parameters["QualityTrail"]; } } public LookupParameter CorrelationLengthParameter { get { return (LookupParameter)Parameters["CorrelationLength"]; } } public LookupParameter AutoCorrelationParameter { get { return (LookupParameter)Parameters["AutoCorrelation"]; } } #endregion #region Constructors & Cloning [StorableConstructor] protected RuggednessCalculator(bool deserializing) : base(deserializing) { } protected RuggednessCalculator(RuggednessCalculator original, Cloner cloner) : base(original, cloner) { } public RuggednessCalculator() { Parameters.Add(new LookupParameter("QualityTrail", "Historical values of walk qualities")); Parameters.Add(new LookupParameter("CorrelationLength", "Average maximum distances between correlated quality values.")); Parameters.Add(new LookupParameter("AutoCorrelation", "AutoCorrelation")); } public override IDeepCloneable Clone(Cloner cloner) { return new RuggednessCalculator(this, cloner); } #endregion public override IOperation Apply() { double[] qualities = QualityTrailParameter.ActualValue.Rows.First().Values.ToArray(); double[] autocorrelation; CorrelationLengthParameter.ActualValue = new IntValue(CalculateCorrelationLength(qualities, out autocorrelation)); AutoCorrelationParameter.ActualValue = new DoubleArray(autocorrelation); return base.Apply(); } public static int CalculateCorrelationLength(double[] qualities, out double[] acf) { double[] correlations = new double[qualities.Length]; alglib.corr.corrr1dcircular(qualities, qualities.Length, qualities, qualities.Length, ref correlations); double mean = 0; double variance = 0; double skewness = 0; double kurtosis = 0; alglib.basestat.samplemoments(qualities, qualities.Length, ref mean, ref variance, ref skewness, ref kurtosis); List autocorrelation = new List() { 1.0 }; double bound = Math.Min(2 / Math.Sqrt(qualities.Length), 1.0); int correlationLength = 1; for (; correlationLength < qualities.Length; correlationLength++) { double value = correlations[correlationLength]/qualities.Length - mean * mean; if (variance > 0) value = Math.Max(Math.Min(value/variance, 1.0), -1.0); else value = 1; autocorrelation.Add(value); if (Math.Abs(value) < bound) break; } acf = autocorrelation.ToArray(); return correlationLength-1; } public static bool AnyGreaterOne(double[] values) { return values.Any(d => d > 1); } } }