#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.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;
// type definitions for ease of use
namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
///
/// Population diversity analyzer
///
[Item("SymbolicDataAnalysisPopulationDiversityAnalyzer", "An operator that tracks population diversity")]
[StorableClass]
public sealed class SymbolicDataAnalysisPopulationDiversityAnalyzer : SingleSuccessorOperator, IAnalyzer {
#region Parameter names
private const string MaximumSymbolicExpressionTreeDepthParameterName = "MaximumSymbolicExpressionTreeDepth";
private const string SymbolicExpressionTreeParameterName = "SymbolicExpressionTree";
private const string UpdateIntervalParameterName = "UpdateInterval";
private const string UpdateCounterParameterName = "UpdateCounter";
private const string ResultsParameterName = "Results";
private const string GenerationsParameterName = "Generations";
private const string StoreHistoryParameterName = "StoreHistory";
// comparer parameters
private const string SimilarityValuesParmeterName = "Similarity";
private const string DistanceCalculatorParameterName = "DistanceCalculator";
#endregion
#region Parameters
public IValueLookupParameter MaximumSymbolicExpressionTreeDepthParameter {
get { return (IValueLookupParameter)Parameters[MaximumSymbolicExpressionTreeDepthParameterName]; }
}
public ValueParameter UpdateIntervalParameter {
get { return (ValueParameter)Parameters[UpdateIntervalParameterName]; }
}
public ValueParameter UpdateCounterParameter {
get { return (ValueParameter)Parameters[UpdateCounterParameterName]; }
}
public LookupParameter ResultsParameter {
get { return (LookupParameter)Parameters[ResultsParameterName]; }
}
public LookupParameter GenerationsParameter {
get { return (LookupParameter)Parameters[GenerationsParameterName]; }
}
public ValueParameter StoreHistoryParameter {
get { return (ValueParameter)Parameters[StoreHistoryParameterName]; }
}
public IScopeTreeLookupParameter SymbolicExpressionTreeParameter {
get { return (IScopeTreeLookupParameter)Parameters[SymbolicExpressionTreeParameterName]; }
}
public ILookupParameter SimilarityParameter {
get { return (ILookupParameter)Parameters[SimilarityValuesParmeterName]; }
}
public IValueParameter DistanceCalculatorParameter {
get { return (IValueParameter)Parameters[DistanceCalculatorParameterName]; }
}
#endregion
#region Parameter properties
public IntValue MaximumSymbolicExpressionTreeDepth { get { return MaximumSymbolicExpressionTreeDepthParameter.ActualValue; } }
public IntValue UpdateInterval { get { return UpdateIntervalParameter.Value; } }
public IntValue UpdateCounter { get { return UpdateCounterParameter.Value; } }
public ResultCollection Results { get { return ResultsParameter.ActualValue; } }
public IntValue Generations { get { return GenerationsParameter.ActualValue; } }
public BoolValue StoreHistory { get { return StoreHistoryParameter.Value; } }
#endregion
[StorableConstructor]
private SymbolicDataAnalysisPopulationDiversityAnalyzer(bool deserializing)
: base(deserializing) {
}
private SymbolicDataAnalysisPopulationDiversityAnalyzer(
SymbolicDataAnalysisPopulationDiversityAnalyzer original, Cloner cloner)
: base(original, cloner) {
}
public override IDeepCloneable Clone(Cloner cloner) {
return new SymbolicDataAnalysisPopulationDiversityAnalyzer(this, cloner);
}
public SymbolicDataAnalysisPopulationDiversityAnalyzer() {
// add parameters
Parameters.Add(new ScopeTreeLookupParameter(SymbolicExpressionTreeParameterName, "The symbolic expression trees to analyze."));
Parameters.Add(new ValueParameter(UpdateIntervalParameterName, "The interval in which the tree length analysis should be applied.", new IntValue(1)));
Parameters.Add(new ValueParameter(UpdateCounterParameterName, "The value which counts how many times the operator was called since the last update", new IntValue(0)));
Parameters.Add(new ValueLookupParameter(ResultsParameterName, "The results collection where the analysis values should be stored."));
Parameters.Add(new LookupParameter(GenerationsParameterName, "The number of generations so far."));
Parameters.Add(new ValueParameter(StoreHistoryParameterName, "True if the tree lengths history of the population should be stored.", new BoolValue(false)));
Parameters.Add(new LookupParameter(SimilarityValuesParmeterName, ""));
Parameters.Add(new ValueLookupParameter(MaximumSymbolicExpressionTreeDepthParameterName, "The maximal depth of the symbolic expression tree (a tree with one node has depth = 0)."));
Parameters.Add(new ValueParameter(DistanceCalculatorParameterName, "The distance calculator between trees.", new BottomUpTreeDistanceCalculator()));
UpdateCounterParameter.Hidden = true;
UpdateIntervalParameter.Hidden = true;
}
[StorableHook(HookType.AfterDeserialization)]
private void AfterDeserialization() {
if (!Parameters.ContainsKey(MaximumSymbolicExpressionTreeDepthParameterName)) {
Parameters.Add(new ValueLookupParameter(MaximumSymbolicExpressionTreeDepthParameterName, "The maximal depth of the symbolic expression tree (a tree with one node has depth = 0)."));
}
}
#region IStatefulItem members
public override void InitializeState() {
UpdateCounter.Value = 0;
base.InitializeState();
}
#endregion
public bool EnabledByDefault {
get { return true; }
}
public override IOperation Apply() {
if (SimilarityParameter.ActualValue == null || SimilarityParameter.ActualValue.Value.IsAlmost(-1.0)) {
UpdateCounter.Value++;
if (UpdateCounter.Value != UpdateInterval.Value) return base.Apply();
UpdateCounter.Value = 0;
var trees = SymbolicExpressionTreeParameter.ActualValue.ToList();
SimilarityParameter.ActualValue = new DoubleValue();
var operations = new OperationCollection { Parallel = true };
foreach (var tree in trees) {
var op = new SymbolicDataAnalysisExpressionTreeSimilarityCalculator(DistanceCalculatorParameter.Value) {
CurrentSymbolicExpressionTree = tree,
MaximumTreeDepth = MaximumSymbolicExpressionTreeDepth.Value
};
var operation = ExecutionContext.CreateChildOperation(op, ExecutionContext.Scope);
operations.Add(operation);
}
return new OperationCollection { operations, ExecutionContext.CreateOperation(this) };
}
var results = ResultsParameter.ActualValue;
// population diversity
DataTable populationDiversityTable;
if (!results.ContainsKey("PopulationDiversity")) {
populationDiversityTable = new DataTable("PopulationDiversity") { VisualProperties = { YAxisTitle = "Diversity" } };
results.Add(new Result("PopulationDiversity", populationDiversityTable));
}
populationDiversityTable = (DataTable)results["PopulationDiversity"].Value;
if (!populationDiversityTable.Rows.ContainsKey("Diversity"))
populationDiversityTable.Rows.Add(new DataRow("Diversity") { VisualProperties = { StartIndexZero = true } });
int length = SymbolicExpressionTreeParameter.ActualValue.Length;
var similarity = SimilarityParameter.ActualValue.Value / (length * (length - 1) / 2.0);
var diversity = 1 - similarity;
SimilarityParameter.ActualValue.Value = -1.0;
populationDiversityTable.Rows["Diversity"].Values.Add(diversity);
return base.Apply();
}
}
}