module Data.Manifold.PseudoAffine (
Manifold
, Semimanifold(..), Needle'
, PseudoAffine(..)
, Metric, Metric', euclideanMetric
, RieMetric, RieMetric'
, RealDimension, AffineManifold
, LinearManifold
, WithField
, HilbertSpace
, EuclidSpace
, LocallyScalable
, palerp
) where
import Data.List
import qualified Data.Vector.Generic as Arr
import qualified Data.Vector
import Data.Maybe
import Data.Semigroup
import Data.Function (on)
import Data.Fixed
import Data.VectorSpace
import Data.LinearMap
import Data.LinearMap.HerMetric
import Data.MemoTrie (HasTrie(..))
import Data.AffineSpace
import Data.Basis
import Data.Complex hiding (magnitude)
import Data.Void
import Data.Tagged
import Data.Manifold.Types.Primitive
import Data.CoNat
import Data.VectorSpace.FiniteDimensional
import qualified Numeric.LinearAlgebra.HMatrix as HMat
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
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)
class (PseudoAffine m, LinearManifold (Needle m), Interior m ~ m) => Manifold m
instance (PseudoAffine m, LinearManifold (Needle m), Interior m ~ m) => Manifold m
type LocallyScalable s x = ( PseudoAffine x
, HasMetric (Needle x)
, s ~ Scalar (Needle x) )
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 => Tagged x (Metric x)
euclideanMetric = Tagged 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
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 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 (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 (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 (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 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