Index: stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/ClassificationSolutionVariableImpactsView.Designer.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/ClassificationSolutionVariableImpactsView.Designer.cs	(revision 16437)
+++ stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/ClassificationSolutionVariableImpactsView.Designer.cs	(revision 16438)
@@ -19,4 +19,6 @@
  */
 #endregion
+
+
 namespace HeuristicLab.Problems.DataAnalysis.Views {
   partial class ClassificationSolutionVariableImpactsView {
@@ -44,61 +46,73 @@
     /// </summary>
     private void InitializeComponent() {
-      this.variableImactsArrayView = new HeuristicLab.Data.Views.StringConvertibleArrayView();
-      this.dataPartitionComboBox = new System.Windows.Forms.ComboBox();
-      this.dataPartitionLabel = new System.Windows.Forms.Label();
-      this.numericVarReplacementLabel = new System.Windows.Forms.Label();
-      this.replacementComboBox = new System.Windows.Forms.ComboBox();
-      this.factorVarReplacementLabel = new System.Windows.Forms.Label();
-      this.factorVarReplComboBox = new System.Windows.Forms.ComboBox();
       this.ascendingCheckBox = new System.Windows.Forms.CheckBox();
       this.sortByLabel = new System.Windows.Forms.Label();
       this.sortByComboBox = new System.Windows.Forms.ComboBox();
-      this.backgroundWorker = new System.ComponentModel.BackgroundWorker();
+      this.factorVarReplComboBox = new System.Windows.Forms.ComboBox();
+      this.factorVarReplacementLabel = new System.Windows.Forms.Label();
+      this.replacementComboBox = new System.Windows.Forms.ComboBox();
+      this.numericVarReplacementLabel = new System.Windows.Forms.Label();
+      this.dataPartitionLabel = new System.Windows.Forms.Label();
+      this.dataPartitionComboBox = new System.Windows.Forms.ComboBox();
+      this.variableImpactsArrayView = new HeuristicLab.Data.Views.StringConvertibleArrayView();
       this.SuspendLayout();
       // 
-      // variableImactsArrayView
-      // 
-      this.variableImactsArrayView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
-            | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-      this.variableImactsArrayView.Caption = "StringConvertibleArray View";
-      this.variableImactsArrayView.Content = null;
-      this.variableImactsArrayView.Location = new System.Drawing.Point(3, 84);
-      this.variableImactsArrayView.Name = "variableImactsArrayView";
-      this.variableImactsArrayView.ReadOnly = true;
-      this.variableImactsArrayView.Size = new System.Drawing.Size(662, 278);
-      this.variableImactsArrayView.TabIndex = 2;
-      // 
-      // dataPartitionComboBox
-      // 
-      this.dataPartitionComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-      this.dataPartitionComboBox.FormattingEnabled = true;
-      this.dataPartitionComboBox.Items.AddRange(new object[] {
-            HeuristicLab.Problems.DataAnalysis.ClassificationSolutionVariableImpactsCalculator.DataPartitionEnum.Training,
-            HeuristicLab.Problems.DataAnalysis.ClassificationSolutionVariableImpactsCalculator.DataPartitionEnum.Test,
-            HeuristicLab.Problems.DataAnalysis.ClassificationSolutionVariableImpactsCalculator.DataPartitionEnum.All});
-      this.dataPartitionComboBox.Location = new System.Drawing.Point(197, 3);
-      this.dataPartitionComboBox.Name = "dataPartitionComboBox";
-      this.dataPartitionComboBox.Size = new System.Drawing.Size(121, 21);
-      this.dataPartitionComboBox.TabIndex = 1;
-      this.dataPartitionComboBox.SelectedIndexChanged += new System.EventHandler(this.dataPartitionComboBox_SelectedIndexChanged);
-      // 
-      // dataPartitionLabel
-      // 
-      this.dataPartitionLabel.AutoSize = true;
-      this.dataPartitionLabel.Location = new System.Drawing.Point(3, 6);
-      this.dataPartitionLabel.Name = "dataPartitionLabel";
-      this.dataPartitionLabel.Size = new System.Drawing.Size(73, 13);
-      this.dataPartitionLabel.TabIndex = 0;
-      this.dataPartitionLabel.Text = "Data partition:";
-      // 
-      // numericVarReplacementLabel
-      // 
-      this.numericVarReplacementLabel.AutoSize = true;
-      this.numericVarReplacementLabel.Location = new System.Drawing.Point(3, 33);
-      this.numericVarReplacementLabel.Name = "numericVarReplacementLabel";
-      this.numericVarReplacementLabel.Size = new System.Drawing.Size(173, 13);
-      this.numericVarReplacementLabel.TabIndex = 2;
-      this.numericVarReplacementLabel.Text = "Replacement for numeric variables:";
+      // ascendingCheckBox
+      // 
+      this.ascendingCheckBox.AutoSize = true;
+      this.ascendingCheckBox.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+      this.ascendingCheckBox.Location = new System.Drawing.Point(452, 32);
+      this.ascendingCheckBox.Name = "ascendingCheckBox";
+      this.ascendingCheckBox.Size = new System.Drawing.Size(76, 17);
+      this.ascendingCheckBox.TabIndex = 7;
+      this.ascendingCheckBox.Text = "Ascending";
+      this.ascendingCheckBox.UseVisualStyleBackColor = true;
+      this.ascendingCheckBox.CheckedChanged += new System.EventHandler(this.ascendingCheckBox_CheckedChanged);
+      // 
+      // sortByLabel
+      // 
+      this.sortByLabel.AutoSize = true;
+      this.sortByLabel.Location = new System.Drawing.Point(324, 6);
+      this.sortByLabel.Name = "sortByLabel";
+      this.sortByLabel.Size = new System.Drawing.Size(77, 13);
+      this.sortByLabel.TabIndex = 4;
+      this.sortByLabel.Text = "Sorting criteria:";
+      // 
+      // sortByComboBox
+      // 
+      this.sortByComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.sortByComboBox.FormattingEnabled = true;
+      this.sortByComboBox.Items.AddRange(new object[] {
+            HeuristicLab.Problems.DataAnalysis.Views.ClassificationSolutionVariableImpactsView.SortingCriteria.ImpactValue,
+            HeuristicLab.Problems.DataAnalysis.Views.ClassificationSolutionVariableImpactsView.SortingCriteria.Occurrence,
+            HeuristicLab.Problems.DataAnalysis.Views.ClassificationSolutionVariableImpactsView.SortingCriteria.VariableName});
+      this.sortByComboBox.Location = new System.Drawing.Point(407, 3);
+      this.sortByComboBox.Name = "sortByComboBox";
+      this.sortByComboBox.Size = new System.Drawing.Size(121, 21);
+      this.sortByComboBox.TabIndex = 5;
+      this.sortByComboBox.SelectedIndexChanged += new System.EventHandler(this.sortByComboBox_SelectedIndexChanged);
+      // 
+      // factorVarReplComboBox
+      // 
+      this.factorVarReplComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.factorVarReplComboBox.FormattingEnabled = true;
+      this.factorVarReplComboBox.Items.AddRange(new object[] {
+            HeuristicLab.Problems.DataAnalysis.ClassificationSolutionVariableImpactsCalculator.FactorReplacementMethodEnum.Best,
+            HeuristicLab.Problems.DataAnalysis.ClassificationSolutionVariableImpactsCalculator.FactorReplacementMethodEnum.Mode,
+            HeuristicLab.Problems.DataAnalysis.ClassificationSolutionVariableImpactsCalculator.FactorReplacementMethodEnum.Shuffle});
+      this.factorVarReplComboBox.Location = new System.Drawing.Point(197, 57);
+      this.factorVarReplComboBox.Name = "factorVarReplComboBox";
+      this.factorVarReplComboBox.Size = new System.Drawing.Size(121, 21);
+      this.factorVarReplComboBox.TabIndex = 1;
+      this.factorVarReplComboBox.SelectedIndexChanged += new System.EventHandler(this.replacementComboBox_SelectedIndexChanged);
+      // 
+      // factorVarReplacementLabel
+      // 
+      this.factorVarReplacementLabel.AutoSize = true;
+      this.factorVarReplacementLabel.Location = new System.Drawing.Point(3, 60);
+      this.factorVarReplacementLabel.Name = "factorVarReplacementLabel";
+      this.factorVarReplacementLabel.Size = new System.Drawing.Size(188, 13);
+      this.factorVarReplacementLabel.TabIndex = 0;
+      this.factorVarReplacementLabel.Text = "Replacement for categorical variables:";
       // 
       // replacementComboBox
@@ -117,56 +131,48 @@
       this.replacementComboBox.SelectedIndexChanged += new System.EventHandler(this.replacementComboBox_SelectedIndexChanged);
       // 
-      // factorVarReplacementLabel
-      // 
-      this.factorVarReplacementLabel.AutoSize = true;
-      this.factorVarReplacementLabel.Location = new System.Drawing.Point(3, 60);
-      this.factorVarReplacementLabel.Name = "factorVarReplacementLabel";
-      this.factorVarReplacementLabel.Size = new System.Drawing.Size(188, 13);
-      this.factorVarReplacementLabel.TabIndex = 0;
-      this.factorVarReplacementLabel.Text = "Replacement for categorical variables:";
-      // 
-      // factorVarReplComboBox
-      // 
-      this.factorVarReplComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-      this.factorVarReplComboBox.FormattingEnabled = true;
-      this.factorVarReplComboBox.Items.AddRange(new object[] {
-            HeuristicLab.Problems.DataAnalysis.ClassificationSolutionVariableImpactsCalculator.FactorReplacementMethodEnum.Best,
-            HeuristicLab.Problems.DataAnalysis.ClassificationSolutionVariableImpactsCalculator.FactorReplacementMethodEnum.Mode,
-            HeuristicLab.Problems.DataAnalysis.ClassificationSolutionVariableImpactsCalculator.FactorReplacementMethodEnum.Shuffle});
-      this.factorVarReplComboBox.Location = new System.Drawing.Point(197, 57);
-      this.factorVarReplComboBox.Name = "factorVarReplComboBox";
-      this.factorVarReplComboBox.Size = new System.Drawing.Size(121, 21);
-      this.factorVarReplComboBox.TabIndex = 1;
-      this.factorVarReplComboBox.SelectedIndexChanged += new System.EventHandler(this.replacementComboBox_SelectedIndexChanged);
-      // 
-      // ascendingCheckBox
-      // 
-      this.ascendingCheckBox.AutoSize = true;
-      this.ascendingCheckBox.Location = new System.Drawing.Point(534, 6);
-      this.ascendingCheckBox.Name = "ascendingCheckBox";
-      this.ascendingCheckBox.Size = new System.Drawing.Size(76, 17);
-      this.ascendingCheckBox.TabIndex = 10;
-      this.ascendingCheckBox.Text = "Ascending";
-      this.ascendingCheckBox.UseVisualStyleBackColor = true;
-      this.ascendingCheckBox.CheckedChanged += new System.EventHandler(this.ascendingCheckBox_CheckedChanged);
-      // 
-      // sortByLabel
-      // 
-      this.sortByLabel.AutoSize = true;
-      this.sortByLabel.Location = new System.Drawing.Point(324, 6);
-      this.sortByLabel.Name = "sortByLabel";
-      this.sortByLabel.Size = new System.Drawing.Size(77, 13);
-      this.sortByLabel.TabIndex = 8;
-      this.sortByLabel.Text = "Sorting criteria:";
-      // 
-      // sortByComboBox
-      // 
-      this.sortByComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-      this.sortByComboBox.FormattingEnabled = true;
-      this.sortByComboBox.Location = new System.Drawing.Point(407, 3);
-      this.sortByComboBox.Name = "sortByComboBox";
-      this.sortByComboBox.Size = new System.Drawing.Size(121, 21);
-      this.sortByComboBox.TabIndex = 9;
-      this.sortByComboBox.SelectedIndexChanged += new System.EventHandler(this.sortByComboBox_SelectedIndexChanged);
+      // numericVarReplacementLabel
+      // 
+      this.numericVarReplacementLabel.AutoSize = true;
+      this.numericVarReplacementLabel.Location = new System.Drawing.Point(3, 33);
+      this.numericVarReplacementLabel.Name = "numericVarReplacementLabel";
+      this.numericVarReplacementLabel.Size = new System.Drawing.Size(173, 13);
+      this.numericVarReplacementLabel.TabIndex = 2;
+      this.numericVarReplacementLabel.Text = "Replacement for numeric variables:";
+      // 
+      // dataPartitionLabel
+      // 
+      this.dataPartitionLabel.AutoSize = true;
+      this.dataPartitionLabel.Location = new System.Drawing.Point(3, 6);
+      this.dataPartitionLabel.Name = "dataPartitionLabel";
+      this.dataPartitionLabel.Size = new System.Drawing.Size(73, 13);
+      this.dataPartitionLabel.TabIndex = 0;
+      this.dataPartitionLabel.Text = "Data partition:";
+      // 
+      // dataPartitionComboBox
+      // 
+      this.dataPartitionComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.dataPartitionComboBox.FormattingEnabled = true;
+      this.dataPartitionComboBox.Items.AddRange(new object[] {
+            HeuristicLab.Problems.DataAnalysis.ClassificationSolutionVariableImpactsCalculator.DataPartitionEnum.Training,
+            HeuristicLab.Problems.DataAnalysis.ClassificationSolutionVariableImpactsCalculator.DataPartitionEnum.Test,
+            HeuristicLab.Problems.DataAnalysis.ClassificationSolutionVariableImpactsCalculator.DataPartitionEnum.All});
+      this.dataPartitionComboBox.Location = new System.Drawing.Point(197, 3);
+      this.dataPartitionComboBox.Name = "dataPartitionComboBox";
+      this.dataPartitionComboBox.Size = new System.Drawing.Size(121, 21);
+      this.dataPartitionComboBox.TabIndex = 1;
+      this.dataPartitionComboBox.SelectedIndexChanged += new System.EventHandler(this.dataPartitionComboBox_SelectedIndexChanged);
+      // 
+      // variableImpactsArrayView
+      // 
+      this.variableImpactsArrayView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.variableImpactsArrayView.Caption = "StringConvertibleArray View";
+      this.variableImpactsArrayView.Content = null;
+      this.variableImpactsArrayView.Location = new System.Drawing.Point(3, 84);
+      this.variableImpactsArrayView.Name = "variableImpactsArrayView";
+      this.variableImpactsArrayView.ReadOnly = true;
+      this.variableImpactsArrayView.Size = new System.Drawing.Size(706, 278);
+      this.variableImpactsArrayView.TabIndex = 2;
       // 
       // ClassificationSolutionVariableImpactsView
@@ -183,7 +189,7 @@
       this.Controls.Add(this.dataPartitionLabel);
       this.Controls.Add(this.dataPartitionComboBox);
-      this.Controls.Add(this.variableImactsArrayView);
+      this.Controls.Add(this.variableImpactsArrayView);
       this.Name = "ClassificationSolutionVariableImpactsView";
-      this.Size = new System.Drawing.Size(668, 365);
+      this.Size = new System.Drawing.Size(712, 365);
       this.VisibleChanged += new System.EventHandler(this.ClassificationSolutionVariableImpactsView_VisibleChanged);
       this.ResumeLayout(false);
@@ -194,5 +200,5 @@
     #endregion
 
-    private Data.Views.StringConvertibleArrayView variableImactsArrayView;
+    private Data.Views.StringConvertibleArrayView variableImpactsArrayView;
     private System.Windows.Forms.ComboBox dataPartitionComboBox;
     private System.Windows.Forms.Label dataPartitionLabel;
@@ -201,8 +207,7 @@
     private System.Windows.Forms.Label factorVarReplacementLabel;
     private System.Windows.Forms.ComboBox factorVarReplComboBox;
-    private System.Windows.Forms.CheckBox ascendingCheckBox;
     private System.Windows.Forms.Label sortByLabel;
     private System.Windows.Forms.ComboBox sortByComboBox;
-    private System.ComponentModel.BackgroundWorker backgroundWorker;
+    private System.Windows.Forms.CheckBox ascendingCheckBox;
   }
 }
Index: stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/ClassificationSolutionVariableImpactsView.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/ClassificationSolutionVariableImpactsView.cs	(revision 16437)
+++ stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/ClassificationSolutionVariableImpactsView.cs	(revision 16438)
@@ -33,5 +33,4 @@
   [Content(typeof(IClassificationSolution))]
   public partial class ClassificationSolutionVariableImpactsView : DataAnalysisSolutionEvaluationView {
-    #region Nested Types
     private enum SortingCriteria {
       ImpactValue,
@@ -39,12 +38,7 @@
       VariableName
     }
-    #endregion
-
-    #region Fields
-    private Dictionary<string, double> rawVariableImpacts = new Dictionary<string, double>();
-    private Thread thread;
-    #endregion
-
-    #region Getter/Setter
+    private CancellationTokenSource cancellationToken = new CancellationTokenSource();
+    private List<Tuple<string, double>> rawVariableImpacts = new List<Tuple<string, double>>();
+
     public new IClassificationSolution Content {
       get { return (IClassificationSolution)base.Content; }
@@ -53,22 +47,16 @@
       }
     }
-    #endregion
-
-    #region Ctor
+
     public ClassificationSolutionVariableImpactsView()
       : base() {
       InitializeComponent();
 
-      this.sortByComboBox.Items.AddRange(Enum.GetValues(typeof(SortingCriteria)).Cast<object>().ToArray());
-      this.sortByComboBox.SelectedItem = SortingCriteria.ImpactValue;
-
       //Set the default values
       this.dataPartitionComboBox.SelectedIndex = 0;
-      this.replacementComboBox.SelectedIndex = 0;
+      this.replacementComboBox.SelectedIndex = 3;
       this.factorVarReplComboBox.SelectedIndex = 0;
-    }
-    #endregion
-
-    #region Events
+      this.sortByComboBox.SelectedItem = SortingCriteria.ImpactValue;
+    }
+
     protected override void RegisterContentEvents() {
       base.RegisterContentEvents();
@@ -76,5 +64,4 @@
       Content.ProblemDataChanged += new EventHandler(Content_ProblemDataChanged);
     }
-
     protected override void DeregisterContentEvents() {
       base.DeregisterContentEvents();
@@ -86,63 +73,44 @@
       OnContentChanged();
     }
-
     protected virtual void Content_ModelChanged(object sender, EventArgs e) {
       OnContentChanged();
     }
-
     protected override void OnContentChanged() {
       base.OnContentChanged();
+      rawVariableImpacts.Clear();
+
       if (Content == null) {
-        variableImactsArrayView.Content = null;
+        variableImpactsArrayView.Content = null;
       } else {
         UpdateVariableImpact();
       }
     }
-
     private void ClassificationSolutionVariableImpactsView_VisibleChanged(object sender, EventArgs e) {
-      if (thread == null) { return; }
-
-      if (thread.IsAlive) { thread.Abort(); }
-      thread = null;
-    }
-
+      cancellationToken.Cancel();
+    }
 
     private void dataPartitionComboBox_SelectedIndexChanged(object sender, EventArgs e) {
+      rawVariableImpacts.Clear();
       UpdateVariableImpact();
     }
-
     private void replacementComboBox_SelectedIndexChanged(object sender, EventArgs e) {
+      rawVariableImpacts.Clear();
       UpdateVariableImpact();
     }
-
     private void sortByComboBox_SelectedIndexChanged(object sender, EventArgs e) {
       //Update the default ordering (asc,desc), but remove the eventHandler beforehand (otherwise the data would be ordered twice)
       ascendingCheckBox.CheckedChanged -= ascendingCheckBox_CheckedChanged;
-      switch ((SortingCriteria)sortByComboBox.SelectedItem) {
-        case SortingCriteria.ImpactValue:
-          ascendingCheckBox.Checked = false;
-          break;
-        case SortingCriteria.Occurrence:
-          ascendingCheckBox.Checked = true;
-          break;
-        case SortingCriteria.VariableName:
-          ascendingCheckBox.Checked = true;
-          break;
-        default:
-          throw new NotImplementedException("Ordering for selected SortingCriteria not implemented");
-      }
+      ascendingCheckBox.Checked = (SortingCriteria)sortByComboBox.SelectedItem != SortingCriteria.ImpactValue;
       ascendingCheckBox.CheckedChanged += ascendingCheckBox_CheckedChanged;
 
-      UpdateDataOrdering();
-    }
-
+      UpdateOrdering();
+    }
     private void ascendingCheckBox_CheckedChanged(object sender, EventArgs e) {
-      UpdateDataOrdering();
-    }
-
-    #endregion
-
-    #region Helper Methods   
-    private void UpdateVariableImpact() {
+      UpdateOrdering();
+    }
+
+    private async void UpdateVariableImpact() {
+      IProgress progress;
+
       //Check if the selection is valid
       if (Content == null) { return; }
@@ -157,30 +125,72 @@
       var dataPartition = (ClassificationSolutionVariableImpactsCalculator.DataPartitionEnum)dataPartitionComboBox.SelectedItem;
 
-      variableImactsArrayView.Caption = Content.Name + " Variable Impacts";
-
-      mainForm.AddOperationProgressToView(this, "Calculating variable impacts for " + Content.Name);
-
-      Task.Factory.StartNew(() => {
-        thread = Thread.CurrentThread;
-        //Remember the original ordering of the variables
-        var impacts = ClassificationSolutionVariableImpactsCalculator.CalculateImpacts(Content, dataPartition, replMethod, factorReplMethod);
+      variableImpactsArrayView.Caption = Content.Name + " Variable Impacts";
+      progress = mainForm.AddOperationProgressToView(this, "Calculating variable impacts for " + Content.Name);
+      progress.ProgressValue = 0;
+
+      cancellationToken = new CancellationTokenSource();
+
+      try {
         var problemData = Content.ProblemData;
         var inputvariables = new HashSet<string>(problemData.AllowedInputVariables.Union(Content.Model.VariablesUsedForPrediction));
-        var originalVariableOrdering = problemData.Dataset.VariableNames.Where(v => inputvariables.Contains(v)).Where(problemData.Dataset.VariableHasType<double>).ToList();
-
-        rawVariableImpacts.Clear();
-        originalVariableOrdering.ForEach(v => rawVariableImpacts.Add(v, impacts.First(vv => vv.Item1 == v).Item2));
-      }).ContinueWith((o) => {
-        UpdateDataOrdering();
-        mainForm.RemoveOperationProgressFromView(this);
-        thread = null;
-      }, TaskScheduler.FromCurrentSynchronizationContext());
+        //Remember the original ordering of the variables
+        var originalVariableOrdering = problemData.Dataset.VariableNames
+          .Where(v => inputvariables.Contains(v))
+          .Where(v => problemData.Dataset.VariableHasType<double>(v) || problemData.Dataset.VariableHasType<string>(v))
+          .ToList();
+
+        List<Tuple<string, double>> impacts = null;
+        await Task.Run(() => { impacts = CalculateVariableImpacts(originalVariableOrdering, Content.Model, problemData, Content.EstimatedClassValues, dataPartition, replMethod, factorReplMethod, cancellationToken.Token, progress); });
+        if (impacts == null) { return; }
+
+        rawVariableImpacts.AddRange(impacts);
+        UpdateOrdering();
+      }
+      finally {
+        ((MainForm.WindowsForms.MainForm)MainFormManager.MainForm).RemoveOperationProgressFromView(this);
+      }
+    }
+    private List<Tuple<string, double>> CalculateVariableImpacts(List<string> originalVariableOrdering,
+      IClassificationModel model,
+      IClassificationProblemData problemData,
+      IEnumerable<double> estimatedClassValues,
+      ClassificationSolutionVariableImpactsCalculator.DataPartitionEnum dataPartition,
+      ClassificationSolutionVariableImpactsCalculator.ReplacementMethodEnum replMethod,
+      ClassificationSolutionVariableImpactsCalculator.FactorReplacementMethodEnum factorReplMethod,
+      CancellationToken token,
+      IProgress progress) {
+      List<Tuple<string, double>> impacts = new List<Tuple<string, double>>();
+      int count = originalVariableOrdering.Count;
+      int i = 0;
+      var modifiableDataset = ((Dataset)(problemData.Dataset).Clone()).ToModifiable();
+      IEnumerable<int> rows = ClassificationSolutionVariableImpactsCalculator.GetPartitionRows(dataPartition, problemData);
+
+      //Calculate original quality-values (via calculator, default is R²)
+      IEnumerable<double> targetValuesPartition = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
+      IEnumerable<double> estimatedClassValuesPartition = Content.GetEstimatedClassValues(rows);
+
+      var originalCalculatorValue = ClassificationSolutionVariableImpactsCalculator.CalculateQuality(targetValuesPartition, estimatedClassValuesPartition);
+      var clonedModel = (IClassificationModel)model.Clone();
+      foreach (var variableName in originalVariableOrdering) {
+        if (cancellationToken.Token.IsCancellationRequested) { return null; }
+        progress.ProgressValue = (double)++i / count;
+        progress.Status = string.Format("Calculating impact for variable {0} ({1} of {2})", variableName, i, count);
+
+        double impact = 0;
+        //If the variable isn't used for prediction, it has zero impact.
+        if (model.VariablesUsedForPrediction.Contains(variableName)) {
+          impact = ClassificationSolutionVariableImpactsCalculator.CalculateImpact(variableName, clonedModel, problemData, modifiableDataset, rows, replMethod, factorReplMethod, targetValuesPartition, originalCalculatorValue);
+        }
+        impacts.Add(new Tuple<string, double>(variableName, impact));
+      }
+
+      return impacts;
     }
 
     /// <summary>
-    /// Updates the <see cref="variableImactsArrayView"/> according to the selected ordering <see cref="ascendingCheckBox"/> of the selected Column <see cref="sortByComboBox"/>
+    /// Updates the <see cref="variableImpactsArrayView"/> according to the selected ordering <see cref="ascendingCheckBox"/> of the selected Column <see cref="sortByComboBox"/>
     /// The default is "Descending" by "VariableImpact" (as in previous versions)
     /// </summary>
-    private void UpdateDataOrdering() {
+    private void UpdateOrdering() {
       //Check if valid sortingCriteria is selected and data exists
       if (sortByComboBox.SelectedIndex == -1) { return; }
@@ -191,10 +201,10 @@
       bool ascending = ascendingCheckBox.Checked;
 
-      IEnumerable<KeyValuePair<string, double>> orderedEntries = null;
+      IEnumerable<Tuple<string, double>> orderedEntries = null;
 
       //Sort accordingly
       switch (selectedItem) {
         case SortingCriteria.ImpactValue:
-          orderedEntries = rawVariableImpacts.OrderBy(v => v.Value);
+          orderedEntries = rawVariableImpacts.OrderBy(v => v.Item2);
           break;
         case SortingCriteria.Occurrence:
@@ -202,5 +212,5 @@
           break;
         case SortingCriteria.VariableName:
-          orderedEntries = rawVariableImpacts.OrderBy(v => v.Key, new NaturalStringComparer());
+          orderedEntries = rawVariableImpacts.OrderBy(v => v.Item1, new NaturalStringComparer());
           break;
         default:
@@ -211,14 +221,13 @@
 
       //Write the data back
-      var impactArray = new DoubleArray(orderedEntries.Select(i => i.Value).ToArray()) {
-        ElementNames = orderedEntries.Select(i => i.Key)
+      var impactArray = new DoubleArray(orderedEntries.Select(i => i.Item2).ToArray()) {
+        ElementNames = orderedEntries.Select(i => i.Item1)
       };
 
       //Could be, if the View was closed
-      if (!variableImactsArrayView.IsDisposed) {
-        variableImactsArrayView.Content = (DoubleArray)impactArray.AsReadOnly();
-      }
-    }
-    #endregion  
+      if (!variableImpactsArrayView.IsDisposed) {
+        variableImpactsArrayView.Content = (DoubleArray)impactArray.AsReadOnly();
+      }
+    }
   }
 }
Index: stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionVariableImpactsView.Designer.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionVariableImpactsView.Designer.cs	(revision 16437)
+++ stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionVariableImpactsView.Designer.cs	(revision 16438)
@@ -55,5 +55,5 @@
       this.dataPartitionLabel = new System.Windows.Forms.Label();
       this.dataPartitionComboBox = new System.Windows.Forms.ComboBox();
-      this.variableImactsArrayView = new HeuristicLab.Data.Views.StringConvertibleArrayView();
+      this.variableImpactsArrayView = new HeuristicLab.Data.Views.StringConvertibleArrayView();
       this.SuspendLayout();
       // 
@@ -61,5 +61,6 @@
       // 
       this.ascendingCheckBox.AutoSize = true;
-      this.ascendingCheckBox.Location = new System.Drawing.Point(534, 6);
+      this.ascendingCheckBox.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+      this.ascendingCheckBox.Location = new System.Drawing.Point(452, 32);
       this.ascendingCheckBox.Name = "ascendingCheckBox";
       this.ascendingCheckBox.Size = new System.Drawing.Size(76, 17);
@@ -162,16 +163,16 @@
       this.dataPartitionComboBox.SelectedIndexChanged += new System.EventHandler(this.dataPartitionComboBox_SelectedIndexChanged);
       // 
-      // variableImactsArrayView
-      // 
-      this.variableImactsArrayView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      // variableImpactsArrayView
+      // 
+      this.variableImpactsArrayView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
-      this.variableImactsArrayView.Caption = "StringConvertibleArray View";
-      this.variableImactsArrayView.Content = null;
-      this.variableImactsArrayView.Location = new System.Drawing.Point(3, 84);
-      this.variableImactsArrayView.Name = "variableImactsArrayView";
-      this.variableImactsArrayView.ReadOnly = true;
-      this.variableImactsArrayView.Size = new System.Drawing.Size(706, 278);
-      this.variableImactsArrayView.TabIndex = 2;
+      this.variableImpactsArrayView.Caption = "StringConvertibleArray View";
+      this.variableImpactsArrayView.Content = null;
+      this.variableImpactsArrayView.Location = new System.Drawing.Point(3, 84);
+      this.variableImpactsArrayView.Name = "variableImpactsArrayView";
+      this.variableImpactsArrayView.ReadOnly = true;
+      this.variableImpactsArrayView.Size = new System.Drawing.Size(706, 278);
+      this.variableImpactsArrayView.TabIndex = 2;
       // 
       // RegressionSolutionVariableImpactsView
@@ -188,5 +189,5 @@
       this.Controls.Add(this.dataPartitionLabel);
       this.Controls.Add(this.dataPartitionComboBox);
-      this.Controls.Add(this.variableImactsArrayView);
+      this.Controls.Add(this.variableImpactsArrayView);
       this.Name = "RegressionSolutionVariableImpactsView";
       this.Size = new System.Drawing.Size(712, 365);
@@ -199,5 +200,5 @@
     #endregion
 
-    private Data.Views.StringConvertibleArrayView variableImactsArrayView;
+    private Data.Views.StringConvertibleArrayView variableImpactsArrayView;
     private System.Windows.Forms.ComboBox dataPartitionComboBox;
     private System.Windows.Forms.Label dataPartitionLabel;
Index: stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionVariableImpactsView.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionVariableImpactsView.cs	(revision 16437)
+++ stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionVariableImpactsView.cs	(revision 16438)
@@ -33,5 +33,4 @@
   [Content(typeof(IRegressionSolution))]
   public partial class RegressionSolutionVariableImpactsView : DataAnalysisSolutionEvaluationView {
-    private CancellationTokenSource cancellationToken = new CancellationTokenSource();
     private enum SortingCriteria {
       ImpactValue,
@@ -39,4 +38,5 @@
       VariableName
     }
+    private CancellationTokenSource cancellationToken = new CancellationTokenSource();
     private List<Tuple<string, double>> rawVariableImpacts = new List<Tuple<string, double>>();
 
@@ -64,5 +64,4 @@
       Content.ProblemDataChanged += new EventHandler(Content_ProblemDataChanged);
     }
-
     protected override void DeregisterContentEvents() {
       base.DeregisterContentEvents();
@@ -74,31 +73,29 @@
       OnContentChanged();
     }
-
     protected virtual void Content_ModelChanged(object sender, EventArgs e) {
       OnContentChanged();
     }
-
     protected override void OnContentChanged() {
       base.OnContentChanged();
+      rawVariableImpacts.Clear();
+
       if (Content == null) {
-        variableImactsArrayView.Content = null;
+        variableImpactsArrayView.Content = null;
       } else {
         UpdateVariableImpact();
       }
     }
-
     private void RegressionSolutionVariableImpactsView_VisibleChanged(object sender, EventArgs e) {
       cancellationToken.Cancel();
     }
 
-
     private void dataPartitionComboBox_SelectedIndexChanged(object sender, EventArgs e) {
+      rawVariableImpacts.Clear();
       UpdateVariableImpact();
     }
-
     private void replacementComboBox_SelectedIndexChanged(object sender, EventArgs e) {
+      rawVariableImpacts.Clear();
       UpdateVariableImpact();
     }
-
     private void sortByComboBox_SelectedIndexChanged(object sender, EventArgs e) {
       //Update the default ordering (asc,desc), but remove the eventHandler beforehand (otherwise the data would be ordered twice)
@@ -109,9 +106,7 @@
       UpdateOrdering();
     }
-
     private void ascendingCheckBox_CheckedChanged(object sender, EventArgs e) {
       UpdateOrdering();
     }
-
 
     private async void UpdateVariableImpact() {
@@ -130,21 +125,14 @@
       var dataPartition = (RegressionSolutionVariableImpactsCalculator.DataPartitionEnum)dataPartitionComboBox.SelectedItem;
 
-      variableImactsArrayView.Caption = Content.Name + " Variable Impacts";
+      variableImpactsArrayView.Caption = Content.Name + " Variable Impacts";
       progress = mainForm.AddOperationProgressToView(this, "Calculating variable impacts for " + Content.Name);
       progress.ProgressValue = 0;
 
       cancellationToken = new CancellationTokenSource();
-      //Remember the original ordering of the variables
+
       try {
-        var impacts = await Task.Run(() => RegressionSolutionVariableImpactsCalculator.CalculateImpacts(Content, dataPartition, replMethod, factorReplMethod,
-          (i, s) => {
-            progress.ProgressValue = i;
-            progress.Status = s;
-            return cancellationToken.Token.IsCancellationRequested;
-          }), cancellationToken.Token);
-
-        if (cancellationToken.Token.IsCancellationRequested) { return; }
         var problemData = Content.ProblemData;
         var inputvariables = new HashSet<string>(problemData.AllowedInputVariables.Union(Content.Model.VariablesUsedForPrediction));
+        //Remember the original ordering of the variables
         var originalVariableOrdering = problemData.Dataset.VariableNames
           .Where(v => inputvariables.Contains(v))
@@ -152,14 +140,54 @@
           .ToList();
 
-        rawVariableImpacts.Clear();
-        originalVariableOrdering.ForEach(v => rawVariableImpacts.Add(new Tuple<string, double>(v, impacts.First(vv => vv.Item1 == v).Item2)));
+        List<Tuple<string, double>> impacts = null;
+        await Task.Run(() => { impacts = CalculateVariableImpacts(originalVariableOrdering, Content.Model, problemData, Content.EstimatedValues, dataPartition, replMethod, factorReplMethod, cancellationToken.Token, progress); });
+        if (impacts == null) { return; }
+
+        rawVariableImpacts.AddRange(impacts);
         UpdateOrdering();
-      } finally {
+      }
+      finally {
         ((MainForm.WindowsForms.MainForm)MainFormManager.MainForm).RemoveOperationProgressFromView(this);
       }
     }
+    private List<Tuple<string, double>> CalculateVariableImpacts(List<string> originalVariableOrdering,
+      IRegressionModel model,
+      IRegressionProblemData problemData,
+      IEnumerable<double> estimatedValues,
+      RegressionSolutionVariableImpactsCalculator.DataPartitionEnum dataPartition,
+      RegressionSolutionVariableImpactsCalculator.ReplacementMethodEnum replMethod,
+      RegressionSolutionVariableImpactsCalculator.FactorReplacementMethodEnum factorReplMethod,
+      CancellationToken token,
+      IProgress progress) {
+      List<Tuple<string, double>> impacts = new List<Tuple<string, double>>();
+      int count = originalVariableOrdering.Count;
+      int i = 0;
+      var modifiableDataset = ((Dataset)(problemData.Dataset).Clone()).ToModifiable();
+      IEnumerable<int> rows = RegressionSolutionVariableImpactsCalculator.GetPartitionRows(dataPartition, problemData);
+
+      //Calculate original quality-values (via calculator, default is R²)
+      IEnumerable<double> targetValuesPartition = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
+      IEnumerable<double> estimatedValuesPartition = Content.GetEstimatedValues(rows);
+
+      var originalCalculatorValue = RegressionSolutionVariableImpactsCalculator.CalculateQuality(targetValuesPartition, estimatedValuesPartition);
+
+      foreach (var variableName in originalVariableOrdering) {
+        if (cancellationToken.Token.IsCancellationRequested) { return null; }
+        progress.ProgressValue = (double)++i / count;
+        progress.Status = string.Format("Calculating impact for variable {0} ({1} of {2})", variableName, i, count);
+
+        double impact = 0;
+        //If the variable isn't used for prediction, it has zero impact.
+        if (model.VariablesUsedForPrediction.Contains(variableName)) {
+          impact = RegressionSolutionVariableImpactsCalculator.CalculateImpact(variableName, model, problemData, modifiableDataset, rows, replMethod, factorReplMethod, targetValuesPartition, originalCalculatorValue);
+        }
+        impacts.Add(new Tuple<string, double>(variableName, impact));
+      }
+
+      return impacts;
+    }
 
     /// <summary>
-    /// Updates the <see cref="variableImactsArrayView"/> according to the selected ordering <see cref="ascendingCheckBox"/> of the selected Column <see cref="sortByComboBox"/>
+    /// Updates the <see cref="variableImpactsArrayView"/> according to the selected ordering <see cref="ascendingCheckBox"/> of the selected Column <see cref="sortByComboBox"/>
     /// The default is "Descending" by "VariableImpact" (as in previous versions)
     /// </summary>
@@ -198,6 +226,6 @@
 
       //Could be, if the View was closed
-      if (!variableImactsArrayView.IsDisposed) {
-        variableImactsArrayView.Content = (DoubleArray)impactArray.AsReadOnly();
+      if (!variableImpactsArrayView.IsDisposed) {
+        variableImpactsArrayView.Content = (DoubleArray)impactArray.AsReadOnly();
       }
     }
Index: stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolutionVariableImpactsCalculator.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolutionVariableImpactsCalculator.cs	(revision 16437)
+++ stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolutionVariableImpactsCalculator.cs	(revision 16438)
@@ -23,4 +23,5 @@
 
 using System;
+using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
@@ -36,4 +37,5 @@
   [Item("ClassificationSolution Impacts Calculator", "Calculation of the impacts of input variables for any classification solution")]
   public sealed class ClassificationSolutionVariableImpactsCalculator : ParameterizedNamedItem {
+    #region Parameters/Properties
     public enum ReplacementMethodEnum {
       Median,
@@ -54,8 +56,12 @@
 
     private const string ReplacementParameterName = "Replacement Method";
+    private const string FactorReplacementParameterName = "Factor Replacement Method";
     private const string DataPartitionParameterName = "DataPartition";
 
     public IFixedValueParameter<EnumValue<ReplacementMethodEnum>> ReplacementParameter {
       get { return (IFixedValueParameter<EnumValue<ReplacementMethodEnum>>)Parameters[ReplacementParameterName]; }
+    }
+    public IFixedValueParameter<EnumValue<FactorReplacementMethodEnum>> FactorReplacementParameter {
+      get { return (IFixedValueParameter<EnumValue<FactorReplacementMethodEnum>>)Parameters[FactorReplacementParameterName]; }
     }
     public IFixedValueParameter<EnumValue<DataPartitionEnum>> DataPartitionParameter {
@@ -67,136 +73,154 @@
       set { ReplacementParameter.Value.Value = value; }
     }
+    public FactorReplacementMethodEnum FactorReplacementMethod {
+      get { return FactorReplacementParameter.Value.Value; }
+      set { FactorReplacementParameter.Value.Value = value; }
+    }
     public DataPartitionEnum DataPartition {
       get { return DataPartitionParameter.Value.Value; }
       set { DataPartitionParameter.Value.Value = value; }
     }
-
-
+    #endregion
+
+    #region Ctor/Cloner
     [StorableConstructor]
     private ClassificationSolutionVariableImpactsCalculator(bool deserializing) : base(deserializing) { }
     private ClassificationSolutionVariableImpactsCalculator(ClassificationSolutionVariableImpactsCalculator original, Cloner cloner)
       : base(original, cloner) { }
+    public ClassificationSolutionVariableImpactsCalculator()
+      : base() {
+      Parameters.Add(new FixedValueParameter<EnumValue<ReplacementMethodEnum>>(ReplacementParameterName, "The replacement method for variables during impact calculation.", new EnumValue<ReplacementMethodEnum>(ReplacementMethodEnum.Shuffle)));
+      Parameters.Add(new FixedValueParameter<EnumValue<FactorReplacementMethodEnum>>(FactorReplacementParameterName, "The replacement method for factor variables during impact calculation.", new EnumValue<FactorReplacementMethodEnum>(FactorReplacementMethodEnum.Best)));
+      Parameters.Add(new FixedValueParameter<EnumValue<DataPartitionEnum>>(DataPartitionParameterName, "The data partition on which the impacts are calculated.", new EnumValue<DataPartitionEnum>(DataPartitionEnum.Training)));
+    }
+
     public override IDeepCloneable Clone(Cloner cloner) {
       return new ClassificationSolutionVariableImpactsCalculator(this, cloner);
     }
-
-    public ClassificationSolutionVariableImpactsCalculator()
-      : base() {
-      Parameters.Add(new FixedValueParameter<EnumValue<ReplacementMethodEnum>>(ReplacementParameterName, "The replacement method for variables during impact calculation.", new EnumValue<ReplacementMethodEnum>(ReplacementMethodEnum.Median)));
-      Parameters.Add(new FixedValueParameter<EnumValue<DataPartitionEnum>>(DataPartitionParameterName, "The data partition on which the impacts are calculated.", new EnumValue<DataPartitionEnum>(DataPartitionEnum.Training)));
-    }
+    #endregion
 
     //mkommend: annoying name clash with static method, open to better naming suggestions
     public IEnumerable<Tuple<string, double>> Calculate(IClassificationSolution solution) {
-      return CalculateImpacts(solution, DataPartition, ReplacementMethod);
+      return CalculateImpacts(solution, ReplacementMethod, FactorReplacementMethod, DataPartition);
     }
 
     public static IEnumerable<Tuple<string, double>> CalculateImpacts(
       IClassificationSolution solution,
-      DataPartitionEnum data = DataPartitionEnum.Training,
-      ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Median,
+      ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Shuffle,
+      FactorReplacementMethodEnum factorReplacementMethod = FactorReplacementMethodEnum.Best,
+      DataPartitionEnum dataPartition = DataPartitionEnum.Training) {
+
+      IEnumerable<int> rows = GetPartitionRows(dataPartition, solution.ProblemData);
+      IEnumerable<double> estimatedClassValues = solution.GetEstimatedClassValues(rows);
+      var model = (IClassificationModel)solution.Model.Clone(); //mkommend: clone of model is necessary, because the thresholds for IDiscriminantClassificationModels are updated
+
+      return CalculateImpacts(model, solution.ProblemData, estimatedClassValues, rows, replacementMethod, factorReplacementMethod);
+    }
+
+    public static IEnumerable<Tuple<string, double>> CalculateImpacts(
+     IClassificationModel model,
+     IClassificationProblemData problemData,
+     IEnumerable<double> estimatedClassValues,
+     IEnumerable<int> rows,
+     ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Shuffle,
+     FactorReplacementMethodEnum factorReplacementMethod = FactorReplacementMethodEnum.Best) {
+
+      //fholzing: try and catch in case a different dataset is loaded, otherwise statement is neglectable
+      var missingVariables = model.VariablesUsedForPrediction.Except(problemData.Dataset.VariableNames);
+      if (missingVariables.Any()) {
+        throw new InvalidOperationException(string.Format("Can not calculate variable impacts, because the model uses inputs missing in the dataset ({0})", string.Join(", ", missingVariables)));
+      }
+      IEnumerable<double> targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
+      var originalQuality = CalculateQuality(targetValues, estimatedClassValues);
+
+      var impacts = new Dictionary<string, double>();
+      var inputvariables = new HashSet<string>(problemData.AllowedInputVariables.Union(model.VariablesUsedForPrediction));
+      var modifiableDataset = ((Dataset)(problemData.Dataset).Clone()).ToModifiable();
+
+      foreach (var inputVariable in inputvariables) {
+        impacts[inputVariable] = CalculateImpact(inputVariable, model, problemData, modifiableDataset, rows, replacementMethod, factorReplacementMethod, targetValues, originalQuality);
+      }
+
+      return impacts.Select(i => Tuple.Create(i.Key, i.Value));
+    }
+
+    public static double CalculateImpact(string variableName,
+      IClassificationModel model,
+      IClassificationProblemData problemData,
+      ModifiableDataset modifiableDataset,
+      IEnumerable<int> rows,
+      ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Shuffle,
+      FactorReplacementMethodEnum factorReplacementMethod = FactorReplacementMethodEnum.Best,
+      IEnumerable<double> targetValues = null,
+      double quality = double.NaN) {
+
+      if (!model.VariablesUsedForPrediction.Contains(variableName)) { return 0.0; }
+      if (!problemData.Dataset.VariableNames.Contains(variableName)) {
+        throw new InvalidOperationException(string.Format("Can not calculate variable impact, because the model uses inputs missing in the dataset ({0})", variableName));
+      }
+
+      if (targetValues == null) {
+        targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
+      }
+      if (quality == double.NaN) {
+        quality = CalculateQuality(model.GetEstimatedClassValues(modifiableDataset, rows), targetValues);
+      }
+
+      IList originalValues = null;
+      IList replacementValues = GetReplacementValues(modifiableDataset, variableName, model, rows, targetValues, out originalValues, replacementMethod, factorReplacementMethod);
+
+      double newValue = CalculateQualityForReplacement(model, modifiableDataset, variableName, originalValues, rows, replacementValues, targetValues);
+      double impact = quality - newValue;
+
+      return impact;
+    }
+
+    private static IList GetReplacementValues(ModifiableDataset modifiableDataset,
+      string variableName,
+      IClassificationModel model,
+      IEnumerable<int> rows,
+      IEnumerable<double> targetValues,
+      out IList originalValues,
+      ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Shuffle,
       FactorReplacementMethodEnum factorReplacementMethod = FactorReplacementMethodEnum.Best) {
 
-      var problemData = solution.ProblemData;
-      var dataset = problemData.Dataset;
-      var model = (IClassificationModel)solution.Model.Clone(); //mkommend: clone of model is necessary, because the thresholds for IDiscriminantClassificationModels are updated
-
-      IEnumerable<int> rows;
-      IEnumerable<double> targetValues;
-      double originalAccuracy;
-
-      OnlineCalculatorError error;
-
-      switch (data) {
-        case DataPartitionEnum.All:
-          rows = problemData.AllIndices;
-          targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.AllIndices).ToList();
-          originalAccuracy = OnlineAccuracyCalculator.Calculate(targetValues, solution.EstimatedClassValues, out error);
-          if (error != OnlineCalculatorError.None) throw new InvalidOperationException("Error during accuracy calculation.");
-          break;
-        case DataPartitionEnum.Training:
-          rows = problemData.TrainingIndices;
-          targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices).ToList();
-          originalAccuracy = OnlineAccuracyCalculator.Calculate(targetValues, solution.EstimatedTrainingClassValues, out error);
-          if (error != OnlineCalculatorError.None) throw new InvalidOperationException("Error during accuracy calculation.");
-          break;
-        case DataPartitionEnum.Test:
-          rows = problemData.TestIndices;
-          targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TestIndices).ToList();
-          originalAccuracy = OnlineAccuracyCalculator.Calculate(targetValues, solution.EstimatedTestClassValues, out error);
-          if (error != OnlineCalculatorError.None) throw new InvalidOperationException("Error during accuracy calculation.");
-          break;
-        default: throw new ArgumentException(string.Format("DataPartition {0} cannot be handled.", data));
-      }
-
-      var impacts = new Dictionary<string, double>();
-      var modifiableDataset = ((Dataset)dataset).ToModifiable();
-
-      var inputvariables = new HashSet<string>(problemData.AllowedInputVariables.Union(solution.Model.VariablesUsedForPrediction));
-      var allowedInputVariables = dataset.VariableNames.Where(v => inputvariables.Contains(v)).ToList();
-
-      // calculate impacts for double variables
-      foreach (var inputVariable in allowedInputVariables.Where(problemData.Dataset.VariableHasType<double>)) {
-        var newEstimates = EvaluateModelWithReplacedVariable(model, inputVariable, modifiableDataset, rows, replacementMethod);
-        var newAccuracy = OnlineAccuracyCalculator.Calculate(targetValues, newEstimates, out error);
-        if (error != OnlineCalculatorError.None) throw new InvalidOperationException("Error during R² calculation with replaced inputs.");
-
-        impacts[inputVariable] = originalAccuracy - newAccuracy;
-      }
-
-      // calculate impacts for string variables
-      foreach (var inputVariable in allowedInputVariables.Where(problemData.Dataset.VariableHasType<string>)) {
-        if (factorReplacementMethod == FactorReplacementMethodEnum.Best) {
-          // try replacing with all possible values and find the best replacement value
-          var smallestImpact = double.PositiveInfinity;
-          foreach (var repl in problemData.Dataset.GetStringValues(inputVariable, rows).Distinct()) {
-            var newEstimates = EvaluateModelWithReplacedVariable(model, inputVariable, modifiableDataset, rows,
-              Enumerable.Repeat(repl, dataset.Rows));
-            var newAccuracy = OnlineAccuracyCalculator.Calculate(targetValues, newEstimates, out error);
-            if (error != OnlineCalculatorError.None)
-              throw new InvalidOperationException("Error during accuracy calculation with replaced inputs.");
-
-            var impact = originalAccuracy - newAccuracy;
-            if (impact < smallestImpact) smallestImpact = impact;
-          }
-          impacts[inputVariable] = smallestImpact;
-        } else {
-          // for replacement methods shuffle and mode
-          // calculate impacts for factor variables
-
-          var newEstimates = EvaluateModelWithReplacedVariable(model, inputVariable, modifiableDataset, rows,
-            factorReplacementMethod);
-          var newAccuracy = OnlineAccuracyCalculator.Calculate(targetValues, newEstimates, out error);
-          if (error != OnlineCalculatorError.None)
-            throw new InvalidOperationException("Error during accuracy calculation with replaced inputs.");
-
-          impacts[inputVariable] = originalAccuracy - newAccuracy;
-        }
-      } // foreach
-      return impacts.OrderByDescending(i => i.Value).Select(i => Tuple.Create(i.Key, i.Value));
-    }
-
-    private static IEnumerable<double> EvaluateModelWithReplacedVariable(IClassificationModel model, string variable, ModifiableDataset dataset, IEnumerable<int> rows, ReplacementMethodEnum replacement = ReplacementMethodEnum.Median) {
-      var originalValues = dataset.GetReadOnlyDoubleValues(variable).ToList();
+      IList replacementValues = null;
+      if (modifiableDataset.VariableHasType<double>(variableName)) {
+        originalValues = modifiableDataset.GetReadOnlyDoubleValues(variableName).ToList();
+        replacementValues = GetReplacementValuesForDouble(modifiableDataset, rows, (List<double>)originalValues, replacementMethod);
+      } else if (modifiableDataset.VariableHasType<string>(variableName)) {
+        originalValues = modifiableDataset.GetReadOnlyStringValues(variableName).ToList();
+        replacementValues = GetReplacementValuesForString(model, modifiableDataset, variableName, rows, (List<string>)originalValues, targetValues, factorReplacementMethod);
+      } else {
+        throw new NotSupportedException("Variable not supported");
+      }
+
+      return replacementValues;
+    }
+
+    private static IList GetReplacementValuesForDouble(ModifiableDataset modifiableDataset,
+      IEnumerable<int> rows,
+      List<double> originalValues,
+      ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Shuffle) {
+
+      IRandom random = new FastRandom(31415);
+      List<double> replacementValues;
       double replacementValue;
-      List<double> replacementValues;
-      IRandom rand;
-
-      switch (replacement) {
+
+      switch (replacementMethod) {
         case ReplacementMethodEnum.Median:
           replacementValue = rows.Select(r => originalValues[r]).Median();
-          replacementValues = Enumerable.Repeat(replacementValue, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(replacementValue, modifiableDataset.Rows).ToList();
           break;
         case ReplacementMethodEnum.Average:
           replacementValue = rows.Select(r => originalValues[r]).Average();
-          replacementValues = Enumerable.Repeat(replacementValue, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(replacementValue, modifiableDataset.Rows).ToList();
           break;
         case ReplacementMethodEnum.Shuffle:
           // new var has same empirical distribution but the relation to y is broken
-          rand = new FastRandom(31415);
           // prepare a complete column for the dataset
-          replacementValues = Enumerable.Repeat(double.NaN, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(double.NaN, modifiableDataset.Rows).ToList();
           // shuffle only the selected rows
-          var shuffledValues = rows.Select(r => originalValues[r]).Shuffle(rand).ToList();
+          var shuffledValues = rows.Select(r => originalValues[r]).Shuffle(random).ToList();
           int i = 0;
           // update column values 
@@ -208,29 +232,46 @@
           var avg = rows.Select(r => originalValues[r]).Average();
           var stdDev = rows.Select(r => originalValues[r]).StandardDeviation();
-          rand = new FastRandom(31415);
           // prepare a complete column for the dataset
-          replacementValues = Enumerable.Repeat(double.NaN, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(double.NaN, modifiableDataset.Rows).ToList();
           // update column values 
           foreach (var r in rows) {
-            replacementValues[r] = NormalDistributedRandom.NextDouble(rand, avg, stdDev);
+            replacementValues[r] = NormalDistributedRandom.NextDouble(random, avg, stdDev);
           }
           break;
 
         default:
-          throw new ArgumentException(string.Format("ReplacementMethod {0} cannot be handled.", replacement));
-      }
-
-      return EvaluateModelWithReplacedVariable(model, variable, dataset, rows, replacementValues);
-    }
-
-    private static IEnumerable<double> EvaluateModelWithReplacedVariable(
-      IClassificationModel model, string variable, ModifiableDataset dataset,
-      IEnumerable<int> rows,
-      FactorReplacementMethodEnum replacement = FactorReplacementMethodEnum.Shuffle) {
-      var originalValues = dataset.GetReadOnlyStringValues(variable).ToList();
-      List<string> replacementValues;
-      IRandom rand;
-
-      switch (replacement) {
+          throw new ArgumentException(string.Format("ReplacementMethod {0} cannot be handled.", replacementMethod));
+      }
+
+      return replacementValues;
+    }
+
+    private static IList GetReplacementValuesForString(IClassificationModel model,
+      ModifiableDataset modifiableDataset,
+      string variableName,
+      IEnumerable<int> rows,
+      List<string> originalValues,
+      IEnumerable<double> targetValues,
+      FactorReplacementMethodEnum factorReplacementMethod = FactorReplacementMethodEnum.Shuffle) {
+
+      List<string> replacementValues = null;
+      IRandom random = new FastRandom(31415);
+
+      switch (factorReplacementMethod) {
+        case FactorReplacementMethodEnum.Best:
+          // try replacing with all possible values and find the best replacement value
+          var bestQuality = double.NegativeInfinity;
+          foreach (var repl in modifiableDataset.GetStringValues(variableName, rows).Distinct()) {
+            List<string> curReplacementValues = Enumerable.Repeat(repl, modifiableDataset.Rows).ToList();
+            //fholzing: this result could be used later on (theoretically), but is neglected for better readability/method consistency 
+            var newValue = CalculateQualityForReplacement(model, modifiableDataset, variableName, originalValues, rows, curReplacementValues, targetValues);
+            var curQuality = newValue;
+
+            if (curQuality > bestQuality) {
+              bestQuality = curQuality;
+              replacementValues = curReplacementValues;
+            }
+          }
+          break;
         case FactorReplacementMethodEnum.Mode:
           var mostCommonValue = rows.Select(r => originalValues[r])
@@ -238,13 +279,12 @@
             .OrderByDescending(g => g.Count())
             .First().Key;
-          replacementValues = Enumerable.Repeat(mostCommonValue, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(mostCommonValue, modifiableDataset.Rows).ToList();
           break;
         case FactorReplacementMethodEnum.Shuffle:
           // new var has same empirical distribution but the relation to y is broken
-          rand = new FastRandom(31415);
           // prepare a complete column for the dataset
-          replacementValues = Enumerable.Repeat(string.Empty, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(string.Empty, modifiableDataset.Rows).ToList();
           // shuffle only the selected rows
-          var shuffledValues = rows.Select(r => originalValues[r]).Shuffle(rand).ToList();
+          var shuffledValues = rows.Select(r => originalValues[r]).Shuffle(random).ToList();
           int i = 0;
           // update column values 
@@ -254,44 +294,59 @@
           break;
         default:
-          throw new ArgumentException(string.Format("FactorReplacementMethod {0} cannot be handled.", replacement));
-      }
-
-      return EvaluateModelWithReplacedVariable(model, variable, dataset, rows, replacementValues);
-    }
-
-    private static IEnumerable<double> EvaluateModelWithReplacedVariable(IClassificationModel model, string variable,
-      ModifiableDataset dataset, IEnumerable<int> rows, IEnumerable<double> replacementValues) {
-      var originalValues = dataset.GetReadOnlyDoubleValues(variable).ToList();
-      dataset.ReplaceVariable(variable, replacementValues.ToList());
-
+          throw new ArgumentException(string.Format("FactorReplacementMethod {0} cannot be handled.", factorReplacementMethod));
+      }
+
+      return replacementValues;
+    }
+
+    private static double CalculateQualityForReplacement(
+      IClassificationModel model,
+      ModifiableDataset modifiableDataset,
+      string variableName,
+      IList originalValues,
+      IEnumerable<int> rows,
+      IList replacementValues,
+      IEnumerable<double> targetValues) {
+
+      modifiableDataset.ReplaceVariable(variableName, replacementValues);
       var discModel = model as IDiscriminantFunctionClassificationModel;
       if (discModel != null) {
-        var problemData = new ClassificationProblemData(dataset, dataset.VariableNames, model.TargetVariable);
+        var problemData = new ClassificationProblemData(modifiableDataset, modifiableDataset.VariableNames, model.TargetVariable);
         discModel.RecalculateModelParameters(problemData, rows);
       }
 
       //mkommend: ToList is used on purpose to avoid lazy evaluation that could result in wrong estimates due to variable replacements
-      var estimates = model.GetEstimatedClassValues(dataset, rows).ToList();
-      dataset.ReplaceVariable(variable, originalValues);
-
-      return estimates;
-    }
-    private static IEnumerable<double> EvaluateModelWithReplacedVariable(IClassificationModel model, string variable,
-      ModifiableDataset dataset, IEnumerable<int> rows, IEnumerable<string> replacementValues) {
-      var originalValues = dataset.GetReadOnlyStringValues(variable).ToList();
-      dataset.ReplaceVariable(variable, replacementValues.ToList());
-
-
-      var discModel = model as IDiscriminantFunctionClassificationModel;
-      if (discModel != null) {
-        var problemData = new ClassificationProblemData(dataset, dataset.VariableNames, model.TargetVariable);
-        discModel.RecalculateModelParameters(problemData, rows);
-      }
-
-      //mkommend: ToList is used on purpose to avoid lazy evaluation that could result in wrong estimates due to variable replacements
-      var estimates = model.GetEstimatedClassValues(dataset, rows).ToList();
-      dataset.ReplaceVariable(variable, originalValues);
-
-      return estimates;
+      var estimates = model.GetEstimatedClassValues(modifiableDataset, rows).ToList();
+      var ret = CalculateQuality(targetValues, estimates);
+      modifiableDataset.ReplaceVariable(variableName, originalValues);
+
+      return ret;
+    }
+
+    public static double CalculateQuality(IEnumerable<double> targetValues, IEnumerable<double> estimatedClassValues) {
+      OnlineCalculatorError errorState;
+      var ret = OnlineAccuracyCalculator.Calculate(targetValues, estimatedClassValues, out errorState);
+      if (errorState != OnlineCalculatorError.None) { throw new InvalidOperationException("Error during calculation with replaced inputs."); }
+      return ret;
+    }
+
+    public static IEnumerable<int> GetPartitionRows(DataPartitionEnum dataPartition, IClassificationProblemData problemData) {
+      IEnumerable<int> rows;
+
+      switch (dataPartition) {
+        case DataPartitionEnum.All:
+          rows = problemData.AllIndices;
+          break;
+        case DataPartitionEnum.Test:
+          rows = problemData.TestIndices;
+          break;
+        case DataPartitionEnum.Training:
+          rows = problemData.TrainingIndices;
+          break;
+        default:
+          throw new NotSupportedException("DataPartition not supported");
+      }
+
+      return rows;
     }
   }
Index: stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolutionVariableImpactsCalculator.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolutionVariableImpactsCalculator.cs	(revision 16437)
+++ stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolutionVariableImpactsCalculator.cs	(revision 16438)
@@ -23,4 +23,5 @@
 
 using System;
+using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
@@ -36,4 +37,5 @@
   [Item("RegressionSolution Impacts Calculator", "Calculation of the impacts of input variables for any regression solution")]
   public sealed class RegressionSolutionVariableImpactsCalculator : ParameterizedNamedItem {
+    #region Parameters/Properties
     public enum ReplacementMethodEnum {
       Median,
@@ -54,8 +56,12 @@
 
     private const string ReplacementParameterName = "Replacement Method";
+    private const string FactorReplacementParameterName = "Factor Replacement Method";
     private const string DataPartitionParameterName = "DataPartition";
 
     public IFixedValueParameter<EnumValue<ReplacementMethodEnum>> ReplacementParameter {
       get { return (IFixedValueParameter<EnumValue<ReplacementMethodEnum>>)Parameters[ReplacementParameterName]; }
+    }
+    public IFixedValueParameter<EnumValue<FactorReplacementMethodEnum>> FactorReplacementParameter {
+      get { return (IFixedValueParameter<EnumValue<FactorReplacementMethodEnum>>)Parameters[FactorReplacementParameterName]; }
     }
     public IFixedValueParameter<EnumValue<DataPartitionEnum>> DataPartitionParameter {
@@ -67,148 +73,152 @@
       set { ReplacementParameter.Value.Value = value; }
     }
+    public FactorReplacementMethodEnum FactorReplacementMethod {
+      get { return FactorReplacementParameter.Value.Value; }
+      set { FactorReplacementParameter.Value.Value = value; }
+    }
     public DataPartitionEnum DataPartition {
       get { return DataPartitionParameter.Value.Value; }
       set { DataPartitionParameter.Value.Value = value; }
     }
-
-
+    #endregion
+
+    #region Ctor/Cloner
     [StorableConstructor]
     private RegressionSolutionVariableImpactsCalculator(bool deserializing) : base(deserializing) { }
     private RegressionSolutionVariableImpactsCalculator(RegressionSolutionVariableImpactsCalculator original, Cloner cloner)
       : base(original, cloner) { }
+    public RegressionSolutionVariableImpactsCalculator()
+      : base() {
+      Parameters.Add(new FixedValueParameter<EnumValue<ReplacementMethodEnum>>(ReplacementParameterName, "The replacement method for variables during impact calculation.", new EnumValue<ReplacementMethodEnum>(ReplacementMethodEnum.Shuffle)));
+      Parameters.Add(new FixedValueParameter<EnumValue<FactorReplacementMethodEnum>>(FactorReplacementParameterName, "The replacement method for factor variables during impact calculation.", new EnumValue<FactorReplacementMethodEnum>(FactorReplacementMethodEnum.Best)));
+      Parameters.Add(new FixedValueParameter<EnumValue<DataPartitionEnum>>(DataPartitionParameterName, "The data partition on which the impacts are calculated.", new EnumValue<DataPartitionEnum>(DataPartitionEnum.Training)));
+    }
+
     public override IDeepCloneable Clone(Cloner cloner) {
       return new RegressionSolutionVariableImpactsCalculator(this, cloner);
     }
-
-    public RegressionSolutionVariableImpactsCalculator()
-      : base() {
-      Parameters.Add(new FixedValueParameter<EnumValue<ReplacementMethodEnum>>(ReplacementParameterName, "The replacement method for variables during impact calculation.", new EnumValue<ReplacementMethodEnum>(ReplacementMethodEnum.Median)));
-      Parameters.Add(new FixedValueParameter<EnumValue<DataPartitionEnum>>(DataPartitionParameterName, "The data partition on which the impacts are calculated.", new EnumValue<DataPartitionEnum>(DataPartitionEnum.Training)));
-    }
+    #endregion
 
     //mkommend: annoying name clash with static method, open to better naming suggestions
     public IEnumerable<Tuple<string, double>> Calculate(IRegressionSolution solution) {
-      return CalculateImpacts(solution, DataPartition, ReplacementMethod);
+      return CalculateImpacts(solution, ReplacementMethod, FactorReplacementMethod, DataPartition);
     }
 
     public static IEnumerable<Tuple<string, double>> CalculateImpacts(
       IRegressionSolution solution,
-      DataPartitionEnum data = DataPartitionEnum.Training,
-      ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Median,
+      ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Shuffle,
       FactorReplacementMethodEnum factorReplacementMethod = FactorReplacementMethodEnum.Best,
-      Func<double, string, bool> progressCallback = null) {
-
-      var problemData = solution.ProblemData;
-      var dataset = problemData.Dataset;
-
-      IEnumerable<int> rows;
-      IEnumerable<double> targetValues;
-      double originalR2 = -1;
-
-      OnlineCalculatorError error;
-
-      switch (data) {
-        case DataPartitionEnum.All:
-          rows = solution.ProblemData.AllIndices;
-          targetValues = problemData.TargetVariableValues.ToList();
-          originalR2 = OnlinePearsonsRCalculator.Calculate(problemData.TargetVariableValues, solution.EstimatedValues, out error);
-          if (error != OnlineCalculatorError.None) throw new InvalidOperationException("Error during R² calculation.");
-          originalR2 = originalR2 * originalR2;
-          break;
-        case DataPartitionEnum.Training:
-          rows = problemData.TrainingIndices;
-          targetValues = problemData.TargetVariableTrainingValues.ToList();
-          originalR2 = solution.TrainingRSquared;
-          break;
-        case DataPartitionEnum.Test:
-          rows = problemData.TestIndices;
-          targetValues = problemData.TargetVariableTestValues.ToList();
-          originalR2 = solution.TestRSquared;
-          break;
-        default: throw new ArgumentException(string.Format("DataPartition {0} cannot be handled.", data));
-      }
+      DataPartitionEnum dataPartition = DataPartitionEnum.Training) {
+
+      IEnumerable<int> rows = GetPartitionRows(dataPartition, solution.ProblemData);
+      IEnumerable<double> estimatedValues = solution.GetEstimatedValues(rows);
+      return CalculateImpacts(solution.Model, solution.ProblemData, estimatedValues, rows, replacementMethod, factorReplacementMethod);
+    }
+
+    public static IEnumerable<Tuple<string, double>> CalculateImpacts(
+     IRegressionModel model,
+     IRegressionProblemData problemData,
+     IEnumerable<double> estimatedValues,
+     IEnumerable<int> rows,
+     ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Shuffle,
+     FactorReplacementMethodEnum factorReplacementMethod = FactorReplacementMethodEnum.Best) {
+
+      //fholzing: try and catch in case a different dataset is loaded, otherwise statement is neglectable
+      var missingVariables = model.VariablesUsedForPrediction.Except(problemData.Dataset.VariableNames);
+      if (missingVariables.Any()) {
+        throw new InvalidOperationException(string.Format("Can not calculate variable impacts, because the model uses inputs missing in the dataset ({0})", string.Join(", ", missingVariables)));
+      }
+      IEnumerable<double> targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
+      var originalQuality = CalculateQuality(targetValues, estimatedValues);
 
       var impacts = new Dictionary<string, double>();
-      var modifiableDataset = ((Dataset)dataset).ToModifiable();
-
-      var inputvariables = new HashSet<string>(problemData.AllowedInputVariables.Union(solution.Model.VariablesUsedForPrediction));
-      var allowedInputVariables = dataset.VariableNames.Where(v => inputvariables.Contains(v)).ToList();
-
-      int curIdx = 0;
-      int count = allowedInputVariables.Where(problemData.Dataset.VariableHasType<double>).Count();
-      // calculate impacts for double variables
-      foreach (var inputVariable in allowedInputVariables.Where(problemData.Dataset.VariableHasType<double>)) {
-        //Report the current progress in percent. If the callback returns true, it means the execution shall be stopped
-        if (progressCallback != null) {
-          curIdx++;
-          if (progressCallback((double)curIdx / count, string.Format("Calculating impact for variable {0} ({1} of {2})", inputVariable, curIdx, count))) { return null; }
-        }
-        var newEstimates = EvaluateModelWithReplacedVariable(solution.Model, inputVariable, modifiableDataset, rows, replacementMethod);
-        var newR2 = OnlinePearsonsRCalculator.Calculate(targetValues, newEstimates, out error);
-        if (error != OnlineCalculatorError.None) throw new InvalidOperationException("Error during R² calculation with replaced inputs.");
-
-        newR2 = newR2 * newR2;
-        var impact = originalR2 - newR2;
-        impacts[inputVariable] = impact;
-      }
-
-      // calculate impacts for string variables
-      foreach (var inputVariable in allowedInputVariables.Where(problemData.Dataset.VariableHasType<string>)) {
-        if (factorReplacementMethod == FactorReplacementMethodEnum.Best) {
-          // try replacing with all possible values and find the best replacement value
-          var smallestImpact = double.PositiveInfinity;
-          foreach (var repl in problemData.Dataset.GetStringValues(inputVariable, rows).Distinct()) {
-            var newEstimates = EvaluateModelWithReplacedVariable(solution.Model, inputVariable, modifiableDataset, rows,
-              Enumerable.Repeat(repl, dataset.Rows));
-            var newR2 = OnlinePearsonsRCalculator.Calculate(targetValues, newEstimates, out error);
-            if (error != OnlineCalculatorError.None)
-              throw new InvalidOperationException("Error during R² calculation with replaced inputs.");
-
-            newR2 = newR2 * newR2;
-            var impact = originalR2 - newR2;
-            if (impact < smallestImpact) smallestImpact = impact;
-          }
-          impacts[inputVariable] = smallestImpact;
-        } else {
-          // for replacement methods shuffle and mode
-          // calculate impacts for factor variables
-
-          var newEstimates = EvaluateModelWithReplacedVariable(solution.Model, inputVariable, modifiableDataset, rows,
-            factorReplacementMethod);
-          var newR2 = OnlinePearsonsRCalculator.Calculate(targetValues, newEstimates, out error);
-          if (error != OnlineCalculatorError.None)
-            throw new InvalidOperationException("Error during R² calculation with replaced inputs.");
-
-          newR2 = newR2 * newR2;
-          var impact = originalR2 - newR2;
-          impacts[inputVariable] = impact;
-        }
-      } // foreach
-      return impacts.OrderByDescending(i => i.Value).Select(i => Tuple.Create(i.Key, i.Value));
-    }
-
-
-    private static IEnumerable<double> EvaluateModelWithReplacedVariable(IRegressionModel model, string variable, ModifiableDataset dataset, IEnumerable<int> rows, ReplacementMethodEnum replacement = ReplacementMethodEnum.Median) {
-      var originalValues = dataset.GetReadOnlyDoubleValues(variable).ToList();
+      var inputvariables = new HashSet<string>(problemData.AllowedInputVariables.Union(model.VariablesUsedForPrediction));
+      var modifiableDataset = ((Dataset)(problemData.Dataset).Clone()).ToModifiable();
+
+      foreach (var inputVariable in inputvariables) {
+        impacts[inputVariable] = CalculateImpact(inputVariable, model, problemData, modifiableDataset, rows, replacementMethod, factorReplacementMethod, targetValues, originalQuality);
+      }
+
+      return impacts.Select(i => Tuple.Create(i.Key, i.Value));
+    }
+
+    public static double CalculateImpact(string variableName,
+      IRegressionModel model,
+      IRegressionProblemData problemData,
+      ModifiableDataset modifiableDataset,
+      IEnumerable<int> rows,
+      ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Shuffle,
+      FactorReplacementMethodEnum factorReplacementMethod = FactorReplacementMethodEnum.Best,
+      IEnumerable<double> targetValues = null,
+      double quality = double.NaN) {
+
+      if (!model.VariablesUsedForPrediction.Contains(variableName)) { return 0.0; }
+      if (!problemData.Dataset.VariableNames.Contains(variableName)) {
+        throw new InvalidOperationException(string.Format("Can not calculate variable impact, because the model uses inputs missing in the dataset ({0})", variableName));
+      }
+
+      if (targetValues == null) {
+        targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
+      }
+      if (quality == double.NaN) {
+        quality = CalculateQuality(model.GetEstimatedValues(modifiableDataset, rows), targetValues);
+      }
+
+      IList originalValues = null;
+      IList replacementValues = GetReplacementValues(modifiableDataset, variableName, model, rows, targetValues, out originalValues, replacementMethod, factorReplacementMethod);
+
+      double newValue = CalculateQualityForReplacement(model, modifiableDataset, variableName, originalValues, rows, replacementValues, targetValues);
+      double impact = quality - newValue;
+
+      return impact;
+    }
+
+    private static IList GetReplacementValues(ModifiableDataset modifiableDataset,
+      string variableName,
+      IRegressionModel model,
+      IEnumerable<int> rows,
+      IEnumerable<double> targetValues,
+      out IList originalValues,
+      ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Shuffle,
+      FactorReplacementMethodEnum factorReplacementMethod = FactorReplacementMethodEnum.Best) {
+
+      IList replacementValues = null;
+      if (modifiableDataset.VariableHasType<double>(variableName)) {
+        originalValues = modifiableDataset.GetReadOnlyDoubleValues(variableName).ToList();
+        replacementValues = GetReplacementValuesForDouble(modifiableDataset, rows, (List<double>)originalValues, replacementMethod);
+      } else if (modifiableDataset.VariableHasType<string>(variableName)) {
+        originalValues = modifiableDataset.GetReadOnlyStringValues(variableName).ToList();
+        replacementValues = GetReplacementValuesForString(model, modifiableDataset, variableName, rows, (List<string>)originalValues, targetValues, factorReplacementMethod);
+      } else {
+        throw new NotSupportedException("Variable not supported");
+      }
+
+      return replacementValues;
+    }
+
+    private static IList GetReplacementValuesForDouble(ModifiableDataset modifiableDataset,
+      IEnumerable<int> rows,
+      List<double> originalValues,
+      ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Shuffle) {
+
+      IRandom random = new FastRandom(31415);
+      List<double> replacementValues;
       double replacementValue;
-      List<double> replacementValues;
-      IRandom rand;
-
-      switch (replacement) {
+
+      switch (replacementMethod) {
         case ReplacementMethodEnum.Median:
           replacementValue = rows.Select(r => originalValues[r]).Median();
-          replacementValues = Enumerable.Repeat(replacementValue, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(replacementValue, modifiableDataset.Rows).ToList();
           break;
         case ReplacementMethodEnum.Average:
           replacementValue = rows.Select(r => originalValues[r]).Average();
-          replacementValues = Enumerable.Repeat(replacementValue, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(replacementValue, modifiableDataset.Rows).ToList();
           break;
         case ReplacementMethodEnum.Shuffle:
           // new var has same empirical distribution but the relation to y is broken
-          rand = new FastRandom(31415);
           // prepare a complete column for the dataset
-          replacementValues = Enumerable.Repeat(double.NaN, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(double.NaN, modifiableDataset.Rows).ToList();
           // shuffle only the selected rows
-          var shuffledValues = rows.Select(r => originalValues[r]).Shuffle(rand).ToList();
+          var shuffledValues = rows.Select(r => originalValues[r]).Shuffle(random).ToList();
           int i = 0;
           // update column values 
@@ -220,29 +230,46 @@
           var avg = rows.Select(r => originalValues[r]).Average();
           var stdDev = rows.Select(r => originalValues[r]).StandardDeviation();
-          rand = new FastRandom(31415);
           // prepare a complete column for the dataset
-          replacementValues = Enumerable.Repeat(double.NaN, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(double.NaN, modifiableDataset.Rows).ToList();
           // update column values 
           foreach (var r in rows) {
-            replacementValues[r] = NormalDistributedRandom.NextDouble(rand, avg, stdDev);
+            replacementValues[r] = NormalDistributedRandom.NextDouble(random, avg, stdDev);
           }
           break;
 
         default:
-          throw new ArgumentException(string.Format("ReplacementMethod {0} cannot be handled.", replacement));
-      }
-
-      return EvaluateModelWithReplacedVariable(model, variable, dataset, rows, replacementValues);
-    }
-
-    private static IEnumerable<double> EvaluateModelWithReplacedVariable(
-      IRegressionModel model, string variable, ModifiableDataset dataset,
-      IEnumerable<int> rows,
-      FactorReplacementMethodEnum replacement = FactorReplacementMethodEnum.Shuffle) {
-      var originalValues = dataset.GetReadOnlyStringValues(variable).ToList();
-      List<string> replacementValues;
-      IRandom rand;
-
-      switch (replacement) {
+          throw new ArgumentException(string.Format("ReplacementMethod {0} cannot be handled.", replacementMethod));
+      }
+
+      return replacementValues;
+    }
+
+    private static IList GetReplacementValuesForString(IRegressionModel model,
+      ModifiableDataset modifiableDataset,
+      string variableName,
+      IEnumerable<int> rows,
+      List<string> originalValues,
+      IEnumerable<double> targetValues,
+      FactorReplacementMethodEnum factorReplacementMethod = FactorReplacementMethodEnum.Shuffle) {
+
+      List<string> replacementValues = null;
+      IRandom random = new FastRandom(31415);
+
+      switch (factorReplacementMethod) {
+        case FactorReplacementMethodEnum.Best:
+          // try replacing with all possible values and find the best replacement value
+          var bestQuality = double.NegativeInfinity;
+          foreach (var repl in modifiableDataset.GetStringValues(variableName, rows).Distinct()) {
+            List<string> curReplacementValues = Enumerable.Repeat(repl, modifiableDataset.Rows).ToList();
+            //fholzing: this result could be used later on (theoretically), but is neglected for better readability/method consistency 
+            var newValue = CalculateQualityForReplacement(model, modifiableDataset, variableName, originalValues, rows, curReplacementValues, targetValues);
+            var curQuality = newValue;
+
+            if (curQuality > bestQuality) {
+              bestQuality = curQuality;
+              replacementValues = curReplacementValues;
+            }
+          }
+          break;
         case FactorReplacementMethodEnum.Mode:
           var mostCommonValue = rows.Select(r => originalValues[r])
@@ -250,13 +277,12 @@
             .OrderByDescending(g => g.Count())
             .First().Key;
-          replacementValues = Enumerable.Repeat(mostCommonValue, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(mostCommonValue, modifiableDataset.Rows).ToList();
           break;
         case FactorReplacementMethodEnum.Shuffle:
           // new var has same empirical distribution but the relation to y is broken
-          rand = new FastRandom(31415);
           // prepare a complete column for the dataset
-          replacementValues = Enumerable.Repeat(string.Empty, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(string.Empty, modifiableDataset.Rows).ToList();
           // shuffle only the selected rows
-          var shuffledValues = rows.Select(r => originalValues[r]).Shuffle(rand).ToList();
+          var shuffledValues = rows.Select(r => originalValues[r]).Shuffle(random).ToList();
           int i = 0;
           // update column values 
@@ -266,29 +292,53 @@
           break;
         default:
-          throw new ArgumentException(string.Format("FactorReplacementMethod {0} cannot be handled.", replacement));
-      }
-
-      return EvaluateModelWithReplacedVariable(model, variable, dataset, rows, replacementValues);
-    }
-
-    private static IEnumerable<double> EvaluateModelWithReplacedVariable(IRegressionModel model, string variable,
-      ModifiableDataset dataset, IEnumerable<int> rows, IEnumerable<double> replacementValues) {
-      var originalValues = dataset.GetReadOnlyDoubleValues(variable).ToList();
-      dataset.ReplaceVariable(variable, replacementValues.ToList());
+          throw new ArgumentException(string.Format("FactorReplacementMethod {0} cannot be handled.", factorReplacementMethod));
+      }
+
+      return replacementValues;
+    }
+
+    private static double CalculateQualityForReplacement(
+      IRegressionModel model,
+      ModifiableDataset modifiableDataset,
+      string variableName,
+      IList originalValues,
+      IEnumerable<int> rows,
+      IList replacementValues,
+      IEnumerable<double> targetValues) {
+
+      modifiableDataset.ReplaceVariable(variableName, replacementValues);
       //mkommend: ToList is used on purpose to avoid lazy evaluation that could result in wrong estimates due to variable replacements
-      var estimates = model.GetEstimatedValues(dataset, rows).ToList();
-      dataset.ReplaceVariable(variable, originalValues);
-
-      return estimates;
-    }
-    private static IEnumerable<double> EvaluateModelWithReplacedVariable(IRegressionModel model, string variable,
-      ModifiableDataset dataset, IEnumerable<int> rows, IEnumerable<string> replacementValues) {
-      var originalValues = dataset.GetReadOnlyStringValues(variable).ToList();
-      dataset.ReplaceVariable(variable, replacementValues.ToList());
-      //mkommend: ToList is used on purpose to avoid lazy evaluation that could result in wrong estimates due to variable replacements
-      var estimates = model.GetEstimatedValues(dataset, rows).ToList();
-      dataset.ReplaceVariable(variable, originalValues);
-
-      return estimates;
+      var estimates = model.GetEstimatedValues(modifiableDataset, rows).ToList();
+      var ret = CalculateQuality(targetValues, estimates);
+      modifiableDataset.ReplaceVariable(variableName, originalValues);
+
+      return ret;
+    }
+
+    public static double CalculateQuality(IEnumerable<double> targetValues, IEnumerable<double> estimatedValues) {
+      OnlineCalculatorError errorState;
+      var ret = OnlinePearsonsRCalculator.Calculate(targetValues, estimatedValues, out errorState);
+      if (errorState != OnlineCalculatorError.None) { throw new InvalidOperationException("Error during calculation with replaced inputs."); }
+      return ret * ret;
+    }
+
+    public static IEnumerable<int> GetPartitionRows(DataPartitionEnum dataPartition, IRegressionProblemData problemData) {
+      IEnumerable<int> rows;
+
+      switch (dataPartition) {
+        case DataPartitionEnum.All:
+          rows = problemData.AllIndices;
+          break;
+        case DataPartitionEnum.Test:
+          rows = problemData.TestIndices;
+          break;
+        case DataPartitionEnum.Training:
+          rows = problemData.TrainingIndices;
+          break;
+        default:
+          throw new NotSupportedException("DataPartition not supported");
+      }
+
+      return rows;
     }
   }
Index: stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/ClassificationVariableImpactCalculationTest.cs
===================================================================
--- stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/ClassificationVariableImpactCalculationTest.cs	(revision 16438)
+++ stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/ClassificationVariableImpactCalculationTest.cs	(revision 16438)
@@ -0,0 +1,269 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using HeuristicLab.Algorithms.DataAnalysis;
+using HeuristicLab.Common;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Problems.DataAnalysis.Symbolic;
+using HeuristicLab.Problems.DataAnalysis.Symbolic.Classification;
+using HeuristicLab.Problems.Instances.DataAnalysis;
+using HeuristicLab.Random;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace HeuristicLab.Problems.DataAnalysis.Tests {
+
+  [TestClass()]
+  public class ClassificationVariableImpactCalculationTest {
+    private TestContext testContextInstance;
+    /// <summary>
+    ///Gets or sets the test context which provides
+    ///information about and functionality for the current test run.
+    ///</summary>
+    public TestContext TestContext {
+      get { return testContextInstance; }
+      set { testContextInstance = value; }
+    }
+
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void ConstantModelVariableImpactTest() {
+      IClassificationProblemData problemData = LoadIrisProblem();
+      IClassificationModel model = new ConstantModel(5, "y");
+      IClassificationSolution solution = new ClassificationSolution(model, problemData);
+      Dictionary<string, double> expectedImpacts = GetExpectedValuesForConstantModel();
+
+      CheckDefaultAsserts(solution, expectedImpacts);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void KNNIrisVariableImpactTest() {
+      IClassificationProblemData problemData = LoadIrisProblem();
+      IClassificationSolution solution = NearestNeighbourClassification.CreateNearestNeighbourClassificationSolution(problemData, 3);
+      ClassificationSolutionVariableImpactsCalculator.CalculateImpacts(solution);
+      Dictionary<string, double> expectedImpacts = GetExpectedValuesForIrisKNNModel();
+
+      CheckDefaultAsserts(solution, expectedImpacts);
+    }
+
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void LDAIrisVariableImpactTest() {
+      IClassificationProblemData problemData = LoadIrisProblem();
+      IClassificationSolution solution = LinearDiscriminantAnalysis.CreateLinearDiscriminantAnalysisSolution(problemData);
+      ClassificationSolutionVariableImpactsCalculator.CalculateImpacts(solution);
+      Dictionary<string, double> expectedImpacts = GetExpectedValuesForIrisLDAModel();
+
+      CheckDefaultAsserts(solution, expectedImpacts);
+    }
+
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void CustomModelVariableImpactTest() {
+      IClassificationProblemData problemData = CreateDefaultProblem();
+      ISymbolicExpressionTree tree = CreateCustomExpressionTree();
+      var model = new SymbolicNearestNeighbourClassificationModel(problemData.TargetVariable, 3, tree, new SymbolicDataAnalysisExpressionTreeInterpreter());
+      model.RecalculateModelParameters(problemData, problemData.TrainingIndices);
+      IClassificationSolution solution = new ClassificationSolution(model, (IClassificationProblemData)problemData.Clone());
+      Dictionary<string, double> expectedImpacts = GetExpectedValuesForCustomProblem();
+
+      CheckDefaultAsserts(solution, expectedImpacts);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void CustomModelVariableImpactNoInfluenceTest() {
+      IClassificationProblemData problemData = CreateDefaultProblem();
+      ISymbolicExpressionTree tree = CreateCustomExpressionTreeNoInfluenceX1();
+      var model = new SymbolicNearestNeighbourClassificationModel(problemData.TargetVariable, 3, tree, new SymbolicDataAnalysisExpressionTreeInterpreter());
+      model.RecalculateModelParameters(problemData, problemData.TrainingIndices);
+      IClassificationSolution solution = new ClassificationSolution(model, (IClassificationProblemData)problemData.Clone());
+      Dictionary<string, double> expectedImpacts = GetExpectedValuesForCustomProblemNoInfluence();
+
+      CheckDefaultAsserts(solution, expectedImpacts);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    [ExpectedException(typeof(ArgumentException))]
+    public void WrongDataSetVariableImpactClassificationTest() {
+      IClassificationProblemData problemData = LoadIrisProblem();
+      IClassificationSolution solution = NearestNeighbourClassification.CreateNearestNeighbourClassificationSolution(problemData, 3);
+      ClassificationSolutionVariableImpactsCalculator.CalculateImpacts(solution);
+      Dictionary<string, double> expectedImpacts = GetExpectedValuesForIrisKNNModel();
+
+      solution.ProblemData = LoadMammographyProblem();
+      ClassificationSolutionVariableImpactsCalculator.CalculateImpacts(solution);
+    }
+
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "medium")]
+    public void PerformanceVariableImpactClassificationTest() {
+      int rows = 1500;
+      int columns = 77;
+      IClassificationProblemData problemData = CreateDefaultProblem(rows, columns);
+      IClassificationSolution solution = NearestNeighbourClassification.CreateNearestNeighbourClassificationSolution(problemData, 3);
+
+      Stopwatch watch = new Stopwatch();
+      watch.Start();
+      var results = ClassificationSolutionVariableImpactsCalculator.CalculateImpacts(solution);
+      watch.Stop();
+
+      TestContext.WriteLine("");
+      TestContext.WriteLine("Calculated cells per millisecond: {0}.", rows * columns / watch.ElapsedMilliseconds);
+    }
+
+    #region Load ClassificationProblemData
+    private IClassificationProblemData LoadIrisProblem() {
+      UCIInstanceProvider provider = new UCIInstanceProvider();
+      var instance = provider.GetDataDescriptors().Where(x => x.Name.Equals("Iris, M. Marshall, 1988")).Single();
+      return provider.LoadData(instance);
+    }
+    private IClassificationProblemData LoadMammographyProblem() {
+      UCIInstanceProvider provider = new UCIInstanceProvider();
+      var instance = provider.GetDataDescriptors().Where(x => x.Name.Equals("Mammography, M. Elter, 2007")).Single();
+      return provider.LoadData(instance);
+    }
+    private IClassificationProblemData CreateDefaultProblem() {
+      List<string> allowedInputVariables = new List<string>() { "x1", "x2", "x3", "x4", "x5" };
+      string targetVariable = "y";
+      var variableNames = allowedInputVariables.Union(targetVariable.ToEnumerable());
+      double[,] variableValues = new double[100, variableNames.Count()];
+
+      FastRandom random = new FastRandom(12345);
+      int len0 = variableValues.GetLength(0);
+      int len1 = variableValues.GetLength(1);
+      for (int i = 0; i < len0; i++) {
+        for (int j = 0; j < len1; j++) {
+          if (j == len1 - 1) {
+            variableValues[i, j] = (j + i) % 2;
+          } else {
+            variableValues[i, j] = random.Next(1, 100);
+          }
+        }
+      }
+
+      Dataset dataset = new Dataset(variableNames, variableValues);
+      var ret = new ClassificationProblemData(dataset, allowedInputVariables, targetVariable);
+
+      ret.SetClassName(0, "NOK");
+      ret.SetClassName(1, "OK");
+      return ret;
+    }
+
+    private IClassificationProblemData CreateDefaultProblem(int rows, int columns) {
+      List<string> allowedInputVariables = Enumerable.Range(0, columns - 1).Select(x => "x" + x.ToString()).ToList();
+      string targetVariable = "y";
+      var variableNames = allowedInputVariables.Union(targetVariable.ToEnumerable());
+      double[,] variableValues = new double[rows, columns];
+
+      FastRandom random = new FastRandom(12345);
+      int len0 = variableValues.GetLength(0);
+      int len1 = variableValues.GetLength(1);
+      for (int i = 0; i < len0; i++) {
+        for (int j = 0; j < len1; j++) {
+          if (j == len1 - 1) {
+            variableValues[i, j] = (j + i) % 2;
+          } else {
+            variableValues[i, j] = random.Next(1, 100);
+          }
+        }
+      }
+
+      Dataset dataset = new Dataset(variableNames, variableValues);
+      var ret = new ClassificationProblemData(dataset, allowedInputVariables, targetVariable);
+
+      ret.SetClassName(0, "NOK");
+      ret.SetClassName(1, "OK");
+      return ret;
+    }
+
+    #endregion
+
+    #region Create SymbolicExpressionTree
+    private ISymbolicExpressionTree CreateCustomExpressionTree() {
+      return new InfixExpressionParser().Parse("x1*x2 - x2*x2 + x3*x3 + x4*x4 - x5*x5 + 14/12");
+    }
+    private ISymbolicExpressionTree CreateCustomExpressionTreeNoInfluenceX1() {
+      return new InfixExpressionParser().Parse("x1/x1*x2 - x2*x2 + x3*x3 + x4*x4 - x5*x5 + 14/12");
+    }
+    #endregion
+
+    #region Get Expected Values      
+    private Dictionary<string, double> GetExpectedValuesForConstantModel() {
+      Dictionary<string, double> expectedImpacts = new Dictionary<string, double>();
+      expectedImpacts.Add("petal_length", 0);
+      expectedImpacts.Add("petal_width", 0);
+      expectedImpacts.Add("sepal_length", 0);
+      expectedImpacts.Add("sepal_width", 0);
+
+      return expectedImpacts;
+    }
+    private Dictionary<string, double> GetExpectedValuesForIrisKNNModel() {
+      Dictionary<string, double> expectedImpacts = new Dictionary<string, double>();
+      expectedImpacts.Add("petal_length", 0.21);
+      expectedImpacts.Add("petal_width", 0.25);
+      expectedImpacts.Add("sepal_length", 0.05);
+      expectedImpacts.Add("sepal_width", 0.05);
+
+      return expectedImpacts;
+    }
+    private Dictionary<string, double> GetExpectedValuesForCustomProblem() {
+      Dictionary<string, double> expectedImpacts = new Dictionary<string, double>();
+      expectedImpacts.Add("x1", 0.04);
+      expectedImpacts.Add("x2", 0.22);
+      expectedImpacts.Add("x3", 0.26);
+      expectedImpacts.Add("x4", 0.24);
+      expectedImpacts.Add("x5", 0.2);
+
+      return expectedImpacts;
+    }
+    private Dictionary<string, double> GetExpectedValuesForCustomProblemNoInfluence() {
+      Dictionary<string, double> expectedImpacts = new Dictionary<string, double>();
+      expectedImpacts.Add("x1", 0);
+      expectedImpacts.Add("x2", 0.22);
+      expectedImpacts.Add("x3", 0.14);
+      expectedImpacts.Add("x4", 0.3);
+      expectedImpacts.Add("x5", 0.44);
+
+      return expectedImpacts;
+    }
+    private Dictionary<string, double> GetExpectedValuesForIrisLDAModel() {
+      Dictionary<string, double> expectedImpacts = new Dictionary<string, double>();
+      expectedImpacts.Add("sepal_width", 0.01);
+      expectedImpacts.Add("sepal_length", 0.03);
+      expectedImpacts.Add("petal_width", 0.2);
+      expectedImpacts.Add("petal_length", 0.5);
+
+      return expectedImpacts;
+    }
+    #endregion
+
+    private void CheckDefaultAsserts(IClassificationSolution solution, Dictionary<string, double> expectedImpacts) {
+      IClassificationProblemData problemData = solution.ProblemData;
+      IEnumerable<double> estimatedValues = solution.GetEstimatedClassValues(solution.ProblemData.TrainingIndices);
+
+      var solutionImpacts = ClassificationSolutionVariableImpactsCalculator.CalculateImpacts(solution);
+      var modelImpacts = ClassificationSolutionVariableImpactsCalculator.CalculateImpacts(solution.Model, problemData, estimatedValues, problemData.TrainingIndices);
+
+      //Both ways should return equal results
+      Assert.IsTrue(solutionImpacts.SequenceEqual(modelImpacts));
+
+      //Check if impacts are as expected
+      Assert.AreEqual(modelImpacts.Count(), expectedImpacts.Count);
+      Assert.IsTrue(modelImpacts.All(v => v.Item2.IsAlmost(expectedImpacts[v.Item1])));
+    }
+  }
+}
Index: stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/RegressionVariableImpactCalculationTest.cs
===================================================================
--- stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/RegressionVariableImpactCalculationTest.cs	(revision 16438)
+++ stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/RegressionVariableImpactCalculationTest.cs	(revision 16438)
@@ -0,0 +1,338 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using HeuristicLab.Algorithms.DataAnalysis;
+using HeuristicLab.Common;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Problems.DataAnalysis.Symbolic;
+using HeuristicLab.Problems.DataAnalysis.Symbolic.Regression;
+using HeuristicLab.Problems.Instances.DataAnalysis;
+using HeuristicLab.Random;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace HeuristicLab.Problems.DataAnalysis.Tests {
+
+  [TestClass()]
+  public class RegressionVariableImpactCalculationTest {
+    private TestContext testContextInstance;
+    /// <summary>
+    ///Gets or sets the test context which provides
+    ///information about and functionality for the current test run.
+    ///</summary>
+    public TestContext TestContext {
+      get { return testContextInstance; }
+      set { testContextInstance = value; }
+    }
+
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void ConstantModelVariableImpactTest() {
+      IRegressionProblemData problemData = LoadDefaultTowerProblem();
+      IRegressionModel model = new ConstantModel(5, "y");
+      IRegressionSolution solution = new RegressionSolution(model, problemData);
+      Dictionary<string, double> expectedImpacts = GetExpectedValuesForConstantModel();
+
+      CheckDefaultAsserts(solution, expectedImpacts);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void LinearRegressionModelVariableImpactTowerTest() {
+      IRegressionProblemData problemData = LoadDefaultTowerProblem();
+      double rmsError;
+      double cvRmsError;
+      var solution = LinearRegression.CreateSolution(problemData, out rmsError, out cvRmsError);
+      Dictionary<string, double> expectedImpacts = GetExpectedValuesForLRTower();
+
+      CheckDefaultAsserts(solution, expectedImpacts);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void LinearRegressionModelVariableImpactMibaTest() {
+      IRegressionProblemData problemData = LoadDefaultMibaProblem();
+      double rmsError;
+      double cvRmsError;
+      var solution = LinearRegression.CreateSolution(problemData, out rmsError, out cvRmsError);
+      Dictionary<string, double> expectedImpacts = GetExpectedValuesForLRMiba();
+
+      CheckDefaultAsserts(solution, expectedImpacts);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void RandomForestModelVariableImpactTowerTest() {
+      IRegressionProblemData problemData = LoadDefaultTowerProblem();
+      double rmsError;
+      double avgRelError;
+      double outOfBagRmsError;
+      double outofBagAvgRelError;
+      var solution = RandomForestRegression.CreateRandomForestRegressionSolution(problemData, 50, 0.2, 0.5, 1234, out rmsError, out avgRelError, out outOfBagRmsError, out outofBagAvgRelError);
+      Dictionary<string, double> expectedImpacts = GetExpectedValuesForRFTower();
+
+      CheckDefaultAsserts(solution, expectedImpacts);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void CustomModelVariableImpactTest() {
+      IRegressionProblemData problemData = CreateDefaultProblem();
+      ISymbolicExpressionTree tree = CreateCustomExpressionTree();
+      IRegressionModel model = new SymbolicRegressionModel(problemData.TargetVariable, tree, new SymbolicDataAnalysisExpressionTreeInterpreter());
+      IRegressionSolution solution = new RegressionSolution(model, (IRegressionProblemData)problemData.Clone());
+      Dictionary<string, double> expectedImpacts = GetExpectedValuesForCustomProblem();
+
+      CheckDefaultAsserts(solution, expectedImpacts);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void CustomModelVariableImpactNoInfluenceTest() {
+      IRegressionProblemData problemData = CreateDefaultProblem();
+      ISymbolicExpressionTree tree = CreateCustomExpressionTreeNoInfluenceX1();
+      IRegressionModel model = new SymbolicRegressionModel(problemData.TargetVariable, tree, new SymbolicDataAnalysisExpressionTreeInterpreter());
+      IRegressionSolution solution = new RegressionSolution(model, (IRegressionProblemData)problemData.Clone());
+      Dictionary<string, double> expectedImpacts = GetExpectedValuesForCustomProblemNoInfluence();
+
+      CheckDefaultAsserts(solution, expectedImpacts);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    [ExpectedException(typeof(ArgumentException))]
+    public void WrongDataSetVariableImpactRegressionTest() {
+      IRegressionProblemData problemData = LoadDefaultTowerProblem();
+      double rmsError;
+      double cvRmsError;
+      var solution = LinearRegression.CreateSolution(problemData, out rmsError, out cvRmsError);
+      solution.ProblemData = LoadDefaultMibaProblem();
+      RegressionSolutionVariableImpactsCalculator.CalculateImpacts(solution);
+
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "medium")]
+    public void PerformanceVariableImpactRegressionTest() {
+      int rows = 20000;
+      int columns = 77;
+      var dataSet = OnlineCalculatorPerformanceTest.CreateRandomDataset(new MersenneTwister(1234), rows, columns);
+      IRegressionProblemData problemData = new RegressionProblemData(dataSet, dataSet.VariableNames.Except("y".ToEnumerable()), "y");
+      double rmsError;
+      double cvRmsError;
+      var solution = LinearRegression.CreateSolution(problemData, out rmsError, out cvRmsError);
+
+      Stopwatch watch = new Stopwatch();
+      watch.Start();
+      var results = RegressionSolutionVariableImpactsCalculator.CalculateImpacts(solution);
+      watch.Stop();
+
+      TestContext.WriteLine("");
+      TestContext.WriteLine("Calculated cells per millisecond: {0}.", rows * columns / watch.ElapsedMilliseconds);
+
+    }
+
+    #region Load RegressionProblemData
+    private IRegressionProblemData LoadDefaultTowerProblem() {
+      RegressionRealWorldInstanceProvider provider = new RegressionRealWorldInstanceProvider();
+      var tower = new HeuristicLab.Problems.Instances.DataAnalysis.Tower();
+      return provider.LoadData(tower);
+    }
+    private IRegressionProblemData LoadDefaultMibaProblem() {
+      MibaFrictionRegressionInstanceProvider provider = new MibaFrictionRegressionInstanceProvider();
+      var cf1 = new HeuristicLab.Problems.Instances.DataAnalysis.CF1();
+      return provider.LoadData(cf1);
+    }
+    private IRegressionProblemData CreateDefaultProblem() {
+      List<string> allowedInputVariables = new List<string>() { "x1", "x2", "x3", "x4", "x5" };
+      string targetVariable = "y";
+      var variableNames = allowedInputVariables.Union(targetVariable.ToEnumerable());
+      double[,] variableValues = new double[100, variableNames.Count()];
+
+      FastRandom random = new FastRandom(12345);
+      for (int i = 0; i < variableValues.GetLength(0); i++) {
+        for (int j = 0; j < variableValues.GetLength(1); j++) {
+          variableValues[i, j] = random.Next(1, 100);
+        }
+      }
+
+      Dataset dataset = new Dataset(variableNames, variableValues);
+      return new RegressionProblemData(dataset, allowedInputVariables, targetVariable);
+    }
+    #endregion
+
+    #region Create SymbolicExpressionTree
+
+    private ISymbolicExpressionTree CreateCustomExpressionTree() {
+      return new InfixExpressionParser().Parse("x1*x2 - x2*x2 + x3*x3 + x4*x4 - x5*x5 + 14/12");
+    }
+    private ISymbolicExpressionTree CreateCustomExpressionTreeNoInfluenceX1() {
+      return new InfixExpressionParser().Parse("x1/x1*x2 - x2*x2 + x3*x3 + x4*x4 - x5*x5 + 14/12");
+    }
+    #endregion
+
+    #region Get Expected Values
+    private Dictionary<string, double> GetExpectedValuesForConstantModel() {
+      Dictionary<string, double> expectedImpacts = new Dictionary<string, double>();
+      expectedImpacts.Add("x1", 0);
+      expectedImpacts.Add("x10", 0);
+      expectedImpacts.Add("x11", 0);
+      expectedImpacts.Add("x12", 0);
+      expectedImpacts.Add("x13", 0);
+      expectedImpacts.Add("x14", 0);
+      expectedImpacts.Add("x15", 0);
+      expectedImpacts.Add("x16", 0);
+      expectedImpacts.Add("x17", 0);
+      expectedImpacts.Add("x18", 0);
+      expectedImpacts.Add("x19", 0);
+      expectedImpacts.Add("x2", 0);
+      expectedImpacts.Add("x20", 0);
+      expectedImpacts.Add("x21", 0);
+      expectedImpacts.Add("x22", 0);
+      expectedImpacts.Add("x23", 0);
+      expectedImpacts.Add("x24", 0);
+      expectedImpacts.Add("x25", 0);
+      expectedImpacts.Add("x3", 0);
+      expectedImpacts.Add("x4", 0);
+      expectedImpacts.Add("x5", 0);
+      expectedImpacts.Add("x6", 0);
+      expectedImpacts.Add("x7", 0);
+      expectedImpacts.Add("x8", 0);
+      expectedImpacts.Add("x9", 0);
+
+      return expectedImpacts;
+    }
+    private Dictionary<string, double> GetExpectedValuesForLRTower() {
+      Dictionary<string, double> expectedImpacts = new Dictionary<string, double>();
+      expectedImpacts.Add("x1", 0.639933657675427);
+      expectedImpacts.Add("x10", 0.0127006885259798);
+      expectedImpacts.Add("x11", 0.648236047877475);
+      expectedImpacts.Add("x12", 0.248350173524562);
+      expectedImpacts.Add("x13", 0.550889987109547);
+      expectedImpacts.Add("x14", 0.0882824237877192);
+      expectedImpacts.Add("x15", 0.0391276799061169);
+      expectedImpacts.Add("x16", 0.743632451088798);
+      expectedImpacts.Add("x17", 0.00254276857715308);
+      expectedImpacts.Add("x18", 0.0021548147614302);
+      expectedImpacts.Add("x19", 0.00513473927463037);
+      expectedImpacts.Add("x2", 0.0107583487931443);
+      expectedImpacts.Add("x20", 0.18085069746933);
+      expectedImpacts.Add("x21", 0.138053600700762);
+      expectedImpacts.Add("x22", 0.000339539790460086);
+      expectedImpacts.Add("x23", 0.362111965467117);
+      expectedImpacts.Add("x24", 0.0320167935572304);
+      expectedImpacts.Add("x25", 0.57460423230969);
+      expectedImpacts.Add("x3", 0.688142635515862);
+      expectedImpacts.Add("x4", 0.000176632348454664);
+      expectedImpacts.Add("x5", 0.0213915503114581);
+      expectedImpacts.Add("x6", 0.807976486909701);
+      expectedImpacts.Add("x7", 0.716217843319252);
+      expectedImpacts.Add("x8", 0.772701841392564);
+      expectedImpacts.Add("x9", 0.178418730050997);
+
+      return expectedImpacts;
+    }
+    private Dictionary<string, double> GetExpectedValuesForLRMiba() {
+      Dictionary<string, double> expectedImpacts = new Dictionary<string, double>();
+      expectedImpacts.Add("Grooving", 0.0380558091030508);
+      expectedImpacts.Add("Material", 0.02195836766156);
+      expectedImpacts.Add("Material_Cat", 0.000338687689067418);
+      expectedImpacts.Add("Oil", 0.363464994447857);
+      expectedImpacts.Add("x10", 0.0015309669014415);
+      expectedImpacts.Add("x11", -3.60432578908609E-05);
+      expectedImpacts.Add("x12", 0.00118953859087612);
+      expectedImpacts.Add("x13", 0.00164240977191832);
+      expectedImpacts.Add("x14", 0.000688363685380056);
+      expectedImpacts.Add("x15", -4.75067203969948E-05);
+      expectedImpacts.Add("x16", 0.00130388206125076);
+      expectedImpacts.Add("x17", 0.132351838646134);
+      expectedImpacts.Add("x2", -2.47981401556574E-05);
+      expectedImpacts.Add("x20", 0.716541716605016);
+      expectedImpacts.Add("x22", 0.174959377282835);
+      expectedImpacts.Add("x3", -2.65979754026091E-05);
+      expectedImpacts.Add("x4", -1.24764212947603E-05);
+      expectedImpacts.Add("x5", 0.001184959455798);
+      expectedImpacts.Add("x6", 0.000743336665237626);
+      expectedImpacts.Add("x7", 0.00188965927889773);
+      expectedImpacts.Add("x8", 0.00415201581536351);
+      expectedImpacts.Add("x9", 0.00365653880518491);
+
+      return expectedImpacts;
+    }
+    private Dictionary<string, double> GetExpectedValuesForRFTower() {
+      Dictionary<string, double> expectedImpacts = new Dictionary<string, double>();
+      expectedImpacts.Add("x5", 0.00138095702433039);
+      expectedImpacts.Add("x19", 0.00220739387855795);
+      expectedImpacts.Add("x14", 0.00225120540266954);
+      expectedImpacts.Add("x18", 0.00311857736968479);
+      expectedImpacts.Add("x9", 0.00313474690023097);
+      expectedImpacts.Add("x20", 0.00321781251408282);
+      expectedImpacts.Add("x21", 0.00397483365571383);
+      expectedImpacts.Add("x16", 0.00433280262892111);
+      expectedImpacts.Add("x15", 0.00529918809786456);
+      expectedImpacts.Add("x3", 0.00658791244929757);
+      expectedImpacts.Add("x24", 0.0078645281886035);
+      expectedImpacts.Add("x4", 0.00907314110749047);
+      expectedImpacts.Add("x13", 0.0102943761648944);
+      expectedImpacts.Add("x22", 0.0107132858548163);
+      expectedImpacts.Add("x12", 0.0157078677788507);
+      expectedImpacts.Add("x23", 0.0235857534562318);
+      expectedImpacts.Add("x7", 0.0304143401617055);
+      expectedImpacts.Add("x11", 0.0310773441767309);
+      expectedImpacts.Add("x25", 0.0328308945873665);
+      expectedImpacts.Add("x17", 0.0428771226844575);
+      expectedImpacts.Add("x10", 0.0456335367972532);
+      expectedImpacts.Add("x8", 0.049849257881126);
+      expectedImpacts.Add("x1", 0.0663686086323108);
+      expectedImpacts.Add("x2", 0.0799083890750926);
+      expectedImpacts.Add("x6", 0.196557814244287);
+
+      return expectedImpacts;
+    }
+    private Dictionary<string, double> GetExpectedValuesForCustomProblem() {
+      Dictionary<string, double> expectedImpacts = new Dictionary<string, double>();
+      expectedImpacts.Add("x1", -0.000573340275115796);
+      expectedImpacts.Add("x2", 0.000781819784095592);
+      expectedImpacts.Add("x3", -0.000390473234921058);
+      expectedImpacts.Add("x4", -0.00116083274627995);
+      expectedImpacts.Add("x5", -0.00036161186207545);
+
+      return expectedImpacts;
+    }
+    private Dictionary<string, double> GetExpectedValuesForCustomProblemNoInfluence() {
+      Dictionary<string, double> expectedImpacts = new Dictionary<string, double>();
+      expectedImpacts.Add("x1", 0);
+      expectedImpacts.Add("x2", 0.00263393690342982);
+      expectedImpacts.Add("x3", -0.00053248037514929);
+      expectedImpacts.Add("x4", 0.00450365819257568);
+      expectedImpacts.Add("x5", -0.000550911612888904);
+
+      return expectedImpacts;
+    }
+    #endregion
+
+    private void CheckDefaultAsserts(IRegressionSolution solution, Dictionary<string, double> expectedImpacts) {
+      IRegressionProblemData problemData = solution.ProblemData;
+      IEnumerable<double> estimatedValues = solution.GetEstimatedValues(solution.ProblemData.TrainingIndices);
+
+      var solutionImpacts = RegressionSolutionVariableImpactsCalculator.CalculateImpacts(solution);
+      var modelImpacts = RegressionSolutionVariableImpactsCalculator.CalculateImpacts(solution.Model, problemData, estimatedValues, problemData.TrainingIndices);
+
+      //Both ways should return equal results
+      Assert.IsTrue(solutionImpacts.SequenceEqual(modelImpacts));
+
+      //Check if impacts are as expected
+      Assert.AreEqual(modelImpacts.Count(), expectedImpacts.Count);
+      Assert.IsTrue(modelImpacts.All(v => v.Item2.IsAlmost(expectedImpacts[v.Item1])));
+    }
+  }
+}
Index: stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/VariableImpactCalculationTest.cs
===================================================================
--- stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/VariableImpactCalculationTest.cs	(revision 16437)
+++ 	(revision )
@@ -1,238 +1,0 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Linq;
-using HeuristicLab.Algorithms.ALPS;
-using HeuristicLab.Algorithms.DataAnalysis;
-using HeuristicLab.Data;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-using HeuristicLab.Problems.DataAnalysis.Symbolic;
-using HeuristicLab.Problems.DataAnalysis.Symbolic.Regression;
-using HeuristicLab.Problems.Instances.DataAnalysis;
-using HeuristicLab.Selection;
-using HeuristicLab.Tests;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace HeuristicLab.Problems.DataAnalysis.Tests {
-
-  [TestClass()]
-  public class VariableImpactCalculationTest {
-    [TestMethod]
-    [TestCategory("Problems.DataAnalysis")]
-    [TestProperty("Time", "medium")]
-    public void RunAlpsSymRegFactoryVariableMibaC1Test() {
-      var alpsGA = CreateAlpsGaSymRegMibaC1Sample();
-      alpsGA.Start();
-      var ers = alpsGA.Results.FirstOrDefault(v => v.Name == "Variable impacts").Value as DoubleMatrix;
-      Assert.IsNotNull(ers);
-      Assert.IsTrue(ers.Rows == 22);
-      List<string> expectedVariableOrder = new List<string> { "Oil", "Grooving", "Material_Cat", "x20", "Material", "x14", "x12", "x3", "x7", "x2", "x16", "x15", "x8", "x10", "x11", "x22", "x4", "x5", "x6", "x9", "x17", "x13" };
-      List<double> expectedVariableImpacts = new List<double> { 0.206, 0.179, 0.136, 0.099, 0.092, 0.07, 0.048, 0.033, 0.029, 0.026, 0.017, 0.01, 0.007, 0.007, 0.007, 0.006, 0.005, 0.005, 0.005, 0.005, 0.005, 0.003 };
-      Assert.IsTrue(ers.RowNames.SequenceEqual(expectedVariableOrder));
-      Assert.IsTrue(ers.SequenceEqual(expectedVariableImpacts));
-    }
-
-    [TestMethod]
-    [TestCategory("Problems.DataAnalysis")]
-    [TestProperty("Time", "medium")]
-    public void RunAlpsSymRegFactoryVariableMibaWear1Test() {
-      var alpsGA = CreateAlpsGaSymRegMibaWear1Sample();
-      alpsGA.Start();
-      var ers = alpsGA.Results.FirstOrDefault(v => v.Name == "Variable impacts").Value as DoubleMatrix;
-      Assert.IsNotNull(ers);
-      Assert.IsTrue(ers.Rows == 27);
-      List<string> expectedVariableOrder = new List<string> { "Oil", "Material_Cat", "Material", "Grooving", "x8", "x1", "x14", "x11", "x19", "x10", "x5", "x9", "x17", "x6", "x18", "x7", "Source1", "x2", "x3", "x4", "x16", "x20", "x12", "x13", "x15", "x22", "x21" };
-      List<double> expectedVariableImpacts = new List<double> { 0.194, 0.184, 0.163, 0.155, 0.022, 0.019, 0.019, 0.018, 0.017, 0.016, 0.015, 0.015, 0.015, 0.014, 0.014, 0.013, 0.012, 0.011, 0.011, 0.011, 0.011, 0.011, 0.01, 0.009, 0.009, 0.008, 0.006 };
-      Assert.IsTrue(ers.RowNames.SequenceEqual(expectedVariableOrder));
-      Assert.IsTrue(ers.SequenceEqual(expectedVariableImpacts));
-    }
-
-    [TestMethod]
-    [TestCategory("Problems.DataAnalysis")]
-    [TestProperty("Time", "medium")]
-    public void RunAlpsSymRegFactoryVariableRealworldTowerTest() {
-      var alpsGA = CreateAlpsGaSymReRealworldTowerSample();
-      alpsGA.Start();
-      var ers = alpsGA.Results.FirstOrDefault(v => v.Name == "Variable impacts").Value as DoubleMatrix;
-      Assert.IsNotNull(ers);
-      Assert.IsTrue(ers.Rows == 25);
-      List<string> expectedVariableOrder = new List<string> { "x5", "x4", "x21", "x22", "x13", "x3", "x9", "x19", "x1", "x12", "x8", "x10", "x25", "x11", "x23", "x7", "x24", "x6", "x14", "x15", "x20", "x2", "x16", "x18", "x17" };
-      List<double> expectedVariableImpacts = new List<double> { 0.057, 0.051, 0.047, 0.047, 0.046, 0.045, 0.044, 0.044, 0.043, 0.043, 0.041, 0.04, 0.04, 0.038, 0.038, 0.037, 0.037, 0.036, 0.036, 0.034, 0.033, 0.031, 0.031, 0.031, 0.03 };
-      Assert.IsTrue(ers.RowNames.SequenceEqual(expectedVariableOrder));
-      Assert.IsTrue(ers.SequenceEqual(expectedVariableImpacts));
-    }
-
-    [TestMethod]
-    [TestCategory("Problems.DataAnalysis")]
-    [TestProperty("Time", "short")]
-    public void RunRandomForestPolyTenTest() {
-      var randomForestRegression = new RandomForestRegression() {
-        M = 0.4,
-        R = 0.3,
-        NumberOfTrees = 50,
-        SetSeedRandomly = false,
-        Seed = 42
-      };
-
-      var symbRegProblem = new SymbolicRegressionSingleObjectiveProblem();
-      symbRegProblem.ProblemData = new PolyTen(555000).GenerateRegressionData();
-      randomForestRegression.Problem = symbRegProblem;
-      randomForestRegression.Start();
-
-      var rfs = randomForestRegression.Results.FirstOrDefault(v => v.Name == "Random forest regression solution").Value as RandomForestRegressionSolution;
-      Assert.IsNotNull(rfs);
-      var result = new RegressionSolutionVariableImpactsCalculator().Calculate(rfs);
-
-      //Set expected impacts
-      List<Tuple<string, double>> aux = new List<Tuple<string, double>>();
-      aux.Add(new Tuple<string, double>("X6", 0.14984398650032071));
-      aux.Add(new Tuple<string, double>("X5", 0.14361275357221248));
-      aux.Add(new Tuple<string, double>("X1", 0.10607502238071009));
-      aux.Add(new Tuple<string, double>("X3", 0.1056849194554953));
-      aux.Add(new Tuple<string, double>("X4", 0.0906750779077492));
-      aux.Add(new Tuple<string, double>("X2", 0.089817766590950532));
-      aux.Add(new Tuple<string, double>("X8", 0.042797597332305481));
-      aux.Add(new Tuple<string, double>("X9", 0.038609311722408446));
-      aux.Add(new Tuple<string, double>("X10", 0.036202503161574362));
-      aux.Add(new Tuple<string, double>("X7", 0.033539038256832465));
-      Assert.IsTrue(result.SequenceEqual(aux));
-    }
-
-    [TestMethod]
-    [TestCategory("Problems.DataAnalysis")]
-    [TestProperty("Time", "short")]
-    public void RunLinearRegressionBreimanITest() {
-      LinearRegression lr = new LinearRegression();
-      var symbRegProblem = new SymbolicRegressionSingleObjectiveProblem();
-      symbRegProblem.ProblemData = new BreimanOne(1234).GenerateRegressionData();
-
-      lr.Problem = symbRegProblem;
-      lr.Start();
-
-      var lrs = lr.Results.FirstOrDefault(v => v.Name == "Linear regression solution").Value as IRegressionSolution;
-      Assert.IsNotNull(lrs);
-      var result = new RegressionSolutionVariableImpactsCalculator().Calculate(lrs);
-
-      //Set expected impacts
-      List<Tuple<string, double>> aux = new List<Tuple<string, double>>();
-      aux.Add(new Tuple<string, double>("X1", 0.43328518823918716));
-      aux.Add(new Tuple<string, double>("X2", 0.073284548674773631));
-      aux.Add(new Tuple<string, double>("X5", 0.070306657566311159));
-      aux.Add(new Tuple<string, double>("X3", 0.035352205426012917));
-      aux.Add(new Tuple<string, double>("X6", 0.031710492680145475));
-      aux.Add(new Tuple<string, double>("X4", 0.0081659530036176653));
-      aux.Add(new Tuple<string, double>("X7", 0.0070869550705255913));
-      aux.Add(new Tuple<string, double>("X9", 8.0546619615096127E-05));
-      aux.Add(new Tuple<string, double>("X8", 6.2072921147349192E-05));
-      aux.Add(new Tuple<string, double>("X10", 1.9113559758254794E-06));
-
-      Assert.IsTrue(result.SequenceEqual(aux));
-    }
-
-    private AlpsGeneticAlgorithm CreateAlpsGaSymRegMibaC1Sample() {
-      AlpsGeneticAlgorithm alpsGa = new AlpsGeneticAlgorithm();
-      #region Problem Configuration
-      var provider = new MibaFrictionRegressionInstanceProvider();
-      var instance = provider.GetDataDescriptors().Single(x => x.Name.StartsWith("CF1"));
-      var symbRegProblem = new SymbolicRegressionSingleObjectiveProblem();
-      symbRegProblem.Load(provider.LoadData(instance));
-
-      symbRegProblem.MaximumSymbolicExpressionTreeDepth.Value = 35;
-      symbRegProblem.MaximumSymbolicExpressionTreeLength.Value = 35;
-
-      var grammar = (TypeCoherentExpressionGrammar)symbRegProblem.SymbolicExpressionTreeGrammar;
-      grammar.Symbols.OfType<Exponential>().Single().Enabled = false;
-      grammar.Symbols.OfType<Logarithm>().Single().Enabled = false;
-
-      #endregion
-      #region Algorithm Configuration
-      alpsGa.Name = "ALPS Genetic Programming - Symbolic Regression";
-      alpsGa.Description = "An ALPS-GP to solve a symbolic regression problem";
-      alpsGa.Problem = symbRegProblem;
-      SamplesUtils.ConfigureAlpsGeneticAlgorithmParameters<GeneralizedRankSelector, SubtreeCrossover, MultiSymbolicExpressionTreeManipulator>(alpsGa,
-        numberOfLayers: 1000,
-        popSize: 100,
-        mutationRate: 0.25,
-        elites: 1,
-        plusSelection: false,
-        agingScheme: AgingScheme.Polynomial,
-        ageGap: 15,
-        ageInheritance: 1.0,
-        maxGens: 10);
-
-      alpsGa.SetSeedRandomly.Value = false;
-      alpsGa.Seed.Value = 1234;
-      #endregion
-      return alpsGa;
-    }
-    private AlpsGeneticAlgorithm CreateAlpsGaSymRegMibaWear1Sample() {
-      AlpsGeneticAlgorithm alpsGa = new AlpsGeneticAlgorithm();
-      #region Problem Configuration
-      var provider = new MibaFrictionRegressionInstanceProvider();
-      var instance = provider.GetDataDescriptors().Single(x => x.Name.StartsWith("Wear1"));
-      var symbRegProblem = new SymbolicRegressionSingleObjectiveProblem();
-      symbRegProblem.Load(provider.LoadData(instance));
-
-      symbRegProblem.MaximumSymbolicExpressionTreeDepth.Value = 77;
-      symbRegProblem.MaximumSymbolicExpressionTreeLength.Value = 77;
-
-      var grammar = (TypeCoherentExpressionGrammar)symbRegProblem.SymbolicExpressionTreeGrammar;
-
-      #endregion
-      #region Algorithm Configuration
-      alpsGa.Name = "ALPS Genetic Programming - Symbolic Regression";
-      alpsGa.Description = "An ALPS-GP to solve a symbolic regression problem";
-      alpsGa.Problem = symbRegProblem;
-      SamplesUtils.ConfigureAlpsGeneticAlgorithmParameters<RandomSelector, SubtreeCrossover, MultiSymbolicExpressionTreeManipulator>(alpsGa,
-        numberOfLayers: 1000,
-        popSize: 200,
-        mutationRate: 0.25,
-        elites: 1,
-        plusSelection: false,
-        agingScheme: AgingScheme.Polynomial,
-        ageGap: 15,
-        ageInheritance: 1.0,
-        maxGens: 10);
-
-      alpsGa.SetSeedRandomly.Value = false;
-      alpsGa.Seed.Value = 11121314;
-      #endregion
-      return alpsGa;
-    }
-    private AlpsGeneticAlgorithm CreateAlpsGaSymReRealworldTowerSample() {
-      AlpsGeneticAlgorithm alpsGa = new AlpsGeneticAlgorithm();
-      #region Problem Configuration
-      var provider = new RegressionRealWorldInstanceProvider();
-      var instance = provider.GetDataDescriptors().Single(x => x.Name.StartsWith("Tower"));
-      var symbRegProblem = new SymbolicRegressionSingleObjectiveProblem();
-      symbRegProblem.Load(provider.LoadData(instance));
-
-      symbRegProblem.MaximumSymbolicExpressionTreeDepth.Value = 77;
-      symbRegProblem.MaximumSymbolicExpressionTreeLength.Value = 77;
-
-      var grammar = (TypeCoherentExpressionGrammar)symbRegProblem.SymbolicExpressionTreeGrammar;
-
-      #endregion
-      #region Algorithm Configuration
-      alpsGa.Name = "ALPS Genetic Programming - Symbolic Regression";
-      alpsGa.Description = "An ALPS-GP to solve a symbolic regression problem";
-      alpsGa.Problem = symbRegProblem;
-      SamplesUtils.ConfigureAlpsGeneticAlgorithmParameters<RandomSelector, SubtreeCrossover, MultiSymbolicExpressionTreeManipulator>(alpsGa,
-        numberOfLayers: 1000,
-        popSize: 200,
-        mutationRate: 0.25,
-        elites: 1,
-        plusSelection: false,
-        agingScheme: AgingScheme.Polynomial,
-        ageGap: 15,
-        ageInheritance: 1.0,
-        maxGens: 10);
-
-      alpsGa.SetSeedRandomly.Value = false;
-      alpsGa.Seed.Value = 1111;
-      #endregion
-      return alpsGa;
-    }
-
-    //TODO: Add Function-Tests once the Branch of #2904 is done
-  }
-}
Index: stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/IntervalInterpreterTest.cs
===================================================================
--- stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/IntervalInterpreterTest.cs	(revision 16437)
+++ stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/IntervalInterpreterTest.cs	(revision 16438)
@@ -1,6 +1,4 @@
 ﻿using System;
 using System.Collections.Generic;
-using HeuristicLab.Problems.DataAnalysis;
-using HeuristicLab.Problems.DataAnalysis.Symbolic;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 
Index: stable/HeuristicLab.Tests/HeuristicLab.Tests.csproj
===================================================================
--- stable/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 16437)
+++ stable/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 16438)
@@ -583,9 +583,10 @@
     <Compile Include="HeuristicLab.Persistence-3.3\UseCases.cs" />
     <Compile Include="HeuristicLab.PluginInfraStructure-3.3\TypeExtensionsTest.cs" />
+    <Compile Include="HeuristicLab.Problems.DataAnalysis-3.4\ClassificationVariableImpactCalculationTest.cs" />
     <Compile Include="HeuristicLab.Problems.DataAnalysis-3.4\IntervalTest.cs" />
+    <Compile Include="HeuristicLab.Problems.DataAnalysis-3.4\RegressionVariableImpactCalculationTest.cs" />
     <Compile Include="HeuristicLab.Problems.DataAnalysis-3.4\ThresholdCalculatorsTest.cs" />
     <Compile Include="HeuristicLab.Problems.DataAnalysis-3.4\OnlineCalculatorPerformanceTest.cs" />
     <Compile Include="HeuristicLab.Problems.DataAnalysis-3.4\StatisticCalculatorsTest.cs" />
-    <Compile Include="HeuristicLab.Problems.DataAnalysis-3.4\VariableImpactCalculationTest.cs" />
     <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\InfixExpressionParserTest.cs" />
     <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\IntervalInterpreterTest.cs" />
