Free cookie consent management tool by TermsFeed Policy Generator

source: branches/gp-crossover/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover.cs @ 7035

Last change on this file since 7035 was 7035, checked in by bburlacu, 12 years ago

#1682: Added base class SymbolicDataAnalysisExpressionCrossover for data analysis crossovers (crossovers that also perform evaluation for computing distance metrics). Made adjustments to other classes to accommodate the new crossovers (some methods became more general and were moved), changes affect CutPoint.cs, SubtreeCrossover.cs, SymbolicExpressionTreeNode.cs and others.

File size: 7.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 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;
23using System.Collections.Generic;
24using System.Linq;
25using System.Text;
26using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
30using HeuristicLab.Data;
31
32namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
33
34  [Item("ProbabilisticFunctionalCrossover", "An operator which performs subtree swapping based on behavioral similarity")]
35  public sealed class SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover<T> : SymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData
36  {
37    [StorableConstructor]
38    private SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover(bool deserializing) : base(deserializing) { }
39    private SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover(SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover<T> original, Cloner cloner)
40      : base(original, cloner) {
41    }
42    public SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover()
43      : base() {
44    }
45    public override IDeepCloneable Clone(Cloner cloner) {
46      return new SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover<T>(this, cloner);
47    }
48    protected override ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) {
49      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter = SymbolicDataAnalysisTreeInterpreterParameter.ActualValue;
50      IEnumerable<int> rows = GenerateRowsToEvaluate();
51      T problemData = ProblemDataParameter.ActualValue;
52      return Cross(random, parent0, parent1, interpreter, problemData, rows, MaximumSymbolicExpressionTreeDepth.Value, MaximumSymbolicExpressionTreeLength.Value);
53    }
54
55    /// <summary>
56    /// Takes two parent individuals P0 and P1.
57    /// Randomly choose a node i from the first parent, then for each matching node j from the second parent, calculate the behavioral distance based on the range:
58    /// d(i,j) = 0.5 * ( abs(max(i) - max(j)) + abs(min(i) - min(j)) ).
59    /// Next, assign probabilities for the selection of the second cross point based on the inversed and normalized behavioral distance and
60    /// choose the second crosspoint via a random weighted selection procedure.
61    /// </summary>
62    public static ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1,
63                                                ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, T problemData, IEnumerable<int> rows, int maxDepth, int maxLength) {
64      List<CutPoint> crossoverPoints0 = new List<CutPoint>();
65      parent0.Root.ForEachNodePostfix((n) => {
66        if (n.Subtrees.Any() && n != parent0.Root)
67          foreach (var child in n.Subtrees)
68            crossoverPoints0.Add(new CutPoint(n, child));
69      });
70      CutPoint crossoverPoint0 = crossoverPoints0[random.Next(crossoverPoints0.Count)];
71      int level = parent0.Root.GetBranchLevel(crossoverPoint0.Child);
72      int length = parent0.Root.GetLength() - crossoverPoint0.Child.GetLength();
73
74      List<ISymbolicExpressionTreeNode> allowedBranches = new List<ISymbolicExpressionTreeNode>();
75      parent1.Root.ForEachNodePostfix((n) => {
76        if (n.Subtrees.Any() && n != parent1.Root)
77          foreach (var child in n.Subtrees)
78            if (crossoverPoint0.IsMatchingPointType(child) && (child.GetDepth() + level <= maxDepth) && (child.GetLength() + length <= maxLength))
79              allowedBranches.Add(n);
80      });
81
82      // check if empty branch is allowed
83      if (crossoverPoint0.IsMatchingPointType(null)) allowedBranches.Add(null);
84
85      if (allowedBranches.Count == 0)
86        return parent0;
87
88      var dataset = problemData.Dataset;
89
90      // create symbols in order to improvize an ad-hoc tree so that the child can be evaluated
91      var rootSymbol = new ProgramRootSymbol();
92      var startSymbol = new StartSymbol();
93      var tree0 = CreateTreeFromNode(random, crossoverPoint0.Child, rootSymbol, startSymbol);
94      IEnumerable<double> estimatedValues0 = interpreter.GetSymbolicExpressionTreeValues(tree0, dataset, rows);
95      double min0 = estimatedValues0.Min();
96      double max0 = estimatedValues0.Max();
97
98      List<double> weights = new List<double>();
99      foreach (var node in allowedBranches) {
100        var tree1 = CreateTreeFromNode(random, node, rootSymbol, startSymbol);
101        IEnumerable<double> estimatedValues1 = interpreter.GetSymbolicExpressionTreeValues(tree1, dataset, rows);
102        double min1 = estimatedValues1.Min();
103        double max1 = estimatedValues1.Max();
104
105        double behavioralDistance = (Math.Abs(min0 - min1) + Math.Abs(max0 - max1)) / 2;
106
107        weights.Add(behavioralDistance);
108      }
109
110      ISymbolicExpressionTreeNode selectedBranch = SelectRandomBranch(random, allowedBranches, weights);
111
112      // perform the actual swap
113      if (crossoverPoint0.Child != null) {
114        // manipulate the tree of parent0 in place
115        // replace the branch in tree0 with the selected branch from tree1
116        crossoverPoint0.Parent.RemoveSubtree(crossoverPoint0.ChildIndex);
117        if (selectedBranch != null) {
118          crossoverPoint0.Parent.InsertSubtree(crossoverPoint0.ChildIndex, selectedBranch);
119        }
120      } else {
121        // child is null (additional child should be added under the parent)
122        if (selectedBranch != null) {
123          crossoverPoint0.Parent.AddSubtree(selectedBranch);
124        }
125      }
126
127      return parent0;
128    }
129
130    private static ISymbolicExpressionTreeNode SelectRandomBranch(IRandom random, List<ISymbolicExpressionTreeNode> nodes, List<double> weights) {
131      // transform similarity distances into probabilities by normalizing and inverting the values
132      double sum = weights.Sum();
133      for (int i = 0; i != weights.Count; ++i)
134        weights[i] = (1 - weights[i] / sum);
135      double r = weights.Sum() * random.NextDouble();
136      for (int i = 0; i != nodes.Count; ++i) {
137        if (r < weights[i])
138          return nodes[i];       
139        r -= weights[i];
140      }
141      return null;
142    }
143  }
144}
Note: See TracBrowser for help on using the repository browser.