Index: branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeVectorInterpreter.cs
===================================================================
--- branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeVectorInterpreter.cs	(revision 17786)
+++ branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeVectorInterpreter.cs	(revision 17830)
@@ -209,6 +209,5 @@
 
     public SymbolicDataAnalysisExpressionTreeVectorInterpreter()
-      : this("SymbolicDataAnalysisExpressionTreeVectorInterpreter", "Interpreter for symbolic expression trees including vector arithmetic.") {
-    }
+      : this("SymbolicDataAnalysisExpressionTreeVectorInterpreter", "Interpreter for symbolic expression trees including vector arithmetic.") { }
 
     protected SymbolicDataAnalysisExpressionTreeVectorInterpreter(string name, string description)
@@ -752,8 +751,421 @@
           }
 
+        #region Time Series Symbols
+        case OpCodes.Median: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => s,
+              v => Statistics.Median(v));
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.Quantile: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            var q = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => s,
+              v => Statistics.Quantile(v, q.Scalar));
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+
+        case OpCodes.AbsoluteEnergy: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => s * s,
+              v => v.PointwisePower(2.0).Sum());
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+
+        case OpCodes.BinnedEntropy: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            var m = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => {
+                int bins = (int)Math.Round(m.Scalar);
+                double minValue = v.Minimum();
+                double maxValue = v.Maximum();
+                double intervalWidth = (maxValue - minValue) / bins;
+                int totalValues = v.Count;
+                double sum = 0;
+                for (int i = 0; i < Math.Max(bins, v.Count); i++) {
+                  double binMin = minValue * i;
+                  double binMax = binMin + intervalWidth;
+                  double countBin = v.Map(e => (e > binMin && e < binMax) ? 1 : 0).Sum();
+                  double percBin = countBin / totalValues;
+                  sum += percBin * Math.Log(percBin);
+                }
+
+                return sum;
+              });
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.HasLargeStandardDeviation: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => Statistics.PopulationStandardDeviation(v) > (Statistics.Maximum(v) - Statistics.Minimum(v)) / 2 ? 1 : 0);
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.HasVarianceLargerThanStd: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => Statistics.PopulationVariance(v) > Statistics.StandardDeviation(v) ? 1 : 0);
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.IsSymmetricLooking: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => Math.Abs(Statistics.Mean(v) - Statistics.Median(v)) < (Statistics.Maximum(v) - Statistics.Minimum(v)) / 2 ? 1 : 0);
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.NumberDataPointsAboveMean: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => {
+                double mean = Statistics.Mean(v);
+                return v.Map(e => e > mean ? 1 : 0).Sum();
+              });
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.NumberDataPointsAboveMedian: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => {
+                double median = Statistics.Median(v);
+                return v.Map(e => e > median ? 1 : 0).Sum();
+              });
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.NumberDataPointsBelowMean: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => {
+                double mean = Statistics.Mean(v);
+                return v.Map(e => e < mean ? 1 : 0).Sum();
+              });
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.NumberDataPointsBelowMedian: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => {
+                double median = Statistics.Median(v);
+                return v.Map(e => e < median ? 1 : 0).Sum();
+              });
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+
+        case OpCodes.ArimaModelCoefficients: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            var i = Evaluate(dataset, ref row, state, traceDict);
+            var k = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => throw new NotImplementedException(""));
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.ContinuousWaveletTransformationCoefficients: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            var a = Evaluate(dataset, ref row, state, traceDict);
+            var b = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => throw new NotImplementedException(""));
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.FastFourierTransformationCoefficient: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            var k = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => throw new NotImplementedException(""));
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.FirstIndexMax: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => (double)v.MaximumIndex() / v.Count);
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.FirstIndexMin: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => (double)v.MinimumIndex() / v.Count);
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.LastIndexMax: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => (double)(v.Count - DoubleVector.Build.DenseOfEnumerable(v.Reverse()).MaximumIndex()) / v.Count);
+
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.LastIndexMin: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => (double)(v.Count - DoubleVector.Build.DenseOfEnumerable(v.Reverse()).MinimumIndex()) / v.Count);
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.LongestStrikeAboveMean: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => LongestStrikeAbove(v, Statistics.Mean(v)));
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.LongestStrikeAboveMedian: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => LongestStrikeAbove(v, Statistics.Median(v)));
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.LongestStrikeBelowMean: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => LongestStrikeBelow(v, Statistics.Mean(v)));
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.LongestStrikeBelowMedian: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => LongestStrikeBelow(v, Statistics.Median(v)));
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.LongestStrikePositive: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => LongestStrikeAbove(v, 0));
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.LongestStrikeNegative: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => LongestStrikeAbove(v, 0));
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.LongestStrikeZero: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => LongestStrikeEqual(v, 0));
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.MeanAbsoluteChange: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => {
+                double sum = 0.0;
+                for (int i = 0; i < v.Count - 1; i++) {
+                  sum += Math.Abs(v[i + 1] - v[i]);
+                }
+
+                return sum / v.Count;
+              });
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.MeanAbsoluteChangeQuantiles: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            var ql = Evaluate(dataset, ref row, state, traceDict);
+            var qu = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => {
+                var lowerBound = Statistics.Quantile(v, ql.Scalar);
+                var upperBound = Statistics.Quantile(v, qu.Scalar);
+                var inBounds = v.Select(e => e > lowerBound && e < upperBound).ToList();
+                double sum = 0.0;
+                int count = 0;
+                for (int i = 0; i < v.Count - 1; i++) {
+                  if (inBounds[i] && inBounds[i + 1]) {
+                    sum += Math.Abs(v[i + 1] - v[i]);
+                    count++;
+                  }
+                }
+
+                return sum / count;
+              });
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.MeanAutocorrelation: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => {
+                double sum = 0.0;
+                double mean = Statistics.Mean(v);
+                for (int l = 0; l < v.Count; l++) {
+                  for (int i = 0; i < v.Count - l; i++) {
+                    sum += (v[i] - mean) * (v[i + l] - mean);
+                  }
+                }
+
+                return sum / (v.Count - 1) / Statistics.PopulationVariance(v);
+              });
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.LaggedAutocorrelation: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            var lVal = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => {
+                double sum = 0.0;
+                int l = (int)Math.Round(lVal.Scalar);
+                double mean = Statistics.Mean(v);
+                for (int i = 0; i < v.Count - l; i++) {
+                  sum += (v[i] - mean) * (v[i + l] - mean);
+                }
+
+                return sum / Statistics.PopulationVariance(v);
+              });
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.MeanSecondDerivateCentral: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => {
+                double sum = 0.0;
+                for (int i = 1; i < v.Count - 1; i++) {
+                  sum += (v[i - 1] - 2 * v[i] + v[i + 1]) / 2;
+                }
+
+                return sum / (v.Count - 2);
+              });
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.NumberPeaksOfSize: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            var l = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => CountNumberOfPeaks(v, l.Scalar));
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.LargeNumberOfPeaks: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            var l = Evaluate(dataset, ref row, state, traceDict);
+            var m = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => CountNumberOfPeaks(v, l.Scalar) > m.Scalar ? 1.0 : 0.0);
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        case OpCodes.TimeReversalAsymmetryStatistic: {
+            var cur = Evaluate(dataset, ref row, state, traceDict);
+            var l = Evaluate(dataset, ref row, state, traceDict);
+            cur = AggregateApply(cur,
+              s => 0,
+              v => {
+                int lag = (int)Math.Round(l.Scalar);
+                double sum = 0.0;
+                for (int i = 0; i < v.Count - 2 * lag; i++) {
+                  sum += Math.Pow(v[i + 2 * lag], 2) * v[i + lag] - v[i + lag] * Math.Pow(v[i], 2);
+                }
+
+                return sum / (v.Count - 2 * lag);
+              });
+            TraceEvaluation(currentInstr, cur);
+            return cur;
+          }
+        #endregion
+
         default:
           throw new NotSupportedException($"Unsupported OpCode: {currentInstr.opCode}");
       }
     }
+
+    private static int LongestStrikeAbove(DoubleVector v, double threshold) {
+      int longestStrike = 0, currentStrike = 0;
+      for (int i = 0; i < v.Count; i++) {
+        if (v[i] > threshold) {
+          currentStrike++;
+          longestStrike = Math.Max(longestStrike, currentStrike);
+        } else
+          currentStrike = 0;
+      }
+      return longestStrike;
+    }
+    private static int LongestStrikeBelow(DoubleVector v, double threshold) {
+      int longestStrike = 0, currentStrike = 0;
+      for (int i = 0; i < v.Count; i++) {
+        if (v[i] < threshold) {
+          currentStrike++;
+          longestStrike = Math.Max(longestStrike, currentStrike);
+        } else
+          currentStrike = 0;
+      }
+      return longestStrike;
+    }
+
+    private static int LongestStrikeEqual(DoubleVector v, double value, double epsilon = double.Epsilon) {
+      int longestStrike = 0, currentStrike = 0;
+      for (int i = 0; i < v.Count; i++) {
+        if (v[i].IsAlmost(epsilon)) {
+          currentStrike++;
+          longestStrike = Math.Max(longestStrike, currentStrike);
+        } else
+          currentStrike = 0;
+      }
+      return longestStrike;
+    }
+    private static int CountNumberOfPeaks(DoubleVector v, double heightDifference) {
+      int count = 0;
+      for (int i = 0; i < v.Count; i++) {
+        bool largerThanPrev = i == 0 || v[i] > v[i - 1] + heightDifference;
+        bool largerThanNext = i == v.Count - 1 || v[i] > v[i + 1] + heightDifference;
+        if (largerThanPrev && largerThanNext)
+          count++;
+      }
+      return count;
+    }
   }
 }
