Index: branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 17298)
+++ branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 17303)
@@ -182,4 +182,5 @@
     <Compile Include="Interpreter\VectorAutoDiffEvaluator.cs" />
     <Compile Include="Interpreter\VectorEvaluator.cs" />
+    <Compile Include="Interpreter\VectorOfAlgebraic.cs" />
     <Compile Include="Selectors\DiversitySelector.cs" />
     <Compile Include="SymbolicDataAnalysisExpressionTreeAverageSimilarityCalculator.cs" />
Index: branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/Algebraic.cs
===================================================================
--- branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/Algebraic.cs	(revision 17298)
+++ branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/Algebraic.cs	(revision 17303)
@@ -12,7 +12,4 @@
     public static T IntRoot<T>(this T a, int r) where T : IAlgebraicType<T> { a.AssignIntRoot(a.Clone(), r); return a; }
 
-    internal static T Min<T>(T a, T b) where T : IAlgebraicType<T> { return a.Clone().AssignMin(b); }
-    internal static T Max<T>(T a, T b) where T : IAlgebraicType<T> { return a.Clone().AssignMax(b); }
-
     // public static T Max<T>(T a, T b) where T : IAlgebraicType<T> {
     //   // ((a + b) + abs(b - a)) / 2
Index: branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicDouble.cs
===================================================================
--- branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicDouble.cs	(revision 17298)
+++ branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicDouble.cs	(revision 17303)
@@ -5,5 +5,5 @@
   // algebraic type wrapper for a double value
   [DebuggerDisplay("{Value}")]
-  public sealed class AlgebraicDouble : IAlgebraicType<AlgebraicDouble> {
+  public sealed class AlgebraicDouble : IComparableAlgebraicType<AlgebraicDouble> {
     public static implicit operator AlgebraicDouble(double value) { return new AlgebraicDouble(value); }
     public static implicit operator double(AlgebraicDouble value) { return value.Value; }
@@ -35,6 +35,6 @@
     public AlgebraicDouble AssignIntPower(AlgebraicDouble a, int p) { Value = Math.Pow(a.Value, p); return this; }
     public AlgebraicDouble AssignIntRoot(AlgebraicDouble a, int r) { Value = IntRoot(a.Value, r); return this; }
-    public AlgebraicDouble AssignMin(AlgebraicDouble other) { Value = Math.Min(Value, other.Value); return this; }
-    public AlgebraicDouble AssignMax(AlgebraicDouble other) { Value = Math.Max(Value, other.Value); return this; }
+    //public AlgebraicDouble AssignMin(AlgebraicDouble other) { Value = Math.Min(Value, other.Value); return this; }
+    //public AlgebraicDouble AssignMax(AlgebraicDouble other) { Value = Math.Max(Value, other.Value); return this; }
     public AlgebraicDouble AssignAbs(AlgebraicDouble a) { Value = Math.Abs(a.Value); return this; }
     public AlgebraicDouble AssignSgn(AlgebraicDouble a) { Value = double.IsNaN(a.Value) ? double.NaN : Math.Sign(a.Value); return this; }
@@ -51,4 +51,8 @@
       return Value.ToString();
     }
+
+    public int CompareTo(AlgebraicDouble other) {
+      return Value.CompareTo(other.Value);
+    }
   }
 }
Index: branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicDoubleVector.cs
===================================================================
--- branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicDoubleVector.cs	(revision 17298)
+++ branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicDoubleVector.cs	(revision 17303)
@@ -6,4 +6,5 @@
   // a simple vector as an algebraic type
   [DebuggerDisplay("DoubleVector(len={Length}): {string.}")]
+  [Obsolete("Use VectorOfAlgebraic instead")]
   public class AlgebraicDoubleVector : IAlgebraicType<AlgebraicDoubleVector> {
     private double[] arr;
@@ -40,6 +41,6 @@
     public AlgebraicDoubleVector AssignIntPower(AlgebraicDoubleVector a, int p) { for (int i = 0; i < arr.Length; ++i) { arr[i] = Math.Pow(a.arr[i], p); } return this; }
     public AlgebraicDoubleVector AssignIntRoot(AlgebraicDoubleVector a, int r) { for (int i = 0; i < arr.Length; ++i) { arr[i] = IntRoot(a.arr[i], r); } return this; }
-    public AlgebraicDoubleVector AssignMin(AlgebraicDoubleVector other) { for (int i = 0; i < arr.Length; ++i) { arr[i] = Math.Min(arr[i], other.arr[i]); } return this; }
-    public AlgebraicDoubleVector AssignMax(AlgebraicDoubleVector other) { for (int i = 0; i < arr.Length; ++i) { arr[i] = Math.Max(arr[i], other.arr[i]); } return this; }
+    //public AlgebraicDoubleVector AssignMin(AlgebraicDoubleVector other) { for (int i = 0; i < arr.Length; ++i) { arr[i] = Math.Min(arr[i], other.arr[i]); } return this; }
+    //public AlgebraicDoubleVector AssignMax(AlgebraicDoubleVector other) { for (int i = 0; i < arr.Length; ++i) { arr[i] = Math.Max(arr[i], other.arr[i]); } return this; }
     public AlgebraicDoubleVector AssignAbs(AlgebraicDoubleVector a) { for (int i = 0; i < arr.Length; ++i) { arr[i] = Math.Abs(a.arr[i]); } return this; }
     public AlgebraicDoubleVector AssignSgn(AlgebraicDoubleVector a) { for (int i = 0; i < arr.Length; ++i) { arr[i] = Math.Sign(a.arr[i]); } return this; }
Index: branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicInterval.cs
===================================================================
--- branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicInterval.cs	(revision 17298)
+++ branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicInterval.cs	(revision 17303)
@@ -47,16 +47,7 @@
       var v4 = high.Clone().Mul(a.high);
 
-      low = Min(Min(v1, v2), Min(v3, v4));
-      high = Max(Max(v1, v2), Max(v3, v4));
-
-      return this;
-    }
-
-
-    private static MultivariateDual<AlgebraicDouble> Min(MultivariateDual<AlgebraicDouble> a, MultivariateDual<AlgebraicDouble> b) {
-      return a.Value < b.Value ? a : b;
-    }
-    private static MultivariateDual<AlgebraicDouble> Max(MultivariateDual<AlgebraicDouble> a, MultivariateDual<AlgebraicDouble> b) {
-      return a.Value > b.Value ? a : b;
+      AssignLowAndHigh(v1, v2, v3, v4);
+
+      return this;
     }
 
@@ -133,10 +124,7 @@
         if (a.Contains(0.0)) {
           low = new MultivariateDual<AlgebraicDouble>(0.0);
-          high = a.low.IntPower(p).AssignMax(a.high.IntPower(p));
-        } else {
-          var lowPower = a.low.IntPower(p);
-          var highPower = a.high.IntPower(p);
-          low = lowPower.AssignMin(highPower);
-          high = lowPower.AssignMax(highPower);
+          AssignMax(high, a.low.IntPower(p), a.high.IntPower(p));
+        } else {
+          AssignLowAndHigh(a.low.IntPower(p), a.high.IntPower(p));
         }
       } else {
@@ -148,6 +136,6 @@
           var lowPower = a.low.IntPower(p);
           var highPower = a.high.IntPower(p);
-          low = lowPower.AssignMin(highPower);
-          high = lowPower.AssignMax(highPower);
+          AssignMin(low, lowPower, highPower);
+          AssignMax(high, lowPower, highPower);
         }
       }
@@ -217,6 +205,5 @@
 
       // assume low and high are in the same quadrant
-      low = Algebraic.Min(a.LowerBound.Clone().Sin(), a.UpperBound.Clone().Sin());
-      high = Algebraic.Max(a.LowerBound.Clone().Sin(), a.UpperBound.Clone().Sin());
+      AssignLowAndHigh(a.LowerBound.Clone().Sin(), a.UpperBound.Clone().Sin()); // AssignLowAndHigh determines the lower and higher value 
 
       // override min and max if necessary
@@ -260,13 +247,10 @@
     public AlgebraicInterval AssignAbs(AlgebraicInterval a) {
       if (a.Contains(0.0)) {
+        low.Assign(new MultivariateDual<AlgebraicDouble>(0.0)); // lost gradient for lower bound
+        AssignMax(high, a.low.Clone().Abs(), a.high.Clone().Abs());
+      } else {
         var abslow = a.low.Clone().Abs();
         var abshigh = a.high.Clone().Abs();
-        a.high.Assign(Algebraic.Max(abslow, abshigh));
-        a.low.Assign(new MultivariateDual<AlgebraicDouble>(0.0)); // lost gradient for lower bound
-      } else {
-        var abslow = a.low.Clone().Abs();
-        var abshigh = a.high.Clone().Abs();
-        a.low.Assign(Algebraic.Min(abslow, abshigh));
-        a.high.Assign(Algebraic.Max(abslow, abshigh));
+        AssignLowAndHigh(abslow, abshigh);
       }
       return this;
@@ -279,15 +263,43 @@
     }
 
-    public AlgebraicInterval AssignMin(AlgebraicInterval other) {
-      low.AssignMin(other.low);
-      high.AssignMin(other.high);
-      return this;
-    }
-
-    public AlgebraicInterval AssignMax(AlgebraicInterval other) {
-      low.AssignMax(other.low);
-      high.AssignMax(other.high);
-      return this;
-    }
+
+    #region helper
+    private void AssignMin(MultivariateDual<AlgebraicDouble> dest, MultivariateDual<AlgebraicDouble> a, MultivariateDual<AlgebraicDouble> b) {
+      if (a.Value.CompareTo(b.Value) <= 0) {
+        dest.Assign(a);
+      } else {
+        dest.Assign(b);
+      }
+    }
+    private void AssignMax(MultivariateDual<AlgebraicDouble> dest, MultivariateDual<AlgebraicDouble> a, MultivariateDual<AlgebraicDouble> b) {
+      if (a.Value.CompareTo(b.Value) <= 0) {
+        dest.Assign(b);
+      } else {
+        dest.Assign(a);
+      }
+    }
+
+    // determines the smaller and larger value and sets low and high accordingly
+    private void AssignLowAndHigh(MultivariateDual<AlgebraicDouble> a, MultivariateDual<AlgebraicDouble> b) {
+      // we must make sure that low and high are different objects when a == b
+      if (a.Value.CompareTo(b.Value) == 0) {
+        low.Assign(a);
+        high.Assign(b);
+      } else {
+        AssignMin(low, a, b);
+        AssignMax(high, a, b);
+      }
+    }
+    private void AssignLowAndHigh(params MultivariateDual<AlgebraicDouble>[] xs) {
+      if (xs.Length <= 2) throw new ArgumentException("need at least 3 arguments");
+      AssignLowAndHigh(xs[0], xs[1]);
+      for(int i=2;i<xs.Length;i++) {
+        // we must make sure that low and high are different objects when a == b
+        if (low.Value.CompareTo(xs[i].Value) > 0) low.Assign(xs[i]);
+        if (high.Value.CompareTo(xs[i].Value) < 0) high.Assign(xs[i]);
+      }
+    }
+    #endregion
+
   }
 }
Index: branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicSparseVector.cs
===================================================================
--- branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicSparseVector.cs	(revision 17298)
+++ branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/AlgebraicSparseVector.cs	(revision 17303)
@@ -109,29 +109,4 @@
     }
 
-    public AlgebraicSparseVector<K, T> AssignMin(AlgebraicSparseVector<K, T> other) {
-      // assumes that keys without a matching key in other are zero and vice versa
-      foreach (var kvp in elems) if (!other.elems.ContainsKey(kvp.Key)) kvp.Value.AssignMin(kvp.Value.Zero); // min(v, 0)
-      foreach (var kvp in other.elems) {
-        if (elems.TryGetValue(kvp.Key, out T value))
-          value.AssignMin(kvp.Value);
-        else
-          elems.Add(kvp.Key, kvp.Value.Zero.AssignMin(kvp.Value));
-      }
-      return this;
-    }
-
-    public AlgebraicSparseVector<K, T> AssignMax(AlgebraicSparseVector<K, T> other) {
-      // assumes that keys without a matching key in other are zero and vice versa
-      foreach (var kvp in elems) if (!other.elems.ContainsKey(kvp.Key)) kvp.Value.AssignMax(kvp.Value.Zero); // max(v, 0)
-      foreach (var kvp in other.elems) {
-        if (elems.TryGetValue(kvp.Key, out T value))
-          value.AssignMax(kvp.Value);
-        else
-          elems.Add(kvp.Key, kvp.Value.Zero.AssignMax(kvp.Value));
-      }
-      return this;
-    }
-
-
     public AlgebraicSparseVector<K, T> Clone() {
       return new AlgebraicSparseVector<K, T>(this);
Index: branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/Dual.cs
===================================================================
--- branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/Dual.cs	(revision 17298)
+++ branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/Dual.cs	(revision 17303)
@@ -4,5 +4,5 @@
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
   public class Dual<V> : IAlgebraicType<Dual<V>>
-    where V : IAlgebraicType<V> {
+    where V : IComparableAlgebraicType<V> {
     [DebuggerBrowsable(DebuggerBrowsableState.Never)]
     private V v;
@@ -54,9 +54,17 @@
 
     public Dual<V> AssignMin(Dual<V> other) {
-      throw new NotImplementedException();
+      if(v.CompareTo(other.v) > 0) {
+        v.Assign(other.v);
+        dv.Assign(other.dv);
+      }
+      return this;
     }
 
     public Dual<V> AssignMax(Dual<V> other) {
-      throw new NotImplementedException();
+      if (v.CompareTo(other.v) <= 0) {
+        v.Assign(other.v);
+        dv.Assign(other.dv);
+      }
+      return this;
     }
   }
Index: branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IAlgebraicType.cs
===================================================================
--- branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IAlgebraicType.cs	(revision 17298)
+++ branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IAlgebraicType.cs	(revision 17303)
@@ -1,3 +1,5 @@
-﻿namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+﻿using System;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
   public interface IAlgebraicType<T> {
     T Zero { get; } // Zero and One must create new objects
@@ -21,7 +23,11 @@
     T AssignIntRoot(T a, int r);
     T AssignSgn(T a); // set this to sign(a)
-    T AssignMin(T other); // set this min(this, other)
-    T AssignMax(T other); // set this max(this, other)
+    //T AssignMin(T other); // set this min(this, other)
+    //T AssignMax(T other); // set this max(this, other)
     T Clone();
   }
+
+  public interface IComparableAlgebraicType<T> : IAlgebraicType<T>, IComparable<T> {
+
+  }
 }
Index: branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/MultivariateDual.cs
===================================================================
--- branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/MultivariateDual.cs	(revision 17298)
+++ branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/MultivariateDual.cs	(revision 17303)
@@ -17,5 +17,14 @@
     public AlgebraicSparseVector<object, V> Gradient => dv; // <key,value> partial derivative identified via the key
 
+
     private MultivariateDual(MultivariateDual<V> orig) { this.v = orig.v.Clone(); this.dv = orig.dv.Clone(); }
+
+    /// <summary>
+    /// Constructor which sets value and derivative to zero
+    /// </summary>
+    public MultivariateDual() {
+      v = new V(); // assumed to be zero
+      dv = new AlgebraicSparseVector<object, V>();
+    }
 
     /// <summary>
@@ -83,12 +92,4 @@
     public MultivariateDual<V> AssignAbs(MultivariateDual<V> a) { v.AssignAbs(a.v); dv.Assign(a.dv).Scale(a.v.Clone().Sgn()); return this; }      // abs(f(x))' = f(x)*f'(x) / |f(x)|  doesn't work for intervals      
     public MultivariateDual<V> AssignSgn(MultivariateDual<V> a) { v.AssignSgn(a.v); dv = a.dv.Zero; return this; } // sign(f(x))' = 0;     
-
-    public MultivariateDual<V> AssignMin(MultivariateDual<V> other) {
-      throw new NotImplementedException();
-    }
-
-    public MultivariateDual<V> AssignMax(MultivariateDual<V> other) {
-      throw new NotImplementedException();
-    }
   }
 }
Index: branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/VectorAutoDiffEvaluator.cs
===================================================================
--- branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/VectorAutoDiffEvaluator.cs	(revision 17298)
+++ branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/VectorAutoDiffEvaluator.cs	(revision 17303)
@@ -5,5 +5,5 @@
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
-  public sealed class VectorAutoDiffEvaluator : InterpreterBase<MultivariateDual<AlgebraicDoubleVector>> {
+  public sealed class VectorAutoDiffEvaluator : InterpreterBase<VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>> {
     private const int BATCHSIZE = 128;
     [ThreadStatic]
@@ -57,13 +57,18 @@
       for (rowIndex = 0; rowIndex < roundedTotal; rowIndex += BATCHSIZE) {
         Evaluate(code);
-        code[0].value.Value.CopyTo(fi, rowIndex, BATCHSIZE);
 
-        // TRANSPOSE into JAC
-        var g = code[0].value.Gradient;
-        for (int j = 0; j < nParams; ++j) {
-          if (g.Elements.TryGetValue(j, out AlgebraicDoubleVector v)) {
-            v.CopyColumnTo(jac, j, rowIndex, BATCHSIZE);
-          } else {
-            for (int r = 0; r < BATCHSIZE; r++) jac[rowIndex + r, j] = 0.0;
+        // code[0].value.Value.CopyTo(fi, rowIndex, BATCHSIZE);
+        var v = code[0].value;
+        for (int k = 0; k < BATCHSIZE; k++) {
+          fi[rowIndex + k] = v[k].Value.Value;
+
+          // copy gradient to Jacobian
+          var g = v[k].Gradient;
+          for (int j = 0; j < nParams; ++j) {
+            if (g.Elements.TryGetValue(j, out AlgebraicDouble gj)) {
+              jac[rowIndex + k, j] = gj.Value;
+            } else {
+              jac[rowIndex + k, j] = 0.0;
+            }
           }
         }
@@ -72,33 +77,39 @@
       if (remainingRows > 0) {
         Evaluate(code);
-        code[0].value.Value.CopyTo(fi, roundedTotal, remainingRows);
+        // code[0].value.Value.CopyTo(fi, roundedTotal, remainingRows);
+        var v = code[0].value;
+        for (int k = 0; k < remainingRows; k++) {
+          fi[roundedTotal + k] = v[k].Value.Value;
 
-        var g = code[0].value.Gradient;
-        for (int j = 0; j < nParams; ++j)
-          if (g.Elements.TryGetValue(j, out AlgebraicDoubleVector v)) {
-            v.CopyColumnTo(jac, j, roundedTotal, remainingRows);
-          } else {
-            for (int r = 0; r < remainingRows; r++) jac[roundedTotal + r, j] = 0.0;
+          var g = v[k].Gradient;
+          for (int j = 0; j < nParams; ++j) {
+            if (g.Elements.TryGetValue(j, out AlgebraicDouble gj)) {
+              jac[roundedTotal + k, j] = gj.Value;
+            } else {
+              jac[roundedTotal + k, j] = 0.0;
+            }
           }
+        }
       }
     }
 
     protected override void InitializeInternalInstruction(ref Instruction instruction, ISymbolicExpressionTreeNode node) {
-      var zero = new AlgebraicDoubleVector(BATCHSIZE);
-      instruction.value = new MultivariateDual<AlgebraicDoubleVector>(zero);
+      instruction.value = new VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>(BATCHSIZE).Zero; // XXX zero needed?
     }
 
     protected override void InitializeTerminalInstruction(ref Instruction instruction, ConstantTreeNode constant) {
-      var g_arr = new double[BATCHSIZE];
       if (node2paramIdx.TryGetValue(constant, out var paramIdx)) {
-        for (int i = 0; i < BATCHSIZE; i++) g_arr[i] = 1.0;
-        var g = new AlgebraicDoubleVector(g_arr);
-        instruction.value = new MultivariateDual<AlgebraicDoubleVector>(new AlgebraicDoubleVector(BATCHSIZE), paramIdx, g); // only a single column for the gradient
+        instruction.value = new VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>(BATCHSIZE);
+        for (int k = 0; k < BATCHSIZE; k++) {
+          instruction.value[k] = new MultivariateDual<AlgebraicDouble>(constant.Value, paramIdx, 1.0); // gradient is 1.0 for all elements
+        }
       } else {
-        instruction.value = new MultivariateDual<AlgebraicDoubleVector>(new AlgebraicDoubleVector(BATCHSIZE));
+        instruction.value = new VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>(BATCHSIZE);
+        for (int k = 0; k < BATCHSIZE; k++) {
+          instruction.value[k] = new MultivariateDual<AlgebraicDouble>(constant.Value); // zero gradient
+        }
       }
 
-      instruction.dblVal = constant.Value;
-      instruction.value.Value.AssignConstant(instruction.dblVal);
+      instruction.dblVal = constant.Value; // also store the parameter value in the instruction (not absolutely necessary, will not be used)
     }
 
@@ -115,13 +126,17 @@
       if (node2paramIdx.ContainsKey(variable)) {
         paramIdx = node2paramIdx[variable];
-        var f = new AlgebraicDoubleVector(BATCHSIZE);
-        var g = new AlgebraicDoubleVector(BATCHSIZE);
-        instruction.value = new MultivariateDual<AlgebraicDoubleVector>(f, paramIdx, g);
+        instruction.value = new VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>(BATCHSIZE);
+        for(int k=0;k<BATCHSIZE;k++) {
+          instruction.value[k] = new MultivariateDual<AlgebraicDouble>(0.0, paramIdx, 0.0); // values are set in LoadVariable()
+        }
       } else {
         var f = new AlgebraicDoubleVector(BATCHSIZE);
-        instruction.value = new MultivariateDual<AlgebraicDoubleVector>(f);
+        instruction.value = new VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>(BATCHSIZE);
+        for (int k = 0; k < BATCHSIZE; k++) {
+          instruction.value[k] = new MultivariateDual<AlgebraicDouble>(0.0); // values are set in LoadVariable()
+        }
       }
 
-      instruction.dblVal = variable.Weight;
+      instruction.dblVal = variable.Weight; 
       instruction.data = new object[] { data, paramIdx };
     }
@@ -131,12 +146,12 @@
       var data = (double[])((object[])a.data)[0];
 
-      for (int i = rowIndex; i < rows.Length && i - rowIndex < BATCHSIZE; i++) a.value.Value[i - rowIndex] = data[rows[i]];
-      a.value.Scale(a.dblVal);
+      for (int i = rowIndex; i < rows.Length && i - rowIndex < BATCHSIZE; i++) {
+        a.value[i - rowIndex].Value.Assign(a.dblVal * data[rows[i]]);
+      }
 
       if (paramIdx >= 0) {
         // update gradient with variable values
-        var g = a.value.Gradient.Elements[paramIdx];
         for (int i = rowIndex; i < rows.Length && i - rowIndex < BATCHSIZE; i++) {
-          g[i - rowIndex] = data[rows[i]];
+          a.value[i - rowIndex].Gradient.Elements[paramIdx].Assign(data[rows[i]]);
         }
       }
Index: branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/VectorOfAlgebraic.cs
===================================================================
--- branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/VectorOfAlgebraic.cs	(revision 17303)
+++ branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/VectorOfAlgebraic.cs	(revision 17303)
@@ -0,0 +1,99 @@
+﻿using System;
+using System.Diagnostics;
+using System.Linq;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  // A vector where each element is an algebraic
+  // Operations on the vector are broadcast to each element
+  [DebuggerDisplay("VectorOfAlgebraic(len={Length}): {string}")]
+  public class VectorOfAlgebraic<T> : IAlgebraicType<VectorOfAlgebraic<T>> where T : IAlgebraicType<T>, new() {
+    private T[] arr;
+    public T this[int idx] { get { return arr[idx]; } set { arr[idx] = value; } }
+    public int Length => arr.Length;
+
+    public VectorOfAlgebraic(int length) { arr = new T[length]; }
+
+    public VectorOfAlgebraic() { }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="arr">array is not copied</param>
+    public VectorOfAlgebraic(T[] arr) { this.arr = arr; }
+
+    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+    public VectorOfAlgebraic<T> Zero {
+      get {
+        var zero = new T[this.Length];
+        for (int i = 0; i < zero.Length; i++) {
+          zero[i] = new T(); // assumed to be initialized to zero
+        }
+        return new VectorOfAlgebraic<T>(zero);
+      }
+    }
+    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+    public VectorOfAlgebraic<T> One {
+      get {
+        var one = new T[this.Length];
+        for (int i = 0; i < one.Length; i++) {
+          one[i] = new T().One;
+        }
+        return new VectorOfAlgebraic<T>(one);
+      }
+    }
+
+    public VectorOfAlgebraic<T> Assign(VectorOfAlgebraic<T> a) { for (int i = 0; i < arr.Length; ++i) { arr[i].Assign(a.arr[i]); } return this; }
+    public VectorOfAlgebraic<T> Add(VectorOfAlgebraic<T> a) { for (int i = 0; i < arr.Length; ++i) { arr[i].Add(a.arr[i]); } return this; }
+    public VectorOfAlgebraic<T> Sub(VectorOfAlgebraic<T> a) { for (int i = 0; i < arr.Length; ++i) { arr[i].Sub(a.arr[i]); } return this; }
+    public VectorOfAlgebraic<T> Mul(VectorOfAlgebraic<T> a) { for (int i = 0; i < arr.Length; ++i) { arr[i].Mul(a.arr[i]); } return this; }
+    public VectorOfAlgebraic<T> Div(VectorOfAlgebraic<T> a) { for (int i = 0; i < arr.Length; ++i) { arr[i].Div(a.arr[i]); } return this; }
+    public VectorOfAlgebraic<T> AssignNeg(VectorOfAlgebraic<T> a) { for (int i = 0; i < arr.Length; ++i) { arr[i].AssignNeg(a.arr[i]); } return this; }
+    public VectorOfAlgebraic<T> AssignInv(VectorOfAlgebraic<T> a) { for (int i = 0; i < arr.Length; ++i) { arr[i].AssignInv(a.arr[i]); } return this; }
+    public VectorOfAlgebraic<T> Scale(double s) { for (int i = 0; i < arr.Length; ++i) { arr[i].Scale(s); } return this; }
+    public VectorOfAlgebraic<T> AssignLog(VectorOfAlgebraic<T> a) { for (int i = 0; i < arr.Length; ++i) { arr[i].AssignLog(a.arr[i]); } return this; }
+    public VectorOfAlgebraic<T> AssignSin(VectorOfAlgebraic<T> a) { for (int i = 0; i < arr.Length; ++i) { arr[i].AssignSin(a.arr[i]); } return this; }
+    public VectorOfAlgebraic<T> AssignExp(VectorOfAlgebraic<T> a) { for (int i = 0; i < arr.Length; ++i) { arr[i].AssignExp(a.arr[i]); } return this; }
+    public VectorOfAlgebraic<T> AssignCos(VectorOfAlgebraic<T> a) { for (int i = 0; i < arr.Length; ++i) { arr[i].AssignCos(a.arr[i]); } return this; }
+    public VectorOfAlgebraic<T> AssignTanh(VectorOfAlgebraic<T> a) { for (int i = 0; i < arr.Length; ++i) { arr[i].AssignTanh(a.arr[i]); } return this; }
+    public VectorOfAlgebraic<T> AssignIntPower(VectorOfAlgebraic<T> a, int p) { for (int i = 0; i < arr.Length; ++i) { arr[i].AssignIntPower(a.arr[i], p); } return this; }
+    public VectorOfAlgebraic<T> AssignIntRoot(VectorOfAlgebraic<T> a, int r) { for (int i = 0; i < arr.Length; ++i) { arr[i].AssignIntRoot(a.arr[i], r); } return this; }
+    public VectorOfAlgebraic<T> AssignAbs(VectorOfAlgebraic<T> a) { for (int i = 0; i < arr.Length; ++i) { arr[i].AssignAbs(a.arr[i]); } return this; }
+    public VectorOfAlgebraic<T> AssignSgn(VectorOfAlgebraic<T> a) { for (int i = 0; i < arr.Length; ++i) { arr[i].AssignSgn(a.arr[i]); } return this; }
+
+    public VectorOfAlgebraic<T> Clone() {
+      var v = Zero; // create new zero vector
+      v.Assign(this); // copy each element
+      return v;
+    }
+
+    public VectorOfAlgebraic<T> AssignConstant(T constantValue) {
+      for (int i = 0; i < arr.Length; ++i) {
+        arr[i].Assign(constantValue);
+      }
+      return this;
+    }
+
+    public void CopyTo(T[] dest, int idx, int length) {
+      throw new NotImplementedException(); // TODO: check if we need to copy all elements
+      // Array.Copy(arr, 0, dest, idx, length); 
+    }
+
+    public void CopyFrom(T[] data, int rowIndex) {
+      throw new NotImplementedException(); // TODO: check if we need to copy all elements
+      // Array.Copy(data, rowIndex, arr, 0, Math.Min(arr.Length, data.Length - rowIndex));
+    }
+    public void CopyRowTo(T[,] dest, int row) {
+      throw new NotImplementedException(); // TODO: check if we need to copy all elements
+      // for (int j = 0; j < arr.Length; ++j) dest[row, j] = arr[j];
+    }
+
+    internal void CopyColumnTo(T[,] dest, int column, int row, int len) {
+      throw new NotImplementedException(); // TODO: check if we need to copy all elements
+      // for (int j = 0; j < len; ++j) dest[row + j, column] = arr[j];
+    }
+
+    public override string ToString() {
+      return "{" + string.Join(", ", arr.Take(Math.Max(5, arr.Length))) + (arr.Length > 5 ? "..." : string.Empty) + "}";
+    }
+  }
+}
