예제 #1
0
def test_sum_of_sums():
    w \
        = 0.3*(0.4*(X >> norm()) | 0.6*(X >> norm())) \
        | 0.7*(0.1*(X >> norm()) | 0.9*(X >> norm()))
    assert isinstance(w, SumSPE)
    assert len(w.children) == 4
    assert allclose(float(w.weights[0]), log(0.3) + log(0.4))
    assert allclose(float(w.weights[1]), log(0.3) + log(0.6))
    assert allclose(float(w.weights[2]), log(0.7) + log(0.1))
    assert allclose(float(w.weights[3]), log(0.7) + log(0.9))

    w \
        = 0.3*(0.4*(X >> norm()) | 0.6*(X >> norm())) \
        | 0.2*(0.1*(X >> norm()) | 0.9*(X >> norm()))
    assert isinstance(w, PartialSumSPE)
    assert allclose(float(w.weights[0]), 0.3)
    assert allclose(float(w.weights[1]), 0.2)

    a = w | 0.5*(X >> gamma(a=1))
    assert isinstance(a, SumSPE)
    assert len(a.children) == 5
    assert allclose(float(a.weights[0]), log(0.3) + log(0.4))
    assert allclose(float(a.weights[1]), log(0.3) + log(0.6))
    assert allclose(float(a.weights[2]), log(0.2) + log(0.1))
    assert allclose(float(a.weights[3]), log(0.2) + log(0.9))
    assert allclose(float(a.weights[4]), log(0.5))

    # Wrong symbol.
    with pytest.raises(ValueError):
        z = w | 0.4*(Y >> gamma(a=1))
예제 #2
0
def test_or_and():
    with pytest.raises(ValueError):
        (0.3*(X >> norm()) | 0.7*(Y >> gamma(a=1))) & (Z >> norm())
    a = (0.3*(X >> norm()) | 0.7*(X >> gamma(a=1))) & (Z >> norm())
    assert isinstance(a, ProductSPE)
    assert isinstance(a.children[0], SumSPE)
    assert isinstance(a.children[1], ContinuousLeaf)
예제 #3
0
def test_product_leaf():
    with pytest.raises(TypeError):
        0.3*(X >> gamma(a=1)) & (X >> norm())
    with pytest.raises(TypeError):
        (X >> norm()) & 0.3*(X >> gamma(a=1))
    with pytest.raises(ValueError):
        (X >> norm()) & (X >> gamma(a=1))

    y = (X >> norm()) & (Y >> gamma(a=1)) & (Z >> norm())
    assert isinstance(y, ProductSPE)
    assert len(y.children) == 3
    assert y.get_symbols() == frozenset([X, Y, Z])
예제 #4
0
def test_sum_leaf():
    # Cannot sum leaves without weights.
    with pytest.raises(TypeError):
        (X >> norm()) | (X >> gamma(a=1))
    # Cannot sum a leaf with a partial sum.
    with pytest.raises(TypeError):
        0.3*(X >> norm()) | (X >> gamma(a=1))
    # Cannot sum a leaf with a partial sum.
    with pytest.raises(TypeError):
        (X >> norm()) | 0.3*(X >> gamma(a=1))
    # Wrong symbol.
    with pytest.raises(ValueError):
        0.4*(X >> norm()) | 0.6*(Y >> gamma(a=1))
    # Sum exceeds one.
    with pytest.raises(ValueError):
        0.4*(X >> norm()) | 0.7*(Y >> gamma(a=1))

    y = 0.4*(X >> norm()) | 0.3*(X >> gamma(a=1))
    assert isinstance(y, PartialSumSPE)
    assert len(y.weights) == 2
    assert allclose(float(y.weights[0]), 0.4)
    assert allclose(float(y.weights[1]), 0.3)

    y = 0.4*(X >> norm()) | 0.6*(X >> gamma(a=1))
    assert isinstance(y, SumSPE)
    assert len(y.weights) == 2
    assert allclose(float(y.weights[0]), log(0.4))
    assert allclose(float(y.weights[1]), log(0.6))
    # Sum exceeds one.
    with pytest.raises(TypeError):
        y | 0.7 * (X >> norm())

    y = 0.4*(X >> norm()) | 0.3*(X >> gamma(a=1)) | 0.1*(X >> norm())
    assert isinstance(y, PartialSumSPE)
    assert len(y.weights) == 3
    assert allclose(float(y.weights[0]), 0.4)
    assert allclose(float(y.weights[1]), 0.3)
    assert allclose(float(y.weights[2]), 0.1)

    y = 0.4*(X >> norm()) | 0.3*(X >> gamma(a=1)) | 0.3*(X >> norm())
    assert isinstance(y, SumSPE)
    assert len(y.weights) == 3
    assert allclose(float(y.weights[0]), log(0.4))
    assert allclose(float(y.weights[1]), log(0.3))
    assert allclose(float(y.weights[2]), log(0.3))

    with pytest.raises(TypeError):
        (0.3)*(0.3*(X >> norm()))
    with pytest.raises(TypeError):
        (0.3*(X >> norm())) * (0.3)
    with pytest.raises(TypeError):
        0.3*(0.3*(X >> norm()) | 0.5*(X >> norm()))

    w = 0.3*(0.4*(X >> norm()) | 0.6*(X >> norm()))
    assert isinstance(w, PartialSumSPE)
예제 #5
0
def test_sum_normal_gamma():
    X = Id('X')
    weights = [log(Fraction(2, 3)), log(Fraction(1, 3))]
    spe = SumSPE([
        X >> norm(loc=0, scale=1),
        X >> gamma(loc=0, a=1),
    ], weights)

    assert spe.logprob(X > 0) == logsumexp([
        spe.weights[0] + spe.children[0].logprob(X > 0),
        spe.weights[1] + spe.children[1].logprob(X > 0),
    ])
    assert spe.logprob(X < 0) == log(Fraction(2, 3)) + log(Fraction(1, 2))
    samples = spe.sample(100, prng=numpy.random.RandomState(1))
    assert all(s[X] for s in samples)
    spe.sample_func(lambda X: abs(X**3), 100)
    with pytest.raises(ValueError):
        spe.sample_func(lambda Y: abs(X**3), 100)

    spe_condition = spe.condition(X < 0)
    assert isinstance(spe_condition, ContinuousLeaf)
    assert spe_condition.conditioned
    assert spe_condition.logprob(X < 0) == 0
    samples = spe_condition.sample(100)
    assert all(s[X] < 0 for s in samples)

    assert spe.logprob(X < 0) == logsumexp([
        spe.weights[0] + spe.children[0].logprob(X < 0),
        spe.weights[1] + spe.children[1].logprob(X < 0),
    ])
예제 #6
0
def test_logpdf_mixture_real_continuous_continuous():
    spe = X >> (.3*norm() | .7*gamma(a=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}),
        ]))
예제 #7
0
def test_product_condition_or_probabilithy_zero():
    X = Id('X')
    Y = Id('Y')
    spe = ProductSPE([X >> norm(loc=0, scale=1), Y >> gamma(a=1)])

    # Condition on event which has probability zero.
    event = (X > 2) & (X < 2)
    with pytest.raises(ValueError):
        spe.condition(event)
    assert spe.logprob(event) == -float('inf')

    # Condition on event which has probability zero.
    event = (Y < 0) | (Y < -1)
    with pytest.raises(ValueError):
        spe.condition(event)
    assert spe.logprob(event) == -float('inf')
    # Condition on an event where one clause has probability
    # zero, yielding a single product.
    spe_condition = spe.condition((Y < 0) | ((Log(X) >= 0) & (1 <= Y)))
    assert isinstance(spe_condition, ProductSPE)
    assert spe_condition.children[0].symbol == X
    assert spe_condition.children[0].conditioned
    assert spe_condition.children[0].support == Interval(1, oo)
    assert spe_condition.children[1].symbol == Y
    assert spe_condition.children[1].conditioned
    assert spe_condition.children[0].support == Interval(1, oo)

    # We have (X < 2) & ~(1 < exp(|3X**2|) is empty.
    # Thus Y remains unconditioned,
    #   and X is partitioned into (-oo, 0) U (0, oo) with equal weight.
    event = (Exp(abs(3 * X**2)) > 1) | ((Log(Y) < 0.5) & (X < 2))
    spe_condition = spe.condition(event)
    #
    # The most concise representation of spe_condition is:
    #   (Product (Sum [.5 .5] X|X<0 X|X>0) Y)
    assert isinstance(spe_condition, ProductSPE)
    assert isinstance(spe_condition.children[0], SumSPE)
    assert spe_condition.children[0].weights == (-log(2), -log(2))
    assert spe_condition.children[0].children[0].conditioned
    assert spe_condition.children[0].children[1].conditioned
    assert spe_condition.children[0].children[0].support \
        in [Interval.Ropen(-oo, 0), Interval.Lopen(0, oo)]
    assert spe_condition.children[0].children[1].support \
        in [Interval.Ropen(-oo, 0), Interval.Lopen(0, oo)]
    assert spe_condition.children[0].children[0].support \
        != spe_condition.children[0].children[1].support
    assert spe_condition.children[1].symbol == Y
    assert not spe_condition.children[1].conditioned
예제 #8
0
def test_sum_simplify_nested_sum_1():
    X = Id('X')
    children = [
        SumSPE(
            [X >> norm(loc=0, scale=1), X >> norm(loc=0, scale=2)],
            [log(0.4), log(0.6)]),
        X >> gamma(loc=0, a=1),
    ]
    spe = SumSPE(children, [log(0.7), log(0.3)])
    assert spe.size() == 4
    assert spe.children == (
        children[0].children[0],
        children[0].children[1],
        children[1]
    )
    assert allclose(spe.weights[0], log(0.7) + log(0.4))
    assert allclose(spe.weights[1], log(0.7) + log(0.6))
    assert allclose(spe.weights[2], log(0.3))
예제 #9
0
def test_product_distribution_normal_gamma_basic():
    X1 = Id('X1')
    X2 = Id('X2')
    X3 = Id('X3')
    X4 = Id('X4')
    children = [
        ProductSPE([
            X1 >> norm(loc=0, scale=1),
            X4 >> norm(loc=10, scale=1),
        ]), X2 >> gamma(loc=0, a=1), X3 >> norm(loc=2, scale=3)
    ]
    spe = ProductSPE(children)
    assert spe.children == (
        children[0].children[0],
        children[0].children[1],
        children[1],
        children[2],
    )
    assert spe.get_symbols() == frozenset([X1, X2, X3, X4])
    assert spe.size() == 5

    samples = spe.sample(2)
    assert len(samples) == 2
    for sample in samples:
        assert len(sample) == 4
        assert all([X in sample for X in (X1, X2, X3, X4)])

    samples = spe.sample_subset((X1, X2), 10)
    assert len(samples) == 10
    for sample in samples:
        assert len(sample) == 2
        assert X1 in sample
        assert X2 in sample

    samples = spe.sample_func(lambda X1, X2, X3: (X1, (X2**2, X3)), 1)
    assert len(samples) == 1
    assert len(samples[0]) == 2
    assert len(samples[0][1]) == 2

    with pytest.raises(ValueError):
        spe.sample_func(lambda X1, X5: X1 + X4, 1)
예제 #10
0
def test_sum_normal_gamma_exposed():
    X = Id('X')
    W = Id('W')
    weights = W >> choice({
        '0': Fraction(2, 3),
        '1': Fraction(1, 3),
    })
    children = {
        '0': X >> norm(loc=0, scale=1),
        '1': X >> gamma(loc=0, a=1),
    }
    spe = ExposedSumSPE(children, weights)

    assert spe.logprob(W << {'0'}) == log(Fraction(2, 3))
    assert spe.logprob(W << {'1'}) == log(Fraction(1, 3))
    assert allclose(spe.logprob((W << {'0'}) | (W << {'1'})), 0)
    assert spe.logprob((W << {'0'}) & (W << {'1'})) == -float('inf')

    assert allclose(spe.logprob((W << {'0', '1'}) & (X < 1)),
                    spe.logprob(X < 1))

    assert allclose(spe.logprob((W << {'0'}) & (X < 1)),
                    spe.weights[0] + spe.children[0].logprob(X < 1))

    spe_condition = spe.condition((W << {'1'}) | (W << {'0'}))
    assert isinstance(spe_condition, SumSPE)
    assert len(spe_condition.weights) == 2
    assert \
        allclose(spe_condition.weights[0], log(Fraction(2,3))) \
            and allclose(spe_condition.weights[0], log(Fraction(2,3))) \
        or \
        allclose(spe_condition.weights[1], log(Fraction(2,3))) \
            and allclose(spe_condition.weights[0], log(Fraction(2,3))
        )

    spe_condition = spe.condition((W << {'1'}))
    assert isinstance(spe_condition, ProductSPE)
    assert isinstance(spe_condition.children[0], NominalLeaf)
    assert isinstance(spe_condition.children[1], ContinuousLeaf)
    assert spe_condition.logprob(X < 5) == spe.children[1].logprob(X < 5)
예제 #11
0
def test_product_inclusion_exclusion_basic():
    X = Id('X')
    Y = Id('Y')
    spe = ProductSPE([X >> norm(loc=0, scale=1), Y >> gamma(a=1)])

    a = spe.logprob(X > 0.1)
    b = spe.logprob(Y < 0.5)
    c = spe.logprob((X > 0.1) & (Y < 0.5))
    d = spe.logprob((X > 0.1) | (Y < 0.5))
    e = spe.logprob((X > 0.1) | ((Y < 0.5) & ~(X > 0.1)))
    f = spe.logprob(~(X > 0.1))
    g = spe.logprob((Y < 0.5) & ~(X > 0.1))

    assert allclose(a, spe.children[0].logprob(X > 0.1))
    assert allclose(b, spe.children[1].logprob(Y < 0.5))

    # Pr[A and B]  = Pr[A] * Pr[B]
    assert allclose(c, a + b)
    # Pr[A or B] = Pr[A] + Pr[B] - Pr[AB]
    assert allclose(d, logdiffexp(logsumexp([a, b]), c))
    # Pr[A or B] = Pr[A] + Pr[B & ~A]
    assert allclose(e, d)
    # Pr[A and B]  = Pr[A] * Pr[B]
    assert allclose(g, b + f)
    # Pr[A or (B & ~A)] = Pr[A] + Pr[B & ~A]
    assert allclose(e, logsumexp([a, b + f]))

    # (A => B) => Pr[A or B] = Pr[B]
    # i.e.,k (X > 1) => (X > 0).
    assert allclose(spe.logprob((X > 0) | (X > 1)), spe.logprob(X > 0))

    # Positive probability event.
    # Pr[A] = 1 - Pr[~A]
    event = ((0 < X) < 0.5) | ((Y < 0) & (1 < X))
    assert allclose(spe.logprob(event), logdiffexp(0, spe.logprob(~event)))

    # Probability zero event.
    event = ((0 < X) < 0.5) & ((Y < 0) | (1 < X))
    assert isinf_neg(spe.logprob(event))
    assert allclose(spe.logprob(~event), 0)
예제 #12
0
def test_product_condition_basic():
    X = Id('X')
    Y = Id('Y')
    spe = ProductSPE([X >> norm(loc=0, scale=1), Y >> gamma(a=1)])

    # Condition on (X > 0) and ((X > 0) | (Y < 0))
    # where the second clause reduces to first as Y < 0
    # has probability zero.
    for event in [(X > 0), (X > 0) | (Y < 0)]:
        dX = spe.condition(event)
        assert isinstance(dX, ProductSPE)
        assert dX.children[0].symbol == Id('X')
        assert dX.children[0].conditioned
        assert dX.children[0].support == Interval.open(0, oo)
        assert dX.children[1].symbol == Id('Y')
        assert not dX.children[1].conditioned
        assert dX.children[1].Fl == 0
        assert dX.children[1].Fu == 1

    # Condition on (Y < 0.5)
    dY = spe.condition(Y < 0.5)
    assert isinstance(dY, ProductSPE)
    assert dY.children[0].symbol == Id('X')
    assert not dY.children[0].conditioned
    assert dY.children[1].symbol == Id('Y')
    assert dY.children[1].conditioned
    assert dY.children[1].support == Interval.Ropen(0, 0.5)

    # Condition on (X > 0) & (Y < 0.5)
    dXY_and = spe.condition((X > 0) & (Y < 0.5))
    assert isinstance(dXY_and, ProductSPE)
    assert dXY_and.children[0].symbol == Id('X')
    assert dXY_and.children[0].conditioned
    assert dXY_and.children[0].support == Interval.open(0, oo)
    assert dXY_and.children[1].symbol == Id('Y')
    assert dXY_and.children[1].conditioned
    assert dXY_and.children[1].support == Interval.Ropen(0, 0.5)

    # Condition on (X > 0) | (Y < 0.5)
    event = (X > 0) | (Y < 0.5)
    dXY_or = spe.condition((X > 0) | (Y < 0.5))
    assert isinstance(dXY_or, SumSPE)
    assert all(isinstance(d, ProductSPE) for d in dXY_or.children)
    assert allclose(dXY_or.logprob(X > 0), dXY_or.weights[0])
    samples = dXY_or.sample(100, prng=numpy.random.RandomState(1))
    assert all(event.evaluate(sample) for sample in samples)

    # Condition on a disjoint union with one term in second clause.
    dXY_disjoint_one = spe.condition((X > 0) & (Y < 0.5) | (X <= 0))
    assert isinstance(dXY_disjoint_one, SumSPE)
    component_0 = dXY_disjoint_one.children[0]
    assert component_0.children[0].symbol == Id('X')
    assert component_0.children[0].conditioned
    assert component_0.children[0].support == Interval.open(0, oo)
    assert component_0.children[1].symbol == Id('Y')
    assert component_0.children[1].conditioned
    assert component_0.children[1].support == Interval.Ropen(0, 0.5)
    component_1 = dXY_disjoint_one.children[1]
    assert component_1.children[0].symbol == Id('X')
    assert component_1.children[0].conditioned
    assert component_1.children[0].support == Interval(-oo, 0)
    assert component_1.children[1].symbol == Id('Y')
    assert not component_1.children[1].conditioned

    # Condition on a disjoint union with two terms in each clause
    dXY_disjoint_two = spe.condition((X > 0) & (Y < 0.5)
                                     | ((X <= 0) & ~(Y < 3)))
    assert isinstance(dXY_disjoint_two, SumSPE)
    component_0 = dXY_disjoint_two.children[0]
    assert component_0.children[0].symbol == Id('X')
    assert component_0.children[0].conditioned
    assert component_0.children[0].support == Interval.open(0, oo)
    assert component_0.children[1].symbol == Id('Y')
    assert component_0.children[1].conditioned
    assert component_0.children[1].support == Interval.Ropen(0, 0.5)
    component_1 = dXY_disjoint_two.children[1]
    assert component_1.children[0].symbol == Id('X')
    assert component_1.children[0].conditioned
    assert component_1.children[0].support == Interval(-oo, 0)
    assert component_1.children[1].symbol == Id('Y')
    assert component_1.children[1].conditioned
    assert component_1.children[1].support == Interval(3, oo)

    # Some various conditioning.
    spe.condition((X > 0) & (Y < 0.5) | ((X <= 1) | ~(Y < 3)))
    spe.condition((X > 0) & (Y < 0.5) | ((X <= 1) & (Y < 3)))
예제 #13
0
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,
    X**(1,3),
    Exponential(X, base=3),