PyXR

c:\python24\lib \ test \ test_random.py



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
SourceForge.net Logo