Free cookie consent management tool by TermsFeed Policy Generator

source: branches/VOSGA/HeuristicLab.Algorithms.VOffspringSelectionGeneticAlgorithm/OffspringSelectors/EliteOffspringSelector.cs @ 13599

Last change on this file since 13599 was 12363, checked in by ascheibe, 10 years ago

#2267 added another offspring selector

File size: 16.3 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 System.Linq;
24using HeuristicLab.Analysis;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Operators;
29using HeuristicLab.Optimization;
30using HeuristicLab.Optimization.Operators;
31using HeuristicLab.Parameters;
32using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
33using HeuristicLab.PluginInfrastructure;
34
35namespace HeuristicLab.Algorithms.VOffspringSelectionGeneticAlgorithm {
36  [Item("EliteOffspringSelector", "M2")]
37  [StorableClass]
38  public class EliteOffspringSelector : InstrumentedOperator, IOffspringSelector {
39
40    private const string SuccessRatioChart = "SuccessRatioChart";
41    private const string SuccessRatioDataRow = "SuccessRatio";
42
43
44    public ValueLookupParameter<DoubleValue> MaximumSelectionPressureParameter {
45      get { return (ValueLookupParameter<DoubleValue>)Parameters["MaximumSelectionPressure"]; }
46    }
47    public ValueLookupParameter<DoubleValue> SuccessRatioParameter {
48      get { return (ValueLookupParameter<DoubleValue>)Parameters["SuccessRatio"]; }
49    }
50    public LookupParameter<DoubleValue> SelectionPressureParameter {
51      get { return (ValueLookupParameter<DoubleValue>)Parameters["SelectionPressure"]; }
52    }
53    public LookupParameter<DoubleValue> CurrentSuccessRatioParameter {
54      get { return (LookupParameter<DoubleValue>)Parameters["CurrentSuccessRatio"]; }
55    }
56    public LookupParameter<ItemList<IScope>> OffspringPopulationParameter {
57      get { return (LookupParameter<ItemList<IScope>>)Parameters["OffspringPopulation"]; }
58    }
59    public LookupParameter<IntValue> OffspringPopulationWinnersParameter {
60      get { return (LookupParameter<IntValue>)Parameters["OffspringPopulationWinners"]; }
61    }
62    public ScopeTreeLookupParameter<BoolValue> SuccessfulOffspringParameter {
63      get { return (ScopeTreeLookupParameter<BoolValue>)Parameters["SuccessfulOffspring"]; }
64    }
65    public IValueLookupParameter<BoolValue> FillPopulationWithParentsParameter {
66      get { return (IValueLookupParameter<BoolValue>)Parameters["FillPopulationWithParents"]; }
67    }
68    public ILookupParameter<BoolValue> EnoughChildrenGeneratedParameter {
69      get { return (ILookupParameter<BoolValue>)Parameters["EnoughChildrenGenerated"]; }
70    }
71    public IValueLookupParameter<ISolutionSimilarityCalculator> SimilarityCalculatorParameter {
72      get { return (IValueLookupParameter<ISolutionSimilarityCalculator>)Parameters["SimilarityCalculator"]; }
73    }
74    public ValueLookupParameter<ResultCollection> ResultsParameter {
75      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
76    }
77
78    public ValueLookupParameter<DoubleValue> DiversityComparisonFactorParameter {
79      get { return (ValueLookupParameter<DoubleValue>)Parameters["DiversityComparisonFactor"]; }
80    }
81    private ValueLookupParameter<DoubleValue> ComparisonFactorLowerBoundParameter {
82      get { return (ValueLookupParameter<DoubleValue>)Parameters["DiversityComparisonFactorLowerBound"]; }
83    }
84    private ValueLookupParameter<DoubleValue> ComparisonFactorUpperBoundParameter {
85      get { return (ValueLookupParameter<DoubleValue>)Parameters["DiversityComparisonFactorUpperBound"]; }
86    }
87
88    public IConstrainedValueParameter<IDiscreteDoubleValueModifier> ComparisonFactorModifierParameter {
89      get { return (IConstrainedValueParameter<IDiscreteDoubleValueModifier>)Parameters["ComparisonFactorModifier"]; }
90    }
91
92    [StorableConstructor]
93    protected EliteOffspringSelector(bool deserializing) : base(deserializing) { }
94    protected EliteOffspringSelector(EliteOffspringSelector original, Cloner cloner)
95      : base(original, cloner) {
96    }
97    public override IDeepCloneable Clone(Cloner cloner) {
98      return new EliteOffspringSelector(this, cloner);
99    }
100    public EliteOffspringSelector()
101      : base() {
102      Parameters.Add(new ValueLookupParameter<DoubleValue>("MaximumSelectionPressure", "The maximum selection pressure which prematurely terminates the offspring selection step."));
103      Parameters.Add(new ValueLookupParameter<DoubleValue>("SuccessRatio", "The ratio of successful offspring that has to be produced."));
104      Parameters.Add(new ValueLookupParameter<DoubleValue>("SelectionPressure", "The amount of selection pressure currently necessary to fulfill the success ratio."));
105      Parameters.Add(new ValueLookupParameter<DoubleValue>("CurrentSuccessRatio", "The current success ratio indicates how much of the successful offspring have already been generated."));
106      Parameters.Add(new LookupParameter<ItemList<IScope>>("OffspringPopulation", "Temporary store of the offspring population."));
107      Parameters.Add(new LookupParameter<IntValue>("OffspringPopulationWinners", "Temporary store the number of successful offspring in the offspring population."));
108      Parameters.Add(new ScopeTreeLookupParameter<BoolValue>("SuccessfulOffspring", "True if the offspring was more successful than its parents.", 2));
109      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."));
110      Parameters.Add(new LookupParameter<BoolValue>("EnoughChildrenGenerated", "True if enough children have been generated, otherwise false."));
111      Parameters.Add(new ValueLookupParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The similarity calculator that should be used to calculate solution similarity."));
112      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The result collection where the population diversity analysis results should be stored."));
113
114      Parameters.Add(new ValueLookupParameter<DoubleValue>("DiversityComparisonFactor", "Determines if the quality should be compared to the better parent (1.0), to the worse (0.0) or to any linearly interpolated value between them.", new DoubleValue(0.0)));
115      Parameters.Add(new ValueLookupParameter<DoubleValue>("DiversityComparisonFactorLowerBound", "The lower bound of the comparison factor (start).", new DoubleValue(0.5)));
116      Parameters.Add(new ValueLookupParameter<DoubleValue>("DiversityComparisonFactorUpperBound", "The upper bound of the comparison factor (end).", new DoubleValue(1.0)));
117      Parameters.Add(new OptionalConstrainedValueParameter<IDiscreteDoubleValueModifier>("ComparisonFactorModifier", "The operator used to modify the comparison factor.", new ItemSet<IDiscreteDoubleValueModifier>(new IDiscreteDoubleValueModifier[] { new LinearDiscreteDoubleValueModifier() }), new LinearDiscreteDoubleValueModifier()));
118
119
120      foreach (IDiscreteDoubleValueModifier modifier in ApplicationManager.Manager.GetInstances<IDiscreteDoubleValueModifier>().OrderBy(x => x.Name))
121        ComparisonFactorModifierParameter.ValidValues.Add(modifier);
122      IDiscreteDoubleValueModifier linearModifier = ComparisonFactorModifierParameter.ValidValues.FirstOrDefault(x => x.GetType().Name.Equals("LinearDiscreteDoubleValueModifier"));
123      if (linearModifier != null) ComparisonFactorModifierParameter.Value = linearModifier;
124      ParameterizeComparisonFactorModifiers();
125
126      this.AfterExecutionOperators.Clear();
127      this.AfterExecutionOperators.Add(ComparisonFactorModifierParameter.Value);
128      ComparisonFactorModifierParameter.ValueChanged += ComparisonFactorModifierParameter_ValueChanged;
129    }
130
131    void ComparisonFactorModifierParameter_ValueChanged(object sender, EventArgs e) {
132      this.AfterExecutionOperators.Clear();
133      this.AfterExecutionOperators.Add(ComparisonFactorModifierParameter.Value);
134    }
135
136    private void ParameterizeComparisonFactorModifiers() {
137      //TODO: does not work if Generations parameter names are changed
138      foreach (IDiscreteDoubleValueModifier modifier in ComparisonFactorModifierParameter.ValidValues) {
139        modifier.IndexParameter.ActualName = "Generations";
140        modifier.EndIndexParameter.ActualName = "MaximumGenerations";
141        modifier.EndValueParameter.ActualName = ComparisonFactorUpperBoundParameter.Name;
142        modifier.StartIndexParameter.Value = new IntValue(0);
143        modifier.StartValueParameter.ActualName = ComparisonFactorLowerBoundParameter.Name;
144        modifier.ValueParameter.ActualName = "DiversityComparisonFactor";
145      }
146    }
147
148    public override IOperation InstrumentedApply() {
149      double maxSelPress = MaximumSelectionPressureParameter.ActualValue.Value;
150      double successRatio = SuccessRatioParameter.ActualValue.Value;
151      bool fillPopulationWithParents = false;
152      if (FillPopulationWithParentsParameter.ActualValue != null)
153        fillPopulationWithParents = FillPopulationWithParentsParameter.ActualValue.Value;
154      IScope scope = ExecutionContext.Scope;
155      IScope parents = scope.SubScopes[0];
156      IScope offspring = scope.SubScopes[1];
157      int populationSize = parents.SubScopes.Count;
158
159      // retrieve actual selection pressure and success ratio
160      DoubleValue selectionPressure = SelectionPressureParameter.ActualValue;
161      if (selectionPressure == null) {
162        selectionPressure = new DoubleValue(0);
163        SelectionPressureParameter.ActualValue = selectionPressure;
164      }
165      DoubleValue currentSuccessRatio = CurrentSuccessRatioParameter.ActualValue;
166      if (currentSuccessRatio == null) {
167        currentSuccessRatio = new DoubleValue(0);
168        CurrentSuccessRatioParameter.ActualValue = currentSuccessRatio;
169      }
170
171      DataTable successRatioDataTable;
172      if (ResultsParameter.ActualValue.ContainsKey(SuccessRatioChart)) {
173        successRatioDataTable = (DataTable)ResultsParameter.ActualValue[SuccessRatioChart].Value;
174      } else {
175        successRatioDataTable = new DataTable(SuccessRatioChart);
176        successRatioDataTable.Rows.Add(new DataRow(SuccessRatioDataRow));
177        ResultsParameter.ActualValue.Add(new Result(SuccessRatioChart, successRatioDataTable));
178      }
179
180      // retrieve next population
181      ItemList<IScope> population = OffspringPopulationParameter.ActualValue;
182      IntValue successfulOffspring;
183      if (population == null) {
184        population = new ItemList<IScope>();
185        OffspringPopulationParameter.ActualValue = population;
186        selectionPressure.Value = 0; // initialize selection pressure for this round
187        currentSuccessRatio.Value = 0; // initialize current success ratio for this round
188        successfulOffspring = new IntValue(0);
189        OffspringPopulationWinnersParameter.ActualValue = successfulOffspring;
190      } else successfulOffspring = OffspringPopulationWinnersParameter.ActualValue;
191
192      int worseOffspringNeeded = (int)((1 - successRatio) * populationSize) - (population.Count - successfulOffspring.Value);
193      int successfulOffspringAdded = 0;
194      double avgPopDiv = DiversityComparisonFactorParameter.Value.Value;
195
196      // 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
197      string tname = SuccessfulOffspringParameter.TranslatedName;
198      double tmpSelPress = selectionPressure.Value, tmpSelPressInc = 1.0 / populationSize;
199      for (int i = 0; i < offspring.SubScopes.Count; i++) {
200        // fetch value
201        IVariable tmpVar;
202        if (!offspring.SubScopes[i].Variables.TryGetValue(tname, out tmpVar)) throw new InvalidOperationException(Name + ": Could not determine if an offspring was successful or not.");
203        BoolValue tmp = (tmpVar.Value as BoolValue);
204        if (tmp == null) throw new InvalidOperationException(Name + ": The variable that indicates whether an offspring is successful or not must contain a BoolValue.");
205
206        if (!offspring.SubScopes[i].Variables.TryGetValue("ResultImprovement", out tmpVar)) throw new InvalidOperationException(Name + ": Could not find ResultImprovment.");
207        BoolValue betterThanWorseParent = (tmpVar.Value as BoolValue);
208        if (betterThanWorseParent == null) throw new InvalidOperationException(Name + ": Could not find ResultImprovment.");
209
210        //this is an "elite" solution candidate
211        double tmpCurSuccRatio = (successfulOffspring.Value + successfulOffspringAdded) / (double)populationSize;
212        if (tmp.Value && tmpCurSuccRatio <= successRatio) {
213          //this overrides the diversity mechanism; always fill up elites if there is space
214          IScope currentOffspring = offspring.SubScopes[i];
215          offspring.SubScopes.Remove(currentOffspring);
216          i--;
217          population.Add(currentOffspring);
218          successfulOffspringAdded++;
219        } else if (!tmp.Value && betterThanWorseParent.Value) {
220          //quality is ok, check for diversity
221          IScope currentOffspring = offspring.SubScopes[i];
222
223          if (!population.Any()) {
224            offspring.SubScopes.Remove(currentOffspring);
225            i--;
226            worseOffspringNeeded--;
227            population.Add(currentOffspring);
228          } else {
229            Scope tmpScope = new Scope();
230            tmpScope.SubScopes.AddRange(population);
231            Scope tmpCurrentScope = new Scope();
232            tmpCurrentScope.SubScopes.Add(currentOffspring);
233            double curDiv = SimilarityCalculatorParameter.ActualValue.CalculateSolutionCrowdSimilarity(tmpCurrentScope, tmpScope)[0].Average();
234            if (curDiv < avgPopDiv) {
235              if (worseOffspringNeeded > 0 || tmpSelPress >= maxSelPress) {
236                if (!fillPopulationWithParents || worseOffspringNeeded > 0) {
237                  offspring.SubScopes.Remove(currentOffspring);
238                  i--;
239                  worseOffspringNeeded--;
240                } else {
241                  currentOffspring = parents.SubScopes[i];
242                }
243                population.Add(currentOffspring);
244              }
245            }
246          }
247        }
248
249        tmpSelPress += tmpSelPressInc;
250        if (population.Count >= populationSize) break;
251      }
252      successfulOffspring.Value += successfulOffspringAdded;
253
254      // calculate actual selection pressure and success ratio
255      selectionPressure.Value = tmpSelPress;
256      currentSuccessRatio.Value = successfulOffspring.Value / ((double)populationSize);
257      successRatioDataTable.Rows[SuccessRatioDataRow].Values.Add(currentSuccessRatio.Value);
258
259      if (EnoughChildrenGeneratedParameter.ActualValue == null) {
260        EnoughChildrenGeneratedParameter.ActualValue = new BoolValue();
261      }
262      // check if enough children have been generated
263      if (((selectionPressure.Value < maxSelPress) &&
264        (currentSuccessRatio.Value < successRatio) &&
265        (population.Count < populationSize)) ||
266          (population.Count < populationSize)) {
267        // more children required -> reduce left and start children generation again
268        scope.SubScopes.Remove(parents);
269        scope.SubScopes.Remove(offspring);
270        while (parents.SubScopes.Count > 0) {
271          IScope parent = parents.SubScopes[0];
272          parents.SubScopes.RemoveAt(0);
273          scope.SubScopes.Add(parent);
274        }
275        EnoughChildrenGeneratedParameter.ActualValue.Value = false;
276      } else {
277        // enough children generated
278        offspring.SubScopes.Clear();
279        offspring.SubScopes.AddRange(population);
280
281        scope.Variables.Remove(OffspringPopulationParameter.TranslatedName);
282        scope.Variables.Remove(OffspringPopulationWinnersParameter.TranslatedName);
283        EnoughChildrenGeneratedParameter.ActualValue.Value = true;
284      }
285
286      return base.InstrumentedApply();
287    }
288  }
289}
Note: See TracBrowser for help on using the repository browser.