Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2665 PooledPushProgram reduces memory usage and increases performance

File size: 7.6 KB
Line 
1namespace HeuristicLab.Problems.ProgramSynthesis.Push.Interpreter {
2  using System;
3  using System.Collections.Generic;
4#if DEBUG
5  using System.Linq;
6#endif
7  using System.Runtime.CompilerServices;
8  using System.Threading;
9  using System.Threading.Tasks;
10  using HeuristicLab.Core;
11  using HeuristicLab.Problems.ProgramSynthesis.Push.Configuration;
12  using HeuristicLab.Problems.ProgramSynthesis.Push.Data.Pool;
13  using HeuristicLab.Problems.ProgramSynthesis.Push.Expressions;
14  using HeuristicLab.Problems.ProgramSynthesis.Push.Parser;
15  using HeuristicLab.Problems.ProgramSynthesis.Push.Stack;
16  using HeuristicLab.Random;
17
18  public class PushInterpreter : IPushInterpreter {
19    private Task currentTask;
20
21    public PushInterpreter(IReadonlyPushConfiguration config = null, IRandom random = null) {
22      Random = random ?? new FastRandom();
23
24      Configuration = config ?? new PushConfiguration();
25
26      // setting the capacity of the stacks to max points ensures that there will be enough memory at runtime
27      ExecStack = new PushStack<Expression>(Configuration.EvalPushLimit);
28
29      CodeStack = new PushStack<Expression>(Configuration.EvalPushLimit) {
30        IsEnabled = Configuration.IsCodeStackEnabled
31      };
32
33      NameStack = new PushStack<string> {
34        IsEnabled = Configuration.IsNameStackEnabled
35      };
36      BooleanStack = new PushStack<bool> {
37        IsEnabled = Configuration.IsBooleanStackEnabled
38      };
39      IntegerStack = new PushStack<long> {
40        IsEnabled = Configuration.IsIntegerStackEnabled
41      };
42      FloatStack = new PushStack<double> {
43        IsEnabled = Configuration.IsFloatStackEnabled
44      };
45
46      CustomExpressions = new Dictionary<string, Expression>();
47    }
48
49    public PushInterpreter(int seed, IReadonlyPushConfiguration config = null)
50      : this(config, new FastRandom(seed)) {
51    }
52
53    public IRandom Random { get; set; }
54
55    public int ExecCounter { get; private set; }
56
57    public bool IsPaused { get; private set; }
58
59    public bool IsAborted { get; private set; }
60
61    public bool IsRunning
62    {
63      get
64      {
65        return !ExecStack.IsEmpty &&
66               !IsPaused &&
67               !IsAborted &&
68               (ExecCounter < Configuration.EvalPushLimit);
69      }
70    }
71
72    public bool IsCompleted
73    {
74      get
75      {
76        return ExecStack.Count == 0;
77      }
78    }
79
80    public bool CanStep
81    {
82      get
83      {
84        return !IsCompleted && !IsAborted && IsPaused;
85      }
86    }
87
88    public IManagedPool<PushProgram> PushProgramPool { get; set; }
89
90    public IReadonlyPushConfiguration Configuration { get; protected set; }
91
92    public IStack<Expression> CodeStack { get; private set; }
93
94    public IStack<Expression> ExecStack { get; private set; }
95
96    public IStack<string> NameStack { get; private set; }
97
98    public IStack<bool> BooleanStack { get; private set; }
99
100    public IStack<long> IntegerStack { get; private set; }
101
102    public IStack<double> FloatStack { get; private set; }
103
104    public IDictionary<string, Expression> CustomExpressions { get; private set; }
105
106    public bool IsNameQuoteFlagSet { get; set; }
107
108    public Task RunAsync(string code, bool stepwise = false, CancellationToken token = default(CancellationToken)) {
109      var program = PushParser.Parse(code);
110
111      currentTask = RunAsync(program, stepwise, token);
112
113      return currentTask;
114    }
115    public async Task RunAsync(
116      Expression expression,
117      bool stepwise = false,
118      CancellationToken token = default(CancellationToken)) {
119      await Task.Run(() => Run(expression, stepwise), token);
120    }
121
122    public void Run(string code, bool stepwise = false) {
123      var program = PushParser.Parse(code);
124      Run(program, stepwise);
125    }
126
127
128    public void Run(Expression program, bool stepwise = false) {
129      IsPaused = stepwise;
130
131      /* Push top expression so the loop is able to enter
132       * If the top expression is a single statement then the loop has nothing to do
133       * Otherwise the expand expression will be evaluated and pushes code onto the EXEC stack */
134      ExecStack.Push(program);
135
136      if (Configuration.TopLevelPushCode) CodeStack.Insert(0, program);
137
138      // run top expression
139      DoStep();
140
141      Interpret();
142    }
143
144    public async Task AbortAsync() {
145      if (IsAborted || IsCompleted) return;
146
147      IsAborted = true;
148
149      if (currentTask != null) await currentTask;
150    }
151
152    public async Task AbortAndResetAsync() {
153      await AbortAsync();
154      Reset();
155    }
156
157    public async Task PauseAsync() {
158      if (IsPaused || IsCompleted) return;
159
160      IsPaused = true;
161
162      if (currentTask != null) await currentTask;
163    }
164
165    public async Task ResumeAsync() {
166      if (IsPaused || !IsAborted) {
167        IsPaused = false;
168        await InterpretAsync();
169      } else await currentTask;
170    }
171
172    public void Resume() {
173      if (!IsPaused && IsAborted)
174        return;
175
176      IsPaused = false;
177      Interpret();
178    }
179
180    [MethodImpl(MethodImplOptions.AggressiveInlining)]
181    public bool Step() {
182      if (!CanStep) return false;
183
184      var successful = DoStep();
185      Finally();
186
187      return successful;
188    }
189
190    [MethodImpl(MethodImplOptions.AggressiveInlining)]
191    public void Step(int count) {
192      for (var i = 0; i < count; i++) Step();
193    }
194
195    public void PrintStacks() {
196      PrintStack("EXEC", ExecStack);
197      PrintStack("CODE", CodeStack);
198      PrintStack("NAME", NameStack);
199      PrintStack("BOOLEAN", BooleanStack);
200      PrintStack("FLOAT", FloatStack);
201      PrintStack("INTEGER", IntegerStack);
202
203      if (CustomExpressions.Count == 0) return;
204      Console.WriteLine("--------- Custom Expressions ---------");
205      foreach (var ce in CustomExpressions) {
206        Console.WriteLine("{0}: {1}", ce.Key, ce.Value);
207      }
208    }
209
210    /// <summary>
211    /// Clears stacks
212    /// </summary>
213    public void Reset() {
214      IsAborted = false;
215      IsPaused = false;
216      currentTask = null;
217
218      Clear();
219    }
220
221    /// <summary>
222    /// Clears stacks
223    /// </summary>
224    public void Clear() {
225      ExecCounter = 0;
226
227      ExecStack.Clear();
228      CodeStack.Clear();
229
230      NameStack.Clear();
231      BooleanStack.Clear();
232      IntegerStack.Clear();
233      FloatStack.Clear();
234
235      CustomExpressions.Clear();
236    }
237
238    [MethodImpl(MethodImplOptions.AggressiveInlining)]
239    private void Interpret() {
240      while (IsRunning) {
241        DoStep();
242        ExecCounter++;
243      }
244
245      Finally();
246    }
247
248    [MethodImpl(MethodImplOptions.AggressiveInlining)]
249    private void Finally() {
250      if (!IsCompleted)
251        return;
252
253      if (Configuration.TopLevelPopCode && (CodeStack.Count > 0))
254        CodeStack.Pop();
255    }
256
257#if DEBUG
258    private Expression last;
259    private bool DoStep() {
260      var expression = ExecStack.Pop();
261
262      if (ExecStack.Any(e => e == null)) {
263        throw new InvalidProgramException();
264      }
265
266      var succ = expression.Eval(this);
267      last = expression;
268
269      return succ;
270    }
271#else
272    [MethodImpl(MethodImplOptions.AggressiveInlining)]
273    private bool DoStep() {
274      return ExecStack.Pop().Eval(this);
275    }
276#endif
277
278    private Task InterpretAsync() {
279      currentTask = Task.Run(() => Interpret());
280
281      return currentTask;
282    }
283
284    private void PrintStack<T>(string name, IStack<T> stack) {
285      if (stack.IsEmpty) return;
286      Console.WriteLine("--------- {0} ---------\n{1}\n", name, stack);
287    }
288  }
289}
Note: See TracBrowser for help on using the repository browser.