├── .ctags ├── .gitignore ├── .travis.yml ├── .yamllint ├── CONTRIBUTING.md ├── Control ├── Permutation.idr └── Permutation │ ├── Mod.idr │ ├── Proofs.idr │ └── Types.idr ├── Data └── Group.idr ├── LICENSE ├── Makefile ├── README.md ├── TODO.md ├── Test └── Spec.idr ├── docs ├── alternative.css ├── blackandwhite.css ├── default.css ├── docs │ ├── Control.Permutation.Mod.html │ ├── Control.Permutation.Proofs.html │ ├── Control.Permutation.Types.html │ ├── Control.Permutation.html │ └── Data.Group.html └── index.html ├── permutations.ipkg └── test.ipkg /.ctags: -------------------------------------------------------------------------------- 1 | --langdef=Idris 2 | --langmap=Idris:.idr 3 | --regex-Idris=/^ *([[:lower:]][[:alnum:]_]+)[[:blank:]]*:[^:].*->.*/\1/f,function,functions/ 4 | --regex-Idris=/^ *([[:lower:]][[:alnum:]_]+)[[:blank:]]*:[^:][^-]+$/\1/c,constant,constants/ 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | tags 3 | *.ibc 4 | *.swp 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | sudo: false 3 | language: python 4 | cache: 5 | directories: 6 | - $HOME/.cabal 7 | - $HOME/.ghc 8 | addons: 9 | apt: 10 | sources: 11 | - hvr-ghc 12 | packages: 13 | - libgmp3-dev 14 | - ghc-8.2.1 15 | - cabal-install-head 16 | 17 | install: 18 | - rm -rf $HOME/.cabal 19 | - export PATH=/opt/ghc/$GHCVER/bin:$PATH 20 | - export PATH=$HOME/.cabal/bin:$PATH 21 | - cabal update 22 | - travis_wait 30 cabal new-install idris 23 | - git clone https://github.com/pheymann/specdris 24 | - cd specdris/ 25 | - idris --install specdris.ipkg 26 | 27 | script: 28 | - cd ../ 29 | - idris --testpkg test.ipkg 30 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | rules: 3 | braces: 4 | min-spaces-inside: 0 5 | max-spaces-inside: 0 6 | min-spaces-inside-empty: -1 7 | max-spaces-inside-empty: -1 8 | brackets: 9 | min-spaces-inside: 0 10 | max-spaces-inside: 0 11 | min-spaces-inside-empty: -1 12 | max-spaces-inside-empty: -1 13 | colons: 14 | max-spaces-before: 0 15 | max-spaces-after: 1 16 | commas: 17 | max-spaces-before: 0 18 | min-spaces-after: 1 19 | max-spaces-after: 1 20 | comments: 21 | level: warning 22 | require-starting-space: true 23 | min-spaces-from-content: 2 24 | comments-indentation: 25 | level: warning 26 | document-end: disable 27 | document-start: 28 | level: warning 29 | present: true 30 | empty-lines: 31 | max: 2 32 | max-start: 0 33 | max-end: 0 34 | hyphens: 35 | max-spaces-after: 1 36 | indentation: 37 | spaces: consistent 38 | indent-sequences: false 39 | check-multi-line-strings: false 40 | key-duplicates: enable 41 | line-length: disable 42 | new-line-at-end-of-file: enable 43 | new-lines: 44 | type: unix 45 | trailing-spaces: enable 46 | truthy: disable 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | I emphatically welcome bug reports, issues you may encounter, documentation, and 4 | pull requests. Feature requests may or may not get a response, though you can 5 | always open a PR to add a feature you'd like. 6 | 7 | ## Getting started 8 | 9 | If you'd like ideas for ways to contribute, check out `TODO.md`. Feel free to 10 | open a PR or an issue if you want guidance on how to implement something. If 11 | you're new to Idris, I can provide help to the best of my abilities. 12 | 13 | ## Rules etc. 14 | We follow the [rust standards of 15 | conduct](https://www.rust-lang.org/en-US/conduct.html), with the addendum that 16 | we are committed to providing a friendly, safe and welcoming environment 17 | regardless of sex worker status or previous sex worker status. 18 | 19 | In addition, please be aware that not everyone speaks English as a first 20 | language. 21 | -------------------------------------------------------------------------------- /Control/Permutation.idr: -------------------------------------------------------------------------------- 1 | module Control.Permutation 2 | 3 | import public Data.Group 4 | import public Control.Permutation.Types 5 | import public Control.Permutation.Mod 6 | import public Control.Permutation.Proofs 7 | -------------------------------------------------------------------------------- /Control/Permutation/Mod.idr: -------------------------------------------------------------------------------- 1 | -- loosely based off Alyssa Carter's code 2 | module Control.Permutation.Mod 3 | 4 | import Data.Nat 5 | import Data.List 6 | import Control.Permutation.Types 7 | import Data.Vect 8 | 9 | %default total 10 | 11 | mutual 12 | even : Nat -> Bool 13 | even Z = True 14 | even (S k) = odd k 15 | 16 | odd : Nat -> Bool 17 | odd Z = False 18 | odd (S k) = even k 19 | 20 | private 21 | natToFin' : (n : Nat) -> Fin (S n) 22 | natToFin' Z = FZ 23 | natToFin' (S k) = FS (natToFin' k) 24 | 25 | rangeFromZero : Fin n -> List (Fin n) 26 | rangeFromZero FZ = [FZ] 27 | rangeFromZero m@(FS k) = m :: map weaken (rangeFromZero k) 28 | 29 | rangeFromOne : Fin (S n) -> List (Fin (S n)) 30 | rangeFromOne FZ = Nil 31 | rangeFromOne m@(FS k) = m :: map weaken (rangeFromZero k) 32 | 33 | ||| This permutation reverses a vector completely 34 | reverse : {n : Nat} -> Permutation n 35 | reverse {n=Z} = Control.Permutation.Types.Nil 36 | reverse {n=S _} = last :* reverse 37 | 38 | private 39 | finiteL : (n : Nat) -> Vect (S n) (Fin (S n)) 40 | finiteL Z = FZ :: Nil 41 | finiteL n@(S m) = natToFin' n :: (map weaken $ finiteL m) 42 | 43 | public export 44 | factorial : Nat -> Nat 45 | factorial Z = S Z 46 | factorial (S k) = (S k) * factorial k 47 | 48 | combine : {m,n : Nat} -> Vect m (a -> b) -> Vect n a -> Vect (m * n) b 49 | combine {m} {n} fs xs = rewrite multCommutative m n in 50 | concat $ map (g fs) xs 51 | where 52 | g : Vect m (a -> b) -> a -> Vect m b 53 | g fs x = fs <*> pure x 54 | 55 | ||| All permutations of a certain order. 56 | export 57 | enumerateStrict : {n : Nat} -> Vect (factorial n) (Permutation n) 58 | enumerateStrict {n=Z} = Nil :: Nil 59 | enumerateStrict {n=S Z} = ((FZ :* Nil) :: Data.Vect.Nil) 60 | enumerateStrict {n=(S m)} = combine (map (:*) (finiteL m)) enumerateStrict 61 | 62 | ||| Show where an integer is sent. 63 | ||| @p A permutation 64 | ||| @m The integer 65 | fixNat : {n : Nat} -> (p : Permutation n) -> (m : Fin n) -> Fin n 66 | fixNat p m = index m $ (toVector p) 67 | where 68 | index : Fin l -> Lazy (Vect l e) -> e 69 | index FZ (x::xs) = x 70 | index (FS k) (x::xs) = index k xs 71 | 72 | ||| Orbit generated by a given element. 73 | ||| @p A permutation 74 | ||| @i The starting point 75 | orbit : {n : Nat} -> (p : Permutation (S n)) -> (i : Fin (S n)) -> Stream (Fin (S n)) 76 | orbit p i = i :: go i where 77 | go : Fin (S n) -> Stream (Fin (S n)) 78 | go j = next :: go next where 79 | next : Fin (S n) 80 | next = fixNat p j 81 | 82 | ||| Return the orbit of some permutation. 83 | finOrbit : {n : Nat} -> Permutation (S n) -> Fin (S n) -> List (Fin (S n)) 84 | finOrbit p {n} i = nub $ take (S n) (orbit p i) 85 | 86 | ||| Return a list of disjoint cycles given a permutation. We use this for our 87 | ||| pretty-printer. 88 | export 89 | cycles : {n : Nat} -> Permutation (S n) -> List (List (Fin (S n))) 90 | cycles p {n} = nubBy g . map (finOrbit p) . rangeFromZero $ (natToFin' n) 91 | where 92 | g : List (Fin (S n)) -> List (Fin (S n)) -> Bool 93 | g x y = and $ map (delay . flip elem y) x 94 | 95 | export 96 | order : {n : Nat} -> Permutation (S n) -> Nat 97 | order = assert_total $ foldr lcm 1 . map length . cycles 98 | 99 | private 100 | checkId : String -> String 101 | checkId "" = "id" 102 | checkId x = x 103 | 104 | implementation {n : Nat} -> Show (Permutation (S n)) where 105 | show {n} p = checkId (concatMap (go n) (cycles p)) 106 | where 107 | go : Nat -> List (Fin (S n)) -> String 108 | go _ l@(_::_::_) = if n <= 9 109 | then "(" ++ concatMap show l ++ ")" 110 | else "(" ++ concat ((intersperse "," . map show) l) ++ ")" 111 | go _ _ = "" 112 | 113 | private 114 | fill : {n : Nat} -> Fin n -> Permutation n 115 | fill FZ = neutral 116 | fill (FS k) = FS (zeros k) :* fill k 117 | where zeros : Fin m -> Fin m 118 | zeros FZ = FZ 119 | zeros (FS _) = FZ 120 | 121 | ||| The permutation π_ij 122 | export 123 | piPerm : {n : Nat } -> Fin n -> Fin n -> Permutation n 124 | piPerm (FS j) (FS k) = FZ :* piPerm j k 125 | piPerm (FS j) FZ = FS j :* fill j 126 | piPerm FZ (FS k) = FS k :* fill k 127 | piPerm FZ FZ = neutral 128 | 129 | ||| For S_4, (1234) 130 | export 131 | circulate : {n : Nat} -> Permutation n 132 | circulate {n=Z} = Nil 133 | circulate {n=S Z} = FZ :* Nil 134 | circulate {n=S (S m)} = foldl (<+>) neutral pis 135 | where 136 | pis : List (Permutation (S (S m))) 137 | pis = zipWith piPerm (rangeFromZero (weaken $ natToFin' m)) (rangeFromOne (natToFin' (S m))) 138 | 139 | ||| Factors a permutation into a product of swaps. 140 | export 141 | swaps : {n : Nat} -> Permutation n -> List (Permutation n) 142 | swaps {n=Z} _ = [] 143 | swaps {n=n@(S _)} p = go overlaps p 144 | where 145 | go : (List (Fin n) -> List (Permutation n)) -> Permutation n -> List (Permutation n) 146 | go f p = (>>= f) $ cycles p 147 | overlaps : List (Fin n) -> List (Permutation n) 148 | overlaps (x::xs@(y::ys)) = piPerm x y :: overlaps xs 149 | overlaps x = [] 150 | 151 | ||| Test whether a permutation is even. 152 | export 153 | isEven : {n : Nat} -> Permutation n -> Bool 154 | isEven = even . length . swaps 155 | -------------------------------------------------------------------------------- /Control/Permutation/Proofs.idr: -------------------------------------------------------------------------------- 1 | module Control.Permutation.Proofs 2 | 3 | import Control.Permutation.Mod 4 | import Data.Nat 5 | 6 | ||| Proof that (n + 1)! >= n! 7 | export 8 | factorialIncr : (n : Nat) -> LTE (factorial n) (factorial (S n)) 9 | factorialIncr Z = reflexive {x = S Z} 10 | factorialIncr n = lteAddRight (factorial n) 11 | 12 | ||| Proof that n! >= 1 13 | export 14 | factorialLTE : (n : Nat) -> LTE 1 (factorial n) 15 | factorialLTE Z = ?base_hole 16 | factorialLTE (S k) = transitive {x=S Z} (factorialLTE k) (factorialIncr k) 17 | -------------------------------------------------------------------------------- /Control/Permutation/Types.idr: -------------------------------------------------------------------------------- 1 | module Control.Permutation.Types 2 | 3 | import Data.List 4 | import Data.Vect 5 | import Data.Fin 6 | import Data.Group 7 | 8 | %default total 9 | 10 | infixr 7 :* 11 | 12 | ||| This is something like `Vector k a`, except we restrict ourselves to only 1,...,n for `Permutation n`. 13 | public export 14 | data Permutation : Nat -> Type where 15 | Nil : Permutation Z 16 | (:*) : Fin (S n) -> Permutation n -> Permutation (S n) 17 | 18 | implementation Eq (Permutation n) where 19 | (==) Nil Nil = True 20 | (==) (x :* xs) (y :* ys) = x == y && xs == ys 21 | 22 | private 23 | id : {n : Nat} -> Permutation n 24 | id {n=Z} = [] 25 | id {n=S _} = FZ :* id 26 | 27 | export 28 | debug : Permutation n -> String 29 | debug Nil = "Nil" 30 | debug (p:*ps) = show (finToNat p) ++ " :* " ++ (debug ps) 31 | 32 | ||| This is essentially a group action. Given a permutation, we apply it to a vector. 33 | sigma : {n : Nat} -> Permutation n -> Vect n a -> Vect n a 34 | sigma _ [] = [] 35 | sigma {n=S _} (p:*ps) (x::xs) = insert (sigma ps xs) p 36 | where 37 | insert : Vect n a -> Fin (S n) -> Vect (S n) a 38 | insert l FZ = x::l 39 | insert Data.Vect.Nil _ = [x] 40 | insert (e::es) (FS k) = e :: insert es k 41 | 42 | export 43 | toVector : {n : Nat} -> Permutation n -> Vect n (Fin n) 44 | toVector {n} p = sigma p (sequential n) 45 | where 46 | sequential : (n : Nat) -> Vect n (Fin n) 47 | sequential Z = [] 48 | sequential (S k) = FZ :: map FS (sequential k) 49 | 50 | private 51 | indices : {n : Nat} -> Permutation n -> Vect n (Fin n) 52 | indices [] = Nil 53 | indices (p :* ps) = p :: map (thin p) (indices ps) 54 | where 55 | thin : {n : Nat} -> Fin (S n) -> Fin n -> Fin (S n) 56 | thin FZ i = FS i 57 | thin _ FZ = FZ 58 | thin (FS i) (FS j) = FS (thin i j) 59 | 60 | private 61 | delete : {n : Nat} -> Fin (S n) -> Permutation (S n) -> Permutation n 62 | delete FZ (j :* p) = p 63 | delete {n=Z} (FS _) _ = Nil 64 | delete {n=S _} (FS i) (j :* p) = fromMaybe (lifter j) (strengthen j) :* delete i p 65 | where 66 | lifter : {n : Nat} -> Fin (S n) -> Fin n 67 | lifter {n=Z} _ = ?hole 68 | lifter {n=S _} (FS k) = k 69 | lifter {n=S _} FZ = FZ 70 | 71 | private 72 | compose : {n : Nat} -> Permutation n -> Permutation n -> Permutation n 73 | compose Nil p = p 74 | compose (i :* p) p' = index i (indices p') :* compose p (delete i p') 75 | 76 | export 77 | invert : {n : Nat} -> Permutation n -> Permutation n 78 | invert Nil = Nil 79 | invert p@(i :* is) = index (i' p) (indices p) :* delete (i' p) p 80 | where 81 | i' : Permutation n -> Fin n 82 | i' p = index i (indices p) 83 | 84 | export 85 | implementation {n : Nat} -> Semigroup (Permutation n) where 86 | (<+>) = compose 87 | 88 | export 89 | implementation {n : Nat} -> Monoid (Permutation n) where 90 | neutral = id 91 | 92 | export 93 | implementation {n : Nat} -> Group (Permutation n) where 94 | inverse = invert 95 | -------------------------------------------------------------------------------- /Data/Group.idr: -------------------------------------------------------------------------------- 1 | module Data.Group 2 | 3 | import Data.Stream 4 | 5 | ||| This extends 'Monoid' by defining an inverse for every element. 6 | public export 7 | interface (Monoid t) => Group t where 8 | inverse : t -> t 9 | 10 | ||| Stream of elements starting at some given element. 11 | public export 12 | generate : (Monoid g) => g -> Stream g 13 | generate g1 = neutral :: map (<+> g1) (generate g1) 14 | 15 | ||| (Positive) integer exponentiation. 16 | public export 17 | exp : (Monoid g) => (n : Nat) -> g -> g 18 | exp n g = Prelude.head (drop n (generate g)) 19 | 20 | ||| Whether a group element is idempotent 21 | public export 22 | total 23 | idempotent : (Eq g, Semigroup g) => g -> Bool 24 | idempotent x = x == (x <+> x) 25 | 26 | ||| Commutator of two elements. 27 | public export 28 | total 29 | commutator : (Group g) => g -> g -> g 30 | commutator a b = inverse a <+> inverse b <+> a <+> b 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Vanessa McHale (c) 2017 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build install 2 | 3 | build: 4 | idris2 --build permutations.ipkg 5 | 6 | install: 7 | idris2 --install permutations.ipkg 8 | 9 | docs: 10 | rm -rf docs 11 | idris2 --mkdoc permutations.ipkg 12 | mv build/docs/ . 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # permutations 2 | 3 | This is a library providing a type-safe implementation of permutations. 4 | 5 | ## Installation 6 | 7 | ```bash 8 | $ idris --install permutations.ipkg 9 | ``` 10 | 11 | ## Use 12 | 13 | ### Tips 14 | 15 | The most useful thing this library provides is a `Group` instance for 16 | permutations. You can multiply two elements with `<+>`, invert with `inverse`, 17 | an so on. 18 | 19 | #### Notation 20 | 21 | The `Show` instance for `Permutation` uses cycle notation. You can read more 22 | [here](http://dlmf.nist.gov/26.13) if you find it confusing. 23 | 24 | ### Documentation 25 | 26 | [Documentation](https://vmchale.github.io/permutations/index.html). 27 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # Bugs 2 | - [ ] Pretty-printer fails for `n >= 10`. 3 | # Features 4 | - [ ] Parse cycle notation. 5 | - [ ] `Control.Permutation.Arity` lacks sufficient generality. 6 | # Performance 7 | - [ ] `inverse` is really slow right now. 8 | # Code Maintenance 9 | - [ ] `head` with a hole is horrible. 10 | -------------------------------------------------------------------------------- /Test/Spec.idr: -------------------------------------------------------------------------------- 1 | module Test.Spec 2 | 3 | import Specdris.Spec 4 | import Control.Permutation 5 | import Data.Vect 6 | 7 | export 8 | specSuite : IO () 9 | specSuite = 10 | spec $ do 11 | describe "circulate" $ do 12 | it "should work (1/2)" $ do 13 | show circ `shouldBe` "(01234)" 14 | it "should work (2/2)" $ do 15 | sigma circulate [0, 1, 2, 3, 4] `shouldBe` [1, 2, 3, 4, 0] 16 | describe "isEven" $ do 17 | it "should work" $ do 18 | map isEven ps `shouldBe` [False, True] 19 | it "should work with exp" $ do 20 | map (isEven . exp 2) ps `shouldBe` [True, True] 21 | describe "trivial" $ do 22 | it "should permute a vector" $ 23 | toVector trivial `shouldBe` [0, 3, 2, 1] 24 | it "work on reversed" $ 25 | toVector reverse `shouldBe` [3, 2, 1, 0] 26 | describe "cycle precursor" $ do 27 | it "should give a fixNat function" $ 28 | fixNat trivial 1 `shouldBe` 3 29 | it "should give a orbit function" $ 30 | finOrbit trivial 1 `shouldBe` [1, 3] 31 | describe "show" $ do 32 | it "should pretty-print for n < 10" $ do 33 | show trivial `shouldBe` "(13)" 34 | describe "compose" $ do 35 | it "should compose nicely (1/2)" $ do 36 | toVector (trivial <+> disjoint) `shouldBe` [2, 3, 0, 1] 37 | it "should compose nicely (2/2)" $ do 38 | show (trivial <+> swap) `shouldBe` "(02)(13)" 39 | describe "invert" $ do 40 | it "should invert a permutation" $ 41 | inverse trivial `shouldBe` trivial 42 | it "should satisfy x⁻¹x=e" $ 43 | inverse trivial <+> trivial `shouldBe` neutral 44 | describe "issue #2" $ do 45 | it "should hold" $ 46 | neutral <+> circSmall `shouldBe` circSmall 47 | 48 | -- TODO property test: composing disjoint swaps should commute! 49 | -- Also associativity. or better yet proofs? 50 | where trivial : Permutation 4 51 | trivial = pi (FS 0) (FS 2) 52 | disjoint : Permutation 4 53 | disjoint = pi (FZ) (FS 1) 54 | big : Permutation 11 55 | big = pi (FS 0) (FS 9) 56 | swap : Permutation 4 57 | swap = pi FZ (FS 1) 58 | ps : Vect 2 (Permutation 2) 59 | ps = enumerateStrict 60 | circSmall : Permutation 3 61 | circSmall = circulate 62 | x : Permutation 3 63 | x = pi FZ (FS 1) 64 | circ : Permutation 5 65 | circ = circulate 66 | -------------------------------------------------------------------------------- /docs/alternative.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | margin: 0; 4 | padding: 0; 5 | border: 0; 6 | height: 100%; 7 | font-family: "Trebuchet MS", Helvetica, sans-serif; 8 | font-size: 11pt; 9 | background-color: #fff; 10 | } 11 | 12 | a, 13 | a:active, 14 | a:visited { 15 | text-decoration: none; 16 | color: inherit; 17 | } 18 | 19 | a:hover { 20 | text-decoration: underline; 21 | } 22 | 23 | header { 24 | padding: 5px 11px; 25 | border-bottom: 3px solid #659fdb; 26 | box-shadow: 0 -8px 22px 0; 27 | background-color: #252525; 28 | color: white; 29 | font-size: 9pt; 30 | } 31 | 32 | .wrapper { 33 | min-height: 100%; 34 | } 35 | 36 | header nav, 37 | header strong { 38 | font-size: 11pt; 39 | } 40 | 41 | header nav { 42 | float: right; 43 | } 44 | 45 | footer { 46 | height: 30px; 47 | width: 100%; 48 | border-top: 1px solid #aaa; 49 | margin-top: -31px; 50 | text-align: center; 51 | color: #666; 52 | line-height: 30px; 53 | font-size: 9pt; 54 | background: none repeat scroll 0 0 #ddd; 55 | } 56 | 57 | .container { 58 | padding: 10px 10px 41px 20px; 59 | } 60 | 61 | h1 { 62 | margin: 0; 63 | margin-bottom: 5px; 64 | font-size: 14pt; 65 | font-family: "Trebuchet MS", Helvetica, sans-serif; 66 | } 67 | 68 | #moduleHeader { 69 | border-bottom: 1px solid #bbb; 70 | padding-bottom: 2px; 71 | } 72 | 73 | ul { 74 | list-style-type: none; 75 | margin: 0; 76 | padding: 0; 77 | } 78 | 79 | hr { 80 | margin: 0; 81 | padding: 0; 82 | border: 0; 83 | border-bottom: 1px solid #bbb; 84 | } 85 | 86 | p { 87 | margin: 0; 88 | padding: 0; 89 | } 90 | 91 | pre { 92 | display: inline; 93 | margin: 0; 94 | padding: 0; 95 | } 96 | 97 | .code { 98 | font-family: "Lucida Console", Monaco, monospace; 99 | font-size: 10pt; 100 | } 101 | 102 | .decls { 103 | margin-top: 5px; 104 | } 105 | 106 | .decls > dt { 107 | font-family: "Lucida Console", Monaco, monospace; 108 | font-size: 10pt; 109 | line-height: 20px; 110 | padding: 2px 6px; 111 | border: 1px solid #ccc; 112 | background-color: #f0f0f0; 113 | display: table; 114 | width: 100%; 115 | box-sizing: border-box; 116 | white-space: pre-wrap; 117 | } 118 | 119 | .decls > dd { 120 | margin: 10px 0 20px 20px; 121 | font-family: Arial, sans-serif; 122 | font-size: 10pt; 123 | } 124 | 125 | .decls > dd > p { 126 | margin-bottom: 8px; 127 | } 128 | 129 | .decls > dd > dl:not(.decls):not(:first-child) { 130 | padding-top: 5px; 131 | border-top: 1px solid #eee; 132 | } 133 | 134 | .decls > dd > dl:not(.decls) > dt { 135 | display: block; 136 | min-width: 70px; 137 | float: left; 138 | font-weight: bold; 139 | } 140 | 141 | .decls > dd > dl:not(.decls) > dd { 142 | margin-bottom: 2px; 143 | } 144 | 145 | .fixity { 146 | font-style: italic; 147 | font-weight: normal !important; 148 | } 149 | 150 | dd.fixity { 151 | cursor: default; 152 | } 153 | 154 | .word { 155 | display: table-cell; 156 | white-space: nowrap; 157 | width: 0; 158 | } 159 | 160 | .signature { 161 | display: table-cell; 162 | width: 100%; 163 | } 164 | 165 | .name { 166 | white-space: nowrap; 167 | width: 0; 168 | } 169 | 170 | .documented, 171 | .name { 172 | cursor: default; 173 | } 174 | 175 | .documented { 176 | font-weight: bold; 177 | } 178 | 179 | /* The following colours are taken from the conservative 8 color palette given 180 | in http://mkweb.bcgsc.ca/colorblind/palettes.mhtml 181 | */ 182 | 183 | a.function { 184 | color: rgb(53, 155, 115); 185 | } 186 | 187 | .function { 188 | color: rgb(53, 155, 115); 189 | } 190 | 191 | a.constructor { 192 | color: rgb(213, 94, 0); 193 | } 194 | 195 | .constructor { 196 | color: rgb(213, 94, 0); 197 | } 198 | 199 | a.type { 200 | color: rgb(61, 183, 233); 201 | } 202 | 203 | .type { 204 | color: rgb(61, 183, 233); 205 | } 206 | 207 | .keyword { 208 | color: inherit; 209 | } 210 | 211 | .boundvar { 212 | color: rgb(247, 72, 165); /* Too much colour makes it hard to differ the rest of the colours */ 213 | color: inherit; 214 | } 215 | 216 | .boundvar.implicit { 217 | text-decoration: underline; 218 | } 219 | 220 | ul.names { 221 | border: 1px solid #666; 222 | } 223 | 224 | ul.names li { 225 | padding-left: 5px; 226 | } 227 | 228 | ul.names li a { 229 | display: inline-block; 230 | width: 100%; 231 | padding: 2px 0; 232 | } 233 | 234 | ul.names li:nth-child(odd) { 235 | background-color: #eeeeef; 236 | } 237 | 238 | ul.names li:nth-child(even) { 239 | background-color: white; 240 | } 241 | 242 | body.index .container a:visited { 243 | color: #666; 244 | } 245 | 246 | body.index .container a:hover { 247 | color: #04819e; 248 | } 249 | -------------------------------------------------------------------------------- /docs/blackandwhite.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | margin: 0; 4 | padding: 0; 5 | border: 0; 6 | height: 100%; 7 | font-family: "Trebuchet MS", Helvetica, sans-serif; 8 | font-size: 11pt; 9 | background-color: #fff; 10 | } 11 | 12 | a, 13 | a:active, 14 | a:visited { 15 | text-decoration: none; 16 | color: inherit; 17 | } 18 | 19 | a:hover { 20 | text-decoration: underline; 21 | } 22 | 23 | header { 24 | padding: 5px 11px; 25 | border-bottom: 3px solid #659fdb; 26 | box-shadow: 0 -8px 22px 0; 27 | background-color: #252525; 28 | color: white; 29 | font-size: 9pt; 30 | } 31 | 32 | .wrapper { 33 | min-height: 100%; 34 | } 35 | 36 | header nav, 37 | header strong { 38 | font-size: 11pt; 39 | } 40 | 41 | header nav { 42 | float: right; 43 | } 44 | 45 | footer { 46 | height: 30px; 47 | width: 100%; 48 | border-top: 1px solid #aaa; 49 | margin-top: -31px; 50 | text-align: center; 51 | color: #666; 52 | line-height: 30px; 53 | font-size: 9pt; 54 | background: none repeat scroll 0 0 #ddd; 55 | } 56 | 57 | .container { 58 | padding: 10px 10px 41px 20px; 59 | } 60 | 61 | h1 { 62 | margin: 0; 63 | margin-bottom: 5px; 64 | font-size: 14pt; 65 | font-family: "Trebuchet MS", Helvetica, sans-serif; 66 | } 67 | 68 | #moduleHeader { 69 | border-bottom: 1px solid #bbb; 70 | padding-bottom: 2px; 71 | } 72 | 73 | ul { 74 | list-style-type: none; 75 | margin: 0; 76 | padding: 0; 77 | } 78 | 79 | hr { 80 | margin: 0; 81 | padding: 0; 82 | border: 0; 83 | border-bottom: 1px solid #bbb; 84 | } 85 | 86 | p { 87 | margin: 0; 88 | padding: 0; 89 | } 90 | 91 | pre { 92 | display: inline; 93 | margin: 0; 94 | padding: 0; 95 | } 96 | 97 | .code { 98 | font-family: "Lucida Console", Monaco, monospace; 99 | font-size: 10pt; 100 | } 101 | 102 | .decls { 103 | margin-top: 5px; 104 | } 105 | 106 | .decls > dt { 107 | font-family: "Lucida Console", Monaco, monospace; 108 | font-size: 10pt; 109 | line-height: 20px; 110 | padding: 2px 6px; 111 | border: 1px solid #ccc; 112 | background-color: #f0f0f0; 113 | display: table; 114 | width: 100%; 115 | box-sizing: border-box; 116 | white-space: pre-wrap; 117 | } 118 | 119 | .decls > dd { 120 | margin: 10px 0 20px 20px; 121 | font-family: Arial, sans-serif; 122 | font-size: 10pt; 123 | } 124 | 125 | .decls > dd > p { 126 | margin-bottom: 8px; 127 | } 128 | 129 | .decls > dd > dl:not(.decls):not(:first-child) { 130 | padding-top: 5px; 131 | border-top: 1px solid #eee; 132 | } 133 | 134 | .decls > dd > dl:not(.decls) > dt { 135 | display: block; 136 | min-width: 70px; 137 | float: left; 138 | font-weight: bold; 139 | } 140 | 141 | .decls > dd > dl:not(.decls) > dd { 142 | margin-bottom: 2px; 143 | } 144 | 145 | .fixity { 146 | font-style: italic; 147 | font-weight: normal !important; 148 | } 149 | 150 | dd.fixity { 151 | cursor: default; 152 | } 153 | 154 | .word { 155 | display: table-cell; 156 | white-space: nowrap; 157 | width: 0; 158 | } 159 | 160 | .signature { 161 | display: table-cell; 162 | width: 100%; 163 | } 164 | 165 | .name { 166 | white-space: nowrap; 167 | width: 0; 168 | } 169 | 170 | .documented, 171 | .name { 172 | cursor: default; 173 | font-weight: normal; 174 | font-style: normal; 175 | font-variant: normal; 176 | } 177 | 178 | .documented { 179 | font-weight: bold; 180 | } 181 | 182 | a.function { 183 | font-style: italic; 184 | } 185 | 186 | .function { 187 | font-style: italic; 188 | } 189 | 190 | a.constructor { 191 | font-weight: bold; 192 | } 193 | 194 | .constructor { 195 | font-weight: bold; 196 | } 197 | 198 | a.type { 199 | font-variant: small-caps !important; 200 | } 201 | 202 | .type { 203 | font-variant: small-caps !important; 204 | } 205 | 206 | .keyword { 207 | text-decoration: underline; 208 | color: inherit; 209 | } 210 | 211 | .boundvar { 212 | color: #bf30bf; /* Too much colour makes it hard to differ the rest of the colours */ 213 | color: inherit; 214 | } 215 | 216 | .boundvar.implicit { 217 | text-decoration: underline; 218 | } 219 | 220 | ul.names { 221 | border: 1px solid #666; 222 | } 223 | 224 | ul.names li { 225 | padding-left: 5px; 226 | } 227 | 228 | ul.names li a { 229 | display: inline-block; 230 | width: 100%; 231 | padding: 2px 0; 232 | } 233 | 234 | ul.names li:nth-child(odd) { 235 | background-color: #eeeeef; 236 | } 237 | 238 | ul.names li:nth-child(even) { 239 | background-color: white; 240 | } 241 | 242 | body.index .container a:visited { 243 | color: #666; 244 | } 245 | 246 | body.index .container a:hover { 247 | color: #04819e; 248 | } 249 | -------------------------------------------------------------------------------- /docs/default.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | margin: 0; 4 | padding: 0; 5 | border: 0; 6 | height: 100%; 7 | font-family: "Trebuchet MS", Helvetica, sans-serif; 8 | font-size: 11pt; 9 | background-color: #fff; 10 | } 11 | 12 | a, 13 | a:active, 14 | a:visited { 15 | text-decoration: none; 16 | color: inherit; 17 | } 18 | 19 | a:hover { 20 | text-decoration: underline; 21 | } 22 | 23 | header { 24 | padding: 5px 11px; 25 | border-bottom: 3px solid #659fdb; 26 | box-shadow: 0 -8px 22px 0; 27 | background-color: #252525; 28 | color: white; 29 | font-size: 9pt; 30 | } 31 | 32 | .wrapper { 33 | min-height: 100%; 34 | } 35 | 36 | header nav, 37 | header strong { 38 | font-size: 11pt; 39 | } 40 | 41 | header nav { 42 | float: right; 43 | } 44 | 45 | footer { 46 | height: 30px; 47 | width: 100%; 48 | border-top: 1px solid #aaa; 49 | margin-top: -31px; 50 | text-align: center; 51 | color: #666; 52 | line-height: 30px; 53 | font-size: 9pt; 54 | background: none repeat scroll 0 0 #ddd; 55 | } 56 | 57 | .container { 58 | padding: 10px 10px 41px 20px; 59 | } 60 | 61 | h1 { 62 | margin: 0; 63 | margin-bottom: 5px; 64 | font-size: 14pt; 65 | font-family: "Trebuchet MS", Helvetica, sans-serif; 66 | } 67 | 68 | #moduleHeader { 69 | border-bottom: 1px solid #bbb; 70 | padding-bottom: 2px; 71 | } 72 | 73 | ul { 74 | list-style-type: none; 75 | margin: 0; 76 | padding: 0; 77 | } 78 | 79 | hr { 80 | margin: 0; 81 | padding: 0; 82 | border: 0; 83 | border-bottom: 1px solid #bbb; 84 | } 85 | 86 | p { 87 | margin: 0; 88 | padding: 0; 89 | } 90 | 91 | pre { 92 | display: inline; 93 | margin: 0; 94 | padding: 0; 95 | } 96 | 97 | .code { 98 | font-family: "Lucida Console", Monaco, monospace; 99 | font-size: 10pt; 100 | } 101 | 102 | .decls { 103 | margin-top: 5px; 104 | } 105 | 106 | .decls > dt { 107 | font-family: "Lucida Console", Monaco, monospace; 108 | font-size: 10pt; 109 | line-height: 20px; 110 | padding: 2px 6px; 111 | border: 1px solid #ccc; 112 | background-color: #f0f0f0; 113 | display: table; 114 | width: 100%; 115 | box-sizing: border-box; 116 | white-space: pre-wrap; 117 | } 118 | 119 | .decls > dd { 120 | margin: 10px 0 20px 20px; 121 | font-family: Arial, sans-serif; 122 | font-size: 10pt; 123 | } 124 | 125 | .decls > dd > p { 126 | margin-bottom: 8px; 127 | } 128 | 129 | .decls > dd > dl:not(.decls):not(:first-child) { 130 | padding-top: 5px; 131 | border-top: 1px solid #eee; 132 | } 133 | 134 | .decls > dd > dl:not(.decls) > dt { 135 | display: block; 136 | min-width: 70px; 137 | float: left; 138 | font-weight: bold; 139 | } 140 | 141 | .decls > dd > dl:not(.decls) > dd { 142 | margin-bottom: 2px; 143 | } 144 | 145 | .fixity { 146 | font-style: italic; 147 | font-weight: normal !important; 148 | } 149 | 150 | dd.fixity { 151 | cursor: default; 152 | } 153 | 154 | .word { 155 | display: table-cell; 156 | white-space: nowrap; 157 | width: 0; 158 | } 159 | 160 | .signature { 161 | display: table-cell; 162 | width: 100%; 163 | } 164 | 165 | .name { 166 | white-space: nowrap; 167 | width: 0; 168 | } 169 | 170 | .documented, 171 | .name { 172 | cursor: default; 173 | } 174 | 175 | .documented { 176 | font-weight: bold; 177 | } 178 | 179 | a.function { 180 | color: #00ba00; 181 | } 182 | 183 | .function { 184 | color: #007c21; 185 | } 186 | 187 | a.constructor { 188 | color: #f00; 189 | } 190 | 191 | .constructor { 192 | color: #bf3030; 193 | } 194 | 195 | a.type { 196 | color: #00f; 197 | } 198 | 199 | .type { 200 | color: #050599; 201 | } 202 | 203 | .keyword { 204 | color: inherit; 205 | } 206 | 207 | .boundvar { 208 | color: #bf30bf; /* Too much colour makes it hard to differ the rest of the colours */ 209 | color: inherit; 210 | } 211 | 212 | .boundvar.implicit { 213 | text-decoration: underline; 214 | } 215 | 216 | ul.names { 217 | border: 1px solid #666; 218 | } 219 | 220 | ul.names li { 221 | padding-left: 5px; 222 | } 223 | 224 | ul.names li a { 225 | display: inline-block; 226 | width: 100%; 227 | padding: 2px 0; 228 | } 229 | 230 | ul.names li:nth-child(odd) { 231 | background-color: #eeeeef; 232 | } 233 | 234 | ul.names li:nth-child(even) { 235 | background-color: white; 236 | } 237 | 238 | body.index .container a:visited { 239 | color: #666; 240 | } 241 | 242 | body.index .container a:hover { 243 | color: #04819e; 244 | } 245 | -------------------------------------------------------------------------------- /docs/docs/Control.Permutation.Mod.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Control.Permutation.Mod 5 | 6 | 33 | 34 | 35 |
36 | Idris2Doc : Control.Permutation.Mod 37 | 45 | 57 |
58 |

Control.Permutation.Mod

circulate : Permutationn
  For S_4, (1234)

Totality: total
cycles : Permutation (Sn) -> List (List (Fin (Sn)))
  Return a list of disjoint cycles given a permutation. We use this for our
pretty-printer.

Totality: total
enumerateStrict : Vect (factorialn) (Permutationn)
  All permutations of a certain order.

Totality: total
factorial : Nat -> Nat
Totality: total
isEven : Permutationn -> Bool
  Test whether a permutation is even.

Totality: total
order : Permutation (Sn) -> Nat
Totality: total
piPerm : Finn -> Finn -> Permutationn
  The permutation π_ij

Totality: total
swaps : Permutationn -> List (Permutationn)
  Factors a permutation into a product of swaps.

Totality: total
-------------------------------------------------------------------------------- /docs/docs/Control.Permutation.Proofs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Control.Permutation.Proofs 5 | 6 | 33 | 34 | 35 |
36 | Idris2Doc : Control.Permutation.Proofs 37 | 45 | 57 |
58 |

Control.Permutation.Proofs

factorialIncr : (n : Nat) -> LTE (factorialn) (factorial (Sn))
  Proof that (n + 1)! >= n!

factorialLTE : (n : Nat) -> LTE1 (factorialn)
  Proof that n! >= 1

-------------------------------------------------------------------------------- /docs/docs/Control.Permutation.Types.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Control.Permutation.Types 5 | 6 | 33 | 34 | 35 |
36 | Idris2Doc : Control.Permutation.Types 37 | 45 | 57 |
58 |

Control.Permutation.Types

dataPermutation : Nat -> Type
  This is something like `Vector k a`, except we restrict ourselves to only 1,...,n for `Permutation n`.

Totality: total
Constructors:
Nil : Permutation0
(:*) : Fin (Sn) -> Permutationn -> Permutation (Sn)
debug : Permutationn -> String
Totality: total
invert : Permutationn -> Permutationn
Totality: total
toVector : Permutationn -> Vectn (Finn)
Totality: total
-------------------------------------------------------------------------------- /docs/docs/Control.Permutation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Control.Permutation 5 | 6 | 33 | 34 | 35 |
36 | Idris2Doc : Control.Permutation 37 | 45 | 57 |
58 |

Control.Permutation

-------------------------------------------------------------------------------- /docs/docs/Data.Group.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Data.Group 5 | 6 | 33 | 34 | 35 |
36 | Idris2Doc : Data.Group 37 | 45 | 57 |
58 |

Data.Group

interfaceGroup : Type -> Type
  This extends 'Monoid' by defining an inverse for every element.

Parameters: t
Constraints: Monoid t
Methods:
inverse : t -> t

Implementation: 
Group (Permutationn)
commutator : Groupg => g -> g -> g
  Commutator of two elements.

Totality: total
exp : Monoidg => Nat -> g -> g
  (Positive) integer exponentiation.

generate : Monoidg => g -> Streamg
  Stream of elements starting at some given element.

idempotent : (Eqg, Semigroupg) => g -> Bool
  Whether a group element is idempotent

Totality: total
inverse : Groupt => t -> t
-------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | permutations 5 | 6 | 33 | 34 | 35 |
36 | Idris2Doc : permutations 37 | 45 | 57 |
58 |

Package permutations - Namespaces

-------------------------------------------------------------------------------- /permutations.ipkg: -------------------------------------------------------------------------------- 1 | package permutations 2 | 3 | modules = Control.Permutation, 4 | Control.Permutation.Types, 5 | Control.Permutation.Mod, 6 | Control.Permutation.Proofs, 7 | Data.Group 8 | 9 | depends = base, prelude 10 | -------------------------------------------------------------------------------- /test.ipkg: -------------------------------------------------------------------------------- 1 | package permutations 2 | 3 | sourceloc = git://git@github.com:vmchale/permutations.git 4 | bugtracker = http://www.github.com/vmchale/permutations/issues 5 | 6 | pkgs = specdris 7 | , contrib 8 | 9 | modules = Control.Permutation.Types 10 | , Control.Permutation 11 | , Control.Permutation.Proofs 12 | , Data.Group 13 | , Test.Spec 14 | 15 | tests = Test.Spec.specSuite 16 | --------------------------------------------------------------------------------