Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurations/ParameterConfiguration.cs @ 5207

Last change on this file since 5207 was 5207, checked in by cneumuel, 13 years ago

#1215

  • lots of memory-consumption improvements
  • validValues -> validTypes (this saves memory!)
  • changed manipulators; modifications are less significant, out-of-bound-values are resampled instead of set to lower or upper bound
  • changed the way a base-level algorithm gets executed -> introduced AlgorithmExecutor
File size: 15.4 KB
Line 
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.Linq;
5using HeuristicLab.Common;
6using HeuristicLab.Core;
7using HeuristicLab.Data;
8using HeuristicLab.Parameters;
9using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
10using HeuristicLab.PluginInfrastructure;
11using System.Text;
12using System.Reflection;
13
14namespace HeuristicLab.Problems.MetaOptimization {
15  [StorableClass]
16  public class ParameterConfiguration : Item, IParameterConfiguration, IStorableContent {
17    public bool IsOptimizable {
18      get { return true; }
19    }
20
21    [Storable]
22    public string Filename { get; set; }
23
24    [Storable]
25    protected bool optimize;
26    public bool Optimize {
27      get { return optimize; }
28      set {
29        if (optimize != value) {
30          optimize = value;
31          if (optimize) {
32            PopulateValueConfigurations();
33          } else {
34            this.ValueConfigurations.Clear();
35          }
36          OnOptimizeChanged();
37          OnToStringChanged();
38        }
39      }
40    }
41
42    [Storable]
43    protected string parameterName;
44    public string ParameterName {
45      get { return parameterName; }
46      set {
47        if (parameterName != value) {
48          parameterName = value;
49          OnToStringChanged();
50        }
51      }
52    }
53
54    [Storable]
55    protected Type parameterDataType;
56    public Type ParameterDataType {
57      get { return this.parameterDataType; }
58    }
59
60    [Storable]
61    protected Type[] validTypes;
62    public Type[] ValidTypes {
63      get { return validTypes; }
64      protected set {
65        if (this.validTypes != value) {
66          this.validTypes = value;
67        }
68      }
69    }
70
71    [Storable]
72    protected Type valueDataType;
73    public Type ValueDataType {
74      get { return valueDataType; }
75      protected set { this.valueDataType = value; }
76    }
77
78    [Storable]
79    protected ICheckedValueConfigurationCollection valueConfigurations;
80    public ICheckedValueConfigurationCollection ValueConfigurations {
81      get { return this.valueConfigurations; }
82      protected set {
83        if (this.valueConfigurations != value) {
84          if (this.valueConfigurations != null) DeregisterValueConfigurationEvents();
85          this.valueConfigurations = value;
86          if (this.valueConfigurations != null) RegisterValueConfigurationEvents();
87        }
88      }
89    }
90
91    [Storable]
92    private int actualValueConfigurationIndex = 0;
93    public int ActualValueConfigurationIndex {
94      get { return actualValueConfigurationIndex; }
95      set { actualValueConfigurationIndex = value; }
96    }
97
98    [Storable]
99    protected ConstrainedValue actualValue;
100    public ConstrainedValue ActualValue {
101      get { return actualValue; }
102      set {
103        if (actualValue != value) {
104          DeregisterActualValueEvents();
105          actualValue = value;
106          RegisterActualValueEvents();
107        }
108      }
109    }
110
111    [Storable]
112    protected bool isNullable;
113    public bool IsNullable {
114      get { return isNullable; }
115      protected set {
116        if (this.isNullable != value) {
117          this.isNullable = value;
118        }
119      }
120    }
121
122    #region Constructors and Cloning
123    public ParameterConfiguration(string parameterName, IValueParameter valueParameter) {
124      this.ParameterName = parameterName;
125      this.parameterDataType = valueParameter.GetType();
126      this.valueDataType = valueParameter.DataType;
127      this.validTypes = GetValidTypes(valueParameter).ToArray();
128      this.IsNullable = valueParameter.ItemName.StartsWith("Optional");
129      if (IsNullable) {
130        validTypes = new List<Type>(validTypes) { typeof(NullValue) }.ToArray();
131      }
132      this.ValueConfigurations = new CheckedValueConfigurationCollection(this.validTypes);
133      this.ActualValue = new ConstrainedValue(valueParameter.Value != null ? (IItem)valueParameter.Value.Clone() : null, valueParameter.DataType, this.ValidTypes, this.IsNullable);
134      if (Optimize) {
135        PopulateValueConfigurations();
136      }
137    }
138
139    public ParameterConfiguration() { }
140    [StorableConstructor]
141    protected ParameterConfiguration(bool deserializing) { }
142    protected ParameterConfiguration(ParameterConfiguration original, Cloner cloner)
143      : base(original, cloner) {
144      this.parameterName = original.ParameterName;
145      this.parameterDataType = original.parameterDataType;
146      this.valueDataType = original.ValueDataType;
147      this.validTypes = original.validTypes.ToArray();
148      this.valueConfigurations = cloner.Clone(original.ValueConfigurations);
149      this.ActualValue = cloner.Clone(original.ActualValue);
150      this.optimize = original.optimize;
151      this.actualValueConfigurationIndex = original.actualValueConfigurationIndex;
152      this.isNullable = original.isNullable;
153      if (this.valueConfigurations != null) RegisterValueConfigurationEvents();
154    }
155    public override IDeepCloneable Clone(Cloner cloner) {
156      return new ParameterConfiguration(this, cloner);
157    }
158    [StorableHook(HookType.AfterDeserialization)]
159    private void AfterDeserialization() {
160      if (this.valueConfigurations != null) RegisterValueConfigurationEvents();
161    }
162    #endregion
163
164    private void RegisterValueConfigurationEvents() {
165      this.ValueConfigurations.CheckedItemsChanged += new Collections.CollectionItemsChangedEventHandler<IValueConfiguration>(ValueConfigurations_CheckedItemsChanged);
166      this.ValueConfigurations.ItemsAdded += new Collections.CollectionItemsChangedEventHandler<IValueConfiguration>(ValueConfigurations_ItemsAdded);
167      this.ValueConfigurations.ItemsRemoved += new Collections.CollectionItemsChangedEventHandler<IValueConfiguration>(ValueConfigurations_ItemsRemoved);
168    }
169
170    private void DeregisterValueConfigurationEvents() {
171      this.ValueConfigurations.CheckedItemsChanged -= new Collections.CollectionItemsChangedEventHandler<IValueConfiguration>(ValueConfigurations_CheckedItemsChanged);
172      this.ValueConfigurations.ItemsAdded -= new Collections.CollectionItemsChangedEventHandler<IValueConfiguration>(ValueConfigurations_ItemsAdded);
173      this.ValueConfigurations.ItemsRemoved -= new Collections.CollectionItemsChangedEventHandler<IValueConfiguration>(ValueConfigurations_ItemsRemoved);
174    }
175
176    private void RegisterActualValueEvents() {
177      if (this.ActualValue != null) this.ActualValue.ToStringChanged += new EventHandler(ActualValue_ToStringChanged);
178    }
179    private void DeregisterActualValueEvents() {
180      if (this.ActualValue != null) this.ActualValue.ToStringChanged -= new EventHandler(ActualValue_ToStringChanged);
181    }
182
183    private void PopulateValueConfigurations() {
184      foreach (Type t in this.validTypes) {
185        if (t == typeof(NullValue)) {
186          this.ValueConfigurations.Add(new NullValueConfiguration());
187        } else {
188          IItem val;
189          if (ActualValue.Value != null && ActualValue.ValueDataType == t) {
190            val = ActualValue.Value; // use existing value for that type (if available)
191          } else {
192            val = (IItem)Activator.CreateInstance(t);
193          }
194          this.ValueConfigurations.Add(new ValueConfiguration(val, val.GetType()), true);
195        }
196      }
197    }
198
199    private IEnumerable<Type> GetValidTypes(IValueParameter parameter) {
200      //if (IsSubclassOfRawGeneric(typeof(OptionalConstrainedValueParameter<>), parameter.GetType())) {
201      //  var x = (IEnumerable)parameter.GetType().GetProperty("ValidValues").GetValue(parameter, new object[] { });
202      //  return new ItemSet<IItem>(x.Cast<IItem>());
203      //} else {
204      //  return new ItemSet<IItem>(ApplicationManager.Manager.GetInstances(valueDataType).Select(x => (IItem)x).OrderBy(x => x.ItemName));
205      //}
206      return ApplicationManager.Manager.GetTypes(valueDataType, true);
207    }
208
209    private static bool IsSubclassOfRawGeneric(Type generic, Type toCheck) {
210      while (toCheck != typeof(object)) {
211        var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
212        if (generic == cur) {
213          return true;
214        }
215        toCheck = toCheck.BaseType;
216      }
217      return false;
218    }
219
220    void ValueConfigurations_CheckedItemsChanged(object sender, Collections.CollectionItemsChangedEventArgs<IValueConfiguration> e) {
221      OnToStringChanged();
222    }
223    void ValueConfigurations_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<IValueConfiguration> e) {
224      OnToStringChanged();
225    }
226    void ValueConfigurations_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<IValueConfiguration> e) {
227      OnToStringChanged();
228    }
229
230    #region INamedItem Properties
231    public virtual string Name {
232      get { return ParameterName; }
233      set { throw new NotSupportedException(); }
234    }
235    public virtual string Description {
236      get { return base.ItemDescription; }
237      set { throw new NotSupportedException(); }
238    }
239    public virtual bool CanChangeDescription {
240      get { return false; }
241    }
242    public virtual bool CanChangeName {
243      get { return false; }
244    }
245    public override string ItemDescription {
246      //get { return parameter != null ? parameter.Description : base.ItemDescription; }
247      get { return base.ItemDescription; }
248    }
249    public override System.Drawing.Image ItemImage {
250      //get { return parameter != null ? parameter.ItemImage : base.ItemImage; }
251      get { return base.ItemImage; }
252    }
253    public override string ItemName {
254      //get { return parameter != null ?parameter.ItemName : base.ItemName; }
255      get { return base.ItemName; }
256    }
257    #endregion
258
259    #region Events
260    void ActualValue_ToStringChanged(object sender, EventArgs e) {
261      OnToStringChanged();
262    }
263    #endregion
264
265    #region Event Handler
266    public virtual event EventHandler NameChanged;
267    protected virtual void OnNameChanged(object sender, EventArgs e) {
268      var handler = NameChanged;
269      if (handler != null) handler(sender, e);
270    }
271
272    public virtual event EventHandler<CancelEventArgs<string>> NameChanging;
273    protected virtual void OnNameChanging(object sender, CancelEventArgs<string> e) {
274      var handler = NameChanging;
275      if (handler != null) handler(sender, e);
276    }
277
278    public virtual event EventHandler DescriptionChanged;
279    protected virtual void OnDescriptionChanged(object sender, EventArgs e) {
280      var handler = DescriptionChanged;
281      if (handler != null) handler(sender, e);
282    }
283
284    public virtual event EventHandler IsOptimizableChanged;
285    private void OnIsOptimizableChanged() {
286      var handler = IsOptimizableChanged;
287      if (handler != null) handler(this, EventArgs.Empty);
288    }
289
290    public virtual event EventHandler OptimizeChanged;
291    protected virtual void OnOptimizeChanged() {
292      var handler = OptimizeChanged;
293      if (handler != null) handler(this, EventArgs.Empty);
294    }
295    #endregion
296
297    public override string ToString() {
298      if (Optimize) {
299        return string.Format("{0}: (Optimize: {1})", ParameterName, ValueConfigurations.CheckedItems.Count());
300      } else {
301        return string.Format("{0}: {1}", ParameterName, ActualValue.Value);
302      }
303    }
304
305    public string ParameterInfoString {
306      get {
307        StringBuilder sb = new StringBuilder();
308        if (this.Optimize) {
309          sb.Append(string.Format("{0}: {1}", parameterName, this.ActualValue.Value != null ? this.ActualValue.Value.ToString() : "null"));
310
311          if (this.ActualValue.Value is IParameterizedItem) {
312            string subParams = this.ValueConfigurations.CheckedItems.ElementAt(actualValueConfigurationIndex).ParameterInfoString;
313            if (!string.IsNullOrEmpty(subParams)) {
314              sb.Append(" (");
315              sb.Append(subParams);
316              sb.Append(")");
317            }
318          }
319        }
320        return sb.ToString();
321      }
322    }
323
324    public static IParameterConfiguration Create(IParameterizedNamedItem parent, IParameter parameter) {
325      if (parameter is IValueParameter) {
326        IValueParameter valueParameter = parameter as IValueParameter;
327        return new ParameterConfiguration(parameter.Name, valueParameter);
328      }
329      return null;
330    }
331
332    public void Parameterize(IValueParameter parameter) {
333      if (Optimize) {
334        if (this.ActualValue.Value is IParameterizedItem) {
335          this.ValueConfigurations.CheckedItems.ElementAt(actualValueConfigurationIndex).Parameterize((IParameterizedItem)this.ActualValue.Value);
336        }
337      }
338      var clonedValue = this.ActualValue.Value != null ? (IItem)this.ActualValue.Value.Clone() : null;
339      AdaptValidValues(parameter, clonedValue);
340      parameter.Value = clonedValue;
341    }
342
343    /// <summary>
344    /// Adds value to the ValidValues of the parameter if they don't contain the value
345    /// </summary>
346    private void AdaptValidValues(IValueParameter parameter, IItem value) {
347      // this requires some tricky reflection, because the type is unknown at runtime so parameter.ValidValues cannot be casted to Collection<?>
348      if (IsSubclassOfRawGeneric(typeof(OptionalConstrainedValueParameter<>), parameter.GetType())) {
349        var validValues = parameter.GetType().GetProperty("ValidValues").GetValue(parameter, new object[] { });
350        Type validValuesType = validValues.GetType();
351
352        var containsMethod = validValuesType.GetMethod("Contains");
353        if (!(bool)containsMethod.Invoke(validValues, new object[] { value })) {
354          var addMethod = validValuesType.GetMethod("Add");
355          addMethod.Invoke(validValues, new object[] { value });
356        }
357      }
358    }
359
360    public void Randomize(IRandom random) {
361      if (Optimize) {
362        foreach (var vc in this.ValueConfigurations.CheckedItems) {
363          vc.Randomize(random);
364        }
365        actualValueConfigurationIndex = random.Next(ValueConfigurations.CheckedItems.Count());
366        this.ActualValue = this.ValueConfigurations.CheckedItems.ElementAt(actualValueConfigurationIndex).ActualValue;
367      }
368    }
369
370    public void Mutate(IRandom random, MutateDelegate mutate, ParameterConfigurationManipulator pcmanip) {
371      if (Optimize) {
372        foreach (IValueConfiguration vc in this.ValueConfigurations.CheckedItems) {
373          vc.Mutate(random, mutate, pcmanip);
374        }
375        mutate(random, this, pcmanip);
376      }
377    }
378
379    public void Cross(IRandom random, IOptimizable other, CrossDelegate cross, ParameterConfigurationCrossover pccross) {
380      if (Optimize) {
381        IParameterConfiguration otherPc = (IParameterConfiguration)other;
382        for (int i = 0; i < this.ValueConfigurations.Count; i++) {
383          cross(random, other, pccross);
384          //this.ValueConfigurations.ElementAt(i).Cross(otherPc.ValueConfigurations.ElementAt(i), random);
385        }
386        //if (random.NextDouble() > 0.5) {
387        //  actualValueConfigurationIndex = ((ParameterConfiguration)other).actualValueConfigurationIndex;
388        //}
389        //this.ActualValue = this.ValueConfigurations.CheckedItems.ElementAt(actualValueConfigurationIndex).ActualValue;
390      }
391    }
392
393    public void UpdateActualValueIndexToItem(IValueConfiguration vc) {
394      for (int i = 0; i < this.ValueConfigurations.CheckedItems.Count(); i++) {
395        if (this.ValueConfigurations.CheckedItems.ElementAt(i) == vc) {
396          this.actualValueConfigurationIndex = i;
397          return;
398        }
399      }
400    }
401
402  }
403}
Note: See TracBrowser for help on using the repository browser.