source: trunk/sources/HeuristicLab.Encodings.RealVectorEncoding/3.3/RealVectorEncoding.cs @ 12012

Last change on this file since 12012 was 12012, checked in by ascheibe, 5 years ago

#2212 merged r12008, r12009, r12010 back into trunk

File size: 14.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 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 HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
31using HeuristicLab.PluginInfrastructure;
32
33namespace HeuristicLab.Encodings.RealVectorEncoding {
34  [Item("RealVectorEncoding", "Describes a real vector encoding.")]
35  [StorableClass]
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(bool deserializing) : base(deserializing) { }
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
129      SolutionCreator = new UniformRandomRealVectorCreator();
130      RegisterParameterEvents();
131      DiscoverOperators();
132    }
133
134    private void OnLengthParameterChanged() {
135      RegisterLengthParameterEvents();
136      ConfigureOperators(Operators);
137    }
138    private void OnBoundsParameterChanged() {
139      RegisterBoundsParameterEvents();
140      ConfigureOperators(Operators);
141    }
142
143    private void RegisterParameterEvents() {
144      RegisterLengthParameterEvents();
145      RegisterBoundsParameterEvents();
146    }
147    private void RegisterLengthParameterEvents() {
148      LengthParameter.ValueChanged += (o, s) => ConfigureOperators(Operators);
149      LengthParameter.Value.ValueChanged += (o, s) => ConfigureOperators(Operators);
150    }
151    private void RegisterBoundsParameterEvents() {
152      BoundsParameter.ValueChanged += (o, s) => ConfigureOperators(Operators);
153      boundsParameter.Value.ToStringChanged += (o, s) => ConfigureOperators(Operators);
154    }
155
156    #region Operator Discovery
157    private static readonly IEnumerable<Type> encodingSpecificOperatorTypes;
158    static RealVectorEncoding() {
159      encodingSpecificOperatorTypes = new List<Type>() {
160          typeof (IRealVectorOperator),
161          typeof (IRealVectorCreator),
162          typeof (IRealVectorCrossover),
163          typeof (IRealVectorManipulator),
164          typeof (IRealVectorStdDevStrategyParameterOperator),
165          typeof (IRealVectorSwarmUpdater),
166          typeof (IRealVectorParticleCreator),
167          typeof (IRealVectorParticleUpdater),
168          typeof (IRealVectorMultiNeighborhoodShakingOperator),
169          typeof (IRealVectorBoundsChecker),
170          typeof (IRealVectorMoveOperator),
171          typeof (IRealVectorMoveGenerator)
172      };
173    }
174    private void DiscoverOperators() {
175      var assembly = typeof(IRealVectorOperator).Assembly;
176      var discoveredTypes = ApplicationManager.Manager.GetTypes(encodingSpecificOperatorTypes, assembly, true, false, false);
177      var operators = discoveredTypes.Select(t => (IOperator)Activator.CreateInstance(t));
178      var newOperators = operators.Except(Operators, new TypeEqualityComparer<IOperator>()).ToList();
179
180      ConfigureOperators(newOperators);
181      foreach (var @operator in newOperators)
182        AddOperator(@operator);
183
184      foreach (var strategyVectorCreator in Operators.OfType<IRealVectorStdDevStrategyParameterCreator>())
185        strategyVectorCreator.BoundsParameter.ValueChanged += strategyVectorCreator_BoundsParameter_ValueChanged;
186    }
187    #endregion
188
189
190    private void strategyVectorCreator_BoundsParameter_ValueChanged(object sender, EventArgs e) {
191      var boundsParameter = (IValueLookupParameter<DoubleMatrix>)sender;
192      if (boundsParameter.Value == null) return;
193      foreach (var strategyVectorManipulator in Operators.OfType<IRealVectorStdDevStrategyParameterManipulator>())
194        strategyVectorManipulator.BoundsParameter.Value = (DoubleMatrix)boundsParameter.Value.Clone();
195    }
196
197    public override void ConfigureOperators(IEnumerable<IOperator> operators) {
198      ConfigureCreators(operators.OfType<IRealVectorCreator>());
199      ConfigureCrossovers(operators.OfType<IRealVectorCrossover>());
200      ConfigureManipulators(operators.OfType<IRealVectorManipulator>());
201      ConfigureStdDevStrategyParameterOperators(operators.OfType<IRealVectorStdDevStrategyParameterOperator>());
202      ConfigureSwarmUpdaters(operators.OfType<IRealVectorSwarmUpdater>());
203      ConfigureParticleCreators(operators.OfType<IRealVectorParticleCreator>());
204      ConfigureParticleUpdaters(operators.OfType<IRealVectorParticleUpdater>());
205      ConfigureShakingOperators(operators.OfType<IRealVectorMultiNeighborhoodShakingOperator>());
206      ConfigureBoundsCheckers(operators.OfType<IRealVectorBoundsChecker>());
207      ConfigureMoveGenerators(operators.OfType<IRealVectorMoveGenerator>());
208      ConfigureMoveOperators(operators.OfType<IRealVectorMoveOperator>());
209      ConfigureAdditiveMoveOperator(operators.OfType<IAdditiveRealVectorMoveOperator>());
210    }
211
212    #region Specific Operator Wiring
213    private void ConfigureCreators(IEnumerable<IRealVectorCreator> creators) {
214      foreach (var creator in creators) {
215        creator.RealVectorParameter.ActualName = Name;
216        creator.LengthParameter.ActualName = LengthParameter.Name;
217        creator.BoundsParameter.ActualName = BoundsParameter.Name;
218      }
219    }
220    private void ConfigureCrossovers(IEnumerable<IRealVectorCrossover> crossovers) {
221      foreach (var crossover in crossovers) {
222        crossover.ChildParameter.ActualName = Name;
223        crossover.ParentsParameter.ActualName = Name;
224        crossover.BoundsParameter.ActualName = BoundsParameter.Name;
225      }
226    }
227    private void ConfigureManipulators(IEnumerable<IRealVectorManipulator> manipulators) {
228      foreach (var manipulator in manipulators) {
229        manipulator.RealVectorParameter.ActualName = Name;
230        manipulator.BoundsParameter.ActualName = BoundsParameter.Name;
231        manipulator.BoundsParameter.Hidden = true;
232        var sm = manipulator as ISelfAdaptiveManipulator;
233        if (sm != null) {
234          var p = sm.StrategyParameterParameter as ILookupParameter;
235          if (p != null) {
236            p.ActualName = Name + ".Strategy";
237          }
238        }
239      }
240    }
241    private void ConfigureStdDevStrategyParameterOperators(IEnumerable<IRealVectorStdDevStrategyParameterOperator> strategyOperators) {
242      var bounds = new DoubleMatrix(Bounds.Rows, Bounds.Columns);
243      for (var i = 0; i < Bounds.Rows; i++) {
244        bounds[i, 0] = 0;
245        bounds[i, 1] = 0.1 * (Bounds[i, 1] - Bounds[i, 0]);
246      }
247      foreach (var s in strategyOperators) {
248        var c = s as IRealVectorStdDevStrategyParameterCreator;
249        if (c != null) {
250          c.BoundsParameter.Value = (DoubleMatrix)bounds.Clone();
251          c.LengthParameter.ActualName = LengthParameter.Name;
252          c.StrategyParameterParameter.ActualName = Name + ".Strategy";
253        }
254        var m = s as IRealVectorStdDevStrategyParameterManipulator;
255        if (m != null) {
256          m.BoundsParameter.Value = (DoubleMatrix)bounds.Clone();
257          m.StrategyParameterParameter.ActualName = Name + ".Strategy";
258        }
259        var mm = s as StdDevStrategyVectorManipulator;
260        if (mm != null) {
261          mm.GeneralLearningRateParameter.Value = new DoubleValue(1.0 / Math.Sqrt(2 * Length));
262          mm.LearningRateParameter.Value = new DoubleValue(1.0 / Math.Sqrt(2 * Math.Sqrt(Length)));
263        }
264        var x = s as IRealVectorStdDevStrategyParameterCrossover;
265        if (x != null) {
266          x.ParentsParameter.ActualName = Name + ".Strategy";
267          x.StrategyParameterParameter.ActualName = Name + ".Strategy";
268        }
269      }
270    }
271    private void ConfigureSwarmUpdaters(IEnumerable<IRealVectorSwarmUpdater> swarmUpdaters) {
272      foreach (var su in swarmUpdaters) {
273        su.RealVectorParameter.ActualName = Name;
274      }
275    }
276    private void ConfigureParticleCreators(IEnumerable<IRealVectorParticleCreator> particleCreators) {
277      foreach (var particleCreator in particleCreators) {
278        particleCreator.RealVectorParameter.ActualName = Name;
279        particleCreator.BoundsParameter.ActualName = BoundsParameter.Name;
280        particleCreator.ProblemSizeParameter.ActualName = LengthParameter.Name;
281      }
282    }
283    private void ConfigureParticleUpdaters(IEnumerable<IRealVectorParticleUpdater> particleUpdaters) {
284      foreach (var particleUpdater in particleUpdaters) {
285        particleUpdater.RealVectorParameter.ActualName = Name;
286        particleUpdater.BoundsParameter.ActualName = BoundsParameter.Name;
287      }
288    }
289    private void ConfigureShakingOperators(IEnumerable<IRealVectorMultiNeighborhoodShakingOperator> shakingOperators) {
290      foreach (var shakingOperator in shakingOperators) {
291        shakingOperator.RealVectorParameter.ActualName = Name;
292        shakingOperator.BoundsParameter.ActualName = BoundsParameter.Name;
293      }
294    }
295    private void ConfigureBoundsCheckers(IEnumerable<IRealVectorBoundsChecker> boundsCheckers) {
296      foreach (var boundsChecker in boundsCheckers) {
297        boundsChecker.RealVectorParameter.ActualName = Name;
298        boundsChecker.BoundsParameter.ActualName = BoundsParameter.Name;
299      }
300    }
301    private void ConfigureMoveOperators(IEnumerable<IRealVectorMoveOperator> moveOperators) {
302      foreach (var moveOperator in moveOperators)
303        moveOperator.RealVectorParameter.ActualName = Name;
304    }
305
306    private void ConfigureMoveGenerators(IEnumerable<IRealVectorMoveGenerator> moveGenerators) {
307      foreach (var moveGenerator in moveGenerators)
308        moveGenerator.BoundsParameter.ActualName = BoundsParameter.Name;
309    }
310
311    private void ConfigureAdditiveMoveOperator(IEnumerable<IAdditiveRealVectorMoveOperator> additiveMoveOperators) {
312      foreach (var additiveMoveOperator in additiveMoveOperators) {
313        additiveMoveOperator.AdditiveMoveParameter.ActualName = Name + ".AdditiveMove";
314      }
315    }
316    #endregion
317  }
318
319  public static class IndividualExtensionMethods {
320    public static RealVector RealVector(this Individual individual) {
321      var encoding = individual.GetEncoding<RealVectorEncoding>();
322      return individual.RealVector(encoding.Name);
323    }
324    public static RealVector RealVector(this Individual individual, string name) {
325      return (RealVector)individual[name];
326    }
327  }
328}
Note: See TracBrowser for help on using the repository browser.