Index: /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/Analysis/RSquaredEvaluator.cs
===================================================================
--- /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/Analysis/RSquaredEvaluator.cs	(revision 15824)
+++ /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/Analysis/RSquaredEvaluator.cs	(revision 15824)
@@ -0,0 +1,88 @@
+﻿using System;
+using HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration.GrammarEnumeration;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Problems.DataAnalysis;
+using HeuristicLab.Problems.DataAnalysis.Symbolic;
+using HeuristicLab.Problems.DataAnalysis.Symbolic.Regression;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration {
+  public class RSquaredEvaluator : Item, IGrammarEnumerationAnalyzer {
+    private readonly string BestTrainingQualityResultName = "Best R² (Training)";
+    private readonly string BestTrainingModelResultName = "Best model (Training)";
+    private readonly string BestTrainingSolutionResultName = "Best solution (Training)";
+
+    private readonly ISymbolicDataAnalysisExpressionTreeInterpreter expressionTreeLinearInterpreter = new SymbolicDataAnalysisExpressionTreeLinearInterpreter();
+
+    public RSquaredEvaluator() { }
+
+    protected RSquaredEvaluator(RSquaredEvaluator original, Cloner cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RSquaredEvaluator(this, cloner);
+    }
+
+    public void Register(GrammarEnumerationAlgorithm algorithm) {
+      algorithm.Started += OnStarted;
+      algorithm.Stopped += OnStopped;
+
+      algorithm.DistinctSentenceGenerated += AlgorithmOnDistinctSentenceGenerated;
+    }
+
+    public void Deregister(GrammarEnumerationAlgorithm algorithm) {
+      algorithm.Started -= OnStarted;
+      algorithm.Stopped -= OnStopped;
+
+      algorithm.DistinctSentenceGenerated -= AlgorithmOnDistinctSentenceGenerated;
+    }
+
+    private void AlgorithmOnDistinctSentenceGenerated(object sender, PhraseAddedEventArgs phraseAddedEventArgs) {
+      GrammarEnumerationAlgorithm algorithm = (GrammarEnumerationAlgorithm)sender;
+      EvaluateSentence(algorithm, phraseAddedEventArgs.NewPhrase);
+    }
+
+    private void OnStarted(object sender, EventArgs eventArgs) {
+      GrammarEnumerationAlgorithm algorithm = (GrammarEnumerationAlgorithm)sender;
+      algorithm.Results.Add(new Result(BestTrainingQualityResultName, new DoubleValue(-1.0)));
+
+      algorithm.BestTrainingSentence = null;
+    }
+
+    private void OnStopped(object sender, EventArgs eventArgs) {
+      GrammarEnumerationAlgorithm algorithm = (GrammarEnumerationAlgorithm)sender;
+      if (algorithm.Results.ContainsKey(BestTrainingModelResultName)) {
+        SymbolicRegressionModel model = (SymbolicRegressionModel)algorithm.Results[BestTrainingModelResultName].Value;
+        IRegressionSolution bestTrainingSolution = new RegressionSolution(model, algorithm.Problem.ProblemData);
+
+        algorithm.Results.AddOrUpdateResult(BestTrainingSolutionResultName, bestTrainingSolution);
+      }
+    }
+
+    private void EvaluateSentence(GrammarEnumerationAlgorithm algorithm, SymbolString symbolString) {
+      SymbolicExpressionTree tree = algorithm.Grammar.ParseSymbolicExpressionTree(symbolString);
+
+      var problemData = algorithm.Problem.ProblemData;
+      SymbolicRegressionModel model = new SymbolicRegressionModel(
+        problemData.TargetVariable,
+        tree,
+        expressionTreeLinearInterpreter);
+
+      var target = problemData.TargetVariableTrainingValues;
+      var estVals = model.GetEstimatedValues(problemData.Dataset, problemData.TrainingIndices);
+      OnlineCalculatorError error;
+      var r2 = OnlinePearsonsRCalculator.Calculate(target, estVals, out error);
+      if (error != OnlineCalculatorError.None) r2 = 0.0;
+
+      var bestR2Result = (DoubleValue)algorithm.Results[BestTrainingQualityResultName].Value;
+      if (r2 > bestR2Result.Value) {
+        bestR2Result.Value = r2;
+        algorithm.Results.AddOrUpdateResult(BestTrainingModelResultName, model);
+
+        algorithm.BestTrainingSentence = symbolString;
+      }
+    }
+  }
+}
Index: /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/GrammarEnumeration/GrammarEnumerationAlgorithm.cs
===================================================================
--- /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/GrammarEnumeration/GrammarEnumerationAlgorithm.cs	(revision 15823)
+++ /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/GrammarEnumeration/GrammarEnumerationAlgorithm.cs	(revision 15824)
@@ -8,11 +8,8 @@
 using HeuristicLab.Core;
 using HeuristicLab.Data;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Optimization;
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.Problems.DataAnalysis;
-using HeuristicLab.Problems.DataAnalysis.Symbolic;
-using HeuristicLab.Problems.DataAnalysis.Symbolic.Regression;
 
 namespace HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration {
@@ -22,6 +19,4 @@
   public class GrammarEnumerationAlgorithm : FixedDataAnalysisAlgorithm<IRegressionProblem> {
     #region properties and result names
-    private readonly string BestTrainingQualityName = "Best R² (Training)";
-    private readonly string BestTrainingSolutionName = "Best solution (Training)";
     private readonly string SearchStructureSizeName = "Search Structure Size";
     private readonly string GeneratedPhrasesName = "Generated/Archived Phrases";
@@ -32,4 +27,5 @@
     private readonly string OverwrittenSentencesName = "Sentences overwritten";
     private readonly string AnalyzersParameterName = "Analyzers";
+    private readonly string ExpansionsPerSecondName = "Expansions per second";
 
 
@@ -72,6 +68,5 @@
     }
 
-    public SymbolString BestTrainingSentence;
-
+    public SymbolString BestTrainingSentence { get; set; }     // Currently set in RSquaredEvaluator: quite hacky, but makes testing much easier for now...
     #endregion
 
@@ -91,5 +86,4 @@
     public Grammar Grammar { get; private set; }
 
-    private readonly ISymbolicDataAnalysisExpressionTreeInterpreter expressionTreeLinearInterpreter = new SymbolicDataAnalysisExpressionTreeLinearInterpreter();
 
     #region ctors
@@ -109,5 +103,6 @@
       var availableAnalyzers = new IGrammarEnumerationAnalyzer[] {
         new SearchGraphVisualizer(),
-        new SentenceLogger()
+        new SentenceLogger(),
+        new RSquaredEvaluator()
       };
       Parameters.Add(new FixedValueParameter<ReadOnlyCheckedItemCollection<IGrammarEnumerationAnalyzer>>(
@@ -119,4 +114,5 @@
       }
       Analyzers.CheckedItemsChanged += AnalyzersOnCheckedItemsChanged;
+      Analyzers.SetItemCheckedState(Analyzers.First(analyzer => analyzer is RSquaredEvaluator), true);
     }
 
@@ -179,6 +175,4 @@
 
                 DistinctSentencesLength[phraseHash] = newPhrase.Count;
-                EvaluateSentence(newPhrase);
-
                 OnDistinctSentenceGenerated(fetchedPhrase.Hash, fetchedPhrase.SymbolString, phraseHash, newPhrase, expandedSymbol, productionAlternative);
               }
@@ -191,42 +185,10 @@
         }
       }
-
       UpdateView(force: true);
-      UpdateFinalResults();
-    }
-
-    #region Evaluation of generated models.
-
-    // Evaluate sentence within an algorithm run.
-    private void EvaluateSentence(SymbolString symbolString) {
-      SymbolicExpressionTree tree = Grammar.ParseSymbolicExpressionTree(symbolString);
-      SymbolicRegressionModel model = new SymbolicRegressionModel(
-        Problem.ProblemData.TargetVariable,
-        tree,
-        expressionTreeLinearInterpreter);
-
-      var probData = Problem.ProblemData;
-      var target = probData.TargetVariableTrainingValues;
-      var estVals = model.GetEstimatedValues(probData.Dataset, probData.TrainingIndices);
-      OnlineCalculatorError error;
-      var r2 = OnlinePearsonsRSquaredCalculator.Calculate(target, estVals, out error);
-      if (error != OnlineCalculatorError.None) r2 = 0.0;
-
-      var bestR2 = ((DoubleValue)Results[BestTrainingQualityName].Value).Value;
-      if (r2 > bestR2) {
-        ((DoubleValue)Results[BestTrainingQualityName].Value).Value = r2;
-        BestTrainingSentence = symbolString;
-      }
-    }
-
-    #endregion
+    }
 
     #region Visualization in HL
     // Initialize entries in result set.
     private void InitResults() {
-      BestTrainingSentence = null;
-
-      Results.Add(new Result(BestTrainingQualityName, new DoubleValue(-1.0)));
-
       Results.Add(new Result(GeneratedPhrasesName, new IntValue(0)));
       Results.Add(new Result(SearchStructureSizeName, new IntValue(0)));
@@ -236,4 +198,5 @@
       Results.Add(new Result(OverwrittenSentencesName, new IntValue(0)));
       Results.Add(new Result(AverageSentenceLengthName, new DoubleValue(1.0)));
+      Results.Add(new Result(ExpansionsPerSecondName, "In Thousand expansions per second", new IntValue(0)));
     }
 
@@ -251,17 +214,7 @@
         ((DoubleValue)Results[AverageSentenceLengthName].Value).Value = DistinctSentencesLength.Select(pair => pair.Value).Average();
         ((IntValue)Results[OverwrittenSentencesName].Value).Value = OverwrittenSentencesCount;
-      }
-    }
-
-    // Generate all Results after an algorithm run.
-    private void UpdateFinalResults() {
-      SymbolicExpressionTree tree = Grammar.ParseSymbolicExpressionTree(BestTrainingSentence);
-      SymbolicRegressionModel model = new SymbolicRegressionModel(
-        Problem.ProblemData.TargetVariable,
-        tree,
-        new SymbolicDataAnalysisExpressionTreeLinearInterpreter());
-
-      IRegressionSolution bestTrainingSolution = new RegressionSolution(model, Problem.ProblemData);
-      Results.AddOrUpdateResult(BestTrainingSolutionName, bestTrainingSolution);
+        ((IntValue)Results[ExpansionsPerSecondName].Value).Value = (int)((PhraseExpansionCount /
+                                                                          ExecutionTime.TotalSeconds) / 1000.0);
+      }
     }
     #endregion
Index: /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration.csproj
===================================================================
--- /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration.csproj	(revision 15823)
+++ /branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration.csproj	(revision 15824)
@@ -49,61 +49,61 @@
     <Reference Include="HeuristicLab.Common-3.3">
       <HintPath>..\..\..\trunk\bin\HeuristicLab.Common-3.3.dll</HintPath>
-	  <Private>False</Private>
+      <Private>False</Private>
     </Reference>
     <Reference Include="HeuristicLab.Core-3.3">
       <HintPath>..\..\..\trunk\bin\HeuristicLab.Core-3.3.dll</HintPath>
-	  <Private>False</Private>
+      <Private>False</Private>
     </Reference>
     <Reference Include="HeuristicLab.Data-3.3">
       <HintPath>..\..\..\trunk\bin\HeuristicLab.Data-3.3.dll</HintPath>
-	  <Private>False</Private>
+      <Private>False</Private>
     </Reference>
     <Reference Include="HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4">
       <HintPath>..\..\..\trunk\bin\HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4.dll</HintPath>
       <Private>False</Private>
-	</Reference>
+    </Reference>
     <Reference Include="HeuristicLab.Operators-3.3">
       <HintPath>..\..\..\trunk\bin\HeuristicLab.Operators-3.3.dll</HintPath>
       <Private>False</Private>
-	</Reference>
+    </Reference>
     <Reference Include="HeuristicLab.Optimization-3.3">
       <HintPath>..\..\..\trunk\bin\HeuristicLab.Optimization-3.3.dll</HintPath>
-	  <Private>False</Private>
+      <Private>False</Private>
     </Reference>
     <Reference Include="HeuristicLab.Parameters-3.3">
       <HintPath>..\..\..\trunk\bin\HeuristicLab.Parameters-3.3.dll</HintPath>
-	  <Private>False</Private>
+      <Private>False</Private>
     </Reference>
     <Reference Include="HeuristicLab.Persistence-3.3">
       <HintPath>..\..\..\trunk\bin\HeuristicLab.Persistence-3.3.dll</HintPath>
-	  <Private>False</Private>
+      <Private>False</Private>
     </Reference>
     <Reference Include="HeuristicLab.PluginInfrastructure-3.3">
       <HintPath>..\..\..\trunk\bin\HeuristicLab.PluginInfrastructure-3.3.dll</HintPath>
-	  <Private>False</Private>
+      <Private>False</Private>
     </Reference>
     <Reference Include="HeuristicLab.Problems.DataAnalysis-3.4">
       <HintPath>..\..\..\trunk\bin\HeuristicLab.Problems.DataAnalysis-3.4.dll</HintPath>
-	  <Private>False</Private>
+      <Private>False</Private>
     </Reference>
     <Reference Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4">
       <HintPath>..\..\..\trunk\bin\HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.dll</HintPath>
       <Private>False</Private>
-	</Reference>
+    </Reference>
     <Reference Include="HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4">
       <HintPath>..\..\..\trunk\bin\HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.dll</HintPath>
-	  <Private>False</Private>
+      <Private>False</Private>
     </Reference>
     <Reference Include="HeuristicLab.Problems.Instances-3.3">
       <HintPath>..\..\..\trunk\bin\HeuristicLab.Problems.Instances-3.3.dll</HintPath>
-	  <Private>False</Private>
+      <Private>False</Private>
     </Reference>
     <Reference Include="HeuristicLab.Random-3.3">
       <HintPath>..\..\..\trunk\bin\HeuristicLab.Random-3.3.dll</HintPath>
-	  <Private>False</Private>
+      <Private>False</Private>
     </Reference>
     <Reference Include="HeuristicLab.Problems.Instances.DataAnalysis-3.3">
       <HintPath>..\..\..\trunk\bin\HeuristicLab.Problems.Instances.DataAnalysis-3.3.dll</HintPath>
-	  <Private>False</Private>
+      <Private>False</Private>
     </Reference>
     <Reference Include="System" />
@@ -111,4 +111,5 @@
   <ItemGroup>
     <Compile Include="Analysis\IGrammarEnumerationAnalyzer.cs" />
+    <Compile Include="Analysis\RSquaredEvaluator.cs" />
     <Compile Include="Analysis\SentenceLogger.cs" />
     <Compile Include="Analysis\SearchGraphVisualizer.cs" />
@@ -119,4 +120,5 @@
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="GrammarEnumeration\Symbol.cs" />
+    <Compile Include="Plugin.cs" />
   </ItemGroup>
   <ItemGroup>
Index: /branches/2886_SymRegGrammarEnumeration/Test/TreeHashingTest.cs
===================================================================
--- /branches/2886_SymRegGrammarEnumeration/Test/TreeHashingTest.cs	(revision 15823)
+++ /branches/2886_SymRegGrammarEnumeration/Test/TreeHashingTest.cs	(revision 15824)
@@ -170,26 +170,4 @@
       Assert.AreNotEqual(hash1, hash2);
     }*/
-
-    #region parser
-
-    [TestMethod]
-    [TestCategory("Parser")]
-    public void InfixParserSimpleTest() {
-      SymbolString postfix = new SymbolString(new[] { varA, varB, varC, grammar.Addition, grammar.Addition });
-      SymbolString infix = new SymbolString(new[] { varA, grammar.Addition, varB, grammar.Addition, varC });
-
-      Assert.AreEqual(infix.ToString(), grammar.ToInfixString(postfix));
-    }
-
-    [TestMethod]
-    [TestCategory("Parser")]
-    public void InfixParserComplexTest() {
-      SymbolString postfix = new SymbolString(new[] { varB, varA, varB, varC, grammar.Multiplication, grammar.Addition, grammar.Addition });
-      SymbolString infix = new SymbolString(new[] { varB, grammar.Addition, varA, grammar.Addition, varB, grammar.Multiplication, varC });
-
-      Assert.AreEqual(infix.ToString(), grammar.ToInfixString(postfix));
-    }
-
-    #endregion
   }
 }
