We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Incorrect result from Delta's batch_log_pdf
It looks like there may be a bug in Delta's `batch_log_pdf` method. When the value we're computing the log prob of doesn't match the parameter I expect `batch_log_pdf` to return `-inf` but it doesn't. For example:

```
x = Variable(torch.Tensor([[1.0]]))
y = Variable(torch.Tensor([[2.0]]))

# This is OK, it returns zero as expected:
print(Delta(x).batch_log_pdf(x))

# Here I expect -inf, but get 2.5500e+08
print(Delta(x).batch_log_pdf(y))
```

`log_pdf` works as expected.

(This isn't high priority for me.)

--- 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/__init__.py`
Content:
```
1 # abstract base class
2 from pyro.distributions.bernoulli import Bernoulli
3 from pyro.distributions.beta import Beta
4 from pyro.distributions.categorical import Categorical
5 from pyro.distributions.cauchy import Cauchy
6 from pyro.distributions.half_cauchy import HalfCauchy
7 from pyro.distributions.delta import Delta
8 from pyro.distributions.distribution import Distribution  # noqa: F401
9 # specific distributions
10 from pyro.distributions.diag_normal import DiagNormal
11 from pyro.distributions.dirichlet import Dirichlet
12 from pyro.distributions.exponential import Exponential
13 from pyro.distributions.gamma import Gamma
14 from pyro.distributions.log_normal import LogNormal
15 from pyro.distributions.multinomial import Multinomial
16 from pyro.distributions.poisson import Poisson
17 from pyro.distributions.random_primitive import RandomPrimitive
18 from pyro.distributions.uniform import Uniform
19 
20 # function aliases
21 diagnormal = DiagNormal()
22 lognormal = RandomPrimitive(LogNormal)
23 categorical = Categorical()
24 bernoulli = RandomPrimitive(Bernoulli)
25 beta = RandomPrimitive(Beta)
26 delta = Delta()
27 exponential = RandomPrimitive(Exponential)
28 gamma = RandomPrimitive(Gamma)
29 multinomial = RandomPrimitive(Multinomial)
30 poisson = RandomPrimitive(Poisson)
31 uniform = RandomPrimitive(Uniform)
32 dirichlet = RandomPrimitive(Dirichlet)
33 cauchy = RandomPrimitive(Cauchy)
34 halfcauchy = RandomPrimitive(HalfCauchy)
35
```

Path: `pyro/distributions/delta.py`
Content:
```
1 import torch
2 from torch.autograd import Variable
3 
4 from pyro.distributions.distribution import Distribution
5 
6 
7 class Delta(Distribution):
8     """
9     :param v: support element *(any)*
10 
11     Discrete distribution that assigns probability one to the single element in
12     its support. Delta distribution parameterized by a random choice should not
13     be used with MCMC based inference, as doing so produces incorrect results.
14     """
15     enumerable = True
16 
17     def _sanitize_input(self, v):
18         if v is not None:
19             # stateless distribution
20             return v
21         elif self.v is not None:
22             # stateful distribution
23             return self.v
24         else:
25             raise ValueError("Parameter(s) were None")
26 
27     def __init__(self, v=None, batch_size=1, *args, **kwargs):
28         """
29         Params:
30           `v` - value
31         """
32         self.v = v
33         if v is not None:
34             if v.dim() == 1 and batch_size > 1:
35                 self.v = v.expand(v, v.size(0))
36         super(Delta, self).__init__(*args, **kwargs)
37 
38     def sample(self, v=None):
39         v = self._sanitize_input(v)
40         if isinstance(v, Variable):
41             return v
42         return Variable(v)
43 
44     def batch_log_pdf(self, x, v=None, batch_size=1):
45         v = self._sanitize_input(v)
46         if x.dim == 1:
47             x = x.expand(batch_size, x.size(0))
48         return (torch.eq(x, v.expand_as(x)) - 1).float() * 999999
49 
50     def log_pdf(self, x, v=None, *args, **kwargs):
51         v = self._sanitize_input(v)
52         if torch.equal(x.data, v.data.expand_as(x.data)):
53             return Variable(torch.zeros(1).type_as(v.data))
54         return Variable(torch.Tensor([-float("inf")]).type_as(v.data))
55 
56     def support(self, v=None):
57         """
58         Returns the delta distribution's support, as a tensor along the first dimension.
59 
60         :param v: torch variable where each element of the tensor represents the point at
61             which the delta distribution is concentrated.
62         :return: torch variable enumerating the support of the delta distribution.
63         :rtype: torch.autograd.Variable.
64         """
65         v = self._sanitize_input(v)
66         # univariate case
67         return Variable(v.data)
68
```
--- 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/__init__.py b/pyro/distributions/__init__.py
--- a/pyro/distributions/__init__.py
+++ b/pyro/distributions/__init__.py
@@ -23,7 +23,7 @@
 categorical = Categorical()
 bernoulli = RandomPrimitive(Bernoulli)
 beta = RandomPrimitive(Beta)
-delta = Delta()
+delta = RandomPrimitive(Delta)
 exponential = RandomPrimitive(Exponential)
 gamma = RandomPrimitive(Gamma)
 multinomial = RandomPrimitive(Multinomial)
diff --git a/pyro/distributions/delta.py b/pyro/distributions/delta.py
--- a/pyro/distributions/delta.py
+++ b/pyro/distributions/delta.py
@@ -14,44 +14,40 @@
     """
     enumerable = True
 
-    def _sanitize_input(self, v):
-        if v is not None:
-            # stateless distribution
-            return v
-        elif self.v is not None:
-            # stateful distribution
-            return self.v
-        else:
-            raise ValueError("Parameter(s) were None")
-
-    def __init__(self, v=None, batch_size=1, *args, **kwargs):
+    def __init__(self, v, batch_size=None, *args, **kwargs):
         """
         Params:
           `v` - value
         """
         self.v = v
-        if v is not None:
-            if v.dim() == 1 and batch_size > 1:
-                self.v = v.expand(v, v.size(0))
+        if not isinstance(self.v, Variable):
+            self.v = Variable(self.v)
+        if v.dim() == 1 and batch_size is not None:
+            self.v = v.expand(v, v.size(0))
         super(Delta, self).__init__(*args, **kwargs)
 
-    def sample(self, v=None):
-        v = self._sanitize_input(v)
-        if isinstance(v, Variable):
-            return v
-        return Variable(v)
+    def batch_shape(self, x=None):
+        event_dim = 1
+        v = self.v
+        if x is not None and x.size() != v.size():
+            v = self.v.expand_as(x)
+        return v.size()[:-event_dim]
+
+    def event_shape(self):
+        event_dim = 1
+        return self.v.size()[-event_dim:]
+
+    def shape(self, x=None):
+        return self.batch_shape(x) + self.event_shape()
 
-    def batch_log_pdf(self, x, v=None, batch_size=1):
-        v = self._sanitize_input(v)
-        if x.dim == 1:
-            x = x.expand(batch_size, x.size(0))
-        return (torch.eq(x, v.expand_as(x)) - 1).float() * 999999
+    def sample(self):
+        return self.v
 
-    def log_pdf(self, x, v=None, *args, **kwargs):
-        v = self._sanitize_input(v)
-        if torch.equal(x.data, v.data.expand_as(x.data)):
-            return Variable(torch.zeros(1).type_as(v.data))
-        return Variable(torch.Tensor([-float("inf")]).type_as(v.data))
+    def batch_log_pdf(self, x):
+        v = self.v
+        if x.size() != v.size():
+            v = v.expand_as(x)
+        return torch.sum(torch.eq(x, v).float().log(), -1)
 
     def support(self, v=None):
         """
@@ -62,6 +58,4 @@
         :return: torch variable enumerating the support of the delta distribution.
         :rtype: torch.autograd.Variable.
         """
-        v = self._sanitize_input(v)
-        # univariate case
-        return Variable(v.data)
+        return Variable(self.v.data)

{"golden_diff": "diff --git a/pyro/distributions/__init__.py b/pyro/distributions/__init__.py\n--- a/pyro/distributions/__init__.py\n+++ b/pyro/distributions/__init__.py\n@@ -23,7 +23,7 @@\n categorical = Categorical()\n bernoulli = RandomPrimitive(Bernoulli)\n beta = RandomPrimitive(Beta)\n-delta = Delta()\n+delta = RandomPrimitive(Delta)\n exponential = RandomPrimitive(Exponential)\n gamma = RandomPrimitive(Gamma)\n multinomial = RandomPrimitive(Multinomial)\ndiff --git a/pyro/distributions/delta.py b/pyro/distributions/delta.py\n--- a/pyro/distributions/delta.py\n+++ b/pyro/distributions/delta.py\n@@ -14,44 +14,40 @@\n     \"\"\"\n     enumerable = True\n \n-    def _sanitize_input(self, v):\n-        if v is not None:\n-            # stateless distribution\n-            return v\n-        elif self.v is not None:\n-            # stateful distribution\n-            return self.v\n-        else:\n-            raise ValueError(\"Parameter(s) were None\")\n-\n-    def __init__(self, v=None, batch_size=1, *args, **kwargs):\n+    def __init__(self, v, batch_size=None, *args, **kwargs):\n         \"\"\"\n         Params:\n           `v` - value\n         \"\"\"\n         self.v = v\n-        if v is not None:\n-            if v.dim() == 1 and batch_size > 1:\n-                self.v = v.expand(v, v.size(0))\n+        if not isinstance(self.v, Variable):\n+            self.v = Variable(self.v)\n+        if v.dim() == 1 and batch_size is not None:\n+            self.v = v.expand(v, v.size(0))\n         super(Delta, self).__init__(*args, **kwargs)\n \n-    def sample(self, v=None):\n-        v = self._sanitize_input(v)\n-        if isinstance(v, Variable):\n-            return v\n-        return Variable(v)\n+    def batch_shape(self, x=None):\n+        event_dim = 1\n+        v = self.v\n+        if x is not None and x.size() != v.size():\n+            v = self.v.expand_as(x)\n+        return v.size()[:-event_dim]\n+\n+    def event_shape(self):\n+        event_dim = 1\n+        return self.v.size()[-event_dim:]\n+\n+    def shape(self, x=None):\n+        return self.batch_shape(x) + self.event_shape()\n \n-    def batch_log_pdf(self, x, v=None, batch_size=1):\n-        v = self._sanitize_input(v)\n-        if x.dim == 1:\n-            x = x.expand(batch_size, x.size(0))\n-        return (torch.eq(x, v.expand_as(x)) - 1).float() * 999999\n+    def sample(self):\n+        return self.v\n \n-    def log_pdf(self, x, v=None, *args, **kwargs):\n-        v = self._sanitize_input(v)\n-        if torch.equal(x.data, v.data.expand_as(x.data)):\n-            return Variable(torch.zeros(1).type_as(v.data))\n-        return Variable(torch.Tensor([-float(\"inf\")]).type_as(v.data))\n+    def batch_log_pdf(self, x):\n+        v = self.v\n+        if x.size() != v.size():\n+            v = v.expand_as(x)\n+        return torch.sum(torch.eq(x, v).float().log(), -1)\n \n     def support(self, v=None):\n         \"\"\"\n@@ -62,6 +58,4 @@\n         :return: torch variable enumerating the support of the delta distribution.\n         :rtype: torch.autograd.Variable.\n         \"\"\"\n-        v = self._sanitize_input(v)\n-        # univariate case\n-        return Variable(v.data)\n+        return Variable(self.v.data)\n", "issue": "Incorrect result from Delta's batch_log_pdf\nIt looks like there may be a bug in Delta's `batch_log_pdf` method. When the value we're computing the log prob of doesn't match the parameter I expect `batch_log_pdf` to return `-inf` but it doesn't. For example:\r\n\r\n```\r\nx = Variable(torch.Tensor([[1.0]]))\r\ny = Variable(torch.Tensor([[2.0]]))\r\n\r\n# This is OK, it returns zero as expected:\r\nprint(Delta(x).batch_log_pdf(x))\r\n\r\n# Here I expect -inf, but get 2.5500e+08\r\nprint(Delta(x).batch_log_pdf(y))\r\n```\r\n\r\n`log_pdf` works as expected.\r\n\r\n(This isn't high priority for me.)\n", "before_files": [{"content": "# abstract base class\nfrom pyro.distributions.bernoulli import Bernoulli\nfrom pyro.distributions.beta import Beta\nfrom pyro.distributions.categorical import Categorical\nfrom pyro.distributions.cauchy import Cauchy\nfrom pyro.distributions.half_cauchy import HalfCauchy\nfrom pyro.distributions.delta import Delta\nfrom pyro.distributions.distribution import Distribution  # noqa: F401\n# specific distributions\nfrom pyro.distributions.diag_normal import DiagNormal\nfrom pyro.distributions.dirichlet import Dirichlet\nfrom pyro.distributions.exponential import Exponential\nfrom pyro.distributions.gamma import Gamma\nfrom pyro.distributions.log_normal import LogNormal\nfrom pyro.distributions.multinomial import Multinomial\nfrom pyro.distributions.poisson import Poisson\nfrom pyro.distributions.random_primitive import RandomPrimitive\nfrom pyro.distributions.uniform import Uniform\n\n# function aliases\ndiagnormal = DiagNormal()\nlognormal = RandomPrimitive(LogNormal)\ncategorical = Categorical()\nbernoulli = RandomPrimitive(Bernoulli)\nbeta = RandomPrimitive(Beta)\ndelta = Delta()\nexponential = RandomPrimitive(Exponential)\ngamma = RandomPrimitive(Gamma)\nmultinomial = RandomPrimitive(Multinomial)\npoisson = RandomPrimitive(Poisson)\nuniform = RandomPrimitive(Uniform)\ndirichlet = RandomPrimitive(Dirichlet)\ncauchy = RandomPrimitive(Cauchy)\nhalfcauchy = RandomPrimitive(HalfCauchy)\n", "path": "pyro/distributions/__init__.py"}, {"content": "import torch\nfrom torch.autograd import Variable\n\nfrom pyro.distributions.distribution import Distribution\n\n\nclass Delta(Distribution):\n    \"\"\"\n    :param v: support element *(any)*\n\n    Discrete distribution that assigns probability one to the single element in\n    its support. Delta distribution parameterized by a random choice should not\n    be used with MCMC based inference, as doing so produces incorrect results.\n    \"\"\"\n    enumerable = True\n\n    def _sanitize_input(self, v):\n        if v is not None:\n            # stateless distribution\n            return v\n        elif self.v is not None:\n            # stateful distribution\n            return self.v\n        else:\n            raise ValueError(\"Parameter(s) were None\")\n\n    def __init__(self, v=None, batch_size=1, *args, **kwargs):\n        \"\"\"\n        Params:\n          `v` - value\n        \"\"\"\n        self.v = v\n        if v is not None:\n            if v.dim() == 1 and batch_size > 1:\n                self.v = v.expand(v, v.size(0))\n        super(Delta, self).__init__(*args, **kwargs)\n\n    def sample(self, v=None):\n        v = self._sanitize_input(v)\n        if isinstance(v, Variable):\n            return v\n        return Variable(v)\n\n    def batch_log_pdf(self, x, v=None, batch_size=1):\n        v = self._sanitize_input(v)\n        if x.dim == 1:\n            x = x.expand(batch_size, x.size(0))\n        return (torch.eq(x, v.expand_as(x)) - 1).float() * 999999\n\n    def log_pdf(self, x, v=None, *args, **kwargs):\n        v = self._sanitize_input(v)\n        if torch.equal(x.data, v.data.expand_as(x.data)):\n            return Variable(torch.zeros(1).type_as(v.data))\n        return Variable(torch.Tensor([-float(\"inf\")]).type_as(v.data))\n\n    def support(self, v=None):\n        \"\"\"\n        Returns the delta distribution's support, as a tensor along the first dimension.\n\n        :param v: torch variable where each element of the tensor represents the point at\n            which the delta distribution is concentrated.\n        :return: torch variable enumerating the support of the delta distribution.\n        :rtype: torch.autograd.Variable.\n        \"\"\"\n        v = self._sanitize_input(v)\n        # univariate case\n        return Variable(v.data)\n", "path": "pyro/distributions/delta.py"}], "after_files": [{"content": "# abstract base class\nfrom pyro.distributions.bernoulli import Bernoulli\nfrom pyro.distributions.beta import Beta\nfrom pyro.distributions.categorical import Categorical\nfrom pyro.distributions.cauchy import Cauchy\nfrom pyro.distributions.half_cauchy import HalfCauchy\nfrom pyro.distributions.delta import Delta\nfrom pyro.distributions.distribution import Distribution  # noqa: F401\n# specific distributions\nfrom pyro.distributions.diag_normal import DiagNormal\nfrom pyro.distributions.dirichlet import Dirichlet\nfrom pyro.distributions.exponential import Exponential\nfrom pyro.distributions.gamma import Gamma\nfrom pyro.distributions.log_normal import LogNormal\nfrom pyro.distributions.multinomial import Multinomial\nfrom pyro.distributions.poisson import Poisson\nfrom pyro.distributions.random_primitive import RandomPrimitive\nfrom pyro.distributions.uniform import Uniform\n\n# function aliases\ndiagnormal = DiagNormal()\nlognormal = RandomPrimitive(LogNormal)\ncategorical = Categorical()\nbernoulli = RandomPrimitive(Bernoulli)\nbeta = RandomPrimitive(Beta)\ndelta = RandomPrimitive(Delta)\nexponential = RandomPrimitive(Exponential)\ngamma = RandomPrimitive(Gamma)\nmultinomial = RandomPrimitive(Multinomial)\npoisson = RandomPrimitive(Poisson)\nuniform = RandomPrimitive(Uniform)\ndirichlet = RandomPrimitive(Dirichlet)\ncauchy = RandomPrimitive(Cauchy)\nhalfcauchy = RandomPrimitive(HalfCauchy)\n", "path": "pyro/distributions/__init__.py"}, {"content": "import torch\nfrom torch.autograd import Variable\n\nfrom pyro.distributions.distribution import Distribution\n\n\nclass Delta(Distribution):\n    \"\"\"\n    :param v: support element *(any)*\n\n    Discrete distribution that assigns probability one to the single element in\n    its support. Delta distribution parameterized by a random choice should not\n    be used with MCMC based inference, as doing so produces incorrect results.\n    \"\"\"\n    enumerable = True\n\n    def __init__(self, v, batch_size=None, *args, **kwargs):\n        \"\"\"\n        Params:\n          `v` - value\n        \"\"\"\n        self.v = v\n        if not isinstance(self.v, Variable):\n            self.v = Variable(self.v)\n        if v.dim() == 1 and batch_size is not None:\n            self.v = v.expand(v, v.size(0))\n        super(Delta, self).__init__(*args, **kwargs)\n\n    def batch_shape(self, x=None):\n        event_dim = 1\n        v = self.v\n        if x is not None and x.size() != v.size():\n            v = self.v.expand_as(x)\n        return v.size()[:-event_dim]\n\n    def event_shape(self):\n        event_dim = 1\n        return self.v.size()[-event_dim:]\n\n    def shape(self, x=None):\n        return self.batch_shape(x) + self.event_shape()\n\n    def sample(self):\n        return self.v\n\n    def batch_log_pdf(self, x):\n        v = self.v\n        if x.size() != v.size():\n            v = v.expand_as(x)\n        return torch.sum(torch.eq(x, v).float().log(), -1)\n\n    def support(self, v=None):\n        \"\"\"\n        Returns the delta distribution's support, as a tensor along the first dimension.\n\n        :param v: torch variable where each element of the tensor represents the point at\n            which the delta distribution is concentrated.\n        :return: torch variable enumerating the support of the delta distribution.\n        :rtype: torch.autograd.Variable.\n        \"\"\"\n        return Variable(self.v.data)\n", "path": "pyro/distributions/delta.py"}]}