""" Created on Fri Feb 12 10:42:00 2021 Author: Josef Perktold License: BSD-3 """ import numpy as np from numpy.testing import assert_allclose, assert_equal from scipy import stats import statsmodels.distributions.tools as dt def test_grid(): # test bivariate independent beta k1, k2 = 3, 5 xg1 = np.arange(k1) / (k1 - 1) xg2 = np.arange(k2) / (k2 - 1) # histogram values for distribution distr1 = stats.beta(2, 5) distr2 = stats.beta(4, 3) cdf1 = distr1.cdf(xg1) cdf2 = distr2.cdf(xg2) prob1 = np.diff(cdf1, prepend=0) prob2 = np.diff(cdf2, prepend=0) cd2d = cdf1[:, None] * cdf2 pd2d = prob1[:, None] * prob2 probs = dt.cdf2prob_grid(cd2d) cdfs = dt.prob2cdf_grid(pd2d) assert_allclose(cdfs, cd2d, atol=1e-12) assert_allclose(probs, pd2d, atol=1e-12) # check random sample nobs = 1000 np.random.seed(789123) rvs = np.column_stack([distr1.rvs(size=nobs), distr2.rvs(size=nobs)]) hist = np.histogramdd(rvs, [xg1, xg2]) assert_allclose(probs[1:, 1:], hist[0] / len(rvs), atol=0.02) def test_average_grid(): x1 = np.arange(1, 4) x2 = np.arange(4) y = x1[:, None] * x2 res1 = np.array([[0.75, 2.25, 3.75], [1.25, 3.75, 6.25]]) res0 = dt.average_grid(y, coords=[x1, x2]) assert_allclose(res0, res1, rtol=1e-13) res0 = dt.average_grid(y, coords=[x1, x2], _method="slicing") assert_allclose(res0, res1, rtol=1e-13) res0 = dt.average_grid(y, coords=[x1, x2], _method="convolve") assert_allclose(res0, res1, rtol=1e-13) res0 = dt.average_grid(y, coords=[x1 / x1.max(), x2 / x2.max()]) assert_allclose(res0, res1 / x1.max() / x2.max(), rtol=1e-13) res0 = dt.average_grid(y, coords=[x1 / x1.max(), x2 / x2.max()], _method="convolve") assert_allclose(res0, res1 / x1.max() / x2.max(), rtol=1e-13) def test_grid_class(): res = {'k_grid': [3, 5], 'x_marginal': [np.array([0., 0.5, 1.]), np.array([0., 0.25, 0.5, 0.75, 1.])], 'idx_flat.T': np.array([ [0., 0., 0., 0., 0., 1., 1., 1., 1., 1., 2., 2., 2., 2., 2.], [0., 1., 2., 3., 4., 0., 1., 2., 3., 4., 0., 1., 2., 3., 4.]]) } gg = dt._Grid([3, 5]) assert_equal(gg.k_grid, res["k_grid"]) assert gg.x_marginal, res["x_marginal"] assert_allclose(gg.idx_flat, res["idx_flat.T"].T, atol=1e-12) assert_allclose(gg.x_flat, res["idx_flat.T"].T / [2, 4], atol=1e-12) gg = dt._Grid([3, 5], eps=0.001) assert_allclose(gg.x_flat.min(), 0.001, atol=1e-12) assert_allclose(gg.x_flat.max(), 0.999, atol=1e-12) xmf = np.concatenate(gg.x_marginal) assert_allclose(xmf.min(), 0.001, atol=1e-12) assert_allclose(xmf.max(), 0.999, atol=1e-12) # 1-dim gg = dt._Grid([5], eps=0.001) res = {'k_grid': [5], 'x_marginal': [np.array([0.001, 0.25, 0.5, 0.75, 0.999])], 'idx_flat.T': np.array([[0., 1., 2., 3., 4.]]) } assert_equal(gg.k_grid, res["k_grid"]) assert gg.x_marginal, res["x_marginal"] assert_allclose(gg.idx_flat, res["idx_flat.T"].T, atol=1e-12) # x_flat is 2-dim even if grid is 1-dim, TODO: maybe change assert_allclose(gg.x_flat, res["x_marginal"][0][:, None], atol=1e-12) # 3-dim gg = dt._Grid([3, 3, 2], eps=0.) res = {'k_grid': [3, 3, 2], 'x_marginal': [np.array([0., 0.5, 1.]), np.array([0., 0.5, 1.]), np.array([0., 1.])], 'idx_flat.T': np.array([ [0., 0., 0., 0., 0., 0., 1., 1., 1., 1., 1., 1., 2., 2., 2., 2., 2., 2.], [0., 0., 1., 1., 2., 2., 0., 0., 1., 1., 2., 2., 0., 0., 1., 1., 2., 2.], [0., 1., 0., 1., 0., 1., 0., 1., 0., 1., 0., 1., 0., 1., 0., 1., 0., 1.]]) } assert_equal(gg.k_grid, res["k_grid"]) assert gg.x_marginal, res["x_marginal"] assert_allclose(gg.idx_flat, res["idx_flat.T"].T, atol=1e-12) assert_allclose(gg.x_flat, res["idx_flat.T"].T / [2, 2, 1], atol=1e-12) def test_bernstein_1d(): k = 5 xg1 = np.arange(k) / (k - 1) xg2 = np.arange(2 * k) / (2 * k - 1) # verify linear coefficients are mapped to themselves res_bp = dt._eval_bernstein_1d(xg2, xg1) assert_allclose(res_bp, xg2, atol=1e-12) res_bp = dt._eval_bernstein_1d(xg2, xg1, method="beta") assert_allclose(res_bp, xg2, atol=1e-12) res_bp = dt._eval_bernstein_1d(xg2, xg1, method="bpoly") assert_allclose(res_bp, xg2, atol=1e-12) def test_bernstein_2d(): k = 5 xg1 = np.arange(k) / (k - 1) cd2d = xg1[:, None] * xg1 # verify linear coefficients are mapped to themselves for evalbp in (dt._eval_bernstein_2d, dt._eval_bernstein_dd): k_x = 2 * k # create flattened grid of bivariate values x2d = np.column_stack( np.unravel_index(np.arange(k_x * k_x), (k_x, k_x)) ).astype(float) x2d /= x2d.max(0) res_bp = evalbp(x2d, cd2d) assert_allclose(res_bp, np.prod(x2d, axis=1), atol=1e-12) # check univariate margins x2d = np.column_stack((np.arange(k_x) / (k_x - 1), np.ones(k_x))) res_bp = evalbp(x2d, cd2d) assert_allclose(res_bp, x2d[:, 0], atol=1e-12) # check univariate margins x2d = np.column_stack((np.ones(k_x), np.arange(k_x) / (k_x - 1))) res_bp = evalbp(x2d, cd2d) assert_allclose(res_bp, x2d[:, 1], atol=1e-12)