{-| Module : Complex Description : Mod 2 vector space. Copyright : Adam Saltz License : BSD3 Maintainer : saltz.adam@gmail.com Stability : experimental Longer description to come. -} module Complex ( Generator(..), Sign(..), signToNum, AlgGen(..), wrapGen, toSet, Morphisms, addMod2, addMod2Set, addMod2Map, addToKey, fromTo ) where import Braids import Data.Set (Set) import qualified Data.Set as S import Data.Map (Map, (!)) import qualified Data.Map as M import Data.Monoid {- | A 'Generator' is a 'Set' of 'Components' labled with 'Sign's. Strictly speaking, we could make do without components, as @components = Data.Set.fromList . Data.Map.keys $ signs@. kgrade depends totally on signs, so it should be taken out too. -} data Generator = Generator { resolution :: Resolution , components :: Set Component , signs :: Map Component Sign , kgrade :: Int} deriving (Eq, Ord, Show) -- | These stand for v_+ and v_- in Khovanov homology. We could include some more algebra here, but -- | for now I don't see a reason to. data Sign = Plus | Minus deriving (Eq, Show, Ord) signToNum :: Sign -> Int signToNum Plus = 1 signToNum Minus = (-1) -- | Stands for sums of generators modulo 2. 'wrapGen' wraps a single generator. -- | Should be a type synonym instead? -- | This is something like an implementation of mod 2 vector spaces. Could this be done better with vector-spaces or linear? newtype AlgGen = AlgGen (Set Generator) deriving (Show, Ord, Eq) wrapGen :: Generator -> AlgGen wrapGen = AlgGen . S.singleton toSet :: AlgGen -> Set Generator toSet (AlgGen s) = s instance Monoid AlgGen where mempty = AlgGen S.empty mappend (AlgGen s) (AlgGen s') = AlgGen (addMod2Set s s') -- | 'Morphisms' is a map from (a linear combination of) 'Generator's to a set of (linear combinations of) 'Generator's. type Morphisms = Map AlgGen (Set AlgGen) -- | Generates all arrows from elements of @s@ to elements of @s'@ with the latter wrapped as singleton `Set`s. -- This is purely algebraic -- the function doesn't check if their ought to be any such arrows. fromTo :: Set AlgGen -> Set AlgGen -> [(AlgGen, Set AlgGen)] fromTo s s' = [(x,S.singleton y) | x <- S.toList s, y <- S.toList s'] -- | The next three functions implement mod 2 addition at the level of 'Set's and 'Map's. addMod2 :: (Eq a, Ord a) => a -> Set a -> Set a addMod2 b set = if S.member b set then S.delete b set else S.insert b set addMod2Set :: (Eq a, Ord a) => Set a -> Set a -> Set a addMod2Set bs set = S.foldr addMod2 set bs addMod2Map :: (Ord a, Ord k) => Map k (Set a) -> Map k (Set a) -> Map k (Set a) addMod2Map x y = M.filter (not . S.null) (M.unionWith addMod2Set x y) -- | Adds a x to the key key (but only if key is a key of mors). addToKey :: (Ord k, Monoid k, Monoid a) => k -> k -> Map k a -> Map k a addToKey x key mors = if key `M.member` mors then M.insert (x <> key) (mors ! key) . M.delete key $ mors else mors