Index: branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Analyzer/IPushExpressionAnalyzer.cs
===================================================================
--- branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Analyzer/IPushExpressionAnalyzer.cs	(revision 15033)
+++ branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Analyzer/IPushExpressionAnalyzer.cs	(revision 15033)
@@ -0,0 +1,6 @@
+﻿namespace HeuristicLab.Problems.ProgramSynthesis.Push.Analyzer {
+  using HeuristicLab.Optimization;
+
+  internal interface IPushExpressionAnalyzer : IAnalyzer {
+  }
+}
Index: branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Analyzer/PushExpressionFrequencyAnalyzer.cs
===================================================================
--- branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Analyzer/PushExpressionFrequencyAnalyzer.cs	(revision 15033)
+++ branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Analyzer/PushExpressionFrequencyAnalyzer.cs	(revision 15033)
@@ -0,0 +1,145 @@
+﻿namespace HeuristicLab.Problems.ProgramSynthesis.Push.Analyzer {
+  using System;
+  using System.Linq;
+
+  using HeuristicLab.Analysis;
+  using HeuristicLab.Common;
+  using HeuristicLab.Core;
+  using HeuristicLab.Data;
+  using HeuristicLab.Encodings.IntegerVectorEncoding;
+  using HeuristicLab.Operators;
+  using HeuristicLab.Optimization;
+  using HeuristicLab.Parameters;
+  using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+  using HeuristicLab.Problems.ProgramSynthesis.Push.Configuration;
+  using HeuristicLab.Problems.ProgramSynthesis.Push.Expressions;
+  using HeuristicLab.Problems.ProgramSynthesis.Push.Problem;
+
+  /// <summary>
+  /// An operater that tracks the frequencies of distinct push expressions in a push solution
+  /// </summary>
+  [Item("PushExpressionFrequencyAnalyzer", "An operater that tracks the frequencies of distinct push expressions in a push solution")]
+  [StorableClass]
+  public class PushExpressionFrequencyAnalyzer : SingleSuccessorOperator, IPushExpressionAnalyzer {
+
+    private const string PushConfigurationParameterName = "PushConfiguration";
+    private const string IntegerVectorParameterName = "IntegerVector";
+    private const string ResultsParameterName = "Results";
+    private const string ExpressionFrequenciesParameterName = "InstructionFrequencies";
+    private const string AggregateStackTypesParameterName = "Aggregate stack types";
+
+    public PushExpressionFrequencyAnalyzer() {
+      Parameters.Add(new LookupParameter<IReadOnlyPushConfiguration>(PushConfigurationParameterName, "The current specified push configuration."));
+      Parameters.Add(new ScopeTreeLookupParameter<IntegerVector>(IntegerVectorParameterName, "The integer vectors to analyze."));
+      Parameters.Add(new LookupParameter<DataTable>(ExpressionFrequenciesParameterName, "The data table to store the instruction frequencies."));
+      Parameters.Add(new LookupParameter<ResultCollection>(ResultsParameterName, "The result collection where the symbol frequencies should be stored."));
+
+      Parameters.Add(new FixedValueParameter<BoolValue>(AggregateStackTypesParameterName, "Determines if expressions should be aggregated by their primary stack type."));
+    }
+
+    [StorableConstructor]
+    public PushExpressionFrequencyAnalyzer(bool deserializing) : base(deserializing) { }
+
+    public PushExpressionFrequencyAnalyzer(PushExpressionFrequencyAnalyzer origin, Cloner cloner) : base(origin, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PushExpressionFrequencyAnalyzer(this, cloner);
+    }
+
+    public bool EnabledByDefault { get { return true; } }
+
+    public ILookupParameter<IReadOnlyPushConfiguration> PushConfigurationParameter
+    {
+      get { return (ILookupParameter<IReadOnlyPushConfiguration>)Parameters[PushConfigurationParameterName]; }
+    }
+
+    public IScopeTreeLookupParameter<IntegerVector> IntegerVectorParameter
+    {
+      get { return (IScopeTreeLookupParameter<IntegerVector>)Parameters[IntegerVectorParameterName]; }
+    }
+
+    public ILookupParameter<DataTable> ExpressionFrequenciesParameter
+    {
+      get { return (ILookupParameter<DataTable>)Parameters[ExpressionFrequenciesParameterName]; }
+    }
+
+    public ILookupParameter<ResultCollection> ResultsParameter
+    {
+      get { return (ILookupParameter<ResultCollection>)Parameters[ResultsParameterName]; }
+    }
+
+    public IValueParameter<BoolValue> AggregateStackTypesParameter
+    {
+      get { return (IValueParameter<BoolValue>)Parameters[AggregateStackTypesParameterName]; }
+    }
+
+    public bool AggregateStackTypes
+    {
+      get { return AggregateStackTypesParameter.Value.Value; }
+      set { AggregateStackTypesParameter.Value.Value = value; }
+    }
+
+
+    public override IOperation Apply() {
+      var config = PushConfigurationParameter.ActualValue;
+      var integerVectors = IntegerVectorParameter.ActualValue;
+      var pushPrograms = integerVectors.Select(iv => iv.ToPushProgram(config)).ToArray();
+
+      var results = ResultsParameter.ActualValue;
+      var frequencies = ExpressionFrequenciesParameter.ActualValue;
+
+      if (frequencies == null) {
+        frequencies = new DataTable(
+          "Instruction frequencies",
+          "Relative frequency of instructions aggregated over the whole population.") {
+          VisualProperties = {
+            YAxisTitle = "Relative Instruction Frequency"
+          }
+        };
+
+        ExpressionFrequenciesParameter.ActualValue = frequencies;
+        results.Add(new Result("Instruction frequencies", frequencies));
+      }
+
+      var allExpressions = pushPrograms
+        .SelectMany(p => p.DepthLast())
+        .Select(e => new {
+          Expression = e,
+          Attribute = ExpressionTable.TypeToAttributeTable[e.GetType()]
+        });
+
+      var expressionFrequencies = allExpressions
+        .GroupBy(x => AggregateStackTypes
+          ? x.Attribute.StackType.ToString()
+          : x.Attribute.Name)
+        .ToDictionary(
+          group => group.Key,
+          group => group.Count());
+
+      var totalNumberofExpressions = Math.Max(1.0, expressionFrequencies.Values.Sum());
+
+      // all rows must have the same number of values so we can just take the first
+      var numberOfValues = frequencies.Rows.Select(r => r.Values.Count).FirstOrDefault();
+
+      foreach (var pair in expressionFrequencies) {
+        if (!frequencies.Rows.ContainsKey(pair.Key)) {
+          var row = new DataRow(pair.Key, string.Empty, Enumerable.Repeat(0.0, numberOfValues)) {
+            VisualProperties = {
+              StartIndexZero = true
+            }
+          };
+
+          frequencies.Rows.Add(row);
+        }
+
+        frequencies.Rows[pair.Key].Values.Add(Math.Round(pair.Value / totalNumberofExpressions, 3));
+      }
+
+      // add a zero for each data row that was not modified in the previous loop
+      foreach (var row in frequencies.Rows.Where(r => r.Values.Count != numberOfValues + 1))
+        row.Values.Add(0.0);
+
+      return base.Apply();
+    }
+  }
+}
Index: branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Extensions/EnumExtensions.cs
===================================================================
--- branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Extensions/EnumExtensions.cs	(revision 15033)
+++ branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Extensions/EnumExtensions.cs	(revision 15033)
@@ -0,0 +1,33 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace HeuristicLab.Problems.ProgramSynthesis.Push.Extensions {
+  public static class EnumExtensions {
+    public static T ToMask<T>(this IEnumerable<T> values) where T : struct, IConvertible {
+      if (!typeof(T).IsEnum)
+        throw new ArgumentException("T must be an enumerated type.");
+
+      var builtValue = Enum
+        .GetValues(typeof(T))
+        .Cast<T>()
+        .Where(values.Contains)
+        .Aggregate(0, (current, value) => current | Convert.ToInt32(value));
+
+      return (T)Enum.Parse(typeof(T), builtValue.ToString());
+    }
+
+    public static IEnumerable<T> ToValues<T>(this T flags) where T : struct, IConvertible {
+      if (!typeof(T).IsEnum)
+        throw new ArgumentException("T must be an enumerated type.");
+
+      var inputInt = (int)(object)flags;
+      foreach (T value in Enum.GetValues(typeof(T))) {
+        var valueInt = (int)(object)value;
+        if (0 != (valueInt & inputInt)) {
+          yield return value;
+        }
+      }
+    }
+  }
+}
