# Peculiar Issue with PyMC3.Potential

**URL:** <https://discourse.pymc.io/t/peculiar-issue-with-pymc3-potential/5537>\
**Category:** Questions\
**Created:** [July 29, 2020, 5:45am UTC](https://discourse.pymc.io/t/peculiar-issue-with-pymc3-potential/5537 "2020-07-29T05:45:27Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![mabrur](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/mabrur/32/5670_2.png) [@mabrur](https://discourse.pymc.io/u/mabrur)\
**Post date:** [July 29, 2020, 5:45am UTC](https://discourse.pymc.io/t/peculiar-issue-with-pymc3-potential/5537/1 "2020-07-29T05:45:27Z")

</div>

Hello, I have only recently got familiar with PyMC3. I have been trying to use the potential function to impose constraints on a distribution. I was trying to run the following piece of code:

```
*import pymc3 as pm*
*import numpy as np*

*with pm.Model() as model:*
* 2D_binary_vectors = pm.Bernoulli('2D_binary_vectors', p = 0.7, shape=2)*
* exclude00 = pm.Potential('exclude00', pm.math.switch(pm.math.sum(2D_binary_vectors) >= 1 , 0, -np.inf))*
* trace = pm.sample(20000)*

*trace [2D_binary_vectors]*

```

I get output like this:

```
**array([[1, 1],**
**[1, 1],**
**[1, 1],**
 **...,**
**[0, 1],**
**[0, 1],**
**[1, 1]], dtype=int64)**

```

Which is expected! There are no [0,0] which is what I expect the potential would do. However, if I decrease the value of the parameter in the Bernoulli prior to p = 0.5, the same code gives me nothing but [0,0]. So, for the following code:

```
**with pm.Model() as model:**
**2D_binary_vectors = pm.Bernoulli('2D_binary_vectors', p = 0.5, shape=2)**
**exclude00 = pm.Potential('exclude00', pm.math.switch(pm.math.sum(2D_binary_vectors) >= 1 , 0, -np.inf))**
**trace = pm.sample(20000)**

**trace [2D_binary_vectors]**

```

I get:

```
**array([[0, 0],**
**[0, 0],**
**[0, 0],**
 **...,**
**[0, 0],**
**[0, 0],**
**[0, 0]], dtype=int64)**

```

I get nothing but [0,0], which was the only thing I was trying to exclude. I don’t understand what’s going on here.

---

<div class="post-metadata">

**Author:** ![Elenchus](https://avatars.discourse-cdn.com/v4/letter/e/ccd318/32.png) [@Elenchus](https://discourse.pymc.io/u/Elenchus)\
**Post date:** [July 29, 2020, 9:30am UTC](https://discourse.pymc.io/t/peculiar-issue-with-pymc3-potential/5537/2 "2020-07-29T09:30:25Z")

</div>

You mention “if I decrease the value of the parameter in the Bernoulli prior to p = 0.5” but you’ve got p = 0.5 in both examples. However, in the second you’ve got np.inf whereas in the first you have -np.inf. I couldn’t run either example because I don’t have the ‘dorm1’ variable, but maybe check if the sign is making a difference.

---

<div class="post-metadata">

**Author:** ![mabrur](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/mabrur/32/5670_2.png) [@mabrur](https://discourse.pymc.io/u/mabrur)\
**Post date:** [July 29, 2020, 1:42pm UTC](https://discourse.pymc.io/t/peculiar-issue-with-pymc3-potential/5537/3 "2020-07-29T13:42:24Z")

</div>

I edited the post to correct the mistakes. The code I tried to run looked like this

---

<div class="post-metadata">

**Author:** ![Elenchus](https://avatars.discourse-cdn.com/v4/letter/e/ccd318/32.png) [@Elenchus](https://discourse.pymc.io/u/Elenchus)\
**Post date:** [July 29, 2020, 10:32pm UTC](https://discourse.pymc.io/t/peculiar-issue-with-pymc3-potential/5537/4 "2020-07-29T22:32:25Z")

</div>

This worked for me:

```auto
with pm.Model() as model:
    _binary_vectors = pm.Bernoulli('_binary_vectors', p = 0.3, shap
      e=2)
    exclude00 = pm.Potential('exclude00', pm.math.switch(
        pm.math.sum(_binary_vectors) <= 0 , (1,1), _binary_vectors))

pred = pm.sample_prior_predictive(500, model=model)

```

I think sample is just taking from the original distribution of the Bernoulli distribution, not the distribution adjusted by the Potential - possibly because there aren’t any observed values to update the prior with, but I’m not sure (I’m new to pymc3 too). Note that with what I’ve got (0, 0) is being replaced with (1, 1), which would affect the probability of drawing it - you’d have to do something a bit different to keep the distribution you want

---

<div class="post-metadata">

**Author:** ![AlexAndorra](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/alexandorra/32/9142_2.png) [@AlexAndorra](https://discourse.pymc.io/u/AlexAndorra)\
**Post date:** [July 30, 2020, 3:25pm UTC](https://discourse.pymc.io/t/peculiar-issue-with-pymc3-potential/5537/5 "2020-07-30T15:25:04Z")

</div>

Note that forward sampling distributions (i.e `sample_prior/posterior_predictive`) ignore `Potential`s – only `sample` takes them into account; [see this issue](https://github.com/pymc-devs/pymc3/issues/3865), for which help is welcome by the way 🙂  
This means that to have the constraints in your forward samples, you need to implement the contraints by hand

---

<div class="post-metadata">

**Author:** ![mabrur](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/mabrur/32/5670_2.png) [@mabrur](https://discourse.pymc.io/u/mabrur)\
**Post date:** [July 30, 2020, 4:23pm UTC](https://discourse.pymc.io/t/peculiar-issue-with-pymc3-potential/5537/6 "2020-07-30T16:23:35Z")

</div>

Thank you for the reply. I think the problem is I don’t understand the use of the switch function.

---

<div class="post-metadata">

**Author:** ![mabrur](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/mabrur/32/5670_2.png) [@mabrur](https://discourse.pymc.io/u/mabrur)\
**Post date:** [July 30, 2020, 4:27pm UTC](https://discourse.pymc.io/t/peculiar-issue-with-pymc3-potential/5537/7 "2020-07-30T16:27:47Z")

</div>

Thank you for the reply. Could you elaborate on what you mean by implementing by hand?

---

<div class="post-metadata">

**Author:** ![Elenchus](https://avatars.discourse-cdn.com/v4/letter/e/ccd318/32.png) [@Elenchus](https://discourse.pymc.io/u/Elenchus)\
**Post date:** [July 30, 2020, 11:32pm UTC](https://discourse.pymc.io/t/peculiar-issue-with-pymc3-potential/5537/8 "2020-07-30T23:32:41Z")

</div>

Switch takes the format [if cond then ift else iff](https://docs.pymc.io/api/math.html), as you probably know.

So what I thought was happening - which may well be incorrect, @AlexAndorra your input would be most welcome - is that the Potential would examine each pair of outputs from the Bernoulli distribution, and then the switch if their sum was 0 (cond), replace the pair with (1, 1) (ift), otherwise it would output the pair from the Bernoulli (iff).

After reading the link Alex provided, it seems Potential should influence logp of the Bernoulli. I tried

```auto
with model:
    trace = pm.sample(2000, tune=1000)
    az.summary(trace)

```

and got  
 ![image](https://canada1.discourse-cdn.com/flex036/uploads/pymc3/original/2X/7/7377bd5275f41ed47cb34b04256fbc3d85fa16e0.png)  
The mean is quite a bit lower than 0.3, so obviously there is some effect from the Potential. However,

```auto
trace[_binary_vectors]

```

gives  
 ![image](https://canada1.discourse-cdn.com/flex036/uploads/pymc3/original/2X/1/1edc75bd038f51bbea52624a65e1e8f633f53da3.png)

And I was about to write ‘whereas pred had no [0,0] values’, but I just tried it again to make sure and it does. My apologies - not sure what I did yesterday that made me think it didn’t have them

EDIT:  
pred is a dictionary with values from \_binary\_vectors and exclude00. So pred[‘exclude00’] looks like  
 ![image](https://canada1.discourse-cdn.com/flex036/uploads/pymc3/original/2X/c/c2b865e86a1551041c35e2e6b11883d2549bc763.png)  
which should be what you want
