Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PushGP/HeuristicLab.Algorithms.PushGP/HeuristicLab.Algorithms.PushGP/Expressions/ExecExpressions.cs @ 14392

Last change on this file since 14392 was 14392, checked in by pkimmesw, 8 years ago

#2665 Full Push 3.0 instruction set and tests; Added first benchmark test (count odds) for random walk tests;

File size: 8.1 KB
Line 
1using System.Collections.Generic;
2using System.Linq;
3using System.Text;
4using HeuristicLab.Algorithms.PushGP.Interpreter;
5using HeuristicLab.Common;
6
7namespace HeuristicLab.Algorithms.PushGP.Expressions
8{
9    public class ExecExpandExpression : Expression
10    {
11        private const string prefix = "( ";
12        private const string postfix = ")";
13        private const string delimiter = " ";
14
15        public readonly Expression[] Expressions;
16        private List<Expression> treeIndex;
17
18        public static readonly Expression Empty = new ExecExpandExpression(new Expression[0]);
19
20        public ExecExpandExpression(Expression[] expressions) : base()
21        {
22            this.Expressions = expressions;
23        }
24
25        // copy constructor
26        public ExecExpandExpression(ExecExpandExpression expression, Cloner cloner) : base(expression, cloner)
27        {
28            this.Expressions = expression.Expressions;
29            this.treeIndex = expression.treeIndex;
30        }
31
32        /// <summary>
33        /// Use this method to ensure the amount of expressions is not higher than the limit configured (Configuration.MaxPointsInProgram)
34        /// </summary>
35        /// <param name="expressions"></param>
36        /// <param name="config"></param>
37        /// <returns>Returns an ExpandExpression if maxPoints smaller or equal to Configuration.MaxProgramPoints and Noop otherwise</returns>
38        public static Expression TryCreate(Expression[] expressions, Configuration config)
39        {
40            if (config.MaxPointsInProgram > expressions.Length)
41            {
42                return new ExecExpandExpression(expressions);
43            }
44            else
45            {
46                return new CodeNoopExpression();
47            }
48        }
49
50        private string GetStringRepresentation()
51        {
52            if (this.StringRepresentation == null)
53            {
54                var sb = new StringBuilder();
55
56                sb.Append(prefix);
57
58                for (var i = this.Expressions.Length - 1; i >= 0; i--)
59                {
60                    sb.Append(this.Expressions[i].ToString() + delimiter);
61                }
62
63                sb.Append(postfix);
64
65                this.StringRepresentation = sb.ToString();
66            }
67
68            return this.StringRepresentation;
69        }
70
71        public override IDeepCloneable Clone(Cloner cloner)
72        {
73            return new ExecExpandExpression(this, cloner);
74        }
75
76        public override bool Equals(object obj)
77        {
78            if (obj == null || obj.GetType() != typeof(ExecExpandExpression))
79            {
80                return false;
81            }
82
83            if (ReferenceEquals(this, obj))
84            {
85                return true;
86            }
87
88            var other = obj as ExecExpandExpression;
89
90            return this.Expressions.SequenceEqual(other.Expressions);
91        }
92
93        public override string ToString()
94        {
95            return this.GetStringRepresentation();
96        }
97
98        public override void Eval(IInterpreter interpreter)
99        {
100            interpreter.ExecStack.Push(this.Expressions);
101        }
102
103        /// <summary>
104        /// Returns the amount of elements in the whole tree
105        /// </summary>
106        /// <returns></returns>
107        public int TotalCount
108        {
109            get
110            {
111                this.BuildIndexIfNecessary();
112
113                return this.treeIndex.Count;
114            }
115        }
116
117        /// <summary>
118        /// Returns the element with the given index whereby the tree is indexed in depth first manner
119        /// </summary>
120        /// <param name="index">The index of the required element</param>
121        /// <returns>The required element</returns>
122        public Expression GetFromTree(int index)
123        {
124            this.BuildIndexIfNecessary();
125
126            return this.treeIndex[index];
127        }
128
129        private void BuildIndexIfNecessary()
130        {
131            if (this.treeIndex != null)
132                return;
133
134            this.treeIndex = new List<Expression>(this.Expressions.Length) { this };
135
136            for (var i = this.Expressions.Length - 1; i >= 0; i--)
137            {
138                var subExpression = this.Expressions[i];
139
140                if (subExpression.GetType() == typeof(ExecExpandExpression))
141                {
142                    var list = subExpression as ExecExpandExpression;
143
144                    list.BuildIndexIfNecessary();
145                    this.treeIndex.AddRange(list.treeIndex);
146                }
147                else
148                {
149                    this.treeIndex.Add(subExpression);
150                }
151
152            }
153        }
154    }
155
156    /// <summary>
157    /// If the top item of the BOOLEAN stack is TRUE then this removes the second item on the EXEC stack, leaving the first item to be
158    /// executed. If it is false then it removes the first item, leaving the second to be executed. This is similar to CODE.IF except
159    /// that it operates on the EXEC stack. This acts as a NOOP unless there are at least two items on the EXEC stack and one item on
160    /// the BOOLEAN stack.
161    /// </summary>
162    public class ExecIfExpression : Expression
163    {
164        public ExecIfExpression() : base("EXEC.IF") { }
165
166        public override void Eval(IInterpreter interpreter)
167        {
168            // not enough arguments on stack
169            if (interpreter.BooleanStack.Count == 0 ||
170                interpreter.ExecStack.Count < 2)
171                return;
172
173            var condition = interpreter.BooleanStack.Pop();
174
175            if (condition)
176                interpreter.ExecStack.RemoveAt(interpreter.ExecStack.Count - 2);
177            else
178                interpreter.ExecStack.RemoveTop();
179        }
180    }
181
182    /// <summary>
183    /// The Push implementation of the "Y combinator". Inserts beneath the top item of the EXEC stack a new item of the form
184    /// "( EXEC.Y <TopItem> )".
185    /// </summary>
186    public class ExecYExpression : Expression
187    {
188        public ExecYExpression() : base("EXEC.Y")
189        {
190        }
191
192        public override void Eval(IInterpreter interpreter)
193        {
194            // not enough arguments on stack
195            if (interpreter.ExecStack.Count == 0)
196                return;
197
198            var expandExpression = ExecExpandExpression.TryCreate(new[]
199            {
200                interpreter.ExecStack.Top,
201                new ExecYExpression()
202            }, interpreter.Configuration);
203
204            interpreter.ExecStack.Insert(interpreter.ExecStack.Count - 1, expandExpression);
205        }
206    }
207
208    /// <summary>
209    /// The Push implementation of the "K combinator". Removes the second item on the EXEC stack.
210    /// </summary>
211    public class ExecKExpression : Expression
212    {
213        public ExecKExpression() : base("EXEC.K") { }
214
215        public override void Eval(IInterpreter interpreter)
216        {
217            if (interpreter.ExecStack.Count < 2)
218                return;
219
220            var top = interpreter.ExecStack.Pop();
221            interpreter.ExecStack.SetTop(top);
222        }
223    }
224
225    /// <summary>
226    /// The Push implementation of the "S combinator". Pops 3 items from the EXEC stack, which we will call A, B, and C
227    /// (with A being the first one popped). Then pushes a list containing B and C back onto the EXEC stack, followed by
228    /// another instance of C, followed by another instance of A.
229    /// </summary>
230    public class ExecSExpression : Expression
231    {
232        public ExecSExpression() : base("EXEC.S") { }
233
234        public override void Eval(IInterpreter interpreter)
235        {
236            if (interpreter.ExecStack.Count < 3)
237                return;
238
239            var expressions = interpreter.ExecStack.Pop(2);
240            var a = expressions[1];
241            var b = expressions[0];
242            var c = interpreter.ExecStack.Top;
243
244            interpreter.ExecStack.SetTop(ExecExpandExpression.TryCreate(new[] { c, b }, interpreter.Configuration));
245            interpreter.ExecStack.Push(c, a);
246        }
247    }
248}
Note: See TracBrowser for help on using the repository browser.