Example #1
0
    def sample(self, num, d=1, rng=np.random, ntm=Sobol()):
        if d == 1:
            return super(ScatteredHypersphere, self).sample(num, d, rng)

        if self.surface:
            cube = ntm.sample(num, d-1)
            radius = 1.0
        else:
            dcube = ntm.sample(num, d)
            cube, radius = dcube[:, :-1], dcube[:, -1:] ** (1.0 / d)

        # inverse transform method (section 1.5.2)
        for j in range(d-1):
            cube[:, j] = SphericalCoords(d-1-j).ppf(cube[:, j])

        # spherical coordinate transform
        mapped = np.ones((num, d))
        i = np.ones(d-1)
        i[-1] = 2.0
        s = np.sin(i[None, :] * np.pi * cube)
        c = np.cos(i[None, :] * np.pi * cube)
        mapped[:, 1:] = np.cumprod(s, axis=1)
        mapped[:, :-1] *= c

        # radius adjustment for ball versus sphere, and rotate
        rotation = random_orthogonal(d, rng=rng)
        return np.dot(mapped * radius, rotation)