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 16406)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 16407)
@@ -163,4 +163,5 @@
     <Compile Include="Interpreter\BatchInstruction.cs" />
     <Compile Include="Interpreter\BatchOperations.cs" />
+    <Compile Include="Interpreter\IntervalInterpreter.cs" />
     <Compile Include="Interpreter\SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs" />
     <Compile Include="Interpreter\SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs" />
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs	(revision 16407)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs	(revision 16407)
@@ -0,0 +1,275 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  [Item("IntervalInterpreter", "Intperter 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 int EvaluatedSolutions {
+      get { return EvaluatedSolutionsParameter.Value.Value; }
+      set { EvaluatedSolutionsParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    private IntervalInterpreter(bool deserializing) : base(deserializing) { }
+    private IntervalInterpreter(IntervalInterpreter original, Cloner 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)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new IntervalInterpreter(this, cloner);
+    }
+
+    private readonly object syncRoot = new object();
+
+    #region IStatefulItem Members
+    public void InitializeState() {
+      EvaluatedSolutions = 0;
+    }
+    public void ClearState() { }
+    #endregion
+
+    public Interval GetSymbolicExressionTreeInterval(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows = null) {
+      var variableRanges = DatasetUtil.GetVariableRanges(dataset, rows);
+      return GetSymbolicExressionTreeInterval(tree, variableRanges);
+    }
+
+    public Interval GetSymbolicExressionTreeIntervals(ISymbolicExpressionTree tree, IDataset dataset,
+      out Dictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals, IEnumerable<int> rows = null) {
+      var variableRanges = DatasetUtil.GetVariableRanges(dataset, rows);
+      return GetSymbolicExressionTreeIntervals(tree, variableRanges, out nodeIntervals);
+    }
+
+    public Interval GetSymbolicExressionTreeInterval(ISymbolicExpressionTree tree, Dictionary<string, Interval> variableRanges) {
+      lock (syncRoot) {
+        EvaluatedSolutions++;
+      }
+      int instructionCount = 0;
+      var instructions = PrepareInterpreterState(tree, variableRanges);
+      var outputInterval = Evaluate(instructions, ref instructionCount);
+
+      return outputInterval;
+    }
+
+
+    public Interval GetSymbolicExressionTreeIntervals(ISymbolicExpressionTree tree,
+      Dictionary<string, Interval> variableRanges, out Dictionary<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);
+
+      nodeIntervals = intervals;
+
+      return outputInterval;
+    }
+
+
+    private static Instruction[] PrepareInterpreterState(ISymbolicExpressionTree tree, Dictionary<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)) {
+        var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
+        instr.data = variableRanges[variableTreeNode.VariableName];
+      }
+      return code;
+    }
+
+    private Interval Evaluate(Instruction[] instructions, ref int instructionCounter, Dictionary<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
+      instructionCounter++;
+      Interval result = null;
+
+      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;
+
+            result = Interval.Multiply(variableInterval, weightInterval);
+            break;
+          }
+        case OpCodes.Constant: {
+            var constTreeNode = (ConstantTreeNode)currentInstr.dynamicNode;
+            result = new Interval(constTreeNode.Value, constTreeNode.Value);
+            break;
+          }
+        //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 = Interval.Add(result, argumentInterval);
+            }
+            break;
+          }
+        case OpCodes.Sub: {
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            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);
+              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 = Interval.Multiply(result, argumentInterval);
+            }
+            break;
+          }
+        case OpCodes.Div: {
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            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);
+              result = Interval.Divide(result, argumentInterval);
+            }
+            break;
+          }
+        //Trigonometric functions
+        case OpCodes.Sin: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Interval.Sine(argumentInterval);
+            break;
+          }
+        case OpCodes.Cos: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Interval.Cosine(argumentInterval);
+            break;
+          }
+        case OpCodes.Tan: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Interval.Tangens(argumentInterval);
+            break;
+          }
+        //Exponential functions
+        case OpCodes.Log: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Interval.Logarithm(argumentInterval);
+            break;
+          }
+        case OpCodes.Exp: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Interval.Exponential(argumentInterval);
+            break;
+          }
+        case OpCodes.Power: {
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            for (int i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+              result = Interval.Power(result, argumentInterval);
+            }
+            break;
+          }
+        case OpCodes.Square: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Interval.Square(argumentInterval);
+            break;
+          }
+        case OpCodes.Root: {
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            for (int i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+              result = Interval.Root(result, argumentInterval);
+            }
+            break;
+          }
+        case OpCodes.SquareRoot: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Interval.SquareRoot(argumentInterval);
+            break;
+          }
+        default:
+          throw new NotSupportedException($"The tree contains the unknown symbol {currentInstr.dynamicNode.Symbol}");
+      }
+
+      if (nodeIntervals != null)
+        nodeIntervals.Add(currentInstr.dynamicNode, result);
+
+      return result;
+    }
+
+    public static bool IsCompatible(ISymbolicExpressionTree tree) {
+      var containsUnknownSyumbol = (
+        from n in tree.Root.GetSubtree(0).IterateNodesPrefix()
+        where
+          !(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 Logarithm) &&
+          !(n.Symbol is Exponential) &&
+          !(n.Symbol is Power) &&
+          !(n.Symbol is Square) &&
+          !(n.Symbol is Root) &&
+          !(n.Symbol is SquareRoot) &&
+          !(n.Symbol is Problems.DataAnalysis.Symbolic.Variable) &&
+          !(n.Symbol is Constant)
+        select n).Any();
+      return !containsUnknownSyumbol;
+    }
+  }
+}
Index: /trunk/HeuristicLab.Problems.DataAnalysis/3.4/DatasetUtil.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis/3.4/DatasetUtil.cs	(revision 16406)
+++ /trunk/HeuristicLab.Problems.DataAnalysis/3.4/DatasetUtil.cs	(revision 16407)
@@ -93,4 +93,20 @@
     }
 
+    public static Dictionary<string, Interval> GetVariableRanges(IDataset dataset, IEnumerable<int> rows = null) {
+      Dictionary<string, Interval> variableRanges = new Dictionary<string, Interval>();
+
+      foreach (var variable in dataset.VariableNames) {
+        IEnumerable<double> values = null;
+
+        if (rows == null) values = dataset.GetDoubleValues(variable);
+        else values = dataset.GetDoubleValues(variable, rows);
+
+        var range = Interval.GetInterval(values);
+        variableRanges.Add(variable, range);
+      }
+
+      return variableRanges;
+    }
+
     private static bool GetEqualValues(this Dictionary<ValuesType, ValuesType> variableValuesMapping, ValuesType originalValues, out ValuesType matchingValues) {
       if (variableValuesMapping.ContainsKey(originalValues)) {
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 16406)
+++ /trunk/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 16407)
@@ -140,4 +140,5 @@
     <Compile Include="Implementation\ConstantModel.cs" />
     <Compile Include="Implementation\DataAnalysisModel.cs" />
+    <Compile Include="Implementation\Interval.cs" />
     <Compile Include="Implementation\Regression\ConfidenceBoundRegressionSolution.cs" />
     <Compile Include="Implementation\Regression\ConstantRegressionModel.cs" />
Index: /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval.cs	(revision 16407)
+++ /trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval.cs	(revision 16407)
@@ -0,0 +1,219 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Common;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public class Interval : IEquatable<Interval> {
+    public double LowerBound { get; private set; }
+    public double UpperBound { get; private set; }
+
+    public Interval(double lowerBound, double upperBound) {
+      if (lowerBound > upperBound)
+        throw new ArgumentException("LowerBound must be smaller than UpperBound.");
+
+      this.LowerBound = lowerBound;
+      this.UpperBound = upperBound;
+    }
+
+    public bool Contains(double value) {
+      return LowerBound <= value && value <= UpperBound;
+    }
+
+    public override string ToString() {
+      return "Interval: [" + LowerBound + ", " + UpperBound + "]";
+    }
+
+    public bool IsInfiniteOrUndefined {
+      get {
+        return double.IsInfinity(LowerBound) || double.IsInfinity(UpperBound) ||
+                double.IsNaN(LowerBound) || double.IsNaN(UpperBound);
+      }
+    }
+
+    public static Interval GetInterval(IEnumerable<double> values) {
+      if (values == null) throw new ArgumentNullException("values");
+      if (!values.Any()) throw new ArgumentException($"No values are present.");
+
+      var min = double.MaxValue;
+      var max = double.MinValue;
+
+      foreach (var value in values) {
+        //If an value is NaN return an interval [NaN, NaN]
+        if (double.IsNaN(value)) return new Interval(double.NaN, double.NaN);
+
+        if (value < min) min = value;
+        if (value > max) max = value;
+      }
+
+      return new Interval(min, max);
+    }
+
+    #region Equals, GetHashCode, == , !=
+    public bool Equals(Interval other) {
+      if (other == null)
+        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)));
+    }
+
+    public override bool Equals(object obj) {
+      return Equals(obj as Interval);
+    }
+
+    public override int GetHashCode() {
+      return LowerBound.GetHashCode() ^ UpperBound.GetHashCode();
+    }
+
+    public static bool operator ==(Interval interval1, Interval interval2) {
+      if (ReferenceEquals(interval1, null)) return ReferenceEquals(interval2, null);
+      return interval1.Equals(interval2);
+    }
+    public static bool operator !=(Interval interval1, Interval interval2) {
+      return !(interval1 == interval2);
+    }
+    #endregion
+
+    #region operations
+
+    // [x1,x2] + [y1,y2] = [x1 + y1,x2 + y2]
+    public static Interval Add(Interval a, Interval b) {
+      return new Interval(a.LowerBound + b.LowerBound, a.UpperBound + b.UpperBound);
+    }
+
+    // [x1,x2] − [y1,y2] = [x1 − y2,x2 − y1]
+    public static Interval Subtract(Interval a, Interval b) {
+      return new Interval(a.LowerBound - b.UpperBound, a.UpperBound - b.LowerBound);
+    }
+
+    // [x1,x2] * [y1,y2] = [min(x1*y1,x1*y2,x2*y1,x2*y2),max(x1*y1,x1*y2,x2*y1,x2*y2)]
+    public static Interval Multiply(Interval a, Interval b) {
+      double v1 = a.LowerBound * b.LowerBound;
+      double v2 = a.LowerBound * b.UpperBound;
+      double v3 = a.UpperBound * b.LowerBound;
+      double v4 = a.UpperBound * b.UpperBound;
+
+      double min = Math.Min(Math.Min(v1, v2), Math.Min(v3, v4));
+      double max = Math.Max(Math.Min(v1, v2), Math.Max(v3, v4));
+      return new Interval(min, max);
+    }
+
+    //mkommend: Division by intervals containing 0 is implemented as defined in
+    //http://en.wikipedia.org/wiki/Interval_arithmetic
+    public static Interval Divide(Interval a, Interval b) {
+      if (b.Contains(0.0)) {
+        if (b.LowerBound.IsAlmost(0.0)) return Interval.Multiply(a, new Interval(1.0 / b.UpperBound, double.PositiveInfinity));
+        else if (b.UpperBound.IsAlmost(0.0)) return Interval.Multiply(a, new Interval(double.NegativeInfinity, 1.0 / b.LowerBound));
+        else return new Interval(double.NegativeInfinity, double.PositiveInfinity);
+      }
+      return Interval.Multiply(a, new Interval(1.0 / b.UpperBound, 1.0 / b.LowerBound));
+    }
+
+    public static Interval Sine(Interval a) {
+      if (Math.Abs(a.UpperBound - a.LowerBound) >= Math.PI * 2) return new Interval(-1, 1);
+
+      //divide the interval by PI/2 so that the optima lie at x element of N (0,1,2,3,4,...)
+      double Pihalf = Math.PI / 2;
+      Interval scaled = Interval.Divide(a, new Interval(Pihalf, Pihalf));
+      //move to positive scale
+      if (scaled.LowerBound < 0) {
+        int periodsToMove = Math.Abs((int)scaled.LowerBound / 4) + 1;
+        scaled = Interval.Add(scaled, new Interval(periodsToMove * 4, periodsToMove * 4));
+      }
+
+      double scaledLowerBound = scaled.LowerBound % 4.0;
+      double scaledUpperBound = scaled.UpperBound % 4.0;
+      if (scaledUpperBound < scaledLowerBound) scaledUpperBound += 4.0;
+      List<double> sinValues = new List<double>();
+      sinValues.Add(Math.Sin(scaledLowerBound * Pihalf));
+      sinValues.Add(Math.Sin(scaledUpperBound * Pihalf));
+
+      int startValue = (int)Math.Ceiling(scaledLowerBound);
+      while (startValue < scaledUpperBound) {
+        sinValues.Add(Math.Sin(startValue * Pihalf));
+        startValue += 1;
+      }
+
+      return new Interval(sinValues.Min(), sinValues.Max());
+    }
+    public static Interval Cosine(Interval a) {
+      return Interval.Sine(Interval.Subtract(a, new Interval(Math.PI / 2, Math.PI / 2)));
+    }
+    public static Interval Tangens(Interval a) {
+      return Interval.Divide(Interval.Sine(a), Interval.Cosine(a));
+    }
+
+    public static Interval Logarithm(Interval a) {
+      return new Interval(Math.Log(a.LowerBound), Math.Log(a.UpperBound));
+    }
+    public static Interval Exponential(Interval a) {
+      return new Interval(Math.Exp(a.LowerBound), Math.Exp(a.UpperBound));
+    }
+
+    public static Interval Power(Interval a, Interval b) {
+      if (a.Contains(0.0) && b.LowerBound < 0) return new Interval(double.NaN, double.NaN);
+
+      int bLower = (int)Math.Round(b.LowerBound);
+      int bUpper = (int)Math.Round(b.UpperBound);
+
+      List<double> powerValues = new List<double>();
+      powerValues.Add(Math.Pow(a.UpperBound, bUpper));
+      powerValues.Add(Math.Pow(a.UpperBound, bUpper - 1));
+      powerValues.Add(Math.Pow(a.UpperBound, bLower));
+      powerValues.Add(Math.Pow(a.UpperBound, bLower + 1));
+
+      powerValues.Add(Math.Pow(a.LowerBound, bUpper));
+      powerValues.Add(Math.Pow(a.LowerBound, bUpper - 1));
+      powerValues.Add(Math.Pow(a.LowerBound, bLower));
+      powerValues.Add(Math.Pow(a.LowerBound, bLower + 1));
+
+      return new Interval(powerValues.Min(), powerValues.Max());
+    }
+
+    public static Interval Square(Interval a) {
+      return Power(a, new Interval(2, 2));
+    }
+
+    public static Interval Cubic(Interval a) {
+      return Power(a, new Interval(3, 3));
+    }
+
+    public static Interval Root(Interval a, Interval b) {
+      int lower = (int)Math.Round(b.LowerBound);
+      int higher = (int)Math.Round(b.UpperBound);
+
+      return new Interval(Math.Pow(a.LowerBound, 1.0 / higher), Math.Pow(a.UpperBound, 1.0 / lower));
+    }
+
+    public static Interval SquareRoot(Interval a) {
+      return Root(a, new Interval(2, 2));
+    }
+
+    public static Interval CubicRoot(Interval a) {
+      return Root(a, new Interval(3, 3));
+    }
+    #endregion
+  }
+}
Index: /trunk/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/IntervalTest.cs
===================================================================
--- /trunk/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/IntervalTest.cs	(revision 16407)
+++ /trunk/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/IntervalTest.cs	(revision 16407)
@@ -0,0 +1,127 @@
+﻿using System;
+using HeuristicLab.Problems.DataAnalysis;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace HeuristicLab.Problems.DataAnalysis.Tests {
+  [TestClass]
+  public class IntervalTest {
+    private readonly Interval a = new Interval(-1, 1);
+    private readonly Interval b = new Interval(-2, 2);
+    private readonly Interval c = new Interval(0, 3);
+    private readonly Interval d = new Interval(1, 3);
+    private readonly Interval e = new Interval(4, 6);
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalAddOperation() {
+      //add        [x1,x2] + [y1,y2] = [x1 + y1,x2 + y2]
+
+      // [-1,1] + [-2,2] = [-3,3]
+      Assert.AreEqual(Interval.Add(a, b), new Interval(-3, 3));
+      //([-1, 1] + [-2, 2]) + [0, 3] = [-3, 6]
+      Assert.AreEqual(Interval.Add(Interval.Add(a, b), c), new Interval(-3, 6));
+      //([-1, 1] + [0, 3]) + [-2, 2] = [-3, 6]
+      Assert.AreEqual(Interval.Add(Interval.Add(a, c), b), new Interval(-3, 6));
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalSubOperation() {
+      //subtract   [x1,x2] − [y1,y2] = [x1 − y2,x2 − y1]
+
+      //[-1, 1] - [-2, 2] = [-3, 3]
+      Assert.AreEqual<Interval>(Interval.Subtract(a, b), new Interval(-3, 3));
+      //([-1, 1] - [-2, 2]) - [0, 3] = [-6, 3]
+      Assert.AreEqual<Interval>(Interval.Subtract(Interval.Subtract(a, b), c), new Interval(-6, 3));
+      //([-1, 1] - [0, 3]) - [-2, 2] = [-6, 3]
+      Assert.AreEqual<Interval>(Interval.Subtract(Interval.Subtract(a, c), b), new Interval(-6, 3));
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalMutlipyOperation() {
+      //multiply   [x1,x2] * [y1,y2] = [min(x1*y1,x1*y2,x2*y1,x2*y2),max(x1*y1,x1*y2,x2*y1,x2*y2)]
+
+      //[-1, 1] * [-2, 2] = [-2, 2]
+      Assert.AreEqual<Interval>(Interval.Multiply(a, b), new Interval(-2, 2));
+      //([-1, 1] * [-2, 2]) * [0, 3] = [-6, 6]
+      Assert.AreEqual<Interval>(Interval.Multiply(Interval.Multiply(a, b), c), new Interval(-6, 6));
+      //([-1, 1] * [0, 3]) * [-2, 2] = [-6, 6]
+      Assert.AreEqual<Interval>(Interval.Multiply(Interval.Multiply(a, c), b), new Interval(-6, 6));
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalDivideOperation() {
+      //divide  [x1, x2] / [y1, y2] = [x1, x2] * (1/[y1, y2]), where 1 / [y1,y2] = [1 / y2,1 / y1] if 0 not in [y_1, y_2].
+
+      //[4, 6] / [1, 3] = [4/3, 6]
+      Assert.AreEqual<Interval>(Interval.Divide(e, d), new Interval(4.0 / 3.0, 6));
+      //([4, 6] / [1, 3]) / [1, 3] = [4/9, 6]
+      Assert.AreEqual<Interval>(Interval.Divide(Interval.Divide(e, d), d), new Interval(4.0 / 9.0, 6));
+      //[4, 6] / [0, 3] = [4/3, +Inf]
+      Assert.AreEqual<Interval>(Interval.Divide(e, c), new Interval(4.0 / 3.0, double.PositiveInfinity));
+      //[-1, 1] / [0, 3] = [+Inf, -Inf]
+      Assert.AreEqual<Interval>(Interval.Divide(a, c), new Interval(double.NegativeInfinity, double.PositiveInfinity));
+      //Devision by 0 ==> IsInfiniteOrUndefined == true
+      Assert.IsTrue(Interval.Divide(e, c).IsInfiniteOrUndefined);
+      //Devision by 0 ==> IsInfiniteOrUndefined == true
+      Assert.IsTrue(Interval.Divide(a, c).IsInfiniteOrUndefined);
+      Assert.AreEqual<Interval>(Interval.Divide(d, b), new Interval(double.NegativeInfinity, double.PositiveInfinity));
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalSineOperator() {
+      //sine depends on interval
+      //sin([0, 2*pi]) = [-1, 1]
+      Assert.AreEqual<Interval>(Interval.Sine(new Interval(0, 2 * Math.PI)), new Interval(-1, 1));
+      //sin([-pi/2, pi/2]) = [sin(-pi/2), sin(pi/2)]
+      Assert.AreEqual<Interval>(Interval.Sine(new Interval(-1 * Math.PI / 2, Math.PI / 2)), new Interval(-1, 1));
+      //sin([0, pi/2]) = [sin(0), sin(pi/2)]
+      Assert.AreEqual<Interval>(Interval.Sine(new Interval(0, Math.PI / 2)), new Interval(0, 1));
+      //sin([pi, 3*pi/2]) = [sin(pi), sin(3*pi/2)]
+      Assert.AreEqual<Interval>(Interval.Sine(new Interval(Math.PI, 3 * Math.PI / 2)), new Interval(-1, 0));
+      Assert.AreEqual<Interval>(Interval.Sine(new Interval(1, 2)), new Interval(Math.Min(Math.Sin(1), Math.Sin(2)), 1));
+      Assert.AreEqual<Interval>(Interval.Sine(new Interval(1, 3)), new Interval(Math.Min(Math.Sin(1), Math.Sin(3)), 1));
+      Assert.AreEqual<Interval>(Interval.Sine(new Interval(Math.PI, 5 * Math.PI / 2)), new Interval(-1, 1));
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalCosineOperator() {
+      //Cosine uses sine Interval.Sine(Interval.Subtract(a, new Interval(Math.PI / 2, Math.PI / 2)));
+      Assert.AreEqual<Interval>(Interval.Cosine(new Interval(0, 2 * Math.PI)), new Interval(-1, 1));
+      Assert.AreEqual<Interval>(new Interval(-1, 1), Interval.Cosine(new Interval(Math.PI, 4 * Math.PI / 2)));
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalLogOperator() {
+      //Log([3, 5]) = [log(3), log(5)]
+      Assert.AreEqual<Interval>(new Interval(Math.Log(3), Math.Log(5)), Interval.Logarithm(new Interval(3, 5)));
+      //Log([0.5, 1]) = [log(0.5), log(1)]
+      Assert.AreEqual<Interval>(new Interval(Math.Log(0.5), 0), Interval.Logarithm(new Interval(0.5, 1)));
+      //Log([-1, 5]) = [NaN, log(5)]
+      var result = Interval.Logarithm(new Interval(-1, 5));
+      Assert.AreEqual<Interval>(new Interval(double.NaN, Math.Log(5)),result);
+      Assert.IsTrue(result.IsInfiniteOrUndefined);
+    }
+
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalExpOperator() {
+      //Exp([0, 1]) = [exp(0), exp(1)]
+      Assert.AreEqual<Interval>(new Interval(1, Math.Exp(1)), Interval.Exponential(new Interval(0, 1)));
+    }
+  }
+}
Index: /trunk/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/IntervalInterpreterTest.cs
===================================================================
--- /trunk/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/IntervalInterpreterTest.cs	(revision 16407)
+++ /trunk/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/IntervalInterpreterTest.cs	(revision 16407)
@@ -0,0 +1,117 @@
+﻿using System;
+using System.Collections.Generic;
+using HeuristicLab.Problems.DataAnalysis;
+using HeuristicLab.Problems.DataAnalysis.Symbolic;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Tests {
+  [TestClass]
+  public class IntervalInterpreterTest {
+    private IRegressionProblemData problemData;
+    private Dictionary<string, Interval> variableRanges;
+
+    [TestInitialize]
+    public void InitTest() {
+      double[,] arr = new double[4, 3];
+
+      arr[0, 0] = 3;
+      arr[0, 1] = 6;
+      arr[0, 2] = 2;
+      arr[1, 0] = 5;
+      arr[1, 1] = 2;
+      arr[1, 2] = 1;
+      arr[2, 0] = 8;
+      arr[2, 1] = 5;
+      arr[2, 2] = 0;
+      arr[3, 0] = 3;
+      arr[3, 1] = 4;
+      arr[3, 2] = 2;
+
+      var ds = new Dataset(new string[] { "x1", "x2", "y" }, arr);
+      problemData = (IRegressionProblemData)new RegressionProblemData(ds, new string[] { "x1", "x2" }, "y");
+
+      variableRanges = new Dictionary<string, Interval>();
+      variableRanges.Add("x1", new Interval(1, 10));
+      variableRanges.Add("x2", new Interval(4, 6));
+    }
+
+    private void EvaluateTest(string expression, Interval expectedResult, Dictionary<string, Interval> variableRanges = null) {
+      var parser = new InfixExpressionParser();
+      var tree = parser.Parse(expression);
+      var interpreter = new IntervalInterpreter();
+      Interval result;
+      if (variableRanges == null)
+        result = interpreter.GetSymbolicExressionTreeInterval(tree, problemData.Dataset, problemData.AllIndices);
+      else
+        result = interpreter.GetSymbolicExressionTreeInterval(tree, variableRanges);
+
+      Assert.AreEqual(expectedResult, result);
+    }
+
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterAdd() {
+      EvaluateTest("x1 + x2", new Interval(5, 14));
+      EvaluateTest("x1 + x2", new Interval(5, 16), variableRanges);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterLogAdd() {
+      EvaluateTest("log(x1 + x2)", new Interval(Math.Log(5), Math.Log(14)));
+      EvaluateTest("log(x1 + x2)", new Interval(Math.Log(5), Math.Log(16)), variableRanges);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterLogAddMul() {
+      EvaluateTest("log(3*x1 + x2)", new Interval(Math.Log(11), Math.Log(30)));
+      EvaluateTest("log(3*x1 + x2)", new Interval(Math.Log(7), Math.Log(36)), variableRanges);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterSin() {
+      EvaluateTest("sin(x1+x2)", new Interval(-1, 1));
+      EvaluateTest("sin(x1+x2)", new Interval(-1, 1), variableRanges);
+      EvaluateTest("sin(1+2)", new Interval(Math.Sin(3), Math.Sin(3)));
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterCos() {
+      EvaluateTest("cos(x1+x2)", new Interval(-1, 1));
+      EvaluateTest("cos(x1+x2)", new Interval(-1, 1), variableRanges);
+      EvaluateTest("cos(1+2)", new Interval(Math.Sin(3 - Math.PI / 2), Math.Sin(3 - Math.PI / 2)));
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterExp() {
+      EvaluateTest("exp(x1-x2)", new Interval(Math.Exp(-3), Math.Exp(6)));
+      EvaluateTest("exp(x1-x2)", new Interval(Math.Exp(-5), Math.Exp(6)), variableRanges);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterExpRoot() {
+      EvaluateTest("exp(root(x1*x2, 2))", new Interval(Math.Exp(Math.Sqrt(6)), Math.Exp(Math.Sqrt(48))));
+      EvaluateTest("exp(root(x1*x2, 2))", new Interval(Math.Exp(Math.Sqrt(4)), Math.Exp(Math.Sqrt(60))), variableRanges);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterPower() {
+      EvaluateTest("pow(x1, 2)", new Interval(Math.Pow(3, 1), Math.Pow(8, 3)));
+    }
+  }
+}
Index: /trunk/HeuristicLab.Tests/HeuristicLab.Tests.csproj
===================================================================
--- /trunk/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 16406)
+++ /trunk/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 16407)
@@ -583,4 +583,5 @@
     <Compile Include="HeuristicLab.Persistence-3.3\UseCases.cs" />
     <Compile Include="HeuristicLab.PluginInfraStructure-3.3\TypeExtensionsTest.cs" />
+    <Compile Include="HeuristicLab.Problems.DataAnalysis-3.4\IntervalTest.cs" />
     <Compile Include="HeuristicLab.Problems.DataAnalysis-3.4\ThresholdCalculatorsTest.cs" />
     <Compile Include="HeuristicLab.Problems.DataAnalysis-3.4\OnlineCalculatorPerformanceTest.cs" />
@@ -589,4 +590,5 @@
     <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\DeriveTest.cs" />
     <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\InfixExpressionParserTest.cs" />
+    <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\IntervalInterpreterTest.cs" />
     <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\SymbolicExpressionTreeBottomUpSimilarityCalculatorTest.cs" />
     <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\SymbolicExpressionTreeMaxCommonSubtreeSimilarityCalculatorTest.cs" />
