Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2521_ProblemRefactoring/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/ParameterlessPopulationPyramid.cs @ 16723

Last change on this file since 16723 was 16723, checked in by abeham, 5 years ago

#2521: merged changes from r15684 to trunk HEAD (r16716) and resolved all merge conflicts

  • it doesn't build
File size: 12.2 KB
RevLine 
[11664]1#region License Information
2/* HeuristicLab
[16723]3 * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[11838]4 * and the BEACON Center for the Study of Evolution in Action.
5 *
[11664]6 * This file is part of HeuristicLab.
7 *
8 * HeuristicLab is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * HeuristicLab is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
20 */
21#endregion
22
23using System;
24using System.Collections.Generic;
[16692]25using System.Linq;
[11791]26using System.Threading;
[11666]27using HeuristicLab.Analysis;
[11664]28using HeuristicLab.Common;
29using HeuristicLab.Core;
30using HeuristicLab.Data;
[11666]31using HeuristicLab.Encodings.BinaryVectorEncoding;
[11664]32using HeuristicLab.Optimization;
33using HeuristicLab.Parameters;
[16723]34using HEAL.Attic;
[11664]35using HeuristicLab.Random;
36
37namespace HeuristicLab.Algorithms.ParameterlessPopulationPyramid {
[11838]38  // This code is based off the publication
39  // B. W. Goldman and W. F. Punch, "Parameter-less Population Pyramid," GECCO, pp. 785–792, 2014
40  // and the original source code in C++11 available from: https://github.com/brianwgoldman/Parameter-less_Population_Pyramid
[13173]41  [Item("Parameter-less Population Pyramid (P3)", "Binary value optimization algorithm which requires no configuration. B. W. Goldman and W. F. Punch, Parameter-less Population Pyramid, GECCO, pp. 785–792, 2014")]
[16723]42  [StorableType("CAD84CAB-1ECC-4D76-BDC5-701AAF690E17")]
[13173]43  [Creatable(CreatableAttribute.Categories.PopulationBasedAlgorithms, Priority = 400)]
[11791]44  public class ParameterlessPopulationPyramid : BasicAlgorithm {
45    public override Type ProblemType {
[16692]46      get { return typeof(SingleObjectiveProblem<BinaryVectorEncoding, BinaryVector>); }
[11791]47    }
[16692]48    public new SingleObjectiveProblem<BinaryVectorEncoding, BinaryVector> Problem {
49      get { return (SingleObjectiveProblem<BinaryVectorEncoding, BinaryVector>)base.Problem; }
50      set { base.Problem = value; }
[11791]51    }
[11667]52
[16692]53    [Storable]
[11666]54    private readonly IRandom random = new MersenneTwister();
[16692]55    [Storable]
56    private List<Population> pyramid = new List<Population>();
57    [Storable]
[11666]58    private EvaluationTracker tracker;
[11664]59
60    // Tracks all solutions in Pyramid for quick membership checks
[16692]61
[11987]62    private HashSet<BinaryVector> seen = new HashSet<BinaryVector>(new EnumerableBoolEqualityComparer());
[16692]63    [Storable]
64    private IEnumerable<BinaryVector> StorableSeen {
65      get { return seen; }
66      set { seen = new HashSet<BinaryVector>(value, new EnumerableBoolEqualityComparer()); }
67    }
[11681]68
[11669]69    #region ParameterNames
[11666]70    private const string MaximumIterationsParameterName = "Maximum Iterations";
[11669]71    private const string MaximumEvaluationsParameterName = "Maximum Evaluations";
[11791]72    private const string MaximumRuntimeParameterName = "Maximum Runtime";
[11669]73    private const string SeedParameterName = "Seed";
74    private const string SetSeedRandomlyParameterName = "SetSeedRandomly";
75    #endregion
[11681]76
[11669]77    #region ParameterProperties
[11666]78    public IFixedValueParameter<IntValue> MaximumIterationsParameter {
79      get { return (IFixedValueParameter<IntValue>)Parameters[MaximumIterationsParameterName]; }
[11664]80    }
[11669]81    public IFixedValueParameter<IntValue> MaximumEvaluationsParameter {
82      get { return (IFixedValueParameter<IntValue>)Parameters[MaximumEvaluationsParameterName]; }
83    }
[11791]84    public IFixedValueParameter<IntValue> MaximumRuntimeParameter {
85      get { return (IFixedValueParameter<IntValue>)Parameters[MaximumRuntimeParameterName]; }
86    }
[11669]87    public IFixedValueParameter<IntValue> SeedParameter {
88      get { return (IFixedValueParameter<IntValue>)Parameters[SeedParameterName]; }
89    }
90    public FixedValueParameter<BoolValue> SetSeedRandomlyParameter {
91      get { return (FixedValueParameter<BoolValue>)Parameters[SetSeedRandomlyParameterName]; }
92    }
93    #endregion
[11667]94
[11669]95    #region Properties
[11666]96    public int MaximumIterations {
97      get { return MaximumIterationsParameter.Value.Value; }
98      set { MaximumIterationsParameter.Value.Value = value; }
[11664]99    }
[11666]100    public int MaximumEvaluations {
101      get { return MaximumEvaluationsParameter.Value.Value; }
102      set { MaximumEvaluationsParameter.Value.Value = value; }
103    }
[11791]104    public int MaximumRuntime {
105      get { return MaximumRuntimeParameter.Value.Value; }
106      set { MaximumRuntimeParameter.Value.Value = value; }
107    }
[11666]108    public int Seed {
109      get { return SeedParameter.Value.Value; }
110      set { SeedParameter.Value.Value = value; }
111    }
112    public bool SetSeedRandomly {
113      get { return SetSeedRandomlyParameter.Value.Value; }
114      set { SetSeedRandomlyParameter.Value.Value = value; }
115    }
[11669]116    #endregion
[11666]117
118    #region ResultsProperties
119    private double ResultsBestQuality {
120      get { return ((DoubleValue)Results["Best Quality"].Value).Value; }
121      set { ((DoubleValue)Results["Best Quality"].Value).Value = value; }
122    }
123
124    private BinaryVector ResultsBestSolution {
125      get { return (BinaryVector)Results["Best Solution"].Value; }
126      set { Results["Best Solution"].Value = value; }
127    }
128
129    private int ResultsBestFoundOnEvaluation {
130      get { return ((IntValue)Results["Evaluation Best Solution Was Found"].Value).Value; }
131      set { ((IntValue)Results["Evaluation Best Solution Was Found"].Value).Value = value; }
132    }
133
134    private int ResultsEvaluations {
135      get { return ((IntValue)Results["Evaluations"].Value).Value; }
136      set { ((IntValue)Results["Evaluations"].Value).Value = value; }
137    }
138    private int ResultsIterations {
139      get { return ((IntValue)Results["Iterations"].Value).Value; }
140      set { ((IntValue)Results["Iterations"].Value).Value = value; }
141    }
142
143    private DataTable ResultsQualities {
144      get { return ((DataTable)Results["Qualities"].Value); }
145    }
146    private DataRow ResultsQualitiesBest {
147      get { return ResultsQualities.Rows["Best Quality"]; }
148    }
149
150    private DataRow ResultsQualitiesIteration {
151      get { return ResultsQualities.Rows["Iteration Quality"]; }
152    }
[11681]153
154
155    private DataRow ResultsLevels {
156      get { return ((DataTable)Results["Pyramid Levels"].Value).Rows["Levels"]; }
157    }
158
159    private DataRow ResultsSolutions {
160      get { return ((DataTable)Results["Stored Solutions"].Value).Rows["Solutions"]; }
161    }
[11666]162    #endregion
163
[16692]164    public override bool SupportsPause { get { return true; } }
165
[11664]166    [StorableConstructor]
[16723]167    protected ParameterlessPopulationPyramid(StorableConstructorFlag _) : base(_) { }
[11664]168
169    protected ParameterlessPopulationPyramid(ParameterlessPopulationPyramid original, Cloner cloner)
170      : base(original, cloner) {
[16692]171      random = cloner.Clone(original.random);
172      pyramid = original.pyramid.Select(cloner.Clone).ToList();
173      tracker = cloner.Clone(original.tracker);
174      seen = new HashSet<BinaryVector>(original.seen.Select(cloner.Clone), new EnumerableBoolEqualityComparer());
[11664]175    }
176
177    public override IDeepCloneable Clone(Cloner cloner) {
178      return new ParameterlessPopulationPyramid(this, cloner);
179    }
180
[16692]181    public ParameterlessPopulationPyramid() : base() {
[11668]182      Parameters.Add(new FixedValueParameter<IntValue>(MaximumIterationsParameterName, "", new IntValue(Int32.MaxValue)));
[11791]183      Parameters.Add(new FixedValueParameter<IntValue>(MaximumEvaluationsParameterName, "", new IntValue(Int32.MaxValue)));
184      Parameters.Add(new FixedValueParameter<IntValue>(MaximumRuntimeParameterName, "The maximum runtime in seconds after which the algorithm stops. Use -1 to specify no limit for the runtime", new IntValue(3600)));
[11666]185      Parameters.Add(new FixedValueParameter<IntValue>(SeedParameterName, "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
186      Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyParameterName, "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
[11664]187    }
188
[11791]189    protected override void OnExecutionTimeChanged() {
190      base.OnExecutionTimeChanged();
191      if (CancellationTokenSource == null) return;
192      if (MaximumRuntime == -1) return;
193      if (ExecutionTime.TotalSeconds > MaximumRuntime) CancellationTokenSource.Cancel();
194    }
195
[11987]196    private void AddIfUnique(BinaryVector solution, int level) {
[11664]197      // Don't add things you have seen
198      if (seen.Contains(solution)) return;
199      if (level == pyramid.Count) {
[13361]200        pyramid.Add(new Population(Problem.Encoding.Length, random));
[11664]201      }
[11987]202      var copied = (BinaryVector)solution.Clone();
[11667]203      pyramid[level].Add(copied);
204      seen.Add(copied);
[11664]205    }
206
[11672]207    // In the GECCO paper, Figure 1
[11664]208    private double iterate() {
209      // Create a random solution
[13361]210      BinaryVector solution = new BinaryVector(Problem.Encoding.Length);
[11664]211      for (int i = 0; i < solution.Length; i++) {
212        solution[i] = random.Next(2) == 1;
213      }
[11987]214      double fitness = tracker.Evaluate(solution, random);
[11666]215      fitness = HillClimber.ImproveToLocalOptimum(tracker, solution, fitness, random);
[11664]216      AddIfUnique(solution, 0);
[11667]217
[11664]218      for (int level = 0; level < pyramid.Count; level++) {
219        var current = pyramid[level];
[11666]220        double newFitness = LinkageCrossover.ImproveUsingTree(current.Tree, current.Solutions, solution, fitness, tracker, random);
[11664]221        // add it to the next level if its a strict fitness improvement
[11666]222        if (tracker.IsBetter(newFitness, fitness)) {
[11664]223          fitness = newFitness;
224          AddIfUnique(solution, level + 1);
225        }
226      }
227      return fitness;
228    }
229
[16692]230    protected override void Initialize(CancellationToken cancellationToken) {
[11669]231      // Set up the algorithm
[16723]232      if (SetSeedRandomly) Seed = RandomSeedGenerator.GetSeed();
[11664]233      pyramid = new List<Population>();
[11667]234      seen.Clear();
[11666]235      random.Reset(Seed);
236      tracker = new EvaluationTracker(Problem, MaximumEvaluations);
[11669]237
238      // Set up the results display
[11666]239      Results.Add(new Result("Iterations", new IntValue(0)));
240      Results.Add(new Result("Evaluations", new IntValue(0)));
241      Results.Add(new Result("Best Solution", new BinaryVector(tracker.BestSolution)));
242      Results.Add(new Result("Best Quality", new DoubleValue(tracker.BestQuality)));
243      Results.Add(new Result("Evaluation Best Solution Was Found", new IntValue(tracker.BestFoundOnEvaluation)));
244      var table = new DataTable("Qualities");
245      table.Rows.Add(new DataRow("Best Quality"));
246      var iterationRows = new DataRow("Iteration Quality");
247      iterationRows.VisualProperties.LineStyle = DataRowVisualProperties.DataRowLineStyle.Dot;
248      table.Rows.Add(iterationRows);
249      Results.Add(new Result("Qualities", table));
[11669]250
[11681]251      table = new DataTable("Pyramid Levels");
252      table.Rows.Add(new DataRow("Levels"));
253      Results.Add(new Result("Pyramid Levels", table));
254
255      table = new DataTable("Stored Solutions");
256      table.Rows.Add(new DataRow("Solutions"));
257      Results.Add(new Result("Stored Solutions", table));
258
[16692]259      base.Initialize(cancellationToken);
260    }
261
262    protected override void Run(CancellationToken cancellationToken) {
[11669]263      // Loop until iteration limit reached or canceled.
[16692]264      while (ResultsIterations < MaximumIterations) {
[11666]265        double fitness = double.NaN;
266
267        try {
268          fitness = iterate();
[16692]269          ResultsIterations++;
[11791]270          cancellationToken.ThrowIfCancellationRequested();
[13339]271        }
272        finally {
[11666]273          ResultsEvaluations = tracker.Evaluations;
274          ResultsBestSolution = new BinaryVector(tracker.BestSolution);
275          ResultsBestQuality = tracker.BestQuality;
276          ResultsBestFoundOnEvaluation = tracker.BestFoundOnEvaluation;
277          ResultsQualitiesBest.Values.Add(tracker.BestQuality);
278          ResultsQualitiesIteration.Values.Add(fitness);
[11681]279          ResultsLevels.Values.Add(pyramid.Count);
280          ResultsSolutions.Values.Add(seen.Count);
[11667]281        }
[11664]282      }
283    }
284  }
285}
Note: See TracBrowser for help on using the repository browser.