Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Algorithms.ALPS/3.3/AlpsOffspringSelector.cs @ 15973

Last change on this file since 15973 was 15973, checked in by gkronber, 6 years ago

#2522: merged trunk changes from r13402:15972 to branch resolving conflicts where necessary

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