Index: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/DerivativeCalculator.cs
===================================================================
--- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/DerivativeCalculator.cs	(revision 17832)
+++ 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 17832)
+++ 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 17832)
+++ 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 17832)
+++ 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);
+      }
+    }
+  }
+}
