def test_discrepancy_hierarchy(self): seed = 68756348576543 lhs = qmc.LatinHypercube(d=2, seed=seed) sample_ref = lhs.random(n=20) disc_ref = qmc.discrepancy(sample_ref) optimal_ = qmc.LatinHypercube(d=2, seed=seed, optimization="random-CD") sample_ = optimal_.random(n=20) disc_ = qmc.discrepancy(sample_) assert disc_ < disc_ref
def test_discrepancy_hierarchy(self): seed = np.random.RandomState(123456) lhs = qmc.LatinHypercube(d=2, seed=seed) sample_ref = lhs.random(n=20) disc_ref = qmc.discrepancy(sample_ref) seed = np.random.RandomState(123456) optimal_ = qmc.LatinHypercube(d=2, seed=seed, optimization="random-CD") sample_ = optimal_.random(n=20) disc_ = qmc.discrepancy(sample_) assert disc_ < disc_ref
def test_discrepancy_parallel(self, monkeypatch): sample = np.array([[2, 1, 1, 2, 2, 2], [1, 2, 2, 2, 2, 2], [2, 1, 1, 1, 1, 1], [1, 1, 1, 1, 2, 2], [1, 2, 2, 2, 1, 1], [2, 2, 2, 2, 1, 1], [2, 2, 2, 1, 2, 2]]) sample = (2.0 * sample - 1.0) / (2.0 * 2.0) assert_allclose(qmc.discrepancy(sample, method='MD', workers=8), 2.5000, atol=1e-4) assert_allclose(qmc.discrepancy(sample, method='WD', workers=8), 1.3680, atol=1e-4) assert_allclose(qmc.discrepancy(sample, method='CD', workers=8), 0.3172, atol=1e-4) # From Tim P. et al. Minimizing the L2 and Linf star discrepancies # of a single point in the unit hypercube. JCAM, 2005 # Table 1 on Page 283 for dim in [2, 4, 8, 16, 32, 64]: ref = np.sqrt(3 ** (-dim)) assert_allclose(qmc.discrepancy(np.array([[1] * dim]), method='L2-star', workers=-1), ref) monkeypatch.setattr(os, 'cpu_count', lambda: None) with pytest.raises(NotImplementedError, match="Cannot determine the"): qmc.discrepancy(sample, workers=-1) with pytest.raises(ValueError, match="Invalid number of workers..."): qmc.discrepancy(sample, workers=-2)
def test_perm_discrepancy(self): rng = np.random.default_rng(46449423132557934943847369749645759997) qmc_gen = qmc.LatinHypercube(5, seed=rng) sample = qmc_gen.random(10) disc = qmc.discrepancy(sample) for i in range(100): row_1 = rng.integers(10) row_2 = rng.integers(10) col = rng.integers(5) disc = _perturb_discrepancy(sample, row_1, row_2, col, disc) sample[row_1, col], sample[row_2, col] = ( sample[row_2, col], sample[row_1, col]) disc_reference = qmc.discrepancy(sample) assert_allclose(disc, disc_reference)
def test_update_discrepancy(self): space_1 = np.array([[1, 3], [2, 6], [3, 2], [4, 5], [5, 1], [6, 4]]) space_1 = (2.0 * space_1 - 1.0) / (2.0 * 6.0) disc_init = qmc.discrepancy(space_1[:-1], iterative=True) disc_iter = update_discrepancy(space_1[-1], space_1[:-1], disc_init) assert_allclose(disc_iter, 0.0081, atol=1e-4) # errors with pytest.raises(ValueError, match=r"Sample is not in unit " r"hypercube"): update_discrepancy(space_1[-1], space_1[:-1] + 1, disc_init) with pytest.raises(ValueError, match=r"Sample is not a 2D array"): update_discrepancy(space_1[-1], space_1[0], disc_init) x_new = [1, 3] with pytest.raises(ValueError, match=r"x_new is not in unit " r"hypercube"): update_discrepancy(x_new, space_1[:-1], disc_init) x_new = [[0.5, 0.5]] with pytest.raises(ValueError, match=r"x_new is not a 1D array"): update_discrepancy(x_new, space_1[:-1], disc_init) x_new = [0.3, 0.1, 0] with pytest.raises(ValueError, match=r"x_new and sample must be " r"broadcastable"): update_discrepancy(x_new, space_1[:-1], disc_init)
def test_perm_discrepancy(self): seed = np.random.RandomState(123456) qmc_gen = qmc.LatinHypercube(5, seed=seed) sample = qmc_gen.random(10) disc = qmc.discrepancy(sample) for i in range(100): row_1 = np.random.randint(10) row_2 = np.random.randint(10) col = np.random.randint(5) disc = _perturb_discrepancy(sample, row_1, row_2, col, disc) sample[row_1, col], sample[row_2, col] = (sample[row_2, col], sample[row_1, col]) disc_reference = qmc.discrepancy(sample) assert_allclose(disc, disc_reference)
def test_update_discrepancy(self): # From Fang et al. Design and modeling for computer experiments, 2006 space_1 = np.array([[1, 3], [2, 6], [3, 2], [4, 5], [5, 1], [6, 4]]) space_1 = (2.0 * space_1 - 1.0) / (2.0 * 6.0) disc_init = qmc.discrepancy(space_1[:-1], iterative=True) disc_iter = update_discrepancy(space_1[-1], space_1[:-1], disc_init) assert_allclose(disc_iter, 0.0081, atol=1e-4) # n<d rng = np.random.default_rng(241557431858162136881731220526394276199) space_1 = rng.random((4, 10)) disc_ref = qmc.discrepancy(space_1) disc_init = qmc.discrepancy(space_1[:-1], iterative=True) disc_iter = update_discrepancy(space_1[-1], space_1[:-1], disc_init) assert_allclose(disc_iter, disc_ref, atol=1e-4) # errors with pytest.raises(ValueError, match=r"Sample is not in unit " r"hypercube"): update_discrepancy(space_1[-1], space_1[:-1] + 1, disc_init) with pytest.raises(ValueError, match=r"Sample is not a 2D array"): update_discrepancy(space_1[-1], space_1[0], disc_init) x_new = [1, 3] with pytest.raises(ValueError, match=r"x_new is not in unit " r"hypercube"): update_discrepancy(x_new, space_1[:-1], disc_init) x_new = [[0.5, 0.5]] with pytest.raises(ValueError, match=r"x_new is not a 1D array"): update_discrepancy(x_new, space_1[:-1], disc_init) x_new = [0.3, 0.1, 0] with pytest.raises(ValueError, match=r"x_new and sample must be " r"broadcastable"): update_discrepancy(x_new, space_1[:-1], disc_init)
def test_discrepancy_errors(self): sample = np.array([[1, 3], [2, 6], [3, 2], [4, 5], [5, 1], [6, 4]]) with pytest.raises(ValueError, match=r"Sample is not in unit hypercube"): qmc.discrepancy(sample) with pytest.raises(ValueError, match=r"Sample is not a 2D array"): qmc.discrepancy([1, 3]) sample = [[0, 0], [1, 1], [0.5, 0.5]] with pytest.raises(ValueError, match=r"'toto' is not a valid ..."): qmc.discrepancy(sample, method="toto")
def test_discrepancy(self): space_1 = np.array([[1, 3], [2, 6], [3, 2], [4, 5], [5, 1], [6, 4]]) space_1 = (2.0 * space_1 - 1.0) / (2.0 * 6.0) space_2 = np.array([[1, 5], [2, 4], [3, 3], [4, 2], [5, 1], [6, 6]]) space_2 = (2.0 * space_2 - 1.0) / (2.0 * 6.0) # From Fang et al. Design and modeling for computer experiments, 2006 assert_allclose(qmc.discrepancy(space_1), 0.0081, atol=1e-4) assert_allclose(qmc.discrepancy(space_2), 0.0105, atol=1e-4) # From Zhou Y.-D. et al. Mixture discrepancy for quasi-random point # sets. Journal of Complexity, 29 (3-4), pp. 283-301, 2013. # Example 4 on Page 298 sample = np.array([[2, 1, 1, 2, 2, 2], [1, 2, 2, 2, 2, 2], [2, 1, 1, 1, 1, 1], [1, 1, 1, 1, 2, 2], [1, 2, 2, 2, 1, 1], [2, 2, 2, 2, 1, 1], [2, 2, 2, 1, 2, 2]]) sample = (2.0 * sample - 1.0) / (2.0 * 2.0) assert_allclose(qmc.discrepancy(sample, method='MD'), 2.5000, atol=1e-4) assert_allclose(qmc.discrepancy(sample, method='WD'), 1.3680, atol=1e-4) assert_allclose(qmc.discrepancy(sample, method='CD'), 0.3172, atol=1e-4) # From Tim P. et al. Minimizing the L2 and Linf star discrepancies # of a single point in the unit hypercube. JCAM, 2005 # Table 1 on Page 283 for dim in [2, 4, 8, 16, 32, 64]: ref = np.sqrt(3**(-dim)) assert_allclose(qmc.discrepancy(np.array([[1]*dim]), method='L2-star'), ref)
def test_discrepancy_alternative_implementation(self): """Alternative definitions from Matt Haberland.""" def disc_c2(x): n, s = x.shape xij = x disc1 = np.sum(np.prod((1 + 1/2*np.abs(xij-0.5) - 1/2*np.abs(xij-0.5)**2), axis=1)) xij = x[None, :, :] xkj = x[:, None, :] disc2 = np.sum(np.sum(np.prod(1 + 1/2*np.abs(xij - 0.5) + 1/2*np.abs(xkj - 0.5) - 1/2*np.abs(xij - xkj), axis=2), axis=0)) return (13/12)**s - 2/n * disc1 + 1/n**2*disc2 def disc_wd(x): n, s = x.shape xij = x[None, :, :] xkj = x[:, None, :] disc = np.sum(np.sum(np.prod(3/2 - np.abs(xij - xkj) + np.abs(xij - xkj)**2, axis=2), axis=0)) return -(4/3)**s + 1/n**2 * disc def disc_md(x): n, s = x.shape xij = x disc1 = np.sum(np.prod((5/3 - 1/4*np.abs(xij-0.5) - 1/4*np.abs(xij-0.5)**2), axis=1)) xij = x[None, :, :] xkj = x[:, None, :] disc2 = np.sum(np.sum(np.prod(15/8 - 1/4*np.abs(xij - 0.5) - 1/4*np.abs(xkj - 0.5) - 3/4*np.abs(xij - xkj) + 1/2*np.abs(xij - xkj)**2, axis=2), axis=0)) return (19/12)**s - 2/n * disc1 + 1/n**2*disc2 def disc_star_l2(x): n, s = x.shape return np.sqrt( 3 ** (-s) - 2 ** (1 - s) / n * np.sum(np.prod(1 - x ** 2, axis=1)) + np.sum([ np.prod(1 - np.maximum(x[k, :], x[j, :])) for k in range(n) for j in range(n) ]) / n ** 2 ) rng = np.random.default_rng(117065081482921065782761407107747179201) sample = rng.random((30, 10)) disc_curr = qmc.discrepancy(sample, method='CD') disc_alt = disc_c2(sample) assert_allclose(disc_curr, disc_alt) disc_curr = qmc.discrepancy(sample, method='WD') disc_alt = disc_wd(sample) assert_allclose(disc_curr, disc_alt) disc_curr = qmc.discrepancy(sample, method='MD') disc_alt = disc_md(sample) assert_allclose(disc_curr, disc_alt) disc_curr = qmc.discrepancy(sample, method='L2-star') disc_alt = disc_star_l2(sample) assert_allclose(disc_curr, disc_alt)