1.3K views

Uploaded by Derek O'Connor

These are notes on the generation of large random permutations. Included is a description of the RPGLab package written in Matlab that can be used to generate and test random permutations.

- Permutation
- Design for Assembly line performance: The link between DFA metrics and Assembly line performance metrics
- simulation handbook.pdf
- Permutation Patterns
- 338
- 2149
- fasc1
- The Art of Computer Programming, Volume 4A
- O'Connor -- Fisher-Yates & Durstenfeld Shuffle Algorithms: History
- O'Connor -- Common Errors in Numerical Programming
- O'Connor -- Boolean Matrix Inverses
- p06
- Securing Speech in GSM Networks using DES with Random Permutation and Inversion Algorithm
- 0478_w15_ms_21
- Permutations Combinations
- Bioelectrical ConcentrationF12
- ccalc
- Recommending System Assignment - 10131006
- Assignment 2 on network security
- Laplace

You are on page 1of 36

AND THE

Derek O’Connor

1 Introduction

Permutations and combinations have been studied seriously for at least 500 years. Some

of the best mathematicians have contributed to this research: Bernoulli, Newton, Stir-

ling, Euler, . . ., etc. This area of study has expanded greatly in the last 100 years and is

now called Combinatorics, with permutations and combinations forming the foundation.

That is, you can’t do combinatorics unless you know (and mind) your P s and C s.

Permutations and combinations are considered to be so important that even school-

children are required to study the subject. Figure 1 shows the opening page of the

P&C chapter in Hall’s Algebra, which I bought as a secondary school pupil in 1960, price

10s/6d. Note that they use the good-old-fashioned notation nCr rather than the ambigu-

ous (nr). They also use nPr , but I don’t know the modern equivalent.1

This is an outline of these notes:

* Started: 3rd Jan 2010. Web: http://www.derekro
onnor.net email : derekro
onnoreir
om.net

1 There is no need for all this notational fuss: C ( n, k ) for combinations and P (n, k) for permutations will

do nicely.

1

Derek O’Connor Random Permutation Generation

Figure 1. H. S. H ALL , An Algebra for Schools, 1 ST E DITION 1912, REPRINTED 1956, M ACMILLAN , L ONDON

Derek O’Connor Random Permutation Generation

2 Definitions

ordered list A = {a1 , a2 , . . . , an } into a one-to-one correspondence with A itself.

In what follows we assume that A is the set {1, 2, . . . , n}. We will represent any per-

mutation as a M ATLAB vector p(1 : n), where p(i ) is the position of element i in the

permutation. Thus we have

p

{ a1 , a2 , . . . , a n } −

→ { a p ( 1) , a p ( 2) , . . . , a p ( n ) } (2.1)

i 1 2 3 4 5 6 7 8 9 10

p (i ) 3 4 9 2 10 8 6 1 5 7

exact closed form for n!, but Stirling’s Approximation is excellent for even modest n

√ n n 1 1 139

1

n! ≈ 2πn 1+ + + + O (2.2)

e 12n 288n2 5140n3 n4

n N = n!

101 107

102 10158

103 102,568

104 1035,659

105 10456,573

106 105,565,709

107 1065,657,059

108 10756,570,556

109 108,565,705,523

1010 1095,657,055,186

in a few minutes. Table 2 is there to remind us of the truly gigantic size of the permutation

space from which these are generated.

Definition 2. (Identity.) The identity permutation is p = [1, 2, . . . , n], that is, p(i ) = i, i =

1, 2, . . . , n. In M ATLAB the statement p = 1:n; generates the identity permutation.

of its elements i, j with all others staying the same. Any transposition of p gives a new

permutation q, if i 6= j.

Derek O’Connor Random Permutation Generation

Definition 4. (Fixed Point.) A fixed point of a permutation p is any i such that p(i ) = i. It

is called a fixed point because the element ai does not move under the permutation. The

Identity Permutation p = (1, 2, . . . , n) has n fixed points.

p(i ) 6= i, i = 1, 2, . . . , n.

of a cycle is the number of elements in the cycle. A fixed point is a cycle of length 1. The

identity permutation has n cycles of length 1.

Definition 7. (Cyclic Permutation.) A cyclic permutation has 1 cycle. That is, starting at

any point i we have a sequence i → p(i ) → · · · → j → p( j) → i, which includes every

element of {1, 2, . . . , n}. This cycle has length n.

It should be obvious that a cyclic permutation has no fixed points and is, therefore, a

derangement. Equally obvious is that not all derangements are cyclic permutations.

3 Random Permutations

the set of all n ! permutations of n numbers. That is, a permutation p is drawn from the

set of all permutations in such a way that the probability of drawing a given permutation,

p, is 1/n ! .

The reason for our interest in random permutations is simple: we are interested in permu-

tation vectors where n ≥ 106 . For example, if we wish to test a new super-duper sorting

algorithm on inputs of size n ≥ 106 , then we must resort to testing with a random sample

from the vast (N ≥ 106 !) space of permutations.

A directed arc i → j exists if p[i ] = j. Of necessity there can be only one arc from any

node i. Also, of necessity, each node has one incoming arc. [ WHY ?] Hence a permutation

is a directed graph with n nodes and n directed arcs. An example of a permutation graph

of 10 nodes is shown in Figure 2. The the permutation shown in Figure 2 has 10 nodes,

1 5 2 3 4 6 8 7 9 10

5 1 3 6 8 4 2 7 10 9

p 5 3 6 8 1 4 7 2 10 9

1 2 3 4 5 6 7 8 9 10

Derek O’Connor Random Permutation Generation

The Number of Fixed Points. The probability that a permutation of length n has k fixed

points is

1

Pr( p has k fixed points ) ∼ , (3.1)

ek!

and the average number of cycles of length k in a permutation of length n is 1/k with

variance 1/k. Hence, the average number of fixed points in a permutation of length n is 1, with

variance 1. This is a surprising result because the average is independent of the length of

the permutation.

The Number of Derangements. Let D (n) be the number of derangements in the set of

n! permutations of length n. Then

n

(−1)k n! + 1

n!

D (n) = n! ∑ = → , as n → ∞. (3.2)

k=0

k! e e

Hence

D (n) 1

→ ≈ 0.36788.

Pr( p is a derangement) = (3.3)

n! e

This means that in a large sample of random permutations about 37% of them will be

derangements, independent of n, the length of the permutation.

The Number of Cycles. The number of cycles in a random permutation ranges from 1,

a cyclic permutation, to n, the identity permutation. Let Ck (n) be the number of cycles of

length k in a permutation p(1 : n).

The expected number of cycles of length less than or equal to m is Hm .

The expected number of cycles of any length is Hn , or about log n. The average length of

n

a cycle is thus .

log n

and (n − 1) ! of these will be cyclic.

Cn ( n ) 1

Cn (n) = (n − 1)! and Pr( p(n) is cyclic) = = . (3.4)

n! n

This means that in a large sample of random permutations a decreasing fraction of them

will be cyclic (e.g., 1% for n = 100, 0.1% for n = 1000), while the fraction of derangements

remains constant at 37%.

2 Most of what follows is from Sedgewick & Flajolet, Analysis of Algorithms, Addison-Wesley, 1996, Chap-

ter 6.

Derek O’Connor Random Permutation Generation

i Start Length Start Length Start Length Start Length

1 1 419486 3 765,295 3 7,946,786 1 715510740

2 2 563485 1 183,715 2 1,805,558 4 143677250

3 44 15656 38 41,873 74 168,213 20 135801148

4 509 432 97 8,007 586 53,765 148 3267451

5 1010 119 1,114 775 1 13,346 1303 1160044

6 5793 542 4,374 216 1,409 11,991 2774 461529

7 7003 255 3,307 100 14,927 329 9415 119643

8 16043 27 465 15 934,615 7 459730 1876

9 220629 2 253,498 4 958,846 3 7116764 135

10 578575 5 1,805,235 1 4362180 76

11 815788 2 3,807,650 1 9884753 37

12 30479687 29

13 112643112 23

14 111244636 19

In the next section we will discuss the two main algorithms for generating random per-

mutations. However, before we do this we should have methods for checking the prop-

erties of random permutations. This will allow us to check the output of any generator

so that we do not waste time developing bad algorithms and programs that implement

them. These methods have been collected in a package called RPGL AB which is dis-

cussed in Section 8.

Derek O’Connor Random Permutation Generation

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

34 60 68 78 50 4 7 97 16 74 98 76 8 65 99 75 10 30 91 95

21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40

42 15 80 6 90 70 28 47 32 1 63 51 49 57 59 72 66 85 53 94

41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

p =

9 83 87 81 43 84 12 23 54 22 79 92 45 62 64 31 46 82 52 93

61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80

5 58 35 55 20 37 18 19 67 44 24 26 11 41 27 88 73 89 13 36

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

56 40 38 3 29 21 69 48 71 17 39 96 25 33 2 14 61 86 77

57

34 46

1

84

30

3

18

68

64

67

19

55 95 20

65

2

14 69

60 91

96

93

87

92 39

25 8 97 43 53

52 45

13 61

90 79 5

59

66 51

17 50

35

37 7 62

32 54

10 22

58

63

49

29 15

74

82

31

33

85 99

41 40

94

56

38 77

9

81

83 73

16

42 11 44

21 98

75 86

70

27 6 24

26

28

72 4 71

47

36

78 89

12

80

76 23

88 48

3 Figure 3 produced by the M ATLAB function GrVizp.m and GraphViz with ‘neato’ layout.

Derek O’Connor Random Permutation Generation

84 56

102 23

130 74

20 41

2 77

127 118

119 55

78

128

144

94

121

92

45

38

104

59

22

14

116

90

82

80

96

12

70

149

25 147

150 68 3

137

50 8

4 103

39

34

123 93

126 95 85

69 142

148 15

17

141 32

81 29

140 136 6

1

110 72

120 139

135

122 51

125 27 146

52 21 13

48

10 57

54 53

63 5

49

129

65 138

24

46

67 117

86

31

133 112

33

83 11

60 134

61 143

26 44 75

101

97 7

124

100 79 47

107 91

35

64 145 73

43

40

62 131

19

113 106 111

66

30 28

132

58 105

89

114

37

36

98

99

9

115 87

42 88

109 18

76 16

108 71

Derek O’Connor Random Permutation Generation

137 7 103

195

68

118

189

34

11

166

121

48

28

3

99

180

120

172

40

9

24

156

190

74 86

23 52 147

126

44 1

76

50 15

200

38 26

73

29

70 64

161

168

138

132 158

154 185

124

65

12 108 80 179

153

19 110 130

199 104 53 90

67 51 159

92

96

101 21 174

20 58

46 66 18 5

181 42

139 143

54

145

93

167 173

106

32

144

83 142 72

155 194

59

136 87

71 119

111 94 160

116 186

100 127

10 43 131 35 157

81 107

69

163

57

117

151

188 36

148

141 62

191 150

196 25 114

182

61

102

13

37 60 129

33

152

184

128 177

183 193

165

41 77

79

169 170

84

30

75 63

113

112

146 98

49

22 109

6

16 4

2

125

115

135

133 176

134 78 105

82

192

31

56

91

88

175 164

187

197

95 17

89 122

85

140 198

171

45 14

162

39

55 178

123 47 149

97 27

Derek O’Connor Random Permutation Generation

Algorithms and programs for generating random permutations have been around since

the start of the computer age. In fact Knuth has tracked down the first known algorithm

to R. A. Fisher and F. Yates, Statistical Tables, (London, 1938), Example 12.4 There appear

to be just two types of algorithm which are based on: (1) Random transpositions, and (2)

Sorting a random vector.

The production of random permutations may be viewed in different ways:

2. Sampling with replacement from the set of all permutations of length n.

3. Sampling without replacement from the set of integers {1, 2, . . . , n}.

Conceptually, building a random permutation step-by-step is simple: take a random sam-

ple of size n without replacement from a set of n elements S = {s1 , s2 , . . . , sn }.

Algorithm RandPerm(S) →p

S = { s1 , s2 , . . . , s n }

elements of the set

for k := 1 to n do

Choose an element srk at random from S

S := S − {srk }

p[k] := srk

endfor k

return p

endalg RandPerm

Notice that all the elements of S will be chosen and put into the array p. The array

is needed to preserve the random order in which the elements were drawn. Thus p is

returned containing a random permutation of S.

the set S. We need to show that each permutation is equally likely with probability 1/n!

of occurring. We prove this by induction on k.

The size of the set |S| decreases by 1 at each stage and so Pr(srk ) = 1/(n − k + 1) at stage

k, where srk is the element chosen at random at stage k. This is obviously true for k = 1,

with Pr(s1r ) = 1/n. Hence, because srk is chosen uniformly and independently, we have

1 1 1 1

Pr(s1r , s2r , . . . , srn ) = Pr(s1r ) Pr(s2r ) · · · Pr(srn ) = · ··· = . (4.1)

n n−1 1 n!

Thus we have proved that Algorithm RandPerm generates all possible permutations of

the set S with equal probability.

4 Available here: http://digital.library.adelaide.edu.au/ oll/spe ial/sher/

Derek O’Connor Random Permutation Generation

If we assume that each set operation can be performed in O(1) time, then this algorithm

runs in O(n) time, which is optimal up to a multiplicative constant. There are many ways

to implement the set operations, either explicitly or implicitly.

Durstenfeld.5 The most succinct statement of the Fisher-Yates Shuffle Algorithm is given

by Reingold, et al.6 :

where π is a permutation of length n, and rand(i, j) returns a random integer from the

set {i, i + 1, . . . , j − 1, j}. This is a truly elegant algorithm: it is tiny, uses no extra space,

and is optimal. Also, it can shuffle any array in place, not just permutations.7

Hence any sorting algorithm will generate, implicitly or explicitly, a permutation and its

associated sorted vector:

x = rand(1,8); [s,p] = sort(x); table = [x;s;p;x(p)]

i 1 2 3 4 5 6 7 8

x 0.146529 0.118308 0.315581 0.683211 0.914784 0.912839 0.753141 0.437558

s 0.118308 0.146529 0.315581 0.437558 0.683211 0.753141 0.912839 0.914784

p 2 1 3 5 8 7 6 4

x [ p] 0.118308 0.146529 0.315581 0.437558 0.683211 0.753141 0.912839 0.914784

We can see that the permutation p has one fixed point p[3] = 3, and three cycles (1, 2, 1),

(4, 5, 8, 4), and (6, 7, 6).

A random permutation is obtained from the sorting algorithm if it is given a randomly-

ordered vector to sort. This is done by filling a vector r[1 : n] with random numbers

5 RichardDurstenfeld, Algorithm 235, Random Permutation, Communications of the ACM, Vol. 7, July

1964, page 420.

6 Edward M. Reingold, Jurg Nievergelt, and Narsingh Deo, Combinatorial Algorithms: Theory and Practice,

7 Here is an interesting page on card shuffling by Richard J. Wagner: http://www-personal.umi h.edu/

~wagnerr/shue/. Elsewhere on his site is his C++ implementation of the Mersenne Twister random number

generator.

Derek O’Connor Random Permutation Generation

distributed uniformly on (0, 1) : r[1 : n] := RandReal(0, 1), and the sorting this random

vector : [s, p] := Sort(r[1 : n]), where s = r[ p]. Thus a random permutation operating on

a random vector gives an ordered vector.

Here are the two algorithms, side-by-side for easy comparison:

Generates a random permuation Generates a random permuation

of the integers 1,2,...,n of the integers 1,2,...,n

p := [1, 2, . . . , n] Identity perm. for k := 1 to n do

for k := 2 to n do r [k] := RandReal(0, 1)

r := RandInt(1, k) endfor k

p [ k ] : = : p [r ] Swap [s, p] := Sort(r )

endfor k return p

return p endfunc GRPsort

endfunc GRPfys

= (n − 1)( Tr + Ts ) time, where Tr

and Ts are the times to perform the random number generation and swap, respectively.

We say the time (or step) complexity of this algorithm is O(n). This is asymptotically

optimal – just to read a permutation requires O(n) time.

GRPsort has one for loop (1 : n), which requires nTr time, followed by a sort which

requires O(n log n) time. The total time is Tgs (n) = nTr + O(n log n). The time (or step)

complexity of this algorithm is O(n log n).

An important difference between the algorithms is that GRPsort requires twice as much

storage as the Shuffle algorithm, assuming that the vector r[1 : n] is over-written by

s [1 : n ].

Derek O’Connor Random Permutation Generation

The M ATLAB functions here are all minor variations of the Fisher-Yates Shuffle algorithm,

except M ATLAB’s own randperm which uses sorting.

In the M ATLAB functions that follow, all loops are incremented rather than decremented.

In the original Knuth algorithm P, he decrements the loop because in those days this gave

faster loops. This is no longer true. 8

Fisher-Yates Implementations

function p = GRPfys(n)

p = 1:n; Identity permutation

for k = 2:n

r = ceil(k*rand); Random integer between 1 and k

t = p(r);

p(r) = p(k); Swap(p(r),p(k))

p(k) = t;

end;

return; GRPfys

Knuth, in the 3rd edition of Volume 2, TAOCP, points out in the second-last paragraph

on page 145 that there is no need for the swap if we don’t want to shuffle a given vector,

but just want a random permutation. This is implemented below as GRPNS

function p = GRPns(n)

p = 1:n; Identity permutation

for k = 2:n

r = ceil(k*rand); Random integer between 1 and k

p(k) = p(r); No Swap

p(r) = k;

end;

return; GRPns

The final variation of GRPfys is what all right-thinking M ATLAB-ers consider ‘good prac-

tice’, viz., vectorization. In this variation the generation of the random integer r is moved

8 The decremented (or backward) loop, and its close cousin, the zero-based array, have been constant

sources of error in the student programs that I have seen over the 25 years of teaching algorithms and data

structures. People from childhood have been taught to count from 1 upwards and mistakes are inevitable

when this is reversed. The rot set in, I believe, with Sputnik and the American Space Program – all those

Houston count-downs. And remember, Knuth started programming at that time.

Likewise with zero-based arrays: people do not naturally start counting from 0. Except of course in

Ireland and the UK. Here, in these sceptre’d isles, we count the floors of our buildings from 0 upwards. But

we don’t call the first floor Floor Zero. Oh no! We have a special name for it: the Ground Floor. I have

lost count (pardon the pun) of the number of Americans wandering lost around our university buildings

saying, “But Prof Jones states in his letter that his office is on the second floor of the Gerry Adams Memorial

Building”. M ATLAB , very sensibly, does not allow zero-based arrays, but I’m sure they get many requests

for them.

Derek O’Connor Random Permutation Generation

outside the loop and a random integer vector r is generated before entering the loop. Im-

mediately we see that this has doubled the memory required: two vectors p and r instead

of just p. But if it speeds up the function, it may be worth it.

function p = GRPvec(n);

p = I(n);

r = ceil(rand(n,1).*(1:n)’); Vector of random integers

for k = 2:n

t = p(r(k));

p(r(k)) = p(k); Swap(p(r),p(k))

p(k) = t;

end;

return; GRPvec

We can see in Table 5 that GRPVec takes 20% longer for n = 107 , and 6% longer for n = 108 ,

than the loop version. In this simple function vectorization has given us the worst of both

worlds: increased time and increased space. Vectorization, like the optimizing compiler,

seems to be a mixed blessing.

I decided to replace the 3-statement swap with a slick one-statement in the original Shuf-

fle method.

function p = GRPvswap(n)

p = 1:n;

for k = n:-1:2

r = ceil(k*rand);

1 t = p(r);

2 p([k r]) = p([r k]); p(r) = p(k);

3 p(k) = t;

end;

return; GRPvswap

This 1-statement swap had a disastrous effect on the execution time of this simple func-

tion. This function took 14 to 40 times longer to execute than the original. The slow-down

is caused by the need to construct two vectors [k r], [r k] for each swap. This is ex-

pensive, according to Jan Simon.9

9 http://www.mathworks.
om/matlab
entral/newsreader/view_thread/295414.

Derek O’Connor Random Permutation Generation

Jan Simon

function X = Shuffle(N,’index’)

% <--- snip --->

% INPUT:

% X: Array with any size. Types: DOUBLE, SINGLE, CHAR, LOGICAL,

% (U)INT64/32/16/8. This works for CELL and STRUCT arrays also, but

% shuffling their indices is faster.

% Author: Jan Simon, Heidelberg, (C) 2010

% Simple Knuth shuffle in forward direction:

for i = 1:length(X)

w = ceil(rand * i);

t = X(w);

X(w) = X(i);

X(i) = t;

end;

return; % Shuffle

This is Knuth’s Algorithm P with the loop direction reversed. Note that this function can

shuffle any vector, not just permutations. Also, it is very general and well-written, being

able to handle various integer arrays as well as the usual double precision array.

This M ATLAB function is not actually used. Instead, Simon has written this in C and put a

MEX wrapper around it so that when it is compiled it can be called from M ATLAB. This is

because the C compiler can generate much faster code than M ATLAB’s interpreter. Thus

this is a code generation improvement and not an algorithmic improvement.

M ATLAB

function p = randperm(n)

%RANDPERM Random permutation.

% RANDPERM(n) is a random permutation of the integers from 1 to n.

% For example, RANDPERM(6) might be [2 4 5 6 1 3].

%

% Note that RANDPERM calls RAND and therefore changes RAND’s state.

%

% See also PERMUTE.

% Copyright 1984-2004 The MathWorks, Inc.

% Revision : 5.10.4.1 Date : 2004/03/0221 : 48 : 27

[ignore,p] = sort(rand(1,n));

If you have a good sorting method then this is a quick ’n slick method for generating

random permutations. Others might call it quick ’n dirty. Yet others would call it just

dirty. But let’s not quibble: it works fine and it is fast because M ATLAB has carefully

implemented (in C or assembly?) a good sorting algorithm, Hoare’s Quicksort, I believe.

Although all the M ATLAB functions listed above use rand, which returns a standard IEEE

8-byte double precision floating point number, only M ATLAB uses a whole n−vector of

them. But the methods above generate n rands, don’t they? Yes, but one-at-a-time, so the

Derek O’Connor Random Permutation Generation

integer n−vector and 1 double precision n−vector. This can make a big difference if you

work with truly large permutations.

The results here show that all variants of GRPfys are about the same and so the choice

of function is reduced to three: GRPfys, GRPmex, or randperm. Jan Simon’s GRPmex is the

GRPfys Derek O’Connor Dec 2010 1 2.0 24.0 315

GRPns ” Dec 2010 1 2.0 24.0 310

GRPvec ” Dec 2010 1 2.2 25.5 350

GRPmex Jan Simon 2010 1 0.6 7.6 156

randperm Matlab 2005 2 2.3 26.0

Windows7 64-bit Prof., M ATLAB R2008a, 7.6.0.324

’mexed’ version of GRPfys, and runs 2–3 times faster. Both require 1 array of size n. If you

do not have the appropriate C compiler then you are forced to use GRPfys or something

similar.

M ATLAB’s randperm is the very slick one-liner [s,p] = sort(rand(n,1)). This method’s

complexity is O(n log n) which means that an O(n) method such as Shuffle will even-

tually beat it when n is large enough. If Tshuf = cshuf n and Tsort = csort n log n, then the

average times per array element are cshuf and csort log n. Thus the average time of M AT-

LAB’s sort method grows with n, while the Shuffle remains constant.

Table 5 shows that there is very little difference between GRPfys and randperm for n = 107

and n = 108 . But the crucial difference is that M ATLAB’s method uses twice as much

working memory as GRPfys. This is why there is a blank in the table for randperm at n =

109 : 16 GB memory was not enough to allow randperm to generate a random permutation

of size 8 bytes × 109 = 8 GB.

The general conclusion from these tests is that the simplest implementations of the Fisher-

Yates algorithm are the best. Fancy vectorizations and array index manipulations not

only obscure the algorithm, but are error-prone, and are slower than the simpler methods.

to switch to single processor mode before running the profiler, otherwise the results will

be erratic. See the M ATLAB profiler help for details.

Derek O’Connor Random Permutation Generation

1 function p = GRPfys(n);

0.08 1.0 1 p = 1:n;

1 for k = 2:n

1.87 22.6 9999999 r = ceil(rand*k);

1.29 15.7 9999999 t = p(r);

1.89 22.9 9999999 p(r) = p(k);

1.80 21.8 9999999 p(k) = t;

1.32 16.0 9999999 end;

1 return;

We can see that there are no ‘hot spots’ in this code and that time is fairly evenly spread

across each statement. This suggests that there is little we can do in M ATLAB to speed it

up. But what about vectorization?, I hear you cry. Let us try profiling GRPvec above. Here

are the results for n = 108 :

function p = GRPfys(n); | function p = GRPvec(n);

0.66 1 p = 1:n; | 0.74 1 p = 1:n;

| 6.22 1 r = ceil(rand(n,1).*(1:n)’);

1 for k = 2:n | 1 for k = 2:n

18.05 99999999 r = ceil(rand*k); |

12.69 99999999 t = p(r); | 21.55 99999999 t = p(r(k));

20.50 99999999 p(r) = p(k); | 22.97 99999999 p(r(k)) = p(k);

21.70 99999999 p(k) = t; | 12.93 99999999 p(k) = t;

12.57 99999999 end; | 12.54 99999999 end;

----- | -----

86.16 total | 77.10 total

We can see that the unvectorized code GRPfys on the left requires 86.16/77.1 − 1 = 0.1175

= 12% more time that GRPvec. Random number generation takes 18.05 secs in GRPfys

but only 6.22 secs in GRPvec. The time taken by the other statements in the loop are about

the same for both versions. Hence the 12% difference is accounted for by the vectorization

of the random number generator. Or so it seems.

Because profiling adds a lot of overhead to the run times, it is always a good idea to get

the actual times without the profiler on. Still with the computer in the single cpu mode

GRPfys and GRPvec were timed, again with n = 108 . Here are the command-line results:

» tic;p=GRPvec(1e8);toc

Elapsed time is 27.283832 seconds.

» tic;p=GRPvec(1e8);toc

Elapsed time is 27.352696 seconds.

» tic;p=GRPfys(1e8);toc

Elapsed time is 23.726308 seconds.

» tic;p=GRPfys(1e8);toc

Elapsed time is 23.714992 seconds.

This shows that the GRPvec takes 27.3/23.7 − 1 = 15% more time than the unvectorized

GRPfys, a complete reversal of the profiler results. In this case the M ATLAB profiler has

been worse than useless — it has been grossly misleading. We can see that the profiler

added about (86.16 − 23.7)/23.7 = 263% overhead time to the actual running time of

Derek O’Connor Random Permutation Generation

GRPfys. This overhead time is noise (we don’t want it) which is swamping out the actual

time signal. The only reliable information given out by the profiler is the statement count.

But apart from the erroneous profiler results, this example shows that vectorization is

not (always) a good thing: not only has it added 15% to the run time, it has doubled the

working memory required.

“It was once true that vectorization would improve the speed of your MATLAB code.

However, that is largely no longer true with the JIT-accelerator” – Matlab Doug, Mar.

2010.

The Fisher-Yates Shuffle Algorithm is provably correct and, when implemented with a

good random number generator, produces all possible permutations with equal proba-

bility. A special permutation is one which has some special property or restriction: it is

cyclic, it is a derangement, it must have 2 fixed points, etc.

The simplest way to generate special permutations is by the Rejection Method, as shown

in the function GRPSpec: repeatedly generate a permutation until it has the special prop-

erty or restriction. The main problem with this general method is that many permutations

may need to be generated before a desirable one is found.

function GRPSpec(n) → p

Generates a special random permutation

of the integers 1,2,...,n

p := [1, 2, . . . , n] Identity perm.

while p is not special do

p := GRPfys(n)

endwhile p

return p

endfunc GRPSpec

This type of algorithm is called a Las Vegas Algorithm:10 an algorithm that is guaranteed to

give the correct output, but may take a very long (random) time to do so. It is important

to understand that GRPfys( p) is sampling uniformly with replacement from the set of all

permutations of length n, and knows nothing about the special property. We have seen

that the time complexity of GRPfys(n) is Ts (n) = cs n ∈ O(n). This is not a random time,

but constant for a given n.

The random uniform output of GRPfys( p) means that we do no know how many times

the while loop is performed: it is a random number nw . Hence the time complexity of

GRPSpec(n ) is a random function

nw

Tspec (n) = ∑ (Ttest (n) + Ts (n)). (6.1)

k=1

E [ Tspec (n)] = E [nw ]E [ Ttest (n) + Ts (n)] = E [nw ](E [ Ttest (n)] + E [ Ts (n)]). (6.2)

10 See Brassard & Bratley, Fundamentals of Algorithmics, Prentice-Hall, 1996, Chapter 10.

Derek O’Connor Random Permutation Generation

We have E [ Ts (n)] = Ts (n) is a constant for a given n, but we do not know much about

Ttest (n). Is it a random number or a constant? Usually these tests can be performed in

O(n) time, e.g., IsCyc( p) and IsDer( p) are O(n). Assuming that the test is , at worst, a

constant ct n, then we have E [ Tspec (n)] = E [nw ](ct n + cs n) = cnE [nw ].

What can be said about nw and its expected value? Obviously nw > 0 and nw < ∞,

assuming that the desired permutation type is not an impossibility, e.g., p(1 : 10) has at

least one p(i ) = 59, say. Consider asking for p = (n, n − 1, . . . , 2, 1), the reverse identity.

The probability of this permutation occurring is 1/n!, and so GRPfys may spend a very

long time until it ’hits’ it. An upper bound on nw would seem to be O(n!). This is, of

course, the essence of a Las Vegas algorithm: it will find the correct answer, but it may

take forever.

ously, a permutation can be checked in O(n) time to determine if it is a derangement.

In this case the rejection method works in O(n) time because Pr( p is a derangement) =

D (n)/n! → 1/e ≈ 0.36788. Hence the expected time complexity is E(nw )n = en ≈

2.718n, i.e., on average, the while loop of GRDrej is performed about 2.718 times per

derangement generated.

function p = GRDrej(n);

Generate a random permutation p(1:n) using GRPfys

and reject if this is not a derangement.

Requires expected e = 2.7183... passes through the while-loop.

NotDer = true;

while NotDer

p = GRPfys(n);

NotDer = HasFP(p); Derangement check

end;

return GRDrej

This is a new derangement algorithm by Martinez, et al.11 that is not easy to understand

but seems to work well. Shown below are the original algorithm and it M ATLAB imple-

mentation.

11 http://www.siam.org/pro
eedings/anal
o/2008/anl08_022martinez
.pdf

Derek O’Connor Random Permutation Generation

function GRPmpp(n) → p

Martinez et al’s original Algorithm which generates a random

derangement of the integers 1,2,...,n

p : = [1, 2, . . . , n ] Identity permutation

Mark[1 : n ] : =false;

i : = n; u : = n

while u ≥ 2 do

if ¬ Mark[i ] then

repeat

j : =Random(1, i − 1)

until ¬ Mark[ j]

p[i ] : = : p[ j ] Swap

u : =Uniform(0, 1)

if u < (u − 1) Du−2 /Du then

Mark[ j] : =true

u := u − 1

endif u

u := u − 1

endif ¬ Mark[i ]

i := i − 1

endwhile j

return p

endfunc GRPmpp

function p = GRDmpp(n);

p = I(n); identity permutation

mark = p < 0; mark(1:n) = false

i = n; u = n;

while u > 1

if ∼mark(i)

j = ceil(rand*(i-1)); random j in [1,i-1]

while mark(j)

j = ceil(rand*(i-1)); random j in [1,i-1]

end;

t = p(i);

p(i) = p(j); Swap p(i) and p(j)

p(j) = t;

r = rand;

if r < 1/u Prob. if test for n large

mark(j) = true;

u = u-1;

end;

u = u-1;

end; if ∼mark

i = i-1;

end; while u > 1

return GRDmpp

Tests on GRDmpp show that on average the outer while loop is performed 2 times, as

predicted by the analysis. Hence this is faster than the Rejection algorithm which requires

e = 2.718 loops, on average.

Derek O’Connor Random Permutation Generation

Timing tests were run on the two derangement functions along with GRDmex which is

GRDrej using Jan Simon’s fast GRPmex function.

105 0.04 8.91 0.01 1 0.02 4.13

106 0.26 3.48 0.08 1 0.24 3.20

107 18.06 5.70 4.83 1.52 3.17 1

108 144.11 14.38 10.02 1 38.03 3.80

Times and normalized times, averaged over a

sample of 10 runs for each n.

The Rejection algorithm (GRDrej) and the Martinez algorithm (GRDmpp) are examples of

Las Vegas Algorithms, i.e., they are guaranteed to give the correct result but they may

run for a long (random) time. The Fisher-Yates Shuffle algorithm has a constant running

time for a given n, which I will call Ts (n). The running time of the Rejection algorithm

is Tr (n) = nw × ( Tt (n) + Ts (n)), where nw is a random variable that counts the number

of times the while loop is executed. The expected value of nw is e = 2.7183 . . . because

the probability of the Shuffle algorithm generating a derangement is 1/e. Hence Tr (n) =

e( Tt (n) + Ts (n)) = 2.7183Ts (n), if we assume that Tt (n) is negligible compared to Ts (n).

Martinez, et al., prove that the expected running time of their algorithm is Tm (n) = 2Ts (n)

and so it is faster, on average, than the Rejection algorithm, but not by much. My advice

would be: if you have a good fast Fisher-Yates Shuffle program, use it in the Rejection

algorithm, especially if you are risk-averse, because the Martinez algorithm is harder to

implement correctly. We can see in the timing table above that the Rejection algorithm

using Jan Simon’s GRPmex was fastest for n = 105 , n = 106 and n = 108 . GRDmpp was

fastest for n = 107 . An important added advantage of the Rejection algorithm is that it

uses just 1 array of length n, whereas the Martinez algorithm uses 2 arrays of length n.

The interesting question remains: is random derangement generation inherently more

difficult than random permutation generation, or is a there a derangement algorithm

with Td (n) = Ts (n) ?

A cyclic permutation has a single cycle of length n. A permutation can be tested in O(n)

time to see if it is cyclic. Hence GRPSpec will perform an O(n) cyclic test followed by an

O(n) permutation generation for each iteration of the while loop. If nw is the number

of times the while loop is performed then the complexity of this method is O(nw n).

From (3.4) we have Pr( p is cyclic) = 1/n. Hence the expected value of nw is n and so the

expected complexity of GRPSpec is O(n2 ), for cyclic permutations.

Derek O’Connor Random Permutation Generation

S. Sattola, in her Master’s thesis, gave a very simple modification of the Fisher-Yates

algorithm that generates random cyclic permutations.12

function GRCsat(n) → p

Generates a random cyclic permutation

of the integers 1,2,...,n

p := [1, 2, . . . , n] Identity perm.

for k := 2 to n do

r := RandInt(1, k − 1) Sattola’s modification

p [ k ] : = : p [r ] Swap

endfor k

return p

endfunc GRCsat

We can see that the only change in the Fisher-Yates algorithm is this: r := RandInt(1, k)

becomes r := RandInt(1, k − 1). This change ensures that it swaps different elements of

p, i.e, p[k] :=: p[r], k 6= r. It is remarkable that such a small change in the Fisher-Yates

algorithm can make such a big difference in its output.

The correctness of this algorithm has been proved and it has been thoroughly analysed

by Prodinger13 It obviously has the same O(n) complexity as the Fisher-Yates algorithm,

and so it is an order of magnitude faster than the rejection method.

12 S.

Sattola, “An algorithm to generate a random cyclic permutation”. Information Processing Letters, Vol.

22, pages 315–317, 1986.

13 Prodinger, Helmut, “On the analysis of an algorithm to generate a random cyclic permutation”, Ars

Derek O’Connor Random Permutation Generation

Combinatorial generation algorithms and programs are often small, deceptively simple,

subtle, and, above all, error-prone. These small programs are often buried deep as sub-

programs (functions) in large simulations whose operation depends crucially on their

correct and efficient working. It should go without saying that these generators must be

rigourously tested.

These tests are for any n, but usually with n in the range [106 , 1010 ], where exhaustive

testing is out of the question.

1. Existential. Does the generator output the correct form of combinatorial object. For

example, (1) does a permutation generator produce (all possible) permutations?

(2) does a random derangement generator produce (all possible) derangements?,

and (3) does a random cyclic permutation generator produce (all possible) cyclic

permutations.

2. Uniformity. Are the random permutations distributed uniformly over the popula-

tion of n! permutations. Uniformity implies that each number in {1, 2, . . . , n} occurs

with relative frequency 1/n.

4. Others

— TO BE COMPLETED —

Derek O’Connor Random Permutation Generation

% Check if RPG can hit (find) the permutation ’target’

% USE: [p,k,t] = FindPerm([5 4 6 7 1 8 10 2 3 9]);

% The example target is a derangement but not cyclic

% Warning: use small permutations. O(n!) time.

% Derek O’Connor 28 Dec 2010.

n = length(target)

p = randpermfull2(n);

limit = 5*factorial(n);

k = 0;

tic;

while any(p-target) && k < limit

p = randpermfull2(n); % Ver 2, Jos van der Geest’s ’derangement’ gen.

k = k+1;

end;

t = toc;

Frac = k/factorial(n);

dispa(’-------------------------------------’);

if k == limit

dispa(’Target NOT FOUND after k =’, k,’iterations. Time =’,t,’secs.’);

else

dispa(’Target FOUND after k =’, k,’iterations. Time =’,t,’secs.’);

end;

dispa(’Fraction of Space searched (k/n!) =’, Frac ,’Rate =’, ceil(k/t), ’per second’);

[target;p]

return

target is a derangement. Let’s see if it is a cyclic permutations: IsCyc(target) returns 0

or false, so now we know that target is a derangement that is not cyclic. If randpermfull is a

true derangement generator then it should generate this derangement after a sufficiently

large number of iterations. Here is what happens:

target = [5 4 6 7 1 8 10 2 3 9];

[p,k,t] = FindPerm(target);

-------------------------------------------------------

Target NOT FOUND after k = 18144000 iterations. Time = 202.6715 secs.

Fraction of Space searched (k/n!) = 5 Rate = 89525 per second

ans =

5 4 6 7 1 8 10 2 3 9

6 5 4 1 10 8 3 2 7 9

Derek O’Connor Random Permutation Generation

% Frequency Count of fixed points in a

% a sample of random permutations p(1:n).

% USE: [nfp,avfp,sdevfp] = FreqFixedPts(20,10ˆ4);

% Derek O’Connor 8th Jan 2011. derekroconnor@eircom.net

nfp = zeros(nsamp,1);

for s = 1:nsamp

p = GRPfys(n);

nfp(s) = CountFixedPts(p);

end;

OutFreqFixedPts(nfp);

return; % FreqFixedPts

Figure 6 confirms that the expected value and variance of the number of fixed points is 1,

for any n, and that the relative frequency of 0 fixed points is about 1/e ≈ 0.3679, which

is the relative frequency of derangements. A bad RPG would be unlikely to give these

results. Indeed, it was this test that showed that there was something wrong with GRDrej.

The fault was identified in the ‘simple’ IsDer interrogation function: a compound while

test was wrong. The function was re-written as IsDer(p) = ∼HasFP(p).

— TO BE COMPLETED —

Derek O’Connor Random Permutation Generation

8 RPGLab

In this section14 we describe a set of simple tools, M ATLAB functions, that help us ma-

nipulate and test permutations. This is done in the spirit of Kernighan and Plauger’s

Software Tools in Pascal, Addison-Wesley, 1981, one of the great books in computer sci-

ence. Sadly, the lessons and insights of this book are either unknown to or ignored by

many of today’s M ATLAB programmers. In the same spirit as Kernighan & Plauger, the

books by Jon Bentley are a devoted to small, simple, but powerful programs.

I hope that these simple functions will prove useful to those who wish to experiment

with random permutations. Hence the suffix L AB.

simple as possible and as simple to use as possible. The inputs are: an integer n, or a row

vector p(1 : n), or an integer and a vector. Outputs are: a logical ans, or a vector p.

Naming Conventions. Mathematics derives its power from the judicious choice of sym-

bols it uses to name objects and processes. For example, ∑ni=1 xi , conveys an immense

amount of information in a very compact form. Expressing this in a programming lan-

guage (except APL) would take many more symbols, while expressing it in ordinary

English would take a paragraph or more. With this in mind we have used the short-

est possible names that are compatible with conveying information that is essential to

understanding a piece of code. The names we use are not explanations but symbolic

reminders of what the name stands for. Thus p = GRPfys(n) reminds us that it stands

for the process of Generating a Random Permutation of length n using the f isher-yates

shuffle algorithm, and stores it in the row vector p. This name and others have to be

studied, understood, and remembered, before they can be used with facility – just as in

Mathematics.

Error Checking. What may shock many M ATLABers is the lack of input error checking.

This is in the spirit of Kernighan & Plauger who assume that the users are reasonably

competent and not lazy. After all, the makers of 36" pipe wrenches don’t check to see if

you are using one to fix your bicycle.

If you generate and manipulate permutations with these functions only, then only valid

permutations will be generated. Otherwise you must do your own error-checking.

Comments. Another shock is that very few comments are used, except for a succinct

statement of purpose at the head of each function. It has become fashionable in some

quarters to write mini-theses at the start of each function, along with enough biographical

data to satisfy the Library of Congress. I do include my name in the header of each

function.15 The header comments in the functions that follow have been stripped out to

save space, but they are in the m-files.

14 I

have written this section to be independent of the others. As a result, some code and discussions are

repeated.

15 This reminds me of a comment by a famous art historian: “No matter how abstract the painting, the

Derek O’Connor Random Permutation Generation

’M ATLAB-isms’. Perhaps the biggest shock to M ATLABers will be that there is virtually

no use of M ATLAB’s vectorizations and fancy array manipulation functions. Most code is

written in loop or component form, as the Numerical Linear Algebra people call it. I be-

lieve that M ATLAB’s matrix-vector notation and manipulation functions are very useful,

when used in the proper place, but many M ATLABers have made a fetish of vectorization

and index manipulation, to the detriment of code clarity, and, quite often, to speed.

A benefit of not using what I call ‘M ATLAB-isms’, is that these functions are easily trans-

lated into other languages, such as Fortran and C, making them good Mex candidates.

M ATLAB is a very powerful and useful system for numerical computing. It allows the

knowledgeable user to do in a few lines what would take hundreds of lines of tedious

Fortran or C code. A superb example of the power of good M ATLAB programming is

Trefethen’s Chebfun system.16. Trefethen, by the way, claims to be the first license holder

of M ATLAB.

These are the low-level functions that are used everywhere and are so simple that they

are, we hope, obviously correct. Writing such simple functions is not a trivial task.

These primitives fall into two classes: (1) permutation constructors, and (2) permutation

interrogators.

I Generate the identity permutation p = I(n)

Trans Transpose elements i and j of p p = Trans(p,i,j)

Constrs. Rev Reverse the elements p(i ), . . . , p( j) p = Rev(p,i,j)

Rot Left circular shift p by k positions p = Rot(p,k)

GRPfys Generate a random permutation p(1 : n) p = GRPfys(n)

GRPmex Generate a random permutation p(1 : n) p = GRPmex(n)

IsPer Is p a permutation? ans = IsPer(p)

Interrs. HasFP Does p have a fixed point? ans = HasFP(p)

IsDer Is p a derangement? ans = IsDer(p)

IsCyc Is p cyclic? ans = IsCyc(p)

Derek O’Connor Random Permutation Generation

8.2 Constructors

Identity. p = I(n)

function p = I(n);

p = 1:n; a row vector

return; I(n)

Transpose. p = Trans(p,i,j)

function p = Trans(p,i,j);

t = p(i);

p(i) = p(j);

p(j) = t;

return; Trans

Reverse. p = Rev(p,i,j)

function p = Rev(p,i,j);

while i < j

p = Trans(p,i,j);

i = i+1;

j = j-1;

end;

return; Rev

This code reverses elements p(i ) . . . p( j) of p(1, 2, . . . , n). 17 Although there is no error

i j

p 5 3 6 8 1 4 7 2 10 9

1 2 3 4 5 6 7 8 9 10

i j

p 5 3 7 8 1 4 6 2 10 9

1 2 3 4 5 6 7 8 9 10

i=j

p 5 3 7 4 1 8 6 2 10 9

1 2 3 4 5 6 7 8 9 10

checking, this code is quite robust: if i ≥ j then nothing happens. In practice, the trans-

position function is replaced by the 3-statement swap operation. This operation is now

used in the rotation operation in a very clever way.

17 See Kernighan & Plauger, Software Tools in Pascal, Addison-Wesley, 1981, pages 194,195.

Derek O’Connor Random Permutation Generation

Rotate. p = Rot(p,k)

function p = Rot(p,k);

n = length(p);

p = Rev(p,1,k);

p = Rev(p,k+1,n);

p = Rev(p,1,n);

return; Rot

This does a left circular shift of all elements of p by k positions. That is,

Rot( p,k)

[ p(1), . . . p(k), p(k + 1), . . . , p(n)] −−−−→ [ p(k + 1), . . . , p(n), p(1), . . . , p(k)]

Here is how the three reversals work:

Rev( p,1,k)

[ p(1), . . . p(k), p(k + 1), . . . , p(n)] −−−−−→ [ p(k), . . . , p(1), p(k + 1), . . . , p(n)]

Rev( p,k+1,n )

[ p(k), . . . p(1), p(k + 1), . . . , p(n)] −−−−−−−→ [ p(k), . . . , p(1), p(n), . . . , p(k + 1)]

Rev( p,1,n )

[ p(k), . . . p(1), p(n), . . . , p(k + 1)] −−−−−→ [ p(k + 1), . . . , p(n), p(1), . . . , p(k)]

At first glance, this code may seem inefficient because it is doing three reversals. Firstly,

it should be obvious that the Reverse function is efficient: it performs ( j − i )/2 transpo-

sitions, or a total of 3( j − i )/2 element moves. Hence, the Rotate operation performs

3( k − 1) 3( n − k − 1) 3( n − 1) 6n − 9

+ + = ∼ 3n element moves.

2 2 2 2

Although this is not optimal (each element is moved twice) it is very efficient nonetheless.

There is an extensive body of research literature on this and related topics. The rotation

operation is an important low-level operation in text editors.

function p = GRPfys(n);

p = I(n);

for k = 2:n

r = RandInt(1,k);

p = Trans(p,k,r);

end;

return; GRPfys

This is the increasing-loop version of the Durstenfeld version of the Fisher-Yates Shuffle

algorithm, shown below, along with Pike’s modification for a partial shuffle.

For those who have never seen, let alone written an Algol program, the function entier( x)

is the largest integer not greater than the value of x.18

18 Looking at Durstenfeld’s nicely-typeset Shuffle procedure, it is a shock to realize that it is a valid Algol

procedure, comments and all. Now, fifty years later, it is a poor reflection on today’s language designers,

compiler-interpreter writers, and program-editor makers, that they cannot handle or present us with nicely

typeset programs, despite the huge strides made in mathematical typesetting, a much more difficult task

than program typesetting. But we do have 19 different types of assignment statements in Java. Programmers

of the World, Protest!

Derek O’Connor Random Permutation Generation

function p = GRPmex(n);

p = ShuffleMex(n,’index’); Jan Simon’s mexed version of F-Y Shuffle

return; GRPmex

Derek O’Connor Random Permutation Generation

8.3 Interrogators

n = length(p);

count = zeros(n,1);

ans = true;

for k = 1:n

if count(p(k)) == 0

count(p(k)) = count(p(k))+1;

else

ans = false; Stop after first bad p(k)

return

end;

end; for k

return; IsPer

Derek O’Connor Random Permutation Generation

A permutation p is valid if and only if each k ∈ {1, 2, . . . , n} appears once and only once.

This is an expensive check because it uses an extra array.19 Notice that the function re-

turns as soon as a bad value is found. No further time is wasted checking for other bad

points. We will use this stop-as-soon-as-possible principle throughout the other interroga-

tion functions.

n = length(p);

ans = false;

for k = 1:n

if p(k) == k

ans = true;

return; stops after first fixed point.

end;

end; for k

return HasFP

HasFP(p) returns false if p is a derangement. This function could be written more suc-

cinctly with a compound while statement, but such statements are (for me at least) error

prone. It is well to remember that succinctness and simplicity are often at odds.

ans = ∼HasFP(p);

return IsDer

If you are sure that HasFP(p) is correct, then IsDer(p) is obviously correct. Replace the

function call with inline code if necessary, but check it carefully.20

19 I’m

sure there are better ways of doing this check. Later, maybe.

20 My

first attempt at IsDer(p) had an error in a compound while check. This error did not show up until

much later, when I did frequency tests on the permutation generators.

Derek O’Connor Random Permutation Generation

n = length(p);

start = 1;

next = p(start);

L = 1;

L = L+1;

next = p(next);

end;

ans = L == n;

return; IsCyc

element 1. If element 1 is part of a cycle whose length is less than n, then p cannot be

cyclic, and false is returned.

There are many special permutations. Here we give two which seem to be the most

useful: Derangement and Cyclic.

GRDrej Generate a random derangement p(1 : n) p = GRDrej(n)

GRDmex Generate a random derangement p(1 : n) p = GRDmex(n)

GRDmpp Generate a random derangement p(1 : n) p = GRDmpp(n)

GRCsat Generate a random cyclic permutation p(1 : n) p = GRCsat(n)

function p = GRDrej(n);

NotDer = true;

while NotDer

p = GRPfys(n);

NotDer = HasFP(p); Derangement check

end;

return GRDrej

Derek O’Connor Random Permutation Generation

function p = GRDmex(n);

NotDer = true;

while NotDer

p = GRPmex(n);

NotDer = HasFP(p); Derangement check

end;

return GRDmex

This is just GRDrej using GRPmex which uses Jan Simon’s ShuffleMex. This gives a 2 to 3

speedup.

function p = GRCsat(n)

p = I(n);

for k = 2:n

r = RandInt(1,k-1); Changing k to k-1 in GRPfys

p = Trans(p,k,r);

end;

return; GRCsat

This is Sattola’s modification of GRPfys. We can see that the only change in GRCsat is

to use of k − 1 instead of k. This causes a dramatic change in the output of this func-

tion: it generates cyclic permutations only. The correctness of this algorithm has been

proved and it has been thoroughly analysed by Prodinger21 It obviously has the same

O(n) complexity as the Fisher-Yates algorithm.

21 Prodinger, Helmut, “On the analysis of an algorithm to generate a random cyclic permutation”, Ars

Derek O’Connor Random Permutation Generation

This function is included because it is easy to get wrong. It can be replaced by the single

line of code below. The purpose of this function is to pick a random integer from the set

{ L, L + 1, . . . , U − 1, U }. This is done with the single statement

We wish to prove that this statement works correctly, given that rand is M ATLAB’s imple-

mentation of the Mersenne Twister generator. M ATLAB’s documentation on rand states

that

The rand function now supports a method of random number generation called the

Mersenne Twister. The algorithm used by this method, developed by Nishimura and

Matsumoto, generates double precision values in the closed interval [2−53, 1 − 2−53 ],

with a period of (219937 − 1)/2

= L + floor[2−53 (U − L + 1), (U − L + 1) − 2−53 (U − L + 1)],

= L + floor[ǫ, U − L + 1 − ǫ], where ǫ = 2−53 (U − L + 1),

= L + [⌊ǫ⌋, ⌊(U − L + 1 − ǫ)⌋],

= L + [0, U − L], if ǫ < 1,

= [ L, U ].

signed integers then (U − L + 1) is also a 32-bit signed integer in [−231 , 231 − 1]. Hence

−231 ≤ (U − L + 1) ≤ 231 − 1, and the condition ǫ < 1, or (U − L + 1) < 253 , obviously

holds.

If L and U are 64-bit signed integers then (U − L + 1) is also a 64-bit signed integer

in [−263 , 263 − 1]. Hence −263 ≤ (U − L + 1) ≤ 263 − 1, and the condition ǫ < 1, or

(U − L + 1) < 253 , may not hold.

The period of rand is (219937 − 1)/2 ≈ 20 × 106000 , which is a gigantic number, at least

to ordinary mortals. However, the sets of permutations that GRPfys(n) samples from are

gigantically larger that rand’s gigantic period (See Table 2 above). On a 2.3 GHz, 16 GB

machine, random permutations of length n = 109 can be generated in a few minutes.

Thus we are sampling from a space of N = n! = (109 )! objects. Using Stirling’s approx-

imation we find loge (109 )! ≈ 2 × 1010 which means that N = n! is an integer with about

1010 digits. This means that despite rand’s gigantic period – an integer with a mere 6000

digits – GRPfys(n) will never visit more than an infinitesimally small fraction of the per-

mutation space. Yet we can say, with a certain amount of confidence, that GRPfys will

produce a permutation p(1 : 109 ) with probability 1/(1010 - digit number).

Derek O’Connor Random Permutation Generation

— TO BE COMPLETED —

InvP The inverse of p. p(q) = q( p) = I q = InvP(p)

CanForm Arrange p in canonical form q = CanForm(p)

CycStruct Determine cycle structure of p [ncyc,S,L] = CycStruct(p)

FindPerm Can an RPG ‘hit’ the target pt [p,k,time] = FindPerm(pt)

- PermutationUploaded bytechzones
- Design for Assembly line performance: The link between DFA metrics and Assembly line performance metricsUploaded byraghavakashyap
- simulation handbook.pdfUploaded byPawan Pathak
- Permutation PatternsUploaded bySoloreleo
- 338Uploaded byprabodh20
- 2149Uploaded byLivia Marsa
- fasc1Uploaded bybrodskye
- The Art of Computer Programming, Volume 4AUploaded byAxolnom
- O'Connor -- Fisher-Yates & Durstenfeld Shuffle Algorithms: HistoryUploaded byDerek O'Connor
- O'Connor -- Common Errors in Numerical ProgrammingUploaded byDerek O'Connor
- O'Connor -- Boolean Matrix InversesUploaded byDerek O'Connor
- p06Uploaded bysboy888
- Securing Speech in GSM Networks using DES with Random Permutation and Inversion AlgorithmUploaded byijdps
- 0478_w15_ms_21Uploaded byZanfalawy Basha
- Permutations CombinationsUploaded byShivangi Jaiswal
- Bioelectrical ConcentrationF12Uploaded byMohammad Ahmed
- ccalcUploaded byKshitij Banerjee
- Recommending System Assignment - 10131006Uploaded byDwi Nur Amalia
- Assignment 2 on network securityUploaded byDebomitra Sinha
- LaplaceUploaded byJosue Gonzalez Garcia
- lecturenotes6.pptxUploaded byKevin Paxson
- algebra sg notes v 3 16Uploaded byapi-324751152
- Soalan Xm Test 1Uploaded byNanick Chinoiz
- bij (1)Uploaded byhongnh-1
- Abaqus Users - Johnson Cook VUMATUploaded bybibekananda87
- OR_ch7Uploaded byKavi Yarasi
- Independent DominationUploaded bychithu1234
- Fuzzy Modelling Using Sector NonlinearUploaded byGeorge Iskander
- Sequencing ProblemUploaded bySaurabh Mishra

- Rutherford -- Inverses of Boolean MatricesUploaded byDerek O'Connor
- Bellman -- On the Routing ProblemUploaded byDerek O'Connor
- O'Connor -- The Bellman-Ford-Moore Shortest Path AlgorithmUploaded byDerek O'Connor
- Bannon -- John F Muth (1930 - 2005)Uploaded byDerek O'Connor
- OConnor -- Zeno's ParadoxUploaded byDerek O'Connor
- Kelly & O'Neill -- The Network Simplex MethodUploaded byDerek O'Connor
- O'Connor -- Matrix BenchmarksUploaded byDerek O'Connor
- O'Connor -- A Historical Note on the Fisher-Yates Shuffle Algorithm.Uploaded byDerek O'Connor
- O'Shea, Tom -- Lambay IslandUploaded byDerek O'Connor
- Foulds & O'Connor -- Heuristics for the Sparse TSPUploaded byDerek O'Connor
- O'Connor -- Common Errors in Numerical ProgrammingUploaded byDerek O'Connor
- O'Connor -- Boolean Matrix InversesUploaded byDerek O'Connor
- O'Connor -- NewismsUploaded byDerek O'Connor
- Pentium IEEE FDIV BugUploaded byDerek O'Connor
- A note on two problems in connexion with graphsUploaded byJeff Pratt
- Higham & Moler -- Three Measures of PrecisionUploaded byDerek O'Connor
- Kalman -- A New Approach to Linear Filtering, etc. (1960)Uploaded byDerek O'Connor
- Durstenfeld -- Random Permutation AlgorithmUploaded byDerek O'Connor
- O'Connor -- Mrs La Touche of HarristownUploaded byDerek O'Connor
- Ng -- Argument Reduction for Huge Arguments: Good to the Last BitUploaded byDerek O'Connor
- O'Connor -- Alglat: A Minimum Change AlgorithmUploaded byDerek O'Connor
- O'Connor -- Fisher-Yates & Durstenfeld Shuffle Algorithms: HistoryUploaded byDerek O'Connor
- Moler & Morrison -- Pythagorean SumsUploaded byDerek O'Connor
- O'Connor -- Matlab's Floating Point SystemUploaded byDerek O'Connor
- Kalman -- Probability in the Real WorldUploaded byDerek O'Connor
- O'Connor -- The Lenovo ThinkPad X220 JourneyUploaded byDerek O'Connor
- O'Connor -- Matrix Chain MultiplicationUploaded byDerek O'Connor
- Forsythe, Malcolm, & Moler -- URAND generator.Uploaded byDerek O'Connor
- O'Connor -- The Birthday Paradox and Random Number GenerationUploaded byDerek O'Connor

- 2nd Quarter Math 1st Summative- With TOSUploaded byMary Athena Ibardaloza Adesna
- lesson 9 3 simplified form for radicalsUploaded byapi-233527181
- Factoring Polynomials Rev ExUploaded byCoolman Poon
- Solving Polynomial EquationsUploaded byparinyaa
- NBHM Question Paper 2015Uploaded bysignums
- Symmetry breaking operators for strongly spherical reductive pairs and the Gross-Prasad conjecture for complex orthogonal groupsUploaded byraveneyesdead
- complex.pdfUploaded byspsarathy
- Worksheet on Properties of Multiplication of Rational Numbers _ AnswersUploaded byKamran_Saif
- chapter2 mcqsUploaded byAman Bhutta
- Matrices NotesUploaded byAnonymous gUySMcpSq
- PracticeExam1Solns.pdfUploaded bySceptic Granny
- Exercicios Pol Interp2Uploaded byFabio Ferraz de Carvalho
- Vector AnalysisUploaded byJorge Florez Castrejon
- Plane GroupsUploaded byAndrew Wang
- Smarandache Fuzzy Strong Ideal and Smarandache Fuzzy n-Fold Strong Ideal of a BH-AlgebraUploaded byDon Hass
- hw13aUploaded byAjay Varma
- Chapter2-R09.pdfUploaded byAzhar Mahmood
- Clifford Cl (5, C) Unified Field Theories of Conformal Gravity, Maxwell and U (4 ) x U (4) Yang-MillsUploaded byKathryn Wilson
- ZpZ - Joshua Nichols-Barrer - MOP (Black) 2011.pdfUploaded byMihnea
- Roots and CoefficientsUploaded byຄະນິດສາດ ຈີເນຍສ ວຽງສຸພາ
- Theorem LurothUploaded byEmmanureva
- Sketch_ Of_ ProofUploaded bySpanu Dumitru Viorel
- Binomial ExpansionsUploaded byTesai
- A Note on the Fractional CalculusUploaded byJesús Avalos Rodríguez
- Numeralogy (III) or Properties of NumbersUploaded byAnonymous 0U9j6BLllB
- Algebra Grid Games for fun math reviewUploaded byMelisa Rice
- Linear Algebra AnswersUploaded bydull_matter
- Exercicios gerales Aneis e IdeaisUploaded byMoisés Toledo
- HandbookUploaded byHao Li
- LOGIC SIMPLIFICATION SLIDEUploaded byتوان ظاهيرو الدين