source: branches/ProgrammableProblem/HeuristicLab.Problems.Programmable/3.3/Encodings/RealEncoding.cs @ 11753

Last change on this file since 11753 was 11753, checked in by mkommend, 5 years ago

#2174: First working version of refactored programmable problem.

File size: 14.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2014 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.Encodings.RealVectorEncoding;
29using HeuristicLab.Optimization;
30using HeuristicLab.Parameters;
31using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
32using HeuristicLab.PluginInfrastructure;
33
34namespace HeuristicLab.Problems.Programmable {
35  [Item("RealEncoding", "Describes a real vector encoding.")]
36  [StorableClass]
37  public sealed class RealEncoding : Encoding<IRealVectorCreator> {
38    #region Encoding Parameters
39    [Storable]
40    private IFixedValueParameter<IntValue> lengthParameter;
41    public IFixedValueParameter<IntValue> LengthParameter {
42      get { return lengthParameter; }
43      set {
44        if (value == null) throw new ArgumentNullException("Length parameter must not be null.");
45        if (value.Value == null) throw new ArgumentNullException("Length parameter value must not be null.");
46        if (lengthParameter == value) return;
47
48        if (lengthParameter != null) Parameters.Remove(lengthParameter);
49        lengthParameter = value;
50        Parameters.Add(lengthParameter);
51        OnLengthParameterChanged();
52      }
53    }
54    [Storable]
55    private IValueParameter<DoubleMatrix> boundsParameter;
56    public IValueParameter<DoubleMatrix> BoundsParameter {
57      get { return boundsParameter; }
58      set {
59        if (value == null) throw new ArgumentNullException("Bounds parameter must not be null.");
60        if (boundsParameter == value) return;
61
62        if (boundsParameter != null) Parameters.Remove(boundsParameter);
63        boundsParameter = value;
64        Parameters.Add(boundsParameter);
65        OnBoundsParameterChanged();
66      }
67    }
68    #endregion
69
70    public int Length {
71      get { return LengthParameter.Value.Value; }
72      set { LengthParameter.Value.Value = value; }
73    }
74    public DoubleMatrix Bounds {
75      get { return BoundsParameter.Value; }
76      set { BoundsParameter.Value = value; }
77    }
78
79    [StorableConstructor]
80    private RealEncoding(bool deserializing) : base(deserializing) { }
81    [StorableHook(HookType.AfterDeserialization)]
82    private void AfterDeserialization() {
83      RegisterParameterEvents();
84      DiscoverOperators();
85    }
86
87    public override IDeepCloneable Clone(Cloner cloner) { return new RealEncoding(this, cloner); }
88    private RealEncoding(RealEncoding original, Cloner cloner)
89      : base(original, cloner) {
90      lengthParameter = cloner.Clone(original.lengthParameter);
91      boundsParameter = cloner.Clone(original.boundsParameter);
92      RegisterParameterEvents();
93    }
94
95    public RealEncoding() : this("RealVector", 10) { }
96    public RealEncoding(int length) : this("RealVector", length) { }
97    public RealEncoding(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 RealEncoding(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 RealEncoding() {
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 pluginDescription = ApplicationManager.Manager.GetDeclaringPlugin(typeof(IRealVectorOperator));
176      var discoveredTypes = ApplicationManager.Manager.GetTypes(encodingSpecificOperatorTypes, pluginDescription, 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        encodingOperators.Add(@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      }
293    }
294    private void ConfigureBoundsCheckers(IEnumerable<IRealVectorBoundsChecker> boundsCheckers) {
295      foreach (var boundsChecker in boundsCheckers) {
296        boundsChecker.RealVectorParameter.ActualName = Name;
297        boundsChecker.BoundsParameter.ActualName = BoundsParameter.Name;
298      }
299    }
300    private void ConfigureMoveOperators(IEnumerable<IRealVectorMoveOperator> moveOperators) {
301      foreach (var moveOperator in moveOperators)
302        moveOperator.RealVectorParameter.ActualName = Name;
303    }
304
305    private void ConfigureMoveGenerators(IEnumerable<IRealVectorMoveGenerator> moveGenerators) {
306      foreach (var moveGenerator in moveGenerators)
307        moveGenerator.BoundsParameter.ActualName = BoundsParameter.Name;
308    }
309
310    private void ConfigureAdditiveMoveOperator(IEnumerable<IAdditiveRealVectorMoveOperator> additiveMoveOperators) {
311      foreach (var additiveMoveOperator in additiveMoveOperators) {
312        additiveMoveOperator.AdditiveMoveParameter.ActualName = Name + ".AdditiveMove";
313      }
314    }
315    #endregion
316  }
317}
Note: See TracBrowser for help on using the repository browser.