Free cookie consent management tool by TermsFeed Policy Generator

source: addons/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/DoRangeExpressions.cs @ 16958

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

#2665 Testet Problems, Testet error functions, Small fixes, Created HL files

File size: 6.8 KB
Line 
1namespace HeuristicLab.Problems.ProgramSynthesis.Push.Expressions {
2  using System;
3  using Attributes;
4  using Interpreter;
5  using Persistence.Default.CompositeSerializers.Storable;
6  using Stack;
7
8  /// <summary>
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.
20  /// </summary>
21  [Serializable]
22  [StorableClass]
23  [PushExpression(
24    StackTypes.Code,
25    "CODE.DO*RANGE",
26    "An iteration instruction that executes the top item on the CODE stack a number of times that depends on the top two integers, while also pushing the loop counter onto the INTEGER stack for possible access during the execution of the body of the loop.",
27    StackTypes.Integer)]
28  public class CodeDoRangeExpression : StatelessExpression {
29    public CodeDoRangeExpression() { }
30    [StorableConstructor]
31    protected CodeDoRangeExpression(bool deserializing) : base(deserializing) { }
32
33    public override bool IsNoop(IInternalPushInterpreter interpreter) {
34      return interpreter.IntegerStack.Count < 2 || interpreter.CodeStack.IsEmpty;
35    }
36
37    public override void Eval(IInternalPushInterpreter interpreter) {
38      var toDo = interpreter.CodeStack.Pop();
39      var currentIndex = interpreter.IntegerStack[1];
40      var destinationIndex = interpreter.IntegerStack[0];
41
42      interpreter.IntegerStack.Pop();
43
44      if (currentIndex != destinationIndex) {
45
46        var incrementor = currentIndex < destinationIndex ? 1 : -1;
47        var continuation = interpreter.PoolContainer.ExpressionListPool.Get();
48        var pool = interpreter.PoolContainer.GetStatefulExpressionPool<IntegerPushExpression>();
49
50        continuation.Add(this);
51        continuation.Add(toDo);
52        continuation.Add(ExpressionTable.GetStatelessExpression<CodeQuoteExpression>());
53        continuation.Add(IntegerPushExpression.Create(pool, destinationIndex));
54        continuation.Add(IntegerPushExpression.Create(pool, currentIndex + incrementor));
55
56        var program = PushProgram.Create(interpreter.PoolContainer.PushProgramPool, continuation);
57        interpreter.ExecStack.Push(program);
58      }
59
60      interpreter.ExecStack.Push(toDo);
61    }
62  }
63
64  /// <summary>
65  ///     An iteration instruction that executes the top item on the EXEC stack a number of times that depends on the top two
66  ///     integers, while also pushing the loop counter onto the INTEGER stack for possible access during the execution of the body of
67  ///     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
68  ///     "destination index" and the second integer is the "current index." Last the code and the integer arguments are
69  ///     saved locally and popped. Then the integers are compared. If the integers are equal then the current index is pushed onto the
70  ///     INTEGER stack and the code (which is the "body" of the loop) is pushed onto the EXEC stack for subsequent execution. If the
71  ///     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
72  ///     stack -- first a recursive call to EXEC.DO*RANGE (with the same code and destination index, but with a current index that
73  ///     has been either incremented or decremented by 1 to be closer to the destination index) and then the body code. Note that the
74  ///     range is inclusive of both endpoints; a call with integer arguments 3 and 5 will cause its body to be executed 3 times, with
75  ///     the loop counter having the values 3, 4, and 5. Note also that one can specify a loop that "counts down" by providing a
76  ///     destination index that is less than the specified current index.
77  /// </summary>
78  [Serializable]
79  [StorableClass]
80  [PushExpression(
81    stackType: StackTypes.Exec,
82    name: "EXEC.DO*RANGE",
83    description: "An iteration instruction that executes the top item on the EXEC stack a number of times that depends on the top two integers, while also pushing the loop counter onto the INTEGER stack for possible access during the execution of the body of the loop.",
84    additionalStackDependencies: StackTypes.Integer,
85    requiredBlockCount: 1)]
86  public class ExecDoRangeExpression : StatelessExpression {
87    public ExecDoRangeExpression() { }
88
89    [StorableConstructor]
90    protected ExecDoRangeExpression(bool deserializing) : base(deserializing) { }
91
92    public override bool IsNoop(IInternalPushInterpreter interpreter) {
93      return interpreter.IntegerStack.Count < 2 || interpreter.ExecStack.IsEmpty;
94    }
95
96    public override void Eval(IInternalPushInterpreter interpreter) {
97      var currentIndex = interpreter.IntegerStack[1];
98      var destinationIndex = interpreter.IntegerStack[0];
99
100      interpreter.IntegerStack.Pop();
101
102      if (currentIndex == destinationIndex)
103        return;
104
105      var toDo = interpreter.ExecStack.Top;
106      var incrementor = currentIndex < destinationIndex ? 1 : -1;
107      var continuation = interpreter.PoolContainer.ExpressionListPool.Get();
108      var pool = interpreter.PoolContainer.GetStatefulExpressionPool<IntegerPushExpression>();
109
110      continuation.Add(toDo);
111      continuation.Add(this);
112      continuation.Add(IntegerPushExpression.Create(pool, destinationIndex));
113      continuation.Add(IntegerPushExpression.Create(pool, currentIndex + incrementor));
114
115      interpreter.ExecStack.Top = PushProgram.Create(interpreter.PoolContainer.PushProgramPool, continuation);
116      interpreter.ExecStack.Push(toDo);
117    }
118  }
119}
Note: See TracBrowser for help on using the repository browser.