Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.Selection/3.3/OffspringSelector.cs @ 16178

Last change on this file since 16178 was 15583, checked in by swagner, 7 years ago

#2640: Updated year of copyrights in license headers

File size: 10.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 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 = false;
102      if (FillPopulationWithParentsParameter.ActualValue != null)
103        fillPopulationWithParents = FillPopulationWithParentsParameter.ActualValue.Value;
104      IScope scope = ExecutionContext.Scope;
105      IScope parents = scope.SubScopes[0];
106      IScope offspring = scope.SubScopes[1];
107      int populationSize = parents.SubScopes.Count;
108
109      // retrieve actual selection pressure and success ratio
110      DoubleValue selectionPressure = SelectionPressureParameter.ActualValue;
111      if (selectionPressure == null) {
112        selectionPressure = new DoubleValue(0);
113        SelectionPressureParameter.ActualValue = selectionPressure;
114      }
115      DoubleValue currentSuccessRatio = CurrentSuccessRatioParameter.ActualValue;
116      if (currentSuccessRatio == null) {
117        currentSuccessRatio = new DoubleValue(0);
118        CurrentSuccessRatioParameter.ActualValue = currentSuccessRatio;
119      }
120
121      // retrieve next population
122      ItemList<IScope> population = OffspringPopulationParameter.ActualValue;
123      IntValue successfulOffspring;
124      if (population == null) {
125        population = new ItemList<IScope>();
126        OffspringPopulationParameter.ActualValue = population;
127        selectionPressure.Value = 0; // initialize selection pressure for this round
128        currentSuccessRatio.Value = 0; // initialize current success ratio for this round
129        successfulOffspring = new IntValue(0);
130        OffspringPopulationWinnersParameter.ActualValue = successfulOffspring;
131      } else successfulOffspring = OffspringPopulationWinnersParameter.ActualValue;
132
133      int worseOffspringNeeded = (int)((1 - successRatio) * populationSize) - (population.Count - successfulOffspring.Value);
134      int successfulOffspringAdded = 0;
135
136      // 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
137      string tname = SuccessfulOffspringParameter.TranslatedName;
138      double tmpSelPress = selectionPressure.Value, tmpSelPressInc = 1.0 / populationSize;
139      for (int i = 0; i < offspring.SubScopes.Count; i++) {
140        // fetch value
141        IVariable tmpVar;
142        if (!offspring.SubScopes[i].Variables.TryGetValue(tname, out tmpVar)) throw new InvalidOperationException(Name + ": Could not determine if an offspring was successful or not.");
143        BoolValue tmp = (tmpVar.Value as BoolValue);
144        if (tmp == null) throw new InvalidOperationException(Name + ": The variable that indicates whether an offspring is successful or not must contain a BoolValue.");
145
146        // add to population
147        if (tmp.Value) {
148          IScope currentOffspring = offspring.SubScopes[i];
149          offspring.SubScopes.Remove(currentOffspring);
150          i--;
151          population.Add(currentOffspring);
152          successfulOffspringAdded++;
153        } else if (worseOffspringNeeded > 0 || tmpSelPress >= maxSelPress) {
154          IScope currentOffspring;
155          if (!fillPopulationWithParents || worseOffspringNeeded > 0) {
156            currentOffspring = offspring.SubScopes[i];
157            offspring.SubScopes.Remove(currentOffspring);
158            i--;
159            worseOffspringNeeded--;
160          } else {
161            currentOffspring = parents.SubScopes[i];
162          }
163          population.Add(currentOffspring);
164        }
165        tmpSelPress += tmpSelPressInc;
166        if (population.Count == populationSize) break;
167      }
168      successfulOffspring.Value += successfulOffspringAdded;
169
170      // calculate actual selection pressure and success ratio
171      selectionPressure.Value = tmpSelPress;
172      currentSuccessRatio.Value = successfulOffspring.Value / ((double)populationSize);
173
174      // check if enough children have been generated
175      if (((selectionPressure.Value < maxSelPress) && (currentSuccessRatio.Value < successRatio)) ||
176          (population.Count < populationSize)) {
177        // more children required -> reduce left and start children generation again
178        scope.SubScopes.Remove(parents);
179        scope.SubScopes.Remove(offspring);
180        while (parents.SubScopes.Count > 0) {
181          IScope parent = parents.SubScopes[0];
182          parents.SubScopes.RemoveAt(0);
183          scope.SubScopes.Add(parent);
184        }
185
186        IOperator moreOffspring = OffspringCreatorParameter.ActualValue as IOperator;
187        if (moreOffspring == null) throw new InvalidOperationException(Name + ": More offspring are required, but no operator specified for creating them.");
188        return ExecutionContext.CreateOperation(moreOffspring);
189      } else {
190        // enough children generated
191        offspring.SubScopes.Clear();
192        offspring.SubScopes.AddRange(population);
193
194        scope.Variables.Remove(OffspringPopulationParameter.TranslatedName);
195        scope.Variables.Remove(OffspringPopulationWinnersParameter.TranslatedName);
196        return base.Apply();
197      }
198    }
199  }
200}
Note: See TracBrowser for help on using the repository browser.