1 | #region License Information
|
---|
2 | /* HeuristicLab
|
---|
3 | * Copyright (C) 2002-2010 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 |
|
---|
22 | using System;
|
---|
23 | using System.Collections.Generic;
|
---|
24 | using System.Linq;
|
---|
25 | using HeuristicLab.Core;
|
---|
26 | using HeuristicLab.Data;
|
---|
27 | using HeuristicLab.Operators;
|
---|
28 | using HeuristicLab.Parameters;
|
---|
29 | using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
|
---|
30 |
|
---|
31 | namespace HeuristicLab.Optimization.Operators {
|
---|
32 | [Item("OffspringSelector", "Selects among the offspring population those that are designated successful and discards the unsuccessful offspring, except for some lucky losers.")]
|
---|
33 | [StorableClass]
|
---|
34 | public class OffspringSelector : SingleSuccessorOperator {
|
---|
35 |
|
---|
36 | public ValueLookupParameter<IntValue> PopulationSizeParameter {
|
---|
37 | get { return (ValueLookupParameter<IntValue>)Parameters["PopulationSize"]; }
|
---|
38 | }
|
---|
39 | public ValueLookupParameter<DoubleValue> MaximumSelectionPressureParameter {
|
---|
40 | get { return (ValueLookupParameter<DoubleValue>)Parameters["MaximiumSelectionPressure"]; }
|
---|
41 | }
|
---|
42 | public ValueLookupParameter<DoubleValue> SuccessRatioParameter {
|
---|
43 | get { return (ValueLookupParameter<DoubleValue>)Parameters["SuccessRatio"]; }
|
---|
44 | }
|
---|
45 | public LookupParameter<DoubleValue> SelectionPressureParameter {
|
---|
46 | get { return (ValueLookupParameter<DoubleValue>)Parameters["SelectionPressure"]; }
|
---|
47 | }
|
---|
48 | public LookupParameter<DoubleValue> CurrentSuccessRatioParameter {
|
---|
49 | get { return (LookupParameter<DoubleValue>)Parameters["CurrentSuccessRatio"]; }
|
---|
50 | }
|
---|
51 | public SubScopesLookupParameter<BoolValue> SuccessfulOffspringParameter {
|
---|
52 | get { return (SubScopesLookupParameter<BoolValue>)Parameters["SuccessfulOffspring"]; }
|
---|
53 | }
|
---|
54 | public LookupParameter<ItemList<IScope>> WinnersParameter {
|
---|
55 | get { return (LookupParameter<ItemList<IScope>>)Parameters["Winners"]; }
|
---|
56 | }
|
---|
57 | public LookupParameter<ItemList<IScope>> LuckyLosersParameter {
|
---|
58 | get { return (LookupParameter<ItemList<IScope>>)Parameters["LuckyLosers"]; }
|
---|
59 | }
|
---|
60 | public OperatorParameter OffspringCreatorParameter {
|
---|
61 | get { return (OperatorParameter)Parameters["OffspringCreator"]; }
|
---|
62 | }
|
---|
63 |
|
---|
64 | public IOperator OffspringCreator {
|
---|
65 | get { return OffspringCreatorParameter.Value; }
|
---|
66 | set { OffspringCreatorParameter.Value = value; }
|
---|
67 | }
|
---|
68 |
|
---|
69 | public OffspringSelector()
|
---|
70 | : base() {
|
---|
71 | Parameters.Add(new ValueLookupParameter<IntValue>("PopulationSize", "The number of offspring to create."));
|
---|
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 SubScopesLookupParameter<BoolValue>("SuccessfulOffspring", "True if the offspring was successful, otherwise false."));
|
---|
77 | Parameters.Add(new LookupParameter<ItemList<IScope>>("Winners", "Temporary store of the successful offspring."));
|
---|
78 | Parameters.Add(new LookupParameter<ItemList<IScope>>("LuckyLosers", "Temporary store of the lucky losers."));
|
---|
79 | Parameters.Add(new OperatorParameter("OffspringCreator", "The operator used to create new offspring."));
|
---|
80 | }
|
---|
81 |
|
---|
82 | public override IOperation Apply() {
|
---|
83 | int populationSize = PopulationSizeParameter.ActualValue.Value;
|
---|
84 | double maxSelPress = MaximumSelectionPressureParameter.ActualValue.Value;
|
---|
85 | double successRatio = SuccessRatioParameter.ActualValue.Value;
|
---|
86 | IScope scope = ExecutionContext.Scope;
|
---|
87 | IScope parents = scope.SubScopes[0];
|
---|
88 | IScope children = scope.SubScopes[1];
|
---|
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 winners and lucky losers
|
---|
103 | ItemList<IScope> winners = WinnersParameter.ActualValue;
|
---|
104 | if (winners == null) {
|
---|
105 | winners = new ItemList<IScope>();
|
---|
106 | WinnersParameter.ActualValue = winners;
|
---|
107 | selectionPressure.Value = 0; // initialize selection pressure for this round
|
---|
108 | currentSuccessRatio.Value = 0; // initialize current success ratio for this round
|
---|
109 | }
|
---|
110 | ItemList<IScope> luckyLosers = LuckyLosersParameter.ActualValue;
|
---|
111 | if (luckyLosers == null) {
|
---|
112 | luckyLosers = new ItemList<IScope>();
|
---|
113 | LuckyLosersParameter.ActualValue = luckyLosers;
|
---|
114 | }
|
---|
115 |
|
---|
116 | // separate new offspring in winners and lucky losers, the unlucky losers are discarded, sorry guys
|
---|
117 | int winnersCount = 0;
|
---|
118 | int losersCount = 0;
|
---|
119 | ItemArray<BoolValue> offspring = SuccessfulOffspringParameter.ActualValue;
|
---|
120 | for (int i = 0; i < offspring.Length; i++) {
|
---|
121 | IScope child = children.SubScopes[0];
|
---|
122 | if (offspring[i].Value) {
|
---|
123 | winnersCount++;
|
---|
124 | winners.Add(child);
|
---|
125 | } else {
|
---|
126 | losersCount++;
|
---|
127 | // only keep the offspring if we have not filled up the pool or if we reached the
|
---|
128 | // selection pressure limit in which case we have to keep more lucky losers than usual
|
---|
129 | if ((1 - successRatio) * populationSize > luckyLosers.Count ||
|
---|
130 | selectionPressure.Value >= maxSelPress) {
|
---|
131 | luckyLosers.Add(child);
|
---|
132 | }
|
---|
133 | }
|
---|
134 | children.SubScopes.RemoveAt(0);
|
---|
135 | }
|
---|
136 |
|
---|
137 | // calculate actual selection pressure and success ratio
|
---|
138 | selectionPressure.Value += (winnersCount + losersCount) / ((double)populationSize);
|
---|
139 | currentSuccessRatio.Value = winners.Count / ((double)populationSize);
|
---|
140 |
|
---|
141 | // check if enough children have been generated
|
---|
142 | if (((selectionPressure.Value < maxSelPress) && (currentSuccessRatio.Value < successRatio)) ||
|
---|
143 | ((winners.Count + luckyLosers.Count) < populationSize)) {
|
---|
144 | // more children required -> reduce left and start children generation again
|
---|
145 | scope.SubScopes.Remove(parents);
|
---|
146 | scope.SubScopes.Remove(children);
|
---|
147 | for (int i = 0; i < parents.SubScopes.Count; i++)
|
---|
148 | scope.SubScopes.Add(parents.SubScopes[i]);
|
---|
149 |
|
---|
150 | IOperator moreOffspring = OffspringCreatorParameter.ActualValue as IOperator;
|
---|
151 | if (moreOffspring == null) throw new InvalidOperationException(Name + ": More offspring are required, but no operator specified for creating them.");
|
---|
152 | return ExecutionContext.CreateOperation(moreOffspring);
|
---|
153 | } else {
|
---|
154 | // enough children generated
|
---|
155 | while (children.SubScopes.Count < populationSize) {
|
---|
156 | if (winners.Count > 0) {
|
---|
157 | children.SubScopes.Add((IScope)winners[0]);
|
---|
158 | winners.RemoveAt(0);
|
---|
159 | } else {
|
---|
160 | children.SubScopes.Add((IScope)luckyLosers[0]);
|
---|
161 | luckyLosers.RemoveAt(0);
|
---|
162 | }
|
---|
163 | }
|
---|
164 |
|
---|
165 | scope.Variables.Remove(WinnersParameter.ActualName);
|
---|
166 | scope.Variables.Remove(LuckyLosersParameter.ActualName);
|
---|
167 | return base.Apply();
|
---|
168 | }
|
---|
169 | }
|
---|
170 | }
|
---|
171 | }
|
---|