Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
03/11/17 12:42:31 (7 years ago)
Author:
pkimmesw
Message:

#2665 Merged ExecExpandExpression and PushProgram due to performance reasons, Tested managed object pooling

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/PushProgram.cs

    r14744 r14745  
    1 using System.Collections.Generic;
     1using System;
     2using System.Collections.Generic;
     3using System.Linq;
    24
    35namespace HeuristicLab.Problems.ProgramSynthesis.Push.Expressions {
    46  using System.Diagnostics;
    5   using System.Linq;
    6 
    7   public class PushProgram {
     7
     8  using Interpreter;
     9
     10  public class PushProgram : StatefulExpression<Expression[]> {
     11    public static readonly PushProgram Empty = new PushProgram();
    812
    913    private const string Prefix = "(";
     
    1317    private const string Delimiter = " ";
    1418
    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;
     19    public readonly bool IsEmpty;
     20
     21    public PushProgram(params Expression[] state) : base(state) {
     22      IsEmpty = state.Length == 0;
     23    }
     24
     25    public PushProgram(IEnumerable<Expression> state) : this(state.ToArray()) {
     26      // TODO: lazy evaluation of ToArray()
    2327    }
    2428
    2529    private string stringRepresentation;
    26     private string StringRepresentation
     30    public override string StringRepresentation
    2731    {
    2832      get
     
    3539
    3640    private int depth = -1;
    37     private int Depth
     41    public int Depth
    3842    {
    3943      get
     
    4448    }
    4549
    46     private int[] treeIndex = null;
    47     public int[] TreeIndex
    48     {
    49       get
    50       {
    51         return this.treeIndex ?? (this.treeIndex = this.BuildTreeIndex());
     50    private int[] treeIndex;
     51    private int[] TreeIndex
     52    {
     53      get
     54      {
     55        return treeIndex ?? (treeIndex = BuildTreeIndex());
    5256      }
    5357    }
     
    6165        return hashCode;
    6266      }
     67    }
     68
     69    //public PushProgram Copy() {
     70    //  // as the empty list is a static stateless expression, no copy required
     71    //  return ReferenceEquals(this, Empty) || this.State.IsEmpty
     72    //    ? Empty
     73    //    : new PushProgram(this.State.Copy());
     74    //}
     75
     76    public override bool Eval(IPushInterpreter interpreter) {
     77      interpreter.ExecStack.Push(this.State);
     78      return true;
    6379    }
    6480
     
    87103
    88104    public IEnumerable<Expression> DepthFirst() {
    89       foreach (var expr in this.Expressions) {
     105      foreach (var expr in this.State) {
    90106        if (expr.CanExpand) {
    91           var expandExpr = (ExecExpandExpression)expr;
    92 
    93           foreach (var sub in expandExpr.State.DepthFirst())
     107          var expandExpr = (PushProgram)expr;
     108
     109          foreach (var sub in expandExpr.DepthFirst())
    94110            yield return sub;
    95111        } else yield return expr;
     
    98114
    99115    public PushProgram Copy() {
    100       return IsEmpty ? this : new PushProgram((Expression[])Expressions) {
     116      return IsEmpty ? this : new PushProgram(State) {
    101117        stringRepresentation = this.stringRepresentation,
    102118        hashCode = this.hashCode,
     
    106122    }
    107123
    108     public Expression[] CopyExpressions() {
    109       var copy = new Expression[this.Expressions.Count];
    110       ((Expression[])this.Expressions).CopyTo(copy, Expressions.Count);
     124    public Expression[] CopyExpressions()
     125    {
     126      if (IsEmpty) return Empty.State;
     127
     128      var copy = new Expression[State.Length];
     129      State.CopyTo(copy, 0);
    111130
    112131      return copy;
     
    114133
    115134    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 
    123135      var maxDepth = 1;
    124       for (var i = 0; i < Expressions.Count; i++) {
    125         var expression = Expressions[i];
     136      for (var i = 0; i < State.Length; i++) {
     137        var expression = State[i];
    126138        if (!expression.CanExpand) continue;
    127         var expandExpression = (ExecExpandExpression)expression;
    128 
    129         if (expandExpression.State.Depth > maxDepth)
    130           maxDepth = expandExpression.State.Depth;
     139        var expandExpression = (PushProgram)expression;
     140
     141        if (expandExpression.Depth > maxDepth)
     142          maxDepth = expandExpression.Depth;
    131143      }
    132144
     
    137149      // prevent too big string
    138150      return this.TotalCount > 50
    139         ? PrefixReduced + this.Expressions.Count + PostfixReduced
    140         : Prefix + string.Join(Delimiter, this.Expressions.Where(e => !string.IsNullOrWhiteSpace(e.StringRepresentation))) + Postfix;
     151        ? PrefixReduced + this.State.Length + PostfixReduced
     152        : Prefix + string.Join(Delimiter, this.State.Where(e => !string.IsNullOrWhiteSpace(e.StringRepresentation))) + Postfix;
    141153    }
    142154
    143155    private int[] BuildTreeIndex() {
    144       var local_treeIndex = new int[this.Expressions.Count];
     156      var local_treeIndex = new int[State.Length];
    145157
    146158      var next = 1;
    147159
    148       for (var i = this.Expressions.Count - 1; i >= 0; i--) {
    149         var subExpression = this.Expressions[i];
     160      for (var i = State.Length - 1; i >= 0; i--) {
     161        var subExpression = State[i];
    150162
    151163        local_treeIndex[i] = next;
    152164
    153165        if (subExpression.CanExpand) {
    154           next += ((ExecExpandExpression)subExpression).State.TotalCount;
     166          next += ((PushProgram)subExpression).TotalCount;
    155167        } else {
    156168          next++;
     
    164176      var hash = 19 * 31 + this.GetType().FullName.GetHashCode();
    165177
    166       for (var i = 0; i < this.Expressions.Count; i++) {
    167         hash = hash * 31 + this.Expressions[i].GetHashCode();
     178      for (var i = 0; i < State.Length; i++) {
     179        hash = hash * 31 + State[i].GetHashCode();
    168180      }
    169181
     
    171183    }
    172184
    173     private static void CheckIfNested(int level, ExecExpandExpression target, ExecExpandExpression current,
    174         IList<ExecExpandExpression> visited) {
     185    private static void CheckIfNested(int level, PushProgram target, PushProgram current,
     186        IList<PushProgram> visited) {
    175187      if (visited.Any(x => ReferenceEquals(x, current)))
    176188        Debugger.Break();
     
    183195      }
    184196
    185       for (var i = 0; i < current.State.Expressions.Count; i++) {
    186         if (current.State.Expressions[i].CanExpand)
     197      for (var i = 0; i < current.State.Length; i++) {
     198        if (current.State[i].CanExpand)
    187199          continue;
    188200
    189         var subExpression = current.State.Expressions[i] as ExecExpandExpression;
     201        var subExpression = current.State[i] as PushProgram;
    190202
    191203        if (ReferenceEquals(target, subExpression)) {
     
    199211      visited.RemoveAt(visited.Count - 1);
    200212    }
     213
     214    /// <summary>
     215    ///     Returns the element with the given index whereby the tree is indexed in depth first manner
     216    /// </summary>
     217    /// <param name="index">The index of the required element</param>
     218    /// <returns>The required element</returns>
     219    public Expression GetFromTree(int index) {
     220      return GetFromTree(index, (root, parent, child, childIndex, parentIndex) => child);
     221    }
     222
     223    /// <returns>The required element</returns>
     224    public T GetFromTree<T>(int index,
     225        Func<PushProgram, PushProgram, Expression, int, int, T> resolver) {
     226      return GetFromTree(index, 0, null, resolver);
     227    }
     228
     229    private T GetFromTree<T>(int index, int parentIndex, PushProgram parent,
     230        Func<PushProgram, PushProgram, Expression, int, int, T> resolver) {
     231      if (index == 0) return resolver(parent, parent, this, 0, parentIndex);
     232
     233      var min = State.Length - 1;
     234      var max = 0;
     235      var mid = (min + max) / 2;
     236
     237      while ((max <= min) && (TreeIndex[mid] != index)) {
     238        if (TreeIndex[mid] > index) max = mid + 1;
     239        else min = mid - 1;
     240
     241        mid = (min + max) / 2;
     242      }
     243
     244      return TreeIndex[mid] == index
     245          ? resolver(parent, this, State[mid], mid, parentIndex)
     246          : (State[mid + 1] as PushProgram).GetFromTree(index - TreeIndex[mid + 1], mid + 1,
     247              this, resolver);
     248    }
    201249  }
    202250}
Note: See TracChangeset for help on using the changeset viewer.