#region License Information /* HeuristicLab * Copyright (C) 2002-2015 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.Linq; using HeuristicLab.Analysis; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; using HeuristicLab.EvolutionTracking; using HeuristicLab.Optimization; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Tracking.Analyzers { [Item("SymbolicDataAnalysisFragmentLengthAnalyzer", "An analyzer for fragment length.")] [StorableClass] public class SymbolicDataAnalysisFragmentLengthAnalyzer : EvolutionTrackingAnalyzer { private const string StoreHistoryParameterName = "StoryHistory"; public IFixedValueParameter StoreHistoryParameter { get { return (IFixedValueParameter)Parameters[StoreHistoryParameterName]; } } public bool StoreHistory { get { return StoreHistoryParameter.Value.Value; } set { StoreHistoryParameter.Value.Value = value; } } [StorableConstructor] protected SymbolicDataAnalysisFragmentLengthAnalyzer(bool deserializing) : base(deserializing) { } public SymbolicDataAnalysisFragmentLengthAnalyzer() { UpdateCounterParameter.ActualName = "FragmentLengthAnalyzerUpdateCounter"; Parameters.Add(new FixedValueParameter(StoreHistoryParameterName, new BoolValue(false))); } protected SymbolicDataAnalysisFragmentLengthAnalyzer(SymbolicDataAnalysisFragmentLengthAnalyzer original, Cloner cloner) : base(original, cloner) { } public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicDataAnalysisFragmentLengthAnalyzer(this, cloner); } public override IOperation Apply() { int updateInterval = UpdateIntervalParameter.Value.Value; IntValue updateCounter = UpdateCounterParameter.ActualValue; // if counter does not yet exist then initialize it with update interval // to make sure the solutions are analyzed on the first application of this operator if (updateCounter == null) { updateCounter = new IntValue(updateInterval); UpdateCounterParameter.ActualValue = updateCounter; } //analyze solutions only every 'updateInterval' times if (updateCounter.Value != updateInterval) { updateCounter.Value++; return base.Apply(); } updateCounter.Value = 1; if (PopulationGraph == null || Generation.Value == 0) return base.Apply(); // consider all fragments (including those of the intermediate crossover children) var vertices = PopulationGraph.Vertices.Where(x => x.Rank > Generation.Value - 1); var crossoverFragmentLengthDistribution = new List(); var replacedCrossoverFragmentLengthDistribution = new List(); var mutationFragmentLengthDistribution = new List(); var replacedMutationFragmentLengthDistribution = new List(); foreach (var v in vertices) { if (!v.InArcs.Any() || v.InArcs.Last().Data == null) continue; var fragment = (IFragment)v.InArcs.Last().Data; if (v.InDegree == 2) { crossoverFragmentLengthDistribution.Add(fragment.Root.GetLength()); int index = 0; foreach (var s in v.Parents.First().Data.IterateNodesPrefix()) { if (index == fragment.Index1) { replacedCrossoverFragmentLengthDistribution.Add(s.GetLength()); break; } index++; } } else { mutationFragmentLengthDistribution.Add(fragment.Root.GetLength()); int index = 0; foreach (var s in v.Parents.First().Data.IterateNodesPrefix()) { if (index == fragment.Index1) { replacedMutationFragmentLengthDistribution.Add(s.GetLength()); break; } index++; } } } var avgCXFragmentLength = crossoverFragmentLengthDistribution.Any() ? crossoverFragmentLengthDistribution.Average() : 0; var avgReplacedCXFragmentLength = replacedCrossoverFragmentLengthDistribution.Any() ? replacedCrossoverFragmentLengthDistribution.Average() : 0; var avgMutFragmentLength = mutationFragmentLengthDistribution.Any() ? mutationFragmentLengthDistribution.Average() : 0; var avgReplacedMutFragmentLength = replacedMutationFragmentLengthDistribution.Any() ? replacedMutationFragmentLengthDistribution.Average() : 0; var avgFragmentLength = (avgCXFragmentLength + avgMutFragmentLength) / 2d; DataTable table; if (!Results.ContainsKey("AverageFragmentLength")) { table = new DataTable("Average fragment length"); var row = new DataRow("Average fragment length") { VisualProperties = { StartIndexZero = true } }; row.Values.Add(avgFragmentLength); table.Rows.Add(row); row = new DataRow("Average crossover fragment length") { VisualProperties = { StartIndexZero = true } }; row.Values.Add(avgCXFragmentLength); table.Rows.Add(row); row = new DataRow("Average replaced crossover fragment length") { VisualProperties = { StartIndexZero = true } }; row.Values.Add(avgReplacedCXFragmentLength); table.Rows.Add(row); row = new DataRow("Average mutation fragment length") { VisualProperties = { StartIndexZero = true } }; row.Values.Add(avgMutFragmentLength); table.Rows.Add(row); row = new DataRow("Average replaced mutation fragment length") { VisualProperties = { StartIndexZero = true } }; row.Values.Add(avgReplacedMutFragmentLength); table.Rows.Add(row); Results.Add(new Result("AverageFragmentLength", table)); } else { table = (DataTable)Results["AverageFragmentLength"].Value; table.Rows["Average fragment length"].Values.Add(avgFragmentLength); table.Rows["Average crossover fragment length"].Values.Add(avgCXFragmentLength); table.Rows["Average replaced crossover fragment length"].Values.Add(avgReplacedCXFragmentLength); table.Rows["Average mutation fragment length"].Values.Add(avgMutFragmentLength); table.Rows["Average replaced mutation fragment length"].Values.Add(avgReplacedMutFragmentLength); } if (!Results.ContainsKey("FragmentLengthDistribution")) { table = new DataTable("Table length distribution"); var row = new DataRow("Crossover fragment length distribution") { VisualProperties = { StartIndexZero = true, ChartType = DataRowVisualProperties.DataRowChartType.Histogram } }; row.Values.Replace(crossoverFragmentLengthDistribution); table.Rows.Add(row); row = new DataRow("Replaced crossover fragment length distribution") { VisualProperties = { StartIndexZero = true, ChartType = DataRowVisualProperties.DataRowChartType.Histogram } }; row.Values.Replace(replacedCrossoverFragmentLengthDistribution); table.Rows.Add(row); row = new DataRow("Mutation fragment length distribution") { VisualProperties = { StartIndexZero = true, ChartType = DataRowVisualProperties.DataRowChartType.Histogram } }; row.Values.Replace(mutationFragmentLengthDistribution); table.Rows.Add(row); row = new DataRow("Replaced mutation fragment length distribution") { VisualProperties = { StartIndexZero = true, ChartType = DataRowVisualProperties.DataRowChartType.Histogram } }; row.Values.Replace(replacedMutationFragmentLengthDistribution); table.Rows.Add(row); Results.Add(new Result("FragmentLengthDistribution", table)); } else { table = (DataTable)Results["FragmentLengthDistribution"].Value; table.Rows["Crossover fragment length distribution"].Values.Replace(crossoverFragmentLengthDistribution); table.Rows["Mutation fragment length distribution"].Values.Replace(mutationFragmentLengthDistribution); table.Rows["Replaced crossover fragment length distribution"].Values.Replace(replacedCrossoverFragmentLengthDistribution); table.Rows["Replaced mutation fragment length distribution"].Values.Replace(replacedMutationFragmentLengthDistribution); } if (StoreHistory) { if (!Results.ContainsKey("FragmentLengthDistributionHistory")) { var history = new DataTableHistory(); history.Add((DataTable)table.Clone()); Results.Add(new Result("FragmentLengthDistributionHistory", history)); } else { var history = (DataTableHistory)Results["FragmentLengthDistributionHistory"].Value; history.Add((DataTable)table.Clone()); } } return base.Apply(); } } }