module Math.VectorSpace.Docile where
import Math.LinearMap.Category.Class
import Math.LinearMap.Category.Instances
import Math.LinearMap.Asserted
import Data.Tree (Tree(..), Forest)
import Data.List (sortBy, foldl')
import qualified Data.Set as Set
import Data.Set (Set)
import Data.Ord (comparing)
import Data.List (maximumBy, unfoldr)
import qualified Data.Vector as Arr
import Data.Foldable (toList)
import Data.Semigroup
import Data.VectorSpace
import Data.Basis
import Prelude ()
import qualified Prelude as Hask
import Control.Category.Constrained.Prelude hiding ((^))
import Control.Arrow.Constrained
import Linear ( V0(V0), V1(V1), V2(V2), V3(V3), V4(V4)
, _x, _y, _z, _w )
import qualified Data.Vector.Unboxed as UArr
import Data.VectorSpace.Free
import Math.VectorSpace.ZeroDimensional
import qualified Linear.Matrix as Mat
import qualified Linear.Vector as Mat
import Control.Lens ((^.))
import Data.Coerce
import Numeric.IEEE
class LSpace v => SemiInner v where
dualBasisCandidates :: [(Int,v)] -> Forest (Int, DualVector v)
cartesianDualBasisCandidates
:: [DualVector v]
-> (v -> [β])
-> ([(Int,v)] -> Forest (Int, DualVector v))
cartesianDualBasisCandidates dvs abss vcas = go 0 0 sorted
where sorted = sortBy (comparing $ negate . snd . snd)
[ (i, (av, maximum av)) | (i,v)<-vcas, let av = abss v ]
go k nDelay scs@((i,(av,_)):scs')
| k<n = Node (i, dv) (go (k+1) 0 [(i',(zeroAt j av',m)) | (i',(av',m))<-scs'])
: go k (nDelay+1) (bringToFront (nDelay+1) scs)
where (j,_) = maximumBy (comparing snd) $ zip jfus av
dv = dvs !! j
go _ _ _ = []
jfus = [0 .. n1]
n = length dvs
zeroAt :: Int -> [β] -> [β]
zeroAt _ [] = []
zeroAt 0 (_:l) = (1/0):l
zeroAt j (e:l) = e : zeroAt (j1) l
bringToFront :: Int -> [a] -> [a]
bringToFront i l = case splitAt i l of
(_,[]) -> []
(f,s:l') -> s : f++l'
instance (Fractional'' s, SemiInner s) => SemiInner (ZeroDim s) where
dualBasisCandidates _ = []
instance (Fractional'' s, SemiInner s) => SemiInner (V0 s) where
dualBasisCandidates _ = []
(<.>^) :: LSpace v => DualVector v -> v -> Scalar v
f<.>^v = (applyDualVector$f)$v
orthonormaliseDuals :: (SemiInner v, LSpace v, RealFrac' (Scalar v))
=> Scalar v -> [(v, DualVector v)] -> [(v,DualVector v)]
orthonormaliseDuals _ [] = []
orthonormaliseDuals Ξ΅ ((v,v'β):ws)
| abs ovl > Ξ΅ = (v,v') : [(w, w' ^-^ (w'<.>^v)*^v') | (w,w')<-wssys]
| otherwise = (v,zeroV) : wssys
where wssys = orthonormaliseDuals Ξ΅ ws
v'β = foldl' (\v'i (w,w') -> v'i ^-^ (v'i<.>^w)*^w') (v'β ^/ (v'β<.>^v)) wssys
v' = v'β ^/ ovl
ovl = v'β<.>^v
dualBasis :: (SemiInner v, LSpace v, RealFrac' (Scalar v)) => [v] -> [DualVector v]
dualBasis vs = snd <$> orthonormaliseDuals epsilon (zip' vsIxed candidates)
where zip' ((i,v):vs) ((j,v'):ds)
| i<j = zip' vs ((j,v'):ds)
| i==j = (v,v') : zip' vs ds
zip' _ _ = []
candidates
| Just bestCandidates <- findBest n $ dualBasisCandidates vsIxed
= sortBy (comparing fst) bestCandidates
where findBest 0 _ = Just []
findBest _ [] = Nothing
findBest n (Node (i,v') bv' : alts)
| v'<.>^(lookupArr Arr.! i) /= 0
, Just best' <- findBest (n1) bv'
= Just $ (i,v') : best'
| otherwise = findBest n alts
vsIxed = zip [0..] vs
lookupArr = Arr.fromList vs
n = Arr.length lookupArr
instance SemiInner β where
dualBasisCandidates = fmap ((`Node`[]) . second recip)
. sortBy (comparing $ negate . abs . snd)
. filter ((/=0) . snd)
instance (Fractional'' s, Ord s, SemiInner s) => SemiInner (V1 s) where
dualBasisCandidates = fmap ((`Node`[]) . second recip)
. sortBy (comparing $ negate . abs . snd)
. filter ((/=0) . snd)
#define FreeSemiInner(V, sabs) \
instance SemiInner (V) where { \
dualBasisCandidates \
= cartesianDualBasisCandidates Mat.basis (fmap sabs . toList) }
FreeSemiInner(V2 β, abs)
FreeSemiInner(V3 β, abs)
FreeSemiInner(V4 β, abs)
instance β u v . ( SemiInner u, SemiInner v, Scalar u ~ Scalar v ) => SemiInner (u,v) where
dualBasisCandidates = fmap (\(i,(u,v))->((i,u),(i,v))) >>> unzip
>>> dualBasisCandidates *** dualBasisCandidates
>>> combineBaseis False mempty
where combineBaseis :: Bool -> Set Int
-> ( Forest (Int, DualVector u)
, Forest (Int, DualVector v) )
-> Forest (Int, (DualVector u, DualVector v))
combineBaseis _ _ ([], []) = []
combineBaseis False forbidden (Node (i,du) bu' : abu, bv)
| i`Set.member`forbidden = combineBaseis False forbidden (abu, bv)
| otherwise
= Node (i, (du, zeroV))
(combineBaseis True (Set.insert i forbidden) (bu', bv))
: combineBaseis False forbidden (abu, bv)
combineBaseis True forbidden (bu, Node (i,dv) bv' : abv)
| i`Set.member`forbidden = combineBaseis True forbidden (bu, abv)
| otherwise
= Node (i, (zeroV, dv))
(combineBaseis False (Set.insert i forbidden) (bu, bv'))
: combineBaseis True forbidden (bu, abv)
combineBaseis _ forbidden (bu, []) = combineBaseis False forbidden (bu,[])
combineBaseis _ forbidden ([], bv) = combineBaseis True forbidden ([],bv)
instance β s u v . ( SimpleSpace u, SimpleSpace v, Scalar u ~ s, Scalar v ~ s )
=> SemiInner (Tensor s u v) where
dualBasisCandidates = map (fmap (second $ arr transposeTensor . arr asTensor))
. dualBasisCandidates
. map (second $ arr asLinearMap)
instance β s u v . ( SimpleSpace u, SimpleSpace v, Scalar u ~ s, Scalar v ~ s )
=> SemiInner (LinearMap s u v) where
dualBasisCandidates = sequenceForest
. map (second pseudoInverse)
where sequenceForest [] = []
sequenceForest (x:xs) = [Node x $ sequenceForest xs]
(^/^) :: (InnerSpace v, Eq (Scalar v), Fractional (Scalar v)) => v -> v -> Scalar v
v^/^w = case (v<.>w) of
0 -> 0
vw -> vw / (w<.>w)
type DList x = [x]->[x]
class (LSpace v, LSpace (Scalar v)) => FiniteDimensional v where
data SubBasis v :: *
entireBasis :: SubBasis v
enumerateSubBasis :: SubBasis v -> [v]
subbasisDimension :: SubBasis v -> Int
subbasisDimension = length . enumerateSubBasis
decomposeLinMap :: (LSpace w, Scalar w ~ Scalar v) => (v+>w) -> (SubBasis v, DList w)
decomposeLinMapWithin :: (LSpace w, Scalar w ~ Scalar v)
=> SubBasis v -> (v+>w) -> Either (SubBasis v, DList w) (DList w)
recomposeSB :: SubBasis v -> [Scalar v] -> (v, [Scalar v])
recomposeSBTensor :: (FiniteDimensional w, Scalar w ~ Scalar v)
=> SubBasis v -> SubBasis w -> [Scalar v] -> (vβw, [Scalar v])
recomposeLinMap :: (LSpace w, Scalar w~Scalar v) => SubBasis v -> [w] -> (v+>w, [w])
recomposeContraLinMap :: (LinearSpace w, Scalar w ~ Scalar v, Hask.Functor f)
=> (f (Scalar w) -> w) -> f (DualVector v) -> v+>w
recomposeContraLinMapTensor
:: ( FiniteDimensional u, LinearSpace w
, Scalar u ~ Scalar v, Scalar w ~ Scalar v, Hask.Functor f )
=> (f (Scalar w) -> w) -> f (DualVector vβDualVector u) -> (vβu)+>w
uncanonicallyFromDual :: DualVector v -+> v
uncanonicallyToDual :: v -+> DualVector v
instance (Num''' s) => FiniteDimensional (ZeroDim s) where
data SubBasis (ZeroDim s) = ZeroBasis
entireBasis = ZeroBasis
enumerateSubBasis ZeroBasis = []
subbasisDimension ZeroBasis = 0
recomposeSB ZeroBasis l = (Origin, l)
recomposeSBTensor ZeroBasis _ l = (Tensor Origin, l)
recomposeLinMap ZeroBasis l = (LinearMap Origin, l)
decomposeLinMap _ = (ZeroBasis, id)
decomposeLinMapWithin ZeroBasis _ = pure id
recomposeContraLinMap _ _ = LinearMap Origin
recomposeContraLinMapTensor _ _ = LinearMap Origin
uncanonicallyFromDual = id
uncanonicallyToDual = id
instance (Num''' s, LinearSpace s) => FiniteDimensional (V0 s) where
data SubBasis (V0 s) = V0Basis
entireBasis = V0Basis
enumerateSubBasis V0Basis = []
subbasisDimension V0Basis = 0
recomposeSB V0Basis l = (V0, l)
recomposeSBTensor V0Basis _ l = (Tensor V0, l)
recomposeLinMap V0Basis l = (LinearMap V0, l)
decomposeLinMap _ = (V0Basis, id)
decomposeLinMapWithin V0Basis _ = pure id
recomposeContraLinMap _ _ = LinearMap V0
recomposeContraLinMapTensor _ _ = LinearMap V0
uncanonicallyFromDual = id
uncanonicallyToDual = id
instance FiniteDimensional β where
data SubBasis β = RealsBasis
entireBasis = RealsBasis
enumerateSubBasis RealsBasis = [1]
subbasisDimension RealsBasis = 1
recomposeSB RealsBasis [] = (0, [])
recomposeSB RealsBasis (ΞΌ:cs) = (ΞΌ, cs)
recomposeSBTensor RealsBasis bw = first Tensor . recomposeSB bw
recomposeLinMap RealsBasis (w:ws) = (LinearMap w, ws)
decomposeLinMap (LinearMap v) = (RealsBasis, (v:))
decomposeLinMapWithin RealsBasis (LinearMap v) = pure (v:)
recomposeContraLinMap fw = LinearMap . fw
recomposeContraLinMapTensor fw = arr uncurryLinearMap . LinearMap
. recomposeContraLinMap fw . fmap getTensorProduct
uncanonicallyFromDual = id
uncanonicallyToDual = id
#define FreeFiniteDimensional(V, VB, dimens, take, give) \
instance (Num''' s, LSpace s) \
=> FiniteDimensional (V s) where { \
data SubBasis (V s) = VB deriving (Show); \
entireBasis = VB; \
enumerateSubBasis VB = toList $ Mat.identity; \
subbasisDimension VB = dimens; \
uncanonicallyFromDual = id; \
uncanonicallyToDual = id; \
recomposeSB _ (take:cs) = (give, cs); \
recomposeSB b cs = recomposeSB b $ cs ++ [0]; \
recomposeSBTensor VB bw cs = case recomposeMultiple bw dimens cs of \
{(take:[], cs') -> (Tensor (give), cs')}; \
recomposeLinMap VB (take:ws') = (LinearMap (give), ws'); \
decomposeLinMap (LinearMap m) = (VB, (toList m ++)); \
decomposeLinMapWithin VB (LinearMap m) = pure (toList m ++); \
recomposeContraLinMap fw mv \
= LinearMap $ (\v -> fw $ fmap (<.>^v) mv) <$> Mat.identity; \
recomposeContraLinMapTensor fw mv = LinearMap $ \
(\v -> fromLinearMap $ recomposeContraLinMap fw \
$ fmap (\(Tensor q) -> foldl' (^+^) zeroV $ liftA2 (*^) v q) mv) \
<$> Mat.identity }
FreeFiniteDimensional(V1, V1Basis, 1, cβ , V1 cβ )
FreeFiniteDimensional(V2, V2Basis, 2, cβ:cβ , V2 cβ cβ )
FreeFiniteDimensional(V3, V3Basis, 3, cβ:cβ:cβ , V3 cβ cβ cβ )
FreeFiniteDimensional(V4, V4Basis, 4, cβ:cβ:cβ:cβ, V4 cβ cβ cβ cβ)
recomposeMultiple :: FiniteDimensional w
=> SubBasis w -> Int -> [Scalar w] -> ([w], [Scalar w])
recomposeMultiple bw n dc
| n<1 = ([], dc)
| otherwise = case recomposeSB bw dc of
(w, dc') -> first (w:) $ recomposeMultiple bw (n1) dc'
deriving instance Show (SubBasis β)
instance ( FiniteDimensional u, FiniteDimensional v
, Scalar u ~ Scalar v )
=> FiniteDimensional (u,v) where
data SubBasis (u,v) = TupleBasis !(SubBasis u) !(SubBasis v)
entireBasis = TupleBasis entireBasis entireBasis
enumerateSubBasis (TupleBasis bu bv)
= ((,zeroV)<$>enumerateSubBasis bu) ++ ((zeroV,)<$>enumerateSubBasis bv)
subbasisDimension (TupleBasis bu bv) = subbasisDimension bu + subbasisDimension bv
decomposeLinMap (LinearMap (fu, fv))
= case (decomposeLinMap (asLinearMap$fu), decomposeLinMap (asLinearMap$fv)) of
((bu, du), (bv, dv)) -> (TupleBasis bu bv, du . dv)
decomposeLinMapWithin (TupleBasis bu bv) (LinearMap (fu, fv))
= case ( decomposeLinMapWithin bu (asLinearMap$fu)
, decomposeLinMapWithin bv (asLinearMap$fv) ) of
(Left (bu', du), Left (bv', dv)) -> Left (TupleBasis bu' bv', du . dv)
(Left (bu', du), Right dv) -> Left (TupleBasis bu' bv, du . dv)
(Right du, Left (bv', dv)) -> Left (TupleBasis bu bv', du . dv)
(Right du, Right dv) -> Right $ du . dv
recomposeSB (TupleBasis bu bv) coefs = case recomposeSB bu coefs of
(u, coefs') -> case recomposeSB bv coefs' of
(v, coefs'') -> ((u,v), coefs'')
recomposeSBTensor (TupleBasis bu bv) bw cs = case recomposeSBTensor bu bw cs of
(tuw, cs') -> case recomposeSBTensor bv bw cs' of
(tvw, cs'') -> (Tensor (tuw, tvw), cs'')
recomposeLinMap (TupleBasis bu bv) ws = case recomposeLinMap bu ws of
(lmu, ws') -> first (lmuβ) $ recomposeLinMap bv ws'
recomposeContraLinMap fw dds
= recomposeContraLinMap fw (fst<$>dds)
β recomposeContraLinMap fw (snd<$>dds)
recomposeContraLinMapTensor fw dds
= uncurryLinearMap
$ LinearMap ( fromLinearMap . curryLinearMap
$ recomposeContraLinMapTensor fw (fmap (\(Tensor(tu,_))->tu) dds)
, fromLinearMap . curryLinearMap
$ recomposeContraLinMapTensor fw (fmap (\(Tensor(_,tv))->tv) dds) )
uncanonicallyFromDual = uncanonicallyFromDual *** uncanonicallyFromDual
uncanonicallyToDual = uncanonicallyToDual *** uncanonicallyToDual
deriving instance (Show (SubBasis u), Show (SubBasis v))
=> Show (SubBasis (u,v))
instance β s u v .
( FiniteDimensional u, FiniteDimensional v
, Scalar u~s, Scalar v~s, Fractional' (Scalar v) )
=> FiniteDimensional (Tensor s u v) where
data SubBasis (Tensor s u v) = TensorBasis !(SubBasis u) !(SubBasis v)
entireBasis = TensorBasis entireBasis entireBasis
enumerateSubBasis (TensorBasis bu bv)
= [ uβv | u <- enumerateSubBasis bu, v <- enumerateSubBasis bv ]
subbasisDimension (TensorBasis bu bv) = subbasisDimension bu * subbasisDimension bv
decomposeLinMap muvw = case decomposeLinMap $ curryLinearMap $ muvw of
(bu, mvwsg) -> first (TensorBasis bu) . go $ mvwsg []
where (go, _) = tensorLinmapDecompositionhelpers
decomposeLinMapWithin (TensorBasis bu bv) muvw
= case decomposeLinMapWithin bu $ curryLinearMap $ muvw of
Left (bu', mvwsg) -> let (_, (bv', ws)) = goWith bv id (mvwsg []) id
in Left (TensorBasis bu' bv', ws)
where (_, goWith) = tensorLinmapDecompositionhelpers
recomposeSB (TensorBasis bu bv) = recomposeSBTensor bu bv
recomposeSBTensor (TensorBasis bu bv) bw
= first (arr lassocTensor) . recomposeSBTensor bu (TensorBasis bv bw)
recomposeLinMap (TensorBasis bu bv) ws =
( uncurryLinearMap $ fst . recomposeLinMap bu $ unfoldr (pure . recomposeLinMap bv) ws
, drop (subbasisDimension bu * subbasisDimension bv) ws )
recomposeContraLinMap = recomposeContraLinMapTensor
recomposeContraLinMapTensor fw dds
= uncurryLinearMap . uncurryLinearMap . fmap (curryLinearMap) . curryLinearMap
$ recomposeContraLinMapTensor fw $ fmap (arr rassocTensor) dds
uncanonicallyToDual = fmap uncanonicallyToDual
>>> transposeTensor >>> fmap uncanonicallyToDual
>>> transposeTensor
uncanonicallyFromDual = fmap uncanonicallyFromDual
>>> transposeTensor >>> fmap uncanonicallyFromDual
>>> transposeTensor
tensorLinmapDecompositionhelpers
:: ( FiniteDimensional v, LSpace w , Scalar v~s, Scalar w~s )
=> ( [v+>w] -> (SubBasis v, DList w)
, SubBasis v -> DList w -> [v+>w] -> DList (v+>w)
-> (Bool, (SubBasis v, DList w)) )
tensorLinmapDecompositionhelpers = (go, goWith)
where go [] = decomposeLinMap zeroV
go (mvw:mvws) = case decomposeLinMap mvw of
(bv, cfs) -> snd (goWith bv cfs mvws (mvw:))
goWith bv prevdc [] prevs = (False, (bv, prevdc))
goWith bv prevdc (mvw:mvws) prevs = case decomposeLinMapWithin bv mvw of
Right cfs -> goWith bv (prevdc . cfs) mvws (prevs . (mvw:))
Left (bv', cfs) -> first (const True)
( goWith bv' (regoWith bv' (prevs[]) . cfs)
mvws (prevs . (mvw:)) )
regoWith _ [] = id
regoWith bv (mvw:mvws) = case decomposeLinMapWithin bv mvw of
Right cfs -> cfs . regoWith bv mvws
Left _ -> error $
"Misbehaved FiniteDimensional instance: `decomposeLinMapWithin` should,\
\\nif it cannot decompose in the given basis, do so in a proper\
\\nsuperbasis of the given one (so that any vector that could be\
\\ndecomposed in the old basis can also be decomposed in the new one)."
deriving instance (Show (SubBasis u), Show (SubBasis v))
=> Show (SubBasis (Tensor s u v))
instance β s u v .
( LSpace u, FiniteDimensional (DualVector u), FiniteDimensional v
, Scalar u~s, Scalar v~s, Fractional' (Scalar v) )
=> FiniteDimensional (LinearMap s u v) where
data SubBasis (LinearMap s u v) = LinMapBasis !(SubBasis (DualVector u)) !(SubBasis v)
entireBasis = case entireBasis of TensorBasis bu bv -> LinMapBasis bu bv
enumerateSubBasis (LinMapBasis bu bv)
= arr (fmap asLinearMap) . enumerateSubBasis $ TensorBasis bu bv
subbasisDimension (LinMapBasis bu bv) = subbasisDimension bu * subbasisDimension bv
decomposeLinMap = first (\(TensorBasis bv bu)->LinMapBasis bu bv)
. decomposeLinMap . coerce
decomposeLinMapWithin (LinMapBasis bu bv) m
= case decomposeLinMapWithin (TensorBasis bv bu) (coerce m) of
Right ws -> Right ws
Left (TensorBasis bv' bu', ws) -> Left (LinMapBasis bu' bv', ws)
recomposeSB (LinMapBasis bu bv)
= recomposeSB (TensorBasis bu bv) >>> first (arr fromTensor)
recomposeSBTensor (LinMapBasis bu bv) bw
= recomposeSBTensor (TensorBasis bu bv) bw >>> first coerce
recomposeLinMap (LinMapBasis bu bv) ws =
( coUncurryLinearMap . fmap asTensor $ fst . recomposeLinMap bv
$ unfoldr (pure . recomposeLinMap bu) ws
, drop (subbasisDimension bu * subbasisDimension bv) ws )
recomposeContraLinMap fw dds = coUncurryLinearMap . fmap fromLinearMap . curryLinearMap
$ recomposeContraLinMapTensor fw $ fmap (arr asTensor) dds
recomposeContraLinMapTensor fw dds
= uncurryLinearMap . coUncurryLinearMap
. fmap (fromLinearMap . curryLinearMap) . curryLinearMap
$ recomposeContraLinMapTensor fw $ fmap (arr $ asTensor . hasteLinearMap) dds
uncanonicallyToDual = fmap uncanonicallyToDual >>> arr asTensor
>>> transposeTensor >>> arr fromTensor >>> fmap uncanonicallyToDual
uncanonicallyFromDual = fmap uncanonicallyFromDual >>> arr asTensor
>>> transposeTensor >>> arr fromTensor >>> fmap uncanonicallyFromDual
deriving instance (Show (SubBasis (DualVector u)), Show (SubBasis v))
=> Show (SubBasis (LinearMap s u v))
infixr 0 \$
(\$) :: β u v . ( SimpleSpace u, SimpleSpace v, Scalar u ~ Scalar v )
=> (u+>v) -> v -> u
(\$) m
| du > dv = (unsafeRightInverse m $)
| du < dv = (unsafeLeftInverse m $)
| otherwise = let v's = dualBasis $ mdecomp []
(mbas, mdecomp) = decomposeLinMap m
in fst . \v -> recomposeSB mbas [v'<.>^v | v' <- v's]
where du = subbasisDimension (entireBasis :: SubBasis u)
dv = subbasisDimension (entireBasis :: SubBasis v)
pseudoInverse :: β u v . ( SimpleSpace u, SimpleSpace v, Scalar u ~ Scalar v )
=> (u+>v) -> v+>u
pseudoInverse m
| du > dv = unsafeRightInverse m
| du < dv = unsafeLeftInverse m
| otherwise = unsafeInverse m
where du = subbasisDimension (entireBasis :: SubBasis u)
dv = subbasisDimension (entireBasis :: SubBasis v)
unsafeLeftInverse :: β u v . ( SimpleSpace u, SimpleSpace v, Scalar u ~ Scalar v )
=> (u+>v) -> v+>u
unsafeLeftInverse m = unsafeInverse (m' . (fmap uncanonicallyToDual $ m))
. m' . arr uncanonicallyToDual
where m' = adjoint $ m :: DualVector v +> DualVector u
unsafeRightInverse :: β u v . ( SimpleSpace u, SimpleSpace v, Scalar u ~ Scalar v )
=> (u+>v) -> v+>u
unsafeRightInverse m = (fmap uncanonicallyToDual $ m')
. unsafeInverse (m . (fmap uncanonicallyToDual $ m'))
where m' = adjoint $ m :: DualVector v +> DualVector u
unsafeInverse :: ( SimpleSpace u, SimpleSpace v, Scalar u ~ Scalar v )
=> (u+>v) -> v+>u
unsafeInverse m = recomposeContraLinMap (fst . recomposeSB mbas) v's
where v's = dualBasis $ mdecomp []
(mbas, mdecomp) = decomposeLinMap m
riesz :: (FiniteDimensional v, InnerSpace v) => DualVector v -+> v
riesz = LinearFunction $ \dv ->
let (bas, compos) = decomposeLinMap $ sampleLinearFunction $ applyDualVector $ dv
in fst . recomposeSB bas $ compos []
sRiesz :: FiniteDimensional v => DualSpace v -+> v
sRiesz = LinearFunction $ \dv ->
let (bas, compos) = decomposeLinMap $ dv
in fst . recomposeSB bas $ compos []
coRiesz :: (LSpace v, Num''' (Scalar v), InnerSpace v) => v -+> DualVector v
coRiesz = fromFlatTensor . arr asTensor . sampleLinearFunction . inner
showsPrecAsRiesz :: ( FiniteDimensional v, InnerSpace v, Show v
, HasBasis (Scalar v), Basis (Scalar v) ~ () )
=> Int -> DualSpace v -> ShowS
showsPrecAsRiesz p dv = showParen (p>0) $ ("().<"++)
. showsPrec 7 (sRiesz$dv)
instance Show (LinearMap β (V0 β) β) where showsPrec = showsPrecAsRiesz
instance Show (LinearMap β β β) where showsPrec = showsPrecAsRiesz
instance Show (LinearMap β (V1 β) β) where showsPrec = showsPrecAsRiesz
instance Show (LinearMap β (V2 β) β) where showsPrec = showsPrecAsRiesz
instance Show (LinearMap β (V3 β) β) where showsPrec = showsPrecAsRiesz
instance Show (LinearMap β (V4 β) β) where showsPrec = showsPrecAsRiesz
infixl 7 .<
(.<) :: ( FiniteDimensional v, Num''' (Scalar v)
, InnerSpace v, LSpace w, HasBasis w, Scalar v ~ Scalar w )
=> Basis w -> v -> v+>w
bw .< v = sampleLinearFunction $ LinearFunction $ \v' -> recompose [(bw, v<.>v')]
instance Show (LinearMap s v (V0 s)) where
show _ = "zeroV"
instance (FiniteDimensional v, v ~ DualVector v, Scalar v ~ β, Show v)
=> Show (LinearMap β v (V1 β)) where
showsPrec p m = showParen (p>6) $ ("ex .< "++)
. showsPrec 7 (sRiesz $ fmap (LinearFunction (^._x)) $ m)
instance (FiniteDimensional v, v ~ DualVector v, Scalar v ~ β, Show v)
=> Show (LinearMap β v (V2 β)) where
showsPrec p m = showParen (p>6)
$ ("ex.<"++) . showsPrec 7 (sRiesz $ fmap (LinearFunction (^._x)) $ m)
. (" ^+^ ey.<"++) . showsPrec 7 (sRiesz $ fmap (LinearFunction (^._y)) $ m)
instance (FiniteDimensional v, v ~ DualVector v, Scalar v ~ β, Show v)
=> Show (LinearMap β v (V3 β)) where
showsPrec p m = showParen (p>6)
$ ("ex.<"++) . showsPrec 7 (sRiesz $ fmap (LinearFunction (^._x)) $ m)
. (" ^+^ ey.<"++) . showsPrec 7 (sRiesz $ fmap (LinearFunction (^._y)) $ m)
. (" ^+^ ez.<"++) . showsPrec 7 (sRiesz $ fmap (LinearFunction (^._z)) $ m)
instance (FiniteDimensional v, v ~ DualVector v, Scalar v ~ β, Show v)
=> Show (LinearMap β v (V4 β)) where
showsPrec p m = showParen (p>6)
$ ("ex.<"++) . showsPrec 7 (sRiesz $ fmap (LinearFunction (^._x)) $ m)
. (" ^+^ ey.<"++) . showsPrec 7 (sRiesz $ fmap (LinearFunction (^._y)) $ m)
. (" ^+^ ez.<"++) . showsPrec 7 (sRiesz $ fmap (LinearFunction (^._z)) $ m)
. (" ^+^ ew.<"++) . showsPrec 7 (sRiesz $ fmap (LinearFunction (^._w)) $ m)
(^) :: Num a => a -> Int -> a
(^) = (Hask.^)
type HilbertSpace v = (LSpace v, InnerSpace v, DualVector v ~ v)
type RealFrac' s = (IEEE s, HilbertSpace s, Scalar s ~ s)
type RealFloat' s = (RealFrac' s, Floating s)
type SimpleSpace v = ( FiniteDimensional v, FiniteDimensional (DualVector v)
, SemiInner v, SemiInner (DualVector v)
, RealFrac' (Scalar v) )
instance β s u v .
( FiniteDimensional u, LSpace v, FiniteFreeSpace v
, Scalar u~s, Scalar v~s ) => FiniteFreeSpace (LinearMap s u v) where
freeDimension _ = subbasisDimension (entireBasis :: SubBasis u)
* freeDimension ([]::[v])
toFullUnboxVect = decomposeLinMapWithin entireBasis >>> \case
Right l -> UArr.concat $ toFullUnboxVect <$> l []
unsafeFromFullUnboxVect arrv = fst . recomposeLinMap entireBasis
$ [unsafeFromFullUnboxVect $ UArr.slice (dv*j) dv arrv | j <- [0 .. du1]]
where du = subbasisDimension (entireBasis :: SubBasis u)
dv = freeDimension ([]::[v])
instance β s u v .
( LSpace u, FiniteDimensional (DualVector u), LSpace v, FiniteFreeSpace v
, Scalar u~s, Scalar v~s ) => FiniteFreeSpace (Tensor s u v) where
freeDimension _ = subbasisDimension (entireBasis :: SubBasis (DualVector u))
* freeDimension ([]::[v])
toFullUnboxVect = arr asLinearMap >>> decomposeLinMapWithin entireBasis >>> \case
Right l -> UArr.concat $ toFullUnboxVect <$> l []
unsafeFromFullUnboxVect arrv = fromLinearMap $ fst . recomposeLinMap entireBasis
$ [unsafeFromFullUnboxVect $ UArr.slice (dv*j) dv arrv | j <- [0 .. du1]]
where du = subbasisDimension (entireBasis :: SubBasis (DualVector u))
dv = freeDimension ([]::[v])
instance β s u v .
( FiniteDimensional u, LSpace v, FiniteFreeSpace v
, Scalar u~s, Scalar v~s ) => FiniteFreeSpace (LinearFunction s u v) where
freeDimension _ = subbasisDimension (entireBasis :: SubBasis u)
* freeDimension ([]::[v])
toFullUnboxVect f = toFullUnboxVect (arr f :: LinearMap s u v)
unsafeFromFullUnboxVect arrv = arr (unsafeFromFullUnboxVect arrv :: LinearMap s u v)
adjoint :: (LSpace v, LSpace w, Scalar v ~ Scalar w)
=> (v +> DualVector w) -+> (w +> DualVector v)
adjoint = arr fromTensor . transposeTensor . arr asTensor