module Music.Theory.Permutations where
import Data.List
import qualified Numeric
import qualified Music.Theory.List as L
factorial :: Integral n => n -> n
factorial :: forall n. Integral n => n -> n
factorial n
n = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product [n
1..n
n]
nk_permutations :: Integral a => a -> a -> a
nk_permutations :: forall a. Integral a => a -> a -> a
nk_permutations a
n a
k = forall n. Integral n => n -> n
factorial a
n forall a. Integral a => a -> a -> a
`div` forall n. Integral n => n -> n
factorial (a
n forall a. Num a => a -> a -> a
- a
k)
n_permutations :: (Integral a) => a -> a
n_permutations :: forall n. Integral n => n -> n
n_permutations a
n = forall a. Integral a => a -> a -> a
nk_permutations a
n a
n
type Permutation = [Int]
permutation :: Eq t => [t] -> [t] -> Permutation
permutation :: forall t. Eq t => [t] -> [t] -> Permutation
permutation [t]
p [t]
q =
let f :: t -> Int
f t
x = forall a. Eq a => a -> [a] -> Int
L.elem_index_unique t
x [t]
p
in forall a b. (a -> b) -> [a] -> [b]
map t -> Int
f [t]
q
permutation_to_swaps :: Permutation -> [(Int,Int)]
permutation_to_swaps :: Permutation -> [(Int, Int)]
permutation_to_swaps = forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..]
swaps_to_permutation :: [(Int,Int)] -> Permutation
swaps_to_permutation :: [(Int, Int)] -> Permutation
swaps_to_permutation = forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => [a] -> [a]
sort
cycles_to_swaps :: [[Int]] -> [(Int,Int)]
cycles_to_swaps :: [Permutation] -> [(Int, Int)]
cycles_to_swaps = forall a. Ord a => [a] -> [a]
sort forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (forall t. Int -> [t] -> [(t, t)]
L.adj2_cyclic Int
1)
swaps_to_cycles :: [(Int, Int)] -> [[Int]]
swaps_to_cycles :: [(Int, Int)] -> [Permutation]
swaps_to_cycles [(Int, Int)]
s =
let z :: Int
z = forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Int, Int)]
s
next :: Int -> Int
next Int
k = forall k v. Eq k => k -> [(k, v)] -> v
L.lookup_err Int
k [(Int, Int)]
s
trace :: Int -> Permutation
trace Int
k =
let f :: Permutation -> Int -> Permutation
f Permutation
r Int
i = let j :: Int
j = Int -> Int
next Int
i in if Int
j forall a. Eq a => a -> a -> Bool
== Int
k then forall a. [a] -> [a]
reverse Permutation
r else Permutation -> Int -> Permutation
f (Int
j forall a. a -> [a] -> [a]
: Permutation
r) Int
j
in Permutation -> Int -> Permutation
f [Int
k] Int
k
step :: [Permutation] -> Int -> [Permutation]
step [Permutation]
r Int
k =
if Int
k forall a. Eq a => a -> a -> Bool
== Int
z
then forall a. [a] -> [a]
reverse [Permutation]
r
else if Int
k forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [Permutation]
r then [Permutation] -> Int -> [Permutation]
step [Permutation]
r (Int
k forall a. Num a => a -> a -> a
+ Int
1) else [Permutation] -> Int -> [Permutation]
step (Int -> Permutation
trace Int
k forall a. a -> [a] -> [a]
: [Permutation]
r) (Int
k forall a. Num a => a -> a -> a
+ Int
1)
in [Permutation] -> Int -> [Permutation]
step [] Int
0
apply_permutation :: Permutation -> [t] -> [t]
apply_permutation :: forall t. Permutation -> [t] -> [t]
apply_permutation Permutation
f [t]
p = forall a b. (a -> b) -> [a] -> [b]
map ([t]
p forall a. [a] -> Int -> a
!!) Permutation
f
apply_permutation_c_zero_indexed :: [[Int]] -> [a] -> [a]
apply_permutation_c_zero_indexed :: forall a. [Permutation] -> [a] -> [a]
apply_permutation_c_zero_indexed = forall t. Permutation -> [t] -> [t]
apply_permutation forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Permutation] -> Permutation
from_cycles_zero_indexed
p_inverse :: Permutation -> Permutation
p_inverse :: Permutation -> Permutation
p_inverse = forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => [a] -> [a]
sort forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..]
p_cycles :: Permutation -> [[Int]]
p_cycles :: Permutation -> [Permutation]
p_cycles = [(Int, Int)] -> [Permutation]
swaps_to_cycles forall b c a. (b -> c) -> (a -> b) -> a -> c
. Permutation -> [(Int, Int)]
permutation_to_swaps
non_invertible :: Permutation -> Bool
non_invertible :: Permutation -> Bool
non_invertible Permutation
p = Permutation
p forall a. Eq a => a -> a -> Bool
== Permutation -> Permutation
p_inverse Permutation
p
from_cycles_zero_indexed :: [[Int]] -> Permutation
from_cycles_zero_indexed :: [Permutation] -> Permutation
from_cycles_zero_indexed = [(Int, Int)] -> Permutation
swaps_to_permutation forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Permutation] -> [(Int, Int)]
cycles_to_swaps
from_cycles_one_indexed :: [[Int]] -> Permutation
from_cycles_one_indexed :: [Permutation] -> Permutation
from_cycles_one_indexed = [Permutation] -> Permutation
from_cycles_zero_indexed forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (forall a b. (a -> b) -> [a] -> [b]
map (forall a. Num a => a -> a -> a
subtract Int
1))
permutations_n :: Int -> [Permutation]
permutations_n :: Int -> [Permutation]
permutations_n Int
n =
let minus :: [t] -> t -> [t]
minus [] t
_ = []
minus (t
x:[t]
xs) t
i = if t
x forall a. Ord a => a -> a -> Bool
< t
i then t
x forall a. a -> [a] -> [a]
: [t] -> t -> [t]
minus [t]
xs t
i else [t]
xs
f :: [a] -> [[a]]
f [] = [[]]
f [a]
xs = [a
i forall a. a -> [a] -> [a]
: [a]
ys | a
i <- [a]
xs , [a]
ys <- [a] -> [[a]]
f ([a]
xs forall {t}. Ord t => [t] -> t -> [t]
`minus` a
i)]
in case Int
n of
Int
0 -> []
Int
1 -> [[Int
0]]
Int
_ -> forall {a}. Ord a => [a] -> [[a]]
f [Int
0 .. Int
n forall a. Num a => a -> a -> a
- Int
1]
p_size :: Permutation -> Int
p_size :: Permutation -> Int
p_size = forall (t :: * -> *) a. Foldable t => t a -> Int
length
compose :: Permutation -> Permutation -> Permutation
compose :: Permutation -> Permutation -> Permutation
compose Permutation
p Permutation
q =
let n :: Int
n = Permutation -> Int
p_size Permutation
q
i :: Permutation
i = [Int
1 .. Int
n]
j :: Permutation
j = forall t. Permutation -> [t] -> [t]
apply_permutation Permutation
p Permutation
i
k :: Permutation
k = forall t. Permutation -> [t] -> [t]
apply_permutation Permutation
q Permutation
j
in forall t. Eq t => [t] -> [t] -> Permutation
permutation Permutation
i Permutation
k
cycles_one_indexed :: Permutation -> [[Int]]
cycles_one_indexed :: Permutation -> [Permutation]
cycles_one_indexed = forall a b. (a -> b) -> [a] -> [b]
map (forall a b. (a -> b) -> [a] -> [b]
map (forall a. Num a => a -> a -> a
+ Int
1)) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Permutation -> [Permutation]
p_cycles
permutation_mul :: Permutation -> Permutation -> Permutation
permutation_mul :: Permutation -> Permutation -> Permutation
permutation_mul Permutation
p Permutation
q = Permutation -> Permutation -> Permutation
compose Permutation
q Permutation
p
two_line :: Permutation -> ([Int],[Int])
two_line :: Permutation -> (Permutation, Permutation)
two_line Permutation
p =
let n :: Int
n = Permutation -> Int
p_size Permutation
p
i :: Permutation
i = [Int
1..Int
n]
in (Permutation
i,forall t. Permutation -> [t] -> [t]
apply_permutation Permutation
p Permutation
i)
one_line :: Permutation -> [Int]
one_line :: Permutation -> Permutation
one_line = forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. Permutation -> (Permutation, Permutation)
two_line
one_line_compact :: Permutation -> String
one_line_compact :: Permutation -> String
one_line_compact =
let f :: a -> String
f a
n = if a
n forall a. Ord a => a -> a -> Bool
>= a
0 Bool -> Bool -> Bool
&& a
n forall a. Ord a => a -> a -> Bool
<= a
15
then forall a. (Integral a, Show a) => a -> ShowS
Numeric.showHex a
n String
""
else forall a. HasCallStack => String -> a
error String
"one_line_compact:not(0-15)"
in forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap forall {a}. (Integral a, Show a) => a -> String
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. Permutation -> Permutation
one_line
multiplication_table :: Int -> [[Permutation]]
multiplication_table :: Int -> [[Permutation]]
multiplication_table Int
n =
let ps :: [Permutation]
ps = Int -> [Permutation]
permutations_n Int
n
f :: Permutation -> [Permutation]
f Permutation
p = forall a b. (a -> b) -> [a] -> [b]
map (Permutation -> Permutation -> Permutation
compose Permutation
p) [Permutation]
ps
in forall a b. (a -> b) -> [a] -> [b]
map Permutation -> [Permutation]
f [Permutation]
ps