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

Last change on this file since 14908 was 14908, checked in by pkimmesw, 3 years ago

#2665 Removed "this" qualifier

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