public IEnumerable <TimePoint <ChemicalSystem> > GetPath(IList <Reaction> reactions, ChemicalSystem initialSystem, double endTime, int numPoints)
        {
            double t = 0;
            var    evolvingSystem = initialSystem;
            int    numReactions   = reactions.Count;

            double reportingInterval = endTime / (double)numPoints;
            double nextPoint         = reportingInterval;

            do
            {
                var randoms      = _random.GetNext();
                var propensities = reactions.Select(r => r.Propensity(evolvingSystem));

                var totalPropensity = propensities.Sum();

                var normalisedPropensities = propensities.Select(p => p / totalPropensity).ToList();

                var selectedReaction = Partitioner.ToIntervals(normalisedPropensities)
                                       .Zip(reactions, (interval, reaction) => new Tuple <Tuple <double, double>, Reaction>(interval, reaction))
                                       .Single(pair => randoms.r2 > pair.Item1.Item1 && randoms.r2 < pair.Item1.Item2)
                                       .Item2;

                t += Math.Log(1.0 / randoms.r1) / totalPropensity;

                evolvingSystem = evolvingSystem.React(selectedReaction);

                if (t > nextPoint)
                {
                    yield return(new TimePoint <ChemicalSystem>(t, evolvingSystem));

                    nextPoint += reportingInterval;
                }
            } while (t <= endTime);
        }
        public void should_partition_unit_interval()
        {
            var sequence = new [] { 0.5, 0.25, 0.125, 0.06025 };
            var expected = new [] {
                new Tuple <double, double>(0, 0.5),
                new Tuple <double, double>(0.5, 0.75),
                new Tuple <double, double>(0.75, 0.875),
                new Tuple <double, double>(0.875, 1.0)
            };

            Assert.Equal(expected, Partitioner.ToIntervals(sequence));
        }