Free cookie consent management tool by TermsFeed Policy Generator

source: branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/SymbolicExpressionTreeNode.cs @ 17039

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

#1772: Merge trunk changes

File size: 7.4 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 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 HeuristicLab.Common;
25using HeuristicLab.Core;
26using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
27
28namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding {
29  [StorableClass]
30  public class SymbolicExpressionTreeNode : DeepCloneable, ISymbolicExpressionTreeNode {
31    [Storable]
32    private IList<ISymbolicExpressionTreeNode> subtrees;
33    [Storable]
34    private ISymbol symbol;
35
36    // cached values to prevent unnecessary tree iterations
37    private ushort length;
38    private ushort depth;
39
40    public ISymbol Symbol {
41      get { return symbol; }
42      protected set { symbol = value; }
43    }
44
45    [Storable]
46    private ISymbolicExpressionTreeNode parent;
47    public ISymbolicExpressionTreeNode Parent {
48      get { return parent; }
49      set { parent = value; }
50    }
51
52    [Storable]
53    public double NodeWeight { get; set; }
54
55    [StorableConstructor]
56    protected SymbolicExpressionTreeNode(bool deserializing) { }
57    protected SymbolicExpressionTreeNode(SymbolicExpressionTreeNode original, Cloner cloner)
58      : base(original, cloner) {
59      symbol = original.symbol; // symbols are reused
60      length = original.length;
61      depth = original.depth;
62      NodeWeight = original.NodeWeight;
63      if (original.subtrees != null) {
64        subtrees = new List<ISymbolicExpressionTreeNode>(original.subtrees.Count);
65        foreach (var subtree in original.subtrees) {
66          var clonedSubtree = cloner.Clone(subtree);
67          subtrees.Add(clonedSubtree);
68          clonedSubtree.Parent = this;
69        }
70      }
71    }
72    public override IDeepCloneable Clone(Cloner cloner) {
73      return new SymbolicExpressionTreeNode(this, cloner);
74    }
75
76    internal SymbolicExpressionTreeNode()
77      : base() {
78      // don't allocate subtrees list here!
79      // because we don't want to allocate it in terminal nodes
80    }
81
82    public SymbolicExpressionTreeNode(ISymbol symbol)
83      : base() {
84      subtrees = new List<ISymbolicExpressionTreeNode>(3);
85      this.symbol = symbol;
86    }
87
88
89    [StorableHook(HookType.AfterDeserialization)]
90    private void AfterDeserialization() {
91      if (subtrees != null) {
92        foreach (var subtree in subtrees)
93          if (subtree.Parent == null)
94            subtree.Parent = this;
95      }
96    }
97
98    public virtual bool HasLocalParameters {
99      get { return false; }
100    }
101
102    public virtual IEnumerable<ISymbolicExpressionTreeNode> Subtrees {
103      get { return subtrees; }
104    }
105
106    public virtual ISymbolicExpressionTreeGrammar Grammar {
107      get { return parent.Grammar; }
108    }
109
110    public int GetLength() {
111      if (length > 0) return length;
112      else {
113        ushort l = 1;
114        if (subtrees != null) {
115          for (int i = 0; i < subtrees.Count; i++) {
116            checked { l += (ushort)subtrees[i].GetLength(); }
117          }
118        }
119        length = l;
120        return length;
121      }
122    }
123
124    public int GetDepth() {
125      if (depth > 0) return depth;
126      else {
127        ushort d = 0;
128        if (subtrees != null) {
129          for (int i = 0; i < subtrees.Count; i++) d = Math.Max(d, (ushort)subtrees[i].GetDepth());
130        }
131        d++;
132        depth = d;
133        return depth;
134      }
135    }
136
137    public int GetBranchLevel(ISymbolicExpressionTreeNode child) {
138      return GetBranchLevel(this, child);
139    }
140
141    private static int GetBranchLevel(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode point) {
142      if (root == point)
143        return 0;
144      foreach (var subtree in root.Subtrees) {
145        int branchLevel = GetBranchLevel(subtree, point);
146        if (branchLevel < int.MaxValue)
147          return 1 + branchLevel;
148      }
149      return int.MaxValue;
150    }
151
152    public virtual void ResetLocalParameters(IRandom random) { }
153    public virtual void ShakeLocalParameters(IRandom random, double shakingFactor) { }
154
155    public int SubtreeCount {
156      get {
157        if (subtrees == null) return 0;
158        return subtrees.Count;
159      }
160    }
161
162    public virtual ISymbolicExpressionTreeNode GetSubtree(int index) {
163      return subtrees[index];
164    }
165    public virtual int IndexOfSubtree(ISymbolicExpressionTreeNode tree) {
166      return subtrees.IndexOf(tree);
167    }
168    public virtual void AddSubtree(ISymbolicExpressionTreeNode tree) {
169      subtrees.Add(tree);
170      tree.Parent = this;
171      ResetCachedValues();
172    }
173    public virtual void InsertSubtree(int index, ISymbolicExpressionTreeNode tree) {
174      subtrees.Insert(index, tree);
175      tree.Parent = this;
176      ResetCachedValues();
177    }
178    public virtual void RemoveSubtree(int index) {
179      subtrees[index].Parent = null;
180      subtrees.RemoveAt(index);
181      ResetCachedValues();
182    }
183
184    public IEnumerable<ISymbolicExpressionTreeNode> IterateNodesBreadth() {
185      var list = new List<ISymbolicExpressionTreeNode>(GetLength()) { this };
186      int i = 0;
187      while (i != list.Count) {
188        for (int j = 0; j != list[i].SubtreeCount; ++j)
189          list.Add(list[i].GetSubtree(j));
190        ++i;
191      }
192      return list;
193    }
194
195    public IEnumerable<ISymbolicExpressionTreeNode> IterateNodesPrefix() {
196      List<ISymbolicExpressionTreeNode> list = new List<ISymbolicExpressionTreeNode>();
197      ForEachNodePrefix((n) => list.Add(n));
198      return list;
199    }
200
201    public void ForEachNodePrefix(Action<ISymbolicExpressionTreeNode> a) {
202      a(this);
203      if (subtrees != null) {
204        //avoid linq to reduce memory pressure
205        for (int i = 0; i < subtrees.Count; i++) {
206          subtrees[i].ForEachNodePrefix(a);
207        }
208      }
209    }
210
211    public IEnumerable<ISymbolicExpressionTreeNode> IterateNodesPostfix() {
212      List<ISymbolicExpressionTreeNode> list = new List<ISymbolicExpressionTreeNode>();
213      ForEachNodePostfix((n) => list.Add(n));
214      return list;
215    }
216
217    public void ForEachNodePostfix(Action<ISymbolicExpressionTreeNode> a) {
218      if (subtrees != null) {
219        //avoid linq to reduce memory pressure
220        for (int i = 0; i < subtrees.Count; i++) {
221          subtrees[i].ForEachNodePostfix(a);
222        }
223      }
224      a(this);
225    }
226
227    public override string ToString() {
228      if (Symbol != null) return Symbol.Name;
229      return "SymbolicExpressionTreeNode";
230    }
231
232    private void ResetCachedValues() {
233      length = 0; depth = 0;
234      SymbolicExpressionTreeNode parentNode = parent as SymbolicExpressionTreeNode;
235      if (parentNode != null) parentNode.ResetCachedValues();
236    }
237  }
238}
Note: See TracBrowser for help on using the repository browser.