Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
06/13/12 13:20:38 (12 years ago)
Author:
bburlacu
Message:

#1772: New analyzer: SymbolicExpressionTreeRelativeLengthAnalyzer. Rewrote the SymbolicExpressionTreeFragmentsAnalyzer, added generic wrapper to wrap HL objects as items.

File:
1 edited

Legend:

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

    r7800 r7997  
    2020#endregion
    2121
    22 using System;
    2322using System.Collections.Generic;
    2423using System.Linq;
     
    3231using HeuristicLab.Parameters;
    3332using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
    34 // type definitions for ease of use
     33// type definitions for convenience
    3534using CloneMapType = HeuristicLab.Core.ItemDictionary<HeuristicLab.Core.IItem, HeuristicLab.Core.IItem>;
     35using SymbolicExpressionTreeNodeItem = HeuristicLab.EvolutionaryTracking.GenericWrapper<HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.SymbolicExpressionTreeNode>;
    3636using TraceMapType = HeuristicLab.Core.ItemDictionary<HeuristicLab.Core.IItem, HeuristicLab.Core.IItemList<HeuristicLab.Core.IItem>>;
    3737
     
    4141  /// (Tracking of genetic variance and heredity)
    4242  /// </summary>
    43   /// [Item("SymbolicExpressionTreeGenealogyAnalyzer", "An operator that tracks tree lengths of Symbolic Expression Trees")]
     43  [Item("SymbolicExpressionTreeFragmentsAnalyzer", "An operator that provides statistics about crossover fragments")]
    4444  [StorableClass]
    4545  public sealed class SymbolicExpressionTreeFragmentsAnalyzer : SingleSuccessorOperator, IAnalyzer {
     
    4747    private const string UpdateCounterParameterName = "UpdateCounter";
    4848    private const string ResultsParameterName = "Results";
     49    private const string SecondaryTraceMapParameterName = "SecondaryTraceMap";
     50    private const string SecondaryFragmentMapParameterName = "SecondaryFragmentMap";
     51    private const string SecondaryCloneMapParameterName = "SecondaryCloneMap";
    4952    private const string GlobalTraceMapParameterName = "GlobalTraceMap";
    5053    private const string GlobalCloneMapParameterName = "GlobalCloneMap";
     
    5356    private const string FragmentStatisticsParameterName = "FragmentStatistics";
    5457    private const string FragmentLengthsDistributionParametersName = "FragmentLengths";
     58    private const string FragmentFrequenciesParameterName = "FragmentFrequencies";
    5559
    5660    #region Parameter properties
     
    6468      get { return (LookupParameter<ResultCollection>)Parameters[ResultsParameterName]; }
    6569    }
     70    public LookupParameter<IntValue> GenerationsParameter {
     71      get { return (LookupParameter<IntValue>)Parameters[GenerationsParameterName]; }
     72    }
     73    // tracking structures
    6674    public LookupParameter<TraceMapType> GlobalTraceMapParameter {
    6775      get { return (LookupParameter<TraceMapType>)Parameters[GlobalTraceMapParameterName]; }
     
    7381      get { return (LookupParameter<CloneMapType>)Parameters[GlobalFragmentMapParameterName]; }
    7482    }
    75     public LookupParameter<IntValue> GenerationsParameter {
    76       get { return (LookupParameter<IntValue>)Parameters[GenerationsParameterName]; }
     83    public LookupParameter<ItemList<ItemList<IItem>>> FragmentFrequenciesParameter {
     84      get { return (LookupParameter<ItemList<ItemList<IItem>>>)Parameters[FragmentFrequenciesParameterName]; }
    7785    }
    7886    public LookupParameter<DataTable> FragmentStatisticsParameter {
     
    8189    public LookupParameter<DataTable> FragmentLengthsParameter {
    8290      get { return (LookupParameter<DataTable>)Parameters[FragmentLengthsDistributionParametersName]; }
     91    }
     92    // auxiliary structures for tracking fragments and individuals from the previous generation
     93    // (this is needed because tracking is done in connection to the current generation, i.e., for
     94    // counting "successful" offspring and fragments
     95    public LookupParameter<TraceMapType> SecondaryTraceMapParameter {
     96      get { return (LookupParameter<TraceMapType>)Parameters[SecondaryTraceMapParameterName]; }
     97    }
     98    public LookupParameter<CloneMapType> SecondaryFragmentMapParameter {
     99      get { return (LookupParameter<CloneMapType>)Parameters[SecondaryFragmentMapParameterName]; }
     100    }
     101    public LookupParameter<CloneMapType> SecondaryCloneMapParameter {
     102      get { return (LookupParameter<CloneMapType>)Parameters[SecondaryCloneMapParameterName]; }
    83103    }
    84104    #endregion
     
    103123      get { return GlobalTraceMapParameter.ActualValue; }
    104124    }
     125    public TraceMapType SecondaryTraceMap {
     126      get { return SecondaryTraceMapParameter.ActualValue; }
     127      set { SecondaryTraceMapParameter.ActualValue = value; }
     128    }
     129    public CloneMapType SecondaryFragmentMap {
     130      get { return SecondaryFragmentMapParameter.ActualValue; }
     131      set { SecondaryFragmentMapParameter.ActualValue = value; }
     132    }
     133    public CloneMapType SecondaryCloneMap {
     134      get { return SecondaryCloneMapParameter.ActualValue; }
     135      set { SecondaryCloneMapParameter.ActualValue = value; }
     136    }
    105137    public CloneMapType GlobalFragmentMap {
    106138      get { return GlobalFragmentMapParameter.ActualValue; }
     
    114146    public DataTable FragmentLengths {
    115147      get { return FragmentLengthsParameter.ActualValue; }
     148    }
     149    public ItemList<ItemList<IItem>> FragmentFrequencies {
     150      get { return FragmentFrequenciesParameter.ActualValue; }
    116151    }
    117152    #endregion
     
    129164    public SymbolicExpressionTreeFragmentsAnalyzer()
    130165      : base() {
     166      // analyzer update counter and update interval
    131167      Parameters.Add(new ValueParameter<IntValue>(UpdateIntervalParameterName, "The interval in which the tree length analysis should be applied.", new IntValue(1)));
    132168      Parameters.Add(new ValueParameter<IntValue>(UpdateCounterParameterName, "The value which counts how many times the operator was called since the last update", new IntValue(0)));
     169      // tracking
    133170      Parameters.Add(new LookupParameter<TraceMapType>(GlobalTraceMapParameterName, "A global cache containing the whole genealogy."));
    134171      Parameters.Add(new LookupParameter<CloneMapType>(GlobalCloneMapParameterName, "A global map keeping track of trees and their clones (made during selection)."));
    135172      Parameters.Add(new LookupParameter<CloneMapType>(GlobalFragmentMapParameterName, "A global map keeping track of tree fragments received via crossover."));
     173      // secondary tracking
     174      Parameters.Add(new LookupParameter<TraceMapType>(SecondaryTraceMapParameterName, "Parameter to store the trace map from the previous generation"));
     175      Parameters.Add(new LookupParameter<CloneMapType>(SecondaryCloneMapParameterName, "Parameter to store the clone map from the previous generation"));
     176      Parameters.Add(new LookupParameter<CloneMapType>(SecondaryFragmentMapParameterName, "Parameter to store the fragment map from the previous generation"));
     177      // other params
    136178      Parameters.Add(new ValueLookupParameter<ResultCollection>(ResultsParameterName, "The results collection where the analysis values should be stored."));
    137179      Parameters.Add(new LookupParameter<IntValue>(GenerationsParameterName, "The number of generations so far."));
    138180      Parameters.Add(new LookupParameter<DataTable>(FragmentStatisticsParameterName, "The data table to store the fragment statistics."));
    139181      Parameters.Add(new LookupParameter<DataTable>(FragmentLengthsDistributionParametersName, "The data table to store the distribution of fragment lengths."));
     182      Parameters.Add(new LookupParameter<ItemList<ItemList<IItem>>>(FragmentFrequenciesParameterName, "A data structure for fragment frequencies"));
    140183      UpdateCounterParameter.Hidden = true;
    141184      UpdateIntervalParameter.Hidden = true;
     
    154197      if (!Parameters.ContainsKey(FragmentLengthsDistributionParametersName)) {
    155198        Parameters.Add(new LookupParameter<DataTable>(FragmentLengthsDistributionParametersName, "The data table to store the distribution of fragment lengths."));
     199      }
     200      if (!Parameters.ContainsKey(FragmentFrequenciesParameterName)) {
     201        Parameters.Add(new LookupParameter<ItemList<ItemList<IItem>>>(FragmentFrequenciesParameterName, "A data structure for fragment frequencies"));
    156202      }
    157203    }
     
    179225          results.Add(new Result("Fragment Statistics", FragmentStatistics));
    180226        }
    181         if (FragmentLengths == null) {
    182           FragmentLengthsParameter.ActualValue = new DataTable("Fragment and Tree Lengths", "Distribution of the lengths of the trees sampled by crossover");
    183           FragmentLengths.VisualProperties.XAxisTitle = "Tree/fragment length";
    184           results.Add(new Result("Fragment Lengths", FragmentLengths));
     227        if (FragmentFrequencies == null) {
     228          FragmentFrequenciesParameter.ActualValue = new ItemList<ItemList<IItem>>();
     229        }
     230        if (SecondaryTraceMap == null) {
     231          SecondaryTraceMap = new TraceMapType();
     232        }
     233        if (SecondaryCloneMap == null) {
     234          SecondaryCloneMap = new CloneMapType();
     235        }
     236        if (SecondaryFragmentMap == null) {
     237          SecondaryFragmentMap = new CloneMapType();
    185238        }
    186239
     
    189242        while (gScope.Parent != null) gScope = gScope.Parent;
    190243
    191         #region Fragment Statistics
    192         #region Table data
    193         if (!FragmentLengths.Rows.ContainsKey("Parent lengths distribution")) {
    194           var parentLenghtsRow = new DataRow("Parent lengths distribution");
    195           parentLenghtsRow.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Histogram;
    196           parentLenghtsRow.VisualProperties.StartIndexZero = true;
    197           parentLenghtsRow.VisualProperties.ScaleFactor = 1.0;
    198           FragmentLengths.Rows.Add(parentLenghtsRow);
    199         }
    200         if (!FragmentLengths.Rows.ContainsKey("Child lengths distribution")) {
    201           var treeLengthsRow = new DataRow("Child lengths distribution");
    202           treeLengthsRow.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Histogram;
    203           treeLengthsRow.VisualProperties.StartIndexZero = true;
    204           treeLengthsRow.VisualProperties.ScaleFactor = 1.0;
    205           FragmentLengths.Rows.Add(treeLengthsRow);
    206         }
    207         if (!FragmentLengths.Rows.ContainsKey("Fragment lengths distribution")) {
    208           var fragmentLengthsRow = new DataRow("Fragment lengths distribution");
    209           fragmentLengthsRow.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Histogram;
    210           fragmentLengthsRow.VisualProperties.StartIndexZero = true;
    211           fragmentLengthsRow.VisualProperties.ScaleFactor = 1.0;
    212           FragmentLengths.Rows.Add(fragmentLengthsRow);
    213         }
    214         // fragments
    215         if (!FragmentStatistics.Rows.ContainsKey("Average fragment length")) {
    216           var row = new DataRow("Average fragment length") { VisualProperties = { StartIndexZero = true } };
    217           FragmentStatistics.Rows.Add(row);
    218         }
    219         // child trees
    220         if (!FragmentStatistics.Rows.ContainsKey("Average child length")) {
    221           var row = new DataRow("Average child length") { VisualProperties = { StartIndexZero = true } };
    222           FragmentStatistics.Rows.Add(row);
    223         }
    224 
    225         // parents
    226         if (!FragmentStatistics.Rows.ContainsKey("Average parent length")) {
    227           var row = new DataRow("Average parent length") { VisualProperties = { StartIndexZero = true } };
    228           FragmentStatistics.Rows.Add(row);
    229         }
    230         // exact similarity
    231         if (!FragmentStatistics.Rows.ContainsKey("Similarity (exact)")) {
    232           var row = new DataRow("Similarity (exact)") { VisualProperties = { StartIndexZero = true } };
    233           FragmentStatistics.Rows.Add(row);
    234         }
    235         #endregion
    236 
    237         var fragments = new List<ISymbolicExpressionTreeNode>();
    238         var parents = new List<ISymbolicExpressionTree>();
    239         var trees = (from s in gScope.SubScopes select s.Variables.First().Value as ISymbolicExpressionTree).ToList();
    240 
    241         foreach (var tree in trees.Where(x => GlobalTraceMap.ContainsKey(x))) {
    242           if (GlobalTraceMap[tree].Count == 2) { // crossover
    243             var parent0 = (ISymbolicExpressionTree)GlobalTraceMap[tree][0];
    244             var nodes = tree.IterateNodesBreadth() as List<ISymbolicExpressionTreeNode>;
    245             var index = ((IntValue)GlobalFragmentMap[tree]).Value;
    246             var fragment = nodes[index];
    247             if (fragment == null) throw new ArgumentException("Fragment not found");
    248             parents.Add(parent0);
    249             fragments.Add(fragment);
    250           } else { // crossover followed by mutation
    251             // maybe mutation fragments should be also taken into account?
    252             var parent0 = (ISymbolicExpressionTree)GlobalTraceMap[tree][0];
    253             if (!GlobalFragmentMap.ContainsKey(parent0)) throw new ArgumentException("Fragment not found");
    254             var nodes = parent0.IterateNodesBreadth() as List<ISymbolicExpressionTreeNode>;
    255             var index = ((IntValue)GlobalFragmentMap[parent0]).Value;
    256             var fragment = nodes[index];
    257             fragments.Add(fragment);
    258             if (!GlobalTraceMap.ContainsKey(parent0)) throw new ArgumentException("Parent information not found");
    259             parents.Add(parent0);
     244        // for this kind of tracking/analysis, we need at least 2 successive generations of crossover
     245        if (Generations.Value > 1) {
     246          #region Fragment Statistics
     247          InitializeRows();
     248          // create a dictionary for fast lookup of parents (to see which children from the previous generation become parents, and count their fragments)
     249          var parentsLookup = new Dictionary<ISymbolicExpressionTree, bool>();
     250          foreach (var parent in GlobalTraceMap.Values.SelectMany(x => x.Cast<ISymbolicExpressionTree>())) {
     251            if (!parentsLookup.ContainsKey(parent)) {
     252              parentsLookup.Add(parent, true);
     253            }
    260254          }
    261         }
    262         //var zeros = new List<int>(Enumerable.Repeat<int>(0, 201));
    263         //var lengths = (from t in fragments
    264         //               let len = t.GetLength()
    265         //               orderby len
    266         //               group len by len into g
    267         //               select new Tuple<int,int>(g.First(), g.Count()));
    268         //foreach (var len in lengths)
    269         //  zeros[len.Item1] = len.Item2;
    270         FragmentLengths.Rows["Parent lengths distribution"].Values.Replace(parents.Select(x => (double)x.Length));
    271         FragmentLengths.Rows["Child lengths distribution"].Values.Replace(trees.Select(x => (double)x.Length));
    272         FragmentLengths.Rows["Fragment lengths distribution"].Values.Replace(fragments.Select(x => (double)x.GetLength()));
    273 
    274         // write values to file
    275         double a1 = fragments.Average(x => x.GetLength());
    276         double a2 = trees.Average(x => x.Length);
    277         double a3 = parents.Average(x => x.Length);
    278         double s1 = CalculateSimilarity(fragments, (int)SymbolicExpressionTreeMatching.SimilarityLevel.Exact);
    279 
    280 
    281         FragmentStatistics.Rows["Average fragment length"].Values.Add(a1);
    282         FragmentStatistics.Rows["Average child length"].Values.Add(a2);
    283         FragmentStatistics.Rows["Average parent length"].Values.Add(a3);
    284         FragmentStatistics.Rows["Similarity (exact)"].Values.Add(s1);
    285 
    286         #endregion
     255          // the same, for fast lookup of clones (might not be needed after all)
     256          var clonesLookup = new Dictionary<ISymbolicExpressionTree, bool>();
     257          foreach (var original in GlobalCloneMap.Values.Cast<ISymbolicExpressionTree>()) {
     258            if (!clonesLookup.ContainsKey(original)) {
     259              clonesLookup.Add(original, true);
     260            }
     261          }
     262          var goodFragments = new List<ISymbolicExpressionTreeNode>();
     263          var goodParents = new List<ISymbolicExpressionTree>();
     264          var goodChildren = new List<ISymbolicExpressionTree>();
     265          // take all individuals that have received a fragment in the previous generation
     266          foreach (var m in SecondaryFragmentMap) {
     267            var individual = m.Key as ISymbolicExpressionTree;
     268            // check if the individual became a parent in the current generation,
     269            // by checking if it appears among the parents from the current generation trace map
     270            if (parentsLookup.ContainsKey(individual)) {
     271              var fragmentItem = m.Value as SymbolicExpressionTreeNodeItem;
     272              goodFragments.Add(fragmentItem.Content);
     273              goodParents.AddRange(SecondaryTraceMap[individual].Cast<ISymbolicExpressionTree>());
     274              goodChildren.Add(individual);
     275            }
     276          }
     277          var allFragments = SecondaryFragmentMap.Values.Select(x => ((SymbolicExpressionTreeNodeItem)x).Content as ISymbolicExpressionTreeNode).ToList();
     278          var allParents = SecondaryTraceMap.Values.SelectMany(x => x.Cast<ISymbolicExpressionTree>()).ToList();
     279          var allChildren = SecondaryFragmentMap.Keys.Select(x => x as ISymbolicExpressionTree).ToList();
     280
     281          FragmentStatistics.Rows["Fragment lengths (good)"].Values.Add(goodFragments.Average(x => x.GetLength()));
     282          FragmentStatistics.Rows["Fragment lengths (all)"].Values.Add(allFragments.Average(x => x.GetLength()));
     283          FragmentStatistics.Rows["Parent lengths (good)"].Values.Add(goodParents.Average(x => x.Length));
     284          FragmentStatistics.Rows["Parent lengths (all)"].Values.Add(allParents.Average(x => x.Length));
     285          FragmentStatistics.Rows["Child lengths (good)"].Values.Add(goodChildren.Average(x => x.Length));
     286          FragmentStatistics.Rows["Child lengths (all)"].Values.Add(allChildren.Average(x => x.Length));
     287          //FragmentStatistics.Rows["Exact similarity (good fragments)"].Values.Add(CalculateSimilarity(goodFragments, (int)SymbolicExpressionTreeMatching.SimilarityLevel.Exact));
     288          //FragmentStatistics.Rows["Exact similarity (all fragments)"].Values.Add(CalculateSimilarity(allFragments, (int)SymbolicExpressionTreeMatching.SimilarityLevel.Exact));
     289
     290          //WriteFragmentFrequencies(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + "\\FragmentFrequencies.dat");
     291          #endregion
     292        }
     293        // save the current generation so it can be compared to the following one, next time the analyzer is applied
     294        SecondaryTraceMap.Clear();
     295        foreach (var m in GlobalTraceMap)
     296          SecondaryTraceMap.Add(m.Key, m.Value);
     297        SecondaryCloneMap.Clear();
     298        foreach (var m in GlobalCloneMap)
     299          SecondaryCloneMap.Add(m.Key, m.Value);
     300        SecondaryFragmentMap.Clear();
     301        foreach (var m in GlobalFragmentMap)
     302          SecondaryFragmentMap.Add(m.Key, m.Value);
    287303
    288304        // clear the global maps to save memory
     
    296312    }
    297313
     314    private void InitializeRows() {
     315      if (!FragmentStatistics.Rows.ContainsKey("Parent lengths (good)")) {
     316        FragmentStatistics.Rows.Add(new DataRow("Parent lengths (good)") {
     317          VisualProperties = { StartIndexZero = true }
     318        });
     319      }
     320      if (!FragmentStatistics.Rows.ContainsKey("Parent lengths (all)")) {
     321        FragmentStatistics.Rows.Add(new DataRow("Parent lengths (all)") {
     322          VisualProperties = { StartIndexZero = true }
     323        });
     324      }
     325      if (!FragmentStatistics.Rows.ContainsKey("Child lengths (good)")) {
     326        FragmentStatistics.Rows.Add(new DataRow("Child lengths (good)") {
     327          VisualProperties = { StartIndexZero = true }
     328        });
     329      }
     330      if (!FragmentStatistics.Rows.ContainsKey("Child lengths (all)")) {
     331        FragmentStatistics.Rows.Add(new DataRow("Child lengths (all)") {
     332          VisualProperties = { StartIndexZero = true }
     333        });
     334      }
     335      if (!FragmentStatistics.Rows.ContainsKey("Fragment lengths (good)")) {
     336        FragmentStatistics.Rows.Add(new DataRow("Fragment lengths (good)") {
     337          VisualProperties = { StartIndexZero = true }
     338        });
     339      }
     340      if (!FragmentStatistics.Rows.ContainsKey("Fragment lengths (all)")) {
     341        FragmentStatistics.Rows.Add(new DataRow("Fragment lengths (all)") {
     342          VisualProperties = { StartIndexZero = true }
     343        });
     344      }
     345      // exact similarity
     346      if (!FragmentStatistics.Rows.ContainsKey("Exact similarity (good fragments)")) {
     347        FragmentStatistics.Rows.Add(new DataRow("Exact similarity (good fragments)") {
     348          VisualProperties = { StartIndexZero = true }
     349        });
     350      }
     351      if (!FragmentStatistics.Rows.ContainsKey("Exact similarity (all fragments)")) {
     352        FragmentStatistics.Rows.Add(new DataRow("Exact similarity (all fragments)") {
     353          VisualProperties = { StartIndexZero = true }
     354        });
     355      }
     356    }
     357
     358    private void WriteFragmentFrequencies(string path) {
     359      using (var file = new System.IO.StreamWriter(path)) {
     360        foreach (var f in FragmentFrequencies) {
     361          file.WriteLine(((SymbolicExpressionTreeNodeItem)f[0]).Content.GetLength() + " " + ((IntValue)f[1]).Value);
     362        }
     363      }
     364    }
     365
    298366    #region Similarity computations
    299     #region Obsolete code
    300     private void CalculateDiversityIndicators(IEnumerable<ISymbolicExpressionTreeNode> fragments, out double a, out double b, out double c) {
    301       //var frags = fragments.Where(x => x.GetLength() > 1).ToList();
    302       var frags = fragments.ToList();
    303       var sieve = new bool[frags.Count];
    304       int max = 0;
    305       for (int i = 0; i != frags.Count - 1; ++i) {
    306         if (sieve[i]) continue;
    307         int count = 0;
    308         for (int j = i + 1; j != frags.Count; ++j) {
    309           if (sieve[j]) continue;
    310           if (frags[i].IsSimilarTo(frags[j], (int)SymbolicExpressionTreeMatching.SimilarityLevel.Exact)) {
    311             ++count;
    312             sieve[i] = true;
    313             sieve[j] = true;
    314           }
    315         }
    316         if (max < count) max = count;
    317       }
    318       a = (double)sieve.Count(x => x) / sieve.Length;
    319       sieve = new bool[frags.Count];
    320       max = 0;
    321       for (int i = 0; i != frags.Count - 1; ++i) {
    322         if (sieve[i]) continue;
    323         int count = 0;
    324         for (int j = i + 1; j != frags.Count; ++j) {
    325           if (sieve[j]) continue;
    326           if (frags[i].IsSimilarTo(frags[j], (int)SymbolicExpressionTreeMatching.SimilarityLevel.High)) {
    327             ++count;
    328             sieve[i] = true;
    329             sieve[j] = true;
    330           }
    331         }
    332         if (max < count) max = count;
    333       }
    334       b = (double)sieve.Count(x => x) / sieve.Length;
    335       sieve = new bool[frags.Count];
    336       max = 0;
    337       for (int i = 0; i != frags.Count - 1; ++i) {
    338         if (sieve[i]) continue;
    339         int count = 0;
    340         for (int j = i + 1; j != frags.Count; ++j) {
    341           if (sieve[j]) continue;
    342           if (frags[i].IsSimilarTo(frags[j], (int)SymbolicExpressionTreeMatching.SimilarityLevel.Relaxed)) {
    343             ++count;
    344             sieve[i] = true;
    345             sieve[j] = true;
    346           }
    347         }
    348         if (max < count) max = count;
    349       }
    350       c = (double)sieve.Count(x => x) / max;
    351     }
    352     #endregion
    353 
    354367    /// <summary>
    355368    /// Provide a measure of how similar the fragments that get passed by crossover from one generation to the next are.
     
    358371    /// <param name="mode">The similarity mode (0 - exact, 1 - high, 2 - relaxed)</param>
    359372    /// <returns>The average number of similar fragments</returns>
    360     private double CalculateSimilarity(List<ISymbolicExpressionTreeNode> fragments, int mode) {
     373    private static double CalculateSimilarity(IList<ISymbolicExpressionTreeNode> fragments, int mode) {
    361374      var visited = new bool[fragments.Count];
    362375      int groups = 0;
Note: See TracChangeset for help on using the changeset viewer.