Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2665 Started Plush Encoding, Added Zero Error Individual Count Analyzer

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