Serhiy Storchaka added the comment:
> Serhiy: do you know how the original formulas arose?
No. I have not found any articles or books in the open access.
> A test would be good!
I was waiting for issue13355 and issue17149. Here is an updated patch with
tests.
----------
Added file: http://bugs.python.org/file29028/random_vonmisesvariate_2.patch
_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue17141>
_______________________________________
diff -r 2704e11da558 Lib/random.py
--- a/Lib/random.py Sun Feb 10 14:17:20 2013 +0000
+++ b/Lib/random.py Sun Feb 10 16:44:50 2013 +0200
@@ -432,22 +432,20 @@
if kappa <= 1e-6:
return TWOPI * random()
- a = 1.0 + _sqrt(1.0 + 4.0 * kappa * kappa)
- b = (a - _sqrt(2.0 * a))/(2.0 * kappa)
- r = (1.0 + b * b)/(2.0 * b)
+ s = 0.5 / kappa
+ r = s + _sqrt(1.0 + s * s)
while 1:
u1 = random()
+ z = _cos(_pi * u1)
- z = _cos(_pi * u1)
- f = (1.0 + r * z)/(r + z)
- c = kappa * (r - f)
-
+ d = z / (r + z)
u2 = random()
-
- if u2 < c * (2.0 - c) or u2 <= c * _exp(1.0 - c):
+ if u2 < 1.0 - d * d or u2 <= (1.0 - d) * _exp(d):
break
+ q = 1.0 / r
+ f = (q + z) / (1.0 + q * z)
u3 = random()
if u3 > 0.5:
theta = (mu + _acos(f)) % TWOPI
diff -r 2704e11da558 Lib/test/test_random.py
--- a/Lib/test/test_random.py Sun Feb 10 14:17:20 2013 +0000
+++ b/Lib/test/test_random.py Sun Feb 10 16:44:50 2013 +0200
@@ -5,7 +5,7 @@
import time
import pickle
import warnings
-from math import log, exp, pi, fsum, sin
+from math import log, exp, pi, fsum, sin, sqrt
from test import support
class TestBasicOps(unittest.TestCase):
@@ -473,6 +473,7 @@
g.random = x[:].pop; g.paretovariate(1.0)
g.random = x[:].pop; g.expovariate(1.0)
g.random = x[:].pop; g.weibullvariate(1.0, 1.0)
+ g.random = x[:].pop; g.vonmisesvariate(1.0, 1.0)
g.random = x[:].pop; g.normalvariate(0.0, 1.0)
g.random = x[:].pop; g.gauss(0.0, 1.0)
g.random = x[:].pop; g.lognormvariate(0.0, 1.0)
@@ -493,6 +494,8 @@
(g.uniform, (1.0,10.0), (10.0+1.0)/2, (10.0-1.0)**2/12),
(g.triangular, (0.0, 1.0, 1.0/3.0), 4.0/9.0, 7.0/9.0/18.0),
(g.expovariate, (1.5,), 1/1.5, 1/1.5**2),
+ (g.vonmisesvariate, (1.23, 0), pi, pi**2/3),
+ (g.vonmisesvariate, (1.23, 100), 1.23, 1/sqrt(2)/100),
(g.paretovariate, (5.0,), 5.0/(5.0-1),
5.0/((5.0-1)**2*(5.0-2))),
(g.weibullvariate, (1.0, 3.0), gamma(1+1/3.0),
@@ -509,8 +512,30 @@
s1 += e
s2 += (e - mu) ** 2
N = len(y)
- self.assertAlmostEqual(s1/N, mu, places=2)
- self.assertAlmostEqual(s2/(N-1), sigmasqrd, places=2)
+ self.assertAlmostEqual(s1/N, mu, places=2,
+ msg='%s%r' % (variate.__name__, args))
+ self.assertAlmostEqual(s2/(N-1), sigmasqrd, places=2,
+ msg='%s%r' % (variate.__name__, args))
+
+ def test_constant(self):
+ g = random.Random()
+ N = 100
+ for variate, args, expected in [
+ (g.uniform, (10.0, 10.0), 10.0),
+ (g.triangular, (10.0, 10.0), 10.0),
+ #(g.triangular, (10.0, 10.0, 10.0), 10.0),
+ (g.expovariate, (float('inf'),), 0.0),
+ (g.vonmisesvariate, (3.0, float('inf')), 3.0),
+ (g.gauss, (10.0, 0.0), 10.0),
+ (g.lognormvariate, (0.0, 0.0), 1.0),
+ (g.lognormvariate, (-float('inf'), 0.0), 0.0),
+ (g.normalvariate, (10.0, 0.0), 10.0),
+ (g.paretovariate, (float('inf'),), 1.0),
+ (g.weibullvariate, (10.0, float('inf')), 10.0),
+ (g.weibullvariate, (0.0, 10.0), 0.0),
+ ]:
+ for i in range(N):
+ self.assertEqual(variate(*args), expected)
def test_von_mises_range(self):
# Issue 17149: von mises variates were not consistently in the
@@ -526,6 +551,12 @@
msg=("vonmisesvariate({}, {}) produced a result {} out"
" of range [0, 2*pi]").format(mu, kappa, sample))
+ def test_von_mises_large_kappa(self):
+ # Issue #17141: vonmisesvariate() was hang for large kappas
+ random.vonmisesvariate(0, 1e15)
+ random.vonmisesvariate(0, 1e100)
+
+
class TestModule(unittest.TestCase):
def testMagicConstants(self):
self.assertAlmostEqual(random.NV_MAGICCONST, 1.71552776992141)
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com