/// <summary>
        /// Starts the clustering.
        /// </summary>
        /// <param name="elements"></param>
        /// <param name="fusion"></param>
        /// <param name="metric"></param>
        /// <returns></returns>
        protected internal Cluster[] Cluster(List<Element> elements, Fusion fusion, IDistanceMetric metric)
        {
            HashSet<Cluster> clusters = new HashSet<Cluster>();
            ClusterPairs pairs = new ClusterPairs();

            // 1. Initialize each element as a cluster
            foreach (Element el in elements)
            {
                Cluster cl = new Cluster(fusion);
                cl.AddElement(el);
                clusters.Add(cl);
            }

            // 2. a) Calculate the distances of all clusters to all other clusters
            foreach (Cluster cl1 in clusters)
            {
                foreach (Cluster cl2 in clusters)
                {
                    if (cl1 == cl2)
                        continue;

                    ClusterPair pair = new ClusterPair(cl1, cl2, cl1.CalculateDistance(cl2));

                    pairs.AddPair(pair);
                }
            }

            // 2. b) Initialize the pair with the lowest distance to each other.
            ClusterPair lowestDistancePair = pairs.LowestDistancePair;

            // 3. Merge clusters to new clusters and recalculate distances in a loop until there are only countCluster clusters
            while (!isFinished(clusters, lowestDistancePair))
            {
                // a) Merge: Create a new cluster and add the elements of the two old clusters
                lowestDistancePair = pairs.LowestDistancePair;

                Cluster newCluster = new Cluster(fusion);
                newCluster.AddElements(lowestDistancePair.Cluster1.GetElements());
                newCluster.AddElements(lowestDistancePair.Cluster2.GetElements());

                // b)Remove the two old clusters from clusters
                clusters.Remove(lowestDistancePair.Cluster1);
                clusters.Remove(lowestDistancePair.Cluster2);

                // c) Remove the two old clusters from pairs
                pairs.RemovePairsByOldClusters(lowestDistancePair.Cluster1, lowestDistancePair.Cluster2);

                // d) Calculate the distance of the new cluster to all other clusters and save each as pair
                foreach (Cluster cluster in clusters)
                {
                    ClusterPair pair = new ClusterPair(cluster, newCluster, cluster.CalculateDistance(newCluster));
                    pairs.AddPair(pair);
                }

                // e) Add the new cluster to clusters
                clusters.Add(newCluster);
            }

            return clusters.ToArray<Cluster>();
        }
        internal void RemovePairsByOldClusters(Cluster cluster1, Cluster cluster2)
        {
            List<ClusterPair> toRemove = new List<ClusterPair>();

            foreach(ClusterPair pair in pairs)
            {
                if (pair.HasCluster(cluster1) || pair.HasCluster(cluster2))
                {
                    toRemove.Add(pair);
                }
            }

            foreach (ClusterPair pair in toRemove)
            {
                pairs.Remove(pair);
            }
        }
 internal bool HasCluster(Cluster cluster)
 {
     return cluster1 == cluster || cluster2 == cluster;
 }
Exemple #4
0
 internal float CalculateDistance(Cluster otherCluster)
 {
     return fusion.CalculateDistance(this, otherCluster);
 }
 public ClusterPair(Cluster cluster1, Cluster cluster2, float distance)
 {
     this.cluster1 = cluster1;
     this.cluster2 = cluster2;
     this.distance = distance;
 }