예제 #1
0
        public void TestCumulativeP()
        {
            var    emptyBlock = new RandomisationArm[0];
            double d          = 0;
            var    moqRand    = new Mock <IRandom>(MockBehavior.Strict);

            moqRand.Setup(m => m.NextDouble()).Returns(() => d);
            foreach (var r in GetRatio())
            {
                var    counter   = new Counter <RandomisationArm>();
                double blockSize = r.TotalBlockSize();
                double increment = 1 / (blockSize);
                for (d = increment / 2; d < 1; d += increment)
                {
                    var nextAlloc = BlockRandomisation.NextAllocation(emptyBlock, r, moqRand.Object);
                    counter[nextAlloc]++;
                }
                MyCollectionAssert.AreEquivalent(r.GetAllocations(), counter);
            }
        }
예제 #2
0
        public void TestRandomisingAlgorithm()
        {
            var moqRand = new Mock <IRandom>(MockBehavior.Strict);
            var rnd     = new Random();

            moqRand.Setup(m => m.NextDouble()).Returns(rnd.NextDouble);
            int minAllocations = int.MaxValue;

            foreach (var r in GetRatio())
            {
                const int maxRptIncr   = 3;
                const int sameBlockRpt = 1000;
                for (int incr = 0; incr < maxRptIncr; incr++)
                {
                    var allArms     = new List <List <RandomisationArm> >(sameBlockRpt);
                    var rClone      = r.Clone((byte)(r.Repeats + incr));
                    int allocations = rClone.TotalBlockSize();
                    if (allocations < minAllocations)
                    {
                        minAllocations = allocations;
                    }
                    foreach (var dummy in Enumerable.Repeat(0, sameBlockRpt))
                    {
                        var arms = new List <RandomisationArm>(allocations);
                        while (arms.Count < allocations)
                        {
                            var newArm = BlockRandomisation.NextAllocation(arms, rClone, moqRand.Object);
                            arms.Add(newArm);
                        }
                        CollectionAssert.AreEquivalent(rClone.ToList(), arms);

                        allArms.Add(arms);
                    }
                    //keep this simple 2 arms, block size 4 - total permutations = 2^2, block size 6 = 6*5*4
                    //block 3 arms, block size 6 - permutations = 6*5 + 4*3
                    //blokk 3 arms, 2:1:1 size 8 = 8*7*6*5 + 4*3
                    //

                    var ocurrences = new Counter <IList <RandomisationArm> >(new EnumListEqualityComparer <RandomisationArm>());
                    foreach (var block in allArms)
                    {
                        ocurrences[block]++;
                    }

                    double permutations = SpecialFunctions.Factorial(allocations)
                                          /
                                          rClone.Ratios.Values.Aggregate(1, (prev, cur) => (int)(prev * SpecialFunctions.Factorial(cur * rClone.Repeats)));

                    double       expectedOccurence = sameBlockRpt / permutations;
                    string       assertMessage     = null;
                    const double accceptableP      = 0.00001;
                    var          bin = new MathNet.Numerics.Distributions.Binomial(1 / permutations, allArms.Count);
                    foreach (var kv in ocurrences)
                    {
                        string msg;
                        double p;
                        if (kv.Value > expectedOccurence)
                        {
                            p   = 1 - bin.CumulativeDistribution(kv.Value - 1);
                            msg = "(as or more extreme)";
                        }
                        else
                        {
                            p   = bin.CumulativeDistribution(kv.Value);
                            msg = "(as or less extreme)";
                        }
                        msg = String.Format("{{{0}}} occured {1} times: p {2:N4} " + msg,
                                            string.Join(",", kv.Key.Select(a => ((int)a).ToString())),
                                            kv.Value,
                                            p);
                        Console.WriteLine(msg);
                        if (p < accceptableP)
                        {
                            assertMessage = msg;
                        }
                    }
                    int unusedPermutations = (int)permutations - ocurrences.Count;
                    var cc = ocurrences.CountOfCounts();
                    cc[0] = unusedPermutations;
                    var mean     = (double)cc.Sum(kv => kv.Key * kv.Value) / permutations;
                    var variance = (double)cc.Sum(kv => Math.Pow(kv.Key - mean, 2) * kv.Value) / permutations;
                    Console.WriteLine("mean: {0} variance: {1}", mean, variance);
                    if (unusedPermutations > 0)
                    {
                        //double p0 = MathNet.Numerics.Distributions.Binomial.PMF(unusedPermutations / permutations, (int)permutations * sameBlockRpt, 0);
                        double lambda = sameBlockRpt / permutations;
                        double p0     = MathNet.Numerics.Distributions.Poisson.PMF(lambda, 0);
                        double z      = (unusedPermutations / sameBlockRpt - p0) / Math.Sqrt(lambda);
                        string msg    = String.Format("{0} other permutations were never used, p {1:N4}",
                                                      unusedPermutations,
                                                      p0);
                        Console.WriteLine(msg);
                    }

                    /*
                     * //to do - get poisson deviance and pearson statistic for binomial in order to validate gof
                     * var pBin = MathNet.Numerics.Distributions.ChiSquared.CDF(cc.Count,binCor);
                     * var poi = new MathNet.Numerics.Distributions.Poisson(1 / permutations);
                     * //
                     * var pPoi = MathNet.Numerics.Distributions.ChiSquared.CDF(cc.Count, poiCor);
                     * */
                    if (assertMessage != null)
                    {
                        throw new AssertFailedException("unacceptably low probability " + assertMessage);
                    }
                }
            }
        }