Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.Encodings.RealVectorEncoding/3.3/RealVectorEncoding.cs

Last change on this file was 17181, checked in by swagner, 5 years ago

#2875: Merged r17180 from trunk to stable

File size: 14.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 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.Linq;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Optimization;
29using HeuristicLab.Parameters;
30using HEAL.Attic;
31using HeuristicLab.PluginInfrastructure;
32
33namespace HeuristicLab.Encodings.RealVectorEncoding {
34  [Item("RealVectorEncoding", "Describes a real vector encoding.")]
35  [StorableType("155FFE02-931F-457D-AC95-A0389B0BFECD")]
36  public sealed class RealVectorEncoding : Encoding<IRealVectorCreator> {
37    #region Encoding Parameters
38    [Storable]
39    private IFixedValueParameter<IntValue> lengthParameter;
40    public IFixedValueParameter<IntValue> LengthParameter {
41      get { return lengthParameter; }
42      set {
43        if (value == null) throw new ArgumentNullException("Length parameter must not be null.");
44        if (value.Value == null) throw new ArgumentNullException("Length parameter value must not be null.");
45        if (lengthParameter == value) return;
46
47        if (lengthParameter != null) Parameters.Remove(lengthParameter);
48        lengthParameter = value;
49        Parameters.Add(lengthParameter);
50        OnLengthParameterChanged();
51      }
52    }
53    [Storable]
54    private IValueParameter<DoubleMatrix> boundsParameter;
55    public IValueParameter<DoubleMatrix> BoundsParameter {
56      get { return boundsParameter; }
57      set {
58        if (value == null) throw new ArgumentNullException("Bounds parameter must not be null.");
59        if (boundsParameter == value) return;
60
61        if (boundsParameter != null) Parameters.Remove(boundsParameter);
62        boundsParameter = value;
63        Parameters.Add(boundsParameter);
64        OnBoundsParameterChanged();
65      }
66    }
67    #endregion
68
69    public int Length {
70      get { return LengthParameter.Value.Value; }
71      set { LengthParameter.Value.Value = value; }
72    }
73    public DoubleMatrix Bounds {
74      get { return BoundsParameter.Value; }
75      set { BoundsParameter.Value = value; }
76    }
77
78    [StorableConstructor]
79    private RealVectorEncoding(StorableConstructorFlag _) : base(_) { }
80    [StorableHook(HookType.AfterDeserialization)]
81    private void AfterDeserialization() {
82      RegisterParameterEvents();
83      DiscoverOperators();
84    }
85
86    public override IDeepCloneable Clone(Cloner cloner) { return new RealVectorEncoding(this, cloner); }
87    private RealVectorEncoding(RealVectorEncoding original, Cloner cloner)
88      : base(original, cloner) {
89      lengthParameter = cloner.Clone(original.lengthParameter);
90      boundsParameter = cloner.Clone(original.boundsParameter);
91      RegisterParameterEvents();
92    }
93
94    public RealVectorEncoding() : this("RealVector", 10) { }
95    public RealVectorEncoding(string name) : this(name, 10) { }
96    public RealVectorEncoding(int length) : this("RealVector", length) { }
97    public RealVectorEncoding(string name, int length, double min = double.MinValue, double max = double.MaxValue)
98      : base(name) {
99      if (min >= max) throw new ArgumentException("min must be less than max", "min");
100
101      var bounds = new DoubleMatrix(1, 2);
102      bounds[0, 0] = min;
103      bounds[0, 1] = max;
104
105      lengthParameter = new FixedValueParameter<IntValue>(Name + ".Length", new IntValue(length));
106      boundsParameter = new ValueParameter<DoubleMatrix>(Name + ".Bounds", bounds);
107      Parameters.Add(lengthParameter);
108      Parameters.Add(boundsParameter);
109
110      SolutionCreator = new UniformRandomRealVectorCreator();
111      RegisterParameterEvents();
112      DiscoverOperators();
113    }
114
115    public RealVectorEncoding(string name, int length, IList<double> min, IList<double> max)
116      : base(name) {
117      if (min.Count == 0) throw new ArgumentException("Bounds must be given for the real parameters.");
118      if (min.Count != max.Count) throw new ArgumentException("min must be of the same length as max", "min");
119      if (min.Zip(max, (mi, ma) => mi >= ma).Any(x => x)) throw new ArgumentException("min must be less than max in each dimension", "min");
120
121      var bounds = new DoubleMatrix(min.Count, 2);
122      for (int i = 0; i < min.Count; i++) {
123        bounds[i, 0] = min[i];
124        bounds[i, 1] = max[i];
125      }
126      lengthParameter = new FixedValueParameter<IntValue>(Name + ".Length", new IntValue(length));
127      boundsParameter = new ValueParameter<DoubleMatrix>(Name + ".Bounds", bounds);
128      Parameters.Add(lengthParameter);
129      Parameters.Add(boundsParameter);
130
131      SolutionCreator = new UniformRandomRealVectorCreator();
132      RegisterParameterEvents();
133      DiscoverOperators();
134    }
135
136    private void OnLengthParameterChanged() {
137      RegisterLengthParameterEvents();
138      ConfigureOperators(Operators);
139    }
140    private void OnBoundsParameterChanged() {
141      RegisterBoundsParameterEvents();
142      ConfigureOperators(Operators);
143    }
144
145    private void RegisterParameterEvents() {
146      RegisterLengthParameterEvents();
147      RegisterBoundsParameterEvents();
148    }
149    private void RegisterLengthParameterEvents() {
150      LengthParameter.ValueChanged += (o, s) => ConfigureOperators(Operators);
151      LengthParameter.Value.ValueChanged += (o, s) => ConfigureOperators(Operators);
152    }
153    private void RegisterBoundsParameterEvents() {
154      BoundsParameter.ValueChanged += (o, s) => ConfigureOperators(Operators);
155      boundsParameter.Value.ToStringChanged += (o, s) => ConfigureOperators(Operators);
156    }
157
158    #region Operator Discovery
159    private static readonly IEnumerable<Type> encodingSpecificOperatorTypes;
160    static RealVectorEncoding() {
161      encodingSpecificOperatorTypes = new List<Type>() {
162          typeof (IRealVectorOperator),
163          typeof (IRealVectorCreator),
164          typeof (IRealVectorCrossover),
165          typeof (IRealVectorManipulator),
166          typeof (IRealVectorStdDevStrategyParameterOperator),
167          typeof (IRealVectorSwarmUpdater),
168          typeof (IRealVectorParticleCreator),
169          typeof (IRealVectorParticleUpdater),
170          typeof (IRealVectorMultiNeighborhoodShakingOperator),
171          typeof (IRealVectorBoundsChecker),
172          typeof (IRealVectorMoveOperator),
173          typeof (IRealVectorMoveGenerator)
174      };
175    }
176    private void DiscoverOperators() {
177      var assembly = typeof(IRealVectorOperator).Assembly;
178      var discoveredTypes = ApplicationManager.Manager.GetTypes(encodingSpecificOperatorTypes, assembly, true, false, false);
179      var operators = discoveredTypes.Select(t => (IOperator)Activator.CreateInstance(t));
180      var newOperators = operators.Except(Operators, new TypeEqualityComparer<IOperator>()).ToList();
181
182      ConfigureOperators(newOperators);
183      foreach (var @operator in newOperators)
184        AddOperator(@operator);
185
186      foreach (var strategyVectorCreator in Operators.OfType<IRealVectorStdDevStrategyParameterCreator>())
187        strategyVectorCreator.BoundsParameter.ValueChanged += strategyVectorCreator_BoundsParameter_ValueChanged;
188    }
189    #endregion
190
191
192    private void strategyVectorCreator_BoundsParameter_ValueChanged(object sender, EventArgs e) {
193      var boundsParameter = (IValueLookupParameter<DoubleMatrix>)sender;
194      if (boundsParameter.Value == null) return;
195      foreach (var strategyVectorManipulator in Operators.OfType<IRealVectorStdDevStrategyParameterManipulator>())
196        strategyVectorManipulator.BoundsParameter.Value = (DoubleMatrix)boundsParameter.Value.Clone();
197    }
198
199    public override void ConfigureOperators(IEnumerable<IOperator> operators) {
200      ConfigureCreators(operators.OfType<IRealVectorCreator>());
201      ConfigureCrossovers(operators.OfType<IRealVectorCrossover>());
202      ConfigureManipulators(operators.OfType<IRealVectorManipulator>());
203      ConfigureStdDevStrategyParameterOperators(operators.OfType<IRealVectorStdDevStrategyParameterOperator>());
204      ConfigureSwarmUpdaters(operators.OfType<IRealVectorSwarmUpdater>());
205      ConfigureParticleCreators(operators.OfType<IRealVectorParticleCreator>());
206      ConfigureParticleUpdaters(operators.OfType<IRealVectorParticleUpdater>());
207      ConfigureShakingOperators(operators.OfType<IRealVectorMultiNeighborhoodShakingOperator>());
208      ConfigureBoundsCheckers(operators.OfType<IRealVectorBoundsChecker>());
209      ConfigureMoveGenerators(operators.OfType<IRealVectorMoveGenerator>());
210      ConfigureMoveOperators(operators.OfType<IRealVectorMoveOperator>());
211      ConfigureAdditiveMoveOperator(operators.OfType<IAdditiveRealVectorMoveOperator>());
212    }
213
214    #region Specific Operator Wiring
215    private void ConfigureCreators(IEnumerable<IRealVectorCreator> creators) {
216      foreach (var creator in creators) {
217        creator.RealVectorParameter.ActualName = Name;
218        creator.LengthParameter.ActualName = LengthParameter.Name;
219        creator.BoundsParameter.ActualName = BoundsParameter.Name;
220      }
221    }
222    private void ConfigureCrossovers(IEnumerable<IRealVectorCrossover> crossovers) {
223      foreach (var crossover in crossovers) {
224        crossover.ChildParameter.ActualName = Name;
225        crossover.ParentsParameter.ActualName = Name;
226        crossover.BoundsParameter.ActualName = BoundsParameter.Name;
227      }
228    }
229    private void ConfigureManipulators(IEnumerable<IRealVectorManipulator> manipulators) {
230      foreach (var manipulator in manipulators) {
231        manipulator.RealVectorParameter.ActualName = Name;
232        manipulator.BoundsParameter.ActualName = BoundsParameter.Name;
233        manipulator.BoundsParameter.Hidden = true;
234        var sm = manipulator as ISelfAdaptiveManipulator;
235        if (sm != null) {
236          var p = sm.StrategyParameterParameter as ILookupParameter;
237          if (p != null) {
238            p.ActualName = Name + ".Strategy";
239          }
240        }
241      }
242    }
243    private void ConfigureStdDevStrategyParameterOperators(IEnumerable<IRealVectorStdDevStrategyParameterOperator> strategyOperators) {
244      var bounds = new DoubleMatrix(Bounds.Rows, Bounds.Columns);
245      for (var i = 0; i < Bounds.Rows; i++) {
246        bounds[i, 0] = 0;
247        bounds[i, 1] = 0.1 * (Bounds[i, 1] - Bounds[i, 0]);
248      }
249      foreach (var s in strategyOperators) {
250        var c = s as IRealVectorStdDevStrategyParameterCreator;
251        if (c != null) {
252          c.BoundsParameter.Value = (DoubleMatrix)bounds.Clone();
253          c.LengthParameter.ActualName = LengthParameter.Name;
254          c.StrategyParameterParameter.ActualName = Name + ".Strategy";
255        }
256        var m = s as IRealVectorStdDevStrategyParameterManipulator;
257        if (m != null) {
258          m.BoundsParameter.Value = (DoubleMatrix)bounds.Clone();
259          m.StrategyParameterParameter.ActualName = Name + ".Strategy";
260        }
261        var mm = s as StdDevStrategyVectorManipulator;
262        if (mm != null) {
263          mm.GeneralLearningRateParameter.Value = new DoubleValue(1.0 / Math.Sqrt(2 * Length));
264          mm.LearningRateParameter.Value = new DoubleValue(1.0 / Math.Sqrt(2 * Math.Sqrt(Length)));
265        }
266        var x = s as IRealVectorStdDevStrategyParameterCrossover;
267        if (x != null) {
268          x.ParentsParameter.ActualName = Name + ".Strategy";
269          x.StrategyParameterParameter.ActualName = Name + ".Strategy";
270        }
271      }
272    }
273    private void ConfigureSwarmUpdaters(IEnumerable<IRealVectorSwarmUpdater> swarmUpdaters) {
274      foreach (var su in swarmUpdaters) {
275        su.RealVectorParameter.ActualName = Name;
276      }
277    }
278    private void ConfigureParticleCreators(IEnumerable<IRealVectorParticleCreator> particleCreators) {
279      foreach (var particleCreator in particleCreators) {
280        particleCreator.RealVectorParameter.ActualName = Name;
281        particleCreator.BoundsParameter.ActualName = BoundsParameter.Name;
282      }
283    }
284    private void ConfigureParticleUpdaters(IEnumerable<IRealVectorParticleUpdater> particleUpdaters) {
285      foreach (var particleUpdater in particleUpdaters) {
286        particleUpdater.RealVectorParameter.ActualName = Name;
287        particleUpdater.BoundsParameter.ActualName = BoundsParameter.Name;
288      }
289    }
290    private void ConfigureShakingOperators(IEnumerable<IRealVectorMultiNeighborhoodShakingOperator> shakingOperators) {
291      foreach (var shakingOperator in shakingOperators) {
292        shakingOperator.RealVectorParameter.ActualName = Name;
293        shakingOperator.BoundsParameter.ActualName = BoundsParameter.Name;
294      }
295    }
296    private void ConfigureBoundsCheckers(IEnumerable<IRealVectorBoundsChecker> boundsCheckers) {
297      foreach (var boundsChecker in boundsCheckers) {
298        boundsChecker.RealVectorParameter.ActualName = Name;
299        boundsChecker.BoundsParameter.ActualName = BoundsParameter.Name;
300      }
301    }
302    private void ConfigureMoveOperators(IEnumerable<IRealVectorMoveOperator> moveOperators) {
303      foreach (var moveOperator in moveOperators)
304        moveOperator.RealVectorParameter.ActualName = Name;
305    }
306
307    private void ConfigureMoveGenerators(IEnumerable<IRealVectorMoveGenerator> moveGenerators) {
308      foreach (var moveGenerator in moveGenerators)
309        moveGenerator.BoundsParameter.ActualName = BoundsParameter.Name;
310    }
311
312    private void ConfigureAdditiveMoveOperator(IEnumerable<IAdditiveRealVectorMoveOperator> additiveMoveOperators) {
313      foreach (var additiveMoveOperator in additiveMoveOperators) {
314        additiveMoveOperator.AdditiveMoveParameter.ActualName = Name + ".AdditiveMove";
315      }
316    }
317    #endregion
318  }
319
320  public static class IndividualExtensionMethods {
321    public static RealVector RealVector(this Individual individual) {
322      var encoding = individual.GetEncoding<RealVectorEncoding>();
323      return individual.RealVector(encoding.Name);
324    }
325    public static RealVector RealVector(this Individual individual, string name) {
326      return (RealVector)individual[name];
327    }
328  }
329}
Note: See TracBrowser for help on using the repository browser.