Esempio n. 1
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),
    ])
Esempio n. 2
0
def test_simple_model_lte():
    command_switch = Sequence(
        Sample(Y, beta(a=2, b=3)),
        Switch(Y, binspace(0, 1, 5),
               lambda i: Sample(X, bernoulli(p=i.right))))
    model_switch = command_switch.interpret()

    command_ifelse = Sequence(
        Sample(Y, beta(a=2, b=3)),
        IfElse(
            Y <= 0,
            Sample(X, bernoulli(p=0)),
            Y <= 0.25,
            Sample(X, bernoulli(p=.25)),
            Y <= 0.50,
            Sample(X, bernoulli(p=.50)),
            Y <= 0.75,
            Sample(X, bernoulli(p=.75)),
            Y <= 1,
            Sample(X, bernoulli(p=1)),
        ))
    model_ifelse = command_ifelse.interpret()

    grid = [float(x) for x in linspace(0, 1, 5)]
    for model in [model_switch, model_ifelse]:
        symbols = model.get_symbols()
        assert symbols == {X, Y}
        assert allclose(
            model.logprob(X << {1}),
            logsumexp([
                model.logprob((il < Y) <= ih) + log(ih)
                for il, ih in zip(grid[:-1], grid[1:])
            ]))
Esempio n. 3
0
def test_simple_model_eq():
    command_switch = Sequence(
        Sample(Y, randint(low=0, high=4)),
        Switch(Y, range(0, 4), lambda i: Sample(X, bernoulli(p=1 / (i + 1)))))
    model_switch = command_switch.interpret()

    command_ifelse = Sequence(
        Sample(Y, randint(low=0, high=4)),
        IfElse(
            Y << {0},
            Sample(X, bernoulli(p=1 / (0 + 1))),
            Y << {1},
            Sample(X, bernoulli(p=1 / (1 + 1))),
            Y << {2},
            Sample(X, bernoulli(p=1 / (2 + 1))),
            Y << {3},
            Sample(X, bernoulli(p=1 / (3 + 1))),
        ))
    model_ifelse = command_ifelse.interpret()

    for model in [model_switch, model_ifelse]:
        symbols = model.get_symbols()
        assert symbols == {X, Y}
        assert allclose(model.logprob(X << {1}),
                        logsumexp([-log(4) - log(i + 1) for i in range(4)]))
Esempio n. 4
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}),
        ]))
Esempio n. 5
0
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'
Esempio n. 6
0
def test_logpdf_lexicographic_both():
    spe = .75*(X >> norm() & Y >> atomic(loc=0) & Z >> discrete({1:.2, 2:.8})) \
        | .25*(X >> discrete({1:.5, 2:.5}) & Y >> norm() & Z >> atomic(loc=2))
    # Lexicographic, Mix
    assignment = {X:1, Y:0, Z:2}
    assert allclose(
        spe.logpdf(assignment),
        logsumexp([
            log(.75) + norm().dist.logpdf(1) + log(1) + log(.8),
            log(.25) + log(.5) + norm().dist.logpdf(0) + log(1)]))
    assert isinstance(spe.constrain(assignment), SumSPE)
Esempio n. 7
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)
Esempio n. 8
0
def entropyc(spe, A, B, memo):
    lpB1 = spe.logprob(B)
    lpB0 = logdiffexp(0, lpB1)
    lp11 = spe.logprob(B & A, memo=memo)
    lp10 = spe.logprob(B & ~A, memo=memo)
    lp01 = spe.logprob(~B & A, memo=memo)
    # lp00 = self.logprob(~B & ~A, memo)
    lp00 = logdiffexp(0, logsumexp([lp11, lp10, lp01]))
    m11 = exp(lp11) * (lpB1 - lp11) if not isinf_neg(lp11) else 0
    m10 = exp(lp10) * (lpB1 - lp10) if not isinf_neg(lp10) else 0
    m01 = exp(lp01) * (lpB0 - lp01) if not isinf_neg(lp01) else 0
    m00 = exp(lp00) * (lpB0 - lp00) if not isinf_neg(lp00) else 0
    return m11 + m10 + m01 + m00
Esempio n. 9
0
def test_sum_normal_nominal():
    X = Id('X')
    children = [
        X >> norm(loc=0, scale=1),
        X >> choice({
            'low': Fraction(3, 10),
            'high': Fraction(7, 10)
        }),
    ]
    weights = [log(Fraction(4, 7)), log(Fraction(3, 7))]

    spe = SumSPE(children, weights)

    assert allclose(spe.logprob(X < 0),
                    log(Fraction(4, 7)) + log(Fraction(1, 2)))

    assert allclose(spe.logprob(X << {'low'}),
                    log(Fraction(3, 7)) + log(Fraction(3, 10)))

    # The semantics of ~(X<<{'low'}) are (X << String and X != 'low')
    assert allclose(spe.logprob(~(X << {'low'})), spe.logprob((X << {'high'})))
    assert allclose(
        spe.logprob((X << FiniteNominal(b=True)) & ~(X << {'low'})),
        spe.logprob((X << FiniteNominal(b=True)) & (X << {'high'})))

    assert isinf_neg(spe.logprob((X < 0) & (X << {'low'})))

    assert allclose(spe.logprob((X < 0) | (X << {'low'})),
                    logsumexp([spe.logprob(X < 0),
                               spe.logprob(X << {'low'})]))

    assert isinf_neg(spe.logprob(X << {'a'}))
    assert allclose(spe.logprob(~(X << {'a'})),
                    spe.logprob(X << {'low', 'high'}))

    assert allclose(spe.logprob(X**2 < 9),
                    log(Fraction(4, 7)) + spe.children[0].logprob(X**2 < 9))

    spe_condition = spe.condition(X**2 < 9)
    assert isinstance(spe_condition, ContinuousLeaf)
    assert spe_condition.support == Interval.open(-3, 3)

    spe_condition = spe.condition((X**2 < 9) | X << {'low'})
    assert isinstance(spe_condition, SumSPE)
    assert spe_condition.children[0].support == Interval.open(-3, 3)
    assert spe_condition.children[1].support == FiniteNominal('low', 'high')
    assert isinf_neg(spe_condition.children[1].logprob(X << {'high'}))

    assert spe_condition == spe.condition((X**2 < 9) | ~(X << {'high'}))
    assert allclose(spe.logprob((X < oo) | ~(X << {'1'})), 0)
Esempio n. 10
0
def test_product_disjoint_union_numerical():
    X = Id('X')
    Y = Id('Y')
    Z = Id('Z')
    spe = ProductSPE([
        X >> norm(loc=0, scale=1),
        Y >> norm(loc=0, scale=2),
        Z >> norm(loc=0, scale=2),
    ])

    for event in [
        (1 / X < 4) | (X > 7),
        (2 * X - 3 > 0) | (Log(Y) < 3),
        ((X > 0) & (Y < 1)) | ((X < 1) & (Y < 3)) | ~(X << {1, 2}),
        ((X > 0) & (Y < 1)) | ((X < 1) & (Y < 3)) | (Z < 0),
        ((X > 0) & (Y < 1)) | ((X < 1) & (Y < 3)) | (Z < 0) | ~(X << {1, 3}),
    ]:
        clauses = dnf_to_disjoint_union(event)
        logps = [spe.logprob(s) for s in clauses.subexprs]
        assert allclose(logsumexp(logps), spe.logprob(event))
Esempio n. 11
0
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)