Free cookie consent management tool by TermsFeed Policy Generator

source: branches/SimSharp/HeuristicLab.Problems.Programmable/3.3/SingleObjectiveProgrammableProblem.cs @ 10850

Last change on this file since 10850 was 10850, checked in by abeham, 10 years ago

#2174: Major refactoring:

  • ParameterVector is only a temporary datastructure that is constructed for evaluation purposes only
  • Multiple permutations are allowed
  • Special support for single-vector encodings (to apply specialized algorithms such as PSO or CMA-ES)
  • General support for multi-vector encoding
File size: 19.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.Drawing;
25using System.Linq;
26using HeuristicLab.Analysis;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Data;
30using HeuristicLab.Encodings.BinaryVectorEncoding;
31using HeuristicLab.Encodings.IntegerVectorEncoding;
32using HeuristicLab.Encodings.PermutationEncoding;
33using HeuristicLab.Encodings.RealVectorEncoding;
34using HeuristicLab.Optimization;
35using HeuristicLab.Parameters;
36using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
37using HeuristicLab.PluginInfrastructure;
38
39namespace HeuristicLab.Problems.Programmable {
40  [Item("Programmable Problem (single-objective)", "Represents a single-objective problem that can be programmed.")]
41  [Creatable("Problems")]
42  [StorableClass]
43  public class SingleObjectiveProgrammableProblem : SingleObjectiveHeuristicOptimizationProblem<ISingleObjectiveProgrammableProblemEvaluator, ISolutionCreator>, IParameterizedNamedItem, IStorableContent {
44    public string Filename { get; set; }
45
46    public static new Image StaticItemImage {
47      get { return HeuristicLab.Common.Resources.VSImageLibrary.Script; }
48    }
49
50    public new ParameterCollection Parameters {
51      get { return base.Parameters; }
52    }
53    IKeyedItemCollection<string, IParameter> IParameterizedItem.Parameters {
54      get { return Parameters; }
55    }
56
57    public IValueParameter<SingleObjectiveScript> ScriptParameter {
58      get { return (IValueParameter<SingleObjectiveScript>)Parameters["Script"]; }
59    }
60
61    public IValueParameter<Configuration> ConfigurationParameter {
62      get { return (IValueParameter<Configuration>)Parameters["Configuration"]; }
63    }
64
65    [Storable]
66    protected List<IParameter> DynamicConfigurationParameters;
67
68    [StorableConstructor]
69    protected SingleObjectiveProgrammableProblem(bool deserializing) : base(deserializing) { }
70
71    protected SingleObjectiveProgrammableProblem(SingleObjectiveProgrammableProblem original, Cloner cloner)
72      : base(original, cloner) {
73      DynamicConfigurationParameters = original.DynamicConfigurationParameters.Select(cloner.Clone).ToList();
74      RegisterEventHandlers();
75    }
76    public SingleObjectiveProgrammableProblem()
77      : base(new SingleObjectiveEvaluator(), new ParameterVectorCreater()) {
78      Parameters.Add(new ValueParameter<SingleObjectiveScript>("Script", "Defines the problem.", new SingleObjectiveScript() { Name = ItemName }));
79      Parameters.Add(new ValueParameter<Configuration>("Configuration", "Describes which parameters exist, what they're called, what type they are and their bounds if any."));
80
81      DynamicConfigurationParameters = new List<IParameter>();
82
83      Operators.Add(new BestScopeSolutionAnalyzer());
84      Operators.Add(Evaluator);
85      Operators.Add(SolutionCreator);
86
87      RegisterEventHandlers();
88    }
89
90    public override IDeepCloneable Clone(Cloner cloner) {
91      return new SingleObjectiveProgrammableProblem(this, cloner);
92    }
93
94    [StorableHook(HookType.AfterDeserialization)]
95    private void AfterDeserialization() {
96      RegisterEventHandlers();
97    }
98
99    private void RegisterEventHandlers() {
100      ScriptParameter.ValueChanged += ScriptParameterOnValueChanged;
101      RegisterScriptInstanceChanges();
102    }
103
104    private void ScriptParameterOnValueChanged(object sender, EventArgs eventArgs) {
105      RegisterScriptInstanceChanges();
106    }
107
108    private void RegisterScriptInstanceChanges() {
109      ScriptParameter.Value.InstanceChanged += ScriptOnInstanceChanged;
110      ScriptParameter.Value.NameChanged += ScriptOnNameChanged;
111    }
112
113    private void ScriptOnNameChanged(object sender, EventArgs eventArgs) {
114      if (sender != ScriptParameter.Value) return;
115      if (Name != ScriptParameter.Value.Name)
116        Name = ScriptParameter.Value.Name;
117    }
118
119    protected override void OnNameChanged() {
120      base.OnNameChanged();
121      if (ScriptParameter.Value.Name != Name)
122        ScriptParameter.Value.Name = Name;
123    }
124
125    protected virtual void ScriptOnInstanceChanged(object sender, EventArgs eventArgs) {
126
127      var instance = ScriptParameter.Value.Instance;
128      if (instance == null) return;
129
130      var configuration = instance.GetConfiguration();
131      ConfigurationParameter.Value = configuration;
132      Maximization.Value = configuration.Maximization;
133
134      foreach (var param in DynamicConfigurationParameters)
135        if (Parameters.Contains(param)) Parameters.Remove(param);
136      DynamicConfigurationParameters.Clear();
137
138      var solutionCreators = new List<ISolutionCreator>();
139      foreach (var parameters in configuration.Parameters) {
140        var binConfig = parameters.Value as BinaryParameterConfiguration;
141        if (binConfig != null) {
142          var p = new ValueParameter<IntValue>(parameters.Key + "Length", binConfig.Length);
143          DynamicConfigurationParameters.Add(p);
144
145          var creator = new RandomBinaryVectorCreator();
146          creator.BinaryVectorParameter.ActualName = parameters.Key;
147          creator.LengthParameter.ActualName = p.Name;
148          solutionCreators.Add(creator);
149        }
150        var intConfig = parameters.Value as IntegerParameterConfiguration;
151        if (intConfig != null) {
152          var l = new ValueParameter<IntValue>(parameters.Key + "Length", intConfig.Length);
153          var b = new ValueParameter<IntMatrix>(parameters.Key + "Bounds", intConfig.Bounds);
154          DynamicConfigurationParameters.Add(l);
155          DynamicConfigurationParameters.Add(b);
156
157          var creator = new UniformRandomIntegerVectorCreator();
158          creator.IntegerVectorParameter.ActualName = parameters.Key;
159          creator.LengthParameter.ActualName = l.Name;
160          creator.BoundsParameter.ActualName = b.Name;
161          solutionCreators.Add(creator);
162        }
163        var realConfig = parameters.Value as RealParameterConfiguration;
164        if (realConfig != null) {
165          var l = new ValueParameter<IntValue>(parameters.Key + "Length", realConfig.Length);
166          var b = new ValueParameter<DoubleMatrix>(parameters.Key + "Bounds", realConfig.Bounds);
167          DynamicConfigurationParameters.Add(l);
168          DynamicConfigurationParameters.Add(b);
169
170          var creator = new UniformRandomRealVectorCreator();
171          creator.RealVectorParameter.ActualName = parameters.Key;
172          creator.LengthParameter.ActualName = l.Name;
173          creator.BoundsParameter.ActualName = b.Name;
174          solutionCreators.Add(creator);
175        }
176        var permConfig = parameters.Value as PermutationParameterConfiguration;
177        if (permConfig != null) {
178          var l = new ValueParameter<IntValue>(parameters.Key + "Length", permConfig.Length);
179          DynamicConfigurationParameters.Add(l);
180
181          var creator = new RandomPermutationCreator();
182          creator.PermutationParameter.ActualName = parameters.Key;
183          creator.LengthParameter.ActualName = l.Name;
184          creator.PermutationTypeParameter.Value = permConfig.Type;
185          solutionCreators.Add(creator);
186        }
187      }
188
189      foreach (var param in DynamicConfigurationParameters) {
190        param.Hidden = true;
191        Parameters.Add(param);
192      }
193
194      // use specialized creators if the configuration consists only of a single parameter type
195      // this allows to use specialized algorithms such as CMA-ES
196      if (solutionCreators.Count == 1) { // single-vector encoding
197        Operators.RemoveAll(x => x is ICrossover);
198        Operators.RemoveAll(x => x is IManipulator);
199        var newCreator = solutionCreators.Single();
200        var binCreator = newCreator as IBinaryVectorCreator;
201        if (binCreator != null) {
202          // do not replace a binary vector creator that was manually set
203          if (!(SolutionCreator is IBinaryVectorCreator)
204              || ((IBinaryVectorCreator)SolutionCreator).BinaryVectorParameter.ActualName != binCreator.BinaryVectorParameter.ActualName) {
205            Operators.Remove(SolutionCreator);
206            SolutionCreator = newCreator;
207            Operators.Add(SolutionCreator);
208          }
209          var crossovers = ApplicationManager.Manager.GetInstances<IBinaryVectorCrossover>().ToList();
210          var manipulators = ApplicationManager.Manager.GetInstances<IBinaryVectorManipulator>().ToList();
211          foreach (var xo in crossovers) {
212            xo.ChildParameter.ActualName = binCreator.BinaryVectorParameter.ActualName;
213            xo.ParentsParameter.ActualName = binCreator.BinaryVectorParameter.ActualName;
214          }
215          foreach (var m in manipulators)
216            m.BinaryVectorParameter.ActualName = binCreator.BinaryVectorParameter.ActualName;
217          Operators.AddRange(crossovers);
218          Operators.AddRange(manipulators);
219        }
220        var intCreator = newCreator as IIntegerVectorCreator;
221        if (intCreator != null) {
222          // do not replace an integer vector creator that was manually set
223          if (!(SolutionCreator is IIntegerVectorCreator)
224              || ((IIntegerVectorCreator)SolutionCreator).IntegerVectorParameter.ActualName != intCreator.IntegerVectorParameter.ActualName) {
225            Operators.Remove(SolutionCreator);
226            SolutionCreator = newCreator;
227            Operators.Add(SolutionCreator);
228          }
229          var crossovers = ApplicationManager.Manager.GetInstances<IIntegerVectorCrossover>().ToList();
230          var manipulators = ApplicationManager.Manager.GetInstances<IIntegerVectorManipulator>().ToList();
231          foreach (var xo in crossovers) {
232            xo.ChildParameter.ActualName = intCreator.IntegerVectorParameter.ActualName;
233            xo.ParentsParameter.ActualName = intCreator.IntegerVectorParameter.ActualName;
234          }
235          foreach (var m in manipulators)
236            m.IntegerVectorParameter.ActualName = intCreator.IntegerVectorParameter.ActualName;
237          foreach (var bo in crossovers.OfType<IBoundedIntegerVectorOperator>().Concat(manipulators.OfType<IBoundedIntegerVectorOperator>()).ToList()) {
238            bo.BoundsParameter.ActualName = intCreator.BoundsParameter.ActualName;
239          }
240          Operators.AddRange(crossovers);
241          Operators.AddRange(manipulators);
242        }
243        var realCreator = newCreator as IRealVectorCreator;
244        if (realCreator != null) {
245          // do not replace a real vector creator that was manually set
246          if (!(SolutionCreator is IRealVectorCreator)
247              || ((IRealVectorCreator)SolutionCreator).RealVectorParameter.ActualName != realCreator.RealVectorParameter.ActualName) {
248            Operators.Remove(SolutionCreator);
249            SolutionCreator = newCreator;
250            Operators.Add(SolutionCreator);
251          }
252          var crossovers = ApplicationManager.Manager.GetInstances<IRealVectorCrossover>().ToList();
253          var manipulators = ApplicationManager.Manager.GetInstances<IRealVectorManipulator>().ToList();
254          foreach (var xo in crossovers) {
255            xo.ChildParameter.ActualName = realCreator.RealVectorParameter.ActualName;
256            xo.ParentsParameter.ActualName = realCreator.RealVectorParameter.ActualName;
257            xo.BoundsParameter.ActualName = realCreator.BoundsParameter.ActualName;
258          }
259          foreach (var m in manipulators) {
260            m.RealVectorParameter.ActualName = realCreator.RealVectorParameter.ActualName;
261            m.BoundsParameter.ActualName = realCreator.BoundsParameter.ActualName;
262          }
263          Operators.AddRange(crossovers);
264          Operators.AddRange(manipulators);
265        }
266        var permCreator = newCreator as IPermutationCreator;
267        if (permCreator != null) {
268          // do not replace a permutation creator that was manually set
269          if (!(SolutionCreator is IPermutationCreator)
270              || ((IPermutationCreator)SolutionCreator).PermutationParameter.ActualName != permCreator.PermutationParameter.ActualName) {
271            Operators.Remove(SolutionCreator);
272            SolutionCreator = newCreator;
273            Operators.Add(SolutionCreator);
274          }
275          var crossovers = ApplicationManager.Manager.GetInstances<IPermutationCrossover>().ToList();
276          var manipulators = ApplicationManager.Manager.GetInstances<IPermutationManipulator>().ToList();
277          foreach (var xo in crossovers) {
278            xo.ChildParameter.ActualName = permCreator.PermutationParameter.ActualName;
279            xo.ParentsParameter.ActualName = permCreator.PermutationParameter.ActualName;
280          }
281          foreach (var m in manipulators)
282            m.PermutationParameter.ActualName = permCreator.PermutationParameter.ActualName;
283          Operators.AddRange(crossovers);
284          Operators.AddRange(manipulators);
285        }
286      } else { // multi-vector encoding
287        var oldCreator = SolutionCreator as ParameterVectorCreater;
288        var newCreator = new ParameterVectorCreater();
289        var newBinParams = new HashSet<string>(solutionCreators.OfType<IBinaryVectorCreator>().Select(x => x.BinaryVectorParameter.ActualName));
290        if (oldCreator != null) { // we want to reuse the old creator
291          var oldParams = new HashSet<string>(oldCreator
292            .BeforeExecutionOperators.OfType<IBinaryVectorCreator>()
293            .Select(x => x.BinaryVectorParameter.ActualName));
294          foreach (var toAdd in newBinParams.Except(oldParams)) {
295            var paramName = toAdd;
296            oldCreator.BeforeExecutionOperators.Add(solutionCreators.OfType<IBinaryVectorCreator>().Single(x => x.BinaryVectorParameter.ActualName == paramName));
297          }
298          foreach (var toRemove in oldParams.Except(newBinParams)) {
299            var paramName = toRemove;
300            oldCreator.BeforeExecutionOperators.RemoveAll(
301              op => op is IBinaryVectorCreator && ((IBinaryVectorCreator)op).BinaryVectorParameter.ActualName == paramName);
302          }
303        } else { // we will use the new creator
304          foreach (var binCreator in solutionCreators.OfType<IBinaryVectorCreator>()) {
305            newCreator.BeforeExecutionOperators.Add(binCreator);
306          }
307        }
308
309        var newIntParams = new HashSet<string>(solutionCreators.OfType<IIntegerVectorCreator>().Select(x => x.IntegerVectorParameter.ActualName));
310        if (oldCreator != null) { // we want to reuse the old creator
311          var oldParams = new HashSet<string>(oldCreator
312            .BeforeExecutionOperators.OfType<IIntegerVectorCreator>()
313            .Select(x => x.IntegerVectorParameter.ActualName));
314          foreach (var toAdd in newIntParams.Except(oldParams)) {
315            var paramName = toAdd;
316            oldCreator.BeforeExecutionOperators.Add(solutionCreators.OfType<IIntegerVectorCreator>().Single(x => x.IntegerVectorParameter.ActualName == paramName));
317          }
318          foreach (var toRemove in oldParams.Except(newIntParams)) {
319            var paramName = toRemove;
320            oldCreator.BeforeExecutionOperators.RemoveAll(
321              op => op is IIntegerVectorCreator && ((IIntegerVectorCreator)op).IntegerVectorParameter.ActualName == paramName);
322          }
323        } else { // we will use the new creator
324          foreach (var intCreator in solutionCreators.OfType<IIntegerVectorCreator>()) {
325            newCreator.BeforeExecutionOperators.Add(intCreator);
326          }
327        }
328
329        var newRealParams = new HashSet<string>(solutionCreators.OfType<IRealVectorCreator>().Select(x => x.RealVectorParameter.ActualName));
330        if (oldCreator != null) { // we want to reuse the old creator
331          var oldParams = new HashSet<string>(oldCreator
332            .BeforeExecutionOperators.OfType<IRealVectorCreator>()
333            .Select(x => x.RealVectorParameter.ActualName));
334          foreach (var toAdd in newRealParams.Except(oldParams)) {
335            var paramName = toAdd;
336            oldCreator.BeforeExecutionOperators.Add(solutionCreators.OfType<IRealVectorCreator>().Single(x => x.RealVectorParameter.ActualName == paramName));
337          }
338          foreach (var toRemove in oldParams.Except(newRealParams)) {
339            var paramName = toRemove;
340            oldCreator.BeforeExecutionOperators.RemoveAll(
341              op => op is IRealVectorCreator && ((IRealVectorCreator)op).RealVectorParameter.ActualName == paramName);
342          }
343        } else { // we will use the new creator
344          foreach (var realCreator in solutionCreators.OfType<IRealVectorCreator>()) {
345            newCreator.BeforeExecutionOperators.Add(realCreator);
346          }
347        }
348
349        var newPermParams = new HashSet<string>(solutionCreators.OfType<IPermutationCreator>().Select(x => x.PermutationParameter.ActualName));
350        if (oldCreator != null) { // we want to reuse the old creator
351          var oldParams = new HashSet<string>(oldCreator
352            .BeforeExecutionOperators.OfType<IPermutationCreator>()
353            .Select(x => x.PermutationParameter.ActualName));
354          foreach (var toAdd in newPermParams.Except(oldParams)) {
355            var paramName = toAdd;
356            oldCreator.BeforeExecutionOperators.Add(solutionCreators.OfType<IPermutationCreator>().Single(x => x.PermutationParameter.ActualName == paramName));
357          }
358          foreach (var toRemove in oldParams.Except(newPermParams)) {
359            var paramName = toRemove;
360            oldCreator.BeforeExecutionOperators.RemoveAll(
361              op => op is IPermutationCreator && ((IPermutationCreator)op).PermutationParameter.ActualName == paramName);
362          }
363          // we also have to sync the permutation type (in case this changes, as it is a value parameter)
364          foreach (var intersect in newPermParams.Intersect(oldParams)) {
365            var paramName = intersect;
366            var oldPermCreator = oldCreator.BeforeExecutionOperators.OfType<IPermutationCreator>()
367              .Single(x => x.PermutationParameter.ActualName == paramName);
368            var newPermCreator = solutionCreators.OfType<IPermutationCreator>()
369                .Single(x => x.PermutationParameter.ActualName == paramName);
370            oldPermCreator.PermutationTypeParameter.Value = newPermCreator.PermutationTypeParameter.Value;
371          }
372        } else { // we will use the new creator
373          foreach (var permCreator in solutionCreators.OfType<IPermutationCreator>()) {
374            newCreator.BeforeExecutionOperators.Add(permCreator);
375          }
376        }
377      }
378    }
379  }
380}
Note: See TracBrowser for help on using the repository browser.