Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2665 Storable problem data, Renamings due to typos, Removed GP from class names

File size: 17.7 KB
Line 
1using System;
2
3namespace HeuristicLab.Problems.ProgramSynthesis.Push.Problem {
4  using System.Collections.Generic;
5  using System.Linq;
6  using BenchmarkSuite.Problems;
7  using Common;
8  using Configuration;
9  using Core;
10  using Encodings.IntegerVectorEncoding;
11  using Expressions;
12  using HeuristicLab.Data;
13  using Instances;
14  using Interpreter;
15  using Optimization;
16  using Parameters;
17  using Persistence.Default.CompositeSerializers.Storable;
18  using Stack;
19
20  [StorableClass]
21  [Creatable(CreatableAttribute.Categories.GeneticProgrammingProblems, Priority = 180)]
22  [Item("Push Problem", "")]
23  public class PushProblem : SingleObjectiveBasicProblem<IntegerVectorEncoding>, IProblemInstanceConsumer<Data> {
24    [Storable]
25    private readonly PushConfiguration config;
26    private PushInterpreterPool pool;
27
28    public PushProblem() {
29      config = new PushConfiguration();
30      pool = new PushInterpreterPool(config);
31
32      InitEvents();
33      InitParameters();
34      Instructions = config;
35    }
36
37    [StorableConstructor]
38    public PushProblem(bool deserializing)
39      : base(deserializing) {
40    }
41
42    public PushProblem(PushProblem original, Cloner cloner)
43      : base(original, cloner) {
44      config = cloner.Clone(original.config);
45      pool = new PushInterpreterPool(config);
46
47      Instructions = config;
48
49      this.InitEvents();
50    }
51
52
53    [StorableHook(HookType.AfterDeserialization)]
54    // ReSharper disable once UnusedMember.Local
55    private void AfterDeserialization() {
56      pool = new PushInterpreterPool(config);
57      Instructions = config;
58
59      InitEvents();
60    }
61
62    private void InitEvents() {
63      config.EnabledExpressionsChanged += EnabledExpressionsChanged;
64    }
65
66    private void EnabledExpressionsChanged(object sender, EnabledExpressionsChangedEventArgs e) {
67      this.Encoding.Bounds[0, 1] = config.EnabledExpressions.Count - 1;
68      this.Encoding.BoundsParameter.Value[0, 1] = config.EnabledExpressions.Count - 1;
69    }
70
71    #region Parameters
72
73    private const string EvalPushLimitParameterName = "EvalPushLimit";
74    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).";
75    private const string MaxProgramLengthParameterName = "MaxProgramLength";
76    private const string MaxProgramLengthParameterDescription = "This is the maximum size of an item on the CODE stack, expressed as a number of points. A point is an instruction, a literal, or a pair of parentheses.";
77    private const string TopLevelPushCodeParameterName = "TopLevelPushCode";
78    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.";
79    private const string TopLevelPopCodeParameterName = "TopLevelPopCode";
80    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.";
81    private const string InstructionsParameterName = "Instructions";
82    private const string InstructionsParameterDescription = "Enables/Disables Instructions";
83    private const string DataParameterName = "Data";
84    private const string DataParameterDescription = "Program Synthesis";
85    private const string MinRandomIntegerParameterName = "MinRandomInteger";
86    private const string MinRandomIntegerParameterDescription = "The minimum INTEGER that will be produced as an ephemeral random INTEGER constant or from a call to INTEGER.RAND.";
87    private const string MaxRandomIntegerParameterName = "MaxRandomInteger";
88    private const string MaxRandomIntegerParameterDescription = "The maximum INTEGER that will be produced as an ephemeral random INTEGER constant or from a call to INTEGER.RAND.";
89    private const string MinRandomFloatParameterName = "MinRandomFloat";
90    private const string MinRandomFloatParameterDescription = "The minimum FLOAT that will be produced as an ephemeral random FLOAT constant or from a call to FLOAT.RAND.";
91    private const string MaxRandomFloatParameterName = "MaxRandomFloat";
92    private const string MaxRandomFloatParameterDescription = "The maximum FLOAT that will be produced as an ephemeral random FLOAT constant or from a call to FLOAT.RAND.";
93    private const string NewErcNameProbabilityParameterName = "NewErcNameProbability";
94    private const string NewErcNameProbabilityParameterDescription = "The probability that the selection of the ephemeral random NAME constant for inclusion in randomly generated code will produce a new name.";
95    private const string ErcProbabilityParameterName = "ErcProbability";
96    private const string ErcProbabilityParameterDescription = "The probability that the selection of a epheral random literal constant for inclusion in randomly generated code will produce a new literal.";
97    private const string MaxPointsInRandomInstructionParameterName = "MaxPointsInRandomInstruction";
98    private const string MaxPointsInRandomInstructionParameterDescription = "MaxPointsInRandomInstruction";
99    private const string DataBoundsParameterName = "DataBounds";
100
101    private void InitParameters() {
102      var bounds = new IntMatrix(1, 3, new[] { "Training Start", "Training End | Test Start", "Test End" });
103      bounds.ItemChanged += (s, e) => {
104        if (Data == null)
105          return;
106
107        var max = Data.OriginalTestCount + Data.OriginalTrainingCount - 1;
108        bounds[0, 0] = Math.Min(Math.Max(bounds[0, 0], 0), max);
109        bounds[0, 2] = Math.Max(Math.Min(bounds[0, 2], max), 0);
110        bounds[0, 1] = Math.Min(Math.Max(bounds[0, 0], bounds[0, 1]), bounds[0, 2]);
111      };
112
113      Parameters.Add(new FixedValueParameter<IntMatrix>(
114        DataBoundsParameterName,
115        bounds));
116
117      Parameters.Add(new FixedValueParameter<IntValue>(
118        EvalPushLimitParameterName,
119        EvalPushLimitParameterDescription,
120        new IntValue(config.EvalPushLimit)));
121
122      Parameters.Add(new FixedValueParameter<IntValue>(
123        MaxProgramLengthParameterName,
124        MaxProgramLengthParameterDescription,
125        new IntValue(config.MaxPointsInProgram)));
126
127      Parameters.Add(new FixedValueParameter<BoolValue>(
128        TopLevelPushCodeParameterName,
129        TopLevelPushCodeParameterDescription,
130        new BoolValue(config.TopLevelPushCode)) { Hidden = true });
131
132      Parameters.Add(new FixedValueParameter<BoolValue>(
133        TopLevelPopCodeParameterName,
134        TopLevelPopCodeParameterDescription,
135        new BoolValue(config.TopLevelPopCode)) { Hidden = true });
136
137      Parameters.Add(new ValueParameter<IEnabledExpressionsConfiguration>(
138        InstructionsParameterName,
139        InstructionsParameterDescription));
140
141      Parameters.Add(new FixedValueParameter<IntValue>(
142        MinRandomIntegerParameterName,
143        MinRandomIntegerParameterDescription,
144        new IntValue(config.MinRandomInteger)) { Hidden = true });
145
146      Parameters.Add(new FixedValueParameter<IntValue>(
147        MaxRandomIntegerParameterName,
148        MaxRandomIntegerParameterDescription,
149        new IntValue(config.MaxRandomInteger)) { Hidden = true });
150
151      Parameters.Add(new FixedValueParameter<DoubleValue>(
152        MinRandomFloatParameterName,
153        MinRandomFloatParameterDescription,
154        new DoubleValue(config.MinRandomFloat)) { Hidden = true });
155
156      Parameters.Add(new FixedValueParameter<DoubleValue>(
157        MaxRandomFloatParameterName,
158        MaxRandomFloatParameterDescription,
159        new DoubleValue(config.MaxRandomFloat)) { Hidden = true });
160
161      Parameters.Add(new FixedValueParameter<PercentValue>(
162        NewErcNameProbabilityParameterName,
163        NewErcNameProbabilityParameterDescription,
164        new PercentValue(config.NewErcNameProbability)) { Hidden = true });
165
166      Parameters.Add(new FixedValueParameter<PercentValue>(
167        ErcProbabilityParameterName,
168        ErcProbabilityParameterDescription,
169        new PercentValue(config.ErcProbability)) { Hidden = true });
170
171      Parameters.Add(new FixedValueParameter<IntValue>(
172        MaxPointsInRandomInstructionParameterName,
173        MaxPointsInRandomInstructionParameterDescription,
174        new IntValue(config.MaxPointsInRandomExpression)) { Hidden = true });
175
176      Parameters.Add(new ValueParameter<Data>(DataParameterName, DataParameterDescription));
177
178      Encoding.Bounds[0, 0] = 0;
179      Encoding.Bounds[0, 1] = config.EnabledExpressions.Count - 1;
180      Encoding.Length = config.MaxPointsInProgram;
181    }
182
183    public IValueParameter<IntMatrix> DataBoundsParameter
184    {
185      get { return (IValueParameter<IntMatrix>)Parameters[DataBoundsParameterName]; }
186    }
187
188    public IntMatrix DataBounds
189    {
190      get { return DataBoundsParameter.Value; }
191      set { DataBoundsParameter.Value = value; }
192    }
193
194
195    public IValueParameter<IEnabledExpressionsConfiguration> InstructionsParameter
196    {
197      get { return (IValueParameter<IEnabledExpressionsConfiguration>)Parameters[InstructionsParameterName]; }
198    }
199
200    public IEnabledExpressionsConfiguration Instructions
201    {
202      get { return InstructionsParameter.Value; }
203      set { InstructionsParameter.Value = value; }
204    }
205
206    public IValueParameter<Data> DataParameter
207    {
208      get { return (IValueParameter<Data>)Parameters[DataParameterName]; }
209    }
210
211    public Data Data
212    {
213      get { return DataParameter.Value; }
214      set { DataParameter.Value = value; }
215    }
216
217    public IValueParameter<IntValue> EvalPushLimitParameter
218    {
219      get { return (IValueParameter<IntValue>)this.Parameters[EvalPushLimitParameterName]; }
220    }
221
222    public int EvalPushLimit
223    {
224      get { return config.EvalPushLimit; }
225      set
226      {
227        this.EvalPushLimitParameter.Value.Value = value;
228        config.EvalPushLimit = value;
229      }
230    }
231
232    public IValueParameter<IntValue> MaxProgramLengthParameter
233    {
234      get { return (IValueParameter<IntValue>)this.Parameters[MaxProgramLengthParameterName]; }
235    }
236
237    public int MaxProgramLength
238    {
239      get { return config.MaxPointsInProgram; }
240      set
241      {
242        this.MaxProgramLengthParameter.Value.Value = value;
243        this.Encoding.LengthParameter.Value.Value = value;
244        config.MaxPointsInProgram = value;
245      }
246    }
247
248    public IValueParameter<BoolValue> TopLevelPushParameter
249    {
250      get { return (IValueParameter<BoolValue>)this.Parameters[TopLevelPushCodeParameterName]; }
251    }
252
253    public bool TopLevelPushCode
254    {
255      get { return config.TopLevelPushCode; }
256      set
257      {
258        this.TopLevelPushParameter.Value.Value = value;
259        config.TopLevelPushCode = value;
260      }
261    }
262
263    public IValueParameter<BoolValue> TopLevelPopParameter
264    {
265      get { return (IValueParameter<BoolValue>)this.Parameters[TopLevelPopCodeParameterName]; }
266    }
267
268    public bool TopLevelPopCode
269    {
270      get { return config.TopLevelPopCode; }
271      set
272      {
273        this.TopLevelPushParameter.Value.Value = value;
274        config.TopLevelPopCode = value;
275      }
276    }
277
278    public IValueParameter<IntValue> MinRandomIntegerParameter
279    {
280      get { return (IValueParameter<IntValue>)this.Parameters[MinRandomIntegerParameterName]; }
281    }
282
283    public int MinRandomInteger
284    {
285      get { return config.MinRandomInteger; }
286      set
287      {
288        this.MinRandomIntegerParameter.Value.Value = value;
289        config.MinRandomInteger = value;
290      }
291    }
292
293    public IValueParameter<IntValue> MaxRandomIntegerParameter
294    {
295      get { return (IValueParameter<IntValue>)this.Parameters[MaxRandomIntegerParameterName]; }
296    }
297
298    public int MaxRandomInteger
299    {
300      get { return config.MaxRandomInteger; }
301      set
302      {
303        this.MaxRandomIntegerParameter.Value.Value = value;
304        config.MaxRandomInteger = value;
305      }
306    }
307
308    public IValueParameter<DoubleValue> MinRandomFloatParameter
309    {
310      get { return (IValueParameter<DoubleValue>)this.Parameters[MinRandomFloatParameterName]; }
311    }
312
313    public double MinRandomFloat
314    {
315      get { return config.MinRandomFloat; }
316      set
317      {
318        this.MinRandomFloatParameter.Value.Value = value;
319        config.MinRandomFloat = value;
320      }
321    }
322
323    public IValueParameter<DoubleValue> MaxRandomFloatParameter
324    {
325      get { return (IValueParameter<DoubleValue>)this.Parameters[MaxRandomFloatParameterName]; }
326    }
327
328    public double MaxRandomFloat
329    {
330      get { return config.MaxRandomFloat; }
331      set
332      {
333        this.MaxRandomFloatParameter.Value.Value = value;
334        config.MaxRandomFloat = value;
335      }
336    }
337
338    public IValueParameter<PercentValue> NewErcNameProbabilityParameter
339    {
340      get { return (IValueParameter<PercentValue>)this.Parameters[NewErcNameProbabilityParameterName]; }
341    }
342
343    public double NewErcNameProbability
344    {
345      get { return config.NewErcNameProbability; }
346      set
347      {
348        this.NewErcNameProbabilityParameter.Value.Value = value;
349        config.NewErcNameProbability = value;
350      }
351    }
352
353    public IValueParameter<PercentValue> ErcProbabilityParameter
354    {
355      get { return (IValueParameter<PercentValue>)this.Parameters[ErcProbabilityParameterName]; }
356    }
357
358    public double ErcProbability
359    {
360      get { return config.ErcProbability; }
361      set
362      {
363        this.ErcProbabilityParameter.Value.Value = value;
364        config.ErcProbability = value;
365      }
366    }
367
368    public IValueParameter<IntValue> MaxPointsInRandomInstructionParameter
369    {
370      get { return (IValueParameter<IntValue>)Parameters[MaxPointsInRandomInstructionParameterName]; }
371    }
372
373    public int MaxPointsInRandomInstruction
374    {
375      get { return config.MaxPointsInRandomExpression; }
376      set
377      {
378        this.MaxPointsInRandomInstructionParameter.Value.Value = value;
379        config.MaxPointsInRandomExpression = value;
380      }
381    }
382
383    #endregion
384
385    public override bool Maximization { get { return false; } }
386
387    public override IDeepCloneable Clone(Cloner cloner) {
388      return new PushProblem(this, cloner);
389    }
390
391    public override void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random) {
392      const string bestSolutionResultName = "Best Solution";
393      var bestQuality = Maximization ? qualities.Max() : qualities.Min();
394      var bestIdx = Array.IndexOf(qualities, bestQuality);
395      var bestIndividual = individuals[bestIdx];
396      var program = bestIndividual.PushProgram(config.EnabledExpressions);
397      var solution = new PushSolution(program, bestQuality, Data, random, pool);
398
399      if (!results.ContainsKey(bestSolutionResultName)) {
400        results.Add(new Result(bestSolutionResultName, solution));
401      } else if (((PushSolution)results[bestSolutionResultName].Value).Quality < qualities[bestIdx]) {
402        results[bestSolutionResultName].Value = solution;
403      }
404    }
405
406    public override double Evaluate(Individual individual, IRandom random) {
407      var program = individual.PushProgram(config.EnabledExpressions);
408      var expandExpression = new ExecExpandExpression(program);
409      var results = new List<double>();
410
411      using (var interpreter = pool.GetInstance(random)) {
412        for (var i = DataBounds[0, 0]; i < DataBounds[0, 1]; i++) {
413          var example = Data.Examples[i];
414
415          interpreter.BooleanStack.Push(example.InputBoolean);
416          interpreter.IntegerStack.Push(example.InputInt);
417          interpreter.FloatStack.Push(example.InputFloat);
418
419          interpreter.Run(expandExpression);
420
421          var diff = GetDiff(example.OutputInt, interpreter.IntegerStack, Data.WorstResult, LongDiffer) +
422                     GetDiff(example.OutputFloat, interpreter.FloatStack, Data.WorstResult, DoubleDiffer) +
423                     GetDiff(example.OutputBoolean, interpreter.BooleanStack, Data.WorstResult, BooleanDiffer);
424
425          results.Add(diff);
426          interpreter.Clear();
427        }
428      }
429
430      return results.Count == 0 ? 0d : results.Average();
431    }
432
433    private static double DoubleDiffer(double a, double b) {
434      var result = a - b;
435
436      return result == double.MinValue ? double.MaxValue : Math.Abs(result);
437    }
438
439    private static double LongDiffer(long a, long b) {
440      var result = a - b;
441
442      return result == long.MinValue ? long.MaxValue : Math.Abs(result);
443    }
444
445    private static double BooleanDiffer(bool a, bool b) {
446      return a && b ? 0 : a || b ? 1 : 2;
447    }
448
449    private static double GetDiff<T>(IReadOnlyList<T> estimated, IStack<T> resultStack, double worstResult, Func<T, T, double> differ)
450      where T : IComparable {
451
452      var count = Math.Min(estimated.Count, resultStack.Count);
453      var result = resultStack.Peek(count);
454      var comparableLength = Math.Min(estimated.Count, result.Length);
455      var diff = 0d;
456
457      for (var i = 0; i < comparableLength; i++) {
458        diff += Math.Min(differ(estimated[i], result[0]), worstResult);
459      }
460
461      if (estimated.Count > result.Length) {
462        diff += worstResult * (estimated.Count - comparableLength);
463      }
464
465      return diff;
466    }
467
468    public void Load(Data data) {
469      Data = data;
470      BestKnownQuality = data.BestResult;
471
472      DataBounds[0, 0] = 0;
473      DataBounds[0, 2] = Data.OriginalTrainingCount + Data.OriginalTestCount;
474      DataBounds[0, 1] = Data.OriginalTrainingCount;
475    }
476  }
477}
Note: See TracBrowser for help on using the repository browser.