示例#1
0
        // Find the minimum eigenvalue of second derivative matrix -- called from shouldSplit
        public void getEigenvaluefromMatrix(double[,] SecondDerivMatrix)
        {
            Eigenvector = new double[Program.ParameterVectorDimension];
            if (!Program.CalculateEigenvaluesfromMatrix)
            {   // Re-use Earlier Calculation of results for all clusters
            }

            //  Calculate Eigenvalues from Matrix
            if (Program.ParameterVectorDimension != 2)
            {
                Exception e = DAVectorUtility.SALSAError(" Illegal Vector Dimension " + Program.ParameterVectorDimension.ToString());
                throw(e);
            }

            //  Case of Two Dimensions
            EigenStatus = 1;
            double tmp = SecondDerivMatrix[0, 0] - SecondDerivMatrix[1, 1];

            tmp            = tmp * tmp + 4.0 * SecondDerivMatrix[0, 1] * SecondDerivMatrix[0, 1];
            Eigenvalue     = 0.5 * (SecondDerivMatrix[0, 0] + SecondDerivMatrix[1, 1] - Math.Sqrt(tmp));
            Eigenvector[0] = -SecondDerivMatrix[0, 1];
            Eigenvector[1] = SecondDerivMatrix[1, 1] - Eigenvalue;

            // Normalize
            tmp = 0.0;
            for (int VectorIndex = 0; VectorIndex < Program.ParameterVectorDimension; VectorIndex++)
            {
                tmp += Eigenvector[VectorIndex] * Eigenvector[VectorIndex];
            }
            tmp = 1.0 / Math.Sqrt(tmp);
            for (int VectorIndex = 0; VectorIndex < Program.ParameterVectorDimension; VectorIndex++)
            {
                Eigenvector[VectorIndex] *= tmp;
            }
        }   // End getEigenvalue(double[,] SecondDerivMatrix)
示例#2
0
        }   // End getEigenvalue(double[,] SecondDerivMatrix)

        public void SetAllEigenvaluesIteratively(ClusteringSolution Solution)
        {
            if (Solution.DistributedExecutionMode)
            {
                Exception e = DAVectorUtility.SALSAError(" Illegal Eigenvalue and Parallelization Combination ");
                throw (e);
            }
            if (Program.SigmaMethod > 0)
            {
                Exception e = DAVectorUtility.SALSAError(" Illegal Eigenvalue and Sigma Method Combination " + Program.SigmaMethod.ToString());
                throw (e);
            }
            this.CurrentSolution        = Solution;
            this.CenterEigenvector      = this.CurrentSolution.Eigenvector_k_i;
            this.CenterEigenvalue       = this.CurrentSolution.Eigenvalue_k;
            this.InitVector             = new double[Program.ParameterVectorDimension];
            this.FirstTerm              = new double[this.CurrentSolution.Ncent_Global];
            this.CenterEigenstatus      = new int[this.CurrentSolution.Ncent_Global];
            this.CenterEigenconvergence = new int[this.CurrentSolution.Ncent_Global];

            Random random   = new Random();
            double InitNorm = 0.0;

            for (int VectorIndex = 0; VectorIndex < Program.ParameterVectorDimension; VectorIndex++)
            {
                InitVector[VectorIndex] = -0.5 + random.NextDouble();
                InitNorm += InitVector[VectorIndex] * InitVector[VectorIndex];
            }
            InitNorm = 1.0 / Math.Sqrt(InitNorm);
            for (int VectorIndex = 0; VectorIndex < Program.ParameterVectorDimension; VectorIndex++)
            {
                InitVector[VectorIndex] *= InitNorm;
            }

            //  Initialization Loop over Clusters
            int somethingtodo = 0;

            for (int ClusterIndex = 0; ClusterIndex < this.CurrentSolution.Ncent_Global; ClusterIndex++)
            {
                this.CenterEigenconvergence[ClusterIndex] = 0;
                this.CenterEigenstatus[ClusterIndex]      = 0;
                this.FirstTerm[ClusterIndex] = 0;
                if (this.CurrentSolution.Splittable_k_[ClusterIndex] != 1)
                {
                    continue;
                }
                ++somethingtodo;
                for (int VectorIndex = 0; VectorIndex < Program.ParameterVectorDimension; VectorIndex++)
                {
                    this.CenterEigenvector[ClusterIndex][VectorIndex] = InitVector[VectorIndex];
                }
            }   // End Loop over Clusters
            if (somethingtodo == 0)
            {
                return;
            }

            GlobalReductions.FindVectorDoubleSum FindClusterFirstTerm     = new GlobalReductions.FindVectorDoubleSum(DAVectorUtility.ThreadCount, this.CurrentSolution.Ncent_Global);
            GlobalReductions.FindDoubleSum       FindNumberScalarProducts = new GlobalReductions.FindDoubleSum(DAVectorUtility.ThreadCount);

            for (int NumPowerIterations = 0; NumPowerIterations < Program.PowerIterationLimit; NumPowerIterations++)
            {
                somethingtodo = 0;
                for (int ClusterIndex = 0; ClusterIndex < this.CurrentSolution.Ncent_Global; ClusterIndex++)
                {
                    if (this.CurrentSolution.LocalStatus[ClusterIndex] != 1)
                    {
                        continue;
                    }
                    if (this.CurrentSolution.Splittable_k_[ClusterIndex] != 1)
                    {
                        continue;
                    }
                    if (this.CenterEigenconvergence[ClusterIndex] == 0)
                    {
                        ++somethingtodo;
                    }
                }
                if (somethingtodo == 0)
                {
                    break;
                }

                GlobalReductions.FindVectorDoubleSum3 FindNewPowerVectors = new GlobalReductions.FindVectorDoubleSum3(DAVectorUtility.ThreadCount,
                                                                                                                      Program.ParameterVectorDimension, this.CurrentSolution.Ncent_Global);

                Parallel.For(0, Program.ParallelOptions.MaxDegreeOfParallelism, Program.ParallelOptions, (ThreadNo) =>
                {
                    FindNewPowerVectors.startthread(ThreadNo);
                    double[] PartVector = new double[Program.ParameterVectorDimension];

                    int indexlen   = DAVectorUtility.PointsperThread[ThreadNo];
                    int beginpoint = DAVectorUtility.StartPointperThread[ThreadNo] - DAVectorUtility.PointStart_Process;
                    for (int alpha = beginpoint; alpha < indexlen + beginpoint; alpha++)
                    {
                        int IndirectSize = this.CurrentSolution.NumClusters_alpha_[alpha];

                        for (int IndirectClusterIndex = 0; IndirectClusterIndex < IndirectSize; IndirectClusterIndex++)
                        {   // Loop over Clusters for this point
                            int RealClusterIndex   = -1;
                            int RemoteIndex        = -1;
                            int ActiveClusterIndex = -1;
                            VectorAnnealIterate.ClusterPointersforaPoint(alpha, IndirectClusterIndex, ref RealClusterIndex, ref ActiveClusterIndex, ref RemoteIndex);
                            if (this.CurrentSolution.Splittable_k_[RealClusterIndex] != 1)
                            {
                                continue;
                            }

                            double Mvalue = this.CurrentSolution.M_alpha_kpointer_[alpha][IndirectClusterIndex];
                            if (NumPowerIterations == 0)
                            {
                                FindClusterFirstTerm.addapoint(ThreadNo, Mvalue, RealClusterIndex);
                            }
                            double multiplier = 0.0;
                            for (int VectorIndex = 0; VectorIndex < Program.ParameterVectorDimension; VectorIndex++)
                            {
                                PartVector[VectorIndex] = this.CurrentSolution.Y_k_i_[RealClusterIndex][VectorIndex] - Program.PointPosition[alpha][VectorIndex];
                                multiplier += PartVector[VectorIndex] * CenterEigenvector[RealClusterIndex][VectorIndex];
                            }
                            FindNumberScalarProducts.addapoint(ThreadNo, 1.0);

                            double wgt = Mvalue * multiplier;
                            for (int VectorIndex = 0; VectorIndex < Program.ParameterVectorDimension; VectorIndex++)
                            {
                                PartVector[VectorIndex] *= wgt;
                            }
                            FindNewPowerVectors.addapoint(ThreadNo, PartVector, RealClusterIndex);
                        }
                    } // End Loop over points
                });   // End loop initialing Point dependent quantities

                FindNewPowerVectors.sumoverthreadsandmpi();
                for (int ClusterIndex = 0; ClusterIndex < this.CurrentSolution.Ncent_Global; ClusterIndex++)
                {
                    if (this.CurrentSolution.LocalStatus[ClusterIndex] != 1)
                    {
                        continue;
                    }
                    if ((this.CurrentSolution.Splittable_k_[ClusterIndex] != 1) || (this.CenterEigenconvergence[ClusterIndex] != 0))
                    {
                        continue;
                    }
                    double[] sums = new double[3];  // Old.New Old.Old New.New
                    for (int loop = 0; loop < 3; loop++)
                    {
                        sums[loop] = 0.0;
                    }
                    for (int VectorIndex = 0; VectorIndex < Program.ParameterVectorDimension; VectorIndex++)
                    {
                        int    TotalIndex = VectorIndex + ClusterIndex * Program.ParameterVectorDimension;
                        double newvalue   = FindNewPowerVectors.TotalVectorSum[TotalIndex];
                        double oldvalue   = CenterEigenvector[ClusterIndex][VectorIndex];
                        sums[0] += oldvalue * newvalue;
                        sums[1] += oldvalue * oldvalue;
                        sums[2] += newvalue * newvalue;
                        CenterEigenvector[ClusterIndex][VectorIndex] = newvalue;
                    }

                    //  Decide if finished and set eigenvalue
                    double CandidateEigenvalue = sums[0] / sums[1];
                    bool   LegalEigenvalue     = (CandidateEigenvalue > 0.0);
                    DAVectorUtility.SynchronizeMPIvariable(ref LegalEigenvalue);

                    //	Check if converged
                    //	Do this in one process ONLY
                    if ((NumPowerIterations > 5) && LegalEigenvalue)
                    { // Arbitrary choice for Number of Power Iterations Cut
                        int EigenvalueDone = 0;
                        if (DAVectorUtility.MPI_Rank == 0)
                        { // Decisions can only be made in one process
                            if (Math.Abs(CandidateEigenvalue - this.CenterEigenvalue[ClusterIndex]) > CandidateEigenvalue * Program.eigenvaluechange)
                            {
                                ++EigenvalueDone;
                            }
                            double delta = sums[2] - 2.0 * sums[0] * CandidateEigenvalue + sums[1] * CandidateEigenvalue * CandidateEigenvalue;   // (Ax- Eigenvalue*Axold)**2
                            if (Math.Abs(delta) > CandidateEigenvalue * CandidateEigenvalue * Program.eigenvectorchange)
                            {
                                ++EigenvalueDone;
                            }
                        }   // End Test on Convergence
                        DAVectorUtility.SynchronizeMPIvariable(ref EigenvalueDone);

                        if (EigenvalueDone == 0)
                        {
                            this.CenterEigenconvergence[ClusterIndex] = 1 + NumPowerIterations;
                        }
                    }
                    this.CenterEigenvalue[ClusterIndex] = CandidateEigenvalue;

                    //  Normalize current Power Vector to 1
                    double wgt = 1.0 / Math.Sqrt(sums[2]);
                    for (int VectorIndex = 0; VectorIndex < Program.ParameterVectorDimension; VectorIndex++)
                    {
                        CenterEigenvector[ClusterIndex][VectorIndex] *= wgt;
                    }
                } // End Loop over Clusters
            }     //  End Loop over NumPowerIterations

            FindClusterFirstTerm.sumoverthreadsandmpi();
            FindNumberScalarProducts.sumoverthreadsandmpi();
            Program.SumEigenSPCalcs += FindNumberScalarProducts.Total;

            for (int ClusterIndex = 0; ClusterIndex < this.CurrentSolution.Ncent_Global; ClusterIndex++)
            {
                this.CenterEigenstatus[ClusterIndex] = 0;
                if (this.CurrentSolution.LocalStatus[ClusterIndex] != 1)
                {
                    continue;
                }
                if ((this.CurrentSolution.Splittable_k_[ClusterIndex] != 1) || (this.CenterEigenconvergence[ClusterIndex] <= 0))
                {
                    continue;
                }
                this.CenterEigenstatus[ClusterIndex] = 1;
                this.FirstTerm[ClusterIndex]         = FindClusterFirstTerm.TotalVectorSum[ClusterIndex];
                double tmp = this.CenterEigenvalue[ClusterIndex] / this.CurrentSolution.Temperature;
                this.CenterEigenvalue[ClusterIndex] = this.FirstTerm[ClusterIndex] - tmp;
            }
        }   // End SetEigenvaluesIteratively(ClusteringSolution Solution)
示例#3
0
        }   // End FindClusterCenters(int[] NearestCentertoPoint, double[][] LastClusterCenter)

        public static void ReadDataFromFile(string fname, int ClusterPosition, int FirstClustervalue, int StartPointPosition)
        {
            char[] _sep = new[] { ' ', ',', '\t' };

            int FirstPointPosition      = 0;
            int TotalNumberPointstoRead = 0;

            FirstPointPosition      = DAVectorUtility.PointStart_Process;
            TotalNumberPointstoRead = DAVectorUtility.PointCount_Process;
            Random RandomObject = new Random(10101010 + DAVectorUtility.MPI_Rank);

            if (ClusterPosition < 0)
            {
                DAVectorUtility.SALSAPrint(0, "Random Start 10101010 plus rank ******************* Option " + ClusterPosition.ToString());
            }
            int MinSplitSize = ClusterPosition + 1;

            if (StartPointPosition >= 0)
            {
                MinSplitSize = Math.Max(MinSplitSize, StartPointPosition + Kmeans.ParameterVectorDimension);
            }
            else
            {
                Exception e = DAVectorUtility.SALSAError("Illegal Start Position on Points file " + fname + " Rank " + DAVectorUtility.MPI_Rank.ToString()
                                                         + " POsition " + StartPointPosition.ToString() + " Number to Read " + TotalNumberPointstoRead.ToString());
                throw (e);
            }
            bool   success          = false;
            string line             = " Unset";
            int    CountLinesinFile = 0;

            try
            {
                StreamReader sr = null;
                if (!string.IsNullOrEmpty(fname))
                {
                    Stream stream = File.Open(fname, FileMode.Open, FileAccess.Read, FileShare.Read);
                    sr = new StreamReader(stream);
                }
                if (sr != null)
                {
                    while (!sr.EndOfStream)
                    {
                        line = sr.ReadLine();
                        if (!string.IsNullOrEmpty(line))
                        {
                            string[] splits = line.Trim().Split(_sep, StringSplitOptions.RemoveEmptyEntries);
                            if (splits.Length < MinSplitSize)
                            {
                                DAVectorUtility.SALSAPrint(0, "Count " + CountLinesinFile.ToString() + " Illegal data length on Point file " + splits.Length.ToString()
                                                           + " " + MinSplitSize.ToString() + " " + line);
                                continue;
                            }   // Skip header lines

                            double junk;
                            if (!Double.TryParse(splits[StartPointPosition], out junk))
                            {
                                continue;   // Skip header lines
                            }
                            if (CountLinesinFile < FirstPointPosition)
                            {
                                CountLinesinFile += 1;
                                continue;
                            }

                            int ActualPointPosition = CountLinesinFile - FirstPointPosition;
                            int label = 0;

                            Kmeans.PointPosition[ActualPointPosition][0] = double.Parse(splits[StartPointPosition]);
                            Kmeans.PointPosition[ActualPointPosition][1] = double.Parse(splits[StartPointPosition + 1]);
                            if (Kmeans.ParameterVectorDimension > 2)
                            {
                                for (int VectorIndex = 2; VectorIndex < Kmeans.ParameterVectorDimension; VectorIndex++)
                                {
                                    Kmeans.PointPosition[ActualPointPosition][VectorIndex] = double.Parse(splits[VectorIndex + StartPointPosition]);
                                }
                            }

                            if (ClusterPosition >= 0)
                            {
                                if (!Int32.TryParse(splits[ClusterPosition], out label))
                                {
                                    label = FirstClustervalue;
                                }
                                Kmeans.InitialPointAssignment[ActualPointPosition] = label - FirstClustervalue;
                            }
                            else
                            {
                                Kmeans.InitialPointAssignment[ActualPointPosition] = RandomObject.Next(Program.InitialNcent);
                                if (ClusterPosition == -2)
                                {   // Force each cluster to have one point
                                    if (CountLinesinFile < Program.InitialNcent)
                                    {
                                        Kmeans.InitialPointAssignment[ActualPointPosition] = CountLinesinFile;
                                    }
                                }
                                if (ClusterPosition == -3)
                                {
                                    int divisor = Program.NumberDataPoints / Program.InitialNcent;
                                    if (CountLinesinFile % divisor == 0)
                                    {
                                        Kmeans.InitialPointAssignment[ActualPointPosition] = CountLinesinFile / divisor;
                                    }
                                }
                                if (ClusterPosition == -4)
                                {
                                    int divisor = Program.NumberDataPoints / Program.InitialNcent;
                                    Kmeans.InitialPointAssignment[ActualPointPosition] = CountLinesinFile / divisor;
                                }
                            }
                            ++ActualPointPosition;
                            ++CountLinesinFile;
                            if (CountLinesinFile >= (FirstPointPosition + TotalNumberPointstoRead))
                            {
                                break;
                            }
                        }
                    }
                    if (CountLinesinFile != (FirstPointPosition + TotalNumberPointstoRead))
                    {
                        Exception e = DAVectorUtility.SALSAError("Illegal count on Points file " + fname + " Rank " + DAVectorUtility.MPI_Rank.ToString()
                                                                 + " Lines in File " + CountLinesinFile.ToString() + " Number to Read " + TotalNumberPointstoRead.ToString());
                        throw (e);
                    }
                    success = true;
                }
                sr.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine("Failed reading Points data " + DAVectorUtility.MPI_Rank.ToString() + " " + CountLinesinFile.ToString() + " Start "
                                  + FirstPointPosition.ToString() + " Number " + TotalNumberPointstoRead.ToString() + " " + line + e);
                throw (e);
            }
            if (!success)
            {
                Exception e = DAVectorUtility.SALSAError("DA Vector File read error " + fname);
                throw (e);
            }
        } // End ReadDataFromFile
示例#4
0
        }   // End GetClusterRadius

        // Use LastClusterCenter if Size 0
        public static void FindClusterCenters(bool begin, int[] NearestCentertoPoint, double[] Distance_NearestCentertoPoint, double[][] LastClusterCenter)
        {   // Calculate Cluster Parameters
            GlobalReductions.FindVectorDoubleSum3 FindCenterVectorSums = new GlobalReductions.FindVectorDoubleSum3(DAVectorUtility.ThreadCount,
                                                                                                                   Kmeans.ParameterVectorDimension, Kmeans.Ncent_Global);
            GlobalReductions.FindVectorIntSum    FindCenterSizeSums = new GlobalReductions.FindVectorIntSum(DAVectorUtility.ThreadCount, Kmeans.Ncent_Global);
            GlobalReductions.FindVectorDoubleMax FindClusterRadius  = new GlobalReductions.FindVectorDoubleMax(DAVectorUtility.ThreadCount, Kmeans.Ncent_Global);
            GlobalReductions.FindVectorDoubleSum FindClusterWidth   = new GlobalReductions.FindVectorDoubleSum(DAVectorUtility.ThreadCount, Kmeans.Ncent_Global);
            ;
            Parallel.For(0, Kmeans._parallelOptions.MaxDegreeOfParallelism, Kmeans._parallelOptions, (ThreadIndex) =>
            {
                FindCenterVectorSums.startthread(ThreadIndex);
                FindCenterSizeSums.startthread(ThreadIndex);
                int indexlen   = DAVectorUtility.PointsperThread[ThreadIndex];
                int beginpoint = DAVectorUtility.StartPointperThread[ThreadIndex] - DAVectorUtility.PointStart_Process;
                for (int alpha = beginpoint; alpha < indexlen + beginpoint; alpha++)
                {
                    int ClusterIndex = NearestCentertoPoint[alpha];
                    if ((ClusterIndex >= Kmeans.Ncent_Global) || (ClusterIndex < 0))
                    {
                        Exception e = DAVectorUtility.SALSAError("Illegal Cluster Index " + ClusterIndex.ToString() + " Number " + Kmeans.Ncent_Global.ToString()
                                                                 + " Point " + (alpha + DAVectorUtility.PointStart_Process).ToString() + " Rank " + DAVectorUtility.MPI_Rank.ToString());
                        throw (e);
                    }
                    FindCenterVectorSums.addapoint(ThreadIndex, PointPosition[alpha], ClusterIndex);
                    FindCenterSizeSums.addapoint(ThreadIndex, 1, ClusterIndex);
                    if (!begin)
                    {
                        FindClusterRadius.addapoint(ThreadIndex, Distance_NearestCentertoPoint[alpha], ClusterIndex);
                        FindClusterWidth.addapoint(ThreadIndex, Distance_NearestCentertoPoint[alpha] * Distance_NearestCentertoPoint[alpha], ClusterIndex);
                    }
                } // End loop over Points
            });   // End Sum over Threads

            FindCenterVectorSums.sumoverthreadsandmpi();
            FindCenterSizeSums.sumoverthreadsandmpi();
            if (!begin)
            {
                FindClusterRadius.sumoverthreadsandmpi();
                FindClusterWidth.sumoverthreadsandmpi();
            }
            Kmeans.AverageRadius       = 0.0;
            Kmeans.AverageWidth        = 0.0;
            Kmeans.AverageCenterChange = 0.0;

            if (Kmeans.UseParallelismoverCenters)
            {   // Centers Parallel over Threads NOT nodes
                double[] AccumulateRadius       = new double[DAVectorUtility.ThreadCount];
                double[] AccumulateWidth        = new double[DAVectorUtility.ThreadCount];
                double[] AccumulateCenterChange = new double[DAVectorUtility.ThreadCount];
                for (int ThreadIndex = 0; ThreadIndex < DAVectorUtility.ThreadCount; ThreadIndex++)
                {
                    AccumulateRadius[ThreadIndex]       = 0.0;
                    AccumulateWidth[ThreadIndex]        = 0.0;
                    AccumulateCenterChange[ThreadIndex] = 0.0;
                }

                Parallel.For(0, Kmeans._parallelOptions.MaxDegreeOfParallelism, Kmeans._parallelOptions, (ThreadIndex) =>
                {
                    int indexlen   = KmeansTriangleInequality.LocalParallel_CentersperThread[ThreadIndex];
                    int beginpoint = KmeansTriangleInequality.LocalParallel_StartCenterperThread[ThreadIndex];
                    for (int CenterIndex = beginpoint; CenterIndex < indexlen + beginpoint; CenterIndex++)
                    {
                        Kmeans.ClusterSize[CenterIndex] = FindCenterSizeSums.TotalVectorSum[CenterIndex];

                        if (Kmeans.ClusterSize[CenterIndex] > 0)
                        {
                            double divisor = 1.0 / (double)Kmeans.ClusterSize[CenterIndex];
                            for (int VectorIndex = 0; VectorIndex < Kmeans.ParameterVectorDimension; VectorIndex++)
                            {
                                int totalindex = VectorIndex + CenterIndex * Kmeans.ParameterVectorDimension;
                                Kmeans.ClusterCenter[CenterIndex][VectorIndex] = FindCenterVectorSums.TotalVectorSum[totalindex] * divisor;
                            }

                            if (!begin)
                            {
                                Kmeans.ClusterRadius[CenterIndex]    = FindClusterRadius.TotalVectorMax[CenterIndex];
                                Kmeans.ClusterWidth[CenterIndex]     = FindClusterWidth.TotalVectorSum[CenterIndex];
                                AccumulateRadius[ThreadIndex]       += Kmeans.ClusterRadius[CenterIndex];
                                AccumulateWidth[ThreadIndex]        += Kmeans.ClusterWidth[CenterIndex];
                                AccumulateCenterChange[ThreadIndex] += DAVectorParallelism.getNOTSquaredUNScaledDistancebetweenVectors(Kmeans.ClusterCenter[CenterIndex], LastClusterCenter[CenterIndex]);
                            }
                        }
                        else
                        {   // Zero Size Cluster
                            if (begin)
                            {
                                Exception e = DAVectorUtility.SALSAError("Empty Input Cluster " + CenterIndex.ToString() + " Number " + Kmeans.Ncent_Global.ToString()
                                                                         + " Rank " + DAVectorUtility.MPI_Rank.ToString());
                                throw (e);
                            }
                            for (int VectorIndex = 0; VectorIndex < Kmeans.ParameterVectorDimension; VectorIndex++)
                            {
                                Kmeans.ClusterCenter[CenterIndex][VectorIndex] = LastClusterCenter[CenterIndex][VectorIndex];
                            }
                            Kmeans.ClusterRadius[CenterIndex] = 0.0;
                            Kmeans.ClusterWidth[CenterIndex]  = 0.0;
                        }
                    }
                }); // End Sum over Threads
                if (!begin)
                {
                    for (int ThreadIndex = 0; ThreadIndex < DAVectorUtility.ThreadCount; ThreadIndex++)
                    {
                        Kmeans.AverageRadius       += AccumulateRadius[ThreadIndex];
                        Kmeans.AverageWidth        += AccumulateWidth[ThreadIndex];
                        Kmeans.AverageCenterChange += AccumulateCenterChange[ThreadIndex];
                    }
                }
            }

            else
            {   // Centers Sequential
                for (int CenterIndex = 0; CenterIndex < Kmeans.Ncent_Global; CenterIndex++)
                {
                    Kmeans.ClusterSize[CenterIndex] = FindCenterSizeSums.TotalVectorSum[CenterIndex];

                    if (Kmeans.ClusterSize[CenterIndex] > 0)
                    {
                        double divisor = 1.0 / (double)Kmeans.ClusterSize[CenterIndex];
                        for (int VectorIndex = 0; VectorIndex < Kmeans.ParameterVectorDimension; VectorIndex++)
                        {
                            int totalindex = VectorIndex + CenterIndex * Kmeans.ParameterVectorDimension;
                            Kmeans.ClusterCenter[CenterIndex][VectorIndex] = FindCenterVectorSums.TotalVectorSum[totalindex] * divisor;
                        }

                        if (!begin)
                        {
                            Kmeans.ClusterRadius[CenterIndex] = FindClusterRadius.TotalVectorMax[CenterIndex];
                            Kmeans.ClusterWidth[CenterIndex]  = FindClusterWidth.TotalVectorSum[CenterIndex];
                            Kmeans.AverageRadius       += Kmeans.ClusterRadius[CenterIndex];
                            Kmeans.AverageWidth        += Kmeans.ClusterWidth[CenterIndex];
                            Kmeans.AverageCenterChange += DAVectorParallelism.getNOTSquaredUNScaledDistancebetweenVectors(Kmeans.ClusterCenter[CenterIndex], LastClusterCenter[CenterIndex]);
                        }
                    }
                    else
                    {
                        if (begin)
                        {
                            Exception e = DAVectorUtility.SALSAError("Empty Input Cluster " + CenterIndex.ToString() + " Number " + Kmeans.Ncent_Global.ToString()
                                                                     + " Rank " + DAVectorUtility.MPI_Rank.ToString());
                            throw (e);
                        }
                        Kmeans.ClusterRadius[CenterIndex] = 0.0;
                        Kmeans.ClusterWidth[CenterIndex]  = 0.0;
                        for (int VectorIndex = 0; VectorIndex < Kmeans.ParameterVectorDimension; VectorIndex++)
                        {
                            Kmeans.ClusterCenter[CenterIndex][VectorIndex] = LastClusterCenter[CenterIndex][VectorIndex];
                        }
                    }
                }   // End Sequential Center Loop
            }

            if (begin)
            {
                return;
            }
            Kmeans.AverageCenterChange = Kmeans.AverageCenterChange / Kmeans.Ncent_Global;
            Kmeans.AverageRadius       = Kmeans.AverageRadius / Kmeans.Ncent_Global;
            Kmeans.AverageWidth        = Kmeans.AverageWidth / DAVectorUtility.PointCount_Global;
            return;
        }   // End FindClusterCenters(int[] NearestCentertoPoint, double[][] LastClusterCenter)