Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/PushProgram.cs @ 14744

Last change on this file since 14744 was 14744, checked in by pkimmesw, 7 years ago

#2665 Renamings due to typos, ManagedPool tests, Skip Noops in Debugger

File size: 5.4 KB
Line 
1using System.Collections.Generic;
2
3namespace HeuristicLab.Problems.ProgramSynthesis.Push.Expressions {
4  using System.Diagnostics;
5  using System.Linq;
6
7  public class PushProgram {
8
9    private const string Prefix = "(";
10    private const string PrefixReduced = "[";
11    private const string Postfix = ")";
12    private const string PostfixReduced = "]";
13    private const string Delimiter = " ";
14
15    public static readonly PushProgram Empty = new PushProgram(new Expression[0]);
16
17    public readonly IReadOnlyList<Expression> Expressions;
18    public bool IsEmpty { get; private set; }
19
20    public PushProgram(Expression[] expressions) {
21      this.Expressions = expressions;
22      this.IsEmpty = expressions.Length == 0;
23    }
24
25    private string stringRepresentation;
26    private string StringRepresentation
27    {
28      get
29      {
30        if (string.IsNullOrEmpty(stringRepresentation))
31          stringRepresentation = BuildString();
32        return stringRepresentation;
33      }
34    }
35
36    private int depth = -1;
37    private int Depth
38    {
39      get
40      {
41        if (depth == -1) depth = CalcDepth();
42        return depth;
43      }
44    }
45
46    private int[] treeIndex = null;
47    public int[] TreeIndex
48    {
49      get
50      {
51        return this.treeIndex ?? (this.treeIndex = this.BuildTreeIndex());
52      }
53    }
54
55    private int hashCode;
56    private int HashCode
57    {
58      get
59      {
60        if (hashCode == default(int)) hashCode = HashExpressions();
61        return hashCode;
62      }
63    }
64
65    public override int GetHashCode() {
66      return HashCode;
67    }
68
69    public override string ToString() {
70      return this.StringRepresentation;
71    }
72
73    /// <summary>
74    /// Returns the amount of elements in the whole tree
75    /// </summary>
76    /// <returns></returns>
77    public int TotalCount
78    {
79      get
80      {
81        return this.IsEmpty
82            ? 1
83            // + 1 because "this" is also counted
84            : TreeIndex[0] + 1;
85      }
86    }
87
88    public IEnumerable<Expression> DepthFirst() {
89      foreach (var expr in this.Expressions) {
90        if (expr.CanExpand) {
91          var expandExpr = (ExecExpandExpression)expr;
92
93          foreach (var sub in expandExpr.State.DepthFirst())
94            yield return sub;
95        } else yield return expr;
96      }
97    }
98
99    public PushProgram Copy() {
100      return IsEmpty ? this : new PushProgram((Expression[])Expressions) {
101        stringRepresentation = this.stringRepresentation,
102        hashCode = this.hashCode,
103        depth = this.depth,
104        treeIndex = this.treeIndex
105      };
106    }
107
108    public Expression[] CopyExpressions() {
109      var copy = new Expression[this.Expressions.Count];
110      ((Expression[])this.Expressions).CopyTo(copy, Expressions.Count);
111
112      return copy;
113    }
114
115    private int CalcDepth() {
116      //var subExpressions = Expressions.Where(e => e.CanExpand);
117      //var depth = subExpressions.Any()
118      //    ? subExpressions.Select(e => e as ExecExpandExpression).Max(e => e.State.Depth) + 1
119      //    : 1;
120
121      ////return depth;
122
123      var maxDepth = 1;
124      for (var i = 0; i < Expressions.Count; i++) {
125        var expression = Expressions[i];
126        if (!expression.CanExpand) continue;
127        var expandExpression = (ExecExpandExpression)expression;
128
129        if (expandExpression.State.Depth > maxDepth)
130          maxDepth = expandExpression.State.Depth;
131      }
132
133      return maxDepth + 1;
134    }
135
136    private string BuildString() {
137      // prevent too big string
138      return this.TotalCount > 50
139        ? PrefixReduced + this.Expressions.Count + PostfixReduced
140        : Prefix + string.Join(Delimiter, this.Expressions.Where(e => !string.IsNullOrWhiteSpace(e.StringRepresentation))) + Postfix;
141    }
142
143    private int[] BuildTreeIndex() {
144      var local_treeIndex = new int[this.Expressions.Count];
145
146      var next = 1;
147
148      for (var i = this.Expressions.Count - 1; i >= 0; i--) {
149        var subExpression = this.Expressions[i];
150
151        local_treeIndex[i] = next;
152
153        if (subExpression.CanExpand) {
154          next += ((ExecExpandExpression)subExpression).State.TotalCount;
155        } else {
156          next++;
157        }
158      }
159
160      return local_treeIndex;
161    }
162
163    private int HashExpressions() {
164      var hash = 19 * 31 + this.GetType().FullName.GetHashCode();
165
166      for (var i = 0; i < this.Expressions.Count; i++) {
167        hash = hash * 31 + this.Expressions[i].GetHashCode();
168      }
169
170      return hash;
171    }
172
173    private static void CheckIfNested(int level, ExecExpandExpression target, ExecExpandExpression current,
174        IList<ExecExpandExpression> visited) {
175      if (visited.Any(x => ReferenceEquals(x, current)))
176        Debugger.Break();
177
178      visited.Add(current);
179      if (level <= 0) {
180        // hirarchy depth > level
181        Debugger.Break();
182        return;
183      }
184
185      for (var i = 0; i < current.State.Expressions.Count; i++) {
186        if (current.State.Expressions[i].CanExpand)
187          continue;
188
189        var subExpression = current.State.Expressions[i] as ExecExpandExpression;
190
191        if (ReferenceEquals(target, subExpression)) {
192          // Endless recursion dedected
193          Debugger.Break();
194        }
195
196        CheckIfNested(level - 1, target, subExpression, visited);
197      }
198
199      visited.RemoveAt(visited.Count - 1);
200    }
201  }
202}
Note: See TracBrowser for help on using the repository browser.