{-# LANGUAGE GeneralizedNewtypeDeriving,ScopedTypeVariables #-} module Weyl where import Control.Applicative ((<$>)) import Control.Monad (replicateM) import Control.Monad.Random (Random(random),evalRandIO,RandomGen,MonadRandom,Rand,StdGen,runRand,getRandom,getRandomR) import Data.List (sort,foldl') import qualified Data.Set as Set import Prelude hiding ((*),Rational,signum) import qualified Algebra.Additive import qualified Algebra.Module import qualified Algebra.Ring import qualified MathObj.Matrix as Matrix import qualified Number.Ratio import NumericPrelude ((*),(*>),Rational,(%),signum,numerator,denominator) -- A value of type 'G' is an element of the Weyl group. newtype G = G { unG :: Matrix.T (Number.Ratio.T Int) } deriving (Eq,Ord,Algebra.Additive.C,Algebra.Ring.C) instance Show G where show = Matrix.format . unG identity :: G identity = G $ Matrix.one 8 hadamard :: G hadamard = G $ (1 % (2 :: Int)) *> Matrix.fromRows 8 8 [ [ 1, 1, 1, 1] ++ [ 0, 0, 0, 0] , [ 1,-1, 1,-1] ++ [ 0, 0, 0, 0] , [ 1, 1,-1,-1] ++ [ 0, 0, 0, 0] , [ 1,-1,-1, 1] ++ [ 0, 0, 0, 0] , [ 0, 0, 0, 0] ++ [ 1, 1, 1, 1] , [ 0, 0, 0, 0] ++ [ 1,-1, 1,-1] , [ 0, 0, 0, 0] ++ [ 1, 1,-1,-1] , [ 0, 0, 0, 0] ++ [ 1,-1,-1, 1] ] instance Random G where random = runRand $ iter identity where iter x = do again <- getRandom if again then do r1 : rs <- permute . Matrix.rows . unG $ x signs <- replicateM 7 $ getRandomR (0,1) let s1 = sum signs :: Int iter $ (hadamard *) . G . Matrix.fromRows 8 8 $ (((-1) ^ s1 % (1 :: Int)) *> r1) : zipWith (\ s r -> ((-1) ^ s % (1 :: Int)) *> r) signs rs else return x -- H acts from the left on the elements of a (right) coset, by permuting and -- sign-changing the rows of the matrix. To normalise a matrix, first permute -- the rows, such that, after taking the lex-absolute value of each, they -- appear lex-nondecreasing in the matrix; after that flip the sign of any row -- but the first that is lex-negative, and flip the sign of the first row, if -- one would otherwise have changed an odd number of signs. normalise :: G -> G normalise = G . Matrix.fromRows 8 8 . changeSigns . sort' . Matrix.rows . unG where sort' = map snd . sort . map (\ x -> (sign x *> x,x)) changeSigns (r1 : rs) = case unzip . map (\ r -> let s = sign r in (s *> r,s)) $ rs of (rs',signs) -> foldl' (*) 1 signs *> r1 : rs' sign = signum . head . dropWhile (== 0) representatives :: forall m. (MonadRandom m,Functor m) => m [G] representatives = Set.toList <$> go (Set.singleton $ normalise identity) where go :: Set.Set G -> m (Set.Set G) go s = if Set.size s == 135 then return s else do g <- getRandom go $ Set.insert (normalise g) s main :: IO () main = do rs <- evalRandIO representatives mapM_ (putStrLn . Matrix.format . fmap (\ x -> 4 * numerator x `div` denominator x) . unG) rs -- Random permutation type RandomList g a = Rand g [a] empty :: RandomList g a empty = return [] singleton :: a -> RandomList g a singleton x = return [x] merge :: (RandomGen g) => RandomList g a -> RandomList g a -> RandomList g a merge rxs rys = do xs <- rxs ys <- rys merge' (length xs, xs) (length ys, ys) where merge' (0 , []) (_ , ys) = return ys merge' (_ , xs) (0 , []) = return xs merge' (nx, x:xs) (ny, y:ys) = do k <- getRandomR (1,nx+ny) if k <= nx then (x:) <$> ((nx-1, xs) `merge'` (ny, y:ys)) else (y:) <$> ((nx, x:xs) `merge'` (ny-1, ys)) permute :: (RandomGen g) => [a] -> RandomList g a permute = fromList where fromList [] = empty fromList [x] = singleton x fromList xs = (fromList l) `merge` (fromList r) where (l,r) = splitAt (length xs `div` 2) xs