home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 June / PCWorld_2005-06_cd.bin / software / vyzkuste / firewally / firewally.exe / framework-2.3.exe / test_random.py < prev    next >
Text File  |  2003-12-30  |  13KB  |  342 lines

  1. #!/usr/bin/env python
  2.  
  3. import unittest
  4. import random
  5. import time
  6. import pickle
  7. from math import log, exp, sqrt, pi
  8. from sets import Set
  9. from test import test_support
  10.  
  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
  14.     # to be tested.
  15.  
  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)]
  19.  
  20.     def test_autoseed(self):
  21.         self.gen.seed()
  22.         state1 = self.gen.getstate()
  23.         time.sleep(0.1)
  24.         self.gen.seed()      # diffent seeds at different times
  25.         state2 = self.gen.getstate()
  26.         self.assertNotEqual(state1, state2)
  27.  
  28.     def test_saverestore(self):
  29.         N = 1000
  30.         self.gen.seed()
  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))
  35.  
  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')]:
  39.             self.gen.seed(arg)
  40.         for arg in [range(3), dict(one=1)]:
  41.             self.assertRaises(TypeError, self.gen.seed, arg)
  42.  
  43.     def test_jumpahead(self):
  44.         self.gen.seed()
  45.         state1 = self.gen.getstate()
  46.         self.gen.jumpahead(100)
  47.         state2 = self.gen.getstate()    # s/b distinct from state1
  48.         self.assertNotEqual(state1, state2)
  49.         self.gen.jumpahead(100)
  50.         state3 = self.gen.getstate()    # s/b distinct from state2
  51.         self.assertNotEqual(state2, state3)
  52.  
  53.         self.assertRaises(TypeError, self.gen.jumpahead)  # needs an arg
  54.         self.assertRaises(TypeError, self.gen.jumpahead, "ick")  # wrong type
  55.         self.assertRaises(TypeError, self.gen.jumpahead, 2.3)  # wrong type
  56.         self.assertRaises(TypeError, self.gen.jumpahead, 2, 3)  # too many
  57.  
  58.     def test_sample(self):
  59.         # For the entire allowable range of 0 <= k <= N, validate that
  60.         # the sample is of the correct length and contains only unique items
  61.         N = 100
  62.         population = xrange(N)
  63.         for k in xrange(N+1):
  64.             s = self.gen.sample(population, k)
  65.             self.assertEqual(len(s), k)
  66.             uniq = Set(s)
  67.             self.assertEqual(len(uniq), k)
  68.             self.failUnless(uniq <= Set(population))
  69.         self.assertEqual(self.gen.sample([], 0), [])  # test edge case N==k==0
  70.  
  71.     def test_sample_distribution(self):
  72.         # For the entire allowable range of 0 <= k <= N, validate that
  73.         # sample generates all possible permutations
  74.         n = 5
  75.         pop = range(n)
  76.         trials = 10000  # large num prevents false negatives without slowing normal case
  77.         def factorial(n):
  78.             return reduce(int.__mul__, xrange(1, n), 1)
  79.         for k in xrange(n):
  80.             expected = factorial(n) / factorial(n-k)
  81.             perms = {}
  82.             for i in xrange(trials):
  83.                 perms[tuple(self.gen.sample(pop, k))] = None
  84.                 if len(perms) == expected:
  85.                     break
  86.             else:
  87.                 self.fail()
  88.  
  89.     def test_sample_inputs(self):
  90.         # SF bug #801342 -- population can be any iterable defining __len__()
  91.         from sets import Set
  92.         self.gen.sample(Set(range(20)), 2)
  93.         self.gen.sample(range(20), 2)
  94.         self.gen.sample(xrange(20), 2)
  95.         self.gen.sample(dict.fromkeys('abcdefghijklmnopqrst'), 2)
  96.         self.gen.sample(str('abcdefghijklmnopqrst'), 2)
  97.         self.gen.sample(unicode('abcdefghijklmnopqrst'), 2)
  98.         self.gen.sample(tuple('abcdefghijklmnopqrst'), 2)
  99.  
  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.
  104.  
  105.         for seed in 1, 12, 123, 1234, 12345, 123456, 654321:
  106.             self.gen.seed(seed)
  107.             x1 = self.gen.random()
  108.             y1 = self.gen.gauss(0, 1)
  109.  
  110.             self.gen.seed(seed)
  111.             x2 = self.gen.random()
  112.             y2 = self.gen.gauss(0, 1)
  113.  
  114.             self.assertEqual(x1, x2)
  115.             self.assertEqual(y1, y2)
  116.  
  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)
  123.  
  124. class WichmannHill_TestBasicOps(TestBasicOps):
  125.     gen = random.WichmannHill()
  126.  
  127.     def test_strong_jumpahead(self):
  128.         # tests that jumpahead(n) semantics correspond to n calls to random()
  129.         N = 1000
  130.         s = self.gen.getstate()
  131.         self.gen.jumpahead(N)
  132.         r1 = self.gen.random()
  133.         # now do it the slow way
  134.         self.gen.setstate(s)
  135.         for i in xrange(N):
  136.             self.gen.random()
  137.         r2 = self.gen.random()
  138.         self.assertEqual(r1, r2)
  139.  
  140.     def test_gauss_with_whseed(self):
  141.         # Ensure that the seed() method initializes all the hidden state.  In
  142.         # particular, through 2.2.1 it failed to reset a piece of state used
  143.         # by (and only by) the .gauss() method.
  144.  
  145.         for seed in 1, 12, 123, 1234, 12345, 123456, 654321:
  146.             self.gen.whseed(seed)
  147.             x1 = self.gen.random()
  148.             y1 = self.gen.gauss(0, 1)
  149.  
  150.             self.gen.whseed(seed)
  151.             x2 = self.gen.random()
  152.             y2 = self.gen.gauss(0, 1)
  153.  
  154.             self.assertEqual(x1, x2)
  155.             self.assertEqual(y1, y2)
  156.  
  157. class MersenneTwister_TestBasicOps(TestBasicOps):
  158.     gen = random.Random()
  159.  
  160.     def test_referenceImplementation(self):
  161.         # Compare the python implementation with results from the original
  162.         # code.  Create 2000 53-bit precision random floats.  Compare only
  163.         # the last ten entries to show that the independent implementations
  164.         # are tracking.  Here is the main() function needed to create the
  165.         # list of expected random numbers:
  166.         #    void main(void){
  167.         #         int i;
  168.         #         unsigned long init[4]={61731, 24903, 614, 42143}, length=4;
  169.         #         init_by_array(init, length);
  170.         #         for (i=0; i<2000; i++) {
  171.         #           printf("%.15f ", genrand_res53());
  172.         #           if (i%5==4) printf("\n");
  173.         #         }
  174.         #     }
  175.         expected = [0.45839803073713259,
  176.                     0.86057815201978782,
  177.                     0.92848331726782152,
  178.                     0.35932681119782461,
  179.                     0.081823493762449573,
  180.                     0.14332226470169329,
  181.                     0.084297823823520024,
  182.                     0.53814864671831453,
  183.                     0.089215024911993401,
  184.                     0.78486196105372907]
  185.  
  186.         self.gen.seed(61731L + (24903L<<32) + (614L<<64) + (42143L<<96))
  187.         actual = self.randomlist(2000)[-10:]
  188.         for a, e in zip(actual, expected):
  189.             self.assertAlmostEqual(a,e,places=14)
  190.  
  191.     def test_strong_reference_implementation(self):
  192.         # Like test_referenceImplementation, but checks for exact bit-level
  193.         # equality.  This should pass on any box where C double contains
  194.         # at least 53 bits of precision (the underlying algorithm suffers
  195.         # no rounding errors -- all results are exact).
  196.         from math import ldexp
  197.  
  198.         expected = [0x0eab3258d2231fL,
  199.                     0x1b89db315277a5L,
  200.                     0x1db622a5518016L,
  201.                     0x0b7f9af0d575bfL,
  202.                     0x029e4c4db82240L,
  203.                     0x04961892f5d673L,
  204.                     0x02b291598e4589L,
  205.                     0x11388382c15694L,
  206.                     0x02dad977c9e1feL,
  207.                     0x191d96d4d334c6L]
  208.  
  209.         self.gen.seed(61731L + (24903L<<32) + (614L<<64) + (42143L<<96))
  210.         actual = self.randomlist(2000)[-10:]
  211.         for a, e in zip(actual, expected):
  212.             self.assertEqual(long(ldexp(a, 53)), e)
  213.  
  214.     def test_long_seed(self):
  215.         # This is most interesting to run in debug mode, just to make sure
  216.         # nothing blows up.  Under the covers, a dynamically resized array
  217.         # is allocated, consuming space proportional to the number of bits
  218.         # in the seed.  Unfortunately, that's a quadratic-time algorithm,
  219.         # so don't make this horribly big.
  220.         seed = (1L << (10000 * 8)) - 1  # about 10K bytes
  221.         self.gen.seed(seed)
  222.  
  223.     def test_53_bits_per_float(self):
  224.         # This should pass whenever a C double has 53 bit precision.
  225.         span = 2 ** 53
  226.         cum = 0
  227.         for i in xrange(100):
  228.             cum |= int(self.gen.random() * span)
  229.         self.assertEqual(cum, span-1)
  230.  
  231.     def test_bigrand(self):
  232.         # The randrange routine should build-up the required number of bits
  233.         # in stages so that all bit positions are active.
  234.         span = 2 ** 500
  235.         cum = 0
  236.         for i in xrange(100):
  237.             r = self.gen.randrange(span)
  238.             self.assert_(0 <= r < span)
  239.             cum |= r
  240.         self.assertEqual(cum, span-1)
  241.  
  242.     def test_bigrand_ranges(self):
  243.         for i in [40,80, 160, 200, 211, 250, 375, 512, 550]:
  244.             start = self.gen.randrange(2 ** i)
  245.             stop = self.gen.randrange(2 ** (i-2))
  246.             if stop <= start:
  247.                 return
  248.             self.assert_(start <= self.gen.randrange(start, stop) < stop)
  249.  
  250.     def test_rangelimits(self):
  251.         for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]:
  252.             self.assertEqual(Set(range(start,stop)),
  253.                 Set([self.gen.randrange(start,stop) for i in xrange(100)]))
  254.  
  255. _gammacoeff = (0.9999999999995183, 676.5203681218835, -1259.139216722289,
  256.               771.3234287757674,  -176.6150291498386, 12.50734324009056,
  257.               -0.1385710331296526, 0.9934937113930748e-05, 0.1659470187408462e-06)
  258.  
  259. def gamma(z, cof=_gammacoeff, g=7):
  260.     z -= 1.0
  261.     sum = cof[0]
  262.     for i in xrange(1,len(cof)):
  263.         sum += cof[i] / (z+i)
  264.     z += 0.5
  265.     return (z+g)**z / exp(z+g) * sqrt(2*pi) * sum
  266.  
  267. class TestDistributions(unittest.TestCase):
  268.     def test_zeroinputs(self):
  269.         # Verify that distributions can handle a series of zero inputs'
  270.         g = random.Random()
  271.         x = [g.random() for i in xrange(50)] + [0.0]*5
  272.         g.random = x[:].pop; g.uniform(1,10)
  273.         g.random = x[:].pop; g.paretovariate(1.0)
  274.         g.random = x[:].pop; g.expovariate(1.0)
  275.         g.random = x[:].pop; g.weibullvariate(1.0, 1.0)
  276.         g.random = x[:].pop; g.normalvariate(0.0, 1.0)
  277.         g.random = x[:].pop; g.gauss(0.0, 1.0)
  278.         g.random = x[:].pop; g.lognormvariate(0.0, 1.0)
  279.         g.random = x[:].pop; g.vonmisesvariate(0.0, 1.0)
  280.         g.random = x[:].pop; g.gammavariate(0.01, 1.0)
  281.         g.random = x[:].pop; g.gammavariate(1.0, 1.0)
  282.         g.random = x[:].pop; g.gammavariate(200.0, 1.0)
  283.         g.random = x[:].pop; g.betavariate(3.0, 3.0)
  284.  
  285.     def test_avg_std(self):
  286.         # Use integration to test distribution average and standard deviation.
  287.         # Only works for distributions which do not consume variates in pairs
  288.         g = random.Random()
  289.         N = 5000
  290.         x = [i/float(N) for i in xrange(1,N)]
  291.         for variate, args, mu, sigmasqrd in [
  292.                 (g.uniform, (1.0,10.0), (10.0+1.0)/2, (10.0-1.0)**2/12),
  293.                 (g.expovariate, (1.5,), 1/1.5, 1/1.5**2),
  294.                 (g.paretovariate, (5.0,), 5.0/(5.0-1),
  295.                                   5.0/((5.0-1)**2*(5.0-2))),
  296.                 (g.weibullvariate, (1.0, 3.0), gamma(1+1/3.0),
  297.                                   gamma(1+2/3.0)-gamma(1+1/3.0)**2) ]:
  298.             g.random = x[:].pop
  299.             y = []
  300.             for i in xrange(len(x)):
  301.                 try:
  302.                     y.append(variate(*args))
  303.                 except IndexError:
  304.                     pass
  305.             s1 = s2 = 0
  306.             for e in y:
  307.                 s1 += e
  308.                 s2 += (e - mu) ** 2
  309.             N = len(y)
  310.             self.assertAlmostEqual(s1/N, mu, 2)
  311.             self.assertAlmostEqual(s2/(N-1), sigmasqrd, 2)
  312.  
  313. class TestModule(unittest.TestCase):
  314.     def testMagicConstants(self):
  315.         self.assertAlmostEqual(random.NV_MAGICCONST, 1.71552776992141)
  316.         self.assertAlmostEqual(random.TWOPI, 6.28318530718)
  317.         self.assertAlmostEqual(random.LOG4, 1.38629436111989)
  318.         self.assertAlmostEqual(random.SG_MAGICCONST, 2.50407739677627)
  319.  
  320.     def test__all__(self):
  321.         # tests validity but not completeness of the __all__ list
  322.         self.failUnless(Set(random.__all__) <= Set(dir(random)))
  323.  
  324. def test_main(verbose=None):
  325.     testclasses =    (WichmannHill_TestBasicOps,
  326.                       MersenneTwister_TestBasicOps,
  327.                       TestDistributions,
  328.                       TestModule)
  329.     test_support.run_unittest(*testclasses)
  330.  
  331.     # verify reference counting
  332.     import sys
  333.     if verbose and hasattr(sys, "gettotalrefcount"):
  334.         counts = [None] * 5
  335.         for i in xrange(len(counts)):
  336.             test_support.run_unittest(*testclasses)
  337.             counts[i] = sys.gettotalrefcount()
  338.         print counts
  339.  
  340. if __name__ == "__main__":
  341.     test_main(verbose=True)
  342.