Index: /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 17767)
+++ /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 17768)
@@ -242,4 +242,5 @@
     <Compile Include="Interpreter\SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs" />
     <Compile Include="Interpreter\SymbolicDataAnalysisExpressionTreeNativeInterpreter.cs" />
+    <Compile Include="IntervalUtil.cs" />
     <Compile Include="Selectors\DiversitySelector.cs" />
     <Compile Include="SymbolicDataAnalysisExpressionTreeAverageSimilarityCalculator.cs" />
Index: /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IBoundsEstimator.cs
===================================================================
--- /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IBoundsEstimator.cs	(revision 17767)
+++ /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IBoundsEstimator.cs	(revision 17768)
@@ -16,5 +16,10 @@
       ISymbolicExpressionTree tree, IntervalCollection variableRanges);
 
+    double CheckConstraint(
+      ISymbolicExpressionTree tree, IntervalCollection variableRanges, IntervalConstraint constraint);
+
+    bool IsCompatible(ISymbolicExpressionTree tree);
+
     int EvaluatedSolutions { get; set; }
-  }
+    }
 }
Index: /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IABoundsEstimator.cs
===================================================================
--- /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IABoundsEstimator.cs	(revision 17767)
+++ /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IABoundsEstimator.cs	(revision 17768)
@@ -3,6 +3,4 @@
 using System.Collections.ObjectModel;
 using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 using HEAL.Attic;
 using HeuristicLab.Common;
@@ -15,5 +13,5 @@
   [StorableType("C8539434-6FB0-47D0-9F5A-2CAE5D8B8B4F")]
   [Item("IA Bounds Estimator", "Interpreter for calculation of intervals of symbolic models.")]
-  public sealed class IABoundsEstimator : ParameterizedNamedItem, IBoundsEstimator{
+  public sealed class IABoundsEstimator : ParameterizedNamedItem, IBoundsEstimator {
     #region Parameters
 
@@ -54,4 +52,5 @@
       set => SplittingWidthParameter.Value.Value = value;
     }
+
     #endregion
 
@@ -60,12 +59,17 @@
     [StorableConstructor]
     private IABoundsEstimator(StorableConstructorFlag _) : base(_) { }
-        
+
     private IABoundsEstimator(IABoundsEstimator original, Cloner cloner) : base(original, cloner) { }
 
-    public IABoundsEstimator() : base("IA Bounds Estimator", "Estimates the bounds of the model with interval arithmetic") {
-      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the estimator has evaluated.", new IntValue(0)));
-      Parameters.Add(new FixedValueParameter<BoolValue>(UseIntervalSplittingParameterName, "Defines whether interval splitting is activated or not.", new BoolValue(false)));
-      Parameters.Add(new FixedValueParameter<IntValue>(SplittingIterationsParameterName, "Defines the number of iterations of splitting.", new IntValue(200)));
-      Parameters.Add(new FixedValueParameter<DoubleValue>(SplittingWidthParameterName, "Width of interval, after the splitting should stop.", new DoubleValue(0.0)));
+    public IABoundsEstimator() : base("IA Bounds Estimator",
+      "Estimates the bounds of the model with interval arithmetic") {
+      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName,
+        "A counter for the total number of solutions the estimator has evaluated.", new IntValue(0)));
+      Parameters.Add(new FixedValueParameter<BoolValue>(UseIntervalSplittingParameterName,
+        "Defines whether interval splitting is activated or not.", new BoolValue(false)));
+      Parameters.Add(new FixedValueParameter<IntValue>(SplittingIterationsParameterName,
+        "Defines the number of iterations of splitting.", new IntValue(200)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(SplittingWidthParameterName,
+        "Width of interval, after the splitting should stop.", new DoubleValue(0.0)));
     }
 
@@ -74,5 +78,5 @@
     }
 
-        #endregion
+    #endregion
 
     #region IStatefulItem Members
@@ -86,5 +90,5 @@
     public void ClearState() { }
 
-        #endregion
+    #endregion
 
     #region Evaluation
@@ -261,9 +265,10 @@
     }
 
-        #endregion
+    #endregion
 
     #region Helpers
 
-    private static IDictionary<string, Interval> GetOccurringVariableRanges(ISymbolicExpressionTree tree, IntervalCollection variableRanges) {
+    private static IDictionary<string, Interval> GetOccurringVariableRanges(
+      ISymbolicExpressionTree tree, IntervalCollection variableRanges) {
       var variables = tree.IterateNodesPrefix().OfType<VariableTreeNode>().Select(v => v.VariableName).Distinct()
                           .ToList();
@@ -321,9 +326,13 @@
     public static Interval EvaluateWithSplitting(Instruction[] instructions,
                                                  IDictionary<string, Interval> variableIntervals,
-                                                 List<string> multipleOccurenceVariables, int splittingIterations, double splittingWidth, IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals = null) {
-      var savedIntervals = variableIntervals.ToDictionary(entry => entry.Key, entry => entry.Value);
-      var min = FindBound(instructions, variableIntervals, multipleOccurenceVariables, splittingIterations, splittingWidth, nodeIntervals,
+                                                 List<string> multipleOccurenceVariables, int splittingIterations,
+                                                 double splittingWidth,
+                                                 IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals =
+                                                   null) {
+      var min = FindBound(instructions, variableIntervals.ToDictionary(entry => entry.Key, entry => entry.Value),
+        multipleOccurenceVariables, splittingIterations, splittingWidth, nodeIntervals,
         minimization: true);
-      var max = FindBound(instructions, savedIntervals,  multipleOccurenceVariables, splittingIterations, splittingWidth, nodeIntervals,
+      var max = FindBound(instructions, variableIntervals.ToDictionary(entry => entry.Key, entry => entry.Value),
+        multipleOccurenceVariables, splittingIterations, splittingWidth, nodeIntervals,
         minimization: false);
 
@@ -333,12 +342,13 @@
     private static double FindBound(Instruction[] instructions,
                                     IDictionary<string, Interval> variableIntervals,
-                                    List<string> multipleOccurenceVariables, int splittingIterations, double splittingWidth, IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals = null, bool minimization = true) {
+                                    List<string> multipleOccurenceVariables, int splittingIterations,
+                                    double splittingWidth,
+                                    IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals = null,
+                                    bool minimization = true, bool stopAtLimit = false, double limit = 0) {
       SortedSet<BoxBound> prioQ = new SortedSet<BoxBound>();
-
       var ic = 0;
+      var stop = false;
       //Calculate full box
-      //IReadOnlyDictionary<string, Interval> readonlyRanges =
-      //  variableIntervals.ToDictionary(k => k.Key, k => k.Value);
-      var interval = Evaluate(instructions, ref ic, nodeIntervals, variableIntervals:variableIntervals);
+      var interval = Evaluate(instructions, ref ic, nodeIntervals, variableIntervals: variableIntervals);
       // the order of keys in a dictionary is guaranteed to be the same order as values in a dictionary
       // https://docs.microsoft.com/en-us/dotnet/api/system.collections.idictionary.keys?view=netcore-3.1#remarks
@@ -348,11 +358,13 @@
       if (minimization) {
         prioQ.Add(new BoxBound(box, interval.LowerBound));
+        if (stopAtLimit && interval.LowerBound >= limit) stop = true;
       } else {
         prioQ.Add(new BoxBound(box, -interval.UpperBound));
+        if (stopAtLimit && interval.UpperBound <= limit) stop = true;
       }
 
       var discardedBound = double.MaxValue;
       var runningBound = double.MaxValue;
-      for (var depth = 0; depth < splittingIterations && prioQ.Count > 0; ++depth) {
+      for (var depth = 0; depth < splittingIterations && prioQ.Count > 0 && !stop; ++depth) {
         var currentBound = prioQ.Min;
         prioQ.Remove(currentBound);
@@ -382,9 +394,5 @@
           var res = Evaluate(instructions, ref ic, nodeIntervals,
             new ReadOnlyDictionary<string, Interval>(variableIntervals));
-          //if (minimization) {
-          //  prioQ.Add(new BoxBound(newBox, res.LowerBound));
-          //} else {
-          //  prioQ.Add(new BoxBound(newBox, -res.UpperBound));
-          //}
+
           var boxBound = new BoxBound(newBox, minimization ? res.LowerBound : -res.UpperBound);
           prioQ.Add(boxBound);
@@ -394,4 +402,11 @@
         runningBound = innerBound;
 
+        if (minimization) {
+          if (stopAtLimit && innerBound >= limit)
+            stop = true;
+        } else {
+          if (stopAtLimit && innerBound <= limit)
+            stop = true;
+        }
       }
 
@@ -413,5 +428,5 @@
 
     private static IEnumerable<IEnumerable<Interval>> Split(List<Interval> box, double minWidth) {
-      List<Interval> toList(Tuple<Interval, Interval> t) => new List<Interval>{t.Item1, t.Item2};
+      List<Interval> toList(Tuple<Interval, Interval> t) => new List<Interval> {t.Item1, t.Item2};
       var boxes = box.Select(region => region.Width > minWidth ? toList(region.Split()) : new List<Interval> {region})
                      .ToList();
@@ -435,5 +450,6 @@
       } else {
         var vars = ContainsVariableMultipleTimes(tree, out var variables);
-        resultInterval = EvaluateWithSplitting(instructions, occuringVariableRanges, variables, SplittingIterations, SplittingWidth);
+        resultInterval = EvaluateWithSplitting(instructions, occuringVariableRanges, variables, SplittingIterations,
+          SplittingWidth);
       }
 
@@ -445,9 +461,89 @@
     }
 
-    public IDictionary<ISymbolicExpressionTreeNode, Interval> GetModelNodesBounds(ISymbolicExpressionTree tree, IntervalCollection variableRanges) {
+    public IDictionary<ISymbolicExpressionTreeNode, Interval> GetModelNodesBounds(
+      ISymbolicExpressionTree tree, IntervalCollection variableRanges) {
       throw new NotImplementedException();
     }
 
-    
+    public double CheckConstraint(
+      ISymbolicExpressionTree tree, IntervalCollection variableRanges, IntervalConstraint constraint) {
+      var occuringVariableRanges = GetOccurringVariableRanges(tree, variableRanges);
+      var instructions = PrepareInterpreterState(tree, occuringVariableRanges);
+      if (!UseIntervalSplitting) {
+        var instructionCounter = 0;
+        var modelBound = Evaluate(instructions, ref instructionCounter, variableIntervals: occuringVariableRanges);
+        if (constraint.Interval.Contains(modelBound)) return 0.0;
+        return Math.Abs(modelBound.LowerBound - constraint.Interval.LowerBound) +
+               Math.Abs(modelBound.UpperBound - constraint.Interval.UpperBound);
+      }
+
+      if (double.IsNegativeInfinity(constraint.Interval.LowerBound) &&
+          double.IsPositiveInfinity(constraint.Interval.UpperBound)) {
+        return 0.0;
+      }
+
+      ContainsVariableMultipleTimes(tree, out var variables);
+
+      var upperBound = 0.0;
+      var lowerBound = 0.0;
+      if (double.IsNegativeInfinity(constraint.Interval.LowerBound)) {
+        upperBound = FindBound(instructions, occuringVariableRanges, variables, SplittingIterations, SplittingWidth,
+          minimization: false, stopAtLimit: true, limit: constraint.Interval.UpperBound);
+
+        return upperBound <= constraint.Interval.UpperBound
+          ? 0.0
+          : Math.Abs(upperBound - constraint.Interval.UpperBound);
+      }
+
+      if (double.IsPositiveInfinity(constraint.Interval.UpperBound)) {
+        lowerBound = FindBound(instructions, occuringVariableRanges, variables, SplittingIterations, SplittingWidth,
+          minimization: true, stopAtLimit: true, limit: constraint.Interval.LowerBound);
+
+        return lowerBound <= constraint.Interval.LowerBound
+          ? 0.0
+          : Math.Abs(lowerBound - constraint.Interval.LowerBound);
+      }
+
+      upperBound = FindBound(instructions, occuringVariableRanges, variables, SplittingIterations, SplittingWidth,
+        minimization: false, stopAtLimit: true, limit: constraint.Interval.UpperBound);
+      lowerBound = FindBound(instructions, occuringVariableRanges, variables, SplittingIterations, SplittingWidth,
+        minimization: true, stopAtLimit: true, limit: constraint.Interval.LowerBound);
+
+
+      var res = 0.0;
+
+      res += upperBound <= constraint.Interval.UpperBound ? 0.0 : Math.Abs(upperBound - constraint.Interval.UpperBound);
+      res += lowerBound <= constraint.Interval.LowerBound ? 0.0 : Math.Abs(lowerBound - constraint.Interval.LowerBound);
+
+      return res;
+    }
+
+
+    public bool IsCompatible(ISymbolicExpressionTree tree) {
+      var containsUnknownSymbols = (
+        from n in tree.Root.GetSubtree(0).IterateNodesPrefix()
+        where
+          !(n.Symbol is Variable) &&
+          !(n.Symbol is Constant) &&
+          !(n.Symbol is StartSymbol) &&
+          !(n.Symbol is Addition) &&
+          !(n.Symbol is Subtraction) &&
+          !(n.Symbol is Multiplication) &&
+          !(n.Symbol is Division) &&
+          !(n.Symbol is Sine) &&
+          !(n.Symbol is Cosine) &&
+          !(n.Symbol is Tangent) &&
+          !(n.Symbol is HyperbolicTangent) &&
+          !(n.Symbol is Logarithm) &&
+          !(n.Symbol is Exponential) &&
+          !(n.Symbol is Square) &&
+          !(n.Symbol is SquareRoot) &&
+          !(n.Symbol is Cube) &&
+          !(n.Symbol is CubeRoot) &&
+          !(n.Symbol is Absolute) &&
+          !(n.Symbol is AnalyticQuotient)
+        select n).Any();
+      return !containsUnknownSymbols;
+    }
   }
 }
Index: /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/IntervalUtil.cs
===================================================================
--- /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/IntervalUtil.cs	(revision 17768)
+++ /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/IntervalUtil.cs	(revision 17768)
@@ -0,0 +1,87 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public static class IntervalUtil {
+    public static double IntervalConstraintViolation(
+      IntervalConstraint constraint, IBoundsEstimator estimator, IntervalCollection intervalCollection,
+      ISymbolicExpressionTree solution) {
+      var variableRanges = intervalCollection.GetReadonlyDictionary();
+
+      if (constraint.Variable != null && !variableRanges.ContainsKey(constraint.Variable)) {
+        throw new ArgumentException(
+          $"The given variable {constraint.Variable} in the constraint does not exist in the model.",
+          nameof(IntervalConstraintsParser));
+      }
+
+      //Create new variable ranges for defined regions
+      var regionRanges = new IntervalCollection();
+      foreach (var kvp in variableRanges) {
+        if (kvp.Key != constraint.Target && constraint.Regions.GetReadonlyDictionary().TryGetValue(kvp.Key, out Interval val)) {
+          regionRanges.AddInterval(kvp.Key, val);
+        } else {
+          regionRanges.AddInterval(kvp.Key, kvp.Value);
+        }
+      }
+
+      var error = 0.0;
+      if (!constraint.IsDerivative) {
+        error = estimator.CheckConstraint(solution, regionRanges, constraint);
+      } else {
+        var tree = solution;
+        for (var i = 0; i < constraint.NumberOfDerivations; ++i) {
+          if (!estimator.IsCompatible(tree) || !DerivativeCalculator.IsCompatible(tree)) {
+            throw new ArgumentException("Cube, Root, Power symbols are not supported.");
+          }
+
+          tree = DerivativeCalculator.Derive(tree, constraint.Variable);
+        }
+
+        error = estimator.CheckConstraint(tree, regionRanges, constraint);
+      }
+
+      return error * constraint.Weight;
+      //Interval resultInterval;
+      //if (!constraint.IsDerivative) {
+      //  resultInterval = estimator.GetModelBound(solution, regionRanges);
+      //} else {
+      //  var tree = solution;
+      //  for (var i = 0; i < constraint.NumberOfDerivations; ++i) {
+      //    if (!estimator.IsCompatible(tree) || !DerivativeCalculator.IsCompatible(tree)) {
+      //      throw new ArgumentException("Cube, Root, Power symbols are not supported.");
+      //    }
+
+      //    tree = DerivativeCalculator.Derive(tree, constraint.Variable);
+      //  }
+
+      //  resultInterval = estimator.GetModelBound(tree, regionRanges);
+      //}
+
+      //var error = 0.0;
+
+      //if (!constraint.Interval.Contains(resultInterval.LowerBound)) {
+      //  error     += Math.Abs(resultInterval.LowerBound - constraint.Interval.LowerBound);
+      //}
+
+      //if (!constraint.Interval.Contains(resultInterval.UpperBound)) {
+      //  error     += Math.Abs(resultInterval.UpperBound - constraint.Interval.UpperBound);
+      //}
+
+      //error *= constraint.Weight;
+
+      //return error;
+    }
+
+    public static IEnumerable<double> IntervalConstraintsViolation(
+      IEnumerable<IntervalConstraint> constraints, IBoundsEstimator estimator, IntervalCollection intervalCollection,
+      ISymbolicExpressionTree solution) {
+      return constraints
+            .Select(constraint => IntervalConstraintViolation(constraint, estimator, intervalCollection, solution))
+            .ToList();
+    }
+  }
+}
Index: /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj
===================================================================
--- /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 17767)
+++ /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 17768)
@@ -192,5 +192,4 @@
     <Compile Include="Implementation\Interval\IntervalConstraint.cs" />
     <Compile Include="Implementation\Interval\IntervalConstraintsParser.cs" />
-    <Compile Include="Implementation\Interval\Region.cs" />
     <Compile Include="Implementation\Regression\ConfidenceBoundRegressionSolution.cs" />
     <Compile Include="Implementation\Regression\ConstantRegressionModel.cs" />
Index: /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/IntervalConstraint.cs
===================================================================
--- /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/IntervalConstraint.cs	(revision 17767)
+++ /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/IntervalConstraint.cs	(revision 17768)
@@ -115,6 +115,6 @@
     }
 
-    [Storable] private IEnumerable<Region> regions;
-    public IEnumerable<Region> Regions {
+    [Storable] private IntervalCollection regions;
+    public IntervalCollection Regions {
       get => regions;
       set {
@@ -146,8 +146,8 @@
                               Interval interval, double weight, bool enabled)
       : this(expression, variable, target, numberOfDerivations,
-             interval, Enumerable.Empty<Region>(), weight, enabled) { }
+             interval, new IntervalCollection(), weight, enabled) { }
 
     public IntervalConstraint(string expression, string variable, string target, int numberOfDerivations,
-                              Interval interval, IEnumerable<Region> regions, double weight, bool enabled) {
+                              Interval interval, IntervalCollection regions, double weight, bool enabled) {
       this.regions = regions;
       this.weight = weight;
@@ -166,5 +166,5 @@
     private IntervalConstraint(IntervalConstraint original, Cloner cloner)
       : base(original, cloner) {
-      Regions = new List<Region>(original.Regions?.Select(r => cloner.Clone(r)) ?? Enumerable.Empty<Region>());
+      Regions = original.Regions;
       Expression = original.Expression;
       Variable = original.Variable;
@@ -207,6 +207,6 @@
                                    "]");
         if(Regions != null) {
-          foreach (var region in Regions)
-            expression += $", {region.VariableName}=({region.Interval.LowerBound} .. {region.Interval.UpperBound})";
+          foreach (var region in Regions.GetReadonlyDictionary())
+            expression += $", {region.Key}=({region.Value.LowerBound} .. {region.Value.UpperBound})";
         }
         
@@ -224,6 +224,6 @@
                                  GetDerivationString(numberOfDerivations));
       if (Regions != null) {
-        foreach (var region in Regions)
-          expression += $", {region.VariableName}=({region.Interval.LowerBound} .. {region.Interval.UpperBound})";
+        foreach (var region in Regions.GetReadonlyDictionary())
+          expression += $", {region.Key}=({region.Value.LowerBound} .. {region.Value.UpperBound})";
       }
       Expression = expression;
Index: /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/IntervalConstraintsParser.cs
===================================================================
--- /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/IntervalConstraintsParser.cs	(revision 17767)
+++ /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/IntervalConstraintsParser.cs	(revision 17768)
@@ -93,14 +93,14 @@
             if (match.Groups[10].Success)
             {
-              IList<Region> regions = new List<Region>();
+              IntervalCollection regions = new IntervalCollection();
               // option variables found
               for(int idx = 0; idx < match.Groups[10].Captures.Count; ++idx)
               {
-                Region region = ParseRegion(
+                KeyValuePair<string, Interval> region = ParseRegion(
                   match.Groups[11].Captures[idx].Value,
                   match.Groups[13].Captures[idx].Value,
                   match.Groups[15].Captures[idx].Value);
-                if(!regions.Any(r => r.VariableName == region.VariableName))
-                  regions.Add(region);
+                if (regions.GetReadonlyDictionary().All(r => r.Key != region.Key))
+                  regions.AddInterval(region.Key, region.Value);
                 else
                   throw new ArgumentException("A constraint cannot contain multiple regions of the same variable.");
@@ -184,14 +184,14 @@
             if(match.Groups[17].Success)
             {
-              IList<Region> regions = new List<Region>();
+              IntervalCollection regions = new IntervalCollection();
               // option variables found
               for (int idx = 0; idx < match.Groups[17].Captures.Count; ++idx)
               {
-                Region region = ParseRegion(
+                KeyValuePair<string, Interval> region = ParseRegion(
                   match.Groups[18].Captures[idx].Value,
                   match.Groups[20].Captures[idx].Value,
                   match.Groups[22].Captures[idx].Value);
-                if (!regions.Any(r => r.VariableName == region.VariableName))
-                  regions.Add(region);
+                if (regions.GetReadonlyDictionary().All(r => r.Key != region.Key))
+                  regions.AddInterval(region.Key, region.Value);
                 else
                   throw new ArgumentException("A constraint cannot contain multiple regions of the same variable.");
@@ -217,9 +217,10 @@
     }
 
-    private static Region ParseRegion(string variable, string lb, string ub)
+    private static KeyValuePair<string, Interval> ParseRegion(string variable, string lb, string ub)
     {
       var regionLb = ParseIntervalBounds(lb);
       var regionUb = ParseIntervalBounds(ub);
-      return new Region(variable, new Interval(regionLb, regionUb));
+      return new KeyValuePair<string, Interval>(variable, new Interval(regionLb, regionUb));
+      //return new Region(variable, new Interval(regionLb, regionUb));
     }
 
Index: anches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/Region.cs
===================================================================
--- /branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/Region.cs	(revision 17767)
+++ 	(revision )
@@ -1,58 +1,0 @@
-﻿using HEAL.Attic;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace HeuristicLab.Problems.DataAnalysis {
-  [StorableType("8E3FEB9B-0B1A-4F06-8CFC-CB8D468EF7EC")]
-  [Item("Region", "A region for an interval constraint.")]
-  public class Region : Item {
-
-    [Storable] private string variableName;
-    public string VariableName {
-      get => variableName;
-      private set {
-        if(variableName == null || variableName != value) {
-          variableName = value;
-          OnChanged();
-        }
-      }
-    }
-
-    [Storable] private Interval interval;
-    public Interval Interval {
-      get => interval;
-      private set {
-        if (interval == null || !interval.Equals(value)) {
-          interval = value;
-          OnChanged();
-        }
-      }
-    }
-
-    [StorableConstructor]
-    private Region(StorableConstructorFlag _) : base(_) { }
-
-    public Region(string variableName, Interval interval) {
-      VariableName = variableName;
-      Interval = interval;
-    }
-
-    private Region(Region original, Cloner cloner)
-      : base(original, cloner) {
-      VariableName = original.VariableName;
-      Interval = original.Interval;
-    }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new Region(this, cloner);
-    }
-
-    public event EventHandler Changed;
-    private void OnChanged() => Changed?.Invoke(this, EventArgs.Empty);
-  }
-}
