/// <summary> /// Run k-means. /// Returns hand values. /// </summary> protected double[][] CalcValuesAndKMeans(KMeansNode parentKmNode, int round, McHand[] hands, out double[][] centers) { double [][] values = new double[hands.Length][].Fill(i => new double[Dim]); double[] min = new double[Dim].Fill(double.MaxValue); double[] max = new double[Dim].Fill(double.MinValue); for (int i = 0; i < hands.Length; ++i) { CalculateValue(hands[i].Cards, hands[i].Length, values[i]); VectorS.UpdateMin(values[i], min); VectorS.UpdateMax(values[i], max); } double [] delta = VectorS.Sub(max, min); if (_normalizeHandValues) { for (int i = 0; i < values.Length; ++i) { VectorS.NormalizeByDiff(values[i], min, delta); } min.CopyTo(parentKmNode.ValueMin, 0); delta.CopyTo(parentKmNode.ValueBounds, 0); } if (_printHandValues || _printHands) { for (int i = 0; i < values.Length; ++i) { if (_printHands) { Console.Write("{0} ", StdDeck.Descriptor.GetCardNames(hands[i].Cards, 0, hands[i].Length)); } if (_printHandValues) { PrintVector(values[i]); } Console.WriteLine(); } } // Calcualate number of clusters. int k = MaxBucketCounts[round]; int adaptingDim = -1; for (int d = 0; d < Dim; ++d) { double clusterSize = ClusterSizes[d][round]; if (clusterSize != 0) { int clCount = (int)Math.Round(delta[d] / clusterSize, 0); if (clCount < k) { adaptingDim = d; k = clCount; } } } // Make sure number of clusters is in the given range. k = Math.Max(MinBucketCounts[round], k); if (IsVerbose) { Console.Write("Min: "); PrintVector(min); Console.Write(" Max: "); PrintVector(max); Console.Write(" Delta: "); PrintVector(delta); if (k < MaxBucketCounts[round]) { Console.Write(" K adapted to {0} by dim: {1}", k, adaptingDim); } Console.WriteLine(); } double [][] differentValues = new double[k][].Fill(i => new double[Dim]); int differentValuesCount = 0; for (int i = 0; i < values.Length; ++i) { for (int j = 0; j < differentValuesCount; ++j) { if (VectorS.AreEqual(values[i], differentValues[j])) { goto RepeatedValue; } } values[i].CopyTo(differentValues[differentValuesCount], 0); differentValuesCount++; if (differentValuesCount == k) { break; } RepeatedValue :; } if (differentValuesCount < k) { // Too few different values to build k clusters. Do not run k-means, it may hang. centers = differentValues; Array.Resize(ref centers, differentValuesCount); if (IsVerbose) { Console.WriteLine("Only {0} different values found. Set cluster count, do not run kmeans", differentValuesCount); } return(values); } _kmParameters.k = k; _kmParameters.n = values.Length; _kmParameters.Allocate(); for (int i = 0; i < values.Length; ++i) { for (int d = 0; d < Dim; ++d) { *_kmParameters.GetPoint(i, d) = values[i][d]; } } fixed(Kml.Parameters *kmlp = &_kmParameters) { Kml.KML_Hybrid(kmlp); } centers = new double[_kmParameters.k][].Fill(i => new double[Dim]); for (int c = 0; c < _kmParameters.k; ++c) { for (int d = 0; d < Dim; ++d) { centers[c][d] = *_kmParameters.GetCenter(c, d); } } _kmParameters.Free(); return(values); }
public void Test_AreEqual() { Assert.IsTrue(VectorS.AreEqual(new double[] { 1, 3 }, new double[] { 1, 3 })); Assert.IsFalse(VectorS.AreEqual(new double[] { 1, 3 }, new double[] { 1, 3, 3 })); Assert.IsFalse(VectorS.AreEqual(new double[] { 1, 3 }, new double[] { 1, 2 })); }