Does MATLAB have a Birthday Problem?
Show older comments
The Birthday Paradox or problem asks for the probability that in a room of n people, 2 or more have the same birthday (not date), assuming all years have N = 365 days. It is called a paradox because most people are surprised by the answer when there are (say) 30 people in the room.
Many applications require long sequences (or large vectors) of random numbers. In MATLAB these are supplied by the simple statement r = rand(n,1). This statement fills the vector r(n,1) with double precision random numbers uniformly distributed on (0,1).
Here is my question:
What is the probability that duplicates occur in r = rand(n,1), as n gets large?
I have an answer to this question but I would like to see what others come up with so that I can check the validity of my answer.
5 Comments
Walter Roberson
on 5 Feb 2011
You will have to specify exactly which random number generator is being used.
Jiro Doke
on 5 Feb 2011
This is more of a mathematics question, rather than a MATLAB question. You should extend the question, state what you have discovered (in regards to "rand"), and ask specific MATLAB programming questions to help you get the final answer.
Oleg Komarov
on 5 Feb 2011
I vote this question for best Title :D
Malcolm Lidierth
on 8 Feb 2011
In the UK, when the BBC first moved its football highlights show ('Match of the Day') from its traditional Saturday night slot, the birth rate tripled 9 months later. The birthday paradox, makes a false assumption: birthdays are not random - they vary seasonally and are influenced by all sorts of things.
Derek O'Connor
on 9 Feb 2011
Accepted Answer
More Answers (4)
Richard Willey
on 7 Feb 2011
1 vote
Hi Derek
Your question about the birthday problem is best viewed as a special case of a more general topic: How should measure the statistical properties of a random number generator?
Rather than using this formulation of the birthday problem to reinvent the wheel, I recommend looking at established literature on this topic. A lot of very qualified experts have spent a lot of time and effort developing criteria to measure the quality of random number generators. The “Diehard” test suite is one such test (Diehard uses a reformulated version of the birthday paradox as one part of the test suite). Alternatively, there is another test suite that uses a combination of
- A monobit test (testing the distribution of ones and zeros in a sequence)
- A “Poker” test (a modified chi-square test)
- A Longruns test (checking whether there are runs of length 34 or greater within a 20,000 bit sequence)
- An autocorrelation test
Most of MATLAB’s code can be inspected by users. If you have questions about the specific implementation of a given algorithm – for example, what version of Twister does MathWorks use – you typically have the option to inspect the function and see how the code was written.
Regards,
Richard
4 Comments
Mark Shore
on 7 Feb 2011
The test suite information is useful, but regardless of the number of "very qualified experts", bugs or flawed algorithms do manage to find their way into code, and the rand function in MATLAB is not clear text code that can be inspected by users.
Walter Roberson
on 7 Feb 2011
The @Randstream.list documentation does indicate which MT algorithm is used and gives a link to a site that has implementation.
However, the description of the code indicate only 32 bit precision for the (0,1) algorithm, and we have demonstrated at least 53 bit precision, which is documented as occurring for [0,1) . Possibly Mathworks wrapped the 53 bit version with a rejection of an exact 0 result; such an implementation is quite plausible, but we don't *know* since the documentation that is available to us does not specify.
The release notes introducing RandStream might have documented the precision and range of MT, but I am unable to dig the information out of the current documentation. I think dropping that table of producible values was a mis-service to the users.
Derek O'Connor
on 7 Feb 2011
Richard Willey
on 9 Feb 2011
Hi Derek
Sorry that I misconstrued your original question. Here’s one last quick comment:
Random number generators are designed to sample from specific distributions.
A random number generator that generates normally distributed random numbers is not identical to a random number generator that generates normally distributed random numbers (but excludes duplicate values)
Suppose you were using an RNG to generate random integers from a Poisson distribution with lambda = 10. Would you be happy if the RNG was “gimmicked” to exclude duplicate values? I’d argue that this would be a very flawed RNG because the samples being generated aren’t actually coming from a Poisson distribution.
Let’s move back to the example using “rand”. We’re dramatically changing the granularity of the problem, but the basic principle remains the same…
At the end of the day, I don’t think it’s reasonable evaluate an RNG based on a design criteria which is (arguably) contrary to the way in one would expect an RNG to behave (in this case, deliberately excluding duplicate values)
If you have an application that needs RNGs that are generated from “some distribution that looks very much like a normal distribution but is guaranteed never to produce a duplicate value” then you should probably find an RNG designed to do precisely that.
From my own perspective, I’d worry about implementations that were this persnicetky…
regards,
Richard
Walter Roberson
on 5 Feb 2011
0 votes
Upper bound: 1/2+(1/2)*sqrt(1+8*S*ln(2)) where S is the number of distinct random numbers that can be generated.
Unfortunately Mathworks does not appear to document which Twister version they are using. Traditionally their random number generators were (0,1); mt19937ar over (0,1) is 32 bits precision, but over [0,1) is 53 bits precision.
If we speculate that Mathworks used the (0,1) version with 32 bits precision, then according to Wikipedia the 50% probability is at 7.7 × 10^4 numbers.
1 Comment
Peter Perkins
on 8 Feb 2011
Walter, the User Guide includes this: "mt19937ar: The Mersenne Twister, as described in [9], with Mersenne prime 2^19937-1. This is the generator documented at http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html. It has a period of 2^19937-1. Each U(0,1) value is created using two 32-bit integers from the generator; the possible values are all multiples of 2^-53 strictly within the interval (0,1)."
Mark Shore
on 5 Feb 2011
0 votes
Using the formula Walter gives leads to the following numbers for a 50% probability:
32-bit 7.716e4
53-bit 1.112e8
57-bit 4.470e8
64-bit 5.056e9
80-bit 1.294e12
A brute-force check of 1e10 random numbers
for n=1:1000 mindiff(n) = min(diff(sort(rand(1e7,1))))/eps(1); end
found 11 identical values, or a ~50% probability for 4.44e8 numbers, suggesting that the equivalent of a 57-bit precision RNG is in use.
14 Comments
Jan
on 5 Feb 2011
Isn't this a strange result, if we can store 53 bits for the mantissa in DOUBLEs only?
Mark Shore
on 5 Feb 2011
Agreed, but I didn't try to work out either the details of the distribution calculation or look at the Mersenne twister RNG algorithm to see if it uses some form of extended precision calculations.
Jan
on 5 Feb 2011
Even if MT use extended precision, the results are stored in DOUBLEs and all bits beyond the 53rd one would be cut away. Anyway, diff(sort(rand)) finds a difference of 1/2^53 => RAND replies 53 bit, as expected.
Walter Roberson
on 5 Feb 2011
I recall that sometime in the fall, I posted that MT generates only multiples of 2^32 (or perhaps it was 2^53), but that the response was that every floating point number in (0,1) could be generated (with appropriately weighted probability.) The numbers below 1/2 gain additional bits from the exponent, so in theory about 62 bits worth should be available (1 sign bit for the number as a whole, and roughly half the 11 bits worth of exponent represent negative exponents, each of which represents a generatible number less than 1.
Each individual uniform random number over (0,1) is not identical probability, as it is necessary to generate [1/2,1) with the same total probability that one generates (0,1/2) even though there are many more representable numbers in (0,1/2). This does, of course, contradict the assumption of the birthday problem that each of the elements is equal probability.
Walter Roberson
on 5 Feb 2011
Jan, you can't be sure -- you just might not have happened to have generated a value smaller than 1/2^53.
Mark Shore
on 5 Feb 2011
I should also point out a possible flaw in my assumption that 1000 trials of 10^7 numbers is the same as a single trial using 10^10 numbers - but the difference should be small. I'll run a few trials with different parameters; my spare computer never complains about working overtime on Saturday...
Jan
on 5 Feb 2011
@Walter: I was too sloppy. I meant: diff(sort(rand)) finds a difference of 1/2^53 => RAND replies _at least_ 53 bit precision, assuming that the values are equally distributed.
Walter Roberson
on 6 Feb 2011
I am having difficulty locating the discussion of whether MT generated multiples of 2^(-53) or generated every possible number in (0,1) .
Bruno Luong
on 6 Feb 2011
According to my test, I have not found RAND generate anything but multiple integer of 2^(-53). So it seems Walter is right.
Mark Shore
on 6 Feb 2011
Some more thought, and test results. First, Jan is correct and whatever internal precision the MT algorithm may use, it will still be converted to MATLAB doubles with a granularity of 2^-53 and 2^53 -1 distinct values over (0,1).
Second, 1000 trials of 1e7 values is NOT the equivalent to 1 trial of 1e10, as Derek's figures (and more work) suggests. 27000 runs of 1e7 gave a probability p of a pair of duplicate values of 0.006 +/- 0.002.
Rearranging a formula in the Wikipedia reference noted by Walter gives, for n draws from a possible 2^53 distinct values, the probability p of at least one duplicated value of
p = 1 - exp(-n^2/(2*2^53))
For n = 1e7, this returns a p of 0.0055, consistent with my test value.
Jan
on 6 Feb 2011
@Bruno: Which theory of Walter do you mean? As far as I understand we all agree that RAND replies more than 32 bits, but at least 53 bits (that's all I wanted to say). And if the numbers should be equally distributed in (0,1), it cannot not be more than 53 bits. Correct until here? Using the additional bits for numbers < 0.5 would be very unkind for a RNG and MEAN(RAND(1e8,1)) would reveal this fast.
Do we agree, that Mark's 57bit theory is not correct?
@Walter: Derek asks for repeated values. I do not see the connection to "every possible number in (0,1)".
Mark Shore
on 6 Feb 2011
@ Jan, to avoid any misunderstanding, my 57-bit hypothesis was based on faulty analysis and is incorrect.
Bruno Luong
on 6 Feb 2011
@Jan: Walter is right by stating the fact that Matlab rand() command returns only integer-multiple of 2^(-53).
Walter Roberson
on 6 Feb 2011
Jan, the testing I did was unable to find a non-zero difference smaller than 2^(-53) as well. But it could just be quite rare. I don't think I have time to generate 2^53-ish values to check!
Walter Roberson
on 8 Feb 2011
0 votes
The Matlab content of this question is:
- How many distinct random numbers can be generated in Matlab. (We still don't know for sure, but 2^53-1 appears likely.)
- Are the numbers generated with equal probability. (The algorithm would have to be examined in detail to be sure. If there is a bias, it is minute.)
- Is the period of the generator greater than the number of different possible values, or is it equal to the number of possible values?
Anything beyond that is a straight-forward application of the Birthday Paradox and is thus a mathematical question rather than a Matlab question. This forum exists to serve Matlab questions, not to serve mathematical questions and especially not to discuss the risks of fly-by-wire or to discuss deliberate fraud by Matlab users.
One only has to look at the period of MT and compare that to the largest number directly representable in Matlab in order to see that rand() will eventually generate a duplicate. Software that expects otherwise is broken.
It would be fair game to ask Mathworks to create a random number generator with no repetitions for those people who need one; it would even be fair game to ask Mathworks to rename rand() to make it clear that duplicates were possible. Those would be Matlab issues. Considering the amount of legacy code that uses rand(), I think Mathworks would want some strong evidence that "rand with replacement" was widely enough misunderstood to be worth renaming; I personally don't think speculation about possible trouble in genome software would qualify.
10 Comments
Bruno Luong
on 8 Feb 2011
I don't agree with Walter. Asking question with relation to Birthday Paradox make it becomes clear why some properties of RAND() are important to be known. It *is* a Matlab related question. The boundary of side topics discussion are possibly up to individual user to judge. Mileages will vary. With all due respect I don't see the reason why we have to stick with your point of view of what has to be discussed here.
The whole notion of "rand with replacement" does not make much sense to me. "RANDI" is probably a better candidate, but that's covered by many existing FEX tools.
The second question is not well formulated. Richard has explained why.
The third question seems to be out of the blue. Period has no relationship with the set cardinal. It can be found on MT papers.
Only the first question make some sense to me.
Peter Perkins
on 8 Feb 2011
Since R2008b, MATLAB (at start-up) has used the "standard" mt19937ar Mersenne Twister. Mark and Derek are right that this code is not visible to the user in the way that much of MATLAB's code is, because for speed reasons it has to be implemented in compiled C code. The idea behind expecting you to use that cryptic "mt19937ar" in your code when creating a random stream was to hopefully help make clear _exactly_ what algorithm is used, and the documentation does point to the original code authored by Nishimura and Matsumoto (similarly for "mrg32k3a", either can be googled). And Bruno is right, the doc does not specifically say how we get from 32bit integers (which is what the MT "natively" creates) to d.p. floating point. If you look at N&M's original code, you'll find that they have a piece of utility code that takes two 32bit integers and shifts and divides to map into (0,1), and that's what MATLAB does (I guess that needs to be added to the doc as well, it's hard to know when to stop). So, mt19937ar in MATLAB produces integer multiples of 2^-53 strictly between 0 and 1, bu since the period is so long you are guaranteed to repeat individual values long before you wrap around.
The other generators are similar in that respect, except for "swb2712". It actually produces all possible floating point values within (0,1), and works "natively" in d.p. Cleve Moler's book Numerical Computing with MATLAB went into great detail on this algorithm when it was the default, you can find it on line.
Bruno Luong
on 8 Feb 2011
Thanks Peter for the info. Now it's clear.
Derek O'Connor
on 8 Feb 2011
Walter Roberson
on 8 Feb 2011
Can't be as simple as that, Derek, that's for [0,1) whereas Mathwork's version is (0,1) .
Derek O'Connor
on 9 Feb 2011
Walter Roberson
on 9 Feb 2011
If "a" and "b" both come out as 0, then Isaku's code would return 0.0, which is not a permitted output from Matlab's rand. Notice the reference to the "closed interval" and the lower endpoint is 0. But http://www.mathworks.com/help/techdoc/ref/rand.html is clear that the output is the open interval -- i.e., excluding 0 from the possibilities.
Bruno Luong
on 9 Feb 2011
Personally I'll believe on the doc and also what Peter wrote earlier:
[ So, mt19937ar in MATLAB produces integer multiples of 2^-53 strictly between 0 and 1,]
There is no indication of the twister on FEX submission is the exact code of Matlab RAND().
Peter Perkins
on 10 Feb 2011
While the code on the FEX is indeed a wrapper around N&M's original mt19937ar code, the wrapper differs slightly from the implementation that the RAND function has used for the MT since that generator was officially supported circa R2007b. You have noticed two things: the range, and the speed. There is also the treatment of a zero seed. I can't recall if there are other differences, but in any case, RAND is RAND, and the FEX submission is the FEX submission.
The doc for RAND and my earlier comments are correct, and in particular RAND (internally) rejects an exact (double precision) zero in the very infrequent event that it happens to generate one.
Hoping this clears it all up. I almost hesitate to even mention it, but as described in the RandStream doc, you can also set the FullPrecision property of an mt19937ar stream to false, and get values that are multiples of 2^-32.
Bruno Luong
on 10 Feb 2011
Thanks again Peter. That settles the question.
Categories
Find more on Birthdays in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!