#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.Collections.Generic;
using System.Linq;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Data;
using HeuristicLab.Encodings.PermutationEncoding;
using HeuristicLab.Operators;
using HeuristicLab.Optimization;
using HeuristicLab.Optimization.Operators;
using HeuristicLab.Parameters;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
using HeuristicLab.Problems.TravelingSalesman;
namespace HeuristicLab.Analysis.AlgorithmBehavior.Analyzers {
[Item("CrossoverPerformanceAnalyzer", "An operator that analyzes the performance of crossovers.")]
[StorableClass]
public class CrossoverPerformanceAnalyzer : SingleSuccessorOperator, IAnalyzer {
private const string ResultsParameterName = "Results";
private const string GenerationsParameterName = "Generations";
#region IAnalyzer Members
public bool EnabledByDefault {
get { return true; }
}
#endregion
#region Parameter properties
public ILookupParameter ResultsParameter {
get { return (ILookupParameter)Parameters[ResultsParameterName]; }
}
public ILookupParameter GenerationsParameter {
get { return (ILookupParameter)Parameters[GenerationsParameterName]; }
}
public ILookupParameter> ParentsParameter {
get { return (ScopeTreeLookupParameter)Parameters["Parents"]; }
}
public ILookupParameter> ParentsQualityParameter {
get { return (ScopeTreeLookupParameter)Parameters["ParentsQuality"]; }
}
public ILookupParameter ChildParameter {
get { return ((LookupParameter)Parameters["Child"]); }
}
public ILookupParameter QualityParameter {
get { return (ILookupParameter)Parameters["Quality"]; }
}
public IValueParameter SimilarityCalculatorParameter {
get { return (IValueParameter)Parameters["SimilarityCalculator"]; }
}
#endregion
#region Properties
public ResultCollection Results {
get { return ResultsParameter.ActualValue; }
}
#endregion
[Storable]
private ScatterPlotHelper plotHelper, childDiversityHelper, parentDiversityHelper;
[Storable]
private DataTableHelper performanceHelper, successHelper, equalParentsHelper;
[Storable]
private int cnt = 0;
[Storable]
private int success = 0;
[Storable]
private int lastGeneration = 0;
[Storable]
private int equalParents = 0;
[Storable]
private List qualityPoints = new List();
[StorableConstructor]
private CrossoverPerformanceAnalyzer(bool deserializing) : base(deserializing) { }
private CrossoverPerformanceAnalyzer(CrossoverPerformanceAnalyzer original, Cloner cloner)
: base(original, cloner) {
cnt = original.cnt;
success = original.success;
lastGeneration = original.lastGeneration;
equalParents = original.equalParents;
qualityPoints = new List(original.qualityPoints);
plotHelper = (ScatterPlotHelper)original.plotHelper.Clone(cloner);
childDiversityHelper = (ScatterPlotHelper)original.childDiversityHelper.Clone(cloner);
parentDiversityHelper = (ScatterPlotHelper)original.parentDiversityHelper.Clone(cloner);
performanceHelper = (DataTableHelper)original.performanceHelper.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("Parents", "The parent permutations which have been crossed."));
ParentsParameter.ActualName = "TSPTour";
Parameters.Add(new LookupParameter("Child", "The child permutation resulting from the crossover."));
ChildParameter.ActualName = "TSPTour";
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"));
plotHelper = new ScatterPlotHelper(false, true);
childDiversityHelper = new ScatterPlotHelper(false, true);
parentDiversityHelper = new ScatterPlotHelper(false, true);
performanceHelper = new DataTableHelper();
successHelper = new DataTableHelper();
equalParentsHelper = new DataTableHelper();
}
public override IDeepCloneable Clone(Cloner cloner) {
return new CrossoverPerformanceAnalyzer(this, cloner);
}
public override IOperation Apply() {
SimilarityCalculatorParameter.Value.QualityVariableName = "TSPTourLength";
SimilarityCalculatorParameter.Value.SolutionVariableName = "TSPTour";
plotHelper.InitializePlot(Results, "Crossover Performance", "Solution Index", "Absolut Quality Difference");
childDiversityHelper.InitializePlot(Results, "Child Diversity", "Solution Index", "Diversity");
parentDiversityHelper.InitializePlot(Results, "Parent Diversity", "Solution Index", "Diversity");
performanceHelper.InitializeChart(Results, "Average Crossover Performance", "Average Crossover Performance per Generation");
successHelper.InitializeChart(Results, "Successfull Crossovers", "Successfull Crossovers per Generation");
equalParentsHelper.InitializeChart(Results, "Number of equal parents", "Absolut number of equal parents");
Point2D qualityPoint, diversityPointChild, diversityPointParent;
var qualityParent1 = ParentsQualityParameter.ActualValue.First().Value;
var qualityParent2 = ParentsQualityParameter.ActualValue.Last().Value;
var child = ChildParameter.ActualValue;
var parent1 = ParentsParameter.ActualValue.First();
var parent2 = ParentsParameter.ActualValue.Last();
var parentDiversity = SimilarityCalculatorParameter.Value.CalculateSolutionSimilarity(ExecutionContext.Scope.SubScopes.First(), ExecutionContext.Scope.SubScopes.Last());
string curGenStr = GenerationsParameter.ActualValue.Value.ToString();
diversityPointParent = new Point2D(cnt, parentDiversity);
double worseQuality = qualityParent1 > qualityParent2 ? qualityParent1 : qualityParent2;
if (qualityParent1 > qualityParent2) {
diversityPointChild = new Point2D(cnt, SimilarityCalculatorParameter.Value.CalculateSolutionSimilarity(ExecutionContext.Scope, ExecutionContext.Scope.SubScopes.First()));
} else {
diversityPointChild = new Point2D(cnt, SimilarityCalculatorParameter.Value.CalculateSolutionSimilarity(ExecutionContext.Scope, ExecutionContext.Scope.SubScopes.Last()));
}
qualityPoint = new Point2D(cnt++, worseQuality - QualityParameter.ActualValue.Value);
if ((worseQuality - QualityParameter.ActualValue.Value) > 0) {
success++;
}
qualityPoints.Add(qualityPoint.Y);
if (TSPSimilarityCalculator.CalculateSimilarity(parent1, parent2) == 1.0) {
equalParents++;
}
if (GenerationsParameter.ActualValue.Value != 0) {
if (GenerationsParameter.ActualValue.Value > lastGeneration) {
double avg = qualityPoints.Average();
performanceHelper.AddPoint(avg);
successHelper.AddPoint(success);
equalParentsHelper.AddPoint(equalParents);
Reset();
}
plotHelper.AddPoint(curGenStr, qualityPoint);
childDiversityHelper.AddPoint(curGenStr, diversityPointChild);
parentDiversityHelper.AddPoint(curGenStr, diversityPointParent);
} else {
Reset();
}
return base.Apply();
}
private void Reset() {
cnt = 0;
success = 0;
lastGeneration = GenerationsParameter.ActualValue.Value;
qualityPoints.Clear();
equalParents = 0;
}
}
}