Index: /branches/2965_CancelablePersistence/Build.ps1
===================================================================
--- /branches/2965_CancelablePersistence/Build.ps1	(revision 16432)
+++ /branches/2965_CancelablePersistence/Build.ps1	(revision 16433)
@@ -19,7 +19,10 @@
 }
 
-if ($msBuildPath -eq $undefined) {
-  "Could not locate MSBuild, ABORTING ..."
-} else {
+Try {
+  If ($msBuildPath -eq $undefined) {
+    "Could not locate MSBuild, ABORTING ..."
+    Return
+  }
+
   $curPath = $MyInvocation.MyCommand.Path
   $curDir = Split-Path $curPath
@@ -27,36 +30,48 @@
   $slnFiles = Get-ChildItem $curDir -Filter *.sln
 
-  "Found the following solutions:"
+  If ($slnFiles.Count -le 0) {
+    "No solutions found, ABORTING ..."
+    Return
+  }
 
-  ""
+  $slnIndices = @()
 
-  $slnFiles | % { $i = 0 } { ("  {0}. `"{1}`"" -f ($i + 1), $_.Name); $i++ }
+  If ($slnFiles.Count -eq 1) {
+    "Selecting the only solution found: `"{0}`"" -f $slnFiles[0].Name
+    $slnIndices += 0
+  } Else {
+    "Found the following solutions:"
 
-  ""
+    ""
 
-  $success = $false
+    $slnFiles | % { $i = 0 } { ("  {0}. `"{1}`"" -f ($i + 1), $_.Name); $i++ }
 
-  # query solution to build
-  $slnIndex = -1
-  $slnIndices = @()
-  Do {
-      $input = Read-Host "Which solution(s) to build? {1..$($slnFiles.Count)}"
-      $inputParts = $input -Split " "
+    ""
 
-      Foreach ($part in $inputParts) {
-        If ($part -eq "") { Continue }
+    $success = $false
 
-        $success = [int]::TryParse($part, [ref]$slnIndex) -and ($slnIndex -gt 0) -and ($slnIndex -le $slnFiles.Count)
+    # query solution to build
+    $slnIndex = -1
+    Do {
+        $input = Read-Host "Which solution(s) to build? (e.g.: 1 2 3) { 1..$($slnFiles.Count) }"
+        $inputParts = $input -Split " "
 
-        If ($success) {
-          $slnIndices += $slnIndex - 1
-        } Else {
-          $slnIndices = @()
-          Break
+        Foreach ($part in $inputParts) {
+          If ($part -eq "") { Continue }
+
+          $success = [int]::TryParse($part, [ref]$slnIndex) -and ($slnIndex -gt 0) -and ($slnIndex -le $slnFiles.Count)
+
+          If ($success) {
+            $slnIndices += $slnIndex - 1
+          } Else {
+            $slnIndices = @()
+            Break
+          }
         }
-      }
-  } While (-Not $success)
+    } While (-Not $success)
 
-  $slnIndices = $slnIndices | Select-Object -Unique
+    $slnIndices = $slnIndices | Select-Object -Unique
+  }
+
 
   # query configuration to build
@@ -80,5 +95,5 @@
   ""
 
-  if ($clean) {
+  If ($clean) {
     Foreach ($slnIndex in $slnIndices) {
       $solution = $slnFiles[$slnIndex]
@@ -107,8 +122,9 @@
     "===== BUILD FINISHED ====="
   }
+} Finally {
+  ""
+
+  Write-Host -NoNewline "Press any key to continue ... "
+
+  [void][System.Console]::ReadKey($true)
 }
-
-""
-
-Write-Host -NoNewline "Press any key to continue ... "
-[void][System.Console]::ReadKey($true)
Index: /branches/2965_CancelablePersistence/HeuristicLab.Algorithms.Benchmarks/3.3/BenchmarkAlgorithm.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Algorithms.Benchmarks/3.3/BenchmarkAlgorithm.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Algorithms.Benchmarks/3.3/BenchmarkAlgorithm.cs	(revision 16433)
@@ -39,6 +39,8 @@
   [Creatable(CreatableAttribute.Categories.TestingAndAnalysis, Priority = 130)]
   [StorableClass]
-  public sealed class BenchmarkAlgorithm : IAlgorithm {
+  public sealed class BenchmarkAlgorithm : IAlgorithm, IStorableContent {
     private CancellationTokenSource cancellationTokenSource;
+
+    public string Filename { get; set; }
 
     public string ItemName {
Index: /branches/2965_CancelablePersistence/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 16433)
@@ -263,4 +263,5 @@
     <Compile Include="Linear\MultinomialLogitClassification.cs" />
     <Compile Include="Linear\MultinomialLogitClassificationSolution.cs" />
+    <Compile Include="Linear\LinearRegressionModel.cs" />
     <Compile Include="Linear\MultinomialLogitModel.cs" />
     <Compile Include="Linear\Scaling.cs" />
Index: /branches/2965_CancelablePersistence/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearRegression.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearRegression.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearRegression.cs	(revision 16433)
@@ -62,5 +62,5 @@
     protected override void Run(CancellationToken cancellationToken) {
       double rmsError, cvRmsError;
-      var solution = CreateLinearRegressionSolution(Problem.ProblemData, out rmsError, out cvRmsError);
+      var solution = CreateSolution(Problem.ProblemData, out rmsError, out cvRmsError);
       Results.Add(new Result(LinearRegressionModelResultName, "The linear regression solution.", solution));
       Results.Add(new Result("Root mean square error", "The root of the mean of squared errors of the linear regression solution on the training set.", new DoubleValue(rmsError)));
@@ -68,18 +68,10 @@
     }
 
+    [Obsolete("Use CreateSolution() instead")]
     public static ISymbolicRegressionSolution CreateLinearRegressionSolution(IRegressionProblemData problemData, out double rmsError, out double cvRmsError) {
-      var dataset = problemData.Dataset;
-      string targetVariable = problemData.TargetVariable;
-      IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
-      IEnumerable<int> rows = problemData.TrainingIndices;
-      var doubleVariables = allowedInputVariables.Where(dataset.VariableHasType<double>);
-      var factorVariableNames = allowedInputVariables.Where(dataset.VariableHasType<string>);
-      var factorVariables = dataset.GetFactorVariableValues(factorVariableNames, rows);
-      double[,] binaryMatrix = dataset.ToArray(factorVariables, rows);
-      double[,] doubleVarMatrix = dataset.ToArray(doubleVariables.Concat(new string[] { targetVariable }), rows);
-      var inputMatrix = binaryMatrix.HorzCat(doubleVarMatrix);
-
-      if (inputMatrix.ContainsNanOrInfinity())
-        throw new NotSupportedException("Linear regression does not support NaN or infinity values in the input dataset.");
+      IEnumerable<string> doubleVariables;
+      IEnumerable<KeyValuePair<string, IEnumerable<string>>> factorVariables;
+      double[,] inputMatrix;
+      PrepareData(problemData, out inputMatrix, out doubleVariables, out factorVariables);
 
       alglib.linearmodel lm = new alglib.linearmodel();
@@ -87,5 +79,4 @@
       int nRows = inputMatrix.GetLength(0);
       int nFeatures = inputMatrix.GetLength(1) - 1;
-      double[] coefficients = new double[nFeatures + 1]; // last coefficient is for the constant
 
       int retVal = 1;
@@ -95,7 +86,8 @@
       cvRmsError = ar.cvrmserror;
 
+      double[] coefficients = new double[nFeatures + 1]; // last coefficient is for the constant
       alglib.lrunpack(lm, out coefficients, out nFeatures);
-
-      int nFactorCoeff = binaryMatrix.GetLength(1);
+      
+      int nFactorCoeff = factorVariables.Sum(kvp=>kvp.Value.Count());
       int nVarCoeff = doubleVariables.Count();
       var tree = LinearModelToTreeConverter.CreateTree(factorVariables, coefficients.Take(nFactorCoeff).ToArray(),
@@ -108,4 +100,54 @@
       return solution;
     }
+
+    public static IRegressionSolution CreateSolution(IRegressionProblemData problemData, out double rmsError, out double cvRmsError) {
+      IEnumerable<string> doubleVariables;
+      IEnumerable<KeyValuePair<string, IEnumerable<string>>> factorVariables;
+      double[,] inputMatrix;
+      PrepareData(problemData, out inputMatrix, out doubleVariables, out factorVariables);
+
+      alglib.linearmodel lm = new alglib.linearmodel();
+      alglib.lrreport ar = new alglib.lrreport();
+      int nRows = inputMatrix.GetLength(0);
+      int nFeatures = inputMatrix.GetLength(1) - 1;
+
+      int retVal = 1;
+      alglib.lrbuild(inputMatrix, nRows, nFeatures, out retVal, out lm, out ar);
+      if (retVal != 1) throw new ArgumentException("Error in calculation of linear regression solution");
+      rmsError = ar.rmserror;
+      cvRmsError = ar.cvrmserror;
+
+      // get parameters of the model
+      double[] w;
+      int nVars;
+      alglib.lrunpack(lm, out w, out nVars);
+
+      // ar.c is the covariation matrix,  array[0..NVars,0..NVars].
+      // C[i, j] = Cov(A[i], A[j])
+
+      var solution = new LinearRegressionModel(w, ar.c, cvRmsError, problemData.TargetVariable, doubleVariables, factorVariables)
+        .CreateRegressionSolution((IRegressionProblemData)problemData.Clone());
+      solution.Name = "Linear Regression Solution";
+      return solution;
+    }
+
+    private static void PrepareData(IRegressionProblemData problemData, 
+      out double[,] inputMatrix, 
+      out IEnumerable<string> doubleVariables, 
+      out IEnumerable<KeyValuePair<string, IEnumerable<string>>> factorVariables) {
+      var dataset = problemData.Dataset;
+      string targetVariable = problemData.TargetVariable;
+      IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
+      IEnumerable<int> rows = problemData.TrainingIndices;
+      doubleVariables = allowedInputVariables.Where(dataset.VariableHasType<double>);
+      var factorVariableNames = allowedInputVariables.Where(dataset.VariableHasType<string>);
+      factorVariables = dataset.GetFactorVariableValues(factorVariableNames, rows);
+      double[,] binaryMatrix = dataset.ToArray(factorVariables, rows);
+      double[,] doubleVarMatrix = dataset.ToArray(doubleVariables.Concat(new string[] { targetVariable }), rows);
+      inputMatrix = binaryMatrix.HorzCat(doubleVarMatrix);
+
+      if (inputMatrix.ContainsNanOrInfinity())
+        throw new NotSupportedException("Linear regression does not support NaN or infinity values in the input dataset.");
+    }
     #endregion
   }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearRegressionModel.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearRegressionModel.cs	(revision 16433)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearRegressionModel.cs	(revision 16433)
@@ -0,0 +1,147 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  /// <summary>
+  /// Represents a linear regression model
+  /// </summary>
+  [StorableClass]
+  [Item("Linear Regression Model", "Represents a linear regression model.")]
+  public sealed class LinearRegressionModel : RegressionModel, IConfidenceRegressionModel {
+
+    [Storable]
+    public double[,] C {
+      get; private set;
+    }
+    [Storable]
+    public double[] W {
+      get; private set;
+    }
+
+    [Storable]
+    public double NoiseSigma {
+      get; private set;
+    }
+    
+    public override IEnumerable<string> VariablesUsedForPrediction {
+      get { return allowedInputVariables.Union(factorVariables.Select(f => f.Key)); }
+    }
+
+    [Storable]
+    private string[] allowedInputVariables;
+    [Storable]
+    private List<KeyValuePair<string, IEnumerable<string>>> factorVariables;
+
+    [StorableConstructor]
+    private LinearRegressionModel(bool deserializing)
+      : base(deserializing) {
+    }
+    private LinearRegressionModel(LinearRegressionModel original, Cloner cloner)
+      : base(original, cloner) {
+      this.W = original.W;
+      this.C = original.C;
+      this.NoiseSigma = original.NoiseSigma;
+
+      allowedInputVariables = (string[])original.allowedInputVariables.Clone();
+      this.factorVariables = original.factorVariables.Select(kvp => new KeyValuePair<string, IEnumerable<string>>(kvp.Key, new List<string>(kvp.Value))).ToList();
+    }
+    public LinearRegressionModel(double[] w, double[,] covariance, double noiseSigma, string targetVariable, IEnumerable<string> doubleInputVariables, IEnumerable<KeyValuePair<string, IEnumerable<string>>> factorVariables)
+      : base(targetVariable) {
+      this.name = ItemName;
+      this.description = ItemDescription;
+      this.W = new double[w.Length];
+      Array.Copy(w, W, w.Length);
+      this.C = new double[covariance.GetLength(0),covariance.GetLength(1)];
+      Array.Copy(covariance, C, covariance.Length);
+      this.NoiseSigma = noiseSigma;
+      var stringInputVariables = factorVariables.Select(f => f.Key).Distinct();
+      this.allowedInputVariables = doubleInputVariables.ToArray();
+      this.factorVariables = factorVariables.Select(kvp => new KeyValuePair<string, IEnumerable<string>>(kvp.Key, new List<string>(kvp.Value))).ToList();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LinearRegressionModel(this, cloner);
+    }
+
+    public override IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
+      double[,] inputData = dataset.ToArray(allowedInputVariables, rows);
+      double[,] factorData = dataset.ToArray(factorVariables, rows);
+
+      inputData = factorData.HorzCat(inputData);
+
+      int n = inputData.GetLength(0);
+      int columns = inputData.GetLength(1);
+
+      for (int row = 0; row < n; row++) {
+        double p = 0.0;
+        for (int column = 0; column < columns; column++) {
+          p += W[column] * inputData[row, column];
+        }
+        p += W[columns];
+        yield return p;
+      }
+    }
+
+    public IEnumerable<double> GetEstimatedVariances(IDataset dataset, IEnumerable<int> rows) {
+      double[,] inputData = dataset.ToArray(allowedInputVariables, rows);
+      double[,] factorData = dataset.ToArray(factorVariables, rows);
+
+      inputData = factorData.HorzCat(inputData);
+
+      int n = inputData.GetLength(0);
+      int columns = inputData.GetLength(1);
+
+      double[] d = new double[C.GetLength(0)];
+      
+      for (int row = 0; row < n; row++) {
+        for (int column = 0; column < columns; column++) {
+          d[column] = inputData[row,column];
+        }
+        d[columns] = 1;
+
+        double var = 0.0;
+        for(int i=0;i<d.Length;i++) {
+          for(int j = 0;j<d.Length;j++) {
+            var += d[i] * C[i, j] * d[j];
+          }
+        }
+        yield return var + NoiseSigma*NoiseSigma;
+      }
+    }
+
+
+    public override IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+      return new ConfidenceRegressionSolution(this, new RegressionProblemData(problemData));
+    }
+  }
+}
Index: /branches/2965_CancelablePersistence/HeuristicLab.Analysis.Statistics.Views/3.3/ChartAnalysisView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Analysis.Statistics.Views/3.3/ChartAnalysisView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Analysis.Statistics.Views/3.3/ChartAnalysisView.cs	(revision 16433)
@@ -173,5 +173,5 @@
 
     private void addLineToChart_Click(object sender, EventArgs e) {
-      MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().AddOperationProgressToView(this, "Adding fitted lines to charts...");
+      Progress.Show(this, "Adding fitted lines to charts...", ProgressMode.Indeterminate);
 
       string resultName = (string)dataTableComboBox.SelectedItem;
@@ -181,10 +181,10 @@
 
       task.ContinueWith((t) => {
-        MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this);
+        Progress.Hide(this);
         ErrorHandling.ShowErrorDialog("An error occured while adding lines to charts. ", t.Exception);
       }, TaskContinuationOptions.OnlyOnFaulted);
 
       task.ContinueWith((t) => {
-        MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this);
+        Progress.Hide(this);
       }, TaskContinuationOptions.OnlyOnRanToCompletion);
     }
@@ -273,10 +273,10 @@
       var task = Task.Factory.StartNew(() => {
         sem.Wait();
-        progress = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().AddOperationProgressToView(this, "Calculating values...");
+        progress = Progress.Show(this, "Calculating values...");
         RebuildDataTable(resultName, rowName);
       });
 
       task.ContinueWith((t) => {
-        MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this);
+        Progress.Hide(this);
         ErrorHandling.ShowErrorDialog("An error occured while calculating values. ", t.Exception);
         sem.Release();
@@ -284,5 +284,5 @@
 
       task.ContinueWith((t) => {
-        MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this);
+        Progress.Hide(this);
         sem.Release();
       }, TaskContinuationOptions.OnlyOnRanToCompletion);
Index: /branches/2965_CancelablePersistence/HeuristicLab.Analysis.Statistics.Views/3.3/StatisticalTestsView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Analysis.Statistics.Views/3.3/StatisticalTestsView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Analysis.Statistics.Views/3.3/StatisticalTestsView.cs	(revision 16433)
@@ -356,6 +356,5 @@
 
       if (data != null && data.All(x => x != null)) {
-        MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>()
-          .AddOperationProgressToView(this, "Calculating...");
+        Progress.Show(this, "Calculating...", ProgressMode.Indeterminate);
 
         string curItem = (string)groupCompComboBox.SelectedItem;
@@ -369,5 +368,5 @@
       CalculatePairwiseTest(groupName);
 
-      MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this);
+      Progress.Hide(this);
     }
 
@@ -377,5 +376,5 @@
         return;
 
-      MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().AddOperationProgressToView(pairwiseTestGroupBox, "Calculating...");
+      Progress.ShowOnControl(pairwiseTestGroupBox, "Calculating...", ProgressMode.Indeterminate);
       Task.Factory.StartNew(() => CalculatePairwiseAsync(groupName));
     }
@@ -384,5 +383,5 @@
       CalculatePairwiseTest(groupName);
 
-      MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(pairwiseTestGroupBox);
+      Progress.HideFromControl(pairwiseTestGroupBox);
     }
 
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Access.Views/3.3/ClientViews/ClientView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Access.Views/3.3/ClientViews/ClientView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Access.Views/3.3/ClientViews/ClientView.cs	(revision 16433)
@@ -77,9 +77,9 @@
     public void StartProgressView() {
       var message = "Downloading client information. Please be patient.";
-      MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().AddOperationProgressToView(this, message);
+      Progress.Show(this, message, ProgressMode.Indeterminate);
     }
 
     public void FinishProgressView() {
-      MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this);
+      Progress.Hide(this);
     }
   }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectJobsView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectJobsView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectJobsView.cs	(revision 16433)
@@ -75,5 +75,5 @@
       progress = new Progress();
 
-      removeButton.Enabled = false;      
+      removeButton.Enabled = false;
     }
 
@@ -81,10 +81,10 @@
       base.RegisterContentEvents();
       matrixView.DataGridView.SelectionChanged += DataGridView_SelectionChanged;
-      MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().AddOperationProgressToView(this, progress);
+      MainForm.Progress.Show(this, progress);
     }
 
     protected override void DeregisterContentEvents() {
       matrixView.DataGridView.SelectionChanged -= DataGridView_SelectionChanged;
-      MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this, false);
+      MainForm.Progress.Hide(this, false);
       base.DeregisterContentEvents();
     }
@@ -114,5 +114,5 @@
         var jobs = GetSelectedJobs().ToList();
         if (jobs.Any()) {
-                    
+
           startButton.Enabled = jobs.All(x =>
             !x.IsProgressing && HiveAdminClient.Instance.Tasks.ContainsKey(x.Id) && HiveAdminClient.Instance.Tasks[x.Id].Count > 0
@@ -135,14 +135,14 @@
     #region Event Handlers
     private void ProjectJobsView_Load(object sender, EventArgs e) {
-      
+
     }
 
     private void refreshButton_Click(object sender, EventArgs e) {
-      progress.Start("Refreshing jobs...");
+      progress.Start("Refreshing jobs...", ProgressMode.Indeterminate);
       SetEnabledStateOfControls();
       var task = System.Threading.Tasks.Task.Factory.StartNew(RefreshJobsAsync);
 
       task.ContinueWith((t) => {
-        progress.Finish();        
+        progress.Finish();
         SetEnabledStateOfControls();
       });
@@ -160,5 +160,5 @@
 
         if (result == DialogResult.Yes) {
-          progress.Start("Removing job(s)...");
+          progress.Start("Removing job(s)...", ProgressMode.Indeterminate);
           SetEnabledStateOfControls();
           var task = System.Threading.Tasks.Task.Factory.StartNew(RemoveJobsAsync, jobs);
@@ -191,10 +191,10 @@
 
         if (result == DialogResult.Yes) {
-          progress.Start("Resuming job(s)...");
+          progress.Start("Resuming job(s)...", ProgressMode.Indeterminate);
           SetEnabledStateOfControls();
           var task = System.Threading.Tasks.Task.Factory.StartNew(ResumeJobsAsync, jobs);
 
           task.ContinueWith((t) => {
-            RefreshJobs();            
+            RefreshJobs();
             progress.Finish();
             SetEnabledStateOfControls();
@@ -227,5 +227,5 @@
 
           task.ContinueWith((t) => {
-            RefreshJobs();            
+            RefreshJobs();
             progress.Finish();
             SetEnabledStateOfControls();
@@ -253,5 +253,5 @@
 
         if (result == DialogResult.Yes) {
-          progress.Start("Stopping job(s)...");
+          progress.Start("Stopping job(s)...", ProgressMode.Indeterminate);
           SetEnabledStateOfControls();
           var task = System.Threading.Tasks.Task.Factory.StartNew(StopJobsAsync, jobs);
@@ -267,5 +267,5 @@
             progress.Finish();
             SetEnabledStateOfControls();
-            MessageBox.Show("An error occured stopping the job(s).", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);            
+            MessageBox.Show("An error occured stopping the job(s).", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
           }, TaskContinuationOptions.OnlyOnFaulted);
         }
@@ -284,10 +284,10 @@
     private IEnumerable<RefreshableJob> GetSelectedJobs() {
       if (Content == null || matrixView.DataGridView.SelectedRows == null || matrixView.DataGridView.SelectedRows.Count == 0)
-        return Enumerable.Empty<RefreshableJob>() ;
+        return Enumerable.Empty<RefreshableJob>();
 
       var jobs = new List<RefreshableJob>();
       foreach (DataGridViewRow r in matrixView.DataGridView.SelectedRows) {
         if (((string)r.Cells[0].Value) == JobState.Online.ToString()) {
-          jobs.Add(HiveAdminClient.Instance.Jobs[Content.Id].FirstOrDefault(x => x.Id == Guid.Parse((string) r.Cells[11].Value)));
+          jobs.Add(HiveAdminClient.Instance.Jobs[Content.Id].FirstOrDefault(x => x.Id == Guid.Parse((string)r.Cells[11].Value)));
         }
       }
@@ -310,6 +310,6 @@
       string[,] values = new string[jobs.Count, 13];
 
-      for(int i = 0; i < jobs.Count; i++) {
-        var job = jobs.ElementAt(i);        
+      for (int i = 0; i < jobs.Count; i++) {
+        var job = jobs.ElementAt(i);
         values[i, 0] = job.Job.State.ToString();
         values[i, 1] = job.ExecutionState.ToString();
@@ -322,9 +322,9 @@
         values[i, 8] = job.Job.CalculatingCount.ToString();
         values[i, 9] = job.Job.FinishedCount.ToString();
-        values[i, 10] = job.Job.Description;        
+        values[i, 10] = job.Job.Description;
         values[i, 11] = job.Job.Id.ToString();
         values[i, 12] = job.Job.OwnerUserId.ToString();
       }
-      
+
       var matrix = new StringMatrix(values);
       matrix.ColumnNames = new string[] { JOB_STATE, JOB_EXECUTIONSTATE, JOB_EXECUTIONTIME, JOB_DATECREATED, JOB_OWNER, JOB_NAME, JOB_TASKCOUNT, JOB_WAITINGTASKCOUNT, JOB_CALCULATINGTASKCOUNT, JOB_FINISHEDTASKCOUNT, JOB_DESCRIPTION, JOB_ID, JOB_OWNERID };
@@ -332,12 +332,12 @@
       return matrix;
     }
-    
+
     private void UpdateJobs() {
       if (InvokeRequired) Invoke((Action)UpdateJobs);
       else {
-        if(Content != null && Content.Id != null && Content.Id != Guid.Empty) {
+        if (Content != null && Content.Id != null && Content.Id != Guid.Empty) {
           var matrix = CreateValueMatrix();
           matrixView.Content = matrix;
-          if(matrix != null) {
+          if (matrix != null) {
             foreach (DataGridViewRow row in matrixView.DataGridView.Rows) {
               string val = ((string)row.Cells[0].Value);
@@ -355,5 +355,5 @@
             matrixView.DataGridView.Columns[1].MinimumWidth = 108;
           }
-        } 
+        }
       }
     }
@@ -367,5 +367,5 @@
       var jobList = (IEnumerable<RefreshableJob>)jobs;
       foreach (var job in jobList) {
-        progress.Status = "Resuming job \"" + job.Job.Name + "\"...";
+        progress.Message = "Resuming job \"" + job.Job.Name + "\"...";
         HiveAdminClient.ResumeJob(job);
       }
@@ -375,5 +375,5 @@
       var jobList = (IEnumerable<RefreshableJob>)jobs;
       foreach (var job in jobList) {
-        progress.Status = "Pausing job \"" + job.Job.Name + "\"...";
+        progress.Message = "Pausing job \"" + job.Job.Name + "\"...";
         HiveAdminClient.PauseJob(job);
       }
@@ -381,7 +381,7 @@
 
     private void StopJobsAsync(object jobs) {
-      var jobList = (IEnumerable<RefreshableJob>) jobs;
-      foreach (var job in jobList) {        
-        progress.Status = "Stopping job \"" + job.Job.Name + "\"...";
+      var jobList = (IEnumerable<RefreshableJob>)jobs;
+      foreach (var job in jobList) {
+        progress.Message = "Stopping job \"" + job.Job.Name + "\"...";
         HiveAdminClient.StopJob(job);
       }
@@ -390,7 +390,7 @@
     private void RemoveJobsAsync(object jobs) {
       var jobList = (IEnumerable<RefreshableJob>)jobs;
-      progress.Start();
+      progress.Start("", ProgressMode.Indeterminate);
       foreach (var job in jobList) {
-        progress.Status = "Removing job \"" + job.Job.Name + "\"...";
+        progress.Message = "Removing job \"" + job.Job.Name + "\"...";
         HiveAdminClient.RemoveJob(job);
       }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectPermissionsView.Designer.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectPermissionsView.Designer.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectPermissionsView.Designer.cs	(revision 16433)
@@ -112,5 +112,5 @@
       this.permissionsGroupBox.TabIndex = 4;
       this.permissionsGroupBox.TabStop = false;
-      this.permissionsGroupBox.Text = "Permissions (Assigned + Included)";
+      this.permissionsGroupBox.Text = "Compute Permissions (Assigned + Included)";
       // 
       // treeView
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectView.Designer.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectView.Designer.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectView.Designer.cs	(revision 16433)
@@ -39,6 +39,5 @@
       this.endLabel = new System.Windows.Forms.Label();
       this.indefiniteCheckBox = new System.Windows.Forms.CheckBox();
-      this.createdTextBox = new System.Windows.Forms.TextBox();
-      this.refreshButton = new System.Windows.Forms.Button();
+      this.createdTextBox = new System.Windows.Forms.TextBox();      
       this.toolTip = new System.Windows.Forms.ToolTip(this.components);
       this.SuspendLayout();
@@ -124,15 +123,4 @@
       this.ownerComboBox.SelectedIndexChanged += new System.EventHandler(this.ownerComboBox_SelectedIndexChanged);
       // 
-      // refreshButton
-      // 
-      this.refreshButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Refresh;
-      this.refreshButton.Location = new System.Drawing.Point(278, 162);
-      this.refreshButton.Name = "refreshButton";
-      this.refreshButton.Size = new System.Drawing.Size(24, 24);
-      this.refreshButton.TabIndex = 5;
-      this.toolTip.SetToolTip(this.refreshButton, "Refresh data");
-      this.refreshButton.UseVisualStyleBackColor = true;
-      this.refreshButton.Click += new System.EventHandler(this.refreshButton_Click);
-      // 
       // createdLabel
       // 
@@ -207,5 +195,4 @@
       this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-      this.Controls.Add(this.refreshButton);
       this.Controls.Add(this.createdTextBox);
       this.Controls.Add(this.indefiniteCheckBox);
@@ -247,6 +234,5 @@
     private System.Windows.Forms.Label endLabel;
     private System.Windows.Forms.CheckBox indefiniteCheckBox;
-    private System.Windows.Forms.TextBox createdTextBox;
-    private System.Windows.Forms.Button refreshButton;
+    private System.Windows.Forms.TextBox createdTextBox;    
     private System.Windows.Forms.ToolTip toolTip;
   }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectView.cs	(revision 16433)
@@ -127,5 +127,4 @@
       nameTextBox.Enabled = enabled;
       descriptionTextBox.Enabled = enabled;
-      refreshButton.Enabled = enabled;
       ownerComboBox.Enabled = enabled;
       createdTextBox.Enabled = enabled;
@@ -161,6 +160,5 @@
       if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshing, sender, e);
       else {
-        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
-        mainForm.AddOperationProgressToView(this, "Refreshing ...");
+        Progress.Show(this, "Refreshing ...", ProgressMode.Indeterminate);
         SetEnabledStateOfControls();
       }
@@ -170,6 +168,5 @@
       if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshed, sender, e);
       else {
-        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
-        mainForm.RemoveOperationProgressFromView(this);
+        Progress.Hide(this);
         SetEnabledStateOfControls();
       }
@@ -188,23 +185,4 @@
     }
 
-    private async void refreshButton_Click(object sender, EventArgs e) {
-      lock (locker) {
-        if (!refreshButton.Enabled) return;
-        refreshButton.Enabled = false;
-      }
-
-      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
-        action: () => UpdateUsers(),
-        finallyCallback: () => {
-          ownerComboBox.SelectedIndexChanged -= ownerComboBox_SelectedIndexChanged;
-          var users = AccessClient.Instance.UsersAndGroups.OfType<LightweightUser>();
-          if (Content != null && !Content.ParentProjectId.HasValue) users = users.Where(x => x.Roles.Select(y => y.Name).Contains(HiveRoles.Administrator));
-          ownerComboBox.DataSource = users.ToList();
-          ownerComboBox.SelectedItem = users.FirstOrDefault(x => x.Id == persistedOwnerUserId);
-          ownerComboBox.SelectedIndexChanged += ownerComboBox_SelectedIndexChanged;
-          refreshButton.Enabled = true;
-        });
-    }
-
     private void nameTextBox_Validating(object sender, CancelEventArgs e) {
       if (string.IsNullOrEmpty(nameTextBox.Text)) {
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.Designer.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.Designer.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.Designer.cs	(revision 16433)
@@ -194,5 +194,5 @@
       this.permissionsTabPage.Size = new System.Drawing.Size(577, 515);
       this.permissionsTabPage.TabIndex = 1;
-      this.permissionsTabPage.Text = "Permissions";
+      this.permissionsTabPage.Text = "Compute Permissions";
       this.permissionsTabPage.UseVisualStyleBackColor = true;
       // 
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.cs	(revision 16433)
@@ -43,5 +43,5 @@
     private const string NOT_STORED_TAG = "*"; // " [not stored]";
     private const string CHANGES_NOT_STORED_TAG = "*"; // " [changes not stored]";
-    private const string INACTIVE_TAG = " [inactive]"; 
+    private const string INACTIVE_TAG = " [inactive]";
 
     private readonly Color selectedBackColor = Color.DodgerBlue;
@@ -111,9 +111,9 @@
 
     protected override void SetEnabledStateOfControls() {
-      base.SetEnabledStateOfControls();      
-
-      bool locked = Content == null || Locked || ReadOnly;      
+      base.SetEnabledStateOfControls();
+
+      bool locked = Content == null || Locked || ReadOnly;
       bool parentOwner = selectedProject != null && HiveAdminClient.Instance.CheckOwnershipOfParentProject(selectedProject, UserInformation.Instance.User.Id);
-      bool selectedProjectDisabled = selectedProject == null 
+      bool selectedProjectDisabled = selectedProject == null
                                      || selectedProject != null && selectedProject.Id == Guid.Empty;
 
@@ -183,6 +183,5 @@
       if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshing, sender, e);
       else {
-        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
-        mainForm.AddOperationProgressToView(this, "Refreshing ...");
+        Progress.Show(this, "Refreshing ...", ProgressMode.Indeterminate);
         SetEnabledStateOfControls();
       }
@@ -192,6 +191,5 @@
       if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshed, sender, e);
       else {
-        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
-        mainForm.RemoveOperationProgressFromView(this);
+        Progress.Hide(this);
         SetEnabledStateOfControls();
       }
@@ -201,6 +199,5 @@
       if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshing, sender, e);
       else {
-        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
-        mainForm.AddOperationProgressToView(this, "Refreshing ...");
+        Progress.Show(this, "Refreshing ...", ProgressMode.Indeterminate);
         SetEnabledStateOfControls();
       }
@@ -210,6 +207,5 @@
       if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshed, sender, e);
       else {
-        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
-        mainForm.RemoveOperationProgressFromView(this);
+        Progress.Hide(this);
         SetEnabledStateOfControls();
       }
@@ -234,5 +230,5 @@
     }
 
-    private void addButton_Click(object sender, EventArgs e) {      
+    private void addButton_Click(object sender, EventArgs e) {
 
       if (selectedProject == null && !IsAdmin()) {
@@ -244,5 +240,5 @@
         return;
       }
-      
+
       if (selectedProject != null && selectedProject.Id == Guid.Empty) {
         MessageBox.Show(
@@ -256,7 +252,7 @@
       var project = new Project {
         Name = "New Project",
-        OwnerUserId = UserInformation.Instance.User.Id,        
+        OwnerUserId = UserInformation.Instance.User.Id,
       };
-      if(selectedProject != null) {
+      if (selectedProject != null) {
         project.ParentProjectId = selectedProject.Id;
         project.EndDate = selectedProject.EndDate;
@@ -285,5 +281,5 @@
         await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
           action: () => {
-            RemoveProject(selectedProject);  
+            RemoveProject(selectedProject);
           });
       }
@@ -304,5 +300,5 @@
           foreach (var project in projectsToSave)
             project.Store();
-          
+
           UpdateProjects();
         },
@@ -316,5 +312,5 @@
       if (node == null) return;
       var p = (Project)node.Tag;
-      if(!HiveAdminClient.Instance.DisabledParentProjects.Contains(p)) ChangeSelectedProjectNode(node);
+      if (!HiveAdminClient.Instance.DisabledParentProjects.Contains(p)) ChangeSelectedProjectNode(node);
     }
 
@@ -357,5 +353,5 @@
       if (targetNode == null) {
         treeView.Nodes.Add(sourceNode);
-      } else if(targetProject.Id != Guid.Empty) {
+      } else if (targetProject.Id != Guid.Empty) {
         targetNode.Nodes.Add(sourceNode);
         sourceProject.ParentProjectId = targetProject.Id;
@@ -422,5 +418,5 @@
         var newNode = new TreeNode(newProject.Name) { Tag = newProject };
         StyleTreeNode(newNode, newProject);
-      
+
         if (selectedProject == null && !disabledParentProjects.Contains(newProject)) {
           SelectedProject = newProject;
@@ -533,7 +529,7 @@
         if (project.Id != Guid.Empty) {
           SelectedProject = HiveAdminClient.Instance.GetAvailableProjectAncestors(project.Id).LastOrDefault();
-          HiveAdminClient.Delete(project);          
+          HiveAdminClient.Delete(project);
           UpdateProjects();
-        } else {          
+        } else {
           SelectedProject = Content.FirstOrDefault(x => x.Id == project.ParentProjectId);
           Content.Remove(project);
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs	(revision 16433)
@@ -185,6 +185,5 @@
       if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshing, sender, e);
       else {
-        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
-        mainForm.AddOperationProgressToView(this, "Refreshing ...");
+        Progress.Show(this, "Refreshing ...", ProgressMode.Indeterminate);
         SetEnabledStateOfControls();
       }
@@ -194,6 +193,5 @@
       if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshed, sender, e);
       else {
-        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
-        mainForm.RemoveOperationProgressFromView(this);
+        Progress.Hide(this);
         SetEnabledStateOfControls();
       }
@@ -203,6 +201,5 @@
       if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshing, sender, e);
       else {
-        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
-        mainForm.AddOperationProgressToView(this, "Refreshing ...");
+        Progress.Show(this, "Refreshing ...", ProgressMode.Indeterminate);
         SetEnabledStateOfControls();
       }
@@ -212,6 +209,5 @@
       if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshed, sender, e);
       else {
-        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
-        mainForm.RemoveOperationProgressFromView(this);
+        Progress.Hide(this);
         SetEnabledStateOfControls();
       }
@@ -247,5 +243,5 @@
     }
 
-    private async void btnRemoveGroup_Click(object sender, EventArgs e) {      
+    private async void btnRemoveGroup_Click(object sender, EventArgs e) {
       var nodes = GetCheckedNodes(treeView.Nodes).ToList();
       var checkedResources = nodes.Select(x => x.Tag).OfType<Resource>().ToList();
@@ -574,5 +570,5 @@
           foreach (var nr in newResources) Content.Remove(nr);
 
-          HiveAdminClient.Delete(resource);          
+          HiveAdminClient.Delete(resource);
           UpdateResources();
         } else {
@@ -588,10 +584,10 @@
       if (resources == null || !resources.Any()) return;
 
-      var ids = resources.Select(x => x.Id).ToList();      
+      var ids = resources.Select(x => x.Id).ToList();
       try {
         bool update = false;
-        foreach (var r in resources) {          
-          if (r.Id != Guid.Empty)  {
-            if(r.Id == SelectedResource.Id)
+        foreach (var r in resources) {
+          if (r.Id != Guid.Empty) {
+            if (r.Id == SelectedResource.Id)
               SelectedResource = HiveAdminClient.Instance.GetAvailableResourceAncestors(r.Id).LastOrDefault();
 
@@ -751,5 +747,5 @@
 
       foreach (var r in resources) {
-        if(!resourceDescendants.ContainsKey(r.Id))
+        if (!resourceDescendants.ContainsKey(r.Id))
           resourceDescendants.Add(r.Id, new HashSet<Resource>());
       }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/MenuItems/RunInHiveMenuItem.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/MenuItems/RunInHiveMenuItem.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/MenuItems/RunInHiveMenuItem.cs	(revision 16433)
@@ -99,5 +99,5 @@
           rJob.Job.ResourceIds = hiveResourceSelectorDialog.SelectedResources.Select(x => x.Id).ToList();
 
-          progress = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().AddOperationProgressToContent(this.content, "Uploading to Hive...");
+          progress = Progress.Show(this.content, "Uploading to Hive...", ProgressMode.Indeterminate);
           rJob.Progress = progress;
           progress.ProgressStateChanged += progress_ProgressStateChanged;
@@ -110,5 +110,5 @@
     private void progress_ProgressStateChanged(object sender, EventArgs e) {
       if (progress.ProgressState != ProgressState.Started) {
-        MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromContent(content);
+        Progress.Hide(content);
         progress.ProgressStateChanged -= progress_ProgressStateChanged;
       }
@@ -116,5 +116,5 @@
 
     private void HandleEx(Exception ex) {
-      MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromContent(content);
+      Progress.Hide(content);
       progress.ProgressStateChanged -= progress_ProgressStateChanged;
       ErrorHandling.ShowErrorDialog("Error uploading tasks", ex);
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.Designer.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.Designer.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.Designer.cs	(revision 16433)
@@ -19,4 +19,6 @@
  */
 #endregion
+
+using System.Windows.Forms;
 
 namespace HeuristicLab.Clients.Hive.JobManager.Views {
@@ -114,4 +116,5 @@
       this.toolTip.SetToolTip(this.searchTextBox, "Enter string to search for resources");
       this.searchTextBox.TextChanged += new System.EventHandler(this.searchTextBox_TextChanged);
+      this.searchTextBox.MouseDown += new MouseEventHandler(this.searchTextBox_MouseDown);
       // 
       // splitContainer2
@@ -146,4 +149,5 @@
       this.projectsTreeView.Size = new System.Drawing.Size(204, 410);
       this.projectsTreeView.TabIndex = 3;
+      this.projectsTreeView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.projectsTreeView_MouseDown);
       this.projectsTreeView.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.projectsTreeView_MouseDoubleClick);
       this.projectsTreeView.BeforeSelect += new System.Windows.Forms.TreeViewCancelEventHandler(this.projectsTreeView_BeforeSelect);
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.cs	(revision 16433)
@@ -145,5 +145,5 @@
         selectedProject = value;
 
-        UpdateResourceTree();
+        UpdateResourceTree();                
         ExtractStatistics();
         OnSelectedProjectChanged();
@@ -223,4 +223,14 @@
       //UpdateFilteredTree();
       UpdateProjectTree();
+    }
+
+    private void searchTextBox_MouseDown(object sender, MouseEventArgs e) {
+      resourcesTreeView.SelectedNode = null;
+      ExtractStatistics();
+    }
+
+    private void projectsTreeView_MouseDown(object sender, MouseEventArgs e) {
+      resourcesTreeView.SelectedNode = null;
+      ExtractStatistics();
     }
 
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.cs	(revision 16433)
@@ -96,6 +96,5 @@
       if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveClient_Instance_Refreshing, sender, e);
       else {
-        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
-        mainForm.AddOperationProgressToView(this, "Refreshing ...");
+        Progress.ShowOnControl(this, "Refreshing", ProgressMode.Indeterminate);
         refreshButton.Enabled = false;
       }
@@ -105,6 +104,5 @@
       if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveClient_Instance_Refreshed, sender, e);
       else {
-        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
-        mainForm.RemoveOperationProgressFromView(this);
+        Progress.HideFromControl(this);
         refreshButton.Enabled = true;
       }
@@ -140,7 +138,7 @@
       okButton.Enabled = hiveResourceSelector.AssignedResources.Any();
 
-      if(!hiveResourceSelector.AssignedResources.Any()) {
+      if (!hiveResourceSelector.AssignedResources.Any()) {
         errorProvider.SetError(okButton, "Note: currently no resources are assigned");
-      } else if(hiveResourceSelector.AssignedCores == 0) {
+      } else if (hiveResourceSelector.AssignedCores == 0) {
         errorProvider.SetError(okButton, "Note: currently no resources with cores are assigned");
       } else {
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobListView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobListView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobListView.cs	(revision 16433)
@@ -47,5 +47,5 @@
       this.itemsListView.FullRowSelect = true;
 
-      this.itemsListView.ListViewItemSorter = new ListViewItemComparer(new int[] { 2, 0 }, new SortOrder[] { SortOrder.Ascending, SortOrder.Ascending });      
+      this.itemsListView.ListViewItemSorter = new ListViewItemComparer(new int[] { 2, 0 }, new SortOrder[] { SortOrder.Ascending, SortOrder.Ascending });
 
       foreach (ColumnHeader c in this.itemsListView.Columns) {
@@ -53,5 +53,5 @@
         int w = c.Width;
         c.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
-        if(w > c.Width) {
+        if (w > c.Width) {
           c.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);
         }
@@ -120,5 +120,5 @@
 
         task.ContinueWith((t) => {
-          MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this);
+          Progress.Hide(this);
           ErrorHandling.ShowErrorDialog("An error occured while deleting the job. ", t.Exception);
         }, TaskContinuationOptions.OnlyOnFaulted);
@@ -131,9 +131,9 @@
 
     private void DeleteHiveJobsAsync(object items) {
-      MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().AddOperationProgressToView(this, "Deleting job...");
+      Progress.Show(this, "Deleting job...", ProgressMode.Indeterminate);
       foreach (RefreshableJob item in (List<RefreshableJob>)items) {
         Content.Remove(item);
       }
-      MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this);
+      Progress.Hide(this);
     }
 
@@ -197,5 +197,5 @@
       listViewItem.SubItems.Insert(1, new ListViewItem.ListViewSubItem(listViewItem, item.Job.Name));
       listViewItem.SubItems.Insert(2, new ListViewItem.ListViewSubItem(listViewItem, HiveClient.Instance.GetProjectAncestry(item.Job.ProjectId)));
-      
+
       listViewItem.Group = GetListViewGroup(item.Job.OwnerUsername);
       return listViewItem;
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.cs	(revision 16433)
@@ -75,5 +75,5 @@
       Content.Loaded += new EventHandler(Content_Loaded);
       Content.TaskReceived += new EventHandler(Content_TaskReceived);
-      MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().AddOperationProgressToView(this, Content.Progress);
+      Progress.Show(this, Content.Progress);
     }
 
@@ -90,5 +90,5 @@
       Content.Loaded -= new EventHandler(Content_Loaded);
       Content.TaskReceived -= new EventHandler(Content_TaskReceived);
-      MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this, false);
+      Progress.Hide(this, false);
       DeregisterHiveExperimentEvents();
       DeregisterHiveTasksEvents();
@@ -133,6 +133,6 @@
           stateLogViewHost.Content = null;
         } else {
-          if(Content.Job != null 
-            && Content.Job.Id != Guid.Empty 
+          if (Content.Job != null
+            && Content.Job.Id != Guid.Empty
             && !originalJobProjectAssignment.ContainsKey(Content.Job.Id)) {
             originalJobProjectAssignment.Add(Content.Job.Id, Content.Job.ProjectId);
@@ -159,5 +159,5 @@
                 projectNameTextBox.Text = HiveClient.Instance.GetProjectAncestry(Content.Job.ProjectId);
                 projectNameTextBox.Text += "   (" + (cores.HasValue ? cores.Value.ToString() : "0") + " cores)";
-              }                
+              }
             }
           } else if (Content.Job != null && Content.Job.ProjectId != Guid.Empty) {
@@ -167,5 +167,5 @@
             }
 
-            if(hiveResourceSelectorDialog == null)
+            if (hiveResourceSelectorDialog == null)
               hiveResourceSelectorDialog = new HiveResourceSelectorDialog(Content.Job.Id, Content.Job.ProjectId);
 
@@ -203,5 +203,5 @@
           executionTimeTextBox.Text = Content.ExecutionTime.ToString();
           refreshAutomaticallyCheckBox.Checked = Content.RefreshAutomatically;
-          
+
           logView.Content = Content.Log;
           lock (runCollectionViewLocker) {
@@ -408,5 +408,5 @@
       if (hiveResourceSelectorDialog == null) {
         hiveResourceSelectorDialog = new HiveResourceSelectorDialog(Content.Job.Id, Content.Job.ProjectId);
-      } else if(hiveResourceSelectorDialog.JobId != Content.Job.Id) {
+      } else if (hiveResourceSelectorDialog.JobId != Content.Job.Id) {
         hiveResourceSelectorDialog.JobId = Content.Job.Id;
         hiveResourceSelectorDialog.SelectedProjectId = Content.Job.ProjectId;
@@ -418,5 +418,5 @@
           hiveResourceSelectorDialog.ProjectId = Guid.Empty;
         }
-      } else if(hiveResourceSelectorDialog.JobId == Guid.Empty && Content.Job.Id == Guid.Empty) {
+      } else if (hiveResourceSelectorDialog.JobId == Guid.Empty && Content.Job.Id == Guid.Empty) {
         hiveResourceSelectorDialog.JobId = Content.Job.Id;
         hiveResourceSelectorDialog.ProjectId = Guid.Empty;
@@ -430,5 +430,5 @@
       if (hiveResourceSelectorDialog.ShowDialog(this) == DialogResult.OK) {
         selectedProject = hiveResourceSelectorDialog.SelectedProject;
-        if(selectedProject != null) {       
+        if (selectedProject != null) {
           Content.Job.ProjectId = selectedProject.Id;
           Content.Job.ResourceIds = hiveResourceSelectorDialog.SelectedResources.Select(x => x.Id).ToList();
@@ -493,5 +493,5 @@
 
     private void PauseJobAsync(object job) {
-      Content.Progress.Start("Pausing job...");
+      Content.Progress.Start("Pausing job...", ProgressMode.Indeterminate);
       HiveClient.PauseJob((RefreshableJob)job);
       Content.Progress.Finish();
@@ -499,5 +499,5 @@
 
     private void StopJobAsync(object job) {
-      Content.Progress.Start("Stopping job...");
+      Content.Progress.Start("Stopping job...", ProgressMode.Indeterminate);
       HiveClient.StopJob((RefreshableJob)job);
       Content.Progress.Finish();
@@ -505,5 +505,5 @@
 
     private void ResumeJobAsync(object job) {
-      Content.Progress.Start("Resuming job...");
+      Content.Progress.Start("Resuming job...", ProgressMode.Indeterminate);
       HiveClient.ResumeJob((RefreshableJob)job);
       Content.Progress.Finish();
@@ -582,6 +582,6 @@
         startButton.Enabled = pauseButton.Enabled = stopButton.Enabled = false;
       } else {
-        startButton.Enabled = Content.IsControllable && Content.HiveTasks != null && Content.HiveTasks.Count > 0 
-          && Content.Job.ProjectId != Guid.Empty && Content.Job.ResourceIds != null  && Content.Job.ResourceIds.Any() 
+        startButton.Enabled = Content.IsControllable && Content.HiveTasks != null && Content.HiveTasks.Count > 0
+          && Content.Job.ProjectId != Guid.Empty && Content.Job.ResourceIds != null && Content.Job.ResourceIds.Any()
           && (Content.ExecutionState == ExecutionState.Prepared || Content.ExecutionState == ExecutionState.Paused) && !Content.IsProgressing;
         pauseButton.Enabled = Content.IsControllable && Content.ExecutionState == ExecutionState.Started && !Content.IsProgressing;
@@ -589,5 +589,5 @@
       }
     }
-   
+
     private Project GetProject(Guid projectId) {
       return HiveServiceLocator.Instance.CallHiveService(s => s.GetProject(projectId));
@@ -595,5 +595,5 @@
 
     private void UpdateSelectorDialog() {
-      if(hiveResourceSelectorDialog != null) {
+      if (hiveResourceSelectorDialog != null) {
         hiveResourceSelectorDialog = null;
         //hiveResourceSelectorDialog.JobId = Content.Job.Id;
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Views/3.3/HiveTasks/OptimizerHiveTaskView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Views/3.3/HiveTasks/OptimizerHiveTaskView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Views/3.3/HiveTasks/OptimizerHiveTaskView.cs	(revision 16433)
@@ -46,5 +46,5 @@
     protected override void Job_ItemChanged(object sender, EventArgs e) {
       if (Content != null && Content.Task != null && Content.ItemTask.Item != null) {
-        Content.ExecuteReadActionOnItemTask(new Action(delegate() {
+        Content.ExecuteReadActionOnItemTask(new Action(delegate () {
           runCollectionViewHost.Content = Content.ItemTask.Item.Runs;
         }));
@@ -58,10 +58,10 @@
       base.RegisterContentEvents();
       Content.IsControllableChanged += new EventHandler(Content_IsControllableChanged);
-      MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().AddOperationProgressToView(this, Content.Progress);
+      Progress.Show(this, Content.Progress);
     }
 
     protected override void DeregisterContentEvents() {
       Content.IsControllableChanged -= new EventHandler(Content_IsControllableChanged);
-      MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this, false);
+      Progress.Hide(this, false);
       base.DeregisterContentEvents();
     }
@@ -99,5 +99,5 @@
 
     private void PauseTaskAsync() {
-      Content.Progress.Start("Pausing task. Please be patient for the command to take effect.");
+      Content.Progress.Start("Pausing task. Please be patient for the command to take effect.", ProgressMode.Indeterminate);
       Content.Pause();
       Content.Progress.Finish();
@@ -105,5 +105,5 @@
 
     private void StopTaskAsync() {
-      Content.Progress.Start("Stopping task. Please be patient for the command to take effect.");
+      Content.Progress.Start("Stopping task. Please be patient for the command to take effect.", ProgressMode.Indeterminate);
       Content.Stop();
       Content.Progress.Finish();
@@ -111,5 +111,5 @@
 
     private void ResumeTaskAsync() {
-      Content.Progress.Start("Resuming task. Please be patient for the command to take effect.");
+      Content.Progress.Start("Resuming task. Please be patient for the command to take effect.", ProgressMode.Indeterminate);
       Content.Restart();
       Content.Progress.Finish();
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive/3.3/HeuristicLab.Clients.Hive-3.3.csproj
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive/3.3/HeuristicLab.Clients.Hive-3.3.csproj	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive/3.3/HeuristicLab.Clients.Hive-3.3.csproj	(revision 16433)
@@ -236,4 +236,9 @@
       <Private>False</Private>
     </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.MainForm.WindowsForms\3.3\HeuristicLab.MainForm.WindowsForms-3.3.csproj">
+      <Project>{AB687BBE-1BFE-476B-906D-44237135431D}</Project>
+      <Name>HeuristicLab.MainForm.WindowsForms-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.MainForm\3.3\HeuristicLab.MainForm-3.3.csproj">
       <Project>{3BD61258-31DA-4B09-89C0-4F71FEF5F05A}</Project>
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive/3.3/HiveClient.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 16433)
@@ -167,12 +167,10 @@
         RefreshDisabledParentProjects();
         RefreshDisabledParentResources();
-      }
-      catch {
+      } catch {
         jobs = null;
         projects = null;
         resources = null;
         throw;
-      }
-      finally {
+      } finally {
         OnRefreshed();
       }
@@ -215,14 +213,13 @@
 
     public void RefreshAsync(Action<Exception> exceptionCallback) {
-      var call = new Func<Exception>(delegate() {
+      var call = new Func<Exception>(delegate () {
         try {
           Refresh();
-        }
-        catch (Exception ex) {
+        } catch (Exception ex) {
           return ex;
         }
         return null;
       });
-      call.BeginInvoke(delegate(IAsyncResult result) {
+      call.BeginInvoke(delegate (IAsyncResult result) {
         Exception ex = call.EndInvoke(result);
         if (ex != null) exceptionCallback(ex);
@@ -244,5 +241,5 @@
       resourceAncestors.Keys.ToList().ForEach(k => resourceDescendants.Add(k, new HashSet<Guid>()));
       foreach (var ra in resourceAncestors) {
-        foreach(var ancestor in ra.Value) {
+        foreach (var ancestor in ra.Value) {
           resourceDescendants[ancestor].Add(ra.Key);
         }
@@ -263,6 +260,6 @@
       // build project descendant list
       projectAncestors.Keys.ToList().ForEach(k => projectDescendants.Add(k, new HashSet<Guid>()));
-      foreach(var pa in projectAncestors) {
-        foreach(var ancestor in pa.Value) {
+      foreach (var pa in projectAncestors) {
+        foreach (var ancestor in pa.Value) {
           projectDescendants[ancestor].Add(pa.Key);
         }
@@ -362,14 +359,13 @@
     }
     public static void StoreAsync(Action<Exception> exceptionCallback, IHiveItem item, CancellationToken cancellationToken) {
-      var call = new Func<Exception>(delegate() {
+      var call = new Func<Exception>(delegate () {
         try {
           Store(item, cancellationToken);
-        }
-        catch (Exception ex) {
+        } catch (Exception ex) {
           return ex;
         }
         return null;
       });
-      call.BeginInvoke(delegate(IAsyncResult result) {
+      call.BeginInvoke(delegate (IAsyncResult result) {
         Exception ex = call.EndInvoke(result);
         if (ex != null) exceptionCallback(ex);
@@ -460,5 +456,5 @@
     public static void UpdateJob(Action<Exception> exceptionCallback, RefreshableJob refreshableJob, CancellationToken cancellationToken) {
       refreshableJob.IsProgressing = true;
-      refreshableJob.Progress.Status = "Saving Job...";
+      refreshableJob.Progress.Message = "Saving Job...";
       HiveClient.StoreAsync(
         new Action<Exception>((Exception ex) => {
@@ -473,5 +469,5 @@
 
       try {
-        refreshableJob.Progress.Start("Saving Job...");
+        refreshableJob.Progress.Start("Saving Job...", ProgressMode.Indeterminate);
         HiveClient.StoreAsync(new Action<Exception>((Exception ex) => {
           throw new Exception("Update failed.", ex);
@@ -492,5 +488,5 @@
       try {
         refreshableJob.IsProgressing = true;
-        refreshableJob.Progress.Start("Connecting to server...");
+        refreshableJob.Progress.Start("Connecting to server...", ProgressMode.Indeterminate);
 
         foreach (OptimizerHiveTask hiveJob in refreshableJob.HiveTasks.OfType<OptimizerHiveTask>()) {
@@ -499,5 +495,5 @@
 
         // upload Job
-        refreshableJob.Progress.Status = "Uploading Job...";
+        refreshableJob.Progress.Message = "Uploading Job...";
         refreshableJob.Job.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddJob(refreshableJob.Job, refreshableJob.Job.ResourceIds));
         refreshableJob.Job = HiveServiceLocator.Instance.CallHiveService((s) => s.GetJob(refreshableJob.Job.Id)); // update owner and permissions
@@ -509,5 +505,5 @@
 
         // upload plugins
-        refreshableJob.Progress.Status = "Uploading plugins...";
+        refreshableJob.Progress.Message = "Uploading plugins...";
         this.OnlinePlugins = HiveServiceLocator.Instance.CallHiveService((s) => s.GetPlugins());
         this.AlreadyUploadedPlugins = new List<Plugin>();
@@ -517,5 +513,7 @@
 
         // upload tasks
-        refreshableJob.Progress.Status = "Uploading tasks...";
+        refreshableJob.Progress.Message = "Uploading tasks...";
+        refreshableJob.Progress.ProgressMode = ProgressMode.Determinate;
+        refreshableJob.Progress.ProgressValue = 0;
 
         var tasks = new List<TS.Task>();
@@ -528,6 +526,5 @@
         }
         TS.Task.WaitAll(tasks.ToArray());
-      }
-      finally {
+      } finally {
         refreshableJob.Job.Modified = false;
         refreshableJob.IsProgressing = false;
@@ -615,5 +612,5 @@
         lock (jobCountLocker) {
           progress.ProgressValue = (double)taskCount[0] / totalJobCount;
-          progress.Status = string.Format("Uploaded task ({0} of {1})", taskCount[0], totalJobCount);
+          progress.Message = string.Format("Uploaded task ({0} of {1})", taskCount[0], totalJobCount);
         }
 
@@ -646,9 +643,11 @@
 
         // fetch all task objects to create the full tree of tree of HiveTask objects
-        refreshableJob.Progress.Start("Downloading list of tasks...");
+        refreshableJob.Progress.Start("Downloading list of tasks...", ProgressMode.Indeterminate);
         allTasks = HiveServiceLocator.Instance.CallHiveService(s => s.GetLightweightJobTasksWithoutStateLog(hiveExperiment.Id));
         totalJobCount = allTasks.Count();
 
-        refreshableJob.Progress.Status = "Downloading tasks...";
+        refreshableJob.Progress.Message = "Downloading tasks...";
+        refreshableJob.Progress.ProgressMode = ProgressMode.Determinate;
+        refreshableJob.Progress.ProgressValue = 0.0;
         downloader = new TaskDownloader(allTasks.Select(x => x.Id));
         downloader.StartAsync();
@@ -656,5 +655,5 @@
         while (!downloader.IsFinished) {
           refreshableJob.Progress.ProgressValue = downloader.FinishedCount / (double)totalJobCount;
-          refreshableJob.Progress.Status = string.Format("Downloading/deserializing tasks... ({0}/{1} finished)", downloader.FinishedCount, totalJobCount);
+          refreshableJob.Progress.Message = string.Format("Downloading/deserializing tasks... ({0}/{1} finished)", downloader.FinishedCount, totalJobCount);
           Thread.Sleep(500);
 
@@ -666,5 +665,7 @@
         var parents = allHiveTasks.Values.Where(x => !x.Task.ParentTaskId.HasValue);
 
-        refreshableJob.Progress.Status = "Downloading/deserializing complete. Displaying tasks...";
+        refreshableJob.Progress.Message = "Downloading/deserializing complete. Displaying tasks...";
+        refreshableJob.Progress.ProgressMode = ProgressMode.Indeterminate;
+
         // build child-task tree
         foreach (HiveTask hiveTask in parents) {
@@ -677,10 +678,9 @@
         } else if (refreshableJob.IsPaused()) {
           refreshableJob.ExecutionState = Core.ExecutionState.Paused;
-        } else { 
+        } else {
           refreshableJob.ExecutionState = Core.ExecutionState.Started;
         }
         refreshableJob.OnLoaded();
-      }
-      finally {
+      } finally {
         refreshableJob.IsProgressing = false;
         refreshableJob.Progress.Finish();
@@ -719,6 +719,5 @@
       try {
         return PersistenceUtil.Deserialize<ItemTask>(taskData.Data);
-      }
-      catch {
+      } catch {
         return null;
       }
@@ -731,6 +730,5 @@
     public static void TryAndRepeat(Action action, int repetitions, string errorMessage, ILog log = null) {
       while (true) {
-        try { action(); return; }
-        catch (Exception e) {
+        try { action(); return; } catch (Exception e) {
           if (repetitions == 0) throw new HiveException(errorMessage, e);
           if (log != null) log.LogMessage(string.Format("{0}: {1} - will try again!", errorMessage, e.ToString()));
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive/3.3/Plugin.cs.frame
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive/3.3/Plugin.cs.frame	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive/3.3/Plugin.cs.frame	(revision 16433)
@@ -37,4 +37,5 @@
   [PluginDependency("HeuristicLab.Hive", "3.3")]  
   [PluginDependency("HeuristicLab.MainForm", "3.3")]
+  [PluginDependency("HeuristicLab.MainForm.WindowsForms", "3.3")]
   [PluginDependency("HeuristicLab.Optimization", "3.3")]
   [PluginDependency("HeuristicLab.Persistence", "3.3")]
Index: /branches/2965_CancelablePersistence/HeuristicLab.Clients.OKB.Views/3.3/RunCreation/Views/OKBExperimentUploadView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Clients.OKB.Views/3.3/RunCreation/Views/OKBExperimentUploadView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Clients.OKB.Views/3.3/RunCreation/Views/OKBExperimentUploadView.cs	(revision 16433)
@@ -188,5 +188,5 @@
       if (InvokeRequired) { Invoke((Action<object, EventArgs>)RunCreationClient_Refreshing, sender, e); return; }
       var message = "Refreshing algorithms and problems...";
-      MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().AddOperationProgressToView(this, message);
+      Progress.Show(this, message, ProgressMode.Indeterminate);
       refreshing = true;
       SetEnabledStateOfControls();
@@ -195,5 +195,5 @@
     private void RunCreationClient_Refreshed(object sender, EventArgs e) {
       if (InvokeRequired) { Invoke((Action<object, EventArgs>)RunCreationClient_Refreshed, sender, e); return; }
-      MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this);
+      Progress.Hide(this);
       refreshing = false;
       SetEnabledStateOfControls();
@@ -203,5 +203,5 @@
       var task = System.Threading.Tasks.Task.Factory.StartNew(UploadAsync);
       task.ContinueWith((t) => {
-        MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this);
+        Progress.Hide(this);
         PluginInfrastructure.ErrorHandling.ShowErrorDialog("An exception occured while uploading the runs to the OKB.", t.Exception);
       }, TaskContinuationOptions.OnlyOnFaulted);
@@ -210,5 +210,5 @@
     private void UploadAsync() {
       var message = "Uploading runs to OKB...";
-      IProgress progress = MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().AddOperationProgressToView(this, message);
+      IProgress progress = Progress.Show(this, message);
       double count = dataGridView.Rows.Count;
       int i = 0;
@@ -226,5 +226,5 @@
         progress.ProgressValue = ((double)i) / count;
       }
-      MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this);
+      Progress.Hide(this);
       ClearRuns();
     }
Index: /branches/2965_CancelablePersistence/HeuristicLab.DataPreprocessing.Views/3.4/DataPreprocessingView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.DataPreprocessing.Views/3.4/DataPreprocessingView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.DataPreprocessing.Views/3.4/DataPreprocessingView.cs	(revision 16433)
@@ -165,11 +165,8 @@
         await Task.Run(() => {
           TProblemData instance;
-          var mainForm = (MainForm.WindowsForms.MainForm)MainFormManager.MainForm;
           // lock active view and show progress bar
-          var activeView = (IContentView)MainFormManager.MainForm.ActiveView;
 
           try {
-            var progress = mainForm.AddOperationProgressToContent(activeView.Content, "Loading problem instance.");
-
+            var progress = Progress.Show(Content, "Loading problem instance.");
             instanceProvider.ProgressChanged += (o, args) => { progress.ProgressValue = args.ProgressPercentage / 100.0; };
 
@@ -177,5 +174,5 @@
           } catch (IOException ex) {
             MessageBox.Show(string.Format("There was an error parsing the file: {0}", Environment.NewLine + ex.Message), "Error while parsing", MessageBoxButtons.OK, MessageBoxIcon.Error);
-            mainForm.RemoveOperationProgressFromContent(activeView.Content);
+            Progress.Hide(Content);
             return;
           }
@@ -185,5 +182,5 @@
             MessageBox.Show(string.Format("This problem does not support loading the instance {0}: {1}", Path.GetFileName(importDialog.Path), Environment.NewLine + ex.Message), "Cannot load instance");
           } finally {
-            mainForm.RemoveOperationProgressFromContent(activeView.Content);
+            Progress.Hide(Content);
           }
         });
@@ -222,11 +219,9 @@
           var storable = itemCreator() as IStorableContent;
           if (storable != null) {
-            var mainForm = (MainForm.WindowsForms.MainForm)MainFormManager.MainForm;
-            var activeView = (IContentView)MainFormManager.MainForm.ActiveView;
             try {
-              mainForm.AddOperationProgressToContent(activeView.Content, "Exporting data.");
+              Progress.Show(Content, "Exporting data.", ProgressMode.Indeterminate);
               ContentManager.Save(storable, saveFileDialog.FileName, compressed);
             } finally {
-              mainForm.RemoveOperationProgressFromContent(activeView.Content);
+              Progress.Hide(Content);
             }
           }
@@ -244,9 +239,7 @@
       if (saveFileDialog.ShowDialog() == DialogResult.OK) {
         Task.Run(() => {
-          var mainForm = (MainForm.WindowsForms.MainForm)MainFormManager.MainForm;
-          var activeView = (IContentView)MainFormManager.MainForm.ActiveView;
           try {
             var problemData = Content.CreateNewProblemData();
-            mainForm.AddOperationProgressToContent(activeView.Content, "Exporting data.");
+            Progress.Show(Content, "Exporting data.", ProgressMode.Indeterminate);
             if (problemData is TimeSeriesPrognosisProblemData)
               Export(new TimeSeriesPrognosisCSVInstanceProvider(), problemData, saveFileDialog.FileName);
@@ -256,5 +249,5 @@
               Export(new ClassificationCSVInstanceProvider(), problemData, saveFileDialog.FileName);
           } finally {
-            mainForm.RemoveOperationProgressFromContent(activeView.Content);
+            Progress.Hide(Content);
           }
         });
Index: /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/HeuristicLab.NativeInterpreter-0.1/DllImporter.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/HeuristicLab.NativeInterpreter-0.1/DllImporter.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/HeuristicLab.NativeInterpreter-0.1/DllImporter.cs	(revision 16433)
@@ -15,5 +15,5 @@
   }
 
-  public class NativeWrapper {
+  public static class NativeWrapper {
     private const string x86dll = "hl-native-interpreter-msvc-x86.dll";
     private const string x64dll = "hl-native-interpreter-msvc-x64.dll";
Index: /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/CMakeLists.txt
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/CMakeLists.txt	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/CMakeLists.txt	(revision 16433)
@@ -17,6 +17,6 @@
 
 if(MSVC)
-    target_compile_options(hl-native-interpreter PRIVATE "/W4" "/Qvec-report:2" "$<$<CONFIG:Release>:/O2>")
-    target_compile_options(hl-native-interpreter-vdt PRIVATE "/W4" "/Qvec-report:2" "$<$<CONFIG:Release>:/O2>")
+    target_compile_options(hl-native-interpreter PRIVATE "/W4" "/Qvec-report:2" "/MT" "$<$<CONFIG:Release>:/O2>")
+    target_compile_options(hl-native-interpreter-vdt PRIVATE "/W4" "/Qvec-report:2" "/MT" "$<$<CONFIG:Release>:/O2>")
     target_compile_definitions(hl-native-interpreter-vdt PRIVATE "USE_VDT")
 else()
Index: /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/README.md
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/README.md	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/README.md	(revision 16433)
@@ -11,5 +11,5 @@
 - Visual Studio
 
-    `cmake -G "Microsoft Visual Studio 15 2017 [arch]" <path-to-repository>`. Leave `arch` empty for x86 or `Win64` for x64. 
+    `cmake -G "Visual Studio 15 2017 [arch]" <path-to-repository>`. Leave `arch` empty for x86 or `Win64` for x64. 
     
     `cmake --build . --config Release`
Index: /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/instruction.h
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/instruction.h	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/instruction.h	(revision 16433)
@@ -23,5 +23,9 @@
     Root = 23,
     Square = 28,
-    Sqrt = 29
+    Sqrt = 29,
+    Absolute = 48,
+    AnalyticalQuotient = 49,
+    Cube = 50,
+    CubeRoot = 51
 };
 
Index: /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/interpreter.cpp
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/interpreter.cpp	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/interpreter.cpp	(revision 16433)
@@ -50,9 +50,6 @@
     if (remainingRows > 0) 
     {
-        for (int rowIndex = total; rowIndex < totalRows; rowIndex += remainingRows)
-        {
-            evaluate(code, codeLength, rows, rowIndex, remainingRows);
-            std::memcpy(result + rowIndex, code[0].buf, remainingRows * sizeof(double));
-        }
+        evaluate(code, codeLength, rows, total, remainingRows);
+        std::memcpy(result + total, code[0].buf, remainingRows * sizeof(double));
     }
     _aligned_free(buffer);
Index: /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/interpreter.h
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/interpreter.h	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/interpreter.h	(revision 16433)
@@ -12,4 +12,5 @@
         switch (in.opcode)
         {
+            case OpCodes::Const: /* nothing to do */ break;
             case OpCodes::Var:
                 {
@@ -102,7 +103,35 @@
             case OpCodes::Sqrt:
                 {
-                    in.value = std::sqrt(code[in.childIndex].value);
-                    break;
-                }
+                    in.value = std::pow(code[in.childIndex].value, 1./2.);
+                    break;
+                }
+            case OpCodes::Square:
+                {
+                    in.value = std::pow(code[in.childIndex].value, 2.);
+                    break;
+                }
+            case OpCodes::CubeRoot:
+                {
+                    in.value = std::pow(code[in.childIndex].value, 1./3.);
+                    break;
+                }
+            case OpCodes::Cube:
+                {
+                    in.value = std::pow(code[in.childIndex].value, 3.);
+                    break;
+                }
+            case OpCodes::Absolute:
+                {
+                    in.value = std::fabs(code[in.childIndex].value);
+                    break;
+                }
+            case OpCodes::AnalyticalQuotient:
+                {
+                    double x = code[in.childIndex].value;
+                    double y = code[in.childIndex + 1].value;
+                    in.value = x / std::sqrt(1 + y*y);
+                    break;
+                }
+            default: in.value = NAN;
         }
     }
@@ -131,4 +160,5 @@
                     break;
                 }
+            case OpCodes::Const: /* nothing to do because buffers for constants are already set */ break;
             case OpCodes::Add:
                 {
@@ -222,8 +252,35 @@
             case OpCodes::Square:
                 {
-                    square(in.buf, code[in.childIndex].buf);
-                    break;
-                }
-        }
+                    pow(in.buf, code[in.childIndex].buf, 2.);
+                    break;
+                }
+            case OpCodes::Sqrt:
+                {
+                    pow(in.buf, code[in.childIndex].buf, 1./2.);
+                    break;
+                }
+            case OpCodes::CubeRoot:
+                {
+                    pow(in.buf, code[in.childIndex].buf, 1./3.);
+                    break;
+                }
+            case OpCodes::Cube:
+                {
+                    pow(in.buf, code[in.childIndex].buf, 3.);
+                    break;
+                }
+            case OpCodes::Absolute:
+                {
+                    abs(in.buf, code[in.childIndex].buf);
+                    break;
+                }
+            case OpCodes::AnalyticalQuotient:
+                {
+                    load(in.buf, code[in.childIndex].buf);
+                    analytical_quotient(in.buf, code[in.childIndex + 1].buf);
+                    break;
+                }
+            default: load(in.buf, NAN);
+            }
     }
 }
Index: /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/vector_operations.h
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/vector_operations.h	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/vector_operations.h	(revision 16433)
@@ -53,4 +53,6 @@
 inline void inv(double* __restrict a, double const * __restrict b) noexcept { FOR(i) a[i] = 1. / b[i]; }
 inline void neg(double* __restrict a, double const * __restrict b) noexcept { FOR(i) a[i] = -b[i]; }
+inline void abs(double* __restrict a, double const * __restrict b) noexcept { FOR(i) a[i] = std::fabs(b[i]); }
+inline void analytical_quotient(double* __restrict a, double const * __restrict b) noexcept { FOR(i) a[i] /= hl_sqrt(b[i]*b[i] + 1.); }
 
 // vector - scalar operations
@@ -60,4 +62,5 @@
 inline void mul(double* __restrict a, double s) noexcept { FOR(i) a[i] *= s; }
 inline void div(double* __restrict a, double s) noexcept { FOR(i) a[i] /= s; }
+inline void pow(double* __restrict dst, double const * __restrict src, double s) noexcept { FOR(i) dst[i] = hl_pow(src[i], s); }
 
 // vector operations
@@ -68,5 +71,4 @@
 inline void sin(double* __restrict a) noexcept { FOR(i) a[i] = hl_sin(a[i]); }
 inline void cos(double* __restrict a) noexcept { FOR(i) a[i] = hl_cos(a[i]); }
-inline void sqrt(double* __restrict a) noexcept { FOR(i) a[i] = hl_sqrt(a[i]); }
 inline void round(double* __restrict a) noexcept { FOR(i) a[i] = hl_round(a[i]); }
 inline void square(double* __restrict a) noexcept { FOR(i) a[i] = hl_pow(a[i], 2.); }
Index: /branches/2965_CancelablePersistence/HeuristicLab.MainForm.WindowsForms/3.3/Controls/ProgressView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.MainForm.WindowsForms/3.3/Controls/ProgressView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.MainForm.WindowsForms/3.3/Controls/ProgressView.cs	(revision 16433)
@@ -25,7 +25,4 @@
 namespace HeuristicLab.MainForm.WindowsForms {
   internal sealed partial class ProgressView : UserControl {
-    private const int defaultControlHeight = 88;
-    private const int collapsedControlHeight = 55;
-
     private readonly Control control;
     public Control Control {
@@ -40,19 +37,16 @@
     public ProgressView(Control control, IProgress content)
       : base() {
-      if (control == null) throw new ArgumentNullException("control", "The control is null.");
-      if (content == null) throw new ArgumentNullException("content", "The passed progress is null.");
+      if (control == null) throw new ArgumentNullException("control");
+      if (content == null) throw new ArgumentNullException("content");
       InitializeComponent();
 
       this.control = control;
       this.content = content;
-      if (content.ProgressState == ProgressState.Started)
+
+      if (content.ProgressState != ProgressState.Finished)
         ShowProgress();
       RegisterContentEvents();
     }
 
-    /// <summary> 
-    /// Clean up any resources being used.
-    /// </summary>
-    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
     protected override void Dispose(bool disposing) {
       DeregisterContentEvents();
@@ -66,14 +60,41 @@
 
     private void RegisterContentEvents() {
-      content.StatusChanged += new EventHandler(progress_StatusChanged);
-      content.ProgressValueChanged += new EventHandler(progress_ProgressValueChanged);
-      content.ProgressStateChanged += new EventHandler(Content_ProgressStateChanged);
-      content.CanBeCanceledChanged += new EventHandler(Content_CanBeCanceledChanged);
+      Content.ProgressStateChanged += new EventHandler(Content_ProgressStateChanged);
+      Content.MessageChanged += new EventHandler(Content_MessageChanged);
+      Content.ProgressBarModeChanged += new EventHandler(Content_ProgressBarModeChanged);
+      Content.ProgressValueChanged += new EventHandler(Content_ProgressValueChanged);
+      Content.CanBeStoppedChanged += new EventHandler(Content_CanBeStoppedChanged);
+      Content.CanBeCanceledChanged += new EventHandler(Content_CanBeCanceledChanged);
     }
     private void DeregisterContentEvents() {
-      content.StatusChanged -= new EventHandler(progress_StatusChanged);
-      content.ProgressValueChanged -= new EventHandler(progress_ProgressValueChanged);
-      content.ProgressStateChanged -= new EventHandler(Content_ProgressStateChanged);
-      content.CanBeCanceledChanged -= new EventHandler(Content_CanBeCanceledChanged);
+      Content.ProgressStateChanged -= new EventHandler(Content_ProgressStateChanged);
+      Content.MessageChanged -= new EventHandler(Content_MessageChanged);
+      Content.ProgressBarModeChanged -= new EventHandler(Content_ProgressBarModeChanged);
+      Content.ProgressValueChanged -= new EventHandler(Content_ProgressValueChanged);
+      Content.CanBeStoppedChanged -= new EventHandler(Content_CanBeStoppedChanged);
+      Content.CanBeCanceledChanged -= new EventHandler(Content_CanBeCanceledChanged);
+    }
+
+    private void Content_ProgressStateChanged(object sender, EventArgs e) {
+      UpdateProgressState();
+      UpdateButtonsState();
+    }
+
+    private void Content_MessageChanged(object sender, EventArgs e) {
+      UpdateProgressMessage();
+    }
+
+    private void Content_ProgressBarModeChanged(object sender, EventArgs e) {
+      UpdateProgressValue();
+    }
+    private void Content_ProgressValueChanged(object sender, EventArgs e) {
+      UpdateProgressValue();
+    }
+
+    private void Content_CanBeStoppedChanged(object sender, EventArgs e) {
+      UpdateButtonsState();
+    }
+    private void Content_CanBeCanceledChanged(object sender, EventArgs e) {
+      UpdateButtonsState();
     }
 
@@ -83,94 +104,91 @@
         return;
       }
-      int height = Content.CanBeCanceled ? Height : collapsedControlHeight;
+      if (Parent != null) return;
 
       Left = (Control.ClientRectangle.Width / 2) - (Width / 2);
-      Top = (Control.ClientRectangle.Height / 2) - (height / 2);
+      Top = (Control.ClientRectangle.Height / 2) - (Height / 2);
       Anchor = AnchorStyles.None;
 
-      control.Enabled = false;
+      UpdateProgressMessage();
+      UpdateProgressValue();
+      UpdateButtonsState();
+
+      Control.Enabled = false;
       Parent = Control.Parent;
       BringToFront();
-
-      UpdateProgressValue();
-      UpdateProgressStatus();
-      UpdateCancelButton();
       Visible = true;
     }
 
     private void HideProgress() {
-      if (InvokeRequired) Invoke((Action)HideProgress);
-      else {
-        control.Enabled = true;
-        Parent = null;
-        Visible = false;
+      if (Control.InvokeRequired) {
+        Control.Invoke((Action)HideProgress);
+        return;
+      }
+      if (Parent == null) return;
+
+      Visible = false;
+      Control.Enabled = true;
+      Parent = null;
+    }
+
+    private void UpdateProgressState() {
+      if (Control.InvokeRequired) {
+        Control.Invoke((Action)UpdateProgressState);
+        return;
+      }
+
+      if (Content.ProgressState != ProgressState.Finished)
+        ShowProgress();
+      else
+        HideProgress();
+    }
+
+    private void UpdateProgressMessage() {
+      if (Control.InvokeRequired) {
+        Control.Invoke((Action)UpdateProgressMessage);
+        return;
+      }
+
+      messageLabel.Text = content.Message;
+    }
+
+    private void UpdateProgressValue() {
+      if (InvokeRequired) {
+        Invoke((Action)UpdateProgressValue);
+        return;
+      }
+
+      switch (Content.ProgressMode) {
+        case ProgressMode.Determinate:
+          progressBar.Style = ProgressBarStyle.Continuous;
+          progressBar.Value = (int)Math.Round(progressBar.Minimum + content.ProgressValue * (progressBar.Maximum - progressBar.Minimum));
+          break;
+        case ProgressMode.Indeterminate:
+          progressBar.Style = ProgressBarStyle.Marquee;
+          progressBar.Value = 0;
+          break;
+        default:
+          throw new NotImplementedException($"Invalid Progress Mode: {content.ProgressMode}");
       }
     }
 
-    private void progress_StatusChanged(object sender, EventArgs e) {
-      UpdateProgressStatus();
+    private void UpdateButtonsState() {
+      if (Control.InvokeRequired) {
+        Control.Invoke((Action)UpdateButtonsState);
+        return;
+      }
+
+      stopButton.Visible = Content.CanBeStopped;
+      stopButton.Enabled = Content.CanBeStopped && content.ProgressState == ProgressState.Started;
+
+      cancelButton.Visible = Content.CanBeCanceled;
+      cancelButton.Enabled = Content.CanBeCanceled && content.ProgressState == ProgressState.Started;
     }
 
-    private void progress_ProgressValueChanged(object sender, EventArgs e) {
-      UpdateProgressValue();
+    private void stopButton_Click(object sender, EventArgs e) {
+      Content.Stop();
     }
-
-    private void Content_ProgressStateChanged(object sender, EventArgs e) {
-      switch (content.ProgressState) {
-        case ProgressState.Finished: HideProgress(); break;
-        case ProgressState.Canceled: HideProgress(); break;
-        case ProgressState.Started: ShowProgress(); break;
-        default: throw new NotSupportedException("The progress state " + content.ProgressState + " is not supported by the ProgressView.");
-      }
-    }
-
-    private void Content_CanBeCanceledChanged(object sender, EventArgs e) {
-      UpdateCancelButton();
-    }
-
-    private void UpdateCancelButton() {
-      cancelButton.Visible = content != null && content.CanBeCanceled;
-      cancelButton.Enabled = content != null && content.CanBeCanceled;
-
-      if (content != null && content.CanBeCanceled) {
-        Height = defaultControlHeight;
-      } else if (content != null && !content.CanBeCanceled) {
-        Height = collapsedControlHeight;
-      }
-    }
-
-    private void UpdateProgressValue() {
-      // prevent problems with object disposal and invoke as suggested by http://stackoverflow.com/a/18647091
-      if (!IsHandleCreated) return;
-      if (InvokeRequired) {
-        try {
-          Invoke((Action)UpdateProgressValue);
-        }
-        catch (InvalidOperationException) {
-          // swallow ObjectDisposedException 
-          // which might occur if the invoke call is executed after or while the control is disposing
-        }
-      } else {
-        if (content != null) {
-          double progressValue = content.ProgressValue;
-          if (progressValue <= 0.0 || progressValue > 1.0) {
-            progressBar.Style = ProgressBarStyle.Marquee;
-          } else {
-            progressBar.Style = ProgressBarStyle.Blocks;
-            progressBar.Value =
-              (int)Math.Round(progressBar.Minimum + progressValue * (progressBar.Maximum - progressBar.Minimum));
-          }
-        }
-      }
-    }
-
-    private void UpdateProgressStatus() {
-      if (InvokeRequired) Invoke((Action)UpdateProgressStatus);
-      else if (content != null)
-        statusLabel.Text = content.Status;
-    }
-
     private void cancelButton_Click(object sender, EventArgs e) {
-      content.Cancel();
+      Content.Cancel();
     }
   }
Index: /branches/2965_CancelablePersistence/HeuristicLab.MainForm.WindowsForms/3.3/Controls/ProgressView.designer.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.MainForm.WindowsForms/3.3/Controls/ProgressView.designer.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.MainForm.WindowsForms/3.3/Controls/ProgressView.designer.cs	(revision 16433)
@@ -27,5 +27,5 @@
     private System.ComponentModel.IContainer components = null;
 
-   
+
     #region Component Designer generated code
 
@@ -36,7 +36,10 @@
     private void InitializeComponent() {
       this.progressBar = new System.Windows.Forms.ProgressBar();
-      this.statusLabel = new System.Windows.Forms.Label();
+      this.messageLabel = new System.Windows.Forms.Label();
+      this.borderPanel = new System.Windows.Forms.Panel();
+      this.panel = new System.Windows.Forms.Panel();
+      this.stopButton = new System.Windows.Forms.Button();
       this.cancelButton = new System.Windows.Forms.Button();
-      this.panel = new System.Windows.Forms.Panel();
+      this.borderPanel.SuspendLayout();
       this.panel.SuspendLayout();
       this.SuspendLayout();
@@ -48,21 +51,58 @@
       this.progressBar.Location = new System.Drawing.Point(3, 3);
       this.progressBar.Name = "progressBar";
-      this.progressBar.Size = new System.Drawing.Size(352, 23);
+      this.progressBar.Size = new System.Drawing.Size(366, 23);
       this.progressBar.Style = System.Windows.Forms.ProgressBarStyle.Marquee;
       this.progressBar.TabIndex = 0;
       // 
-      // statusLabel
+      // messageLabel
       // 
-      this.statusLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+      this.messageLabel.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.messageLabel.Location = new System.Drawing.Point(0, 0);
+      this.messageLabel.Name = "messageLabel";
+      this.messageLabel.Padding = new System.Windows.Forms.Padding(0, 0, 3, 0);
+      this.messageLabel.Size = new System.Drawing.Size(217, 23);
+      this.messageLabel.TabIndex = 1;
+      this.messageLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+      // 
+      // borderPanel
+      // 
+      this.borderPanel.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.statusLabel.Location = new System.Drawing.Point(3, 33);
-      this.statusLabel.Name = "statusLabel";
-      this.statusLabel.Size = new System.Drawing.Size(352, 17);
-      this.statusLabel.TabIndex = 1;
+      this.borderPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+      this.borderPanel.Controls.Add(this.panel);
+      this.borderPanel.Controls.Add(this.progressBar);
+      this.borderPanel.Location = new System.Drawing.Point(0, 0);
+      this.borderPanel.Name = "borderPanel";
+      this.borderPanel.Size = new System.Drawing.Size(374, 62);
+      this.borderPanel.TabIndex = 3;
+      // 
+      // panel
+      // 
+      this.panel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.panel.Controls.Add(this.messageLabel);
+      this.panel.Controls.Add(this.stopButton);
+      this.panel.Controls.Add(this.cancelButton);
+      this.panel.Location = new System.Drawing.Point(3, 32);
+      this.panel.Name = "panel";
+      this.panel.Size = new System.Drawing.Size(367, 23);
+      this.panel.TabIndex = 4;
+      // 
+      // stopButton
+      // 
+      this.stopButton.Dock = System.Windows.Forms.DockStyle.Right;
+      this.stopButton.Location = new System.Drawing.Point(217, 0);
+      this.stopButton.Name = "stopButton";
+      this.stopButton.Size = new System.Drawing.Size(75, 23);
+      this.stopButton.TabIndex = 3;
+      this.stopButton.Text = "Stop";
+      this.stopButton.UseVisualStyleBackColor = true;
+      this.stopButton.Click += new System.EventHandler(this.stopButton_Click);
       // 
       // cancelButton
       // 
-      this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
-      this.cancelButton.Location = new System.Drawing.Point(280, 53);
+      this.cancelButton.Dock = System.Windows.Forms.DockStyle.Right;
+      this.cancelButton.Location = new System.Drawing.Point(292, 0);
       this.cancelButton.Name = "cancelButton";
       this.cancelButton.Size = new System.Drawing.Size(75, 23);
@@ -72,24 +112,11 @@
       this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
       // 
-      // panel
-      // 
-      this.panel.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.panel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
-      this.panel.Controls.Add(this.progressBar);
-      this.panel.Controls.Add(this.cancelButton);
-      this.panel.Controls.Add(this.statusLabel);
-      this.panel.Location = new System.Drawing.Point(0, 0);
-      this.panel.Name = "panel";
-      this.panel.Size = new System.Drawing.Size(360, 88);
-      this.panel.TabIndex = 3;
-      // 
       // ProgressView
       // 
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
-      this.Controls.Add(this.panel);
+      this.Controls.Add(this.borderPanel);
       this.Name = "ProgressView";
-      this.Size = new System.Drawing.Size(360, 88);
+      this.Size = new System.Drawing.Size(374, 62);
+      this.borderPanel.ResumeLayout(false);
       this.panel.ResumeLayout(false);
       this.ResumeLayout(false);
@@ -100,7 +127,9 @@
 
     private System.Windows.Forms.ProgressBar progressBar;
-    private System.Windows.Forms.Label statusLabel;
+    private System.Windows.Forms.Label messageLabel;
+    private System.Windows.Forms.Panel borderPanel;
+    private System.Windows.Forms.Button stopButton;
+    private System.Windows.Forms.Panel panel;
     private System.Windows.Forms.Button cancelButton;
-    private System.Windows.Forms.Panel panel;
   }
 }
Index: /branches/2965_CancelablePersistence/HeuristicLab.MainForm.WindowsForms/3.3/HeuristicLab.MainForm.WindowsForms-3.3.csproj
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.MainForm.WindowsForms/3.3/HeuristicLab.MainForm.WindowsForms-3.3.csproj	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.MainForm.WindowsForms/3.3/HeuristicLab.MainForm.WindowsForms-3.3.csproj	(revision 16433)
@@ -151,4 +151,5 @@
     </Compile>
     <Compile Include="Plugin.cs" />
+    <Compile Include="Progress.cs" />
     <Compile Include="Views\AsynchronousContentView.cs">
       <SubType>UserControl</SubType>
Index: /branches/2965_CancelablePersistence/HeuristicLab.MainForm.WindowsForms/3.3/MainForms/MainForm.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.MainForm.WindowsForms/3.3/MainForms/MainForm.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.MainForm.WindowsForms/3.3/MainForms/MainForm.cs	(revision 16433)
@@ -61,5 +61,5 @@
       set {
         if (InvokeRequired) {
-          Action<string> action = delegate(string s) { this.Title = s; };
+          Action<string> action = delegate (string s) { this.Title = s; };
           Invoke(action, value);
         } else
@@ -72,5 +72,5 @@
       set {
         if (InvokeRequired) {
-          Action<Cursor> action = delegate(Cursor c) { this.Cursor = c; };
+          Action<Cursor> action = delegate (Cursor c) { this.Cursor = c; };
           Invoke(action, value);
         } else
@@ -95,5 +95,5 @@
         if (this.activeView != value) {
           if (InvokeRequired) {
-            Action<IView> action = delegate(IView activeView) { this.ActiveView = activeView; };
+            Action<IView> action = delegate (IView activeView) { this.ActiveView = activeView; };
             Invoke(action, value);
           } else {
@@ -230,5 +230,5 @@
     }
 
-    public IContentView ShowContent<T>(T content, bool reuseExistingView, IEqualityComparer<T> comparer = null) where T : class,IContent {
+    public IContentView ShowContent<T>(T content, bool reuseExistingView, IEqualityComparer<T> comparer = null) where T : class, IContent {
       if (content == null) throw new ArgumentNullException("Content cannot be null.");
       if (!reuseExistingView) return ShowContent(content);
@@ -353,8 +353,8 @@
     /// Adds a <see cref="ProgressView"/> to the <see cref="ContentView"/>s showing the specified content.
     /// </summary>
-    public IProgress AddOperationProgressToContent(IContent content, string progressMessage, bool addToObjectGraphObjects = true) {
+    internal void AddProgressToContent(IContent content, IProgress progress, bool addToObjectGraphObjects) {
       if (InvokeRequired) {
-        IProgress result = (IProgress)Invoke((Func<IContent, string, bool, IProgress>)AddOperationProgressToContent, content, progressMessage, addToObjectGraphObjects);
-        return result;
+        Invoke((Action<IContent, IProgress, bool>)AddProgressToContent, content, progress, addToObjectGraphObjects);
+        return;
       }
       if (contentProgressLookup.ContainsKey(content))
@@ -371,5 +371,4 @@
         contentViews = contentViews.Where(v => v.Content == content);
 
-      var progress = new Progress(progressMessage, ProgressState.Started);
       foreach (var contentView in contentViews) {
         progressViews.Add(new ProgressView(contentView, progress));
@@ -377,5 +376,4 @@
 
       contentProgressLookup[content] = progress;
-      return progress;
     }
 
@@ -383,13 +381,7 @@
     /// Adds a <see cref="ProgressView"/> to the specified view.
     /// </summary>
-    public IProgress AddOperationProgressToView(Control control, string progressMessage) {
-      var progress = new Progress(progressMessage, ProgressState.Started);
-      AddOperationProgressToView(control, progress);
-      return progress;
-    }
-
-    public void AddOperationProgressToView(Control control, IProgress progress) {
+    internal void AddProgressToControl(Control control, IProgress progress) {
       if (InvokeRequired) {
-        Invoke((Action<Control, IProgress>)AddOperationProgressToView, control, progress);
+        Invoke((Action<Control, IProgress>)AddProgressToControl, control, progress);
         return;
       }
@@ -413,7 +405,7 @@
     /// Removes an existing <see cref="ProgressView"/> from the <see cref="ContentView"/>s showing the specified content.
     /// </summary>
-    public void RemoveOperationProgressFromContent(IContent content, bool finishProgress = true) {
+    internal void RemoveProgressFromContent(IContent content, bool finishProgress) {
       if (InvokeRequired) {
-        Invoke((Action<IContent, bool>)RemoveOperationProgressFromContent, content, finishProgress);
+        Invoke((Action<IContent, bool>)RemoveProgressFromContent, content, finishProgress);
         return;
       }
@@ -429,5 +421,4 @@
       }
       contentProgressLookup.Remove(content);
-
     }
 
@@ -435,7 +426,7 @@
     /// Removes an existing <see cref="ProgressView"/> from the specified view.
     /// </summary>
-    public void RemoveOperationProgressFromView(Control control, bool finishProgress = true) {
+    internal void RemoveProgressFromControl(Control control, bool finishProgress) {
       if (InvokeRequired) {
-        Invoke((Action<Control, bool>)RemoveOperationProgressFromView, control, finishProgress);
+        Invoke((Action<Control, bool>)RemoveProgressFromControl, control, finishProgress);
         return;
       }
@@ -560,6 +551,5 @@
       try {
         ((IActionUserInterfaceItem)item.Tag).Execute();
-      }
-      catch (Exception ex) {
+      } catch (Exception ex) {
         ErrorHandling.ShowErrorDialog((Control)MainFormManager.MainForm, ex);
       }
Index: /branches/2965_CancelablePersistence/HeuristicLab.MainForm.WindowsForms/3.3/Progress.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.MainForm.WindowsForms/3.3/Progress.cs	(revision 16433)
+++ /branches/2965_CancelablePersistence/HeuristicLab.MainForm.WindowsForms/3.3/Progress.cs	(revision 16433)
@@ -0,0 +1,266 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Windows.Forms;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.MainForm {
+  public class Progress : IProgress {
+    private ProgressState progressState;
+    public ProgressState ProgressState {
+      get { return progressState; }
+      private set {
+        if (progressState != value) {
+          progressState = value;
+          OnProgressStateChanged();
+        }
+      }
+    }
+
+    private string message;
+    public string Message {
+      get { return message; }
+      set {
+        if (message != value) {
+          message = value;
+          OnMessageChanged();
+        }
+      }
+    }
+
+    private ProgressMode progressMode;
+    public ProgressMode ProgressMode {
+      get { return progressMode; }
+      set {
+        if (progressMode != value) {
+          progressMode = value;
+          OnProgressBarModeChanged();
+        }
+      }
+    }
+
+    private double progressValue;
+    public double ProgressValue {
+      get { return progressValue; }
+      set {
+        if (progressMode == ProgressMode.Indeterminate)
+          throw new InvalidOperationException("Cannot set ProgressValue while ProgressBar is in Indeterminate-Mode");
+        if (progressValue != value) {
+          progressValue = Math.Max(Math.Min(value, 1.0), 0.0);
+          OnProgressChanged();
+        }
+      }
+    }
+
+    private bool canBeStopped;
+    public bool CanBeStopped {
+      get { return canBeStopped; }
+      set {
+        if (canBeStopped != value) {
+          canBeStopped = value;
+          OnCanBeStoppedChanged();
+        }
+      }
+    }
+
+    private bool canBeCanceled;
+    public bool CanBeCanceled {
+      get { return canBeCanceled; }
+      set {
+        if (canBeCanceled != value) {
+          canBeCanceled = value;
+          OnCanBeCanceledChanged();
+        }
+      }
+    }
+
+    public Progress() {
+      progressState = ProgressState.Finished;
+      canBeStopped = false;
+      canBeCanceled = false;
+      progressMode = ProgressMode.Indeterminate;
+      progressValue = 0.0;
+    }
+
+    public void Start(string message, ProgressMode mode = ProgressMode.Determinate) {
+      ProgressState = ProgressState.Started;
+      ProgressMode = mode;
+      if (mode == ProgressMode.Determinate)
+        ProgressValue = 0.0;
+      Message = message;
+    }
+
+    public void Finish() {
+      if (ProgressMode == ProgressMode.Determinate && ProgressValue != 1.0)
+        ProgressValue = 1.0;
+      ProgressState = ProgressState.Finished;
+    }
+
+    public void Stop() {
+      if (canBeStopped) {
+        ProgressState = ProgressState.StopRequested;
+        OnStopRequested();
+      } else throw new NotSupportedException("This progress cannot be stopped.");
+    }
+    public void Cancel() {
+      if (canBeCanceled) {
+        ProgressState = ProgressState.CancelRequested;
+        OnCancelRequested();
+      } else throw new NotSupportedException("This progress cannot be canceled.");
+    }
+
+    #region Show and Hide Progress
+    /// <summary>
+    /// Shows a started Progress on all Views of the specified content.
+    /// </summary>
+    public static IProgress Show(IContent content, string progressMessage, ProgressMode mode = ProgressMode.Determinate, Action stopRequestHandler = null, Action cancelRequestHandler = null, bool addToObjectGraphObjects = true) {
+      var progress = CreateAndStartProgress(progressMessage, mode, stopRequestHandler, cancelRequestHandler);
+      Show(content, progress, addToObjectGraphObjects);
+      return progress;
+    }
+
+    /// <summary>
+    /// Shows a started Progress on the specified view.
+    /// </summary>
+    public static IProgress Show(IView view, string progressMessage, ProgressMode mode = ProgressMode.Determinate, Action stopRequestHandler = null, Action cancelRequestHandler = null) {
+      var progress = CreateAndStartProgress(progressMessage, mode, stopRequestHandler, cancelRequestHandler);
+      Show(view, progress);
+      return progress;
+    }
+    /// <summary>
+    /// Shows a started Progress on the specified control.
+    /// </summary>
+    /// <remarks>For backwards compatibility. Use Progress.Show(IView, ...) if possible.</remarks>
+    public static IProgress ShowOnControl(Control control, string progressMessage, ProgressMode mode = ProgressMode.Determinate, Action stopRequestHandler = null, Action cancelRequestHandler = null) {
+      var progress = CreateAndStartProgress(progressMessage, mode, stopRequestHandler, cancelRequestHandler);
+      ShowOnControl(control, progress);
+      return progress;
+    }
+
+    private static IProgress CreateAndStartProgress(string progressMessage, ProgressMode mode, Action stopRequestHandler, Action cancelRequestHandler) {
+      var progress = new Progress();
+      if (stopRequestHandler != null) {
+        progress.CanBeStopped = true;
+        progress.StopRequested += (s, a) => stopRequestHandler();
+      }
+      if (cancelRequestHandler != null) {
+        progress.CanBeCanceled = true;
+        progress.CancelRequested += (s, a) => cancelRequestHandler();
+      }
+      progress.Start(progressMessage, mode);
+      return progress;
+    }
+
+    /// <summary>
+    /// Shows an existing progress on all Views of the specified content.
+    /// </summary>
+    public static IProgress Show(IContent content, IProgress progress, bool addToObjectGraphObjects = true) {
+      MainFormManager.GetMainForm<WindowsForms.MainForm>().AddProgressToContent(content, progress, addToObjectGraphObjects);
+      return progress;
+    }
+    /// <summary>
+    /// Shows an existing progress on the specified View.
+    /// </summary>
+    public static IProgress Show(IView view, IProgress progress) {
+      return ShowOnControl((Control)view, progress);
+    }
+    /// <summary>
+    /// Shows an existing progress on the specified control.
+    /// </summary>
+    /// <remarks>For backwards compatibility. Use Progress.Show(IView, ...) if possible.</remarks>
+    public static IProgress ShowOnControl(Control control, IProgress progress) {
+      MainFormManager.GetMainForm<WindowsForms.MainForm>().AddProgressToControl(control, progress);
+      return progress;
+    }
+
+    /// <summary>
+    /// Hides the Progress from all Views of the specified content.
+    /// </summary>
+    public static void Hide(IContent content, bool finishProgress = true) {
+      MainFormManager.GetMainForm<WindowsForms.MainForm>().RemoveProgressFromContent(content, finishProgress);
+    }
+    /// <summary>
+    /// Hides the Progress from the specified view.
+    /// </summary>
+    public static void Hide(IView view, bool finishProgress = true) {
+      HideFromControl((Control)view, finishProgress);
+    }
+    /// <summary>
+    /// Hides the Progress from the specified control.
+    /// </summary>
+    /// <remarks>For backwards compatibility. Use Progress.Hide(IView) if possible.</remarks>
+    public static void HideFromControl(Control control, bool finishProgress = true) {
+      MainFormManager.GetMainForm<WindowsForms.MainForm>().RemoveProgressFromControl(control, finishProgress);
+    }
+    #endregion
+
+    #region Event Handler
+    public event EventHandler ProgressStateChanged;
+    private void OnProgressStateChanged() {
+      var handler = ProgressStateChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler MessageChanged;
+    private void OnMessageChanged() {
+      var handler = MessageChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler ProgressBarModeChanged;
+    private void OnProgressBarModeChanged() {
+      var handler = ProgressBarModeChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler ProgressValueChanged;
+    private void OnProgressChanged() {
+      var handler = ProgressValueChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler CanBeStoppedChanged;
+    private void OnCanBeStoppedChanged() {
+      var handler = CanBeStoppedChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler CanBeCanceledChanged;
+    private void OnCanBeCanceledChanged() {
+      var handler = CanBeCanceledChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler StopRequested;
+    private void OnStopRequested() {
+      var handler = StopRequested;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler CancelRequested;
+    private void OnCancelRequested() {
+      var handler = CancelRequested;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    #endregion
+  }
+}
Index: /branches/2965_CancelablePersistence/HeuristicLab.MainForm/3.3/HeuristicLab.MainForm-3.3.csproj
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.MainForm/3.3/HeuristicLab.MainForm-3.3.csproj	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.MainForm/3.3/HeuristicLab.MainForm-3.3.csproj	(revision 16433)
@@ -124,5 +124,4 @@
     <Compile Include="Interfaces\IProgress.cs" />
     <Compile Include="Plugin.cs" />
-    <Compile Include="Progress.cs" />
     <Compile Include="ViewAttribute.cs" />
     <Compile Include="Interfaces\IContentView.cs" />
Index: /branches/2965_CancelablePersistence/HeuristicLab.MainForm/3.3/Interfaces/IProgress.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.MainForm/3.3/Interfaces/IProgress.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.MainForm/3.3/Interfaces/IProgress.cs	(revision 16433)
@@ -24,66 +24,35 @@
 
 namespace HeuristicLab.MainForm {
-  public enum ProgressState { Started = 1, Canceled = 2, Finished = 3 };
+  public enum ProgressState { Started, Finished, StopRequested, CancelRequested }
+  public enum ProgressMode { Determinate, Indeterminate }
 
   public interface IProgress : IContent {
+    ProgressState ProgressState { get; }
+
+    string Message { get; set; }
+
+    ProgressMode ProgressMode { get; set; }
     /// <summary>
-    /// Gets or sets the currently associated status text with the progress.
+    /// Gets or sets the currently associated progress value in the range [0;1] (values outside the range are truncated).
+    /// Changing the ProgressValue when <c>ProgressMode</c> is <c>Indeterminate</c> raises an Exception.
     /// </summary>
-    string Status { get; set; }
-    /// <summary>
-    /// Gets or sets the currently associated progress value in the range (0;1].
-    ///  Values outside this range are permitted and need to be handled in some feasible manner.
-    /// </summary>
+    /// <exception cref="InvalidOperationException">Setting the ProgressValue-property while in the Indeterminate state is invalid.</exception>
     double ProgressValue { get; set; }
-    /// <summary>
-    /// Gets or sets the current state of the progress. Every progress starts in state
-    /// Started and then becomes either Canceled or Finished.
-    /// If it is reused it may be Started again.
-    /// </summary>
-    ProgressState ProgressState { get; }
-    /// <summary>
-    /// Returns whether the operation can be canceled or not.
-    /// This can change during the course of the progress.
-    /// </summary>
-    bool CanBeCanceled { get; }
 
-    /// <summary>
-    /// Requests the operation behind the process to cancel.
-    /// Check the !ProgressState property when the cancellation succeeded.
-    /// The corresponding event will also notify of a success.
-    /// </summary>
-    /// <exception cref="NotSupportedException">Thrown when cancellation is not supported.</exception>
+    bool CanBeStopped { get; set; }
+    bool CanBeCanceled { get; set; }
+
+    void Start(string message, ProgressMode mode = ProgressMode.Determinate);
+    void Finish();
+    void Stop();
     void Cancel();
-    /// <summary>
-    /// Sets the ProgressValue to 1 and the ProgressState to Finished.
-    /// </summary>
-    void Finish();
 
-    /// <summary>
-    /// Starts or restarts a Progress. 
-    /// </summary>
-    void Start();
-
-    void Start(string status);
-
-    /// <summary>
-    /// The status text changed.
-    /// </summary>
-    event EventHandler StatusChanged;
-    /// <summary>
-    /// The value of the progress changed. This is the (0;1] progress value from starting to finish. Values outside this range are permitted and need to be handled in some feasible manner.
-    /// </summary>
+    event EventHandler ProgressStateChanged;
+    event EventHandler MessageChanged;
+    event EventHandler ProgressBarModeChanged;
     event EventHandler ProgressValueChanged;
-    /// <summary>
-    /// The state of the progress changed. The handler is supposed to query the ProgressState property.
-    /// </summary>
-    event EventHandler ProgressStateChanged;
-    /// <summary>
-    /// The progress' ability to cancel changed.
-    /// </summary>
+    event EventHandler CanBeStoppedChanged;
     event EventHandler CanBeCanceledChanged;
-    /// <summary>
-    /// A cancelation is requested.
-    /// </summary>
+    event EventHandler StopRequested;
     event EventHandler CancelRequested;
   }
Index: anches/2965_CancelablePersistence/HeuristicLab.MainForm/3.3/Progress.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.MainForm/3.3/Progress.cs	(revision 16432)
+++ 	(revision )
@@ -1,137 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-
-namespace HeuristicLab.MainForm {
-  public class Progress : IProgress {
-    private string status;
-    public string Status {
-      get { return status; }
-      set {
-        if (status != value) {
-          status = value;
-          OnStatusChanged();
-        }
-      }
-    }
-
-    private double progressValue;
-    public double ProgressValue {
-      get { return progressValue; }
-      set {
-        if (progressValue != value) {
-          progressValue = value;
-          OnProgressChanged();
-        }
-      }
-    }
-
-    private ProgressState progressState;
-    public ProgressState ProgressState {
-      get { return progressState; }
-      private set {
-        if (progressState != value) {
-          progressState = value;
-          OnProgressStateChanged();
-        }
-      }
-    }
-
-    private bool canBeCanceled;
-    public bool CanBeCanceled {
-      get { return canBeCanceled; }
-      set {
-        if (canBeCanceled != value) {
-          canBeCanceled = value;
-          OnCanBeCanceledChanged();
-        }
-      }
-    }
-
-    public Progress() {
-      progressState = ProgressState.Finished;
-      canBeCanceled = false;
-    }
-    public Progress(string status)
-      : this() {
-      this.status = status;
-    }
-    public Progress(string status, ProgressState state)
-      : this() {
-      this.status = status;
-      this.progressState = state;
-    }
-
-    public void Cancel() {
-      if (canBeCanceled)
-        OnCancelRequested();
-    }
-
-    public void Finish() {
-      if (ProgressValue != 1.0) ProgressValue = 1.0;
-      ProgressState = ProgressState.Finished;
-    }
-
-    public void Start() {
-      ProgressValue = 0.0;
-      ProgressState = ProgressState.Started;
-    }
-
-    public void Start(string status) {
-      Start();
-      Status = status;
-    }
-
-    #region Event Handler
-    public event EventHandler StatusChanged;
-    private void OnStatusChanged() {
-      var handler = StatusChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler ProgressValueChanged;
-    private void OnProgressChanged() {
-      var handler = ProgressValueChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler ProgressStateChanged;
-    private void OnProgressStateChanged() {
-      var handler = ProgressStateChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler CanBeCanceledChanged;
-    private void OnCanBeCanceledChanged() {
-      var handler = CanBeCanceledChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler CancelRequested;
-    private void OnCancelRequested() {
-      var handler = CancelRequested;
-      if (handler != null) throw new NotSupportedException("Cancel request was ignored.");
-      else handler(this, EventArgs.Empty);
-    }
-    #endregion
-  }
-}
Index: /branches/2965_CancelablePersistence/HeuristicLab.Optimizer/3.3/FileManager.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Optimizer/3.3/FileManager.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Optimizer/3.3/FileManager.cs	(revision 16433)
@@ -100,5 +100,5 @@
           MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().SetAppStartingCursor();
           var cancellationTokenSource = new CancellationTokenSource();
-          SetSaveOperationProgressInContentViews(content, true);
+          AddProgressInContentViews(content, cancellationTokenSource);
           ContentManager.SaveAsync(content, content.Filename, true, SavingCompleted, cancellationTokenSource.Token);
         }
@@ -134,5 +134,5 @@
           bool compressed = saveFileDialog.FilterIndex != 1;
           var cancellationTokenSource = new CancellationTokenSource();
-          SetSaveOperationProgressInContentViews(content, compressed, saveFileDialog.FileName);
+          AddProgressInContentViews(content, cancellationTokenSource, saveFileDialog.FileName);
 
           ContentManager.SaveAsync(content, saveFileDialog.FileName, compressed, SavingCompleted, cancellationTokenSource.Token);
@@ -144,30 +144,17 @@
         if (error != null) throw error;
         MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().UpdateTitle();
+      } catch (OperationCanceledException) { // do nothing if canceled
       } catch (Exception ex) {
         ErrorHandling.ShowErrorDialog((Control)MainFormManager.MainForm, "Cannot save file.", ex);
       } finally {
-        SetSaveOperationProgressInContentViews(content, false);
+        Progress.Hide(content);
         MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().ResetAppStartingCursor();
       }
     }
 
-    private static void SetSaveOperationProgressInContentViews(IStorableContent content, bool showProgress, string fileName = null) {
-      HeuristicLab.MainForm.WindowsForms.MainForm mainForm = MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>();
-      #region Mono Compatibility
-      // removed the InvokeRequired check because of Mono
-      mainForm.Invoke((Action)delegate {
-        if (showProgress) {
-          mainForm.AddOperationProgressToContent(content, string.Format("Saving to file \"{0}\"...", Path.GetFileName(fileName ?? content.Filename)));
-        } else
-          mainForm.RemoveOperationProgressFromContent(content);
-      });
-      #endregion
-    }
-
-    /* For later merge with #2845
     private static void AddProgressInContentViews(IStorableContent content, CancellationTokenSource cancellationTokenSource, string fileName = null) {
       string message = string.Format("Saving to file \"{0}\"...", Path.GetFileName(fileName ?? content.Filename));
       Progress.Show(content, message, ProgressMode.Indeterminate, cancelRequestHandler: () => cancellationTokenSource.Cancel());
-    }*/
+    }
   }
 }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Optimizer/3.3/StartPage.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Optimizer/3.3/StartPage.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Optimizer/3.3/StartPage.cs	(revision 16433)
@@ -88,5 +88,5 @@
 
     private void LoadSamples(object state) {
-      progress = MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().AddOperationProgressToView(samplesListView, "Loading...");
+      progress = Progress.ShowOnControl(samplesListView, "Loading...");
       try {
         var assembly = Assembly.GetExecutingAssembly();
@@ -112,5 +112,5 @@
         OnAllSamplesLoaded();
       } finally {
-        MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(samplesListView);
+        Progress.HideFromControl(samplesListView);
       }
     }
@@ -138,5 +138,5 @@
         };
       groupLookup[standardProblemsGroup] = standardProblems;
-      var dataAnalysisProblems = new List<string> { "ALPSGP_SymReg", "SGP_SymbClass", "SGP_SymbReg","OSGP_SymReg", "OSGP_TimeSeries", "GE_SymbReg", "GPR" };
+      var dataAnalysisProblems = new List<string> { "ALPSGP_SymReg", "SGP_SymbClass", "SGP_SymbReg", "OSGP_SymReg", "OSGP_TimeSeries", "GE_SymbReg", "GPR" };
       groupLookup[dataAnalysisGroup] = dataAnalysisProblems;
       var scripts = new List<string> { "GA_QAP_Script", "GUI_Automation_Script", "OSGA_Rastrigin_Script",
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/SymbolicClassificationSolutionView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/SymbolicClassificationSolutionView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/SymbolicClassificationSolutionView.cs	(revision 16433)
@@ -60,7 +60,7 @@
         var name = exportFileDialog.FileName;
         using (BackgroundWorker bg = new BackgroundWorker()) {
-          MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().AddOperationProgressToView(this, "Exportion solution to " + name + ".");
+          Progress.Show(this, "Exportion solution to " + name + ".", ProgressMode.Indeterminate);
           bg.DoWork += (o, a) => exporter.Export(Content, name);
-          bg.RunWorkerCompleted += (o, a) => MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this);
+          bg.RunWorkerCompleted += (o, a) => Progress.Hide(this);
           bg.RunWorkerAsync();
         }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/SymbolicDiscriminantFunctionClassificationSolutionView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/SymbolicDiscriminantFunctionClassificationSolutionView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/SymbolicDiscriminantFunctionClassificationSolutionView.cs	(revision 16433)
@@ -59,7 +59,7 @@
         var name = exportFileDialog.FileName;
         using (BackgroundWorker bg = new BackgroundWorker()) {
-          MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().AddOperationProgressToView(this, "Exportion solution to " + name + ".");
+          Progress.Show(this, "Exportion solution to " + name + ".", ProgressMode.Indeterminate);
           bg.DoWork += (o, a) => exporter.Export(Content, name);
-          bg.RunWorkerCompleted += (o, a) => MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this);
+          bg.RunWorkerCompleted += (o, a) => Progress.Hide(this);
           bg.RunWorkerAsync();
         }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/SymbolicRegressionSolutionView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/SymbolicRegressionSolutionView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/SymbolicRegressionSolutionView.cs	(revision 16433)
@@ -61,7 +61,7 @@
         var name = exportFileDialog.FileName;
         using (BackgroundWorker bg = new BackgroundWorker()) {
-          MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().AddOperationProgressToView(this, "Exporting solution to " + name + ".");
+          Progress.Show(this, "Exporting solution to " + name + ".", ProgressMode.Indeterminate);
           bg.DoWork += (o, a) => exporter.Export(Content, name);
-          bg.RunWorkerCompleted += (o, a) => MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this);
+          bg.RunWorkerCompleted += (o, a) => Progress.Hide(this);
           bg.RunWorkerAsync();
         }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs	(revision 16433)
@@ -24,4 +24,5 @@
 using System.Drawing;
 using System.Linq;
+using System.Threading;
 using System.Threading.Tasks;
 using System.Windows.Forms;
@@ -40,5 +41,6 @@
     private readonly ISymbolicDataAnalysisSolutionImpactValuesCalculator impactCalculator;
 
-    private readonly IProgress progress = new Progress();
+    private readonly Progress progress = new Progress();
+    private CancellationTokenSource cancellationTokenSource;
 
     private enum TreeState { Valid, Invalid }
@@ -152,5 +154,6 @@
       Content.ProblemDataChanged += Content_Changed;
       treeChart.Repainted += treeChart_Repainted;
-      MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().AddOperationProgressToView(grpSimplify, progress);
+      Progress.ShowOnControl(grpSimplify, progress);
+      progress.StopRequested += progress_StopRequested;
     }
     protected override void DeregisterContentEvents() {
@@ -159,5 +162,6 @@
       Content.ProblemDataChanged -= Content_Changed;
       treeChart.Repainted -= treeChart_Repainted;
-      MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(grpSimplify, false);
+      Progress.HideFromControl(grpSimplify, false);
+      progress.StopRequested -= progress_StopRequested;
     }
 
@@ -178,4 +182,8 @@
     }
 
+    private void progress_StopRequested(object sender, EventArgs e) {
+      cancellationTokenSource.Cancel();
+    }
+
     private async void UpdateView() {
       if (Content == null || Content.Model == null || Content.ProblemData == null) return;
@@ -184,6 +192,10 @@
 
       progress.Start("Calculate Impact and Replacement Values ...");
+      progress.CanBeStopped = true;
+      cancellationTokenSource = new CancellationTokenSource();
       var impactAndReplacementValues = await Task.Run(() => CalculateImpactAndReplacementValues(tree));
-      await Task.Delay(500); // wait for progressbar to finish animation
+      try {
+        await Task.Delay(500, cancellationTokenSource.Token); // wait for progressbar to finish animation
+      } catch (OperationCanceledException) { }
       var replacementValues = impactAndReplacementValues.ToDictionary(x => x.Key, x => x.Value.Item2);
       foreach (var pair in replacementValues.Where(pair => !(pair.Key is ConstantTreeNode))) {
@@ -192,4 +204,5 @@
       nodeImpacts = impactAndReplacementValues.ToDictionary(x => x.Key, x => x.Value.Item1);
       progress.Finish();
+      progress.CanBeStopped = false;
       PaintNodeImpacts();
     }
@@ -198,4 +211,5 @@
       var impactAndReplacementValues = new Dictionary<ISymbolicExpressionTreeNode, Tuple<double, double>>();
       foreach (var node in tree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix()) {
+        if (progress.ProgressState == ProgressState.StopRequested) continue;
         double impactValue, replacementValue, newQualityForImpactsCalculation;
         impactCalculator.CalculateImpactAndReplacementValues(Content.Model, node, Content.ProblemData, Content.ProblemData.TrainingIndices, out impactValue, out replacementValue, out newQualityForImpactsCalculation);
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/Plugin.cs.frame
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/Plugin.cs.frame	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/Plugin.cs.frame	(revision 16433)
@@ -24,4 +24,6 @@
 using System.Text;
 using HeuristicLab.PluginInfrastructure;
+using System.Runtime.InteropServices;
+using System.IO;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views {
@@ -47,4 +49,20 @@
   [PluginDependency("HeuristicLab.Problems.DataAnalysis.Symbolic", "3.4")]
   public class HeuristicLabProblemsDataAnalysisSymbolicViewsPlugin : PluginBase {
+    // HeuristicLab is marked with zone identifier 'Internet' after download.
+    // This propagates to all extracted files and can be checked in the file properties.
+    // IE prevents execution of MathJax JavaScript inside of untrusted html
+    // Therefore we need to programmatically unblock the displayModelFrame.html file before extracting.
+    // see http://engram404.net/programmatically-unblocking-downloaded-files/
+
+    // for removing the Zone.Identifier alternative NTFS stream (effectively unblocking the file)
+    [DllImport("kernel32.dll", SetLastError = true)]
+    private static extern bool DeleteFile(string lpFileName);
+
+    public override void OnLoad() {
+      base.OnLoad();
+
+      // unblock mathjax.zip () 
+      DeleteFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "displayModelFrame.html:Zone.Identifier"));
+    }
   }
 }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/displayModelFrame.html
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/displayModelFrame.html	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/displayModelFrame.html	(revision 16433)
@@ -7,5 +7,5 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge" />
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta name="viewport" content="width=device-width, initial-scale=1" />
 
     <!-- title change by HEAL -->
@@ -46,5 +46,5 @@
         <hr>
     </noscript>
-    <p id="model">
+    <p id="model">$\cos(x^2)$
     </p>
 </body>
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs	(revision 16433)
@@ -37,4 +37,5 @@
     private static readonly Division divSymbol = new Division();
     private static readonly Constant constSymbol = new Constant();
+    private static readonly Absolute absSymbol = new Absolute();
     private static readonly Logarithm logSymbol = new Logarithm();
     private static readonly Exponential expSymbol = new Exponential();
@@ -42,4 +43,7 @@
     private static readonly Square sqrSymbol = new Square();
     private static readonly SquareRoot sqrtSymbol = new SquareRoot();
+    private static readonly AnalyticQuotient aqSymbol = new AnalyticQuotient();
+    private static readonly Cube cubeSymbol = new Cube();
+    private static readonly CubeRoot cubeRootSymbol = new CubeRoot();
     private static readonly Power powSymbol = new Power();
     private static readonly Sine sineSymbol = new Sine();
@@ -131,4 +135,8 @@
     }
 
+    private static bool IsAbsolute(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Absolute;
+    }
+
     // exponential
     private static bool IsLog(ISymbolicExpressionTreeNode node) {
@@ -152,4 +160,12 @@
     }
 
+    private static bool IsCube(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Cube;
+    }
+
+    private static bool IsCubeRoot(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is CubeRoot;
+    }
+
     private static bool IsPower(ISymbolicExpressionTreeNode node) {
       return node.Symbol is Power;
@@ -167,4 +183,8 @@
     private static bool IsTangent(ISymbolicExpressionTreeNode node) {
       return node.Symbol is Tangent;
+    }
+
+    private static bool IsAnalyticalQuotient(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is AnalyticQuotient;
     }
 
@@ -243,4 +263,6 @@
       if (IsConstant(original) || IsVariableBase(original)) {
         return (ISymbolicExpressionTreeNode)original.Clone();
+      } else if (IsAbsolute(original)) {
+        return SimplifyAbsolute(original);
       } else if (IsAddition(original)) {
         return SimplifyAddition(original);
@@ -261,4 +283,8 @@
       } else if (IsSquareRoot(original)) {
         return SimplifySquareRoot(original);
+      } else if (IsCube(original)) {
+        return SimplifyCube(original);
+      } else if (IsCubeRoot(original)) {
+        return SimplifyCubeRoot(original);
       } else if (IsPower(original)) {
         return SimplifyPower(original);
@@ -271,4 +297,6 @@
       } else if (IsTangent(original)) {
         return SimplifyTangent(original);
+      } else if (IsAnalyticalQuotient(original)) {
+        return SimplifyAnalyticalQuotient(original);
       } else if (IsIfThenElse(original)) {
         return SimplifyIfThenElse(original);
@@ -380,4 +408,8 @@
     }
 
+    private static ISymbolicExpressionTreeNode SimplifyAbsolute(ISymbolicExpressionTreeNode original) {
+      return MakeAbs(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
     private static ISymbolicExpressionTreeNode SimplifyNot(ISymbolicExpressionTreeNode original) {
       return MakeNot(GetSimplifiedTree(original.GetSubtree(0)));
@@ -432,4 +464,11 @@
       return MakeSquareRoot(GetSimplifiedTree(original.GetSubtree(0)));
     }
+    private static ISymbolicExpressionTreeNode SimplifyCube(ISymbolicExpressionTreeNode original) {
+      return MakeCube(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
+    private static ISymbolicExpressionTreeNode SimplifyCubeRoot(ISymbolicExpressionTreeNode original) {
+      return MakeCubeRoot(GetSimplifiedTree(original.GetSubtree(0)));
+    }
 
     private static ISymbolicExpressionTreeNode SimplifyLog(ISymbolicExpressionTreeNode original) {
@@ -443,4 +482,8 @@
     private static ISymbolicExpressionTreeNode SimplifyPower(ISymbolicExpressionTreeNode original) {
       return MakePower(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
+    }
+
+    private static ISymbolicExpressionTreeNode SimplifyAnalyticalQuotient(ISymbolicExpressionTreeNode original) {
+      return MakeAnalyticalQuotient(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
     }
 
@@ -730,8 +773,94 @@
       } else if (IsSquareRoot(node)) {
         return node.GetSubtree(0);
+      } else if (IsMultiplication(node)) {
+        // sqr( x * y ) = sqr(x) * sqr(y)
+        var mulNode = mulSymbol.CreateTreeNode();
+        foreach (var subtree in node.Subtrees) {
+          mulNode.AddSubtree(MakeSquare(subtree));
+        }
+        return mulNode;
+      } else if (IsAbsolute(node)) {
+        return MakeSquare(node.GetSubtree(0)); // sqr(abs(x)) = sqr(x)
+      } else if (IsExp(node)) {
+        return MakeExp(MakeProduct(node.GetSubtree(0), MakeConstant(2.0))); // sqr(exp(x)) = exp(2x)
+      } else if (IsCube(node)) {
+        return MakePower(node.GetSubtree(0), MakeConstant(6));
       } else {
         var sqrNode = sqrSymbol.CreateTreeNode();
         sqrNode.AddSubtree(node);
         return sqrNode;
+      }
+    }
+
+    private static ISymbolicExpressionTreeNode MakeCube(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(constT.Value * constT.Value * constT.Value);
+      } else if (IsFactor(node)) {
+        var factNode = node as FactorVariableTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w * w));
+      } else if (IsBinFactor(node)) {
+        var binFactor = node as BinaryFactorVariableTreeNode;
+        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight * binFactor.Weight);
+      } else if (IsCubeRoot(node)) {
+        return node.GetSubtree(0); // NOTE: not really accurate because cuberoot(x) with negative x is evaluated to NaN and after this simplification we evaluate as x
+      } else if (IsExp(node)) {
+        return MakeExp(MakeProduct(node.GetSubtree(0), MakeConstant(3)));
+      } else if (IsSquare(node)) {
+        return MakePower(node.GetSubtree(0), MakeConstant(6));
+      } else {
+        var cubeNode = cubeSymbol.CreateTreeNode();
+        cubeNode.AddSubtree(node);
+        return cubeNode;
+      }
+    }
+
+    private static ISymbolicExpressionTreeNode MakeAbs(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(Math.Abs(constT.Value));
+      } else if (IsFactor(node)) {
+        var factNode = node as FactorVariableTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Abs(w)));
+      } else if (IsBinFactor(node)) {
+        var binFactor = node as BinaryFactorVariableTreeNode;
+        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Abs(binFactor.Weight));
+      } else if (IsSquare(node) || IsExp(node) || IsSquareRoot(node) || IsCubeRoot(node)) {
+        return node; // abs(sqr(x)) = sqr(x), abs(exp(x)) = exp(x) ...
+      } else if (IsMultiplication(node)) {
+        var mul = mulSymbol.CreateTreeNode();
+        foreach (var st in node.Subtrees) {
+          mul.AddSubtree(MakeAbs(st));
+        }
+        return mul;
+      } else if (IsDivision(node)) {
+        var div = divSymbol.CreateTreeNode();
+        foreach (var st in node.Subtrees) {
+          div.AddSubtree(MakeAbs(st));
+        }
+        return div;
+      } else {
+        var absNode = absSymbol.CreateTreeNode();
+        absNode.AddSubtree(node);
+        return absNode;
+      }
+    }
+
+    // constant folding only
+    private static ISymbolicExpressionTreeNode MakeAnalyticalQuotient(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      if (IsConstant(b)) {
+        var c = b as ConstantTreeNode;
+        return MakeFraction(a, MakeConstant(Math.Sqrt(1.0 + c.Value * c.Value)));
+      } else if (IsFactor(b)) {
+        var factNode = b as FactorVariableTreeNode;
+        return MakeFraction(a, MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(1.0 + w * w))));
+      } else if (IsBinFactor(b)) {
+        var binFactor = b as BinaryFactorVariableTreeNode;
+        return MakeFraction(a, MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(1.0 + binFactor.Weight * binFactor.Weight)));
+      } else {
+        var aqNode = aqSymbol.CreateTreeNode();
+        aqNode.AddSubtree(a);
+        aqNode.AddSubtree(b);
+        return aqNode;
       }
     }
@@ -748,9 +877,28 @@
         return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(binFactor.Weight));
       } else if (IsSquare(node)) {
-        return node.GetSubtree(0);
+        return node.GetSubtree(0); // NOTE: not really accurate because sqrt(x) with negative x is evaluated to NaN and after this simplification we evaluate as x
       } else {
         var sqrtNode = sqrtSymbol.CreateTreeNode();
         sqrtNode.AddSubtree(node);
         return sqrtNode;
+      }
+    }
+
+    private static ISymbolicExpressionTreeNode MakeCubeRoot(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(Math.Pow(constT.Value, 1.0 / 3.0));
+      } else if (IsFactor(node)) {
+        var factNode = node as FactorVariableTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, 1.0 / 3.0)));
+      } else if (IsBinFactor(node)) {
+        var binFactor = node as BinaryFactorVariableTreeNode;
+        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(Math.Pow(binFactor.Weight, 1.0 / 3.0)));
+      } else if (IsCube(node)) {
+        return node.GetSubtree(0);
+      } else {
+        var cubeRootNode = cubeRootSymbol.CreateTreeNode();
+        cubeRootNode.AddSubtree(node);
+        return cubeRootNode;
       }
     }
@@ -927,4 +1075,6 @@
         // a / (b1 / b2) => (a * b2) / b1
         return MakeFraction(MakeProduct(a, b.GetSubtree(1)), b.GetSubtree(0));
+      } else if (IsAnalyticalQuotient(a)) {
+        return MakeAnalyticalQuotient(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
       } else {
         var div = divSymbol.CreateTreeNode();
@@ -1155,4 +1305,19 @@
         MergeVariablesAndConstantsInProduct(a);
         return a;
+      } else if (IsAbsolute(a) && IsAbsolute(b)) {
+        return MakeAbs(MakeProduct(a.GetSubtree(0), b.GetSubtree(0)));
+      } else if (IsAbsolute(a) && IsConstant(b)) {
+        var constNode = b as ConstantTreeNode;
+        var posF = Math.Abs(constNode.Value);
+        if (constNode.Value > 0) {
+          return MakeAbs(MakeProduct(a.GetSubtree(0), MakeConstant(posF)));
+        } else {
+          var mul = mulSymbol.CreateTreeNode();
+          mul.AddSubtree(MakeAbs(MakeProduct(a.GetSubtree(0), MakeConstant(posF))));
+          mul.AddSubtree(MakeConstant(-1.0));
+          return mul;
+        }
+      } else if (IsAnalyticalQuotient(a)) {
+        return MakeAnalyticalQuotient(MakeProduct(a.GetSubtree(0), b), a.GetSubtree(1));
       } else {
         var mul = mulSymbol.CreateTreeNode();
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs	(revision 16433)
@@ -85,4 +85,9 @@
       diff: x => -(Math.Exp(-(x * x)) * Math.Sqrt(Math.Exp(x * x)) * x) / Math.Sqrt(2 * Math.PI));
 
+    private static readonly Func<Term, UnaryFunc> abs = UnaryFunc.Factory(
+      eval: Math.Abs,
+      diff: x => Math.Sign(x)
+      );
+
     #endregion
 
@@ -213,4 +218,13 @@
         else return terms.Aggregate((a, b) => new AutoDiff.Product(a, 1.0 / b));
       }
+      if (node.Symbol is Absolute) {
+        var x1 = ConvertToAutoDiff(node.GetSubtree(0));
+        return abs(x1);
+      }
+      if (node.Symbol is AnalyticQuotient) {
+        var x1 = ConvertToAutoDiff(node.GetSubtree(0));
+        var x2 = ConvertToAutoDiff(node.GetSubtree(1));
+        return x1 / (TermBuilder.Power(1 + x2 * x2, 0.5));
+      }
       if (node.Symbol is Logarithm) {
         return AutoDiff.TermBuilder.Log(
@@ -228,4 +242,12 @@
         return AutoDiff.TermBuilder.Power(
           ConvertToAutoDiff(node.GetSubtree(0)), 0.5);
+      }
+      if (node.Symbol is Cube) {
+        return AutoDiff.TermBuilder.Power(
+          ConvertToAutoDiff(node.GetSubtree(0)), 3.0);
+      }
+      if (node.Symbol is CubeRoot) {
+        return AutoDiff.TermBuilder.Power(
+          ConvertToAutoDiff(node.GetSubtree(0)), 1.0/3.0);
       }
       if (node.Symbol is Sine) {
@@ -301,5 +323,9 @@
           !(n.Symbol is Erf) &&
           !(n.Symbol is Norm) &&
-          !(n.Symbol is StartSymbol)
+          !(n.Symbol is StartSymbol) &&
+          !(n.Symbol is Absolute) &&
+          !(n.Symbol is AnalyticQuotient) &&
+          !(n.Symbol is Cube) &&
+          !(n.Symbol is CubeRoot)
         select n).Any();
       return !containsUnknownSymbol;
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs	(revision 16433)
@@ -62,15 +62,8 @@
       if (node.SubtreeCount > 1) {
         var token = GetToken(node.Symbol);
-        if (token == "+" || token == "-" || token == "OR" || token == "XOR") {
-          strBuilder.Append("(");
-          FormatRecursively(node.Subtrees.First(), strBuilder);
-
-          foreach (var subtree in node.Subtrees.Skip(1)) {
-            strBuilder.Append(" ").Append(token).Append(" ");
-            FormatRecursively(subtree, strBuilder);
-          }
-          strBuilder.Append(")");
-
-        } else if (token == "*" || token == "/" || token == "AND") {
+        // operators
+        if (token == "+" || token == "-" || token == "OR" || token == "XOR" ||
+            token == "*" || token == "/" || token == "AND" ||
+            token == "^") {
           strBuilder.Append("(");
           FormatRecursively(node.Subtrees.First(), strBuilder);
@@ -184,5 +177,5 @@
 
     private string GetToken(ISymbol symbol) {
-      var tok = InfixExpressionParser.knownSymbols.GetBySecond(symbol).SingleOrDefault();
+      var tok = InfixExpressionParser.knownSymbols.GetBySecond(symbol).FirstOrDefault();
       if (tok == null)
         throw new ArgumentException(string.Format("Unknown symbol {0} found.", symbol.Name));
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/FullFunctionalExpressionGrammar.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/FullFunctionalExpressionGrammar.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/FullFunctionalExpressionGrammar.cs	(revision 16433)
@@ -48,4 +48,5 @@
       var mul = new Multiplication();
       var div = new Division();
+      var aq = new AnalyticQuotient();
       var mean = new Average();
       var sin = new Sine();
@@ -53,12 +54,17 @@
       var tan = new Tangent();
       var log = new Logarithm();
+      var abs = new Absolute();
       var pow = new Power();
       pow.InitialFrequency = 0.0;
       var square = new Square();
       square.InitialFrequency = 0.0;
+      var cube = new Cube();
+      cube.InitialFrequency = 0.0;
       var root = new Root();
       root.InitialFrequency = 0.0;
       var sqrt = new SquareRoot();
       sqrt.InitialFrequency = 0.0;
+      var cubeRoot = new CubeRoot();
+      cubeRoot.InitialFrequency = 0.0;
       var airyA = new AiryA();
       airyA.InitialFrequency = 0.0;
@@ -123,12 +129,12 @@
       autoregressiveVariable.Enabled = false;
 
-      var allSymbols = new List<Symbol>() { add, sub, mul, div, mean, sin, cos, tan, log, square, pow, sqrt, root, exp,
+      var allSymbols = new List<Symbol>() { add, sub, mul, div, aq, mean, abs, sin, cos, tan, log, square, cube, pow, sqrt, cubeRoot, root, exp,
         airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi, fresnelCosineIntegral, fresnelSineIntegral, gamma, hypCosineIntegral, hypSineIntegral, norm, psi, sineIntegral,
         @if, gt, lt, and, or, not,xor, timeLag, integral, derivative, constant, variableSymbol, binFactorVariable, factorVariable, laggedVariable,autoregressiveVariable, variableCondition };
-      var unaryFunctionSymbols = new List<Symbol>() { square, sqrt, sin, cos, tan, log, exp, not, timeLag, integral, derivative,
+      var unaryFunctionSymbols = new List<Symbol>() { abs, square, sqrt, cube, cubeRoot, sin, cos, tan, log, exp, not, timeLag, integral, derivative,
         airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi, fresnelCosineIntegral, fresnelSineIntegral, gamma, hypCosineIntegral, hypSineIntegral, norm, psi, sineIntegral
       };
 
-      var binaryFunctionSymbols = new List<Symbol>() { pow, root, gt, lt, variableCondition };
+      var binaryFunctionSymbols = new List<Symbol>() { pow, root, gt, lt, aq, variableCondition };
       var ternarySymbols = new List<Symbol>() { add, sub, mul, div, mean, and, or, xor };
       var terminalSymbols = new List<Symbol>() { variableSymbol, binFactorVariable, factorVariable, constant, laggedVariable, autoregressiveVariable };
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs	(revision 16433)
@@ -69,5 +69,8 @@
       var root = new Root();
       var sqrt = new SquareRoot();
+      var cube = new Cube();
+      var cubeRoot = new CubeRoot();
       var exp = new Exponential();
+      var abs = new Absolute();
 
       var airyA = new AiryA();
@@ -86,4 +89,5 @@
       var psi = new Psi();
       var sineIntegral = new SineIntegral();
+      var analyticalQuotient = new AnalyticQuotient();
 
       var @if = new IfThenElse();
@@ -114,10 +118,10 @@
       var trigonometricSymbols = new GroupSymbol(TrigonometricFunctionsName, new List<ISymbol>() { sin, cos, tan });
       var exponentialAndLogarithmicSymbols = new GroupSymbol(ExponentialFunctionsName, new List<ISymbol> { exp, log });
-      var specialFunctions = new GroupSymbol(SpecialFunctionsName, new List<ISymbol> { airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi,
-        fresnelCosineIntegral,fresnelSineIntegral,gamma,hypCosineIntegral,hypSineIntegral,norm, psi, sineIntegral});
+      var specialFunctions = new GroupSymbol(SpecialFunctionsName, new List<ISymbol> { abs, airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi,
+        fresnelCosineIntegral,fresnelSineIntegral,gamma,hypCosineIntegral,hypSineIntegral,norm, psi, sineIntegral, analyticalQuotient});
       var terminalSymbols = new GroupSymbol(TerminalsName, new List<ISymbol> { constant, variableSymbol, binFactorVariable, factorVariable });
       var realValuedSymbols = new GroupSymbol(RealValuedSymbolsName, new List<ISymbol>() { arithmeticSymbols, trigonometricSymbols, exponentialAndLogarithmicSymbols, specialFunctions, terminalSymbols });
 
-      var powerSymbols = new GroupSymbol(PowerFunctionsName, new List<ISymbol> { square, pow, sqrt, root });
+      var powerSymbols = new GroupSymbol(PowerFunctionsName, new List<ISymbol> { square, pow, sqrt, root, cube, cubeRoot });
 
       var conditionSymbols = new GroupSymbol(ConditionsName, new List<ISymbol> { @if, variableCondition });
@@ -140,7 +144,13 @@
       SetSubtreeCount(root, 2, 2);
       SetSubtreeCount(square, 1, 1);
+      SetSubtreeCount(cube, 1, 1);
       SetSubtreeCount(sqrt, 1, 1);
+      SetSubtreeCount(cubeRoot, 1, 1);
       SetSubtreeCount(exponentialAndLogarithmicSymbols, 1, 1);
-      SetSubtreeCount(specialFunctions, 1, 1);
+      foreach(var sy in specialFunctions.Symbols.Except(new[] { analyticalQuotient})) {
+        SetSubtreeCount(sy, 1, 1);
+      }
+      SetSubtreeCount(analyticalQuotient, 2, 2);
+
       SetSubtreeCount(terminalSymbols, 0, 0);
 
@@ -231,4 +241,5 @@
     public void ConfigureAsDefaultRegressionGrammar() {
       Symbols.First(s => s is Average).Enabled = false;
+      Symbols.First(s => s is Absolute).Enabled = false;
       Symbols.First(s => s.Name == TrigonometricFunctionsName).Enabled = false;
       Symbols.First(s => s.Name == PowerFunctionsName).Enabled = false;
@@ -242,4 +253,5 @@
       Symbols.First(s => s is VariableCondition).Enabled = false;
       Symbols.First(s => s is Xor).Enabled = false;
+      Symbols.First(s => s is Absolute).Enabled = false;
       Symbols.First(s => s.Name == TrigonometricFunctionsName).Enabled = false;
       Symbols.First(s => s.Name == ExponentialFunctionsName).Enabled = false;
@@ -251,4 +263,5 @@
     public void ConfigureAsDefaultTimeSeriesPrognosisGrammar() {
       Symbols.First(s => s is Average).Enabled = false;
+      Symbols.First(s => s is Absolute).Enabled = false;
       Symbols.First(s => s.Name == TrigonometricFunctionsName).Enabled = false;
       Symbols.First(s => s.Name == PowerFunctionsName).Enabled = false;
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Hashing/SymbolicExpressionTreeHash.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Hashing/SymbolicExpressionTreeHash.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Hashing/SymbolicExpressionTreeHash.cs	(revision 16433)
@@ -21,4 +21,5 @@
 
 using System;
+using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
@@ -70,5 +71,5 @@
     }
 
-    // this will only work if lh and rh are sorted 
+    // this will only work if lh and rh are sorted
     private static double ComputeSimilarity(ulong[] lh, ulong[] rh) {
       double count = 0;
@@ -90,10 +91,10 @@
     }
 
-    public static double ComputeAverageSimilarity(ISymbolicExpressionTree[] trees, bool simplify = false, bool strict = false) {
-      var total = (double)trees.Length * (trees.Length - 1) / 2;
+    public static double ComputeAverageSimilarity(IList<ISymbolicExpressionTree> trees, bool simplify = false, bool strict = false) {
+      var total = (double)trees.Count * (trees.Count - 1) / 2;
       double avg = 0;
-      var hashes = new ulong[trees.Length][];
+      var hashes = new ulong[trees.Count][];
       // build hash arrays
-      for (int i = 0; i < trees.Length; ++i) {
+      for (int i = 0; i < trees.Count; ++i) {
         var nodes = trees[i].MakeNodes(strict);
         hashes[i] = (simplify ? nodes.Simplify(HashUtil.DJBHash) : nodes.Sort(HashUtil.DJBHash)).Select(x => x.CalculatedHashValue).ToArray();
@@ -101,6 +102,6 @@
       }
       // compute similarity matrix
-      for (int i = 0; i < trees.Length - 1; ++i) {
-        for (int j = i + 1; j < trees.Length; ++j) {
+      for (int i = 0; i < trees.Count - 1; ++i) {
+        for (int j = i + 1; j < trees.Count; ++j) {
           avg += ComputeSimilarity(hashes[i], hashes[j]);
         }
@@ -109,9 +110,9 @@
     }
 
-    public static double[,] ComputeSimilarityMatrix(ISymbolicExpressionTree[] trees, bool simplify = false, bool strict = false) {
-      var sim = new double[trees.Length, trees.Length];
-      var hashes = new ulong[trees.Length][];
+    public static double[,] ComputeSimilarityMatrix(IList<ISymbolicExpressionTree> trees, bool simplify = false, bool strict = false) {
+      var sim = new double[trees.Count, trees.Count];
+      var hashes = new ulong[trees.Count][];
       // build hash arrays
-      for (int i = 0; i < trees.Length; ++i) {
+      for (int i = 0; i < trees.Count; ++i) {
         var nodes = trees[i].MakeNodes(strict);
         hashes[i] = (simplify ? nodes.Simplify(HashUtil.DJBHash) : nodes.Sort(HashUtil.DJBHash)).Select(x => x.CalculatedHashValue).ToArray();
@@ -119,6 +120,6 @@
       }
       // compute similarity matrix
-      for (int i = 0; i < trees.Length - 1; ++i) {
-        for (int j = i + 1; j < trees.Length; ++j) {
+      for (int i = 0; i < trees.Count - 1; ++i) {
+        for (int j = i + 1; j < trees.Count; ++j) {
           sim[i, j] = sim[j, i] = ComputeSimilarity(hashes[i], hashes[j]);
         }
@@ -218,5 +219,5 @@
     #region tree simplification
     // these simplification methods rely on the assumption that child nodes of the current node have already been simplified
-    // (in other words simplification should be applied in a bottom-up fashion) 
+    // (in other words simplification should be applied in a bottom-up fashion)
     public static ISymbolicExpressionTree Simplify(ISymbolicExpressionTree tree) {
       ulong hashFunction(byte[] bytes) => HashUtil.JSHash(bytes);
@@ -248,5 +249,5 @@
     }
 
-    // simplify multiplications by reducing constants and div terms  
+    // simplify multiplications by reducing constants and div terms
     public static void SimplifyMultiplication(ref HashNode<ISymbolicExpressionTreeNode>[] nodes, int i) {
       var node = nodes[i];
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 16433)
@@ -163,4 +163,5 @@
     <Compile Include="Interpreter\BatchInstruction.cs" />
     <Compile Include="Interpreter\BatchOperations.cs" />
+    <Compile Include="Interpreter\IntervalInterpreter.cs" />
     <Compile Include="Interpreter\SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs" />
     <Compile Include="Interpreter\SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs" />
@@ -213,4 +214,5 @@
     <Compile Include="SymbolicDataAnalysisSolutionImpactValuesCalculator.cs" />
     <Compile Include="Symbols\Addition.cs" />
+    <Compile Include="Symbols\AnalyticQuotient.cs" />
     <Compile Include="Symbols\And.cs" />
     <Compile Include="Symbols\AutoregressiveVariable.cs" />
@@ -223,6 +225,9 @@
     <Compile Include="Symbols\BinaryFactorVariable.cs" />
     <Compile Include="Symbols\BinaryFactorVariableTreeNode.cs" />
+    <Compile Include="Symbols\Cube.cs" />
     <Compile Include="Symbols\FactorVariableTreeNode.cs" />
     <Compile Include="Symbols\FactorVariable.cs" />
+    <Compile Include="Symbols\Absolute.cs" />
+    <Compile Include="Symbols\CubeRoot.cs" />
     <Compile Include="Symbols\VariableBase.cs" />
     <Compile Include="Symbols\VariableTreeNodeBase.cs" />
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs	(revision 16433)
@@ -42,8 +42,11 @@
   /// Expr          = ['-' | '+'] Term { '+' Term | '-' Term }
   /// Term          = Fact { '*' Fact | '/' Fact }
-  /// Fact          = '(' Expr ')' 
-  ///                 | 'LAG' '(' varId ',' ['+' | '-' ] number ')' 
-  ///                 | funcId '(' ArgList ')' 
-  ///                 | VarExpr | number
+  /// Fact          = SimpleFact [ '^' SimpleFact ]
+  /// SimpleFact    = '(' Expr ')'
+  ///                 | '{' Expr '}'
+  ///                 | 'LAG' '(' varId ',' ['+' | '-' ] number ')
+  ///                 | funcId '(' ArgList ')'
+  ///                 | VarExpr
+  ///                 | number
   /// ArgList       = Expr { ',' Expr }
   /// VarExpr       = varId OptFactorPart
@@ -95,10 +98,14 @@
         { "*", new Multiplication()},
         { "-", new Subtraction()},
+        { "^", new Power() },
+        { "ABS", new Absolute() },
         { "EXP", new Exponential()},
         { "LOG", new Logarithm()},
-        { "POW", new Power()},
+        { "POW", new Power() },
         { "ROOT", new Root()},
         { "SQR", new Square() },
         { "SQRT", new SquareRoot() },
+        { "CUBE", new Cube() },
+        { "CUBEROOT", new CubeRoot() },
         { "SIN",new Sine()},
         { "COS", new Cosine()},
@@ -119,4 +126,5 @@
         { "DAWSON", new Dawson()},
         { "EXPINT", new ExponentialIntegralEi()},
+        { "AQ", new AnalyticQuotient() },
         { "MEAN", new Average()},
         { "IF", new IfThenElse()},
@@ -167,6 +175,8 @@
             && str[pos] != '*'
             && str[pos] != '/'
+            && str[pos] != '^'
             && str[pos] != ')'
             && str[pos] != ']'
+            && str[pos] != '}'
             && str[pos] != ',') {
             sb.Append(str[pos]);
@@ -227,4 +237,7 @@
           pos++;
           yield return new Token { TokenType = TokenType.Operator, strVal = "*" };
+        } else if (str[pos] == '^') {
+          pos++;
+          yield return new Token { TokenType = TokenType.Operator, strVal = "^" };
         } else if (str[pos] == '(') {
           pos++;
@@ -239,4 +252,10 @@
           pos++;
           yield return new Token { TokenType = TokenType.RightBracket, strVal = "]" };
+        } else if (str[pos] == '{') {
+          pos++;
+          yield return new Token { TokenType = TokenType.LeftPar, strVal = "{" };
+        } else if (str[pos] == '}') {
+          pos++;
+          yield return new Token { TokenType = TokenType.RightPar, strVal = "}" };
         } else if (str[pos] == '=') {
           pos++;
@@ -360,8 +379,26 @@
     }
 
-    /// Fact          = '(' Expr ')' 
-    ///                 | 'LAG' '(' varId ',' ['+' | '-' ] number ')' 
-    ///                 | funcId '(' ArgList ')' 
-    ///                 | VarExpr | number
+    // Fact = SimpleFact ['^' SimpleFact]
+    private ISymbolicExpressionTreeNode ParseFact(Queue<Token> tokens) {
+      var expr = ParseSimpleFact(tokens);
+      var next = tokens.Peek();
+      if (next.TokenType == TokenType.Operator && next.strVal == "^") {
+        tokens.Dequeue(); // skip;
+
+        var p = GetSymbol("^").CreateTreeNode();
+        p.AddSubtree(expr);
+        p.AddSubtree(ParseSimpleFact(tokens));
+        expr = p;
+      }
+      return expr;
+    }
+
+
+    /// SimpleFact   = '(' Expr ')' 
+    ///                 | '{' Expr '}'
+    ///                 | 'LAG' '(' varId ',' ['+' | '-' ] number ')'
+    ///                 | funcId '(' ArgList ')
+    ///                 | VarExpr
+    ///                 | number
     /// ArgList       = Expr { ',' Expr }
     /// VarExpr       = varId OptFactorPart
@@ -370,12 +407,16 @@
     /// varVal        =  ident | ' ident ' | " ident "
     /// ident         =  '_' | letter { '_' | letter | digit }
-    private ISymbolicExpressionTreeNode ParseFact(Queue<Token> tokens) {
+    private ISymbolicExpressionTreeNode ParseSimpleFact(Queue<Token> tokens) {
       var next = tokens.Peek();
       if (next.TokenType == TokenType.LeftPar) {
-        tokens.Dequeue();
+        var initPar = tokens.Dequeue(); // match par type
         var expr = ParseExpr(tokens);
         var rPar = tokens.Dequeue();
         if (rPar.TokenType != TokenType.RightPar)
-          throw new ArgumentException("expected )");
+          throw new ArgumentException("expected closing parenthesis");
+        if (initPar.strVal == "(" && rPar.strVal == "}")
+          throw new ArgumentException("expected closing )");
+        if (initPar.strVal == "{" && rPar.strVal == ")")
+          throw new ArgumentException("expected closing }");
         return expr;
       } else if (next.TokenType == TokenType.Identifier) {
@@ -424,4 +465,5 @@
           if (rPar.TokenType != TokenType.RightPar)
             throw new ArgumentException("expected )");
+
 
           return funcNode;
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs	(revision 16433)
@@ -41,4 +41,5 @@
         {"*", new Multiplication()},
         {"-", new Subtraction()},
+        {"ABS", new Absolute() },
         {"EXP", new Exponential()},
         {"LOG", new Logarithm()},
@@ -47,4 +48,6 @@
         {"SQR", new Square()},
         {"SQRT", new SquareRoot()},
+        {"CUBE", new Cube()},
+        {"CUBEROOT", new CubeRoot()},
         {"SIN",new Sine()},
         {"COS", new Cosine()},
@@ -65,4 +68,5 @@
         {"DAWSON", new Dawson()},
         {"EXPINT", new ExponentialIntegralEi()},
+        {"AQ", new AnalyticQuotient() },
         {"MEAN", new Average()},
         {"IF", new IfThenElse()},
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/BatchOperations.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/BatchOperations.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/BatchOperations.cs	(revision 16433)
@@ -89,4 +89,24 @@
         a[i] = Math.Sqrt(b[i]);
     }
+
+    public static void Cube(double[] a, double[] b) {
+      for (int i = 0; i < BATCHSIZE; ++i)
+        a[i] = Math.Pow(b[i], 3d);
+    }
+
+    public static void CubeRoot(double[] a, double[] b) {
+      for (int i = 0; i < BATCHSIZE; ++i)
+        a[i] = Math.Pow(b[i], 1d / 3d);
+    }
+
+    public static void Absolute(double[] a, double[] b) {
+      for (int i = 0; i < BATCHSIZE; ++i)
+        a[i] = Math.Abs(b[i]);
+    }
+
+    public static void AnalyticQuotient(double[] a, double[] b) {
+      for (int i = 0; i < BATCHSIZE; ++i)
+        a[i] = a[i] / Math.Sqrt(1d + b[i] * b[i]);
+    }
   }
 }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs	(revision 16433)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs	(revision 16433)
@@ -0,0 +1,275 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  [Item("IntervalInterpreter", "Intperter for calculation of intervals of symbolic models.")]
+  public sealed class IntervalInterpreter : ParameterizedNamedItem, IStatefulItem {
+
+    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
+
+    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
+    }
+
+    public int EvaluatedSolutions {
+      get { return EvaluatedSolutionsParameter.Value.Value; }
+      set { EvaluatedSolutionsParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    private IntervalInterpreter(bool deserializing) : base(deserializing) { }
+    private IntervalInterpreter(IntervalInterpreter original, Cloner cloner)
+        : base(original, cloner) { }
+
+    public IntervalInterpreter()
+        : base("IntervalInterpreter", "Intperter for calculation of intervals of symbolic models.") {
+      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new IntervalInterpreter(this, cloner);
+    }
+
+    private readonly object syncRoot = new object();
+
+    #region IStatefulItem Members
+    public void InitializeState() {
+      EvaluatedSolutions = 0;
+    }
+    public void ClearState() { }
+    #endregion
+
+    public Interval GetSymbolicExressionTreeInterval(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows = null) {
+      var variableRanges = DatasetUtil.GetVariableRanges(dataset, rows);
+      return GetSymbolicExressionTreeInterval(tree, variableRanges);
+    }
+
+    public Interval GetSymbolicExressionTreeIntervals(ISymbolicExpressionTree tree, IDataset dataset,
+      out Dictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals, IEnumerable<int> rows = null) {
+      var variableRanges = DatasetUtil.GetVariableRanges(dataset, rows);
+      return GetSymbolicExressionTreeIntervals(tree, variableRanges, out nodeIntervals);
+    }
+
+    public Interval GetSymbolicExressionTreeInterval(ISymbolicExpressionTree tree, Dictionary<string, Interval> variableRanges) {
+      lock (syncRoot) {
+        EvaluatedSolutions++;
+      }
+      int instructionCount = 0;
+      var instructions = PrepareInterpreterState(tree, variableRanges);
+      var outputInterval = Evaluate(instructions, ref instructionCount);
+
+      return outputInterval;
+    }
+
+
+    public Interval GetSymbolicExressionTreeIntervals(ISymbolicExpressionTree tree,
+      Dictionary<string, Interval> variableRanges, out Dictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals) {
+      lock (syncRoot) {
+        EvaluatedSolutions++;
+      }
+      int instructionCount = 0;
+      var intervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>();
+      var instructions = PrepareInterpreterState(tree, variableRanges);
+      var outputInterval = Evaluate(instructions, ref instructionCount, intervals);
+
+      nodeIntervals = intervals;
+
+      return outputInterval;
+    }
+
+
+    private static Instruction[] PrepareInterpreterState(ISymbolicExpressionTree tree, Dictionary<string, Interval> variableRanges) {
+      if (variableRanges == null)
+        throw new ArgumentNullException("No variablew ranges are present!", nameof(variableRanges));
+
+      //Check if all variables used in the tree are present in the dataset
+      foreach (var variable in tree.IterateNodesPrefix().OfType<VariableTreeNode>().Select(n => n.VariableName).Distinct()) {
+        if (!variableRanges.ContainsKey(variable)) throw new InvalidOperationException($"No ranges for variable {variable} is present");
+      }
+
+      Instruction[] code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
+      foreach (Instruction instr in code.Where(i => i.opCode == OpCodes.Variable)) {
+        var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
+        instr.data = variableRanges[variableTreeNode.VariableName];
+      }
+      return code;
+    }
+
+    private Interval Evaluate(Instruction[] instructions, ref int instructionCounter, Dictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals = null) {
+      Instruction currentInstr = instructions[instructionCounter];
+      //Use ref parameter, because the tree will be iterated through recursively from the left-side branch to the right side
+      //Update instructionCounter, whenever Evaluate is called
+      instructionCounter++;
+      Interval result = null;
+
+      switch (currentInstr.opCode) {
+        //Variables, Constants, ...
+        case OpCodes.Variable: {
+            var variableTreeNode = (VariableTreeNode)currentInstr.dynamicNode;
+            var weightInterval = new Interval(variableTreeNode.Weight, variableTreeNode.Weight);
+            var variableInterval = (Interval)currentInstr.data;
+
+            result = Interval.Multiply(variableInterval, weightInterval);
+            break;
+          }
+        case OpCodes.Constant: {
+            var constTreeNode = (ConstantTreeNode)currentInstr.dynamicNode;
+            result = new Interval(constTreeNode.Value, constTreeNode.Value);
+            break;
+          }
+        //Elementary arithmetic rules
+        case OpCodes.Add: {
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            for (int i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+              result = Interval.Add(result, argumentInterval);
+            }
+            break;
+          }
+        case OpCodes.Sub: {
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            if (currentInstr.nArguments == 1)
+              result = Interval.Multiply(new Interval(-1, -1), result);
+
+            for (int i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+              result = Interval.Subtract(result, argumentInterval);
+            }
+            break;
+          }
+        case OpCodes.Mul: {
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            for (int i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+              result = Interval.Multiply(result, argumentInterval);
+            }
+            break;
+          }
+        case OpCodes.Div: {
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            if (currentInstr.nArguments == 1)
+              result = Interval.Divide(new Interval(1, 1), result);
+
+            for (int i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+              result = Interval.Divide(result, argumentInterval);
+            }
+            break;
+          }
+        //Trigonometric functions
+        case OpCodes.Sin: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Interval.Sine(argumentInterval);
+            break;
+          }
+        case OpCodes.Cos: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Interval.Cosine(argumentInterval);
+            break;
+          }
+        case OpCodes.Tan: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Interval.Tangens(argumentInterval);
+            break;
+          }
+        //Exponential functions
+        case OpCodes.Log: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Interval.Logarithm(argumentInterval);
+            break;
+          }
+        case OpCodes.Exp: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Interval.Exponential(argumentInterval);
+            break;
+          }
+        case OpCodes.Power: {
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            for (int i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+              result = Interval.Power(result, argumentInterval);
+            }
+            break;
+          }
+        case OpCodes.Square: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Interval.Square(argumentInterval);
+            break;
+          }
+        case OpCodes.Root: {
+            result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            for (int i = 1; i < currentInstr.nArguments; i++) {
+              var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+              result = Interval.Root(result, argumentInterval);
+            }
+            break;
+          }
+        case OpCodes.SquareRoot: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Interval.SquareRoot(argumentInterval);
+            break;
+          }
+        default:
+          throw new NotSupportedException($"The tree contains the unknown symbol {currentInstr.dynamicNode.Symbol}");
+      }
+
+      if (nodeIntervals != null)
+        nodeIntervals.Add(currentInstr.dynamicNode, result);
+
+      return result;
+    }
+
+    public static bool IsCompatible(ISymbolicExpressionTree tree) {
+      var containsUnknownSyumbol = (
+        from n in tree.Root.GetSubtree(0).IterateNodesPrefix()
+        where
+          !(n.Symbol is StartSymbol) &&
+          !(n.Symbol is Addition) &&
+          !(n.Symbol is Subtraction) &&
+          !(n.Symbol is Multiplication) &&
+          !(n.Symbol is Division) &&
+          !(n.Symbol is Sine) &&
+          !(n.Symbol is Cosine) &&
+          !(n.Symbol is Tangent) &&
+          !(n.Symbol is Logarithm) &&
+          !(n.Symbol is Exponential) &&
+          !(n.Symbol is Power) &&
+          !(n.Symbol is Square) &&
+          !(n.Symbol is Root) &&
+          !(n.Symbol is SquareRoot) &&
+          !(n.Symbol is Problems.DataAnalysis.Symbolic.Variable) &&
+          !(n.Symbol is Constant)
+        select n).Any();
+      return !containsUnknownSyumbol;
+    }
+  }
+}
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs	(revision 16433)
@@ -46,5 +46,4 @@
     public const byte OR = 14;
     public const byte NOT = 15;
-    public const byte XOR = 45;
 
 
@@ -83,6 +82,11 @@
     public const byte Erf = 43;
     public const byte Bessel = 44;
+    public const byte XOR = 45;
     public const byte FactorVariable = 46;
     public const byte BinaryFactorVariable = 47;
+    public const byte Absolute = 48;
+    public const byte AnalyticQuotient = 49;
+    public const byte Cube = 50;
+    public const byte CubeRoot = 51;
 
 
@@ -113,5 +117,5 @@
       { typeof(Power),OpCodes.Power},
       { typeof(Root),OpCodes.Root},
-      { typeof(TimeLag), OpCodes.TimeLag}, 
+      { typeof(TimeLag), OpCodes.TimeLag},
       { typeof(Integral), OpCodes.Integral},
       { typeof(Derivative), OpCodes.Derivative},
@@ -135,5 +139,9 @@
       { typeof(Bessel), OpCodes.Bessel},
       { typeof(FactorVariable), OpCodes.FactorVariable },
-      { typeof(BinaryFactorVariable), OpCodes.BinaryFactorVariable }
+      { typeof(BinaryFactorVariable), OpCodes.BinaryFactorVariable },
+      { typeof(Absolute), OpCodes.Absolute },
+      { typeof(AnalyticQuotient), OpCodes.AnalyticQuotient },
+      { typeof(Cube), OpCodes.Cube },
+      { typeof(CubeRoot), OpCodes.CubeRoot }
     };
 
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs	(revision 16433)
@@ -41,4 +41,5 @@
 
     #region method info for the commonly called functions
+    private static readonly MethodInfo Abs = typeof(Math).GetMethod("Abs", new[] { typeof(double) });
     private static readonly MethodInfo Sin = typeof(Math).GetMethod("Sin", new[] { typeof(double) });
     private static readonly MethodInfo Cos = typeof(Math).GetMethod("Cos", new[] { typeof(double) });
@@ -207,4 +208,8 @@
             return Expression.Divide(result, Expression.Constant((double)node.SubtreeCount));
           }
+        case OpCodes.Absolute: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            return Expression.Call(Abs, arg);
+          }
         case OpCodes.Cos: {
             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
@@ -222,4 +227,8 @@
             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
             return Expression.Power(arg, Expression.Constant(2.0));
+          }
+        case OpCodes.Cube: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            return Expression.Power(arg, Expression.Constant(3.0));
           }
         case OpCodes.Power: {
@@ -231,4 +240,8 @@
             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
             return Expression.Call(Sqrt, arg);
+          }
+        case OpCodes.CubeRoot: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            return Expression.Power(arg, Expression.Constant(1.0 / 3.0));
           }
         case OpCodes.Root: {
@@ -493,4 +506,13 @@
                 Expression.Assign(result, Expression.Call(Bessel, arg))),
               result);
+          }
+        case OpCodes.AnalyticQuotient: {
+            var x1 = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var x2 = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
+            return Expression.Divide(x1, 
+              Expression.Call(Sqrt, 
+              Expression.Add(
+                Expression.Constant(1.0),
+                Expression.Multiply(x2, x2))));
           }
         case OpCodes.IfThenElse: {
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs	(revision 16433)
@@ -36,5 +36,4 @@
       Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
     }
-
 
     [StorableConstructor]
@@ -111,5 +110,6 @@
 
           case OpCodes.Root: {
-              Root(instr.buf, code[c].buf);
+              Load(instr.buf, code[c].buf);
+              Root(instr.buf, code[c + 1].buf);
               break;
             }
@@ -120,6 +120,16 @@
             }
 
+          case OpCodes.Cube: {
+              Cube(instr.buf, code[c].buf);
+              break;
+            }
+          case OpCodes.CubeRoot: {
+              CubeRoot(instr.buf, code[c].buf);
+              break;
+            }
+
           case OpCodes.Power: {
-              Pow(instr.buf, code[c].buf);
+              Load(instr.buf, code[c].buf);
+              Pow(instr.buf, code[c + 1].buf);
               break;
             }
@@ -149,12 +159,29 @@
               break;
             }
+
+          case OpCodes.Absolute: {
+              Absolute(instr.buf, code[c].buf);
+              break;
+            }
+
+          case OpCodes.AnalyticQuotient: {
+              Load(instr.buf, code[c].buf);
+              AnalyticQuotient(instr.buf, code[c + 1].buf);
+              break;
+            }
         }
       }
     }
+
+    private readonly object syncRoot = new object();
 
     [ThreadStatic]
     private Dictionary<string, double[]> cachedData;
 
+    [ThreadStatic]
+    private IDataset dataset;
+
     private void InitCache(IDataset dataset) {
+      this.dataset = dataset;
       cachedData = new Dictionary<string, double[]>();
       foreach (var v in dataset.DoubleVariables) {
@@ -165,8 +192,13 @@
     public void InitializeState() {
       cachedData = null;
+      dataset = null;
       EvaluatedSolutions = 0;
     }
 
     private double[] GetValues(ISymbolicExpressionTree tree, IDataset dataset, int[] rows) {
+      if (cachedData == null || this.dataset != dataset) {
+        InitCache(dataset);
+      }
+
       var code = Compile(tree, dataset, OpCodes.MapSymbolToOpCode);
       var remainingRows = rows.Length % BATCHSIZE;
@@ -185,11 +217,13 @@
       }
 
+      // when evaluation took place without any error, we can increment the counter
+      lock (syncRoot) {
+        EvaluatedSolutions++;
+      }
+
       return result;
     }
 
     public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, int[] rows) {
-      if (cachedData == null) {
-        InitCache(dataset);
-      }
       return GetValues(tree, dataset, rows);
     }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 16433)
@@ -50,4 +50,5 @@
     private static MethodInfo round = typeof(Math).GetMethod("Round", new Type[] { typeof(double) });
     private static MethodInfo sqrt = typeof(Math).GetMethod("Sqrt", new Type[] { typeof(double) });
+    private static MethodInfo abs = typeof(Math).GetMethod("Abs", new Type[] { typeof(double) });
 
     private static MethodInfo airyA = thisType.GetMethod("AiryA", new Type[] { typeof(double) });
@@ -264,4 +265,9 @@
             return;
           }
+        case OpCodes.Absolute: {
+            CompileInstructions(il, state, ds);
+            il.Emit(System.Reflection.Emit.OpCodes.Call, abs);
+            return;
+          }
         case OpCodes.Cos: {
             CompileInstructions(il, state, ds);
@@ -311,4 +317,10 @@
             return;
           }
+        case OpCodes.Cube: {
+            CompileInstructions(il, state, ds);
+            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 3.0);
+            il.Emit(System.Reflection.Emit.OpCodes.Call, power);
+            return;
+          }
         case OpCodes.SquareRoot: {
             CompileInstructions(il, state, ds);
@@ -316,4 +328,10 @@
             return;
           }
+        case OpCodes.CubeRoot: {
+            CompileInstructions(il, state, ds);
+            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0 / 3.0);
+            il.Emit(System.Reflection.Emit.OpCodes.Call, power);
+            return;
+          }
         case OpCodes.AiryA: {
             CompileInstructions(il, state, ds);
@@ -389,4 +407,16 @@
             CompileInstructions(il, state, ds);
             il.Emit(System.Reflection.Emit.OpCodes.Call, sinIntegral);
+            return;
+          }
+        case OpCodes.AnalyticQuotient: {
+            CompileInstructions(il, state, ds); // x1
+            CompileInstructions(il, state, ds); // x2
+
+            il.Emit(System.Reflection.Emit.OpCodes.Dup);
+            il.Emit(System.Reflection.Emit.OpCodes.Mul); // x2*x2
+            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0);
+            il.Emit(System.Reflection.Emit.OpCodes.Mul); // 1+x2*x2
+            il.Emit(System.Reflection.Emit.OpCodes.Call, sqrt);
+            il.Emit(System.Reflection.Emit.OpCodes.Div);
             return;
           }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 16433)
@@ -203,4 +203,7 @@
             return sum / currentInstr.nArguments;
           }
+        case OpCodes.Absolute: {
+            return Math.Abs(Evaluate(dataset, ref row, state));
+          }
         case OpCodes.Cos: {
             return Math.Cos(Evaluate(dataset, ref row, state));
@@ -214,4 +217,7 @@
         case OpCodes.Square: {
             return Math.Pow(Evaluate(dataset, ref row, state), 2);
+          }
+        case OpCodes.Cube: {
+            return Math.Pow(Evaluate(dataset, ref row, state), 3);
           }
         case OpCodes.Power: {
@@ -223,4 +229,7 @@
             return Math.Sqrt(Evaluate(dataset, ref row, state));
           }
+        case OpCodes.CubeRoot: {
+            return Math.Pow(Evaluate(dataset, ref row, state), 1.0 / 3.0);
+          }
         case OpCodes.Root: {
             double x = Evaluate(dataset, ref row, state);
@@ -340,4 +349,10 @@
             if (double.IsNaN(x)) return double.NaN;
             else return alglib.besseli0(x);
+          }
+
+        case OpCodes.AnalyticQuotient: {
+            var x1 = Evaluate(dataset, ref row, state);
+            var x2 = Evaluate(dataset, ref row, state);
+            return x1 / Math.Pow(1 + x2 * x2, 0.5);
           }
         case OpCodes.IfThenElse: {
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 16433)
@@ -215,4 +215,8 @@
           if (instr.nArguments == 1) p = 1.0 / p;
           instr.value = p;
+        } else if (instr.opCode == OpCodes.AnalyticQuotient) {
+          var x1 = code[instr.childIndex].value;
+          var x2 = code[instr.childIndex + 1].value;
+          instr.value = x1 / Math.Sqrt(1 + x2 * x2);
         } else if (instr.opCode == OpCodes.Average) {
           double s = code[instr.childIndex].value;
@@ -221,4 +225,6 @@
           }
           instr.value = s / instr.nArguments;
+        } else if (instr.opCode == OpCodes.Absolute) {
+          instr.value = Math.Abs(code[instr.childIndex].value);
         } else if (instr.opCode == OpCodes.Cos) {
           instr.value = Math.Cos(code[instr.childIndex].value);
@@ -229,4 +235,6 @@
         } else if (instr.opCode == OpCodes.Square) {
           instr.value = Math.Pow(code[instr.childIndex].value, 2);
+        } else if (instr.opCode == OpCodes.Cube) {
+          instr.value = Math.Pow(code[instr.childIndex].value, 3);
         } else if (instr.opCode == OpCodes.Power) {
           double x = code[instr.childIndex].value;
@@ -235,4 +243,6 @@
         } else if (instr.opCode == OpCodes.SquareRoot) {
           instr.value = Math.Sqrt(code[instr.childIndex].value);
+        } else if (instr.opCode == OpCodes.CubeRoot) {
+          instr.value = Math.Pow(code[instr.childIndex].value, 1.0 / 3.0);
         } else if (instr.opCode == OpCodes.Root) {
           double x = code[instr.childIndex].value;
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeNativeInterpreter.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeNativeInterpreter.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeNativeInterpreter.cs	(revision 16433)
@@ -59,5 +59,4 @@
     protected SymbolicDataAnalysisExpressionTreeNativeInterpreter(bool deserializing) : base(deserializing) { }
 
-
     protected SymbolicDataAnalysisExpressionTreeNativeInterpreter(SymbolicDataAnalysisExpressionTreeNativeInterpreter original, Cloner cloner) : base(original, cloner) {
     }
@@ -99,12 +98,11 @@
     private static Dictionary<string, GCHandle> cachedData;
 
+    [ThreadStatic]
+    private IDataset dataset;
+
     public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows) {
       if (!rows.Any()) return Enumerable.Empty<double>();
 
-      lock (syncRoot) {
-        EvaluatedSolutions++; // increment the evaluated solutions counter
-      }
-
-      if (cachedData == null) {
+      if (cachedData == null || this.dataset != dataset) {
         InitCache(dataset);
       }
@@ -116,8 +114,25 @@
 
       NativeWrapper.GetValuesVectorized(code, code.Length, rowsArray, rowsArray.Length, result);
+
+      // when evaluation took place without any error, we can increment the counter
+      lock (syncRoot) {
+        EvaluatedSolutions++;
+      }
+
       return result;
     }
 
     private void InitCache(IDataset dataset) {
+      this.dataset = dataset;
+
+      // free handles to old data
+      if (cachedData != null) {
+        foreach (var gch in cachedData.Values) {
+          gch.Free();
+        }
+        cachedData = null;
+      }
+
+      // cache new data
       cachedData = new Dictionary<string, GCHandle>();
       foreach (var v in dataset.DoubleVariables) {
@@ -135,4 +150,5 @@
         cachedData = null;
       }
+      dataset = null;
       EvaluatedSolutions = 0;
     }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Absolute.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Absolute.cs	(revision 16433)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Absolute.cs	(revision 16433)
@@ -0,0 +1,48 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  [Item("Absolute", "Symbol that represents the absolute value function abs(x).")]
+  public sealed class Absolute : Symbol {
+    private const int minimumArity = 1;
+    private const int maximumArity = 1;
+
+    public override int MinimumArity {
+      get { return minimumArity; }
+    }
+    public override int MaximumArity {
+      get { return maximumArity; }
+    }
+
+    [StorableConstructor]
+    private Absolute(bool deserializing) : base(deserializing) { }
+    private Absolute(Absolute original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Absolute(this, cloner);
+    }
+    public Absolute() : base("Absolute", "Symbol that represents the absolute value function.") { }
+  }
+}
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/AnalyticQuotient.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/AnalyticQuotient.cs	(revision 16433)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/AnalyticQuotient.cs	(revision 16433)
@@ -0,0 +1,52 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  [Item("Analytic Quotient", "The analytic quotient function aq(a,b) = a / sqrt(b²+1) can be used as an " +
+    "alternative to protected division. See H. Drieberg and P. Rocket, The Use of an Analytic Quotient Operator" +
+    " in Genetic Programming. IEEE Transactions on Evolutionary Computation, Vol. 17, No. 1, February 2013, pp. 146 -- 152")]
+  public sealed class AnalyticQuotient : Symbol {
+    private const int minimumArity = 2;
+    private const int maximumArity = 2;
+
+    public override int MinimumArity {
+      get { return minimumArity; }
+    }
+    public override int MaximumArity {
+      get { return maximumArity; }
+    }
+
+    [StorableConstructor]
+    private AnalyticQuotient(bool deserializing) : base(deserializing) { }
+    private AnalyticQuotient(AnalyticQuotient original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AnalyticQuotient(this, cloner);
+    }
+    public AnalyticQuotient() : base("AnalyticQuotient", "The analytic quotient function aq(a,b) = a / sqrt(b²+1) can be used as an " +
+    "alternative to protected division. See H. Drieberg and P. Rocket, The Use of an Analytic Quotient Operator" +
+    " in Genetic Programming. IEEE Transactions on Evolutionary Computation, Vol. 17, No. 1, February 2013, pp. 146 -- 152") { }
+  }
+}
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Cube.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Cube.cs	(revision 16433)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Cube.cs	(revision 16433)
@@ -0,0 +1,48 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  [Item("Cube", "Symbol that represents the cube function.")]
+  public sealed class Cube : Symbol {
+    private const int minimumArity = 1;
+    private const int maximumArity = 1;
+
+    public override int MinimumArity {
+      get { return minimumArity; }
+    }
+    public override int MaximumArity {
+      get { return maximumArity; }
+    }
+
+    [StorableConstructor]
+    private Cube(bool deserializing) : base(deserializing) { }
+    private Cube(Cube original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Cube(this, cloner);
+    }
+    public Cube() : base("Cube", "Symbol that represents the cube function.") { }
+  }
+}
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/CubeRoot.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/CubeRoot.cs	(revision 16433)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/CubeRoot.cs	(revision 16433)
@@ -0,0 +1,48 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  [Item("CubeRoot", "Symbol that represents the cube root function.")]
+  public sealed class CubeRoot : Symbol {
+    private const int minimumArity = 1;
+    private const int maximumArity = 1;
+
+    public override int MinimumArity {
+      get { return minimumArity; }
+    }
+    public override int MaximumArity {
+      get { return maximumArity; }
+    }
+
+    [StorableConstructor]
+    private CubeRoot(bool deserializing) : base(deserializing) { }
+    private CubeRoot(CubeRoot original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CubeRoot(this, cloner);
+    }
+    public CubeRoot() : base("CubeRoot", "Symbol that represents the cube root function.") { }
+  }
+}
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/ClassificationSolutionVariableImpactsView.Designer.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/ClassificationSolutionVariableImpactsView.Designer.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/ClassificationSolutionVariableImpactsView.Designer.cs	(revision 16433)
@@ -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: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/ClassificationSolutionVariableImpactsView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/ClassificationSolutionVariableImpactsView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/ClassificationSolutionVariableImpactsView.cs	(revision 16433)
@@ -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; }
@@ -152,35 +120,73 @@
 
       //Prepare arguments
-      var mainForm = (MainForm.WindowsForms.MainForm)MainFormManager.MainForm;
       var replMethod = (ClassificationSolutionVariableImpactsCalculator.ReplacementMethodEnum)replacementComboBox.Items[replacementComboBox.SelectedIndex];
       var factorReplMethod = (ClassificationSolutionVariableImpactsCalculator.FactorReplacementMethodEnum)factorVarReplComboBox.Items[factorVarReplComboBox.SelectedIndex];
       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 = Progress.Show(this, "Calculating variable impacts for " + Content.Name);
+      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 {
+        Progress.Hide(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.Message = 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 +197,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 +208,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 +217,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: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Views/3.4/MenuItems/ShrinkDataAnalysisRunsMenuItem.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Views/3.4/MenuItems/ShrinkDataAnalysisRunsMenuItem.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Views/3.4/MenuItems/ShrinkDataAnalysisRunsMenuItem.cs	(revision 16433)
@@ -72,6 +72,6 @@
     public override void Execute() {
       IContentView activeView = (IContentView)MainFormManager.MainForm.ActiveView;
-      var mainForm = (MainForm.WindowsForms.MainForm)MainFormManager.MainForm;
-      mainForm.AddOperationProgressToContent(activeView.Content, "Removing duplicate datasets.");
+      var content = activeView.Content;
+      Progress.Show(content, "Removing duplicate datasets.", ProgressMode.Indeterminate);
 
       Action<IContentView> action = (view) => DatasetUtil.RemoveDuplicateDatasets(view.Content);
@@ -79,5 +79,5 @@
       action.BeginInvoke(activeView, delegate (IAsyncResult result) {
         action.EndInvoke(result);
-        mainForm.RemoveOperationProgressFromContent(activeView.Content);
+        Progress.Hide(content);
       }, null);
     }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionVariableImpactsView.Designer.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionVariableImpactsView.Designer.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionVariableImpactsView.Designer.cs	(revision 16433)
@@ -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: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionVariableImpactsView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionVariableImpactsView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionVariableImpactsView.cs	(revision 16433)
@@ -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,13 +106,9 @@
       UpdateOrdering();
     }
-
     private void ascendingCheckBox_CheckedChanged(object sender, EventArgs e) {
       UpdateOrdering();
     }
 
-
     private async void UpdateVariableImpact() {
-      IProgress progress;
-
       //Check if the selection is valid
       if (Content == null) { return; }
@@ -125,26 +118,16 @@
 
       //Prepare arguments
-      var mainForm = (MainForm.WindowsForms.MainForm)MainFormManager.MainForm;
       var replMethod = (RegressionSolutionVariableImpactsCalculator.ReplacementMethodEnum)replacementComboBox.Items[replacementComboBox.SelectedIndex];
       var factorReplMethod = (RegressionSolutionVariableImpactsCalculator.FactorReplacementMethodEnum)factorVarReplComboBox.Items[factorVarReplComboBox.SelectedIndex];
       var dataPartition = (RegressionSolutionVariableImpactsCalculator.DataPartitionEnum)dataPartitionComboBox.SelectedItem;
 
-      variableImactsArrayView.Caption = Content.Name + " Variable Impacts";
-      progress = mainForm.AddOperationProgressToView(this, "Calculating variable impacts for " + Content.Name);
-      progress.ProgressValue = 0;
-
+      variableImpactsArrayView.Caption = Content.Name + " Variable Impacts";
+      var progress = Progress.Show(this, "Calculating variable impacts for " + Content.Name);
       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 +135,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 {
-        ((MainForm.WindowsForms.MainForm)MainFormManager.MainForm).RemoveOperationProgressFromView(this);
-      }
+      }
+      finally {
+        Progress.Hide(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.Message = 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 +221,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: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis/3.4/DatasetUtil.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis/3.4/DatasetUtil.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis/3.4/DatasetUtil.cs	(revision 16433)
@@ -93,4 +93,20 @@
     }
 
+    public static Dictionary<string, Interval> GetVariableRanges(IDataset dataset, IEnumerable<int> rows = null) {
+      Dictionary<string, Interval> variableRanges = new Dictionary<string, Interval>();
+
+      foreach (var variable in dataset.VariableNames) {
+        IEnumerable<double> values = null;
+
+        if (rows == null) values = dataset.GetDoubleValues(variable);
+        else values = dataset.GetDoubleValues(variable, rows);
+
+        var range = Interval.GetInterval(values);
+        variableRanges.Add(variable, range);
+      }
+
+      return variableRanges;
+    }
+
     private static bool GetEqualValues(this Dictionary<ValuesType, ValuesType> variableValuesMapping, ValuesType originalValues, out ValuesType matchingValues) {
       if (variableValuesMapping.ContainsKey(originalValues)) {
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 16433)
@@ -140,4 +140,5 @@
     <Compile Include="Implementation\ConstantModel.cs" />
     <Compile Include="Implementation\DataAnalysisModel.cs" />
+    <Compile Include="Implementation\Interval.cs" />
     <Compile Include="Implementation\Regression\ConfidenceBoundRegressionSolution.cs" />
     <Compile Include="Implementation\Regression\ConstantRegressionModel.cs" />
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolutionVariableImpactsCalculator.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolutionVariableImpactsCalculator.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolutionVariableImpactsCalculator.cs	(revision 16433)
@@ -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: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval.cs	(revision 16433)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval.cs	(revision 16433)
@@ -0,0 +1,219 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public class Interval : IEquatable<Interval> {
+    public double LowerBound { get; private set; }
+    public double UpperBound { get; private set; }
+
+    public Interval(double lowerBound, double upperBound) {
+      if (lowerBound > upperBound)
+        throw new ArgumentException("LowerBound must be smaller than UpperBound.");
+
+      this.LowerBound = lowerBound;
+      this.UpperBound = upperBound;
+    }
+
+    public bool Contains(double value) {
+      return LowerBound <= value && value <= UpperBound;
+    }
+
+    public override string ToString() {
+      return "Interval: [" + LowerBound + ", " + UpperBound + "]";
+    }
+
+    public bool IsInfiniteOrUndefined {
+      get {
+        return double.IsInfinity(LowerBound) || double.IsInfinity(UpperBound) ||
+                double.IsNaN(LowerBound) || double.IsNaN(UpperBound);
+      }
+    }
+
+    public static Interval GetInterval(IEnumerable<double> values) {
+      if (values == null) throw new ArgumentNullException("values");
+      if (!values.Any()) throw new ArgumentException($"No values are present.");
+
+      var min = double.MaxValue;
+      var max = double.MinValue;
+
+      foreach (var value in values) {
+        //If an value is NaN return an interval [NaN, NaN]
+        if (double.IsNaN(value)) return new Interval(double.NaN, double.NaN);
+
+        if (value < min) min = value;
+        if (value > max) max = value;
+      }
+
+      return new Interval(min, max);
+    }
+
+    #region Equals, GetHashCode, == , !=
+    public bool Equals(Interval other) {
+      if (other == null)
+        return false;
+
+      return (UpperBound.IsAlmost(other.UpperBound) || (double.IsNaN(UpperBound) && double.IsNaN(other.UpperBound)))
+        && (LowerBound.IsAlmost(other.LowerBound) || (double.IsNaN(LowerBound) && double.IsNaN(other.LowerBound)));
+    }
+
+    public override bool Equals(object obj) {
+      return Equals(obj as Interval);
+    }
+
+    public override int GetHashCode() {
+      return LowerBound.GetHashCode() ^ UpperBound.GetHashCode();
+    }
+
+    public static bool operator ==(Interval interval1, Interval interval2) {
+      if (ReferenceEquals(interval1, null)) return ReferenceEquals(interval2, null);
+      return interval1.Equals(interval2);
+    }
+    public static bool operator !=(Interval interval1, Interval interval2) {
+      return !(interval1 == interval2);
+    }
+    #endregion
+
+    #region operations
+
+    // [x1,x2] + [y1,y2] = [x1 + y1,x2 + y2]
+    public static Interval Add(Interval a, Interval b) {
+      return new Interval(a.LowerBound + b.LowerBound, a.UpperBound + b.UpperBound);
+    }
+
+    // [x1,x2] − [y1,y2] = [x1 − y2,x2 − y1]
+    public static Interval Subtract(Interval a, Interval b) {
+      return new Interval(a.LowerBound - b.UpperBound, a.UpperBound - b.LowerBound);
+    }
+
+    // [x1,x2] * [y1,y2] = [min(x1*y1,x1*y2,x2*y1,x2*y2),max(x1*y1,x1*y2,x2*y1,x2*y2)]
+    public static Interval Multiply(Interval a, Interval b) {
+      double v1 = a.LowerBound * b.LowerBound;
+      double v2 = a.LowerBound * b.UpperBound;
+      double v3 = a.UpperBound * b.LowerBound;
+      double v4 = a.UpperBound * b.UpperBound;
+
+      double min = Math.Min(Math.Min(v1, v2), Math.Min(v3, v4));
+      double max = Math.Max(Math.Min(v1, v2), Math.Max(v3, v4));
+      return new Interval(min, max);
+    }
+
+    //mkommend: Division by intervals containing 0 is implemented as defined in
+    //http://en.wikipedia.org/wiki/Interval_arithmetic
+    public static Interval Divide(Interval a, Interval b) {
+      if (b.Contains(0.0)) {
+        if (b.LowerBound.IsAlmost(0.0)) return Interval.Multiply(a, new Interval(1.0 / b.UpperBound, double.PositiveInfinity));
+        else if (b.UpperBound.IsAlmost(0.0)) return Interval.Multiply(a, new Interval(double.NegativeInfinity, 1.0 / b.LowerBound));
+        else return new Interval(double.NegativeInfinity, double.PositiveInfinity);
+      }
+      return Interval.Multiply(a, new Interval(1.0 / b.UpperBound, 1.0 / b.LowerBound));
+    }
+
+    public static Interval Sine(Interval a) {
+      if (Math.Abs(a.UpperBound - a.LowerBound) >= Math.PI * 2) return new Interval(-1, 1);
+
+      //divide the interval by PI/2 so that the optima lie at x element of N (0,1,2,3,4,...)
+      double Pihalf = Math.PI / 2;
+      Interval scaled = Interval.Divide(a, new Interval(Pihalf, Pihalf));
+      //move to positive scale
+      if (scaled.LowerBound < 0) {
+        int periodsToMove = Math.Abs((int)scaled.LowerBound / 4) + 1;
+        scaled = Interval.Add(scaled, new Interval(periodsToMove * 4, periodsToMove * 4));
+      }
+
+      double scaledLowerBound = scaled.LowerBound % 4.0;
+      double scaledUpperBound = scaled.UpperBound % 4.0;
+      if (scaledUpperBound < scaledLowerBound) scaledUpperBound += 4.0;
+      List<double> sinValues = new List<double>();
+      sinValues.Add(Math.Sin(scaledLowerBound * Pihalf));
+      sinValues.Add(Math.Sin(scaledUpperBound * Pihalf));
+
+      int startValue = (int)Math.Ceiling(scaledLowerBound);
+      while (startValue < scaledUpperBound) {
+        sinValues.Add(Math.Sin(startValue * Pihalf));
+        startValue += 1;
+      }
+
+      return new Interval(sinValues.Min(), sinValues.Max());
+    }
+    public static Interval Cosine(Interval a) {
+      return Interval.Sine(Interval.Subtract(a, new Interval(Math.PI / 2, Math.PI / 2)));
+    }
+    public static Interval Tangens(Interval a) {
+      return Interval.Divide(Interval.Sine(a), Interval.Cosine(a));
+    }
+
+    public static Interval Logarithm(Interval a) {
+      return new Interval(Math.Log(a.LowerBound), Math.Log(a.UpperBound));
+    }
+    public static Interval Exponential(Interval a) {
+      return new Interval(Math.Exp(a.LowerBound), Math.Exp(a.UpperBound));
+    }
+
+    public static Interval Power(Interval a, Interval b) {
+      if (a.Contains(0.0) && b.LowerBound < 0) return new Interval(double.NaN, double.NaN);
+
+      int bLower = (int)Math.Round(b.LowerBound);
+      int bUpper = (int)Math.Round(b.UpperBound);
+
+      List<double> powerValues = new List<double>();
+      powerValues.Add(Math.Pow(a.UpperBound, bUpper));
+      powerValues.Add(Math.Pow(a.UpperBound, bUpper - 1));
+      powerValues.Add(Math.Pow(a.UpperBound, bLower));
+      powerValues.Add(Math.Pow(a.UpperBound, bLower + 1));
+
+      powerValues.Add(Math.Pow(a.LowerBound, bUpper));
+      powerValues.Add(Math.Pow(a.LowerBound, bUpper - 1));
+      powerValues.Add(Math.Pow(a.LowerBound, bLower));
+      powerValues.Add(Math.Pow(a.LowerBound, bLower + 1));
+
+      return new Interval(powerValues.Min(), powerValues.Max());
+    }
+
+    public static Interval Square(Interval a) {
+      return Power(a, new Interval(2, 2));
+    }
+
+    public static Interval Cubic(Interval a) {
+      return Power(a, new Interval(3, 3));
+    }
+
+    public static Interval Root(Interval a, Interval b) {
+      int lower = (int)Math.Round(b.LowerBound);
+      int higher = (int)Math.Round(b.UpperBound);
+
+      return new Interval(Math.Pow(a.LowerBound, 1.0 / higher), Math.Pow(a.UpperBound, 1.0 / lower));
+    }
+
+    public static Interval SquareRoot(Interval a) {
+      return Root(a, new Interval(2, 2));
+    }
+
+    public static Interval CubicRoot(Interval a) {
+      return Root(a, new Interval(3, 3));
+    }
+    #endregion
+  }
+}
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolutionVariableImpactsCalculator.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolutionVariableImpactsCalculator.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolutionVariableImpactsCalculator.cs	(revision 16433)
@@ -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: /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis.Views/3.3/RegressionInstanceProviderView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis.Views/3.3/RegressionInstanceProviderView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis.Views/3.3/RegressionInstanceProviderView.cs	(revision 16433)
@@ -46,22 +46,18 @@
 
         Task.Factory.StartNew(() => {
-          var mainForm = (MainForm.WindowsForms.MainForm)MainFormManager.MainForm;
+          var activeView = (IContentView)MainFormManager.MainForm.ActiveView;
+          var content = activeView.Content;
           // lock active view and show progress bar
-          IContentView activeView = (IContentView)MainFormManager.MainForm.ActiveView;
+          try {
+            var progress = Progress.Show(content, "Loading problem instance.");
 
-          try {
-            var progress = mainForm.AddOperationProgressToContent(activeView.Content,
-              "Loading problem instance.");
+            Content.ProgressChanged += (o, args) => { progress.ProgressValue = args.ProgressPercentage / 100.0; };
 
-            Content.ProgressChanged +=
-              (o, args) => { progress.ProgressValue = args.ProgressPercentage / 100.0; };
-
-            instance = Content.ImportData(importTypeDialog.Path, importTypeDialog.ImportType,
-              importTypeDialog.CSVFormat);
+            instance = Content.ImportData(importTypeDialog.Path, importTypeDialog.ImportType, importTypeDialog.CSVFormat);
           } catch (Exception ex) {
             ErrorWhileParsing(ex);
             return;
           } finally {
-            mainForm.RemoveOperationProgressFromContent(activeView.Content);
+            Progress.Hide(content);
           }
 
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/AircraftLift.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/AircraftLift.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/AircraftLift.cs	(revision 16433)
@@ -27,18 +27,26 @@
 namespace HeuristicLab.Problems.Instances.DataAnalysis {
   class AircraftLift : ArtificialRegressionDataDescriptor {
-    public override string Name { get { return "Aircraft Lift Coefficient C_L = x1*(x2 - 2) + x3*x4*x5/x6"; } }
+    public override string Name { get { return "Aircraft Lift Coefficient C_L = C_La (a - a0) + C_Ld_e d_e S_HT / S_ref"; } }
 
     public override string Description {
       get {
-        return "A full description of this problem instance is given in the paper: A multilevel block building algorithm for fast modeling generalized separable systems. " + Environment.NewLine +
-               "Authors: Chen Chen, Changtong Luo, Zonglin Jiang" + Environment.NewLine +
-               "Function: f(X) = x1*(x2 - 2) + x3*x4*x5/x6" + Environment.NewLine +
-               "with x1 in [0.4, 0.8], x2 in [5, 10], x3 in [0.4, 0.8], x4 in [5, 10], x5 in [1, 1.5], x6 in [5, 7]";
+        return "A full description of this problem instance is given in: " + Environment.NewLine +
+          "Chen Chen, Changtong Luo, Zonglin Jiang, \"A multilevel block building algorithm for fast " +
+          "modeling generalized separable systems\", Expert Systems with Applications, Volume 109, 2018, " +
+          "Pages 25-34 https://doi.org/10.1016/j.eswa.2018.05.021. " + Environment.NewLine +
+          "Function: C_L = C_La (a - a0) + C_Ld_e d_e S_HT / S_ref" + Environment.NewLine +
+          "with C_La ∈ [0.4, 0.8]," + Environment.NewLine +
+          "a ∈ [5°, 10°]," + Environment.NewLine +
+          "C_Ld_e ∈ [0.4, 0.8]," + Environment.NewLine +
+          "d_e ∈ [5°, 10°]," + Environment.NewLine +
+          "S_HT ∈ [1m², 1.5m²]," + Environment.NewLine +
+          "S_ref ∈ [5m², 7m²]," + Environment.NewLine +
+          "a0 is set to -2°";
       }
     }
 
-    protected override string TargetVariable { get { return "f(X)"; } }
-    protected override string[] VariableNames { get { return new string[] { "x1", "x2", "x3", "x4", "x5", "x6", "f(X)" }; } }
-    protected override string[] AllowedInputVariables { get { return new string[] { "x1", "x2", "x3", "x4", "x5", "x6" }; } }
+    protected override string TargetVariable { get { return "C_L"; } }
+    protected override string[] VariableNames { get { return new string[] { "C_La", "a", "a0", "C_Ld_e", "d_e", "S_HT", "C_L" }; } }
+    protected override string[] AllowedInputVariables { get { return new string[] { "C_La", "a", "a0", "C_Ld_e", "d_e", "S_HT" }; } }
     protected override int TrainingPartitionStart { get { return 0; } }
     protected override int TrainingPartitionEnd { get { return 100; } }
@@ -58,23 +66,25 @@
 
       List<List<double>> data = new List<List<double>>();
-      var x1 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.4, 0.8).ToList();
-      var x2 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 5.0, 10.0).ToList();
-      var x3 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.4, 0.8).ToList();
-      var x4 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 5.0, 10.0).ToList();
-      var x5 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 1.0, 1.5).ToList();
-      var x6 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 5.0, 7.0).ToList();
+      var C_La = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.4, 0.8).ToList();
+      var a = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 5.0, 10.0).ToList();
+      var C_Ld_e = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.4, 0.8).ToList();
+      var d_e = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 5.0, 10.0).ToList();
+      var S_HT = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 1.0, 1.5).ToList();
+      var S_ref = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 5.0, 7.0).ToList();
 
-      List<double> fx = new List<double>();
-      data.Add(x1);
-      data.Add(x2);
-      data.Add(x3);
-      data.Add(x4);
-      data.Add(x5);
-      data.Add(x6);
-      data.Add(fx);
+      List<double> C_L = new List<double>();
+      data.Add(C_La);
+      data.Add(a);
+      data.Add(C_Ld_e);
+      data.Add(d_e);
+      data.Add(S_HT);
+      data.Add(S_ref);
+      data.Add(C_L);
 
-      for (int i = 0; i < x1.Count; i++) {
-        double fxi = x1[i] * (x2[i] - 2.0) + x3[i] * x4[i] * x5[i] / x6[i];
-        fx.Add(fxi);
+      double a0 = -2.0;
+
+      for (int i = 0; i < C_La.Count; i++) {
+        double C_Li = C_La[i] * (a[i] - a0) + C_Ld_e[i] * d_e[i] * S_HT[i] / S_ref[i];
+        C_L.Add(C_Li);
       }
 
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/AircraftMaximumLift.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/AircraftMaximumLift.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/AircraftMaximumLift.cs	(revision 16433)
@@ -27,21 +27,27 @@
 namespace HeuristicLab.Problems.Instances.DataAnalysis {
   class AircraftMaximumLift : ArtificialRegressionDataDescriptor {
-    public override string Name { get { return "Aircraft Maximum Lift Coefficient"; } }
+    public override string Name { get { return "Aircraft Maximum Lift Coefficient f(X) = x1 - 1/4 x4 x5 x6 (4 + 0.1 x2/x3 - x2²/x3²) + x13 x14/x15 x18 x7 - x13 x14/x15 x8 + x13 x14/x15 x9 + x16 x17/x15 x18 x10 - x16 x17/x15 x11 + x16 x17/x15 x12"; } }
 
     public override string Description {
       get {
-        return "A full description of this problem instance is given in the paper: A multilevel block building algorithm for fast modeling generalized separable systems. " + Environment.NewLine +
-               "Authors: Chen Chen, Changtong Luo, Zonglin Jiang" + Environment.NewLine +
-               "Function: f(X) = x1 - 0.25 x4 x5 x6 (4 + 0.1 x2/x3 - x2²/x3²) + x13 x14/x15 x18 x7 - x13 x14/x15 x8 + x13 x14/x15 x9 + x16 x17/x15 x18 x10 - x16 x17/x15 x11 + x16 x17/x15 x12" + Environment.NewLine +
-               "with x1 in [0.4, 0.8], " +
-               "x2 in [3, 4], " +
-               "x3 in [20, 30], " +
-               "x4, x13, x16 in [2, 5]," +
-               "x14, x17 in [1, 1.5], " +
-               "x15 in [5, 7]," +
-               "x18 in [10, 20]," +
-               "x8, x11 in [1, 1.5]," +
-               "x9, x12 in [1, 2]," +
-               "x7, x10 in [0.5, 1.5]";
+        return "Slightly changed version of the problem instance given in: " + Environment.NewLine +
+          "Chen Chen, Changtong Luo, Zonglin Jiang, \"A multilevel block building algorithm for fast " +
+          "modeling generalized separable systems\", " +
+          "pre-print on arXiv: https://arxiv.org/abs/1706.02281 ." + Environment.NewLine +
+          "Notably, this problem is missing from the peer-reviewed version of the article in Expert Systems with Applications, Volume 109" + Environment.NewLine +
+          "Function: f(X) = x1 - 0.25 x4 x5 x6 (4 + 0.1 x2/x3 - x2²/x3²) + x13 x14/x15 x18 x7 - x13 x14/x15 x8 + x13 x14/x15 x9 + x16 x17/x15 x18 x10 - x16 x17/x15 x11 + x16 x17/x15 x12" + Environment.NewLine +
+          "with x1 ∈ [0.4, 0.8]," + Environment.NewLine +
+          "x2 ∈ [3, 4]," + Environment.NewLine +
+          "x3 ∈ [20, 30]," + Environment.NewLine +
+          "x4, x13, x16 ∈ [2, 5]," + Environment.NewLine +
+          "x14, x17 ∈ [1, 1.5]," + Environment.NewLine +
+          "x15 ∈ [5, 7]," + Environment.NewLine +
+          "x18 ∈ [10, 20]," + Environment.NewLine +
+          "x8, x11 ∈ [1, 1.5]," + Environment.NewLine +
+          "x9, x12 ∈ [1, 2]," + Environment.NewLine +
+          "x7, x10 ∈ [0.5, 1.5]." + Environment.NewLine +
+          "Values for x5 and x6 have not been specified in the reference paper." +
+          " We therefore only use a single (x5) variable in place of ∆αW/c and set x6 to a constant value of 1.0." + Environment.NewLine +
+          "The range for x5 is [0..20].";
       }
     }
@@ -78,6 +84,7 @@
 
 
-      var x5 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 1.0, 1.5).ToList(); // TODO: range for X5 is not specified in the paper
-      var x6 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 5.0, 7.0).ToList(); // TODO: range for X6 is not specified in the paper
+      // in the reference paper \Delta alpha_w/c is replaced by two variables x5*x6. 
+      var x5 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0, 20).ToList(); // range for X5 is not specified in the paper, we use [0°..20°] for ∆αW/c
+      var x6 = Enumerable.Repeat(1.0, x5.Count).ToList(); // range for X6 is not specified in the paper. In the maximum lift formular there is only a single variable ∆αW/c in place of x5*x6.
 
       var x7 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.5, 1.5).ToList();
@@ -96,4 +103,5 @@
 
       var x18 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 10.0, 20.0).ToList();
+
 
       List<double> fx = new List<double>();
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/FluidDynamics.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/FluidDynamics.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/FluidDynamics.cs	(revision 16433)
@@ -27,18 +27,24 @@
 namespace HeuristicLab.Problems.Instances.DataAnalysis {
   class FluidDynamics : ArtificialRegressionDataDescriptor {
-    public override string Name { get { return "Flow psi = x1*x2*x5*(1 - x4²/x5²) + 1/(2*Pi) * x3*log(x5/x4)"; } }
+    public override string Name { get { return "Flow Psi = V_inf r sin(th) (1 - R²/r²) + G/(2 π) ln(r/R)"; } }
 
     public override string Description {
       get {
-        return "A full description of this problem instance is given in the paper: A multilevel block building algorithm for fast modeling generalized separable systems. " + Environment.NewLine +
-               "Authors: Chen Chen, Changtong Luo, Zonglin Jiang" + Environment.NewLine +
-               "Function: f(X) = x1*x2*x5*(1 - x4²/x5²) + 1/(2*Pi) * x3*log(x5/x4)" + Environment.NewLine +
-               "with x1 in [60,65], x2 in [30, 40], x3 in [5,10], x4 in [0.5,0.8], x5 in [0.2,0.5]";
+        return "A full description of this problem instance is given in: " + Environment.NewLine +
+          "Chen Chen, Changtong Luo, Zonglin Jiang, \"A multilevel block building algorithm for fast " +
+          "modeling generalized separable systems\", Expert Systems with Applications, Volume 109, 2018, " +
+          "Pages 25-34 https://doi.org/10.1016/j.eswa.2018.05.021. " + Environment.NewLine +
+          "Function: Psi = V_inf r sin(th) (1 - R²/r²) + G/(2 π) ln(r/R)" + Environment.NewLine +
+          "with V_inf ∈ [60 m/s, 65 m/s]," + Environment.NewLine +
+          "th ∈ [30°, 40°]," + Environment.NewLine +
+          "r ∈ [0.2m, 0.5m]," + Environment.NewLine +
+          "R ∈ [0.5m, 0.8m]," + Environment.NewLine +
+          "G ∈ [5 m²/s, 10 m²/s]";
       }
     }
 
-    protected override string TargetVariable { get { return "f(X)"; } }
-    protected override string[] VariableNames { get { return new string[] { "x1", "x2", "x3", "x4", "x5", "f(X)" }; } }
-    protected override string[] AllowedInputVariables { get { return new string[] { "x1", "x2", "x3", "x4", "x5" }; } }
+    protected override string TargetVariable { get { return "Psi"; } }
+    protected override string[] VariableNames { get { return new string[] { "V_inf", "th", "r", "R", "G", "Psi" }; } }
+    protected override string[] AllowedInputVariables { get { return new string[] { "V_inf", "th", "r", "R", "G" }; } }
     protected override int TrainingPartitionStart { get { return 0; } }
     protected override int TrainingPartitionEnd { get { return 100; } }
@@ -58,22 +64,23 @@
 
       List<List<double>> data = new List<List<double>>();
-      var x1 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 60.0, 65.0).ToList();
-      var x2 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 30.0, 40.0).ToList();
-      var x3 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 5.0, 10.0).ToList();
-      var x4 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.5, 0.8).ToList();
-      var x5 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.2, 0.5).ToList();
+      var V_inf = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 60.0, 65.0).ToList();
+      var th = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 30.0, 40.0).ToList();
+      var r = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.2, 0.5).ToList();
+      var R = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.5, 0.8).ToList();
+      var G = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 5, 10).ToList();
 
-      List<double> fx = new List<double>();
-      data.Add(x1);
-      data.Add(x2);
-      data.Add(x3);
-      data.Add(x4);
-      data.Add(x5);
-      data.Add(fx);
+      List<double> Psi = new List<double>();
+      data.Add(V_inf);
+      data.Add(th);
+      data.Add(r);
+      data.Add(R);
+      data.Add(G);
+      data.Add(Psi);
 
-      for (int i = 0; i < x1.Count; i++) {
-        double fxi = x1[i] * x2[i] * x5[i] * (1 - (x4[i] * x4[i]) / (x5[i] * x5[i])) +
-                     (1 / (2 * Math.PI)) * x3[i] * Math.Log(x5[i] / x4[i]);
-        fx.Add(fxi);
+      for (int i = 0; i < V_inf.Count; i++) {
+        var th_rad = Math.PI * th[i] / 180.0;
+        double Psi_i = V_inf[i] * r[i] * Math.Sin(th_rad) * (1 - (R[i] * R[i]) / (r[i] * r[i])) +
+                     (G[i] / (2 * Math.PI)) * Math.Log(r[i] / R[i]);
+        Psi.Add(Psi_i);
       }
 
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/PhysicsInstanceProvider.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/PhysicsInstanceProvider.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/PhysicsInstanceProvider.cs	(revision 16433)
@@ -37,9 +37,8 @@
     public override string Name { get { return "Physics Benchmark Problems"; } }
     public override string Description { get { return ""; } }
-    public override Uri WebLink { get { return new Uri(@"https://arxiv.org/abs/1706.02281"); } }
+    public override Uri WebLink { get { return new Uri(@"https://doi.org/10.1016/j.eswa.2018.05.021"); } }
     public override string ReferencePublication {
       get {
-        return "Chen Chen, Changtong Luo, Zonglin Jiang, 2017 " +
-"\"A multilevel block search algorithm for fast modeling generalized separable systems.\" arXiv preprint arXiv:1706.02281, v3";
+        return "Chen Chen, Changtong Luo, Zonglin Jiang, \"A multilevel block building algorithm for fast modeling generalized separable systems\", Expert Systems with Applications, Volume 109, 2018, Pages 25-34 https://doi.org/10.1016/j.eswa.2018.05.021 as well as the (slightly different) pre-print on arXiv: https://arxiv.org/abs/1706.02281";
       }
     }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/RocketFuelFlow.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/RocketFuelFlow.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Physics/RocketFuelFlow.cs	(revision 16433)
@@ -27,18 +27,24 @@
 namespace HeuristicLab.Problems.Instances.DataAnalysis {
   class RocketFuelFlow : ArtificialRegressionDataDescriptor {
-    public override string Name { get { return "Rocket Fuel Flow f(X) = 4000*x1*x2/sqrt(x3)"; } }
+    public override string Name { get { return "Rocket Fuel Flow m_dot = p0 A / sqrt(T0) * sqrt(γ/R (2/(γ+1))^((γ+1) / (γ-1)))"; } }
 
     public override string Description {
       get {
-        return "A full description of this problem instance is given in the paper: A multilevel block building algorithm for fast modeling generalized separable systems. " + Environment.NewLine +
-               "Authors: Chen Chen, Changtong Luo, Zonglin Jiang" + Environment.NewLine +
-               "Function: f(X) = 4000*x1*x2/sqrt(x3)" + Environment.NewLine +
-               "with x1 in [4,6], x2 in [0.5, 1.5], x3 in [250,260]";
+        return "A full description of this problem instance is given in: " + Environment.NewLine +
+          "Chen Chen, Changtong Luo, Zonglin Jiang, \"A multilevel block building algorithm for fast " +
+          "modeling generalized separable systems\", Expert Systems with Applications, Volume 109, 2018, " +
+          "Pages 25-34 https://doi.org/10.1016/j.eswa.2018.05.021. " + Environment.NewLine +
+          "Function: m_dot = p0 A / sqrt(T0) * sqrt(γ/R (2/(γ+1))^((γ+1) / (γ-1)))" + Environment.NewLine +
+          "with p0 ∈ [4e5 Pa, 6e5 Pa]," + Environment.NewLine +
+          "A ∈ [0.5m², 1.5m²]," + Environment.NewLine +
+          "T0 ∈ [250°K, 260°K]," + Environment.NewLine +
+          "γ=1.4 and R=287 J/(kg*K)" + Environment.NewLine +
+          "The factor sqrt(γ/R (2/(γ+1))^((γ+1) / (γ-1))) is constant as γ and R are constants.";
       }
     }
 
-    protected override string TargetVariable { get { return "f(X)"; } }
-    protected override string[] VariableNames { get { return new string[] { "x1", "x2", "x3", "f(X)" }; } }
-    protected override string[] AllowedInputVariables { get { return new string[] { "x1", "x2", "x3" }; } }
+    protected override string TargetVariable { get { return "m_dot"; } }
+    protected override string[] VariableNames { get { return new string[] { "p0", "A", "T0", "m_dot" }; } }
+    protected override string[] AllowedInputVariables { get { return new string[] { "p0", "A", "T0" }; } }
     protected override int TrainingPartitionStart { get { return 0; } }
     protected override int TrainingPartitionEnd { get { return 100; } }
@@ -58,17 +64,19 @@
 
       List<List<double>> data = new List<List<double>>();
-      var x1 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 4.0, 6.0).ToList();
-      var x2 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.5, 1.5).ToList();
-      var x3 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 250.0, 260.0).ToList();
+      var p0 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 4.0e5, 6.0e5).ToList();
+      var A = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.5, 1.5).ToList();
+      var T0 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 250.0, 260.0).ToList();
 
-      List<double> fx = new List<double>();
-      data.Add(x1);
-      data.Add(x2);
-      data.Add(x3);
-      data.Add(fx);
-
-      for (int i = 0; i < x1.Count; i++) {
-        double fxi = 4000 * x1[i] * x2[i] / Math.Sqrt(x3[i]);
-        fx.Add(fxi);
+      List<double> m_dot = new List<double>();
+      data.Add(p0);
+      data.Add(A);
+      data.Add(T0);
+      data.Add(m_dot);
+      double R = 287.0;
+      double γ = 1.4;
+      var c = Math.Sqrt(γ / R * Math.Pow(2 / (γ + 1), (γ + 1) / (γ - 1)));
+      for (int i = 0; i < p0.Count; i++) {
+        double m_dot_i = p0[i] * A[i] / Math.Sqrt(T0[i]) * c;
+        m_dot.Add(m_dot_i);
       }
 
Index: /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.Views/3.3/ProblemInstanceProviderViewGeneric.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.Views/3.3/ProblemInstanceProviderViewGeneric.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Problems.Instances.Views/3.3/ProblemInstanceProviderViewGeneric.cs	(revision 16433)
@@ -121,7 +121,7 @@
 
         IContentView activeView = (IContentView)MainFormManager.MainForm.ActiveView;
-        var mainForm = (MainForm.WindowsForms.MainForm)MainFormManager.MainForm;
+        var content = activeView.Content;
         // lock active view and show progress bar
-        mainForm.AddOperationProgressToContent(activeView.Content, "Loading problem instance.");
+        Progress.Show(content, "Loading problem instance.", ProgressMode.Indeterminate);
 
         Task.Factory.StartNew(() => {
@@ -131,5 +131,5 @@
           } catch (Exception ex) {
             ErrorHandling.ShowErrorDialog(String.Format("Could not load the problem instance {0}", descriptor.Name), ex);
-            mainForm.RemoveOperationProgressFromContent(activeView.Content);
+            Progress.Hide(content);
             return;
           }
@@ -139,5 +139,5 @@
             ErrorHandling.ShowErrorDialog(String.Format("This problem does not support loading the instance {0}", descriptor.Name), ex);
           } finally {
-            mainForm.RemoveOperationProgressFromContent(activeView.Content);
+            Progress.Hide(content);
           }
         });
Index: /branches/2965_CancelablePersistence/HeuristicLab.Scripting.Views/3.3/ScriptView.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Scripting.Views/3.3/ScriptView.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Scripting.Views/3.3/ScriptView.cs	(revision 16433)
@@ -178,6 +178,5 @@
 
     private void AddProgressView(string progressMessage) {
-      var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
-      mainForm.AddOperationProgressToView(this, progressMessage);
+      Progress.Show(this, progressMessage, ProgressMode.Indeterminate);
       progressViewCreated = true;
     }
@@ -185,6 +184,5 @@
     private void RemoveProgressView() {
       if (!progressViewCreated) return;
-      var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
-      mainForm.RemoveOperationProgressFromView(this);
+      Progress.Hide(this);
       progressViewCreated = false;
     }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab-3.3/Samples/GPSymbolicRegressionSampleWithOSTest.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab-3.3/Samples/GPSymbolicRegressionSampleWithOSTest.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab-3.3/Samples/GPSymbolicRegressionSampleWithOSTest.cs	(revision 16433)
@@ -104,4 +104,6 @@
       var squareroot = grammar.Symbols.OfType<SquareRoot>().Single();
       var root = grammar.Symbols.OfType<Root>().Single();
+      var cube = grammar.Symbols.OfType<Cube>().Single();
+      var cuberoot = grammar.Symbols.OfType<CubeRoot>().Single();
       var log = grammar.Symbols.OfType<Logarithm>().Single();
       var exp = grammar.Symbols.OfType<Exponential>().Single();
@@ -130,4 +132,6 @@
       grammar.AddAllowedChildSymbol(squareroot, variable);
 
+      cube.Enabled = false;
+      cuberoot.Enabled = false;
       root.Enabled = false;
 
Index: /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/ClassificationVariableImpactCalculationTest.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/ClassificationVariableImpactCalculationTest.cs	(revision 16433)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/ClassificationVariableImpactCalculationTest.cs	(revision 16433)
@@ -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: /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/IntervalTest.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/IntervalTest.cs	(revision 16433)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/IntervalTest.cs	(revision 16433)
@@ -0,0 +1,127 @@
+﻿using System;
+using HeuristicLab.Problems.DataAnalysis;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace HeuristicLab.Problems.DataAnalysis.Tests {
+  [TestClass]
+  public class IntervalTest {
+    private readonly Interval a = new Interval(-1, 1);
+    private readonly Interval b = new Interval(-2, 2);
+    private readonly Interval c = new Interval(0, 3);
+    private readonly Interval d = new Interval(1, 3);
+    private readonly Interval e = new Interval(4, 6);
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalAddOperation() {
+      //add        [x1,x2] + [y1,y2] = [x1 + y1,x2 + y2]
+
+      // [-1,1] + [-2,2] = [-3,3]
+      Assert.AreEqual(Interval.Add(a, b), new Interval(-3, 3));
+      //([-1, 1] + [-2, 2]) + [0, 3] = [-3, 6]
+      Assert.AreEqual(Interval.Add(Interval.Add(a, b), c), new Interval(-3, 6));
+      //([-1, 1] + [0, 3]) + [-2, 2] = [-3, 6]
+      Assert.AreEqual(Interval.Add(Interval.Add(a, c), b), new Interval(-3, 6));
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalSubOperation() {
+      //subtract   [x1,x2] − [y1,y2] = [x1 − y2,x2 − y1]
+
+      //[-1, 1] - [-2, 2] = [-3, 3]
+      Assert.AreEqual<Interval>(Interval.Subtract(a, b), new Interval(-3, 3));
+      //([-1, 1] - [-2, 2]) - [0, 3] = [-6, 3]
+      Assert.AreEqual<Interval>(Interval.Subtract(Interval.Subtract(a, b), c), new Interval(-6, 3));
+      //([-1, 1] - [0, 3]) - [-2, 2] = [-6, 3]
+      Assert.AreEqual<Interval>(Interval.Subtract(Interval.Subtract(a, c), b), new Interval(-6, 3));
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalMutlipyOperation() {
+      //multiply   [x1,x2] * [y1,y2] = [min(x1*y1,x1*y2,x2*y1,x2*y2),max(x1*y1,x1*y2,x2*y1,x2*y2)]
+
+      //[-1, 1] * [-2, 2] = [-2, 2]
+      Assert.AreEqual<Interval>(Interval.Multiply(a, b), new Interval(-2, 2));
+      //([-1, 1] * [-2, 2]) * [0, 3] = [-6, 6]
+      Assert.AreEqual<Interval>(Interval.Multiply(Interval.Multiply(a, b), c), new Interval(-6, 6));
+      //([-1, 1] * [0, 3]) * [-2, 2] = [-6, 6]
+      Assert.AreEqual<Interval>(Interval.Multiply(Interval.Multiply(a, c), b), new Interval(-6, 6));
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalDivideOperation() {
+      //divide  [x1, x2] / [y1, y2] = [x1, x2] * (1/[y1, y2]), where 1 / [y1,y2] = [1 / y2,1 / y1] if 0 not in [y_1, y_2].
+
+      //[4, 6] / [1, 3] = [4/3, 6]
+      Assert.AreEqual<Interval>(Interval.Divide(e, d), new Interval(4.0 / 3.0, 6));
+      //([4, 6] / [1, 3]) / [1, 3] = [4/9, 6]
+      Assert.AreEqual<Interval>(Interval.Divide(Interval.Divide(e, d), d), new Interval(4.0 / 9.0, 6));
+      //[4, 6] / [0, 3] = [4/3, +Inf]
+      Assert.AreEqual<Interval>(Interval.Divide(e, c), new Interval(4.0 / 3.0, double.PositiveInfinity));
+      //[-1, 1] / [0, 3] = [+Inf, -Inf]
+      Assert.AreEqual<Interval>(Interval.Divide(a, c), new Interval(double.NegativeInfinity, double.PositiveInfinity));
+      //Devision by 0 ==> IsInfiniteOrUndefined == true
+      Assert.IsTrue(Interval.Divide(e, c).IsInfiniteOrUndefined);
+      //Devision by 0 ==> IsInfiniteOrUndefined == true
+      Assert.IsTrue(Interval.Divide(a, c).IsInfiniteOrUndefined);
+      Assert.AreEqual<Interval>(Interval.Divide(d, b), new Interval(double.NegativeInfinity, double.PositiveInfinity));
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalSineOperator() {
+      //sine depends on interval
+      //sin([0, 2*pi]) = [-1, 1]
+      Assert.AreEqual<Interval>(Interval.Sine(new Interval(0, 2 * Math.PI)), new Interval(-1, 1));
+      //sin([-pi/2, pi/2]) = [sin(-pi/2), sin(pi/2)]
+      Assert.AreEqual<Interval>(Interval.Sine(new Interval(-1 * Math.PI / 2, Math.PI / 2)), new Interval(-1, 1));
+      //sin([0, pi/2]) = [sin(0), sin(pi/2)]
+      Assert.AreEqual<Interval>(Interval.Sine(new Interval(0, Math.PI / 2)), new Interval(0, 1));
+      //sin([pi, 3*pi/2]) = [sin(pi), sin(3*pi/2)]
+      Assert.AreEqual<Interval>(Interval.Sine(new Interval(Math.PI, 3 * Math.PI / 2)), new Interval(-1, 0));
+      Assert.AreEqual<Interval>(Interval.Sine(new Interval(1, 2)), new Interval(Math.Min(Math.Sin(1), Math.Sin(2)), 1));
+      Assert.AreEqual<Interval>(Interval.Sine(new Interval(1, 3)), new Interval(Math.Min(Math.Sin(1), Math.Sin(3)), 1));
+      Assert.AreEqual<Interval>(Interval.Sine(new Interval(Math.PI, 5 * Math.PI / 2)), new Interval(-1, 1));
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalCosineOperator() {
+      //Cosine uses sine Interval.Sine(Interval.Subtract(a, new Interval(Math.PI / 2, Math.PI / 2)));
+      Assert.AreEqual<Interval>(Interval.Cosine(new Interval(0, 2 * Math.PI)), new Interval(-1, 1));
+      Assert.AreEqual<Interval>(new Interval(-1, 1), Interval.Cosine(new Interval(Math.PI, 4 * Math.PI / 2)));
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalLogOperator() {
+      //Log([3, 5]) = [log(3), log(5)]
+      Assert.AreEqual<Interval>(new Interval(Math.Log(3), Math.Log(5)), Interval.Logarithm(new Interval(3, 5)));
+      //Log([0.5, 1]) = [log(0.5), log(1)]
+      Assert.AreEqual<Interval>(new Interval(Math.Log(0.5), 0), Interval.Logarithm(new Interval(0.5, 1)));
+      //Log([-1, 5]) = [NaN, log(5)]
+      var result = Interval.Logarithm(new Interval(-1, 5));
+      Assert.AreEqual<Interval>(new Interval(double.NaN, Math.Log(5)),result);
+      Assert.IsTrue(result.IsInfiniteOrUndefined);
+    }
+
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalExpOperator() {
+      //Exp([0, 1]) = [exp(0), exp(1)]
+      Assert.AreEqual<Interval>(new Interval(1, Math.Exp(1)), Interval.Exponential(new Interval(0, 1)));
+    }
+  }
+}
Index: /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/RegressionVariableImpactCalculationTest.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/RegressionVariableImpactCalculationTest.cs	(revision 16433)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/RegressionVariableImpactCalculationTest.cs	(revision 16433)
@@ -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: anches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/VariableImpactCalculationTest.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/VariableImpactCalculationTest.cs	(revision 16432)
+++ 	(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 SymbolicRegressionSolution;
-      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: /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/DeriveTest.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/DeriveTest.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/DeriveTest.cs	(revision 16433)
@@ -113,11 +113,11 @@
         var t = new SymbolicExpressionTree(root);
 
-        Assert.AreEqual("(('y' * 'z' * 60) / SQR(('y' * 'z' * 20)))", // actually 3 / (4y  5z) but simplifier is not smart enough to cancel numerator and denominator
-                                                                      // 60 y z / y² z² 20² == 6 / y z 40 == 3 / y z 20
+        Assert.AreEqual("(('y' * 'z' * 60) / (SQR('y') * SQR('z') * 400))", // actually 3 / (4y  5z) but simplifier is not smart enough to cancel numerator and denominator
+                                                                             // 60 y z / y² z² 20² == 6 / y z 40 == 3 / y z 20
           formatter.Format(DerivativeCalculator.Derive(t, "x")));
-        Assert.AreEqual("(('x' * 'z' * (-60)) / SQR(('y' * 'z' * 20)))", // actually 3x * -(4 5 z) / (4y 5z)² = -3x / (20 y² z)
+        Assert.AreEqual("(('x' * 'z' * (-60)) / (SQR('y') * SQR('z') * 400))", // actually 3x * -(4 5 z) / (4y 5z)² = -3x / (20 y² z)
                                                                          // -3 4 5 x z / 4² y² 5² z² = -60 x z / 20² z² y² ==    -60 x z / y² z² 20² 
           formatter.Format(DerivativeCalculator.Derive(t, "y")));
-        Assert.AreEqual("(('x' * 'y' * (-60)) / SQR(('y' * 'z' * 20)))",
+        Assert.AreEqual("(('x' * 'y' * (-60)) / (SQR('y') * SQR('z') * 400))",
           formatter.Format(DerivativeCalculator.Derive(t, "z")));
       }
Index: /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/InfixExpressionParserTest.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/InfixExpressionParserTest.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/InfixExpressionParserTest.cs	(revision 16433)
@@ -61,15 +61,15 @@
 
       Console.WriteLine(formatter.Format(parser.Parse("log(3)")));
-      Console.WriteLine(formatter.Format(parser.Parse("log(-3)")));
+      Console.WriteLine(formatter.Format(parser.Parse("log(-3)")));   // should produce log(-3) as output
       Console.WriteLine(formatter.Format(parser.Parse("exp(3)")));
-      Console.WriteLine(formatter.Format(parser.Parse("exp(-3)")));
+      Console.WriteLine(formatter.Format(parser.Parse("exp(-3)")));  // should produce exp(-3) as output
       Console.WriteLine(formatter.Format(parser.Parse("sqrt(3)")));
 
-      Console.WriteLine(formatter.Format(parser.Parse("sqr((-3))")));
+      Console.WriteLine(formatter.Format(parser.Parse("sqr((-3))")));  // should produce sqr((-3)) as output
 
-      Console.WriteLine(formatter.Format(parser.Parse("3/3+2/2+1/1")));
-      Console.WriteLine(formatter.Format(parser.Parse("-3+30-2+20-1+10")));
+      Console.WriteLine(formatter.Format(parser.Parse("3/3+2/2+1/1"))); // ((3 * 1 / 3) + (2 * 1 / 2) + (1 * 1 / 1))
+      Console.WriteLine(formatter.Format(parser.Parse("-3+30-2+20-1+10")));   //  not (30 + 20 + 10 + ((-1) * (3 + 2 + 1)))
       // round trip
-      Console.WriteLine(formatter.Format(parser.Parse(formatter.Format(parser.Parse("-3+30-2+20-1+10")))));
+      Console.WriteLine(formatter.Format(parser.Parse(formatter.Format(parser.Parse("-3+30-2+20-1+10")))));   // not (30 + 20 + 10 + ((-(1)) * (3 + 2 + 1)))
 
       Console.WriteLine(formatter.Format(parser.Parse("\"x1\"")));
Index: /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/IntervalInterpreterTest.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/IntervalInterpreterTest.cs	(revision 16433)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/IntervalInterpreterTest.cs	(revision 16433)
@@ -0,0 +1,115 @@
+﻿using System;
+using System.Collections.Generic;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Tests {
+  [TestClass]
+  public class IntervalInterpreterTest {
+    private IRegressionProblemData problemData;
+    private Dictionary<string, Interval> variableRanges;
+
+    [TestInitialize]
+    public void InitTest() {
+      double[,] arr = new double[4, 3];
+
+      arr[0, 0] = 3;
+      arr[0, 1] = 6;
+      arr[0, 2] = 2;
+      arr[1, 0] = 5;
+      arr[1, 1] = 2;
+      arr[1, 2] = 1;
+      arr[2, 0] = 8;
+      arr[2, 1] = 5;
+      arr[2, 2] = 0;
+      arr[3, 0] = 3;
+      arr[3, 1] = 4;
+      arr[3, 2] = 2;
+
+      var ds = new Dataset(new string[] { "x1", "x2", "y" }, arr);
+      problemData = (IRegressionProblemData)new RegressionProblemData(ds, new string[] { "x1", "x2" }, "y");
+
+      variableRanges = new Dictionary<string, Interval>();
+      variableRanges.Add("x1", new Interval(1, 10));
+      variableRanges.Add("x2", new Interval(4, 6));
+    }
+
+    private void EvaluateTest(string expression, Interval expectedResult, Dictionary<string, Interval> variableRanges = null) {
+      var parser = new InfixExpressionParser();
+      var tree = parser.Parse(expression);
+      var interpreter = new IntervalInterpreter();
+      Interval result;
+      if (variableRanges == null)
+        result = interpreter.GetSymbolicExressionTreeInterval(tree, problemData.Dataset, problemData.AllIndices);
+      else
+        result = interpreter.GetSymbolicExressionTreeInterval(tree, variableRanges);
+
+      Assert.AreEqual(expectedResult, result);
+    }
+
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterAdd() {
+      EvaluateTest("x1 + x2", new Interval(5, 14));
+      EvaluateTest("x1 + x2", new Interval(5, 16), variableRanges);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterLogAdd() {
+      EvaluateTest("log(x1 + x2)", new Interval(Math.Log(5), Math.Log(14)));
+      EvaluateTest("log(x1 + x2)", new Interval(Math.Log(5), Math.Log(16)), variableRanges);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterLogAddMul() {
+      EvaluateTest("log(3*x1 + x2)", new Interval(Math.Log(11), Math.Log(30)));
+      EvaluateTest("log(3*x1 + x2)", new Interval(Math.Log(7), Math.Log(36)), variableRanges);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterSin() {
+      EvaluateTest("sin(x1+x2)", new Interval(-1, 1));
+      EvaluateTest("sin(x1+x2)", new Interval(-1, 1), variableRanges);
+      EvaluateTest("sin(1+2)", new Interval(Math.Sin(3), Math.Sin(3)));
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterCos() {
+      EvaluateTest("cos(x1+x2)", new Interval(-1, 1));
+      EvaluateTest("cos(x1+x2)", new Interval(-1, 1), variableRanges);
+      EvaluateTest("cos(1+2)", new Interval(Math.Sin(3 - Math.PI / 2), Math.Sin(3 - Math.PI / 2)));
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterExp() {
+      EvaluateTest("exp(x1-x2)", new Interval(Math.Exp(-3), Math.Exp(6)));
+      EvaluateTest("exp(x1-x2)", new Interval(Math.Exp(-5), Math.Exp(6)), variableRanges);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterExpRoot() {
+      EvaluateTest("exp(root(x1*x2, 2))", new Interval(Math.Exp(Math.Sqrt(6)), Math.Exp(Math.Sqrt(48))));
+      EvaluateTest("exp(root(x1*x2, 2))", new Interval(Math.Exp(Math.Sqrt(4)), Math.Exp(Math.Sqrt(60))), variableRanges);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterPower() {
+      EvaluateTest("pow(x1, 2)", new Interval(Math.Pow(3, 1), Math.Pow(8, 3)));
+    }
+  }
+}
Index: /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeSimplifierTest.cs
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeSimplifierTest.cs	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeSimplifierTest.cs	(revision 16433)
@@ -228,4 +228,45 @@
       AssertEqualAfterSimplification("(- (factor a 2.0 3.0) (binfactor a x0 2.0))", "(factor a 0.0 3.0)");
       #endregion
+
+      #region abs
+      AssertEqualAfterSimplification("(abs 2.0)", "2.0");
+      AssertEqualAfterSimplification("(abs -2.0)", "2.0"); // constant folding
+      AssertEqualAfterSimplification("(abs (exp (variable 2.0 x)))", "(exp (variable 2.0 x)))"); // exp is always positive
+      AssertEqualAfterSimplification("(abs (exp (variable 2.0 x)))", "(exp (variable 2.0 x)))"); // exp is always positive
+      AssertEqualAfterSimplification("(abs (sqr (variable 2.0 a)))", "(sqr (variable 2.0 a))"); // sqr is always positive
+      AssertEqualAfterSimplification("(abs (sqrt (variable 2.0 a)))", "(sqrt (variable 2.0 a))"); // sqrt is always positive (for our cases)
+      AssertEqualAfterSimplification("(abs (cuberoot (variable 2.0 a)))", "(cuberoot (variable 2.0 a))"); // cuberoot is always positive (for our cases)
+
+      AssertEqualAfterSimplification("(* (abs (variable 2.0 x)) 2.0)", "(abs (variable 4.0 x))");  // can multiply positive constants into abs
+      AssertEqualAfterSimplification("(* (abs (variable 2.0 x)) -2.0)", "(* (abs (variable 4.0 x)) -1.0)"); // for negative constants keep the sign
+
+      AssertEqualAfterSimplification("(abs (* (variable 1.0 a) (variable 2.0 b)))", "(* (abs (variable 1.0 a)) (abs (variable 1.0 b)) 2.0))");
+      AssertEqualAfterSimplification("(abs (/ (variable 1.0 a) (variable 2.0 b)))", "(/ (abs (variable 1.0 a)) (abs (variable 2.0 b))))");
+      #endregion
+
+      #region square and sqrt
+      AssertEqualAfterSimplification("(sqr (sqrt (variable 2.0 x)))", "(variable 2.0 x)");
+      AssertEqualAfterSimplification("(sqrt (sqr (variable 2.0 x)))", "(variable 2.0 x)");
+      AssertEqualAfterSimplification("(sqr (abs (variable 2.0 a)))", "(sqr (variable 2.0 a))");
+      AssertEqualAfterSimplification("(sqr (exp (variable 2.0 x)))", "(exp (variable 4.0 x))");
+
+      AssertEqualAfterSimplification("(sqr (* (variable 2.0 a) (variable 3.0 b) (variable 4.0 c)))",
+        "(* (sqr (variable 1.0 a)) (sqr (variable 1.0 b)) (sqr (variable 1.0 c)) 576)"); // 2²*3²*4²
+      #endregion
+
+      #region cube and cuberoot
+      AssertEqualAfterSimplification("(cube (cuberoot (variable 2.0 x)))", "(variable 2.0 x)");
+      AssertEqualAfterSimplification("(cuberoot (cube (variable 2.0 x)))", "(variable 2.0 x)");
+      AssertEqualAfterSimplification("(cube (exp (variable 2.0 x)))", "(exp (variable 6.0 x))");
+
+      AssertEqualAfterSimplification("(sqr (cube (variable 2.0 x)))", "(pow (variable 2.0 x) 6)");
+      AssertEqualAfterSimplification("(cube (sqr (variable 2.0 x)))", "(pow (variable 2.0 x) 6)");
+      #endregion
+
+      #region AQ
+      AssertEqualAfterSimplification("(* (aq (variable 1.0 x) (variable 1.0 y)) 2.0)", "(aq (variable 2.0 x) (variable 1.0 y))");
+      AssertEqualAfterSimplification("(/ (aq (variable 1.0 x) (variable 1.0 y)) 2.0)", "(aq (variable 0.5 x) (variable 1.0 y))");
+
+      #endregion
     }
 
Index: /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Tests.csproj
===================================================================
--- /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 16432)
+++ /branches/2965_CancelablePersistence/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 16433)
@@ -583,10 +583,13 @@
     <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\DeriveTest.cs" />
     <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\InfixExpressionParserTest.cs" />
+    <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\IntervalInterpreterTest.cs" />
     <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\SymbolicExpressionTreeBottomUpSimilarityCalculatorTest.cs" />
     <Compile Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4\SymbolicExpressionTreeMaxCommonSubtreeSimilarityCalculatorTest.cs" />
