Repository: ARM-software/mango

Issue:
Domain error in loguniform
Hi, 
seems that there is a problem with `loguniform` when one of its argument is negative. For example, my code is runnable when the first argument of `loguniform` is positive and it generates domain error when the first argument is a negative number. Any thought on this?


Comments:

Patch:
diff --git a/mango/domain/distribution.py b/mango/domain/distribution.py
index 4f5b69d..bb9e14d 100644
--- a/mango/domain/distribution.py
+++ b/mango/domain/distribution.py
@@ -1,49 +1,5 @@
-# Defining loguniform distribution
-"""
-Credits: Extended from the original definition of rvs function in scipy/scipy/stats/_distn_infrastructure.py
-for the class rv_generic and the _rvs function for the uniform distribution from
-scipy/scipy/stats/_continuous_distns.py
-"""
+from scipy.stats import loguniform as _loguniform
 
-from scipy.stats import rv_continuous
-import numpy as np
 
-
-class log_uniform_gen(rv_continuous):
-    """A log uniform distribution with base 10
-    """
-
-    def __init__(self, *args, **kwargs):
-        self.base = 10
-        super(log_uniform_gen, self).__init__(*args, **kwargs)
-
-    def _log(self, x):
-        return np.log(x) / np.log(self.base)
-
-    def _argcheck(self, a, b):
-        return (a > 0) & (b > a)
-
-    def _get_support(self, a, b):
-        return a, b
-
-    def _pdf(self, x, a, b):
-        # reciprocal.pdf(x, a, b) = 1 / (x*log(b/a))
-        return 1.0 / (x * self._log(b * 1.0 / a))
-
-    def _logpdf(self, x, a, b):
-        return np.log(x) - np.log(self._log(b * 1.0 / a))
-
-    def _cdf(self, x, a, b):
-        return (self._log(x) - self._log(a)) / self._log(b * 1.0 / a)
-
-    def _ppf(self, q, a, b):
-        return a*pow(b*1.0/a, q)
-
-    def _munp(self, n, a, b):
-        return 1.0/self._log(b*1.0/a) / n * (pow(b*1.0, n) - pow(a*1.0, n))
-
-    def _entropy(self, a, b):
-        return 0.5*np.log(a*b)+np.log(self._log(b*1.0/a))
-
-
-loguniform = log_uniform_gen(name='loguniform')
\ No newline at end of file
+def loguniform(a, b):
+    return _loguniform(10 ** a, 10 ** (a + b))


Test patch:
diff --git a/mango/tests/test_domain_space.py b/mango/tests/test_domain_space.py
index f393f2b..58fcbc6 100644
--- a/mango/tests/test_domain_space.py
+++ b/mango/tests/test_domain_space.py
@@ -2,6 +2,7 @@ import numpy as np
 from scipy.stats import uniform, loguniform
 
 from mango.domain.domain_space import domain_space
+from mango.domain.distribution import loguniform as mango_loguniform
 
 
 def test_domain():
@@ -34,6 +35,15 @@ def test_domain():
             assert (sample[param] in params[param])
 
 
+def test_mango_loguniform():
+    space = {
+        'a': mango_loguniform(-3, 6)
+    }
+    ds = domain_space(space, domain_size=1000)
+    samples = ds.get_domain()
+    assert all(1e-3 < sample['a'] < 1e3 for sample in samples)
+
+
 def test_gp_samples_to_params():
     space = {
         'a': range(10),
@@ -91,7 +101,7 @@ def test_gp_space():
     assert (X >= 0.0).all()
     assert (X[:, 0] == 1.).all()  # a
     assert (X[:, 1] == 0.).all()  # b
-    assert np.isin(X[:, 2], [0.0, 0.5, 1.0]).all() # c
+    assert np.isin(X[:, 2], [0.0, 0.5, 1.0]).all()  # c
     assert np.isin(X[:, 4:7], np.eye(3)).all()  # e
     assert X.shape == (ds.domain_size, 12)
 
@@ -110,5 +120,3 @@ def test_gp_space():
 
     X2 = ds.convert_to_gp(params)
     assert np.isclose(X2, X).all()
-
-