manifolds-0.6.1.0: Math/Manifold/Homogeneous.hs
-- |
-- Module : Math.Manifold.Homogeneous
-- Copyright : (c) Justus Sagemüller 2022
-- License : GPL v3
--
-- Maintainer : (@) jsag $ hvl.no
-- Stability : experimental
-- Portability : portable
--
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE UnicodeSyntax #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE TemplateHaskell #-}
module Math.Manifold.Homogeneous
( LieGroup(..), LieAlgebra, ActsOn(..)
, SO
) where
import Data.VectorSpace
import Data.AffineSpace
import Data.Basis
import Math.Manifold.Core.PseudoAffine
import Data.Manifold.PseudoAffine
import Math.Manifold.Core.Types
import Data.Manifold.Types.Primitive
import Math.Manifold.VectorSpace.ZeroDimensional
import Math.LinearMap.Category
import Math.VectorSpace.Dual
import Data.Complex as ℂ
import Linear (V0, V1, V2, V3(..), V4, Quaternion(..), cross)
import qualified Linear.Affine as LinAff
import Data.Monoid.Additive
import Prelude hiding (($), (^))
import Control.Arrow.Constrained ((<<<), ($))
import Control.Applicative
import Data.Semigroup hiding (Dual)
import qualified Test.QuickCheck as QC
import Data.Kind (Type)
import GHC.TypeLits (Nat)
import Data.Coerce
import Data.Type.Coercion
newtype LieAlgebra g
= LieAlgebra { getLieNeedle :: Needle g }
copyNewtypeInstances [t| ∀ g . (Semimanifold g) => LieAlgebra g |]
[''AdditiveGroup]
-- | Manifolds with a continuous group structure, whose 'Needle' space
-- is isomorphic to the associated Lie algebra.
--
-- Laws:
--
-- @
-- expMap zeroV ≡ mempty
-- lieBracket w v ≡ negateV (lieBracket v w)
-- ...
-- @
class (Semimanifold g, Monoid g) => LieGroup g where
expMap :: LieAlgebra g -> g
lieBracket :: Bilinear (LieAlgebra g) (LieAlgebra g) (LieAlgebra g)
data family SO_ (n :: Nat) (r :: Type)
type SO n = SO_ n Double
data instance SO_ 1 r = SO1Identity
deriving (Eq, Show)
instance (QC.Arbitrary r, Floating r) => QC.Arbitrary (SO_ 1 r) where
arbitrary = pure SO1Identity
instance Semigroup (SO_ 1 r) where
SO1Identity <> SO1Identity = SO1Identity
instance Monoid (SO_ 1 r) where
mempty = SO1Identity
mappend = (<>)
instance RealFloat' r => Semimanifold (SO_ 1 r) where
type Needle (SO_ 1 r) = ZeroDim r
SO1Identity .+~^ Origin = SO1Identity
semimanifoldWitness = case linearManifoldWitness @r of
LinearManifoldWitness -> SemimanifoldWitness
newtype instance SO_ 2 r = SO2 { unitReprSO2 :: Complex r }
deriving (Eq, Show)
instance (QC.Arbitrary r, Floating r) => QC.Arbitrary (SO_ 2 r) where
arbitrary = SO2 . ℂ.cis <$> QC.arbitrary
instance RealFloat r => Semigroup (SO_ 2 r) where
SO2 a <> SO2 b = SO2 $ a*b -- perhaps should normalize?
instance RealFloat r => Monoid (SO_ 2 r) where
mempty = SO2 1
mappend = (<>)
instance RealFloat' r => Semimanifold (SO_ 2 r) where
type Needle (SO_ 2 r) = r
p .+~^ d = p <> expMap (LieAlgebra d)
semimanifoldWitness = case linearManifoldWitness @r of
LinearManifoldWitness -> SemimanifoldWitness
instance RealFloat' r => LieGroup (SO_ 2 r) where
expMap = SO2 . cis . getLieNeedle
lieBracket = zeroV
newtype instance SO_ 3 r = SO3 { unitReprSO3 :: Quaternion r }
deriving (Eq, Show)
instance (QC.Arbitrary r, RealFloat r) => QC.Arbitrary (SO_ 3 r) where
arbitrary = do
(a,b,c,d) <- QC.arbitrary
pure . SO3 $ case sqrt . sum $ (^2)<$>[a,b,c,d] of
l | l>0 -> Quaternion (a/l) (V3 b c d ^/ l)
| otherwise -> 1
instance RealFloat r => Semigroup (SO_ 3 r) where
SO3 a <> SO3 b = SO3 $ a*b -- perhaps should normalize?
instance RealFloat r => Monoid (SO_ 3 r) where
mempty = SO3 1
mappend = (<>)
instance RealFloat' r => Semimanifold (SO_ 3 r) where
type Needle (SO_ 3 r) = V3 r
p .+~^ d = p <> expMap (LieAlgebra d)
semimanifoldWitness = case linearManifoldWitness @r of
LinearManifoldWitness -> SemimanifoldWitness
instance ∀ r . RealFloat' r => LieGroup (SO_ 3 r) where
expMap (LieAlgebra a) = SO3 . exp $ Quaternion 0 a
lieBracket = coerce (cross :: V3 r -> V3 r -> V3 r)
embedPureImagUnitQuaternion :: RealFloat r => S²_ r -> Quaternion r
embedPureImagUnitQuaternion = Quaternion 0 . embed
projectPureImagUnitQuaternion :: RealFloat r => Quaternion r -> S²_ r
projectPureImagUnitQuaternion (Quaternion _ p) = coEmbed p
-- | Manifolds that are homogeneous with respect to action by a Lie group.
-- Laws:
--
-- @
-- action mempty ≡ id (Identity)
-- action (a<>b) ≡ action a . action b (Compatibility)
-- @
class (Semimanifold m, LieGroup g) => g `ActsOn` m where
action :: g -> m -> m
instance RealFloat' r => SO_ 2 r`ActsOn`S¹_ r where
action (SO2 β) p = p .+~^ ℂ.phase β
instance RealFloat' r => SO_ 3 r`ActsOn`S²_ r where
action (SO3 γ) p = projectPureImagUnitQuaternion $ γ * α * recip γ
where α = embedPureImagUnitQuaternion p