Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2665 PushGP HL Integration, Views, Parameters

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