Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 18213)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 18214)
@@ -177,4 +177,5 @@
     <Compile Include="Interfaces\ISymbolicDataAnalysisExpressionManipulator.cs" />
     <Compile Include="Mutators\SegmentOptimization\SamplingSegmentOptimizationManipulator.cs" />
+    <Compile Include="Mutators\SamplingSubVectorImprovementManipulator.cs" />
     <Compile Include="Mutators\SymbolicDataAnalysisExpressionManipulator.cs" />
     <Compile Include="Crossovers\SymbolicDataAnalysisExpressionDiversityPreservingCrossover.cs" />
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 18213)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeVectorInterpreter.cs	(revision 18214)
@@ -729,8 +729,7 @@
         case OpCodes.SubVector: {
           DoubleVector SubVector(DoubleVector v , double start, double end) {
-            int Mod(int x, int m) => (x % m + m) % m;
-            int startIdx = Mod((int)Math.Round(start * v.Count), v.Count);
-            int endIdx = Mod((int)Math.Round(end * v.Count), v.Count);
-              int size = v.Count;
+            int size = v.Count;
+            int startIdx = Math.Abs((int)Math.Round(start * (size - 1)) % size);
+            int endIdx = Math.Abs((int)Math.Round(end * (size - 1)) % size);
             if (startIdx < endIdx) {
               return v.SubVector(startIdx, count: endIdx - startIdx);
Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Mutators/MultiSymbolicDataAnalysisExpressionManipulator.cs
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Mutators/MultiSymbolicDataAnalysisExpressionManipulator.cs	(revision 18213)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Mutators/MultiSymbolicDataAnalysisExpressionManipulator.cs	(revision 18214)
@@ -124,5 +124,7 @@
 
     private void InitializeOperators() {
-      var list = ApplicationManager.Manager.GetInstances<ISymbolicExpressionTreeManipulator>().ToList();
+      var list = ApplicationManager.Manager.GetInstances<ISymbolicExpressionTreeManipulator>()
+        .Where(c => !(c is IMultiOperator<ISymbolicExpressionTreeManipulator>))
+        .ToList();
       var dataAnalysisManipulators = from type in ApplicationManager.Manager.GetTypes(typeof(ISymbolicDataAnalysisExpressionManipulator<T>))
                                    where this.GetType().Assembly == type.Assembly
Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Mutators/SamplingSubVectorImprovementManipulator.cs
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Mutators/SamplingSubVectorImprovementManipulator.cs	(revision 18214)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Mutators/SamplingSubVectorImprovementManipulator.cs	(revision 18214)
@@ -0,0 +1,138 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+
+  [Item("SamplingSubVectorImprovementManipulator", "Sampling Mutator that optimizes the ranges for a subvector symbol.")]
+  [StorableType("70E884F3-EB69-4FA8-9588-843FCE90882E")]
+  public class SamplingSubVectorImprovementManipulator<T> : SymbolicDataAnalysisExpressionManipulator<T> where T : class, IDataAnalysisProblemData {
+
+    #region Parameter Properties
+    public ValueParameter<IntValue> MaxOptimizedNodesParameter => (ValueParameter<IntValue>)Parameters["MaxOptimizedNodes"];
+    public ValueParameter<IntValue> IterationsParameter => (ValueParameter<IntValue>)Parameters["Iterations"];
+
+    public ValueParameter<EnumValue<SamplingSegmentOptimizationManipulator.DimensionType>> DimensionParameter => (ValueParameter<EnumValue<SamplingSegmentOptimizationManipulator.DimensionType>>)Parameters["Dimension"];
+    public ValueParameter<EnumValue<SamplingSegmentOptimizationManipulator.SearchRangeType>> SearchRangeParameter => (ValueParameter<EnumValue<SamplingSegmentOptimizationManipulator.SearchRangeType>>)Parameters["SearchRange"];
+    public ValueParameter<EnumValue<SamplingSegmentOptimizationManipulator.SamplingType>> SamplingParameter => (ValueParameter<EnumValue<SamplingSegmentOptimizationManipulator.SamplingType>>)Parameters["Sampling"];
+    public ValueParameter<IntValue> SampleCountParameter => (ValueParameter<IntValue>)Parameters["SampleCount"];
+    public ValueParameter<EnumValue<SamplingSegmentOptimizationManipulator.SamplingPointsType>> SamplingPointsParameter => (ValueParameter<EnumValue<SamplingSegmentOptimizationManipulator.SamplingPointsType>>)Parameters["SamplingPoints"];
+    #endregion
+
+    #region Properties
+    public int MaxOptimizedNodes { get { return MaxOptimizedNodesParameter.Value.Value; } set { MaxOptimizedNodesParameter.Value.Value = value; } }
+    public int Iterations { get { return IterationsParameter.Value.Value; } set { IterationsParameter.Value.Value = value; } }
+
+    public SamplingSegmentOptimizationManipulator.DimensionType Dimension { get { return DimensionParameter.Value.Value; } set { DimensionParameter.Value.Value = value; } }
+    public SamplingSegmentOptimizationManipulator.SearchRangeType SearchRange { get { return SearchRangeParameter.Value.Value; } set { SearchRangeParameter.Value.Value = value; } }
+    public SamplingSegmentOptimizationManipulator.SamplingType Sampling { get { return SamplingParameter.Value.Value; } set { SamplingParameter.Value.Value = value; } }
+    public int SampleCount { get { return SampleCountParameter.Value.Value; } set { SampleCountParameter.Value.Value = value; } }
+    public SamplingSegmentOptimizationManipulator.SamplingPointsType SamplingPoints { get { return SamplingPointsParameter.Value.Value; } set { SamplingPointsParameter.Value.Value = value; } }
+    #endregion
+
+    public SamplingSubVectorImprovementManipulator() : base() {
+      Parameters.Add(new ValueParameter<IntValue>("MaxOptimizedNodes", "Number of SubVectorNodes that are optimized. -1 for all.", new IntValue(-1))); 
+      Parameters.Add(new ValueParameter<IntValue>("Iterations", new IntValue(10)));
+      Parameters.Add(new ValueParameter<EnumValue<SamplingSegmentOptimizationManipulator.DimensionType>>("Dimension", new EnumValue<SamplingSegmentOptimizationManipulator.DimensionType>(SamplingSegmentOptimizationManipulator.DimensionType.Single)));
+      Parameters.Add(new ValueParameter<EnumValue<SamplingSegmentOptimizationManipulator.SearchRangeType>>("SearchRange", new EnumValue<SamplingSegmentOptimizationManipulator.SearchRangeType>(SamplingSegmentOptimizationManipulator.SearchRangeType.Full)));
+      Parameters.Add(new ValueParameter<EnumValue<SamplingSegmentOptimizationManipulator.SamplingType>>("Sampling", new EnumValue<SamplingSegmentOptimizationManipulator.SamplingType>(SamplingSegmentOptimizationManipulator.SamplingType.Exhaustive)));
+      Parameters.Add(new ValueParameter<IntValue>("SampleCount")); // only used when sampling != Exhaustive
+      Parameters.Add(new ValueParameter<EnumValue<SamplingSegmentOptimizationManipulator.SamplingPointsType>>("SamplingPoints", new EnumValue<SamplingSegmentOptimizationManipulator.SamplingPointsType>(SamplingSegmentOptimizationManipulator.SamplingPointsType.BeforeCombinations | SamplingSegmentOptimizationManipulator.SamplingPointsType.AfterCombinations)));
+    }
+
+    private SamplingSubVectorImprovementManipulator(SamplingSubVectorImprovementManipulator<T> original, Cloner cloner) : base(original, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SamplingSubVectorImprovementManipulator<T>(this, cloner);
+    }
+
+    [StorableConstructor]
+    private SamplingSubVectorImprovementManipulator(StorableConstructorFlag _) : base(_) { }
+
+    private static ISymbolicExpressionTreeNode ActualRoot(ISymbolicExpressionTree tree) {
+      return tree.Root.GetSubtree(0).GetSubtree(0);
+    }
+
+    public override void Manipulate(IRandom random, ISymbolicExpressionTree symbolicExpressionTree) {
+      List<int> rows = GenerateRowsToEvaluate().ToList();
+      T problemData = ProblemDataParameter.ActualValue;
+      ISymbolicDataAnalysisSingleObjectiveEvaluator<T> evaluator = EvaluatorParameter.ActualValue;
+
+      ImproveSubVector(random, symbolicExpressionTree,
+        ExecutionContext, evaluator, problemData, rows,
+        MaxOptimizedNodes, Iterations,
+        Dimension, SearchRange, Sampling, SampleCount, SamplingPoints);
+    }
+
+    public static void ImproveSubVector(IRandom random, ISymbolicExpressionTree symbolicExpressionTree,
+      IExecutionContext context,
+      ISymbolicDataAnalysisSingleObjectiveEvaluator<T> evaluator, T problemData, List<int> rows,
+      int maxOptimizedNodes, int iterations,
+      SamplingSegmentOptimizationManipulator.DimensionType dimension, SamplingSegmentOptimizationManipulator.SearchRangeType searchRange, SamplingSegmentOptimizationManipulator.SamplingType sampling, int sampleCount, SamplingSegmentOptimizationManipulator.SamplingPointsType samplingPoints) {
+      var root = ActualRoot(symbolicExpressionTree);
+
+      var windowedNodes = root.IterateNodesPostfix().OfType<WindowedSymbolTreeNode>().Where(n => n.HasLocalParameters).ToList();
+      if (!windowedNodes.Any()) return;
+
+      var vectorLengths = problemData.Dataset.DoubleVectorVariables
+        .Select(v => problemData.Dataset.GetDoubleVectorValue(v, row: 0).Count)
+        .Distinct().ToList();
+      if (vectorLengths.Count > 1)
+        throw new InvalidOperationException("Different Vector Lengths not supported.");
+      var length = vectorLengths[0];
+      var bounds = new IntMatrix(new int[1, 2] { { 0, length } });
+
+      var selectedNodes = maxOptimizedNodes < 0
+        ? windowedNodes // all
+        : windowedNodes.SampleRandom(random, count: maxOptimizedNodes);
+      foreach (var node in selectedNodes) {
+        foreach (int iteration in Enumerable.Range(0, iterations)) {
+          var current = GetIndices(node, length);
+
+          var indices = SamplingSegmentOptimizationManipulator.CreateIndices(
+            random, current, bounds, dimension, searchRange, 0, null);
+
+          if (samplingPoints.HasFlag(SamplingSegmentOptimizationManipulator.SamplingPointsType.BeforeCombinations))
+            indices = indices.Select(i => SamplingSegmentOptimizationManipulator.SampleIndices(i, sampling, random, sampleCount).ToList()).ToArray();
+
+          var solutions = SamplingSegmentOptimizationManipulator.CreateCombinations(indices[0], indices[1]);
+          if (!solutions.Any()) {
+            if (samplingPoints.HasFlag(SamplingSegmentOptimizationManipulator.SamplingPointsType.BeforeCombinations))
+              return; // no valid combinations -> no mutation
+            throw new InvalidOperationException("no indices!");
+          }
+
+          if (samplingPoints.HasFlag(SamplingSegmentOptimizationManipulator.SamplingPointsType.AfterCombinations))
+            solutions = SamplingSegmentOptimizationManipulator.SampleIndices(solutions, sampling, random, sampleCount);
+
+          var evaluate = new Func<IntegerVector, double>(integerVector => {
+            UpdateNode(node, integerVector, length);
+            return evaluator.Evaluate(context, symbolicExpressionTree, problemData, rows);
+          });
+          var best = SamplingSegmentOptimizationManipulator.FindBest(solutions, evaluate, minimize: !evaluator.Maximization);
+          UpdateNode(node, best.Item1, length);
+        }
+      }
+    }
+
+    private static void UpdateNode(WindowedSymbolTreeNode node, IntegerVector vec, int length) {
+      node.Offset = (double)vec[0] / (length - 1);
+      node.Length = (double)vec[1] / (length - 1);
+    }
+
+    private static IntegerVector GetIndices(WindowedSymbolTreeNode node, int length) {
+      int startIdx = Math.Abs((int)Math.Round(node.Offset * (length - 1)) % length);
+      int endIdx = Math.Abs((int)Math.Round(node.Length * (length - 1)) % length);
+
+      return new IntegerVector(new[] { Math.Min(startIdx, endIdx), Math.Max(startIdx, endIdx) });
+    }
+  }
+}
Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Mutators/SegmentOptimization/SamplingSegmentOptimizationManipulator.cs
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Mutators/SegmentOptimization/SamplingSegmentOptimizationManipulator.cs	(revision 18213)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Mutators/SegmentOptimization/SamplingSegmentOptimizationManipulator.cs	(revision 18214)
@@ -46,5 +46,7 @@
       Full,
       RandomDirection,
-      RandomRange
+      RandomRange,
+      DirectedDirection,
+      DirectedRange
     }
     [StorableType("A9EBE01E-53DE-4EB7-94B3-26C624034A08")]
@@ -66,4 +68,5 @@
     public DimensionType Dimension { get { return DimensionParameter.Value.Value; } set { DimensionParameter.Value.Value = value; } }
     public SearchRangeType SearchRange { get { return SearchRangeParameter.Value.Value; } set { SearchRangeParameter.Value.Value = value; } }
+    public int SlopeCalculationRange { get { return SlopeCalculationRangeParameter.Value.Value; } set { SlopeCalculationRangeParameter.Value.Value = value; } }
     public SamplingType Sampling { get { return SamplingParameter.Value.Value; } set { SamplingParameter.Value.Value = value; } }
     public int SampleCount { get { return SampleCountParameter.Value.Value; } set { SampleCountParameter.Value.Value = value; } }
@@ -74,8 +77,10 @@
     public ValueParameter<EnumValue<DimensionType>> DimensionParameter => (ValueParameter<EnumValue<DimensionType>>)Parameters["Dimension"];
     public ValueParameter<EnumValue<SearchRangeType>> SearchRangeParameter => (ValueParameter<EnumValue<SearchRangeType>>)Parameters["SearchRange"];
+    public ValueParameter<IntValue> SlopeCalculationRangeParameter => (ValueParameter<IntValue>)Parameters["SlopeCalculationRange"];
     public ValueParameter<EnumValue<SamplingType>> SamplingParameter => (ValueParameter<EnumValue<SamplingType>>)Parameters["Sampling"];
     public ValueParameter<IntValue> SampleCountParameter => (ValueParameter<IntValue>)Parameters["SampleCount"];
     public ValueParameter<EnumValue<SamplingPointsType>> SamplingPointsParameter => (ValueParameter<EnumValue<SamplingPointsType>>)Parameters["SamplingPoints"];
     public ValueParameter<BoolValue> CountSamplesAsEvaluationsParameter => (ValueParameter<BoolValue>)Parameters["CountSamplesAsEvaluations"];
+
     public LookupParameter<IntValue> EvaluatedSolutionsParameter => (LookupParameter<IntValue>)Parameters["EvaluatedSolutions"];
     #endregion
@@ -84,4 +89,5 @@
       Parameters.Add(new ValueParameter<EnumValue<DimensionType>>("Dimension", new EnumValue<DimensionType>(DimensionType.All)));
       Parameters.Add(new ValueParameter<EnumValue<SearchRangeType>>("SearchRange", new EnumValue<SearchRangeType>(SearchRangeType.Full)));
+      Parameters.Add(new ValueParameter<IntValue>("SlopeCalculationRange", new IntValue(5)));
       Parameters.Add(new ValueParameter<EnumValue<SamplingType>>("Sampling", new EnumValue<SamplingType>(SamplingType.Exhaustive)));
       Parameters.Add(new ValueParameter<IntValue>("SampleCount")); // only used when sampling != Exhaustive
@@ -95,9 +101,15 @@
       return new SamplingSegmentOptimizationManipulator(this, cloner);
     }
+
     [StorableConstructor]
     public SamplingSegmentOptimizationManipulator(StorableConstructorFlag _) : base(_) { }
-   
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey("SlopeCalculationRange"))
+        Parameters.Add(new ValueParameter<IntValue>("SlopeCalculationRange", new IntValue(5)));
+    }
+
     protected override void ManipulateBounded(IRandom random, IntegerVector integerVector, IntMatrix bounds) {
-      var indices = CreateIndices(random, new IntegerVector(new [] { integerVector.Min(), integerVector.Max() }), bounds, Dimension, SearchRange);
+      var indices = CreateIndices(random, new IntegerVector(new [] { integerVector.Min(), integerVector.Max() }), bounds, Dimension, SearchRange, SlopeCalculationRange, DataParameter.ActualValue);
       
       if (SamplingPoints.HasFlag(SamplingPointsType.BeforeCombinations))
@@ -119,5 +131,5 @@
       }
 
-      var best = FindBest(solutions);
+      var best = FindBest(solutions, Evaluate);
       if (best != null) {
         CopyTo(best.Item1, integerVector);
@@ -125,10 +137,10 @@
     }
     
-    private static IEnumerable<int>[] CreateIndices(IRandom random, IntegerVector integerVector, IntMatrix bounds, DimensionType dimension, SearchRangeType indexRange) {
+    public static IEnumerable<int>[] CreateIndices(IRandom random, IntegerVector integerVector, IntMatrix bounds, DimensionType dimension, SearchRangeType indexRange, int gradientRange, DoubleMatrix data) {
       var indices = new IEnumerable<int>[integerVector.Length];
       int targetIndex = random.Next(indices.Length); // first or second index
       for (int i = 0; i < indices.Length; i++) {
         var searchRange = dimension == DimensionType.All || targetIndex == i ? indexRange : SearchRangeType.None;
-        indices[i] = CreateSingleIndices(bounds[i % bounds.Rows, 1], integerVector[i], searchRange, random).ToList();
+        indices[i] = CreateSingleIndices(bounds[i % bounds.Rows, 1], integerVector[i], searchRange, gradientRange, data, random).ToList();
         if (!indices[i].Any()) {
           throw new InvalidOperationException("no indices!");
@@ -139,5 +151,5 @@
     }
 
-    protected static IEnumerable<int> CreateSingleIndices(int length, int currentIndex, SearchRangeType searchRange, IRandom random) {
+    public static IEnumerable<int> CreateSingleIndices(int length, int currentIndex, SearchRangeType searchRange, int gradientRange, DoubleMatrix data, IRandom random) {
       switch (searchRange) {
         case SearchRangeType.Full:
@@ -152,4 +164,11 @@
           int start = random.Next(0, currentIndex + 1), end = random.Next(currentIndex, length);
           return Enumerable.Range(start, end - start + 1);
+        case SearchRangeType.DirectedDirection:
+          var slope = CalculateSlope(currentIndex, gradientRange, data); // slope of original data, non-aggregated
+          return slope < 0
+            ? Enumerable.Range(0, currentIndex + 1) // left
+            : Enumerable.Range(currentIndex, length - currentIndex); // right
+        //case SearchRangeType.DirectedRange:
+        //  var slope = CalculateSlope(currentIndex, gradientRange, data);
         default:
           throw new ArgumentOutOfRangeException(nameof(searchRange), searchRange, null);
@@ -157,5 +176,27 @@
     }
 
-    protected static IEnumerable<IntegerVector> CreateCombinations(IEnumerable<int> startIndices, IEnumerable<int> endIndices) {
+    private static double CalculateSlope(int position, int range, DoubleMatrix data) {
+      int begin = Math.Max((int)(position - range / 2.0), 0);
+      int remaining = data.Columns - begin;
+      var indices = Enumerable.Range(begin, Math.Min(range, remaining)).ToArray();
+
+      int num = data.Rows * indices.Length;
+      double[] xs = new double[num], ys = new double[num];
+
+      for (int i = 0; i < data.Rows; i++) {
+        for (int j = 0; j < indices.Length; j++) {
+          int idx = i * indices.Length + j;
+          xs[idx] = indices[j];
+          ys[idx] = data[i, j];
+        }
+      }
+      
+      var  coefficients = MathNet.Numerics.LinearRegression.SimpleRegression.Fit(xs, ys);
+      var slope = coefficients.Item2;
+      
+      return slope;
+    }
+
+    public static IEnumerable<IntegerVector> CreateCombinations(IEnumerable<int> startIndices, IEnumerable<int> endIndices) {
       return 
         from s in startIndices
@@ -165,5 +206,5 @@
     }
 
-    protected static IEnumerable<T> SampleIndices<T>(IEnumerable<T> indices, SamplingType sampling, IRandom random, int count) {
+    public static IEnumerable<T> SampleIndices<T>(IEnumerable<T> indices, SamplingType sampling, IRandom random, int count) {
       switch (sampling) {
         case SamplingType.Exhaustive:
@@ -173,4 +214,5 @@
         case SamplingType.LinearSelection:
           var indicesList = indices.ToList();
+          // if single sample, the last is always returned
           var selected = MathNet.Numerics.Generate.LinearSpaced(count, 0, indicesList.Count - 1) // LinearSpaced stop is inclusive
             .Select(i => (int)Math.Floor(i))
@@ -182,8 +224,8 @@
     }
 
-    protected Tuple<IntegerVector, double> FindBest(IEnumerable<IntegerVector> solutions) {
-      var evaluatedSolutions = solutions.Select(s => Tuple.Create(s, Evaluate(s)));
-      var best = evaluatedSolutions.OrderBy(t => t.Item2).FirstOrDefault();
-      return best;
+    public static Tuple<T, double> FindBest<T>(IEnumerable<T> solutions, Func<T, double> evaluate, bool minimize = true) {
+      var evaluatedSolutions = solutions.Select(s => Tuple.Create(s, evaluate(s)));
+      var sorted = evaluatedSolutions.OrderBy(t => t.Item2);
+      return minimize ? sorted.FirstOrDefault() : sorted.LastOrDefault();
     }
 
