robison@m.cs.uiuc.edu (08/17/88)
Though the following appears to be a math problem, I'm posting in comp.lang.misc because the problem was stated in the context of imperative languages vs. applicative languages. [1] says that the fastest imperative algorithm takes O(n) time, while the fastest applicative algorithm takes O(n log n) time. Problem: Random Permutation Description: Given n and a sequence of n integers drawn independently from a uniform distribution over 1..n, produce a uniformly random permutation of the sequence 1..n. My question is: Am I either misreading the question? It would seem to be impossible. There are n^n possible inputs, and n! possible outputs. In general n! does not divide n^n evenly. Can anyone clarify this, or put me in contact with the authors? [1] Carl G. Ponder, Patrick C. McGeer, and Antony P-C. Ng, "Are applicative languages inefficient?", SIGPLAN Notices, vol. 23,6, June 1988, 135-139. Arch D. Robison University of Illinois at Urbana-Champaign CSNET: robison@UIUC.CSNET UUCP: {pur-ee,convex}!uiucdcs!robison ARPA: robison@CS.UIUC.EDU (robison@UIUC.ARPA)
g-rh@cca.CCA.COM (Richard Harter) (08/17/88)
In article <5200012@m.cs.uiuc.edu> robison@m.cs.uiuc.edu writes: >Though the following appears to be a math problem, I'm posting in comp.lang.misc >because the problem was stated in the context of imperative languages vs. >applicative languages. [1] says that the fastest imperative algorithm takes >O(n) time, while the fastest applicative algorithm takes O(n log n) time. > Problem: Random Permutation > Description: Given n and a sequence of n integers drawn independently > from a uniform distribution over 1..n, produce a uniformly > random permutation of the sequence 1..n. >My question is: Am I either misreading the question? It would seem to >be impossible. There are n^n possible inputs, and n! possible outputs. >In general n! does not divide n^n evenly. Can anyone clarify this, or >put me in contact with the authors? You are misreading the question. There is only one input, namely the given sequence of length n. The problem is that you are given a sequence of integers a1 ... an. Generate a uniformly random permutation of that sequence. From the statement of the problem there may be duplicates in the sequence, but that is irrelevant. The imperative algorithm runs as follows: for i from [1...n] sequentially chosen select j from [i...n] randomly exchange a(i),a(j) end loop --- -- In the fields of Hell where the grass grows high Are the graves of dreams allowed to die. Richard Harter, SMDS Inc.
ken@aiva.ed.ac.uk (Ken Johnson) (08/19/88)
Story so far: Looking for a way of randomly permuting N elements in a declarative language. The imperative algorithm is > for i from [1...n] sequentially chosen > select j from [i...n] randomly > exchange a(i),a(j) > end loop Here it is in Prolog. Untested etc. I am reasonably certain you could speed this up, but the question was to show that it could be done at all, and I've only got ten minutes... % randperm(List_in,List_out) % Random permutation of List_in. Mode: randperm(+,-). % Not debugged, warranted or anything. If you copy this source in a % program and make money out of it, please send me some. % Good Luck! randperm(List_in,List_out) :- length(List_in,N), % Length of list (system func) randperm(1,N,List_in,List_out). randperm(I,N,List_in,List_in) :- % Done I > N. randperm(I,N,List_in,List_out) :- I =< N, random(N,R), % Library function (?) R is random int % between 1 and N inclusive exchange_elements(I,R,List_in,List_1), % Swap elements J is I + 1, randperm(J,N,List_1,List_out). exchange_elements(I,J,List_in,List_out) :- % Get Ith and Jth elements get_elem(I,List_in,Ei), % and swap. This is more get_elem(J,List_in,Ej), % time consuming than put_elem(J,List_in,Ei,List_1), % necessary but it will work put_elem(I,List_in,Ej,List_out). get_elem(1,[X|_],X). % Find I'th element of list get_elem(I,[_|T],X) :- I > 1, I1 is I - 1, get_elem(I1,T,X). put_elem(1,[_|T],X,[X|T]). % Replace I'th element of % list by X giving new list put_elem(I,[H|T],X,[H|U]) :- I > 1, I1 is I - 1, put_elem(I1,T,X,U). -- ------------------------------------------------------------------------------ From: Ken Johnson (Half Man Half Bicycle) Address: AI Applications Institute, The University, EDINBURGH Phone: 031-225 4464 ext 212 Email: k.johnson@ed.ac.uk
wsmith@m.cs.uiuc.edu (08/22/88)
This is an example of why informal specifications are not always the best. If the problem that was meant to be described and the problem that was described in responses to this discussion are put next to each other, they don't match. The specification says that the random integers are drawn from 1 to n, while the implementation draws the integers from [i..n]. ^ ^ These are not the same thing. # # Problem: Random Permutation # # Description: Given n and a sequence of n integers drawn independently # from a uniform distribution over 1..n, produce a uniformly ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # random permutation of the sequence 1..n. > for i from [1...n] sequentially chosen > select j from [i...n] randomly ^^^^^^^ > exchange a(i),a(j) > end loop I would vote that the informal specification does not specify the intended problem. I propose that instead of selecting n integers drawn from 1..n, the problem specifiction only require that the product of the ranges of the selected numbers equal n!. I think that, if it were correct, the original specification is biased to the imperative language's implementation. Proposed problem definition: < Description: Given n and a sequence of integers selected from a < uniform distribution of 1 to m[i] for the ith integer, < subject to the constraint that the product of the m[i]'s < equals n!, produce a uniformly random permutation of the < sequence 1..n. The problem requires the numbers being shuffled to be the numbers 1 to n and that the amount of "randomness" used to be a minimum. Bill Smith wsmith@cs.uiuc.edu uiucdcs!wsmith
robison@m.cs.uiuc.edu (08/23/88)
The paper cited[1] deliberately specifies problems biased towards imperative languages. The authors are asking if applicative languages are inherently slower than imperative languages (in the asymptotic sense). Seven problems were specified for which the known imperative solutions are faster than the known applicative solutions. For example, another problem in the paper is: Problem: Array Transactions Description: Given n and sequence of k read/write operations to array indexed 1,...,n, produce the sequence of results of the read operations. Let k>n. This is solvable in O(k) time on an imperative machine, but the best known on an applicative machine is O(k log n). (The solution simulates the array with an AVL tree.) [1] Carl G. Ponder, Patrick C. McGeer, and Antony P-C. Ng, "Are applicative languages inefficient?", SIGPLAN Notices, vol. 23,6, June 1988, 135-139. Arch D. Robison University of Illinois at Urbana-Champaign CSNET: robison@UIUC.CSNET UUCP: {pur-ee,convex}!uiucdcs!robison ARPA: robison@CS.UIUC.EDU (robison@UIUC.ARPA)
ok@quintus.uucp (Richard A. O'Keefe) (08/23/88)
In article <532@aiva.ed.ac.uk> ken@uk.ac.ed.aiva (Ken Johnson,E32 SB x212E) writes: >Story so far: Looking for a way of randomly permuting N elements >in a declarative language. >Here it is in Prolog. Untested etc. I am reasonably certain you could >speed this up, but the question was to show that it could be done at all, >and I've only got ten minutes... This topic has already been discussed in comp.lang.prolog. Results to date: if terms can have at most K elements, an O(N.log N) worst case time method exists. K if terms can have any number of elements (say >2N), an O(N) expected time method exists. An O(N.lg N) method is available in the Quintus Prolog library. It has the structure of a sort, but instead of doing comparisons it generates O(N.lg N) random bits. [An N.log(K,N) method would be like a radix sort.] Note that since there are N! permutations, a method of generating random permutations must generate at least lg(N!) = O(N.lg N) random bits.