Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Interpreter/PushInterpreter.cs @ 14875

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

#2665 BenchmarkSuite, all examples, partially tested, VectorExpressions added

File size: 10.1 KB
Line 
1namespace HeuristicLab.Problems.ProgramSynthesis.Push.Interpreter {
2  using System;
3  using System.Collections.Generic;
4  using System.Runtime.CompilerServices;
5  using System.Threading;
6  using System.Threading.Tasks;
7  using Attributes;
8  using Configuration;
9  using Core;
10  using Expressions;
11  using Parser;
12  using Random;
13  using Stack;
14
15#if DEBUG
16  using System.Diagnostics;
17  using System.Linq;
18#endif
19
20  public class PushInterpreter : IInternalPushInterpreter, IDisposable {
21    private Task currentTask;
22
23    public PushInterpreter(IReadOnlyPushConfiguration config = null, IRandom random = null, InterpreterPoolContainer poolContainer = null) {
24      Random = random ?? new FastRandom();
25
26      Configuration = config ?? new PushConfiguration();
27
28      // setting the capacity of the stacks to max points ensures that there will be enough memory at runtime
29      ExecStack = new PushStack<Expression>(Configuration.MaxPointsInProgram);
30
31      CodeStack = new PushStack<Expression> {
32        IsEnabled = Configuration.EnabledStacks[StackTypes.Code]
33      };
34
35      NameStack = new PushStack<string> {
36        IsEnabled = Configuration.EnabledStacks[StackTypes.Code]
37      };
38
39      BooleanStack = new PushStack<bool> {
40        IsEnabled = Configuration.EnabledStacks[StackTypes.Boolean]
41      };
42
43      IntegerStack = new PushStack<long> {
44        IsEnabled = Configuration.EnabledStacks[StackTypes.Integer]
45      };
46
47      FloatStack = new PushStack<double> {
48        IsEnabled = Configuration.EnabledStacks[StackTypes.Float]
49      };
50
51      CharStack = new PushStack<char> {
52        IsEnabled = Configuration.EnabledStacks[StackTypes.Char]
53      };
54
55      StringStack = new PushStack<string> {
56        IsEnabled = Configuration.EnabledStacks[StackTypes.String]
57      };
58
59      IntegerVectorStack = new PushStack<List<long>> {
60        IsEnabled = Configuration.EnabledStacks[StackTypes.IntegerVector]
61      };
62
63      FloatVectorStack = new PushStack<List<double>> {
64        IsEnabled = Configuration.EnabledStacks[StackTypes.FloatVector]
65      };
66
67      BooleanVectorStack = new PushStack<List<bool>> {
68        IsEnabled = Configuration.EnabledStacks[StackTypes.BooleanVector]
69      };
70
71      StringVectorStack = new PushStack<List<string>> {
72        IsEnabled = Configuration.EnabledStacks[StackTypes.StringVector]
73      };
74
75      CustomExpressions = new Dictionary<string, Expression>();
76      PoolContainer = poolContainer ?? new InterpreterPoolContainer();
77    }
78
79    public PushInterpreter(int seed, IReadOnlyPushConfiguration config = null)
80      : this(config, new FastRandom(seed)) {
81    }
82
83    public IRandom Random { get; set; }
84
85    public long ExecCounter { get; private set; }
86
87    public bool IsPaused { get; private set; }
88
89    public bool IsAborted { get; private set; }
90
91    public bool IsRunning
92    {
93      get
94      {
95        return !ExecStack.IsEmpty &&
96               !IsPaused &&
97               !IsAborted &&
98               (ExecCounter < Configuration.EvalPushLimit);
99      }
100    }
101
102    public bool IsCompleted
103    {
104      get
105      {
106        return ExecStack.IsEmpty || ExecCounter >= Configuration.EvalPushLimit;
107      }
108    }
109
110    public bool CanStep
111    {
112      get
113      {
114        return !IsCompleted && !IsAborted && IsPaused;
115      }
116    }
117
118    public InterpreterPoolContainer PoolContainer { get; private set; }
119
120    public IReadOnlyPushConfiguration Configuration { get; protected set; }
121
122    [PushStack(StackTypes.Code)]
123    public IPushStack<Expression> CodeStack { get; private set; }
124
125    [PushStack(StackTypes.Exec)]
126    public IPushStack<Expression> ExecStack { get; private set; }
127
128    [PushStack(StackTypes.Name)]
129    public IPushStack<string> NameStack { get; private set; }
130
131    [PushStack(StackTypes.Boolean)]
132    public IPushStack<bool> BooleanStack { get; private set; }
133
134    [PushStack(StackTypes.Integer)]
135    public IPushStack<long> IntegerStack { get; private set; }
136
137    [PushStack(StackTypes.Float)]
138    public IPushStack<double> FloatStack { get; private set; }
139
140    [PushStack(StackTypes.Char)]
141    public IPushStack<char> CharStack { get; private set; }
142
143    [PushStack(StackTypes.String)]
144    public IPushStack<string> StringStack { get; private set; }
145
146    [PushStack(StackTypes.IntegerVector)]
147    public IPushStack<List<long>> IntegerVectorStack { get; private set; }
148
149    [PushStack(StackTypes.FloatVector)]
150    public IPushStack<List<double>> FloatVectorStack { get; private set; }
151
152    [PushStack(StackTypes.BooleanVector)]
153    public IPushStack<List<bool>> BooleanVectorStack { get; private set; }
154
155    [PushStack(StackTypes.StringVector)]
156    public IPushStack<List<string>> StringVectorStack { get; private set; }
157
158    public IDictionary<string, Expression> CustomExpressions { get; private set; }
159
160    public bool IsNameQuoteFlagSet { get; set; }
161
162    public Task RunAsync(string code, CancellationToken token = default(CancellationToken)) {
163      var program = PushParser.Parse(code);
164      currentTask = RunAsync(program, token);
165      return currentTask;
166    }
167    public async Task RunAsync(Expression expression, CancellationToken token = default(CancellationToken)) {
168      await Task.Run(() => Run(expression), token);
169    }
170
171    public void Run(string code, bool stepwise = false) {
172      var program = PushParser.Parse(code);
173      Run(program, stepwise);
174    }
175
176    public void Run(Expression expression, bool stepwise = false) {
177      IsPaused = stepwise;
178
179      /* Push top expression so the loop is able to enter
180       * If the top expression is a single statement then the loop has nothing to do.
181       * Otherwise the expand expression will be evaluated and pushes code onto the EXEC stack.
182       * Expanding the initial program is not counted */
183      ExecStack.Push(expression);
184
185      if (Configuration.TopLevelPushCode) CodeStack.Push(expression);
186
187      // expand if program
188      if (expression.IsProgram)
189        DoStep();
190
191      Run();
192    }
193
194    public bool CanRun(int count) {
195      return ExecStack.Count >= count &&
196             !IsPaused &&
197             !IsAborted &&
198             ExecCounter + count < Configuration.EvalPushLimit;
199    }
200
201    public async Task AbortAsync() {
202      if (IsAborted || IsCompleted) return;
203
204      IsAborted = true;
205
206      PoolContainer.DisposePools();
207
208      if (currentTask != null) await currentTask;
209    }
210
211    public async Task AbortAndResetAsync() {
212      await AbortAsync();
213      Reset();
214    }
215
216    public async Task PauseAsync() {
217      if (IsPaused || IsCompleted) return;
218
219      IsPaused = true;
220
221      if (currentTask != null) await currentTask;
222    }
223
224    public async Task ResumeAsync() {
225      if (IsPaused || !IsAborted) {
226        IsPaused = false;
227        await InterpretAsync();
228      } else await currentTask;
229    }
230
231    public void Resume() {
232      if (!IsPaused && IsAborted)
233        return;
234
235      IsPaused = false;
236      this.Run();
237    }
238
239    [MethodImpl(MethodImplOptions.AggressiveInlining)]
240    public bool Step() {
241      if (!CanStep) return false;
242
243      var successful = DoStep();
244
245      if (IsCompleted)
246        Finally();
247
248      return successful;
249    }
250
251    [MethodImpl(MethodImplOptions.AggressiveInlining)]
252    public void Step(int count) {
253      for (var i = 0u; i < count; i++) Step();
254    }
255
256    /// <summary>
257    /// Reset while interpreter
258    /// </summary>
259    public void Reset() {
260      ExecCounter = 0;
261
262      IsAborted = false;
263      IsPaused = false;
264      currentTask = null;
265
266      Clear();
267    }
268
269    /// <summary>
270    /// Clears stacks and custom expressions
271    /// </summary>
272    public void Clear() {
273      ExecStack.Clear();
274      CodeStack.Clear();
275      NameStack.Clear();
276      BooleanStack.Clear();
277      IntegerStack.Clear();
278      FloatStack.Clear();
279
280      CustomExpressions.Clear();
281    }
282
283    [MethodImpl(MethodImplOptions.AggressiveInlining)]
284    private void Run() {
285      // if no stack which is modifies the exec stack is enabled, unroll loop due to performance reasons
286      if (!Configuration.EnabledStacks[StackTypes.Exec] &&
287          !Configuration.EnabledStacks[StackTypes.Code]) {
288        while (CanRun(10))
289          DoTenSteps();
290      }
291
292      while (IsRunning)
293        DoStep();
294
295      if (IsCompleted)
296        Finally();
297    }
298
299    [MethodImpl(MethodImplOptions.AggressiveInlining)]
300    private void Finally() {
301      if (Configuration.TopLevelPopCode && !CodeStack.IsEmpty)
302        CodeStack.Pop();
303
304      PoolContainer.DisposePools();
305    }
306
307#if DEBUG
308    private Expression last;
309    private bool DoStep() {
310      double[] bk;
311      if (!FloatStack.IsEmpty) {
312        bk = FloatStack.Peek(Math.Min(FloatStack.Count, 3));
313      }
314
315      var expression = ExecStack.Pop();
316      var succ = expression.Eval(this);
317
318      if ((ExecStack.Count > 0 && ExecStack.Top == null) ||
319          (CodeStack.Count > 0 && CodeStack.Top == null) ||
320          FloatStack.Any(x => double.IsNaN(x) || double.IsInfinity(x)) ||
321          StringStack.Count > 0 && StringStack.Any(x => x == null)) {
322        Debugger.Break();
323      }
324
325      ExecCounter++;
326      last = expression;
327      return succ;
328    }
329#else
330    [MethodImpl(MethodImplOptions.AggressiveInlining)]
331    private bool DoStep() {
332      ExecCounter++;
333      return ExecStack.Pop().Eval(this);
334    }
335#endif
336
337    [MethodImpl(MethodImplOptions.AggressiveInlining)]
338    private void DoTenSteps() {
339      ExecStack[0].Eval(this);
340      ExecStack[1].Eval(this);
341      ExecStack[2].Eval(this);
342      ExecStack[3].Eval(this);
343      ExecStack[4].Eval(this);
344      ExecStack[5].Eval(this);
345      ExecStack[6].Eval(this);
346      ExecStack[7].Eval(this);
347      ExecStack[8].Eval(this);
348      ExecStack[9].Eval(this);
349
350      ExecStack.Remove(10);
351      ExecCounter += 10;
352    }
353
354    private Task InterpretAsync() {
355      currentTask = Task.Run(() => this.Run());
356
357      return currentTask;
358    }
359
360    public virtual void Dispose() {
361      PoolContainer.DisposePools();
362    }
363  }
364}
Note: See TracBrowser for help on using the repository browser.