Exemple #1
0
        public void Read(BinaryReader r, int serializationFormatVersion)
        {
            int dim = r.ReadInt32();

            Center = new double[dim];
            for (int d = 0; d < Center.Length; ++d)
            {
                Center[d] = r.ReadDouble();
            }
            ValueMin    = new double[dim];
            ValueBounds = new double[dim].Fill(1);
            if (serializationFormatVersion > 0)
            {
                for (int d = 0; d < Center.Length; ++d)
                {
                    ValueMin[d] = r.ReadDouble();
                }
                for (int d = 0; d < Center.Length; ++d)
                {
                    ValueBounds[d] = r.ReadDouble();
                }
            }
            int childCount = r.ReadInt32();

            Children = childCount == 0 ? null : new KMeansNode[childCount];
            for (int i = 0; i < ChildrenCount; ++i)
            {
                Children[i] = new KMeansNode();
                Children[i].Read(r, serializationFormatVersion);
            }
        }
Exemple #2
0
 public void AllocateChildren(int childCount)
 {
     if (childCount != 0)
     {
         Children = new KMeansNode[childCount];
     }
 }
        public virtual IClusterNode OnGenerateBegin()
        {
            Kml.Init(null);

            KMeansNode root = new KMeansNode(Dim, MaxBucketCounts[0]);

            for (int i = 0; i < root.ChildrenCount; ++i)
            {
                root.Children[i] = new KMeansNode(Dim, 0);
            }
            return(root);
        }
        public Bucket[] BucketizeHands(int round, McHand[] hands, IClusterNode parentNode)
        {
            KMeansNode parentKmNode = (KMeansNode)parentNode;

            if (hands == null || hands.Length == 0)
            {
                parentKmNode.AllocateChildren(1);
                parentKmNode.Children[0] = new KMeansNode(Dim, 0);
                return(new Bucket[] { new Bucket() });
            }

            double[][] centers;
            double[][] values = CalcValuesAndKMeans(parentKmNode, round, hands, out centers);

            if (IsVerbose)
            {
                Console.Write("Centers:");
                PrintCenters(centers);
                Console.WriteLine();
            }
            Array.Sort(centers, new CenterComparer());
            if (IsVerbose)
            {
                Console.Write("Sorted centers:");
                PrintCenters(centers);
                Console.WriteLine();
            }

            parentKmNode.AllocateChildren(centers.Length);
            for (int c = 0; c < centers.Length; ++c)
            {
                KMeansNode node = new KMeansNode(Dim, 0);
                centers[c].CopyTo(node.Center, 0);
                parentKmNode.Children[c] = node;
            }

            Bucket[] buckets = new Bucket[parentKmNode.Children.Length].Fill(i => new Bucket());
            for (int i = 0; i < hands.Length; ++i)
            {
                // Never normalize values here, because it is either not necessary or already done (for k-means).
                int abstrCard = parentKmNode.FindClosestChild(values[i], false);
                buckets[abstrCard].Hands.Add(hands[i]);
            }
            return(buckets);
        }
        public int GetAbstractCard(int[] hand, int handLength)
        {
            int round     = HeHelper.HandSizeToRound[handLength];
            int abstrCard = GetPreflopAbstrCard(hand);

            if (round == 0)
            {
                return(abstrCard);
            }
            KMeansNode kn = (KMeansNode)_clusterTree.Root.GetChild(abstrCard);

            double[] point = new double[Dim];
            for (int r = 1; r <= round; ++r)
            {
                CalculateValue(hand, HeHelper.RoundToHandSize[r], point);
                abstrCard = kn.FindClosestChild(point, _normalizeHandValues);
                kn        = kn.Children[abstrCard];
            }
            Debug.Assert(abstrCard >= 0 && abstrCard < MaxBucketCounts[round]);
            return(abstrCard);
        }
        /// <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);
        }