Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2665 Fixed small issues, testet benchmark suite, added INX Expressions

File size: 14.1 KB
Line 
1namespace HeuristicLab.Problems.ProgramSynthesis.Push.Interpreter {
2  using System;
3  using System.Collections.Generic;
4  using System.Linq;
5  using System.Runtime.CompilerServices;
6  using System.Threading;
7  using System.Threading.Tasks;
8  using Attributes;
9  using Configuration;
10  using Core;
11  using Expressions;
12  using Parser;
13  using Random;
14  using Stack;
15
16
17  public class PushInterpreter : IInternalPushInterpreter, IDisposable {
18    private Task currentTask;
19    private Expression currentProgram;
20
21    public PushInterpreter(IReadOnlyPushConfiguration config = null, IRandom random = null, InterpreterPoolContainer poolContainer = null) {
22      Random = random ?? new MersenneTwister();
23      Configuration = config ?? new PushConfiguration();
24
25      // setting the capacity of the Stacks to max points ensures that there will be enough memory at runtime
26      ExecStack = new PushStack<Expression>(Configuration.MaxPointsInProgram);
27      CodeStack = new PushStack<Expression>();
28      NameStack = new PushStack<string>();
29      BooleanStack = new PushStack<bool>();
30      IntegerStack = new PushStack<long>();
31      FloatStack = new PushStack<double>();
32      CharStack = new PushStack<char>();
33      StringStack = new PushStack<string>();
34      IntegerVectorStack = new PushStack<IReadOnlyList<long>>();
35      FloatVectorStack = new PushStack<IReadOnlyList<double>>();
36      BooleanVectorStack = new PushStack<IReadOnlyList<bool>>();
37      StringVectorStack = new PushStack<IReadOnlyList<string>>();
38      PrintStack = new PrintStack();
39
40      Stacks = new Dictionary<StackTypes, IPushStack> {
41        { StackTypes.Exec, ExecStack },
42        { StackTypes.Code, CodeStack },
43        { StackTypes.Integer, IntegerStack },
44        { StackTypes.Float, FloatStack },
45        { StackTypes.Boolean, BooleanStack },
46        { StackTypes.Char, CharStack },
47        { StackTypes.String, StringStack },
48        { StackTypes.Name, NameStack },
49        { StackTypes.Print, PrintStack },
50        { StackTypes.IntegerVector, IntegerVectorStack },
51        { StackTypes.FloatVector, FloatVectorStack },
52        { StackTypes.BooleanVector, BooleanVectorStack },
53        { StackTypes.StringVector, StringVectorStack },
54      };
55
56      supportedStackTypes = Stacks.Keys.ToArray();
57
58      CustomExpressions = new Dictionary<string, Expression>();
59      PoolContainer = poolContainer ?? new InterpreterPoolContainer();
60
61      ConfigureStacks();
62    }
63
64    public PushInterpreter(int seed, IReadOnlyPushConfiguration config = null)
65      : this(config, new FastRandom(seed)) {
66    }
67
68    private readonly StackTypes[] supportedStackTypes;
69    public IReadOnlyDictionary<StackTypes, IPushStack> Stacks { get; private set; }
70
71    public IRandom Random { get; set; }
72
73    public long ExecCounter { get; private set; }
74
75    public bool IsPaused { get; private set; }
76
77    public bool IsAborted { get; private set; }
78
79    public bool IsRunning
80    {
81      get
82      {
83        return !ExecStack.IsEmpty &&
84               !IsPaused &&
85               !IsAborted &&
86               (ExecCounter < Configuration.EvalPushLimit);
87      }
88    }
89
90    public bool IsCompleted
91    {
92      get
93      {
94        return ExecStack.IsEmpty || ExecCounter >= Configuration.EvalPushLimit;
95      }
96    }
97
98    public bool CanStep
99    {
100      get
101      {
102        return !IsCompleted && !IsAborted && IsPaused;
103      }
104    }
105
106    public InterpreterPoolContainer PoolContainer { get; private set; }
107
108    public IReadOnlyPushConfiguration Configuration { get; protected set; }
109    [PushStack(StackTypes.Code)]
110    public IPushStack<Expression> CodeStack { get; private set; }
111    [PushStack(StackTypes.Exec)]
112    public IPushStack<Expression> ExecStack { get; private set; }
113    [PushStack(StackTypes.Name)]
114    public IPushStack<string> NameStack { get; private set; }
115    [PushStack(StackTypes.Boolean)]
116    public IPushStack<bool> BooleanStack { get; private set; }
117    [PushStack(StackTypes.Integer)]
118    public IPushStack<long> IntegerStack { get; private set; }
119    [PushStack(StackTypes.Float)]
120    public IPushStack<double> FloatStack { get; private set; }
121    [PushStack(StackTypes.Char)]
122    public IPushStack<char> CharStack { get; private set; }
123    [PushStack(StackTypes.String)]
124    public IPushStack<string> StringStack { get; private set; }
125    [PushStack(StackTypes.IntegerVector)]
126    public IPushStack<IReadOnlyList<long>> IntegerVectorStack { get; private set; }
127    [PushStack(StackTypes.FloatVector)]
128    public IPushStack<IReadOnlyList<double>> FloatVectorStack { get; private set; }
129    [PushStack(StackTypes.BooleanVector)]
130    public IPushStack<IReadOnlyList<bool>> BooleanVectorStack { get; private set; }
131    [PushStack(StackTypes.StringVector)]
132    public IPushStack<IReadOnlyList<string>> StringVectorStack { get; private set; }
133    [PushStack(StackTypes.Print)]
134    public IPrintStack PrintStack { get; private set; }
135
136    public IDictionary<string, Expression> CustomExpressions { get; private set; }
137
138    public bool IsNameQuoteFlagSet { get; set; }
139
140    private readonly List<Expression> inputExpressions = new List<Expression>();
141    IReadOnlyList<Expression> IInternalPushInterpreter.InputExpressions { get { return inputExpressions; } }
142
143    public void SetInput(
144      IReadOnlyList<long> integers = null,
145      IReadOnlyList<double> floats = null,
146      IReadOnlyList<bool> booleans = null,
147      IReadOnlyList<char> chars = null,
148      IReadOnlyList<string> strings = null,
149      IReadOnlyList<IReadOnlyList<long>> integerVectors = null,
150      IReadOnlyList<IReadOnlyList<double>> floatVectors = null,
151      IReadOnlyList<IReadOnlyList<string>> stringVectors = null) {
152
153      // Integer
154      if (integers != null && integers.Count > 0) {
155        var integerPushExpressionPool = PoolContainer.GetStatefulExpressionPool<IntegerPushExpression>();
156
157        for (var i = 0; i < integers.Count; i++) {
158          var expression = IntegerPushExpression.Create(integerPushExpressionPool, integers[i]);
159          inputExpressions.Add(expression);
160        }
161      }
162
163      // Float
164      if (floats != null && floats.Count > 0) {
165        var floatPushExpressionPool = PoolContainer.GetStatefulExpressionPool<FloatPushExpression>();
166
167        for (var i = 0; i < floats.Count; i++) {
168          var expression = FloatPushExpression.Create(floatPushExpressionPool, floats[i]);
169          inputExpressions.Add(expression);
170        }
171      }
172
173      // Booleans
174      if (booleans != null && booleans.Count > 0) {
175        var booleanPushExpressionPool = PoolContainer.GetStatefulExpressionPool<BooleanPushExpression>();
176
177        for (var i = 0; i < booleans.Count; i++) {
178          var expression = BooleanPushExpression.Create(booleanPushExpressionPool, booleans[i]);
179          inputExpressions.Add(expression);
180        }
181      }
182
183      // Char
184      if (chars != null && chars.Count > 0) {
185        var charPushExpressionPool = PoolContainer.GetStatefulExpressionPool<CharPushExpression>();
186
187        for (var i = 0; i < chars.Count; i++) {
188          var expression = CharPushExpression.Create(charPushExpressionPool, chars[i]);
189          inputExpressions.Add(expression);
190        }
191      }
192
193      // String
194      if (strings != null && strings.Count > 0) {
195        var stringPushExpressionPool = PoolContainer.GetStatefulExpressionPool<StringPushExpression>();
196
197        for (var i = 0; i < strings.Count; i++) {
198          var expression = StringPushExpression.Create(stringPushExpressionPool, strings[i]);
199          inputExpressions.Add(expression);
200        }
201      }
202
203      // IntegerVector
204      if (integerVectors != null && integerVectors.Count > 0) {
205        var integerVectorPushExpressionPool = PoolContainer.GetStatefulExpressionPool<IntegerVectorPushExpression>();
206
207        for (var i = 0; i < integerVectors.Count; i++) {
208          var expression = IntegerVectorPushExpression.Create(integerVectorPushExpressionPool, integerVectors[i]);
209          inputExpressions.Add(expression);
210        }
211      }
212
213      // FloatVector
214      if (floatVectors != null && floatVectors.Count > 0) {
215        var floatVectorPushExpressionPool = PoolContainer.GetStatefulExpressionPool<FloatVectorPushExpression>();
216
217        for (var i = 0; i < floatVectors.Count; i++) {
218          var expression = FloatVectorPushExpression.Create(floatVectorPushExpressionPool, floatVectors[i]);
219          inputExpressions.Add(expression);
220        }
221      }
222
223      // StringVector
224      if (stringVectors != null && stringVectors.Count > 0) {
225        var stringVectorPushExpressionPool = PoolContainer.GetStatefulExpressionPool<StringVectorPushExpression>();
226
227        for (var i = 0; i < stringVectors.Count; i++) {
228          var expression = StringVectorPushExpression.Create(stringVectorPushExpressionPool, stringVectors[i]);
229          inputExpressions.Add(expression);
230        }
231      }
232    }
233
234
235    public Task RunAsync(string code, CancellationToken token = default(CancellationToken)) {
236      var program = PushParser.Parse(code);
237      currentTask = RunAsync(program, token);
238      return currentTask;
239    }
240    public async Task RunAsync(Expression expression, CancellationToken token = default(CancellationToken)) {
241      await Task.Run(() => Run(expression), token);
242    }
243
244    public void Run(string code, bool stepwise = false) {
245      var program = PushParser.Parse(code);
246      Run(program, stepwise);
247    }
248
249    public void Run(bool stepwise) {
250      Run(PushProgram.Empty, stepwise);
251    }
252
253    public void Run(Expression expression, bool stepwise = false) {
254      IsPaused = stepwise;
255      currentProgram = expression;
256
257      /* Push top expression so the loop is able to enter
258       * If the top expression is a single statement it gets evaluated in Run.
259       * Otherwise the push program will be evaluated and the expressions of the program are pushed onto the EXEC stack.
260       * Expanding the initial program is not counted in ExecCount */
261      InitRun(expression);
262
263      if (Configuration.TopLevelPushCode && CodeStack.IsEnabled)
264        CodeStack.Push(expression);
265
266      Run();
267    }
268
269    public bool CanRun(int count) {
270      return ExecStack.Count >= count &&
271             !IsPaused &&
272             !IsAborted &&
273             ExecCounter + count < Configuration.EvalPushLimit;
274    }
275
276    public async Task AbortAsync() {
277      if (IsAborted || IsCompleted) return;
278
279      IsAborted = true;
280
281      PoolContainer.DisposePools();
282
283      if (currentTask != null) await currentTask;
284    }
285
286    public async Task AbortAndResetAsync() {
287      await AbortAsync();
288      Reset();
289    }
290
291    public async Task PauseAsync() {
292      if (IsPaused || IsCompleted) return;
293
294      IsPaused = true;
295
296      if (currentTask != null) await currentTask;
297    }
298
299    public async Task ResumeAsync() {
300      if (IsPaused || !IsAborted) {
301        IsPaused = false;
302        await InterpretAsync();
303      } else await currentTask;
304    }
305
306    public void Resume() {
307      if (!IsPaused && IsAborted)
308        return;
309
310      IsPaused = false;
311      Run();
312    }
313
314    [MethodImpl(MethodImplOptions.AggressiveInlining)]
315    public bool Step() {
316      if (!CanStep) return false;
317
318      var successful = DoStep();
319
320      if (IsCompleted)
321        Finally();
322
323      return successful;
324    }
325
326    [MethodImpl(MethodImplOptions.AggressiveInlining)]
327    public void Step(int count) {
328      for (var i = 0u; i < count; i++) Step();
329    }
330
331    /// <summary>
332    /// Reset while interpreter
333    /// </summary>
334    public void Reset() {
335      ExecCounter = 0;
336      IsAborted = false;
337      IsPaused = false;
338      currentTask = null;
339      currentProgram = null;
340
341      inputExpressions.Clear();
342      Clear();
343      ConfigureStacks();
344    }
345
346    private void ConfigureStacks() {
347      for (var i = 0u; i < supportedStackTypes.Length; i++) {
348        var key = supportedStackTypes[i];
349        Stacks[key].IsEnabled = Configuration.IsStackEnabled(key);
350      }
351
352      // exec stack must always be enabled
353      this.ExecStack.IsEnabled = true;
354    }
355
356    /// <summary>
357    /// Clears Stacks and custom expressions
358    /// </summary>
359    public void Clear() {
360      for (var i = 0u; i < supportedStackTypes.Length; i++) {
361        var key = supportedStackTypes[i];
362        Stacks[key].Clear();
363      }
364
365      CustomExpressions.Clear();
366    }
367
368    [MethodImpl(MethodImplOptions.AggressiveInlining)]
369    private void Run() {
370      // if no stack which is modifies the exec stack is enabled, unroll loop due to performance reasons
371      if (!Configuration.IsStackEnabled(StackTypes.Exec)) {
372        while (CanRun(10))
373          DoTenSteps();
374      }
375
376      while (IsRunning)
377        DoStep();
378
379      if (IsCompleted)
380        Finally();
381    }
382
383    [MethodImpl(MethodImplOptions.AggressiveInlining)]
384    private void Finally() {
385      if (Configuration.TopLevelPopCode && !CodeStack.IsEmpty && CodeStack.IsEnabled)
386        CodeStack.Pop();
387
388      PoolContainer.DisposePools();
389    }
390
391    private void InitRun(Expression expression) {
392      ExecStack.Push(expression);
393
394      if (!expression.IsProgram)
395        return;
396
397      DoStep();
398      ExecCounter--;   // unpacking the initial program is not counted
399    }
400
401    [MethodImpl(MethodImplOptions.AggressiveInlining)]
402    private bool DoStep() {
403      ExecCounter++;
404      return ExecStack.Pop().TryEval(this);
405    }
406
407    [MethodImpl(MethodImplOptions.AggressiveInlining)]
408    private void DoTenSteps() {
409      ExecStack[0].TryEval(this);
410      ExecStack[1].TryEval(this);
411      ExecStack[2].TryEval(this);
412      ExecStack[3].TryEval(this);
413      ExecStack[4].TryEval(this);
414      ExecStack[5].TryEval(this);
415      ExecStack[6].TryEval(this);
416      ExecStack[7].TryEval(this);
417      ExecStack[8].TryEval(this);
418      ExecStack[9].TryEval(this);
419
420      ExecStack.Remove(10);
421      ExecCounter += 10;
422    }
423
424    private Task InterpretAsync() {
425      currentTask = Task.Run(() => Run());
426
427      return currentTask;
428    }
429
430    public virtual void Dispose() {
431      PoolContainer.DisposePools();
432    }
433  }
434}
Note: See TracBrowser for help on using the repository browser.