[15275] | 1 | using System;
|
---|
| 2 | using System.Linq;
|
---|
[15771] | 3 | using HeuristicLab.Common;
|
---|
| 4 | using HeuristicLab.Core;
|
---|
| 5 | using HeuristicLab.Data;
|
---|
| 6 | using HeuristicLab.Optimization;
|
---|
| 7 | using HeuristicLab.Parameters;
|
---|
| 8 | using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
|
---|
| 9 | using HeuristicLab.Random;
|
---|
[15275] | 10 |
|
---|
[15771] | 11 | namespace HeuristicLab.Problems.ProgramSynthesis { |
---|
[15275] | 12 | [StorableClass]
|
---|
| 13 | public abstract class PushProblemBase<T> : SingleObjectiveBasicProblem<T> where T : class, IEncoding {
|
---|
| 14 | [Storable]
|
---|
[15334] | 15 | public readonly PushConfiguration Config;
|
---|
[15275] | 16 |
|
---|
| 17 | protected PushInterpreterPool Pool;
|
---|
| 18 | protected readonly SeededRandomPool RandomPool = new SeededRandomPool();
|
---|
| 19 |
|
---|
| 20 | [Storable]
|
---|
| 21 | protected readonly IPushEvaluator PushEvaluator;
|
---|
| 22 |
|
---|
| 23 | private const string BEST_TRAINING_SOLUTION_RESULT_NAME = "Best Solution";
|
---|
| 24 | private const string TEST_QUALITY_RESULT_NAME = "Test Quality";
|
---|
| 25 | private const string PUSH_CONFIGURATION_PARAMETER_NAME = "PushConfiguration";
|
---|
| 26 |
|
---|
| 27 | public const string CasesScopeParameterName = "CaseQualities";
|
---|
| 28 | public const string CaseQualitiesScopeParameterName = "CaseQualities";
|
---|
[15289] | 29 | public const string SeedScopeParameterName = "Seed";
|
---|
[15275] | 30 |
|
---|
| 31 | protected PushProblemBase(IPushEvaluator evaluator) {
|
---|
[15334] | 32 | Config = new PushConfiguration();
|
---|
[15275] | 33 | PushEvaluator = evaluator;
|
---|
| 34 |
|
---|
| 35 | InitData();
|
---|
| 36 | InitParameters();
|
---|
| 37 | }
|
---|
| 38 |
|
---|
| 39 | [StorableConstructor]
|
---|
| 40 | protected PushProblemBase(bool deserializing)
|
---|
| 41 | : base(deserializing) {
|
---|
| 42 | }
|
---|
| 43 |
|
---|
| 44 | protected PushProblemBase(PushProblemBase<T> original, Cloner cloner)
|
---|
| 45 | : base(original, cloner) {
|
---|
| 46 | Config = cloner.Clone(original.Config);
|
---|
| 47 | PushEvaluator = cloner.Clone(original.PushEvaluator);
|
---|
| 48 |
|
---|
| 49 | InitData();
|
---|
| 50 | }
|
---|
| 51 |
|
---|
| 52 | [StorableHook(HookType.AfterDeserialization)]
|
---|
| 53 | // ReSharper disable once UnusedMember.Local
|
---|
| 54 | private void AfterDeserialization() {
|
---|
| 55 | InitData();
|
---|
| 56 | InitParameters();
|
---|
| 57 | }
|
---|
| 58 |
|
---|
| 59 | private void InitData() {
|
---|
| 60 | Pool = new PushInterpreterPool(Environment.ProcessorCount * 2, 4096, 1024, Config);
|
---|
| 61 | }
|
---|
| 62 |
|
---|
| 63 | private void InitParameters() {
|
---|
| 64 | foreach (var paramater in Config.Parameters) {
|
---|
| 65 | if (!Parameters.ContainsKey(paramater.Name)) {
|
---|
| 66 | Parameters.Add(paramater);
|
---|
| 67 | }
|
---|
| 68 | }
|
---|
| 69 |
|
---|
| 70 | if (!Parameters.ContainsKey(PUSH_CONFIGURATION_PARAMETER_NAME))
|
---|
| 71 | Parameters.Add(new ValueParameter<IReadOnlyPushConfiguration>(PUSH_CONFIGURATION_PARAMETER_NAME, Config) {
|
---|
| 72 | Hidden = true
|
---|
| 73 | });
|
---|
| 74 |
|
---|
| 75 | if (!Parameters.ContainsKey(CasesScopeParameterName))
|
---|
| 76 | Parameters.Add(new LookupParameter<BoolArray>(CasesScopeParameterName, "The training cases that have been successfully executed."));
|
---|
| 77 |
|
---|
| 78 | if (!Parameters.ContainsKey(CaseQualitiesScopeParameterName))
|
---|
| 79 | Parameters.Add(new LookupParameter<DoubleArray>(CaseQualitiesScopeParameterName, "The quality of every single training case for each individual"));
|
---|
| 80 | }
|
---|
| 81 |
|
---|
| 82 | public override bool Maximization { get { return false; } }
|
---|
| 83 |
|
---|
| 84 | public override void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random) {
|
---|
| 85 | var bestQuality = Maximization ? qualities.Max() : qualities.Min();
|
---|
| 86 | var bestIdx = Array.IndexOf(qualities, bestQuality);
|
---|
[15289] | 87 | var bestIndividual = individuals[bestIdx];
|
---|
| 88 | var seed = (IntValue)bestIndividual[SeedScopeParameterName];
|
---|
| 89 | var program = MapIndividual(bestIndividual);
|
---|
[15275] | 90 |
|
---|
[15289] | 91 | var rand = new FastRandom(seed.Value);
|
---|
| 92 | var isIndividualBetter = AnalyzeBestTrainingSolution(program, bestQuality, results, rand);
|
---|
[15275] | 93 |
|
---|
| 94 | if (isIndividualBetter) {
|
---|
[15289] | 95 | rand.Reset(seed.Value);
|
---|
| 96 | AnalyzeBestTestSolution(program, results, rand);
|
---|
[15275] | 97 | }
|
---|
| 98 | }
|
---|
| 99 |
|
---|
| 100 | protected void AnalyzeBestTestSolution(PushProgram program, ResultCollection results, IRandom random) {
|
---|
[15289] | 101 | var testResult = PushEvaluator.EvaluateTest(Pool, program, random);
|
---|
[15275] | 102 |
|
---|
| 103 | if (!results.ContainsKey(TEST_QUALITY_RESULT_NAME)) {
|
---|
| 104 | results.Add(new Result(TEST_QUALITY_RESULT_NAME, new DoubleValue(testResult.AvgQuality)));
|
---|
| 105 | } else {
|
---|
| 106 | ((DoubleValue)results[TEST_QUALITY_RESULT_NAME].Value).Value = testResult.AvgQuality;
|
---|
| 107 | }
|
---|
| 108 | }
|
---|
| 109 |
|
---|
| 110 | protected bool AnalyzeBestTrainingSolution(PushProgram program, double bestQuality, ResultCollection results, IRandom random) {
|
---|
[15289] | 111 | var solution = CreatePushSolution(
|
---|
[15275] | 112 | program,
|
---|
| 113 | bestQuality,
|
---|
[15289] | 114 | random, // is already cloned
|
---|
[15275] | 115 | (IReadOnlyPushConfiguration)Config.Clone());
|
---|
| 116 |
|
---|
[15289] | 117 | if (!results.ContainsKey(BEST_TRAINING_SOLUTION_RESULT_NAME)) {
|
---|
[15275] | 118 | results.Add(new Result(BEST_TRAINING_SOLUTION_RESULT_NAME, solution));
|
---|
| 119 | return true;
|
---|
| 120 | }
|
---|
| 121 |
|
---|
| 122 | var currentBestQuality = ((PushSolution)results[BEST_TRAINING_SOLUTION_RESULT_NAME].Value).Quality;
|
---|
| 123 |
|
---|
| 124 | if ((!Maximization && currentBestQuality > bestQuality) ||
|
---|
| 125 | (Maximization && currentBestQuality < bestQuality)) {
|
---|
[15289] | 126 | results[BEST_TRAINING_SOLUTION_RESULT_NAME].Value = solution;
|
---|
[15275] | 127 | return true;
|
---|
| 128 | }
|
---|
| 129 |
|
---|
| 130 | return false;
|
---|
| 131 | }
|
---|
| 132 |
|
---|
| 133 | public override double Evaluate(Individual individual, IRandom random) {
|
---|
[15289] | 134 | var program = MapIndividual(individual);
|
---|
| 135 | var seed = random.Next();
|
---|
| 136 | var rand = new FastRandom(seed);
|
---|
| 137 | var result = PushEvaluator.EvaluateTraining(Pool, program, rand);
|
---|
[15275] | 138 |
|
---|
| 139 | individual[CaseQualitiesScopeParameterName] = new DoubleArray(result.ExampleQualities);
|
---|
[15289] | 140 | individual[SeedScopeParameterName] = new IntValue(seed);
|
---|
[15275] | 141 |
|
---|
| 142 | return result.AvgQuality;
|
---|
| 143 | }
|
---|
| 144 |
|
---|
[15289] | 145 | protected abstract PushProgram MapIndividual(Individual individual);
|
---|
[15275] | 146 |
|
---|
| 147 | protected abstract PushSolution CreatePushSolution(
|
---|
| 148 | PushProgram program,
|
---|
| 149 | double bestQuality,
|
---|
| 150 | IRandom random,
|
---|
| 151 | IReadOnlyPushConfiguration config);
|
---|
| 152 | }
|
---|
| 153 | }
|
---|