#region License Information /* HeuristicLab * Copyright (C) 2002-2014 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; 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.Operators; using HeuristicLab.Optimization; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Analyzers { [StorableClass] [Item("SymbolicDataAnalysisInternalDiversityAnalyzer", "An analyzer that determines the average diversity of symbolic expression trees.")] public class SymbolicDataAnalysisInternalDiversityAnalyzer : SingleSuccessorOperator, ISymbolicDataAnalysisAnalyzer { private const string SymbolicExpressionTreeParameterName = "SymbolicExpressionTree"; private const string QualityParameterName = "Quality"; private const string PercentageOfBestSolutionsParameterName = "PercentageOfBestSolutions"; private const string ResultCollectionParameterName = "Results"; private readonly BottomUpSimilarityCalculator busCalculator; public SymbolicDataAnalysisInternalDiversityAnalyzer() { busCalculator = new BottomUpSimilarityCalculator(); Parameters.Add(new ScopeTreeLookupParameter(SymbolicExpressionTreeParameterName)); Parameters.Add(new ScopeTreeLookupParameter(QualityParameterName)); Parameters.Add(new LookupParameter(ResultCollectionParameterName)); Parameters.Add(new FixedValueParameter(PercentageOfBestSolutionsParameterName)); } protected SymbolicDataAnalysisInternalDiversityAnalyzer(SymbolicDataAnalysisInternalDiversityAnalyzer original, Cloner cloner) : base(original, cloner) { } public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicDataAnalysisInternalDiversityAnalyzer(this, cloner); } #region parameter properties public IScopeTreeLookupParameter SymbolicExpressionTreeParameter { get { return (IScopeTreeLookupParameter)Parameters[SymbolicExpressionTreeParameterName]; } } public IScopeTreeLookupParameter QualityParameter { get { return (IScopeTreeLookupParameter)Parameters[QualityParameterName]; } } public ILookupParameter ResultCollectionParameter { get { return (ILookupParameter)Parameters[ResultCollectionParameterName]; } } public IFixedValueParameter PercentageOfBestSolutionsParameter { get { return (IFixedValueParameter)Parameters[PercentageOfBestSolutionsParameterName]; } } #endregion public double PercentageOfBestSolutions { get { return PercentageOfBestSolutionsParameter.Value.Value; } set { PercentageOfBestSolutionsParameter.Value.Value = value; } } public bool EnabledByDefault { get { return true; } } public override IOperation Apply() { var results = ResultCollectionParameter.ActualValue; DataTable table; if (!results.ContainsKey("Avg. Internal Diversity")) { table = new DataTable("Internal Diversity") { VisualProperties = { YAxisTitle = "Internal Diversity" } }; var row = new DataRow("Avg. Internal Diversity") { VisualProperties = { StartIndexZero = true } }; table.Rows.Add(row); results.Add(new Result("Avg. Internal Diversity", table)); } else { table = (DataTable)results["Avg. Internal Diversity"].Value; } var trees = SymbolicExpressionTreeParameter.ActualValue.ToArray(); var qualities = QualityParameter.ActualValue.ToArray(); Array.Sort(qualities, trees, new ReverseComparer()); int n = (int)Math.Floor(trees.Length * PercentageOfBestSolutions); double avgInternalDiversity = trees.Take(n).Average(tree => CalculateInternalDiversity(tree)); table.Rows["Avg. Internal Diversity"].Values.Add(avgInternalDiversity); return base.Apply(); } private double CalculateInternalDiversity(ISymbolicExpressionTree tree) { var branchPoint = tree.IterateNodesPrefix().FirstOrDefault(x => x.SubtreeCount == 2); if (branchPoint == null) return 1; var s1 = branchPoint.GetSubtree(0); var s2 = branchPoint.GetSubtree(1); // set parents to null because otherwise the bottom-up calculator will throw an exception var p1 = s1.Parent; s1.Parent = null; var p2 = s2.Parent; s2.Parent = null; var m = busCalculator.ComputeBottomUpMapping(s1, s2); var diversity = 1 - 2.0 * m.Count / (s1.GetLength() + s2.GetLength()); // restore parents s1.Parent = p1; s2.Parent = p2; return diversity; } } internal class ReverseComparer : IComparer { public int Compare(DoubleValue x, DoubleValue y) { return y.CompareTo(x); } } }