#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 }