public void Smc_Dice()
        {
            // Exact posterior conditioned die
            var twoRollsExact = Dice.ConditionalDieExact(2);

            Debug.WriteLine(twoRollsExact.Histogram());

            // Posterior inferred with SMC
            var twoRolls     = Dice.ConditionalDie(2);
            var smcPosterior = twoRolls.SmcMultiple(100, 100);
            var sampled      = smcPosterior.Sample();
            var weights      = sampled.MapSample(sum => (double)sum)
                               .Weights;

            var klDivergence = KullbackLeibler.KLDivergence(sampled, twoRollsExact, d => d);

            Assert.IsTrue(klDivergence < 0.5);
            Debug.WriteLine($"KL divergence: {klDivergence}");
            Debug.WriteLine(Histogram.Weighted(weights, scale: 60));
        }
        public void Pimh_Dice()
        {
            // Exact posterior conditioned die
            var twoRollsExact = Dice.ConditionalDieExact(2);

            Debug.WriteLine(twoRollsExact.Histogram());

            // Posterior inferred with SMC
            var twoRolls      = Dice.ConditionalDie(2);
            var pimhPosterior = Pimh.Create(100, 1000, twoRolls).Sample();
            var weights       = from samples in pimhPosterior
                                from sample in samples
                                select sample;
            var klDivergence = KullbackLeibler.KLDivergence(Samples(weights), twoRollsExact, d => d);

            Debug.WriteLine($"KL divergence: {klDivergence}");
            Assert.IsTrue(klDivergence < 0.5);

            var doubleWeights = weights.Select(ip => ItemProb((double)ip.Item, ip.Prob));

            Debug.WriteLine(Histogram.Weighted(doubleWeights, scale: 60));
        }