Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Crossovers/TracingSymbolicExpressionTreeCrossover.cs @ 12547

Last change on this file since 12547 was 9835, checked in by bburlacu, 11 years ago

#1772: Merged remaining trunk changes into the EvolutionaryTracking branch.

File size: 5.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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.Linq;
24using HeuristicLab.Common;
25using HeuristicLab.Core;
26using HeuristicLab.Parameters;
27using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
28
29namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding {
30  /// <summary>
31  /// A base class for operators that perform a crossover of symbolic expression trees.
32  /// </summary>
33  [Item("SymbolicExpressionTreeCrossover", "A base class for operators that perform a crossover of symbolic expression trees.")]
34  [StorableClass]
35  public abstract class TracingSymbolicExpressionTreeCrossover : TracingSymbolicExpressionTreeOperator, ISymbolicExpressionTreeCrossover {
36    private const string ParentsParameterName = "Parents";
37    private const string ChildParameterName = "Child";
38
39    #region Parameter Properties
40    public ILookupParameter<ItemArray<ISymbolicExpressionTree>> ParentsParameter {
41      get { return (ScopeTreeLookupParameter<ISymbolicExpressionTree>)Parameters[ParentsParameterName]; }
42    }
43    public ILookupParameter<ISymbolicExpressionTree> ChildParameter {
44      get { return (ILookupParameter<ISymbolicExpressionTree>)Parameters[ChildParameterName]; }
45    }
46    #endregion
47
48    #region Properties
49    public ItemArray<ISymbolicExpressionTree> Parents {
50      get { return ParentsParameter.ActualValue; }
51    }
52    public ISymbolicExpressionTree Child {
53      get { return ChildParameter.ActualValue; }
54      set { ChildParameter.ActualValue = value; }
55    }
56    #endregion
57
58    [StorableConstructor]
59    protected TracingSymbolicExpressionTreeCrossover(bool deserializing)
60      : base(deserializing) {
61    }
62    protected TracingSymbolicExpressionTreeCrossover(TracingSymbolicExpressionTreeCrossover original, Cloner cloner)
63      : base(original, cloner) {
64    }
65    protected TracingSymbolicExpressionTreeCrossover()
66      : base() {
67      Parameters.Add(new ScopeTreeLookupParameter<ISymbolicExpressionTree>(ParentsParameterName, "The parent symbolic expression trees which should be crossed."));
68      Parameters.Add(new LookupParameter<ISymbolicExpressionTree>(ChildParameterName, "The child symbolic expression tree resulting from the crossover."));
69    }
70    public override IOperation Apply() {
71      if (Parents.Length != 2)
72        throw new ArgumentException("Number of parents must be exactly two for symbolic expression tree crossover operators.");
73
74      AddTracingVariablesToGlobalScope();
75
76      // save the nodes of parent0 in a list so we can track what modifications are made by crossover
77      var nodes0 = Parents[0].IterateNodesPrefix().ToList();
78      var nodes1 = Parents[1].IterateNodesPrefix().ToList();
79
80      // perform crossover
81      Child = Crossover(Random, Parents[0], Parents[1]);
82
83      // create another list of parent0's nodes, so we can compare it with the first list to see what changed
84      var childNodes = Child.IterateNodesPrefix().ToList();
85
86      // compare the two node lists and check the difference (comparing node references so we avoid false functional identity).
87      int i = 0, min0 = Math.Min(nodes0.Count, childNodes.Count);
88      // find the index of the fragment (with respect to the prefix order of nodes) in Parent0
89      while (i < min0 && ReferenceEquals(nodes0[i], childNodes[i])) ++i;
90
91      var fragmentRoot = (i == min0) ? null : childNodes[i];
92      int j = 0;
93      // find the index of the fragment (with respect to the prefix order of nodes) in Parent1
94      while (j < nodes1.Count && !ReferenceEquals(nodes1[j], fragmentRoot)) ++j; // this works because the swapped subtree is not removed from the non-root parent
95
96      if (i < min0 && j < nodes1.Count && !ReferenceEquals(childNodes[i], nodes1[j])) {
97        throw new Exception("The two array elements should reference the same subtree.");
98      }
99
100      // map child to its corresponding parents from the previous generation
101      GlobalTraceMap[Child] = new ItemList<IItem>(from p in Parents select GlobalCloneMap[p]);
102      var fragment0 = new Fragment { Root = i == min0 ? null : nodes0[i], Index = i }; // fragment replaced in Parent0
103      var fragment1 = new Fragment { Root = fragmentRoot, Index = i, OldIndex = j }; // fragment received from Parent1
104      GlobalFragmentMap[Child] = fragment1; // map child to the index of its fragment
105      // transaction.FragmentIn = the fragment received from the other parent
106      // transaction.FragmentOut = the fragment that got replaced
107      GlobalGeneticExchangeMap.Add(new GeneticExchange { FragmentIn = fragment1, FragmentOut = fragment0 });
108      return base.Apply();
109    }
110
111    public abstract ISymbolicExpressionTree Crossover(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1);
112  }
113}
Note: See TracBrowser for help on using the repository browser.