source: trunk/sources/HeuristicLab.Selection/3.3/OffspringSelector.cs @ 7259

Last change on this file since 7259 was 7259, checked in by swagner, 11 years ago

Updated year of copyrights to 2012 (#1716)

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