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;
+
+ ///
+ /// An operater that tracks the frequencies of distinct push expressions in a push solution
+ ///
+ [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(PushConfigurationParameterName, "The current specified push configuration."));
+ Parameters.Add(new ScopeTreeLookupParameter(IntegerVectorParameterName, "The integer vectors to analyze."));
+ Parameters.Add(new LookupParameter(ExpressionFrequenciesParameterName, "The data table to store the instruction frequencies."));
+ Parameters.Add(new LookupParameter(ResultsParameterName, "The result collection where the symbol frequencies should be stored."));
+
+ Parameters.Add(new FixedValueParameter(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 PushConfigurationParameter
+ {
+ get { return (ILookupParameter)Parameters[PushConfigurationParameterName]; }
+ }
+
+ public IScopeTreeLookupParameter IntegerVectorParameter
+ {
+ get { return (IScopeTreeLookupParameter)Parameters[IntegerVectorParameterName]; }
+ }
+
+ public ILookupParameter ExpressionFrequenciesParameter
+ {
+ get { return (ILookupParameter)Parameters[ExpressionFrequenciesParameterName]; }
+ }
+
+ public ILookupParameter ResultsParameter
+ {
+ get { return (ILookupParameter)Parameters[ResultsParameterName]; }
+ }
+
+ public IValueParameter AggregateStackTypesParameter
+ {
+ get { return (IValueParameter)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(this IEnumerable 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()
+ .Where(values.Contains)
+ .Aggregate(0, (current, value) => current | Convert.ToInt32(value));
+
+ return (T)Enum.Parse(typeof(T), builtValue.ToString());
+ }
+
+ public static IEnumerable ToValues(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;
+ }
+ }
+ }
+ }
+}