module Data.Manifold.Cone where
import qualified Data.Vector.Generic as Arr
import Data.Maybe
import Data.Semigroup
import Data.VectorSpace
import Data.LinearMap.HerMetric
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
import Data.Manifold.PseudoAffine
type ConeVecArr m = FinVecArrRep Cℝay (CℝayInterior m) (Scalar (Needle m))
type ConeNeedle m = Needle (ConeVecArr m)
type SConn'dConeVecArr m = FinVecArrRep Cℝay (ℝ, Interior m) ℝ
class ( Semimanifold m, Semimanifold (Interior (Interior m))
, Semimanifold (ConeVecArr m)
, Interior (ConeVecArr m) ~ ConeVecArr m )
=> ConeSemimfd m where
type CℝayInterior m :: *
fromCℝayInterior :: ConeVecArr m -> Cℝay m
fromCℝayInterior = projCD¹ToCℝay . fromCD¹Interior
fromCD¹Interior :: ConeVecArr m -> CD¹ m
fromCD¹Interior = embCℝayToCD¹ . fromCℝayInterior
toCℝayInterior :: Cℝay m -> Option (ConeVecArr m)
toCℝayInterior = toCD¹Interior . embCℝayToCD¹
toCD¹Interior :: CD¹ m -> Option (ConeVecArr m)
toCD¹Interior = toCℝayInterior . projCD¹ToCℝay
instance (ConeSemimfd m) => Semimanifold (Cℝay m) where
type Needle (Cℝay m) = ConeNeedle m
type Interior (Cℝay m) = ConeVecArr m
fromInterior = fromCℝayInterior
toInterior = toCℝayInterior
translateP = ctp
where ctp :: Tagged (Cℝay m) (ConeVecArr m -> ConeNeedle m -> ConeVecArr m)
ctp = Tagged ctp'
where Tagged ctp' = translateP
:: Tagged (ConeVecArr m) (ConeVecArr m -> ConeNeedle m -> ConeVecArr m)
instance (ConeSemimfd m) => Semimanifold (CD¹ m) where
type Needle (CD¹ m) = ConeNeedle m
type Interior (CD¹ m) = ConeVecArr m
fromInterior = fromCD¹Interior
toInterior = toCD¹Interior
translateP = ctp
where ctp :: Tagged (CD¹ m) (ConeVecArr m -> ConeNeedle m -> ConeVecArr m)
ctp = Tagged ctp'
where Tagged ctp' = translateP
:: Tagged (ConeVecArr m) (ConeVecArr m -> ConeNeedle m -> ConeVecArr m)
instance (ConeSemimfd m, SmoothScalar (Scalar (Needle m))) => PseudoAffine (Cℝay m) where
p.-~.i = (.-~.i) =<< toInterior p
instance (ConeSemimfd m, SmoothScalar (Scalar (Needle m))) => PseudoAffine (CD¹ m) where
p.-~.i = (.-~.i) =<< toInterior p
instance ConeSemimfd (ZeroDim ℝ) where
type CℝayInterior (ZeroDim ℝ) = ℝ
fromCℝayInterior (FinVecArrRep qb) | HMat.size qb == 0 = Cℝay 1 Origin
| x <- qb HMat.! 0 = Cℝay (bijectℝtoℝplus x) Origin
toCℝayInterior (Cℝay 0 Origin) = empty
toCℝayInterior (Cℝay y Origin) = pure . FinVecArrRep $ 1 HMat.|>[bijectℝplustoℝ y]
instance ConeSemimfd ℝ where
type CℝayInterior ℝ = ℝ²
fromCℝayInterior (FinVecArrRep qb) = Cℝay (q'+b') (q'b')
where [q', b'] = HMat.toList $ HMat.cmap ((/2) . bijectℝtoℝplus) qb
toCℝayInterior (Cℝay 0 _) = empty
toCℝayInterior (Cℝay h x) = pure . FinVecArrRep
. HMat.cmap bijectℝplustoℝ $ HMat.fromList [h+x, hx]
fromCD¹Interior (FinVecArrRep qb) = CD¹ (bijectℝplustoIntv $ q'+b') (q'b')
where [q', b'] = HMat.toList $ HMat.cmap ((/2) . bijectℝtoℝplus) qb
toCD¹Interior (CD¹ h x) = pure . FinVecArrRep
. HMat.cmap bijectℝplustoℝ $ HMat.fromList [h'+x, h'x]
where h' = bijectIntvtoℝplus h
instance ConeSemimfd S⁰ where
type CℝayInterior S⁰ = ℝ
fromCℝayInterior xa | x>0 = Cℝay x PositiveHalfSphere
| otherwise = Cℝay (x) NegativeHalfSphere
where x = getFinVecArrRep xa HMat.! 0
toCℝayInterior (Cℝay x PositiveHalfSphere) = return . FinVecArrRep $ HMat.scalar x
toCℝayInterior (Cℝay x NegativeHalfSphere) = return . FinVecArrRep . HMat.scalar $ x
fromCD¹Interior xa | x>0 = CD¹ (bijectℝtoIntv x) PositiveHalfSphere
| otherwise = CD¹ (bijectℝtoIntv x) NegativeHalfSphere
where x = getFinVecArrRep xa HMat.! 0
toCD¹Interior (CD¹ 1 _) = empty
toCD¹Interior (CD¹ x PositiveHalfSphere)
= return . FinVecArrRep . HMat.scalar $ bijectIntvtoℝ x
toCD¹Interior (CD¹ x NegativeHalfSphere)
= return . FinVecArrRep . HMat.scalar $ bijectℝtoIntv x
instance ConeSemimfd S¹ where
type CℝayInterior S¹ = ℝ²
fromCℝayInterior (FinVecArrRep xy) = Cℝay r (S¹ $ atan2 y x)
where r = HMat.norm_2 xy
[x,y] = HMat.toList xy
toCℝayInterior (Cℝay r (S¹ φ)) = return . FinVecArrRep
. HMat.scale r $ HMat.fromList [cos φ, sin φ]
fromCD¹Interior (FinVecArrRep xy) = CD¹ (bijectℝtoIntv r) (S¹ $ atan2 y x)
where r = HMat.norm_2 xy
[x,y] = HMat.toList xy
toCD¹Interior (CD¹ 1 _) = empty
toCD¹Interior (CD¹ r (S¹ φ)) = return . FinVecArrRep
. HMat.scale r' $ HMat.fromList [cos φ, sin φ]
where r' = bijectIntvtoℝ r
instance ConeSemimfd S² where
type CℝayInterior S² = ℝ³
fromCℝayInterior (FinVecArrRep xyz) = Cℝay r (S² (acos $ z/r) (atan2 y x))
where r = HMat.norm_2 xyz
[x,y,z] = HMat.toList xyz
toCℝayInterior (Cℝay r (S² ϑ φ)) = return . FinVecArrRep
. HMat.scale r $ HMat.fromList [w*x₀, w*y₀, z₀]
where x₀ = cos φ; y₀ = sin φ; z₀ = cos ϑ; w = sin ϑ
instance ( PseudoAffine x, PseudoAffine y
, WithField ℝ HilbertSpace (Interior x), WithField ℝ HilbertSpace (Interior y)
, LinearManifold (FinVecArrRep Cℝay (ℝ, (Interior x, Interior y)) ℝ)
) => ConeSemimfd (x,y) where
type CℝayInterior (x,y) = (ℝ, (Interior x, Interior y))
fromCℝayInterior = simplyCncted_fromCℝayInterior
toCℝayInterior = simplyCncted_toCℝayInterior
instance ( KnownNat n ) => ConeSemimfd (ℝ^n) where
type CℝayInterior (ℝ^n) = (ℝ, ℝ^n)
fromCℝayInterior = simplyCncted_fromCℝayInterior
toCℝayInterior = simplyCncted_toCℝayInterior
instance ( HilbertSpace (FinVecArrRep t v ℝ) ) => ConeSemimfd (FinVecArrRep t v ℝ) where
type CℝayInterior (FinVecArrRep t v ℝ) = (ℝ, FinVecArrRep t v ℝ)
fromCℝayInterior = simplyCncted_fromCℝayInterior
toCℝayInterior = simplyCncted_toCℝayInterior
instance ( WithField ℝ ConeSemimfd x, PseudoAffine (Cℝay x)
, HilbertSpace (CℝayInterior x)
, HilbertSpace (FinVecArrRep Cℝay (CℝayInterior x) ℝ)
) => ConeSemimfd (CD¹ x) where
type CℝayInterior (CD¹ x) = (ℝ, ConeVecArr x)
fromCℝayInterior i = Cℝay h (embCℝayToCD¹ o)
where (Cℝay h o) = simplyCncted_fromCℝayInterior i
toCℝayInterior (Cℝay _ (CD¹ 1 _)) = empty
toCℝayInterior (Cℝay h p) = simplyCncted_toCℝayInterior $ Cℝay h (projCD¹ToCℝay p)
instance ( WithField ℝ ConeSemimfd x, PseudoAffine (Cℝay x)
, HilbertSpace (CℝayInterior x)
, HilbertSpace (FinVecArrRep Cℝay (CℝayInterior x) ℝ)
) => ConeSemimfd (Cℝay x) where
type CℝayInterior (Cℝay x) = (ℝ, ConeVecArr x)
fromCℝayInterior = simplyCncted_fromCℝayInterior
toCℝayInterior = simplyCncted_toCℝayInterior
simplyCncted_fromCℝayInterior :: (PseudoAffine x, WithField ℝ HilbertSpace (Interior x))
=> SConn'dConeVecArr x -> Cℝay x
simplyCncted_fromCℝayInterior (FinVecArrRep ri) = Cℝay h . fromInterior . fromPackedVector
$ subtract (h/n) `Arr.map` Arr.tail cmps
where h = Arr.sum cmps
cmps = bijectℝtoℝplus `HMat.cmap` ri
n = fromIntegral $ Arr.length cmps
simplyCncted_toCℝayInterior :: (PseudoAffine x, WithField ℝ HilbertSpace (Interior x))
=> Cℝay x -> Option (SConn'dConeVecArr x)
simplyCncted_toCℝayInterior (Cℝay h v) | h/=0, Option (Just vi) <- toInterior v
= let cmps'' = asPackedVector vi
cmps' = (+ h/n) `HMat.cmap` cmps''
cmps = (h Arr.sum cmps') `Arr.cons` cmps
n = fromIntegral $ Arr.length cmps
in return $ FinVecArrRep (bijectℝplustoℝ `Arr.map` cmps)
simplyCncted_toCℝayInterior (Cℝay _ _) = empty
bijectℝtoℝplus , bijectℝplustoℝ
, bijectIntvtoℝplus, bijectℝplustoIntv
, bijectIntvtoℝ, bijectℝtoIntv
:: ℝ -> ℝ
bijectℝplustoℝ x = x 1/x
bijectℝtoℝplus y = y/2 + sqrt(y^2/4 + 1)
bijectℝplustoIntv y = 1 recip (y+1)
bijectIntvtoℝplus x = recip(1x) 1
bijectℝtoIntv y | y>0 = 1/(2*y) + sqrt(1/(4*y^2) + 1)
| y<0 = 1/(2*y) sqrt(1/(4*y^2) + 1)
| otherwise = 0
bijectIntvtoℝ x = x / (1x^2)
embCℝayToCD¹ :: Cℝay m -> CD¹ m
embCℝayToCD¹ (Cℝay h m) = CD¹ (bijectℝplustoIntv h) m
projCD¹ToCℝay :: CD¹ m -> Cℝay m
projCD¹ToCℝay (CD¹ h m) = Cℝay (bijectIntvtoℝplus h) m
stiefel1Project :: LinearManifold v =>
DualSpace v
-> Stiefel1 v
stiefel1Project = Stiefel1
stiefel1Embed :: HilbertSpace v => Stiefel1 v -> v
stiefel1Embed (Stiefel1 n) = normalized n
class (PseudoAffine v, InnerSpace v, NaturallyEmbedded (UnitSphere v) (DualSpace v))
=> HasUnitSphere v where
type UnitSphere v :: *
stiefel :: UnitSphere v -> Stiefel1 v
stiefel = Stiefel1 . embed
unstiefel :: Stiefel1 v -> UnitSphere v
unstiefel = coEmbed . getStiefel1N
instance HasUnitSphere ℝ where type UnitSphere ℝ = S⁰
instance HasUnitSphere (FinVecArrRep t ℝ ℝ) where type UnitSphere (FinVecArrRep t ℝ ℝ) = S⁰
instance HasUnitSphere ℝ² where type UnitSphere ℝ² = S¹
instance HasUnitSphere (FinVecArrRep t ℝ² ℝ) where type UnitSphere (FinVecArrRep t ℝ² ℝ) = S¹
instance HasUnitSphere ℝ³ where type UnitSphere ℝ³ = S²
instance HasUnitSphere (FinVecArrRep t ℝ³ ℝ) where type UnitSphere (FinVecArrRep t ℝ³ ℝ) = S²