8 from math
import log
, exp
, sqrt
, pi
9 from test
import test_support
11 class TestBasicOps(unittest
.TestCase
):
12 # Superclass with tests common to all generators.
13 # Subclasses must arrange for self.gen to retrieve the Random instance
16 def randomlist(self
, n
):
17 """Helper function to make a list of random numbers"""
18 return [self
.gen
.random() for i
in xrange(n
)]
20 def test_autoseed(self
):
22 state1
= self
.gen
.getstate()
24 self
.gen
.seed() # diffent seeds at different times
25 state2
= self
.gen
.getstate()
26 self
.assertNotEqual(state1
, state2
)
28 def test_saverestore(self
):
31 state
= self
.gen
.getstate()
32 randseq
= self
.randomlist(N
)
33 self
.gen
.setstate(state
) # should regenerate the same sequence
34 self
.assertEqual(randseq
, self
.randomlist(N
))
36 def test_seedargs(self
):
37 for arg
in [None, 0, 0L, 1, 1L, -1, -1L, 10**20, -(10**20),
38 3.14, 1+2j
, 'a', tuple('abc')]:
40 for arg
in [range(3), dict(one
=1)]:
41 self
.assertRaises(TypeError, self
.gen
.seed
, arg
)
42 self
.assertRaises(TypeError, self
.gen
.seed
, 1, 2)
43 self
.assertRaises(TypeError, type(self
.gen
), [])
45 def test_jumpahead(self
):
47 state1
= self
.gen
.getstate()
48 self
.gen
.jumpahead(100)
49 state2
= self
.gen
.getstate() # s/b distinct from state1
50 self
.assertNotEqual(state1
, state2
)
51 self
.gen
.jumpahead(100)
52 state3
= self
.gen
.getstate() # s/b distinct from state2
53 self
.assertNotEqual(state2
, state3
)
55 self
.assertRaises(TypeError, self
.gen
.jumpahead
) # needs an arg
56 self
.assertRaises(TypeError, self
.gen
.jumpahead
, "ick") # wrong type
57 self
.assertRaises(TypeError, self
.gen
.jumpahead
, 2.3) # wrong type
58 self
.assertRaises(TypeError, self
.gen
.jumpahead
, 2, 3) # too many
60 def test_sample(self
):
61 # For the entire allowable range of 0 <= k <= N, validate that
62 # the sample is of the correct length and contains only unique items
64 population
= xrange(N
)
66 s
= self
.gen
.sample(population
, k
)
67 self
.assertEqual(len(s
), k
)
69 self
.assertEqual(len(uniq
), k
)
70 self
.failUnless(uniq
<= set(population
))
71 self
.assertEqual(self
.gen
.sample([], 0), []) # test edge case N==k==0
73 def test_sample_distribution(self
):
74 # For the entire allowable range of 0 <= k <= N, validate that
75 # sample generates all possible permutations
78 trials
= 10000 # large num prevents false negatives without slowing normal case
80 return reduce(int.__mul
__, xrange(1, n
), 1)
82 expected
= factorial(n
) // factorial(n
-k
)
84 for i
in xrange(trials
):
85 perms
[tuple(self
.gen
.sample(pop
, k
))] = None
86 if len(perms
) == expected
:
91 def test_sample_inputs(self
):
92 # SF bug #801342 -- population can be any iterable defining __len__()
93 self
.gen
.sample(set(range(20)), 2)
94 self
.gen
.sample(range(20), 2)
95 self
.gen
.sample(xrange(20), 2)
96 self
.gen
.sample(dict.fromkeys('abcdefghijklmnopqrst'), 2)
97 self
.gen
.sample(str('abcdefghijklmnopqrst'), 2)
98 self
.gen
.sample(tuple('abcdefghijklmnopqrst'), 2)
100 def test_gauss(self
):
101 # Ensure that the seed() method initializes all the hidden state. In
102 # particular, through 2.2.1 it failed to reset a piece of state used
103 # by (and only by) the .gauss() method.
105 for seed
in 1, 12, 123, 1234, 12345, 123456, 654321:
107 x1
= self
.gen
.random()
108 y1
= self
.gen
.gauss(0, 1)
111 x2
= self
.gen
.random()
112 y2
= self
.gen
.gauss(0, 1)
114 self
.assertEqual(x1
, x2
)
115 self
.assertEqual(y1
, y2
)
117 def test_pickling(self
):
118 state
= pickle
.dumps(self
.gen
)
119 origseq
= [self
.gen
.random() for i
in xrange(10)]
120 newgen
= pickle
.loads(state
)
121 restoredseq
= [newgen
.random() for i
in xrange(10)]
122 self
.assertEqual(origseq
, restoredseq
)
124 class WichmannHill_TestBasicOps(TestBasicOps
):
125 gen
= random
.WichmannHill()
127 def test_setstate_first_arg(self
):
128 self
.assertRaises(ValueError, self
.gen
.setstate
, (2, None, None))
130 def test_strong_jumpahead(self
):
131 # tests that jumpahead(n) semantics correspond to n calls to random()
133 s
= self
.gen
.getstate()
134 self
.gen
.jumpahead(N
)
135 r1
= self
.gen
.random()
136 # now do it the slow way
140 r2
= self
.gen
.random()
141 self
.assertEqual(r1
, r2
)
143 def test_gauss_with_whseed(self
):
144 # Ensure that the seed() method initializes all the hidden state. In
145 # particular, through 2.2.1 it failed to reset a piece of state used
146 # by (and only by) the .gauss() method.
148 for seed
in 1, 12, 123, 1234, 12345, 123456, 654321:
149 self
.gen
.whseed(seed
)
150 x1
= self
.gen
.random()
151 y1
= self
.gen
.gauss(0, 1)
153 self
.gen
.whseed(seed
)
154 x2
= self
.gen
.random()
155 y2
= self
.gen
.gauss(0, 1)
157 self
.assertEqual(x1
, x2
)
158 self
.assertEqual(y1
, y2
)
160 def test_bigrand(self
):
161 # Verify warnings are raised when randrange is too large for random()
162 oldfilters
= warnings
.filters
[:]
163 warnings
.filterwarnings("error", "Underlying random")
164 self
.assertRaises(UserWarning, self
.gen
.randrange
, 2**60)
165 warnings
.filters
[:] = oldfilters
167 class SystemRandom_TestBasicOps(TestBasicOps
):
168 gen
= random
.SystemRandom()
170 def test_autoseed(self
):
171 # Doesn't need to do anything except not fail
174 def test_saverestore(self
):
175 self
.assertRaises(NotImplementedError, self
.gen
.getstate
)
176 self
.assertRaises(NotImplementedError, self
.gen
.setstate
, None)
178 def test_seedargs(self
):
179 # Doesn't need to do anything except not fail
182 def test_jumpahead(self
):
183 # Doesn't need to do anything except not fail
184 self
.gen
.jumpahead(100)
186 def test_gauss(self
):
187 self
.gen
.gauss_next
= None
189 self
.assertEqual(self
.gen
.gauss_next
, None)
191 def test_pickling(self
):
192 self
.assertRaises(NotImplementedError, pickle
.dumps
, self
.gen
)
194 def test_53_bits_per_float(self
):
195 # This should pass whenever a C double has 53 bit precision.
198 for i
in xrange(100):
199 cum |
= int(self
.gen
.random() * span
)
200 self
.assertEqual(cum
, span
-1)
202 def test_bigrand(self
):
203 # The randrange routine should build-up the required number of bits
204 # in stages so that all bit positions are active.
207 for i
in xrange(100):
208 r
= self
.gen
.randrange(span
)
209 self
.assert_(0 <= r
< span
)
211 self
.assertEqual(cum
, span
-1)
213 def test_bigrand_ranges(self
):
214 for i
in [40,80, 160, 200, 211, 250, 375, 512, 550]:
215 start
= self
.gen
.randrange(2 ** i
)
216 stop
= self
.gen
.randrange(2 ** (i
-2))
219 self
.assert_(start
<= self
.gen
.randrange(start
, stop
) < stop
)
221 def test_rangelimits(self
):
222 for start
, stop
in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]:
223 self
.assertEqual(set(range(start
,stop
)),
224 set([self
.gen
.randrange(start
,stop
) for i
in xrange(100)]))
226 def test_genrandbits(self
):
228 for k
in xrange(1, 1000):
229 self
.assert_(0 <= self
.gen
.getrandbits(k
) < 2**k
)
231 # Verify all bits active
232 getbits
= self
.gen
.getrandbits
233 for span
in [1, 2, 3, 4, 31, 32, 32, 52, 53, 54, 119, 127, 128, 129]:
235 for i
in xrange(100):
237 self
.assertEqual(cum
, 2**span
-1)
239 # Verify argument checking
240 self
.assertRaises(TypeError, self
.gen
.getrandbits
)
241 self
.assertRaises(TypeError, self
.gen
.getrandbits
, 1, 2)
242 self
.assertRaises(ValueError, self
.gen
.getrandbits
, 0)
243 self
.assertRaises(ValueError, self
.gen
.getrandbits
, -1)
244 self
.assertRaises(TypeError, self
.gen
.getrandbits
, 10.1)
246 def test_randbelow_logic(self
, _log
=log
, int=int):
247 # check bitcount transition points: 2**i and 2**(i+1)-1
248 # show that: k = int(1.001 + _log(n, 2))
249 # is equal to or one greater than the number of bits in n
250 for i
in xrange(1, 1000):
251 n
= 1L << i
# check an exact power of two
253 k
= int(1.00001 + _log(n
, 2))
254 self
.assertEqual(k
, numbits
)
255 self
.assert_(n
== 2**(k
-1))
257 n
+= n
- 1 # check 1 below the next power of two
258 k
= int(1.00001 + _log(n
, 2))
259 self
.assert_(k
in [numbits
, numbits
+1])
260 self
.assert_(2**k
> n
> 2**(k
-2))
262 n
-= n
>> 15 # check a little farther below the next power of two
263 k
= int(1.00001 + _log(n
, 2))
264 self
.assertEqual(k
, numbits
) # note the stronger assertion
265 self
.assert_(2**k
> n
> 2**(k
-1)) # note the stronger assertion
268 class MersenneTwister_TestBasicOps(TestBasicOps
):
269 gen
= random
.Random()
271 def test_setstate_first_arg(self
):
272 self
.assertRaises(ValueError, self
.gen
.setstate
, (1, None, None))
274 def test_setstate_middle_arg(self
):
275 # Wrong type, s/b tuple
276 self
.assertRaises(TypeError, self
.gen
.setstate
, (2, None, None))
277 # Wrong length, s/b 625
278 self
.assertRaises(ValueError, self
.gen
.setstate
, (2, (1,2,3), None))
279 # Wrong type, s/b tuple of 625 ints
280 self
.assertRaises(TypeError, self
.gen
.setstate
, (2, ('a',)*625, None))
281 # Last element s/b an int also
282 self
.assertRaises(TypeError, self
.gen
.setstate
, (2, (0,)*624+('a',), None))
284 def test_referenceImplementation(self
):
285 # Compare the python implementation with results from the original
286 # code. Create 2000 53-bit precision random floats. Compare only
287 # the last ten entries to show that the independent implementations
288 # are tracking. Here is the main() function needed to create the
289 # list of expected random numbers:
292 # unsigned long init[4]={61731, 24903, 614, 42143}, length=4;
293 # init_by_array(init, length);
294 # for (i=0; i<2000; i++) {
295 # printf("%.15f ", genrand_res53());
296 # if (i%5==4) printf("\n");
299 expected
= [0.45839803073713259,
303 0.081823493762449573,
305 0.084297823823520024,
307 0.089215024911993401,
310 self
.gen
.seed(61731L + (24903L<<32) + (614L<<64) + (42143L<<96))
311 actual
= self
.randomlist(2000)[-10:]
312 for a
, e
in zip(actual
, expected
):
313 self
.assertAlmostEqual(a
,e
,places
=14)
315 def test_strong_reference_implementation(self
):
316 # Like test_referenceImplementation, but checks for exact bit-level
317 # equality. This should pass on any box where C double contains
318 # at least 53 bits of precision (the underlying algorithm suffers
319 # no rounding errors -- all results are exact).
320 from math
import ldexp
322 expected
= [0x0eab3258d2231fL
,
332 self
.gen
.seed(61731L + (24903L<<32) + (614L<<64) + (42143L<<96))
333 actual
= self
.randomlist(2000)[-10:]
334 for a
, e
in zip(actual
, expected
):
335 self
.assertEqual(long(ldexp(a
, 53)), e
)
337 def test_long_seed(self
):
338 # This is most interesting to run in debug mode, just to make sure
339 # nothing blows up. Under the covers, a dynamically resized array
340 # is allocated, consuming space proportional to the number of bits
341 # in the seed. Unfortunately, that's a quadratic-time algorithm,
342 # so don't make this horribly big.
343 seed
= (1L << (10000 * 8)) - 1 # about 10K bytes
346 def test_53_bits_per_float(self
):
347 # This should pass whenever a C double has 53 bit precision.
350 for i
in xrange(100):
351 cum |
= int(self
.gen
.random() * span
)
352 self
.assertEqual(cum
, span
-1)
354 def test_bigrand(self
):
355 # The randrange routine should build-up the required number of bits
356 # in stages so that all bit positions are active.
359 for i
in xrange(100):
360 r
= self
.gen
.randrange(span
)
361 self
.assert_(0 <= r
< span
)
363 self
.assertEqual(cum
, span
-1)
365 def test_bigrand_ranges(self
):
366 for i
in [40,80, 160, 200, 211, 250, 375, 512, 550]:
367 start
= self
.gen
.randrange(2 ** i
)
368 stop
= self
.gen
.randrange(2 ** (i
-2))
371 self
.assert_(start
<= self
.gen
.randrange(start
, stop
) < stop
)
373 def test_rangelimits(self
):
374 for start
, stop
in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]:
375 self
.assertEqual(set(range(start
,stop
)),
376 set([self
.gen
.randrange(start
,stop
) for i
in xrange(100)]))
378 def test_genrandbits(self
):
379 # Verify cross-platform repeatability
380 self
.gen
.seed(1234567)
381 self
.assertEqual(self
.gen
.getrandbits(100),
382 97904845777343510404718956115L)
384 for k
in xrange(1, 1000):
385 self
.assert_(0 <= self
.gen
.getrandbits(k
) < 2**k
)
387 # Verify all bits active
388 getbits
= self
.gen
.getrandbits
389 for span
in [1, 2, 3, 4, 31, 32, 32, 52, 53, 54, 119, 127, 128, 129]:
391 for i
in xrange(100):
393 self
.assertEqual(cum
, 2**span
-1)
395 # Verify argument checking
396 self
.assertRaises(TypeError, self
.gen
.getrandbits
)
397 self
.assertRaises(TypeError, self
.gen
.getrandbits
, 'a')
398 self
.assertRaises(TypeError, self
.gen
.getrandbits
, 1, 2)
399 self
.assertRaises(ValueError, self
.gen
.getrandbits
, 0)
400 self
.assertRaises(ValueError, self
.gen
.getrandbits
, -1)
402 def test_randbelow_logic(self
, _log
=log
, int=int):
403 # check bitcount transition points: 2**i and 2**(i+1)-1
404 # show that: k = int(1.001 + _log(n, 2))
405 # is equal to or one greater than the number of bits in n
406 for i
in xrange(1, 1000):
407 n
= 1L << i
# check an exact power of two
409 k
= int(1.00001 + _log(n
, 2))
410 self
.assertEqual(k
, numbits
)
411 self
.assert_(n
== 2**(k
-1))
413 n
+= n
- 1 # check 1 below the next power of two
414 k
= int(1.00001 + _log(n
, 2))
415 self
.assert_(k
in [numbits
, numbits
+1])
416 self
.assert_(2**k
> n
> 2**(k
-2))
418 n
-= n
>> 15 # check a little farther below the next power of two
419 k
= int(1.00001 + _log(n
, 2))
420 self
.assertEqual(k
, numbits
) # note the stronger assertion
421 self
.assert_(2**k
> n
> 2**(k
-1)) # note the stronger assertion
423 _gammacoeff
= (0.9999999999995183, 676.5203681218835, -1259.139216722289,
424 771.3234287757674, -176.6150291498386, 12.50734324009056,
425 -0.1385710331296526, 0.9934937113930748e-05, 0.1659470187408462e-06)
427 def gamma(z
, cof
=_gammacoeff
, g
=7):
430 for i
in xrange(1,len(cof
)):
431 sum += cof
[i
] / (z
+i
)
433 return (z
+g
)**z
/ exp(z
+g
) * sqrt(2*pi
) * sum
435 class TestDistributions(unittest
.TestCase
):
436 def test_zeroinputs(self
):
437 # Verify that distributions can handle a series of zero inputs'
439 x
= [g
.random() for i
in xrange(50)] + [0.0]*5
440 g
.random
= x
[:].pop
; g
.uniform(1,10)
441 g
.random
= x
[:].pop
; g
.paretovariate(1.0)
442 g
.random
= x
[:].pop
; g
.expovariate(1.0)
443 g
.random
= x
[:].pop
; g
.weibullvariate(1.0, 1.0)
444 g
.random
= x
[:].pop
; g
.normalvariate(0.0, 1.0)
445 g
.random
= x
[:].pop
; g
.gauss(0.0, 1.0)
446 g
.random
= x
[:].pop
; g
.lognormvariate(0.0, 1.0)
447 g
.random
= x
[:].pop
; g
.vonmisesvariate(0.0, 1.0)
448 g
.random
= x
[:].pop
; g
.gammavariate(0.01, 1.0)
449 g
.random
= x
[:].pop
; g
.gammavariate(1.0, 1.0)
450 g
.random
= x
[:].pop
; g
.gammavariate(200.0, 1.0)
451 g
.random
= x
[:].pop
; g
.betavariate(3.0, 3.0)
453 def test_avg_std(self
):
454 # Use integration to test distribution average and standard deviation.
455 # Only works for distributions which do not consume variates in pairs
458 x
= [i
/float(N
) for i
in xrange(1,N
)]
459 for variate
, args
, mu
, sigmasqrd
in [
460 (g
.uniform
, (1.0,10.0), (10.0+1.0)/2, (10.0-1.0)**2/12),
461 (g
.expovariate
, (1.5,), 1/1.5, 1/1.5**2),
462 (g
.paretovariate
, (5.0,), 5.0/(5.0-1),
463 5.0/((5.0-1)**2*(5.0-2))),
464 (g
.weibullvariate
, (1.0, 3.0), gamma(1+1/3.0),
465 gamma(1+2/3.0)-gamma(1+1/3.0)**2) ]:
468 for i
in xrange(len(x
)):
470 y
.append(variate(*args
))
478 self
.assertAlmostEqual(s1
/N
, mu
, 2)
479 self
.assertAlmostEqual(s2
/(N
-1), sigmasqrd
, 2)
481 class TestModule(unittest
.TestCase
):
482 def testMagicConstants(self
):
483 self
.assertAlmostEqual(random
.NV_MAGICCONST
, 1.71552776992141)
484 self
.assertAlmostEqual(random
.TWOPI
, 6.28318530718)
485 self
.assertAlmostEqual(random
.LOG4
, 1.38629436111989)
486 self
.assertAlmostEqual(random
.SG_MAGICCONST
, 2.50407739677627)
488 def test__all__(self
):
489 # tests validity but not completeness of the __all__ list
490 self
.failUnless(set(random
.__all
__) <= set(dir(random
)))
492 def test_main(verbose
=None):
493 testclasses
= [WichmannHill_TestBasicOps
,
494 MersenneTwister_TestBasicOps
,
499 random
.SystemRandom().random()
500 except NotImplementedError:
503 testclasses
.append(SystemRandom_TestBasicOps
)
505 test_support
.run_unittest(*testclasses
)
507 # verify reference counting
509 if verbose
and hasattr(sys
, "gettotalrefcount"):
511 for i
in xrange(len(counts
)):
512 test_support
.run_unittest(*testclasses
)
513 counts
[i
] = sys
.gettotalrefcount()
516 if __name__
== "__main__":
517 test_main(verbose
=True)