Index: branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/BaselineClassifiers/OneR.cs
===================================================================
--- branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/BaselineClassifiers/OneR.cs	(revision 13090)
+++ branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/BaselineClassifiers/OneR.cs	(revision 13090)
@@ -0,0 +1,170 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  /// <summary>
+  /// 1R classification algorithm.
+  /// </summary>
+  [Item("OneR Classification", "A simple classification algorithm the searches the best single-variable split (does not support categorical features correctly). See R.C. Holte (1993). Very simple classification rules perform well on most commonly used datasets. Machine Learning. 11:63-91.")]
+  [StorableClass]
+  [Creatable("Data Analysis")] // TODO
+  public sealed class OneR : FixedDataAnalysisAlgorithm<IClassificationProblem> {
+
+    public IValueParameter<IntValue> MinBucketSizeParameter {
+      get { return (IValueParameter<IntValue>)Parameters["MinBucketSize"]; }
+    }
+
+    [StorableConstructor]
+    private OneR(bool deserializing) : base(deserializing) { }
+
+    private OneR(OneR original, Cloner cloner)
+      : base(original, cloner) { }
+
+    public OneR()
+      : base() {
+      Parameters.Add(new ValueParameter<IntValue>("MinBucketSize", "Minimum size of a bucket for numerical values. (Except for the rightmost bucket)", new IntValue(6)));
+      Problem = new ClassificationProblem();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OneR(this, cloner);
+    }
+
+    protected override void Run() {
+      var solution = CreateOneRSolution(Problem.ProblemData, MinBucketSizeParameter.Value.Value);
+      Results.Add(new Result("OneR solution", "The 1R classifier.", solution));
+    }
+
+    public static IClassificationSolution CreateOneRSolution(IClassificationProblemData problemData, int minBucketSize = 6) {
+      var bestClassified = 0;
+      List<Split> bestSplits = null;
+      string bestVariable = string.Empty;
+      double bestMissingValuesClass = double.NaN;
+      var classValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices);
+
+      foreach (var variable in problemData.AllowedInputVariables) {
+        var inputValues = problemData.Dataset.GetDoubleValues(variable, problemData.TrainingIndices);
+        var samples = inputValues.Zip(classValues, (i, v) => new Sample(i, v)).OrderBy(s => s.inputValue);
+
+        var missingValuesDistribution = samples.Where(s => double.IsNaN(s.inputValue)).GroupBy(s => s.classValue).ToDictionary(s => s.Key, s => s.Count()).MaxItems(s => s.Value).FirstOrDefault();
+
+        //calculate class distributions for all distinct inputValues
+        List<Dictionary<double, int>> classDistributions = new List<Dictionary<double, int>>();
+        List<double> thresholds = new List<double>();
+        double lastValue = double.NaN;
+        foreach (var sample in samples.Where(s => !double.IsNaN(s.inputValue))) {
+          if (sample.inputValue > lastValue || double.IsNaN(lastValue)) {
+            if (!double.IsNaN(lastValue)) thresholds.Add((lastValue + sample.inputValue) / 2);
+            lastValue = sample.inputValue;
+            classDistributions.Add(new Dictionary<double, int>());
+            foreach (var classValue in problemData.ClassValues)
+              classDistributions[classDistributions.Count - 1][classValue] = 0;
+
+          }
+          classDistributions[classDistributions.Count - 1][sample.classValue]++;
+        }
+        thresholds.Add(double.PositiveInfinity);
+
+        var distribution = classDistributions[0];
+        var threshold = thresholds[0];
+        var splits = new List<Split>();
+
+        for (int i = 1; i < classDistributions.Count; i++) {
+          var samplesInSplit = distribution.Max(d => d.Value);
+          //join splits if there are too few samples in the split or the distributions has the same maximum class value as the current split
+          if (samplesInSplit < minBucketSize ||
+            classDistributions[i].MaxItems(d => d.Value).Select(d => d.Key).Contains(
+              distribution.MaxItems(d => d.Value).Select(d => d.Key).First())) {
+            foreach (var classValue in classDistributions[i])
+              distribution[classValue.Key] += classValue.Value;
+            threshold = thresholds[i];
+          } else {
+            splits.Add(new Split(threshold, distribution.MaxItems(d => d.Value).Select(d => d.Key).First()));
+            distribution = classDistributions[i];
+            threshold = thresholds[i];
+          }
+        }
+        splits.Add(new Split(double.PositiveInfinity, distribution.MaxItems(d => d.Value).Select(d => d.Key).First()));
+
+        int correctClassified = 0;
+        int splitIndex = 0;
+        foreach (var sample in samples.Where(s => !double.IsNaN(s.inputValue))) {
+          while (sample.inputValue >= splits[splitIndex].thresholdValue)
+            splitIndex++;
+          correctClassified += sample.classValue == splits[splitIndex].classValue ? 1 : 0;
+        }
+        correctClassified += missingValuesDistribution.Value;
+
+        if (correctClassified > bestClassified) {
+          bestClassified = correctClassified;
+          bestSplits = splits;
+          bestVariable = variable;
+          bestMissingValuesClass = missingValuesDistribution.Value == 0 ? double.NaN : missingValuesDistribution.Key;
+        }
+      }
+
+      //remove neighboring splits with the same class value
+      for (int i = 0; i < bestSplits.Count - 1; i++) {
+        if (bestSplits[i].classValue == bestSplits[i + 1].classValue) {
+          bestSplits.Remove(bestSplits[i]);
+          i--;
+        }
+      }
+
+      var model = new OneRClassificationModel(bestVariable, bestSplits.Select(s => s.thresholdValue).ToArray(), bestSplits.Select(s => s.classValue).ToArray(), bestMissingValuesClass);
+      var solution = new OneRClassificationSolution(model, (IClassificationProblemData)problemData.Clone());
+
+      return solution;
+    }
+
+    #region helper classes
+    private class Split {
+      public double thresholdValue;
+      public double classValue;
+
+      public Split(double thresholdValue, double classValue) {
+        this.thresholdValue = thresholdValue;
+        this.classValue = classValue;
+      }
+    }
+
+    private class Sample {
+      public double inputValue;
+      public double classValue;
+
+      public Sample(double inputValue, double classValue) {
+        this.inputValue = inputValue;
+        this.classValue = classValue;
+      }
+    }
+    #endregion
+  }
+}
Index: branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/BaselineClassifiers/OneRClassificationModel.cs
===================================================================
--- branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/BaselineClassifiers/OneRClassificationModel.cs	(revision 13090)
+++ branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/BaselineClassifiers/OneRClassificationModel.cs	(revision 13090)
@@ -0,0 +1,115 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableClass]
+  [Item("1R Classification Model", "A model that uses intervals for one variable to determine the class.")]
+  public class OneRClassificationModel : NamedItem, IClassificationModel {
+    [Storable]
+    protected string variable;
+    public string Variable {
+      get { return variable; }
+    }
+
+    [Storable]
+    protected double[] splits;
+    public double[] Splits {
+      get { return splits; }
+    }
+
+    [Storable]
+    protected double[] classes;
+    public double[] Classes {
+      get { return classes; }
+    }
+
+    [Storable]
+    protected double missingValuesClass;
+    public double MissingValuesClass {
+      get { return missingValuesClass; }
+    }
+
+    [StorableConstructor]
+    protected OneRClassificationModel(bool deserializing) : base(deserializing) { }
+    protected OneRClassificationModel(OneRClassificationModel original, Cloner cloner)
+      : base(original, cloner) {
+      this.variable = (string)original.variable;
+      this.splits = (double[])original.splits.Clone();
+      this.classes = (double[])original.classes.Clone();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) { return new OneRClassificationModel(this, cloner); }
+
+    public OneRClassificationModel(string variable, double[] splits, double[] classes, double missingValuesClass = double.NaN)
+      : base() {
+      if (splits.Length != classes.Length) {
+        throw new ArgumentException("Number of splits and classes has to be equal.");
+      }
+      if (!Double.IsPositiveInfinity(splits[splits.Length - 1])) {
+        throw new ArgumentException("Last split has to be double.PositiveInfinity, so that all values are covered.");
+      }
+      this.name = ItemName;
+      this.description = ItemDescription;
+      this.variable = variable;
+      this.splits = splits;
+      this.classes = classes;
+      this.missingValuesClass = missingValuesClass;
+    }
+
+    // uses sorting to return the values in the order of rows, instead of using nested for loops
+    // to avoid O(n²) runtime
+    public IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
+      var values = dataset.GetDoubleValues(Variable, rows).ToArray();
+      var rowsArray = rows.ToArray();
+      var order = Enumerable.Range(0, rowsArray.Length).ToArray();
+      double[] estimated = new double[rowsArray.Length];
+      Array.Sort(rowsArray, order);
+      Array.Sort(values, rowsArray);
+      int curSplit = 0, curIndex = 0;
+      while (curIndex < values.Length && Double.IsNaN(values[curIndex])) {
+        estimated[curIndex] = MissingValuesClass;
+        curIndex++;
+      }
+      while (curSplit < Splits.Length) {
+        while (curIndex < values.Length && Splits[curSplit] > values[curIndex]) {
+          estimated[curIndex] = classes[curSplit];
+          curIndex++;
+        }
+        curSplit++;
+      }
+      Array.Sort(rowsArray, estimated);
+      Array.Sort(order, estimated);
+      return estimated;
+    }
+
+    public IClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData) {
+      return new OneRClassificationSolution(this, new ClassificationProblemData(problemData));
+    }
+
+  }
+}
Index: branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/BaselineClassifiers/OneRClassificationSolution.cs
===================================================================
--- branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/BaselineClassifiers/OneRClassificationSolution.cs	(revision 13090)
+++ branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/BaselineClassifiers/OneRClassificationSolution.cs	(revision 13090)
@@ -0,0 +1,48 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableClass]
+  [Item(Name = "1R Classification Solution", Description = "Represents a 1R classification solution (model + data).")]
+  public class OneRClassificationSolution : ClassificationSolution {
+    public new OneRClassificationModel Model {
+      get { return (OneRClassificationModel)base.Model; }
+      set { base.Model = value; }
+    }
+
+    [StorableConstructor]
+    protected OneRClassificationSolution(bool deserializing) : base(deserializing) { }
+    protected OneRClassificationSolution(OneRClassificationSolution original, Cloner cloner) : base(original, cloner) { }
+    public OneRClassificationSolution(OneRClassificationModel model, IClassificationProblemData problemData)
+      : base(model, problemData) {
+      RecalculateResults();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OneRClassificationSolution(this, cloner);
+    }
+  }
+}
Index: branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/BaselineClassifiers/ZeroR.cs
===================================================================
--- branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/BaselineClassifiers/ZeroR.cs	(revision 13090)
+++ branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/BaselineClassifiers/ZeroR.cs	(revision 13090)
@@ -0,0 +1,72 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  /// <summary>
+  /// 0R classification algorithm.
+  /// </summary>
+  [Item("ZeroR", "The simplest possible classifier, ZeroR always predicts the majority class.")]
+  [Creatable("Data Analysis")] // TODO
+  [StorableClass]
+  public sealed class ZeroR : FixedDataAnalysisAlgorithm<IClassificationProblem> {
+
+    [StorableConstructor]
+    private ZeroR(bool deserializing) : base(deserializing) { }
+    private ZeroR(ZeroR original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public ZeroR()
+      : base() {
+      Problem = new ClassificationProblem();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ZeroR(this, cloner);
+    }
+
+    protected override void Run() {
+      var solution = CreateZeroRSolution(Problem.ProblemData);
+      Results.Add(new Result("ZeroR solution", "The simplest possible classifier, ZeroR always predicts the majority class.", solution));
+    }
+
+    public static IClassificationSolution CreateZeroRSolution(IClassificationProblemData problemData) {
+      var dataset = problemData.Dataset;
+      string target = problemData.TargetVariable;
+      var targetValues = dataset.GetDoubleValues(target, problemData.TrainingIndices);
+
+
+      // if multiple classes have the same number of observations then simply take the first one
+      var dominantClass = targetValues.GroupBy(x => x).ToDictionary(g => g.Key, g => g.Count())
+        .MaxItems(kvp => kvp.Value).Select(x => x.Key).First();
+
+      var model = new ConstantRegressionModel(dominantClass);
+      var solution = new ConstantClassificationSolution(model, (IClassificationProblemData)problemData.Clone());
+      return solution;
+    }
+  }
+}
Index: branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj
===================================================================
--- branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 13089)
+++ branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 13090)
@@ -202,4 +202,8 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="BaselineClassifiers\OneR.cs" />
+    <Compile Include="BaselineClassifiers\OneRClassificationModel.cs" />
+    <Compile Include="BaselineClassifiers\OneRClassificationSolution.cs" />
+    <Compile Include="BaselineClassifiers\ZeroR.cs" />
     <Compile Include="CrossValidation.cs">
       <SubType>Code</SubType>
@@ -317,7 +321,4 @@
     </Compile>
     <Compile Include="Linear\AlglibUtil.cs" />
-    <Compile Include="Linear\OneRTest.cs" />
-    <Compile Include="Linear\OneR\OneRClassificationModel.cs" />
-    <Compile Include="Linear\OneR\OneRClassificationSolution.cs" />
     <Compile Include="Linear\Scaling.cs" />
     <Compile Include="Linear\LinearDiscriminantAnalysis.cs" />
@@ -328,5 +329,4 @@
     <Compile Include="Linear\MultinomialLogitClassificationSolution.cs" />
     <Compile Include="Linear\MultinomialLogitModel.cs" />
-    <Compile Include="Linear\ZeroR.cs" />
     <Compile Include="Nca\Initialization\INcaInitializer.cs" />
     <Compile Include="Nca\Initialization\LdaInitializer.cs" />
Index: branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/OneR/OneRClassificationModel.cs
===================================================================
--- branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/OneR/OneRClassificationModel.cs	(revision 13089)
+++ 	(revision )
@@ -1,115 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.Problems.DataAnalysis;
-
-namespace HeuristicLab.Algorithms.DataAnalysis {
-  [StorableClass]
-  [Item("1R Classification Model", "A model that uses intervals for one variable to determine the class.")]
-  public class OneRClassificationModel : NamedItem, IClassificationModel {
-    [Storable]
-    protected string variable;
-    public string Variable {
-      get { return variable; }
-    }
-
-    [Storable]
-    protected double[] splits;
-    public double[] Splits {
-      get { return splits; }
-    }
-
-    [Storable]
-    protected double[] classes;
-    public double[] Classes {
-      get { return classes; }
-    }
-
-    [Storable]
-    protected double missingValuesClass;
-    public double MissingValuesClass {
-      get { return missingValuesClass; }
-    }
-
-    [StorableConstructor]
-    protected OneRClassificationModel(bool deserializing) : base(deserializing) { }
-    protected OneRClassificationModel(OneRClassificationModel original, Cloner cloner)
-      : base(original, cloner) {
-      this.variable = (string)original.variable;
-      this.splits = (double[])original.splits.Clone();
-      this.classes = (double[])original.classes.Clone();
-    }
-    public override IDeepCloneable Clone(Cloner cloner) { return new OneRClassificationModel(this, cloner); }
-
-    public OneRClassificationModel(string variable, double[] splits, double[] classes, double missingValuesClass = double.NaN)
-      : base() {
-      if (splits.Length != classes.Length) {
-        throw new ArgumentException("Number of splits and classes has to be equal.");
-      }
-      if (!Double.IsPositiveInfinity(splits[splits.Length - 1])) {
-        throw new ArgumentException("Last split has to be double.PositiveInfinity, so that all values are covered.");
-      }
-      this.name = ItemName;
-      this.description = ItemDescription;
-      this.variable = variable;
-      this.splits = splits;
-      this.classes = classes;
-      this.missingValuesClass = missingValuesClass;
-    }
-
-    // uses sorting to return the values in the order of rows, instead of using nested for loops
-    // to avoid O(n²) runtime
-    public IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
-      var values = dataset.GetDoubleValues(Variable, rows).ToArray();
-      var rowsArray = rows.ToArray();
-      var order = Enumerable.Range(0, rowsArray.Length).ToArray();
-      double[] estimated = new double[rowsArray.Length];
-      Array.Sort(rowsArray, order);
-      Array.Sort(values, rowsArray);
-      int curSplit = 0, curIndex = 0;
-      while (curIndex < values.Length && Double.IsNaN(values[curIndex])) {
-        estimated[curIndex] = MissingValuesClass;
-        curIndex++;
-      }
-      while (curSplit < Splits.Length) {
-        while (curIndex < values.Length && Splits[curSplit] > values[curIndex]) {
-          estimated[curIndex] = classes[curSplit];
-          curIndex++;
-        }
-        curSplit++;
-      }
-      Array.Sort(rowsArray, estimated);
-      Array.Sort(order, estimated);
-      return estimated;
-    }
-
-    public IClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData) {
-      return new OneRClassificationSolution(this, new ClassificationProblemData(problemData));
-    }
-
-  }
-}
Index: branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/OneR/OneRClassificationSolution.cs
===================================================================
--- branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/OneR/OneRClassificationSolution.cs	(revision 13089)
+++ 	(revision )
@@ -1,48 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.Problems.DataAnalysis;
-
-namespace HeuristicLab.Algorithms.DataAnalysis {
-  [StorableClass]
-  [Item(Name = "1R Classification Solution", Description = "Represents a 1R classification solution (model + data).")]
-  public class OneRClassificationSolution : ClassificationSolution {
-    public new OneRClassificationModel Model {
-      get { return (OneRClassificationModel)base.Model; }
-      set { base.Model = value; }
-    }
-
-    [StorableConstructor]
-    protected OneRClassificationSolution(bool deserializing) : base(deserializing) { }
-    protected OneRClassificationSolution(OneRClassificationSolution original, Cloner cloner) : base(original, cloner) { }
-    public OneRClassificationSolution(OneRClassificationModel model, IClassificationProblemData problemData)
-      : base(model, problemData) {
-      RecalculateResults();
-    }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OneRClassificationSolution(this, cloner);
-    }
-  }
-}
Index: branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/OneRTest.cs
===================================================================
--- branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/OneRTest.cs	(revision 13089)
+++ 	(revision )
@@ -1,169 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System.Collections.Generic;
-using System.Linq;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Data;
-using HeuristicLab.Optimization;
-using HeuristicLab.Parameters;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.Problems.DataAnalysis;
-
-namespace HeuristicLab.Algorithms.DataAnalysis {
-  /// <summary>
-  /// 1R classification algorithm.
-  /// </summary>
-  [Item("OneR Classification", "A simple classification algorithm the searches the best single-variable split (does not support categorical features correctly).")]
-  [StorableClass]
-  public sealed class OneRTest : FixedDataAnalysisAlgorithm<IClassificationProblem> {
-
-    public IValueParameter<IntValue> MinBucketSizeParameter {
-      get { return (IValueParameter<IntValue>)Parameters["MinBucketSize"]; }
-    }
-
-    [StorableConstructor]
-    private OneRTest(bool deserializing) : base(deserializing) { }
-
-    private OneRTest(OneRTest original, Cloner cloner)
-      : base(original, cloner) { }
-
-    public OneRTest()
-      : base() {
-      Parameters.Add(new ValueParameter<IntValue>("MinBucketSize", "Minimum size of a bucket for numerical values. (Except for the rightmost bucket)", new IntValue(6)));
-      Problem = new ClassificationProblem();
-    }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OneRTest(this, cloner);
-    }
-
-    protected override void Run() {
-      var solution = CreateOneRSolution(Problem.ProblemData, MinBucketSizeParameter.Value.Value);
-      Results.Add(new Result("OneR solution", "The 1R classifier.", solution));
-    }
-
-    public static IClassificationSolution CreateOneRSolution(IClassificationProblemData problemData, int minBucketSize = 6) {
-      var bestClassified = 0;
-      List<Split> bestSplits = null;
-      string bestVariable = string.Empty;
-      double bestMissingValuesClass = double.NaN;
-      var classValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices);
-
-      foreach (var variable in problemData.AllowedInputVariables) {
-        var inputValues = problemData.Dataset.GetDoubleValues(variable, problemData.TrainingIndices);
-        var samples = inputValues.Zip(classValues, (i, v) => new Sample(i, v)).OrderBy(s => s.inputValue);
-
-        var missingValuesDistribution = samples.Where(s => double.IsNaN(s.inputValue)).GroupBy(s => s.classValue).ToDictionary(s => s.Key, s => s.Count()).MaxItems(s => s.Value).FirstOrDefault();
-
-        //calculate class distributions for all distinct inputValues
-        List<Dictionary<double, int>> classDistributions = new List<Dictionary<double, int>>();
-        List<double> thresholds = new List<double>();
-        double lastValue = double.NaN;
-        foreach (var sample in samples.Where(s => !double.IsNaN(s.inputValue))) {
-          if (sample.inputValue > lastValue || double.IsNaN(lastValue)) {
-            if (!double.IsNaN(lastValue)) thresholds.Add((lastValue + sample.inputValue) / 2);
-            lastValue = sample.inputValue;
-            classDistributions.Add(new Dictionary<double, int>());
-            foreach (var classValue in problemData.ClassValues)
-              classDistributions[classDistributions.Count - 1][classValue] = 0;
-
-          }
-          classDistributions[classDistributions.Count - 1][sample.classValue]++;
-        }
-        thresholds.Add(double.PositiveInfinity);
-
-        var distribution = classDistributions[0];
-        var threshold = thresholds[0];
-        var splits = new List<Split>();
-
-        for (int i = 1; i < classDistributions.Count; i++) {
-          var samplesInSplit = distribution.Max(d => d.Value);
-          //join splits if there are too few samples in the split or the distributions has the same maximum class value as the current split
-          if (samplesInSplit < minBucketSize ||
-            classDistributions[i].MaxItems(d => d.Value).Select(d => d.Key).Contains(
-              distribution.MaxItems(d => d.Value).Select(d => d.Key).First())) {
-            foreach (var classValue in classDistributions[i])
-              distribution[classValue.Key] += classValue.Value;
-            threshold = thresholds[i];
-          } else {
-            splits.Add(new Split(threshold, distribution.MaxItems(d => d.Value).Select(d => d.Key).First()));
-            distribution = classDistributions[i];
-            threshold = thresholds[i];
-          }
-        }
-        splits.Add(new Split(double.PositiveInfinity, distribution.MaxItems(d => d.Value).Select(d => d.Key).First()));
-
-        int correctClassified = 0;
-        int splitIndex = 0;
-        foreach (var sample in samples.Where(s => !double.IsNaN(s.inputValue))) {
-          while (sample.inputValue >= splits[splitIndex].thresholdValue)
-            splitIndex++;
-          correctClassified += sample.classValue == splits[splitIndex].classValue ? 1 : 0;
-        }
-        correctClassified += missingValuesDistribution.Value;
-
-        if (correctClassified > bestClassified) {
-          bestClassified = correctClassified;
-          bestSplits = splits;
-          bestVariable = variable;
-          bestMissingValuesClass = missingValuesDistribution.Value == 0 ? double.NaN : missingValuesDistribution.Key;
-        }
-      }
-
-      //remove neighboring splits with the same class value
-      for (int i = 0; i < bestSplits.Count - 1; i++) {
-        if (bestSplits[i].classValue == bestSplits[i + 1].classValue) {
-          bestSplits.Remove(bestSplits[i]);
-          i--;
-        }
-      }
-
-      var model = new OneRClassificationModel(bestVariable, bestSplits.Select(s => s.thresholdValue).ToArray(), bestSplits.Select(s => s.classValue).ToArray(), bestMissingValuesClass);
-      var solution = new OneRClassificationSolution(model, (IClassificationProblemData)problemData.Clone());
-
-      return solution;
-    }
-
-    #region helper classes
-    private class Split {
-      public double thresholdValue;
-      public double classValue;
-
-      public Split(double thresholdValue, double classValue) {
-        this.thresholdValue = thresholdValue;
-        this.classValue = classValue;
-      }
-    }
-
-    private class Sample {
-      public double inputValue;
-      public double classValue;
-
-      public Sample(double inputValue, double classValue) {
-        this.inputValue = inputValue;
-        this.classValue = classValue;
-      }
-    }
-    #endregion
-  }
-}
Index: branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/ZeroR.cs
===================================================================
--- branches/ClassificationModelComparison/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/ZeroR.cs	(revision 13089)
+++ 	(revision )
@@ -1,72 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System.Linq;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Optimization;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.Problems.DataAnalysis;
-
-namespace HeuristicLab.Algorithms.DataAnalysis {
-  /// <summary>
-  /// 0R classification algorithm.
-  /// </summary>
-  [Item("ZeroR", "The simplest possible classifier, ZeroR always predicts the majority class.")]
-  [Creatable("Data Analysis")] // TODO
-  [StorableClass]
-  public sealed class ZeroR : FixedDataAnalysisAlgorithm<IClassificationProblem> {
-
-    [StorableConstructor]
-    private ZeroR(bool deserializing) : base(deserializing) { }
-    private ZeroR(ZeroR original, Cloner cloner)
-      : base(original, cloner) {
-    }
-    public ZeroR()
-      : base() {
-      Problem = new ClassificationProblem();
-    }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new ZeroR(this, cloner);
-    }
-
-    protected override void Run() {
-      var solution = CreateZeroRSolution(Problem.ProblemData);
-      Results.Add(new Result("ZeroR solution", "The simplest possible classifier, ZeroR always predicts the majority class.", solution));
-    }
-
-    public static IClassificationSolution CreateZeroRSolution(IClassificationProblemData problemData) {
-      var dataset = problemData.Dataset;
-      string target = problemData.TargetVariable;
-      var targetValues = dataset.GetDoubleValues(target, problemData.TrainingIndices);
-
-
-      // if multiple classes have the same number of observations then simply take the first one
-      var dominantClass = targetValues.GroupBy(x => x).ToDictionary(g => g.Key, g => g.Count())
-        .MaxItems(kvp => kvp.Value).Select(x => x.Key).First();
-
-      var model = new ConstantRegressionModel(dominantClass);
-      var solution = new ConstantClassificationSolution(model, (IClassificationProblemData)problemData.Clone());
-      return solution;
-    }
-  }
-}
