Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2665 Fixed bias 0 issue, PushExpressionFrequencyAnalyzer, Fixed probability for ERC settings, Fixed enable/disable instructions, Added expression descriptions

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