Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Problem/PushProblem.cs @ 14952

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

#2665 Added IsNoop to Expression, Made Expressions storable, Fixed Debugger, Fixed and improved problem data and result visualisation, Added custom ErcOption view, Added problem difficulty to problem data name

File size: 15.6 KB
Line 
1using System;
2
3namespace HeuristicLab.Problems.ProgramSynthesis.Push.Problem {
4  using System.Linq;
5
6  using Common;
7  using Configuration;
8  using Core;
9  using Data.Pool;
10  using HeuristicLab.Data;
11  using HeuristicLab.Encodings.IntegerVectorEncoding;
12  using HeuristicLab.Problems.ProgramSynthesis.Base.Erc;
13  using HeuristicLab.Problems.ProgramSynthesis.Push.Problem.BenchmarkSuite;
14
15  using Interpreter;
16  using Optimization;
17  using Parameters;
18  using Persistence.Default.CompositeSerializers.Storable;
19  using Random;
20
21  [StorableClass]
22  public abstract class PushProblem : SingleObjectiveBasicProblem<IntegerVectorEncoding> {
23    [Storable]
24    protected readonly PushConfiguration config;
25    protected PushInterpreterPool pool;
26    protected readonly ObjectPool<IRandom> randomPool = new ObjectPool<IRandom>(() => new MersenneTwister());
27
28    [Storable]
29    protected readonly IPushEvaluator PushEvaluator;
30
31    public const string CaseQualitiesScopeParameterName = "CaseQualities";
32    private const string BestTrainingSolutionResultName = "Best Solution";
33    private const string TestQualityResultName = "Test Quality";
34
35    protected PushProblem(PushBenchmarkSuiteEvaluator evaluator) {
36      config = new PushConfiguration();
37      PushEvaluator = evaluator;
38
39      InitData();
40      InitEvents();
41      InitParameters();
42    }
43
44    [StorableConstructor]
45    protected PushProblem(bool deserializing)
46      : base(deserializing) {
47    }
48
49    protected PushProblem(PushProblem original, Cloner cloner)
50      : base(original, cloner) {
51      config = cloner.Clone(original.config);
52      PushEvaluator = cloner.Clone(original.PushEvaluator);
53
54      InitData();
55      InitEvents();
56    }
57
58    [StorableHook(HookType.AfterDeserialization)]
59    // ReSharper disable once UnusedMember.Local
60    private void AfterDeserialization() {
61      InitData();
62      InitEvents();
63    }
64
65    private void InitData() {
66      pool = new PushInterpreterPool(Environment.ProcessorCount * 2, 4096, 1024, config);
67    }
68
69    private void InitEvents() {
70      config.EnabledExpressionsChanged += EnabledExpressionsChanged;
71    }
72
73    private void EnabledExpressionsChanged(object sender, EnabledExpressionsChangedEventArgs e) {
74      Encoding.Bounds[0, 1] = config.EnabledExpressions.Count;
75      Encoding.BoundsParameter.Value[0, 1] = config.EnabledExpressions.Count;
76    }
77
78    #region Parameters
79
80    private const string InstructionsParameterName = "Instructions";
81    private const string InstructionsParameterDescription = "Enables/Disables Instructions";
82    private const string EvalPushLimitParameterName = "EvalPushLimit";
83    private const string EvalPushLimitParameterDescription = "This is the maximum allowed number of \"executions\" in a single top-level call to the interpreter. The execution of a single Push instruction counts as one execution, as does the processing of a single literal, as does the descent into one layer of parentheses (that is, the processing of the \"(\" counts as one execution).";
84    private const string MinPointsInProgramParameterName = "MinProgramLength";
85    private const string MinProgramLengthParameterDescription = "This is the minimum size of an item on the CODE/EXEC stack, expressed as a number of points. A point is an instruction, a literal, or a pair of parentheses.";
86    private const string MaxPointsInProgramParameterName = "MaxProgramLength";
87    private const string MaxProgramLengthParameterDescription = "This is the maximum size of an item on the CODE/EXEC stack, expressed as a number of points. A point is an instruction, a literal, or a pair of parentheses.";
88    private const string TopLevelPushCodeParameterName = "TopLevelPushCode";
89    private const string TopLevelPushCodeParameterDescription = "When TRUE (which is the default), code passed to the top level of the interpreter will be pushed onto the CODE stack prior to execution.";
90    private const string TopLevelPopCodeParameterName = "TopLevelPopCode";
91    private const string TopLevelPopCodeParameterDescription = "When TRUE, the CODE stack will be popped at the end of top level calls to the interpreter. The default is FALSE.";
92    private const string MaxPointsInRandomInstructionParameterName = "MaxPointsInRandomInstruction";
93    private const string MaxPointsInRandomInstructionParameterDescription = "MaxPointsInRandomInstruction";
94    private const string ErcOptionsParameterName = "ERC options";
95    private const string MaxStringLengthParameterName = "Max. string length";
96    private const string MaxDepthParameterName = "Max. program recursion";
97
98    private void InitParameters() {
99      Parameters.Add(new ValueParameter<IEnabledExpressionsConfiguration>(
100        InstructionsParameterName,
101        InstructionsParameterDescription,
102        config));
103
104      Parameters.Add(new ValueParameter<ErcOptions>(ErcOptionsParameterName, config.ErcOptions));
105
106      Parameters.Add(new FixedValueParameter<IntValue>(
107        EvalPushLimitParameterName,
108        EvalPushLimitParameterDescription,
109        new IntValue(config.EvalPushLimit)));
110
111      Parameters.Add(new FixedValueParameter<IntValue>(
112        MinPointsInProgramParameterName,
113        MinProgramLengthParameterDescription,
114        new IntValue(config.MinPointsInProgram)) { Hidden = true });
115
116      Parameters.Add(new FixedValueParameter<IntValue>(
117        MaxPointsInProgramParameterName,
118        MaxProgramLengthParameterDescription,
119        new IntValue(config.MaxPointsInProgram)));
120      Encoding.LengthParameter = MaxPointsInProgramParameter as IFixedValueParameter<IntValue>;
121
122      Parameters.Add(new FixedValueParameter<BoolValue>(
123        TopLevelPushCodeParameterName,
124        TopLevelPushCodeParameterDescription,
125        new BoolValue(config.TopLevelPushCode)) { Hidden = true });
126
127      Parameters.Add(new FixedValueParameter<BoolValue>(
128        TopLevelPopCodeParameterName,
129        TopLevelPopCodeParameterDescription,
130        new BoolValue(config.TopLevelPopCode)) { Hidden = true });
131
132      Parameters.Add(new FixedValueParameter<IntValue>(
133        MaxPointsInRandomInstructionParameterName,
134        MaxPointsInRandomInstructionParameterDescription,
135        new IntValue(config.MaxPointsInRandomExpression)) { Hidden = true });
136
137      Parameters.Add(new FixedValueParameter<IntValue>(
138        MaxStringLengthParameterName,
139        new IntValue(config.MaxStringLength)) { Hidden = true });
140
141      Parameters.Add(new FixedValueParameter<IntValue>(
142        MaxDepthParameterName,
143        new IntValue(config.MaxDepth)) { Hidden = true });
144
145      Parameters.Add(new LookupParameter<BoolArray>("Cases", "The training cases that have been successfully executed."));
146      Parameters.Add(new LookupParameter<DoubleArray>(CaseQualitiesScopeParameterName, "The quality of every single training case for each individual"));
147
148      Encoding.Bounds[0, 0] = 0;
149      Encoding.Bounds[0, 1] = config.EnabledExpressions.Count;
150      Encoding.Length = config.MaxPointsInProgram;
151    }
152
153    public IValueParameter<IEnabledExpressionsConfiguration> InstructionsParameter
154    {
155      get { return (IValueParameter<IEnabledExpressionsConfiguration>)Parameters[InstructionsParameterName]; }
156    }
157
158    public IEnabledExpressionsConfiguration Instructions
159    {
160      get { return InstructionsParameter.Value; }
161      set { InstructionsParameter.Value = value; }
162    }
163
164    public IValueParameter<ErcOptions> ErcOptionsParameter
165    {
166      get { return (IValueParameter<ErcOptions>)Parameters[ErcOptionsParameterName]; }
167    }
168
169    public ErcOptions ErcOptions
170    {
171      get { return config.ErcOptions; }
172      set
173      {
174        ErcOptionsParameter.Value = value;
175        config.ErcOptions = value;
176      }
177    }
178
179    /// <summary>
180    ///     This is the maximum allowed number of "executions" in a single top-level call to the interpreter.
181    ///     The execution of a single Push instruction counts as one execution, as does the processing of a single literal,
182    ///     as does the descent into one layer of parentheses (that is, the processing of the "(" counts as one execution).
183    ///     When this limit is exceeded the interpreter aborts immediately, leaving its stacks in the states they were in prior
184    ///     to the abort (so they may still be examined by a calling program). Whether or not this counts as an "abnormal"
185    ///     termination
186    ///     is up to the calling program.
187    /// </summary>
188    public IValueParameter<IntValue> EvalPushLimitParameter
189    {
190      get { return (IValueParameter<IntValue>)Parameters[EvalPushLimitParameterName]; }
191    }
192
193    public int EvalPushLimit
194    {
195      get { return config.EvalPushLimit; }
196      set
197      {
198        EvalPushLimitParameter.Value.Value = value;
199        config.EvalPushLimit = value;
200      }
201    }
202
203    /// <summary>
204    /// This is the maximum of depth a push program can have. Expressions, which lead to exceed this limit are interpreted as NOOP.
205    /// </summary>
206    public IValueParameter<IntValue> MaxDepthParameter
207    {
208      get { return (IValueParameter<IntValue>)Parameters[MaxDepthParameterName]; }
209    }
210
211    public int MaxDepth
212    {
213      get { return config.MaxDepth; }
214      set
215      {
216        MaxDepthParameter.Value.Value = value;
217        config.MaxDepth = value;
218      }
219    }
220
221    /// <summary>
222    ///     This is the maximum size of an item on the CODE stack, expressed as a number of points.
223    ///     A point is an instruction, a literal, or a pair of parentheses. Any instruction that would cause this limit to be
224    ///     exceeded
225    ///     should instead act as a NOOP, leaving all stacks in the states that they were in before the execution of the
226    ///     instruction.
227    /// </summary>
228    public IValueParameter<IntValue> MaxPointsInProgramParameter
229    {
230      get { return (IValueParameter<IntValue>)Parameters[MaxPointsInProgramParameterName]; }
231    }
232
233    public int MaxPointsInProgram
234    {
235      get { return config.MaxPointsInProgram; }
236      set
237      {
238        MaxPointsInProgramParameter.Value.Value = value;
239        config.MaxPointsInProgram = value;
240      }
241    }
242
243    /// <summary>
244    ///     This is the minimum size of an item on the CODE stack, expressed as a number of points.
245    ///     A point is an instruction, a literal, or a pair of parentheses. Any instruction that would cause this limit to be
246    ///     exceeded
247    ///     should instead act as a NOOP, leaving all stacks in the states that they were in before the execution of the
248    ///     instruction.
249    /// </summary>
250    public IValueParameter<IntValue> MinPointsInProgramParameter
251    {
252      get { return (IValueParameter<IntValue>)Parameters[MinPointsInProgramParameterName]; }
253    }
254
255    public int MinPointsInProgram
256    {
257      get { return config.MaxPointsInProgram; }
258      set
259      {
260        MinPointsInProgramParameter.Value.Value = value;
261        config.MinPointsInProgram = value;
262      }
263    }
264
265    /// <summary>
266    ///     The maximum number of points in an expression produced by the CODE.RAND instruction.
267    /// </summary>
268    public IValueParameter<IntValue> MaxPointsInRandomExpressionParameter
269    {
270      get { return (IValueParameter<IntValue>)Parameters[MaxPointsInRandomInstructionParameterName]; }
271    }
272
273    public int MaxPointsInRandomExpression
274    {
275      get { return config.MaxPointsInRandomExpression; }
276      set
277      {
278        MaxPointsInRandomExpressionParameter.Value.Value = value;
279        config.MaxPointsInRandomExpression = value;
280      }
281    }
282
283    /// <summary>
284    ///     When TRUE (which is the default), code passed to the top level of the interpreter
285    ///     will be pushed onto the CODE stack prior to execution.
286    /// </summary>
287    public IValueParameter<BoolValue> TopLevelPushCodeParameter
288    {
289      get { return (IValueParameter<BoolValue>)Parameters[TopLevelPushCodeParameterName]; }
290    }
291
292    public bool TopLevelPushCode
293    {
294      get { return config.TopLevelPushCode; }
295      set
296      {
297        TopLevelPushCodeParameter.Value.Value = value;
298        config.TopLevelPushCode = value;
299      }
300    }
301
302    /// <summary>
303    ///     When TRUE, the CODE stack will be popped at the end of top level calls to the interpreter. The default is FALSE.
304    /// </summary>
305    public IValueParameter<BoolValue> TopLevelPopCodeParameter
306    {
307      get { return (IValueParameter<BoolValue>)Parameters[TopLevelPopCodeParameterName]; }
308    }
309
310    public bool TopLevelPopCode
311    {
312      get { return config.TopLevelPopCode; }
313      set
314      {
315        TopLevelPopCodeParameter.Value.Value = value;
316        config.TopLevelPopCode = value;
317      }
318    }
319
320    public IValueParameter<IntValue> MaxStringLengthParameter
321    {
322      get { return (IValueParameter<IntValue>)Parameters[MaxStringLengthParameterName]; }
323    }
324
325    public int MaxStringLength
326    {
327      get { return config.MaxStringLength; }
328      set
329      {
330        MaxStringLengthParameter.Value.Value = value;
331        config.MaxStringLength = value;
332      }
333    }
334    #endregion
335
336    public override bool Maximization { get { return false; } }
337
338    public override void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random) {
339      var bestQuality = Maximization ? qualities.Max() : qualities.Min();
340      var bestIdx = Array.IndexOf(qualities, bestQuality);
341      var bestIndividual = individuals[bestIdx].IntegerVector();
342
343      var isIndividualBetter = AnalyzeBestTrainingSolution(bestIndividual, bestQuality, results, random);
344
345      if (isIndividualBetter) {
346        AnalyzeBestTestSolution(bestIndividual, results, random);
347      }
348    }
349
350    private void AnalyzeBestTestSolution(IntegerVector bestIndividual, ResultCollection results, IRandom random) {
351      var program = bestIndividual.ToPushProgram(config, randomPool);
352      var testResult = PushEvaluator.EvaluateTest(pool, program, random);
353
354      if (!results.ContainsKey(TestQualityResultName)) {
355        results.Add(new Result(TestQualityResultName, new DoubleValue(testResult.TotalQuality)));
356      } else {
357        ((DoubleValue)results[TestQualityResultName].Value).Value = testResult.TotalQuality;
358      }
359    }
360
361    private bool AnalyzeBestTrainingSolution(IntegerVector bestIndividual, double bestQuality, ResultCollection results, IRandom random) {
362      var solution = CreatePushSolution(
363        bestIndividual,
364        bestQuality,
365        random,
366        config,
367        PushEvaluator);
368
369      if (!results.ContainsKey(BestTrainingSolutionResultName)) {
370        results.Add(new Result(BestTrainingSolutionResultName, solution));
371        return true;
372      }
373
374      var currentBestQuality = ((PushSolution)results[BestTrainingSolutionResultName].Value).Quality;
375
376      if (Maximization && currentBestQuality < bestQuality ||
377         !Maximization && currentBestQuality > bestQuality) {
378        results[BestTrainingSolutionResultName].Value = solution;
379        return true;
380      }
381
382      return false;
383    }
384
385    protected abstract PushSolution CreatePushSolution(
386      IntegerVector vector,
387      double bestQuality,
388      IRandom random,
389      IReadOnlyPushConfiguration config,
390      IPushEvaluator evaluator);
391
392    public override double Evaluate(Individual individual, IRandom random) {
393      var program = individual.ToPushProgram(config, randomPool);
394      var result = PushEvaluator.EvaluateTraining(pool, program, random);
395
396      individual[CaseQualitiesScopeParameterName] = new DoubleArray(result.ExampleQualities);
397
398      return result.TotalQuality;
399    }
400  }
401}
Note: See TracBrowser for help on using the repository browser.