Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Selection.OffspringSelection/OffspringSelector.cs @ 1250

Last change on this file since 1250 was 1157, checked in by vdorfer, 16 years ago

Created API documentation for HeuristicLab.IntVector namespace and changed some comments in HeuristicLab.Random and HeuristicLab.Selection.Offspring namespace(#331)

File size: 8.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 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.Collections.Generic;
24using System.Text;
25using HeuristicLab.Core;
26using HeuristicLab.Data;
27
28namespace HeuristicLab.Selection.OffspringSelection {
29  /// <summary>
30  /// Selects successful and also according to the selection pressure some unsuccessful children.
31  /// </summary>
32  public class OffspringSelector : OperatorBase {
33    /// <inheritdoc select="summary"/>
34    public override string Description {
35      get { return @"TODO\r\nOperator description still missing ..."; }
36    }
37
38    /// <summary>
39    /// Initializes a new instance of <see cref="OffspringSelector"/> with seven variable infos
40    /// (<c>SuccessfulChild</c>, <c>SelectionPressureLimit</c>, <c>SuccessRatioLimit</c>,
41    /// <c>SelectionPressure</c>, <c>SuccessRatio</c>, <c>GoodChildren</c> and <c>BadChildren</c>).
42    /// </summary>
43    public OffspringSelector() {
44      AddVariableInfo(new VariableInfo("SuccessfulChild", "True if the child was successful", typeof(BoolData), VariableKind.In));
45      AddVariableInfo(new VariableInfo("SelectionPressureLimit", "Maximum selection pressure", typeof(DoubleData), VariableKind.In));
46      AddVariableInfo(new VariableInfo("SuccessRatioLimit", "Maximum success ratio", typeof(DoubleData), VariableKind.In));
47      AddVariableInfo(new VariableInfo("SelectionPressure", "Current selection pressure", typeof(DoubleData), VariableKind.New | VariableKind.Out));
48      AddVariableInfo(new VariableInfo("SuccessRatio", "Current success ratio", typeof(DoubleData), VariableKind.New | VariableKind.Out));
49      AddVariableInfo(new VariableInfo("GoodChildren", "Temporarily store successful children", typeof(ItemList<IScope>), VariableKind.New | VariableKind.Out | VariableKind.In | VariableKind.Deleted));
50      AddVariableInfo(new VariableInfo("BadChildren", "Temporarily store unsuccessful children", typeof(ItemList<IScope>), VariableKind.New | VariableKind.Out | VariableKind.In | VariableKind.Deleted));
51    }
52
53    /// <summary>
54    /// Selects successful children and also some bad ones depending on the selection
55    /// pressure out of a population.
56    /// </summary>
57    /// <param name="scope">The current scope of the parents and the children.</param>
58    /// <returns>The next operation or <c>null</c>.</returns>
59    public override IOperation Apply(IScope scope) {
60      double selectionPressureLimit = GetVariableValue<DoubleData>("SelectionPressureLimit", scope, true).Data;
61      double successRatioLimit = GetVariableValue<DoubleData>("SuccessRatioLimit", scope, true).Data;
62
63      IScope parents = scope.SubScopes[0];
64      IScope children = scope.SubScopes[1];
65
66      // retrieve actual selection pressure and success ratio
67      DoubleData selectionPressure = GetVariableValue<DoubleData>("SelectionPressure", scope, false, false);
68      if (selectionPressure == null) {
69        IVariableInfo selectionPressureInfo = GetVariableInfo("SelectionPressure");
70        selectionPressure = new DoubleData(0);
71        if (selectionPressureInfo.Local)
72          AddVariable(new Variable(selectionPressureInfo.ActualName, selectionPressure));
73        else
74          scope.AddVariable(new Variable(scope.TranslateName(selectionPressureInfo.FormalName), selectionPressure));
75      }
76      DoubleData successRatio = GetVariableValue<DoubleData>("SuccessRatio", scope, false, false);
77      if (successRatio == null) {
78        IVariableInfo successRatioInfo = GetVariableInfo("SuccessRatio");
79        successRatio = new DoubleData(0);
80        if (successRatioInfo.Local)
81          AddVariable(new Variable(successRatioInfo.ActualName, successRatio));
82        else
83          scope.AddVariable(new Variable(scope.TranslateName(successRatioInfo.FormalName), successRatio));
84      }
85
86      // retrieve good and bad children
87      ItemList<IScope> goodChildren = GetVariableValue<ItemList<IScope>>("GoodChildren", scope, false, false);
88      if (goodChildren == null) {
89        goodChildren = new ItemList<IScope>();
90        IVariableInfo goodChildrenInfo = GetVariableInfo("GoodChildren");
91        if (goodChildrenInfo.Local)
92          AddVariable(new Variable(goodChildrenInfo.ActualName, goodChildren));
93        else
94          scope.AddVariable(new Variable(scope.TranslateName(goodChildrenInfo.FormalName), goodChildren));
95
96        // no good children available -> first iteration of this generation -> initialize selection pressure
97        selectionPressure.Data = 0;
98      }
99      ItemList<IScope> badChildren = GetVariableValue<ItemList<IScope>>("BadChildren", scope, false, false);
100      if (badChildren == null) {
101        badChildren = new ItemList<IScope>();
102        IVariableInfo badChildrenInfo = GetVariableInfo("BadChildren");
103        if (badChildrenInfo.Local)
104          AddVariable(new Variable(badChildrenInfo.ActualName, badChildren));
105        else
106          scope.AddVariable(new Variable(scope.TranslateName(badChildrenInfo.FormalName), badChildren));
107      }
108
109      // separate new children in good and bad children
110      int goodCount = 0;
111      int badCount = 0;
112      IVariableInfo successfulInfo = GetVariableInfo("SuccessfulChild");
113      while (children.SubScopes.Count > 0) {
114        IScope child = children.SubScopes[0];
115        bool successful = child.GetVariableValue<BoolData>(successfulInfo.FormalName, false).Data;
116        if (successful) {
117          goodCount++;
118          goodChildren.Add(child);
119        } else {
120          badCount++;
121          // only keep the child if we have not filled up the pool or if we reached the
122          // selection pressure limit in which case we have to keep more lucky losers than usual
123          if ((1 - successRatioLimit) * parents.SubScopes.Count > badChildren.Count ||
124            selectionPressure.Data >= selectionPressureLimit) {
125            badChildren.Add(child);
126          }
127        }
128        children.RemoveSubScope(child);
129      }
130
131      // calculate actual selection pressure and success ratio
132      selectionPressure.Data += (goodCount + badCount) / ((double)parents.SubScopes.Count);
133      successRatio.Data = goodChildren.Count / ((double)parents.SubScopes.Count);
134
135      // check if enough children have been generated
136      if (((selectionPressure.Data < selectionPressureLimit) && (successRatio.Data < successRatioLimit)) ||
137          ((goodChildren.Count + badChildren.Count) < parents.SubScopes.Count)) {
138        // more children required -> reduce left and start children generation again
139        scope.RemoveSubScope(parents);
140        scope.RemoveSubScope(children);
141        for (int i = 0; i < parents.SubScopes.Count; i++)
142          scope.AddSubScope(parents.SubScopes[i]);
143
144        return new AtomicOperation(SubOperators[0], scope);
145      } else {
146        // enough children generated
147        while (children.SubScopes.Count < parents.SubScopes.Count) {
148          if (goodChildren.Count > 0) {
149            children.AddSubScope((IScope)goodChildren[0]);
150            goodChildren.RemoveAt(0);
151          } else {
152            children.AddSubScope((IScope)badChildren[0]);
153            badChildren.RemoveAt(0);
154          }
155        }
156
157        // remove good and bad children again
158        IVariableInfo goodChildrenInfo = GetVariableInfo("GoodChildren");
159        if (goodChildrenInfo.Local)
160          RemoveVariable(goodChildrenInfo.ActualName);
161        else
162          scope.RemoveVariable(scope.TranslateName(goodChildrenInfo.FormalName));
163        IVariableInfo badChildrenInfo = GetVariableInfo("BadChildren");
164        if (badChildrenInfo.Local)
165          RemoveVariable(badChildrenInfo.ActualName);
166        else
167          scope.RemoveVariable(scope.TranslateName(badChildrenInfo.FormalName));
168        return null;
169      }
170    }
171  }
172}
Note: See TracBrowser for help on using the repository browser.