#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();
}
}
}