Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
12/05/14 10:40:26 (10 years ago)
Author:
mkommend
Message:

#2282: Refactored LinkageTree and adapted unit tests.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/LinkageTree.cs

    r11656 r11662  
    2323using System.Collections.Generic;
    2424using System.Linq;
    25 using System.Text;
    26 using System.Threading.Tasks;
     25using HeuristicLab.Common;
    2726using HeuristicLab.Core;
    28 using HeuristicLab.Data;
    29 using HeuristicLab.Parameters;
    30 using HeuristicLab.Random;
    31 using HeuristicLab.Common;
    3227
    3328namespace HeuristicLab.Algorithms.ParameterlessPopulationPyramid {
     
    5247      return list;
    5348    }
    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
    5562  }
    5663  public class LinkageTree {
    5764
    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;
    6269
    6370    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++) {
    6875        occurances[i] = new int[i][];
    6976        for (int j = 0; j < i; j++) {
     
    7178        }
    7279      }
    73       clusters = new List<int>[2 * Length - 1];
     80      clusters = new List<int>[2 * length - 1];
    7481      for (int i = 0; i < clusters.Length; i++) {
    7582        clusters[i] = new List<int>();
    7683      }
     84      clusterOrdering = new List<int>();
    7785
    7886      // first "length" clusters just contain a single gene
    79       for (int i = 0; i < Length; i++) {
     87      for (int i = 0; i < length; i++) {
    8088        clusters[i].Add(i);
    8189      }
     
    8391
    8492    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.");
    8694      for (int i = 1; i < solution.Length; i++) {
    8795        for (int j = 0; j < i; j++) {
     
    97105    private static double NegativeEntropy(int[] counts, double total) {
    98106      double sum = 0;
    99       double p;
    100107      foreach (var value in counts) {
    101         if (value != 0) {
    102           p = value / total;
    103           sum += (p * Math.Log(p));
    104         }
     108        if (value == 0) continue;
     109        var p = value / total;
     110        sum += (p * Math.Log(p));
     111
    105112      }
    106113      return sum;
    107114    }
    108    
     115
    109116    private double EntropyDistance(int i, int j) {
    110117      if (i < j) {
     
    126133      double together = NegativeEntropy(entry, total);
    127134      // 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);
    133139    }
    134140
    135141    public void Rebuild(IRandom rand) {
    136142      // 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
    145146
    146147      // Store the distances between all clusters
    147148      double[,] distances = new double[clusters.Length, clusters.Length];
    148       for (int i = 1; i < Length; i++) {
     149      for (int i = 1; i < length; i++) {
    149150        for (int j = 0; j < i; j++) {
    150151          distances[i, j] = EntropyDistance(clusters[i][0], clusters[j][0]);
     
    158159
    159160      // 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++) {
    161162        // Shuffle everything not yet in the path
    162163        topLevel.ShuffleInPlace(rand, end_of_path, topLevel.Count);
     
    195196
    196197        // Only keep a cluster if the distance between the joining clusters is > zero
    197         bool keep = !distances[first, second].IsAlmost(0d);
     198        bool keep = !distances[first, second].IsAlmost(0.0);
    198199        useful[first] = keep;
    199200        useful[second] = keep;
     
    230231      }
    231232      // Extract the useful clusters
    232       cluster_ordering = new List<int>();
     233      clusterOrdering.Clear();
    233234      // Add all useful clusters. The last one is never useful.
    234235      for (int i = 0; i < useful.Length - 1; i++) {
    235         if (useful[i]) cluster_ordering.Add(i);
     236        if (useful[i]) clusterOrdering.Add(i);
    236237      }
    237238      // 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));
    240241    }
    241242
Note: See TracChangeset for help on using the changeset viewer.