Index: trunk/sources/HeuristicLab.DataAnalysis/3.2/Dataset.cs
===================================================================
--- trunk/sources/HeuristicLab.DataAnalysis/3.2/Dataset.cs	(revision 2037)
+++ trunk/sources/HeuristicLab.DataAnalysis/3.2/Dataset.cs	(revision 2038)
@@ -39,4 +39,11 @@
     private double[] scalingFactor;
     private double[] scalingOffset;
+    private bool cachedValuesInvalidated = true;
+
+    private bool fireChangeEvents = true;
+    public bool FireChangeEvents {
+      get { return fireChangeEvents; }
+      set { fireChangeEvents = value; }
+    }
 
     public string Name {
@@ -74,6 +81,6 @@
       if (v != samples[columns * i + j]) {
         samples[columns * i + j] = v;
-        CreateDictionaries();
-        FireChanged();
+        cachedValuesInvalidated = true;
+        if (fireChangeEvents) FireChanged();
       }
     }
@@ -89,6 +96,6 @@
         }
         samples = value;
-        CreateDictionaries();
-        FireChanged();
+        cachedValuesInvalidated = true;
+        if (fireChangeEvents) FireChanged();
       }
     }
@@ -104,14 +111,6 @@
       scalingOffset = new double[] { 0.0 };
       scalingFactor = new double[] { 1.0 };
-    }
-
-    private void CreateDictionaries() {
-      // keep a means and ranges dictionary for each column (possible target variable) of the dataset.
-      cachedMeans = new Dictionary<int, Dictionary<int, double>>[columns];
-      cachedRanges = new Dictionary<int, Dictionary<int, double>>[columns];
-      for (int i = 0; i < columns; i++) {
-        cachedMeans[i] = new Dictionary<int, Dictionary<int, double>>();
-        cachedRanges[i] = new Dictionary<int, Dictionary<int, double>>();
-      }
+      cachedValuesInvalidated = true;
+      fireChangeEvents = true;
     }
 
@@ -206,5 +205,4 @@
         }
       }
-      CreateDictionaries();
     }
 
@@ -270,4 +268,5 @@
 
     public double GetMean(int column, int from, int to) {
+      if (cachedValuesInvalidated) CreateDictionaries();
       if (!cachedMeans[column].ContainsKey(from) || !cachedMeans[column][from].ContainsKey(to)) {
         double[] values = new double[to - from];
@@ -289,4 +288,5 @@
 
     public double GetRange(int column, int from, int to) {
+      if (cachedValuesInvalidated) CreateDictionaries();
       if (!cachedRanges[column].ContainsKey(from) || !cachedRanges[column][from].ContainsKey(to)) {
         double[] values = new double[to - from];
@@ -329,6 +329,6 @@
         else ScaleVariable(column, 1.0 / range, -min);
       }
-      CreateDictionaries();
-      FireChanged();
+      cachedValuesInvalidated = true;
+      if (fireChangeEvents) FireChanged();
     }
 
@@ -340,6 +340,6 @@
         samples[i * columns + column] = (origValue + offset) * factor;
       }
-      CreateDictionaries();
-      FireChanged();
+      cachedValuesInvalidated = true;
+      if (fireChangeEvents) FireChanged();
     }
 
@@ -353,4 +353,16 @@
         scalingOffset[column] = 0.0;
       }
+      cachedValuesInvalidated = true;
+      if (fireChangeEvents) FireChanged();
+    }
+
+    private void CreateDictionaries() {
+      // keep a means and ranges dictionary for each column (possible target variable) of the dataset.
+      cachedMeans = new Dictionary<int, Dictionary<int, double>>[columns];
+      cachedRanges = new Dictionary<int, Dictionary<int, double>>[columns];
+      for (int i = 0; i < columns; i++) {
+        cachedMeans[i] = new Dictionary<int, Dictionary<int, double>>();
+        cachedRanges[i] = new Dictionary<int, Dictionary<int, double>>();
+      }
     }
   }
Index: trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Evaluators/GPEvaluatorBase.cs
===================================================================
--- trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Evaluators/GPEvaluatorBase.cs	(revision 2037)
+++ trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Evaluators/GPEvaluatorBase.cs	(revision 2038)
@@ -72,4 +72,5 @@
         }
       }
+      dataset.FireChangeEvents = false;
 
       Evaluate(scope, evaluator, dataset, targetVariable, start, end, useEstimatedValues);
@@ -81,4 +82,6 @@
         }
       }
+      dataset.FireChangeEvents = true;
+      dataset.FireChanged();
 
       // update the value of total evaluated nodes
Index: trunk/sources/HeuristicLab.Modeling/3.2/HeuristicLab.Modeling-3.2.csproj
===================================================================
--- trunk/sources/HeuristicLab.Modeling/3.2/HeuristicLab.Modeling-3.2.csproj	(revision 2037)
+++ trunk/sources/HeuristicLab.Modeling/3.2/HeuristicLab.Modeling-3.2.csproj	(revision 2038)
@@ -83,5 +83,4 @@
   <ItemGroup>
     <Compile Include="ClassificationProblemInjector.cs" />
-    <Compile Include="VariableImpactCalculator.cs" />
     <Compile Include="Model.cs" />
     <Compile Include="IModel.cs" />
@@ -106,4 +105,5 @@
     <Compile Include="TimeSeriesProblemInjector.cs" />
     <Compile Include="SimpleVarianceAccountedForEvaluator.cs" />
+    <Compile Include="VariableQualityImpactCalculator.cs" />
   </ItemGroup>
   <ItemGroup>
Index: trunk/sources/HeuristicLab.Modeling/3.2/VariableImpactCalculator.cs
===================================================================
--- trunk/sources/HeuristicLab.Modeling/3.2/VariableImpactCalculator.cs	(revision 2037)
+++ 	(revision )
@@ -1,106 +1,0 @@
-#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 class VariableImpactCalculator : OperatorBase {
-    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 VariableImpactCalculator()
-      : 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("VariableImpacts", "Variable impacts", 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;
-
-      if (SubOperators.Count < 1) throw new InvalidOperationException("VariableImpactCalculator needs a suboperator to evaluate the model");
-      IOperator evaluationOperator = this.SubOperators[0];
-
-      ItemList variableImpacts = 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 = referenceQuality / newQuality;
-        double impact = ratio < 1.0 ? 1.0 - ratio : 1.0 - 1.0 / ratio;
-        ItemList row = new ItemList();
-        row.Add(new StringData(dataset.GetVariableName(currentVariable)));
-        row.Add(new DoubleData(impact));
-        variableImpacts.Add(row);
-        ReplaceVariableValues(dirtyDataset, currentVariable, oldValues, start, end);
-      }
-      scope.AddVariable(new Variable(scope.TranslateName("VariableImpacts"), variableImpacts));
-      return null;
-    }
-
-    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;
-    }
-
-    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;
-      foreach(double v in newValues) {
-        ds.SetValue(index++, variableIndex, v);
-      }
-      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 2038)
+++ trunk/sources/HeuristicLab.Modeling/3.2/VariableQualityImpactCalculator.cs	(revision 2038)
@@ -0,0 +1,107 @@
+#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 class VariableQualityImpactCalculator : OperatorBase {
+    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 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;
+    }
+
+    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;
+    }
+
+    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);
+    }
+  }
+}
