예제 #1
0
        /// <summary>
        /// Shuffles count elements in the given sequnce starting from start.
        /// The elements below start are untouched.
        /// </summary>
        public static void Shuffle(Random rng, int [] sequence, int start, int count)
        {
            int end = start + count;

            for (int i = start; i < end; ++i)
            {
                int rndIdx = rng.Next(i, sequence.Length);
                ShortSequence.Swap(ref sequence[rndIdx], ref sequence[i]);
            }
        }
예제 #2
0
        public double Solve(double a, double b, double epsilon, bool verifyFunctionShape)
        {
            if (a > b)
            {
                ShortSequence.Swap(ref a, ref b);
            }

            double x1 = b - (b - a) / GR;
            double x2 = a + (b - a) / GR;
            double f1 = F(x1);
            double f2 = F(x2);
            double fStart = 0, fEnd = 0;

            if (verifyFunctionShape)
            {
                fStart = F(a);
                fEnd   = F(b);
                if (!IsShapeCorrect(fStart, fEnd, f1) || !IsShapeCorrect(fStart, fEnd, f2))
                {
                    throw new ApplicationException("Wrong function shape");
                }
            }

            for (;;)
            {
                if (b - a <= epsilon)
                {
                    return((b + a) * 0.5);
                }
                if (f1 > f2)
                {
                    // Replace a
                    a  = x1;
                    x1 = x2;
                    f1 = f2;
                    x2 = a + (b - a) / GR;
                    f2 = F(x2);
                    if (verifyFunctionShape)
                    {
                        if (!IsShapeCorrect(fStart, fEnd, f2))
                        {
                            throw new ApplicationException("Wrong function shape");
                        }
                    }
                }
                else
                {
                    // Replace b
                    b  = x2;
                    x2 = x1;
                    f2 = f1;
                    x1 = b - (b - a) / GR;
                    f1 = F(x1);
                    if (verifyFunctionShape)
                    {
                        if (!IsShapeCorrect(fStart, fEnd, f1))
                        {
                            throw new ApplicationException("Wrong function shape");
                        }
                    }
                }
                Debug.Assert(FloatingPoint.AreEqual((b - a) / (x2 - a), GR, 1e-10));
                Debug.Assert(FloatingPoint.AreEqual((b - a) / (b - x1), GR, 1e-10));
            }
        }
예제 #3
0
        /// <summary>
        /// Generate an internal chance tree by MC sampling.
        /// </summary>
        /// <param name="chanceAbstractions">An array of chance abstractions</param>
        /// <param name="areAbstractionsEqual">If the absractions are equal,
        /// one MC sample will update multiple nodes of the chance tree.</param>
        /// <param name="samplesCount">Number of samples. If equal absractions are used,
        /// less MC samples will be actually done to reach the specified numbers of updates.</param>
        /// <param name="rngSeed">RNG seed.</param>
        /// <param name="feedback">User feedback callback.</param>
        /// <returns></returns>
        public static Tree Generate(GameDefinition gd, IChanceAbstraction[] chanceAbstractions, bool areAbstractionsEqual, long samplesCount, int rngSeed, FeedbackDelegate feedback)
        {
            if (chanceAbstractions.Length != 2)
            {
                throw new ArgumentOutOfRangeException("Only heads up games are supported now");
            }
            McDealer mcDealer = new McDealer(gd, rngSeed);

            int [][] hands     = new int[chanceAbstractions.Length][].Fill(i => new int[mcDealer.HandSize]);
            int[]    handSizes = gd.GetHandSizes();

            Tree tree = new Tree
            {
                PlayersCount = chanceAbstractions.Length,
                RoundsCount  = gd.RoundsCount,
                SourceInfo   = GetSourceInfo(gd, chanceAbstractions)
            };

            Node root = tree.Root;

            byte[] abstrCards = new byte[gd.RoundsCount * chanceAbstractions.Length];
            uint[] ranks      = new uint[chanceAbstractions.Length];
            Int64  samplesDone;
            int    updateCount = areAbstractionsEqual ? 2 : 1;

            for (samplesDone = 0; samplesDone < samplesCount; samplesDone += updateCount)
            {
                if (feedback != null && (samplesDone % FEEDBACK_PERIOD == 0))
                {
                    if (!feedback(samplesDone))
                    {
                        break;
                    }
                }

                mcDealer.NextDeal(hands);
                gd.GameRules.Showdown(gd, hands, ranks);

                int c = 0;
                for (int r = 0; r < gd.RoundsCount; ++r)
                {
                    for (int p = 0; p < chanceAbstractions.Length; ++p)
                    {
                        int abstrCard = chanceAbstractions[p].GetAbstractCard(hands[p], handSizes[r]);
                        if (abstrCard < byte.MinValue || abstrCard > byte.MaxValue)
                        {
                            throw new ApplicationException(string.Format("Abstract card {0} out of byte range", abstrCard));
                        }
                        abstrCards[c++] = (byte)abstrCard;
                    }
                }

                for (int u = 0; ;)
                {
                    LeafT[] leaves   = tree.GetLeavesByCards(abstrCards);
                    int     lastCard = abstrCards[abstrCards.Length - 1];
                    leaves[lastCard].Update(ranks);

                    if (++u == updateCount)
                    {
                        break;
                    }

                    // If the abstractions are equal, we can update another node
                    // by permuting cards and results
                    // Note: implemented for 2 players only
                    for (c = 0; c < abstrCards.Length; c += 2)
                    {
                        ShortSequence.Swap(ref abstrCards[c], ref abstrCards[c + 1]);
                    }
                    ShortSequence.Swap(ref ranks[0], ref ranks[1]);
                }
            }
            tree.SamplesCount = (UInt64)samplesDone;
            tree.UpdateDescription();
            return(tree);
        }