// 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)
public static double AverageWidth = 0.0; // Average Width each iteration public static void InitializeKmeans(double[][] PointPositionINPUT, ParallelOptions _parallelOptionsINPUT, string FileName, int ClusterPosition, int FirstClusterValue, int StartingPosition, int Ncent_GlobalINPUT, int MaxNcent_GlobalINPUT, int Ncent_Global_ParallelINPUT, int ParameterVectorDimensionINPUT, double CenterChangeINPUT, int IterationCutINPUT) { Kmeans.PointPosition = PointPositionINPUT; Kmeans._parallelOptions = _parallelOptionsINPUT; Kmeans.Ncent_Global = Ncent_GlobalINPUT; Kmeans.MaxNcent_Global = MaxNcent_GlobalINPUT; Kmeans.Ncent_Global_Parallel = Ncent_Global_ParallelINPUT; Kmeans.KmeansCenterChangeCut = CenterChangeINPUT; Kmeans.KmeansIterationCut = IterationCutINPUT; Kmeans.ParameterVectorDimension = ParameterVectorDimensionINPUT; Kmeans.SetParallelCenterDecomposition(); Kmeans.InitialPointAssignment = new int[DAVectorUtility.PointCount_Process]; if (FileName.Length == 0) { return; } // Read Initial Assignments DAVectorUtility.SALSAPrint(0, "Kmeans Read File " + FileName + " Points " + DAVectorUtility.PointCount_Global.ToString() + " Starting at position " + StartingPosition.ToString() + " Dimension " + Kmeans.ParameterVectorDimension.ToString() + " Cluster Position " + ClusterPosition.ToString() + " Initial value " + FirstClusterValue.ToString()); Kmeans.ReadDataFromFile(FileName, ClusterPosition, FirstClusterValue, StartingPosition); } // End InitializeKmeans
} // 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)
} // End SetupKmeans public static void RunKmeans(double[][] ClusterCenterINPUT, int[] ClusterSizeINPUT, double[] ClusteRadiusINPUT, out int Ncent_GlobalFINAL, out double AverageWidthFINAL) { ArrayList KeepPCfractions = new ArrayList(200); ArrayList KeepCCfractions = new ArrayList(200); // Inherit Solution arrays Kmeans.ClusterCenter = ClusterCenterINPUT; Kmeans.ClusterSize = ClusterSizeINPUT; Kmeans.ClusterRadius = ClusteRadiusINPUT; Kmeans.ClusterWidth = new double[Kmeans.MaxNcent_Global]; // Set up TriangleInequality KmeansTriangleInequality.SetExternalFunctions(GetClusterRadius, GetClusterCenters, FindClusterCenters); KmeansTriangleInequality.InitializeTriangleInequality(Kmeans.PointPosition, Kmeans._parallelOptions, Kmeans.ClusterCenter, Kmeans.Ncent_Global, Kmeans.MaxNcent_Global, Kmeans.Ncent_Global_Parallel, Kmeans.ParameterVectorDimension); DAVectorUtility.SALSAPrint(0, "Start Kmeans ****** Number of Centers " + Kmeans.Ncent_Global.ToString() + " Max Number of Centers " + Kmeans.MaxNcent_Global.ToString() + " Center Limit for Parallelism " + Kmeans.Ncent_Global_Parallel.ToString() + " Vector Dimension " + Kmeans.ParameterVectorDimension.ToString()); Kmeans.FindClusterCenters(true, Kmeans.InitialPointAssignment, null, null); Kmeans.CountKmeansIterations = 0; bool StartStop = false; int CountStops = 0; while (Kmeans.CountKmeansIterations < Kmeans.KmeansIterationCut) { double save1 = KmeansTriangleInequality.NumberFullDistancesCalculatedCC; double save2 = KmeansTriangleInequality.NumberFullDistancesCalculatedPC; KmeansTriangleInequality.NextIteration(); ++Kmeans.CountKmeansIterations; bool WillStop = false; if (!StartStop) { if (Kmeans.AverageCenterChange < Kmeans.AverageRadius * Kmeans.KmeansCenterChangeCut) { StartStop = true; } } else { ++CountStops; if (CountStops > 10) { WillStop = true; } } double tmp1 = (KmeansTriangleInequality.NumberFullDistancesCalculatedCC - save1) / (double)Kmeans.MaxNcent_Global; double tmp2 = (KmeansTriangleInequality.NumberFullDistancesCalculatedPC - save2) / ((double)Kmeans.MaxNcent_Global * (double)DAVectorUtility.PointCount_Global); double tmp3 = KmeansTriangleInequality.NumberFullDistancesCalculatedPC / ((double)Kmeans.MaxNcent_Global * (double)(DAVectorUtility.PointCount_Global * Kmeans.CountKmeansIterations)); double tmp4 = (KmeansTriangleInequality.NumberFullDistancesCalculatedPC + KmeansTriangleInequality.NumberFullDistancesCalculatedCC) / ((double)Kmeans.MaxNcent_Global * (double)(DAVectorUtility.PointCount_Global * Kmeans.CountKmeansIterations)); DAVectorUtility.SALSAPrint(0, "Iteration " + Kmeans.CountKmeansIterations.ToString() + " Average Center Change " + Kmeans.AverageCenterChange.ToString("E4") + " Average Radius " + Kmeans.AverageRadius.ToString("E4") + " Average Width " + Kmeans.AverageWidth.ToString("E4") + " CC calcs per C " + tmp1.ToString("F4") + " PC calcs per P&C " + tmp2.ToString("F6") + " Cumul PC / Max " + tmp3.ToString("F6") + " Cumul PC+CC / PC Max " + tmp4.ToString("F6")); KeepPCfractions.Add(tmp2); KeepCCfractions.Add(tmp1 / DAVectorUtility.PointCount_Global); if (((Kmeans.CountKmeansIterations % 10) == 1) || WillStop) { string message = " Sizes"; for (int CenterIndex = 0; CenterIndex < Kmeans.Ncent_Global; CenterIndex++) { message += " " + Kmeans.ClusterSize[CenterIndex].ToString(); } DAVectorUtility.SALSAPrint(0, message); } if (WillStop) { break; } } DAVectorUtility.SALSAPrint(0, "End Kmeans Iterations " + Kmeans.CountKmeansIterations.ToString() + " Iteration Cut " + Kmeans.KmeansIterationCut.ToString() + " Average Center Change " + Kmeans.AverageCenterChange.ToString("E4") + " Average Radius " + Kmeans.AverageRadius.ToString("E4") + " Average Width " + Kmeans.AverageWidth.ToString("E4") + " Fractional Cut " + Kmeans.KmeansCenterChangeCut.ToString("F4")); KmeansTriangleInequality.PrintDiagnostics(); string messagePC = "\nPC Calcs per Point iteration"; string messageCC = "\nCC Calcs per Point iteration"; int numPC = KeepPCfractions.Count; for (int linecount = 0; linecount < numPC; linecount++) { messagePC += " " + ((double)KeepPCfractions[linecount]).ToString("F4") + ","; messageCC += " " + ((double)KeepCCfractions[linecount]).ToString("F4") + ","; } DAVectorUtility.SALSAPrint(0, messagePC); DAVectorUtility.SALSAPrint(0, messageCC); Ncent_GlobalFINAL = Kmeans.Ncent_Global; AverageWidthFINAL = Kmeans.AverageWidth; // Print Histograms if (KmeansTriangleInequality.UseTriangleInequality != 0) { KmeansTriangleInequality.PlotPointHistograms(Math.Sqrt(AverageWidthFINAL)); KmeansTriangleInequality.PlotCenterHistograms(Math.Sqrt(AverageWidthFINAL)); } return; } // End RunKmeans()
} // 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
} // 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)