def test_mixture_ppf_adversarial(): # Make a mixture with one very improbable distribution and one dominant mixture = LogisticMixture( [Logistic(10, 3), Logistic(5, 5)], [1.8629593e-29, 1.0]) assert mixture.ppf(0.5) == pytest.approx(5.0, rel=1e-3) assert mixture.ppf(0.01) == pytest.approx(-17.9755, rel=1e-3) assert mixture.ppf(0.001) == pytest.approx(-29.5337, rel=1e-3) assert mixture.ppf(0.99) == pytest.approx(27.9755, rel=1e-3) assert mixture.ppf(0.999) == pytest.approx(39.5337, rel=1e-3)
def test_mixture_ppf_adversarial(): # Make a mixture with one very improbable distribution and one dominant mixture = LogisticMixture([Logistic(10, 3), Logistic(5, 5)], [1.8629593e-29, 1.0]) assert mixture.ppf(0.5) == pytest.approx(5.0, rel=1e-3) assert mixture.ppf(0.01) == pytest.approx(-17.9755, rel=1e-3) assert mixture.ppf(0.001) == pytest.approx(-29.5337, rel=1e-3) assert mixture.ppf(0.99) == pytest.approx(27.9755, rel=1e-3) assert mixture.ppf(0.999) == pytest.approx(39.5337, rel=1e-3) # Make a mixture with hugely overlapping distributions mixture = LogisticMixture( [ Logistic(4000000.035555004, 200000.02), Logistic(4000000.0329152746, 200000.0), ], [0.5, 0.5], ) assert mixture.ppf(0.5) == pytest.approx(4000000.0342351394, rel=1e-3) assert mixture.ppf(0.01) == pytest.approx(3080976.018257023, rel=1e-3) assert mixture.ppf(0.001) == pytest.approx(2618649.009437881, rel=1e-3) assert mixture.ppf(0.99) == pytest.approx(4919024.050213255, rel=1e-3) assert mixture.ppf(0.999) == pytest.approx(5381351.059032397, rel=1e-3)
def test_truncated_ppf(xscale: Scale): normed_test_loc = 0.5 normed_test_s = 0.1 test_loc = xscale.denormalize_point(normed_test_loc) test_s = normed_test_s * xscale.width normed_baseline_dist = scipy.stats.logistic(normed_test_loc, normed_test_s) def ppf_through_cdf(dist, q): return scipy.optimize.bisect(lambda x: dist.cdf(x) - q, dist.ppf(0.0001), dist.ppf(0.9999), maxiter=1000) # No bounds dist_w_no_bounds = Truncate(Logistic(loc=test_loc, s=test_s, scale=xscale)) for x in np.linspace(0.01, 0.99, 8): assert dist_w_no_bounds.ppf(x) == pytest.approx(float( xscale.denormalize_point(normed_baseline_dist.ppf(x))), rel=0.001) # Floor dist_w_floor = Truncate( Logistic(loc=test_loc, s=test_s, scale=xscale), floor=xscale.denormalize_point(0.5), ) mix_w_floor = LogisticMixture( components=[ Truncate( # type: ignore Logistic(test_loc, s=test_s, scale=xscale), floor=xscale.denormalize_point(0.5), ) ], probs=[1.0], ) for x in np.linspace(0.01, 0.99, 8): assert dist_w_floor.ppf(x) == pytest.approx(float(mix_w_floor.ppf(x)), rel=0.001) assert dist_w_floor.ppf(x) == pytest.approx(float( ppf_through_cdf(dist_w_floor, x)), rel=0.001) # Ceiling dist_w_ceiling = Truncate( Logistic(loc=test_loc, s=test_s, scale=xscale), ceiling=xscale.denormalize_point(0.8), ) mix_w_ceiling = LogisticMixture( components=[ Truncate( # type: ignore Logistic(test_loc, s=test_s, scale=xscale), ceiling=xscale.denormalize_point(0.8), ) ], probs=[1.0], ) for x in np.linspace(0.01, 0.99, 8): assert dist_w_ceiling.ppf(x) == pytest.approx(float( mix_w_ceiling.ppf(x)), rel=0.001) assert dist_w_ceiling.ppf(x) == pytest.approx(float( ppf_through_cdf(dist_w_ceiling, x)), rel=0.001) # Floor and Ceiling dist_w_floor_and_ceiling = Truncate( Logistic(loc=test_loc, s=test_s, scale=xscale), floor=xscale.denormalize_point(0.2), ceiling=xscale.denormalize_point(0.8), ) mix_w_floor_and_ceiling = LogisticMixture( components=[ Truncate( # type: ignore Logistic(test_loc, s=test_s, scale=xscale), floor=xscale.denormalize_point(0.2), ceiling=xscale.denormalize_point(0.8), ) ], probs=[1.0], ) for x in np.linspace(0.01, 0.99, 8): assert dist_w_floor_and_ceiling.ppf(x) == pytest.approx(float( mix_w_floor_and_ceiling.ppf(x)), rel=0.001) assert dist_w_floor_and_ceiling.ppf(x) == pytest.approx(float( ppf_through_cdf(dist_w_floor_and_ceiling, x)), rel=0.001)