Repository: sbi-dev/sbi

Issue:
Issue with the transformation to unconstrained space with new sampler interface
Hey! 

I was trying to use a new sampler interface to sample from a conditional distribution and stumbled upon a problem with the transformation to unconstrained space. Shortly, when my uniform prior has only positive values, the potential for the conditional distribution returns only infs and the sampling doesn't work. 

Here is a minimal example to reproduce the problem:

```
num_dim = 4

prior = BoxUniform(low=[.1,.1,.1,.1], high=[4,4, 4,4])

def linear_gaussian(theta):
    return theta + 1.0 + torch.randn_like(theta) * 0.1

simulator, prior = prepare_for_sbi(linear_gaussian, prior)
inference = SNPE()
theta, x = simulate_for_sbi(simulator, prior, 1000)
posterior_estimator = inference.append_simulations(theta, x).train()

potential_fn, theta_transform = posterior_estimator_based_potential(
    posterior_estimator, prior=prior, x_o=torch.tensor([2,2,2,2])
)

from sbi.analysis import conditonal_potential
conditioned_potential_fn, restricted_tf, restricted_prior = conditonal_potential(
    potential_fn=potential_fn,
    theta_transform=theta_transform,
    prior=prior,
    condition=torch.as_tensor([.0, .0, .0, 1.0]), # the first three values are arbitrary and are ignored internally
    dims_to_sample=[0, 1, 2],
)

mcmc_posterior = MCMCPosterior(
    potential_fn=conditioned_potential_fn,
    theta_transform=None,
    proposal=restricted_prior,
)
cond_samples = mcmc_posterior.sample((100,))
```

The workaround I found so far is not to use the parameters transformation, but mb there is a more general solution.

```
from sbi.analysis.conditional_density import ConditionedPotential

condition=torch.as_tensor([.0, .0, .0, 1.0]).view(1,4)
transformed_condition = condition#theta_transform(condition) 
conditioned_potential_fn = ConditionedPotential(potential_fn, transformed_condition, [0,1,2])

mcmc_posterior = MCMCPosterior(
    potential_fn=conditioned_potential_fn,
    theta_transform=None,
    proposal=restricted_prior,
)
cond_samples = mcmc_posterior.sample((100,))
```


Discussion:

Resolving patch:
diff --git a/sbi/analysis/__init__.py b/sbi/analysis/__init__.py
--- a/sbi/analysis/__init__.py
+++ b/sbi/analysis/__init__.py
@@ -1,6 +1,7 @@
 from sbi.analysis.conditional_density import (
     ConditionedMDN,
     conditional_corrcoeff,
+    conditional_potential,
     conditonal_potential,
     eval_conditional_density,
 )
diff --git a/sbi/analysis/conditional_density.py b/sbi/analysis/conditional_density.py
--- a/sbi/analysis/conditional_density.py
+++ b/sbi/analysis/conditional_density.py
@@ -2,6 +2,7 @@
 # under the Affero General Public License v3, see <https://www.gnu.org/licenses/>.
 
 from typing import Any, Callable, List, Optional, Tuple, Union
+from warnings import warn
 
 import torch
 import torch.distributions.transforms as torch_tf
@@ -236,6 +237,28 @@ def conditonal_potential(
     prior: Distribution,
     condition: Tensor,
     dims_to_sample: List[int],
+) -> Tuple[Callable, torch_tf.Transform, Any]:
+    """
+    Only for backwards compatibility.
+
+    The name of this function was renamed until v0.19.0. (notice the missing `i` in
+    the name).
+    """
+    warn(
+        "The misspelled function `conditonal_potential` will be removed in a future "
+        "release of sbi. Please use `conditional_potential` (spelled correctly)."
+    )
+    return conditional_potential(
+        potential_fn, theta_transform, prior, condition, dims_to_sample
+    )
+
+
+def conditional_potential(
+    potential_fn: Callable,
+    theta_transform: TorchTransform,
+    prior: Distribution,
+    condition: Tensor,
+    dims_to_sample: List[int],
 ) -> Tuple[Callable, torch_tf.Transform, Any]:
     r"""Returns potential function that can be used to sample the conditional potential.
 
@@ -270,11 +293,8 @@ def conditonal_potential(
 
     condition = atleast_2d_float32_tensor(condition)
 
-    # Transform the `condition` to unconstrained space.
-    transformed_condition = theta_transform(condition)
-
     conditioned_potential_fn = ConditionedPotential(
-        potential_fn, transformed_condition, dims_to_sample  # type: ignore
+        potential_fn, condition, dims_to_sample  # type: ignore
     )
 
     restricted_prior = RestrictedPriorForConditional(prior, dims_to_sample)


Test patch:
diff --git a/tests/linearGaussian_snpe_test.py b/tests/linearGaussian_snpe_test.py
--- a/tests/linearGaussian_snpe_test.py
+++ b/tests/linearGaussian_snpe_test.py
@@ -12,7 +12,7 @@
 
 from sbi import analysis as analysis
 from sbi import utils as utils
-from sbi.analysis import ConditionedMDN, conditonal_potential
+from sbi.analysis import ConditionedMDN, conditional_potential
 from sbi.inference import (
     SNPE_A,
     SNPE_B,
@@ -468,7 +468,11 @@ def simulator(theta):
     potential_fn, theta_transform = posterior_estimator_based_potential(
         posterior_estimator, prior=prior, x_o=x_o
     )
-    (conditioned_potential_fn, restricted_tf, restricted_prior,) = conditonal_potential(
+    (
+        conditioned_potential_fn,
+        restricted_tf,
+        restricted_prior,
+    ) = conditional_potential(
         potential_fn=potential_fn,
         theta_transform=theta_transform,
         prior=prior,