0001 #!/usr/bin/env python 0002 0003 import unittest 0004 import random 0005 import time 0006 import pickle 0007 import warnings 0008 from math import log, exp, sqrt, pi 0009 from test import test_support 0010 0011 class TestBasicOps(unittest.TestCase): 0012 # Superclass with tests common to all generators. 0013 # Subclasses must arrange for self.gen to retrieve the Random instance 0014 # to be tested. 0015 0016 def randomlist(self, n): 0017 """Helper function to make a list of random numbers""" 0018 return [self.gen.random() for i in xrange(n)] 0019 0020 def test_autoseed(self): 0021 self.gen.seed() 0022 state1 = self.gen.getstate() 0023 time.sleep(0.1) 0024 self.gen.seed() # diffent seeds at different times 0025 state2 = self.gen.getstate() 0026 self.assertNotEqual(state1, state2) 0027 0028 def test_saverestore(self): 0029 N = 1000 0030 self.gen.seed() 0031 state = self.gen.getstate() 0032 randseq = self.randomlist(N) 0033 self.gen.setstate(state) # should regenerate the same sequence 0034 self.assertEqual(randseq, self.randomlist(N)) 0035 0036 def test_seedargs(self): 0037 for arg in [None, 0, 0L, 1, 1L, -1, -1L, 10**20, -(10**20), 0038 3.14, 1+2j, 'a', tuple('abc')]: 0039 self.gen.seed(arg) 0040 for arg in [range(3), dict(one=1)]: 0041 self.assertRaises(TypeError, self.gen.seed, arg) 0042 self.assertRaises(TypeError, self.gen.seed, 1, 2) 0043 self.assertRaises(TypeError, type(self.gen), []) 0044 0045 def test_jumpahead(self): 0046 self.gen.seed() 0047 state1 = self.gen.getstate() 0048 self.gen.jumpahead(100) 0049 state2 = self.gen.getstate() # s/b distinct from state1 0050 self.assertNotEqual(state1, state2) 0051 self.gen.jumpahead(100) 0052 state3 = self.gen.getstate() # s/b distinct from state2 0053 self.assertNotEqual(state2, state3) 0054 0055 self.assertRaises(TypeError, self.gen.jumpahead) # needs an arg 0056 self.assertRaises(TypeError, self.gen.jumpahead, "ick") # wrong type 0057 self.assertRaises(TypeError, self.gen.jumpahead, 2.3) # wrong type 0058 self.assertRaises(TypeError, self.gen.jumpahead, 2, 3) # too many 0059 0060 def test_sample(self): 0061 # For the entire allowable range of 0 <= k <= N, validate that 0062 # the sample is of the correct length and contains only unique items 0063 N = 100 0064 population = xrange(N) 0065 for k in xrange(N+1): 0066 s = self.gen.sample(population, k) 0067 self.assertEqual(len(s), k) 0068 uniq = set(s) 0069 self.assertEqual(len(uniq), k) 0070 self.failUnless(uniq <= set(population)) 0071 self.assertEqual(self.gen.sample([], 0), []) # test edge case N==k==0 0072 0073 def test_sample_distribution(self): 0074 # For the entire allowable range of 0 <= k <= N, validate that 0075 # sample generates all possible permutations 0076 n = 5 0077 pop = range(n) 0078 trials = 10000 # large num prevents false negatives without slowing normal case 0079 def factorial(n): 0080 return reduce(int.__mul__, xrange(1, n), 1) 0081 for k in xrange(n): 0082 expected = factorial(n) // factorial(n-k) 0083 perms = {} 0084 for i in xrange(trials): 0085 perms[tuple(self.gen.sample(pop, k))] = None 0086 if len(perms) == expected: 0087 break 0088 else: 0089 self.fail() 0090 0091 def test_sample_inputs(self): 0092 # SF bug #801342 -- population can be any iterable defining __len__() 0093 self.gen.sample(set(range(20)), 2) 0094 self.gen.sample(range(20), 2) 0095 self.gen.sample(xrange(20), 2) 0096 self.gen.sample(dict.fromkeys('abcdefghijklmnopqrst'), 2) 0097 self.gen.sample(str('abcdefghijklmnopqrst'), 2) 0098 self.gen.sample(tuple('abcdefghijklmnopqrst'), 2) 0099 0100 def test_gauss(self): 0101 # Ensure that the seed() method initializes all the hidden state. In 0102 # particular, through 2.2.1 it failed to reset a piece of state used 0103 # by (and only by) the .gauss() method. 0104 0105 for seed in 1, 12, 123, 1234, 12345, 123456, 654321: 0106 self.gen.seed(seed) 0107 x1 = self.gen.random() 0108 y1 = self.gen.gauss(0, 1) 0109 0110 self.gen.seed(seed) 0111 x2 = self.gen.random() 0112 y2 = self.gen.gauss(0, 1) 0113 0114 self.assertEqual(x1, x2) 0115 self.assertEqual(y1, y2) 0116 0117 def test_pickling(self): 0118 state = pickle.dumps(self.gen) 0119 origseq = [self.gen.random() for i in xrange(10)] 0120 newgen = pickle.loads(state) 0121 restoredseq = [newgen.random() for i in xrange(10)] 0122 self.assertEqual(origseq, restoredseq) 0123 0124 class WichmannHill_TestBasicOps(TestBasicOps): 0125 gen = random.WichmannHill() 0126 0127 def test_setstate_first_arg(self): 0128 self.assertRaises(ValueError, self.gen.setstate, (2, None, None)) 0129 0130 def test_strong_jumpahead(self): 0131 # tests that jumpahead(n) semantics correspond to n calls to random() 0132 N = 1000 0133 s = self.gen.getstate() 0134 self.gen.jumpahead(N) 0135 r1 = self.gen.random() 0136 # now do it the slow way 0137 self.gen.setstate(s) 0138 for i in xrange(N): 0139 self.gen.random() 0140 r2 = self.gen.random() 0141 self.assertEqual(r1, r2) 0142 0143 def test_gauss_with_whseed(self): 0144 # Ensure that the seed() method initializes all the hidden state. In 0145 # particular, through 2.2.1 it failed to reset a piece of state used 0146 # by (and only by) the .gauss() method. 0147 0148 for seed in 1, 12, 123, 1234, 12345, 123456, 654321: 0149 self.gen.whseed(seed) 0150 x1 = self.gen.random() 0151 y1 = self.gen.gauss(0, 1) 0152 0153 self.gen.whseed(seed) 0154 x2 = self.gen.random() 0155 y2 = self.gen.gauss(0, 1) 0156 0157 self.assertEqual(x1, x2) 0158 self.assertEqual(y1, y2) 0159 0160 def test_bigrand(self): 0161 # Verify warnings are raised when randrange is too large for random() 0162 oldfilters = warnings.filters[:] 0163 warnings.filterwarnings("error", "Underlying random") 0164 self.assertRaises(UserWarning, self.gen.randrange, 2**60) 0165 warnings.filters[:] = oldfilters 0166 0167 class SystemRandom_TestBasicOps(TestBasicOps): 0168 gen = random.SystemRandom() 0169 0170 def test_autoseed(self): 0171 # Doesn't need to do anything except not fail 0172 self.gen.seed() 0173 0174 def test_saverestore(self): 0175 self.assertRaises(NotImplementedError, self.gen.getstate) 0176 self.assertRaises(NotImplementedError, self.gen.setstate, None) 0177 0178 def test_seedargs(self): 0179 # Doesn't need to do anything except not fail 0180 self.gen.seed(100) 0181 0182 def test_jumpahead(self): 0183 # Doesn't need to do anything except not fail 0184 self.gen.jumpahead(100) 0185 0186 def test_gauss(self): 0187 self.gen.gauss_next = None 0188 self.gen.seed(100) 0189 self.assertEqual(self.gen.gauss_next, None) 0190 0191 def test_pickling(self): 0192 self.assertRaises(NotImplementedError, pickle.dumps, self.gen) 0193 0194 def test_53_bits_per_float(self): 0195 # This should pass whenever a C double has 53 bit precision. 0196 span = 2 ** 53 0197 cum = 0 0198 for i in xrange(100): 0199 cum |= int(self.gen.random() * span) 0200 self.assertEqual(cum, span-1) 0201 0202 def test_bigrand(self): 0203 # The randrange routine should build-up the required number of bits 0204 # in stages so that all bit positions are active. 0205 span = 2 ** 500 0206 cum = 0 0207 for i in xrange(100): 0208 r = self.gen.randrange(span) 0209 self.assert_(0 <= r < span) 0210 cum |= r 0211 self.assertEqual(cum, span-1) 0212 0213 def test_bigrand_ranges(self): 0214 for i in [40,80, 160, 200, 211, 250, 375, 512, 550]: 0215 start = self.gen.randrange(2 ** i) 0216 stop = self.gen.randrange(2 ** (i-2)) 0217 if stop <= start: 0218 return 0219 self.assert_(start <= self.gen.randrange(start, stop) < stop) 0220 0221 def test_rangelimits(self): 0222 for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]: 0223 self.assertEqual(set(range(start,stop)), 0224 set([self.gen.randrange(start,stop) for i in xrange(100)])) 0225 0226 def test_genrandbits(self): 0227 # Verify ranges 0228 for k in xrange(1, 1000): 0229 self.assert_(0 <= self.gen.getrandbits(k) < 2**k) 0230 0231 # Verify all bits active 0232 getbits = self.gen.getrandbits 0233 for span in [1, 2, 3, 4, 31, 32, 32, 52, 53, 54, 119, 127, 128, 129]: 0234 cum = 0 0235 for i in xrange(100): 0236 cum |= getbits(span) 0237 self.assertEqual(cum, 2**span-1) 0238 0239 # Verify argument checking 0240 self.assertRaises(TypeError, self.gen.getrandbits) 0241 self.assertRaises(TypeError, self.gen.getrandbits, 1, 2) 0242 self.assertRaises(ValueError, self.gen.getrandbits, 0) 0243 self.assertRaises(ValueError, self.gen.getrandbits, -1) 0244 self.assertRaises(TypeError, self.gen.getrandbits, 10.1) 0245 0246 def test_randbelow_logic(self, _log=log, int=int): 0247 # check bitcount transition points: 2**i and 2**(i+1)-1 0248 # show that: k = int(1.001 + _log(n, 2)) 0249 # is equal to or one greater than the number of bits in n 0250 for i in xrange(1, 1000): 0251 n = 1L << i # check an exact power of two 0252 numbits = i+1 0253 k = int(1.00001 + _log(n, 2)) 0254 self.assertEqual(k, numbits) 0255 self.assert_(n == 2**(k-1)) 0256 0257 n += n - 1 # check 1 below the next power of two 0258 k = int(1.00001 + _log(n, 2)) 0259 self.assert_(k in [numbits, numbits+1]) 0260 self.assert_(2**k > n > 2**(k-2)) 0261 0262 n -= n >> 15 # check a little farther below the next power of two 0263 k = int(1.00001 + _log(n, 2)) 0264 self.assertEqual(k, numbits) # note the stronger assertion 0265 self.assert_(2**k > n > 2**(k-1)) # note the stronger assertion 0266 0267 0268 class MersenneTwister_TestBasicOps(TestBasicOps): 0269 gen = random.Random() 0270 0271 def test_setstate_first_arg(self): 0272 self.assertRaises(ValueError, self.gen.setstate, (1, None, None)) 0273 0274 def test_setstate_middle_arg(self): 0275 # Wrong type, s/b tuple 0276 self.assertRaises(TypeError, self.gen.setstate, (2, None, None)) 0277 # Wrong length, s/b 625 0278 self.assertRaises(ValueError, self.gen.setstate, (2, (1,2,3), None)) 0279 # Wrong type, s/b tuple of 625 ints 0280 self.assertRaises(TypeError, self.gen.setstate, (2, ('a',)*625, None)) 0281 # Last element s/b an int also 0282 self.assertRaises(TypeError, self.gen.setstate, (2, (0,)*624+('a',), None)) 0283 0284 def test_referenceImplementation(self): 0285 # Compare the python implementation with results from the original 0286 # code. Create 2000 53-bit precision random floats. Compare only 0287 # the last ten entries to show that the independent implementations 0288 # are tracking. Here is the main() function needed to create the 0289 # list of expected random numbers: 0290 # void main(void){ 0291 # int i; 0292 # unsigned long init[4]={61731, 24903, 614, 42143}, length=4; 0293 # init_by_array(init, length); 0294 # for (i=0; i<2000; i++) { 0295 # printf("%.15f ", genrand_res53()); 0296 # if (i%5==4) printf("\n"); 0297 # } 0298 # } 0299 expected = [0.45839803073713259, 0300 0.86057815201978782, 0301 0.92848331726782152, 0302 0.35932681119782461, 0303 0.081823493762449573, 0304 0.14332226470169329, 0305 0.084297823823520024, 0306 0.53814864671831453, 0307 0.089215024911993401, 0308 0.78486196105372907] 0309 0310 self.gen.seed(61731L + (24903L<<32) + (614L<<64) + (42143L<<96)) 0311 actual = self.randomlist(2000)[-10:] 0312 for a, e in zip(actual, expected): 0313 self.assertAlmostEqual(a,e,places=14) 0314 0315 def test_strong_reference_implementation(self): 0316 # Like test_referenceImplementation, but checks for exact bit-level 0317 # equality. This should pass on any box where C double contains 0318 # at least 53 bits of precision (the underlying algorithm suffers 0319 # no rounding errors -- all results are exact). 0320 from math import ldexp 0321 0322 expected = [0x0eab3258d2231fL, 0323 0x1b89db315277a5L, 0324 0x1db622a5518016L, 0325 0x0b7f9af0d575bfL, 0326 0x029e4c4db82240L, 0327 0x04961892f5d673L, 0328 0x02b291598e4589L, 0329 0x11388382c15694L, 0330 0x02dad977c9e1feL, 0331 0x191d96d4d334c6L] 0332 self.gen.seed(61731L + (24903L<<32) + (614L<<64) + (42143L<<96)) 0333 actual = self.randomlist(2000)[-10:] 0334 for a, e in zip(actual, expected): 0335 self.assertEqual(long(ldexp(a, 53)), e) 0336 0337 def test_long_seed(self): 0338 # This is most interesting to run in debug mode, just to make sure 0339 # nothing blows up. Under the covers, a dynamically resized array 0340 # is allocated, consuming space proportional to the number of bits 0341 # in the seed. Unfortunately, that's a quadratic-time algorithm, 0342 # so don't make this horribly big. 0343 seed = (1L << (10000 * 8)) - 1 # about 10K bytes 0344 self.gen.seed(seed) 0345 0346 def test_53_bits_per_float(self): 0347 # This should pass whenever a C double has 53 bit precision. 0348 span = 2 ** 53 0349 cum = 0 0350 for i in xrange(100): 0351 cum |= int(self.gen.random() * span) 0352 self.assertEqual(cum, span-1) 0353 0354 def test_bigrand(self): 0355 # The randrange routine should build-up the required number of bits 0356 # in stages so that all bit positions are active. 0357 span = 2 ** 500 0358 cum = 0 0359 for i in xrange(100): 0360 r = self.gen.randrange(span) 0361 self.assert_(0 <= r < span) 0362 cum |= r 0363 self.assertEqual(cum, span-1) 0364 0365 def test_bigrand_ranges(self): 0366 for i in [40,80, 160, 200, 211, 250, 375, 512, 550]: 0367 start = self.gen.randrange(2 ** i) 0368 stop = self.gen.randrange(2 ** (i-2)) 0369 if stop <= start: 0370 return 0371 self.assert_(start <= self.gen.randrange(start, stop) < stop) 0372 0373 def test_rangelimits(self): 0374 for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]: 0375 self.assertEqual(set(range(start,stop)), 0376 set([self.gen.randrange(start,stop) for i in xrange(100)])) 0377 0378 def test_genrandbits(self): 0379 # Verify cross-platform repeatability 0380 self.gen.seed(1234567) 0381 self.assertEqual(self.gen.getrandbits(100), 0382 97904845777343510404718956115L) 0383 # Verify ranges 0384 for k in xrange(1, 1000): 0385 self.assert_(0 <= self.gen.getrandbits(k) < 2**k) 0386 0387 # Verify all bits active 0388 getbits = self.gen.getrandbits 0389 for span in [1, 2, 3, 4, 31, 32, 32, 52, 53, 54, 119, 127, 128, 129]: 0390 cum = 0 0391 for i in xrange(100): 0392 cum |= getbits(span) 0393 self.assertEqual(cum, 2**span-1) 0394 0395 # Verify argument checking 0396 self.assertRaises(TypeError, self.gen.getrandbits) 0397 self.assertRaises(TypeError, self.gen.getrandbits, 'a') 0398 self.assertRaises(TypeError, self.gen.getrandbits, 1, 2) 0399 self.assertRaises(ValueError, self.gen.getrandbits, 0) 0400 self.assertRaises(ValueError, self.gen.getrandbits, -1) 0401 0402 def test_randbelow_logic(self, _log=log, int=int): 0403 # check bitcount transition points: 2**i and 2**(i+1)-1 0404 # show that: k = int(1.001 + _log(n, 2)) 0405 # is equal to or one greater than the number of bits in n 0406 for i in xrange(1, 1000): 0407 n = 1L << i # check an exact power of two 0408 numbits = i+1 0409 k = int(1.00001 + _log(n, 2)) 0410 self.assertEqual(k, numbits) 0411 self.assert_(n == 2**(k-1)) 0412 0413 n += n - 1 # check 1 below the next power of two 0414 k = int(1.00001 + _log(n, 2)) 0415 self.assert_(k in [numbits, numbits+1]) 0416 self.assert_(2**k > n > 2**(k-2)) 0417 0418 n -= n >> 15 # check a little farther below the next power of two 0419 k = int(1.00001 + _log(n, 2)) 0420 self.assertEqual(k, numbits) # note the stronger assertion 0421 self.assert_(2**k > n > 2**(k-1)) # note the stronger assertion 0422 0423 _gammacoeff = (0.9999999999995183, 676.5203681218835, -1259.139216722289, 0424 771.3234287757674, -176.6150291498386, 12.50734324009056, 0425 -0.1385710331296526, 0.9934937113930748e-05, 0.1659470187408462e-06) 0426 0427 def gamma(z, cof=_gammacoeff, g=7): 0428 z -= 1.0 0429 sum = cof[0] 0430 for i in xrange(1,len(cof)): 0431 sum += cof[i] / (z+i) 0432 z += 0.5 0433 return (z+g)**z / exp(z+g) * sqrt(2*pi) * sum 0434 0435 class TestDistributions(unittest.TestCase): 0436 def test_zeroinputs(self): 0437 # Verify that distributions can handle a series of zero inputs' 0438 g = random.Random() 0439 x = [g.random() for i in xrange(50)] + [0.0]*5 0440 g.random = x[:].pop; g.uniform(1,10) 0441 g.random = x[:].pop; g.paretovariate(1.0) 0442 g.random = x[:].pop; g.expovariate(1.0) 0443 g.random = x[:].pop; g.weibullvariate(1.0, 1.0) 0444 g.random = x[:].pop; g.normalvariate(0.0, 1.0) 0445 g.random = x[:].pop; g.gauss(0.0, 1.0) 0446 g.random = x[:].pop; g.lognormvariate(0.0, 1.0) 0447 g.random = x[:].pop; g.vonmisesvariate(0.0, 1.0) 0448 g.random = x[:].pop; g.gammavariate(0.01, 1.0) 0449 g.random = x[:].pop; g.gammavariate(1.0, 1.0) 0450 g.random = x[:].pop; g.gammavariate(200.0, 1.0) 0451 g.random = x[:].pop; g.betavariate(3.0, 3.0) 0452 0453 def test_avg_std(self): 0454 # Use integration to test distribution average and standard deviation. 0455 # Only works for distributions which do not consume variates in pairs 0456 g = random.Random() 0457 N = 5000 0458 x = [i/float(N) for i in xrange(1,N)] 0459 for variate, args, mu, sigmasqrd in [ 0460 (g.uniform, (1.0,10.0), (10.0+1.0)/2, (10.0-1.0)**2/12), 0461 (g.expovariate, (1.5,), 1/1.5, 1/1.5**2), 0462 (g.paretovariate, (5.0,), 5.0/(5.0-1), 0463 5.0/((5.0-1)**2*(5.0-2))), 0464 (g.weibullvariate, (1.0, 3.0), gamma(1+1/3.0), 0465 gamma(1+2/3.0)-gamma(1+1/3.0)**2) ]: 0466 g.random = x[:].pop 0467 y = [] 0468 for i in xrange(len(x)): 0469 try: 0470 y.append(variate(*args)) 0471 except IndexError: 0472 pass 0473 s1 = s2 = 0 0474 for e in y: 0475 s1 += e 0476 s2 += (e - mu) ** 2 0477 N = len(y) 0478 self.assertAlmostEqual(s1/N, mu, 2) 0479 self.assertAlmostEqual(s2/(N-1), sigmasqrd, 2) 0480 0481 class TestModule(unittest.TestCase): 0482 def testMagicConstants(self): 0483 self.assertAlmostEqual(random.NV_MAGICCONST, 1.71552776992141) 0484 self.assertAlmostEqual(random.TWOPI, 6.28318530718) 0485 self.assertAlmostEqual(random.LOG4, 1.38629436111989) 0486 self.assertAlmostEqual(random.SG_MAGICCONST, 2.50407739677627) 0487 0488 def test__all__(self): 0489 # tests validity but not completeness of the __all__ list 0490 self.failUnless(set(random.__all__) <= set(dir(random))) 0491 0492 def test_main(verbose=None): 0493 testclasses = [WichmannHill_TestBasicOps, 0494 MersenneTwister_TestBasicOps, 0495 TestDistributions, 0496 TestModule] 0497 0498 try: 0499 random.SystemRandom().random() 0500 except NotImplementedError: 0501 pass 0502 else: 0503 testclasses.append(SystemRandom_TestBasicOps) 0504 0505 test_support.run_unittest(*testclasses) 0506 0507 # verify reference counting 0508 import sys 0509 if verbose and hasattr(sys, "gettotalrefcount"): 0510 counts = [None] * 5 0511 for i in xrange(len(counts)): 0512 test_support.run_unittest(*testclasses) 0513 counts[i] = sys.gettotalrefcount() 0514 print counts 0515 0516 if __name__ == "__main__": 0517 test_main(verbose=True) 0518
Generated by PyXR 0.9.4