Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDiversityPreservingCrossover.cs @ 16565

Last change on this file since 16565 was 16565, checked in by gkronber, 5 years ago

#2520: merged changes from PersistenceOverhaul branch (r16451:16564) into trunk

File size: 6.9 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4
5using HeuristicLab.Common;
6using HeuristicLab.Core;
7using HeuristicLab.Data;
8using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
9using HeuristicLab.Parameters;
10using HEAL.Attic;
11using HeuristicLab.Random;
12using static HeuristicLab.Problems.DataAnalysis.Symbolic.SymbolicExpressionHashExtensions;
13
14namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
15  [Item("DiversityCrossover", "Simple crossover operator prioritizing internal nodes according to the given probability.")]
16  [StorableType("ED35B0D9-9704-4D32-B10B-8F9870E76781")]
17  public sealed class SymbolicDataAnalysisExpressionDiversityPreservingCrossover<T> : SymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData {
18
19    private const string InternalCrossoverPointProbabilityParameterName = "InternalCrossoverPointProbability";
20    private const string WindowingParameterName = "Windowing";
21    private const string ProportionalSamplingParameterName = "ProportionalSampling";
22
23    private static readonly Func<byte[], ulong> hashFunction = HashUtil.JSHash;
24
25    #region Parameter Properties
26    public IValueLookupParameter<PercentValue> InternalCrossoverPointProbabilityParameter {
27      get { return (IValueLookupParameter<PercentValue>)Parameters[InternalCrossoverPointProbabilityParameterName]; }
28    }
29
30    public IValueLookupParameter<BoolValue> WindowingParameter {
31      get { return (IValueLookupParameter<BoolValue>)Parameters[WindowingParameterName]; }
32    }
33
34    public IValueLookupParameter<BoolValue> ProportionalSamplingParameter {
35      get { return (IValueLookupParameter<BoolValue>)Parameters[ProportionalSamplingParameterName]; }
36    }
37    #endregion
38
39    #region Properties
40    public PercentValue InternalCrossoverPointProbability {
41      get { return InternalCrossoverPointProbabilityParameter.ActualValue; }
42    }
43
44    public BoolValue Windowing {
45      get { return WindowingParameter.ActualValue; }
46    }
47
48    public BoolValue ProportionalSampling {
49      get { return ProportionalSamplingParameter.ActualValue; }
50    }
51    #endregion
52
53    public SymbolicDataAnalysisExpressionDiversityPreservingCrossover() {
54      name = "DiversityCrossover";
55      Parameters.Add(new ValueLookupParameter<PercentValue>(InternalCrossoverPointProbabilityParameterName, "The probability to select an internal crossover point (instead of a leaf node).", new PercentValue(0.9)));
56      Parameters.Add(new ValueLookupParameter<BoolValue>(WindowingParameterName, "Use proportional sampling with windowing for cutpoint selection.", new BoolValue(false)));
57      Parameters.Add(new ValueLookupParameter<BoolValue>(ProportionalSamplingParameterName, "Select cutpoints proportionally using probabilities as weights instead of randomly.", new BoolValue(true)));
58    }
59
60    private SymbolicDataAnalysisExpressionDiversityPreservingCrossover(SymbolicDataAnalysisExpressionDiversityPreservingCrossover<T> original, Cloner cloner) : base(original, cloner) {
61    }
62
63    public override IDeepCloneable Clone(Cloner cloner) {
64      return new SymbolicDataAnalysisExpressionDiversityPreservingCrossover<T>(this, cloner);
65    }
66
67    [StorableConstructor]
68    private SymbolicDataAnalysisExpressionDiversityPreservingCrossover(StorableConstructorFlag _) : base(_) { }
69
70    private static ISymbolicExpressionTreeNode ActualRoot(ISymbolicExpressionTree tree) {
71      return tree.Root.GetSubtree(0).GetSubtree(0);
72    }
73
74    public static ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1, double internalCrossoverPointProbability, int maxLength, int maxDepth, bool windowing, bool proportionalSampling = false) {
75      var leafCrossoverPointProbability = 1 - internalCrossoverPointProbability;
76
77      var nodes0 = ActualRoot(parent0).MakeNodes().Sort(hashFunction);
78      var nodes1 = ActualRoot(parent1).MakeNodes().Sort(hashFunction);
79
80      IList<HashNode<ISymbolicExpressionTreeNode>> sampled0;
81      IList<HashNode<ISymbolicExpressionTreeNode>> sampled1;
82
83      if (proportionalSampling) {
84        var p = internalCrossoverPointProbability;
85        var weights0 = nodes0.Select(x => x.IsLeaf ? 1 - p : p);
86        sampled0 = nodes0.SampleProportionalWithoutRepetition(random, nodes0.Length, weights0, windowing: windowing).ToArray();
87
88        var weights1 = nodes1.Select(x => x.IsLeaf ? 1 - p : p);
89        sampled1 = nodes1.SampleProportionalWithoutRepetition(random, nodes1.Length, weights1, windowing: windowing).ToArray();
90      } else {
91        sampled0 = ChooseNodes(random, nodes0, internalCrossoverPointProbability).ShuffleInPlace(random);
92        sampled1 = ChooseNodes(random, nodes1, internalCrossoverPointProbability).ShuffleInPlace(random);
93      }
94
95      foreach (var selected in sampled0) {
96        var cutpoint = new CutPoint(selected.Data.Parent, selected.Data);
97
98        var maxAllowedDepth = maxDepth - parent0.Root.GetBranchLevel(selected.Data);
99        var maxAllowedLength = maxLength - (parent0.Length - selected.Data.GetLength());
100
101        foreach (var candidate in sampled1) {
102          if (candidate.CalculatedHashValue == selected.CalculatedHashValue
103            || candidate.Data.GetDepth() > maxAllowedDepth
104            || candidate.Data.GetLength() > maxAllowedLength
105            || !cutpoint.IsMatchingPointType(candidate.Data)) {
106            continue;
107          }
108
109          Swap(cutpoint, candidate.Data);
110          return parent0;
111        }
112      }
113      return parent0;
114    }
115
116    public override ISymbolicExpressionTree Crossover(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) {
117      if (this.ExecutionContext == null) {
118        throw new InvalidOperationException("ExecutionContext not set.");
119      }
120
121      var maxDepth = MaximumSymbolicExpressionTreeDepth.Value;
122      var maxLength = MaximumSymbolicExpressionTreeLength.Value;
123
124      var internalCrossoverPointProbability = InternalCrossoverPointProbability.Value;
125      var windowing = Windowing.Value;
126      var proportionalSampling = ProportionalSampling.Value;
127
128      return Cross(random, parent0, parent1, internalCrossoverPointProbability, maxLength, maxDepth, windowing, proportionalSampling);
129    }
130
131    private static List<HashNode<ISymbolicExpressionTreeNode>> ChooseNodes(IRandom random, IEnumerable<HashNode<ISymbolicExpressionTreeNode>> nodes, double internalCrossoverPointProbability) {
132      var list = new List<HashNode<ISymbolicExpressionTreeNode>>();
133
134      var chooseInternal = random.NextDouble() < internalCrossoverPointProbability;
135
136      if (chooseInternal) {
137        list.AddRange(nodes.Where(x => !x.IsLeaf && x.Data.Parent != null));
138      }
139      if (!chooseInternal || list.Count == 0) {
140        list.AddRange(nodes.Where(x => x.IsLeaf && x.Data.Parent != null));
141      }
142
143      return list;
144    }
145  }
146}
Note: See TracBrowser for help on using the repository browser.