Skip to content

Permutation

Serge Stinckwich edited this page Jul 8, 2018 · 1 revision

a PMPermutation is a sequential arrangement of a set. the set of integers from one to set size is normally used. for example to produce all permutations of size 3 you can do this:

a:=PMPermutation allOfSize: 3. "-->
an Array(a PMPermutation(1 2 3) a PMPermutation(2 1 3) 
a PMPermutation(3 1 2) a PMPermutation(1 3 2) 
a PMPermutation(2 3 1) a PMPermutation(3 2 1))"

you can think of a permutation like this as a positioning specification for a sequentialCollection

b:=a at:3. "--> a PMPermutation(3 1 2)"

aPMPermutation(3 1 2) says that what used to be the 3rd element is now at position 1, the 1st one is now at position 2 and the 2nd at position 3. you can apply that on any SequenceableCollection

b permute:#('is' 'this' 'what'). "--> #('what' 'is' 'this')"

of course you can produce a permutation the same way on a SequenceableCollection that is sortable:

b:=PMPermutation ordering: #(h c ds db b a).  "-->
a PMPermutation(6 3 5 4 2 1)"
ar:=#(h c ds db b a)sort.
b permute:ar." --> #(#h #c #ds #db #b #a)" "the original Array"

or you can construct a permutation this way:

PMPermutation ordering: #(5 4 0). "--> a PMPermutation(3 2 1)"
"or simply this way:"
PMPermutation ordering: #(3 2 1). "--> a PMPermutation(3 2 1)"

the identity, that does not change the order, can be made like this:

b:=PMPermutation identity: 6. "--> a PMPermutation(1 2 3 4 5 6)"
b permute:#(a b c db ds h). "--> #(#a #b #c #db #ds #h)"

you produce a shifting permutation this way:

PMPermutation size:6 shift: 2. "-->
a PMPermutation(3 4 5 6 1 2)" "a leftshift by 2 positions"
PMPermutation size:6 shift: -1. "-->
a PMPermutation(6 1 2 3 4 5)" "a rightshift by one position"

random permutations of a given size can be made like this:

PMPermutation randomPermutation: 7. "-->
a PMPermutation(2 1 5 3 6 7 4)"

if you apply a permutation on a permutation you get a permutation again:

a:=PMPermutation ordering: #(2 4 3 1). "--> a PMPermutation(2 4 3 1)"
a permute:a. "--> a PMPermutation(4 1 3 2)"

lets have a more detailed look into this:

b:= a permute:#(a b c d). "-->
#(#b #d #c #a)" 
"now lets permute this result in another way:"
c:=PMPermutation ordering:#(3 1 2 4).
c permute: b. "-->
#(#c #b #d #a)" 
"instead we can do this:"
(c permute:a)permute:#(a b c d). "-->
#(#c #b #d #a)"

of course the sequence of doing this is important as permute: is generally not commutative. a case where the sequence is not important is obviously this:

identity:=PMPermutation identity:4. "--> a PMPermutation(1 2 3 4)"
(a permute: identity) = a. "--> true"
(identity permute: a) = a. "--> true"

every permutation has an inverse:

c:=a inverse. "--> a PMPermutation(4 1 3 2)"
c permute: a. "--> a PMPermutation(1 2 3 4)"
(a permute:c)=identity. "--> true"

you can shift a permutation:

a shift:1. "--> a PMPermutation(4 3 1 2)"
"attention: #shift: works on the permutation itself!"
a. "--> a PMPermutation(4 3 1 2)"
a shift: -3. "--> a PMPermutation(3 1 2 4)"

you can make a reversed copy:

b := a reversed. "--> a PMPermutation(4 2 1 3)"

you can make a permutation matrix like that:

m:=b asMatrix. "-->
a PMVector(0 0 0 1)
a PMVector(0 1 0 0)
a PMVector(1 0 0 0)
a PMVector(0 0 1 0)"
"this works like a permutation:"
b permute:#(1 4 9 16)."-->#(16 4 1 9)"
m * #(1 4 9 16) asPMVector ."--> a PMVector(16 4 1 9)"

another way to characterize a permutation is by its cycles

a. "--> a PMPermutation(3 1 2 4)"

at position 1 the permutation puts 3, at 3 it puts 2 and at 2 it puts 1 which closes the cycle. another 1-element cycle is at 4.

b := a asCycles. "--> #(#(1 3 2) #(4))"

of course you can construct a permutation via its cycles:

PMPermutation fromCycles:b. "--> a PMPermutation(3 1 2 4)"
"or, since it is not necessary to specify 1-cycles, eg"
PMPermutation size:4 fromCycles: #((3 2 1)). "-->
a PMPermutation(3 1 2 4)"

that way of looking at permutations as cycles can be interesting for different reasons. lets say you want to know, how difficult it is to sort a permutation. one way could be to count the necessary number of swap:with: operations. these operations - in permutation lingo transpositions - are simple 2-cycles and their number can be calculated by taking the difference between the size of the permutation and the size of the cycles array. an example:

a:= PMPermutation newFrom:#(2 4 3 5 1).
"this calculates the size difference:"
a discriminant. "--> 3"
"an example with 3 transpositions is:"
b:=(PMPermutation fromCycles:#((1 5)))permute:a. "-->
a PMPermutation(1 4 3 5 2)"
b:=(PMPermutation fromCycles:#((4 5)))permute:b. "-->
a PMPermutation(1 4 3 2 5)"
b:=(PMPermutation fromCycles:#((4 2)))permute:b. "-->
a PMPermutation(1 2 3 4 5)"
"btw  permutations can be split up into odd and even permutations
depending on the odd or even number of transpositions."
a odd. "true"

you can also use essentially the above method to calculate the number of transpositions from one permutation to another:

a1:= PMPermutation newFrom:#(3 4 2 1 5). "-->
a PMPermutation(3 4 2 1 5)"
"lets calculate the number of transpositions necessary
from a to a1:"
b:=a inverse permute:a1. "--> a PMPermutation(5 3 2 4 1)"
b discriminant. "-->2"
"ok, using two 2-cycles:"
a1=((PMPermutation fromCycles:#((1 3)(4 5)))permute:a).  "true"
"and btw obviously:"
b even. "true"

generator: takes a collection of permutations and generates all possible combinations of a repeated application of these permutations on themselves. this can eg be used to make symmetry groups and such. i'll make an example:

lets say we want to know the number of ways we can paint one to six points on the sides of a cube. i imagine a dice sitting on a table with its one side on the table and the two side looking south. i can turn it by 90° around the vertical axis.

a:=PMPermutation size:6 fromCycles: #((2 3 5 4)).

of course i can do that 4 times:

PMPermutation generator: {a}. "-->an Array(
a PMPermutation(1 4 2 5 3 6) a PMPermutation(1 3 5 2 4 6)
a PMPermutation(1 2 3 4 5 6) a PMPermutation(1 5 4 3 2 6))"

i also can turn it around another axis going through the sides 2 and 5

b:=PMPermutation size:6 fromCycles: #((1 3 6 4)).

well, these two permutations are enough, but lets assume we have some difficulty turning a dice in our head and therefore we add a third 90° turning around 3 and 4. this is very obviously enough, all other symmetries will automatically be generated.

c:=PMPermutation size:6 fromCycles: #((1 5 6 2)).
d:=PMPermutation generator: {a.b}.
e:=PMPermutation generator: {a.b.c}.
d size. "-->24" "same as:"
e size. "-->24"

we can see that the third turning c was indeed unnecessary. now, the number of all 6-permutations is:

(PMPermutation allOfSize: 6)size. "-->720"
"or simply:"
6 factorial . "--> 720"

and if you paint the dice with another 6-permutation not in d, this will also produce 24 other permutations hence the number of different ways we can paint one to six points on the sides of a cube is 30:

6 factorial / d size. "--> 30"