combinat-0.2.8.2: test/Tests/Braid.hs
-- | Tests for braids.
{-# LANGUAGE
CPP, BangPatterns,
ScopedTypeVariables, ExistentialQuantification,
DataKinds, KindSignatures, Rank2Types,
TypeOperators, TypeFamilies,
StandaloneDeriving #-}
module Tests.Braid where
--------------------------------------------------------------------------------
import Math.Combinat.Groups.Braid
import Math.Combinat.Groups.Braid.NF
import Tests.Permutations () -- arbitrary instance
import Tests.Common
import Test.Framework
import Test.Framework.Providers.QuickCheck2
import Test.QuickCheck
import Test.QuickCheck.Gen
import Data.Proxy
import GHC.TypeLits
import Control.Monad
import Data.List ( mapAccumL , foldl' )
import Data.Array.Unboxed
import Data.Array.ST
import Data.Array.IArray
import Data.Array.MArray
import Data.Array.Unsafe
import Data.Array.Base
import Control.Monad.ST
import System.Random
import Math.Combinat.Sign
import Math.Combinat.Helper
import Math.Combinat.TypeLevel
import Math.Combinat.Numbers.Series
import Math.Combinat.Permutations ( Permutation(..) )
import qualified Math.Combinat.Permutations as P
--------------------------------------------------------------------------------
-- * Types and instances
maxBraidWordLen :: Int
maxBraidWordLen = 600
maxStrands :: Int
maxStrands = 18 -- normal forms are very slow for large ones
shrinkBraid :: KnownNat n => Braid n -> [Braid n]
shrinkBraid (Braid gens) = map Braid list where
len = length gens
list = [ take i gens ++ drop (i+1) gens | i<-[0..len-1] ]
-- someRndBraid :: Int -> (forall (n :: Nat). KnownNat n => g -> (Braid n, g)) -> g -> (SomeBraid, g)
-- someRndBraid n f = \g -> let (x,g') = f g in (someBraid n x, g')
-- | equality as /braid words/
(=:=) :: Braid n -> Braid n -> Bool
(=:=) (Braid gens1) (Braid gens2) = (gens1 == gens2)
data UnreducedBraid = forall n. KnownNat n => Unreduced (Braid n)
data ReducedBraid = forall n. KnownNat n => Reduced (Braid n)
data PositiveBraid = forall n. KnownNat n => PositiveB (Braid n)
data PerturbedBraid = forall n. KnownNat n => Perturbed (Braid n) (Braid n)
data PermutationBraid = forall n. KnownNat n => PermBraid Permutation (Braid n)
data TwoBraids = forall n. KnownNat n => TwoBraids (Braid n) (Braid n)
deriving instance Show UnreducedBraid
deriving instance Show ReducedBraid
deriving instance Show PositiveBraid
deriving instance Show PerturbedBraid
deriving instance Show PermutationBraid
deriving instance Show TwoBraids
instance KnownNat n => Random (Braid n) where
randomR _ = random
random g0 = (b, g2) where
n = numberOfStrands b
(l,g1) = randomR (0,maxBraidWordLen) g0
(b,g2) = randomBraidWord l g1
instance Random UnreducedBraid where
randomR _ = random
random = runRand $ do
n <- randChoose (2,maxStrands)
l <- randChoose (0,maxBraidWordLen)
withSelectedM Unreduced (rand $ randomBraidWord l) n
instance Random PositiveBraid where
randomR _ = random
random = runRand $ do
n <- randChoose (2,maxStrands)
l <- randChoose (0,maxBraidWordLen)
withSelectedM PositiveB (rand $ randomPositiveBraidWord l) n
instance Random PerturbedBraid where
randomR _ = random
random = runRand $ do
Unreduced b <- rand random
k <- randChoose (20,1000)
c <- rand $ randomPerturbBraidWord k b
return (Perturbed b c)
instance KnownNat n => Arbitrary (Braid n) where
arbitrary = choose_
shrink = shrinkBraid
instance Arbitrary UnreducedBraid where
arbitrary = choose_
shrink (Unreduced b) = map Unreduced (shrinkBraid b)
instance Arbitrary PositiveBraid where
arbitrary = choose_
shrink (PositiveB b) = map PositiveB (shrinkBraid b)
instance Arbitrary ReducedBraid where
arbitrary = do
Unreduced braid <- arbitrary
return $ Reduced $ freeReduceBraidWord braid
instance Arbitrary PerturbedBraid where
arbitrary = choose_
shrink _ = []
instance Arbitrary TwoBraids where
shrink _ = []
arbitrary = do
n <- choose (2::Int, maxStrands)
let snat = case someNatVal (fromIntegral n :: Integer) of
Just sn -> sn
Nothing -> error "TwoBraids/arbitrary: shouldn't happen"
case snat of
SomeNat pxy -> do
(braid1,braid2) <- choosePair_
return $ TwoBraids (asProxyTypeOf1 braid1 pxy) (asProxyTypeOf1 braid2 pxy)
mkPermBraid :: Permutation -> PermutationBraid
mkPermBraid perm =
case snat of
SomeNat pxy -> PermBraid perm (asProxyTypeOf1 (permutationBraid perm) pxy)
where
n = P.permutationSize perm
Just snat = someNatVal (fromIntegral n :: Integer)
instance Arbitrary PermutationBraid where
arbitrary = do
perm <- arbitrary
return $ mkPermBraid perm
shrink (PermBraid x b) = [ PermBraid (braidPermutation s) s | s <- shrinkBraid b ]
--------------------------------------------------------------------------------
-- * test groups
testgroup_Braid :: Test
testgroup_Braid = testGroup "Braid"
[ testProperty "linking matrix is invariant of reduction" prop_link_reduce
, testProperty "linking matrix is invariant of perturbation" prop_link_perturb
, testProperty "tau^2 = identity" prop_tau_square
, testProperty "tau commutes with braidPermutation" prop_permTau_1
, testProperty "braidPermutation . permutationBraid = identity" prop_permBraid_perm
, testProperty "permutation braid is indeed a permutation braid" prop_permBraid_valid
, testProperty "multiplication commutes with braidPermutation" prop_braidPerm_comp
, testProperty "positive braids have positive links" prop_link_positive
, testProperty "definition of linking" prop_linking
]
--------------------------------------------------------------------------------
testgroup_Braid_NF :: Test
testgroup_Braid_NF = testGroup "Braid/NF"
[ testProperty "NF with naive inverse elimination == less naive inverse elimination" prop_braidnf_naive
, testProperty "NF with reduction == NF without reduction" prop_braidnf_reduce
, testProperty "NF = NF of representative word of NF" prop_braidnf_reprs
, testProperty "NF = NF of perturbed word" prop_braidnf_perturb
, testProperty "linking of word == linking of representative of NF" prop_braidnf_link
, testProperty "NF of positive word is positive" prop_braidnf_pos
, testProperty "Lemma 2.5" prop_lemma_2_5
, testProperty "permutationBraid and tau commutes, up to NF" prop_permTau_2
]
--------------------------------------------------------------------------------
-- * braid properties
prop_link_reduce :: UnreducedBraid -> Bool
prop_link_reduce (Unreduced braid) = linkingMatrix braid == linkingMatrix braid' where
braid' = freeReduceBraidWord braid
prop_link_perturb :: PerturbedBraid -> Bool
prop_link_perturb (Perturbed braid1 braid2) = linkingMatrix braid1 == linkingMatrix braid2
prop_tau_square :: ReducedBraid -> Bool
prop_tau_square (Reduced braid) = braidWord (tau (tau braid)) == braidWord braid
prop_permTau_1 :: PermutationBraid -> Bool
prop_permTau_1 (PermBraid perm braid) = tauPerm perm == braidPermutation (tau braid)
prop_permBraid_perm :: PermutationBraid -> Bool
prop_permBraid_perm (PermBraid perm braid) = (braidPermutation braid == perm)
prop_permBraid_valid :: PermutationBraid -> Bool
prop_permBraid_valid (PermBraid perm braid) = isPermutationBraid braid
prop_braidPerm_comp :: TwoBraids -> Bool
prop_braidPerm_comp (TwoBraids b1 b2) = (p == q) where
p = braidPermutation (compose b1 b2)
q = braidPermutation b1 `P.multiply` braidPermutation b2
prop_link_positive :: PositiveBraid -> Bool
prop_link_positive (PositiveB braid) = all (>=0) $ elems $ linkingMatrix braid
prop_linking :: UnreducedBraid -> Bool
prop_linking (Unreduced braid) = (linkingMatrix braid == matrix) where
n = numberOfStrands braid
matrix = array ((1,1),(n,n)) [ ((i,j),strandLinking braid i j) | i<-[1..n], j<-[1..n] ]
--------------------------------------------------------------------------------
prop_braidnf_naive :: UnreducedBraid -> Bool
prop_braidnf_naive (Unreduced braid) = (braidNormalFormNaive' braid == braidNormalForm' braid)
prop_braidnf_reduce :: UnreducedBraid -> Bool
prop_braidnf_reduce (Unreduced braid) = (braidNormalForm' braid == braidNormalForm braid)
prop_braidnf_reprs :: ReducedBraid -> Bool
prop_braidnf_reprs (Reduced braid) = (nf == nf') where
nf = braidNormalForm braid
nf' = braidNormalForm braid'
braid' = nfReprWord nf
prop_braidnf_perturb :: PerturbedBraid -> Bool
prop_braidnf_perturb (Perturbed braid1 braid2) = (braidNormalForm braid1 == braidNormalForm braid2)
prop_braidnf_link :: UnreducedBraid -> Bool
prop_braidnf_link (Unreduced braid) = (linkingMatrix braid == linkingMatrix braid') where
nf = braidNormalForm braid
braid' = nfReprWord nf
prop_braidnf_pos :: PositiveBraid -> Bool
prop_braidnf_pos (PositiveB braid) = (_nfDeltaExp (braidNormalForm braid) >= 0)
prop_lemma_2_5 :: Permutation -> Bool
prop_lemma_2_5 p = and [ check i | i<-[1..n-1] ] where
n = P.permutationSize p
w = _permutationBraid p
s = permWordStartingSet n w
check i = _isPermutationBraid n (i:w) == (not $ elem i s)
prop_permTau_2 :: PermutationBraid -> Bool
prop_permTau_2 (PermBraid perm braid) = (nf1 == nf2) where
nf1 = braidNormalForm $ permutationBraid (tauPerm perm)
nf2 = braidNormalForm $ tau braid
--------------------------------------------------------------------------------