Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.Selection/3.3/OffspringSelector.cs @ 10870

Last change on this file since 10870 was 10644, checked in by mkommend, 11 years ago

#2172: Merged r10639 and r10643 into stable.

File size: 10.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2013 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.Selection {
31  [Item("OffspringSelector", "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 OffspringSelector : SingleSuccessorOperator {
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 OperatorParameter OffspringCreatorParameter {
56      get { return (OperatorParameter)Parameters["OffspringCreator"]; }
57    }
58
59    public IValueLookupParameter<BoolValue> FillPopulationWithParentsParameter {
60      get { return (IValueLookupParameter<BoolValue>)Parameters["FillPopulationWithParents"]; }
61    }
62
63    public IOperator OffspringCreator {
64      get { return OffspringCreatorParameter.Value; }
65      set { OffspringCreatorParameter.Value = value; }
66    }
67
68    [StorableConstructor]
69    protected OffspringSelector(bool deserializing) : base(deserializing) { }
70    [StorableHook(HookType.AfterDeserialization)]
71    private void AfterDeserialization() {
72      // BackwardsCompatibility3.3
73      #region Backwards compatible code, remove with 3.4
74      if (Parameters.ContainsKey("FillPopulationWithParents") && Parameters["FillPopulationWithParents"] is FixedValueParameter<BoolValue>)
75        Parameters.Remove("FillPopulationWithParents");
76      if (!Parameters.ContainsKey("FillPopulationWithParents"))
77        Parameters.Add(new ValueLookupParameter<BoolValue>("FillPopulationWithParents", "True if the population should be filled with parent individuals instead of lucky losers."));
78      #endregion
79    }
80
81    protected OffspringSelector(OffspringSelector original, Cloner cloner) : base(original, cloner) { }
82    public override IDeepCloneable Clone(Cloner cloner) {
83      return new OffspringSelector(this, cloner);
84    }
85    public OffspringSelector()
86      : base() {
87      Parameters.Add(new ValueLookupParameter<DoubleValue>("MaximumSelectionPressure", "The maximum selection pressure which prematurely terminates the offspring selection step."));
88      Parameters.Add(new ValueLookupParameter<DoubleValue>("SuccessRatio", "The ratio of successful offspring that has to be produced."));
89      Parameters.Add(new ValueLookupParameter<DoubleValue>("SelectionPressure", "The amount of selection pressure currently necessary to fulfill the success ratio."));
90      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentSuccessRatio", "The current success ratio indicates how much of the successful offspring have already been generated."));
91      Parameters.Add(new LookupParameter<ItemList<IScope>>("OffspringPopulation", "Temporary store of the offspring population."));
92      Parameters.Add(new LookupParameter<IntValue>("OffspringPopulationWinners", "Temporary store the number of successful offspring in the offspring population."));
93      Parameters.Add(new ScopeTreeLookupParameter<BoolValue>("SuccessfulOffspring", "True if the offspring was more successful than its parents.", 2));
94      Parameters.Add(new OperatorParameter("OffspringCreator", "The operator used to create new offspring."));
95      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."));
96    }
97
98    public override IOperation Apply() {
99      double maxSelPress = MaximumSelectionPressureParameter.ActualValue.Value;
100      double successRatio = SuccessRatioParameter.ActualValue.Value;
101      bool fillPopulationWithParents = FillPopulationWithParentsParameter.ActualValue.Value;
102      IScope scope = ExecutionContext.Scope;
103      IScope parents = scope.SubScopes[0];
104      IScope offspring = scope.SubScopes[1];
105      int populationSize = parents.SubScopes.Count;
106
107      // retrieve actual selection pressure and success ratio
108      DoubleValue selectionPressure = SelectionPressureParameter.ActualValue;
109      if (selectionPressure == null) {
110        selectionPressure = new DoubleValue(0);
111        SelectionPressureParameter.ActualValue = selectionPressure;
112      }
113      DoubleValue currentSuccessRatio = CurrentSuccessRatioParameter.ActualValue;
114      if (currentSuccessRatio == null) {
115        currentSuccessRatio = new DoubleValue(0);
116        CurrentSuccessRatioParameter.ActualValue = currentSuccessRatio;
117      }
118
119      // retrieve next population
120      ItemList<IScope> population = OffspringPopulationParameter.ActualValue;
121      IntValue successfulOffspring;
122      if (population == null) {
123        population = new ItemList<IScope>();
124        OffspringPopulationParameter.ActualValue = population;
125        selectionPressure.Value = 0; // initialize selection pressure for this round
126        currentSuccessRatio.Value = 0; // initialize current success ratio for this round
127        successfulOffspring = new IntValue(0);
128        OffspringPopulationWinnersParameter.ActualValue = successfulOffspring;
129      } else successfulOffspring = OffspringPopulationWinnersParameter.ActualValue;
130
131      int worseOffspringNeeded = (int)((1 - successRatio) * populationSize) - (population.Count - successfulOffspring.Value);
132      int successfulOffspringAdded = 0;
133
134      // 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
135      string tname = SuccessfulOffspringParameter.TranslatedName;
136      double tmpSelPress = selectionPressure.Value, tmpSelPressInc = 1.0 / populationSize;
137      for (int i = 0; i < offspring.SubScopes.Count; i++) {
138        // fetch value
139        IVariable tmpVar;
140        if (!offspring.SubScopes[i].Variables.TryGetValue(tname, out tmpVar)) throw new InvalidOperationException(Name + ": Could not determine if an offspring was successful or not.");
141        BoolValue tmp = (tmpVar.Value as BoolValue);
142        if (tmp == null) throw new InvalidOperationException(Name + ": The variable that indicates whether an offspring is successful or not must contain a BoolValue.");
143
144        // add to population
145        if (tmp.Value) {
146          IScope currentOffspring = offspring.SubScopes[i];
147          offspring.SubScopes.Remove(currentOffspring);
148          i--;
149          population.Add(currentOffspring);
150          successfulOffspringAdded++;
151        } else if (worseOffspringNeeded > 0 || tmpSelPress >= maxSelPress) {
152          IScope currentOffspring;
153          if (!fillPopulationWithParents || worseOffspringNeeded > 0) {
154            currentOffspring = offspring.SubScopes[i];
155            offspring.SubScopes.Remove(currentOffspring);
156            i--;
157            worseOffspringNeeded--;
158          } else {
159            currentOffspring = parents.SubScopes[i];
160          }
161          population.Add(currentOffspring);
162        }
163        tmpSelPress += tmpSelPressInc;
164        if (population.Count == populationSize) break;
165      }
166      successfulOffspring.Value += successfulOffspringAdded;
167
168      // calculate actual selection pressure and success ratio
169      selectionPressure.Value = tmpSelPress;
170      currentSuccessRatio.Value = successfulOffspring.Value / ((double)populationSize);
171
172      // check if enough children have been generated
173      if (((selectionPressure.Value < maxSelPress) && (currentSuccessRatio.Value < successRatio)) ||
174          (population.Count < populationSize)) {
175        // more children required -> reduce left and start children generation again
176        scope.SubScopes.Remove(parents);
177        scope.SubScopes.Remove(offspring);
178        while (parents.SubScopes.Count > 0) {
179          IScope parent = parents.SubScopes[0];
180          parents.SubScopes.RemoveAt(0);
181          scope.SubScopes.Add(parent);
182        }
183
184        IOperator moreOffspring = OffspringCreatorParameter.ActualValue as IOperator;
185        if (moreOffspring == null) throw new InvalidOperationException(Name + ": More offspring are required, but no operator specified for creating them.");
186        return ExecutionContext.CreateOperation(moreOffspring);
187      } else {
188        // enough children generated
189        offspring.SubScopes.Clear();
190        offspring.SubScopes.AddRange(population);
191
192        scope.Variables.Remove(OffspringPopulationParameter.TranslatedName);
193        scope.Variables.Remove(OffspringPopulationWinnersParameter.TranslatedName);
194        return base.Apply();
195      }
196    }
197  }
198}
Note: See TracBrowser for help on using the repository browser.