Free cookie consent management tool by TermsFeed Policy Generator

source: branches/LearningClassifierSystems/HeuristicLab.Optimization.Operators.LCS/3.3/Selection/NichingTournamentSelector.cs @ 13820

Last change on this file since 13820 was 9605, checked in by sforsten, 12 years ago

#1980:

  • set plugin dependencies
  • added smart initialization
  • added hierarchical selection
  • fixed major and minor default rule
  • fixed several smaller bugs
  • some refactoring has been done
File size: 10.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Parameters;
29using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
30using HeuristicLab.Selection;
31
32namespace HeuristicLab.Optimization.Operators.LCS {
33  [Item("NichingTournamentSelector", "Description missing")]
34  [StorableClass]
35  public class NichingTournamentSelector : StochasticSingleObjectiveSelector, INichingSingleObjectiveSelector, IHierarchicalSingleObjectiveSelector {
36
37    #region Parameter Properties
38    public ValueLookupParameter<IntValue> GroupSizeParameter {
39      get { return (ValueLookupParameter<IntValue>)Parameters["GroupSize"]; }
40    }
41    public ILookupParameter<IGAssistProblemData> GAssistNichesProblemDataParameter {
42      get { return (LookupParameter<IGAssistProblemData>)Parameters["GAssistNichesProblemData"]; }
43    }
44    public ILookupParameter<BoolValue> NichingParameter {
45      get { return (LookupParameter<BoolValue>)Parameters["Niching"]; }
46    }
47    public IValueLookupParameter<IntValue> ParentsPerChildParameter {
48      get { return (IValueLookupParameter<IntValue>)Parameters["ParentsPerChild"]; }
49    }
50    public ILookupParameter<ItemArray<IGAssistIndividual>> IndividualParameter {
51      get { return (ILookupParameter<ItemArray<IGAssistIndividual>>)Parameters["Individual"]; }
52    }
53    public ILookupParameter<ItemArray<DoubleValue>> LengthParameter {
54      get { return (ILookupParameter<ItemArray<DoubleValue>>)Parameters["Length"]; }
55    }
56    public IValueLookupParameter<DoubleValue> LengthThresholdParameter {
57      get { return (IValueLookupParameter<DoubleValue>)Parameters["LengthThreshold"]; }
58    }
59    public IValueLookupParameter<IntValue> IterationHirachicalSelectionParameter {
60      get { return (IValueLookupParameter<IntValue>)Parameters["IterationHirachicalSelection"]; }
61    }
62
63    public ILookupParameter<IntValue> IterationsParameter {
64      get { return (ILookupParameter<IntValue>)Parameters["Iterations"]; }
65    }
66    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
67      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
68    }
69    #endregion
70
71    [StorableConstructor]
72    protected NichingTournamentSelector(bool deserializing) : base(deserializing) { }
73    protected NichingTournamentSelector(NichingTournamentSelector original, Cloner cloner)
74      : base(original, cloner) {
75    }
76    public NichingTournamentSelector()
77      : base() {
78      Parameters.Add(new ValueLookupParameter<IntValue>("GroupSize", "The size of the tournament group.", new IntValue(2)));
79      Parameters.Add(new LookupParameter<IGAssistProblemData>("GAssistNichesProblemData", ""));
80      Parameters.Add(new LookupParameter<BoolValue>("Niching", ""));
81      Parameters.Add(new ValueLookupParameter<IntValue>("ParentsPerChild", ""));
82      Parameters.Add(new ScopeTreeLookupParameter<IGAssistIndividual>("Individual", ""));
83      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Length", "The length value contained in each sub-scope which is used for selection."));
84      Parameters.Add(new ValueLookupParameter<DoubleValue>("LengthThreshold", "", new DoubleValue(0.000001)));
85      Parameters.Add(new ValueLookupParameter<IntValue>("IterationHirachicalSelection", "", new IntValue(24)));
86      Parameters.Add(new LookupParameter<IntValue>("Iterations", ""));
87      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", ""));
88    }
89    public override IDeepCloneable Clone(Cloner cloner) {
90      return new NichingTournamentSelector(this, cloner);
91    }
92
93    protected override IScope[] Select(List<IScope> scopes) {
94      int count = NumberOfSelectedSubScopesParameter.ActualValue.Value;
95      bool copy = CopySelectedParameter.Value.Value;
96      IRandom random = RandomParameter.ActualValue;
97      bool maximization = MaximizationParameter.ActualValue.Value;
98      List<double> qualities = QualityParameter.ActualValue.Where(x => IsValidQuality(x.Value)).Select(x => x.Value).ToList();
99      List<double> lengths = LengthParameter.ActualValue.Select(x => x.Value).ToList();
100      bool useLength = lengths.Count > 0;
101      double lengtThreshold = LengthThresholdParameter.ActualValue.Value;
102      List<IGAssistIndividual> individuals = IndividualParameter.ActualValue.ToList();
103      int groupSize = GroupSizeParameter.ActualValue.Value;
104      IScope[] selected = new IScope[count];
105      bool doNiching = NichingParameter.ActualValue.Value;
106
107      //check if list with indexes is as long as the original scope list
108      //otherwise invalid quality values were filtered
109      if (qualities.Count != scopes.Count || individuals.Count != scopes.Count || (useLength && lengths.Count != scopes.Count)) {
110        throw new ArgumentException("The scopes contain invalid quality values (either infinity or double.NaN) on which the selector cannot operate.");
111      }
112
113      int parentsPerChild = ParentsPerChildParameter.ActualValue.Value;
114
115      if (individuals.Any(x => x.Niche == null) && individuals.Any(x => x.Niche != null)) {
116        throw new ArgumentException("Either all individuals have a default action or none.");
117      }
118
119      //null cannot be a key in a dictionary (nicheScope), therefore torunament selection has to be done differently
120      //to keep it a little maintainable, the case that no default rule is used has been separated
121      if (individuals.Any(x => x.Niche == null)) {
122        //normal tournament selection
123        for (int i = 0; i < count; i++) {
124          int best = random.Next(scopes.Count);
125          int index;
126          for (int j = 1; j < groupSize; j++) {
127            index = random.Next(scopes.Count);
128            if (IsBetterHirachical(index, best, qualities, lengths, lengtThreshold, useLength, maximization)) {
129              best = index;
130            }
131          }
132
133          if (copy)
134            selected[i] = (IScope)scopes[best].Clone();
135          else {
136            selected[i] = scopes[best];
137            scopes.RemoveAt(best);
138            qualities.RemoveAt(best);
139          }
140        }
141      } else {
142        var nicheComparer = GAssistNichesProblemDataParameter.ActualValue.GetPossibleNiches().First().Comparer;
143        var selectPerNiche = new Dictionary<IGAssistNiche, int>(nicheComparer);
144        var nicheScope = new Dictionary<IGAssistNiche, List<int>>(nicheComparer);
145        //niching tournament selection
146        for (int i = 0; i < individuals.Count; i++) {
147          if (!nicheScope.ContainsKey(individuals[i].Niche)) {
148            nicheScope.Add(individuals[i].Niche, new List<int>());
149          }
150          nicheScope[individuals[i].Niche].Add(i);
151        }
152
153        var possibleNiches = nicheScope.Keys.ToList();
154        foreach (var niche in possibleNiches) {
155          selectPerNiche.Add(niche, count / possibleNiches.Count);
156        }
157
158        int curCount = 0;
159        while (curCount < count) {
160          IGAssistNiche niche = null;
161          int best = -1;
162          if (doNiching) {
163            niche = GetNiche(random, selectPerNiche, possibleNiches);
164          } else {
165            best = random.Next(scopes.Count);
166          }
167          for (int i = 0; i < parentsPerChild; i++) {
168            int index;
169            if (doNiching) {
170              best = nicheScope[niche][random.Next(nicheScope[niche].Count)];
171            }
172            for (int j = 1; j < groupSize; j++) {
173              if (niche != null) {
174                index = nicheScope[niche][random.Next(nicheScope[niche].Count)];
175              } else {
176                index = random.Next(scopes.Count);
177              }
178              if (IsBetterHirachical(index, best, qualities, lengths, lengtThreshold, useLength, maximization)) {
179                best = index;
180              }
181            }
182
183            niche = individuals[best].Niche;
184
185            if (copy)
186              selected[curCount] = (IScope)scopes[best].Clone();
187            else {
188              selected[curCount] = scopes[best];
189              scopes.RemoveAt(best);
190              qualities.RemoveAt(best);
191            }
192            selectPerNiche[niche]--;
193            curCount++;
194          }
195        }
196      }
197      return selected;
198    }
199
200    private bool IsBetterHirachical(int indexTrue, int indexFalse, IList<double> qualities, IList<double> length, double hierarchicalThreshold, bool useLength, bool maximization) {
201      if (useLength && IterationsParameter.ActualValue.Value >= IterationHirachicalSelectionParameter.ActualValue.Value
202        && Math.Abs(qualities[indexTrue] - qualities[indexFalse]) <= hierarchicalThreshold
203        && length[indexTrue] != length[indexFalse]) {
204        return length[indexTrue] < length[indexFalse];
205      }
206      return IsBetter(indexTrue, indexFalse, qualities, maximization);
207    }
208
209    private bool IsBetter(int indexTrue, int indexFalse, IList<double> qualities, bool maximization) {
210      return ((maximization) && (qualities[indexTrue] > qualities[indexFalse])) ||
211             ((!maximization) && (qualities[indexTrue] < qualities[indexFalse]));
212    }
213
214    private IGAssistNiche GetNiche(IRandom random, Dictionary<IGAssistNiche, int> selectPerNiche, List<IGAssistNiche> possibleNiches) {
215      int sum = selectPerNiche.Values.Sum();
216      if (sum <= 0) { return possibleNiches[random.Next(possibleNiches.Count)]; }
217      int pos = random.Next(sum);
218      int total = 0;
219      IGAssistNiche niche = selectPerNiche.Keys.First();
220      foreach (var item in selectPerNiche) {
221        total += item.Value;
222        niche = item.Key;
223        if (pos < total) {
224          return niche;
225        }
226      }
227      throw new ArgumentException("error in code");
228    }
229  }
230}
Note: See TracBrowser for help on using the repository browser.