Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/Crossovers/ParameterConfigurationCrossover.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/Crossovers/ParameterConfigurationCrossover.cs	(revision 5113)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/Crossovers/ParameterConfigurationCrossover.cs	(revision 5113)
@@ -0,0 +1,97 @@
+﻿using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Encodings.RealVectorEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.MetaOptimization {
+  /// <summary>
+  /// 
+  /// </summary>
+  [Item("ParameterConfigurationCrossover", "TODO")]
+  [StorableClass]
+  public class ParameterConfigurationCrossover : SingleSuccessorOperator, IParameterConfigurationOperator, ICrossover {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public ILookupParameter<ItemArray<IValueConfiguration>> ParentsParameter {
+      get { return (ScopeTreeLookupParameter<IValueConfiguration>)Parameters["Parents"]; }
+    }
+    public ILookupParameter<IValueConfiguration> ChildParameter {
+      get { return (ILookupParameter<IValueConfiguration>)Parameters["Child"]; }
+    }
+
+    public IValueLookupParameter<IIntValueCrossover> IntValueCrossoverParameter {
+      get { return (IValueLookupParameter<IIntValueCrossover>)Parameters[MetaOptimizationProblem.IntValueCrossoverParameterName]; }
+    }
+    public IValueLookupParameter<IDoubleValueCrossover> DoubleValueCrossoverParameter {
+      get { return (IValueLookupParameter<IDoubleValueCrossover>)Parameters[MetaOptimizationProblem.DoubleValueCrossoverParameterName]; }
+    }
+
+    [StorableConstructor]
+    protected ParameterConfigurationCrossover(bool deserializing) : base(deserializing) { }
+    protected ParameterConfigurationCrossover(ParameterConfigurationCrossover original, Cloner cloner) : base(original, cloner) { }
+    public ParameterConfigurationCrossover()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic crossover operators."));
+      Parameters.Add(new ScopeTreeLookupParameter<IValueConfiguration>("Parents", "The parent vectors which should be crossed."));
+      ParentsParameter.ActualName = "ParameterConfigurationTree";
+      Parameters.Add(new LookupParameter<IValueConfiguration>("Child", "The child vector resulting from the crossover."));
+      ChildParameter.ActualName = "ParameterConfigurationTree";
+
+      Parameters.Add(new ValueLookupParameter<IIntValueCrossover>(MetaOptimizationProblem.IntValueCrossoverParameterName, ""));
+      Parameters.Add(new ValueLookupParameter<IDoubleValueCrossover>(MetaOptimizationProblem.DoubleValueCrossoverParameterName, ""));
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ParameterConfigurationCrossover(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      IValueConfiguration child1 = (IValueConfiguration)ParentsParameter.ActualValue[0].Clone();
+      IValueConfiguration child2 = (IValueConfiguration)ParentsParameter.ActualValue[1];
+
+      //child1.Cross(child2, RandomParameter.ActualValue);
+      //this.ChildParameter.ActualValue = child1;
+
+      child1.Cross(RandomParameter.ActualValue, child2, Cross, this);
+      this.ChildParameter.ActualValue = child1;
+
+      return base.Apply();
+    }
+
+    private static void Cross(IRandom random, IOptimizable configuartion, ParameterConfigurationCrossover pccross) {
+      if (configuartion is IValueConfiguration) {
+        var vc = configuartion as IValueConfiguration;
+        var value = vc.ActualValue.Value;
+        var range = vc.RangeConstraint;
+
+        if (value is IntValue) {
+          pccross.IntValueCrossoverParameter.ActualValue.Apply(random, (IntValue)value, (IntValueRange)range);
+        } else if (value is PercentValue) {
+          pccross.DoubleValueCrossoverParameter.ActualValue.Apply(random, (PercentValue)value, ((PercentValueRange)range).AsDoubleValueRange());
+        } else if (value is DoubleValue) {
+          pccross.DoubleValueCrossoverParameter.ActualValue.Apply(random, (DoubleValue)value, (DoubleValueRange)range);
+        }
+      } else if (configuartion is IParameterConfiguration) {
+
+      }
+    }
+
+    private IntValue CrossInteger(IParameterConfiguration parameter1, IParameterConfiguration parameter2) {
+      IntegerVector integerChild = HeuristicLab.Encodings.IntegerVectorEncoding.DiscreteCrossover.Apply(
+        RandomParameter.ActualValue,
+        new IntegerVector(new IntArray(new int[] { ((IntValue)parameter1.ActualValue.Value).Value })),
+        new IntegerVector(new IntArray(new int[] { ((IntValue)parameter2.ActualValue.Value).Value })));
+      return new IntValue(integerChild[0]);
+    }
+
+  }
+}
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/Manipulators/ParameterConfigurationManipulator.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/Manipulators/ParameterConfigurationManipulator.cs	(revision 5113)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/Manipulators/ParameterConfigurationManipulator.cs	(revision 5113)
@@ -0,0 +1,78 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Core;
+using HeuristicLab.Parameters;
+using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.Problems.MetaOptimization {
+  // todo: item name/descr...
+  [StorableClass]
+  public class ParameterConfigurationManipulator : SingleSuccessorOperator, IParameterConfigurationManipulator, IStochasticOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public IValueLookupParameter<ParameterConfigurationTree> ParameterConfigurationTreeParameter {
+      get { return (IValueLookupParameter<ParameterConfigurationTree>)Parameters["ParameterConfigurationTree"]; }
+    }
+
+    public IValueLookupParameter<IIntValueManipulator> IntValueManipulatorParameter {
+      get { return (IValueLookupParameter<IIntValueManipulator>)Parameters[MetaOptimizationProblem.IntValueManipulatorParameterName]; }
+    }
+    public IValueLookupParameter<IDoubleValueManipulator> DoubleValueManipulatorParameter {
+      get { return (IValueLookupParameter<IDoubleValueManipulator>)Parameters[MetaOptimizationProblem.DoubleValueManipulatorParameterName]; }
+    }
+
+    public ParameterConfigurationManipulator() {
+      Parameters.Add(new ValueLookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
+      Parameters.Add(new ValueLookupParameter<ParameterConfigurationTree>("ParameterConfigurationTree", "The parameter configuration which should be manipulated."));
+
+      Parameters.Add(new ValueLookupParameter<IIntValueManipulator>(MetaOptimizationProblem.IntValueManipulatorParameterName, ""));
+      Parameters.Add(new ValueLookupParameter<IDoubleValueManipulator>(MetaOptimizationProblem.DoubleValueManipulatorParameterName, ""));
+    }
+    [StorableConstructor]
+    protected ParameterConfigurationManipulator(bool deserializing) : base(deserializing) { }
+    protected ParameterConfigurationManipulator(ParameterConfigurationManipulator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ParameterConfigurationManipulator(this, cloner);
+    }
+
+    public sealed override IOperation Apply() {
+      Apply(RandomParameter.ActualValue, ParameterConfigurationTreeParameter.ActualValue, this);
+      return base.Apply();
+    }
+
+    public static void Apply(IRandom random, IValueConfiguration configuration, ParameterConfigurationManipulator pcmanip) {
+      configuration.Mutate(random, Mutate, pcmanip);
+    }
+
+    private static void Mutate(IRandom random, IOptimizable configuration, ParameterConfigurationManipulator pcmanip) {
+      if (configuration is IValueConfiguration) {
+        var vc = configuration as IValueConfiguration;
+        var value = vc.ActualValue.Value;
+        var range = vc.RangeConstraint;
+        if (value is IntValue) {
+          pcmanip.IntValueManipulatorParameter.ActualValue.Apply(random, (IntValue)value, (IntValueRange)range);
+        } else if (value is PercentValue) {
+          pcmanip.DoubleValueManipulatorParameter.ActualValue.Apply(random, (PercentValue)value, ((PercentValueRange)range).AsDoubleValueRange());
+        } else if (value is DoubleValue) {
+          pcmanip.DoubleValueManipulatorParameter.ActualValue.Apply(random, (DoubleValue)value, (DoubleValueRange)range);
+        }
+      } else if (configuration is IParameterConfiguration) {
+        var pc = configuration as IParameterConfiguration;
+        pc.ActualValueConfigurationIndex = random.Next(pc.ValueConfigurations.CheckedItems.Count());
+        pc.ActualValue = pc.ValueConfigurations.CheckedItems.ElementAt(pc.ActualValueConfigurationIndex).ActualValue;
+      }
+    }
+  }
+}
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/NullValue.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/NullValue.cs	(revision 5113)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/NullValue.cs	(revision 5113)
@@ -0,0 +1,23 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Problems.MetaOptimization {
+  [StorableClass]
+  public class NullValue : ValueTypeValue<int> {
+
+    public NullValue() { }
+    [StorableConstructor]
+    protected NullValue(bool deserializing) : base(deserializing) { }
+    protected NullValue(NullValue original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new NullValue(this, cloner);
+    }
+  }
+}
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurationTree.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurationTree.cs	(revision 5113)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurationTree.cs	(revision 5113)
@@ -0,0 +1,183 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Optimization;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.Problems.MetaOptimization {
+  // todo: storable, name, descr, ...
+  [StorableClass]
+  public class ParameterConfigurationTree : ValueConfiguration {
+    //[Storable]
+    //public EngineAlgorithm Algorithm {
+    //  get { return (EngineAlgorithm)base.ActualValue.Value; }
+    //  set {
+    //    base.ActualValue.Value = value;
+    //  }
+    //}
+
+    [Storable]
+    private DoubleValue bestQuality;
+    public DoubleValue BestQuality {
+      get { return bestQuality; }
+      set {
+        if (bestQuality != value) {
+          if (bestQuality != null) DeregisterQualityEvents();
+          bestQuality = value;
+          if (bestQuality != null) RegisterQualityEvents();
+          OnQualityChanged();
+        }
+      }
+    }
+
+    [Storable]
+    private DoubleValue averageQuality;
+    public DoubleValue AverageQuality {
+      get { return averageQuality; }
+      set { averageQuality = value; }
+    }
+
+    [Storable]
+    private DoubleValue worstQuality;
+    public DoubleValue WorstQuality {
+      get { return worstQuality; }
+      set { worstQuality = value; }
+    }
+
+    [Storable]
+    private DoubleValue qualityVariance;
+    public DoubleValue QualityVariance {
+      get { return qualityVariance; }
+      set { qualityVariance = value; }
+    }
+
+    [Storable]
+    private DoubleValue qualityStandardDeviation;
+    public DoubleValue QualityStandardDeviation {
+      get { return qualityStandardDeviation; }
+      set { qualityStandardDeviation = value; }
+    }
+
+    [Storable]
+    private TimeSpanValue averageExecutionTime;
+    public TimeSpanValue AverageExecutionTime {
+      get { return averageExecutionTime; }
+      set { averageExecutionTime = value; }
+    }
+
+    [Storable]
+    private IntValue repetitions;
+    public IntValue Repetitions {
+      get { return repetitions; }
+      set { repetitions = value; }
+    }
+
+    [Storable]
+    protected RunCollection runs;
+    public RunCollection Runs {
+      get { return runs; }
+      set { runs = value; }
+     }
+
+    protected IDictionary<string, IItem> parameters;
+    public IDictionary<string, IItem> Parameters {
+      get { return parameters; }
+      set { parameters = value; }
+    }
+
+    #region constructors and cloning
+    public ParameterConfigurationTree(EngineAlgorithm algorithm)
+      : base(null, algorithm.GetType()) {
+      this.Optimize = true; // root must always be optimized
+      this.BestQuality = new DoubleValue();
+      this.parameters = new Dictionary<string, IItem>();
+
+      PopulateParameterConfigurations(algorithm);
+      Initialize();
+    }
+    public ParameterConfigurationTree() {
+      Initialize();
+    }
+    [StorableConstructor]
+    protected ParameterConfigurationTree(bool deserializing) : base(deserializing) { }
+    protected ParameterConfigurationTree(ParameterConfigurationTree original, Cloner cloner)
+      : base(original, cloner) {
+      this.bestQuality = cloner.Clone(original.BestQuality);
+      this.parameters = new Dictionary<string, IItem>();
+      foreach (var p in original.parameters) {
+        this.parameters.Add(p.Key, cloner.Clone(p.Value));
+      }
+      Initialize();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ParameterConfigurationTree(this, cloner);
+    }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      Initialize();
+    }
+    #endregion
+
+    private void Initialize() {
+      //if (algorithm != null) RegisterAlgorithmEvents();
+      if (bestQuality != null) RegisterQualityEvents();
+    }
+
+    public virtual void CollectResultValues(IDictionary<string, IItem> values) {
+      values.Add("RunsAverageExecutionTime", AverageExecutionTime);
+      values.Add("Repetitions", Repetitions);
+      values.Add("RunsBestQuality", BestQuality);
+      values.Add("RunsAverageQuality", AverageQuality);
+      values.Add("RunsWorstQuality", WorstQuality);
+      values.Add("RunsQualityVariance", QualityVariance);
+      values.Add("RunsQualityStandardDeviation", QualityStandardDeviation);
+      values.Add("Runs", Runs);
+    }
+
+    public virtual void CollectParameterValues(IDictionary<string, IItem> values) {
+      foreach (var p in parameters) {
+        values.Add(p);
+      }
+    }
+
+    #region Events
+    //public event EventHandler AlgorithmChanged;
+    //private void OnAlgorithmChanged() {
+    //  var handler = AlgorithmChanged;
+    //  if (handler != null) handler(this, EventArgs.Empty);
+    //}
+    public event EventHandler QualityChanged;
+    private void OnQualityChanged() {
+      var handler = QualityChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    //private void RegisterAlgorithmEvents() {
+
+    //}
+    //private void DeregisterAlgorithmEvents() {
+
+    //}
+    private void RegisterQualityEvents() {
+      BestQuality.ValueChanged += new EventHandler(Quality_ValueChanged);
+    }
+    private void DeregisterQualityEvents() {
+      BestQuality.ValueChanged -= new EventHandler(Quality_ValueChanged);
+    }
+
+    private void Quality_ValueChanged(object sender, EventArgs e) {
+      OnQualityChanged();
+    }
+    #endregion
+
+    public override void Parameterize(IParameterizedItem item) {
+      base.Parameterize(item);
+      this.parameters.Clear();
+      ((IAlgorithm)item).CollectParameterValues(this.Parameters);
+    }
+  }
+}
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurations/ParameterConfiguration.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurations/ParameterConfiguration.cs	(revision 5113)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ParameterConfigurations/ParameterConfiguration.cs	(revision 5113)
@@ -0,0 +1,351 @@
+﻿using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Problems.MetaOptimization {
+  [StorableClass]
+  public class ParameterConfiguration : Item, IParameterConfiguration, IStorableContent {
+    public bool IsOptimizable { 
+      get { return true; } 
+    }
+
+    [Storable]
+    public string Filename { get; set; }
+
+    [Storable]
+    protected bool optimize;
+    public bool Optimize {
+      get { return optimize; }
+      set {
+        if (optimize != value) {
+          optimize = value;
+          if (optimize) {
+            PopulateValueConfigurations();
+          } else {
+            this.ValueConfigurations.Clear();
+          }
+          OnOptimizeChanged();
+          OnToStringChanged();
+        }
+      }
+    }
+
+    [Storable]
+    protected string parameterName;
+    public string ParameterName {
+      get { return parameterName; }
+      set {
+        if (parameterName != value) {
+          parameterName = value;
+          OnToStringChanged();
+        }
+      }
+    }
+
+    [Storable]
+    protected Type parameterDataType;
+    public Type ParameterDataType {
+      get { return this.parameterDataType; }
+    }
+
+    [Storable]
+    protected IItemSet<IItem> validValues;
+    public IItemSet<IItem> ValidValues {
+      get { return validValues; }
+      protected set {
+        if (this.validValues != value) {
+          this.validValues = value;
+        }
+      }
+    }
+
+    [Storable]
+    protected Type valueDataType;
+    public Type ValueDataType {
+      get { return valueDataType; }
+      protected set { this.valueDataType = value; }
+    }
+
+    [Storable]
+    protected ICheckedValueConfigurationCollection valueConfigurations;
+    public ICheckedValueConfigurationCollection ValueConfigurations {
+      get { return this.valueConfigurations; }
+      protected set {
+        if (this.valueConfigurations != value) {
+          if (this.valueConfigurations != null) DeregisterValueConfigurationEvents();
+          this.valueConfigurations = value;
+          if (this.valueConfigurations != null) RegisterValueConfigurationEvents();
+        }
+      }
+    }
+
+    [Storable]
+    private int actualValueConfigurationIndex = 0;
+    public int ActualValueConfigurationIndex {
+      get { return actualValueConfigurationIndex; }
+      set { actualValueConfigurationIndex = value; }
+    }
+
+    [Storable]
+    protected ConstrainedValue actualValue;
+    public ConstrainedValue ActualValue {
+      get { return actualValue; }
+      set {
+        if (actualValue != value) {
+          DeregisterActualValueEvents();
+          actualValue = value;
+          RegisterActualValueEvents();
+        }
+      }
+    }
+
+    [Storable]
+    protected bool isNullable;
+    public bool IsNullable {
+      get { return isNullable; }
+      protected set {
+        if (this.isNullable != value) {
+          this.isNullable = value;
+        }
+      }
+    }
+
+    #region Constructors and Cloning
+    public ParameterConfiguration(string parameterName, IValueParameter valueParameter) {
+      this.ParameterName = parameterName;
+      this.parameterDataType = valueParameter.GetType();
+      this.valueDataType = valueParameter.DataType;
+      this.validValues = GetValidValues(valueParameter);
+      this.IsNullable = valueParameter.ItemName.StartsWith("Optional");
+      if (IsNullable) {
+        validValues.Add(new NullValue());
+      }
+      this.ValueConfigurations = new CheckedValueConfigurationCollection(this.validValues);
+      this.ActualValue = new ConstrainedValue(valueParameter.Value, valueParameter.DataType, this.ValidValues, this.IsNullable);
+      if (Optimize) {
+        PopulateValueConfigurations();
+      }
+    }
+
+    public ParameterConfiguration() { }
+    [StorableConstructor]
+    protected ParameterConfiguration(bool deserializing) { }
+    protected ParameterConfiguration(ParameterConfiguration original, Cloner cloner) : base(original, cloner) {
+      this.parameterName = original.ParameterName;
+      this.parameterDataType = original.parameterDataType;
+      this.valueDataType = original.ValueDataType;
+      this.validValues = cloner.Clone(original.ValidValues);
+      this.valueConfigurations = cloner.Clone(original.ValueConfigurations);
+      this.ActualValue = cloner.Clone(original.ActualValue);
+      this.optimize = original.optimize;
+      this.actualValueConfigurationIndex = original.actualValueConfigurationIndex;
+      this.isNullable = original.isNullable;
+      if (this.valueConfigurations != null) RegisterValueConfigurationEvents();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ParameterConfiguration(this, cloner);
+    }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (this.valueConfigurations != null) RegisterValueConfigurationEvents();
+    }
+    #endregion
+
+    private void RegisterValueConfigurationEvents() {
+      this.ValueConfigurations.CheckedItemsChanged += new Collections.CollectionItemsChangedEventHandler<IValueConfiguration>(ValueConfigurations_CheckedItemsChanged);
+      this.ValueConfigurations.ItemsAdded += new Collections.CollectionItemsChangedEventHandler<IValueConfiguration>(ValueConfigurations_ItemsAdded);
+      this.ValueConfigurations.ItemsRemoved += new Collections.CollectionItemsChangedEventHandler<IValueConfiguration>(ValueConfigurations_ItemsRemoved);
+    }
+
+    private void DeregisterValueConfigurationEvents() {
+      this.ValueConfigurations.CheckedItemsChanged -= new Collections.CollectionItemsChangedEventHandler<IValueConfiguration>(ValueConfigurations_CheckedItemsChanged);
+      this.ValueConfigurations.ItemsAdded -= new Collections.CollectionItemsChangedEventHandler<IValueConfiguration>(ValueConfigurations_ItemsAdded);
+      this.ValueConfigurations.ItemsRemoved -= new Collections.CollectionItemsChangedEventHandler<IValueConfiguration>(ValueConfigurations_ItemsRemoved);
+    }
+
+    private void RegisterActualValueEvents() {
+      if (this.ActualValue != null) this.ActualValue.ToStringChanged += new EventHandler(ActualValue_ToStringChanged);
+    }
+    private void DeregisterActualValueEvents() {
+      if (this.ActualValue != null) this.ActualValue.ToStringChanged -= new EventHandler(ActualValue_ToStringChanged);
+    }
+
+    private void PopulateValueConfigurations() {
+      foreach (IItem validValue in this.validValues) {
+        if (validValue is NullValue) {
+          this.ValueConfigurations.Add(new NullValueConfiguration());
+        } else {
+          IItem val;
+          if (ActualValue.Value != null && ActualValue.ValueDataType == validValue.GetType()) {
+            val = ActualValue.Value; // use existing value for that type (if available)
+          } else {
+            val = validValue;
+          }
+          this.ValueConfigurations.Add(new ValueConfiguration(val, val.GetType()), true);
+        }
+      }
+    }
+
+    private IItemSet<IItem> GetValidValues(IValueParameter parameter) {
+      if (IsSubclassOfRawGeneric(typeof(OptionalConstrainedValueParameter<>), parameter.GetType())) {
+        var x = (IEnumerable)parameter.GetType().GetProperty("ValidValues").GetValue(parameter, new object[] { });
+        return new ItemSet<IItem>(x.Cast<IItem>());
+      } else {
+        return new ItemSet<IItem>(ApplicationManager.Manager.GetInstances(valueDataType).Select(x => (IItem)x).OrderBy(x => x.ItemName));
+      }
+    }
+
+    private static bool IsSubclassOfRawGeneric(Type generic, Type toCheck) {
+      while (toCheck != typeof(object)) {
+        var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
+        if (generic == cur) {
+          return true;
+        }
+        toCheck = toCheck.BaseType;
+      }
+      return false;
+    }
+
+    void ValueConfigurations_CheckedItemsChanged(object sender, Collections.CollectionItemsChangedEventArgs<IValueConfiguration> e) {
+      OnToStringChanged();
+    }
+    void ValueConfigurations_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<IValueConfiguration> e) {
+      OnToStringChanged();
+    }
+    void ValueConfigurations_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<IValueConfiguration> e) {
+      OnToStringChanged();
+    }
+
+    #region INamedItem Properties
+    public virtual string Name {
+      get { return ParameterName; }
+      set { throw new NotSupportedException(); }
+    }
+    public virtual string Description {
+      get { return base.ItemDescription; }
+      set { throw new NotSupportedException(); }
+    }
+    public virtual bool CanChangeDescription {
+      get { return false; }
+    }
+    public virtual bool CanChangeName {
+      get { return false; }
+    }
+    public override string ItemDescription {
+      //get { return parameter != null ? parameter.Description : base.ItemDescription; }
+      get { return base.ItemDescription; }
+    }
+    public override System.Drawing.Image ItemImage {
+      //get { return parameter != null ? parameter.ItemImage : base.ItemImage; }
+      get { return base.ItemImage; }
+    }
+    public override string ItemName {
+      //get { return parameter != null ?parameter.ItemName : base.ItemName; }
+      get { return base.ItemName; }
+    }
+    #endregion
+
+    #region Events
+    void ActualValue_ToStringChanged(object sender, EventArgs e) {
+      OnToStringChanged();
+    }
+    #endregion
+
+    #region Event Handler
+    public virtual event EventHandler NameChanged;
+    protected virtual void OnNameChanged(object sender, EventArgs e) {
+      var handler = NameChanged;
+      if (handler != null) handler(sender, e);
+    }
+
+    public virtual event EventHandler<CancelEventArgs<string>> NameChanging;
+    protected virtual void OnNameChanging(object sender, CancelEventArgs<string> e) {
+      var handler = NameChanging;
+      if (handler != null) handler(sender, e);
+    }
+
+    public virtual event EventHandler DescriptionChanged;
+    protected virtual void OnDescriptionChanged(object sender, EventArgs e) {
+      var handler = DescriptionChanged;
+      if (handler != null) handler(sender, e);
+    }
+    
+    public virtual event EventHandler IsOptimizableChanged;
+    private void OnIsOptimizableChanged() {
+      var handler = IsOptimizableChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public virtual event EventHandler OptimizeChanged;
+    protected virtual void OnOptimizeChanged() {
+      var handler = OptimizeChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    #endregion
+
+    public override string ToString() {
+      if (Optimize) {
+        return string.Format("{0}: (Optimize: {1})", ParameterName, ValueConfigurations.CheckedItems.Count());
+      } else {
+        return string.Format("{0}: {1}", ParameterName, ActualValue.Value);
+      }
+    }
+
+    public static IParameterConfiguration Create(IParameterizedNamedItem parent, IParameter parameter) {
+      if (parameter is IValueParameter) {
+        IValueParameter valueParameter = parameter as IValueParameter;
+        return new ParameterConfiguration(parameter.Name, valueParameter);
+      }
+      return null;
+    }
+
+    public void Parameterize(IValueParameter parameter) {
+      if (Optimize) {
+        if (this.ActualValue.Value is IParameterizedItem) {
+          this.ValueConfigurations.CheckedItems.ElementAt(actualValueConfigurationIndex).Parameterize((IParameterizedItem)this.ActualValue.Value);
+        }
+      }
+      parameter.Value = this.ActualValue.Value;
+    }
+
+    public void Randomize(IRandom random) {
+      if (Optimize) {
+        foreach (var vc in this.ValueConfigurations.CheckedItems) {
+          vc.Randomize(random);
+        }
+        actualValueConfigurationIndex = random.Next(ValueConfigurations.CheckedItems.Count());
+        this.ActualValue = this.ValueConfigurations.CheckedItems.ElementAt(actualValueConfigurationIndex).ActualValue;
+      }
+    }
+
+    public void Mutate(IRandom random, MutateDelegate mutate, ParameterConfigurationManipulator pcmanip) {
+      if (Optimize) {
+        foreach (IValueConfiguration vc in this.ValueConfigurations.CheckedItems) {
+          vc.Mutate(random, mutate, pcmanip);
+        }
+        mutate(random, this, pcmanip);
+      }
+    }
+
+    public void Cross(IRandom random, IOptimizable other, CrossDelegate cross, ParameterConfigurationCrossover pccross) {
+      if (Optimize) {
+        IParameterConfiguration otherPc = (IParameterConfiguration)other;
+        for (int i = 0; i < this.ValueConfigurations.Count; i++) {
+          cross(random, other, pccross);
+          //this.ValueConfigurations.ElementAt(i).Cross(otherPc.ValueConfigurations.ElementAt(i), random);
+        }
+        //if (random.NextDouble() > 0.5) {
+        //  actualValueConfigurationIndex = ((ParameterConfiguration)other).actualValueConfigurationIndex;
+        //}
+        //this.ActualValue = this.ValueConfigurations.CheckedItems.ElementAt(actualValueConfigurationIndex).ActualValue;
+      }
+    }
+  }
+}
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/RangeConstraints/ConstrainedValue.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/RangeConstraints/ConstrainedValue.cs	(revision 5113)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/RangeConstraints/ConstrainedValue.cs	(revision 5113)
@@ -0,0 +1,96 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.Problems.MetaOptimization {
+  [StorableClass]
+  public class ConstrainedValue : Item {
+    [Storable]
+    protected Type valueDataType;
+    public Type ValueDataType {
+      get { return this.valueDataType; }
+      protected set { this.valueDataType = value; }
+    }
+
+    [Storable]
+    protected IItem value;
+    public IItem Value {
+      get { return value; }
+      set {
+        if (this.value != value) {
+          if(this.value != null) DeregisterEvents();
+          this.value = value;
+          if(this.value != null) RegisterEvents();
+          OnToStringChanged();
+        }
+      }
+    }
+
+    [Storable]
+    protected IItemSet<IItem> validValues;
+    public IItemSet<IItem> ValidValues {
+      get { return validValues; }
+      protected set {
+        if (this.validValues != value) {
+          this.validValues = value;
+        }
+      }
+    }
+
+    [Storable]
+    protected bool isNullable;
+    public bool IsNullable {
+      get { return isNullable; }
+      protected set {
+        if (this.isNullable != value) {
+          this.isNullable = value;
+        }
+      }
+    }
+
+    private void RegisterEvents() {
+      this.value.ToStringChanged += new EventHandler(value_ToStringChanged);
+    }
+    private void DeregisterEvents() {
+      this.value.ToStringChanged -= new EventHandler(value_ToStringChanged);
+    }
+
+    #region constructors and cloning
+    public ConstrainedValue() { }
+    [StorableConstructor]
+    protected ConstrainedValue(bool deserializing) : base(deserializing) { }
+    public ConstrainedValue(IItem value, Type valueDataType, IItemSet<IItem> validValues, bool isNullable) {
+      this.Value = value;
+      this.ValueDataType = valueDataType;
+      this.ValidValues = validValues;
+      this.isNullable = isNullable;
+    }
+    protected ConstrainedValue(ConstrainedValue original, Cloner cloner) : base(original, cloner) {
+      this.valueDataType = original.valueDataType;
+      this.Value = cloner.Clone(original.value);
+      this.ValidValues = cloner.Clone(original.ValidValues);
+      this.isNullable = original.isNullable;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ConstrainedValue(this, cloner);
+    }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (this.value != null) RegisterEvents();
+    }
+    #endregion
+
+    void value_ToStringChanged(object sender, EventArgs e) {
+      OnToStringChanged();
+    }
+
+    public override string ToString() {
+      return value != null ? value.ToString() : base.ToString();
+    }
+  }
+}
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/RangeConstraints/DoubleValueRange.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/RangeConstraints/DoubleValueRange.cs	(revision 5113)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/RangeConstraints/DoubleValueRange.cs	(revision 5113)
@@ -0,0 +1,40 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Data;
+using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Problems.MetaOptimization {
+  [StorableClass]
+  public class DoubleValueRange : Range<DoubleValue> {
+
+    public DoubleValueRange(DoubleValue lowerBound, DoubleValue upperBound, DoubleValue stepSize) : base(lowerBound, upperBound, stepSize) { }
+    public DoubleValueRange() { }
+    [StorableConstructor]
+    protected DoubleValueRange(bool deserializing) : base(deserializing) { }
+    protected DoubleValueRange(DoubleValueRange original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DoubleValueRange(this, cloner);
+    }
+
+    protected override DoubleValue GetRandomSample(IRandom random) {
+      double val;
+      do {
+        val = Math.Round((random.NextDouble() * (UpperBound.Value - LowerBound.Value) + LowerBound.Value) / StepSize.Value, 0) * StepSize.Value;
+      } while (val < LowerBound.Value || val > UpperBound.Value);
+      return new DoubleValue(val);
+    }
+
+    public void Fix(DoubleValue value) {
+      // apply stepsize
+      value.Value = ((int)Math.Round(value.Value / this.StepSize.Value, 0)) * this.StepSize.Value;
+
+      // repair bounds
+      if (value.Value > this.UpperBound.Value) value.Value = this.UpperBound.Value;
+      if (value.Value < this.LowerBound.Value) value.Value = this.LowerBound.Value;
+    }
+  }
+}
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/RangeConstraints/IntValueRange.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/RangeConstraints/IntValueRange.cs	(revision 5113)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/RangeConstraints/IntValueRange.cs	(revision 5113)
@@ -0,0 +1,40 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Data;
+using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Problems.MetaOptimization {
+  [StorableClass]
+  public class IntValueRange : Range<IntValue> {
+
+    public IntValueRange(IntValue lowerBound, IntValue upperBound, IntValue stepSize) : base(lowerBound, upperBound, stepSize) { }
+    public IntValueRange() { }
+    [StorableConstructor]
+    protected IntValueRange(bool deserializing) : base(deserializing) { }
+    protected IntValueRange(IntValueRange original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new IntValueRange(this, cloner);
+    }
+
+    protected override IntValue GetRandomSample(IRandom random) {
+      int val;
+      do {
+        val = random.Next(LowerBound.Value / StepSize.Value, UpperBound.Value / StepSize.Value + 1) * StepSize.Value;
+      } while (val < LowerBound.Value || val > UpperBound.Value);
+      return new IntValue(val);
+    }
+
+    public void Fix(IntValue value) {
+      // apply stepsize
+      value.Value = ((int)Math.Round(value.Value / (double)this.StepSize.Value, 0)) * this.StepSize.Value;
+
+      // repair bounds
+      if (value.Value > this.UpperBound.Value) value.Value = this.UpperBound.Value;
+      if (value.Value < this.LowerBound.Value) value.Value = this.LowerBound.Value;
+    }
+  }
+}
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/RangeConstraints/PercentValueRange.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/RangeConstraints/PercentValueRange.cs	(revision 5113)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/RangeConstraints/PercentValueRange.cs	(revision 5113)
@@ -0,0 +1,35 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Data;
+using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Problems.MetaOptimization {
+  [StorableClass]
+  public class PercentValueRange : Range<PercentValue> {
+
+    public PercentValueRange(PercentValue lowerBound, PercentValue upperBound, PercentValue stepSize) : base(lowerBound, upperBound, stepSize) { }
+    public PercentValueRange() { }
+    [StorableConstructor]
+    protected PercentValueRange(bool deserializing) : base(deserializing) { }
+    protected PercentValueRange(PercentValueRange original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PercentValueRange(this, cloner);
+    }
+
+    protected override PercentValue GetRandomSample(IRandom random) {
+      double val;
+      do {
+        val = Math.Round((random.NextDouble() * (UpperBound.Value - LowerBound.Value) + LowerBound.Value) / StepSize.Value, 0) * StepSize.Value;
+      } while (val < LowerBound.Value || val > UpperBound.Value);
+      return new PercentValue(val);
+    }
+
+    public DoubleValueRange AsDoubleValueRange() {
+      return new DoubleValueRange(LowerBound, UpperBound, StepSize);
+    }
+  }
+}
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/RangeConstraints/Range.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/RangeConstraints/Range.cs	(revision 5113)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/RangeConstraints/Range.cs	(revision 5113)
@@ -0,0 +1,213 @@
+﻿using System;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.MetaOptimization {
+  [StorableClass]
+  public abstract class Range<T> : Item, IRange<T> where T : class, IItem, IStringConvertibleValue, IDeepCloneable {
+    [Storable]
+    private T lowerBound;
+    public T LowerBound {
+      get { return lowerBound; }
+      set {
+        if (lowerBound != value) {
+          if (lowerBound != null) {
+            lowerBound.ValueChanged -= new EventHandler(lowerBound_ToStringChanged);
+          }
+          lowerBound = value;
+          if (lowerBound != null) {
+            lowerBound.ValueChanged += new EventHandler(lowerBound_ToStringChanged);
+          }
+          OnLowerBoundChanged();
+        }
+      }
+    }
+
+    [Storable]
+    private T upperBound;
+    public T UpperBound {
+      get { return upperBound; }
+      set {
+        if (upperBound != value) {
+          if (upperBound != null) {
+            upperBound.ValueChanged -= new EventHandler(upperBound_ToStringChanged);
+          }
+          upperBound = value;
+          if (upperBound != null) {
+            upperBound.ValueChanged += new EventHandler(upperBound_ToStringChanged);
+          }
+          OnUpperBoundChanged();
+        }
+      }
+    }
+
+    [Storable]
+    private T stepSize;
+    public T StepSize {
+      get { return stepSize; }
+      set {
+        if (stepSize != value) {
+          if (stepSize != null) {
+            stepSize.ValueChanged -= new EventHandler(upperBound_ToStringChanged);
+          }
+          stepSize = value;
+          if (stepSize != null) {
+            stepSize.ValueChanged += new EventHandler(stepSize_ToStringChanged);
+          }
+          OnStepSizeChanged();
+        }
+      }
+    }
+
+    #region IRange Members
+    object IRange.LowerBound {
+      get { return lowerBound; }
+      set { lowerBound = (T)value; }
+    }
+    object IRange.UpperBound {
+      get { return upperBound; }
+      set { upperBound = (T)value; }
+    }
+    object IRange.StepSize {
+      get { return stepSize; }
+      set { stepSize = (T)value; }
+    }
+    #endregion
+
+    #region Constructors and Cloning
+    public Range(T lowerBound, T upperBound, T stepSize) {
+      this.LowerBound = lowerBound;
+      this.UpperBound = upperBound;
+      this.StepSize = stepSize;
+    }
+
+    public Range() { }
+    [StorableConstructor]
+    protected Range(bool deserializing) : base(deserializing) { }
+    protected Range(Range<T> original, Cloner cloner) : base(original, cloner) {
+      this.LowerBound = cloner.Clone(original.LowerBound);
+      this.UpperBound = cloner.Clone(original.UpperBound);
+      this.StepSize = cloner.Clone(original.StepSize);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (lowerBound != null) {
+        lowerBound.ValueChanged += new EventHandler(lowerBound_ToStringChanged);
+      }
+      if (upperBound != null) {
+        upperBound.ValueChanged += new EventHandler(upperBound_ToStringChanged);
+      }
+      if (stepSize != null) {
+        stepSize.ValueChanged += new EventHandler(stepSize_ToStringChanged);
+      }
+    }
+    #endregion
+
+    #region Events
+    private void lowerBound_ToStringChanged(object sender, EventArgs e) {
+      OnToStringChanged();
+    }
+    private void upperBound_ToStringChanged(object sender, EventArgs e) {
+      OnToStringChanged();
+    }
+    private void stepSize_ToStringChanged(object sender, EventArgs e) {
+      OnToStringChanged();
+    }
+    #endregion
+
+    #region Eventhandler
+    public event EventHandler LowerBoundChanged;
+    private void OnLowerBoundChanged() {
+      var handler = LowerBoundChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler UpperBoundChanged;
+    private void OnUpperBoundChanged() {
+      var handler = UpperBoundChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler StepSizeChanged;
+    private void OnStepSizeChanged() {
+      var handler = StepSizeChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ValueChanged;
+    private void OnValueChanged() {
+      var handler = ValueChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    #endregion
+
+    public override string ToString() {
+      return string.Format("{0},{1}:{2}", LowerBound.ToString(), UpperBound.ToString(), StepSize.ToString());
+    }
+
+    #region IStringConvertibleValue Members
+
+    public string GetValue() {
+      return this.ToString();
+    }
+    public bool ReadOnly {
+      get { return false; }
+    }
+    public bool SetValue(string value) {
+      var parts1 = value.Split(':');
+      if (parts1.Length != 2) return false;
+      var parts2 = parts1[0].Split(',');
+      if (parts2.Length != 2) return false;
+
+      return
+        lowerBound.SetValue(parts2[0]) &&
+        upperBound.SetValue(parts2[1]) &&
+        stepSize.SetValue(parts1[1]);
+    }
+    public bool Validate(string value, out string errorMessage) {
+      // TODO: check that upper is larger than lower and that stepsize < upper-lower
+      T lower = (T)lowerBound.Clone();
+      T upper = (T)upperBound.Clone();
+      T step = (T)stepSize.Clone();
+
+      var parts1 = value.Split(':');
+      if (parts1.Length != 2) {
+        errorMessage = "Could not parse range."; return false;
+      }
+      var parts2 = parts1[0].Split(',');
+      if (parts2.Length != 2) {
+        errorMessage = "Could not parse range."; return false;
+      }
+
+      if (lowerBound.SetValue(parts2[0]) &&
+          upperBound.SetValue(parts2[1]) &&
+          stepSize.SetValue(parts1[1])) {
+        errorMessage = string.Empty; return true;
+      } else {
+        errorMessage = "Could not parse range."; return false;
+      }
+    }
+
+    #endregion
+
+    public T GetRandomValue(IRandom random) {
+      // by a chance return the extreme values of this range to intensify search in those regions
+      if (random.NextDouble() < 0.1) {
+        if (random.NextDouble() < 0.5) {
+          return LowerBound;
+        } else {
+          return UpperBound;
+        }
+      }
+
+      // otherwise sample a random value from the range
+      return GetRandomSample(random);
+    }
+
+    protected abstract T GetRandomSample(IRandom random);
+
+    IItem IRange.GetRandomValue(IRandom random) {
+      return GetRandomValue(random);
+    }
+  }
+}
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ValueConfigurations/CheckedValueConfigurationCollection.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ValueConfigurations/CheckedValueConfigurationCollection.cs	(revision 5113)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ValueConfigurations/CheckedValueConfigurationCollection.cs	(revision 5113)
@@ -0,0 +1,69 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.MetaOptimization {
+  // todo: check that at least 1 elements needs to be selected
+  // todo: control creatable item types
+  [StorableClass]
+  public class CheckedValueConfigurationCollection : CheckedItemCollection<IValueConfiguration>, ICheckedValueConfigurationCollection {
+    [Storable]
+    private int minItemCount = 1;
+    public int MinItemCount { 
+      get { return minItemCount; } 
+    }
+
+    [Storable]
+    protected IItemSet<IItem> validValues;
+    public IItemSet<IItem> ValidValues {
+      get { return validValues; }
+    }
+
+    public CheckedValueConfigurationCollection(IItemSet<IItem> validValues) {
+      this.validValues = validValues;
+      RegisterEvents();
+    }
+    public CheckedValueConfigurationCollection() {
+      RegisterEvents();
+    }
+    [StorableConstructor]
+    protected CheckedValueConfigurationCollection(bool deserializing) : base(deserializing) {
+      RegisterEvents();
+    }
+    protected CheckedValueConfigurationCollection(CheckedValueConfigurationCollection original, Cloner cloner) : base(original, cloner) {
+      this.minItemCount = original.MinItemCount;
+      this.validValues = original.validValues;
+      RegisterEvents();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CheckedValueConfigurationCollection(this, cloner);
+    }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEvents();
+    }
+
+    private void RegisterEvents() {
+      this.ItemsRemoved += new Collections.CollectionItemsChangedEventHandler<IValueConfiguration>(CheckedValueConfigurationCollection_ItemsRemoved);
+    }
+    private void DeregisterEvents() {
+      this.ItemsRemoved -= new Collections.CollectionItemsChangedEventHandler<IValueConfiguration>(CheckedValueConfigurationCollection_ItemsRemoved);
+    }
+
+    private void CheckedValueConfigurationCollection_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<IValueConfiguration> e) {
+      // auch collectionreset gehört berücksichtigt
+      // funktioniert so nicht ganz, weil die view das hinzufügen nicht mitkriegt
+      //if (this.Count < minItemCount) {
+      //  foreach (var item in e.Items) {
+      //    if (this.Count >= minItemCount)
+      //      break;
+      //    this.Add(item);
+      //  }
+      //}
+    }
+  }
+}
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ValueConfigurations/NullValueConfiguration.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ValueConfigurations/NullValueConfiguration.cs	(revision 5113)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ValueConfigurations/NullValueConfiguration.cs	(revision 5113)
@@ -0,0 +1,31 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Problems.MetaOptimization {
+  [StorableClass]
+  public class NullValueConfiguration : ValueConfiguration {
+
+    public NullValueConfiguration() {
+      this.ParameterConfigurations = new ItemList<IParameterConfiguration>();
+      this.ActualValue = new ConstrainedValue(null, null, null, true);
+      this.IsOptimizable = false;
+    }
+    [StorableConstructor]
+    protected NullValueConfiguration(bool deserializing) : base(deserializing) { }
+    protected NullValueConfiguration(NullValueConfiguration original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new NullValueConfiguration(this, cloner);
+    }
+
+    public override string ToString() {
+      return "null";
+    }
+  }
+}
Index: branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ValueConfigurations/ValueConfiguration.cs
===================================================================
--- branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ValueConfigurations/ValueConfiguration.cs	(revision 5113)
+++ branches/HeuristicLab.MetaOptimization/HeuristicLab.Problems.MetaOptimization/3.3/Encoding/ValueConfigurations/ValueConfiguration.cs	(revision 5113)
@@ -0,0 +1,299 @@
+﻿using System;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Data;
+using System.Drawing;
+using HeuristicLab.Encodings.RealVectorEncoding;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Problems.MetaOptimization {
+  // TODO: ItemName/Descr, storability
+  [StorableClass]
+  public class ValueConfiguration : Item, IValueConfiguration {
+    [Storable]
+    protected bool isOptimizable;
+    public bool IsOptimizable {
+      get { return isOptimizable; }
+      set {
+        if (this.isOptimizable != value) {
+          this.isOptimizable = value;
+          OnIsOptimizableChanged();
+        }
+      }
+    }
+
+    [Storable]
+    protected bool optimize;
+    public bool Optimize {
+      get { return optimize; }
+      set {
+        if (optimize != value) {
+          optimize = value;
+          if (optimize) {
+            ClearParameterConfigurations();
+            if (this.actualValue.Value is IParameterizedNamedItem) PopulateParameterConfigurations(this.actualValue.Value as IParameterizedNamedItem);
+          } else {
+            ClearParameterConfigurations();
+          }
+          OnOptimizeChanged();
+          OnToStringChanged();
+        }
+      }
+    }
+
+    [Storable]
+    protected IItemCollection<IParameterConfiguration> parameterConfigurations = new ItemCollection<IParameterConfiguration>();
+    public IItemCollection<IParameterConfiguration> ParameterConfigurations {
+      get { return new ReadOnlyItemCollection<IParameterConfiguration>(this.parameterConfigurations); }
+      protected set { this.parameterConfigurations = value; }
+    }
+
+    [Storable]
+    protected ConstrainedValue actualValue;
+    public virtual ConstrainedValue ActualValue {
+      get { return actualValue; }
+      set {
+        if (this.actualValue != value) {
+          RegisterActualValueEvents();
+          ClearParameterConfigurations();
+          this.actualValue = value;
+          if (this.actualValue.Value is IParameterizedNamedItem) PopulateParameterConfigurations(this.actualValue.Value as IParameterizedNamedItem);
+          OnValueChanged();
+          OnToStringChanged();
+          DeregisterActualValueEvents();
+        }
+      }
+    }
+
+    [Storable]
+    protected IRange rangeConstraint;
+    public IRange RangeConstraint {
+      get { return rangeConstraint; }
+      private set {
+        if (rangeConstraint != value) {
+          DeregisterRangeConstraintEvents();
+          rangeConstraint = value;
+          RegisterActualValueEvents();
+        }
+      }
+    }
+
+    #region Constructors and Cloning
+    public ValueConfiguration(IItem value, Type valueDataType) {
+      this.ParameterConfigurations = new ItemList<IParameterConfiguration>();
+      var validValues = new ItemSet<IItem>(ApplicationManager.Manager.GetInstances(valueDataType).Select(x => (IItem)x).OrderBy(x => x.ItemName));
+      this.ActualValue = new ConstrainedValue(value, valueDataType, validValues, false);
+      this.IsOptimizable = true;
+      if (actualValue.ValueDataType == typeof(IntValue)) {
+        rangeConstraint = new IntValueRange(new IntValue(0), (IntValue)value, new IntValue(1));
+      } else if (actualValue.ValueDataType == typeof(DoubleValue)) {
+        rangeConstraint = new DoubleValueRange(new DoubleValue(0), (DoubleValue)value, new DoubleValue(0.01));
+      } else if (actualValue.ValueDataType == typeof(PercentValue)) {
+        rangeConstraint = new PercentValueRange(new PercentValue(0), new PercentValue(1), new PercentValue(0.001));
+      } else if (actualValue.ValueDataType == typeof(BoolValue)) {
+        this.IsOptimizable = false; // there is nothing to configure for bools
+      } else {
+        rangeConstraint = null;
+      }
+      RegisterRangeConstraintEvents();
+    }
+
+    public ValueConfiguration() { }
+    [StorableConstructor]
+    protected ValueConfiguration(bool deserializing) { }
+    protected ValueConfiguration(ValueConfiguration original, Cloner cloner)
+      : base(original, cloner) {
+      this.ParameterConfigurations = cloner.Clone(original.parameterConfigurations);
+      this.actualValue = cloner.Clone(original.ActualValue);
+      this.rangeConstraint = cloner.Clone(original.RangeConstraint);
+      this.isOptimizable = original.isOptimizable;
+      this.optimize = original.optimize;
+      RegisterActualValueEvents();
+      RegisterRangeConstraintEvents();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ValueConfiguration(this, cloner);
+    }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterRangeConstraintEvents();
+    }
+    #endregion
+
+    protected virtual void PopulateParameterConfigurations(IParameterizedNamedItem parameterizedItem) {
+      foreach (var childParameter in parameterizedItem.Parameters) {
+        var pc = ParameterConfiguration.Create(parameterizedItem, childParameter);
+        if (pc != null) this.parameterConfigurations.Add(pc);
+      }
+    }
+    protected virtual void ClearParameterConfigurations() {
+      parameterConfigurations.Clear();
+    }
+
+    private void RegisterRangeConstraintEvents() {
+      if (this.RangeConstraint != null) this.RangeConstraint.ToStringChanged += new EventHandler(RangeConstraint_ToStringChanged);
+    }
+    private void DeregisterRangeConstraintEvents() {
+      if (this.RangeConstraint != null) this.RangeConstraint.ToStringChanged -= new EventHandler(RangeConstraint_ToStringChanged);
+    }
+    private void RegisterActualValueEvents() {
+      if (this.actualValue != null) this.actualValue.ToStringChanged += new EventHandler(actualValue_ToStringChanged);
+    }
+    private void DeregisterActualValueEvents() {
+      if (this.actualValue != null) this.actualValue.ToStringChanged -= new EventHandler(actualValue_ToStringChanged);
+    }
+
+    #region Events
+    void actualValue_ToStringChanged(object sender, EventArgs e) {
+      OnToStringChanged();
+    }
+    void RangeConstraint_ToStringChanged(object sender, EventArgs e) {
+      OnToStringChanged();
+    }
+    #endregion
+    
+    #region IItem Members
+    public override string ItemDescription {
+      get { return (actualValue != null && actualValue.Value != null) ? actualValue.Value.ItemDescription : base.ItemDescription; }
+    }
+
+    public override Image ItemImage {
+      get { return (actualValue != null && actualValue.Value != null) ? actualValue.Value.ItemImage : base.ItemImage; }
+    }
+
+    public override string ItemName {
+      get { return (actualValue != null && actualValue.Value != null) ? actualValue.Value.ItemDescription : base.ItemName; }
+    }
+    #endregion
+    
+    #region Event Handlers
+    public virtual event EventHandler ValueChanged;
+    protected virtual void OnValueChanged() {
+      var handler = ValueChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public virtual event EventHandler IsOptimizableChanged;
+    private void OnIsOptimizableChanged() {
+      var handler = IsOptimizableChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public virtual event EventHandler OptimizeChanged;
+    protected virtual void OnOptimizeChanged() {
+      var handler = OptimizeChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    #endregion
+
+    public override string ToString() {
+      if (ActualValue != null && ActualValue.Value != null) {
+        if (ActualValue.Value is IParameterizedItem) {
+          if (Optimize) {
+            return string.Format("{0} (Optimize)", ActualValue.Value.ItemName);
+          } else {
+            return string.Format("{0}", ActualValue.Value.ItemName);
+          }
+        } else {
+          if (Optimize) {
+            return string.Format("{0} (Optimize: {1})", ActualValue.Value.ItemName, RangeConstraint);
+          } else {
+            return string.Format("{0}: {1}", ActualValue.Value.ItemName, ActualValue.Value);
+          }
+        }
+      } else {
+        return base.ToString();
+      }
+    }
+
+    public virtual void Parameterize(IParameterizedItem item) {
+      foreach (IParameterConfiguration pc in this.ParameterConfigurations) {
+        pc.Parameterize((IValueParameter)item.Parameters[pc.ParameterName]);
+      }
+    }
+
+    public void Randomize(IRandom random) {
+      if (Optimize) {
+        if (rangeConstraint != null) {
+          this.actualValue.Value = rangeConstraint.GetRandomValue(random);
+        } else {
+          foreach (IParameterConfiguration pc in this.ParameterConfigurations) {
+            pc.Randomize(random);
+          }
+        }
+      }
+    }
+
+    public void Mutate(IRandom random, MutateDelegate mutate, ParameterConfigurationManipulator pcmanip) {
+      if (Optimize) {
+        if (rangeConstraint != null) {
+          mutate(random, this, pcmanip);
+        } else {
+          foreach (IParameterConfiguration pc in this.ParameterConfigurations) {
+            pc.Mutate(random, mutate, pcmanip);
+          }
+        }
+      }
+    }
+
+    public void Cross(IRandom random, IOptimizable other, CrossDelegate cross, ParameterConfigurationCrossover pccross) {
+      if (Optimize) {
+        IValueConfiguration otherVc = (IValueConfiguration)other;
+        if (rangeConstraint != null) {
+          cross(random, this, pccross);
+
+          //if (this.actualValue.ValueDataType == typeof(IntValue)) {
+          //  //this.actualValue.Value = new IntValue((((IntValue)this.actualValue.Value).Value + ((IntValue)other.ActualValue.Value).Value) / 2);
+
+          //  IntegerVector[] parents = new IntegerVector[2];
+          //  parents[0] = new IntegerVector(new int[] { ((IntValue)this.actualValue.Value).Value });
+          //  parents[1] = new IntegerVector(new int[] { ((IntValue)other.ActualValue.Value).Value });
+
+          //  this.actualValue.Value = new IntValue(HeuristicLab.Encodings.IntegerVectorEncoding.DiscreteCrossover.Apply(random, parents[0], parents[1]).First());
+
+          //} else if (this.actualValue.ValueDataType == typeof(DoubleValue)) {
+          //  //this.actualValue.Value = new DoubleValue((((DoubleValue)this.actualValue.Value).Value + ((DoubleValue)other.ActualValue.Value).Value) / 2);
+          //  RealVector[] parents = new RealVector[2];
+          //  parents[0] = new RealVector(new double[] { ((DoubleValue)this.actualValue.Value).Value });
+          //  parents[1] = new RealVector(new double[] { ((DoubleValue)other.ActualValue.Value).Value });
+
+          //  if (random.NextDouble() < 0.5) {
+          //    this.actualValue.Value = new DoubleValue(AverageCrossover.Apply(random, new ItemArray<RealVector>(parents)).First());
+          //  } else {
+          //    this.actualValue.Value = new DoubleValue(HeuristicLab.Encodings.RealVectorEncoding.DiscreteCrossover.Apply(random, new ItemArray<RealVector>(parents)).First());
+          //  }
+          //  //this.actualValue.Value = new DoubleValue(AverageCrossover.Apply(random, new ItemArray<RealVector>(parents)).First());
+
+          //} else if (this.actualValue.ValueDataType == typeof(PercentValue)) {
+          //  //this.actualValue.Value = new PercentValue((((PercentValue)this.actualValue.Value).Value + ((PercentValue)other.ActualValue.Value).Value) / 2);
+
+          //  RealVector[] parents = new RealVector[2];
+          //  parents[0] = new RealVector(new double[] { ((PercentValue)this.actualValue.Value).Value });
+          //  parents[1] = new RealVector(new double[] { ((PercentValue)other.ActualValue.Value).Value });
+
+          //  if (random.NextDouble() < 0.5) {
+          //    this.actualValue.Value = new PercentValue(AverageCrossover.Apply(random, new ItemArray<RealVector>(parents)).First());
+          //  } else {
+          //    this.actualValue.Value = new PercentValue(HeuristicLab.Encodings.RealVectorEncoding.DiscreteCrossover.Apply(random, new ItemArray<RealVector>(parents)).First());
+          //  }
+
+          //} else if (this.actualValue.ValueDataType == typeof(BoolValue)) {
+          //  if (random.NextDouble() > 0.5)
+          //    this.actualValue.Value = this.actualValue.Value;
+          //  else
+          //    this.actualValue.Value = other.ActualValue.Value;
+          //} else {
+          //  throw new NotImplementedException();
+          //}
+        } else {
+          for (int i = 0; i < this.ParameterConfigurations.Count; i++) {
+            this.ParameterConfigurations.ElementAt(i).Cross(random, otherVc.ParameterConfigurations.ElementAt(i), cross, pccross);
+          }
+        }
+      }
+    }
+  }
+}
