#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 System.Collections.Generic; using System.Drawing; using System.Linq; using HeuristicLab.Collections; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Operators; using HeuristicLab.Optimization.Operators; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Analysis.FitnessLandscape.Analysis { [StorableClass] public class UpDownWalkAnalyzer : AlgorithmOperator, 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 UpDownStepsParameter { get { return (LookupParameter)Parameters["UpDownSteps"]; } } public LookupParameter UpDownLevelsParameter { get { return (LookupParameter)Parameters["UpDownLevels"]; } } 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 UpperLevelParameter { get { return (LookupParameter)Parameters["UpperLevel"]; } } public LookupParameter LowerLevelParameter { get { return (LookupParameter)Parameters["LowerLevel"]; } } 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("UpDownSteps", "Distribution of upward and downward steps between extremes.")); Parameters.Add(new LookupParameter("UpDownLevels", "Distribution of upper and lower levels in up-down walks.")); 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("UpperLevel", "Average maximum fitness value.")); Parameters.Add(new LookupParameter("LowerLevel", "Average minimum fitness value.")); Parameters.Add(new LookupParameter("LowerVariance", "Lower level variance.")); Parameters.Add(new LookupParameter("UpperVariance", "Upper level variance.")); var resultsCollector = new ResultsCollector(); resultsCollector.CollectedValues.Add(new LookupParameter(UpDownStepsParameter.Name)); resultsCollector.CollectedValues.Add(new LookupParameter(UpDownLevelsParameter.Name)); resultsCollector.CollectedValues.Add(new LookupParameter(DownWalkLengthParameter.Name)); resultsCollector.CollectedValues.Add(new LookupParameter(UpWalkLengthParameter.Name)); resultsCollector.CollectedValues.Add(new LookupParameter(UpWalkLenVarParameter.Name)); resultsCollector.CollectedValues.Add(new LookupParameter(DownWalkLenVarParameter.Name)); resultsCollector.CollectedValues.Add(new LookupParameter(UpperLevelParameter.Name)); resultsCollector.CollectedValues.Add(new LookupParameter(LowerLevelParameter.Name)); resultsCollector.CollectedValues.Add(new LookupParameter(UpperVarianceParameter.Name)); resultsCollector.CollectedValues.Add(new LookupParameter(LowerVarianceParameter.Name)); OperatorGraph.InitialOperator = resultsCollector; resultsCollector.Successor = null; } public override IDeepCloneable Clone(Cloner cloner) { return new UpDownWalkAnalyzer(this, cloner); } public override IOperation Apply() { var stepsTable = GetOrCreateTable(UpDownStepsParameter, "Up", "Down"); var levelsTable = GetOrCreateTable(UpDownLevelsParameter, "Top", "Bottom"); DataTable qualityTrail = QualityTrailParameter.ActualValue; if (qualityTrail != null && qualityTrail.Rows.Count > 0) { var qualities = qualityTrail.Rows.First().Values.ToList(); if (qualities.Count > 2) { 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(); ReplaceHistogram(stepsTable.Rows["Up"], topLengths); ReplaceHistogram(levelsTable.Rows["Top"], topVals); UpperLevelParameter.ActualValue = new DoubleValue(topVals.Average()); UpperVarianceParameter.ActualValue = new DoubleValue(topVals.Variance()); UpWalkLengthParameter.ActualValue = new DoubleValue(topLengths.Average()); UpWalkLenVarParameter.ActualValue = new DoubleValue(topLengths.Variance()); } if (bottoms.Count > 0) { var bottomLengths = bottoms.Select(b => (double) b.length).ToList(); var bottomVals = bottoms.Select(b => b.value).ToList(); ReplaceHistogram(stepsTable.Rows["Down"], bottomLengths); ReplaceHistogram(levelsTable.Rows["Bottom"], bottomVals); LowerLevelParameter.ActualValue = new DoubleValue(bottomVals.Average()); LowerVarianceParameter.ActualValue = new DoubleValue(bottomVals.Variance()); DownWalkLengthParameter.ActualValue = new DoubleValue(bottomLengths.Average()); DownWalkLenVarParameter.ActualValue = new DoubleValue(bottomLengths.Variance()); } } } } return base.Apply(); } private void ReplaceHistogram(DataRow row, IEnumerable values) { row.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Histogram; row.VisualProperties.Bins = 25; row.Values.Clear(); row.Values.AddRange(values); } private DataTable GetOrCreateTable(LookupParameter tableParameter, params string[] rowNames) { DataTable table = tableParameter.ActualValue; if (table == null) { table = new DataTable(tableParameter.Name, tableParameter.Description); tableParameter.ActualValue = table; foreach (var name in rowNames) { table.Rows.Add(new DataRow(name)); } } return table; } } }