Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2895_PushGP_GenealogyAnalysis/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/DoRangeExpressions.cs @ 16724

Last change on this file since 16724 was 15771, checked in by bburlacu, 7 years ago

#2895: Add solution skeleton for PushGP with genealogy analysis.

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