source: branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/DoRangeExpressions.cs @ 14834

Last change on this file since 14834 was 14834, checked in by pkimmesw, 3 years ago

#2665 LexicaseSelector, Performance improvements, UI Fixes, Debugger only shows used stacks, fixed Debugger stepping, Added vector expressions, ERCOptions,

File size: 5.7 KB
Line 
1namespace HeuristicLab.Problems.ProgramSynthesis.Push.Expressions {
2  using System;
3
4  using Attributes;
5  using Interpreter;
6  using Stack;
7
8  [Serializable]
9  public abstract class DoRangeExpression : LoopExpression {
10    protected DoRangeExpression() { }
11    protected DoRangeExpression(LoopState state) : base(state) { }
12    protected override bool HasInsufficientArguments(IInternalPushInterpreter interpreter, IPushStack<Expression> sourceStack) {
13      return interpreter.IntegerStack.Count < 2 ||
14             sourceStack.Count == 0 ||
15             interpreter.IntegerStack.Top == interpreter.IntegerStack.ReverseElementAt(1);
16    }
17
18    protected override LoopState InitState(IInternalPushInterpreter interpreter, IPushStack<Expression> sourceStack) {
19      var destinationIndex = interpreter.IntegerStack.Pop();
20      var incrementor = destinationIndex < interpreter.IntegerStack.Top ? -1 : 1;
21
22      return LoopState.Create(interpreter.PoolContainer.LoopStatePool,
23          body: sourceStack.Pop(),
24          currentIndex: interpreter.IntegerStack.Top + incrementor,
25          destinationIndex: destinationIndex,
26          incrementor: incrementor);
27    }
28  }
29
30  /// <summary>
31  ///     An iteration instruction that executes the top item on the CODE stack a number of times that depends on the
32  ///     top two integers, while also pushing the loop counter onto the INTEGER stack for possible access during the
33  ///     execution of
34  ///     the body of the loop. The top integer is the "destination index" and the second integer is the "current index."
35  ///     Last the code
36  ///     and the integer arguments are saved locally and popped. Then the integers are compared. If the integers are equal
37  ///     then the current
38  ///     index is pushed onto the INTEGER stack and the code (which is the "body" of the loop) is pushed onto the EXEC stack
39  ///     for subsequent
40  ///     execution. If the integers are not equal then the current index will still be pushed onto the INTEGER stack but two
41  ///     items will be
42  ///     pushed onto the EXEC stack -- first a recursive call to CODE.DO*RANGE (with the same code and destination index,
43  ///     but with a current
44  ///     index that has been either incremented or decremented by 1 to be closer to the destination index) and then the body
45  ///     code. Note that
46  ///     the range is inclusive of both endpoints; a call with integer arguments 3 and 5 will cause its body to be executed
47  ///     3 times, with the
48  ///     loop counter having the values 3, 4, and 5. Note also that one can specify a loop that "counts down" by providing a
49  ///     destination index
50  ///     that is less than the specified current index.
51  /// </summary>
52  [Serializable]
53  [PushExpression(StackTypes.Code, "CODE.DO*RANGE", StackTypes.Integer)]
54  public class CodeDoRangeExpression : DoRangeExpression {
55    public CodeDoRangeExpression() { }
56
57    public CodeDoRangeExpression(LoopState state) : base(state) { }
58    public override bool Eval(IInternalPushInterpreter interpreter) {
59      return this.Eval(interpreter, interpreter.CodeStack);
60    }
61
62    protected override LoopExpression Clone(LoopState state, IInternalPushInterpreter interpreter) {
63      var expression = interpreter.PoolContainer.GetStatefulExpression<CodeDoRangeExpression>();
64      expression.State = state;
65
66      return expression;
67    }
68  }
69
70  /// <summary>
71  ///     An iteration instruction that executes the top item on the EXEC stack a number of times that depends on the top two
72  ///     integers,
73  ///     while also pushing the loop counter onto the INTEGER stack for possible access during the execution of the body of
74  ///     the loop.
75  ///     This is similar to CODE.DO*COUNT except that it takes its code argument from the EXEC stack. The top integer is the
76  ///     "destination index" and the second integer is the "current index." Last the code and the integer arguments are
77  ///     saved locally
78  ///     and popped. Then the integers are compared. If the integers are equal then the current index is pushed onto the
79  ///     INTEGER stack
80  ///     and the code (which is the "body" of the loop) is pushed onto the EXEC stack for subsequent execution. If the
81  ///     integers are not
82  ///     equal then the current index will still be pushed onto the INTEGER stack but two items will be pushed onto the EXEC
83  ///     stack
84  ///     -- first a recursive call to EXEC.DO*RANGE (with the same code and destination index, but with a current index that
85  ///     has been
86  ///     either incremented or decremented by 1 to be closer to the destination index) and then the body code. Note that the
87  ///     range is
88  ///     inclusive of both endpoints; a call with integer arguments 3 and 5 will cause its body to be executed 3 times, with
89  ///     the loop
90  ///     counter having the values 3, 4, and 5. Note also that one can specify a loop that "counts down" by providing a
91  ///     destination
92  ///     index that is less than the specified current index.
93  /// </summary>
94  [Serializable]
95  [PushExpression(StackTypes.Exec, "EXEC.DO*RANGE", StackTypes.Integer)]
96  public class ExecDoRangeExpression : DoRangeExpression {
97    public ExecDoRangeExpression() { }
98
99    public ExecDoRangeExpression(LoopState state) : base(state) { }
100    public override bool Eval(IInternalPushInterpreter interpreter) {
101      return this.Eval(interpreter, interpreter.ExecStack);
102    }
103    protected override LoopExpression Clone(LoopState state, IInternalPushInterpreter interpreter) {
104      var expression = interpreter.PoolContainer.GetStatefulExpression<ExecDoRangeExpression>();
105      expression.State = state;
106
107      return expression;
108    }
109  }
110}
Note: See TracBrowser for help on using the repository browser.