We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
New Bernoulli parameterization lead to subtle bug in AIR model
When I merged #416 into a local branch it broke the AIR example.

Here's a simplified instance of the problem:

```python
import torch
from torch.autograd import Variable
from pyro.distributions import Bernoulli
from torch.nn.functional import sigmoid

p = Variable(torch.Tensor([0]), requires_grad=True)
b = Bernoulli(sigmoid(p) * 0.0)
log_pdf = b.batch_log_pdf(Variable(torch.Tensor([0])))
log_pdf.sum().backward()
print(p.grad)
```

Prior to #416 this returned a `grad` of zero as expected, but it now returns `nan`:

```
pyro$ git rev-parse --short HEAD
71bca18
pyro$ python3 bern.py 
Variable containing:
-0
[torch.FloatTensor of size 1]

pyro$ git rev-parse --short HEAD
a85525a
pyro$ python3 bern.py 
Variable containing:
nan
[torch.FloatTensor of size 1]
```

I suspect that the problem is that converting between probabilities and log odds introduces an intemediate `-inf`, which messes up autograd.

I may be able to adjust the model to work around this, but either way, should this be considered a bug? (It seems like it could trip other people up, and chasing down the source of the `nan`s is tricky.)


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pyro/distributions/util.py`
Content:
```
1 import torch
2 import torch.nn.functional as F
3 from torch.autograd import Variable
4 
5 
6 def log_gamma(xx):
7     if isinstance(xx, Variable):
8         ttype = xx.data.type()
9     elif isinstance(xx, torch.Tensor):
10         ttype = xx.type()
11     gamma_coeff = [
12         76.18009172947146,
13         -86.50532032941677,
14         24.01409824083091,
15         -1.231739572450155,
16         0.1208650973866179e-2,
17         -0.5395239384953e-5,
18     ]
19     magic1 = 1.000000000190015
20     magic2 = 2.5066282746310005
21     x = xx - 1.0
22     t = x + 5.5
23     t = t - (x + 0.5) * torch.log(t)
24     ser = Variable(torch.ones(x.size()).type(ttype)) * magic1
25     for c in gamma_coeff:
26         x = x + 1.0
27         ser = ser + torch.pow(x / c, -1)
28     return torch.log(ser * magic2) - t
29 
30 
31 def log_beta(t):
32     """
33     Computes log Beta function.
34 
35     :param t:
36     :type t: torch.autograd.Variable of dimension 1 or 2
37     :rtype: torch.autograd.Variable of float (if t.dim() == 1) or torch.Tensor (if t.dim() == 2)
38     """
39     assert t.dim() in (1, 2)
40     if t.dim() == 1:
41         numer = torch.sum(log_gamma(t))
42         denom = log_gamma(torch.sum(t))
43     else:
44         numer = torch.sum(log_gamma(t), 1)
45         denom = log_gamma(torch.sum(t, 1))
46     return numer - denom
47 
48 
49 def move_to_same_host_as(source, destin):
50     """
51     Returns source or a copy of `source` such that `source.is_cuda == `destin.is_cuda`.
52     """
53     return source.cuda() if destin.is_cuda else source.cpu()
54 
55 
56 def torch_zeros_like(x):
57     """
58     Polyfill for `torch.zeros_like()`.
59     """
60     # Work around https://github.com/pytorch/pytorch/issues/2906
61     if isinstance(x, Variable):
62         return Variable(torch_zeros_like(x.data))
63     # Support Pytorch before https://github.com/pytorch/pytorch/pull/2489
64     try:
65         return torch.zeros_like(x)
66     except AttributeError:
67         return torch.zeros(x.size()).type_as(x)
68 
69 
70 def torch_ones_like(x):
71     """
72     Polyfill for `torch.ones_like()`.
73     """
74     # Work around https://github.com/pytorch/pytorch/issues/2906
75     if isinstance(x, Variable):
76         return Variable(torch_ones_like(x.data))
77     # Support Pytorch before https://github.com/pytorch/pytorch/pull/2489
78     try:
79         return torch.ones_like(x)
80     except AttributeError:
81         return torch.ones(x.size()).type_as(x)
82 
83 
84 def torch_eye(n, m=None, out=None):
85     """
86     Like `torch.eye()`, but works with cuda tensors.
87     """
88     if m is None:
89         m = n
90     try:
91         return torch.eye(n, m, out=out)
92     except TypeError:
93         # Only catch errors due to torch.eye() not being availble for cuda tensors.
94         module = torch.Tensor.__module__ if out is None else type(out).__module__
95         if module != 'torch.cuda':
96             raise
97     Tensor = getattr(torch, torch.Tensor.__name__)
98     cpu_out = Tensor(n, m)
99     cuda_out = torch.eye(m, n, out=cpu_out).cuda()
100     return cuda_out if out is None else out.copy_(cuda_out)
101 
102 
103 def torch_multinomial(input, num_samples, replacement=False):
104     """
105     Like `torch.multinomial()` but works with cuda tensors.
106     Does not support keyword argument `out`.
107     """
108     if input.is_cuda:
109         return torch_multinomial(input.cpu(), num_samples, replacement).cuda()
110     else:
111         return torch.multinomial(input, num_samples, replacement)
112 
113 
114 def softmax(x, dim=-1):
115     """
116     TODO: change to use the default pyTorch implementation when available
117     Source: https://discuss.pytorch.org/t/why-softmax-function-cant-specify-the-dimension-to-operate/2637
118     :param x: tensor
119     :param dim: Dimension to apply the softmax function to. The elements of the tensor in this
120         dimension must sum to 1.
121     :return: tensor having the same dimension as `x` rescaled along dim
122     """
123     input_size = x.size()
124 
125     trans_input = x.transpose(dim, len(input_size) - 1)
126     trans_size = trans_input.size()
127 
128     input_2d = trans_input.contiguous().view(-1, trans_size[-1])
129 
130     soft_max_2d = F.softmax(input_2d)
131 
132     soft_max_nd = soft_max_2d.view(*trans_size)
133     return soft_max_nd.transpose(dim, len(input_size) - 1)
134 
135 
136 def get_probs_and_logits(ps=None, logits=None, is_multidimensional=True):
137     """
138     Convert probability values to logits, or vice-versa. Either `ps` or
139     `logits` should be specified, but not both.
140 
141     :param ps: tensor of probabilities. Should be in the interval *[0, 1]*.
142         If, `is_multidimensional = True`, then must be normalized along
143         axis -1.
144     :param logits: tensor of logit values.
145     :param is_multidimensional: determines the computation of ps from logits,
146         and vice-versa. For the multi-dimensional case, logit values are
147         assumed to be non-normalized log probabilities, whereas for the uni-
148         dimensional case, it specifically refers to log odds.
149     :return: tuple containing raw probabilities and logits as tensors
150     """
151     assert (ps is None) != (logits is None)
152     if is_multidimensional:
153         if ps is None:
154             ps = softmax(logits, -1)
155         else:
156             logits = torch.log(ps)
157     else:
158         if ps is None:
159             ps = F.sigmoid(logits)
160         else:
161             logits = torch.log(ps) - torch.log1p(-ps)
162     return ps, logits
163
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pyro/distributions/util.py b/pyro/distributions/util.py
--- a/pyro/distributions/util.py
+++ b/pyro/distributions/util.py
@@ -133,6 +133,15 @@
     return soft_max_nd.transpose(dim, len(input_size) - 1)
 
 
+def _get_clamping_buffer(tensor):
+    clamp_eps = 1e-6
+    if isinstance(tensor, Variable):
+        tensor = tensor.data
+    if isinstance(tensor, (torch.DoubleTensor, torch.cuda.DoubleTensor)):
+        clamp_eps = 1e-15
+    return clamp_eps
+
+
 def get_probs_and_logits(ps=None, logits=None, is_multidimensional=True):
     """
     Convert probability values to logits, or vice-versa. Either `ps` or
@@ -149,14 +158,17 @@
     :return: tuple containing raw probabilities and logits as tensors
     """
     assert (ps is None) != (logits is None)
+    if ps is not None:
+        eps = _get_clamping_buffer(ps)
+        ps_clamped = ps.clamp(min=eps, max=1 - eps)
     if is_multidimensional:
         if ps is None:
             ps = softmax(logits, -1)
         else:
-            logits = torch.log(ps)
+            logits = torch.log(ps_clamped)
     else:
         if ps is None:
             ps = F.sigmoid(logits)
         else:
-            logits = torch.log(ps) - torch.log1p(-ps)
+            logits = torch.log(ps_clamped) - torch.log1p(-ps_clamped)
     return ps, logits

{"golden_diff": "diff --git a/pyro/distributions/util.py b/pyro/distributions/util.py\n--- a/pyro/distributions/util.py\n+++ b/pyro/distributions/util.py\n@@ -133,6 +133,15 @@\n     return soft_max_nd.transpose(dim, len(input_size) - 1)\n \n \n+def _get_clamping_buffer(tensor):\n+    clamp_eps = 1e-6\n+    if isinstance(tensor, Variable):\n+        tensor = tensor.data\n+    if isinstance(tensor, (torch.DoubleTensor, torch.cuda.DoubleTensor)):\n+        clamp_eps = 1e-15\n+    return clamp_eps\n+\n+\n def get_probs_and_logits(ps=None, logits=None, is_multidimensional=True):\n     \"\"\"\n     Convert probability values to logits, or vice-versa. Either `ps` or\n@@ -149,14 +158,17 @@\n     :return: tuple containing raw probabilities and logits as tensors\n     \"\"\"\n     assert (ps is None) != (logits is None)\n+    if ps is not None:\n+        eps = _get_clamping_buffer(ps)\n+        ps_clamped = ps.clamp(min=eps, max=1 - eps)\n     if is_multidimensional:\n         if ps is None:\n             ps = softmax(logits, -1)\n         else:\n-            logits = torch.log(ps)\n+            logits = torch.log(ps_clamped)\n     else:\n         if ps is None:\n             ps = F.sigmoid(logits)\n         else:\n-            logits = torch.log(ps) - torch.log1p(-ps)\n+            logits = torch.log(ps_clamped) - torch.log1p(-ps_clamped)\n     return ps, logits\n", "issue": "New Bernoulli parameterization lead to subtle bug in AIR model\nWhen I merged #416 into a local branch it broke the AIR example.\r\n\r\nHere's a simplified instance of the problem:\r\n\r\n```python\r\nimport torch\r\nfrom torch.autograd import Variable\r\nfrom pyro.distributions import Bernoulli\r\nfrom torch.nn.functional import sigmoid\r\n\r\np = Variable(torch.Tensor([0]), requires_grad=True)\r\nb = Bernoulli(sigmoid(p) * 0.0)\r\nlog_pdf = b.batch_log_pdf(Variable(torch.Tensor([0])))\r\nlog_pdf.sum().backward()\r\nprint(p.grad)\r\n```\r\n\r\nPrior to #416 this returned a `grad` of zero as expected, but it now returns `nan`:\r\n\r\n```\r\npyro$ git rev-parse --short HEAD\r\n71bca18\r\npyro$ python3 bern.py \r\nVariable containing:\r\n-0\r\n[torch.FloatTensor of size 1]\r\n\r\npyro$ git rev-parse --short HEAD\r\na85525a\r\npyro$ python3 bern.py \r\nVariable containing:\r\nnan\r\n[torch.FloatTensor of size 1]\r\n```\r\n\r\nI suspect that the problem is that converting between probabilities and log odds introduces an intemediate `-inf`, which messes up autograd.\r\n\r\nI may be able to adjust the model to work around this, but either way, should this be considered a bug? (It seems like it could trip other people up, and chasing down the source of the `nan`s is tricky.)\r\n\n", "before_files": [{"content": "import torch\nimport torch.nn.functional as F\nfrom torch.autograd import Variable\n\n\ndef log_gamma(xx):\n    if isinstance(xx, Variable):\n        ttype = xx.data.type()\n    elif isinstance(xx, torch.Tensor):\n        ttype = xx.type()\n    gamma_coeff = [\n        76.18009172947146,\n        -86.50532032941677,\n        24.01409824083091,\n        -1.231739572450155,\n        0.1208650973866179e-2,\n        -0.5395239384953e-5,\n    ]\n    magic1 = 1.000000000190015\n    magic2 = 2.5066282746310005\n    x = xx - 1.0\n    t = x + 5.5\n    t = t - (x + 0.5) * torch.log(t)\n    ser = Variable(torch.ones(x.size()).type(ttype)) * magic1\n    for c in gamma_coeff:\n        x = x + 1.0\n        ser = ser + torch.pow(x / c, -1)\n    return torch.log(ser * magic2) - t\n\n\ndef log_beta(t):\n    \"\"\"\n    Computes log Beta function.\n\n    :param t:\n    :type t: torch.autograd.Variable of dimension 1 or 2\n    :rtype: torch.autograd.Variable of float (if t.dim() == 1) or torch.Tensor (if t.dim() == 2)\n    \"\"\"\n    assert t.dim() in (1, 2)\n    if t.dim() == 1:\n        numer = torch.sum(log_gamma(t))\n        denom = log_gamma(torch.sum(t))\n    else:\n        numer = torch.sum(log_gamma(t), 1)\n        denom = log_gamma(torch.sum(t, 1))\n    return numer - denom\n\n\ndef move_to_same_host_as(source, destin):\n    \"\"\"\n    Returns source or a copy of `source` such that `source.is_cuda == `destin.is_cuda`.\n    \"\"\"\n    return source.cuda() if destin.is_cuda else source.cpu()\n\n\ndef torch_zeros_like(x):\n    \"\"\"\n    Polyfill for `torch.zeros_like()`.\n    \"\"\"\n    # Work around https://github.com/pytorch/pytorch/issues/2906\n    if isinstance(x, Variable):\n        return Variable(torch_zeros_like(x.data))\n    # Support Pytorch before https://github.com/pytorch/pytorch/pull/2489\n    try:\n        return torch.zeros_like(x)\n    except AttributeError:\n        return torch.zeros(x.size()).type_as(x)\n\n\ndef torch_ones_like(x):\n    \"\"\"\n    Polyfill for `torch.ones_like()`.\n    \"\"\"\n    # Work around https://github.com/pytorch/pytorch/issues/2906\n    if isinstance(x, Variable):\n        return Variable(torch_ones_like(x.data))\n    # Support Pytorch before https://github.com/pytorch/pytorch/pull/2489\n    try:\n        return torch.ones_like(x)\n    except AttributeError:\n        return torch.ones(x.size()).type_as(x)\n\n\ndef torch_eye(n, m=None, out=None):\n    \"\"\"\n    Like `torch.eye()`, but works with cuda tensors.\n    \"\"\"\n    if m is None:\n        m = n\n    try:\n        return torch.eye(n, m, out=out)\n    except TypeError:\n        # Only catch errors due to torch.eye() not being availble for cuda tensors.\n        module = torch.Tensor.__module__ if out is None else type(out).__module__\n        if module != 'torch.cuda':\n            raise\n    Tensor = getattr(torch, torch.Tensor.__name__)\n    cpu_out = Tensor(n, m)\n    cuda_out = torch.eye(m, n, out=cpu_out).cuda()\n    return cuda_out if out is None else out.copy_(cuda_out)\n\n\ndef torch_multinomial(input, num_samples, replacement=False):\n    \"\"\"\n    Like `torch.multinomial()` but works with cuda tensors.\n    Does not support keyword argument `out`.\n    \"\"\"\n    if input.is_cuda:\n        return torch_multinomial(input.cpu(), num_samples, replacement).cuda()\n    else:\n        return torch.multinomial(input, num_samples, replacement)\n\n\ndef softmax(x, dim=-1):\n    \"\"\"\n    TODO: change to use the default pyTorch implementation when available\n    Source: https://discuss.pytorch.org/t/why-softmax-function-cant-specify-the-dimension-to-operate/2637\n    :param x: tensor\n    :param dim: Dimension to apply the softmax function to. The elements of the tensor in this\n        dimension must sum to 1.\n    :return: tensor having the same dimension as `x` rescaled along dim\n    \"\"\"\n    input_size = x.size()\n\n    trans_input = x.transpose(dim, len(input_size) - 1)\n    trans_size = trans_input.size()\n\n    input_2d = trans_input.contiguous().view(-1, trans_size[-1])\n\n    soft_max_2d = F.softmax(input_2d)\n\n    soft_max_nd = soft_max_2d.view(*trans_size)\n    return soft_max_nd.transpose(dim, len(input_size) - 1)\n\n\ndef get_probs_and_logits(ps=None, logits=None, is_multidimensional=True):\n    \"\"\"\n    Convert probability values to logits, or vice-versa. Either `ps` or\n    `logits` should be specified, but not both.\n\n    :param ps: tensor of probabilities. Should be in the interval *[0, 1]*.\n        If, `is_multidimensional = True`, then must be normalized along\n        axis -1.\n    :param logits: tensor of logit values.\n    :param is_multidimensional: determines the computation of ps from logits,\n        and vice-versa. For the multi-dimensional case, logit values are\n        assumed to be non-normalized log probabilities, whereas for the uni-\n        dimensional case, it specifically refers to log odds.\n    :return: tuple containing raw probabilities and logits as tensors\n    \"\"\"\n    assert (ps is None) != (logits is None)\n    if is_multidimensional:\n        if ps is None:\n            ps = softmax(logits, -1)\n        else:\n            logits = torch.log(ps)\n    else:\n        if ps is None:\n            ps = F.sigmoid(logits)\n        else:\n            logits = torch.log(ps) - torch.log1p(-ps)\n    return ps, logits\n", "path": "pyro/distributions/util.py"}], "after_files": [{"content": "import torch\nimport torch.nn.functional as F\nfrom torch.autograd import Variable\n\n\ndef log_gamma(xx):\n    if isinstance(xx, Variable):\n        ttype = xx.data.type()\n    elif isinstance(xx, torch.Tensor):\n        ttype = xx.type()\n    gamma_coeff = [\n        76.18009172947146,\n        -86.50532032941677,\n        24.01409824083091,\n        -1.231739572450155,\n        0.1208650973866179e-2,\n        -0.5395239384953e-5,\n    ]\n    magic1 = 1.000000000190015\n    magic2 = 2.5066282746310005\n    x = xx - 1.0\n    t = x + 5.5\n    t = t - (x + 0.5) * torch.log(t)\n    ser = Variable(torch.ones(x.size()).type(ttype)) * magic1\n    for c in gamma_coeff:\n        x = x + 1.0\n        ser = ser + torch.pow(x / c, -1)\n    return torch.log(ser * magic2) - t\n\n\ndef log_beta(t):\n    \"\"\"\n    Computes log Beta function.\n\n    :param t:\n    :type t: torch.autograd.Variable of dimension 1 or 2\n    :rtype: torch.autograd.Variable of float (if t.dim() == 1) or torch.Tensor (if t.dim() == 2)\n    \"\"\"\n    assert t.dim() in (1, 2)\n    if t.dim() == 1:\n        numer = torch.sum(log_gamma(t))\n        denom = log_gamma(torch.sum(t))\n    else:\n        numer = torch.sum(log_gamma(t), 1)\n        denom = log_gamma(torch.sum(t, 1))\n    return numer - denom\n\n\ndef move_to_same_host_as(source, destin):\n    \"\"\"\n    Returns source or a copy of `source` such that `source.is_cuda == `destin.is_cuda`.\n    \"\"\"\n    return source.cuda() if destin.is_cuda else source.cpu()\n\n\ndef torch_zeros_like(x):\n    \"\"\"\n    Polyfill for `torch.zeros_like()`.\n    \"\"\"\n    # Work around https://github.com/pytorch/pytorch/issues/2906\n    if isinstance(x, Variable):\n        return Variable(torch_zeros_like(x.data))\n    # Support Pytorch before https://github.com/pytorch/pytorch/pull/2489\n    try:\n        return torch.zeros_like(x)\n    except AttributeError:\n        return torch.zeros(x.size()).type_as(x)\n\n\ndef torch_ones_like(x):\n    \"\"\"\n    Polyfill for `torch.ones_like()`.\n    \"\"\"\n    # Work around https://github.com/pytorch/pytorch/issues/2906\n    if isinstance(x, Variable):\n        return Variable(torch_ones_like(x.data))\n    # Support Pytorch before https://github.com/pytorch/pytorch/pull/2489\n    try:\n        return torch.ones_like(x)\n    except AttributeError:\n        return torch.ones(x.size()).type_as(x)\n\n\ndef torch_eye(n, m=None, out=None):\n    \"\"\"\n    Like `torch.eye()`, but works with cuda tensors.\n    \"\"\"\n    if m is None:\n        m = n\n    try:\n        return torch.eye(n, m, out=out)\n    except TypeError:\n        # Only catch errors due to torch.eye() not being availble for cuda tensors.\n        module = torch.Tensor.__module__ if out is None else type(out).__module__\n        if module != 'torch.cuda':\n            raise\n    Tensor = getattr(torch, torch.Tensor.__name__)\n    cpu_out = Tensor(n, m)\n    cuda_out = torch.eye(m, n, out=cpu_out).cuda()\n    return cuda_out if out is None else out.copy_(cuda_out)\n\n\ndef torch_multinomial(input, num_samples, replacement=False):\n    \"\"\"\n    Like `torch.multinomial()` but works with cuda tensors.\n    Does not support keyword argument `out`.\n    \"\"\"\n    if input.is_cuda:\n        return torch_multinomial(input.cpu(), num_samples, replacement).cuda()\n    else:\n        return torch.multinomial(input, num_samples, replacement)\n\n\ndef softmax(x, dim=-1):\n    \"\"\"\n    TODO: change to use the default pyTorch implementation when available\n    Source: https://discuss.pytorch.org/t/why-softmax-function-cant-specify-the-dimension-to-operate/2637\n    :param x: tensor\n    :param dim: Dimension to apply the softmax function to. The elements of the tensor in this\n        dimension must sum to 1.\n    :return: tensor having the same dimension as `x` rescaled along dim\n    \"\"\"\n    input_size = x.size()\n\n    trans_input = x.transpose(dim, len(input_size) - 1)\n    trans_size = trans_input.size()\n\n    input_2d = trans_input.contiguous().view(-1, trans_size[-1])\n\n    soft_max_2d = F.softmax(input_2d)\n\n    soft_max_nd = soft_max_2d.view(*trans_size)\n    return soft_max_nd.transpose(dim, len(input_size) - 1)\n\n\ndef _get_clamping_buffer(tensor):\n    clamp_eps = 1e-6\n    if isinstance(tensor, Variable):\n        tensor = tensor.data\n    if isinstance(tensor, (torch.DoubleTensor, torch.cuda.DoubleTensor)):\n        clamp_eps = 1e-15\n    return clamp_eps\n\n\ndef get_probs_and_logits(ps=None, logits=None, is_multidimensional=True):\n    \"\"\"\n    Convert probability values to logits, or vice-versa. Either `ps` or\n    `logits` should be specified, but not both.\n\n    :param ps: tensor of probabilities. Should be in the interval *[0, 1]*.\n        If, `is_multidimensional = True`, then must be normalized along\n        axis -1.\n    :param logits: tensor of logit values.\n    :param is_multidimensional: determines the computation of ps from logits,\n        and vice-versa. For the multi-dimensional case, logit values are\n        assumed to be non-normalized log probabilities, whereas for the uni-\n        dimensional case, it specifically refers to log odds.\n    :return: tuple containing raw probabilities and logits as tensors\n    \"\"\"\n    assert (ps is None) != (logits is None)\n    if ps is not None:\n        eps = _get_clamping_buffer(ps)\n        ps_clamped = ps.clamp(min=eps, max=1 - eps)\n    if is_multidimensional:\n        if ps is None:\n            ps = softmax(logits, -1)\n        else:\n            logits = torch.log(ps_clamped)\n    else:\n        if ps is None:\n            ps = F.sigmoid(logits)\n        else:\n            logits = torch.log(ps_clamped) - torch.log1p(-ps_clamped)\n    return ps, logits\n", "path": "pyro/distributions/util.py"}]}