source: branches/VOSGA/HeuristicLab.Algorithms.VOffspringSelectionGeneticAlgorithm/OffspringSelectors/StandardOffspringSelector.cs @ 11510

Last change on this file since 11510 was 11510, checked in by ascheibe, 8 years ago

#2267 made offspring selector configurable

File size: 10.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2014 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 HeuristicLab.Common;
24using HeuristicLab.Core;
25using HeuristicLab.Data;
26using HeuristicLab.Operators;
27using HeuristicLab.Parameters;
28using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
29
30namespace HeuristicLab.Algorithms.VOffspringSelectionGeneticAlgorithm {
31  [Item("StandardOffspringSelector", "Selects among the offspring population those that are designated successful and discards the unsuccessful offspring, except for some lucky losers. It expects the parent scopes to be below the first sub-scope, and offspring scopes to be below the second sub-scope separated again in two sub-scopes, the first with the failed offspring and the second with successful offspring.")]
32  [StorableClass]
33  public class StandardOffspringSelector : SingleSuccessorOperator, IOffspringSelector {
34    public ValueLookupParameter<DoubleValue> MaximumSelectionPressureParameter {
35      get { return (ValueLookupParameter<DoubleValue>)Parameters["MaximumSelectionPressure"]; }
36    }
37    public ValueLookupParameter<DoubleValue> SuccessRatioParameter {
38      get { return (ValueLookupParameter<DoubleValue>)Parameters["SuccessRatio"]; }
39    }
40    public LookupParameter<DoubleValue> SelectionPressureParameter {
41      get { return (ValueLookupParameter<DoubleValue>)Parameters["SelectionPressure"]; }
42    }
43    public LookupParameter<DoubleValue> CurrentSuccessRatioParameter {
44      get { return (LookupParameter<DoubleValue>)Parameters["CurrentSuccessRatio"]; }
45    }
46    public LookupParameter<ItemList<IScope>> OffspringPopulationParameter {
47      get { return (LookupParameter<ItemList<IScope>>)Parameters["OffspringPopulation"]; }
48    }
49    public LookupParameter<IntValue> OffspringPopulationWinnersParameter {
50      get { return (LookupParameter<IntValue>)Parameters["OffspringPopulationWinners"]; }
51    }
52    public ScopeTreeLookupParameter<BoolValue> SuccessfulOffspringParameter {
53      get { return (ScopeTreeLookupParameter<BoolValue>)Parameters["SuccessfulOffspring"]; }
54    }
55    public IValueLookupParameter<BoolValue> FillPopulationWithParentsParameter {
56      get { return (IValueLookupParameter<BoolValue>)Parameters["FillPopulationWithParents"]; }
57    }
58    public ILookupParameter<BoolValue> EnoughChildrenGeneratedParameter {
59      get { return (ILookupParameter<BoolValue>)Parameters["EnoughChildrenGenerated"]; }
60    }
61
62
63    [StorableConstructor]
64    protected StandardOffspringSelector(bool deserializing) : base(deserializing) { }
65    [StorableHook(HookType.AfterDeserialization)]
66    private void AfterDeserialization() {
67      // BackwardsCompatibility3.3
68      #region Backwards compatible code, remove with 3.4
69      if (Parameters.ContainsKey("FillPopulationWithParents") && Parameters["FillPopulationWithParents"] is FixedValueParameter<BoolValue>)
70        Parameters.Remove("FillPopulationWithParents");
71      if (!Parameters.ContainsKey("FillPopulationWithParents"))
72        Parameters.Add(new ValueLookupParameter<BoolValue>("FillPopulationWithParents", "True if the population should be filled with parent individuals instead of lucky losers."));
73      #endregion
74    }
75
76    protected StandardOffspringSelector(StandardOffspringSelector original, Cloner cloner) : base(original, cloner) { }
77    public override IDeepCloneable Clone(Cloner cloner) {
78      return new StandardOffspringSelector(this, cloner);
79    }
80    public StandardOffspringSelector()
81      : base() {
82      Parameters.Add(new ValueLookupParameter<DoubleValue>("MaximumSelectionPressure", "The maximum selection pressure which prematurely terminates the offspring selection step."));
83      Parameters.Add(new ValueLookupParameter<DoubleValue>("SuccessRatio", "The ratio of successful offspring that has to be produced."));
84      Parameters.Add(new ValueLookupParameter<DoubleValue>("SelectionPressure", "The amount of selection pressure currently necessary to fulfill the success ratio."));
85      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentSuccessRatio", "The current success ratio indicates how much of the successful offspring have already been generated."));
86      Parameters.Add(new LookupParameter<ItemList<IScope>>("OffspringPopulation", "Temporary store of the offspring population."));
87      Parameters.Add(new LookupParameter<IntValue>("OffspringPopulationWinners", "Temporary store the number of successful offspring in the offspring population."));
88      Parameters.Add(new ScopeTreeLookupParameter<BoolValue>("SuccessfulOffspring", "True if the offspring was more successful than its parents.", 2));
89      Parameters.Add(new ValueLookupParameter<BoolValue>("FillPopulationWithParents", "True if the population should be filled with parent individual or false if worse children should be used when the maximum selection pressure is exceeded."));
90      Parameters.Add(new LookupParameter<BoolValue>("EnoughChildrenGenerated", "True if enough children have been generated, otherwise false."));
91    }
92
93    public override IOperation Apply() {
94      double maxSelPress = MaximumSelectionPressureParameter.ActualValue.Value;
95      double successRatio = SuccessRatioParameter.ActualValue.Value;
96      bool fillPopulationWithParents = false;
97      if (FillPopulationWithParentsParameter.ActualValue != null)
98        fillPopulationWithParents = FillPopulationWithParentsParameter.ActualValue.Value;
99      IScope scope = ExecutionContext.Scope;
100      IScope parents = scope.SubScopes[0];
101      IScope offspring = scope.SubScopes[1];
102      int populationSize = parents.SubScopes.Count;
103
104      // retrieve actual selection pressure and success ratio
105      DoubleValue selectionPressure = SelectionPressureParameter.ActualValue;
106      if (selectionPressure == null) {
107        selectionPressure = new DoubleValue(0);
108        SelectionPressureParameter.ActualValue = selectionPressure;
109      }
110      DoubleValue currentSuccessRatio = CurrentSuccessRatioParameter.ActualValue;
111      if (currentSuccessRatio == null) {
112        currentSuccessRatio = new DoubleValue(0);
113        CurrentSuccessRatioParameter.ActualValue = currentSuccessRatio;
114      }
115
116      // retrieve next population
117      ItemList<IScope> population = OffspringPopulationParameter.ActualValue;
118      IntValue successfulOffspring;
119      if (population == null) {
120        population = new ItemList<IScope>();
121        OffspringPopulationParameter.ActualValue = population;
122        selectionPressure.Value = 0; // initialize selection pressure for this round
123        currentSuccessRatio.Value = 0; // initialize current success ratio for this round
124        successfulOffspring = new IntValue(0);
125        OffspringPopulationWinnersParameter.ActualValue = successfulOffspring;
126      } else successfulOffspring = OffspringPopulationWinnersParameter.ActualValue;
127
128      int worseOffspringNeeded = (int)((1 - successRatio) * populationSize) - (population.Count - successfulOffspring.Value);
129      int successfulOffspringAdded = 0;
130
131      // implement the ActualValue fetch here - otherwise the parent scope would also be included, given that there may be 1000 or more parents, this is quite unnecessary
132      string tname = SuccessfulOffspringParameter.TranslatedName;
133      double tmpSelPress = selectionPressure.Value, tmpSelPressInc = 1.0 / populationSize;
134      for (int i = 0; i < offspring.SubScopes.Count; i++) {
135        // fetch value
136        IVariable tmpVar;
137        if (!offspring.SubScopes[i].Variables.TryGetValue(tname, out tmpVar)) throw new InvalidOperationException(Name + ": Could not determine if an offspring was successful or not.");
138        BoolValue tmp = (tmpVar.Value as BoolValue);
139        if (tmp == null) throw new InvalidOperationException(Name + ": The variable that indicates whether an offspring is successful or not must contain a BoolValue.");
140
141        // add to population
142        if (tmp.Value) {
143          IScope currentOffspring = offspring.SubScopes[i];
144          offspring.SubScopes.Remove(currentOffspring);
145          i--;
146          population.Add(currentOffspring);
147          successfulOffspringAdded++;
148        } else if (worseOffspringNeeded > 0 || tmpSelPress >= maxSelPress) {
149          IScope currentOffspring;
150          if (!fillPopulationWithParents || worseOffspringNeeded > 0) {
151            currentOffspring = offspring.SubScopes[i];
152            offspring.SubScopes.Remove(currentOffspring);
153            i--;
154            worseOffspringNeeded--;
155          } else {
156            currentOffspring = parents.SubScopes[i];
157          }
158          population.Add(currentOffspring);
159        }
160        tmpSelPress += tmpSelPressInc;
161        if (population.Count == populationSize) break;
162      }
163      successfulOffspring.Value += successfulOffspringAdded;
164
165      // calculate actual selection pressure and success ratio
166      selectionPressure.Value = tmpSelPress;
167      currentSuccessRatio.Value = successfulOffspring.Value / ((double)populationSize);
168
169
170      if (EnoughChildrenGeneratedParameter.ActualValue == null) {
171        EnoughChildrenGeneratedParameter.ActualValue = new BoolValue();
172      }
173      // check if enough children have been generated
174      if (((selectionPressure.Value < maxSelPress) && (currentSuccessRatio.Value < successRatio)) ||
175          (population.Count < populationSize)) {
176        // more children required -> reduce left and start children generation again
177        scope.SubScopes.Remove(parents);
178        scope.SubScopes.Remove(offspring);
179        while (parents.SubScopes.Count > 0) {
180          IScope parent = parents.SubScopes[0];
181          parents.SubScopes.RemoveAt(0);
182          scope.SubScopes.Add(parent);
183        }
184        EnoughChildrenGeneratedParameter.ActualValue.Value = false;
185      } else {
186        // enough children generated
187        offspring.SubScopes.Clear();
188        offspring.SubScopes.AddRange(population);
189
190        scope.Variables.Remove(OffspringPopulationParameter.TranslatedName);
191        scope.Variables.Remove(OffspringPopulationWinnersParameter.TranslatedName);
192        EnoughChildrenGeneratedParameter.ActualValue.Value = true;
193      }
194      return base.Apply();
195    }
196  }
197}
Note: See TracBrowser for help on using the repository browser.