Set constraints on probability distributions


I was wondering whether it is possible to define constraints on probability distributions in the style of the probabilistic programming framework figaro setConstraint? This function multiplies the weight of the sample by the value of the constraint.

I’ve read about pymc3 potentials but they don’t seem to have the same effect.

Thanks in advanced!

1 Like

I have no idea about the implementation in figaro and not sure about the intended use case, but we have pm.Bound for setting constraints on the domain of the probability distribution. And yes you can also use potential with value evaluated on a CDF function to account for constraints (also for modifying the domain of the distribution)

Thanks for the quick answer!

I’ve checked Bounded but it doesn’t seem to work as I expect. Consider the following example:

with pm.Model() as model:
    x = pm.Normal('x', mu=5, sigma=1)
    y = pm.Normal('y', mu=7, sigma=1)

    BoundedDeterministic = pm.Bound(pm.Deterministic, lower=6.0, upper=7.0)    
    z = BoundedDeterministic('z', x+y)

I would like to impose a constraint on z (in this case that the values are between 6.0 and 7.0) and see how it affects the variables x and y. I expect that the sampler gives higher probability to the samples that satisfy the constraint, and disregards the samples that don’t.

Unfortunately, the snippet above doesn’t work. I get an error message saying that pm.Deterministic is not a subclass of distribution. Do you know what class I should use for this case?


You cannot set constrain on deterministic variables, you can only set constraints on random variables.
You can do something like this:

import pymc3 as pm
import numpy as np
import theano.tensor as tt

with pm.Model() as model:
    x = pm.Normal('x', mu=5, sigma=1, testval=.5)
    y = pm.Normal('y', mu=7, sigma=1, testval=6.1)

    z = pm.Deterministic('z', x+y)
    # constraint
    pm.Potential('bound', tt.switch((z>6.)*(z<7.), 0., -np.inf))
    trace = pm.sample(init='adapt_diag')
pm.traceplot(trace, compact=True)

Note that since the constraint, you will get a lot of divergence in the snippet above, as the steps outside of the bound will becomes a divergence.

1 Like

I see, thanks a lot!

BTW, I am new to pymc3 and I don’t understand what the parameter testval does. Could you please let me know where to read about it? It seems that the correctness of the code depends on it. For instance, if I change z to be x+y/2 it stops working. It throws a pymc3.exceptions.SamplingError: Bad initial energy exception.

So the teatval is for over writing the default value. For normal random variable, the default value is the mu, which in this case will be 5 and 7, and 5+7 will be already outside the support.

1 Like