Пример #1
0
 public void SetCentroidsAsMeansHighDimensionality()
 {
     foreach (Cluster Clust in clusters)
     {
         Clust.SetCentroidAsMean(true);
     }
 }
Пример #2
0
 public void SetCentroidsAsMeans()
 {
     foreach (Cluster Clust in clusters)
     {
         Clust.SetCentroidAsMean();
     }
 }
Пример #3
0
        public override void IterateOnce()
        {
            double AlphaI = 0;
            double AlphaJ = 0;
            double Beta   = 0;
            double Gamma  = 0;
            int    Winner;

            if (!stopped)
            {
                if (clusters.Count > 1)
                {
                    DenseMatrix InterimMatrix = new DenseMatrix(currentDistanceMatrix.RowCount);
                    currentDistanceMatrix.CopyTo(InterimMatrix);
                    Cluster[] InterimClusters = new Cluster[clusters.Count];
                    Parallel.For(0, clusters.Count, i => {
                        InterimClusters[i] = (Cluster)clusters[i].Clone();
                    });
                    List <Cluster> InterimClusterList = InterimClusters.ToList <Cluster>();

                    Tuple <int, int, double> CurrentMinimumDistance = new Tuple <int, int, double>(0, 0, 0);
                    Parallel.ForEach <Tuple <int, int, double> >(currentDistanceMatrix.EnumerateIndexed(), CurrentTuple =>
                    {
                        if (CurrentTuple.Item3 == nextDistance)
                        {
                            CurrentMinimumDistance = CurrentTuple;
                        }
                    });
                    switch (style)
                    //this loops initialises coefficient values for the lance williams algorithm - this is within the iterate once method
                    //as some styles require iterative recalculation
                    {
                    case HACDistanceStyle.Centroid:
                        AlphaI = calculateMeanAlpha(clusters[CurrentMinimumDistance.Item1], clusters[CurrentMinimumDistance.Item2]);
                        AlphaJ = calculateMeanAlpha(clusters[CurrentMinimumDistance.Item2], clusters[CurrentMinimumDistance.Item1]);
                        Beta   = calculateCentroidBeta(clusters[CurrentMinimumDistance.Item1], clusters[CurrentMinimumDistance.Item2]);
                        Gamma  = 0;
                        break;

                    case HACDistanceStyle.CLink:
                        AlphaI = 0.5;
                        AlphaJ = 0.5;
                        Beta   = 0;
                        Gamma  = 0.5;
                        break;

                    case HACDistanceStyle.MeanDist:
                        AlphaI = calculateMeanAlpha(clusters[CurrentMinimumDistance.Item1], clusters[CurrentMinimumDistance.Item2]);
                        AlphaJ = calculateMeanAlpha(clusters[CurrentMinimumDistance.Item2], clusters[CurrentMinimumDistance.Item1]);
                        Beta   = 0;
                        Gamma  = 0;
                        break;

                    case HACDistanceStyle.SLink:
                        AlphaI = 0.5;
                        AlphaJ = 0.5;
                        Beta   = 0;
                        Gamma  = -0.5;
                        break;

                    case HACDistanceStyle.Ward:
                        //has to be implemented inside matrix update loop
                        //as requires values for cluster k
                        break;
                    }
                    //handle cluster merging in list
                    InterimClusterList[CurrentMinimumDistance.Item1].Merge(InterimClusterList[CurrentMinimumDistance.Item2]);
                    InterimClusterList.RemoveAt(CurrentMinimumDistance.Item2);
                    updateClusterIndexes(InterimClusterList);
                    //handles removal of subsumed cluster's distances from distance matrix
                    if (CurrentMinimumDistance.Item1 < CurrentMinimumDistance.Item2)
                    {
                        Winner = CurrentMinimumDistance.Item1;
                    }
                    else
                    {
                        //if the item 1 value is further down the distances matrix than the row/column to be removed
                        Winner = CurrentMinimumDistance.Item1 - 1;
                    }
                    InterimMatrix = (DenseMatrix)InterimMatrix.RemoveColumn(CurrentMinimumDistance.Item2).RemoveRow(CurrentMinimumDistance.Item2);
                    Parallel.For(0, InterimMatrix.RowCount, i =>
                    {
                        //recalculate distances from new cluster to all other clusters
                        if (style == HACDistanceStyle.Ward)
                        {
                            AlphaI = calculateWardAlpha(clusters[CurrentMinimumDistance.Item1], clusters[CurrentMinimumDistance.Item2], clusters[i]);
                            AlphaJ = calculateWardAlpha(clusters[CurrentMinimumDistance.Item2], clusters[CurrentMinimumDistance.Item1], clusters[i]);
                            Beta   = calculateWardBeta(clusters[CurrentMinimumDistance.Item1], clusters[CurrentMinimumDistance.Item2], clusters[i]);
                            Gamma  = 0;
                        }
                        double DistanceIJ             = nextDistance;
                        double DistanceIK             = currentDistanceMatrix[CurrentMinimumDistance.Item1, i];
                        double DistanceJK             = currentDistanceMatrix[CurrentMinimumDistance.Item2, i];
                        InterimMatrix[Winner, i]      = runLanceWilliamsEquation(DistanceIK, DistanceJK, DistanceIJ, AlphaI, AlphaJ, Beta, Gamma);
                        InterimMatrix[i, Winner]      = InterimMatrix[Winner, i];
                        InterimMatrix[Winner, Winner] = artificialMax;
                    });
                    lastDistance = nextDistance;
                    nextDistance = InterimMatrix.Values.Min();
                    if (!stopped)
                    {
                        currentDistanceMatrix = (DenseMatrix)InterimMatrix.Clone();
                        double XValue = InterimClusterList[Winner].XValue;

                        Tuple <string, string, double, double> ThisDendroEntry = new Tuple <string, string, double, double>(clusters[CurrentMinimumDistance.Item1].ClusterID, clusters[CurrentMinimumDistance.Item2].ClusterID, lastDistance, XValue);
                        dendrogram.Add(ThisDendroEntry);
                        clusters = InterimClusterList;

                        iterator++;
                        stopped = StoppingConditionMet();
                    }
                    else
                    {
                        Parallel.ForEach(clusters, Clust => {
                            Clust.SetCentroidAsMean();
                        });
                        stopped = true;
                    }
                }
                else
                {
                    stopped = true;
                }
            }
            else
            {
                Parallel.ForEach(clusters, Clust => {
                    Clust.SetCentroidAsMean();
                });
            }
        }