Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2665 Expressions are splitted into StatefullExpressions and StatelessExpressions, Added traits for tests

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