Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
06/01/17 09:28:34 (7 years ago)
Author:
pkimmesw
Message:

#2665 Fixed Benchmark Problem Definition, Converted LoopExpressions to stateless expressions, Added several unit test to ensure funcionality, Fixed UI bugs

File:
1 edited

Legend:

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

    r14952 r15017  
    11namespace HeuristicLab.Problems.ProgramSynthesis.Push.Expressions {
    22  using System;
    3 
    43  using Attributes;
    5 
    6   using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
    7 
    84  using Interpreter;
     5  using Persistence.Default.CompositeSerializers.Storable;
    96  using Stack;
    107
    11   [Serializable]
    12   [StorableClass]
    13   public abstract class DoRangeExpression : LoopExpression {
    14     protected DoRangeExpression() { }
    15     protected DoRangeExpression(LoopState state) : base(state) { }
    16     [StorableConstructor]
    17     protected DoRangeExpression(bool deserializing) : base(deserializing) { }
    18 
    19     protected override bool HasInsufficientArguments(IInternalPushInterpreter interpreter, IPushStack<Expression> sourceStack) {
    20       return interpreter.IntegerStack.Count < 2 ||
    21              sourceStack.Count == 0 ||
    22              interpreter.IntegerStack.Top == interpreter.IntegerStack[1];
    23     }
    24 
    25     protected override LoopState InitState(IInternalPushInterpreter interpreter, IPushStack<Expression> sourceStack) {
    26       var destinationIndex = interpreter.IntegerStack.Pop();
    27       var incrementor = destinationIndex < interpreter.IntegerStack.Top ? -1 : 1;
    28 
    29       return LoopState.Create(interpreter.PoolContainer.LoopStatePool,
    30           body: sourceStack.Pop(),
    31           currentIndex: interpreter.IntegerStack.Top + incrementor,
    32           destinationIndex: destinationIndex,
    33           incrementor: incrementor);
    34     }
    35   }
    36 
    378  /// <summary>
    38   ///     An iteration instruction that executes the top item on the CODE stack a number of times that depends on the
    39   ///     top two integers, while also pushing the loop counter onto the INTEGER stack for possible access during the
    40   ///     execution of
    41   ///     the body of the loop. The top integer is the "destination index" and the second integer is the "current index."
    42   ///     Last the code
    43   ///     and the integer arguments are saved locally and popped. Then the integers are compared. If the integers are equal
    44   ///     then the current
    45   ///     index is pushed onto the INTEGER stack and the code (which is the "body" of the loop) is pushed onto the EXEC stack
    46   ///     for subsequent
    47   ///     execution. If the integers are not equal then the current index will still be pushed onto the INTEGER stack but two
    48   ///     items will be
    49   ///     pushed onto the EXEC stack -- first a recursive call to CODE.DO*RANGE (with the same code and destination index,
    50   ///     but with a current
    51   ///     index that has been either incremented or decremented by 1 to be closer to the destination index) and then the body
    52   ///     code. Note that
    53   ///     the range is inclusive of both endpoints; a call with integer arguments 3 and 5 will cause its body to be executed
    54   ///     3 times, with the
    55   ///     loop counter having the values 3, 4, and 5. Note also that one can specify a loop that "counts down" by providing a
    56   ///     destination index
    57   ///     that is less than the specified current index.
     9  /// An iteration instruction that executes the top item on the CODE stack a number of times that depends on the
     10  /// top two integers, while also pushing the loop counter onto the INTEGER stack for possible access during the
     11  /// execution of the body of the loop. The top integer is the "destination index" and the second integer is the "current index."
     12  /// Last the code and the integer arguments are saved locally and popped. Then the integers are compared. If the integers are equal
     13  /// then the current index is pushed onto the INTEGER stack and the code (which is the "body" of the loop) is pushed onto the EXEC stack
     14  /// for subsequent execution. If the integers are not equal then the current index will still be pushed onto the INTEGER stack but two
     15  /// items will be pushed onto the EXEC stack -- first a recursive call to CODE.DO*RANGE (with the same code and destination index,
     16  /// but with a current index that has been either incremented or decremented by 1 to be closer to the destination index) and then the body
     17  /// code. Note that the range is inclusive of both endpoints; a call with integer arguments 3 and 5 will cause its body to be executed
     18  /// 3 times, with the loop counter having the values 3, 4, and 5. Note also that one can specify a loop that "counts down" by providing a
     19  /// destination index that is less than the specified current index.
    5820  /// </summary>
    5921  [Serializable]
    6022  [StorableClass]
    6123  [PushExpression(StackTypes.Code, "CODE.DO*RANGE", StackTypes.Integer)]
    62   public class CodeDoRangeExpression : DoRangeExpression {
     24  public class CodeDoRangeExpression : StatelessExpression {
    6325    public CodeDoRangeExpression() { }
    64     public CodeDoRangeExpression(LoopState state) : base(state) { }
    6526    [StorableConstructor]
    6627    protected CodeDoRangeExpression(bool deserializing) : base(deserializing) { }
    6728
    6829    public override bool IsNoop(IInternalPushInterpreter interpreter) {
    69       return State.Body == null && HasInsufficientArguments(interpreter, interpreter.CodeStack);
     30      return interpreter.IntegerStack.Count < 2 || interpreter.CodeStack.IsEmpty;
    7031    }
    7132
    7233    public override void Eval(IInternalPushInterpreter interpreter) {
    73       Eval(interpreter, interpreter.CodeStack);
    74     }
     34      var toDo = interpreter.CodeStack.Pop();
     35      var currentIndex = interpreter.IntegerStack[1];
     36      var destinationIndex = interpreter.IntegerStack[0];
    7537
    76     protected override LoopExpression Clone(LoopState state, IInternalPushInterpreter interpreter) {
    77       var expression = interpreter.PoolContainer.GetStatefulExpression<CodeDoRangeExpression>();
    78       expression.State = state;
     38      interpreter.IntegerStack.Pop();
    7939
    80       return expression;
     40      if (currentIndex != destinationIndex) {
     41
     42        var incrementor = currentIndex < destinationIndex ? 1 : -1;
     43        var continuation = interpreter.PoolContainer.ExpressionListPool.Get();
     44        var pool = interpreter.PoolContainer.GetStatefulExpressionPool<IntegerPushExpression>();
     45
     46        continuation.Add(this);
     47        continuation.Add(toDo);
     48        continuation.Add(ExpressionTable.GetStatelessExpression<CodeQuoteExpression>());
     49        continuation.Add(IntegerPushExpression.Create(pool, destinationIndex));
     50        continuation.Add(IntegerPushExpression.Create(pool, currentIndex + incrementor));
     51
     52        var program = PushProgram.Create(interpreter.PoolContainer.PushProgramPool, continuation);
     53        interpreter.ExecStack.Push(program);
     54      }
     55
     56      interpreter.ExecStack.Push(toDo);
    8157    }
    8258  }
     
    8460  /// <summary>
    8561  ///     An iteration instruction that executes the top item on the EXEC stack a number of times that depends on the top two
    86   ///     integers,
    87   ///     while also pushing the loop counter onto the INTEGER stack for possible access during the execution of the body of
    88   ///     the loop.
    89   ///     This is similar to CODE.DO*COUNT except that it takes its code argument from the EXEC stack. The top integer is the
     62  ///     integers, while also pushing the loop counter onto the INTEGER stack for possible access during the execution of the body of
     63  ///     the loop. This is similar to CODE.DO*COUNT except that it takes its code argument from the EXEC stack. The top integer is the
    9064  ///     "destination index" and the second integer is the "current index." Last the code and the integer arguments are
    91   ///     saved locally
    92   ///     and popped. Then the integers are compared. If the integers are equal then the current index is pushed onto the
    93   ///     INTEGER stack
    94   ///     and the code (which is the "body" of the loop) is pushed onto the EXEC stack for subsequent execution. If the
    95   ///     integers are not
    96   ///     equal then the current index will still be pushed onto the INTEGER stack but two items will be pushed onto the EXEC
    97   ///     stack
    98   ///     -- first a recursive call to EXEC.DO*RANGE (with the same code and destination index, but with a current index that
    99   ///     has been
    100   ///     either incremented or decremented by 1 to be closer to the destination index) and then the body code. Note that the
    101   ///     range is
    102   ///     inclusive of both endpoints; a call with integer arguments 3 and 5 will cause its body to be executed 3 times, with
    103   ///     the loop
    104   ///     counter having the values 3, 4, and 5. Note also that one can specify a loop that "counts down" by providing a
    105   ///     destination
    106   ///     index that is less than the specified current index.
     65  ///     saved locally and popped. Then the integers are compared. If the integers are equal then the current index is pushed onto the
     66  ///     INTEGER stack and the code (which is the "body" of the loop) is pushed onto the EXEC stack for subsequent execution. If the
     67  ///     integers are not equal then the current index will still be pushed onto the INTEGER stack but two items will be pushed onto the EXEC
     68  ///     stack -- first a recursive call to EXEC.DO*RANGE (with the same code and destination index, but with a current index that
     69  ///     has been either incremented or decremented by 1 to be closer to the destination index) and then the body code. Note that the
     70  ///     range is inclusive of both endpoints; a call with integer arguments 3 and 5 will cause its body to be executed 3 times, with
     71  ///     the loop counter having the values 3, 4, and 5. Note also that one can specify a loop that "counts down" by providing a
     72  ///     destination index that is less than the specified current index.
    10773  /// </summary>
    10874  [Serializable]
    10975  [StorableClass]
    110   [PushExpression(StackTypes.Exec, "EXEC.DO*RANGE", StackTypes.Integer)]
    111   public class ExecDoRangeExpression : DoRangeExpression {
     76  [PushExpression(StackTypes.Exec, "EXEC.DO*RANGE", StackTypes.Integer, execIn: 1)]
     77  public class ExecDoRangeExpression : StatelessExpression {
    11278    public ExecDoRangeExpression() { }
    11379
    114     public ExecDoRangeExpression(LoopState state) : base(state) { }
    11580    [StorableConstructor]
    11681    protected ExecDoRangeExpression(bool deserializing) : base(deserializing) { }
    11782
    11883    public override bool IsNoop(IInternalPushInterpreter interpreter) {
    119       return State.Body == null && HasInsufficientArguments(interpreter, interpreter.ExecStack);
     84      return interpreter.IntegerStack.Count < 2 || interpreter.ExecStack.IsEmpty;
    12085    }
    12186
    12287    public override void Eval(IInternalPushInterpreter interpreter) {
    123       Eval(interpreter, interpreter.ExecStack);
    124     }
    125     protected override LoopExpression Clone(LoopState state, IInternalPushInterpreter interpreter) {
    126       var expression = interpreter.PoolContainer.GetStatefulExpression<ExecDoRangeExpression>();
    127       expression.State = state;
     88      var currentIndex = interpreter.IntegerStack[1];
     89      var destinationIndex = interpreter.IntegerStack[0];
    12890
    129       return expression;
     91      interpreter.IntegerStack.Pop();
     92
     93      if (currentIndex == destinationIndex)
     94        return;
     95
     96      var toDo = interpreter.ExecStack.Top;
     97      var incrementor = currentIndex < destinationIndex ? 1 : -1;
     98      var continuation = interpreter.PoolContainer.ExpressionListPool.Get();
     99      var pool = interpreter.PoolContainer.GetStatefulExpressionPool<IntegerPushExpression>();
     100
     101      continuation.Add(toDo);
     102      continuation.Add(this);
     103      continuation.Add(IntegerPushExpression.Create(pool, destinationIndex));
     104      continuation.Add(IntegerPushExpression.Create(pool, currentIndex + incrementor));
     105
     106      interpreter.ExecStack.Top = PushProgram.Create(interpreter.PoolContainer.PushProgramPool, continuation);
     107      interpreter.ExecStack.Push(toDo);
    130108    }
    131109  }
Note: See TracChangeset for help on using the changeset viewer.