Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
09/03/12 15:26:04 (12 years ago)
Author:
bburlacu
Message:

#1772: Introduced base class and interface for tracing operators. Introduced SymbolicExpressionTreeNodeComparer interface to be implemented by node matching operators. Fixed bug in the TracingSymbolicExpressionTreeManipulator where nodes modified by the Full- and OnePoint tree shakers were not correctly detected. The SymbolicExpressionTreeNodeSimilarityComparer is now injected in the tracing genetic operators as a parameter.

Location:
branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.EvolutionaryTracking/3.4
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.EvolutionaryTracking/3.4/Analyzers/SymbolicExpressionTreeFragmentsAnalyzer.cs

    r8213 r8557  
    3333using HeuristicLab.Problems.DataAnalysis;
    3434using HeuristicLab.Problems.DataAnalysis.Symbolic;
     35// type definitions for convenience
    3536using HeuristicLab.Problems.DataAnalysis.Symbolic.Regression;
    36 // type definitions for convenience
    3737using CloneMapType = HeuristicLab.Core.ItemDictionary<HeuristicLab.Core.IItem, HeuristicLab.Core.IItem>;
    38 using SymbolicExpressionTreeNodeItem = HeuristicLab.EvolutionaryTracking.GenericWrapper<HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.SymbolicExpressionTreeNode>;
     38using SymbolicExpressionTreeNodeItem = HeuristicLab.EvolutionaryTracking.GenericWrapper<HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.ISymbolicExpressionTreeNode>;
    3939using TraceMapType = HeuristicLab.Core.ItemDictionary<HeuristicLab.Core.IItem, HeuristicLab.Core.IItemList<HeuristicLab.Core.IItem>>;
    4040
     
    4747  [StorableClass]
    4848  public sealed class SymbolicExpressionTreeFragmentsAnalyzer : SingleSuccessorOperator, IAnalyzer {
     49    #region Parameter names
    4950    private const string UpdateIntervalParameterName = "UpdateInterval";
    5051    private const string UpdateCounterParameterName = "UpdateCounter";
     
    6263    private const string FragmentLengthsDistributionParametersName = "FragmentLengths";
    6364    private const string FragmentFrequenciesParameterName = "FragmentFrequencies";
     65    private const string ParentsDiversityParameterName = "ParentsDiversity";
     66    #endregion
    6467
    6568    // impact values calculator
    66     private SymbolicRegressionSolutionValuesCalculator _calculator = new SymbolicRegressionSolutionValuesCalculator();
     69    private readonly SymbolicRegressionSolutionValuesCalculator calculator = new SymbolicRegressionSolutionValuesCalculator();
    6770
    6871    #region Parameter properties
     
    97100    public LookupParameter<DataTable> FragmentLengthsParameter {
    98101      get { return (LookupParameter<DataTable>)Parameters[FragmentLengthsDistributionParametersName]; }
     102    }
     103    public LookupParameter<DataTable> ParentsDiversityParameter {
     104      get { return (LookupParameter<DataTable>)Parameters[ParentsDiversityParameterName]; }
    99105    }
    100106    // auxiliary structures for tracking fragments and individuals from the previous generation
     
    165171      get { return FragmentFrequenciesParameter.ActualValue; }
    166172    }
     173    public DataTable ParentsDiversity {
     174      get { return ParentsDiversityParameter.ActualValue; }
     175    }
    167176    public SymbolicDataAnalysisExpressionTreeInterpreter SymbolicExpressionInterpreter {
    168177      get { return SymbolicExpressionInterpreterParameter.ActualValue; }
     
    174183
    175184    [StorableConstructor]
    176     private SymbolicExpressionTreeFragmentsAnalyzer(bool deserializing)
    177       : base() {
    178     }
    179     private SymbolicExpressionTreeFragmentsAnalyzer(SymbolicExpressionTreeFragmentsAnalyzer original, Cloner cloner)
    180       : base(original, cloner) {
    181     }
     185    private SymbolicExpressionTreeFragmentsAnalyzer(bool deserializing) : base(deserializing) { }
     186    private SymbolicExpressionTreeFragmentsAnalyzer(SymbolicExpressionTreeFragmentsAnalyzer original, Cloner cloner) : base(original, cloner) { }
    182187    public override IDeepCloneable Clone(Cloner cloner) {
    183188      return new SymbolicExpressionTreeFragmentsAnalyzer(this, cloner);
     
    185190    public SymbolicExpressionTreeFragmentsAnalyzer()
    186191      : base() {
     192      #region Add parameters
    187193      // analyzer update counter and update interval
    188194      Parameters.Add(new ValueParameter<IntValue>(UpdateIntervalParameterName, "The interval in which the tree length analysis should be applied.", new IntValue(1)));
     
    196202      Parameters.Add(new LookupParameter<CloneMapType>(SecondaryCloneMapParameterName, "Parameter to store the clone map from the previous generation"));
    197203      Parameters.Add(new LookupParameter<CloneMapType>(SecondaryFragmentMapParameterName, "Parameter to store the fragment map from the previous generation"));
    198       // other params
     204      // fragment statistics parameters
    199205      Parameters.Add(new ValueLookupParameter<ResultCollection>(ResultsParameterName, "The results collection where the analysis values should be stored."));
    200206      Parameters.Add(new LookupParameter<IntValue>(GenerationsParameterName, "The number of generations so far."));
     
    202208      Parameters.Add(new LookupParameter<DataTable>(FragmentLengthsDistributionParametersName, "The data table to store the distribution of fragment lengths."));
    203209      Parameters.Add(new LookupParameter<DataTable>(FragmentFrequenciesParameterName, "A data structure for fragment frequencies"));
     210      Parameters.Add(new LookupParameter<DataTable>(ParentsDiversityParameterName, "A data structure to store the diversity of the parents per generation."));
    204211      // impact calculation
    205212      Parameters.Add(new LookupParameter<SymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicExpressionInterpreterParameterName, "Interpreter for symbolic expression trees"));
    206213      Parameters.Add(new LookupParameter<RegressionProblemData>(SymbolicRegressionProblemDataParameterName, "The symbolic data analysis problem."));
     214      #endregion
     215
    207216      UpdateCounterParameter.Hidden = true;
    208217      UpdateIntervalParameter.Hidden = true;
    209 
    210       //_calculator = new SymbolicRegressionSolutionValuesCalculator();
    211218    }
    212219    #region After deserialization code
     
    230237        Parameters.Add(new LookupParameter<ItemList<ItemList<IItem>>>(FragmentFrequenciesParameterName, "A data structure for fragment frequencies"));
    231238      }
     239      if (!Parameters.ContainsKey(ParentsDiversityParameterName)) {
     240        Parameters.Add(new LookupParameter<DataTable>(ParentsDiversityParameterName, "A data table to store the diversity of the parents per generation."));
     241      }
    232242    }
    233243    #endregion
     
    244254    #endregion
    245255
     256    /* A small description of the way this analyzer works
     257     *
     258     * We keep 3 maps in the global scope: the GlobalTraceMap, the GlobalFragmentMap and the GlobalCloneMap that are updated on each step: selection, crossover, mutation
     259     * These maps provide information about the children, parents and transferred fragments as follows:
     260     *
     261     * 1) GlobalCloneMap
     262     *    This data structure provides the basis for tracking. In the selection step, every selected individual gets cloned and transferred into the recombination pool.
     263     *    The GlobalCloneMap keeps track of clones by mapping them to the original individuals. This is an essential step for building the genealogy graph. Using this
     264     *    structure we can find out how many times each individual was selected.
     265     *    The GlobalCloneMap consists of Key-Value pairs Clone->Original
     266     *
     267     * 2) GlobalTraceMap
     268     *    Keeps information in the form of key-value pairs Child->{Parents}, where {Parents} is a set consisting of
     269     *      - one parent individual (in the case of mutation), by language abuse we say that the individual that mutation acted on is the parent,
     270     *        and the resulting individual is the child
     271     *      - two parent individuals (in the case of crossover), named Parent0 and Parent1. Parent0 is the individual that crossover acts on by replacing
     272     *        one of its subtrees with a compatible subtree, randomly selected from Parent1
     273     *
     274     *    CROSSOVER
     275     *        Parent0     Parent1                                                                    {Parents}
     276     *           \           /                                                                           ^
     277     *            \       fragment (inserted from Parent1 into Parent0 to create the Child)              ^    [Mapping provided by the GlobalTraceMap]
     278     *             \       /                                                                             ^
     279     *              \     /                                                                              ^
     280     *               Child                                                                             Child
     281     *               
     282     *    MUTATION
     283     *        Parent0
     284     *           |
     285     *           |    [mutation acts on a random node/subtree in the 'parent' individual
     286     *           |
     287     *         Child
     288     *         
     289     *    Since crossover and mutation act on individuals in the recombination pool (which in fact are clones of individuals from the previous generation), the GlobalTraceMap
     290     *    is populated with values given by the mappings in the GlobalCloneMap, so that the original parent for each child is known.
     291     *   
     292     *  3) GlobalFragmentMap
     293     *     Keeps information in the form of Key-Value pairs about an individual and its respective fragment
     294     *     (ie., the subtree received via crossover or created/altered by mutation)
     295     * */
    246296    public override IOperation Apply() {
    247       if (Generations.Value == 0) return base.Apply();
    248297      UpdateCounter.Value++;
    249298      if (UpdateCounter.Value == UpdateInterval.Value) {
    250         ResultCollection results = ResultsParameter.ActualValue;
    251         if (FragmentStatistics == null) {
    252           FragmentStatisticsParameter.ActualValue = new DataTable("Fragment Statistics", "Statistical measurements of fragments aggregated over the whole population");
    253           FragmentStatistics.VisualProperties.YAxisTitle = "Fragment length/Similarities";
    254           results.Add(new Result("Fragment Statistics", FragmentStatistics));
     299        UpdateCounter.Value = 0; // reset counter
     300        if (Generations.Value > 0) {
     301          InitializeParameters();
     302
     303          CalculateFragmentStatistics();
     304
     305          // save the current generation so it can be compared to the following one, next time the analyzer is applied
     306          SecondaryTraceMap = (TraceMapType)GlobalTraceMap.Clone();
     307          SecondaryTraceMap.Clear();
     308          foreach (var m in GlobalTraceMap)
     309            SecondaryTraceMap.Add(m.Key, m.Value);
     310
     311          SecondaryCloneMap.Clear();
     312          foreach (var m in GlobalCloneMap)
     313            SecondaryCloneMap.Add(m.Key, m.Value);
     314
     315          SecondaryFragmentMap.Clear();
     316          foreach (var m in GlobalFragmentMap)
     317            SecondaryFragmentMap.Add(m.Key, m.Value);
    255318        }
    256         if (FragmentLengths == null) {
    257           FragmentLengthsParameter.ActualValue = new DataTable("Fragment Lengths", "Histograms for the distribution of fragment and individual lengths");
    258           FragmentLengths.VisualProperties.YAxisTitle = "Frequency";
    259           results.Add(new Result("Fragment Lengths", FragmentLengths));
    260         }
    261         if (FragmentFrequencies == null) {
    262           FragmentFrequenciesParameter.ActualValue = new DataTable("Fragment Frequencies", "Frequencies of good and high impact fragments");
    263           FragmentFrequencies.VisualProperties.YAxisTitle = "Frequency";
    264           results.Add(new Result("Fragment Frequencies", FragmentFrequencies));
    265         }
    266         if (SecondaryTraceMap == null) {
    267           SecondaryTraceMap = new TraceMapType();
    268         }
    269         if (SecondaryCloneMap == null) {
    270           SecondaryCloneMap = new CloneMapType();
    271         }
    272         if (SecondaryFragmentMap == null) {
    273           SecondaryFragmentMap = new CloneMapType();
    274         }
    275 
    276         UpdateCounter.Value = 0; // reset counter
    277         var gScope = ExecutionContext.Scope;
    278         while (gScope.Parent != null) gScope = gScope.Parent;
    279 
    280         // for this kind of tracking/analysis, we need at least 2 successive generations of crossover
    281         if (Generations.Value > 1) {
    282           #region Fragment Statistics
    283           InitializeRows();
    284           // create a dictionary for fast lookup of parents (to see which children from the previous generation become parents, and count their fragments)
    285           var parentsLookup = new Dictionary<ISymbolicExpressionTree, bool>();
    286           foreach (var parent in GlobalTraceMap.Values.SelectMany(x => x.Cast<ISymbolicExpressionTree>())) {
    287             if (!parentsLookup.ContainsKey(parent)) {
    288               parentsLookup.Add(parent, true);
    289             }
    290           }
    291           // the same, for fast lookup of clones (might not be needed after all)
    292           var clonesLookup = new Dictionary<ISymbolicExpressionTree, bool>();
    293           foreach (var original in GlobalCloneMap.Values.Cast<ISymbolicExpressionTree>()) {
    294             if (!clonesLookup.ContainsKey(original)) {
    295               clonesLookup.Add(original, true);
    296             }
    297           }
    298           var goodFragments = new List<ISymbolicExpressionTreeNode>();
    299           var goodParents = new List<ISymbolicExpressionTree>();
    300           var goodChildren = new List<ISymbolicExpressionTree>();
    301           // take all individuals that have received a fragment in the previous generation
    302           foreach (var m in SecondaryFragmentMap) {
    303             var individual = m.Key as ISymbolicExpressionTree;
    304             // check if the individual became a parent in the current generation,
    305             // by checking if it appears among the parents from the current generation trace map
    306             if (parentsLookup.ContainsKey(individual)) {
    307               var fragmentItem = m.Value as SymbolicExpressionTreeNodeItem;
    308               var fragment = fragmentItem.Content;
    309               if (fragment != null) {
    310                 goodFragments.Add(fragmentItem.Content);
    311                 goodParents.AddRange(SecondaryTraceMap[individual].Cast<ISymbolicExpressionTree>());
    312                 goodChildren.Add(individual);
    313               }
    314             }
    315           }
    316           var allFragments = SecondaryFragmentMap.Values.Where(x => ((SymbolicExpressionTreeNodeItem)x).Content != null).Select(x => ((SymbolicExpressionTreeNodeItem)x).Content as ISymbolicExpressionTreeNode).ToList();
    317           var highImpactFragments = new List<ISymbolicExpressionTreeNode>();
    318           var allParents = SecondaryTraceMap.Values.SelectMany(x => x.Cast<ISymbolicExpressionTree>()).ToList();
    319           var allChildren = SecondaryFragmentMap.Keys.Select(x => x as ISymbolicExpressionTree).ToList();
    320           // high impact fragments
    321           //foreach (var c in goodChildren) {
    322           //  var impactValues = _calculator.CalculateImpactValues(c, SymbolicExpressionInterpreter, SymbolicRegressionProblemData, 0, 0);
    323           //  var fragmentItem = SecondaryFragmentMap[c] as SymbolicExpressionTreeNodeItem;
    324           //  var fragment = fragmentItem.Content;
    325           //  if (fragment != null && impactValues[fragment] > 0.1)
    326           //    highImpactFragments.Add(fragment);
    327           //}
    328           FragmentFrequencies.Rows["Frequency of useful fragments"].Values.Add(goodFragments.Count);
    329           FragmentFrequencies.Rows["Frequency of high impact fragments"].Values.Add(highImpactFragments.Count);
    330           FragmentStatistics.Rows["Fragment lengths (good)"].Values.Add(goodFragments.Average(x => x.GetLength()));
    331           FragmentStatistics.Rows["Fragment lengths (all)"].Values.Add(allFragments.Average(x => x.GetLength()));
    332           //double avg = highImpactFragments.Count > 0 ? highImpactFragments.Average(x => x.GetLength()) : 0;
    333           //FragmentStatistics.Rows["Fragment lengths (high impact)"].Values.Add(avg);
    334           FragmentStatistics.Rows["Parent lengths (good)"].Values.Add(goodParents.Average(x => x.Length));
    335           FragmentStatistics.Rows["Parent lengths (all)"].Values.Add(allParents.Average(x => x.Length));
    336           FragmentStatistics.Rows["Child lengths (good)"].Values.Add(goodChildren.Average(x => x.Length));
    337           FragmentStatistics.Rows["Child lengths (all)"].Values.Add(allChildren.Average(x => x.Length));
    338           FragmentStatistics.Rows["Avg visitation length (all children)"].Values.Add(allChildren.Average(x => VisitationLength(x)));
    339           FragmentStatistics.Rows["Avg visitation length (good children)"].Values.Add(goodChildren.Average(x => VisitationLength(x)));
    340           //FragmentStatistics.Rows["Exact similarity (good fragments)"].Values.Add(CalculateSimilarity(allFragments, (int)SymbolicExpressionTreeMatching.SimilarityLevel.Exact));
    341           //foreach (var f in allFragments) f.SortSubtrees();
    342           //FragmentStatistics.Rows["Exact similarity (all fragments)"].Values.Add(CalculateSimilarity(allFragments, (int)SymbolicExpressionTreeMatching.SimilarityLevel.Exact));
    343 
    344           FragmentLengths.Rows["All fragments length distribution"].Values.Replace(allFragments.Select(x => (double)x.GetLength()));
    345           FragmentLengths.Rows["Useful fragments length distribution"].Values.Replace(goodFragments.Select(x => (double)x.GetLength()));
    346           FragmentLengths.Rows["All children length distribution"].Values.Replace(allChildren.Select(x => (double)x.Length));
    347           FragmentLengths.Rows["Useful children length distribution"].Values.Replace(goodChildren.Select(x => (double)x.Length));
    348           #endregion
    349         }
    350         // save the current generation so it can be compared to the following one, next time the analyzer is applied
    351         SecondaryTraceMap.Clear();
    352         foreach (var m in GlobalTraceMap)
    353           SecondaryTraceMap.Add(m.Key, m.Value);
    354 
    355         SecondaryCloneMap.Clear();
    356         foreach (var m in GlobalCloneMap)
    357           SecondaryCloneMap.Add(m.Key, m.Value);
    358 
    359         SecondaryFragmentMap.Clear();
    360         foreach (var m in GlobalFragmentMap)
    361           SecondaryFragmentMap.Add(m.Key, m.Value);
    362 
    363         // clear the global maps to save memory
     319      }
     320      if (Generations.Value > 0)
    364321        if (this.Successor == null || !(this.Successor is SymbolicExpressionTreeGenealogyAnalyzer)) {
     322          // clear the global maps to save memory
    365323          GlobalCloneMap.Clear();
    366324          GlobalTraceMap.Clear();
    367325          GlobalFragmentMap.Clear();
    368326        }
    369       }
    370327      return base.Apply();
     328    }
     329
     330    private void InitializeParameters() {
     331      #region Init parameters
     332      var results = ResultsParameter.ActualValue;
     333
     334      if (FragmentStatistics == null) {
     335        FragmentStatisticsParameter.ActualValue = new DataTable("Fragment Statistics", "Statistical measurements of fragments aggregated over the whole population");
     336        FragmentStatistics.VisualProperties.YAxisTitle = "Fragment length/Similarities";
     337        results.Add(new Result("Fragment Statistics", FragmentStatistics));
     338      }
     339      if (FragmentLengths == null) {
     340        FragmentLengthsParameter.ActualValue = new DataTable("Fragment Lengths", "Histograms for the distribution of fragment and individual lengths");
     341        FragmentLengths.VisualProperties.YAxisTitle = "Frequency";
     342        results.Add(new Result("Fragment Lengths", FragmentLengths));
     343      }
     344      if (FragmentFrequencies == null) {
     345        FragmentFrequenciesParameter.ActualValue = new DataTable("Fragment Frequencies", "Frequencies of good and high impact fragments");
     346        FragmentFrequencies.VisualProperties.YAxisTitle = "Frequency";
     347        results.Add(new Result("Fragment Frequencies", FragmentFrequencies));
     348      }
     349      if (ParentsDiversity == null) {
     350        ParentsDiversityParameter.ActualValue = new DataTable("Parents Diversity", "Number of unique parents per generation");
     351        ParentsDiversity.VisualProperties.YAxisTitle = "Unique parents";
     352        results.Add(new Result("Parents Diversity", ParentsDiversity));
     353      }
     354      if (SecondaryTraceMap == null) {
     355        SecondaryTraceMap = new TraceMapType();
     356      }
     357      if (SecondaryCloneMap == null) {
     358        SecondaryCloneMap = new CloneMapType();
     359      }
     360      if (SecondaryFragmentMap == null) {
     361        SecondaryFragmentMap = new CloneMapType();
     362      }
     363      #endregion
    371364    }
    372365
     
    435428      if (!FragmentFrequencies.Rows.ContainsKey("Frequency of high impact fragments")) {
    436429        FragmentFrequencies.Rows.Add(new DataRow("Frequency of high impact fragments") {
     430          VisualProperties = { StartIndexZero = true }
     431        });
     432      }
     433      if (!ParentsDiversity.Rows.ContainsKey("Unique parents")) {
     434        ParentsDiversity.Rows.Add(new DataRow("Unique parents") {
    437435          VisualProperties = { StartIndexZero = true }
    438436        });
     
    473471    }
    474472
     473    private void CalculateFragmentStatistics() {
     474      // for this kind of tracking/analysis, we need at least 2 successive generations of crossover
     475      if (Generations.Value > 1) {
     476        InitializeRows();
     477
     478        #region Fragment Statistics
     479        // create a hashset for fast lookup of parents (to see which children from the previous generation become parents, and count their fragments)
     480        var parentsLookup = new HashSet<ISymbolicExpressionTree>(GlobalTraceMap.Values.SelectMany(x => x.Cast<ISymbolicExpressionTree>()));
     481        var allParents = SecondaryTraceMap.Values.SelectMany(x => x.Cast<ISymbolicExpressionTree>()).ToList();
     482        var allChildren = SecondaryFragmentMap.Keys.Cast<ISymbolicExpressionTree>().ToList(); /* SecondaryTraceMap.Keys should be the same with SecondaryFragmentMap.Keys */
     483        var allFragments = SecondaryFragmentMap.Values.Cast<SymbolicExpressionTreeNodeItem>().Select(x => x.Content).Where(x => x != null).ToList();
     484        // "good" fragments are fragments contained in a surviving offspring (that became a parent)
     485        // "good" parents are those that produced a surviving offspring
     486        // "good" children are the surviving offspring
     487        var goodFragments = new List<ISymbolicExpressionTreeNode>();
     488        var goodParents = new List<ISymbolicExpressionTree>();
     489        var goodChildren = new List<ISymbolicExpressionTree>();
     490
     491        // take all individuals that have received a fragment in the previous generation
     492        foreach (var m in SecondaryFragmentMap) {
     493          var individual = m.Key as ISymbolicExpressionTree;
     494          // check if the individual became a parent in the current generation,
     495          // by checking if it appears among the parents from the current generation trace map
     496          if (parentsLookup.Contains(individual)) {
     497            var symbExprTreeNodeItem = m.Value as SymbolicExpressionTreeNodeItem;
     498            var fragment = symbExprTreeNodeItem.Content;
     499            if (fragment != null) {
     500              goodFragments.Add(fragment);
     501              goodParents.AddRange(SecondaryTraceMap[individual].Cast<ISymbolicExpressionTree>());
     502              goodChildren.Add(individual);
     503            }
     504          }
     505        }
     506
     507        if (false) {
     508          var highImpactFragments = new List<ISymbolicExpressionTreeNode>();
     509          foreach (var child in goodChildren) {
     510            var impactValues = calculator.CalculateImpactValues(child, SymbolicExpressionInterpreter, SymbolicRegressionProblemData, 0, 0);
     511            var fragmentItem = SecondaryFragmentMap[child] as SymbolicExpressionTreeNodeItem;
     512            var fragment = fragmentItem.Content;
     513            if (fragment != null && impactValues[fragment] > 0.1) {
     514              if (highImpactFragments.Contains(fragment, new SymbolicExpressionTreeNodeSimilarityComparer(SimilarityLevel.Exact)))
     515                continue;
     516              // prune fragment (remove irrelevant/low impact nodes)
     517              // this works because a child will never have an impact value greater than its parent
     518              foreach (var fnode in fragment.IterateNodesBreadth().Where(x => x.SubtreeCount > 0)) {
     519                for (int i = 0; i < fnode.SubtreeCount; ++i) {
     520                  var subtree = fnode.GetSubtree(i);
     521                  if (impactValues[subtree] < 0.1)
     522                    fnode.RemoveSubtree(i);
     523                }
     524              }
     525              highImpactFragments.Add(fragment);
     526            }
     527          }
     528        }
     529
     530        FragmentFrequencies.Rows["Frequency of useful fragments"].Values.Add(goodFragments.Count);
     531        //        FragmentFrequencies.Rows["Frequency of high impact fragments"].Values.Add(highImpactFragments.Count);
     532        FragmentStatistics.Rows["Fragment lengths (good)"].Values.Add(goodFragments.Average(x => x.GetLength()));
     533        FragmentStatistics.Rows["Fragment lengths (all)"].Values.Add(allFragments.Average(x => x.GetLength()));
     534        //        double avg = highImpactFragments.Count > 0 ? highImpactFragments.Average(x => x.GetLength()) : 0;
     535        //        FragmentStatistics.Rows["Fragment lengths (high impact)"].Values.Add(avg);
     536        FragmentStatistics.Rows["Parent lengths (good)"].Values.Add(goodParents.Average(x => x.Length));
     537        FragmentStatistics.Rows["Parent lengths (all)"].Values.Add(allParents.Average(x => x.Length));
     538        FragmentStatistics.Rows["Child lengths (good)"].Values.Add(goodChildren.Average(x => x.Length));
     539        FragmentStatistics.Rows["Child lengths (all)"].Values.Add(allChildren.Average(x => x.Length));
     540        //        FragmentStatistics.Rows["Avg visitation length (all children)"].Values.Add(allChildren.Average(x => VisitationLength(x)));
     541        //        FragmentStatistics.Rows["Avg visitation length (good children)"].Values.Add(goodChildren.Average(x => VisitationLength(x)));
     542        FragmentLengths.Rows["All fragments length distribution"].Values.Replace(allFragments.Select(x => (double)x.GetLength()));
     543        FragmentLengths.Rows["Useful fragments length distribution"].Values.Replace(goodFragments.Select(x => (double)x.GetLength()));
     544        FragmentLengths.Rows["All children length distribution"].Values.Replace(allChildren.Select(x => (double)x.Length));
     545        FragmentLengths.Rows["Useful children length distribution"].Values.Replace(goodChildren.Select(x => (double)x.Length));
     546        ParentsDiversity.Rows["Unique parents"].Values.Add(SecondaryCloneMap.Values.GroupBy(x => x).Count());
     547        #endregion
     548      }
     549    }
     550
    475551    private static int VisitationLength(ISymbolicExpressionTree tree) {
    476552      return VisitationLength(tree.Root);
     
    478554
    479555    private static int VisitationLength(ISymbolicExpressionTreeNode node) {
    480       int sum = 0;
    481       foreach (var n in node.IterateNodesBreadth())
    482         sum += n.GetLength();
    483       return sum;
     556      return node.IterateNodesBreadth().Sum(n => n.GetLength());
    484557    }
    485558
     
    491564    /// <param name="mode">The similarity mode (0 - exact, 1 - high, 2 - relaxed)</param>
    492565    /// <returns>The average number of similar fragments</returns>
    493     private static double CalculateSimilarity(IList<ISymbolicExpressionTreeNode> fragments, int mode) {
     566    private static double CalculateSimilarity(IList<ISymbolicExpressionTreeNode> fragments, SimilarityLevel similarity) {
    494567      var visited = new bool[fragments.Count];
    495568      int groups = 0;
     
    498571        for (int j = i + 1; j != fragments.Count; ++j) {
    499572          if (visited[j]) continue;
    500           if (fragments[i].IsSimilarTo(fragments[j], mode)) visited[j] = true;
     573          if (fragments[i].IsSimilarTo(fragments[j], similarity))
     574            visited[j] = true;
    501575        }
    502576        ++groups;
  • branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.EvolutionaryTracking/3.4/Analyzers/SymbolicExpressionTreeGenealogyAnalyzer.cs

    r8249 r8557  
    2020#endregion
    2121
    22 using System;
    23 using System.Drawing;
    2422using System.Globalization;
    2523using System.Linq;
    26 using System.Text;
    2724using System.Threading;
    2825using HeuristicLab.Common;
     
    4441  /// An operator that tracks the genealogy of every individual
    4542  /// </summary>
    46   [Item("SymbolicExpressionTreeGenealogyAnalyzer", "An operator that tracks tree lengths of Symbolic Expression Trees")]
     43  [Item("SymbolicExpressionTreeGenealogyAnalyzer", "An operator that tracks the genealogy of tree individuals")]
    4744  [StorableClass]
    4845  public sealed class SymbolicExpressionTreeGenealogyAnalyzer : SingleSuccessorOperator, IAnalyzer {
     46    #region Parameter names
    4947    private const string UpdateIntervalParameterName = "UpdateInterval";
    5048    private const string UpdateCounterParameterName = "UpdateCounter";
     
    6361    private const string SymbolicRegressionProblemDataParameterName = "ProblemData";
    6462    private const string SymbolicDataAnalysisProblemEvaluatorParameterName = "Evaluator";
     63    #endregion
    6564
    6665    #region Parameter properties
     
    159158
    160159    [StorableConstructor]
    161     private SymbolicExpressionTreeGenealogyAnalyzer(bool deserializing)
    162       : base() {
    163     }
    164     private SymbolicExpressionTreeGenealogyAnalyzer(SymbolicExpressionTreeGenealogyAnalyzer original, Cloner cloner)
    165       : base(original, cloner) {
    166     }
     160    private SymbolicExpressionTreeGenealogyAnalyzer(bool deserializing) : base(deserializing) { }
     161    private SymbolicExpressionTreeGenealogyAnalyzer(SymbolicExpressionTreeGenealogyAnalyzer original, Cloner cloner) : base(original, cloner) { }
    167162    public override IDeepCloneable Clone(Cloner cloner) {
    168163      return new SymbolicExpressionTreeGenealogyAnalyzer(this, cloner);
     
    218213        UpdateCounter.Value = 0; // reset counter
    219214
    220         var gScope = ExecutionContext.Scope;
    221         while (gScope.Parent != null) gScope = gScope.Parent;
    222215        SymbolicExpressionTreeGenealogyGraph graph;
    223216        if (!Results.ContainsKey(PopulationGraphResultParameterName)) {
     
    227220          graph = (SymbolicExpressionTreeGenealogyGraph)(Results[PopulationGraphResultParameterName].Value);
    228221        }
    229         // get tree quality values (Key => Individual, Value => Quality)
     222
     223        var gScope = ExecutionContext.Scope;
     224        while (gScope.Parent != null) gScope = gScope.Parent;
    230225        var scopes = (from s in gScope.SubScopes
    231226                      let individual = s.Variables.First().Value
     
    240235          var indiv = scopes[i].Tree;
    241236          var label = (generation * scopes.Count + i + 1).ToString(CultureInfo.InvariantCulture);
    242           if (!graph.HasNode(indiv)) {
    243             var node = new GenealogyGraphNode(indiv) { Label = label };
    244             graph.AddNode(node);
    245             // node metadata
    246             graph[node].Ranks.Add(generation);
    247             graph[node].Quality = scopes[i].Quality;
    248             graph[node].IsElite = i < Elites.Value;
    249           } else {
    250             var node = graph.GetNode(indiv);
    251             graph[node].Ranks.Add(generation);
    252           }
     237          var childGraphNode = new SymbolicExpressionGenealogyGraphNode {
     238            SymbolicExpressionTree = indiv,
     239            Quality = scopes[i].Quality,
     240            IsElite = i < Elites.Value,
     241            Label = label
     242          };
     243          graph.AddNode(childGraphNode);
     244          childGraphNode.Ranks.Add(generation);
    253245          if (generation == 0) continue;
    254246          if (!GlobalTraceMap.ContainsKey(indiv)) continue;
     
    256248          var parents = GlobalTraceMap[indiv].Cast<ISymbolicExpressionTree>();
    257249          foreach (var parent in parents) {
    258             object data = ((GenericWrapper<SymbolicExpressionTreeNode>)GlobalFragmentMap[indiv]).Content;
     250            var fragmentFromParent = ((GenericWrapper<ISymbolicExpressionTreeNode>)GlobalFragmentMap[indiv]).Content;
     251            SymbolicExpressionGenealogyGraphNode parentGraphNode;
    259252            if (GlobalTraceMap.ContainsKey(parent)) {
    260               var node = new GenealogyGraphNode(parent) { Label = "X" };
    261               graph.AddNode(node);
    262               graph[node].Quality = Evaluate(parent);
    263               graph[node].Ranks.Add(generation - 0.5);
    264               var pp = GlobalTraceMap[parent].Cast<SymbolicExpressionTree>();
    265               foreach (var p in pp) {
    266                 data = ((GenericWrapper<SymbolicExpressionTreeNode>)GlobalFragmentMap[parent]).Content;
    267                 graph.AddArc(p, parent, null, data);
     253              parentGraphNode = new SymbolicExpressionGenealogyGraphNode {
     254                SymbolicExpressionTree = parent,
     255                Quality = Evaluate(parent)
     256              };
     257              graph.AddNode(parentGraphNode);
     258              parentGraphNode.Ranks.Add(generation - 0.5);
     259              var parentParents = GlobalTraceMap[parent].Cast<SymbolicExpressionTree>();
     260              foreach (var parentParent in parentParents) {
     261                var fragmentFromParentParent = ((GenericWrapper<ISymbolicExpressionTreeNode>)GlobalFragmentMap[parent]).Content;
     262                // we store the fragment in the arc
     263                var parentParentGraphNode = graph.GetGraphNodes(parentParent).Last();
     264                graph.AddArc(parentParentGraphNode, parentGraphNode, null, fragmentFromParentParent);
    268265              }
     266            } else { // individual is an elite
     267              parentGraphNode = graph.GetGraphNodes(parent).Last();
    269268            }
    270             graph.AddArc(parent, indiv, null, data);
     269            graph.AddArc(parentGraphNode, childGraphNode, null, fragmentFromParent);
    271270          }
    272271        }
    273272        // clear trace and clone maps in preparation for the next generation
    274         if (generation == 0) return base.Apply();
     273
     274      }
     275      if (Generations.Value > 0)
    275276        if (this.Successor == null || !(this.Successor is SymbolicExpressionTreeFragmentsAnalyzer)) {
    276277          GlobalTraceMap.Clear();
     
    278279          GlobalFragmentMap.Clear();
    279280        }
    280       }
    281281      return base.Apply();
    282282    }
     
    296296      return quality;
    297297    }
    298 
    299     #region Export to dot file
    300     private static void WriteDot(string path, SymbolicExpressionTreeGenealogyGraph graph) {
    301       using (var file = new System.IO.StreamWriter(path)) {
    302         string nl = Environment.NewLine;
    303         file.WriteLine("digraph \"lineage " + graph.AverageDegree.ToString(CultureInfo.InvariantCulture) + "\" {" + nl + "ratio=auto;" + nl + "mincross=2.0");
    304         file.WriteLine("\tnode [shape=circle,label=\"\",style=filled]");
    305 
    306         foreach (var node in graph.Values) {
    307           var color = Color.FromArgb((int)((1 - graph[node].Quality) * 255), (int)(graph[node].Quality * 255), 0);
    308           string fillColor = String.Format("#{0:x2}{1:x2}{2:x2}", color.R, color.G, color.B);
    309           string shape = "circle";
    310           if (graph[node].IsElite)
    311             shape = "doublecircle";
    312           file.WriteLine("\t\"" + node.Id + "\" [shape=" + shape + ",fillcolor=\"" + fillColor + "\",label=\"" + node.Label + "\"];");
    313           if (node.InEdges == null)
    314             continue;
    315           foreach (var edge in node.InEdges) {
    316             //var edgeStyle = node.InEdges.Count == 1 ? "dashed" : String.Empty;
    317             var edgeStyle = String.Empty;
    318             file.WriteLine("\t\"" + edge.Target.Id + "\" -> \"" + node.Id + "\" [arrowsize=.5, color=\"" + fillColor + "\", style=\"" + edgeStyle + "\"];");
    319           }
    320         }
    321         foreach (var g in graph.Values.GroupBy(x => graph[x].Ranks[0])) {
    322           var sb = new StringBuilder();
    323           sb.Append("\t{rank=same;");
    324           foreach (var node in g)
    325             sb.Append("\"" + node.Id + "\" ");
    326           sb.Append("}\n");
    327           file.Write(sb.ToString());
    328         }
    329         file.WriteLine("}");
    330       }
    331     }
    332     #endregion
    333298  }
    334299}
  • branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.EvolutionaryTracking/3.4/HeuristicLab.EvolutionaryTracking-3.4.csproj

    r8213 r8557  
    8989    <Compile Include="Analyzers\SymbolicExpressionTreeFragmentsAnalyzer.cs" />
    9090    <Compile Include="Analyzers\SymbolicExpressionTreeGenealogyAnalyzer.cs" />
     91    <Compile Include="Analyzers\SymbolicExpressionTreeLineagesAnalyzer.cs" />
    9192    <Compile Include="Analyzers\SymbolicExpressionTreeRelativeLengthAnalyzer.cs" />
    9293    <Compile Include="GenealogyGraph.cs" />
     94    <Compile Include="GenealogyGraphArc.cs" />
     95    <Compile Include="GenealogyGraphNode.cs" />
    9396    <Compile Include="Interfaces\IGenealogyGraph.cs" />
     97    <Compile Include="Interfaces\IGenealogyGraphNode.cs" />
     98    <Compile Include="Interfaces\ISymbolicExpressionTreeGenealogyGraph.cs" />
    9499    <Compile Include="Plugin.cs" />
    95100    <Compile Include="Properties\AssemblyInfo.cs" />
  • branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.EvolutionaryTracking/3.4/Plugin.cs

    r8213 r8557  
    3030  [PluginDependency("HeuristicLab.Common.Resources", "3.3")]
    3131  [PluginDependency("HeuristicLab.Core", "3.3")]
    32   [PluginDependency("HeuristicLab.Data", "3.3")]
    3332  [PluginDependency("HeuristicLab.Encodings.SymbolicExpressionTreeEncoding", "3.4")]
    3433  [PluginDependency("HeuristicLab.Operators", "3.3")]
Note: See TracChangeset for help on using the changeset viewer.