Index: /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/DerivativeCalculator.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/DerivativeCalculator.cs	(revision 17901)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/DerivativeCalculator.cs	(revision 17902)
@@ -149,4 +149,16 @@
         return Product(Product(CreateConstant(3.0), Square(f)), Derive(f, variableName));
       }
+      if (branch.Symbol is Power) {
+        // HL evaluators handle power strangely (exponent is rounded to an integer)
+        // here we only support the case when the exponent is a constant integer 
+        var exponent = branch.GetSubtree(1) as ConstantTreeNode;
+        if (exponent != null && Math.Truncate(exponent.Value) == exponent.Value) {
+          var newPower = (ISymbolicExpressionTreeNode)branch.Clone();
+          var f = (ISymbolicExpressionTreeNode)newPower.GetSubtree(0).Clone();
+          var newExponent = (ConstantTreeNode)newPower.GetSubtree(1);
+          newExponent.Value -= 1;
+          return Product(Product(CreateConstant(exponent.Value), newPower), Derive(f, variableName));
+        } else throw new NotSupportedException("Cannot derive non-integer powers");
+      }
       if (branch.Symbol is Absolute) {
         var f = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
@@ -263,6 +275,8 @@
           !(n.Symbol is Cube) &&
           !(n.Symbol is CubeRoot) &&
+          !(n.Symbol is Power) &&
           !(n.Symbol is Absolute) &&
           !(n.Symbol is AnalyticQuotient) &&
+          !(n.Symbol is HyperbolicTangent) &&
           !(n.Symbol is Sine) &&
           !(n.Symbol is Cosine) &&
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/IntervalArithmeticGrammar.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/IntervalArithmeticGrammar.cs	(revision 17902)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/IntervalArithmeticGrammar.cs	(revision 17902)
@@ -0,0 +1,133 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#endregion
+using System.Collections.Generic;
+using System.Linq;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableType("5A2300A0-D0FC-4F2D-B910-F86384FE9052")]
+  [Item("IntervalArithmeticGrammar", "Represents a grammar for interval arithmetic which includes linear scaling parts implicitly.")]
+  public class IntervalArithmeticGrammar : DataAnalysisGrammar, ISymbolicDataAnalysisGrammar {
+    public IntervalArithmeticGrammar() : base(ItemAttribute.GetName(typeof(IntervalArithmeticGrammar)),
+      ItemAttribute.GetDescription(typeof(IntervalArithmeticGrammar))) {
+      Initialize();
+    }
+
+    [StorableConstructor]
+    public IntervalArithmeticGrammar(StorableConstructorFlag _) : base(_) { }
+
+    protected IntervalArithmeticGrammar(IntervalArithmeticGrammar original, Cloner cloner) : base(original, cloner) { }
+    public IntervalArithmeticGrammar(string name, string description) : base(name, description) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new IntervalArithmeticGrammar(this, cloner);
+    }
+
+    private void Initialize() {
+      #region Symbols
+
+      var add = new Addition();
+      var sub = new Subtraction();
+      var mul = new Multiplication();
+      var div = new Division();
+      var sin = new Sine();
+      var cos = new Cosine();
+      var tan = new Tangent();
+      var tanh = new HyperbolicTangent();
+      var log = new Logarithm();
+      var exp = new Exponential();
+      var square = new Square();
+      var sqrt = new SquareRoot();
+      var cube = new Cube();
+      var cbrt = new CubeRoot();
+      var abs = new Absolute();
+      var aq = new AnalyticQuotient();
+      var constant = new Constant();
+      constant.MinValue = -20;
+      constant.MaxValue = 20;
+      var variableSymbol = new Variable();
+
+      #endregion
+
+      //Special symbols
+      var offset = new Addition { Name = "Offset" };
+      var scaling = new Multiplication { Name = "Scaling" };
+      //all other symbols
+      var allSymbols = new List<Symbol> {
+        add, sub, mul, div, constant, variableSymbol, sin, cos, tan, log, square, sqrt, cube, cbrt, exp,
+        tanh, aq, abs
+      };
+
+      var bivariateFuncs = new List<Symbol> { add, sub, mul, div, aq };
+      var univariateFuncs = new List<Symbol> { sin, cos, tan, tanh, exp, log, abs, square, cube, sqrt, cbrt };
+      var realValueSymbols = new List<Symbol> {
+         add, sub, mul, div, sin, cos, tan, tanh, exp, log, aq, abs, square, cube, sqrt, cbrt,
+         variableSymbol, constant,
+        };
+
+
+      //Add special symbols
+      AddSymbol(offset);
+      AddSymbol(scaling);
+      //Add all other symbols
+      foreach (var symb in allSymbols) AddSymbol(symb);
+
+      #region define subtree count for special symbols
+
+      foreach (var symb in bivariateFuncs) SetSubtreeCount(symb, 2, 2);
+
+      foreach (var symb in univariateFuncs) SetSubtreeCount(symb, 1, 1);
+
+      SetSubtreeCount(offset, 2, 2);
+      SetSubtreeCount(scaling, 2, 2);
+
+      #endregion
+
+      #region child symbols config
+
+      AddAllowedChildSymbol(StartSymbol, offset);
+
+      //Define childs for offset
+      AddAllowedChildSymbol(offset, scaling, 0);
+      AddAllowedChildSymbol(offset, constant, 1);
+
+      //Define childs for scaling
+      foreach (var symb in allSymbols) AddAllowedChildSymbol(scaling, symb, 0);
+      AddAllowedChildSymbol(scaling, constant, 1);
+
+      //Define childs for realvalue symbols
+      foreach (var symb in realValueSymbols) {
+        foreach (var c in realValueSymbols) AddAllowedChildSymbol(symb, c);
+      }
+
+      #endregion
+
+      Symbols.First(s => s is Cube).Enabled = false;
+      Symbols.First(s => s is CubeRoot).Enabled = false;
+      Symbols.First(s => s is Absolute).Enabled = false;
+    }
+  }
+}
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 17901)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 17902)
@@ -107,5 +107,5 @@
       <Private>False</Private>
     </Reference>
-    <Reference Include="HEAL.Attic, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+    <Reference Include="HEAL.Attic, Version=1.4.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\..\bin\HEAL.Attic.dll</HintPath>
@@ -157,4 +157,5 @@
     <Compile Include="Formatters\SymbolicDataAnalysisExpressionCSharpFormatter.cs" />
     <Compile Include="Grammars\DataAnalysisGrammar.cs" />
+    <Compile Include="Grammars\IntervalArithmeticGrammar.cs" />
     <Compile Include="Hashing\HashExtensions.cs" />
     <Compile Include="Hashing\HashUtil.cs" />
@@ -163,4 +164,5 @@
     <Compile Include="Importer\SymbolicExpressionImporter.cs" />
     <Compile Include="Importer\Token.cs" />
+    <Compile Include="Interfaces\IBoundsEstimator.cs" />
     <Compile Include="Interfaces\IModelBacktransformator.cs" />
     <Compile Include="Interfaces\IVariableTreeNode.cs" />
@@ -168,8 +170,11 @@
     <Compile Include="Interpreter\BatchInstruction.cs" />
     <Compile Include="Interpreter\BatchOperations.cs" />
+    <Compile Include="Interpreter\IntervalArithBoundsEstimator.cs" />
+    <Compile Include="Interpreter\IntervalArithCompiledExpressionBoundsEstimator.cs" />
     <Compile Include="Interpreter\IntervalInterpreter.cs" />
     <Compile Include="Interpreter\SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs" />
     <Compile Include="Interpreter\SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs" />
     <Compile Include="Interpreter\SymbolicDataAnalysisExpressionTreeNativeInterpreter.cs" />
+    <Compile Include="IntervalUtil.cs" />
     <Compile Include="Selectors\DiversitySelector.cs" />
     <Compile Include="SymbolicDataAnalysisExpressionTreeAverageSimilarityCalculator.cs" />
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs	(revision 17901)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs	(revision 17902)
@@ -64,5 +64,5 @@
     }
 
-    private class SymbolNameComparer : IEqualityComparer<ISymbol>, IComparer<ISymbol> {
+    private class SymbolComparer : IEqualityComparer<ISymbol>, IComparer<ISymbol> {
       public int Compare(ISymbol x, ISymbol y) {
         return x.Name.CompareTo(y.Name);
@@ -70,9 +70,9 @@
 
       public bool Equals(ISymbol x, ISymbol y) {
-        return Compare(x, y) == 0;
+        return x.GetType() == y.GetType();
       }
 
       public int GetHashCode(ISymbol obj) {
-        return obj.Name.GetHashCode();
+        return obj.GetType().GetHashCode();
       }
     }
@@ -80,5 +80,5 @@
     // the lookup table is also used in the corresponding formatter
     internal static readonly BidirectionalLookup<string, ISymbol>
-      knownSymbols = new BidirectionalLookup<string, ISymbol>(StringComparer.InvariantCulture, new SymbolNameComparer());
+      knownSymbols = new BidirectionalLookup<string, ISymbol>(StringComparer.InvariantCulture, new SymbolComparer());
 
     private Constant constant = new Constant();
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IBoundsEstimator.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IBoundsEstimator.cs	(revision 17902)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IBoundsEstimator.cs	(revision 17902)
@@ -0,0 +1,22 @@
+﻿using System.Collections.Generic;
+using HEAL.Attic;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableType("C94A360D-5A9F-48A3-A6D3-CF920C77E50D")]
+  public interface IBoundsEstimator : INamedItem, IStatefulItem {
+    Interval GetModelBound(ISymbolicExpressionTree tree, IntervalCollection variableRanges);
+
+    IDictionary<ISymbolicExpressionTreeNode, Interval> GetModelNodeBounds(
+      ISymbolicExpressionTree tree, IntervalCollection variableRanges);
+
+    // returns the size of the violation which is the distance to one of the bounds
+    double GetConstraintViolation(
+      ISymbolicExpressionTree tree, IntervalCollection variableRanges, ShapeConstraint constraint);
+
+    bool IsCompatible(ISymbolicExpressionTree tree);
+
+    int EvaluatedSolutions { get; set; }
+  }
+}
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalArithBoundsEstimator.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalArithBoundsEstimator.cs	(revision 17902)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalArithBoundsEstimator.cs	(revision 17902)
@@ -0,0 +1,337 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableType("C8539434-6FB0-47D0-9F5A-2CAE5D8B8B4F")]
+  [Item("Interval Arithmetic Bounds Estimator", "Interpreter for calculation of intervals of symbolic models.")]
+  public sealed class IntervalArithBoundsEstimator : ParameterizedNamedItem, IBoundsEstimator {
+    #region Parameters
+
+    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
+
+    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter =>
+      (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName];
+
+    public int EvaluatedSolutions {
+      get => EvaluatedSolutionsParameter.Value.Value;
+      set => EvaluatedSolutionsParameter.Value.Value = value;
+    }
+    #endregion
+
+    #region Constructors
+
+    [StorableConstructor]
+    private IntervalArithBoundsEstimator(StorableConstructorFlag _) : base(_) { }
+
+    private IntervalArithBoundsEstimator(IntervalArithBoundsEstimator original, Cloner cloner) : base(original, cloner) { }
+
+    public IntervalArithBoundsEstimator() : base("Interval Arithmetic 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)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new IntervalArithBoundsEstimator(this, cloner);
+    }
+
+    #endregion
+
+    #region IStatefulItem Members
+
+    private readonly object syncRoot = new object();
+
+    public void InitializeState() {
+      EvaluatedSolutions = 0;
+    }
+
+    public void ClearState() { }
+
+    #endregion
+
+    #region Evaluation
+
+    private static Instruction[] PrepareInterpreterState(
+      ISymbolicExpressionTree tree,
+      IDictionary<string, Interval> variableRanges) {
+      if (variableRanges == null)
+        throw new ArgumentNullException("No variable ranges are present!", nameof(variableRanges));
+
+      // Check if all variables used in the tree are present in the dataset
+      foreach (var variable in tree.IterateNodesPrefix().OfType<VariableTreeNode>().Select(n => n.VariableName)
+                                   .Distinct())
+        if (!variableRanges.ContainsKey(variable))
+          throw new InvalidOperationException($"No ranges for variable {variable} is present");
+
+      var code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
+      foreach (var instr in code.Where(i => i.opCode == OpCodes.Variable)) {
+        var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
+        instr.data = variableRanges[variableTreeNode.VariableName];
+      }
+
+      return code;
+    }
+
+    // Use ref parameter, because the tree will be iterated through recursively from the left-side branch to the right side
+    // Update instructionCounter, whenever Evaluate is called
+    public static Interval Evaluate(
+      Instruction[] instructions, ref int instructionCounter,
+      IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals = null,
+      IDictionary<string, Interval> variableIntervals = null) {
+      var currentInstr = instructions[instructionCounter];
+      instructionCounter++;
+      Interval result;
+
+      switch (currentInstr.opCode) {
+        case OpCodes.Variable: {
+            var variableTreeNode = (VariableTreeNode)currentInstr.dynamicNode;
+            var weightInterval = new Interval(variableTreeNode.Weight, variableTreeNode.Weight);
+
+            Interval variableInterval;
+            if (variableIntervals != null && variableIntervals.ContainsKey(variableTreeNode.VariableName))
+              variableInterval = variableIntervals[variableTreeNode.VariableName];
+            else
+              variableInterval = (Interval)currentInstr.data;
+
+            result = Interval.Multiply(variableInterval, weightInterval);
+            break;
+          }
+        case OpCodes.Constant: {
+            var constTreeNode = (ConstantTreeNode)currentInstr.dynamicNode;
+            result = new Interval(constTreeNode.Value, constTreeNode.Value);
+            break;
+          }
+        case OpCodes.Add: {
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            for (var i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+              result = Interval.Add(result, argumentInterval);
+            }
+
+            break;
+          }
+        case OpCodes.Sub: {
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            if (currentInstr.nArguments == 1)
+              result = Interval.Multiply(new Interval(-1, -1), result);
+
+            for (var i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+              result = Interval.Subtract(result, argumentInterval);
+            }
+
+            break;
+          }
+        case OpCodes.Mul: {
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            for (var i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+              result = Interval.Multiply(result, argumentInterval);
+            }
+
+            break;
+          }
+        case OpCodes.Div: {
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            if (currentInstr.nArguments == 1)
+              result = Interval.Divide(new Interval(1, 1), result);
+
+            for (var i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+              result = Interval.Divide(result, argumentInterval);
+            }
+
+            break;
+          }
+        case OpCodes.Sin: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            result = Interval.Sine(argumentInterval);
+            break;
+          }
+        case OpCodes.Cos: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            result = Interval.Cosine(argumentInterval);
+            break;
+          }
+        case OpCodes.Tan: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            result = Interval.Tangens(argumentInterval);
+            break;
+          }
+        case OpCodes.Tanh: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            result = Interval.HyperbolicTangent(argumentInterval);
+            break;
+          }
+        case OpCodes.Log: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            result = Interval.Logarithm(argumentInterval);
+            break;
+          }
+        case OpCodes.Exp: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            result = Interval.Exponential(argumentInterval);
+            break;
+          }
+        case OpCodes.Square: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            result = Interval.Square(argumentInterval);
+            break;
+          }
+        case OpCodes.SquareRoot: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            result = Interval.SquareRoot(argumentInterval);
+            break;
+          }
+        case OpCodes.Cube: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            result = Interval.Cube(argumentInterval);
+            break;
+          }
+        case OpCodes.CubeRoot: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            result = Interval.CubicRoot(argumentInterval);
+            break;
+          }
+        case OpCodes.Absolute: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            result = Interval.Absolute(argumentInterval);
+            break;
+          }
+        case OpCodes.AnalyticQuotient: {
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            for (var i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+              result = Interval.AnalyticalQuotient(result, argumentInterval);
+            }
+
+            break;
+          }
+        default:
+          throw new NotSupportedException(
+            $"The tree contains the unknown symbol {currentInstr.dynamicNode.Symbol}");
+      }
+
+      if (!(nodeIntervals == null || nodeIntervals.ContainsKey(currentInstr.dynamicNode)))
+        nodeIntervals.Add(currentInstr.dynamicNode, result);
+
+      return result;
+    }
+
+    #endregion
+
+    #region Helpers
+
+    private static IDictionary<string, Interval> GetOccurringVariableRanges(
+      ISymbolicExpressionTree tree, IntervalCollection variableRanges) {
+      var variables = tree.IterateNodesPrefix().OfType<VariableTreeNode>().Select(v => v.VariableName).Distinct()
+                          .ToList();
+
+      return variables.ToDictionary(x => x, x => variableRanges.GetReadonlyDictionary()[x]);
+    }
+
+    #endregion
+  
+    public Interval GetModelBound(ISymbolicExpressionTree tree, IntervalCollection variableRanges) {
+      lock (syncRoot) {
+        EvaluatedSolutions++;
+      }
+
+      var occuringVariableRanges = GetOccurringVariableRanges(tree, variableRanges);
+      var instructions = PrepareInterpreterState(tree, occuringVariableRanges);
+      Interval resultInterval;
+      var instructionCounter = 0;
+      resultInterval = Evaluate(instructions, ref instructionCounter, variableIntervals: occuringVariableRanges);
+
+      // because of numerical errors the bounds might be incorrect
+      if (resultInterval.IsInfiniteOrUndefined || resultInterval.LowerBound <= resultInterval.UpperBound)
+        return resultInterval;
+
+      return new Interval(resultInterval.UpperBound, resultInterval.LowerBound);
+    }
+
+    public IDictionary<ISymbolicExpressionTreeNode, Interval> GetModelNodeBounds(
+      ISymbolicExpressionTree tree, IntervalCollection variableRanges) {
+      throw new NotImplementedException();
+    }
+
+    public double GetConstraintViolation(
+      ISymbolicExpressionTree tree, IntervalCollection variableRanges, ShapeConstraint constraint) {
+      var occuringVariableRanges = GetOccurringVariableRanges(tree, variableRanges);
+      var instructions = PrepareInterpreterState(tree, occuringVariableRanges);
+      var instructionCounter = 0;
+      var modelBound = Evaluate(instructions, ref instructionCounter, variableIntervals: occuringVariableRanges);
+      if (constraint.Interval.Contains(modelBound)) return 0.0;
+
+
+      var error = 0.0;
+
+      if (!constraint.Interval.Contains(modelBound.LowerBound)) {
+        error += Math.Abs(modelBound.LowerBound - constraint.Interval.LowerBound);
+      }
+
+      if (!constraint.Interval.Contains(modelBound.UpperBound)) {
+        error += Math.Abs(modelBound.UpperBound - constraint.Interval.UpperBound);
+      }
+
+      return error;
+    }
+
+
+    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: /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalArithCompiledExpressionBoundsEstimator.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalArithCompiledExpressionBoundsEstimator.cs	(revision 17902)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalArithCompiledExpressionBoundsEstimator.cs	(revision 17902)
@@ -0,0 +1,255 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#endregion
+
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableType("60015D64-5D8B-408A-90A1-E4111BC114D4")]
+  [Item("Interval Arithmetic Compiled Expression Bounds Estimator", "Compile a symbolic model into a lambda and use it to evaluate model bounds.")]
+  public class IntervalArithCompiledExpressionBoundsEstimator : ParameterizedNamedItem, IBoundsEstimator {
+    // interval method names
+    private static readonly Dictionary<byte, string> methodName = new Dictionary<byte, string>() {
+      { OpCodes.Add, "Add" },
+      { OpCodes.Sub, "Subtract" },
+      { OpCodes.Mul, "Multiply" },
+      { OpCodes.Div, "Divide" },
+      { OpCodes.Sin, "Sine" },
+      { OpCodes.Cos, "Cosine" },
+      { OpCodes.Tan, "Tangens" },
+      { OpCodes.Tanh, "HyperbolicTangent" },
+      { OpCodes.Log, "Logarithm" },
+      { OpCodes.Exp, "Exponential" },
+      { OpCodes.Square, "Square" },
+      { OpCodes.Cube, "Cube" },
+      { OpCodes.SquareRoot, "SquareRoot" },
+      { OpCodes.CubeRoot, "CubicRoot" },
+      { OpCodes.Absolute, "Absolute" },
+      { OpCodes.AnalyticQuotient, "AnalyticalQuotient" },
+    };
+
+    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
+    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter {
+      get => (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName];
+    }
+    public int EvaluatedSolutions {
+      get => EvaluatedSolutionsParameter.Value.Value;
+      set => EvaluatedSolutionsParameter.Value.Value = value;
+    }
+
+    private readonly object syncRoot = new object();
+
+    public IntervalArithCompiledExpressionBoundsEstimator() : base("Interval Arithmetic Compiled Expression Bounds Estimator",
+      "Estimates the bounds of the model with interval arithmetic, by first compiling the model into a lambda.") {
+      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName,
+        "A counter for the total number of solutions the estimator has evaluated.", new IntValue(0)));
+    }
+
+    [StorableConstructor]
+    private IntervalArithCompiledExpressionBoundsEstimator(StorableConstructorFlag _) : base(_) { }
+
+    private IntervalArithCompiledExpressionBoundsEstimator(IntervalArithCompiledExpressionBoundsEstimator original, Cloner cloner) : base(original, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new IntervalArithCompiledExpressionBoundsEstimator(this, cloner);
+    }
+
+    public double GetConstraintViolation(ISymbolicExpressionTree tree, IntervalCollection variableRanges, ShapeConstraint constraint) {
+      var modelBound = GetModelBound(tree, variableRanges);
+      if (constraint.Interval.Contains(modelBound)) return 0.0;
+      return Math.Abs(modelBound.LowerBound - constraint.Interval.LowerBound) +
+             Math.Abs(modelBound.UpperBound - constraint.Interval.UpperBound);
+    }
+
+    public void ClearState() {
+      EvaluatedSolutions = 0;
+    }
+
+    public Interval GetModelBound(ISymbolicExpressionTree tree, IntervalCollection variableRanges) {
+      lock (syncRoot) { EvaluatedSolutions++; }
+      var resultInterval = EstimateBounds(tree, variableRanges.GetReadonlyDictionary());
+
+      if (resultInterval.IsInfiniteOrUndefined || resultInterval.LowerBound <= resultInterval.UpperBound)
+        return resultInterval;
+      return new Interval(resultInterval.UpperBound, resultInterval.LowerBound);
+    }
+
+    public IDictionary<ISymbolicExpressionTreeNode, Interval> GetModelNodeBounds(ISymbolicExpressionTree tree, IntervalCollection variableRanges) {
+      throw new NotSupportedException("Model nodes bounds are not supported.");
+    }
+
+    public void InitializeState() {
+      EvaluatedSolutions = 0;
+    }
+
+    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;
+    }
+
+    #region compile a tree into a IA arithmetic lambda and estimate bounds
+    static Expression MakeExpr(ISymbolicExpressionTreeNode node, IReadOnlyDictionary<string, Interval> variableRanges, IReadOnlyDictionary<string, int> variableIndices, Expression args) {
+      Expression expr(ISymbolicExpressionTreeNode n) => MakeExpr(n, variableRanges, variableIndices, args);
+      var opCode = OpCodes.MapSymbolToOpCode(node);
+
+      switch (opCode) {
+        case OpCodes.Variable: {
+            var name = (node as VariableTreeNode).VariableName;
+            var weight = (node as VariableTreeNode).Weight;
+            var index = variableIndices[name];
+            return Expression.Multiply(
+              Expression.Constant(weight, typeof(double)),
+              Expression.ArrayIndex(args, Expression.Constant(index, typeof(int)))
+            );
+          }
+        case OpCodes.Constant: {
+            var v = (node as ConstantTreeNode).Value;
+            // we have to make an interval out of the constant because this may be the root of the tree (and we are expected to return an Interval)
+            return Expression.Constant(new Interval(v, v), typeof(Interval));
+          }
+        case OpCodes.Add: {
+            var e = expr(node.GetSubtree(0));
+            foreach (var s in node.Subtrees.Skip(1)) {
+              e = Expression.Add(e, expr(s));
+            }
+            return e;
+          }
+        case OpCodes.Sub: {
+            var e = expr(node.GetSubtree(0));
+            if (node.SubtreeCount == 1) {
+              return Expression.Subtract(Expression.Constant(0.0, typeof(double)), e);
+            }
+            foreach (var s in node.Subtrees.Skip(1)) {
+              e = Expression.Subtract(e, expr(s));
+            }
+            return e;
+          }
+        case OpCodes.Mul: {
+            var e = expr(node.GetSubtree(0));
+            foreach (var s in node.Subtrees.Skip(1)) {
+              e = Expression.Multiply(e, expr(s));
+            }
+            return e;
+          }
+        case OpCodes.Div: {
+            var e1 = expr(node.GetSubtree(0));
+            if (node.SubtreeCount == 1) {
+              return Expression.Divide(Expression.Constant(1.0, typeof(double)), e1);
+            }
+            // division is more expensive than multiplication so we use this construct
+            var e2 = expr(node.GetSubtree(1));
+            foreach (var s in node.Subtrees.Skip(2)) {
+              e2 = Expression.Multiply(e2, expr(s));
+            }
+            return Expression.Divide(e1, e2);
+          }
+        // all these cases share the same code: get method info by name, emit call expression
+        case OpCodes.Exp:
+        case OpCodes.Log:
+        case OpCodes.Sin:
+        case OpCodes.Cos:
+        case OpCodes.Tan:
+        case OpCodes.Tanh:
+        case OpCodes.Square:
+        case OpCodes.Cube:
+        case OpCodes.SquareRoot:
+        case OpCodes.CubeRoot:
+        case OpCodes.Absolute:
+        case OpCodes.AnalyticQuotient: {
+            var arg = expr(node.GetSubtree(0));
+            var fun = typeof(Interval).GetMethod(methodName[opCode], new[] { arg.Type });
+            return Expression.Call(fun, arg);
+          }
+        default: {
+            throw new Exception($"Unsupported OpCode {opCode} encountered.");
+          }
+      }
+    }
+
+    public static IReadOnlyDictionary<string, int> GetVariableIndices(ISymbolicExpressionTree tree, IReadOnlyDictionary<string, Interval> variableIntervals, out Interval[] inputIntervals) {
+      var variableIndices = new Dictionary<string, int>();
+      var root = tree.Root;
+      while (root.Symbol is ProgramRootSymbol || root.Symbol is StartSymbol) {
+        root = root.GetSubtree(0);
+      }
+      inputIntervals = new Interval[variableIntervals.Count];
+      int count = 0;
+      foreach (var node in root.IterateNodesPrefix()) {
+        if (node is VariableTreeNode varNode) {
+          var name = varNode.VariableName;
+          if (!variableIndices.ContainsKey(name)) {
+            variableIndices[name] = count;
+            inputIntervals[count] = variableIntervals[name];
+            ++count;
+          }
+        }
+      }
+      Array.Resize(ref inputIntervals, count);
+      return variableIndices;
+    }
+
+    public static Func<Interval[], Interval> Compile(ISymbolicExpressionTree tree, IReadOnlyDictionary<string, Interval> variableRanges, IReadOnlyDictionary<string, int> variableIndices) {
+      var root = tree.Root.GetSubtree(0).GetSubtree(0);
+      var args = Expression.Parameter(typeof(Interval[]));
+      var expr = MakeExpr(root, variableRanges, variableIndices, args);
+      return Expression.Lambda<Func<Interval[], Interval>>(expr, args).Compile();
+    }
+
+    public static Interval EstimateBounds(ISymbolicExpressionTree tree, IReadOnlyDictionary<string, Interval> variableRanges) {
+      var variableIndices = GetVariableIndices(tree, variableRanges, out Interval[] x);
+      var f = Compile(tree, variableRanges, variableIndices);
+      return f(x);
+    }
+    #endregion
+  }
+}
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs	(revision 17901)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs	(revision 17902)
@@ -1,3 +1,4 @@
 ﻿#region License Information
+
 /* HeuristicLab
  * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
@@ -18,4 +19,5 @@
  * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
  */
+
 #endregion
 
@@ -32,26 +34,25 @@
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
   [StorableType("DE6C1E1E-D7C1-4070-847E-63B68562B10C")]
-  [Item("IntervalInterpreter", "Intperter for calculation of intervals of symbolic models.")]
+  [Item("IntervalInterpreter", "Interpreter for calculation of intervals of symbolic models.")]
   public sealed class IntervalInterpreter : ParameterizedNamedItem, IStatefulItem {
-
     private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
-
-    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter {
-      get { return (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
-    }
+    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter =>
+      (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName];
 
     public int EvaluatedSolutions {
-      get { return EvaluatedSolutionsParameter.Value.Value; }
-      set { EvaluatedSolutionsParameter.Value.Value = value; }
+      get => EvaluatedSolutionsParameter.Value.Value;
+      set => EvaluatedSolutionsParameter.Value.Value = value;
     }
 
     [StorableConstructor]
     private IntervalInterpreter(StorableConstructorFlag _) : base(_) { }
+
     private IntervalInterpreter(IntervalInterpreter original, Cloner cloner)
-        : base(original, cloner) { }
+      : base(original, cloner) { }
 
     public IntervalInterpreter()
-        : base("IntervalInterpreter", "Intperter for calculation of intervals of symbolic models.") {
-      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
+      : base("IntervalInterpreter", "Interpreter for calculation of intervals of symbolic models.") {
+      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName,
+        "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
     }
 
@@ -63,48 +64,63 @@
 
     #region IStatefulItem Members
+
     public void InitializeState() {
       EvaluatedSolutions = 0;
     }
+
     public void ClearState() { }
+
     #endregion
 
-    public Interval GetSymbolicExpressionTreeInterval(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows = null) {
+    public Interval GetSymbolicExpressionTreeInterval(
+      ISymbolicExpressionTree tree, IDataset dataset,
+      IEnumerable<int> rows = null) {
       var variableRanges = DatasetUtil.GetVariableRanges(dataset, rows);
       return GetSymbolicExpressionTreeInterval(tree, variableRanges);
     }
 
-    public Interval GetSymbolicExpressionTreeIntervals(ISymbolicExpressionTree tree, IDataset dataset,
-      out IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals, IEnumerable<int> rows = null) {
+    public Interval GetSymbolicExpressionTreeIntervals(
+      ISymbolicExpressionTree tree, IDataset dataset,
+      out IDictionary<ISymbolicExpressionTreeNode, Interval>
+        nodeIntervals, IEnumerable<int> rows = null) {
       var variableRanges = DatasetUtil.GetVariableRanges(dataset, rows);
       return GetSymbolicExpressionTreeIntervals(tree, variableRanges, out nodeIntervals);
     }
 
-    public Interval GetSymbolicExpressionTreeInterval(ISymbolicExpressionTree tree, IReadOnlyDictionary<string, Interval> variableRanges) {
+    public Interval GetSymbolicExpressionTreeInterval(
+      ISymbolicExpressionTree tree,
+      IReadOnlyDictionary<string, Interval> variableRanges) {
       lock (syncRoot) {
         EvaluatedSolutions++;
       }
-      int instructionCount = 0;
+
+      Interval outputInterval;
+
+      var instructionCount = 0;
       var instructions = PrepareInterpreterState(tree, variableRanges);
-      var outputInterval = Evaluate(instructions, ref instructionCount);
-
-      // because of numerical errors the bounds might be incorrect
-      if (outputInterval.LowerBound <= outputInterval.UpperBound)
-        return outputInterval;
-      else
-        return new Interval(outputInterval.UpperBound, outputInterval.LowerBound);
-    }
-
-
-    public Interval GetSymbolicExpressionTreeIntervals(ISymbolicExpressionTree tree,
-      IReadOnlyDictionary<string, Interval> variableRanges, out IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals) {
+      outputInterval = Evaluate(instructions, ref instructionCount);
+
+      return outputInterval.LowerBound <= outputInterval.UpperBound
+        ? outputInterval
+        : new Interval(outputInterval.UpperBound, outputInterval.LowerBound);
+    }
+
+
+    public Interval GetSymbolicExpressionTreeIntervals(
+      ISymbolicExpressionTree tree,
+      IReadOnlyDictionary<string, Interval> variableRanges,
+      out IDictionary<ISymbolicExpressionTreeNode, Interval>
+        nodeIntervals) {
       lock (syncRoot) {
         EvaluatedSolutions++;
       }
-      int instructionCount = 0;
+
       var intervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>();
       var instructions = PrepareInterpreterState(tree, variableRanges);
-      var outputInterval = Evaluate(instructions, ref instructionCount, intervals);
-
-      // fix incorrect intervals if necessary (could occur because of numerical errors)
+
+      Interval outputInterval;
+      var instructionCount = 0;
+      outputInterval = Evaluate(instructions, ref instructionCount, intervals);
+
       nodeIntervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>();
       foreach (var kvp in intervals) {
@@ -119,39 +135,51 @@
       if (outputInterval.IsInfiniteOrUndefined || outputInterval.LowerBound <= outputInterval.UpperBound)
         return outputInterval;
-      else
-        return new Interval(outputInterval.UpperBound, outputInterval.LowerBound);
-    }
-
-
-    private static Instruction[] PrepareInterpreterState(ISymbolicExpressionTree tree, IReadOnlyDictionary<string, Interval> variableRanges) {
+
+      return new Interval(outputInterval.UpperBound, outputInterval.LowerBound);
+    }
+
+
+    private static Instruction[] PrepareInterpreterState(
+      ISymbolicExpressionTree tree,
+      IReadOnlyDictionary<string, Interval> variableRanges) {
       if (variableRanges == null)
         throw new ArgumentNullException("No variablew ranges are present!", nameof(variableRanges));
 
       //Check if all variables used in the tree are present in the dataset
-      foreach (var variable in tree.IterateNodesPrefix().OfType<VariableTreeNode>().Select(n => n.VariableName).Distinct()) {
-        if (!variableRanges.ContainsKey(variable)) throw new InvalidOperationException($"No ranges for variable {variable} is present");
-      }
-
-      Instruction[] code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
-      foreach (Instruction instr in code.Where(i => i.opCode == OpCodes.Variable)) {
+      foreach (var variable in tree.IterateNodesPrefix().OfType<VariableTreeNode>().Select(n => n.VariableName)
+                                   .Distinct())
+        if (!variableRanges.ContainsKey(variable))
+          throw new InvalidOperationException($"No ranges for variable {variable} is present");
+
+      var code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
+      foreach (var instr in code.Where(i => i.opCode == OpCodes.Variable)) {
         var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
         instr.data = variableRanges[variableTreeNode.VariableName];
       }
+
       return code;
     }
 
-    private Interval Evaluate(Instruction[] instructions, ref int instructionCounter, IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals = null) {
-      Instruction currentInstr = instructions[instructionCounter];
-      //Use ref parameter, because the tree will be iterated through recursively from the left-side branch to the right side
-      //Update instructionCounter, whenever Evaluate is called
+    // Use ref parameter, because the tree will be iterated through recursively from the left-side branch to the right side
+    // Update instructionCounter, whenever Evaluate is called
+    public static Interval Evaluate(
+    Instruction[] instructions, ref int instructionCounter,
+      IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals = null,
+      IReadOnlyDictionary<string, Interval> variableIntervals = null) {
+      var currentInstr = instructions[instructionCounter];
+
       instructionCounter++;
-      Interval result = null;
+      Interval result;
 
       switch (currentInstr.opCode) {
-        //Variables, Constants, ...
         case OpCodes.Variable: {
             var variableTreeNode = (VariableTreeNode)currentInstr.dynamicNode;
             var weightInterval = new Interval(variableTreeNode.Weight, variableTreeNode.Weight);
-            var variableInterval = (Interval)currentInstr.data;
+
+            Interval variableInterval;
+            if (variableIntervals != null && variableIntervals.ContainsKey(variableTreeNode.VariableName))
+              variableInterval = variableIntervals[variableTreeNode.VariableName];
+            else
+              variableInterval = (Interval)currentInstr.data;
 
             result = Interval.Multiply(variableInterval, weightInterval);
@@ -165,102 +193,104 @@
         //Elementary arithmetic rules
         case OpCodes.Add: {
-            result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
-            for (int i = 1; i < currentInstr.nArguments; i++) {
-              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            for (var i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
               result = Interval.Add(result, argumentInterval);
             }
+
             break;
           }
         case OpCodes.Sub: {
-            result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
             if (currentInstr.nArguments == 1)
               result = Interval.Multiply(new Interval(-1, -1), result);
 
-            for (int i = 1; i < currentInstr.nArguments; i++) {
-              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            for (var i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
               result = Interval.Subtract(result, argumentInterval);
             }
+
             break;
           }
         case OpCodes.Mul: {
-            result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
-            for (int i = 1; i < currentInstr.nArguments; i++) {
-              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            for (var i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
               result = Interval.Multiply(result, argumentInterval);
             }
+
             break;
           }
         case OpCodes.Div: {
-            result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
             if (currentInstr.nArguments == 1)
               result = Interval.Divide(new Interval(1, 1), result);
 
-            for (int i = 1; i < currentInstr.nArguments; i++) {
-              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            for (var i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
               result = Interval.Divide(result, argumentInterval);
             }
-            break;
-          }
-        //Trigonometric functions
+
+            break;
+          }
         case OpCodes.Sin: {
-            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
             result = Interval.Sine(argumentInterval);
             break;
           }
         case OpCodes.Cos: {
-            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
             result = Interval.Cosine(argumentInterval);
             break;
           }
         case OpCodes.Tan: {
-            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
             result = Interval.Tangens(argumentInterval);
             break;
           }
         case OpCodes.Tanh: {
-            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
             result = Interval.HyperbolicTangent(argumentInterval);
             break;
           }
-        //Exponential functions
         case OpCodes.Log: {
-            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
             result = Interval.Logarithm(argumentInterval);
             break;
           }
         case OpCodes.Exp: {
-            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
             result = Interval.Exponential(argumentInterval);
             break;
           }
         case OpCodes.Square: {
-            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
             result = Interval.Square(argumentInterval);
             break;
           }
         case OpCodes.SquareRoot: {
-            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
             result = Interval.SquareRoot(argumentInterval);
             break;
           }
         case OpCodes.Cube: {
-            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
             result = Interval.Cube(argumentInterval);
             break;
           }
         case OpCodes.CubeRoot: {
-            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
             result = Interval.CubicRoot(argumentInterval);
             break;
           }
         case OpCodes.Absolute: {
-            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
             result = Interval.Absolute(argumentInterval);
             break;
           }
         case OpCodes.AnalyticQuotient: {
-            result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
-            for (var i = 1; i < currentInstr.nArguments; i++) {
-              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
+            for (var i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
               result = Interval.AnalyticalQuotient(result, argumentInterval);
             }
@@ -272,5 +302,5 @@
       }
 
-      if (nodeIntervals != null)
+      if (!(nodeIntervals == null || nodeIntervals.ContainsKey(currentInstr.dynamicNode)))
         nodeIntervals.Add(currentInstr.dynamicNode, result);
 
@@ -278,9 +308,10 @@
     }
 
+
     public static bool IsCompatible(ISymbolicExpressionTree tree) {
-      var containsUnknownSyumbol = (
+      var containsUnknownSymbols = (
         from n in tree.Root.GetSubtree(0).IterateNodesPrefix()
         where
-          !(n.Symbol is Problems.DataAnalysis.Symbolic.Variable) &&
+          !(n.Symbol is Variable) &&
           !(n.Symbol is Constant) &&
           !(n.Symbol is StartSymbol) &&
@@ -292,4 +323,5 @@
           !(n.Symbol is Cosine) &&
           !(n.Symbol is Tangent) &&
+          !(n.Symbol is HyperbolicTangent) &&
           !(n.Symbol is Logarithm) &&
           !(n.Symbol is Exponential) &&
@@ -301,5 +333,5 @@
           !(n.Symbol is AnalyticQuotient)
         select n).Any();
-      return !containsUnknownSyumbol;
+      return !containsUnknownSymbols;
     }
   }
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/IntervalUtil.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/IntervalUtil.cs	(revision 17902)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/IntervalUtil.cs	(revision 17902)
@@ -0,0 +1,72 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public static class IntervalUtil {
+    public static IEnumerable<double> GetConstraintViolations(
+      IEnumerable<ShapeConstraint> constraints, IBoundsEstimator estimator, IntervalCollection intervalCollection,
+      ISymbolicExpressionTree solution) {
+      return constraints.Select(constraint => GetConstraintViolation(constraint, estimator, intervalCollection, solution)).ToList();
+    }
+
+    public static double GetConstraintViolation(
+      ShapeConstraint constraint, IBoundsEstimator estimator, IntervalCollection variableRanges,
+      ISymbolicExpressionTree tree) {
+      var varRanges = variableRanges.GetReadonlyDictionary();
+
+      if (constraint.Variable != null && !varRanges.ContainsKey(constraint.Variable)) {
+        throw new ArgumentException(
+          $"The given variable {constraint.Variable} in the constraint does not exist in the model.",
+          nameof(constraint));
+      }
+
+      // Create new variable ranges for defined regions
+      var regionRanges = new IntervalCollection();
+      foreach (var kvp in varRanges) {
+        if (constraint.Regions.GetReadonlyDictionary().TryGetValue(kvp.Key, out var val)) {
+          regionRanges.AddInterval(kvp.Key, val);
+        } else {
+          regionRanges.AddInterval(kvp.Key, kvp.Value);
+        }
+      }
+
+      if (!constraint.IsDerivative) {
+        return estimator.GetConstraintViolation(tree, regionRanges, constraint);
+      } else {
+        for (var i = 0; i < constraint.NumberOfDerivations; ++i) {
+          if (!estimator.IsCompatible(tree) || !DerivativeCalculator.IsCompatible(tree)) {
+            throw new ArgumentException("The tree contains an unsupported symbol.");
+          }
+
+          tree = DerivativeCalculator.Derive(tree, constraint.Variable);
+        }
+
+        return estimator.GetConstraintViolation(tree, regionRanges, constraint);
+      }
+    }
+  }
+}
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Views-3.4.csproj
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Views-3.4.csproj	(revision 17901)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Views-3.4.csproj	(revision 17902)
@@ -221,10 +221,4 @@
     <Compile Include="Interfaces\IDataPreprocessorStarter.cs" />
     <Compile Include="Interfaces\IPartialDependencePlot.cs" />
-    <Compile Include="IntervalCollectionView.cs">
-      <SubType>UserControl</SubType>
-    </Compile>
-    <Compile Include="IntervalCollectionView.Designer.cs">
-      <DependentUpon>IntervalCollectionView.cs</DependentUpon>
-    </Compile>
     <Compile Include="MenuItems\ChangeDataOfOptimizersMenuItem.cs" />
     <Compile Include="MenuItems\ShrinkDataAnalysisRunsMenuItem.cs" />
@@ -242,4 +236,9 @@
       <DependentUpon>ProblemDataView.cs</DependentUpon>
     </Compile>
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
     <Compile Include="Regression\ConfidenceRegressionSolutionEstimatedValuesView.cs">
       <SubType>UserControl</SubType>
@@ -254,4 +253,10 @@
       <DependentUpon>ConfidenceRegressionSolutionLineChartView.cs</DependentUpon>
     </Compile>
+    <Compile Include="Regression\IntervalCollectionView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Regression\IntervalCollectionView.Designer.cs">
+      <DependentUpon>IntervalCollectionView.cs</DependentUpon>
+    </Compile>
     <Compile Include="Regression\RegressionEnsembleSolutionModelWeightsView.cs">
       <SubType>UserControl</SubType>
@@ -343,4 +348,16 @@
     <Compile Include="Regression\RegressionSolutionScatterPlotView.Designer.cs">
       <DependentUpon>RegressionSolutionScatterPlotView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Regression\ShapeConstraintsView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Regression\ShapeConstraintsView.Designer.cs">
+      <DependentUpon>ShapeConstraintsView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Regression\ShapeConstraintView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Regression\ShapeConstraintView.Designer.cs">
+      <DependentUpon>ShapeConstraintView.cs</DependentUpon>
     </Compile>
     <Compile Include="Solution Views\ClassificationSolutionView.cs">
@@ -605,11 +622,12 @@
       <DependentUpon>AbstractFeatureCorrelationView.cs</DependentUpon>
     </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
   </ItemGroup>
   <ItemGroup>
-    <Reference Include="HEAL.Attic, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\..\bin\HEAL.Attic.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
+    <EmbeddedResource Include="Resources\shapeConstraintsHelp.rtf" />
+    <None Include="Resources\VS2008ImageLibrary_Annotations_Information.png" />
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Index: unk/HeuristicLab.Problems.DataAnalysis.Views/3.4/IntervalCollectionView.Designer.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/IntervalCollectionView.Designer.cs	(revision 17901)
+++ 	(revision )
@@ -1,82 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-namespace HeuristicLab.Problems.DataAnalysis.Views {
-  partial class IntervalCollectionView {
-    /// <summary> 
-    /// Required designer variable.
-    /// </summary>
-    private System.ComponentModel.IContainer components = null;
-
-    /// <summary> 
-    /// Clean up any resources being used.
-    /// </summary>
-    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
-    protected override void Dispose(bool disposing) {
-      if (disposing && (components != null)) {
-        components.Dispose();
-      }
-      base.Dispose(disposing);
-    }
-
-    #region Component Designer generated code
-
-    /// <summary> 
-    /// Required method for Designer support - do not modify 
-    /// the contents of this method with the code editor.
-    /// </summary>
-    private void InitializeComponent() {
-      this.dataGridView = new System.Windows.Forms.DataGridView();
-      ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).BeginInit();
-      this.SuspendLayout();
-      // 
-      // dataGridView
-      // 
-      this.dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
-      this.dataGridView.Dock = System.Windows.Forms.DockStyle.Fill;
-      this.dataGridView.Location = new System.Drawing.Point(0, 0);
-      this.dataGridView.Margin = new System.Windows.Forms.Padding(4);
-      this.dataGridView.Name = "dataGridView";
-      this.dataGridView.RowHeadersWidth = 120;
-      this.dataGridView.Size = new System.Drawing.Size(643, 505);
-      this.dataGridView.TabIndex = 1;
-      this.dataGridView.CellEndEdit += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView_CellEndEdit);
-      this.dataGridView.CellValidating += new System.Windows.Forms.DataGridViewCellValidatingEventHandler(this.dataGridView_CellValidating);
-      this.dataGridView.CellValueChanged += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView_CellValueChanged);
-      // 
-      // IntervalCollectionView
-      // 
-      this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
-      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-      this.Controls.Add(this.dataGridView);
-      this.Margin = new System.Windows.Forms.Padding(4);
-      this.Name = "IntervalCollectionView";
-      this.Size = new System.Drawing.Size(643, 505);
-      ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).EndInit();
-      this.ResumeLayout(false);
-
-    }
-
-    #endregion
-
-    private System.Windows.Forms.DataGridView dataGridView;
-  }
-}
Index: unk/HeuristicLab.Problems.DataAnalysis.Views/3.4/IntervalCollectionView.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/IntervalCollectionView.cs	(revision 17901)
+++ 	(revision )
@@ -1,153 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-
-using System.Windows.Forms;
-using HeuristicLab.MainForm;
-using HeuristicLab.MainForm.WindowsForms;
-
-namespace HeuristicLab.Problems.DataAnalysis.Views {
-
-  [View("IntervalCollection View")]
-  [Content(typeof(IntervalCollection), true)]
-  public sealed partial class IntervalCollectionView : AsynchronousContentView {
-
-    public new IntervalCollection Content {
-      get => (IntervalCollection)base.Content;
-      set => base.Content = value;
-    }
-
-    private DataGridView DataGridView {
-      get => dataGridView;
-    }
-
-    public IntervalCollectionView() {
-      InitializeComponent();
-      dataGridView.AutoGenerateColumns = false;
-      dataGridView.AllowUserToAddRows = false;
-    }
-
-    protected override void OnContentChanged() {
-      base.OnContentChanged();
-      if (Content == null) {
-        DataGridView.Rows.Clear();
-        DataGridView.Columns.Clear();
-      } else {
-        UpdateData();
-      }
-    }
-
-    protected override void SetEnabledStateOfControls() {
-      base.SetEnabledStateOfControls();
-      dataGridView.Enabled = Content != null;
-      dataGridView.ReadOnly = ReadOnly;
-    }
-
-    private void UpdateData() {
-      DataGridView.Rows.Clear();
-      DataGridView.Columns.Clear();
-      SetColumnNames();
-
-
-      var variablesCount = Content.Count;
-
-      DataGridViewRow[] rows = new DataGridViewRow[variablesCount];
-      for (var i = 0; i < variablesCount; ++i) {
-        var row = new DataGridViewRow();
-        rows[i] = row;
-      }
-      dataGridView.Rows.AddRange(rows);
-
-      var j = 0;
-      foreach (var variableInterval in Content.GetVariableIntervals()) {
-        dataGridView.Rows[j].HeaderCell.Value = variableInterval.Item1;
-        dataGridView.Rows[j].Cells[0].Value = variableInterval.Item2.LowerBound;
-        dataGridView.Rows[j].Cells[1].Value = variableInterval.Item2.UpperBound;
-        j++;
-      }
-
-      dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
-      dataGridView.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders);
-      dataGridView.Enabled = true;
-      //Disable Sorting
-      foreach (DataGridViewColumn column in dataGridView.Columns) {
-        column.SortMode = DataGridViewColumnSortMode.NotSortable;
-      }
-    }
-
-    private void SetColumnNames() {
-      dataGridView.Columns.Add("lowerBound", "Lower Bound");
-      dataGridView.Columns.Add("upperBound", "Upper Bound");
-    }
-
-    private void dataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e) {
-      if (e.ColumnIndex < 0 || e.RowIndex < 0) return;
-
-      var key = dataGridView.Rows[e.RowIndex].HeaderCell.Value.ToString();
-      var gridData = dataGridView[e.ColumnIndex, e.RowIndex].Value;
-      //Cells maybe null during initialization
-      var lowerBound = Content.GetInterval(key).LowerBound;
-      var upperBound = Content.GetInterval(key).UpperBound;
-
-      //Check if the input data is a string (user-defined input)
-      //if so parse the toString() of the value, otherwise do a hard-cast
-      //to not loose the double precision
-      double parsedValue;
-      if (gridData is string) {
-        parsedValue = double.Parse(gridData.ToString());
-      } else {
-        parsedValue = (double)gridData;
-      }
-
-      if (e.ColumnIndex == 0) lowerBound = parsedValue;
-      if (e.ColumnIndex == 1) upperBound = parsedValue;
-
-      var newInterval = new Interval(lowerBound, upperBound);
-
-      // update if there was a change
-      if (!Content.GetInterval(key).Equals(newInterval))
-        Content.SetInterval(key, newInterval);
-    }
-
-    private void dataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) {
-      if (!double.TryParse(e.FormattedValue.ToString(), out var value)) {
-        e.Cancel = true;
-        dataGridView.Rows[e.RowIndex].ErrorText = "Value must be a double value.";
-        return;
-      }
-
-      var lowerBound = double.Parse(dataGridView.Rows[e.RowIndex].Cells[0].Value.ToString());
-      var upperBound = double.Parse(dataGridView.Rows[e.RowIndex].Cells[1].Value.ToString());
-
-      if (e.ColumnIndex == 0 && value > upperBound || e.ColumnIndex == 1 && value < lowerBound) {
-        e.Cancel = true;
-        dataGridView.Rows[e.RowIndex].ErrorText = "Lower bound of interval must be smaller than upper bound.";
-        return;
-      }
-
-      dataGridView[e.ColumnIndex, e.RowIndex].Value = value;
-    }
-
-    private void dataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e) {
-      dataGridView.Rows[e.RowIndex].ErrorText = string.Empty;
-    }
-  }
-}
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Properties/Resources.Designer.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Properties/Resources.Designer.cs	(revision 17902)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Properties/Resources.Designer.cs	(revision 17902)
@@ -0,0 +1,89 @@
+﻿//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace HeuristicLab.Problems.DataAnalysis.Views.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("HeuristicLab.Problems.DataAnalysis.Views.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to {\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang2057{\fonttbl{\f0\fnil\fcharset0 Arial;}{\f1\fnil\fcharset0 Consolas;}{\f2\fnil\fcharset1 Cambria Math;}}
+        ///{\colortbl ;\red0\green0\blue0;}
+        ///{\*\generator Riched20 10.0.18362}{\*\mmathPr\mmathFont2\mwrapIndent1440 }\viewkind4\uc1 
+        ///\pard\sa200\sl276\slmult1\cf1\fs19\lang9 Within the text field you can define different types of shape constraints e.g. range constraints, monotonicity constraints.\par
+        ///
+        ///\pard\sl276\slmult1 To define a model constraint: \par
+        ///
+        ///\p [rest of string was truncated]&quot;;.
+        /// </summary>
+        internal static string shapeConstraintsHelp_rtf {
+            get {
+                return ResourceManager.GetString("shapeConstraintsHelp.rtf", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap VS2008ImageLibrary_Annotations_Information {
+            get {
+                object obj = ResourceManager.GetObject("VS2008ImageLibrary_Annotations_Information", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+    }
+}
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Properties/Resources.resx
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Properties/Resources.resx	(revision 17902)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Properties/Resources.resx	(revision 17902)
@@ -0,0 +1,127 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="shapeConstraintsHelp.rtf" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\shapeConstraintsHelp.rtf;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
+  </data>
+  <data name="VS2008ImageLibrary_Annotations_Information" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\VS2008ImageLibrary_Annotations_Information.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+</root>
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/IntervalCollectionView.Designer.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/IntervalCollectionView.Designer.cs	(revision 17902)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/IntervalCollectionView.Designer.cs	(revision 17902)
@@ -0,0 +1,82 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+  partial class IntervalCollectionView {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.dataGridView = new System.Windows.Forms.DataGridView();
+      ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // dataGridView
+      // 
+      this.dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+      this.dataGridView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.dataGridView.Location = new System.Drawing.Point(0, 0);
+      this.dataGridView.Margin = new System.Windows.Forms.Padding(4);
+      this.dataGridView.Name = "dataGridView";
+      this.dataGridView.RowHeadersWidth = 120;
+      this.dataGridView.Size = new System.Drawing.Size(643, 505);
+      this.dataGridView.TabIndex = 1;
+      this.dataGridView.CellEndEdit += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView_CellEndEdit);
+      this.dataGridView.CellValidating += new System.Windows.Forms.DataGridViewCellValidatingEventHandler(this.dataGridView_CellValidating);
+      this.dataGridView.CellValueChanged += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView_CellValueChanged);
+      // 
+      // IntervalCollectionView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.dataGridView);
+      this.Margin = new System.Windows.Forms.Padding(4);
+      this.Name = "IntervalCollectionView";
+      this.Size = new System.Drawing.Size(643, 505);
+      ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).EndInit();
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.DataGridView dataGridView;
+  }
+}
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/IntervalCollectionView.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/IntervalCollectionView.cs	(revision 17902)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/IntervalCollectionView.cs	(revision 17902)
@@ -0,0 +1,153 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+
+using System.Windows.Forms;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+
+  [View("IntervalCollection View")]
+  [Content(typeof(IntervalCollection), true)]
+  public sealed partial class IntervalCollectionView : AsynchronousContentView {
+
+    public new IntervalCollection Content {
+      get => (IntervalCollection)base.Content;
+      set => base.Content = value;
+    }
+
+    private DataGridView DataGridView {
+      get => dataGridView;
+    }
+
+    public IntervalCollectionView() {
+      InitializeComponent();
+      dataGridView.AutoGenerateColumns = false;
+      dataGridView.AllowUserToAddRows = false;
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      if (Content == null) {
+        DataGridView.Rows.Clear();
+        DataGridView.Columns.Clear();
+      } else {
+        UpdateData();
+      }
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      dataGridView.Enabled = Content != null;
+      dataGridView.ReadOnly = ReadOnly;
+    }
+
+    private void UpdateData() {
+      DataGridView.Rows.Clear();
+      DataGridView.Columns.Clear();
+      SetColumnNames();
+
+
+      var variablesCount = Content.Count;
+
+      DataGridViewRow[] rows = new DataGridViewRow[variablesCount];
+      for (var i = 0; i < variablesCount; ++i) {
+        var row = new DataGridViewRow();
+        rows[i] = row;
+      }
+      dataGridView.Rows.AddRange(rows);
+
+      var j = 0;
+      foreach (var variableInterval in Content.GetVariableIntervals()) {
+        dataGridView.Rows[j].HeaderCell.Value = variableInterval.Item1;
+        dataGridView.Rows[j].Cells[0].Value = variableInterval.Item2.LowerBound;
+        dataGridView.Rows[j].Cells[1].Value = variableInterval.Item2.UpperBound;
+        j++;
+      }
+
+      dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
+      dataGridView.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders);
+      dataGridView.Enabled = true;
+      //Disable Sorting
+      foreach (DataGridViewColumn column in dataGridView.Columns) {
+        column.SortMode = DataGridViewColumnSortMode.NotSortable;
+      }
+    }
+
+    private void SetColumnNames() {
+      dataGridView.Columns.Add("lowerBound", "Lower bound");
+      dataGridView.Columns.Add("upperBound", "Upper bound");
+    }
+
+    private void dataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e) {
+      if (e.ColumnIndex < 0 || e.RowIndex < 0) return;
+
+      var key = dataGridView.Rows[e.RowIndex].HeaderCell.Value.ToString();
+      var gridData = dataGridView[e.ColumnIndex, e.RowIndex].Value;
+      //Cells maybe null during initialization
+      var lowerBound = Content.GetInterval(key).LowerBound;
+      var upperBound = Content.GetInterval(key).UpperBound;
+
+      //Check if the input data is a string (user-defined input)
+      //if so parse the toString() of the value, otherwise do a hard-cast
+      //to not loose the double precision
+      double parsedValue;
+      if (gridData is string) {
+        parsedValue = double.Parse(gridData.ToString());
+      } else {
+        parsedValue = (double)gridData;
+      }
+
+      if (e.ColumnIndex == 0) lowerBound = parsedValue;
+      if (e.ColumnIndex == 1) upperBound = parsedValue;
+
+      var newInterval = new Interval(lowerBound, upperBound);
+
+      // update if there was a change
+      if (!Content.GetInterval(key).Equals(newInterval))
+        Content.SetInterval(key, newInterval);
+    }
+
+    private void dataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) {
+      if (!double.TryParse(e.FormattedValue.ToString(), out var value)) {
+        e.Cancel = true;
+        dataGridView.Rows[e.RowIndex].ErrorText = "Value must be a double value.";
+        return;
+      }
+
+      var lowerBound = double.Parse(dataGridView.Rows[e.RowIndex].Cells[0].Value.ToString());
+      var upperBound = double.Parse(dataGridView.Rows[e.RowIndex].Cells[1].Value.ToString());
+
+      if (e.ColumnIndex == 0 && value > upperBound || e.ColumnIndex == 1 && value < lowerBound) {
+        e.Cancel = true;
+        dataGridView.Rows[e.RowIndex].ErrorText = "Lower bound of interval must be smaller than upper bound.";
+        return;
+      }
+
+      dataGridView[e.ColumnIndex, e.RowIndex].Value = value;
+    }
+
+    private void dataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e) {
+      dataGridView.Rows[e.RowIndex].ErrorText = string.Empty;
+    }
+  }
+}
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/ShapeConstraintView.Designer.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/ShapeConstraintView.Designer.cs	(revision 17902)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/ShapeConstraintView.Designer.cs	(revision 17902)
@@ -0,0 +1,245 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+# endregion
+
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+  partial class ShapeConstraintView {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.components = new System.ComponentModel.Container();
+      this.lowerboundLabel = new System.Windows.Forms.Label();
+      this.upperboundLabel = new System.Windows.Forms.Label();
+      this.variableLabel = new System.Windows.Forms.Label();
+      this.numberOfDerivationLabel = new System.Windows.Forms.Label();
+      this.upperboundInput = new System.Windows.Forms.TextBox();
+      this.lowerboundInput = new System.Windows.Forms.TextBox();
+      this.variableInput = new System.Windows.Forms.TextBox();
+      this.groupBox = new System.Windows.Forms.GroupBox();
+      this.weightTextBox = new System.Windows.Forms.TextBox();
+      this.weightLabel = new System.Windows.Forms.Label();
+      this.regionLabel = new System.Windows.Forms.Label();
+      this.regionView = new HeuristicLab.Problems.DataAnalysis.Views.IntervalCollectionView();
+      this.numberOfDerivationsComboBox = new System.Windows.Forms.ComboBox();
+      this.errorProvider = new System.Windows.Forms.ErrorProvider(this.components);
+      this.groupBox.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // lowerboundLabel
+      // 
+      this.lowerboundLabel.AutoSize = true;
+      this.lowerboundLabel.Location = new System.Drawing.Point(8, 75);
+      this.lowerboundLabel.Name = "lowerboundLabel";
+      this.lowerboundLabel.Size = new System.Drawing.Size(72, 13);
+      this.lowerboundLabel.TabIndex = 4;
+      this.lowerboundLabel.Text = "Lower bound:";
+      // 
+      // upperboundLabel
+      // 
+      this.upperboundLabel.AutoSize = true;
+      this.upperboundLabel.Location = new System.Drawing.Point(8, 101);
+      this.upperboundLabel.Name = "upperboundLabel";
+      this.upperboundLabel.Size = new System.Drawing.Size(72, 13);
+      this.upperboundLabel.TabIndex = 6;
+      this.upperboundLabel.Text = "Upper bound:";
+      // 
+      // variableLabel
+      // 
+      this.variableLabel.AutoSize = true;
+      this.variableLabel.Location = new System.Drawing.Point(8, 22);
+      this.variableLabel.Name = "variableLabel";
+      this.variableLabel.Size = new System.Drawing.Size(48, 13);
+      this.variableLabel.TabIndex = 0;
+      this.variableLabel.Text = "Variable:";
+      // 
+      // numberderivationLabel
+      // 
+      this.numberOfDerivationLabel.AutoSize = true;
+      this.numberOfDerivationLabel.Location = new System.Drawing.Point(8, 48);
+      this.numberOfDerivationLabel.Name = "numberderivationLabel";
+      this.numberOfDerivationLabel.Size = new System.Drawing.Size(58, 13);
+      this.numberOfDerivationLabel.TabIndex = 2;
+      this.numberOfDerivationLabel.Text = "Derivative:";
+      // 
+      // upperboundInput
+      // 
+      this.upperboundInput.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.upperboundInput.Location = new System.Drawing.Point(86, 98);
+      this.upperboundInput.Name = "upperboundInput";
+      this.upperboundInput.Size = new System.Drawing.Size(495, 20);
+      this.upperboundInput.TabIndex = 7;
+      this.upperboundInput.Validating += new System.ComponentModel.CancelEventHandler(this.upperboundInput_Validating);
+      this.upperboundInput.Validated += new System.EventHandler(this.upperboundInput_Validated);
+      // 
+      // lowerboundInput
+      // 
+      this.lowerboundInput.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.lowerboundInput.Location = new System.Drawing.Point(86, 72);
+      this.lowerboundInput.Name = "lowerboundInput";
+      this.lowerboundInput.Size = new System.Drawing.Size(495, 20);
+      this.lowerboundInput.TabIndex = 5;
+      this.lowerboundInput.Validating += new System.ComponentModel.CancelEventHandler(this.lowerboundInput_Validating);
+      this.lowerboundInput.Validated += new System.EventHandler(this.lowerboundInput_Validated);
+      // 
+      // variableInput
+      // 
+      this.variableInput.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.variableInput.Location = new System.Drawing.Point(86, 19);
+      this.variableInput.Name = "variableInput";
+      this.variableInput.Size = new System.Drawing.Size(495, 20);
+      this.variableInput.TabIndex = 1;
+      // 
+      // groupBox
+      // 
+      this.groupBox.Controls.Add(this.weightTextBox);
+      this.groupBox.Controls.Add(this.weightLabel);
+      this.groupBox.Controls.Add(this.regionLabel);
+      this.groupBox.Controls.Add(this.regionView);
+      this.groupBox.Controls.Add(this.numberOfDerivationsComboBox);
+      this.groupBox.Controls.Add(this.variableInput);
+      this.groupBox.Controls.Add(this.lowerboundInput);
+      this.groupBox.Controls.Add(this.upperboundInput);
+      this.groupBox.Controls.Add(this.numberOfDerivationLabel);
+      this.groupBox.Controls.Add(this.variableLabel);
+      this.groupBox.Controls.Add(this.upperboundLabel);
+      this.groupBox.Controls.Add(this.lowerboundLabel);
+      this.groupBox.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.groupBox.Location = new System.Drawing.Point(0, 0);
+      this.groupBox.Name = "groupBox";
+      this.groupBox.Size = new System.Drawing.Size(587, 380);
+      this.groupBox.TabIndex = 0;
+      this.groupBox.TabStop = false;
+      this.groupBox.Text = "Shape Constraint Detail";
+      // 
+      // weightInput
+      // 
+      this.weightTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.weightTextBox.Location = new System.Drawing.Point(86, 124);
+      this.weightTextBox.Name = "weightInput";
+      this.weightTextBox.Size = new System.Drawing.Size(495, 20);
+      this.weightTextBox.TabIndex = 9;
+      this.weightTextBox.TextChanged += new System.EventHandler(this.weightInput_TextChanged);
+      // 
+      // WeightLab
+      // 
+      this.weightLabel.AutoSize = true;
+      this.weightLabel.Location = new System.Drawing.Point(8, 127);
+      this.weightLabel.Name = "WeightLab";
+      this.weightLabel.Size = new System.Drawing.Size(44, 13);
+      this.weightLabel.TabIndex = 8;
+      this.weightLabel.Text = "Weight:";
+      // 
+      // regionLab
+      // 
+      this.regionLabel.AutoSize = true;
+      this.regionLabel.Location = new System.Drawing.Point(8, 150);
+      this.regionLabel.Name = "regionLab";
+      this.regionLabel.Size = new System.Drawing.Size(49, 13);
+      this.regionLabel.TabIndex = 10;
+      this.regionLabel.Text = "Regions:";
+      // 
+      // regionView
+      // 
+      this.regionView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+            | System.Windows.Forms.AnchorStyles.Left)
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.regionView.Caption = "IntervalCollection View";
+      this.regionView.Content = null;
+      this.regionView.Location = new System.Drawing.Point(86, 150);
+      this.regionView.Name = "regionView";
+      this.regionView.ReadOnly = false;
+      this.regionView.Size = new System.Drawing.Size(495, 224);
+      this.regionView.TabIndex = 11;
+      this.regionView.TabStop = false;
+      // 
+      // numberderivationInput
+      // 
+      this.numberOfDerivationsComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.numberOfDerivationsComboBox.FormattingEnabled = true;
+      this.numberOfDerivationsComboBox.Location = new System.Drawing.Point(86, 45);
+      this.numberOfDerivationsComboBox.Name = "numberderivationInput";
+      this.numberOfDerivationsComboBox.Size = new System.Drawing.Size(495, 21);
+      this.numberOfDerivationsComboBox.TabIndex = 3;
+      this.numberOfDerivationsComboBox.SelectedIndexChanged += new System.EventHandler(this.numberderivationInput_SelectedIndexChanged);
+      // 
+      // errorProvider
+      // 
+      this.errorProvider.ContainerControl = this;
+      this.errorProvider.RightToLeft = true;
+      // 
+      // ShapeConstraintView
+      // 
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.Controls.Add(this.groupBox);
+      this.Name = "ShapeConstraintView";
+      this.Size = new System.Drawing.Size(587, 380);
+      this.groupBox.ResumeLayout(false);
+      this.groupBox.PerformLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.Label lowerboundLabel;
+    private System.Windows.Forms.Label upperboundLabel;
+    private System.Windows.Forms.Label variableLabel;
+    private System.Windows.Forms.Label numberOfDerivationLabel;
+    private System.Windows.Forms.TextBox upperboundInput;
+    private System.Windows.Forms.TextBox lowerboundInput;
+    private System.Windows.Forms.TextBox variableInput;
+    private System.Windows.Forms.GroupBox groupBox;
+    private System.Windows.Forms.ErrorProvider errorProvider;
+    private System.Windows.Forms.ComboBox numberOfDerivationsComboBox;
+    private IntervalCollectionView regionView;
+    private System.Windows.Forms.Label regionLabel;
+    private System.Windows.Forms.TextBox weightTextBox;
+    private System.Windows.Forms.Label weightLabel;
+  }
+}
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/ShapeConstraintView.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/ShapeConstraintView.cs	(revision 17902)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/ShapeConstraintView.cs	(revision 17902)
@@ -0,0 +1,204 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#endregion
+
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+  [View("Shape Constraint View")]
+  [Content(typeof(ShapeConstraint), true)]
+  public sealed partial class ShapeConstraintView : ItemView {
+    public new ShapeConstraint Content {
+      get => (ShapeConstraint)base.Content;
+      set => base.Content = value;
+    }
+
+    public ShapeConstraintView() {
+      InitializeComponent();
+      int[] items = { 1, 2, 3 };
+      numberOfDerivationsComboBox.DataSource = items;
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      this.regionView.Content = Content.Regions;
+      UpdateControls();
+    }
+
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.Changed += Content_Changed;
+    }
+
+    protected override void DeregisterContentEvents() {
+      Content.Changed -= Content_Changed;
+      base.DeregisterContentEvents();
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      variableInput.Enabled = Content != null && !Locked && !ReadOnly;
+      numberOfDerivationsComboBox.Enabled = Content != null && !Locked && !ReadOnly;
+      lowerboundInput.Enabled = Content != null && !Locked && !ReadOnly;
+      upperboundInput.Enabled = Content != null && !Locked && !ReadOnly;
+      weightTextBox.Enabled = Content != null && !Locked && !ReadOnly;
+    }
+
+
+    #region helpers
+
+    private static double ParseDoubleValue(string input, Control control, ErrorProvider errorProvider) {
+      input = input.ToLower();
+      switch (input) {
+        case "inf.":
+        case "+inf.":
+        case "Infinity":
+          return double.PositiveInfinity;
+        case "-inf.":
+        case "-Infinity":
+          return double.NegativeInfinity;
+        default: {
+            if (double.TryParse(input, out var value)) {
+              return value;
+            }
+
+            errorProvider.SetError(control, "Invalid input: value must be a double.");
+            return double.NaN;
+          }
+      }
+    }
+
+    private void UpdateControls() {
+      if (Content == null) {
+        lowerboundInput.Text = string.Empty;
+        upperboundInput.Text = string.Empty;
+        weightTextBox.Text = string.Empty;
+        return;
+      }
+
+      lowerboundInput.Text = Content.Interval.LowerBound.ToString();
+      upperboundInput.Text = Content.Interval.UpperBound.ToString();
+      weightTextBox.Text = Content.Weight.ToString();
+
+      variableInput.Text = Content.Variable;
+      if (!Content.IsDerivative) {
+        numberOfDerivationsComboBox.Enabled = false;
+        numberOfDerivationsComboBox.SelectedItem = null;
+        numberOfDerivationsComboBox.Text = "0";
+      } else {
+        numberOfDerivationLabel.Visible = true;
+        numberOfDerivationsComboBox.Visible = true;
+        numberOfDerivationsComboBox.Enabled = true;
+        numberOfDerivationsComboBox.SelectedItem = Content.NumberOfDerivations;
+      }
+
+      regionView.Content = Content.Regions;
+    }
+
+    #endregion
+
+    #region control event handlers
+
+    private void lowerboundInput_Validating(object sender, CancelEventArgs e) {
+      var value = ParseDoubleValue(lowerboundInput.Text, lowerboundInput, errorProvider);
+      if (double.IsNaN(value)) {
+        errorProvider.SetError(lowerboundInput, "Invalid input: lower bound must be a double value.");
+        e.Cancel = true;
+        return;
+      }
+
+      if (value > Content.Interval.UpperBound) {
+        errorProvider.SetError(lowerboundInput, "Invalid input: lower bound must be smaller than upper bound.");
+        e.Cancel = true;
+        return;
+      }
+
+      errorProvider.SetError(lowerboundInput, string.Empty);
+      e.Cancel = false;
+    }
+
+    private void lowerboundInput_Validated(object sender, EventArgs e) {
+      var value =
+        ParseDoubleValue(lowerboundInput.Text, lowerboundInput, errorProvider);
+      if (!double.IsNaN(value)) Content.Interval = new Interval(value, Content.Interval.UpperBound);
+    }
+
+    private void upperboundInput_Validating(object sender, CancelEventArgs e) {
+      var value = ParseDoubleValue(upperboundInput.Text, upperboundInput, errorProvider);
+      if (double.IsNaN(value)) {
+        errorProvider.SetError(upperboundInput, "Invalid Input: upper bound must be a double value.");
+        e.Cancel = true;
+        return;
+      }
+
+      if (value < Content.Interval.LowerBound) {
+        errorProvider.SetError(upperboundInput, "Invalid input: upper bound must be bigger than lower bound.");
+        e.Cancel = true;
+        return;
+      }
+
+      errorProvider.SetError(upperboundInput, string.Empty);
+      e.Cancel = false;
+    }
+
+    private void upperboundInput_Validated(object sender, EventArgs e) {
+      var value =
+        ParseDoubleValue(upperboundInput.Text, upperboundInput, errorProvider);
+      if (!double.IsNaN(value)) Content.Interval = new Interval(Content.Interval.LowerBound, value);
+    }
+
+    private void numberderivationInput_SelectedIndexChanged(object sender, EventArgs e) {
+      if (numberOfDerivationsComboBox.SelectedItem == null) {
+        Content.NumberOfDerivations = 0;
+        numberOfDerivationsComboBox.Enabled = false;
+        return;
+      }
+
+      if ((int)numberOfDerivationsComboBox.SelectedItem == 1)
+        Content.NumberOfDerivations = 1;
+      else if ((int)numberOfDerivationsComboBox.SelectedItem == 2)
+        Content.NumberOfDerivations = 2;
+      else if ((int)numberOfDerivationsComboBox.SelectedItem == 3)
+        Content.NumberOfDerivations = 3;
+    }
+
+    private void weightInput_TextChanged(object sender, EventArgs e) {
+      var value = ParseDoubleValue(weightTextBox.Text, weightTextBox, errorProvider);
+      if (!double.IsNaN(value)) Content.Weight = value;
+    }
+
+
+    #endregion
+
+    #region content event handlers
+
+    private void Content_Changed(object sender, EventArgs e) {
+      UpdateControls();
+    }
+
+   #endregion
+  }
+}
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/ShapeConstraintsView.Designer.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/ShapeConstraintsView.Designer.cs	(revision 17902)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/ShapeConstraintsView.Designer.cs	(revision 17902)
@@ -0,0 +1,184 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#endregion
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+using HeuristicLab.Core.Views;
+
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+  partial class ShapeConstraintsView {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+            this.components = new System.ComponentModel.Container();
+            this.splitContainer = new System.Windows.Forms.SplitContainer();
+            this.groupBox = new System.Windows.Forms.GroupBox();
+            this.constraintsInput = new System.Windows.Forms.TextBox();
+            this.parseBtn = new System.Windows.Forms.Button();
+            this.infoLabel = new System.Windows.Forms.Label();
+            this.errorOutput = new System.Windows.Forms.Label();
+            this.shapeConstraintsView = new HeuristicLab.Core.Views.CheckedItemListView<ShapeConstraint>();
+            this.toolTip = new System.Windows.Forms.ToolTip(this.components);
+            ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
+            this.splitContainer.Panel1.SuspendLayout();
+            this.splitContainer.Panel2.SuspendLayout();
+            this.splitContainer.SuspendLayout();
+            this.groupBox.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // splitContainer1
+            // 
+            this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.splitContainer.Location = new System.Drawing.Point(0, 0);
+            this.splitContainer.Name = "splitContainer1";
+            // 
+            // splitContainer1.Panel1
+            // 
+            this.splitContainer.Panel1.Controls.Add(this.groupBox);
+            // 
+            // splitContainer1.Panel2
+            // 
+            this.splitContainer.Panel2.Controls.Add(this.shapeConstraintsView);
+            this.splitContainer.Size = new System.Drawing.Size(888, 629);
+            this.splitContainer.SplitterDistance = 296;
+            this.splitContainer.TabIndex = 0;
+            // 
+            // groupBox1
+            // 
+            this.groupBox.Controls.Add(this.constraintsInput);
+            this.groupBox.Controls.Add(this.parseBtn);
+            this.groupBox.Controls.Add(this.infoLabel);
+            this.groupBox.Controls.Add(this.errorOutput);
+            this.groupBox.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.groupBox.Location = new System.Drawing.Point(0, 0);
+            this.groupBox.Name = "groupBox1";
+            this.groupBox.Size = new System.Drawing.Size(296, 629);
+            this.groupBox.TabIndex = 3;
+            this.groupBox.TabStop = false;
+            this.groupBox.Text = "Constraints Input";
+            // 
+            // constraintsInput
+            // 
+            this.constraintsInput.AcceptsTab = true;
+            this.constraintsInput.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.constraintsInput.Location = new System.Drawing.Point(3, 29);
+            this.constraintsInput.Multiline = true;
+            this.constraintsInput.Name = "constraintsInput";
+            this.constraintsInput.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.constraintsInput.Size = new System.Drawing.Size(290, 561);
+            this.constraintsInput.TabIndex = 2;
+            this.constraintsInput.TextChanged += new System.EventHandler(this.constraintsInput_TextChanged);
+            // 
+            // parseBtn
+            // 
+            this.parseBtn.Dock = System.Windows.Forms.DockStyle.Bottom;
+            this.parseBtn.Location = new System.Drawing.Point(3, 590);
+            this.parseBtn.Name = "parseBtn";
+            this.parseBtn.Size = new System.Drawing.Size(290, 23);
+            this.parseBtn.TabIndex = 1;
+            this.parseBtn.Text = "Parse Constraints";
+            this.parseBtn.UseVisualStyleBackColor = true;
+            this.parseBtn.Click += new System.EventHandler(this.parseBtn_Click);
+            // 
+            // label1
+            // 
+            this.infoLabel.AutoSize = true;
+            this.infoLabel.Dock = System.Windows.Forms.DockStyle.Top;
+            this.infoLabel.Image = global::HeuristicLab.Problems.DataAnalysis.Views.Properties.Resources.VS2008ImageLibrary_Annotations_Information;
+            this.infoLabel.Location = new System.Drawing.Point(3, 16);
+            this.infoLabel.Name = "label1";
+            this.infoLabel.Size = new System.Drawing.Size(19, 13);
+            this.infoLabel.TabIndex = 4;
+            this.infoLabel.Text = "    ";
+            this.toolTip.SetToolTip(this.infoLabel, "Double-click to open description.");
+            this.infoLabel.DoubleClick += new System.EventHandler(this.helpButton_DoubleClick);
+            // 
+            // errorOutput
+            // 
+            this.errorOutput.AutoSize = true;
+            this.errorOutput.Dock = System.Windows.Forms.DockStyle.Bottom;
+            this.errorOutput.ForeColor = System.Drawing.Color.DarkRed;
+            this.errorOutput.Location = new System.Drawing.Point(3, 613);
+            this.errorOutput.MaximumSize = new System.Drawing.Size(350, 0);
+            this.errorOutput.Name = "errorOutput";
+            this.errorOutput.Size = new System.Drawing.Size(35, 13);
+            this.errorOutput.TabIndex = 3;
+            this.errorOutput.Text = "label2";
+            // 
+            // intervalConstraintsView
+            // 
+            this.shapeConstraintsView.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.shapeConstraintsView.Location = new System.Drawing.Point(0, 0);
+            this.shapeConstraintsView.Name = "intervalConstraintsView";
+            this.shapeConstraintsView.Size = new System.Drawing.Size(588, 629);
+            this.shapeConstraintsView.TabIndex = 2;
+            this.shapeConstraintsView.TabStop = false;
+            // 
+            // ShapeConstraintsView
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.splitContainer);
+            this.Name = "ShapeConstraintsView";
+            this.Size = new System.Drawing.Size(888, 629);
+            this.splitContainer.Panel1.ResumeLayout(false);
+            this.splitContainer.Panel2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
+            this.splitContainer.ResumeLayout(false);
+            this.groupBox.ResumeLayout(false);
+            this.groupBox.PerformLayout();
+            this.ResumeLayout(false);
+
+    }
+    #endregion
+
+    private System.Windows.Forms.SplitContainer splitContainer;
+    private System.Windows.Forms.GroupBox groupBox;
+    private System.Windows.Forms.Button parseBtn;
+    private HeuristicLab.Core.Views.CheckedItemListView<ShapeConstraint> shapeConstraintsView;
+    private System.Windows.Forms.TextBox constraintsInput;
+    private Label errorOutput;
+    private Label infoLabel;
+    protected ToolTip toolTip;
+    }
+}
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/ShapeConstraintsView.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/ShapeConstraintsView.cs	(revision 17902)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/ShapeConstraintsView.cs	(revision 17902)
@@ -0,0 +1,177 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#endregion
+
+using System;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.Collections;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+  [View("ShapeConstraints View")]
+  [Content(typeof(ShapeConstraints), true)]
+  public partial class ShapeConstraintsView : AsynchronousContentView {
+    public new ShapeConstraints Content {
+      get => (ShapeConstraints)base.Content;
+      set => base.Content = value;
+    }
+
+    public bool suspendUpdates = false;
+
+    public ShapeConstraintsView() {
+      InitializeComponent();
+      errorOutput.Text = "";
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      this.shapeConstraintsView.Content = Content;
+      UpdateControl();
+    }
+
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.ItemsAdded += constraints_Added;
+      Content.ItemsRemoved += constraint_Removed;
+      Content.Changed += Content_Changed;
+      Content.CollectionReset += constraints_Reset;
+      Content.ItemsMoved += constraints_Moved;
+      Content.ItemsReplaced += Content_ItemsReplaced;
+      Content.CheckedItemsChanged += Content_CheckedItemsChanged;
+    }
+
+
+    protected override void DeregisterContentEvents() {
+      Content.ItemsAdded -= constraints_Added;
+      Content.ItemsRemoved -= constraint_Removed;
+      Content.Changed -= Content_Changed;
+      Content.CollectionReset -= constraints_Reset;
+      Content.ItemsMoved -= constraints_Moved;
+      Content.ItemsReplaced -= Content_ItemsReplaced;
+      Content.CheckedItemsChanged -= Content_CheckedItemsChanged;
+      base.DeregisterContentEvents();
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      constraintsInput.Enabled = Content != null && !Locked && !ReadOnly;
+    }
+
+
+    private void parseBtn_Click(object sender, EventArgs e) {
+      if (constraintsInput.Text != null) {
+        suspendUpdates = true;
+        Content.Clear();
+        try {
+          var parsedConstraints = ShapeConstraintsParser.ParseConstraints(constraintsInput.Text);
+          Content.AddRange(parsedConstraints);
+          errorOutput.Text = "Constraints successfully parsed.";
+          errorOutput.ForeColor = Color.DarkGreen;
+        } catch (ArgumentException ex) {
+          errorOutput.Text = ex.Message.Replace("Parameter name", "@Line");
+          errorOutput.ForeColor = Color.DarkRed;
+        } finally {
+          suspendUpdates = false;
+        }
+      } else {
+        errorOutput.Text = "No constraints were found!";
+      }
+    }
+
+    private void UpdateControl() {
+      if (suspendUpdates) return;
+      if (Content == null) {
+        constraintsInput.Text = string.Empty;
+      } else {
+        var newText = ToString(Content);
+        if (newText != constraintsInput.Text)
+          constraintsInput.Text = newText;
+      }
+    }
+
+    private string ToString(ShapeConstraints constraints) {
+      var sb = new StringBuilder();
+      foreach (var constraint in constraints) {
+        if (!constraints.ItemChecked(constraint)) {
+          sb.Append("# ").AppendLine(constraint.ToString());
+        } else {
+          sb.AppendLine(constraint.ToString());
+        }
+      }
+      return sb.ToString();
+    }
+
+    private void constraint_Changed(object sender, EventArgs e) {
+      UpdateControl();
+    }
+
+    private void constraints_Added(object sender,
+                                     CollectionItemsChangedEventArgs<IndexedItem<ShapeConstraint>> e) {
+      foreach (var addedItem in e.Items) addedItem.Value.Changed += constraint_Changed;
+      UpdateControl();
+    }
+
+    private void constraint_Removed(object sender, CollectionItemsChangedEventArgs<IndexedItem<ShapeConstraint>> e) {
+      foreach (var removedItem in e.Items) removedItem.Value.Changed -= constraint_Changed;
+      UpdateControl();
+    }
+
+    private void constraints_Moved(object sender, CollectionItemsChangedEventArgs<IndexedItem<ShapeConstraint>> e) {
+      UpdateControl();
+    }
+
+    private void constraints_Reset(object sender, CollectionItemsChangedEventArgs<IndexedItem<ShapeConstraint>> e) {
+      foreach (var addedItem in e.Items) addedItem.Value.Changed += constraint_Changed;
+      foreach (var removedItem in e.OldItems) removedItem.Value.Changed -= constraint_Changed;
+      UpdateControl();
+    }
+
+    private void Content_CheckedItemsChanged(object sender, CollectionItemsChangedEventArgs<IndexedItem<ShapeConstraint>> e) {
+      UpdateControl();
+    }
+
+    private void Content_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<ShapeConstraint>> e) {
+      foreach (var addedItem in e.Items) addedItem.Value.Changed += constraint_Changed;
+      foreach (var removedItem in e.OldItems) removedItem.Value.Changed -= constraint_Changed;
+      UpdateControl();
+    }
+
+    private void constraintsInput_TextChanged(object sender, EventArgs e) {
+      errorOutput.Text = "Unparsed changes! Press parse button to save changes.";
+      errorOutput.ForeColor = Color.DarkOrange;
+    }
+
+    private void Content_Changed(object sender, EventArgs e) {
+      UpdateControl();
+    }
+
+    private void helpButton_DoubleClick(object sender, EventArgs e) {
+      using (InfoBox dialog = new InfoBox("Help for shape constraints",
+        "HeuristicLab.Problems.DataAnalysis.Views.Resources.shapeConstraintsHelp.rtf",
+        this)) {
+        dialog.ShowDialog(this);
+      }
+    }
+  }
+}
Index: /trunk/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 17901)
+++ /trunk/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 17902)
@@ -142,7 +142,10 @@
     <Compile Include="Implementation\Interval\Interval.cs" />
     <Compile Include="Implementation\Interval\IntervalCollection.cs" />
+    <Compile Include="Implementation\Interval\ShapeConstraint.cs" />
+    <Compile Include="Implementation\Interval\ShapeConstraintsParser.cs" />
     <Compile Include="Implementation\Regression\ConfidenceBoundRegressionSolution.cs" />
     <Compile Include="Implementation\Regression\ConstantRegressionModel.cs" />
     <Compile Include="Implementation\Regression\ConstantRegressionSolution.cs" />
+    <Compile Include="Implementation\Regression\ShapeConstraints.cs" />
     <Compile Include="Implementation\Regression\RegressionEnsembleProblemData.cs" />
     <Compile Include="Implementation\Regression\RegressionEnsembleModel.cs">
Index: /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/Interval.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/Interval.cs	(revision 17901)
+++ /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/Interval.cs	(revision 17902)
@@ -33,4 +33,6 @@
     [Storable]
     public double UpperBound { get; private set; }
+
+    public double Width => UpperBound - LowerBound;
 
     [StorableConstructor]
@@ -67,4 +69,6 @@
     }
 
+    private Interval(double v) : this(v, v) { }
+
     public bool Contains(double value) {
       return LowerBound <= value && value <= UpperBound;
@@ -126,6 +130,6 @@
         return false;
 
-      return (UpperBound.IsAlmost(other.UpperBound) || (double.IsNaN(UpperBound) && double.IsNaN(other.UpperBound)))
-        && (LowerBound.IsAlmost(other.LowerBound) || (double.IsNaN(LowerBound) && double.IsNaN(other.LowerBound)));
+      return (UpperBound==other.UpperBound || (double.IsNaN(UpperBound) && double.IsNaN(other.UpperBound)))
+        && (LowerBound==other.LowerBound || (double.IsNaN(LowerBound) && double.IsNaN(other.LowerBound)));
     }
 
@@ -276,4 +280,34 @@
     }
     #endregion
+
+    #region arithmetic overloads
+    public static Interval operator +(Interval a, Interval b) => Add(a, b);
+    public static Interval operator +(Interval a, double b) => Add(a, new Interval(b));
+    public static Interval operator +(double a, Interval b) => Add(new Interval(a), b);
+    public static Interval operator -(Interval a, Interval b) => Subtract(a, b);
+    public static Interval operator -(Interval a, double b) => Subtract(a, new Interval(b));
+    public static Interval operator -(double a, Interval b) => Subtract(new Interval(a), b);
+    public static Interval operator -(Interval a) => Subtract(new Interval(0), a);
+    public static Interval operator *(Interval a, Interval b) => Multiply(a, b);
+    public static Interval operator *(Interval a, double b) => Multiply(a, new Interval(b));
+    public static Interval operator *(double a, Interval b) => Multiply(new Interval(a), b);
+    public static Interval operator /(Interval a, Interval b) => Divide(a, b);
+    public static Interval operator /(Interval a, double b) => Divide(a, new Interval(b));
+    public static Interval operator /(double a, Interval b) => Divide(new Interval(a), b);
+    public static Interval Exponential(double a) { return Exponential(new Interval(a)); }
+    public static Interval Logarithm(double a) { return Logarithm(new Interval(a)); }
+    public static Interval Sine(double a) { return Sine(new Interval(a)); }
+    public static Interval Cosine(double a) { return Cosine(new Interval(a)); }
+    public static Interval Tangens(double a) { return Tangens(new Interval(a)); }
+    public static Interval HyperbolicTangent(double a) { return HyperbolicTangent(new Interval(a)); }
+    public static Interval Square(double a) { return Square(new Interval(a)); }
+    public static Interval Cube(double a) { return Cube(new Interval(a)); }
+    public static Interval SquareRoot(double a) { return SquareRoot(new Interval(a)); }
+    public static Interval CubicRoot(double a) { return CubicRoot(new Interval(a)); }
+    public static Interval Absolute(double a) { return Absolute(new Interval(a)); }
+    public static Interval AnalyticQuotient(Interval a, double b) { return AnalyticalQuotient(a, new Interval(b)); }
+    public static Interval AnalyticQuotient(double a, Interval b) { return AnalyticalQuotient(new Interval(a), b); }
+    public static Interval AnalyticQuotient(double a, double b) { return AnalyticalQuotient(new Interval(a), new Interval(b)); }
+    #endregion
   }
 }
Index: /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/IntervalCollection.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/IntervalCollection.cs	(revision 17901)
+++ /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/IntervalCollection.cs	(revision 17902)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -34,20 +34,34 @@
       get => HeuristicLab.Common.Resources.VSImageLibrary.Object;
     }
-    private IDictionary<string, Interval> intervals { get; } = new Dictionary<string, Interval>();
 
-    [Storable(Name = "StorableIntervalInformation")]
+    //[Storable]
+    private IDictionary<string, Interval> intervals { get; set; } = new Dictionary<string, Interval>();
+
+    [Storable(OldName = "StorableIntervalInformation")]
     private KeyValuePair<string, double[]>[] StorableIntervalInformation {
+      set {
+        foreach (var varInt in value)
+          intervals.Add(varInt.Key, new Interval(varInt.Value[0], varInt.Value[1]));
+      }
+    }
+
+    [Storable]
+    private object[] StorableIntervals {
       get {
-        var l = new List<KeyValuePair<string, double[]>>();
-        foreach (var varInt in intervals)
+        var names = intervals.Keys.ToArray();
+        var lowerBounds = intervals.Values.Select(i => i.LowerBound).ToArray();
+        var upperBounds = intervals.Values.Select(i => i.UpperBound).ToArray();
 
-          l.Add(new KeyValuePair<string, double[]>(varInt.Key,
-            new double[] { varInt.Value.LowerBound, varInt.Value.UpperBound }));
-        return l.ToArray();
+        return new object[] { names, lowerBounds, upperBounds };
       }
 
       set {
-        foreach (var varInt in value)
-          intervals.Add(varInt.Key, new Interval(varInt.Value[0], varInt.Value[1]));
+        var names = (string[])value[0];
+        var lowerBounds = (double[])value[1];
+        var upperBounds = (double[])value[2];
+
+        for (int i = 0; i < names.Length; i++) {
+          intervals.Add(names[i], new Interval(lowerBounds[i], upperBounds[i]));
+        }
       }
     }
@@ -80,15 +94,22 @@
     public void SetInterval(string identifier, Interval interval) {
       intervals[identifier] = interval;
+      RaiseChanged();
     }
 
     public void AddInterval(string identifier, Interval interval) {
       intervals.Add(identifier, interval);
+      RaiseChanged();
     }
 
     public void DeleteInterval(string identifier) {
       intervals.Remove(identifier);
+      RaiseChanged();
     }
 
     public IReadOnlyDictionary<string, Interval> GetReadonlyDictionary() {
+      return intervals.ToDictionary(pair => pair.Key, pair => pair.Value);
+    }
+
+    public IDictionary<string, Interval> GetDictionary() {
       return intervals.ToDictionary(pair => pair.Key, pair => pair.Value);
     }
@@ -98,4 +119,12 @@
         yield return Tuple.Create(variableInterval.Key, variableInterval.Value);
     }
+
+    public event EventHandler Changed;
+    private void RaiseChanged() {
+      var handler = Changed;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+
   }
 }
Index: /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/ShapeConstraint.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/ShapeConstraint.cs	(revision 17902)
+++ /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/ShapeConstraint.cs	(revision 17902)
@@ -0,0 +1,207 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#endregion
+using System;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableType("8109BE58-CCFB-4462-A2F4-EEE5DFADAFF7")]
+  [Item("ShapeConstraint", "Constraint on the shape of a function e.g. monotonicity.")]
+  public sealed class ShapeConstraint : Item {
+    [Storable]
+    private string variable;
+
+    public string Variable {
+      get => variable;
+      private set {
+        if (variable == value)
+          return;
+        variable = value;
+        OnToStringChanged();
+        OnChanged();
+      }
+    }
+
+    public bool IsDerivative => NumberOfDerivations > 0;
+
+    [Storable]
+    private int numberOfDerivations;
+
+    public int NumberOfDerivations {
+      get => numberOfDerivations;
+      set {
+        if (value < 0 || value > 3)
+          throw new ArgumentException("Number of derivation has to be between 0 - 3.");
+        if (numberOfDerivations == value)
+          return;
+        numberOfDerivations = value;
+        OnToStringChanged();
+        OnChanged();
+      }
+    }
+
+    [Storable]
+    private Interval interval;
+
+    public Interval Interval {
+      get => interval;
+      set {
+        if (interval == value)
+          return;
+        interval = value;
+        OnToStringChanged();
+        OnChanged();
+      }
+    }
+
+    [Storable]
+    private IntervalCollection regions;
+    public IntervalCollection Regions {
+      get => regions;
+      set {
+        if (regions != value) {
+          if (regions != null) regions.Changed -= regions_Changed;
+          regions = value;
+          if (regions != null) regions.Changed += regions_Changed;
+          OnToStringChanged();
+          OnChanged();
+        }
+      }
+    }
+
+
+    [Storable]
+    private double weight = 1.0;
+    public double Weight {
+      get => weight;
+      set {
+        if (weight <= 0.0) throw new ArgumentOutOfRangeException("Weight must be larger than zero.");
+        if (weight != value) {
+          weight = value;
+          OnToStringChanged();
+          OnChanged();
+        }
+      }
+    }
+
+    [StorableConstructor]
+    private ShapeConstraint(StorableConstructorFlag _) : base(_) { }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (regions != null) regions.Changed += regions_Changed;
+    }
+
+    // without derivation
+    public ShapeConstraint(Interval interval, double weight)
+      : this(string.Empty, 0,
+         interval, new IntervalCollection(), weight) { }
+
+    public ShapeConstraint(Interval interval, IntervalCollection regions, double weight)
+      : this(string.Empty, 0,
+         interval, regions, weight) { }
+
+    public ShapeConstraint(string variable, int numberOfDerivations,
+                              Interval interval, double weight)
+      : this(variable, numberOfDerivations,
+             interval, new IntervalCollection(), weight) { }
+
+    public ShapeConstraint(string variable, int numberOfDerivations,
+                              Interval interval, IntervalCollection regions, double weight) {
+      Variable = variable;
+      NumberOfDerivations = numberOfDerivations;
+      Interval = interval;
+      Regions = regions;
+      Weight = weight;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ShapeConstraint(this, cloner);
+    }
+
+    private ShapeConstraint(ShapeConstraint original, Cloner cloner)
+      : base(original, cloner) {
+      Variable = original.Variable;
+      NumberOfDerivations = original.NumberOfDerivations;
+      Interval = original.Interval;
+      Regions = cloner.Clone(original.Regions);
+      Weight = original.weight;
+    }
+
+    public event EventHandler Changed;
+
+    private void OnChanged() {
+      var handlers = Changed;
+      if (handlers != null)
+        handlers(this, EventArgs.Empty);
+    }
+
+
+    private void regions_Changed(object sender, EventArgs e) {
+      OnToStringChanged();
+      OnChanged();
+    }
+
+    public override string ToString() {
+      return GenerateExpressionString();
+    }
+
+
+    private string GenerateExpressionString() {
+      string expression;
+
+      if (!IsDerivative) {
+        expression = string.Format($"f in [{Interval?.LowerBound} .. {Interval?.UpperBound}]");
+        if (Regions != null) {
+          foreach (var region in Regions.GetReadonlyDictionary())
+            expression += $", {region.Key} in [{region.Value.LowerBound} .. {region.Value.UpperBound}]";
+        }
+        if (Weight != 1.0) {
+          expression += $" weight: {weight}";
+        }
+
+        return expression;
+      }
+
+      var derivationString = string.Empty;
+      switch (numberOfDerivations) {
+        case 1:
+          derivationString = ""; break;
+        case 2:
+          derivationString = "²"; break;
+        case 3:
+          derivationString = "³"; break;
+      }
+      expression = string.Format($"∂{derivationString}f/∂{Variable}{derivationString} in [{Interval?.LowerBound} .. {Interval?.UpperBound}]");
+      if (Regions != null) {
+        foreach (var region in Regions.GetReadonlyDictionary())
+          expression += $", {region.Key} in [{region.Value.LowerBound} .. {region.Value.UpperBound}]";
+      }
+      if (Weight != 1.0) {
+        expression += $" weight: {weight}";
+      }
+      return expression;
+    }
+  }
+}
Index: /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/ShapeConstraintsParser.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/ShapeConstraintsParser.cs	(revision 17902)
+++ /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/ShapeConstraintsParser.cs	(revision 17902)
@@ -0,0 +1,242 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public static class ShapeConstraintsParser {
+    public static ShapeConstraints ParseConstraints(string text) {
+      if (string.IsNullOrEmpty(text)) throw new ArgumentNullException(nameof(text));
+
+      var lines = text.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
+
+      var sc = new ShapeConstraints();
+      foreach (var line in lines) {
+        var trimmedLine = line.Trim();
+        if (trimmedLine == "") continue; // If it is a comment just continue without saving anything
+        if (trimmedLine.StartsWith("#")) {
+          // disabled constraints are commented
+          var constraint = ParseConstaint(trimmedLine.TrimStart('#', ' '));
+          sc.Add(constraint);
+          sc.SetItemCheckedState(constraint, false);
+        } else {
+          var constraint = ParseConstaint(trimmedLine);
+          sc.Add(constraint);
+          sc.SetItemCheckedState(constraint, true);
+        }
+      }
+      return sc;
+    }
+
+    public static ShapeConstraint ParseConstaint(string expr) {
+      var trimmedLine = expr.TrimStart();
+      if (trimmedLine.StartsWith("f")) {
+        return ParseFunctionRangeConstraint(expr);
+      } else if (trimmedLine.StartsWith("d") || trimmedLine.StartsWith("∂")) {
+        return ParseDerivationConstraint(expr);
+      } else {
+        throw new
+          ArgumentException("Error at your constraints definition constraints have to start with (f | d | ∂ | #)",
+                            nameof(expr));
+      }
+    }
+
+    // [124 .. 145]
+    private const string intervalRegex = @"\s*[\[]" +
+                                         @"\s*(?<lowerBound>[^\s\.;]*)" +
+                                         @"\s*(\.{2}|\s+|;)" +
+                                         @"\s*(?<upperBound>[^\s\]]*)" +
+                                         @"\s*[\]]";
+
+    private const string variableRegex = @"(['](?<varName>.*)[']|(?<varName>[^\s²³]+))\s*";
+    private const string weightRegex = @"\s*(weight:\s*(?<weight>\S*))?";
+    public static ShapeConstraint ParseFunctionRangeConstraint(string expr) {
+      if (!expr.StartsWith("f")) throw new ArgumentException("Invalid function range constraint (e.g. f in [1..2])", nameof(expr));
+      var start = "f".Length;
+      var end = expr.Length;
+      var targetConstraint = expr.Substring(start, end - start);
+
+
+      // # Example for a target variable constraint:
+      // f in [0 .. 100]
+      // # Example for constraints on model parameters: 
+      // df/d'x' in [0 .. 10]
+      // ∂²f/∂'x'² in [-1 .. inf.]
+      // df/d'x' in [0 .. 10] weight: 2.0
+      // df / d'x' in [0..10], 'x' in [1 .. 3]
+      // df / d'x' in [0..10], 'x' in [1 .. 3], y in [10..30] weight: 1.2
+
+      var match = Regex.Match(targetConstraint,
+                    @"\s*\bin\b" +
+                    intervalRegex +
+                    @"(" +
+                      @"\s*,\s*"+ variableRegex +
+                      @"\s *\bin\b" +
+                      intervalRegex +
+                    @")*" +
+                    weightRegex
+                    ); 
+
+
+      if (match.Success) {
+        // if (match.Groups.Count < 19) throw new ArgumentException("The target-constraint is not complete.", nameof(expr));
+
+        var lowerBound = ParseIntervalBounds(match.Groups["lowerBound"].Captures[0].Value);
+        var upperBound = ParseIntervalBounds(match.Groups["upperBound"].Captures[0].Value);
+        var interval = new Interval(lowerBound, upperBound);
+        var weight = 1.0;
+
+        if (match.Groups["weight"].Success && !string.IsNullOrWhiteSpace(match.Groups["weight"].Value))
+          weight = ParseAndValidateDouble(match.Groups["weight"].Value);
+
+        if (match.Groups["varName"].Success) {
+          IntervalCollection regions = new IntervalCollection();
+          // option variables found
+          for (int idx = 0; idx < match.Groups["varName"].Captures.Count; ++idx) {
+            KeyValuePair<string, Interval> region = ParseRegion(
+              variable: match.Groups["varName"].Captures[idx].Value,
+              lb: match.Groups["lowerBound"].Captures[idx + 1].Value,
+              ub: match.Groups["upperBound"].Captures[idx + 1].Value);
+            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.");
+          }
+          return new ShapeConstraint(interval, regions, weight);
+        } else
+          return new ShapeConstraint(interval, weight);
+      } else
+        throw new ArgumentException("The inserted target constraint is not valid.", nameof(expr));
+    }
+    public static ShapeConstraint ParseDerivationConstraint(string expr) {
+      var match = Regex.Match(expr,
+                                @"([d∂])" +
+                                @"(?<numDerivations>[²³]?)\s*" +
+                                @"f\s*" +
+                                @"(\/)\s*" +
+                                @"([d∂])\s*" +
+                                variableRegex +
+                                @"(?<numDerivations>[²³]?)\s*\bin\b\s*" +
+                                intervalRegex +
+                                @"(" +
+                                  @"\s*,\s*" + variableRegex +
+                                  @"\s *\bin\b" +
+                                  intervalRegex +
+                                  @")*" +
+                                weightRegex
+                                ); 
+
+      if (match.Success) {
+        // if (match.Groups.Count < 26)
+        //   throw new ArgumentException("The given derivation-constraint is not complete.", nameof(expr));
+
+        var derivationVariable = match.Groups["varName"].Captures[0].Value.Trim();
+
+        var enumeratorNumDeriv = match.Groups["numDerivations"].Captures[0].Value.Trim();
+        var denominatorNumDeriv = match.Groups["numDerivations"].Captures[1].Value.Trim();
+        if (enumeratorNumDeriv != "" || denominatorNumDeriv != "") {
+          if (enumeratorNumDeriv == "" || denominatorNumDeriv == "")
+            throw new ArgumentException("Number of derivation has to be written on both sides.", nameof(expr));
+          if (enumeratorNumDeriv != denominatorNumDeriv)
+            throw new ArgumentException("Derivation number is not equal on both sides.", nameof(expr));
+        }
+
+        var lowerBound = ParseIntervalBounds(match.Groups["lowerBound"].Captures[0].Value);
+        var upperBound = ParseIntervalBounds(match.Groups["upperBound"].Captures[0].Value);
+        var variable = derivationVariable;
+        var numberOfDerivation = ParseDerivationCount(enumeratorNumDeriv);
+        var interval = new Interval(lowerBound, upperBound);
+        var weight = 1.0;
+
+        if (match.Groups["weight"].Success && !string.IsNullOrWhiteSpace(match.Groups["weight"].Value))
+          weight = ParseAndValidateDouble(match.Groups["weight"].Value);
+
+        if (match.Groups["varName"].Captures.Count > 1) {
+          IntervalCollection regions = new IntervalCollection();
+          // option variables found
+          for (int idx = 0; idx < match.Groups["varName"].Captures.Count - 1; ++idx) {
+            KeyValuePair<string, Interval> region = ParseRegion(
+              variable: match.Groups["varName"].Captures[idx + 1].Value,
+              lb: match.Groups["lowerBound"].Captures[idx + 1].Value,
+              ub: match.Groups["upperBound"].Captures[idx + 1].Value);
+            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.");
+          }
+          return new ShapeConstraint(variable, numberOfDerivation, interval, regions, weight);
+        } else
+          return new ShapeConstraint(variable, numberOfDerivation, interval, weight);
+      } else
+        throw new ArgumentException("The inserted derivation constraint is not valid.", nameof(expr));
+    }
+
+
+    private static KeyValuePair<string, Interval> ParseRegion(string variable, string lb, string ub) {
+      var regionLb = ParseIntervalBounds(lb);
+      var regionUb = ParseIntervalBounds(ub);
+      return new KeyValuePair<string, Interval>(variable, new Interval(regionLb, regionUb));
+    }
+
+    private static double ParseIntervalBounds(string input) {
+      input = input.ToLower();
+      switch (input) {
+        case "+inf.":
+        case "inf.":
+          return double.PositiveInfinity;
+        case "-inf.":
+          return double.NegativeInfinity;
+        default: {
+            return ParseAndValidateDouble(input);
+          }
+      }
+    }
+
+    private static double ParseAndValidateDouble(string input) {
+      var valid = double.TryParse(input, out var value);
+      if (!valid) {
+        throw new ArgumentException("Invalid value (valid value format: \"" + FormatPatterns.GetDoubleFormatPattern() + "\")");
+      }
+
+      return value;
+    }
+
+    private static int ParseDerivationCount(string input) {
+      switch (input) {
+        case "":
+          return 1;
+        case "²":
+          return 2;
+        case "³":
+          return 3;
+        default:
+          int.TryParse(input, out var value);
+          return value;
+      }
+    }
+  }
+}
Index: /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblemData.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblemData.cs	(revision 17901)
+++ /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblemData.cs	(revision 17902)
@@ -35,5 +35,5 @@
     protected const string TargetVariableParameterName = "TargetVariable";
     protected const string VariableRangesParameterName = "VariableRanges";
-    protected const string IntervalConstraintsParameterName = "IntervalConstraints";
+    protected const string ShapeConstraintsParameterName = "ShapeConstraints";
     public string Filename { get; set; }
 
@@ -94,4 +94,5 @@
       problemData.Parameters.Add(new ConstrainedValueParameter<StringValue>(TargetVariableParameterName, new ItemSet<StringValue>()));
       problemData.Parameters.Add(new FixedValueParameter<IntervalCollection>(VariableRangesParameterName, "", new IntervalCollection()));
+      problemData.Parameters.Add(new FixedValueParameter<ShapeConstraints>(ShapeConstraintsParameterName, "", new ShapeConstraints()));
       emptyProblemData = problemData;
     }
@@ -107,4 +108,9 @@
       get => VariableRangesParameter.Value;
     }
+
+    public IFixedValueParameter<ShapeConstraints> ShapeConstraintsParameter =>
+      (IFixedValueParameter<ShapeConstraints>) Parameters[ShapeConstraintsParameterName];
+
+    public ShapeConstraints ShapeConstraints => ShapeConstraintsParameter.Value;
 
 
@@ -140,4 +146,13 @@
         Parameters.Add(new FixedValueParameter<IntervalCollection>(VariableRangesParameterName, intervalCollection));
       }
+      if(Parameters.ContainsKey("IntervalConstraints")) {
+        var param = (IFixedValueParameter<ShapeConstraints>)Parameters["IntervalConstraints"];
+        Parameters.Remove(param);
+        Parameters.Add(new FixedValueParameter<ShapeConstraints>(ShapeConstraintsParameterName, param.Value));
+      }
+      if (!Parameters.ContainsKey(ShapeConstraintsParameterName)) {
+        Parameters.Add(new FixedValueParameter<ShapeConstraints>(ShapeConstraintsParameterName, new ShapeConstraints()));
+      }
+
       RegisterParameterEvents();
     }
@@ -163,10 +178,19 @@
     }
 
-    public RegressionProblemData(IDataset dataset, IEnumerable<string> allowedInputVariables, string targetVariable, IEnumerable<ITransformation> transformations = null)
+    public RegressionProblemData(IDataset dataset, IEnumerable<string> allowedInputVariables, string targetVariable, 
+      IEnumerable<ITransformation> transformations = null,
+      IntervalCollection variableRanges = null,
+      ShapeConstraints shapeConstraints = null)
       : base(dataset, allowedInputVariables, transformations ?? Enumerable.Empty<ITransformation>()) {
       var variables = InputVariables.Select(x => x.AsReadOnly()).ToList();
       Parameters.Add(new ConstrainedValueParameter<StringValue>(TargetVariableParameterName, new ItemSet<StringValue>(variables), variables.Where(x => x.Value == targetVariable).First()));
-      var intervalCollection = CalculateDatasetIntervals(this.Dataset);
-      Parameters.Add(new FixedValueParameter<IntervalCollection>(VariableRangesParameterName, intervalCollection));
+      if (variableRanges == null) {
+        variableRanges = CalculateDatasetIntervals(this.Dataset);
+      }
+      Parameters.Add(new FixedValueParameter<IntervalCollection>(VariableRangesParameterName, variableRanges));
+      if (shapeConstraints == null) {
+        shapeConstraints = new ShapeConstraints();
+      } 
+      Parameters.Add(new FixedValueParameter<ShapeConstraints>(ShapeConstraintsParameterName, shapeConstraints));
       RegisterParameterEvents();
     }
@@ -174,5 +198,5 @@
     private static IntervalCollection CalculateDatasetIntervals(IDataset dataset) {
       IntervalCollection intervalCollection = new IntervalCollection();
-      foreach (var variable in dataset.DoubleVariables) {// intervals are only possible for double variables
+      foreach (var variable in dataset.DoubleVariables) { // intervals are only possible for double variables
         var variableInterval = Interval.GetInterval(dataset.GetDoubleValues(variable));
         intervalCollection.AddInterval(variable, variableInterval);
Index: /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ShapeConstraints.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ShapeConstraints.cs	(revision 17902)
+++ /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ShapeConstraints.cs	(revision 17902)
@@ -0,0 +1,85 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#endregion
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Collections;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableType("A56BFB05-8F11-4766-9FBF-20C7010F1CA3")]
+  [Item("ShapeConstraints", "Represents shape constraints associated with a regression problem data e.g. monotonicity constraints.")]
+  public class ShapeConstraints : CheckedItemList<ShapeConstraint> {
+    public IEnumerable<ShapeConstraint> EnabledConstraints => base.CheckedItems.Select(checkedItem => checkedItem.Value);
+
+    protected override void OnItemsAdded(IEnumerable<IndexedItem<ShapeConstraint>> items) {
+      base.OnItemsAdded(items);
+      foreach (var item in items)
+        item.Value.Changed += Item_Changed;
+    }
+
+    protected override void OnItemsRemoved(IEnumerable<IndexedItem<ShapeConstraint>> items) {
+      base.OnItemsRemoved(items);
+      foreach (var item in items)
+        item.Value.Changed -= Item_Changed;
+    }
+
+    protected override void OnCollectionReset(
+      IEnumerable<IndexedItem<ShapeConstraint>> items,
+      IEnumerable<IndexedItem<ShapeConstraint>> oldItems) {
+      base.OnCollectionReset(items, oldItems);
+      foreach (var item in items)
+        item.Value.Changed += Item_Changed;
+      foreach (var item in oldItems)
+        item.Value.Changed -= Item_Changed;
+    }
+
+    private void Item_Changed(object sender, EventArgs e) {
+      RaiseChanged();
+    }
+
+    [StorableConstructor]
+    protected ShapeConstraints(StorableConstructorFlag _) : base(_) { }
+
+    protected ShapeConstraints(ShapeConstraints original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ShapeConstraints(this, cloner);
+    }
+
+    public ShapeConstraints() : base() {
+    }
+
+    public event EventHandler Changed;
+
+    private void RaiseChanged() {
+      var handlers = Changed;
+      if (handlers != null)
+        handlers(this, EventArgs.Empty);
+    }
+  }
+}
Index: /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionProblemData.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionProblemData.cs	(revision 17901)
+++ /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionProblemData.cs	(revision 17902)
@@ -1,3 +1,4 @@
 ﻿#region License Information
+
 /* HeuristicLab
  * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
@@ -18,4 +19,5 @@
  * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
  */
+
 #endregion
 
@@ -28,5 +30,6 @@
     string TargetVariable { get; set; }
 
-    IntervalCollection VariableRanges { get;}
+    IntervalCollection VariableRanges { get; }
+    ShapeConstraints ShapeConstraints { get; }
 
     IEnumerable<double> TargetVariableValues { get; }
