} // 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 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)