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
RevLine 
[14744]1namespace HeuristicLab.Problems.ProgramSynthesis.Push.Interpreter {
2  using System;
3  using System.Collections.Generic;
[15189]4  using System.Linq;
[14744]5  using System.Runtime.CompilerServices;
6  using System.Threading;
7  using System.Threading.Tasks;
[15017]8  using Attributes;
[14834]9  using Configuration;
10  using Core;
11  using Expressions;
12  using Parser;
13  using Random;
14  using Stack;
[14744]15
[14834]16
17  public class PushInterpreter : IInternalPushInterpreter, IDisposable {
[14744]18    private Task currentTask;
[15032]19    private Expression currentProgram;
[14744]20
[14777]21    public PushInterpreter(IReadOnlyPushConfiguration config = null, IRandom random = null, InterpreterPoolContainer poolContainer = null) {
[15017]22      Random = random ?? new MersenneTwister();
[14744]23      Configuration = config ?? new PushConfiguration();
24
[14914]25      // setting the capacity of the Stacks to max points ensures that there will be enough memory at runtime
[14875]26      ExecStack = new PushStack<Expression>(Configuration.MaxPointsInProgram);
[15032]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>>();
[15189]38      PrintStack = new PrintStack();
[14744]39
[14914]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 },
[15017]49        { StackTypes.Print, PrintStack },
[14914]50        { StackTypes.IntegerVector, IntegerVectorStack },
51        { StackTypes.FloatVector, FloatVectorStack },
52        { StackTypes.BooleanVector, BooleanVectorStack },
53        { StackTypes.StringVector, StringVectorStack },
54      };
55
[15189]56      supportedStackTypes = Stacks.Keys.ToArray();
57
[14744]58      CustomExpressions = new Dictionary<string, Expression>();
[14777]59      PoolContainer = poolContainer ?? new InterpreterPoolContainer();
[15032]60
61      ConfigureStacks();
[14744]62    }
63
[14777]64    public PushInterpreter(int seed, IReadOnlyPushConfiguration config = null)
[14744]65      : this(config, new FastRandom(seed)) {
66    }
67
[15189]68    private readonly StackTypes[] supportedStackTypes;
[14914]69    public IReadOnlyDictionary<StackTypes, IPushStack> Stacks { get; private set; }
70
[14744]71    public IRandom Random { get; set; }
72
[14875]73    public long ExecCounter { get; private set; }
[14744]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      {
[14834]94        return ExecStack.IsEmpty || ExecCounter >= Configuration.EvalPushLimit;
[14744]95      }
96    }
97
98    public bool CanStep
99    {
100      get
101      {
102        return !IsCompleted && !IsAborted && IsPaused;
103      }
104    }
105
[14777]106    public InterpreterPoolContainer PoolContainer { get; private set; }
[14746]107
[14777]108    public IReadOnlyPushConfiguration Configuration { get; protected set; }
[14834]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)]
[15017]126    public IPushStack<IReadOnlyList<long>> IntegerVectorStack { get; private set; }
[14834]127    [PushStack(StackTypes.FloatVector)]
[15017]128    public IPushStack<IReadOnlyList<double>> FloatVectorStack { get; private set; }
[14834]129    [PushStack(StackTypes.BooleanVector)]
[15017]130    public IPushStack<IReadOnlyList<bool>> BooleanVectorStack { get; private set; }
[14834]131    [PushStack(StackTypes.StringVector)]
[15017]132    public IPushStack<IReadOnlyList<string>> StringVectorStack { get; private set; }
[14897]133    [PushStack(StackTypes.Print)]
[15189]134    public IPrintStack PrintStack { get; private set; }
[14897]135
[14744]136    public IDictionary<string, Expression> CustomExpressions { get; private set; }
137
138    public bool IsNameQuoteFlagSet { get; set; }
139
[15189]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
[14834]235    public Task RunAsync(string code, CancellationToken token = default(CancellationToken)) {
[14744]236      var program = PushParser.Parse(code);
[14834]237      currentTask = RunAsync(program, token);
[14744]238      return currentTask;
239    }
[14834]240    public async Task RunAsync(Expression expression, CancellationToken token = default(CancellationToken)) {
[14875]241      await Task.Run(() => Run(expression), token);
[14744]242    }
243
[14745]244    public void Run(string code, bool stepwise = false) {
245      var program = PushParser.Parse(code);
246      Run(program, stepwise);
[14744]247    }
248
[15017]249    public void Run(bool stepwise) {
250      Run(PushProgram.Empty, stepwise);
251    }
252
[14834]253    public void Run(Expression expression, bool stepwise = false) {
[14777]254      IsPaused = stepwise;
[15032]255      currentProgram = expression;
[14744]256
[14777]257      /* Push top expression so the loop is able to enter
[14952]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);
[14744]262
[14952]263      if (Configuration.TopLevelPushCode && CodeStack.IsEnabled)
264        CodeStack.Push(expression);
[14744]265
[14834]266      Run();
[14744]267    }
268
[14875]269    public bool CanRun(int count) {
270      return ExecStack.Count >= count &&
271             !IsPaused &&
272             !IsAborted &&
273             ExecCounter + count < Configuration.EvalPushLimit;
274    }
275
[14744]276    public async Task AbortAsync() {
277      if (IsAborted || IsCompleted) return;
278
279      IsAborted = true;
280
[14777]281      PoolContainer.DisposePools();
[14747]282
[14744]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;
[14908]311      Run();
[14744]312    }
313
314    [MethodImpl(MethodImplOptions.AggressiveInlining)]
315    public bool Step() {
316      if (!CanStep) return false;
317
318      var successful = DoStep();
319
[14834]320      if (IsCompleted)
321        Finally();
322
[14744]323      return successful;
324    }
325
326    [MethodImpl(MethodImplOptions.AggressiveInlining)]
327    public void Step(int count) {
[14875]328      for (var i = 0u; i < count; i++) Step();
[14744]329    }
330
331    /// <summary>
[14875]332    /// Reset while interpreter
[14744]333    /// </summary>
334    public void Reset() {
[14834]335      ExecCounter = 0;
[14744]336      IsAborted = false;
337      IsPaused = false;
338      currentTask = null;
[15032]339      currentProgram = null;
[14744]340
[15189]341      inputExpressions.Clear();
[14744]342      Clear();
[15032]343      ConfigureStacks();
[14744]344    }
345
[15032]346    private void ConfigureStacks() {
[15189]347      for (var i = 0u; i < supportedStackTypes.Length; i++) {
348        var key = supportedStackTypes[i];
349        Stacks[key].IsEnabled = Configuration.IsStackEnabled(key);
[15032]350      }
351
352      // exec stack must always be enabled
353      this.ExecStack.IsEnabled = true;
354    }
355
[14744]356    /// <summary>
[14914]357    /// Clears Stacks and custom expressions
[14744]358    /// </summary>
359    public void Clear() {
[15189]360      for (var i = 0u; i < supportedStackTypes.Length; i++) {
361        var key = supportedStackTypes[i];
362        Stacks[key].Clear();
363      }
[14744]364
365      CustomExpressions.Clear();
366    }
367
368    [MethodImpl(MethodImplOptions.AggressiveInlining)]
[14834]369    private void Run() {
[14875]370      // if no stack which is modifies the exec stack is enabled, unroll loop due to performance reasons
[15032]371      if (!Configuration.IsStackEnabled(StackTypes.Exec)) {
[14875]372        while (CanRun(10))
373          DoTenSteps();
374      }
375
[14834]376      while (IsRunning)
[14744]377        DoStep();
378
[14834]379      if (IsCompleted)
380        Finally();
[14744]381    }
382
383    [MethodImpl(MethodImplOptions.AggressiveInlining)]
384    private void Finally() {
[14952]385      if (Configuration.TopLevelPopCode && !CodeStack.IsEmpty && CodeStack.IsEnabled)
[14834]386        CodeStack.Pop();
[14744]387
[14834]388      PoolContainer.DisposePools();
[14744]389    }
390
[14952]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
[14744]401    [MethodImpl(MethodImplOptions.AggressiveInlining)]
402    private bool DoStep() {
[14834]403      ExecCounter++;
[14952]404      return ExecStack.Pop().TryEval(this);
[14744]405    }
406
[14875]407    [MethodImpl(MethodImplOptions.AggressiveInlining)]
408    private void DoTenSteps() {
[14952]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);
[14875]419
420      ExecStack.Remove(10);
421      ExecCounter += 10;
422    }
423
[14744]424    private Task InterpretAsync() {
[14908]425      currentTask = Task.Run(() => Run());
[14744]426
427      return currentTask;
428    }
429
[14834]430    public virtual void Dispose() {
431      PoolContainer.DisposePools();
[14744]432    }
433  }
434}
Note: See TracBrowser for help on using the repository browser.