Article View: comp.lang.functional
Article #1072Re: Random permutations, linear time, fully functional?
From: Paul Crowley
Date: Mon, 11 Jan 1993 03:17
Date: Mon, 11 Jan 1993 03:17
71 lines
3571 bytes
3571 bytes
Quoting quale@spock.cs.wisc.edu (Doug Quale) in article <1993Jan10.080153.10321@daffy.cs.wisc.edu>:
>In article <C0KG2y.HvE@dcs.ed.ac.uk> pdc@dcs.ed.ac.uk (Paul Crowley) writes:
>This C code does not solve the problem correctly. It gives n**n
>possible outcomes, and in general the number of permutations of n
>objects, n!, does not divide n**n. For example, it doesn't work
>for n = 3 (try it!).
Damn, you're right. This is more than a little embarassing since I've
been standing by that code all last term. However six does not divide
nine, so I guess I've got to modify it. I think it'll work if I make a
slight change to the source array. This time I'll prove it correct.
/*
* source and result are arrays of integers of length n.
* For random permutations, source should be made up of a lot of
* random numbers such that 0 <= source[i] <= i.
*/
void randpermute(source, result, n)
int *source, *result, n;
{
int i;
for(i = 0; i < n; i++) {
/*
* Loop invariant: just before the test against n,
* result[k] for 0 <= k < i is a permutation of the nat. numbers less than i
* and the permutation is random if source is random as specified.
* Proof below.
*/
result[i] = result[source[i]];
result[source[i]] = i;
}
}
A permutation of length k is random if the probability of it being equal
to a given permutation gperm is 1/(k!). Base case of the invariant: the
null permutation arises with probability 1 = 1/(0!).
Inductive step: supposing the invariant holds for i = k where k < n.
After the execution of the next two source lines, is the subarray size
k+1 a permutation at all? This divides into two subcases:
* source[k] = k
In this case, result[k] ends up being equal to k and the rest of the
array is unchanged; since the rest of the array is a permutation, this
is a permutation.
* source[k] < i
In this case, result[k] takes some value between 0 and k-1, and the
entry that used to hold that value now holds k. Since the rest of the
array was a permutation, all the values between 0 and k are still
present and the new subarray is also a permutation.
Now, consider the element h in gperm such that gperm[h] = k. In order
for the resulting subarray to equal gperm, two conditions must hold:
result[k] must equal h, and the old subarray before the loop stepped
around must be equal to gperm except that result[h] must equal gperm[k].
The probability of these two is 1/(k+1) and 1/(k!) respectively, so the
probability that the new subarray is gperm is 1/((k+1)!) as required.
Sorry if this isn't very clear but it's 3am where I am. For people who
want to know what all this C is doing in comp.lang.functional, I asked
if the thing that this C function does in linear time can be done in a
pure functional style in linear time. Except that I got the C wrong.
Apologies, and thanks to Doug Quale for pointing it out.
__ _____
\/ o\ Paul Crowley pdc@dcs.ed.ac.uk \\ //
/\__/ Trust me. I know what I'm doing. \X/
Technical Details
Message-ID:
<C0o6HH.2L2@dcs.ed.ac.uk>Path:
arc1-ca.pugleaf.net!sparky!uunet!pipex!doc.ic.ac.uk!uknet!edcastle!dcs.ed.ac.uk!pdcReferences:
<C0KG2y.HvE@dcs.ed.ac.uk> <1993Jan10.080153.10321@daffy.cs.wisc.edu>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!sparky!uunet!pipex!doc.ic.ac.uk!uknet!edcastle!dcs.ed.ac.uk!pdc From: pdc@dcs.ed.ac.uk (Paul Crowley) Newsgroups: comp.lang.functional Subject: Re: Random permutations, linear time, fully functional? Message-ID: <C0o6HH.2L2@dcs.ed.ac.uk> Date: 11 Jan 93 03:17:40 GMT References: <C0KG2y.HvE@dcs.ed.ac.uk> <1993Jan10.080153.10321@daffy.cs.wisc.edu> Sender: cnews@dcs.ed.ac.uk (UseNet News Admin) Reply-To: pdc@dcs.ed.ac.uk (Paul Crowley) Organization: Edinburgh University Lines: 71