source: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisGeneticOperatorImprovementAnalyzer.cs @ 12966

Last change on this file since 12966 was 12966, checked in by bburlacu, 6 years ago

#1772: Fixed unit test errors.

File size: 9.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System.Linq;
23using HeuristicLab.Analysis;
24using HeuristicLab.Common;
25using HeuristicLab.Core;
26using HeuristicLab.Data;
27using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
28using HeuristicLab.EvolutionTracking;
29using HeuristicLab.Optimization;
30using HeuristicLab.Parameters;
31using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
32
33namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Analyzers {
34  [StorableClass]
35  [Item("SymbolicDataAnalysisGeneticOperatorImprovementAnalyzer", "An analyzer which records the best and average genetic operator improvement")]
36  public class SymbolicDataAnalysisGeneticOperatorImprovementAnalyzer : EvolutionTrackingAnalyzer<ISymbolicExpressionTree> {
37    public const string QualityParameterName = "Quality";
38    public const string PopulationParameterName = "SymbolicExpressionTree";
39    public const string CountIntermediateChildrenParameterName = "CountIntermediateChildren";
40
41    public IScopeTreeLookupParameter<DoubleValue> QualityParameter {
42      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters[QualityParameterName]; }
43    }
44
45    public IScopeTreeLookupParameter<ISymbolicExpressionTree> PopulationParameter {
46      get { return (IScopeTreeLookupParameter<ISymbolicExpressionTree>)Parameters[PopulationParameterName]; }
47    }
48
49    public IFixedValueParameter<BoolValue> CountIntermediateChildrenParameter {
50      get { return (IFixedValueParameter<BoolValue>)Parameters[CountIntermediateChildrenParameterName]; }
51    }
52
53    public bool CountIntermediateChildren {
54      get { return CountIntermediateChildrenParameter.Value.Value; }
55      set { CountIntermediateChildrenParameter.Value.Value = value; }
56    }
57
58    public SymbolicDataAnalysisGeneticOperatorImprovementAnalyzer() {
59      Parameters.Add(new ScopeTreeLookupParameter<ISymbolicExpressionTree>(PopulationParameterName, "The population of individuals."));
60      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>(QualityParameterName, "The individual qualities."));
61      Parameters.Add(new FixedValueParameter<BoolValue>(CountIntermediateChildrenParameterName, "Specifies whether to consider intermediate children (when crossover was followed by mutation). This should be set to false for offspring selection.", new BoolValue(true)));
62
63      CountIntermediateChildrenParameter.Hidden = true;
64    }
65
66
67    [StorableConstructor]
68    protected SymbolicDataAnalysisGeneticOperatorImprovementAnalyzer(bool deserializing) : base(deserializing) { }
69
70    public SymbolicDataAnalysisGeneticOperatorImprovementAnalyzer(
71    SymbolicDataAnalysisGeneticOperatorImprovementAnalyzer original, Cloner cloner) : base(original, cloner) {
72      CountIntermediateChildren = original.CountIntermediateChildren;
73    }
74
75    public override IDeepCloneable Clone(Cloner cloner) {
76      return new SymbolicDataAnalysisGeneticOperatorImprovementAnalyzer(this, cloner);
77    }
78
79    [StorableHook(HookType.AfterDeserialization)]
80    private void AfterDeserialization() {
81      if (!Parameters.ContainsKey(CountIntermediateChildrenParameterName))
82        Parameters.Add(new FixedValueParameter<BoolValue>(CountIntermediateChildrenParameterName, "Specifies whether to consider intermediate children (when crossover was followed by mutation", new BoolValue(true)));
83      CountIntermediateChildrenParameter.Hidden = true;
84    }
85
86    public override IOperation Apply() {
87      IntValue updateCounter = UpdateCounterParameter.ActualValue;
88      if (updateCounter == null) {
89        updateCounter = new IntValue(0);
90        UpdateCounterParameter.ActualValue = updateCounter;
91      }
92      updateCounter.Value++;
93      if (updateCounter.Value != UpdateInterval.Value) return base.Apply();
94      updateCounter.Value = 0;
95
96      var graph = PopulationGraph;
97      if (graph == null || Generation.Value == 0)
98        return base.Apply();
99
100      var generation = Generation.Value;
101      var averageQuality = QualityParameter.ActualValue.Average(x => x.Value);
102      var population = PopulationParameter.ActualValue;
103      var populationSize = population.Length;
104
105      var vertices = population.Select(graph.GetByContent).ToList();
106      DataTable table;
107      double aac = 0; // ratio of above average children produced
108      double aacp = 0; // ratio of above average children from above average parents
109      #region crossover improvement
110      if (!Results.ContainsKey("Crossover improvement")) {
111        table = new DataTable("Crossover improvement");
112        Results.Add(new Result("Crossover improvement", table));
113        table.Rows.AddRange(new[]
114          {
115              new DataRow("Average crossover improvement (root parent)") { VisualProperties = { StartIndexZero = true } },
116              new DataRow("Average crossover improvement (non-root parent)") { VisualProperties = { StartIndexZero = true } },
117              new DataRow("Average child-parents quality difference") { VisualProperties = { StartIndexZero = true } },
118              new DataRow("Best crossover improvement (root parent)") { VisualProperties = { StartIndexZero = true } },
119              new DataRow("Best crossover improvement (non-root parent)") { VisualProperties = { StartIndexZero = true }},
120              new DataRow("Above average children") { VisualProperties = { StartIndexZero = true }},
121              new DataRow("Above average children from above average parents") { VisualProperties = { StartIndexZero = true } },
122            });
123      } else {
124        table = (DataTable)Results["Crossover improvement"].Value;
125      }
126      var crossoverChildren = vertices.Where(x => x.InDegree == 2).ToList();
127      if (CountIntermediateChildren)
128        crossoverChildren.AddRange(vertices.Where(x => x.InDegree == 1).Select(v => v.Parents.First()).Where(p => p.Rank.IsAlmost(generation - 0.5))); // add intermediate children
129
130      foreach (var c in crossoverChildren) {
131        if (c.Quality > averageQuality) {
132          aac++;
133          if (c.Parents.All(x => x.Quality > averageQuality))
134            aacp++;
135        }
136      }
137      var avgRootParentQualityImprovement = crossoverChildren.Average(x => x.Quality - x.Parents.First().Quality);
138      var avgNonRootParentQualityImprovement = crossoverChildren.Average(x => x.Quality - x.Parents.Last().Quality);
139      var avgChildParentQuality = crossoverChildren.Average(x => x.Quality - x.Parents.Average(p => p.Quality));
140      var bestRootParentQualityImprovement = crossoverChildren.Max(x => x.Quality - x.Parents.First().Quality);
141      var bestNonRootParentQualityImprovement = crossoverChildren.Max(x => x.Quality - x.Parents.Last().Quality);
142      table.Rows["Average crossover improvement (root parent)"].Values.Add(avgRootParentQualityImprovement);
143      table.Rows["Average crossover improvement (non-root parent)"].Values.Add(avgNonRootParentQualityImprovement);
144      table.Rows["Best crossover improvement (root parent)"].Values.Add(bestRootParentQualityImprovement);
145      table.Rows["Best crossover improvement (non-root parent)"].Values.Add(bestNonRootParentQualityImprovement);
146      table.Rows["Average child-parents quality difference"].Values.Add(avgChildParentQuality);
147      table.Rows["Above average children"].Values.Add(aac / populationSize);
148      table.Rows["Above average children from above average parents"].Values.Add(aacp / populationSize);
149      #endregion
150
151      #region mutation improvement
152      if (!Results.ContainsKey("Mutation improvement")) {
153        table = new DataTable("Mutation improvement");
154        Results.Add(new Result("Mutation improvement", table));
155        table.Rows.AddRange(new[]
156          {
157              new DataRow("Average mutation improvement") { VisualProperties = { StartIndexZero = true } },
158              new DataRow("Best mutation improvement") { VisualProperties = { StartIndexZero = true } },
159              new DataRow("Above average children") { VisualProperties = { StartIndexZero = true } },
160              new DataRow("Above average children from above average parents") { VisualProperties = { StartIndexZero = true } },
161            });
162      } else {
163        table = (DataTable)Results["Mutation improvement"].Value;
164      }
165
166      aac = 0;
167      aacp = 0;
168      var mutationChildren = vertices.Where(x => x.InDegree == 1).ToList();
169
170      foreach (var c in mutationChildren) {
171        if (c.Quality > averageQuality) {
172          aac++;
173          if (c.Parents.All(x => x.Quality > averageQuality))
174            aacp++;
175        }
176      }
177      var avgMutationImprovement = mutationChildren.Average(x => x.Quality - x.Parents.First().Quality);
178      var bestMutationImprovement = mutationChildren.Max(x => x.Quality - x.Parents.First().Quality);
179
180      table.Rows["Average mutation improvement"].Values.Add(avgMutationImprovement);
181      table.Rows["Best mutation improvement"].Values.Add(bestMutationImprovement);
182      table.Rows["Above average children"].Values.Add(aac / populationSize);
183      table.Rows["Above average children from above average parents"].Values.Add(aacp / populationSize);
184      #endregion
185      return base.Apply();
186    }
187  }
188}
Note: See TracBrowser for help on using the repository browser.