Index: trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/AlgorithmBase.cs
===================================================================
--- trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/AlgorithmBase.cs	(revision 2040)
+++ trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/AlgorithmBase.cs	(revision 2041)
@@ -423,4 +423,23 @@
       model.TrainingMeanSquaredError = bestModelScope.GetVariableValue<DoubleData>("Quality", false).Data;
       model.ValidationMeanSquaredError = bestModelScope.GetVariableValue<DoubleData>("ValidationQuality", false).Data;
+      // calculate and set variable impacts
+      VariableEvaluationImpactCalculator evaluationImpactCalculator = new VariableEvaluationImpactCalculator();
+      VariableQualityImpactCalculator qualityImpactCalculator = new VariableQualityImpactCalculator();
+
+      evaluationImpactCalculator.Apply(bestModelScope);
+      qualityImpactCalculator.Apply(bestModelScope);
+
+      ItemList evaluationImpacts = bestModelScope.GetVariableValue<ItemList>("VariableEvaluationImpacts", false);
+      ItemList qualityImpacts = bestModelScope.GetVariableValue<ItemList>("VariableQualityImpacts", false);
+      foreach (ItemList row in evaluationImpacts) {
+        string variableName = ((StringData)row[0]).Data;
+        double impact = ((DoubleData)row[0]).Data;
+        model.SetVariableEvaluationImpact(variableName, impact);
+      }
+      foreach (ItemList row in qualityImpacts) {
+        string variableName = ((StringData)row[0]).Data;
+        double impact = ((DoubleData)row[0]).Data;
+        model.SetVariableQualityImpact(variableName, impact);
+      }
       return model;
     }
Index: trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Evaluators/SimpleEvaluator.cs
===================================================================
--- trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Evaluators/SimpleEvaluator.cs	(revision 2040)
+++ trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Evaluators/SimpleEvaluator.cs	(revision 2041)
@@ -33,11 +33,11 @@
     public SimpleEvaluator()
       : base() {
-      AddVariableInfo(new VariableInfo("Values", "The values of the target variable as predicted by the model and the original value of the target variable", typeof(ItemList), VariableKind.New | VariableKind.Out));
+      AddVariableInfo(new VariableInfo("Values", "Target vs. predicted values", typeof(DoubleMatrixData), VariableKind.New | VariableKind.Out));
     }
 
     public override void Evaluate(IScope scope, ITreeEvaluator evaluator, Dataset dataset, int targetVariable, int start, int end, bool updateTargetValues) {
-      ItemList values = GetVariableValue<ItemList>("Values", scope, false, false);
+      DoubleMatrixData values = GetVariableValue<DoubleMatrixData>("Values", scope, false, false);
       if (values == null) {
-        values = new ItemList();
+        values = new DoubleMatrixData();
         IVariableInfo info = GetVariableInfo("Values");
         if (info.Local)
@@ -46,8 +46,8 @@
           scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName(info.FormalName), values));
       }
-      values.Clear();
+
+      double[,] v = new double[end - start, 2];
 
       for (int sample = start; sample < end; sample++) {
-        ItemList row = new ItemList();
         double estimated = evaluator.Evaluate(sample);
         double original = dataset.GetValue(sample, targetVariable);
@@ -55,8 +55,8 @@
           dataset.SetValue(sample, targetVariable, estimated);
         }
-        row.Add(new DoubleData(estimated));
-        row.Add(new DoubleData(original));
-        values.Add(row);
+        v[sample - start, 0] = original;
+        v[sample - start, 1] = estimated;
       }
+      values.Data = v;
     }
   }
Index: trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Evaluators/VariableEvaluationImpactCalculator.cs
===================================================================
--- trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Evaluators/VariableEvaluationImpactCalculator.cs	(revision 2041)
+++ trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Evaluators/VariableEvaluationImpactCalculator.cs	(revision 2041)
@@ -0,0 +1,57 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 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.Text;
+using System.Xml;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.DataAnalysis;
+using System.Linq;
+
+namespace HeuristicLab.GP.StructureIdentification {
+  public class VariableEvaluationImpactCalculator : HeuristicLab.Modeling.VariableEvaluationImpactCalculator {
+
+    public VariableEvaluationImpactCalculator()
+      : base() {
+      AddVariableInfo(new VariableInfo("TreeEvaluator", "The evaluator that should be used to evaluate the expression tree", typeof(ITreeEvaluator), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionTree", "The function tree that should be evaluated", typeof(IFunctionTree), VariableKind.In));
+      AddVariableInfo(new VariableInfo("TreeSize", "Size (number of nodes) of the tree to evaluate", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("PunishmentFactor", "Punishment factor for invalid estimations", typeof(DoubleData), VariableKind.In));
+    }
+
+
+    protected override double[] GetOutputs(IScope scope, Dataset dataset, int targetVariable, int start, int end) {
+      ITreeEvaluator evaluator = GetVariableValue<ITreeEvaluator>("TreeEvaluator", scope, true);
+      IFunctionTree tree = GetVariableValue<IFunctionTree>("FunctionTree", scope, true);
+      double punishmentFactor = GetVariableValue<DoubleData>("PunishmentFactor", scope, true).Data;
+      evaluator.PrepareForEvaluation(dataset, targetVariable, start, end, punishmentFactor, tree);
+
+      double[] result = new double[end - start];
+      for (int i = start; i < end; i++) {
+        result[i - start] = evaluator.Evaluate(i);
+      }
+
+      return result;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Evaluators/VariableQualityImpactCalculator.cs
===================================================================
--- trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Evaluators/VariableQualityImpactCalculator.cs	(revision 2041)
+++ trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Evaluators/VariableQualityImpactCalculator.cs	(revision 2041)
@@ -0,0 +1,57 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 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.Text;
+using System.Xml;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.DataAnalysis;
+using System.Linq;
+
+namespace HeuristicLab.GP.StructureIdentification {
+  public class VariableQualityImpactCalculator : HeuristicLab.Modeling.VariableQualityImpactCalculator {
+
+    public VariableQualityImpactCalculator()
+      : base() {
+      AddVariableInfo(new VariableInfo("TreeEvaluator", "The evaluator that should be used to evaluate the expression tree", typeof(ITreeEvaluator), VariableKind.In));
+      AddVariableInfo(new VariableInfo("FunctionTree", "The function tree that should be evaluated", typeof(IFunctionTree), VariableKind.In));
+      AddVariableInfo(new VariableInfo("TreeSize", "Size (number of nodes) of the tree to evaluate", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("PunishmentFactor", "Punishment factor for invalid estimations", typeof(DoubleData), VariableKind.In));
+    }
+
+    protected override double CalculateQuality(IScope scope, Dataset dataset, int targetVariable, int start, int end) {
+      ITreeEvaluator evaluator = GetVariableValue<ITreeEvaluator>("TreeEvaluator", scope, true);
+      IFunctionTree tree = GetVariableValue<IFunctionTree>("FunctionTree", scope, true);
+      double punishmentFactor = GetVariableValue<DoubleData>("PunishmentFactor", scope, true).Data;
+      evaluator.PrepareForEvaluation(dataset, targetVariable, start, end, punishmentFactor, tree);
+
+      double[,] result = new double[end - start,2];
+      for (int i = start; i < end; i++) {
+        result[i - start, 0] = dataset.GetValue(i, targetVariable);
+        result[i - start,1] = evaluator.Evaluate(i);
+      }
+
+      return HeuristicLab.Modeling.SimpleMSEEvaluator.Calculate(result);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/HeuristicLab.GP.StructureIdentification-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/HeuristicLab.GP.StructureIdentification-3.3.csproj	(revision 2040)
+++ trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/HeuristicLab.GP.StructureIdentification-3.3.csproj	(revision 2041)
@@ -140,4 +140,6 @@
     <Compile Include="Tangens.cs" />
     <Compile Include="Variable.cs" />
+    <Compile Include="Evaluators\VariableEvaluationImpactCalculator.cs" />
+    <Compile Include="Evaluators\VariableQualityImpactCalculator.cs" />
     <Compile Include="Xor.cs" />
   </ItemGroup>
Index: trunk/sources/HeuristicLab.Modeling/3.2/HeuristicLab.Modeling-3.2.csproj
===================================================================
--- trunk/sources/HeuristicLab.Modeling/3.2/HeuristicLab.Modeling-3.2.csproj	(revision 2040)
+++ trunk/sources/HeuristicLab.Modeling/3.2/HeuristicLab.Modeling-3.2.csproj	(revision 2041)
@@ -83,4 +83,6 @@
   <ItemGroup>
     <Compile Include="ClassificationProblemInjector.cs" />
+    <Compile Include="VariableImpactCalculatorBase.cs" />
+    <Compile Include="VariableEvaluationImpactCalculator.cs" />
     <Compile Include="Model.cs" />
     <Compile Include="IModel.cs" />
Index: trunk/sources/HeuristicLab.Modeling/3.2/IModel.cs
===================================================================
--- trunk/sources/HeuristicLab.Modeling/3.2/IModel.cs	(revision 2040)
+++ trunk/sources/HeuristicLab.Modeling/3.2/IModel.cs	(revision 2041)
@@ -45,5 +45,6 @@
     double ValidationVarianceAccountedFor { get; }
     double TestVarianceAccountedFor { get; }
-    double GetVariableImpact(string variableName);
+    double GetVariableEvaluationImpact(string variableName);
+    double GetVariableQualityImpact(string variableName);
 
     IItem Data { get; }
Index: trunk/sources/HeuristicLab.Modeling/3.2/Model.cs
===================================================================
--- trunk/sources/HeuristicLab.Modeling/3.2/Model.cs	(revision 2040)
+++ trunk/sources/HeuristicLab.Modeling/3.2/Model.cs	(revision 2041)
@@ -120,6 +120,11 @@
     }
 
-    public double GetVariableImpact(string variableName) {
-      if (variableImpacts.ContainsKey(variableName)) return variableImpacts[variableName];
+    public double GetVariableQualityImpact(string variableName) {
+      if (variableQualityImpacts.ContainsKey(variableName)) return variableQualityImpacts[variableName];
+      else return 1.0;
+    }
+
+    public double GetVariableEvaluationImpact(string variableName) {
+      if (variableEvaluationImpacts.ContainsKey(variableName)) return variableEvaluationImpacts[variableName];
       else return 0.0;
     }
@@ -133,11 +138,20 @@
     #endregion
 
-    private Dictionary<string, double> variableImpacts = new Dictionary<string, double>();
-    public void SetVariableImpact(string variableName, double impact) {
-      variableImpacts[variableName] = impact;
+    private Dictionary<string, double> variableQualityImpacts = new Dictionary<string, double>();
+    public void SetVariableQualityImpact(string variableName, double impact) {
+      variableQualityImpacts[variableName] = impact;
     }
 
-    public void SetVariableImpact(int variableIndex, double impact) {
-      variableImpacts[dataset.GetVariableName(variableIndex)] = impact;
+    public void SetVariableQualityImpact(int variableIndex, double impact) {
+      variableQualityImpacts[dataset.GetVariableName(variableIndex)] = impact;
+    }
+
+    private Dictionary<string, double> variableEvaluationImpacts = new Dictionary<string, double>();
+    public void SetVariableEvaluationImpact(string variableName, double impact) {
+      variableEvaluationImpacts[variableName] = impact;
+    }
+
+    public void SetVariableEvaluationImpact(int variableIndex, double impact) {
+      variableEvaluationImpacts[dataset.GetVariableName(variableIndex)] = impact;
     }
   }
Index: trunk/sources/HeuristicLab.Modeling/3.2/VariableEvaluationImpactCalculator.cs
===================================================================
--- trunk/sources/HeuristicLab.Modeling/3.2/VariableEvaluationImpactCalculator.cs	(revision 2041)
+++ trunk/sources/HeuristicLab.Modeling/3.2/VariableEvaluationImpactCalculator.cs	(revision 2041)
@@ -0,0 +1,70 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 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.Text;
+using System.Xml;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.DataAnalysis;
+using System.Linq;
+
+namespace HeuristicLab.Modeling {
+  public abstract class VariableEvaluationImpactCalculator : VariableImpactCalculatorBase<double[]> {
+    public override string OutputVariableName {
+      get { return "VariableEvaluationImpacts"; }
+    }
+
+    public override string Description {
+      get { return @"Calculates the impact of all allowed input variables on the model outputs using evaluator supplied as suboperator."; }
+    }
+
+    private double[,] CombineOutputs(double[] referenceOutputs, double[] newOutputs) {
+      if (referenceOutputs.Length != newOutputs.Length) throw new InvalidProgramException();
+      double[,] result = new double[referenceOutputs.Length, 2];
+      for (int i = 0; i < referenceOutputs.Length; i++) {
+        result[i, 0] = referenceOutputs[i];
+        result[i, 1] = newOutputs[i];
+      }
+      return result;
+    }
+
+    protected override double CalculateImpact(double[] referenceValue, double[] newValue) {
+      return SimpleMSEEvaluator.Calculate(CombineOutputs(referenceValue, newValue));
+    }
+
+    protected override double[] CalculateValue(IScope scope, Dataset dataset, int targetVariable, int start, int end) {
+      return GetOutputs(scope, dataset, targetVariable, start, end);
+    }
+
+    protected override double[] PostProcessImpacts(double[] impacts) {
+      double mseSum = impacts.Sum();
+      if (mseSum == 0.0) mseSum = 1.0;
+      for (int i = 0; i < impacts.Length; i++) {
+        impacts[i] = impacts[i] / mseSum;
+      }
+      return impacts;
+    }
+
+    protected abstract double[] GetOutputs(IScope scope, Dataset dataset, int targetVariable, int start, int end);
+  }
+}
Index: trunk/sources/HeuristicLab.Modeling/3.2/VariableImpactCalculatorBase.cs
===================================================================
--- trunk/sources/HeuristicLab.Modeling/3.2/VariableImpactCalculatorBase.cs	(revision 2041)
+++ trunk/sources/HeuristicLab.Modeling/3.2/VariableImpactCalculatorBase.cs	(revision 2041)
@@ -0,0 +1,111 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 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.Text;
+using System.Xml;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.DataAnalysis;
+using System.Linq;
+
+namespace HeuristicLab.Modeling {
+  public abstract class VariableImpactCalculatorBase<T> : OperatorBase {
+    public override string Description {
+      get { return @"Calculates the impact of all allowed input variables on the model."; }
+    }
+
+    public abstract string OutputVariableName { get; }
+
+    public VariableImpactCalculatorBase()
+      : base() {
+      AddVariableInfo(new VariableInfo("Dataset", "Dataset", typeof(Dataset), VariableKind.In));
+      AddVariableInfo(new VariableInfo("TargetVariable", "TargetVariable", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("AllowedFeatures", "Indexes of allowed input variables", typeof(ItemList<IntData>), VariableKind.In));
+      AddVariableInfo(new VariableInfo("TrainingSamplesStart", "TrainingSamplesStart", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("TrainingSamplesEnd", "TrainingSamplesEnd", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo(OutputVariableName, OutputVariableName, typeof(ItemList), VariableKind.New));
+    }
+
+    public override IOperation Apply(IScope scope) {
+      ItemList<IntData> allowedFeatures = GetVariableValue<ItemList<IntData>>("AllowedFeatures", scope, true);
+      int targetVariable = GetVariableValue<IntData>("TargetVariable", scope, true).Data;
+      Dataset dataset = GetVariableValue<Dataset>("Dataset", scope, true);
+      Dataset dirtyDataset = (Dataset)dataset.Clone();
+      int start = GetVariableValue<IntData>("TrainingSamplesStart", scope, true).Data;
+      int end = GetVariableValue<IntData>("TrainingSamplesEnd", scope, true).Data;
+
+      T referenceValue = CalculateValue(scope, dataset, targetVariable, start, end);
+      double[] impacts = new double[allowedFeatures.Count];
+
+      for (int i = 0; i < allowedFeatures.Count; i++) {
+        int currentVariable = allowedFeatures[i].Data;
+        var oldValues = ReplaceVariableValues(dirtyDataset, currentVariable , CalculateNewValues(dirtyDataset, currentVariable, start, end), start, end);
+        T newValue = CalculateValue(scope, dirtyDataset, targetVariable, start, end);
+        impacts[i] = CalculateImpact(referenceValue, newValue);
+        ReplaceVariableValues(dirtyDataset, currentVariable, oldValues, start, end);
+      }
+
+      impacts = PostProcessImpacts(impacts);
+
+      ItemList variableImpacts = new ItemList();
+      for (int i = 0; i < allowedFeatures.Count; i++) {
+        int currentVariable = allowedFeatures[i].Data;
+        ItemList row = new ItemList();
+        row.Add(new StringData(dataset.GetVariableName(currentVariable)));
+        row.Add(new DoubleData(impacts[i]));
+        variableImpacts.Add(row);
+      }
+
+      scope.AddVariable(new Variable(scope.TranslateName(OutputVariableName), variableImpacts));
+      return null;
+    }
+
+    protected abstract T CalculateValue(IScope scope, Dataset dataset, int targetVariable, int start, int end);
+
+    protected abstract double CalculateImpact(T referenceValue, T newValue);
+
+    protected virtual double[] PostProcessImpacts(double[] impacts) {
+      return impacts;
+    }
+
+    private IEnumerable<double> ReplaceVariableValues(Dataset ds, int variableIndex, IEnumerable<double> newValues, int start, int end) {
+      double[] oldValues = new double[end - start];
+      for (int i = 0; i < end - start; i++) oldValues[i] = ds.GetValue(i + start, variableIndex);
+      if (newValues.Count() != end - start) throw new ArgumentException("The length of the new values sequence doesn't match the required length (number of replaced values)");
+
+      int index = start;
+      ds.FireChangeEvents = false;
+      foreach(double v in newValues) {
+        ds.SetValue(index++, variableIndex, v);
+      }
+      ds.FireChangeEvents = true;
+      ds.FireChanged();
+      return oldValues;
+    }
+
+    private IEnumerable<double> CalculateNewValues(Dataset ds, int variableIndex, int start, int end) {
+      double mean = ds.GetMean(variableIndex, start, end);
+      return Enumerable.Repeat(mean, end - start);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Modeling/3.2/VariableQualityImpactCalculator.cs
===================================================================
--- trunk/sources/HeuristicLab.Modeling/3.2/VariableQualityImpactCalculator.cs	(revision 2040)
+++ trunk/sources/HeuristicLab.Modeling/3.2/VariableQualityImpactCalculator.cs	(revision 2041)
@@ -30,78 +30,22 @@
 
 namespace HeuristicLab.Modeling {
-  public class VariableQualityImpactCalculator : OperatorBase {
+  public abstract class VariableQualityImpactCalculator : VariableImpactCalculatorBase<double> {
     public override string Description {
       get { return @"Calculates the impact of all allowed input variables on the quality of the model using evaluator supplied as suboperator."; }
     }
 
-    public VariableQualityImpactCalculator()
-      : base() {
-      AddVariableInfo(new VariableInfo("Dataset", "Dataset", typeof(Dataset), VariableKind.In));
-      AddVariableInfo(new VariableInfo("TargetVariable", "TargetVariable", typeof(IntData), VariableKind.In));
-      AddVariableInfo(new VariableInfo("AllowedFeatures", "Indexes of allowed input variables", typeof(ItemList<IntData>), VariableKind.In));
-      AddVariableInfo(new VariableInfo("TrainingSamplesStart", "TrainingSamplesStart", typeof(IntData), VariableKind.In));
-      AddVariableInfo(new VariableInfo("TrainingSamplesEnd", "TrainingSamplesEnd", typeof(IntData), VariableKind.In));
-      AddVariableInfo(new VariableInfo("VariableQualityImpacts", "Effect on quality of model (percentage of original quality) if variable is replaced by its mean.", typeof(ItemList), VariableKind.New));
+    public override string OutputVariableName {
+      get { return "VariableQualityImpacts"; }
     }
 
-    public override IOperation Apply(IScope scope) {
-      ItemList<IntData> allowedFeatures = GetVariableValue<ItemList<IntData>>("AllowedFeatures", scope, true);
-      int targetVariable = GetVariableValue<IntData>("TargetVariable", scope, true).Data;
-      Dataset dataset = GetVariableValue<Dataset>("Dataset", scope, true);
-      Dataset dirtyDataset = (Dataset)dataset.Clone();
-      int start = GetVariableValue<IntData>("TrainingSamplesStart", scope, true).Data;
-      int end = GetVariableValue<IntData>("TrainingSamplesEnd", scope, true).Data;
-
-      if (SubOperators.Count < 1) throw new InvalidOperationException("VariableQualityImpactCalculator needs a suboperator to evaluate the model");
-      IOperator evaluationOperator = this.SubOperators[0];
-      ItemList variableQualityImpacts = new ItemList();
-
-      // calculateReferenceQuality
-      double referenceQuality = CalculateQuality(scope, dataset, evaluationOperator);
-
-      for (int i = 0; i < allowedFeatures.Count; i++) {
-        int currentVariable = allowedFeatures[i].Data;
-        var oldValues = ReplaceVariableValues(dirtyDataset, currentVariable , CalculateNewValues(dirtyDataset, currentVariable, start, end), start, end);
-        double newQuality = CalculateQuality(scope, dirtyDataset, evaluationOperator);
-        double ratio = newQuality / referenceQuality;
-        ItemList row = new ItemList();
-        row.Add(new StringData(dataset.GetVariableName(currentVariable)));
-        row.Add(new DoubleData(ratio));
-        variableQualityImpacts.Add(row);
-        ReplaceVariableValues(dirtyDataset, currentVariable, oldValues, start, end);
-      }
-      scope.AddVariable(new Variable(scope.TranslateName("VariableQualityImpacts"), variableQualityImpacts));
-      return null;
+    protected override double CalculateImpact(double referenceValue, double newValue) {
+      return newValue / referenceValue;
     }
 
-    private double CalculateQuality(IScope scope, Dataset dataset, IOperator evaluationOperator) {
-      Scope s = new Scope();
-      s.AddVariable(new Variable("Dataset", dataset));
-      scope.AddSubScope(s);
-      evaluationOperator.Execute(s);
-      double quality = s.GetVariableValue<DoubleData>("Quality", false).Data;
-      scope.RemoveSubScope(s);
-      return quality;
+    protected override double CalculateValue(IScope scope, Dataset dataset, int targetVariable, int start, int end) {
+      return CalculateQuality(scope, dataset, targetVariable, start, end);
     }
 
-    private IEnumerable<double> ReplaceVariableValues(Dataset ds, int variableIndex, IEnumerable<double> newValues, int start, int end) {
-      double[] oldValues = new double[end - start];
-      for (int i = 0; i < end - start; i++) oldValues[i] = ds.GetValue(i + start, variableIndex);
-      if (newValues.Count() != end - start) throw new ArgumentException("The length of the new values sequence doesn't match the required length (number of replaced values)");
-
-      int index = start;
-      ds.FireChangeEvents = false;
-      foreach(double v in newValues) {
-        ds.SetValue(index++, variableIndex, v);
-      }
-      ds.FireChangeEvents = true;
-      ds.FireChanged();
-      return oldValues;
-    }
-
-    private IEnumerable<double> CalculateNewValues(Dataset ds, int variableIndex, int start, int end) {
-      double mean = ds.GetMean(variableIndex, start, end);
-      return Enumerable.Repeat(mean, end - start);
-    }
+    protected abstract double CalculateQuality(IScope scope, Dataset dataset, int targetVariable, int start, int end);
   }
 }
