Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Manipulators/TracingSymbolicExpressionTreeManipulator.cs @ 9083

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

#1772: Merged HeuristicLab.Encodings.SymbolicExpressionTreeEncoding from trunk. Added Fragment class implementing IFragment interface.

File size: 7.3 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.Collections.Generic;
24using System.Linq;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Parameters;
28using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
29
30namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding {
31  /// <summary>
32  /// A base class for operators that manipulate real-valued vectors.
33  /// </summary>
34  [Item("TracingSymbolicExpressionTreeManipulator", "A base class for operators that manipulate symbolic expression trees.")]
35  [StorableClass]
36  public abstract class TracingSymbolicExpressionTreeManipulator : TracingSymbolicExpressionTreeOperator, ISymbolicExpressionTreeManipulator {
37    private const string SymbolicExpressionTreeParameterName = "SymbolicExpressionTree";
38    [Storable]
39    private readonly Dictionary<Type, byte> manipulationTypes = new Dictionary<Type, byte>();
40
41    #region Parameter Properties
42    public ILookupParameter<ISymbolicExpressionTree> SymbolicExpressionTreeParameter {
43      get { return (ILookupParameter<ISymbolicExpressionTree>)Parameters[SymbolicExpressionTreeParameterName]; }
44    }
45    #endregion
46
47    #region Properties
48    public ISymbolicExpressionTree SymbolicExpressionTree {
49      get { return SymbolicExpressionTreeParameter.ActualValue; }
50    }
51    #endregion
52
53    [StorableConstructor]
54    protected TracingSymbolicExpressionTreeManipulator(bool deserializing) : base(deserializing) { }
55    protected TracingSymbolicExpressionTreeManipulator(TracingSymbolicExpressionTreeManipulator original, Cloner cloner)
56      : base(original, cloner) {
57      this.manipulationTypes = new Dictionary<Type, byte>(original.manipulationTypes);
58    }
59    public TracingSymbolicExpressionTreeManipulator()
60      : base() {
61      Parameters.Add(new LookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName, "The symbolic expression tree on which the operator should be applied."));
62
63      manipulationTypes.Add(typeof(FullTreeShaker), ManipulationType.FullTreeShaker);
64      manipulationTypes.Add(typeof(OnePointShaker), ManipulationType.OnePointShaker);
65      manipulationTypes.Add(typeof(ChangeNodeTypeManipulation), ManipulationType.ChangeNodeTypeManipulation);
66      manipulationTypes.Add(typeof(ReplaceBranchManipulation), ManipulationType.ReplaceBranchManipulation);
67    }
68
69    public sealed override IOperation Apply() {
70      ISymbolicExpressionTree tree = SymbolicExpressionTreeParameter.ActualValue;
71
72      AddTracingVariablesToGlobalScope();
73
74      /* The following block needs to be explained in more detail;
75       * If the tree was already affected by crossover (before mutation), then:
76       * - it will already be contained in the GlobalTraceMap
77       * - In order to preserve information, a clone of the tree is created
78       * - The clone represents the intermediate stage of the tree, before mutation is applied
79       * - The clone therefore represents the child after crossover so GlobalTraceMap[clone] will get tree's parents
80       *   and GlobalFragmentMap[clone] will get the subtree from clone that represents the cloned fragment
81       * - After tree is mutated, we set GlobalTraceMap[tree] = clone and GlobalFragmentMap[tree] = modified node from tree
82       */
83      Fragment fragment = null;
84      if (GlobalTraceMap.ContainsKey(tree)) {
85        var clone = (IItem)tree.Clone();
86        GlobalCloneMap[clone] = GlobalCloneMap[tree];
87        GlobalCloneMap[tree] = clone;
88        GlobalTraceMap[clone] = GlobalTraceMap[tree]; // clone gets parents of tree
89        GlobalTraceMap[tree] = new ItemList<IItem> { clone }; // tree gets clone as parent
90        fragment = (Fragment)GlobalFragmentMap[tree];
91        int index = tree.IterateNodesBreadth().ToList().IndexOf(fragment.Root); // returns -1 if fragment is not present in tree (can happen if fragment is null)
92        GlobalFragmentMap[clone] = new Fragment(index == -1 ? null : ((ISymbolicExpressionTree)clone).IterateNodesBreadth().ElementAt(index));
93      } else {
94        GlobalTraceMap[tree] = new ItemList<IItem> { GlobalCloneMap[tree] };
95      }
96
97      var concreteType = this.GetType();
98
99      if (!manipulationTypes.ContainsKey(concreteType))
100        throw new Exception(this.Name + ": Unknown manipulation type (key not found in the dictionary).");
101
102      var nodes0 = tree.IterateNodesBreadth().ToList(); // list of nodes before manipulation
103      Manipulate(RandomParameter.ActualValue, tree);
104      var nodes1 = tree.IterateNodesBreadth().ToList(); // list of nodes after manipulation
105      int min = Math.Min(nodes0.Count, nodes1.Count);
106
107      switch (manipulationTypes[concreteType]) {
108        case ManipulationType.FullTreeShaker: {
109            // the FullTreeShaker changes the local parameters of all the nodes in the tree
110            // therefore, the whole tree is considered to be the fragment
111            fragment = new Fragment(tree.Root.GetSubtree(0).GetSubtree(0));
112            break;
113          }
114        case ManipulationType.OnePointShaker: {
115            var original = (ISymbolicExpressionTree)GlobalCloneMap[tree];
116            var nodesOriginal = original.IterateNodesBreadth().ToList();
117            int i = 0;
118            var comparer = SymbolicExpressionTreeNodeComparer;
119            while (i != min && comparer.Equals(nodesOriginal[i], nodes1[i])) ++i;
120            fragment = new Fragment(i == min ? null : nodes1[i], 1);
121            break;
122          }
123        case ManipulationType.ChangeNodeTypeManipulation: {
124            int i = 0;
125            while (i != min && ReferenceEquals(nodes0[i], nodes1[i])) ++i;
126            fragment = new Fragment(i == min ? null : nodes1[i], 1);
127            break;
128          }
129        case ManipulationType.ReplaceBranchManipulation: {
130            int i = 0;
131            while (i != min && ReferenceEquals(nodes0[i], nodes1[i])) ++i;
132            fragment = new Fragment(i == min ? null : nodes1[i]);
133            break;
134          }
135        default:
136          throw new Exception(Name + ": Unknown manipulaton type.");
137      }
138
139      GlobalFragmentMap[tree] = fragment;
140      return base.Apply();
141    }
142
143    protected abstract void Manipulate(IRandom random, ISymbolicExpressionTree symbolicExpressionTree);
144
145    private struct ManipulationType {
146      public const byte FullTreeShaker = 1;
147      public const byte OnePointShaker = 2;
148      public const byte ChangeNodeTypeManipulation = 3;
149      public const byte ReplaceBranchManipulation = 4;
150    }
151  }
152}
Note: See TracBrowser for help on using the repository browser.