Beispiel #1
0
 def propagate(self,
               time0,
               value0,
               time,
               variate=None,
               state0=None,
               random_state=None):
     if time == time0:
         return npu.to_ndim_2(value0, ndim_1_to_col=True, copy=True)
     value0 = npu.to_ndim_2(value0, ndim_1_to_col=True, copy=False)
     if variate is None:
         if random_state is None: random_state = rnd.random_state()
         variate = random_state.normal(size=self.noise_dim)
     variate = npu.to_ndim_2(variate, ndim_1_to_col=True, copy=False)
     time_delta = time - time0
     if isinstance(time_delta, np.timedelta64):
         time_delta = time_delta.item()
     if isinstance(time_delta, dt.timedelta):
         time_delta = time_delta.total_seconds(
         ) / self._time_unit.total_seconds()
     mrf = self.mean_reversion_factor(time_delta)
     eye_minus_mrf = np.eye(self.process_dim) - mrf
     m = np.dot(mrf, value0) + np.dot(eye_minus_mrf, self._mean)
     c = self.noise_covariance(time_delta)
     return m + np.dot(np.linalg.cholesky(c), variate)
Beispiel #2
0
 def test_random_state(self):
     rs = np.random.RandomState(seed=42)
     rnd.random_state(rs, force=True)
     self.assertEqual(rnd.random_state(), rs)
     with self.assertRaises(exc.NumericError):
         rnd.random_state(rs)
     rs = np.random.RandomState(seed=132)
     rnd.random_state(rs, force=True)
     self.assertEqual(rnd.random_state(), rs)
Beispiel #3
0
    def test_euler_maruyama(self):
        rnd.random_state(np.random.RandomState(seed=42), force=True)

        W = proc.WienerProcess.create_2d(mean1=-.5,
                                         mean2=3.,
                                         sd1=3.,
                                         sd2=4.,
                                         cor=.5)
        em = sim.EulerMaruyama(process=W)

        t, v = next(em)
        npt.assert_almost_equal(t, 0.)
        npt.assert_almost_equal(v, npu.col(0.0, 0.0))

        t, v = next(em)
        npt.assert_almost_equal(t, 1.)
        npt.assert_almost_equal(v, npu.col(0.9901425, 3.5144667))
Beispiel #4
0
 def __init__(self, time, state_distr, process,
              weighting_func=None,
              particle_count=1000, observation_dim=1,
              random_state=None,
              predicted_observation_sampler=None, outlier_threshold=None,
              name=None, pype=None, pype_options=frozenset(filtering.FilterPypeOptions)):
     super().__init__(name)
     self._pype = pype
     self._pype_options = frozenset() if (pype_options is None or pype is None) else frozenset(pype_options)
     if not checks.is_iterable(process): process = (process,)
     process = checks.check_iterable_over_instances(process, proc.SolvedItoProcess)
     if weighting_func is None: weighting_func = KDEWeightingFunction()
     self._time = time
     self._observation_dim = observation_dim
     self._state_distr = state_distr
     self._processes = tuple(process)
     self._state_dim = sum([p.process_dim for p in self._processes])
     self._weighting_func = weighting_func
     self._particle_count = particle_count
     self._current_particle_idx = None
     self._random_state = rnd.random_state() if random_state is None else random_state
     self._predicted_observation_sampler = predicted_observation_sampler
     
     self._prior_particles = np.empty((self._particle_count, self._state_dim))
     self._resampled_particles = np.empty((self._particle_count, self._state_dim))
     self._unnormalised_weights = np.empty((self._particle_count,))
     self._weights = np.empty((self._particle_count,))
     self._resampled_particles_uptodate = False
     
     self._last_observation = None
     
     self._cached_prior_mean = None
     self._cached_prior_var = None
     self._cached_posterior_mean = None
     self._cached_posterior_var = None
     self._cached_resampled_mean = None
     self._cached_resampled_var = None
     
     self.log_likelihood = 0.0
     self.effective_sample_size = np.NaN
     
     if self._predicted_observation_sampler is not None:
         self.predicted_observation_particles = None
         self.predicted_observation_kde = None
         self.predicted_observation = np.NaN
         self.innovation = np.NaN
         self.innovationvar = np.NaN
         
     assert self._predicted_observation_sampler is not None or outlier_threshold is None 
     self._outlier_threshold = outlier_threshold
         
     self._context = OrderedDict()
     
     self._initialise()
Beispiel #5
0
    def test_run(self):
        rnd.random_state(np.random.RandomState(seed=42), force=True)

        W = proc.WienerProcess.create_2d(mean1=.25,
                                         mean2=.5,
                                         sd1=3.,
                                         sd2=4.,
                                         cor=.5)
        em = sim.EulerMaruyama(process=W)

        df = sim.run(em, nstep=10)
        pdt.assert_frame_equal(
            df,
            pd.DataFrame(
                data=[[0.000000, 0.000000], [1.740142, 1.014467],
                      [3.933208, 8.085774], [3.480748, 7.306393],
                      [8.468386, 13.623291], [7.309963, 15.063825],
                      [6.169710, 13.023654], [7.145597, 7.379782],
                      [2.220843, 2.482125], [-0.567650, 2.045047]],
                index=[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]))
Beispiel #6
0
def multinomial_resample(empirical_distr, target_particle_count=None, random_state=None):
    if target_particle_count is None: target_particle_count = empirical_distr.particle_count
    if random_state is None: random_state = rnd.random_state()
    counts = rnd.multinomial(target_particle_count, npu.to_ndim_1(empirical_distr.normalized_weights))
    assert np.sum(counts) == target_particle_count
    particle_idx = 0
    resampled_particles = np.empty((target_particle_count, np.shape(empirical_distr.particles)[1]))
    for i in range(empirical_distr.particle_count):
        for _ in range(counts[i]):
            resampled_particles[particle_idx,:] = npu.to_ndim_1(empirical_distr.particle(i))
            particle_idx += 1
    return EmpiricalDistr(particles=resampled_particles, weights=np.ones((target_particle_count,)))
Beispiel #7
0
    def test_exponential(self):
        rnd.random_state(np.random.RandomState(seed=42), force=True)

        values = rnd.exponential(.25, size=5)
        npt.assert_almost_equal(
            values,
            np.array([0.117317, 0.7525304, 0.3291864, 0.2282356, 0.0424062]))

        values = rnd.exponential(.25, size=1000000)
        npt.assert_almost_equal(np.mean(values), .25, decimal=3)

        values = rnd.exponential(dt.timedelta(minutes=25), size=5)
        values = [v.total_seconds() for v in values]
        npt.assert_almost_equal(
            values,
            np.array([
                1138.023383, 2274.520394, 265.023984, 221.528354, 3365.675561
            ]))

        values = rnd.exponential(dt.timedelta(minutes=25), size=1000000)
        npt.assert_almost_equal(np.mean([v.total_seconds() for v in values]),
                                1497.6779794581771,
                                decimal=3)
Beispiel #8
0
 def propagate(self,
               time0,
               value0,
               time,
               variate=None,
               state0=None,
               random_state=None):
     if time == time0:
         return npu.to_ndim_2(value0, ndim_1_to_col=True, copy=True)
     value0 = npu.to_ndim_2(value0, ndim_1_to_col=True, copy=False)
     if variate is None:
         if random_state is None: random_state = rnd.random_state()
         variate = random_state.normal(size=self.noise_dim)
     variate = npu.to_ndim_2(variate, ndim_1_to_col=True, copy=False)
     time_delta = time - time0
     if isinstance(time_delta, np.timedelta64):
         time_delta = time_delta.item()
     if isinstance(time_delta, dt.timedelta):
         time_delta = time_delta.total_seconds(
         ) / self._time_unit.total_seconds()
     final_time_minus_time0 = self.__final_time - time0
     if isinstance(final_time_minus_time0, np.timedelta64):
         final_time_minus_time0 = final_time_minus_time0.item()
     if isinstance(final_time_minus_time0, dt.timedelta):
         final_time_minus_time0 = final_time_minus_time0.total_seconds(
         ) / self._time_unit.total_seconds()
     final_time_minus_time = self.__final_time - time
     if isinstance(final_time_minus_time, np.timedelta64):
         final_time_minus_time = time_delta.item()
     if isinstance(final_time_minus_time, dt.timedelta):
         final_time_minus_time = final_time_minus_time.total_seconds(
         ) / self._time_unit.total_seconds()
     mean = value0 + time_delta / final_time_minus_time0 * (
         self.__final_value - value0)
     cov_factor = time_delta * final_time_minus_time / final_time_minus_time0
     vol_factor = np.sqrt(cov_factor)
     vol = vol_factor * self.__vol
     return mean + np.dot(vol, variate)
Beispiel #9
0
 def propagate(self,
               time0,
               value0,
               time,
               variate=None,
               state0=None,
               random_state=None):
     if time == time0:
         return npu.to_ndim_2(value0, ndim_1_to_col=True, copy=True)
     value0 = npu.to_ndim_2(value0, ndim_1_to_col=True, copy=False)
     if variate is None:
         if random_state is None: random_state = rnd.random_state()
         variate = random_state.normal(size=self.noise_dim)
     variate = npu.to_ndim_2(variate, ndim_1_to_col=True, copy=False)
     time_delta = time - time0
     if isinstance(time_delta, np.timedelta64):
         time_delta = time_delta.item()
     if isinstance(time_delta, dt.timedelta):
         time_delta = time_delta.total_seconds(
         ) / self._time_unit.total_seconds()
     return value0 * np.exp(
             (self._pct_drift - .5 * npu.col(*np.sum(self._pct_vol**2, axis=1))) * time_delta + \
             np.dot(self._pct_vol, np.sqrt(time_delta) * variate))
Beispiel #10
0
 def propagate(self,
               time0,
               value0,
               time,
               variate=None,
               state0=None,
               random_state=None):
     if self.noise_dim != self.process_dim:
         raise NotImplementedError(
             'Cannot utilize the propagate_distr of the Markov process in propagate if noise_dim != process_dim; provide a custom implementation'
         )
     if time == time0:
         return npu.to_ndim_2(value0, ndim_1_to_col=True, copy=True)
     value0 = npu.to_ndim_2(value0, ndim_1_to_col=True, copy=False)
     if variate is None:
         if random_state is None: random_state = rnd.random_state()
         variate = random_state.normal(size=self.noise_dim)
     variate = npu.to_ndim_2(variate, ndim_1_to_col=True, copy=False)
     distr = self.propagate_distr(time,
                                  time0,
                                  distrs.DiracDeltaDistr.create(value0),
                                  assume_distr=True)
     return distr.mean + np.dot(np.linalg.cholesky(distr.cov), variate)
Beispiel #11
0
    def test_multinomial_resample(self):
        rnd.random_state(np.random.RandomState(seed=42), force=True)
        
        normal_distr = distrs.NormalDistr(mean=[10., 100.], cov=[[4., -3.], [-3., 9.]])
        particles = normal_distr.sample(size=100000)
        approx_normal_empirical_2d = distrs.EmpiricalDistr(particles=particles, weights=np.ones((100000,)))
        self.assertEqual(approx_normal_empirical_2d.particle_count, 100000)
        npt.assert_almost_equal(approx_normal_empirical_2d.effective_particle_count, 100000.)
        self.assertEqual(approx_normal_empirical_2d.dim, 2)
        npt.assert_almost_equal(approx_normal_empirical_2d.particles, particles)
        npt.assert_almost_equal(approx_normal_empirical_2d.particle(0), npu.col(*particles[0]))
        npt.assert_almost_equal(approx_normal_empirical_2d.weights, npu.col(*np.ones((100000,))))
        npt.assert_almost_equal(approx_normal_empirical_2d.weight(0), 1.)
        npt.assert_almost_equal(approx_normal_empirical_2d.normalised_weights, npu.col(*np.ones((100000,))) / 100000.)
        npt.assert_almost_equal(approx_normal_empirical_2d.normalised_weight(0), .00001)
        self.assertEqual(approx_normal_empirical_2d.weight_sum, 100000.)
        npt.assert_almost_equal(approx_normal_empirical_2d.mean, [[   9.9866994], [ 100.0141095]])
        npt.assert_almost_equal(approx_normal_empirical_2d.var_n, [[ 3.9902435], [ 9.0362717]])
        npt.assert_almost_equal(approx_normal_empirical_2d.var_n_minus_1, [[ 3.9902834], [ 9.036362 ]])
        npt.assert_almost_equal(approx_normal_empirical_2d.cov_n, [[ 3.9902435, -3.011222 ], [-3.011222 ,  9.0362717]])
        npt.assert_almost_equal(approx_normal_empirical_2d.cov_n_minus_1, [[ 3.9902834, -3.0112521], [-3.0112521,  9.036362 ]])
        npt.assert_almost_equal(approx_normal_empirical_2d.cov, [[ 3.9902435, -3.011222 ], [-3.011222 ,  9.0362717]])
        npt.assert_almost_equal(approx_normal_empirical_2d.vol_n, [[ 1.9975594,  0.       ], [-1.5074505,  2.6007431]])
        npt.assert_almost_equal(approx_normal_empirical_2d.vol_n_minus_1, [[ 1.9975694,  0.       ], [-1.5074581,  2.6007561]])
        npt.assert_almost_equal(approx_normal_empirical_2d.vol, [[ 1.9975594,  0.       ], [-1.5074505,  2.6007431]])
        
        rnd.random_state(np.random.RandomState(seed=43), force=True)

        resampled_approx_normal_empirical_2d = distrs.multinomial_resample(approx_normal_empirical_2d)
        self.assertEqual(resampled_approx_normal_empirical_2d.particle_count, 100000)
        npt.assert_almost_equal(resampled_approx_normal_empirical_2d.effective_particle_count, 100000.)
        self.assertEqual(resampled_approx_normal_empirical_2d.dim, 2)
        # The resampled particles should ("almost certainly") be different from the original ones:
        self.assertFalse(np.sum(resampled_approx_normal_empirical_2d.particles) == np.sum(particles))
        npt.assert_almost_equal(resampled_approx_normal_empirical_2d.particle(0), npu.col(*particles[1]))
        npt.assert_almost_equal(resampled_approx_normal_empirical_2d.weights, npu.col(*np.ones((100000,))))
        npt.assert_almost_equal(resampled_approx_normal_empirical_2d.weight(0), 1.)
        npt.assert_almost_equal(resampled_approx_normal_empirical_2d.normalised_weights, npu.col(*np.ones((100000,))) / 100000.)
        npt.assert_almost_equal(resampled_approx_normal_empirical_2d.normalised_weight(0), .00001)
        self.assertEqual(resampled_approx_normal_empirical_2d.weight_sum, 100000.)
        # But the stats should be pretty close to those of the original empirical distribution, though not to seven
        # decimal places:
        npt.assert_almost_equal(resampled_approx_normal_empirical_2d.mean, [[   9.9866994], [ 100.0141095]], decimal=1)
        npt.assert_almost_equal(resampled_approx_normal_empirical_2d.var_n, [[ 3.9902435], [ 9.0362717]], decimal=1)
        npt.assert_almost_equal(resampled_approx_normal_empirical_2d.var_n_minus_1, [[ 3.9902834], [ 9.036362 ]], decimal=1)
        npt.assert_almost_equal(resampled_approx_normal_empirical_2d.cov_n, [[ 3.9902435, -3.011222 ], [-3.011222 ,  9.0362717]], decimal=1)
        npt.assert_almost_equal(resampled_approx_normal_empirical_2d.cov_n_minus_1, [[ 3.9902834, -3.0112521], [-3.0112521,  9.036362 ]], decimal=1)
        npt.assert_almost_equal(resampled_approx_normal_empirical_2d.cov, [[ 3.9902435, -3.011222 ], [-3.011222 ,  9.0362717]], decimal=1)
        npt.assert_almost_equal(resampled_approx_normal_empirical_2d.vol_n, [[ 1.9975594,  0.       ], [-1.5074505,  2.6007431]], decimal=1)
        npt.assert_almost_equal(resampled_approx_normal_empirical_2d.vol_n_minus_1, [[ 1.9975694,  0.       ], [-1.5074581,  2.6007561]], decimal=1)
        npt.assert_almost_equal(resampled_approx_normal_empirical_2d.vol, [[ 1.9975594,  0.       ], [-1.5074505,  2.6007431]], decimal=1)
        
        rnd.random_state(np.random.RandomState(seed=43), force=True)
        
        resampled_approx_normal_empirical_2d_particles = approx_normal_empirical_2d.sample(size=100000)
        npt.assert_almost_equal(resampled_approx_normal_empirical_2d_particles, resampled_approx_normal_empirical_2d.particles)

        subsampled_approx_normal_empirical_2d = distrs.multinomial_resample(approx_normal_empirical_2d, target_particle_count=40000)
        self.assertEqual(subsampled_approx_normal_empirical_2d.particle_count, 40000)
        npt.assert_almost_equal(subsampled_approx_normal_empirical_2d.effective_particle_count, 40000.)
        self.assertEqual(subsampled_approx_normal_empirical_2d.dim, 2)
        # The resampled particles should ("almost certainly") be different from the original ones:
        self.assertFalse(np.sum(subsampled_approx_normal_empirical_2d.particles) == np.sum(particles))
        npt.assert_almost_equal(subsampled_approx_normal_empirical_2d.particle(0), npu.col(*particles[1]))
        npt.assert_almost_equal(subsampled_approx_normal_empirical_2d.weights, npu.col(*np.ones((40000,))))
        npt.assert_almost_equal(subsampled_approx_normal_empirical_2d.weight(0), 1.)
        npt.assert_almost_equal(subsampled_approx_normal_empirical_2d.normalised_weights, npu.col(*np.ones((40000,))) / 40000.)
        npt.assert_almost_equal(subsampled_approx_normal_empirical_2d.normalised_weight(0), .000025)
        self.assertEqual(subsampled_approx_normal_empirical_2d.weight_sum, 40000.)
        # But the stats should be pretty close to those of the original empirical distribution, though not to seven
        # decimal places:
        npt.assert_almost_equal(subsampled_approx_normal_empirical_2d.mean, [[   9.9866994], [ 100.0141095]], decimal=1)
        npt.assert_almost_equal(subsampled_approx_normal_empirical_2d.var_n, [[ 3.9902435], [ 9.0362717]], decimal=1)
        npt.assert_almost_equal(subsampled_approx_normal_empirical_2d.var_n_minus_1, [[ 3.9902834], [ 9.036362 ]], decimal=1)
        npt.assert_almost_equal(subsampled_approx_normal_empirical_2d.cov_n, [[ 3.9902435, -3.011222 ], [-3.011222 ,  9.0362717]], decimal=1)
        npt.assert_almost_equal(subsampled_approx_normal_empirical_2d.cov_n_minus_1, [[ 3.9902834, -3.0112521], [-3.0112521,  9.036362 ]], decimal=1)
        npt.assert_almost_equal(subsampled_approx_normal_empirical_2d.cov, [[ 3.9902435, -3.011222 ], [-3.011222 ,  9.0362717]], decimal=1)
        npt.assert_almost_equal(subsampled_approx_normal_empirical_2d.vol_n, [[ 1.9975594,  0.       ], [-1.5074505,  2.6007431]], decimal=1)
        npt.assert_almost_equal(subsampled_approx_normal_empirical_2d.vol_n_minus_1, [[ 1.9975694,  0.       ], [-1.5074581,  2.6007561]], decimal=1)
        npt.assert_almost_equal(subsampled_approx_normal_empirical_2d.vol, [[ 1.9975594,  0.       ], [-1.5074505,  2.6007431]], decimal=1)

        supersampled_approx_normal_empirical_2d = distrs.multinomial_resample(approx_normal_empirical_2d, target_particle_count=300000)
        self.assertEqual(supersampled_approx_normal_empirical_2d.particle_count, 300000)
        npt.assert_almost_equal(supersampled_approx_normal_empirical_2d.effective_particle_count, 300000.)
        self.assertEqual(supersampled_approx_normal_empirical_2d.dim, 2)
        # The resampled particles should ("almost certainly") be different from the original ones:
        self.assertFalse(np.sum(supersampled_approx_normal_empirical_2d.particles) == np.sum(particles))
        npt.assert_almost_equal(supersampled_approx_normal_empirical_2d.particle(0), npu.col(*particles[0]))
        npt.assert_almost_equal(supersampled_approx_normal_empirical_2d.weights, npu.col(*np.ones((300000,))))
        npt.assert_almost_equal(supersampled_approx_normal_empirical_2d.weight(0), 1.)
        npt.assert_almost_equal(supersampled_approx_normal_empirical_2d.normalised_weights, npu.col(*np.ones((300000,))) / 300000.)
        npt.assert_almost_equal(supersampled_approx_normal_empirical_2d.normalised_weight(0), 3.3333333333333333e-06)
        self.assertEqual(supersampled_approx_normal_empirical_2d.weight_sum, 300000.)
        # But the stats should be pretty close to those of the original empirical distribution, though not to seven
        # decimal places:
        npt.assert_almost_equal(supersampled_approx_normal_empirical_2d.mean, [[   9.9866994], [ 100.0141095]], decimal=1)
        npt.assert_almost_equal(supersampled_approx_normal_empirical_2d.var_n, [[ 3.9902435], [ 9.0362717]], decimal=1)
        npt.assert_almost_equal(supersampled_approx_normal_empirical_2d.var_n_minus_1, [[ 3.9902834], [ 9.036362 ]], decimal=1)
        npt.assert_almost_equal(supersampled_approx_normal_empirical_2d.cov_n, [[ 3.9902435, -3.011222 ], [-3.011222 ,  9.0362717]], decimal=1)
        npt.assert_almost_equal(supersampled_approx_normal_empirical_2d.cov_n_minus_1, [[ 3.9902834, -3.0112521], [-3.0112521,  9.036362 ]], decimal=1)
        npt.assert_almost_equal(supersampled_approx_normal_empirical_2d.cov, [[ 3.9902435, -3.011222 ], [-3.011222 ,  9.0362717]], decimal=1)
        npt.assert_almost_equal(supersampled_approx_normal_empirical_2d.vol_n, [[ 1.9975594,  0.       ], [-1.5074505,  2.6007431]], decimal=1)
        npt.assert_almost_equal(supersampled_approx_normal_empirical_2d.vol_n_minus_1, [[ 1.9975694,  0.       ], [-1.5074581,  2.6007561]], decimal=1)
        npt.assert_almost_equal(supersampled_approx_normal_empirical_2d.vol, [[ 1.9975594,  0.       ], [-1.5074505,  2.6007431]], decimal=1)
Beispiel #12
0
    def test_normal_distr(self):
        rnd.random_state(np.random.RandomState(seed=42), force=True)

        std_normal_1d = distrs.NormalDistr(dim=1)
        npt.assert_almost_equal(std_normal_1d.mean, 0.)
        npt.assert_almost_equal(std_normal_1d.cov, 1.)
        npt.assert_almost_equal(std_normal_1d.vol, 1.)
        
        sample = std_normal_1d.sample()
        self.assertEqual(np.shape(sample), (1, 1))
        npt.assert_almost_equal(sample, [[ 0.49671415]])
        
        sample = std_normal_1d.sample(size=10)
        self.assertEqual(np.shape(sample), (10, 1))
        npt.assert_almost_equal(sample, [
                [-0.1382643 ],
                [ 0.64768854],
                [ 1.52302986],
                [-0.23415337],
                [-0.23413696],
                [ 1.57921282],
                [ 0.76743473],
                [-0.46947439],
                [ 0.54256004],
                [-0.46341769]])
        
        std_normal_2d = distrs.NormalDistr(dim=2)
        npt.assert_almost_equal(std_normal_2d.mean, npu.col_of(2, 0.))
        npt.assert_almost_equal(std_normal_2d.cov, np.eye(2))
        npt.assert_almost_equal(std_normal_2d.vol, np.eye(2))
        
        sample = std_normal_2d.sample(size=10)
        self.assertEqual(np.shape(sample), (10, 2))
        npt.assert_almost_equal(sample, [
                [-0.46572975,  0.24196227],
                [-1.91328024, -1.72491783],
                [-0.56228753, -1.01283112],
                [ 0.31424733, -0.90802408],
                [-1.4123037 ,  1.46564877],
                [-0.2257763 ,  0.0675282 ],
                [-1.42474819, -0.54438272],
                [ 0.11092259, -1.15099358],
                [ 0.37569802, -0.60063869],
                [-0.29169375, -0.60170661]])

        sd1=3.; sd2=4.; cor=-.5

        normal_2d = distrs.NormalDistr(mean=[1., 2.], cov=stats.make_cov_2d(sd1=sd1, sd2=sd2, cor=cor))
        npt.assert_almost_equal(normal_2d.mean, npu.col(1., 2.))
        npt.assert_almost_equal(normal_2d.cov, [[sd1*sd1, cor*sd1*sd2], [cor*sd1*sd2, sd2*sd2]])
        npt.assert_almost_equal(normal_2d.vol, [[sd1, 0.], [cor*sd2, np.sqrt(1.-cor*cor)*sd2]])

        sample = normal_2d.sample(size=10)
        self.assertEqual(np.shape(sample), (10, 2))
        npt.assert_almost_equal(sample, [
                [-3.09581812,  9.06710684],
                [ 5.00400357, -1.07912958],
                [ 4.10821238, -2.42324481],
                [ 2.58989516, -7.05256838],
                [ 2.07671635,  3.61955714],
                [ 0.38728403,  2.5195548 ],
                [-1.36010204, -0.88681309],
                [ 1.63968707, -1.29329703],
                [-0.61960168,  6.44566548],
                [ 5.53451941, -4.36131646]])

        normal_2d = distrs.NormalDistr(mean=[1., 2.], vol=stats.make_vol_2d(sd1=sd1, sd2=sd2, cor=cor))
        npt.assert_almost_equal(normal_2d.mean, npu.col(1., 2.))
        npt.assert_almost_equal(normal_2d.cov, [[sd1*sd1, cor*sd1*sd2], [cor*sd1*sd2, sd2*sd2]])
        npt.assert_almost_equal(normal_2d.vol, [[sd1, 0.], [cor*sd2, np.sqrt(1.-cor*cor)*sd2]])

        sample = normal_2d.sample(size=10)
        self.assertEqual(np.shape(sample), (10, 2))
        npt.assert_almost_equal(sample, [
                [ 0.4624506 , -0.26705979],
                [ 1.76344545,  5.54913479],
                [-2.76038957,  4.57609973],
                [ 2.35608833,  1.20642031],
                [-2.1218454 ,  5.16796697],
                [-0.85307657, -0.00850715],
                [ 5.28771297, -1.62048489],
                [-2.12592264,  7.1016208 ],
                [-0.46508111,  6.26189296],
                [ 3.15543223, -0.04269231]])
Beispiel #13
0
    def test_empirical_distr(self):
        rnd.random_state(np.random.RandomState(seed=42), force=True)
        
        trivial_empirical_1d = distrs.EmpiricalDistr(particles=[[0.]], weights=[1.])
        self.assertEqual(trivial_empirical_1d.particle_count, 1)
        npt.assert_almost_equal(trivial_empirical_1d.effective_particle_count, 1.)
        self.assertEqual(trivial_empirical_1d.dim, 1)
        npt.assert_almost_equal(trivial_empirical_1d.particles, np.array([[0.]]))
        npt.assert_almost_equal(trivial_empirical_1d.particle(0), np.array([[0.]]))
        npt.assert_almost_equal(trivial_empirical_1d.weights, np.array([[1.]]))
        npt.assert_almost_equal(trivial_empirical_1d.weight(0), 1.)
        npt.assert_almost_equal(trivial_empirical_1d.normalised_weights, np.array([[1.]]))
        npt.assert_almost_equal(trivial_empirical_1d.normalised_weight(0), 1.)
        self.assertEqual(trivial_empirical_1d.weight_sum, 1.)
        self.assertEqual(trivial_empirical_1d.mean, 0.)
        self.assertEqual(trivial_empirical_1d.var_n, 0.)
        npt.assert_almost_equal(trivial_empirical_1d.var_n_minus_1, np.nan)
        self.assertEqual(trivial_empirical_1d.var, 0.)
        self.assertEqual(trivial_empirical_1d.cov_n, 0.)
        npt.assert_almost_equal(trivial_empirical_1d.cov_n_minus_1, np.nan)
        self.assertEqual(trivial_empirical_1d.cov, 0.)
        with self.assertRaises(np.linalg.LinAlgError):  # Matrix is not positive definite
            trivial_empirical_1d.vol_n
        with self.assertRaises(np.linalg.LinAlgError):  # Matrix is not positive definite
            trivial_empirical_1d.vol_n_minus_1
        with self.assertRaises(np.linalg.LinAlgError):  # Matrix is not positive definite
            trivial_empirical_1d.vol

        simple_empirical_1d = distrs.EmpiricalDistr(particles=[[-1.], [1.]], weights=[.5, .5])
        self.assertEqual(simple_empirical_1d.particle_count, 2)
        npt.assert_almost_equal(simple_empirical_1d.effective_particle_count, 2.)
        self.assertEqual(simple_empirical_1d.dim, 1)
        npt.assert_almost_equal(simple_empirical_1d.particles, np.array([[-1.], [1.]]))
        npt.assert_almost_equal(simple_empirical_1d.particle(0), np.array([[-1.]]))
        npt.assert_almost_equal(simple_empirical_1d.weights, np.array([[.5], [.5]]))
        npt.assert_almost_equal(simple_empirical_1d.weight(0), .5)
        npt.assert_almost_equal(simple_empirical_1d.normalised_weights, np.array([[.5], [.5]]))
        npt.assert_almost_equal(simple_empirical_1d.normalised_weight(0), .5)
        self.assertEqual(simple_empirical_1d.weight_sum, 1.)
        self.assertEqual(simple_empirical_1d.mean, 0.)
        self.assertEqual(simple_empirical_1d.var_n, 1.)
        # "n minus 1" (unbiased) stats don't make sense as we are not using "repeat"-type weights, meaning that each
        # weight represents the number of occurrences of one observation:
        npt.assert_almost_equal(simple_empirical_1d.var_n_minus_1, np.inf)
        self.assertEqual(simple_empirical_1d.cov_n, 1.)
        # "n minus 1" (unbiased) stats don't make sense as we are not using "repeat"-type weights, meaning that each
        # weight represents the number of occurrences of one observation:
        npt.assert_almost_equal(simple_empirical_1d.cov_n_minus_1, np.inf)
        self.assertEqual(simple_empirical_1d.cov, 1.)
        self.assertEqual(simple_empirical_1d.vol_n, 1.)
        # "n minus 1" (unbiased) stats don't make sense as we are not using "repeat"-type weights, meaning that each
        # weight represents the number of occurrences of one observation:
        self.assertEqual(simple_empirical_1d.vol_n_minus_1, np.inf)
        self.assertEqual(simple_empirical_1d.vol, 1.)

        # The weights can be specified as a one-dimensional array...
        simple_empirical_1d = distrs.EmpiricalDistr(particles=[[-1.], [1.]], weights=[.5, .5])
        self.assertEqual(simple_empirical_1d.particle_count, 2)
        npt.assert_almost_equal(simple_empirical_1d.effective_particle_count, 2.)
        self.assertEqual(simple_empirical_1d.dim, 1)
        npt.assert_almost_equal(simple_empirical_1d.particles, np.array([[-1.], [1.]]))
        # ...but they come back as a (two-dimensional) column vector:
        npt.assert_almost_equal(simple_empirical_1d.weights, np.array([[.5], [.5]]))

        # ...alternatively, the weights can be specified as a (two-dimensional) column vector:
        simple_empirical_1d = distrs.EmpiricalDistr(particles=[[-1.], [1.]], weights=[[.5], [.5]])
        self.assertEqual(simple_empirical_1d.particle_count, 2)
        npt.assert_almost_equal(simple_empirical_1d.effective_particle_count, 2.)
        self.assertEqual(simple_empirical_1d.dim, 1)
        npt.assert_almost_equal(simple_empirical_1d.particles, np.array([[-1.], [1.]]))
        # ...they always come back as a (two-dimensional) column vector:
        npt.assert_almost_equal(simple_empirical_1d.weights, np.array([[.5], [.5]]))

        # If the particles are specified as a one-dimensional array, they are interpreted as...
        simple_empirical_1d = distrs.EmpiricalDistr(particles=[-1., 1.], weights=[.5, .5])
        self.assertEqual(simple_empirical_1d.particle_count, 2)
        npt.assert_almost_equal(simple_empirical_1d.effective_particle_count, 2.)
        self.assertEqual(simple_empirical_1d.dim, 1)
        # ...multiple one-dimensional particles (each row corresponds to a particle, each column to a dimension):
        npt.assert_almost_equal(simple_empirical_1d.particles, np.array([[-1.], [1.]]))
        npt.assert_almost_equal(simple_empirical_1d.weights, np.array([[.5], [.5]]))

        # Now we shall be using "repeat"-type weights:
        repeat_empirical_1d = distrs.EmpiricalDistr(particles=[[-1.], [1.]], weights=[2., 1.])
        self.assertEqual(repeat_empirical_1d.particle_count, 2)
        npt.assert_almost_equal(repeat_empirical_1d.effective_particle_count, 1.7999999999999998)
        self.assertEqual(repeat_empirical_1d.dim, 1)
        npt.assert_almost_equal(repeat_empirical_1d.particles, np.array([[-1.], [1.]]))
        npt.assert_almost_equal(repeat_empirical_1d.particle(0), np.array([[-1.]]))
        npt.assert_almost_equal(repeat_empirical_1d.weights, np.array([[2.], [1.]]))
        npt.assert_almost_equal(repeat_empirical_1d.weight(0), 2.)
        npt.assert_almost_equal(repeat_empirical_1d.normalised_weights, np.array([[ 0.6666667], [ 0.3333333]]))
        npt.assert_almost_equal(repeat_empirical_1d.normalised_weight(0), 0.6666667)
        self.assertEqual(repeat_empirical_1d.weight_sum, 3.)
        npt.assert_almost_equal(repeat_empirical_1d.mean, -0.33333333)
        npt.assert_almost_equal(repeat_empirical_1d.var_n, 0.88888889)
        npt.assert_almost_equal(repeat_empirical_1d.var_n_minus_1, 1.3333333)
        npt.assert_almost_equal(repeat_empirical_1d.cov_n, 0.88888889)
        npt.assert_almost_equal(repeat_empirical_1d.cov_n_minus_1, 1.3333333)
        npt.assert_almost_equal(repeat_empirical_1d.cov, 0.88888889)
        npt.assert_almost_equal(repeat_empirical_1d.vol_n, 0.94280904)
        npt.assert_almost_equal(repeat_empirical_1d.vol_n_minus_1, 1.15470054)
        npt.assert_almost_equal(repeat_empirical_1d.vol, 0.94280904)

        # Now we shall be using "repeat"-type weights. There are three two-dimensional particles:
        repeat_empirical_2d = distrs.EmpiricalDistr(particles=[[-2., 2.], [0., 0.], [1., -1.]], weights=[2., 1., 1.])
        self.assertEqual(repeat_empirical_2d.particle_count, 3)
        npt.assert_almost_equal(repeat_empirical_2d.effective_particle_count, 2.6666666666666665)
        self.assertEqual(repeat_empirical_2d.dim, 2)
        npt.assert_almost_equal(repeat_empirical_2d.particles, np.array([[-2., 2.], [0., 0.], [1., -1.]]))
        npt.assert_almost_equal(repeat_empirical_2d.particle(0), np.array([[-2.], [2.]]))
        npt.assert_almost_equal(repeat_empirical_2d.weights, np.array([[2.], [1.], [1.]]))
        npt.assert_almost_equal(repeat_empirical_2d.weight(0), 2.)
        npt.assert_almost_equal(repeat_empirical_2d.normalised_weights, np.array([[ 0.5 ], [ 0.25], [ 0.25]]))
        npt.assert_almost_equal(repeat_empirical_2d.normalised_weight(0), .5)
        self.assertEqual(repeat_empirical_2d.weight_sum, 4.)
        npt.assert_almost_equal(repeat_empirical_2d.mean, [[-0.75], [ 0.75]])
        npt.assert_almost_equal(repeat_empirical_2d.var_n, [[ 1.6875], [ 1.6875]])
        npt.assert_almost_equal(repeat_empirical_2d.var_n_minus_1, [[ 2.25], [ 2.25]])
        npt.assert_almost_equal(repeat_empirical_2d.cov_n, [[ 1.6875, -1.6875], [-1.6875,  1.6875]])
        npt.assert_almost_equal(repeat_empirical_2d.cov_n_minus_1, [[ 2.25, -2.25], [-2.25,  2.25]])
        npt.assert_almost_equal(repeat_empirical_2d.cov, [[ 1.6875, -1.6875], [-1.6875,  1.6875]])
        with self.assertRaises(np.linalg.LinAlgError):  # Matrix is not positive definite
            repeat_empirical_2d.vol_n
        with self.assertRaises(np.linalg.LinAlgError):  # Matrix is not positive definite
            repeat_empirical_2d.vol_n_minus_1
        with self.assertRaises(np.linalg.LinAlgError):  # Matrix is not positive definite
            repeat_empirical_2d.vol
        
        normal_distr = distrs.NormalDistr(mean=[10., 100.], cov=[[4., -3.], [-3., 9.]])
        particles = normal_distr.sample(size=100)
        approx_normal_empirical_2d = distrs.EmpiricalDistr(particles=particles, weights=np.ones((100,)))
        self.assertEqual(approx_normal_empirical_2d.particle_count, 100)
        npt.assert_almost_equal(approx_normal_empirical_2d.effective_particle_count, 100.)
        self.assertEqual(approx_normal_empirical_2d.dim, 2)
        npt.assert_almost_equal(approx_normal_empirical_2d.particles, particles)
        npt.assert_almost_equal(approx_normal_empirical_2d.particle(0), npu.col(*particles[0]))
        npt.assert_almost_equal(approx_normal_empirical_2d.weights, npu.col(*np.ones((100,))))
        npt.assert_almost_equal(approx_normal_empirical_2d.weight(0), 1.)
        npt.assert_almost_equal(approx_normal_empirical_2d.normalised_weights, npu.col(*np.ones((100,))) / 100.)
        npt.assert_almost_equal(approx_normal_empirical_2d.normalised_weight(0), .01)
        self.assertEqual(approx_normal_empirical_2d.weight_sum, 100.)
        npt.assert_almost_equal(approx_normal_empirical_2d.mean, [[ 10.2077457], [ 99.6856645]])
        npt.assert_almost_equal(approx_normal_empirical_2d.var_n, [[ 3.3516275], [ 6.7649298]])
        npt.assert_almost_equal(approx_normal_empirical_2d.var_n_minus_1, [[ 3.3854823], [ 6.8332624]])
        npt.assert_almost_equal(approx_normal_empirical_2d.cov_n, [[ 3.3516275, -1.8258307], [-1.8258307,  6.7649298]])
        npt.assert_almost_equal(approx_normal_empirical_2d.cov_n_minus_1, [[ 3.3854823, -1.8442735], [-1.8442735,  6.8332624]])
        npt.assert_almost_equal(approx_normal_empirical_2d.cov, [[ 3.3516275, -1.8258307], [-1.8258307,  6.7649298]])
        npt.assert_almost_equal(approx_normal_empirical_2d.vol_n, [[ 1.8307451,  0.       ], [-0.9973157,  2.4021431]])
        npt.assert_almost_equal(approx_normal_empirical_2d.vol_n_minus_1, [[ 1.839968 ,  0.       ], [-1.00234  ,  2.4142446]])
        npt.assert_almost_equal(approx_normal_empirical_2d.vol, [[ 1.8307451,  0.       ], [-0.9973157,  2.4021431]])

        # Using more particles more faithfully approximates the mean and covariance of the normal distribution:
        normal_distr = distrs.NormalDistr(mean=[10., 100.], cov=[[4., -3.], [-3., 9.]])
        particles = normal_distr.sample(size=100000)
        approx_normal_empirical_2d = distrs.EmpiricalDistr(particles=particles, weights=np.ones((100000,)))
        self.assertEqual(approx_normal_empirical_2d.particle_count, 100000)
        npt.assert_almost_equal(approx_normal_empirical_2d.effective_particle_count, 100000.)
        self.assertEqual(approx_normal_empirical_2d.dim, 2)
        npt.assert_almost_equal(approx_normal_empirical_2d.particles, particles)
        npt.assert_almost_equal(approx_normal_empirical_2d.particle(0), npu.col(*particles[0]))
        npt.assert_almost_equal(approx_normal_empirical_2d.weights, npu.col(*np.ones((100000,))))
        npt.assert_almost_equal(approx_normal_empirical_2d.weight(0), 1.)
        npt.assert_almost_equal(approx_normal_empirical_2d.normalised_weights, npu.col(*np.ones((100000,))) / 100000.)
        npt.assert_almost_equal(approx_normal_empirical_2d.normalised_weight(0), .00001)
        self.assertEqual(approx_normal_empirical_2d.weight_sum, 100000.)
        npt.assert_almost_equal(approx_normal_empirical_2d.mean, [[ 9.9863195], [ 100.0145412]])
        npt.assert_almost_equal(approx_normal_empirical_2d.var_n, [[ 3.9901799], [ 9.0390325]])
        npt.assert_almost_equal(approx_normal_empirical_2d.var_n_minus_1, [[ 3.9902198], [ 9.0391229]])
        npt.assert_almost_equal(approx_normal_empirical_2d.cov_n, [[ 3.9901799, -3.0120428], [-3.0120428,  9.0390325]])
        npt.assert_almost_equal(approx_normal_empirical_2d.cov_n_minus_1, [[ 3.9902198, -3.0120729], [-3.0120729,  9.0391229]])
        npt.assert_almost_equal(approx_normal_empirical_2d.cov, [[ 3.9901799, -3.0120428], [-3.0120428,  9.0390325]])
        npt.assert_almost_equal(approx_normal_empirical_2d.vol_n, [[ 1.9975435,  0.       ], [-1.5078735,  2.6010287]])
        npt.assert_almost_equal(approx_normal_empirical_2d.vol_n_minus_1, [[ 1.9975535,  0.       ], [-1.507881 ,  2.6010417]])
        npt.assert_almost_equal(approx_normal_empirical_2d.vol, [[ 1.9975435,  0.       ], [-1.5078735,  2.6010287]])
Beispiel #14
0
    def test_log_normal_distr(self):
        rnd.random_state(np.random.RandomState(seed=42), force=True)

        std_log_normal_1d = distrs.LogNormalDistr(dim=1)
        npt.assert_almost_equal(std_log_normal_1d.mean, [[ 1.6487213]])
        npt.assert_almost_equal(std_log_normal_1d.cov, [[ 4.6707743]])
        npt.assert_almost_equal(std_log_normal_1d.vol, [[ 2.1611974]])
        
        sample = std_log_normal_1d.sample(size=1)
        self.assertEqual(np.shape(sample), (1, 1))
        npt.assert_almost_equal(sample, [[ 1.6433127]])
        
        sample = std_log_normal_1d.sample(size=10)
        self.assertEqual(np.shape(sample), (10, 1))
        npt.assert_almost_equal(sample, [
                [ 0.87086849],
                [ 1.91111824],
                [ 4.58609939],
                [ 0.79124045],
                [ 0.79125344],
                [ 4.85113557],
                [ 2.15423297],
                [ 0.62533086],
                [ 1.72040554],
                [ 0.62912979]])
        
        std_log_normal_2d = distrs.LogNormalDistr(dim=2)
        npt.assert_almost_equal(std_log_normal_2d.mean, [
                [ 1.6487213],
                [ 1.6487213]])
        npt.assert_almost_equal(std_log_normal_2d.cov, [
                [ 4.6707743,  0.       ],
                [ 0.       ,  4.6707743]])
        npt.assert_almost_equal(std_log_normal_2d.vol, [
                [ 2.1611974,  0.       ],
                [ 0.       ,  2.1611974]])
        
        sample = std_log_normal_2d.sample(size=10)
        self.assertEqual(np.shape(sample), (10, 2))
        npt.assert_almost_equal(sample, [
                [ 0.62767689,  1.27374614],
                [ 0.14759544,  0.17818769],
                [ 0.5699039 ,  0.36318929],
                [ 1.36922835,  0.40332037],
                [ 0.2435815 ,  4.33035173],
                [ 0.79789657,  1.06986043],
                [ 0.24056903,  0.58019982],
                [ 1.11730841,  0.31632232],
                [ 1.45600738,  0.54846123],
                [ 0.74699727,  0.54787583]])

        sd1=.4; sd2=.4; cor=-.5

        log_normal_2d = distrs.LogNormalDistr(mean_of_log=[1., 1.3], cov_of_log=stats.make_cov_2d(sd1=sd1, sd2=sd2, cor=cor))
        npt.assert_almost_equal(log_normal_2d.mean_of_log, npu.col(1., 1.3))
        npt.assert_almost_equal(log_normal_2d.cov_of_log, [[sd1*sd1, cor*sd1*sd2], [cor*sd1*sd2, sd2*sd2]])
        npt.assert_almost_equal(log_normal_2d.vol_of_log, [[sd1, 0.], [cor*sd2, np.sqrt(1.-cor*cor)*sd2]])
        npt.assert_almost_equal(log_normal_2d.mean, [[ 2.9446796], [ 3.9749016]])
        npt.assert_almost_equal(log_normal_2d.cov, [[ 1.5045366, -0.8999087], [-0.8999087,  2.7414445]])
        npt.assert_almost_equal(log_normal_2d.vol, [[ 1.2265956,  0.       ], [-0.7336637,  1.484312 ]])

        sample = log_normal_2d.sample(size=10)
        self.assertEqual(np.shape(sample), (10, 2))
        npt.assert_almost_equal(sample, [
                [ 1.42711164,  6.95143797],
                [ 4.62238496,  2.99848502],
                [ 4.32618186,  2.50643161],
                [ 4.10913455,  1.42691268],
                [ 2.94320341,  4.55346303],
                [ 2.50304159,  3.80468825],
                [ 2.24476532,  2.45957906],
                [ 3.18112082,  2.60781028],
                [ 2.01884543,  5.66848303],
                [ 5.34174201,  2.12565878]])

        log_normal_2d = distrs.LogNormalDistr(mean_of_log=[1., 1.3], vol_of_log=stats.make_vol_2d(sd1=sd1, sd2=sd2, cor=cor))
        npt.assert_almost_equal(log_normal_2d.mean_of_log, npu.col(1., 1.3))
        npt.assert_almost_equal(log_normal_2d.cov_of_log, [[sd1*sd1, cor*sd1*sd2], [cor*sd1*sd2, sd2*sd2]])
        npt.assert_almost_equal(log_normal_2d.vol_of_log, [[sd1, 0.], [cor*sd2, np.sqrt(1.-cor*cor)*sd2]])
        npt.assert_almost_equal(log_normal_2d.mean, npu.col(2.9446796, 3.9749016))
        npt.assert_almost_equal(log_normal_2d.cov, [[ 1.5045366, -0.8999087], [-0.8999087,  2.7414445]])
        npt.assert_almost_equal(log_normal_2d.vol, [[ 1.2265956,  0.       ], [-0.7336637,  1.484312 ]])

        sample = log_normal_2d.sample(size=10)
        self.assertEqual(np.shape(sample), (10, 2))
        npt.assert_almost_equal(sample, [
                [ 2.71288329,  2.80448293],
                [ 2.70285608,  5.57387658],
                [ 1.66454464,  4.28346127],
                [ 3.23285936,  3.52238521],
                [ 1.76160691,  4.67441442],
                [ 2.32343609,  2.75776026],
                [ 4.8398479 ,  2.85230385],
                [ 1.67494888,  5.78583855],
                [ 2.06409776,  5.58431178],
                [ 3.6537541 ,  3.15441508]])
Beispiel #15
0
    def test_xtimes_random_step(self):
        rnd.random_state(np.random.RandomState(seed=42), force=True)

        npt.assert_almost_equal(
            list(sim.xtimes(-5., 5., step=lambda x: rnd.exponential(2.5))),
            [-5., -3.8268298, 3.6984738])
        npt.assert_almost_equal(
            list(sim.xtimes(-5., 5., step=lambda x: rnd.exponential(3.25))), [
                -5.0, -4.448719170997375, -3.897531222274908,
                -3.703055224296696, 2.833445085263108
            ])
        npt.assert_almost_equal(
            list(sim.xtimes(5., -5., step=lambda x: -rnd.exponential(2.5))),
            [5.0, 4.9480017300021535, -3.8108919578936264])
        npt.assert_almost_equal(
            list(sim.xtimes(5., -5., step=lambda x: -rnd.exponential(3.25))), [
                5.0, 4.347793286563594, 3.689306162358759, 2.5103565416122082,
                0.09259109131443122, -1.7454043757216628, -2.8641291015219728
            ])

        self.assertEqual(
            list(
                sim.xtimes(dt.datetime(2017, 5, 5), dt.datetime(2017, 5, 10),
                           lambda x: rnd.exponential(dt.timedelta(days=1)))), [
                               dt.datetime(2017, 5, 5),
                               dt.datetime(2017, 5, 5, 8, 17, 32, 540237),
                               dt.datetime(2017, 5, 5, 19, 14, 34, 891891),
                               dt.datetime(2017, 5, 6, 9, 51, 26, 848922),
                               dt.datetime(2017, 5, 7, 22, 46, 4, 520275),
                               dt.datetime(2017, 5, 8, 4, 6, 48, 898763),
                               dt.datetime(2017, 5, 8, 21, 26, 32, 217758),
                               dt.datetime(2017, 5, 9, 18, 58, 56, 625679),
                               dt.datetime(2017, 5, 9, 20, 7, 26, 142298)
                           ])
        self.assertEqual(
            list(
                sim.xtimes(dt.datetime(2017, 5, 10), dt.datetime(2017, 5, 5),
                           lambda x: -rnd.exponential(dt.timedelta(days=1)))),
            [
                dt.datetime(2017, 5, 10),
                dt.datetime(2017, 5, 9, 22, 23, 8, 396372),
                dt.datetime(2017, 5, 6, 23, 1, 1, 771013)
            ])
        self.assertEqual(
            list(
                sim.xtimes(
                    dt.datetime(2017, 5, 5, 8), dt.datetime(2017, 5, 5, 12),
                    lambda x: rnd.exponential(dt.timedelta(minutes=30)))), [
                        dt.datetime(2017, 5, 5, 8),
                        dt.datetime(2017, 5, 5, 8, 10, 53, 918148),
                        dt.datetime(2017, 5, 5, 8, 13, 58, 917315),
                        dt.datetime(2017, 5, 5, 8, 48, 33, 868689),
                        dt.datetime(2017, 5, 5, 9, 5, 58, 32206),
                        dt.datetime(2017, 5, 5, 9, 9, 52, 306227),
                        dt.datetime(2017, 5, 5, 9, 30, 22, 691238),
                        dt.datetime(2017, 5, 5, 9, 31, 25, 679937),
                        dt.datetime(2017, 5, 5, 10, 43, 26, 441134),
                        dt.datetime(2017, 5, 5, 10, 52, 25, 465132),
                        dt.datetime(2017, 5, 5, 11, 25, 0, 725569),
                        dt.datetime(2017, 5, 5, 11, 36, 13, 109416),
                        dt.datetime(2017, 5, 5, 11, 58, 14, 509029)
                    ])
        self.assertEqual(
            list(
                sim.xtimes(
                    dt.datetime(2017, 5, 5, 12), dt.datetime(2017, 5, 5, 8),
                    lambda x: -rnd.exponential(dt.timedelta(minutes=30)))), [
                        dt.datetime(2017, 5, 5, 12),
                        dt.datetime(2017, 5, 5, 10, 15, 12, 947161),
                        dt.datetime(2017, 5, 5, 9, 30, 26, 905482),
                        dt.datetime(2017, 5, 5, 8, 6, 17, 735527)
                    ])
        self.assertEqual(
            list(
                sim.xtimes(
                    dt.datetime(2017, 5, 5,
                                8), dt.datetime(2017, 5, 5, 8, 0, 1), lambda x:
                    rnd.exponential(dt.timedelta(milliseconds=100)))), [
                        dt.datetime(2017, 5, 5, 8),
                        dt.datetime(2017, 5, 5, 8, 0, 0, 254944),
                        dt.datetime(2017, 5, 5, 8, 0, 0, 264210),
                        dt.datetime(2017, 5, 5, 8, 0, 0, 286023),
                        dt.datetime(2017, 5, 5, 8, 0, 0, 290651),
                        dt.datetime(2017, 5, 5, 8, 0, 0, 330004),
                        dt.datetime(2017, 5, 5, 8, 0, 0, 379217),
                        dt.datetime(2017, 5, 5, 8, 0, 0, 410873),
                        dt.datetime(2017, 5, 5, 8, 0, 0, 587329),
                        dt.datetime(2017, 5, 5, 8, 0, 0, 631452),
                        dt.datetime(2017, 5, 5, 8, 0, 0, 664432),
                        dt.datetime(2017, 5, 5, 8, 0, 0, 742673),
                        dt.datetime(2017, 5, 5, 8, 0, 0, 757863),
                        dt.datetime(2017, 5, 5, 8, 0, 0, 919911),
                        dt.datetime(2017, 5, 5, 8, 0, 0, 927659)
                    ])

        self.assertEqual(
            list(
                sim.xtimes(dt.date(2017, 5, 5), dt.date(2017, 5, 10),
                           lambda x: rnd.exponential(dt.timedelta(days=1)))), [
                               dt.date(2017, 5, 5),
                               dt.date(2017, 5, 5),
                               dt.date(2017, 5, 5),
                               dt.date(2017, 5, 6),
                               dt.date(2017, 5, 7),
                               dt.date(2017, 5, 8),
                               dt.date(2017, 5, 9),
                               dt.date(2017, 5, 9),
                               dt.date(2017, 5, 9),
                               dt.date(2017, 5, 9)
                           ])
        self.assertEqual(
            list(
                sim.xtimes(dt.date(2017, 5, 10), dt.date(2017, 5, 5),
                           lambda x: -rnd.exponential(dt.timedelta(days=1)))),
            [
                dt.date(2017, 5, 10),
                dt.date(2017, 5, 9),
                dt.date(2017, 5, 8),
                dt.date(2017, 5, 7),
                dt.date(2017, 5, 6)
            ])

        self.assertEqual(
            list(
                sim.xtimes(
                    dt.time(8), dt.time(12),
                    lambda x: rnd.exponential(dt.timedelta(minutes=30)))), [
                        dt.time(8),
                        dt.time(9, 5, 28, 53442),
                        dt.time(9, 24, 38, 372482),
                        dt.time(9, 28, 27, 642791),
                        dt.time(10, 5, 56, 70211),
                        dt.time(10, 48, 50, 777167),
                        dt.time(11, 13, 33, 774658),
                        dt.time(11, 57, 46, 776598)
                    ])
        self.assertEqual(
            list(
                sim.xtimes(
                    dt.time(12), dt.time(8),
                    lambda x: -rnd.exponential(dt.timedelta(minutes=30)))), [
                        dt.time(12),
                        dt.time(11, 43, 15, 934451),
                        dt.time(11, 42, 29, 588458),
                        dt.time(11, 39, 4, 87075),
                        dt.time(11, 38, 6, 606449),
                        dt.time(11, 7, 45, 493257),
                        dt.time(10, 56, 26, 179181),
                        dt.time(10, 35, 7, 392262),
                        dt.time(9, 23, 41, 114308),
                        dt.time(9, 15, 4, 984427),
                        dt.time(8, 59, 14, 76872),
                        dt.time(8, 16, 58, 328406),
                        dt.time(8, 9, 10, 679124),
                        dt.time(8, 6, 46, 491423)
                    ])

        # Since end is set to None, we have a potentially infinite iteration
        ts = sim.xtimes(dt.datetime(2017, 5, 10), None,
                        lambda x: rnd.exponential(dt.timedelta(days=1)))
        self.assertEqual(dt.datetime(2017, 5, 10), next(ts))
        self.assertEqual(dt.datetime(2017, 5, 12, 15, 43, 7, 687420), next(ts))
        self.assertEqual(dt.datetime(2017, 5, 14, 7, 20, 24, 331174), next(ts))
        ts = sim.xtimes(dt.date(2017, 5, 10), None,
                        lambda x: -rnd.exponential(dt.timedelta(days=1)))
        self.assertEqual(dt.date(2017, 5, 10), next(ts))
        self.assertEqual(dt.date(2017, 5, 7), next(ts))
        self.assertEqual(dt.date(2017, 5, 5), next(ts))