def test_logpdf_mixture_real_continuous_discrete(): spe = X >> (.3*norm() | .7*poisson(mu=1)) assert allclose( spe.logpdf(X << {.5}), logsumexp([ log(.3) + spe.children[0].logpdf({X: 0.5}), log(.7) + spe.children[1].logpdf({X: 0.5}), ])) assert False, 'Invalid base measure addition'
def test_simple_parse_real(): assert isinstance(.3 * bernoulli(p=.1), DistributionMix) a = .3 * bernoulli(p=.1) | .5 * norm() | .2 * poisson(mu=7) spe = a(X) assert isinstance(spe, SumSPE) assert allclose(spe.weights, [log(.3), log(.5), log(.2)]) assert isinstance(spe.children[0], DiscreteLeaf) assert isinstance(spe.children[1], ContinuousLeaf) assert isinstance(spe.children[2], DiscreteLeaf) assert spe.children[0].support == Interval(0, 1) assert spe.children[1].support == Interval(-oo, oo) assert spe.children[2].support == Interval(0, oo)
def test_transform_real_leaf_sample(): X = Id('X') Z = Id('Z') Y = Id('Y') spe = (X >> poisson(loc=-1, mu=1)) spe = spe.transform(Z, X+1) spe = spe.transform(Y, Z-1) samples = spe.sample(100) assert any(s[X] == -1 for s in samples) assert all(0 <= s[Z] for s in samples) assert all(s[Y] == s[X] for s in samples) assert all(spe.sample_func(lambda X,Y,Z: X-Y+Z==Z, 100)) assert all(set(s) == {X,Y} for s in spe.sample_subset([X, Y], 100))
def test_condition_non_contiguous(): X = Id('X') spe = X >> poisson(mu=5) # FiniteSet. for c in [{0, 2, 3}, {-1, 0, 2, 3}, {-1, 0, 2, 3, 'z'}]: spe_condition = spe.condition((X << c)) assert isinstance(spe_condition, SumSPE) assert allclose(0, spe_condition.children[0].logprob(X << {0})) assert allclose(0, spe_condition.children[1].logprob(X << {2, 3})) # FiniteSet or Interval. spe_condition = spe.condition((X << {-1, 'x', 0, 2, 3}) | (X > 7)) assert isinstance(spe_condition, SumSPE) assert len(spe_condition.children) == 3 assert allclose(0, spe_condition.children[0].logprob(X << {0})) assert allclose(0, spe_condition.children[1].logprob(X << {2, 3})) assert allclose(0, spe_condition.children[2].logprob(X > 7))
def test_transform_product(): X = Id('X') Y = Id('Y') W = Id('W') Z = Id('Z') V = Id('V') spe \ = (X >> norm(loc=0, scale=1)) \ & (Y >> poisson(mu=10)) with pytest.raises(Exception): # Cannot use symbols from different transforms. spe.transform(W, (X > 0) | (Y << {'0'})) spe = spe.transform(W, (X**2 - 3*X)**(1,10)) spe = spe.transform(Z, (W > 0) | (X**3 < 1)) spe = spe.transform(V, Y/10) assert allclose( spe.logprob(W>1), spe.logprob((X**2 - 3*X)**(1,10) > 1)) with pytest.raises(Exception): spe.tarnsform(Id('R'), (V>1) | (W < 0))
def test_transform_sum(): X = Id('X') Z = Id('Z') Y = Id('Y') spe \ = 0.3*(X >> norm(loc=0, scale=1)) \ | 0.7*(X >> choice({'0': 0.4, '1': 0.6})) with pytest.raises(Exception): # Cannot transform Nominal variate. spe.transform(Z, X**2) spe \ = 0.3*(X >> norm(loc=0, scale=1)) \ | 0.7*(X >> poisson(mu=2)) spe = spe.transform(Z, X**2) assert spe.logprob(Z < 1) == spe.logprob(X**2 < 1) assert spe.children[0].env == spe.children[1].env spe = spe.transform(Y, Z/2) assert spe.children[0].env \ == spe.children[1].env \ == {X:X, Z:X**2, Y:Z/2}
def test_error(): with pytest.raises(TypeError): 'a' * bernoulli(p=.1) a = .1 * bernoulli(p=.1) | .7 * poisson(mu=8) with pytest.raises(Exception): a(X)
def test_logpdf_real_discrete(): spe = (X >> poisson(mu=2)) assert isinf_neg(spe.logpdf({X: 1.5})) assert isinf_neg(spe.logpdf({X: '1'})) assert not isinf_neg(spe.logpdf({X: 0}))
from sppl.distributions import norm from sppl.distributions import poisson from sppl.sets import EmptySet from sppl.transforms import EventFiniteNominal from sppl.transforms import Exp from sppl.transforms import Exponential from sppl.transforms import Id from sppl.transforms import Log from sppl.transforms import Logarithm X = Id('X') Y = Id('Y') spes = [ X >> norm(loc=0, scale=1), X >> poisson(mu=7), Y >> choice({'a': 0.5, 'b': 0.5}), (X >> norm(loc=0, scale=1)) & (Y >> gamma(a=1)), 0.2*(X >> norm(loc=0, scale=1)) | 0.8*(X >> gamma(a=1)), ((X >> norm(loc=0, scale=1)) & (Y >> gamma(a=1))).constrain({Y:1}), ] @pytest.mark.parametrize('spe', spes) def test_serialize_equal(spe): metadata = spe_to_dict(spe) spe_json_encoded = json.dumps(metadata) spe_json_decoded = json.loads(spe_json_encoded) spe2 = spe_from_dict(spe_json_decoded) assert spe2 == spe transforms = [ X,
def test_poisson(): X = Id('X') spe = X >> poisson(mu=5) a = spe.logprob((1 <= X) <= 7) b = spe.logprob(X << {1, 2, 3, 4, 5, 6, 7}) c = logsumexp([spe.logprob(X << {i}) for i in range(1, 8)]) assert allclose(a, b) assert allclose(a, c) assert allclose(b, c) spe_condition = spe.condition(10 <= X) assert spe_condition.conditioned assert spe_condition.support == Range(10, oo) assert spe_condition.logZ == logdiffexp(0, spe.logprob(X <= 9)) assert allclose(spe_condition.logprob(X <= 10), spe_condition.logprob(X << {10})) assert allclose(spe_condition.logprob(X <= 10), spe_condition.logpdf({X: 10})) samples = spe_condition.sample(100) assert all(10 <= s[X] for s in samples) # Unify X = 5 with left interval to make one distribution. event = ((1 <= X) < 5) | ((3 * X + 1) << {16}) spe_condition = spe.condition(event) assert isinstance(spe_condition, DiscreteLeaf) assert spe_condition.conditioned assert spe_condition.xl == 1 assert spe_condition.xu == 5 assert spe_condition.support == Range(1, 5) samples = spe_condition.sample(100, prng=numpy.random.RandomState(1)) assert all(event.evaluate(s) for s in samples) # Ignore X = 14/3 as a probability zero condition. spe_condition = spe.condition(((1 <= X) < 5) | (3 * X + 1) << {15}) assert isinstance(spe_condition, DiscreteLeaf) assert spe_condition.conditioned assert spe_condition.xl == 1 assert spe_condition.xu == 4 assert spe_condition.support == Interval.Ropen(1, 5) # Make a mixture of two components. spe_condition = spe.condition(((1 <= X) < 5) | (3 * X + 1) << {22}) assert isinstance(spe_condition, SumSPE) xl = spe_condition.children[0].xl idx0 = 0 if xl == 7 else 1 idx1 = 1 if xl == 7 else 0 assert spe_condition.children[idx1].conditioned assert spe_condition.children[idx1].xl == 1 assert spe_condition.children[idx1].xu == 4 assert spe_condition.children[idx0].conditioned assert spe_condition.children[idx0].xl == 7 assert spe_condition.children[idx0].xu == 7 assert spe_condition.children[idx0].support == Range(7, 7) # Condition on probability zero event. with pytest.raises(ValueError): spe.condition(((-3 <= X) < 0) | (3 * X + 1) << {20}) # Condition on FiniteReal contiguous. spe_condition = spe.condition(X << {1, 2, 3}) assert spe_condition.xl == 1 assert spe_condition.xu == 3 assert allclose(spe_condition.logprob((1 <= X) <= 3), 0) # Condition on single point. assert allclose(0, spe.condition(X << {2}).logprob(X << {2})) # Constrain. with pytest.raises(Exception): spe.constrain({X: -1}) with pytest.raises(Exception): spe.constrain({X: .5}) spe_constrain = spe.constrain({X: 10}) assert allclose(spe_constrain.prob(X << {0, 10}), 1)