Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/Analyzers/SymbolicDataAnalysisSchemaFrequencyAnalyzer.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/Analyzers/SymbolicDataAnalysisSchemaFrequencyAnalyzer.cs	(revision 13481)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/Analyzers/SymbolicDataAnalysisSchemaFrequencyAnalyzer.cs	(revision 13481)
@@ -0,0 +1,158 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.EvolutionTracking;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Tracking.Analyzers {
+  [Item("SymbolicDataAnalysisSchemaFrequencyAnalyzer", "An analyzer which counts schema frequencies in the population.")]
+  [StorableClass]
+  public class SymbolicDataAnalysisSchemaFrequencyAnalyzer : EvolutionTrackingAnalyzer<ISymbolicExpressionTree> {
+    private const string MinimumSchemaLengthParameterName = "MinimumSchemaLength";
+
+    [Storable]
+    private readonly SymbolicExpressionTreePhenotypicSimilarityCalculator phenotypicSimilarityCalculator;
+
+    [Storable]
+    private readonly SymbolicExpressionTreeBottomUpSimilarityCalculator genotypicSimilarityCalculator;
+
+    [Storable]
+    private readonly ISymbolicExpressionTreeNodeEqualityComparer comparer;
+    private QueryMatch qm;
+
+    public IFixedValueParameter<IntValue> MinimumSchemaLengthParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[MinimumSchemaLengthParameterName]; }
+    }
+
+    public SymbolicDataAnalysisSchemaFrequencyAnalyzer() {
+      comparer = new SymbolicExpressionTreeNodeEqualityComparer {
+        MatchConstantValues = false,
+        MatchVariableNames = true,
+        MatchVariableWeights = false
+      };
+      qm = new QueryMatch(comparer) { MatchParents = true };
+      phenotypicSimilarityCalculator = new SymbolicExpressionTreePhenotypicSimilarityCalculator();
+      genotypicSimilarityCalculator = new SymbolicExpressionTreeBottomUpSimilarityCalculator { SolutionVariableName = "SymbolicExpressionTree" };
+      Parameters.Add(new FixedValueParameter<IntValue>(MinimumSchemaLengthParameterName, new IntValue(10)));
+    }
+
+    protected SymbolicDataAnalysisSchemaFrequencyAnalyzer(SymbolicDataAnalysisSchemaFrequencyAnalyzer original,
+      Cloner cloner) : base(original, cloner) {
+      comparer = original.comparer;
+      phenotypicSimilarityCalculator = original.phenotypicSimilarityCalculator;
+      genotypicSimilarityCalculator = original.genotypicSimilarityCalculator;
+      qm = new QueryMatch(comparer) { MatchParents = true };
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicDataAnalysisSchemaFrequencyAnalyzer(this, cloner);
+    }
+
+    [StorableConstructor]
+    protected SymbolicDataAnalysisSchemaFrequencyAnalyzer(bool deserializing) : base(deserializing) { }
+
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      qm = new QueryMatch(comparer) { MatchParents = true };
+    }
+
+    public override IOperation Apply() {
+      int updateInterval = UpdateIntervalParameter.Value.Value;
+      IntValue updateCounter = UpdateCounterParameter.ActualValue;
+      // if counter does not yet exist then initialize it with update interval
+      // to make sure the solutions are analyzed on the first application of this operator
+      if (updateCounter == null) {
+        updateCounter = new IntValue(updateInterval);
+        UpdateCounterParameter.ActualValue = updateCounter;
+      }
+      //analyze solutions only every 'updateInterval' times
+      if (updateCounter.Value != updateInterval) {
+        updateCounter.Value++;
+        return base.Apply();
+      }
+      updateCounter.Value = 1;
+
+      if (PopulationGraph == null || Generation.Value == 0)
+        return base.Apply();
+
+      var minimumSchemaLength = MinimumSchemaLengthParameter.Value.Value;
+      var vertices = PopulationGraph.GetByRank(Generation.Value).Cast<IGenealogyGraphNode<ISymbolicExpressionTree>>().ToList();
+      var formatter = new SymbolicExpressionTreeStringFormatter { Indent = false, AppendNewLines = false };
+
+      var schemas = SchemaCreator.GenerateSchemas(vertices, minimumSchemaLength).ToList();
+      var trees = vertices.Select(x => x.Data).ToList();
+      var qualities = vertices.Select(x => x.Quality).ToList();
+      var scopes = ExecutionContext.Scope.SubScopes; // the scopes of all the individuals, needed because the tree evaluated values are stored in the scope and we use them for the phenotypic similarity
+
+      var matrix = new DoubleMatrix(schemas.Count, 5) {
+        RowNames = schemas.Select(x => formatter.Format(x.Root.GetSubtree(0).GetSubtree(0))),
+        ColumnNames = new[] { "Avg. Length", "Avg. Quality", "Relative Frequency", "Avg. Phen. Sim.", "Avg. Gen. Sim" },
+        SortableView = true
+      };
+
+      for (int i = 0; i < schemas.Count; ++i) {
+        var schema = schemas[i];
+        int count = 0;
+        double avgLength = 0;
+        double avgQuality = 0;
+        var matchingScopes = new ScopeList();
+        for (int j = 0; j < trees.Count; ++j) {
+          var tree = trees[j];
+          if (qm.Match(tree, schema)) {
+            count++;
+            avgLength += tree.Length;
+            avgQuality += qualities[j];
+            matchingScopes.Add(scopes[j]);
+          }
+        }
+        avgLength /= count;
+        avgQuality /= count;
+        double relativeFreq = (double)count / trees.Count;
+        double avgPhenotypicSimilarity = SchemaEvaluator.CalculateSimilarity(matchingScopes, phenotypicSimilarityCalculator, true, 4);
+        double avgGenotypicSimilarity = SchemaEvaluator.CalculateSimilarity(matchingScopes, genotypicSimilarityCalculator, true, 4);
+
+        matrix[i, 0] = avgLength;
+        matrix[i, 1] = avgQuality;
+        matrix[i, 2] = relativeFreq;
+        matrix[i, 3] = avgPhenotypicSimilarity;
+        matrix[i, 4] = avgGenotypicSimilarity;
+      }
+
+      if (Results.ContainsKey("Schema Frequencies")) {
+        var result = Results["Schema Frequencies"];
+        result.Value = matrix;
+      } else {
+        var result = new Result("Schema Frequencies", matrix);
+        Results.Add(result);
+      }
+
+      return base.Apply();
+    }
+  }
+}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/Analyzers/SymbolicDataAnalysisSubtreeSampleCountAnalyzer.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/Analyzers/SymbolicDataAnalysisSubtreeSampleCountAnalyzer.cs	(revision 12966)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/Analyzers/SymbolicDataAnalysisSubtreeSampleCountAnalyzer.cs	(revision 13481)
@@ -104,12 +104,4 @@
           g.Weight = v.Weight;
         }
-
-        // analyze subtree frequencies
-        foreach (var v in PopulationGraph.GetByRank(Generation.Value)) {
-          var g = (IGenealogyGraphNode<ISymbolicExpressionTree>)v;
-          var t = g.Data;
-
-
-        }
       }
 
