Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2895_PushGP_GenealogyAnalysis/HeuristicLab.Problems.ProgramSynthesis/Push/Selector/LexicaseSelector.cs @ 15771

Last change on this file since 15771 was 15771, checked in by bburlacu, 6 years ago

#2895: Add solution skeleton for PushGP with genealogy analysis.

File size: 5.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25
26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Data;
29using HeuristicLab.Parameters;
30using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
31using HeuristicLab.Random;
32using HeuristicLab.Selection;
33
34namespace HeuristicLab.Problems.ProgramSynthesis {
35  /// <summary>
36  /// A lexicase selection operator which considers all successful evaluated training cases for selection.
37  /// </summary>
38  [Item("LexicaseSelector", "A lexicase selection operator which considers all successful evaluated training cases for selection.")]
39  [StorableClass]
40  public sealed class LexicaseSelector : StochasticSingleObjectiveSelector, ICaseSingleObjectiveSelector {
41    public ILookupParameter<ItemArray<DoubleArray>> CaseQualitiesParameter {
42      get { return (ILookupParameter<ItemArray<DoubleArray>>)Parameters[IntegerVectorPushProblem.CaseQualitiesScopeParameterName]; }
43    }
44
45    [StorableConstructor]
46    private LexicaseSelector(bool deserializing) : base(deserializing) { }
47    private LexicaseSelector(LexicaseSelector original, Cloner cloner) : base(original, cloner) { }
48    public override IDeepCloneable Clone(Cloner cloner) {
49      return new LexicaseSelector(this, cloner);
50    }
51
52    public LexicaseSelector() {
53      Parameters.Add(new ScopeTreeLookupParameter<DoubleArray>(
54        IntegerVectorPushProblem.CaseQualitiesScopeParameterName,
55        "The quality of every single training case for each individual."));
56    }
57
58
59    protected override IScope[] Select(List<IScope> scopes) {
60      var count = NumberOfSelectedSubScopesParameter.ActualValue.Value;
61      var copy = CopySelectedParameter.Value.Value;
62      var random = RandomParameter.ActualValue;
63      var maximization = MaximizationParameter.ActualValue.Value;
64      var caseQualities = CaseQualitiesParameter.ActualValue.ToList();
65
66      var selected = Apply(
67        scopes,
68        count,
69        copy,
70        maximization,
71        random,
72        caseQualities);
73
74      return selected;
75    }
76
77    public static IScope[] Apply(
78      List<IScope> scopes,
79      int count,
80      bool copy,
81      bool maximization,
82      IRandom random,
83      List<DoubleArray> caseQualities) {
84
85      for (var i = 0; i < caseQualities.Count; i++) {
86        if (caseQualities[i].Length == 0) {
87          scopes.RemoveAt(i);
88          caseQualities.RemoveAt(i);
89        }
90      }
91
92      var qualitiesLength = caseQualities[0].Length;
93
94      if (caseQualities.Any(x => x.Length != qualitiesLength)) {
95        throw new ArgumentException("Not all case qualities have the same length");
96      }
97
98      var selected = new IScope[count];
99
100      var candidates = new List<int>(caseQualities.Count);
101      for (var i = 0; i < caseQualities.Count; i++) candidates.Add(i);
102
103      var orderSource = new List<int>(qualitiesLength);
104      for (var i = 0; i < qualitiesLength; i++) orderSource.Add(i);
105
106      for (var i = 0; i < count; i++) {
107        var index = LexicaseSelect(
108          caseQualities,
109          candidates,
110          orderSource.Shuffle(random),
111          random,
112          maximization);
113
114        if (copy) {
115          selected[i] = (IScope)scopes[index].Clone();
116        } else {
117          selected[i] = scopes[index];
118          scopes.RemoveAt(index);
119          caseQualities.RemoveAt(index);
120        }
121      }
122
123      return selected;
124    }
125
126    private static int LexicaseSelect(
127      List<DoubleArray> caseQualities,
128      List<int> candidates,
129      IEnumerable<int> order,
130      IRandom random,
131      bool maximization) {
132
133      foreach (var curCase in order) {
134        var nextCandidates = new List<int>();
135
136        var best = maximization
137          ? double.NegativeInfinity
138          : double.PositiveInfinity;
139
140        for (var i = 0; i < candidates.Count; i++) {
141          var candidate = candidates[i];
142          var caseQuality = caseQualities[candidate][curCase];
143
144          if (caseQuality.IsAlmost(best)) {
145            // if the individuals is as good as the best one, add it
146            nextCandidates.Add(candidate);
147          } else if (
148             (maximization && (caseQuality > best)) ||
149             (!maximization && (caseQuality < best))) {
150            // if the individual is better than the best one, remove all previous candidates and add the new one
151            nextCandidates.Clear();
152            nextCandidates.Add(candidate);
153            // also set the next best quality value
154            best = caseQuality;
155          }
156          // else {do nothing}
157        }
158
159        if (nextCandidates.Count == 1) {
160          return nextCandidates[0];
161        }
162
163        if (nextCandidates.Count < 1) {
164          return candidates.SampleRandom(random);
165        }
166
167        candidates = nextCandidates;
168      }
169
170      return candidates.Count == 1
171        ? candidates[0]
172        : candidates.SampleRandom(random);
173    }
174  }
175}
Note: See TracBrowser for help on using the repository browser.