#region License Information /* HeuristicLab * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Operators; using HeuristicLab.Optimization; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using System.Linq; namespace HeuristicLab.Analysis.FitnessLandscape { [Item("Up/Down Walk Analyzer", "Analyzes the quality trail produced from an up/down walk.")] [StorableClass] public class UpDownWalkAnalyzer : SingleSuccessorOperator, IQualityTrailAnalyzer { public bool EnabledByDefault { get { return false; } } #region Parameters public LookupParameter QualityTrailParameter { get { return (LookupParameter)Parameters["Quality Trail"]; } } public LookupParameter ResultsParameter { get { return (LookupParameter)Parameters["Results"]; } } public LookupParameter UpWalkLengthParameter { get { return (LookupParameter)Parameters["UpWalkLength"]; } } public LookupParameter DownWalkLengthParameter { get { return (LookupParameter)Parameters["DownWalkLength"]; } } public LookupParameter UpWalkLenVarParameter { get { return (LookupParameter)Parameters["UpWalkLenVar"]; } } public LookupParameter DownWalkLenVarParameter { get { return (LookupParameter)Parameters["DownWalkLenVar"]; } } public LookupParameter UpperVarianceParameter { get { return (LookupParameter)Parameters["UpperVariance"]; } } public LookupParameter LowerVarianceParameter { get { return (LookupParameter)Parameters["LowerVariance"]; } } #endregion [StorableConstructor] protected UpDownWalkAnalyzer(bool deserializing) : base(deserializing) { } protected UpDownWalkAnalyzer(UpDownWalkAnalyzer original, Cloner cloner) : base(original, cloner) { } public UpDownWalkAnalyzer() { Parameters.Add(new LookupParameter("Quality Trail", "The qualities of the solutions")); Parameters.Add(new LookupParameter("Results", "The collection of all results of this algorithm")); Parameters.Add(new LookupParameter("DownWalkLength", "Average downward walk length.")); Parameters.Add(new LookupParameter("UpWalkLength", "Average updward walk length.")); Parameters.Add(new LookupParameter("UpWalkLenVar", "Upward walk length variance.")); Parameters.Add(new LookupParameter("DownWalkLenVar", "Downward walk length variance.")); Parameters.Add(new LookupParameter("LowerVariance", "Lower level variance.")); Parameters.Add(new LookupParameter("UpperVariance", "Upper level variance.")); } public override IDeepCloneable Clone(Cloner cloner) { return new UpDownWalkAnalyzer(this, cloner); } public override IOperation Apply() { var qualityTrail = QualityTrailParameter.ActualValue; if (qualityTrail != null && qualityTrail.Rows.Count > 0) { var qualities = qualityTrail.Rows.First().Values.ToList(); if (qualities.Count > 2) { var results = ResultsParameter.ActualValue; var extremes = qualities .Delta((a, b) => new { a, b, diff = b - a }) .Select((p, i) => new { p.a, p.b, p.diff, i = i + 1 }) .Delta((s1, s2) => new { s1.i, value = s2.a, top = s1.diff >= 0 && s2.diff < 0, bottom = s1.diff <= 0 && s2.diff > 0 }) .Where(x => x.top || x.bottom) .GroupConsecutive(x => x.bottom) .Select(g => g.Count() == 1 ? g.First() : (g.First().bottom ? g.OrderBy(x => x.value).First() : g.OrderByDescending(x => x.value).First())).ToList(); var maxima = extremes.Where(x => x.top).ToList(); var minima = extremes.Where(x => x.bottom).ToList(); var tops = Enumerable.Repeat(new { length = 0, value = 0.0 }, 0).ToList(); var bottoms = tops; if (maxima.Count > 0 && minima.Count > 0) { if (maxima.First().i < minima.First().i) { bottoms = maxima.Zip(minima, (t, b) => new { length = b.i - t.i, b.value }).ToList(); minima.Insert(0, new { i = -1, value = 0.0, top = false, bottom = false }); tops = maxima.Zip(minima, (t, b) => new { length = t.i - b.i, t.value }).ToList(); } else { tops = maxima.Zip(minima, (t, b) => new { length = t.i - b.i, t.value }).ToList(); maxima.Insert(0, new { i = -1, value = 0.0, top = false, bottom = false }); bottoms = maxima.Zip(minima, (t, b) => new { length = b.i - t.i, b.value }).ToList(); } if (tops.Count > 0) { var topLengths = tops.Select(t => (double)t.length).ToList(); var topVals = tops.Select(t => t.value).ToList(); var uv = new DoubleValue(topVals.Variance()); UpperVarianceParameter.ActualValue = uv; AddOrUpdateResult(results, UpperVarianceParameter.Name, uv); var ul = new DoubleValue(topLengths.Average()); UpWalkLengthParameter.ActualValue = ul; AddOrUpdateResult(results, UpWalkLengthParameter.Name, ul); var ulv = new DoubleValue(topLengths.Variance()); UpWalkLenVarParameter.ActualValue = ulv; AddOrUpdateResult(results, UpWalkLenVarParameter.Name, ulv); } if (bottoms.Count > 0) { var bottomLengths = bottoms.Select(b => (double)b.length).ToList(); var bottomVals = bottoms.Select(b => b.value).ToList(); var lv = new DoubleValue(bottomVals.Variance()); LowerVarianceParameter.ActualValue = lv; AddOrUpdateResult(results, LowerVarianceParameter.Name, lv); var dl = new DoubleValue(bottomLengths.Average()); DownWalkLengthParameter.ActualValue = dl; AddOrUpdateResult(results, DownWalkLengthParameter.Name, dl); var dlv = new DoubleValue(bottomLengths.Variance()); DownWalkLenVarParameter.ActualValue = dlv; AddOrUpdateResult(results, DownWalkLenVarParameter.Name, dlv); } } } } return base.Apply(); } private static void AddOrUpdateResult(ResultCollection results, string name, IItem item, bool clone = false) { IResult r; if (!results.TryGetValue(name, out r)) { results.Add(new Result(name, clone ? (IItem)item.Clone() : item)); } else r.Value = clone ? (IItem)item.Clone() : item; } } }