#region License Information /* HeuristicLab * Copyright (C) 2002-2012 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.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Optimization; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Analysis.AlgorithmBehavior.Analyzers { [Item("CrossoverPerformanceAnalyzer", "An operator that analyzes the performance of crossovers.")] [StorableClass] public class CrossoverPerformanceAnalyzer : InitializableOperator, IStatefulItem { private const string ResultsParameterName = "Results"; private const string GenerationsParameterName = "Generations"; private const string SuccessfullCrossoversRowName = "Successfull Crossovers per Generation with CompFact "; #region Parameter properties public IValueLookupParameter MaximizationParameter { get { return (IValueLookupParameter)Parameters["Maximization"]; } } public IValueLookupParameter> ComparisonFactorParameter { get { return (IValueLookupParameter>)Parameters["ComparisonFactor"]; } } public ILookupParameter ResultsParameter { get { return (ILookupParameter)Parameters[ResultsParameterName]; } } public ILookupParameter GenerationsParameter { get { return (ILookupParameter)Parameters[GenerationsParameterName]; } } public ILookupParameter> ParentsQualityParameter { get { return (ScopeTreeLookupParameter)Parameters["ParentsQuality"]; } } public ILookupParameter QualityParameter { get { return (ILookupParameter)Parameters["Quality"]; } } public IValueParameter SimilarityCalculatorParameter { get { return (IValueParameter)Parameters["SimilarityCalculator"]; } } public IValueParameter UnwantedMutationAnalyzerParameter { get { return (IValueParameter)Parameters["UnwantedMutationAnalyzer"]; } } public ILookupParameter> OperatorsParameter { get { return (ILookupParameter>)Parameters["Operators"]; } } #endregion #region Properties public ResultCollection Results { get { return ResultsParameter.ActualValue; } } [Storable] private ScatterPlotHelper worseParentCrossoverPerformancePlot, betterParentCrossoverPerformancePlot, childDiversityToWorseParentHelper, childDiversityToBetterParentHelper, parentDiversityHelper, parentQualityHelper, unwantedMutationsHelper; [Storable] private DataTableHelper successHelper, equalParentsHelper; [Storable] private int cnt = 0; [Storable] private int[] success; [Storable] private int lastGeneration = 0; [Storable] private int equalParents = 0; #endregion [StorableConstructor] private CrossoverPerformanceAnalyzer(bool deserializing) : base(deserializing) { } private CrossoverPerformanceAnalyzer(CrossoverPerformanceAnalyzer original, Cloner cloner) : base(original, cloner) { cnt = original.cnt; success = (int[])original.success.Clone(); lastGeneration = original.lastGeneration; equalParents = original.equalParents; worseParentCrossoverPerformancePlot = (ScatterPlotHelper)original.worseParentCrossoverPerformancePlot.Clone(cloner); betterParentCrossoverPerformancePlot = (ScatterPlotHelper)original.betterParentCrossoverPerformancePlot.Clone(cloner); childDiversityToWorseParentHelper = (ScatterPlotHelper)original.childDiversityToWorseParentHelper.Clone(cloner); childDiversityToBetterParentHelper = (ScatterPlotHelper)original.childDiversityToBetterParentHelper.Clone(cloner); parentDiversityHelper = (ScatterPlotHelper)original.parentDiversityHelper.Clone(cloner); parentQualityHelper = (ScatterPlotHelper)original.parentQualityHelper.Clone(cloner); unwantedMutationsHelper = (ScatterPlotHelper)original.unwantedMutationsHelper.Clone(cloner); successHelper = (DataTableHelper)original.successHelper.Clone(cloner); equalParentsHelper = (DataTableHelper)original.equalParentsHelper.Clone(cloner); } public CrossoverPerformanceAnalyzer() : base() { Parameters.Add(new LookupParameter(ResultsParameterName, "The results collection where the analysis values should be stored.")); Parameters.Add(new LookupParameter(GenerationsParameterName, "Nr of generations.")); Parameters.Add(new ScopeTreeLookupParameter("ParentsQuality", "The quality of the parent solutions.")); ParentsQualityParameter.ActualName = "TSPTourLength"; Parameters.Add(new LookupParameter("Quality", "The evaluated quality of the child solution.")); QualityParameter.ActualName = "TSPTourLength"; Parameters.Add(new ValueParameter("SimilarityCalculator")); Parameters.Add(new ValueParameter("UnwantedMutationAnalyzer")); Parameters.Add(new LookupParameter>("Operators", "The operators and items that the problem provides to the algorithms.")); Parameters.Add(new ValueLookupParameter("Maximization", "True if the problem is a maximization problem, false otherwise")); Parameters.Add(new ValueLookupParameter>("ComparisonFactor", "Determines if the quality should be compared to the better parent (1.0), to the worse (0.0) or to any linearly interpolated value between them.")); worseParentCrossoverPerformancePlot = new ScatterPlotHelper(false, true); betterParentCrossoverPerformancePlot = new ScatterPlotHelper(false, true); childDiversityToWorseParentHelper = new ScatterPlotHelper(false, true); childDiversityToBetterParentHelper = new ScatterPlotHelper(false, true); unwantedMutationsHelper = new ScatterPlotHelper(false, true); parentDiversityHelper = new ScatterPlotHelper(false, true); parentQualityHelper = new ScatterPlotHelper(false, true); successHelper = new DataTableHelper(); equalParentsHelper = new DataTableHelper(); } public override IDeepCloneable Clone(Cloner cloner) { return new CrossoverPerformanceAnalyzer(this, cloner); } protected override void InitializeAction() { if (SimilarityCalculatorParameter.Value == null) { SimilarityCalculatorParameter.Value = OperatorsParameter.ActualValue.OfType().FirstOrDefault(); } if (ComparisonFactorParameter.ActualValue == null) { ComparisonFactorParameter.Value = new ItemCollection(); ComparisonFactorParameter.Value.Add(new DoubleValue(0)); ComparisonFactorParameter.Value.Add(new DoubleValue(0.5)); ComparisonFactorParameter.Value.Add(new DoubleValue(1)); ComparisonFactorParameter.Value.Add(new DoubleValue(1.5)); } if (success == null) { success = new int[ComparisonFactorParameter.Value.Count]; } worseParentCrossoverPerformancePlot.InitializePlot(Results, "Crossover Performance compared to worse parent", "Solution Index", "Absolut Quality Difference"); betterParentCrossoverPerformancePlot.InitializePlot(Results, "Crossover Performance compared to better parent", "Solution Index", "Absolut Quality Difference"); childDiversityToWorseParentHelper.InitializePlot(Results, "Child Diversity to Worse Parent", "Solution Index", "Diversity"); childDiversityToBetterParentHelper.InitializePlot(Results, "Child Diversity to Better Parent", "Solution Index", "Diversity"); parentDiversityHelper.InitializePlot(Results, "Parent Diversity", "Solution Index", "Diversity"); parentQualityHelper.InitializePlot(Results, "Parent Quality Difference", "Solution Index", "Absolut Quality Difference"); equalParentsHelper.InitializeChart(Results, "Number of equal parents", new string[] { "Absolut number of equal parents" }); unwantedMutationsHelper.InitializePlot(Results, "Unwanted Mutations", "Solution Index", "Unwanted Mutation"); List successfullCXRowNames = new List(); foreach (var value in ComparisonFactorParameter.Value) { successfullCXRowNames.Add(SuccessfullCrossoversRowName + value.Value.ToString()); } successHelper.InitializeChart(Results, "Successfull Crossovers", successfullCXRowNames.ToArray()); Reset(); } public override IOperation Apply() { Initialize(); Point2D worseQualityPoint, betterQualityPoint, childDiversityToWorseParent, childDiversityToBetterParent, diversityPointParent, qualityPointParent, unwantedMutationPoint; var qualityParent1 = ParentsQualityParameter.ActualValue.First().Value; var qualityParent2 = ParentsQualityParameter.ActualValue.Last().Value; var qualityChild = QualityParameter.ActualValue.Value; var parentDiversity = SimilarityCalculatorParameter.Value.CalculateSolutionSimilarity(ExecutionContext.Scope.SubScopes.First(), ExecutionContext.Scope.SubScopes.Last()); string curGenStr = GenerationsParameter.ActualValue.Value.ToString(); diversityPointParent = new Point2D(cnt, parentDiversity); qualityPointParent = new Point2D(cnt, Math.Abs(qualityParent1 - qualityParent2)); if (UnwantedMutationAnalyzerParameter.Value != null) { unwantedMutationPoint = new Point2D(cnt, UnwantedMutationAnalyzerParameter.Value.AnalyzeUnwantedMutations(ExecutionContext.Scope.SubScopes.First(), ExecutionContext.Scope.SubScopes.Last(), ExecutionContext.Scope)); } else { //TODO: this is not a good solution unwantedMutationPoint = new Point2D(cnt, 0.0); } double worseQuality, betterQuality; if (qualityParent1 > qualityParent2) { if (MaximizationParameter.ActualValue.Value) { childDiversityToWorseParent = new Point2D(cnt, SimilarityCalculatorParameter.Value.CalculateSolutionSimilarity(ExecutionContext.Scope, ExecutionContext.Scope.SubScopes.Last())); childDiversityToBetterParent = new Point2D(cnt, SimilarityCalculatorParameter.Value.CalculateSolutionSimilarity(ExecutionContext.Scope, ExecutionContext.Scope.SubScopes.First())); worseQuality = qualityParent2; betterQuality = qualityParent1; } else { childDiversityToWorseParent = new Point2D(cnt, SimilarityCalculatorParameter.Value.CalculateSolutionSimilarity(ExecutionContext.Scope, ExecutionContext.Scope.SubScopes.First())); childDiversityToBetterParent = new Point2D(cnt, SimilarityCalculatorParameter.Value.CalculateSolutionSimilarity(ExecutionContext.Scope, ExecutionContext.Scope.SubScopes.Last())); worseQuality = qualityParent1; betterQuality = qualityParent2; } } else { if (MaximizationParameter.ActualValue.Value) { childDiversityToWorseParent = new Point2D(cnt, SimilarityCalculatorParameter.Value.CalculateSolutionSimilarity(ExecutionContext.Scope, ExecutionContext.Scope.SubScopes.First())); childDiversityToBetterParent = new Point2D(cnt, SimilarityCalculatorParameter.Value.CalculateSolutionSimilarity(ExecutionContext.Scope, ExecutionContext.Scope.SubScopes.Last())); worseQuality = qualityParent1; betterQuality = qualityParent2; } else { childDiversityToWorseParent = new Point2D(cnt, SimilarityCalculatorParameter.Value.CalculateSolutionSimilarity(ExecutionContext.Scope, ExecutionContext.Scope.SubScopes.Last())); childDiversityToBetterParent = new Point2D(cnt, SimilarityCalculatorParameter.Value.CalculateSolutionSimilarity(ExecutionContext.Scope, ExecutionContext.Scope.SubScopes.First())); worseQuality = qualityParent2; betterQuality = qualityParent1; } } worseQualityPoint = new Point2D(cnt, Math.Abs(worseQuality - qualityChild)); betterQualityPoint = new Point2D(cnt++, Math.Abs(betterQuality - qualityChild)); if (GenerationsParameter.ActualValue.Value == lastGeneration) { CountSuccess(qualityChild, qualityParent1, qualityParent2); if (parentDiversity == 1.0) { equalParents++; } } if (GenerationsParameter.ActualValue.Value != 0) { if (GenerationsParameter.ActualValue.Value > lastGeneration) { equalParentsHelper.AddPoint(equalParents); for (int i = 0; i < ComparisonFactorParameter.Value.Count; i++) { successHelper.AddPoint(SuccessfullCrossoversRowName + ComparisonFactorParameter.Value.ElementAt(i).Value.ToString(), success[i]); } Reset(); CountSuccess(qualityChild, qualityParent1, qualityParent2); if (parentDiversity == 1.0) { equalParents++; } } betterParentCrossoverPerformancePlot.AddPoint(curGenStr, betterQualityPoint); worseParentCrossoverPerformancePlot.AddPoint(curGenStr, worseQualityPoint); childDiversityToWorseParentHelper.AddPoint(curGenStr, childDiversityToWorseParent); childDiversityToBetterParentHelper.AddPoint(curGenStr, childDiversityToBetterParent); parentDiversityHelper.AddPoint(curGenStr, diversityPointParent); parentQualityHelper.AddPoint(curGenStr, qualityPointParent); unwantedMutationsHelper.AddPoint(curGenStr, unwantedMutationPoint); } return base.Apply(); } private void CountSuccess(double qualityChild, double qualityParent1, double qualityParent2) { //track successfull cx var compFactsArray = ComparisonFactorParameter.Value.ToArray(); for (int i = 0; i < compFactsArray.Length; i++) { if (WeightedParentsQualityComparer.Compare(qualityChild, qualityParent1, qualityParent2, compFactsArray[i].Value, MaximizationParameter.ActualValue.Value)) { success[i]++; } } } private void Reset() { cnt = 0; success = new int[ComparisonFactorParameter.Value.Count]; lastGeneration = GenerationsParameter.ActualValue.Value; equalParents = 0; } public override void ClearState() { betterParentCrossoverPerformancePlot.CleanUp(); worseParentCrossoverPerformancePlot.CleanUp(); childDiversityToWorseParentHelper.CleanUp(); childDiversityToBetterParentHelper.CleanUp(); parentDiversityHelper.CleanUp(); parentQualityHelper.CleanUp(); unwantedMutationsHelper.CleanUp(); } } }