Index: /branches/GBT-trunkintegration/HeuristicLab 3.3.sln
===================================================================
--- /branches/GBT-trunkintegration/HeuristicLab 3.3.sln	(revision 12631)
+++ /branches/GBT-trunkintegration/HeuristicLab 3.3.sln	(revision 12632)
@@ -12,4 +12,6 @@
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Algorithms.DataAnalysis-3.4", "HeuristicLab.Algorithms.DataAnalysis\3.4\HeuristicLab.Algorithms.DataAnalysis-3.4.csproj", "{2E782078-FA81-4B70-B56F-74CE38DAC6C8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{ABBC647A-B54B-4DF3-9F64-DBD11AD46A15}"
 EndProject
 Global
@@ -35,4 +37,12 @@
 		{2E782078-FA81-4B70-B56F-74CE38DAC6C8}.Release|x86.ActiveCfg = Release|x86
 		{2E782078-FA81-4B70-B56F-74CE38DAC6C8}.Release|x86.Build.0 = Release|x86
+		{ABBC647A-B54B-4DF3-9F64-DBD11AD46A15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{ABBC647A-B54B-4DF3-9F64-DBD11AD46A15}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{ABBC647A-B54B-4DF3-9F64-DBD11AD46A15}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{ABBC647A-B54B-4DF3-9F64-DBD11AD46A15}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{ABBC647A-B54B-4DF3-9F64-DBD11AD46A15}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{ABBC647A-B54B-4DF3-9F64-DBD11AD46A15}.Release|Any CPU.Build.0 = Release|Any CPU
+		{ABBC647A-B54B-4DF3-9F64-DBD11AD46A15}.Release|x64.ActiveCfg = Release|Any CPU
+		{ABBC647A-B54B-4DF3-9F64-DBD11AD46A15}.Release|x86.ActiveCfg = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
Index: /branches/GBT-trunkintegration/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesAlgorithm.cs
===================================================================
--- /branches/GBT-trunkintegration/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesAlgorithm.cs	(revision 12631)
+++ /branches/GBT-trunkintegration/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesAlgorithm.cs	(revision 12632)
@@ -49,5 +49,5 @@
     #region ParameterNames
     private const string IterationsParameterName = "Iterations";
-    private const string MaxDepthParameterName = "Maximum Tree Depth";
+    private const string MaxSizeParameterName = "Maximum Tree Size";
     private const string NuParameterName = "Nu";
     private const string RParameterName = "R";
@@ -64,6 +64,6 @@
       get { return (IFixedValueParameter<IntValue>)Parameters[IterationsParameterName]; }
     }
-    public IFixedValueParameter<IntValue> MaxDepthParameter {
-      get { return (IFixedValueParameter<IntValue>)Parameters[MaxDepthParameterName]; }
+    public IFixedValueParameter<IntValue> MaxSizeParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[MaxSizeParameterName]; }
     }
     public IFixedValueParameter<DoubleValue> NuParameter {
@@ -106,7 +106,7 @@
       set { SetSeedRandomlyParameter.Value.Value = value; }
     }
-    public int MaxDepth {
-      get { return MaxDepthParameter.Value.Value; }
-      set { MaxDepthParameter.Value.Value = value; }
+    public int MaxSize {
+      get { return MaxSizeParameter.Value.Value; }
+      set { MaxSizeParameter.Value.Value = value; }
     }
     public double Nu {
@@ -155,5 +155,5 @@
       Parameters.Add(new FixedValueParameter<IntValue>(SeedParameterName, "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
       Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyParameterName, "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
-      Parameters.Add(new FixedValueParameter<IntValue>(MaxDepthParameterName, "Maximal depth of the tree learned in each step (prefer smaller depths if possible)", new IntValue(5)));
+      Parameters.Add(new FixedValueParameter<IntValue>(MaxSizeParameterName, "Maximal size of the tree learned in each step (prefer smaller sizes if possible)", new IntValue(10)));
       Parameters.Add(new FixedValueParameter<DoubleValue>(RParameterName, "Ratio of training rows selected randomly in each step (0 < R <= 1)", new DoubleValue(0.5)));
       Parameters.Add(new FixedValueParameter<DoubleValue>(MParameterName, "Ratio of variables selected randomly in each step (0 < M <= 1)", new DoubleValue(0.5)));
@@ -189,5 +189,5 @@
       var lossFunction = ApplicationManager.Manager.GetInstances<ILossFunction>()
         .Single(l => l.ToString() == LossFunctionParameter.Value.Value);
-      var state = GradientBoostedTreesAlgorithmStatic.CreateGbmState(problemData, lossFunction, (uint)Seed, MaxDepth, R, M, Nu);
+      var state = GradientBoostedTreesAlgorithmStatic.CreateGbmState(problemData, lossFunction, (uint)Seed, MaxSize, R, M, Nu);
 
       var updateInterval = UpdateIntervalParameter.Value.Value;
Index: /branches/GBT-trunkintegration/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesAlgorithmStatic.cs
===================================================================
--- /branches/GBT-trunkintegration/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesAlgorithmStatic.cs	(revision 12631)
+++ /branches/GBT-trunkintegration/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/GradientBoostedTreesAlgorithmStatic.cs	(revision 12632)
@@ -45,5 +45,5 @@
       internal MersenneTwister random { get; private set; }
       internal ILossFunction lossFunction { get; set; }
-      internal int maxDepth { get; set; }
+      internal int maxSize { get; set; }
       internal double nu { get; set; }
       internal double r { get; set; }
@@ -63,7 +63,7 @@
       internal IList<double> weights;
 
-      public GbmState(IRegressionProblemData problemData, ILossFunction lossFunction, uint randSeed, int maxDepth, double r, double m, double nu) {
-        // default settings for MaxDepth, Nu and R
-        this.maxDepth = maxDepth;
+      public GbmState(IRegressionProblemData problemData, ILossFunction lossFunction, uint randSeed, int maxSize, double r, double m, double nu) {
+        // default settings for MaxSize, Nu and R
+        this.maxSize = maxSize;
         this.nu = nu;
         this.r = r;
@@ -111,6 +111,6 @@
       public double GetTestLoss() {
         var yTest = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TestIndices);
-        var wTest = yTest.Select(_ => 1.0); // ones
-        var nRows = yTest.Count();
+        var wTest = problemData.TestIndices.Select(_ => 1.0); // ones
+        var nRows = problemData.TestIndices.Count();
         return lossFunction.GetLoss(yTest, predTest, wTest) / nRows;
       }
@@ -118,11 +118,11 @@
 
     // simple interface
-    public static IRegressionSolution TrainGbm(IRegressionProblemData problemData, int maxDepth, double nu, double r, int maxIterations) {
-      return TrainGbm(problemData, new SquaredErrorLoss(), maxDepth, nu, r, maxIterations);
+    public static IRegressionSolution TrainGbm(IRegressionProblemData problemData, int maxSize, double nu, double r, int maxIterations) {
+      return TrainGbm(problemData, new SquaredErrorLoss(), maxSize, nu, r, maxIterations);
     }
 
     // simple interface
     public static IRegressionSolution TrainGbm(IRegressionProblemData problemData, ILossFunction lossFunction,
-      int maxDepth, double nu, double r, int maxIterations, uint randSeed = 31415) {
+      int maxSize, double nu, double r, int maxIterations, uint randSeed = 31415) {
       Contract.Assert(r > 0);
       Contract.Assert(r <= 1.0);
@@ -131,5 +131,5 @@
 
       var state = (GbmState)CreateGbmState(problemData, lossFunction, randSeed);
-      state.maxDepth = maxDepth;
+      state.maxSize = maxSize;
       state.r = r;
       state.nu = nu;
@@ -144,6 +144,6 @@
 
     // for custom stepping & termination
-    public static IGbmState CreateGbmState(IRegressionProblemData problemData, ILossFunction lossFunction, uint randSeed, int maxDepth = 3, double r = 0.66, double m = 0.5, double nu = 0.01) {
-      return new GbmState(problemData, lossFunction, randSeed, maxDepth, r, m, nu);
+    public static IGbmState CreateGbmState(IRegressionProblemData problemData, ILossFunction lossFunction, uint randSeed, int maxSize = 3, double r = 0.66, double m = 0.5, double nu = 0.01) {
+      return new GbmState(problemData, lossFunction, randSeed, maxSize, r, m, nu);
     }
 
@@ -153,9 +153,9 @@
       if (gbmState == null) throw new ArgumentException("state");
 
-      MakeStep(gbmState, gbmState.maxDepth, gbmState.nu, gbmState.r, gbmState.m);
+      MakeStep(gbmState, gbmState.maxSize, gbmState.nu, gbmState.r, gbmState.m);
     }
 
     // allow dynamic adaptation of maxDepth, nu and r (even though this is not used)
-    public static void MakeStep(IGbmState state, int maxDepth, double nu, double r, double m) {
+    public static void MakeStep(IGbmState state, int maxSize, double nu, double r, double m) {
       var gbmState = state as GbmState;
       if (gbmState == null) throw new ArgumentException("state");
@@ -177,5 +177,5 @@
       }
 
-      var tree = treeBuilder.CreateRegressionTreeForGradientBoosting(pseudoRes, maxDepth, activeIdx, lossFunction.GetLineSearchFunc(y, yPred, w), r, m);
+      var tree = treeBuilder.CreateRegressionTreeForGradientBoosting(pseudoRes, maxSize, activeIdx, lossFunction.GetLineSearchFunc(y, yPred, w), r, m);
 
       int i = 0;
Index: /branches/GBT-trunkintegration/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/RegressionTreeBuilder.cs
===================================================================
--- /branches/GBT-trunkintegration/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/RegressionTreeBuilder.cs	(revision 12631)
+++ /branches/GBT-trunkintegration/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/RegressionTreeBuilder.cs	(revision 12632)
@@ -54,6 +54,4 @@
     private readonly int[][] sortedIdx; // random selection from sortedIdxAll (for r < 1.0)
 
-    private int calls = 0;
-
     // helper arrays which are allocated to maximal necessary size only once in the ctor
     private readonly int[] internalIdx, which, leftTmp, rightTmp;
@@ -64,12 +62,18 @@
     private int curTreeNodeIdx; // the index where the next tree node is stored
 
-    private class Partition {
-      public int ParentNodeIdx { get; set; }
-      public int Depth { get; set; }
-      public int StartIdx { get; set; }
-      public int EndIndex { get; set; }
-      public bool Left { get; set; }
-    }
-    private readonly SortedList<double, Partition> queue;
+    // This class represents information about potential splits.
+    // For each node generated the best splitting variable and threshold as well as
+    // the improvement from the split are stored in a priority queue
+    private class PartitionSplits {
+      public int ParentNodeIdx { get; set; } // the idx of the leaf node representing this partition 
+      public int StartIdx { get; set; } // the start idx of the partition
+      public int EndIndex { get; set; } // the end idx of the partition
+      public string SplittingVariable { get; set; } // the best splitting variable
+      public double SplittingThreshold { get; set; } // the best threshold
+      public double SplittingImprovement { get; set; } // the improvement of the split (for priority queue)
+    }
+
+    // this list hold partitions with the information about the best split (organized as a sorted queue)
+    private readonly IList<PartitionSplits> queue;
 
     // prepare and allocate buffer variables in ctor
@@ -95,5 +99,5 @@
       outx = new double[rows];
       outSortedIdx = new int[rows];
-      queue = new SortedList<double, Partition>();
+      queue = new List<PartitionSplits>(100);
 
       x = new double[nCols][];
@@ -117,5 +121,5 @@
     // r is fraction of rows to use for training
     // m is fraction of variables to use for training
-    public IRegressionModel CreateRegressionTree(int maxDepth, double r = 0.5, double m = 0.5) {
+    public IRegressionModel CreateRegressionTree(int maxSize, double r = 0.5, double m = 0.5) {
       // subtract mean of y first
       var yAvg = y.Average();
@@ -126,5 +130,5 @@
       var ones = Enumerable.Repeat(1.0, y.Length);
 
-      var model = CreateRegressionTreeForGradientBoosting(y, maxDepth, problemData.TrainingIndices.ToArray(), seLoss.GetLineSearchFunc(y, zeros, ones), r, m);
+      var model = CreateRegressionTreeForGradientBoosting(y, maxSize, problemData.TrainingIndices.ToArray(), seLoss.GetLineSearchFunc(y, zeros, ones), r, m);
 
       return new GradientBoostedTreesModel(new[] { new ConstantRegressionModel(yAvg), model }, new[] { 1.0, 1.0 });
@@ -132,6 +136,6 @@
 
     // specific interface that allows to specify the target labels and the training rows which is necessary when for gradient boosted trees
-    public IRegressionModel CreateRegressionTreeForGradientBoosting(double[] y, int maxDepth, int[] idx, LineSearchFunc lineSearch, double r = 0.5, double m = 0.5) {
-      Debug.Assert(maxDepth > 0);
+    public IRegressionModel CreateRegressionTreeForGradientBoosting(double[] y, int maxSize, int[] idx, LineSearchFunc lineSearch, double r = 0.5, double m = 0.5) {
+      Debug.Assert(maxSize > 0);
       Debug.Assert(r > 0);
       Debug.Assert(r <= 1.0);
@@ -174,22 +178,26 @@
       }
 
-      // prepare array for the tree nodes (a tree of maxDepth=1 has 1 node, a tree of maxDepth=d has 2^d - 1 nodes)      
-      int numNodes = (int)Math.Pow(2, maxDepth) - 1;
-      this.tree = new RegressionTreeModel.TreeNode[numNodes];
+      this.tree = new RegressionTreeModel.TreeNode[maxSize];
+      this.queue.Clear();
       this.curTreeNodeIdx = 0;
 
+      // start out with only one leaf node (constant prediction)
+      // and calculate the best split for this root node and enqueue it into a queue sorted by improvement throught the split
       // start and end idx are inclusive
-      queue.Add(calls++, new Partition() { ParentNodeIdx = -1, Depth = maxDepth, StartIdx = 0, EndIndex = effectiveRows - 1 });
-      CreateRegressionTreeForIdx(lineSearch);
-
-      return new RegressionTreeModel(tree);
-    }
-
-    private void CreateRegressionTreeForIdx(LineSearchFunc lineSearch) {
-      while (queue.Any()) {
-        var f = queue.First().Value; // actually a stack
-        queue.RemoveAt(0);
-
-        var depth = f.Depth;
+      CreateLeafNode(0, effectiveRows - 1, lineSearch);
+
+      // process the priority queue to complete the tree
+      CreateRegressionTreeFromQueue(maxSize, lineSearch);
+
+      return new RegressionTreeModel(tree.ToArray());
+    }
+
+
+    // processes potential splits from the queue as long as splits are left and the maximum size of the tree is not reached
+    private void CreateRegressionTreeFromQueue(int maxNodes, LineSearchFunc lineSearch) {
+      while (queue.Any() && curTreeNodeIdx + 1 < maxNodes) { // two nodes are created in each loop
+        var f = queue[queue.Count - 1]; // last element has the largest improvement
+        queue.RemoveAt(queue.Count - 1);
+
         var startIdx = f.StartIdx;
         var endIdx = f.EndIndex;
@@ -199,50 +207,58 @@
         Debug.Assert(endIdx < internalIdx.Length);
 
-        double threshold;
-        string bestVariableName;
-
-        // stop when only one row is left or no split is possible
-        if (depth <= 1 || endIdx - startIdx == 0 || !FindBestVariableAndThreshold(startIdx, endIdx, out threshold, out bestVariableName)) {
-          CreateLeafNode(startIdx, endIdx, lineSearch);
-          if (f.ParentNodeIdx >= 0) if (f.Left) {
-              tree[f.ParentNodeIdx].leftIdx = curTreeNodeIdx;
-            } else {
-              tree[f.ParentNodeIdx].rightIdx = curTreeNodeIdx;
-            }
-          curTreeNodeIdx++;
-        } else {
-          int splitIdx;
-          CreateInternalNode(f.StartIdx, f.EndIndex, bestVariableName, threshold, out splitIdx);
-
-          // connect to parent tree
-          if (f.ParentNodeIdx >= 0) if (f.Left) {
-              tree[f.ParentNodeIdx].leftIdx = curTreeNodeIdx;
-            } else {
-              tree[f.ParentNodeIdx].rightIdx = curTreeNodeIdx;
-            }
-
-          Debug.Assert(splitIdx + 1 <= endIdx);
-          Debug.Assert(startIdx <= splitIdx);
-
-          queue.Add(calls++, new Partition() { ParentNodeIdx = curTreeNodeIdx, Left = true, Depth = depth - 1, StartIdx = startIdx, EndIndex = splitIdx }); // left part before right part (stack organization)
-          queue.Add(calls++, new Partition() { ParentNodeIdx = curTreeNodeIdx, Left = false, Depth = depth - 1, StartIdx = splitIdx + 1, EndIndex = endIdx });
-          curTreeNodeIdx++;
-
-        }
-      }
-    }
-
-
-    private void CreateLeafNode(int startIdx, int endIdx, LineSearchFunc lineSearch) {
-      // max depth reached or only one element    
-      tree[curTreeNodeIdx].varName = RegressionTreeModel.TreeNode.NO_VARIABLE;
-      tree[curTreeNodeIdx].val = lineSearch(internalIdx, startIdx, endIdx);
-    }
-
-    // routine for building the tree for the partition of rows stored in internalIdx between startIdx and endIdx
-    // the lineSearch function calculates the optimal prediction value for tree leaf nodes 
-    // (in the case of squared errors it is the average of target values for the rows represented by the node)
+        // transform the leaf node into an internal node
+        tree[f.ParentNodeIdx].VarName = f.SplittingVariable;
+        tree[f.ParentNodeIdx].Val = f.SplittingThreshold;
+
+        // split partition into left and right
+        int splitIdx;
+        SplitPartition(f.StartIdx, f.EndIndex, f.SplittingVariable, f.SplittingThreshold, out splitIdx);
+        Debug.Assert(splitIdx + 1 <= endIdx);
+        Debug.Assert(startIdx <= splitIdx);
+
+        // create two leaf nodes (and enqueue best splits for both)
+        tree[f.ParentNodeIdx].LeftIdx = CreateLeafNode(startIdx, splitIdx, lineSearch);
+        tree[f.ParentNodeIdx].RightIdx = CreateLeafNode(splitIdx + 1, endIdx, lineSearch);
+      }
+    }
+
+
+    // returns the index of the newly created tree node
+    private int CreateLeafNode(int startIdx, int endIdx, LineSearchFunc lineSearch) {
+      tree[curTreeNodeIdx].VarName = RegressionTreeModel.TreeNode.NO_VARIABLE;
+      tree[curTreeNodeIdx].Val = lineSearch(internalIdx, startIdx, endIdx);
+
+      EnqueuePartitionSplit(curTreeNodeIdx, startIdx, endIdx);
+      curTreeNodeIdx++;
+      return curTreeNodeIdx - 1;
+    }
+
+
+    // calculates the optimal split for the partition [startIdx .. endIdx] (inclusive) 
+    // which is represented by the leaf node with the specified nodeIdx
+    private void EnqueuePartitionSplit(int nodeIdx, int startIdx, int endIdx) {
+      double threshold, improvement;
+      string bestVariableName;
+      // only enqueue a new split if there are at least 2 rows left and a split is possible
+      if (startIdx < endIdx &&
+        FindBestVariableAndThreshold(startIdx, endIdx, out threshold, out bestVariableName, out improvement)) {
+        var split = new PartitionSplits() {
+          ParentNodeIdx = nodeIdx,
+          StartIdx = startIdx,
+          EndIndex = endIdx,
+          SplittingThreshold = threshold,
+          SplittingVariable = bestVariableName
+        };
+        InsertSortedQueue(split);
+      }
+    }
+
+
+    // routine for splitting a partition of rows stored in internalIdx between startIdx and endIdx into
+    // a left partition and a right partition using the given splittingVariable and threshold
+    // the splitIdx is the last index of the left partition 
+    // splitIdx + 1 is the first index of the right partition
     // startIdx and endIdx are inclusive
-    private void CreateInternalNode(int startIdx, int endIdx, string splittingVar, double threshold, out int splitIdx) {
+    private void SplitPartition(int startIdx, int endIdx, string splittingVar, double threshold, out int splitIdx) {
       int bestVarIdx = varName2Index[splittingVar];
       // split - two pass
@@ -303,10 +319,8 @@
       Debug.Assert(startIdx <= j);
 
-      tree[curTreeNodeIdx].varName = splittingVar;
-      tree[curTreeNodeIdx].val = threshold;
       splitIdx = j;
     }
 
-    private bool FindBestVariableAndThreshold(int startIdx, int endIdx, out double threshold, out string bestVar) {
+    private bool FindBestVariableAndThreshold(int startIdx, int endIdx, out double threshold, out string bestVar, out double improvement) {
       Debug.Assert(startIdx < endIdx + 1); // at least 2 elements
 
@@ -345,24 +359,14 @@
       }
       if (bestVar == RegressionTreeModel.TreeNode.NO_VARIABLE) {
-        threshold = bestThreshold;
+        // not successfull
+        threshold = double.PositiveInfinity;
+        improvement = double.NegativeInfinity;
         return false;
       } else {
         UpdateVariableRelevance(bestVar, sumY, bestImprovement, rows);
+        improvement = bestImprovement;
         threshold = bestThreshold;
         return true;
       }
-    }
-
-    private void UpdateVariableRelevance(string bestVar, double sumY, double bestImprovement, int rows) {
-      if (string.IsNullOrEmpty(bestVar)) return;
-      // update variable relevance
-      double baseLine = 1.0 / rows * sumY * sumY; // if best improvement is equal to baseline then the split had no effect
-
-      double delta = (bestImprovement - baseLine);
-      double v;
-      if (!sumImprovements.TryGetValue(bestVar, out v)) {
-        sumImprovements[bestVar] = delta;
-      }
-      sumImprovements[bestVar] = v + delta;
     }
 
@@ -429,4 +433,17 @@
 
 
+    private void UpdateVariableRelevance(string bestVar, double sumY, double bestImprovement, int rows) {
+      if (string.IsNullOrEmpty(bestVar)) return;
+      // update variable relevance
+      double baseLine = 1.0 / rows * sumY * sumY; // if best improvement is equal to baseline then the split had no effect
+
+      double delta = (bestImprovement - baseLine);
+      double v;
+      if (!sumImprovements.TryGetValue(bestVar, out v)) {
+        sumImprovements[bestVar] = delta;
+      }
+      sumImprovements[bestVar] = v + delta;
+    }
+
     public IEnumerable<KeyValuePair<string, double>> GetVariableRelevance() {
       // values are scaled: the most important variable has relevance = 100
@@ -437,4 +454,16 @@
         .OrderByDescending(t => t.Value);
     }
+
+
+    // insert a new parition split (find insertion point and start at first element of the queue)
+    // elements are removed from the queue at the last position
+    // O(n), splits could be organized as a heap to improve runtime (see alglib tsort)
+    private void InsertSortedQueue(PartitionSplits split) {
+      // find insertion position
+      int i = 0;
+      while (i < queue.Count && queue[i].SplittingImprovement < split.SplittingImprovement) { i++; }
+
+      queue.Insert(i, split);
+    }
   }
 }
Index: /branches/GBT-trunkintegration/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/RegressionTreeModel.cs
===================================================================
--- /branches/GBT-trunkintegration/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/RegressionTreeModel.cs	(revision 12631)
+++ /branches/GBT-trunkintegration/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/RegressionTreeModel.cs	(revision 12632)
@@ -36,11 +36,11 @@
     public struct TreeNode {
       public readonly static string NO_VARIABLE = string.Empty;
-      public string varName; // name of the variable for splitting or -1 if terminal node
-      public double val; // threshold
-      public int leftIdx;
-      public int rightIdx;
+      public string VarName { get; set; } // name of the variable for splitting or -1 if terminal node
+      public double Val { get; set; } // threshold
+      public int LeftIdx { get; set; }
+      public int RightIdx { get; set; }
 
       public override int GetHashCode() {
-        return leftIdx ^ rightIdx ^ val.GetHashCode();
+        return LeftIdx ^ RightIdx ^ Val.GetHashCode();
       }
     }
@@ -64,10 +64,10 @@
     private static double GetPredictionForRow(TreeNode[] t, int nodeIdx, IDataset ds, int row) {
       var node = t[nodeIdx];
-      if (node.varName == TreeNode.NO_VARIABLE)
-        return node.val;
-      else if (ds.GetDoubleValue(node.varName, row) <= node.val)
-        return GetPredictionForRow(t, node.leftIdx, ds, row);
+      if (node.VarName == TreeNode.NO_VARIABLE)
+        return node.Val;
+      else if (ds.GetDoubleValue(node.VarName, row) <= node.Val)
+        return GetPredictionForRow(t, node.LeftIdx, ds, row);
       else
-        return GetPredictionForRow(t, node.rightIdx, ds, row);
+        return GetPredictionForRow(t, node.RightIdx, ds, row);
     }
 
Index: anches/GBT-trunkintegration/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/Test.cs
===================================================================
--- /branches/GBT-trunkintegration/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/Test.cs	(revision 12631)
+++ 	(revision )
@@ -1,181 +1,0 @@
-﻿using System;
-using System.Collections;
-using System.Globalization;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using HeuristicLab.Problems.DataAnalysis;
-using HeuristicLab.Random;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace HeuristicLab.Algorithms.DataAnalysis.GradientBoostedTrees {
-  [TestClass()]
-  public class Test {
-    [TestMethod]
-    [TestCategory("Algorithms.DataAnalysis")]
-    [TestProperty("Time", "short")]
-    public void DecisionTreeTest() {
-      {
-        var xy = new double[,]
-        {
-          {1, 20, 0},
-          {1, 20, 0},
-          {2, 10, 0},
-          {2, 10, 0},
-        };
-        var allVariables = new string[] { "y", "x1", "x2" };
-
-        // x1 <= 15 -> 1 
-        // x1 >  15 -> 2
-        BuildTree(xy, allVariables, 10);
-      }
-
-
-      {
-        var xy = new double[,]
-        {
-          {1, 20,  1},
-          {1, 20, -1},
-          {2, 10, -1},
-          {2, 10, 1},
-        };
-        var allVariables = new string[] { "y", "x1", "x2" };
-
-        // ignore irrelevant variables
-        // x1 <= 15 -> 1 
-        // x1 >  15 -> 2
-        BuildTree(xy, allVariables, 10);
-      }
-
-      {
-        // split must be by x1 first 
-        var xy = new double[,]
-        {
-          {1, 20,  1},
-          {2, 20, -1},
-          {3, 10, -1},
-          {4, 10, 1},
-        };
-
-        var allVariables = new string[] { "y", "x1", "x2" };
-
-        // x1 <= 15 AND x2 <= 0 -> 3 
-        // x1 <= 15 AND x2 >  0 -> 4 
-        // x1 >  15 AND x2 <= 0 -> 1
-        // x1 >  15 AND x2 >  0 -> 2
-        BuildTree(xy, allVariables, 10);
-      }
-
-      {
-        // averaging ys
-        var xy = new double[,]
-        {
-          {0.5, 20,  1},
-          {1.5, 20,  1},
-          {1.5, 20, -1},
-          {2.5, 20, -1},
-          {2.5, 10, -1},
-          {3.5, 10, -1},
-          {3.5, 10, 1},
-          {4.5, 10, 1},
-        };
-
-        var allVariables = new string[] { "y", "x1", "x2" };
-
-        // x1 <= 15 AND x2 <= 0 -> 3 
-        // x1 <= 15 AND x2 >  0 -> 4 
-        // x1 >  15 AND x2 <= 0 -> 1
-        // x1 >  15 AND x2 >  0 -> 2
-        BuildTree(xy, allVariables, 10);
-      }
-
-
-      {
-        // diagonal split (no split possible)
-        var xy = new double[,]
-        {
-          {10, 1, 1},
-          {1, 1, 2},
-          {1, 2, 1},
-          {10, 2, 2},
-        };
-
-        var allVariables = new string[] { "y", "x1", "x2" };
-
-        // split cannot be found
-        BuildTree(xy, allVariables, 3);
-      }
-      {
-        // almost diagonal split 
-        var xy = new double[,]
-        {
-          {10, 1, 1},
-          {1, 1, 2},
-          {1, 2, 1},
-          {10.1, 2, 2},
-        };
-
-        var allVariables = new string[] { "y", "x1", "x2" };
-        // x1 <= 1.5 AND x2 <= 1.5 -> 10 
-        // x1 <= 1.5 AND x2 >  1.5 -> 1 
-        // x1 >  1.5 AND x2 <= 1.5 -> 1
-        // x1 >  1.5 AND x2 >  1.5 -> 10.1
-        BuildTree(xy, allVariables, 3);
-      }
-      {
-        // unbalanced split
-        var xy = new double[,]
-        {
-          {-1, 1, 1},
-          {-1, 1, 2},
-          {0.9, 2, 1},
-          {1.1, 2, 2},
-        };
-
-        var allVariables = new string[] { "y", "x1", "x2" };
-        // x1 <= 1.5 -> -1.0 
-        // x1 >  1.5 AND x2 <= 1.5 -> 0.9
-        // x1 >  1.5 AND x2 >  1.5 -> 1.1
-        BuildTree(xy, allVariables, 3);
-      }
-
-    }
-
-    private void BuildTree(double[,] xy, string[] allVariables, int maxDepth) {
-      int nRows = xy.GetLength(0);
-      var allowedInputs = allVariables.Skip(1);
-      var dataset = new Dataset(allVariables, xy);
-      var problemData = new RegressionProblemData(dataset, allowedInputs, allVariables.First());
-      problemData.TrainingPartition.Start = 0;
-      problemData.TrainingPartition.End = nRows;
-      problemData.TestPartition.Start = nRows;
-      problemData.TestPartition.End = nRows;
-      var rand = new MersenneTwister(31415);
-      var builder = new RegressionTreeBuilder(problemData, rand);
-      var model = (GradientBoostedTreesModel)builder.CreateRegressionTree(maxDepth, 1, 1); // maximal depth and use all rows and cols
-      var constM = model.Models.First() as ConstantRegressionModel;
-      var treeM = model.Models.Skip(1).First() as RegressionTreeModel;
-      WriteTree(treeM.tree, 0, "", constM.Constant);
-      Console.WriteLine();
-    }
-
-    private void WriteTree(RegressionTreeModel.TreeNode[] tree, int idx, string partialRule, double offset) {
-      var n = tree[idx];
-      if (n.varName == RegressionTreeModel.TreeNode.NO_VARIABLE) {
-        Console.WriteLine("{0} -> {1:F}", partialRule, n.val + offset);
-      } else {
-        WriteTree(tree, n.leftIdx,
-          string.Format(CultureInfo.InvariantCulture, "{0}{1}{2} <= {3:F}",
-          partialRule,
-          string.IsNullOrEmpty(partialRule) ? "" : " and ",
-          n.varName,
-          n.val), offset);
-        WriteTree(tree, n.rightIdx,
-          string.Format(CultureInfo.InvariantCulture, "{0}{1}{2} >  {3:F}",
-          partialRule,
-          string.IsNullOrEmpty(partialRule) ? "" : " and ",
-          n.varName,
-          n.val), offset);
-      }
-    }
-  }
-}
Index: /branches/GBT-trunkintegration/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj
===================================================================
--- /branches/GBT-trunkintegration/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 12631)
+++ /branches/GBT-trunkintegration/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 12632)
@@ -199,5 +199,4 @@
       <Private>False</Private>
     </Reference>
-    <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
     <Reference Include="System" />
     <Reference Include="System.Core">
@@ -290,5 +289,4 @@
     <Compile Include="GradientBoostedTrees\RegressionTreeBuilder.cs" />
     <Compile Include="GradientBoostedTrees\RegressionTreeModel.cs" />
-    <Compile Include="GradientBoostedTrees\Test.cs" />
     <Compile Include="Interfaces\IGaussianProcessClassificationModelCreator.cs" />
     <Compile Include="Interfaces\IGaussianProcessRegressionModelCreator.cs" />
Index: /branches/GBT-trunkintegration/Tests/Properties/AssemblyInfo.cs
===================================================================
--- /branches/GBT-trunkintegration/Tests/Properties/AssemblyInfo.cs	(revision 12632)
+++ /branches/GBT-trunkintegration/Tests/Properties/AssemblyInfo.cs	(revision 12632)
@@ -0,0 +1,36 @@
+﻿using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Tests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("FH-Hagenberg")]
+[assembly: AssemblyProduct("Tests")]
+[assembly: AssemblyCopyright("Copyright © FH-Hagenberg 2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("7785b2e8-30ca-4071-a49c-cf5e1c490119")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
Index: /branches/GBT-trunkintegration/Tests/Test.cs
===================================================================
--- /branches/GBT-trunkintegration/Tests/Test.cs	(revision 12632)
+++ /branches/GBT-trunkintegration/Tests/Test.cs	(revision 12632)
@@ -0,0 +1,298 @@
+﻿using System;
+using System.Collections;
+using System.Globalization;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Problems.DataAnalysis;
+using HeuristicLab.Random;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.GradientBoostedTrees {
+  [TestClass()]
+  public class Test {
+    [TestMethod]
+    [TestCategory("Algorithms.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void DecisionTreeTest() {
+      {
+        var xy = new double[,]
+        {
+          {1, 20, 0},
+          {1, 20, 0},
+          {2, 10, 0},
+          {2, 10, 0},
+        };
+        var allVariables = new string[] { "y", "x1", "x2" };
+
+        // x1 <= 15 -> 2 
+        // x1 >  15 -> 1
+        BuildTree(xy, allVariables, 10);
+      }
+
+
+      {
+        var xy = new double[,]
+        {
+          {1, 20,  1},
+          {1, 20, -1},
+          {2, 10, -1},
+          {2, 10, 1},
+        };
+        var allVariables = new string[] { "y", "x1", "x2" };
+
+        // ignore irrelevant variables
+        // x1 <= 15 -> 2 
+        // x1 >  15 -> 1
+        BuildTree(xy, allVariables, 10);
+      }
+
+      {
+        // split must be by x1 first 
+        var xy = new double[,]
+        {
+          {1, 20,  1},
+          {2, 20, -1},
+          {3, 10, -1},
+          {4, 10, 1},
+        };
+
+        var allVariables = new string[] { "y", "x1", "x2" };
+
+        // x1 <= 15 AND x2 <= 0 -> 3 
+        // x1 <= 15 AND x2 >  0 -> 4 
+        // x1 >  15 AND x2 <= 0 -> 2
+        // x1 >  15 AND x2 >  0 -> 1
+        BuildTree(xy, allVariables, 10);
+      }
+
+      {
+        // averaging ys
+        var xy = new double[,]
+        {
+          {0.5, 20,  1},
+          {1.5, 20,  1},
+          {1.5, 20, -1},
+          {2.5, 20, -1},
+          {2.5, 10, -1},
+          {3.5, 10, -1},
+          {3.5, 10, 1},
+          {4.5, 10, 1},
+        };
+
+        var allVariables = new string[] { "y", "x1", "x2" };
+
+        // x1 <= 15 AND x2 <= 0 -> 3 
+        // x1 <= 15 AND x2 >  0 -> 4 
+        // x1 >  15 AND x2 <= 0 -> 2
+        // x1 >  15 AND x2 >  0 -> 1
+        BuildTree(xy, allVariables, 10);
+      }
+
+
+      {
+        // diagonal split (no split possible)
+        var xy = new double[,]
+        {
+          {10, 1, 1},
+          {1, 1, 2},
+          {1, 2, 1},
+          {10, 2, 2},
+        };
+
+        var allVariables = new string[] { "y", "x1", "x2" };
+
+        // split cannot be found
+        // -> 5.50
+        BuildTree(xy, allVariables, 3);
+      }
+      {
+        // almost diagonal split 
+        var xy = new double[,]
+        {
+          {10, 1, 1},
+          {1, 1, 2},
+          {1, 2, 1},
+          {10.1, 2, 2},
+        };
+
+        var allVariables = new string[] { "y", "x1", "x2" };
+        // (two possible solutions)
+        // x2 <= 1.5 -> 5.50
+        // x2 >  1.5 -> 5.55
+        BuildTree(xy, allVariables, 3);
+
+        // x1 <= 1.5 AND x2 <= 1.5 -> 10 
+        // x1 <= 1.5 AND x2 >  1.5 -> 1 
+        // x1 >  1.5 AND x2 <= 1.5 -> 1
+        // x1 >  1.5 AND x2 >  1.5 -> 10.1
+        BuildTree(xy, allVariables, 7);
+      }
+      {
+        // unbalanced split
+        var xy = new double[,]
+        {
+          {-1, 1, 1},
+          {-1, 1, 2},
+          {0.9, 2, 1},
+          {1.1, 2, 2},
+        };
+
+        var allVariables = new string[] { "y", "x1", "x2" };
+        // x1 <= 1.5 -> -1.0 
+        // x1 >  1.5 AND x2 <= 1.5 -> 0.9
+        // x1 >  1.5 AND x2 >  1.5 -> 1.1
+        BuildTree(xy, allVariables, 10);
+      }
+
+      {
+        // unbalanced split
+        var xy = new double[,]
+        {
+          {-1, 1, 1},
+          {-1, 1, 2},
+          {-1, 2, 1},
+          { 1, 2, 2},
+        };
+
+        var allVariables = new string[] { "y", "x1", "x2" };
+        // (two possible solutions)
+        // x2 <= 1.5 -> -1.0 
+        // x2 >  1.5 AND x1 <= 1.5 -> -1.0
+        // x2 >  1.5 AND x1 >  1.5 ->  1.0
+        BuildTree(xy, allVariables, 10);
+      }
+    }
+
+    [TestMethod]
+    [TestCategory("Algorithms.DataAnalysis")]
+    [TestProperty("Time", "long")]
+    public void GradientBoostingTestTowerSquaredError() {
+      var gbt = new GradientBoostedTreesAlgorithm();
+      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.RegressionRealWorldInstanceProvider();
+      var instance = provider.GetDataDescriptors().Single(x => x.Name.Contains("Tower"));
+      var regProblem = new RegressionProblem();
+      regProblem.Load(provider.LoadData(instance));
+
+      #region Algorithm Configuration
+      gbt.Problem = regProblem;
+      gbt.Seed = 0;
+      gbt.SetSeedRandomly = false;
+      gbt.Iterations = 5000;
+      gbt.MaxSize = 20;
+      #endregion
+
+      RunAlgorithm(gbt);
+
+      Assert.AreEqual(267.68704241153921, ((DoubleValue)gbt.Results["Loss (train)"].Value).Value, 1E-6);
+      Assert.AreEqual(393.84704062205469, ((DoubleValue)gbt.Results["Loss (test)"].Value).Value, 1E-6);
+    }
+
+    [TestMethod]
+    [TestCategory("Algorithms.DataAnalysis")]
+    [TestProperty("Time", "long")]
+    public void GradientBoostingTestTowerAbsoluteError() {
+      var gbt = new GradientBoostedTreesAlgorithm();
+      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.RegressionRealWorldInstanceProvider();
+      var instance = provider.GetDataDescriptors().Single(x => x.Name.Contains("Tower"));
+      var regProblem = new RegressionProblem();
+      regProblem.Load(provider.LoadData(instance));
+
+      #region Algorithm Configuration
+      gbt.Problem = regProblem;
+      gbt.Seed = 0;
+      gbt.SetSeedRandomly = false;
+      gbt.Iterations = 1000;
+      gbt.MaxSize = 20;
+      gbt.Nu = 0.02;
+      gbt.LossFunctionParameter.Value = gbt.LossFunctionParameter.ValidValues.First(l => l.ToString().Contains("Absolute"));
+      #endregion
+
+      RunAlgorithm(gbt);
+
+      Assert.AreEqual(10.551385044666661, ((DoubleValue)gbt.Results["Loss (train)"].Value).Value, 1E-6);
+      Assert.AreEqual(12.918001745581172, ((DoubleValue)gbt.Results["Loss (test)"].Value).Value, 1E-6);
+    }
+
+    [TestMethod]
+    [TestCategory("Algorithms.DataAnalysis")]
+    [TestProperty("Time", "long")]
+    public void GradientBoostingTestTowerRelativeError() {
+      var gbt = new GradientBoostedTreesAlgorithm();
+      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.RegressionRealWorldInstanceProvider();
+      var instance = provider.GetDataDescriptors().Single(x => x.Name.Contains("Tower"));
+      var regProblem = new RegressionProblem();
+      regProblem.Load(provider.LoadData(instance));
+
+      #region Algorithm Configuration
+      gbt.Problem = regProblem;
+      gbt.Seed = 0;
+      gbt.SetSeedRandomly = false;
+      gbt.Iterations = 3000;
+      gbt.MaxSize = 20;
+      gbt.Nu = 0.005;
+      gbt.LossFunctionParameter.Value = gbt.LossFunctionParameter.ValidValues.First(l => l.ToString().Contains("Relative"));
+      #endregion
+
+      RunAlgorithm(gbt);
+
+      Assert.AreEqual(0.061954221604374943, ((DoubleValue)gbt.Results["Loss (train)"].Value).Value, 1E-6);
+      Assert.AreEqual(0.06316303473499961, ((DoubleValue)gbt.Results["Loss (test)"].Value).Value, 1E-6);
+    }
+
+    // same as in SamplesUtil
+    private void RunAlgorithm(IAlgorithm a) {
+      var trigger = new EventWaitHandle(false, EventResetMode.ManualReset);
+      Exception ex = null;
+      a.Stopped += (src, e) => { trigger.Set(); };
+      a.ExceptionOccurred += (src, e) => { ex = e.Value; trigger.Set(); };
+      a.Prepare();
+      a.Start();
+      trigger.WaitOne();
+
+      Assert.AreEqual(ex, null);
+    }
+
+    #region helper
+    private void BuildTree(double[,] xy, string[] allVariables, int maxDepth) {
+      int nRows = xy.GetLength(0);
+      var allowedInputs = allVariables.Skip(1);
+      var dataset = new Dataset(allVariables, xy);
+      var problemData = new RegressionProblemData(dataset, allowedInputs, allVariables.First());
+      problemData.TrainingPartition.Start = 0;
+      problemData.TrainingPartition.End = nRows;
+      problemData.TestPartition.Start = nRows;
+      problemData.TestPartition.End = nRows;
+      var rand = new MersenneTwister(31415);
+      var builder = new RegressionTreeBuilder(problemData, rand);
+      var model = (GradientBoostedTreesModel)builder.CreateRegressionTree(maxDepth, 1, 1); // maximal depth and use all rows and cols
+      var constM = model.Models.First() as ConstantRegressionModel;
+      var treeM = model.Models.Skip(1).First() as RegressionTreeModel;
+      WriteTree(treeM.tree, 0, "", constM.Constant);
+      Console.WriteLine();
+    }
+
+    private void WriteTree(RegressionTreeModel.TreeNode[] tree, int idx, string partialRule, double offset) {
+      var n = tree[idx];
+      if (n.VarName == RegressionTreeModel.TreeNode.NO_VARIABLE) {
+        Console.WriteLine("{0} -> {1:F}", partialRule, n.Val + offset);
+      } else {
+        WriteTree(tree, n.LeftIdx,
+          string.Format(CultureInfo.InvariantCulture, "{0}{1}{2} <= {3:F}",
+          partialRule,
+          string.IsNullOrEmpty(partialRule) ? "" : " and ",
+          n.VarName,
+          n.Val), offset);
+        WriteTree(tree, n.RightIdx,
+          string.Format(CultureInfo.InvariantCulture, "{0}{1}{2} >  {3:F}",
+          partialRule,
+          string.IsNullOrEmpty(partialRule) ? "" : " and ",
+          n.VarName,
+          n.Val), offset);
+      }
+    }
+    #endregion
+  }
+}
Index: /branches/GBT-trunkintegration/Tests/Tests.csproj
===================================================================
--- /branches/GBT-trunkintegration/Tests/Tests.csproj	(revision 12632)
+++ /branches/GBT-trunkintegration/Tests/Tests.csproj	(revision 12632)
@@ -0,0 +1,116 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{ABBC647A-B54B-4DF3-9F64-DBD11AD46A15}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Tests</RootNamespace>
+    <AssemblyName>Tests</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
+    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
+    <IsCodedUITest>False</IsCodedUITest>
+    <TestProjectType>UnitTest</TestProjectType>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="HeuristicLab.Collections-3.3">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Collections-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Common-3.3">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Common-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Core-3.3">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Core-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Data-3.3">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Data-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Optimization-3.3">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Optimization-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.DataAnalysis-3.4">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Problems.DataAnalysis-3.4.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.Instances-3.3">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Problems.Instances-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.Instances.DataAnalysis-3.3">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Problems.Instances.DataAnalysis-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Random-3.3">
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Random-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+  </ItemGroup>
+  <Choose>
+    <When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
+      <ItemGroup>
+        <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
+      </ItemGroup>
+    </When>
+    <Otherwise>
+      <ItemGroup>
+        <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
+      </ItemGroup>
+    </Otherwise>
+  </Choose>
+  <ItemGroup>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Test.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\HeuristicLab.Algorithms.DataAnalysis\3.4\HeuristicLab.Algorithms.DataAnalysis-3.4.csproj">
+      <Project>{2e782078-fa81-4b70-b56f-74ce38dac6c8}</Project>
+      <Name>HeuristicLab.Algorithms.DataAnalysis-3.4</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Choose>
+    <When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
+      <ItemGroup>
+        <Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+          <Private>False</Private>
+        </Reference>
+        <Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+          <Private>False</Private>
+        </Reference>
+        <Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+          <Private>False</Private>
+        </Reference>
+        <Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+          <Private>False</Private>
+        </Reference>
+      </ItemGroup>
+    </When>
+  </Choose>
+  <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
