Changeset 11662 for branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/LinkageTree.cs
- Timestamp:
- 12/05/14 10:40:26 (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/LinkageTree.cs
r11656 r11662 23 23 using System.Collections.Generic; 24 24 using System.Linq; 25 using System.Text; 26 using System.Threading.Tasks; 25 using HeuristicLab.Common; 27 26 using HeuristicLab.Core; 28 using HeuristicLab.Data;29 using HeuristicLab.Parameters;30 using HeuristicLab.Random;31 using HeuristicLab.Common;32 27 33 28 namespace HeuristicLab.Algorithms.ParameterlessPopulationPyramid { … … 52 47 return list; 53 48 } 54 49 50 public static IEnumerable<T> Shuffle<T>(this IList<T> source, IRandom random) { 51 for (int i = source.Count - 1; i > 0; i--) { 52 // Swap element "i" with a random earlier element (including itself) 53 int swapIndex = random.Next(i + 1); 54 yield return source[swapIndex]; 55 source[swapIndex] = source[i]; 56 // we don't actually perform the swap, we can forget about the 57 // swapped element because we already returned it. 58 } 59 yield return source[0]; 60 } 61 55 62 } 56 63 public class LinkageTree { 57 64 58 private int[][][] occurances;59 private List<int>[] clusters;60 private List<int> cluster_ordering;61 private readonly int Length;65 private readonly int[][][] occurances; 66 private readonly List<int>[] clusters; 67 private readonly List<int> clusterOrdering; 68 private readonly int length; 62 69 63 70 public LinkageTree(int length) { 64 Length = length;65 occurances = new int[ Length][][];66 67 for (int i = 1; i < Length; i++) {71 this.length = length; 72 occurances = new int[length][][]; 73 74 for (int i = 1; i < length; i++) { 68 75 occurances[i] = new int[i][]; 69 76 for (int j = 0; j < i; j++) { … … 71 78 } 72 79 } 73 clusters = new List<int>[2 * Length - 1];80 clusters = new List<int>[2 * length - 1]; 74 81 for (int i = 0; i < clusters.Length; i++) { 75 82 clusters[i] = new List<int>(); 76 83 } 84 clusterOrdering = new List<int>(); 77 85 78 86 // first "length" clusters just contain a single gene 79 for (int i = 0; i < Length; i++) {87 for (int i = 0; i < length; i++) { 80 88 clusters[i].Add(i); 81 89 } … … 83 91 84 92 public void Add(bool[] solution) { 85 if (solution.Length != Length) throw new ArgumentException("The individual has not the correct length.");93 if (solution.Length != length) throw new ArgumentException("The individual has not the correct length."); 86 94 for (int i = 1; i < solution.Length; i++) { 87 95 for (int j = 0; j < i; j++) { … … 97 105 private static double NegativeEntropy(int[] counts, double total) { 98 106 double sum = 0; 99 double p;100 107 foreach (var value in counts) { 101 if (value != 0) {102 103 104 } 108 if (value == 0) continue; 109 var p = value / total; 110 sum += (p * Math.Log(p)); 111 105 112 } 106 113 return sum; 107 114 } 108 115 109 116 private double EntropyDistance(int i, int j) { 110 117 if (i < j) { … … 126 133 double together = NegativeEntropy(entry, total); 127 134 // If together there is 0 entropy, the distance is zero 128 double ratio = 0; 129 if (together != 0) { 130 ratio = 2 - (separate / together); 131 } 132 return ratio; 135 if (together.IsAlmost(0)) { 136 return 0.0; 137 } 138 return 2 - (separate / together); 133 139 } 134 140 135 141 public void Rebuild(IRandom rand) { 136 142 // Keep track of which clusters have not been merged 137 List<int> topLevel = new List<int>(Length); 138 for (int i = 0; i < Length; i++) { 139 topLevel.Add(i); 140 } 141 bool[] useful = new bool[clusters.Length]; 142 for (int i = 0; i < useful.Length; i++) { 143 useful[i] = true; 144 } 143 var topLevel = Enumerable.Range(0, length).ToList(); 144 bool[] useful = Enumerable.Repeat(true, clusters.Length).ToArray(); 145 145 146 146 147 // Store the distances between all clusters 147 148 double[,] distances = new double[clusters.Length, clusters.Length]; 148 for (int i = 1; i < Length; i++) {149 for (int i = 1; i < length; i++) { 149 150 for (int j = 0; j < i; j++) { 150 151 distances[i, j] = EntropyDistance(clusters[i][0], clusters[j][0]); … … 158 159 159 160 // build all clusters of size greater than 1 160 for (int index = Length; index < clusters.Length; index++) {161 for (int index = length; index < clusters.Length; index++) { 161 162 // Shuffle everything not yet in the path 162 163 topLevel.ShuffleInPlace(rand, end_of_path, topLevel.Count); … … 195 196 196 197 // Only keep a cluster if the distance between the joining clusters is > zero 197 bool keep = !distances[first, second].IsAlmost(0 d);198 bool keep = !distances[first, second].IsAlmost(0.0); 198 199 useful[first] = keep; 199 200 useful[second] = keep; … … 230 231 } 231 232 // Extract the useful clusters 232 cluster _ordering = new List<int>();233 clusterOrdering.Clear(); 233 234 // Add all useful clusters. The last one is never useful. 234 235 for (int i = 0; i < useful.Length - 1; i++) { 235 if (useful[i]) cluster _ordering.Add(i);236 if (useful[i]) clusterOrdering.Add(i); 236 237 } 237 238 // TODO Shuffle cluster ordering 238 cluster _ordering.ShuffleInPlace(rand);239 cluster _ordering.Sort((i, j) => clusters[i].Count.CompareTo(clusters[j].Count));239 clusterOrdering.ShuffleInPlace(rand); 240 clusterOrdering.Sort((i, j) => clusters[i].Count.CompareTo(clusters[j].Count)); 240 241 } 241 242
Note: See TracChangeset
for help on using the changeset viewer.