Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1215

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