- Timestamp:
- 09/03/12 15:26:04 (12 years ago)
- 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 33 33 using HeuristicLab.Problems.DataAnalysis; 34 34 using HeuristicLab.Problems.DataAnalysis.Symbolic; 35 // type definitions for convenience 35 36 using HeuristicLab.Problems.DataAnalysis.Symbolic.Regression; 36 // type definitions for convenience37 37 using CloneMapType = HeuristicLab.Core.ItemDictionary<HeuristicLab.Core.IItem, HeuristicLab.Core.IItem>; 38 using SymbolicExpressionTreeNodeItem = HeuristicLab.EvolutionaryTracking.GenericWrapper<HeuristicLab.Encodings.SymbolicExpressionTreeEncoding. SymbolicExpressionTreeNode>;38 using SymbolicExpressionTreeNodeItem = HeuristicLab.EvolutionaryTracking.GenericWrapper<HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.ISymbolicExpressionTreeNode>; 39 39 using TraceMapType = HeuristicLab.Core.ItemDictionary<HeuristicLab.Core.IItem, HeuristicLab.Core.IItemList<HeuristicLab.Core.IItem>>; 40 40 … … 47 47 [StorableClass] 48 48 public sealed class SymbolicExpressionTreeFragmentsAnalyzer : SingleSuccessorOperator, IAnalyzer { 49 #region Parameter names 49 50 private const string UpdateIntervalParameterName = "UpdateInterval"; 50 51 private const string UpdateCounterParameterName = "UpdateCounter"; … … 62 63 private const string FragmentLengthsDistributionParametersName = "FragmentLengths"; 63 64 private const string FragmentFrequenciesParameterName = "FragmentFrequencies"; 65 private const string ParentsDiversityParameterName = "ParentsDiversity"; 66 #endregion 64 67 65 68 // impact values calculator 66 private SymbolicRegressionSolutionValuesCalculator _calculator = new SymbolicRegressionSolutionValuesCalculator();69 private readonly SymbolicRegressionSolutionValuesCalculator calculator = new SymbolicRegressionSolutionValuesCalculator(); 67 70 68 71 #region Parameter properties … … 97 100 public LookupParameter<DataTable> FragmentLengthsParameter { 98 101 get { return (LookupParameter<DataTable>)Parameters[FragmentLengthsDistributionParametersName]; } 102 } 103 public LookupParameter<DataTable> ParentsDiversityParameter { 104 get { return (LookupParameter<DataTable>)Parameters[ParentsDiversityParameterName]; } 99 105 } 100 106 // auxiliary structures for tracking fragments and individuals from the previous generation … … 165 171 get { return FragmentFrequenciesParameter.ActualValue; } 166 172 } 173 public DataTable ParentsDiversity { 174 get { return ParentsDiversityParameter.ActualValue; } 175 } 167 176 public SymbolicDataAnalysisExpressionTreeInterpreter SymbolicExpressionInterpreter { 168 177 get { return SymbolicExpressionInterpreterParameter.ActualValue; } … … 174 183 175 184 [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) { } 182 187 public override IDeepCloneable Clone(Cloner cloner) { 183 188 return new SymbolicExpressionTreeFragmentsAnalyzer(this, cloner); … … 185 190 public SymbolicExpressionTreeFragmentsAnalyzer() 186 191 : base() { 192 #region Add parameters 187 193 // analyzer update counter and update interval 188 194 Parameters.Add(new ValueParameter<IntValue>(UpdateIntervalParameterName, "The interval in which the tree length analysis should be applied.", new IntValue(1))); … … 196 202 Parameters.Add(new LookupParameter<CloneMapType>(SecondaryCloneMapParameterName, "Parameter to store the clone map from the previous generation")); 197 203 Parameters.Add(new LookupParameter<CloneMapType>(SecondaryFragmentMapParameterName, "Parameter to store the fragment map from the previous generation")); 198 // other params204 // fragment statistics parameters 199 205 Parameters.Add(new ValueLookupParameter<ResultCollection>(ResultsParameterName, "The results collection where the analysis values should be stored.")); 200 206 Parameters.Add(new LookupParameter<IntValue>(GenerationsParameterName, "The number of generations so far.")); … … 202 208 Parameters.Add(new LookupParameter<DataTable>(FragmentLengthsDistributionParametersName, "The data table to store the distribution of fragment lengths.")); 203 209 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.")); 204 211 // impact calculation 205 212 Parameters.Add(new LookupParameter<SymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicExpressionInterpreterParameterName, "Interpreter for symbolic expression trees")); 206 213 Parameters.Add(new LookupParameter<RegressionProblemData>(SymbolicRegressionProblemDataParameterName, "The symbolic data analysis problem.")); 214 #endregion 215 207 216 UpdateCounterParameter.Hidden = true; 208 217 UpdateIntervalParameter.Hidden = true; 209 210 //_calculator = new SymbolicRegressionSolutionValuesCalculator();211 218 } 212 219 #region After deserialization code … … 230 237 Parameters.Add(new LookupParameter<ItemList<ItemList<IItem>>>(FragmentFrequenciesParameterName, "A data structure for fragment frequencies")); 231 238 } 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 } 232 242 } 233 243 #endregion … … 244 254 #endregion 245 255 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 * */ 246 296 public override IOperation Apply() { 247 if (Generations.Value == 0) return base.Apply();248 297 UpdateCounter.Value++; 249 298 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); 255 318 } 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) 364 321 if (this.Successor == null || !(this.Successor is SymbolicExpressionTreeGenealogyAnalyzer)) { 322 // clear the global maps to save memory 365 323 GlobalCloneMap.Clear(); 366 324 GlobalTraceMap.Clear(); 367 325 GlobalFragmentMap.Clear(); 368 326 } 369 }370 327 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 371 364 } 372 365 … … 435 428 if (!FragmentFrequencies.Rows.ContainsKey("Frequency of high impact fragments")) { 436 429 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") { 437 435 VisualProperties = { StartIndexZero = true } 438 436 }); … … 473 471 } 474 472 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 475 551 private static int VisitationLength(ISymbolicExpressionTree tree) { 476 552 return VisitationLength(tree.Root); … … 478 554 479 555 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()); 484 557 } 485 558 … … 491 564 /// <param name="mode">The similarity mode (0 - exact, 1 - high, 2 - relaxed)</param> 492 565 /// <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) { 494 567 var visited = new bool[fragments.Count]; 495 568 int groups = 0; … … 498 571 for (int j = i + 1; j != fragments.Count; ++j) { 499 572 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; 501 575 } 502 576 ++groups; -
branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.EvolutionaryTracking/3.4/Analyzers/SymbolicExpressionTreeGenealogyAnalyzer.cs
r8249 r8557 20 20 #endregion 21 21 22 using System;23 using System.Drawing;24 22 using System.Globalization; 25 23 using System.Linq; 26 using System.Text;27 24 using System.Threading; 28 25 using HeuristicLab.Common; … … 44 41 /// An operator that tracks the genealogy of every individual 45 42 /// </summary> 46 [Item("SymbolicExpressionTreeGenealogyAnalyzer", "An operator that tracks t ree lengths of Symbolic Expression Trees")]43 [Item("SymbolicExpressionTreeGenealogyAnalyzer", "An operator that tracks the genealogy of tree individuals")] 47 44 [StorableClass] 48 45 public sealed class SymbolicExpressionTreeGenealogyAnalyzer : SingleSuccessorOperator, IAnalyzer { 46 #region Parameter names 49 47 private const string UpdateIntervalParameterName = "UpdateInterval"; 50 48 private const string UpdateCounterParameterName = "UpdateCounter"; … … 63 61 private const string SymbolicRegressionProblemDataParameterName = "ProblemData"; 64 62 private const string SymbolicDataAnalysisProblemEvaluatorParameterName = "Evaluator"; 63 #endregion 65 64 66 65 #region Parameter properties … … 159 158 160 159 [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) { } 167 162 public override IDeepCloneable Clone(Cloner cloner) { 168 163 return new SymbolicExpressionTreeGenealogyAnalyzer(this, cloner); … … 218 213 UpdateCounter.Value = 0; // reset counter 219 214 220 var gScope = ExecutionContext.Scope;221 while (gScope.Parent != null) gScope = gScope.Parent;222 215 SymbolicExpressionTreeGenealogyGraph graph; 223 216 if (!Results.ContainsKey(PopulationGraphResultParameterName)) { … … 227 220 graph = (SymbolicExpressionTreeGenealogyGraph)(Results[PopulationGraphResultParameterName].Value); 228 221 } 229 // get tree quality values (Key => Individual, Value => Quality) 222 223 var gScope = ExecutionContext.Scope; 224 while (gScope.Parent != null) gScope = gScope.Parent; 230 225 var scopes = (from s in gScope.SubScopes 231 226 let individual = s.Variables.First().Value … … 240 235 var indiv = scopes[i].Tree; 241 236 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); 253 245 if (generation == 0) continue; 254 246 if (!GlobalTraceMap.ContainsKey(indiv)) continue; … … 256 248 var parents = GlobalTraceMap[indiv].Cast<ISymbolicExpressionTree>(); 257 249 foreach (var parent in parents) { 258 object data = ((GenericWrapper<SymbolicExpressionTreeNode>)GlobalFragmentMap[indiv]).Content; 250 var fragmentFromParent = ((GenericWrapper<ISymbolicExpressionTreeNode>)GlobalFragmentMap[indiv]).Content; 251 SymbolicExpressionGenealogyGraphNode parentGraphNode; 259 252 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); 268 265 } 266 } else { // individual is an elite 267 parentGraphNode = graph.GetGraphNodes(parent).Last(); 269 268 } 270 graph.AddArc(parent , indiv, null, data);269 graph.AddArc(parentGraphNode, childGraphNode, null, fragmentFromParent); 271 270 } 272 271 } 273 272 // 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) 275 276 if (this.Successor == null || !(this.Successor is SymbolicExpressionTreeFragmentsAnalyzer)) { 276 277 GlobalTraceMap.Clear(); … … 278 279 GlobalFragmentMap.Clear(); 279 280 } 280 }281 281 return base.Apply(); 282 282 } … … 296 296 return quality; 297 297 } 298 299 #region Export to dot file300 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 #endregion333 298 } 334 299 } -
branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.EvolutionaryTracking/3.4/HeuristicLab.EvolutionaryTracking-3.4.csproj
r8213 r8557 89 89 <Compile Include="Analyzers\SymbolicExpressionTreeFragmentsAnalyzer.cs" /> 90 90 <Compile Include="Analyzers\SymbolicExpressionTreeGenealogyAnalyzer.cs" /> 91 <Compile Include="Analyzers\SymbolicExpressionTreeLineagesAnalyzer.cs" /> 91 92 <Compile Include="Analyzers\SymbolicExpressionTreeRelativeLengthAnalyzer.cs" /> 92 93 <Compile Include="GenealogyGraph.cs" /> 94 <Compile Include="GenealogyGraphArc.cs" /> 95 <Compile Include="GenealogyGraphNode.cs" /> 93 96 <Compile Include="Interfaces\IGenealogyGraph.cs" /> 97 <Compile Include="Interfaces\IGenealogyGraphNode.cs" /> 98 <Compile Include="Interfaces\ISymbolicExpressionTreeGenealogyGraph.cs" /> 94 99 <Compile Include="Plugin.cs" /> 95 100 <Compile Include="Properties\AssemblyInfo.cs" /> -
branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.EvolutionaryTracking/3.4/Plugin.cs
r8213 r8557 30 30 [PluginDependency("HeuristicLab.Common.Resources", "3.3")] 31 31 [PluginDependency("HeuristicLab.Core", "3.3")] 32 [PluginDependency("HeuristicLab.Data", "3.3")]33 32 [PluginDependency("HeuristicLab.Encodings.SymbolicExpressionTreeEncoding", "3.4")] 34 33 [PluginDependency("HeuristicLab.Operators", "3.3")]
Note: See TracChangeset
for help on using the changeset viewer.