Generating
Permutations
Applications of Arrays
Permutations
• a
permutation of n is a one-to-one and onto function from {1,2,…,n} to itself
• permutation
p is represented by writing values of p(1) p(2) …… p(n) in sequence
• 3
1 6 5 4 2 is a permutation of 6
• represented
naturally using an array
• arise
in many contexts
• how
many different permutations of n?
Traveling
Salesman Problem
• input
is a set of n cities and distance between every pair of cities
• output
is a tour of the cities visiting each city exactly once
• many
tours are possible – how many?
• find
one for which total distance traveled
is minimized
• no
efficient method known for this!
Generating
Permutations
• every
possible tour represented by a permutation of the cities
• cities
listed in the order they are visited
• suggests
a simple algorithm
– list all
permutations
– find
distance traveled for each
– take the
minimum of these
• very
time consuming algorithm
Lexicographic
Order
• any
listing of permutations defines an ordering of the permutations
• list
using some natural order
• lexicographic
order
• permutation
p is listed before q iff there is an i such that
– p(j) = q(j)
for 1 <= j < i, and
– p(i) <
q(i)
• similar
to ordering for character strings
• 1
2 3, 1 3 2, 2 1 3, 2 3 1, 3 1 2, 3 2 1
• first
permutation is the identity 1 2 ….. n
• given
a permutation how to generate next?
• intuitive
idea
– keep initial
part the same as far as possible
– increase the
next number by minimum possible
– remaining
numbers in increasing order
Example
• 6
3 5 1 9 2 8 7 4 is a permutation of 9
• what
is the next in lexicographic order?
• if
6 3 5 1 9 2 is fixed next number cannot
be increased
• a
number can be increased only if it has a larger number to its right
• 6
3 5 1 9 is fixed
• increase
2 to 4
• arrange
remaining numbers as 2 7 8
Program
a(1:n) = (/(i,i=1,n)/)
do
print *, a(1:n)
do
j = n-1, 1, -1
if (a(j) < a(j+1)) exit
end do
if ( j == 0) exit !
loop variable used outside
do
k = n, j+1, -1
if (a(k) > a(j)) exit
end do
! a(j) is the rightmost number having a
number greater
! than itself to its right
! a(k) is the smallest number > a(j) to
its right
! exchange a(k) and a(j) and reverse
a(j+1:n)
temp = a(k)
a(k) = a(j)
a(j) = temp
a(j+1:n) = a(n:j+1:-1) ! section in reverse
order
end do
Loop
Invariant
• at
beginning of ith iteration,
a(1:n) contains ith
permutation in lexicographic order
• p
be permutation at start of ith
iteration
• q
be permutation at start of (i+1)th
iteration
• show
that there is no r such that p < r < q in lexicographic order
• suppose
there is an r, p <= r <= q
• p(i)
= q(i), implies p(i) = r(i) for 1 <= i < j
• if
p(j) < r(j) then r(j) = q(j), since q(j) is the smallest number > p(j) to
its right
• thus,
either r(j) = p(j) or r(j) = q(j)
• p(j+1:n)
is a decreasing sequence
• q(j+1:n)
is an increasing sequence
• p(j)
= r(j) and p <= r implies p = r
• r(j)
= q(j) and r <= q implies r = q
• thus
either p = r or r = q
Rank
and Unrank Functions
• rank
of a permutation is the number of permutations < than it in lexicographic
order
• consider
a permutation p(1) p(2)……p(n)
• if
q(1) < p(1), q < p
• there
are (p(1)-1)(n-1)! such permutations
• if
q(1) = p(1) and q(2) < p(2), q < p
• there
are either (p(2)-1)(n-2)! or
(p(2)-2))(n-2)! permutations of
this type
Rank
Function
• in
general, for permutation p(1) ……. p(n)
• rank
= d(1)(n-1)! + d(2)(n-2)! + ……
– d(i) is the
number of p(j), j > i, p(j) < p(i)
• consider
the permutation n n-1 n-2 …… 1
• rank
= n!-1
• d(i)
= i-1
• n!-1
= (n-1)(n-1)!+(n-2)(n-2)!+…….1(1!)
• ranking
functions used to prove identities
Computing
the Rank
rank = 0
fact = 1
do
i = n-1, 1, -1
fact = fact*(n-i)
d = count(a(i+1:n) < a(i))
rank = rank + fact*d
end do
! count is an intrinsic function which counts
number of
! true values in a logical array
Unrank
Function
• given
a number r, find the permutation of n whose rank is r
• 0
<= r <= n!-1
• any
such r can be written uniquely as
• r
= d(1)(n-1)! + d(2)(n-2)!+ ……+d(n).0! such that 0 <= d(i) <= n-i
• d(1)
= r/(n-1)!
• remaining
terms have sum at most (n-1)!-1
Computing
Unrank Function
fact = 1
do
i = 2, n-1
fact = fact*i
end do
do
i = 1, n-1 ! compute d values first
d(i) = r/fact ! integer division
r = r – fact*d(i)
fact = fact/(n-i)
end do
d(n) = 0
do
i = n, 1, -1
a(i) = d(i) + 1
where(a(i+1:n) >= a(i)) a(i+1:n) = a(i+1:n)+1
end do
! computes the permutation iteratively
! a(i:n) is a permutation p’ of n-i+1 such
that a(j) has
! exactly d(j) numbers < than it to its
right, i<=j<=n
! a(1:n) is the required permutation
! separate d array is not required, use a
itself
Other
Listings
• other
orders of listing may be more useful
• listing
by minimal change
– next
permutation obtained by swapping two consecutive numbers
– useful for
computing distances in TSP
• more
efficient rank and unrank functions
– useful for
generating random permutations
• similar
listings possible for other objects
Summary
• permutations
are basic combinatorial objects
• listing
of all permutations is useful
• listing
in lexicographic order
• rank
and unrank functions
• useful
for generating random permutations
• other
orders for listing possible
• other
combinatorial objects may be similarly listed