Free cookie consent management tool by TermsFeed Policy Generator

source: branches/ParameterConfigurationEncoding/HeuristicLab.Encodings.ParameterConfigurationEncoding/3.3/ParameterConfigurations/ParameterConfiguration.cs @ 14815

Last change on this file since 14815 was 8590, checked in by jkarder, 12 years ago

#1853:

  • added MultiDoubleValueCrossover
  • fixed bug in AverageDoubleValueCrossover
  • minor code improvements
File size: 27.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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;
24using System.Collections.Generic;
25using System.Drawing;
26using System.Linq;
27using System.Text;
28using HeuristicLab.Collections;
29using HeuristicLab.Common;
30using HeuristicLab.Core;
31using HeuristicLab.Data;
32using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
33using HeuristicLab.Parameters;
34using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
35using HeuristicLab.PluginInfrastructure;
36
37namespace HeuristicLab.Encodings.ParameterConfigurationEncoding {
38  [StorableClass]
39  public class ParameterConfiguration : Item, IParameterConfiguration, IStorableContent {
40    public bool IsOptimizable {
41      get { return true; }
42    }
43
44    public string Filename { get; set; }
45
46    [Storable]
47    protected bool optimize;
48    public virtual bool Optimize {
49      get { return optimize; }
50      set {
51        if (optimize != value) {
52          optimize = value;
53          if (optimize) {
54            PopulateValueConfigurations();
55          } else {
56            ClearValueConfigurations();
57          }
58          OnOptimizeChanged();
59          OnCombinationsCountChanged();
60          OnToStringChanged();
61        }
62      }
63    }
64
65    [Storable]
66    protected long combinationsCount;
67    public virtual long CombinationsCount {
68      get { return combinationsCount; }
69      set {
70        if (combinationsCount != value) {
71          combinationsCount = value;
72          OnCombinationsCountChanged();
73        }
74      }
75    }
76
77    [Storable]
78    protected Image itemImage;
79    public override Image ItemImage {
80      get { return itemImage ?? base.ItemImage; }
81    }
82
83    [Storable]
84    protected string parameterName;
85    public string ParameterName {
86      get { return parameterName; }
87      set {
88        if (parameterName != value) {
89          parameterName = value;
90          OnToStringChanged();
91        }
92      }
93    }
94
95    [Storable]
96    protected Type parameterDataType;
97    public Type ParameterDataType {
98      get { return parameterDataType; }
99    }
100
101    protected Type[] validTypes;
102    public Type[] ValidTypes {
103      get { return validTypes; }
104      protected set {
105        if (validTypes != value) {
106          validTypes = value;
107        }
108      }
109    }
110
111    [Storable]
112    protected Type valueDataType;
113    public Type ValueDataType {
114      get { return valueDataType; }
115      protected set { valueDataType = value; }
116    }
117
118    [Storable]
119    protected ICheckedValueConfigurationList valueConfigurations;
120    public ICheckedValueConfigurationList ValueConfigurations {
121      get { return valueConfigurations; }
122      protected set {
123        if (valueConfigurations != value) {
124          if (valueConfigurations != null) DeregisterValueConfigurationEvents();
125          valueConfigurations = value;
126          KeepActualValueConfigurationIndexConsistent();
127          if (valueConfigurations != null) RegisterValueConfigurationEvents();
128        }
129      }
130    }
131
132    [Storable]
133    private int actualValueConfigurationIndex;
134    public int ActualValueConfigurationIndex {
135      get { return actualValueConfigurationIndex; }
136      set { actualValueConfigurationIndex = value; }
137    }
138
139    [Storable]
140    protected ConstrainedValue actualValue;
141    public ConstrainedValue ActualValue {
142      get { return actualValue; }
143      set {
144        if (actualValue != value) {
145          DeregisterActualValueEvents();
146          actualValue = value;
147          RegisterActualValueEvents();
148        }
149      }
150    }
151
152    [Storable]
153    protected bool isNullable;
154    public bool IsNullable {
155      get { return isNullable; }
156      protected set {
157        if (isNullable != value) {
158          isNullable = value;
159        }
160      }
161    }
162
163    [Storable]
164    protected bool discoverValidValues;
165    public bool DiscoverValidValues {
166      get { return discoverValidValues; }
167      set { discoverValidValues = value; }
168    }
169
170    protected IItemSet<IItem> validValues;
171
172    [Storable]
173    private bool autoPopulateValueConfigurations = true;
174    public bool AutoPopulateValueConfigurations {
175      get { return autoPopulateValueConfigurations; }
176      set { autoPopulateValueConfigurations = value; }
177    }
178
179    [Storable]
180    protected bool valuesReadOnly = false;
181    public virtual bool ValuesReadOnly {
182      get { return valuesReadOnly; }
183      set {
184        if (valuesReadOnly != value) {
185          valuesReadOnly = value;
186          foreach (var vc in valueConfigurations) {
187            vc.ValuesReadOnly = value;
188          }
189        }
190      }
191    }
192
193    #region Constructors and Cloning
194    public ParameterConfiguration(string parameterName, IValueParameter valueParameter, bool discoverValidValues)
195      : base() {
196      this.AutoPopulateValueConfigurations = true;
197      this.ParameterName = parameterName;
198      this.parameterDataType = valueParameter.GetType();
199      this.valueDataType = valueParameter.DataType;
200      this.discoverValidValues = discoverValidValues;
201      this.validValues = discoverValidValues ? GetValidValues(valueParameter) : new ItemSet<IItem> { valueParameter.Value };
202      this.validTypes = GetValidTypes(valueParameter).ToArray();
203      this.IsNullable = valueParameter.ItemName.StartsWith("Optional");
204      this.itemImage = valueParameter.ItemImage;
205      if (IsNullable) {
206        validTypes = new List<Type>(validTypes) { typeof(NullValue) }.ToArray();
207      }
208      this.ValueConfigurations = new CheckedValueConfigurationList(this.validValues ?? CreateValidValues());
209      this.ActualValue = new ConstrainedValue(
210        valueParameter.Value != null ? valueParameter.Value : null, // don't clone here; otherwise settings of a non-optimized ValueParameter will not be synchronized with the ConstrainedValue
211        valueParameter.DataType,
212        this.validValues != null ? new ItemSet<IItem>(this.validValues) : CreateValidValues(),
213        this.IsNullable);
214      if (Optimize) {
215        PopulateValueConfigurations();
216      }
217    }
218    public ParameterConfiguration(string parameterName, Type type, IItem actualValue, IEnumerable<IValueConfiguration> valueConfigurations)
219      : base() {
220      this.AutoPopulateValueConfigurations = false;
221      this.ParameterName = parameterName;
222      this.parameterDataType = type;
223      this.valueDataType = type;
224      this.discoverValidValues = false;
225      this.validValues = null; // maybe use values from valueConfigurations
226      this.validTypes = new Type[] { type };
227      this.IsNullable = false;
228      this.itemImage = valueConfigurations.Any() ? valueConfigurations.First().ItemImage : null;
229      this.ValueConfigurations = new CheckedValueConfigurationList(valueConfigurations);
230      this.ActualValue = new ConstrainedValue(actualValue, type, CreateValidValues(), this.IsNullable);
231    }
232    public ParameterConfiguration(string parameterName, Type type, IItem actualValue)
233      : base() {
234      this.AutoPopulateValueConfigurations = true;
235      this.ParameterName = parameterName;
236      this.parameterDataType = type;
237      this.valueDataType = type;
238      this.discoverValidValues = false;
239      this.validValues = null;
240      this.validTypes = new Type[] { type };
241      this.IsNullable = false;
242      this.itemImage = actualValue.ItemImage;
243      this.ValueConfigurations = new CheckedValueConfigurationList();
244      this.ActualValue = new ConstrainedValue(actualValue, type, CreateValidValues(), this.IsNullable);
245      if (Optimize) {
246        PopulateValueConfigurations();
247      }
248    }
249    protected ParameterConfiguration() : base() { }
250    [StorableConstructor]
251    protected ParameterConfiguration(bool deserializing) { }
252    protected ParameterConfiguration(ParameterConfiguration original, Cloner cloner)
253      : base(original, cloner) {
254      this.parameterName = original.ParameterName;
255      this.parameterDataType = original.parameterDataType;
256      this.valueDataType = original.ValueDataType;
257      this.validValues = cloner.Clone(original.validValues);
258      this.validTypes = original.validTypes.ToArray();
259      this.valueConfigurations = cloner.Clone(original.ValueConfigurations);
260      if (this.valueConfigurations != null) RegisterValueConfigurationEvents();
261      this.actualValue = cloner.Clone(original.actualValue);
262      if (this.actualValue != null) RegisterActualValueEvents();
263      this.optimize = original.optimize;
264      this.actualValueConfigurationIndex = original.actualValueConfigurationIndex;
265      this.isNullable = original.isNullable;
266      this.itemImage = original.itemImage;
267      this.discoverValidValues = original.discoverValidValues;
268      this.AutoPopulateValueConfigurations = original.AutoPopulateValueConfigurations;
269      this.valuesReadOnly = original.valuesReadOnly;
270    }
271
272    public override IDeepCloneable Clone(Cloner cloner) {
273      return new ParameterConfiguration(this, cloner);
274    }
275    [StorableHook(HookType.AfterDeserialization)]
276    protected virtual void AfterDeserialization() {
277      this.validTypes = GetValidTypes(parameterDataType).ToArray();
278
279      if (IsNullable) {
280        validTypes = new List<Type>(validTypes) { typeof(NullValue) }.ToArray();
281      }
282      this.validValues = CreateValidValues();
283
284      if (this.valueConfigurations != null) RegisterValueConfigurationEvents();
285      if (this.actualValue != null) RegisterActualValueEvents();
286    }
287    #endregion
288
289    private void RegisterValueConfigurationEvents() {
290      this.ValueConfigurations.CheckedItemsChanged += new CollectionItemsChangedEventHandler<IndexedItem<IValueConfiguration>>(ValueConfigurations_CheckedItemsChanged);
291      this.ValueConfigurations.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<IValueConfiguration>>(ValueConfigurations_ItemsAdded);
292      this.ValueConfigurations.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<IValueConfiguration>>(ValueConfigurations_ItemsRemoved);
293    }
294
295    private void DeregisterValueConfigurationEvents() {
296      this.ValueConfigurations.CheckedItemsChanged -= new CollectionItemsChangedEventHandler<IndexedItem<IValueConfiguration>>(ValueConfigurations_CheckedItemsChanged);
297      this.ValueConfigurations.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<IValueConfiguration>>(ValueConfigurations_ItemsAdded);
298      this.ValueConfigurations.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<IValueConfiguration>>(ValueConfigurations_ItemsRemoved);
299    }
300
301    private void RegisterActualValueEvents() {
302      if (this.ActualValue != null) this.ActualValue.ToStringChanged += new EventHandler(ActualValue_ToStringChanged);
303    }
304    private void DeregisterActualValueEvents() {
305      if (this.ActualValue != null) this.ActualValue.ToStringChanged -= new EventHandler(ActualValue_ToStringChanged);
306    }
307
308    protected virtual void PopulateValueConfigurations() {
309      if (!this.AutoPopulateValueConfigurations)
310        return;
311
312      foreach (Type t in this.validTypes) {
313        if (t == typeof(NullValue)) {
314          this.ValueConfigurations.Add(new NullValueConfiguration());
315        } else {
316          IItem val;
317          if (ActualValue.Value != null && ActualValue.Value.GetType() == t) {
318            val = (IItem)ActualValue.Value.Clone(); // use existing value for that type (if available)
319          } else {
320            val = CreateItem(t);
321          }
322          if (val != null) { // val can be null when ValidValues does not contain the type (this can happen when discoverValidValues=false)
323            IValueConfiguration valueConfiguration;
324            if (val is IParameterizedItem) {
325              valueConfiguration = new ParameterizedValueConfiguration(val, val.GetType(), true);
326            } else {
327              if (val is ISymbolicExpressionGrammar) {
328                valueConfiguration = new SymbolicExpressionGrammarValueConfiguration((ISymbolicExpressionGrammar)val);
329              } else {
330                valueConfiguration = new RangeValueConfiguration(val, val.GetType());
331              }
332            }
333            valueConfiguration.CombinationsCountChanged += (sender, args) => OnCombinationsCountChanged();
334            this.ValueConfigurations.Add(valueConfiguration, true);
335          }
336        }
337      }
338    }
339
340    protected virtual void ClearValueConfigurations() {
341      if (!this.AutoPopulateValueConfigurations)
342        return;
343
344      this.ValueConfigurations.Clear();
345    }
346
347    private static IEnumerable<Type> GetValidTypes(IValueParameter parameter) {
348      // in case of IOperator return empty list, otherwise hundreds of types would be returned. this mostly occurs for Successor which will never be optimized
349      if (parameter.DataType == typeof(IOperator))
350        return new List<Type>();
351
352      // return only one type for ValueTypeValues<> (Int, Double, Percent, Bool). Otherwise 2 types would be returned for DoubleValue (PercentValue which is derived)
353      if (IsSubclassOfRawGeneric(typeof(ValueTypeValue<>), parameter.DataType))
354        return new List<Type> { parameter.DataType };
355
356      if (IsSubclassOfRawGeneric(typeof(OptionalConstrainedValueParameter<>), parameter.GetType())) {
357        // use existing validvalues if known
358        var parameterValidValues = (IEnumerable)parameter.GetType().GetProperty("ValidValues").GetValue(parameter, new object[] { });
359        return parameterValidValues.Cast<object>().Select(x => x.GetType());
360      } else {
361        // otherwise use all assignable types
362        return ApplicationManager.Manager.GetTypes(parameter.DataType, true);
363      }
364    }
365
366    private static IEnumerable<Type> GetValidTypes(Type parameter) {
367      // in case of IOperator return empty list, otherwise hundreds of types would be returned. this mostly occurs for Successor which will never be optimized
368      if (parameter == typeof(IOperator))
369        return new List<Type>();
370
371      // return only one type for ValueTypeValues<> (Int, Double, Percent, Bool). Otherwise 2 types would be returned for DoubleValue (PercentValue which is derived)
372      if (IsSubclassOfRawGeneric(typeof(ValueTypeValue<>), parameter))
373        return new List<Type> { parameter };
374
375      // TODO: check if this makes sense; maybe only leave else branch here
376      if (IsSubclassOfRawGeneric(typeof(OptionalConstrainedValueParameter<>), parameter.GetType())) {
377        // use existing validvalues if known
378        var parameterValidValues = (IEnumerable)parameter.GetType().GetProperty("ValidValues").GetValue(parameter, new object[] { });
379        return parameterValidValues.Cast<object>().Select(x => x.GetType());
380      } else {
381        // otherwise use all assignable types
382        return ApplicationManager.Manager.GetTypes(parameter, true);
383      }
384    }
385
386    private IItemSet<IItem> GetValidValues(IValueParameter parameter) {
387      if (IsSubclassOfRawGeneric(typeof(OptionalConstrainedValueParameter<>), parameter.GetType())) {
388        var x = (IEnumerable)parameter.GetType().GetProperty("ValidValues").GetValue(parameter, new object[] { });
389        return new ItemSet<IItem>(x.Cast<IItem>().Select(y => (IItem)y.Clone())); // cloning actually saves memory, because references to event-subscribers are removed
390      } else {
391        return null;
392      }
393    }
394
395    public IItem CreateItem(Type type) {
396      // no valid values; just instantiate
397      try {
398        if (validValues == null)
399          return (IItem)Activator.CreateInstance(type);
400      }
401      catch (MissingMemberException) {
402        return null; // can happen, when ApplicationManager.Manager.GetTypes(type, OnlyInstantiable=true) returns objects which have no default constructor
403      }
404
405      if (type == typeof(NullValue))
406        return new NullValue();
407
408      // copy value from ValidValues; this ensures that previously set ActualNames for a type are kept
409      IItem value = this.validValues.SingleOrDefault(v => v.GetType() == type);
410      if (value != null)
411        return value;
412
413      return null;
414    }
415
416    private IItemSet<IItem> CreateValidValues() {
417      var validValues = new ItemSet<IItem>();
418      foreach (Type t in this.validTypes) {
419        try {
420          var val = CreateItem(t);
421          if (val != null) validValues.Add(val);
422        }
423        catch (MissingMethodException) { /* Constructor is missing, don't use those types */ }
424      }
425      return validValues;
426    }
427
428    public static bool IsSubclassOfRawGeneric(Type generic, Type toCheck) {
429      while (toCheck != typeof(object)) {
430        var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
431        if (generic == cur) {
432          return true;
433        }
434        toCheck = toCheck.BaseType; // baseType is null when toCheck is an Interface
435        if (toCheck == null)
436          return false;
437      }
438      return false;
439    }
440
441    private void ValueConfigurations_CheckedItemsChanged(object sender, Collections.CollectionItemsChangedEventArgs<IndexedItem<IValueConfiguration>> e) {
442      OnToStringChanged();
443      OnCombinationsCountChanged();
444      KeepActualValueConfigurationIndexConsistent();
445    }
446
447    private void ValueConfigurations_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<IndexedItem<IValueConfiguration>> e) {
448      OnToStringChanged();
449      OnCombinationsCountChanged();
450      KeepActualValueConfigurationIndexConsistent();
451    }
452    private void ValueConfigurations_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<IndexedItem<IValueConfiguration>> e) {
453      OnToStringChanged();
454      OnCombinationsCountChanged();
455      KeepActualValueConfigurationIndexConsistent();
456    }
457
458    #region INamedItem Properties
459    public virtual string Name {
460      get { return ParameterName; }
461      set { throw new NotSupportedException(); }
462    }
463    public virtual string Description {
464      get { return base.ItemDescription; }
465      set { throw new NotSupportedException(); }
466    }
467    public virtual bool CanChangeDescription {
468      get { return false; }
469    }
470    public virtual bool CanChangeName {
471      get { return false; }
472    }
473    #endregion
474
475    #region Events
476    protected virtual void ActualValue_ToStringChanged(object sender, EventArgs e) {
477      OnToStringChanged();
478    }
479    #endregion
480
481    #region Event Handler
482    public virtual event EventHandler NameChanged;
483    protected virtual void OnNameChanged(object sender, EventArgs e) {
484      var handler = NameChanged;
485      if (handler != null) handler(sender, e);
486    }
487
488    public virtual event EventHandler<CancelEventArgs<string>> NameChanging;
489    protected virtual void OnNameChanging(object sender, CancelEventArgs<string> e) {
490      var handler = NameChanging;
491      if (handler != null) handler(sender, e);
492    }
493
494    public virtual event EventHandler DescriptionChanged;
495    protected virtual void OnDescriptionChanged(object sender, EventArgs e) {
496      var handler = DescriptionChanged;
497      if (handler != null) handler(sender, e);
498    }
499
500    public virtual event EventHandler IsOptimizableChanged;
501    private void OnIsOptimizableChanged() {
502      var handler = IsOptimizableChanged;
503      if (handler != null) handler(this, EventArgs.Empty);
504    }
505
506    public virtual event EventHandler OptimizeChanged;
507    protected virtual void OnOptimizeChanged() {
508      var handler = OptimizeChanged;
509      if (handler != null) handler(this, EventArgs.Empty);
510    }
511
512    public event EventHandler CombinationsCountChanged;
513    protected void OnCombinationsCountChanged() {
514      var handler = CombinationsCountChanged;
515      if (handler != null) handler(this, EventArgs.Empty);
516    }
517    #endregion
518
519    public override string ToString() {
520      if (Optimize) {
521        return string.Format("{0}: (Optimize: {1})", ParameterName, ValueConfigurations.CheckedItems.Count());
522      } else {
523        return string.Format("{0}: {1}", ParameterName, ActualValue.Value);
524      }
525    }
526
527    public virtual string ParameterInfoString {
528      get {
529        StringBuilder sb = new StringBuilder();
530        if (this.Optimize) {
531          var vc = this.ValueConfigurations[actualValueConfigurationIndex];
532          if (vc.ActualValue == null || vc.ActualValue.Value == null) {
533            sb.Append(string.Format("{0}: null", parameterName));
534          } else if (IsSubclassOfRawGeneric(typeof(ValueTypeValue<>), vc.ActualValue.Value.GetType())) {
535            // for int, double, bool use the value directly
536            sb.Append(string.Format("{0}: {1}", parameterName, this.ActualValue.Value.ToString()));
537          } else {
538            // for other types use NumberedName (this also uses the Number-Property for otherwise ambiguous ValueConfigurations)
539            sb.Append(string.Format("{0}: {1}", parameterName, vc.NumberedName));
540          }
541
542          if (this.ValueConfigurations[actualValueConfigurationIndex] is ParameterizedValueConfiguration) {
543            string subParams = this.ValueConfigurations[actualValueConfigurationIndex].ParameterInfoString;
544            if (!string.IsNullOrEmpty(subParams)) {
545              sb.Append(" (");
546              sb.Append(subParams);
547              sb.Append(")");
548            }
549          }
550        }
551        return sb.ToString();
552      }
553    }
554
555    public static IParameterConfiguration Create(IParameterizedNamedItem parent, IParameter parameter, bool discoverValidValues) {
556      if (parameter is IValueParameter) {
557        IValueParameter valueParameter = parameter as IValueParameter;
558        return new ParameterConfiguration(parameter.Name, valueParameter, discoverValidValues);
559      }
560      return null;
561    }
562
563    public void Parameterize(IValueParameter parameter) {
564      if (!Optimize && ValuesReadOnly)
565        return;
566
567      if (Optimize) {
568        if (this.ActualValue.Value is IParameterizedItem) {
569          ((ParameterizedValueConfiguration)this.ValueConfigurations[actualValueConfigurationIndex]).Parameterize((IParameterizedItem)this.ActualValue.Value);
570        }
571        if (this.ActualValue.Value is ISymbolicExpressionGrammar) {
572          ((SymbolicExpressionGrammarValueConfiguration)this.ValueConfigurations[actualValueConfigurationIndex]).Parameterize((ISymbolicExpressionGrammar)this.ActualValue.Value);
573        }
574      }
575
576      var clonedValue = this.ActualValue.Value != null ? (IItem)this.ActualValue.Value.Clone() : null;
577      if (clonedValue != null) AdaptValidValues(parameter, clonedValue);
578
579      if (!(parameter is IFixedValueParameter)) {
580        parameter.Value = clonedValue;
581      } else {
582        var original = (dynamic)parameter.Value;
583        var clone = (dynamic)clonedValue;
584        if (typeof(ValueTypeValue<>).IsAssignableFrom(parameter.DataType) && !original.ReadOnly) {
585          original.Value = clone.Value;
586        } else if (typeof(ValueTypeArray<>).IsAssignableFrom(parameter.DataType) && !original.ReadOnly) {
587          for (int i = 0; i < original.Length; i++)
588            original[i] = clone[i];
589        } else if (typeof(ValueTypeMatrix<>).IsAssignableFrom(parameter.DataType) && !original.ReadOnly) {
590          for (int i = 0; i < original.Rows; i++)
591            for (int j = 0; j < original.Columns; j++)
592              original[i, j] = clone[i, j];
593        } // StringConvertibleValueTuple<,> not supported
594      }
595    }
596
597    /// <summary>
598    /// Adds value to the ValidValues of the parameter if they don't contain the value
599    /// </summary>
600    private void AdaptValidValues(IValueParameter parameter, IItem value) {
601      // this requires some tricky reflection, because the type is unknown at runtime so parameter.ValidValues cannot be casted to Collection<?>
602      if (IsSubclassOfRawGeneric(typeof(OptionalConstrainedValueParameter<>), parameter.GetType())) {
603        var validValues = parameter.GetType().GetProperty("ValidValues").GetValue(parameter, new object[] { });
604        Type validValuesType = validValues.GetType();
605
606        var containsMethod = validValuesType.GetMethod("Contains");
607        if (!(bool)containsMethod.Invoke(validValues, new object[] { value })) {
608          var addMethod = validValuesType.GetMethod("Add");
609          addMethod.Invoke(validValues, new object[] { value });
610        }
611      }
612    }
613
614    public void Randomize(IRandom random) {
615      if (Optimize) {
616        foreach (var vc in this.ValueConfigurations) {
617          if (this.ValueConfigurations.ItemChecked(vc)) {
618            if (vc.Optimize) vc.Randomize(random);
619          }
620        }
621        do {
622          actualValueConfigurationIndex = random.Next(ValueConfigurations.Count());
623        } while (!this.ValueConfigurations.ItemChecked(this.ValueConfigurations[actualValueConfigurationIndex]));
624        this.ActualValue = this.ValueConfigurations[actualValueConfigurationIndex].ActualValue;
625      }
626    }
627
628    public void UpdateActualValueIndexToItem(IValueConfiguration vc) {
629      for (int i = 0; i < this.ValueConfigurations.Count(); i++) {
630        if (this.ValueConfigurations.ElementAt(i) == vc) {
631          this.actualValueConfigurationIndex = i;
632          return;
633        }
634      }
635    }
636
637    public List<IOptimizable> GetAllOptimizables() {
638      var list = new List<IOptimizable>();
639      foreach (var vc in ValueConfigurations) {
640        if (vc.Optimize) {
641          list.Add(vc);
642          list.AddRange(vc.GetAllOptimizables());
643        }
644      }
645      return list;
646    }
647
648    public void CollectOptimizedParameterNames(List<string> parameterNames, string prefix) {
649      foreach (var vc in ValueConfigurations) {
650        if (vc.Optimize) {
651          vc.CollectOptimizedParameterNames(parameterNames, prefix);
652        }
653      }
654    }
655
656    public double CalculateSimilarity(IOptimizable optimizable) {
657      var other = (IParameterConfiguration)optimizable;
658      if (this.ActualValueConfigurationIndex == other.ActualValueConfigurationIndex) {
659        return this.ValueConfigurations[this.ActualValueConfigurationIndex].CalculateSimilarity(other.ValueConfigurations[other.ActualValueConfigurationIndex]);
660      } else {
661        return 0.0;
662      }
663    }
664
665    /// <summary>
666    /// Ensures that the ActualValueConfigurationIndex has a valid value
667    /// Only indices of items which are checked are allowed
668    /// </summary>
669    private void KeepActualValueConfigurationIndexConsistent() {
670      if (this.valueConfigurations != null && this.valueConfigurations.CheckedItems.Count() > 0) {
671        if (this.valueConfigurations.Count <= this.actualValueConfigurationIndex &&
672           this.valueConfigurations.CheckedItems.Count(x => x.Index == this.actualValueConfigurationIndex) == 1) {
673          // everything is ok; do nothing
674        } else {
675          // current index is invalid, set new one
676          this.ActualValueConfigurationIndex = this.valueConfigurations.CheckedItems.First().Index;
677        }
678      } else {
679        // no checked valueConfiguration is available; cannot be used
680        this.ActualValueConfigurationIndex = -1;
681      }
682    }
683  }
684}
Note: See TracBrowser for help on using the repository browser.