#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.Analysis;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
using HeuristicLab.Optimization;
using HeuristicLab.Parameters;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
// type definitions for convenience
using CloneMapType = HeuristicLab.Core.ItemDictionary;
using TraceMapType = HeuristicLab.Core.ItemDictionary>;
namespace HeuristicLab.EvolutionaryTracking {
///
/// An operator that gathers information on tree fragments that get passed from one generation to the next via genetic operators
/// (Tracking of genetic variance and heredity)
///
[Item("SymbolicExpressionTreeRelativeFragmentDepthAnalyzer", "An operator that provides statistics about crossover fragments")]
[StorableClass]
public sealed class SymbolicExpressionTreeRelativeFragmentDepthAnalyzer : SymbolicExpressionTreeFragmentsAnalyzer {
private const string RelativeFragmentDepthParameterName = "Relative fragment depth";
public ILookupParameter RelativeFragmentDepthParameter { get { return (ILookupParameter)Parameters[RelativeFragmentDepthParameterName]; } }
public DataTable RelativeFragmentDepths {
get { return RelativeFragmentDepthParameter.ActualValue; }
set { RelativeFragmentDepthParameter.ActualValue = value; }
}
[StorableConstructor]
private SymbolicExpressionTreeRelativeFragmentDepthAnalyzer(bool deserializing) : base(deserializing) { }
private SymbolicExpressionTreeRelativeFragmentDepthAnalyzer(SymbolicExpressionTreeRelativeFragmentDepthAnalyzer original, Cloner cloner) : base(original, cloner) { }
public override IDeepCloneable Clone(Cloner cloner) {
return new SymbolicExpressionTreeRelativeFragmentDepthAnalyzer(this, cloner);
}
public SymbolicExpressionTreeRelativeFragmentDepthAnalyzer()
: base() {
#region Add parameters
Parameters.Add(new LookupParameter(RelativeFragmentDepthParameterName));
#endregion
UpdateCounterParameter.Hidden = true;
UpdateIntervalParameter.Hidden = true;
}
#region After deserialization code
[StorableHook(HookType.AfterDeserialization)]
private void AfterDeserialization() {
}
#endregion
#region IStatefulItem members
public override void InitializeState() {
base.InitializeState();
UpdateCounter.Value = 0;
}
public override void ClearState() {
base.ClearState();
UpdateCounter.Value = 0;
}
#endregion
public override IOperation Apply() {
UpdateCounter.Value++;
if (UpdateCounter.Value == UpdateInterval.Value) {
UpdateCounter.Value = 0; // reset counter
if (Generations.Value > 1) {
SecondaryTraceMap = SecondaryTraceMap ?? new TraceMapType();
SecondaryFragmentMap = SecondaryFragmentMap ?? new CloneMapType();
SecondaryCloneMap = SecondaryCloneMap ?? new CloneMapType();
InitializeParameters();
InitializeRows();
var fragmentDepths = (from m in SecondaryFragmentMap
let tree = (ISymbolicExpressionTree)m.Key
let fragment = (IFragment)m.Value
where fragment.Root != null
select tree.Root.GetBranchLevel(fragment.Root)
).ToList();
// fragments of selected offspring
var selected = new HashSet(GlobalTraceMap.Values.SelectMany(list => list.Cast()));
var goodFragmentDepths = (from m in SecondaryFragmentMap
let tree = (ISymbolicExpressionTree)m.Key
let fragment = (IFragment)m.Value
where fragment.Root != null
where selected.Contains(tree)
select tree.Root.GetBranchLevel(fragment.Root)
).ToList();
RelativeFragmentDepths.Rows["Average relative fragment depth (all)"].Values.Add(fragmentDepths.Count > 0 ? fragmentDepths.Average() : 0.0);
RelativeFragmentDepths.Rows["Average relative fragment depth (good)"].Values.Add(goodFragmentDepths.Count > 0 ? goodFragmentDepths.Average() : 0.0);
}
}
return base.Apply();
}
protected override void InitializeParameters() {
var results = ResultsParameter.ActualValue;
if (!results.ContainsKey("Relative fragment depths")) {
RelativeFragmentDepths = RelativeFragmentDepths ?? new DataTable("Relative fragment depths") { VisualProperties = { YAxisTitle = "Relative depth" } };
results.Add(new Result("Relative fragment depths", RelativeFragmentDepths));
}
base.InitializeParameters();
}
private void InitializeRows() {
string[] rowNames = { "Average relative fragment depth (good)", "Average relative fragment depth (all)" };
foreach (var rowName in rowNames.Where(rowName => !RelativeFragmentDepths.Rows.ContainsKey(rowName))) {
RelativeFragmentDepths.Rows.Add(new DataRow(rowName) { VisualProperties = { StartIndexZero = true } });
}
}
} //SymbolicExpressionTreeFragmentLengthAnalyzer
}