module Data.Manifold.PseudoAffine (
Manifold
, Semimanifold(..), Needle'
, PseudoAffine(..)
, Metric, Metric', euclideanMetric
, RieMetric, RieMetric'
, RealDimension, AffineManifold
, LinearManifold
, WithField
, HilbertSpace
, EuclidSpace
, LocallyScalable
, LocalLinear, LocalAffine
, alerpB, palerp, palerpB, LocallyCoercible(..)
, ImpliesMetric(..)
) where
import Data.Maybe
import Data.Semigroup
import Data.Fixed
import Data.VectorSpace
import Data.Embedding
import Data.LinearMap
import Data.LinearMap.HerMetric
import Data.LinearMap.Category
import Data.AffineSpace
import Data.Tagged
import Data.Manifold.Types.Primitive
import Data.CoNat
import Data.VectorSpace.FiniteDimensional
import qualified Prelude
import qualified Control.Applicative as Hask
import Control.Category.Constrained.Prelude hiding ((^))
import Control.Arrow.Constrained
import Control.Monad.Constrained
import Data.Foldable.Constrained
import GHC.Exts (Constraint)
infix 6 .-~.
infixl 6 .+~^, .-~^
class ( AdditiveGroup (Needle x), Interior (Interior x) ~ Interior x )
=> Semimanifold x where
type Needle x :: *
type Interior x :: *
type Interior x = x
(.+~^) :: Interior x -> Needle x -> x
(.+~^) = addvp
where addvp :: ∀ x . Semimanifold x => Interior x -> Needle x -> x
addvp p = fromInterior . tp p
where (Tagged tp) = translateP :: Tagged x (Interior x -> Needle x -> Interior x)
fromInterior :: Interior x -> x
fromInterior p = p .+~^ zeroV
toInterior :: x -> Option (Interior x)
translateP :: Tagged x (Interior x -> Needle x -> Interior x)
(.-~^) :: Interior x -> Needle x -> x
p .-~^ v = p .+~^ negateV v
class ( Semimanifold x, Semimanifold (Interior x)
, Needle (Interior x) ~ Needle x, Interior (Interior x) ~ Interior x)
=> PseudoAffine x where
(.-~.) :: x -> Interior x -> Option (Needle x)
p.-~.q = return $ p.-~!q
(.-~!) :: x -> Interior x -> Needle x
p.-~!q = case p.-~.q of
Option (Just v) -> v
class (PseudoAffine m, LinearManifold (Needle m), Interior m ~ m) => Manifold m
instance (PseudoAffine m, LinearManifold (Needle m), Interior m ~ m) => Manifold m
class (PseudoAffine x, PseudoAffine ξ, Scalar (Needle x) ~ Scalar (Needle ξ))
=> LocallyCoercible x ξ where
locallyTrivialDiffeomorphism :: x -> ξ
instance LocallyCoercible ℝ ℝ where locallyTrivialDiffeomorphism = id
instance LocallyCoercible (ℝ,ℝ) (ℝ,ℝ) where locallyTrivialDiffeomorphism = id
instance LocallyCoercible (ℝ,(ℝ,ℝ)) (ℝ,(ℝ,ℝ)) where locallyTrivialDiffeomorphism = id
instance LocallyCoercible ((ℝ,ℝ),ℝ) ((ℝ,ℝ),ℝ) where locallyTrivialDiffeomorphism = id
type LocallyScalable s x = ( PseudoAffine x
, HasMetric (Needle x)
, s ~ Scalar (Needle x) )
type LocalLinear x y = Linear (Scalar (Needle x)) (Needle x) (Needle y)
type LocalAffine x y = (Needle y, LocalLinear x y)
type LinearManifold x = ( AffineManifold x, Needle x ~ x, HasMetric x )
type LinearManifold' x = ( PseudoAffine x, AffineSpace x, Diff x ~ x
, Interior x ~ x, Needle x ~ x, HasMetric x )
type WithField s c x = ( c x, s ~ Scalar (Needle x) )
type RealDimension r = ( PseudoAffine r, Interior r ~ r, Needle r ~ r
, HasMetric r, DualSpace r ~ r, Scalar r ~ r
, RealFloat r, r ~ ℝ)
type AffineManifold m = ( PseudoAffine m, Interior m ~ m, AffineSpace m
, Needle m ~ Diff m, LinearManifold' (Diff m) )
type HilbertSpace x = ( LinearManifold x, InnerSpace x
, Interior x ~ x, Needle x ~ x, DualSpace x ~ x
, Floating (Scalar x) )
type EuclidSpace x = ( AffineManifold x, InnerSpace (Diff x)
, DualSpace (Diff x) ~ Diff x, Floating (Scalar (Diff x)) )
euclideanMetric :: EuclidSpace x => proxy x -> Metric x
euclideanMetric _ = euclideanMetric'
type Needle' x = DualSpace (Needle x)
type Metric x = HerMetric (Needle x)
type Metric' x = HerMetric' (Needle x)
type RieMetric x = x -> Metric x
type RieMetric' x = x -> Metric' x
palerp :: ∀ x. Manifold x
=> Interior x -> Interior x -> Option (Scalar (Needle x) -> x)
palerp p1 p2 = case (fromInterior p2 :: x) .-~. p1 of
Option (Just v) -> return $ \t -> p1 .+~^ t *^ v
_ -> empty
palerpB :: ∀ x. WithField ℝ Manifold x => Interior x -> Interior x -> Option (D¹ -> x)
palerpB p1 p2 = case (fromInterior p2 :: x) .-~. p1 of
Option (Just v) -> return $ \(D¹ t) -> p1 .+~^ ((t+1)/2) *^ v
_ -> empty
alerpB :: ∀ x. (AffineSpace x, VectorSpace (Diff x), Scalar (Diff x) ~ ℝ)
=> x -> x -> D¹ -> x
alerpB p1 p2 = case p2 .-. p1 of
v -> \(D¹ t) -> p1 .+^ ((t+1)/2) *^ v
hugeℝVal :: ℝ
hugeℝVal = 1e+100
#define deriveAffine(t) \
instance Semimanifold (t) where { \
type Needle (t) = Diff (t); \
fromInterior = id; \
toInterior = pure; \
translateP = Tagged (.+^); \
(.+~^) = (.+^) }; \
instance PseudoAffine (t) where { \
a.-~.b = pure (a.-.b); }
deriveAffine(Double)
deriveAffine(Rational)
instance SmoothScalar s => Semimanifold (FinVecArrRep t b s) where
type Needle (FinVecArrRep t b s) = FinVecArrRep t b s
type Interior (FinVecArrRep t b s) = FinVecArrRep t b s
fromInterior = id
toInterior = pure
translateP = Tagged (.+^)
(.+~^) = (.+^)
instance SmoothScalar s => PseudoAffine (FinVecArrRep t b s) where
a.-~.b = pure (a.-.b)
instance SmoothScalar s => LocallyCoercible (FinVecArrRep t b s) (FinVecArrRep t b s) where
locallyTrivialDiffeomorphism = id
instance (SmoothScalar s, LinearManifold b, Scalar b ~ s)
=> LocallyCoercible (FinVecArrRep t b s) b where
locallyTrivialDiffeomorphism = (concreteArrRep$<-$)
instance (SmoothScalar s, LinearManifold b, Scalar b ~ s)
=> LocallyCoercible b (FinVecArrRep t b s) where
locallyTrivialDiffeomorphism = (concreteArrRep$->$)
instance Semimanifold (ZeroDim k) where
type Needle (ZeroDim k) = ZeroDim k
fromInterior = id
toInterior = pure
Origin .+~^ Origin = Origin
Origin .-~^ Origin = Origin
translateP = Tagged (.+~^)
instance PseudoAffine (ZeroDim k) where
Origin .-~. Origin = pure Origin
instance (Semimanifold a, Semimanifold b) => Semimanifold (a,b) where
type Needle (a,b) = (Needle a, Needle b)
type Interior (a,b) = (Interior a, Interior b)
(a,b).+~^(v,w) = (a.+~^v, b.+~^w)
(a,b).-~^(v,w) = (a.-~^v, b.-~^w)
fromInterior (i,j) = (fromInterior i, fromInterior j)
toInterior (a,b) = fzip (toInterior a, toInterior b)
translateP = tp
where tp :: ∀ a b . (Semimanifold a, Semimanifold b)
=> Tagged (a,b) ( (Interior a, Interior b)
-> (Needle a, Needle b)
-> (Interior a, Interior b) )
tp = Tagged $ \(a,b) (v,w) -> (ta a v, tb b w)
where Tagged ta = translateP :: Tagged a (Interior a -> Needle a -> Interior a)
Tagged tb = translateP :: Tagged b (Interior b -> Needle b -> Interior b)
instance (PseudoAffine a, PseudoAffine b) => PseudoAffine (a,b) where
(a,b).-~.(c,d) = liftA2 (,) (a.-~.c) (b.-~.d)
instance (PseudoAffine a, PseudoAffine b, PseudoAffine c)
=> LocallyCoercible (a,(b,c)) ((a,b),c) where locallyTrivialDiffeomorphism = regroup
instance (PseudoAffine a, PseudoAffine b, PseudoAffine c)
=> LocallyCoercible ((a,b),c) (a,(b,c)) where locallyTrivialDiffeomorphism = regroup'
instance (Semimanifold a, Semimanifold b, Semimanifold c) => Semimanifold (a,b,c) where
type Needle (a,b,c) = (Needle a, Needle b, Needle c)
type Interior (a,b,c) = (Interior a, Interior b, Interior c)
(a,b,c).+~^(v,w,x) = (a.+~^v, b.+~^w, c.+~^x)
(a,b,c).-~^(v,w,x) = (a.-~^v, b.-~^w, c.-~^x)
fromInterior (i,j,k) = (fromInterior i, fromInterior j, fromInterior k)
toInterior (a,b,c) = liftA3 (,,) (toInterior a) (toInterior b) (toInterior c)
translateP = tp
where tp :: ∀ a b v . (Semimanifold a, Semimanifold b, Semimanifold c)
=> Tagged (a,b,c) ( (Interior a, Interior b, Interior c)
-> (Needle a, Needle b, Needle c)
-> (Interior a, Interior b, Interior c) )
tp = Tagged $ \(a,b,c) (v,w,x) -> (ta a v, tb b w, tc c x)
where Tagged ta = translateP :: Tagged a (Interior a -> Needle a -> Interior a)
Tagged tb = translateP :: Tagged b (Interior b -> Needle b -> Interior b)
Tagged tc = translateP :: Tagged c (Interior c -> Needle c -> Interior c)
instance (PseudoAffine a, PseudoAffine b, PseudoAffine c) => PseudoAffine (a,b,c) where
(a,b,c).-~.(d,e,f) = liftA3 (,,) (a.-~.d) (b.-~.e) (c.-~.f)
instance (PseudoAffine a, PseudoAffine b, PseudoAffine c)
=> LocallyCoercible (a,b,c) ((a,b),c) where
locallyTrivialDiffeomorphism (a,b,c) = ((a,b),c)
instance (PseudoAffine a, PseudoAffine b, PseudoAffine c)
=> LocallyCoercible (a,b,c) (a,(b,c)) where
locallyTrivialDiffeomorphism (a,b,c) = (a,(b,c))
instance (PseudoAffine a, PseudoAffine b, PseudoAffine c)
=> LocallyCoercible ((a,b),c) (a,b,c) where
locallyTrivialDiffeomorphism ((a,b),c) = (a,b,c)
instance (PseudoAffine a, PseudoAffine b, PseudoAffine c)
=> LocallyCoercible (a,(b,c)) (a,b,c) where
locallyTrivialDiffeomorphism (a,(b,c)) = (a,b,c)
instance (MetricScalar a, KnownNat n) => Semimanifold (FreeVect n a) where
type Needle (FreeVect n a) = FreeVect n a
fromInterior = id
toInterior = pure
translateP = Tagged (.+~^)
(.+~^) = (.+^)
instance (MetricScalar a, KnownNat n) => PseudoAffine (FreeVect n a) where
a.-~.b = pure (a.-.b)
instance LocallyCoercible ℝ (ℝ ^ S Z) where
locallyTrivialDiffeomorphism = replicVector
instance LocallyCoercible (ℝ ^ S Z) ℝ where
locallyTrivialDiffeomorphism = (<.>^replicVector 1)
instance (HasMetric a, FiniteDimensional b, Scalar a~Scalar b) => Semimanifold (a⊗b) where
type Needle (a⊗b) = a ⊗ b
fromInterior = id
toInterior = pure
translateP = Tagged (.+~^)
(.+~^) = (^+^)
instance (HasMetric a, FiniteDimensional b, Scalar a~Scalar b) => PseudoAffine (a⊗b) where
a.-~.b = pure (a^-^b)
instance (HasMetric a, FiniteDimensional b, Scalar a~Scalar b) => Semimanifold (a:-*b) where
type Needle (a:-*b) = DualSpace a ⊗ b
fromInterior = id
toInterior = pure
translateP = Tagged (.+~^)
p.+~^n = p ^+^ linMapFromTensProd n
instance (HasMetric a, FiniteDimensional b, Scalar a~Scalar b) => PseudoAffine (a:-*b) where
a.-~.b = pure . linMapAsTensProd $ a^-^b
instance (HasMetric a, FiniteDimensional b, Scalar a~s, Scalar b~s)
=> Semimanifold (Linear s a b) where
type Needle (Linear s a b) = Linear s a b
fromInterior = id
toInterior = pure
translateP = Tagged (.+^)
(.+~^) = (^+^)
instance (HasMetric a, FiniteDimensional b, Scalar a~s, Scalar b~s)
=> PseudoAffine (Linear s a b) where
a.-~.b = pure (a^-^b)
instance Semimanifold S⁰ where
type Needle S⁰ = ℝ⁰
fromInterior = id
toInterior = pure
translateP = Tagged (.+~^)
p .+~^ Origin = p
p .-~^ Origin = p
instance PseudoAffine S⁰ where
PositiveHalfSphere .-~. PositiveHalfSphere = pure Origin
NegativeHalfSphere .-~. NegativeHalfSphere = pure Origin
_ .-~. _ = Option Nothing
instance Semimanifold S¹ where
type Needle S¹ = ℝ
fromInterior = id
toInterior = pure
translateP = Tagged (.+~^)
S¹ φ₀ .+~^ δφ
| φ' < 0 = S¹ $ φ' + tau
| otherwise = S¹ $ φ'
where φ' = toS¹range $ φ₀ + δφ
instance PseudoAffine S¹ where
S¹ φ₁ .-~. S¹ φ₀
| δφ > pi = pure (δφ 2*pi)
| δφ < (pi) = pure (δφ + 2*pi)
| otherwise = pure δφ
where δφ = φ₁ φ₀
instance Semimanifold D¹ where
type Needle D¹ = ℝ
type Interior D¹ = ℝ
fromInterior = D¹ . tanh
toInterior (D¹ x) | abs x < 1 = return $ atanh x
| otherwise = empty
translateP = Tagged (+)
instance PseudoAffine D¹ where
D¹ 1 .-~. _ = empty
D¹ (1) .-~. _ = empty
D¹ x .-~. y
| abs x < 1 = return $ atanh x y
| otherwise = empty
instance Semimanifold S² where
type Needle S² = ℝ²
fromInterior = id
toInterior = pure
translateP = Tagged (.+~^)
S² ϑ₀ φ₀ .+~^ δv
| ϑ₀ < pi/2 = sphereFold PositiveHalfSphere $ ϑ₀*^embed(S¹ φ₀) ^+^ δv
| otherwise = sphereFold NegativeHalfSphere $ (piϑ₀)*^embed(S¹ φ₀) ^+^ δv
instance PseudoAffine S² where
S² ϑ₁ φ₁ .-~. S² ϑ₀ φ₀
| ϑ₀ < pi/2 = pure ( ϑ₁*^embed(S¹ φ₁) ^-^ ϑ₀*^embed(S¹ φ₀) )
| otherwise = pure ( (piϑ₁)*^embed(S¹ φ₁) ^-^ (piϑ₀)*^embed(S¹ φ₀) )
sphereFold :: S⁰ -> ℝ² -> S²
sphereFold hfSphere v
| ϑ₀ > pi = S² (inv $ tau ϑ₀) (toS¹range $ φ₀+pi)
| otherwise = S² (inv ϑ₀) φ₀
where S¹ φ₀ = coEmbed v
ϑ₀ = magnitude v `mod'` tau
inv ϑ = case hfSphere of PositiveHalfSphere -> ϑ
NegativeHalfSphere -> pi ϑ
instance Semimanifold ℝP² where
type Needle ℝP² = ℝ²
fromInterior = id
toInterior = pure
translateP = Tagged (.+~^)
ℝP² r₀ φ₀ .+~^ (δr, δφ)
| r₀ > 1/2 = case r₀ + δr of
r₁ | r₁ > 1 -> ℝP² (2r₁) (toS¹range $ φ₀+δφ+pi)
| otherwise -> ℝP² r₁ (toS¹range $ φ₀+δφ)
ℝP² r₀ φ₀ .+~^ δxy = let v = r₀*^embed(S¹ φ₀) ^+^ δxy
S¹ φ₁ = coEmbed v
r₁ = magnitude v `mod'` 1
in ℝP² r₁ φ₁
instance PseudoAffine ℝP² where
ℝP² r₁ φ₁ .-~. ℝP² r₀ φ₀
| r₀ > 1/2 = pure `id` case φ₁φ₀ of
δφ | δφ > 3*pi/2 -> ( r₁ r₀, δφ 2*pi)
| δφ < 3*pi/2 -> ( r₁ r₀, δφ + 2*pi)
| δφ > pi/2 -> (2r₁ r₀, δφ pi )
| δφ < pi/2 -> (2r₁ r₀, δφ + pi )
| otherwise -> ( r₁ r₀, δφ )
| otherwise = pure ( r₁*^embed(S¹ φ₁) ^-^ r₀*^embed(S¹ φ₀) )
tau :: ℝ
tau = 2 * pi
toS¹range :: ℝ -> ℝ
toS¹range φ = (φ+pi)`mod'`tau pi
class ImpliesMetric s where
type MetricRequirement s x :: Constraint
type MetricRequirement s x = Semimanifold x
inferMetric :: (MetricRequirement s x, HasMetric (Needle x))
=> s x -> Option (Metric x)
inferMetric = safeRecipMetric <=< inferMetric'
inferMetric' :: (MetricRequirement s x, HasMetric (Needle x))
=> s x -> Option (Metric' x)
inferMetric' = safeRecipMetric' <=< inferMetric
instance ImpliesMetric HerMetric where
type MetricRequirement HerMetric x = x ~ Needle x
inferMetric = pure
instance ImpliesMetric HerMetric' where
type MetricRequirement HerMetric' x = x ~ Needle x
inferMetric' = pure