packages feed

manifolds 0.2.0.1 → 0.2.2.0

raw patch · 14 files changed

+723/−160 lines, 14 filesbinary-addedPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Data.Manifold.TreeCover: filterDEqnSolution_static :: (WithField ℝ Manifold x, WithField ℝ Manifold y) => DifferentialEqn x y -> x `Shaded` y -> Option (x `Shaded` y)
+ Data.LinearMap.HerMetric: class HasEigenSystem m where type family EigenVector m :: *
+ Data.LinearMap.HerMetric: completeBasisValues :: FiniteDimensional v => [v]
+ Data.LinearMap.HerMetric: eigenSystem :: HasEigenSystem m => m -> ([Stiefel1 (EigenVector m)], [(EigenVector m, DualSpace (EigenVector m))])
+ Data.LinearMap.HerMetric: instance (Data.LinearMap.HerMetric.HasMetric v, Data.VectorSpace.FiniteDimensional.FiniteDimensional w, GHC.Show.Show (Data.LinearMap.HerMetric.DualSpace v), GHC.Show.Show w, Data.VectorSpace.Scalar v ~ s, Data.VectorSpace.Scalar w ~ s) => GHC.Show.Show (Data.LinearMap.Category.Linear s v w)
+ Data.LinearMap.HerMetric: instance (Data.LinearMap.HerMetric.HasMetric v, Data.VectorSpace.Scalar v ~ Data.Manifold.Types.Primitive.ℝ) => Data.LinearMap.HerMetric.HasEigenSystem (Data.LinearMap.HerMetric.HerMetric v)
+ Data.LinearMap.HerMetric: instance (Data.LinearMap.HerMetric.HasMetric v, Data.VectorSpace.Scalar v ~ Data.Manifold.Types.Primitive.ℝ) => Data.LinearMap.HerMetric.HasEigenSystem (Data.LinearMap.HerMetric.HerMetric v, Data.LinearMap.HerMetric.HerMetric v)
+ Data.LinearMap.HerMetric: instance (Data.LinearMap.HerMetric.HasMetric v, Data.VectorSpace.Scalar v ~ Data.Manifold.Types.Primitive.ℝ) => Data.LinearMap.HerMetric.HasEigenSystem (Data.LinearMap.HerMetric.HerMetric' v)
+ Data.LinearMap.HerMetric: instance (Data.LinearMap.HerMetric.HasMetric v, Data.VectorSpace.Scalar v ~ Data.Manifold.Types.Primitive.ℝ) => Data.LinearMap.HerMetric.HasEigenSystem (Data.LinearMap.HerMetric.HerMetric' v, Data.LinearMap.HerMetric.HerMetric' v)
+ Data.LinearMap.HerMetric: outerProducts :: (HasMetric v, FiniteDimensional w, Scalar v ~ s, Scalar w ~ s) => [(w, DualSpace v)] -> Linear s v w
+ Data.LinearMap.HerMetric: projector's :: HasMetric v => [v] -> HerMetric' v
+ Data.LinearMap.HerMetric: projectors :: HasMetric v => [DualSpace v] -> HerMetric v
+ Data.Manifold.PseudoAffine: class (PseudoAffine x, PseudoAffine ξ, Scalar (Needle x) ~ Scalar (Needle ξ)) => LocallyCoercible x ξ
+ Data.Manifold.PseudoAffine: instance (Data.Manifold.PseudoAffine.PseudoAffine a, Data.Manifold.PseudoAffine.PseudoAffine b, Data.Manifold.PseudoAffine.PseudoAffine c) => Data.Manifold.PseudoAffine.LocallyCoercible ((a, b), c) (a, (b, c))
+ Data.Manifold.PseudoAffine: instance (Data.Manifold.PseudoAffine.PseudoAffine a, Data.Manifold.PseudoAffine.PseudoAffine b, Data.Manifold.PseudoAffine.PseudoAffine c) => Data.Manifold.PseudoAffine.LocallyCoercible ((a, b), c) (a, b, c)
+ Data.Manifold.PseudoAffine: instance (Data.Manifold.PseudoAffine.PseudoAffine a, Data.Manifold.PseudoAffine.PseudoAffine b, Data.Manifold.PseudoAffine.PseudoAffine c) => Data.Manifold.PseudoAffine.LocallyCoercible (a, (b, c)) ((a, b), c)
+ Data.Manifold.PseudoAffine: instance (Data.Manifold.PseudoAffine.PseudoAffine a, Data.Manifold.PseudoAffine.PseudoAffine b, Data.Manifold.PseudoAffine.PseudoAffine c) => Data.Manifold.PseudoAffine.LocallyCoercible (a, (b, c)) (a, b, c)
+ Data.Manifold.PseudoAffine: instance (Data.Manifold.PseudoAffine.PseudoAffine a, Data.Manifold.PseudoAffine.PseudoAffine b, Data.Manifold.PseudoAffine.PseudoAffine c) => Data.Manifold.PseudoAffine.LocallyCoercible (a, b, c) ((a, b), c)
+ Data.Manifold.PseudoAffine: instance (Data.Manifold.PseudoAffine.PseudoAffine a, Data.Manifold.PseudoAffine.PseudoAffine b, Data.Manifold.PseudoAffine.PseudoAffine c) => Data.Manifold.PseudoAffine.LocallyCoercible (a, b, c) (a, (b, c))
+ Data.Manifold.PseudoAffine: instance (Data.VectorSpace.FiniteDimensional.SmoothScalar s, Data.Manifold.PseudoAffine.LinearManifold b, Data.VectorSpace.Scalar b ~ s) => Data.Manifold.PseudoAffine.LocallyCoercible (Data.VectorSpace.FiniteDimensional.FinVecArrRep t b s) b
+ Data.Manifold.PseudoAffine: instance (Data.VectorSpace.FiniteDimensional.SmoothScalar s, Data.Manifold.PseudoAffine.LinearManifold b, Data.VectorSpace.Scalar b ~ s) => Data.Manifold.PseudoAffine.LocallyCoercible b (Data.VectorSpace.FiniteDimensional.FinVecArrRep t b s)
+ Data.Manifold.PseudoAffine: instance Data.Manifold.PseudoAffine.LocallyCoercible ((Data.Manifold.Types.Primitive.ℝ, Data.Manifold.Types.Primitive.ℝ), Data.Manifold.Types.Primitive.ℝ) ((Data.Manifold.Types.Primitive.ℝ, Data.Manifold.Types.Primitive.ℝ), Data.Manifold.Types.Primitive.ℝ)
+ Data.Manifold.PseudoAffine: instance Data.Manifold.PseudoAffine.LocallyCoercible (Data.Manifold.Types.Primitive.ℝ Data.CoNat.^ 'Data.CoNat.S 'Data.CoNat.Z) Data.Manifold.Types.Primitive.ℝ
+ Data.Manifold.PseudoAffine: instance Data.Manifold.PseudoAffine.LocallyCoercible (Data.Manifold.Types.Primitive.ℝ, (Data.Manifold.Types.Primitive.ℝ, Data.Manifold.Types.Primitive.ℝ)) (Data.Manifold.Types.Primitive.ℝ, (Data.Manifold.Types.Primitive.ℝ, Data.Manifold.Types.Primitive.ℝ))
+ Data.Manifold.PseudoAffine: instance Data.Manifold.PseudoAffine.LocallyCoercible (Data.Manifold.Types.Primitive.ℝ, Data.Manifold.Types.Primitive.ℝ) (Data.Manifold.Types.Primitive.ℝ, Data.Manifold.Types.Primitive.ℝ)
+ Data.Manifold.PseudoAffine: instance Data.Manifold.PseudoAffine.LocallyCoercible Data.Manifold.Types.Primitive.ℝ (Data.Manifold.Types.Primitive.ℝ Data.CoNat.^ 'Data.CoNat.S 'Data.CoNat.Z)
+ Data.Manifold.PseudoAffine: instance Data.Manifold.PseudoAffine.LocallyCoercible Data.Manifold.Types.Primitive.ℝ Data.Manifold.Types.Primitive.ℝ
+ Data.Manifold.PseudoAffine: instance Data.VectorSpace.FiniteDimensional.SmoothScalar s => Data.Manifold.PseudoAffine.LocallyCoercible (Data.VectorSpace.FiniteDimensional.FinVecArrRep t b s) (Data.VectorSpace.FiniteDimensional.FinVecArrRep t b s)
+ Data.Manifold.PseudoAffine: locallyTrivialDiffeomorphism :: LocallyCoercible x ξ => x -> ξ
+ Data.Manifold.TreeCover: (|±|) :: WithField ℝ EuclidSpace x => x -> [Needle x] -> Shade' x
+ Data.Manifold.TreeCover: class (WithField ℝ Manifold y) => Refinable y where subShade' (Shade' ac ae) tsh = all ((< 1) . minusLogOcclusion' tsh) [ac .+~^ σ *^ v | σ <- [0, 1], v <- eigenCoSpan' ae] refineShade' (Shade' c e) (Shade' ζ η) | μe < 1 && μη < 1 = return $ Shade' iCtr iExpa | otherwise = empty where [c', ζ'] = [ctr .+~^ linearCombo [(v, 1 / (1 + metricSq oExpa w)) | v <- (*^) <$> [- 1, 1] <*> span, let p = ctr .+~^ v :: y Option (Just w) = p .-~. oCtr] | ctr <- [c, ζ] | span <- eigenCoSpan' <$> [e, η] | (oCtr, oExpa) <- [(ζ, η), (c, e)]] Option (Just c'2ζ') = ζ' .-~. c' Option (Just c2ζ') = ζ' .-~. c Option (Just ζ2c') = c' .-~. ζ μc = metricSq e c2ζ' μζ = metricSq η ζ2c' iCtr = c' .+~^ c'2ζ' ^* (μζ / (μc + μζ)) Option (Just rc) = c .-~. iCtr Option (Just rζ) = ζ .-~. iCtr rcⰰ = toDualWith e rc rζⰰ = toDualWith η rζ μe = rcⰰ <.>^ rc μη = rζⰰ <.>^ rζ iExpa = (e ^+^ η) ^/ 2 ^+^ projector rcⰰ ^/ (1 - μe) ^+^ projector rζⰰ ^/ (1 - μη) convolveShade' (Shade' y₀ ey) (Shade' δ₀ eδ) = Shade' (y₀ .+~^ δ₀) (projectors [f ^* ζ crl | (f, _) <- eδsp | crl <- corelap]) where (_, eδsp) = eigenSystem (ey, eδ) corelap = map (metric ey . snd) eδsp ζ = case filter (> 0) corelap of { [] -> const 0 nzrelap -> let cre₁ = 1 / minimum nzrelap cre₂ = maximum nzrelap edgeFactor = sqrt ((1 + cre₁) ^ 2 + (1 + cre₂) ^ 2) / (sqrt (1 + cre₁ ^ 2) + sqrt (1 + cre₂ ^ 2)) in \case { 0 -> 0 sq -> edgeFactor / (recip sq + 1) } }
+ Data.Manifold.TreeCover: coerceShade :: (IsShade shade, Manifold x, Manifold y, LocallyCoercible x y) => shade x -> shade y
+ Data.Manifold.TreeCover: constShaded :: y -> ShadeTree x -> x `Shaded` y
+ Data.Manifold.TreeCover: convolveShade' :: Refinable y => Shade' y -> Shade' (Needle y) -> Shade' y
+ Data.Manifold.TreeCover: filterDEqnSolution_loc :: (WithField ℝ Manifold x, Refinable y) => DifferentialEqn x y -> ((x, Shade' y), NonEmpty (x, Shade' y)) -> Option (Shade' y)
+ Data.Manifold.TreeCover: indexShadeTree :: WithField ℝ Manifold x => ShadeTree x -> Int -> Either Int ([ShadeTree x], x)
+ Data.Manifold.TreeCover: instance (Data.Manifold.TreeCover.Refinable a, Data.Manifold.TreeCover.Refinable b) => Data.Manifold.TreeCover.Refinable (a, b)
+ Data.Manifold.TreeCover: instance Data.Manifold.TreeCover.Refinable Data.Manifold.Types.Primitive.ℝ
+ Data.Manifold.TreeCover: pointsCovers :: WithField ℝ Manifold x => [x] -> [Shade x]
+ Data.Manifold.TreeCover: refineShade' :: Refinable y => Shade' y -> Shade' y -> Option (Shade' y)
+ Data.Manifold.TreeCover: stripShadedUntopological :: x `Shaded` y -> ShadeTree x
+ Data.Manifold.Types: type LocalLinear x y = Linear (Scalar (Needle x)) (Needle x) (Needle y)
+ Data.Manifold.Web: PointsWeb :: ShadeTree x -> Vector (y, NeighbourRefs) -> PointsWeb x y
+ Data.Manifold.Web: [webNodeAssocData] :: PointsWeb x y -> Vector (y, NeighbourRefs)
+ Data.Manifold.Web: [webNodeRsc] :: PointsWeb x y -> ShadeTree x
+ Data.Manifold.Web: data PointsWeb :: * -> * -> *
+ Data.Manifold.Web: filterDEqnSolution_static :: (WithField ℝ Manifold x, Refinable y) => DifferentialEqn x y -> PointsWeb x (Shade' y) -> Option (PointsWeb x (Shade' y))
+ Data.Manifold.Web: fromShadeTree :: WithField ℝ Manifold x => (Shade x -> Metric x) -> ShadeTree x -> PointsWeb x ()
+ Data.Manifold.Web: fromShadeTree_auto :: WithField ℝ Manifold x => ShadeTree x -> PointsWeb x ()
+ Data.Manifold.Web: fromShaded :: WithField ℝ Manifold x => (Shade x -> Metric x) -> (x `Shaded` y) -> PointsWeb x y
+ Data.Manifold.Web: fromWebNodes :: WithField ℝ Manifold x => (Shade x -> Metric x) -> [(x, y)] -> PointsWeb x y
+ Data.Manifold.Web: indexWeb :: WithField ℝ Manifold x => PointsWeb x y -> WebNodeId -> Option (x, y)
+ Data.Manifold.Web: instance (Control.DeepSeq.NFData x, Control.DeepSeq.NFData (Data.Manifold.PseudoAffine.Needle' x), Control.DeepSeq.NFData y) => Control.DeepSeq.NFData (Data.Manifold.Web.PointsWeb x y)
+ Data.Manifold.Web: instance Data.Foldable.Constrained.Foldable (Data.Manifold.Web.PointsWeb x) (->) (->)
+ Data.Manifold.Web: instance Data.Foldable.Foldable (Data.Manifold.Web.PointsWeb a)
+ Data.Manifold.Web: instance Data.Traversable.Constrained.Traversable (Data.Manifold.Web.PointsWeb x) (Data.Manifold.Web.PointsWeb x) (->) (->)
+ Data.Manifold.Web: instance Data.Traversable.Traversable (Data.Manifold.Web.PointsWeb a)
+ Data.Manifold.Web: instance GHC.Base.Functor (Data.Manifold.Web.PointsWeb a)
+ Data.Manifold.Web: instance GHC.Generics.Constructor Data.Manifold.Web.C1_0PointsWeb
+ Data.Manifold.Web: instance GHC.Generics.Datatype Data.Manifold.Web.D1PointsWeb
+ Data.Manifold.Web: instance GHC.Generics.Generic (Data.Manifold.Web.PointsWeb a b)
+ Data.Manifold.Web: instance GHC.Generics.Selector Data.Manifold.Web.S1_0_0PointsWeb
+ Data.Manifold.Web: instance GHC.Generics.Selector Data.Manifold.Web.S1_0_1PointsWeb
+ Data.Manifold.Web: localFocusWeb :: WithField ℝ Manifold x => PointsWeb x y -> PointsWeb x ((x, y), [(x, y)])
+ Data.Manifold.Web: type NeighbourRefs = Vector WebNodeId
+ Data.Manifold.Web: type WebNodeId = Int
+ Data.Manifold.Web: webEdges :: WithField ℝ Manifold x => PointsWeb x y -> [((x, y), (x, y))]
- Data.LinearMap.HerMetric: class (HasBasis v, HasTrie (Basis v), SmoothScalar (Scalar v)) => FiniteDimensional v where completeBasis = liftA2 (\ dim f -> f <$> [0 .. dim - 1]) dimension indexBasis asPackedVector v = fromList $ snd <$> decompose v asPackedMatrix = defaultAsPackedMatrix where defaultAsPackedMatrix :: forall v w s. (FiniteDimensional v, FiniteDimensional w, s ~ Scalar v, s ~ Scalar w) => (v :-* w) -> Matrix s defaultAsPackedMatrix m = fromColumns $ asPackedVector . atBasis m <$> cb where (Tagged cb) = completeBasis :: Tagged v [Basis v] fromPackedVector v = result where result = recompose $ zip cb (toList v) cb = witness completeBasis result fromPackedMatrix = defaultFromPackedMatrix where defaultFromPackedMatrix :: forall v w s. (FiniteDimensional v, FiniteDimensional w, s ~ Scalar v, s ~ Scalar w) => Matrix s -> (v :-* w) defaultFromPackedMatrix m = linear $ fromPackedVector . app m . asPackedVector
+ Data.LinearMap.HerMetric: class (HasBasis v, HasTrie (Basis v), SmoothScalar (Scalar v)) => FiniteDimensional v where completeBasis = liftA2 (\ dim f -> f <$> [0 .. dim - 1]) dimension indexBasis completeBasisValues = defCBVs where defCBVs :: forall v. FiniteDimensional v => [v] defCBVs = basisValue <$> cb where Tagged cb = completeBasis :: Tagged v [Basis v] asPackedVector v = fromList $ snd <$> decompose v asPackedMatrix = defaultAsPackedMatrix where defaultAsPackedMatrix :: forall v w s. (FiniteDimensional v, FiniteDimensional w, s ~ Scalar v, s ~ Scalar w) => (v :-* w) -> Matrix s defaultAsPackedMatrix m = fromColumns $ asPackedVector . atBasis m <$> cb where (Tagged cb) = completeBasis :: Tagged v [Basis v] fromPackedVector v = result where result = recompose $ zip cb (toList v) cb = witness completeBasis result fromPackedMatrix = defaultFromPackedMatrix where defaultFromPackedMatrix :: forall v w s. (FiniteDimensional v, FiniteDimensional w, s ~ Scalar v, s ~ Scalar w) => Matrix s -> (v :-* w) defaultFromPackedMatrix m = linear $ fromPackedVector . app m . asPackedVector
- Data.Manifold.PseudoAffine: euclideanMetric :: EuclidSpace x => Tagged x (Metric x)
+ Data.Manifold.PseudoAffine: euclideanMetric :: EuclidSpace x => proxy x -> Metric x
- Data.Manifold.TreeCover: intersectShade's :: WithField ℝ Manifold y => [Shade' y] -> Option (Shade' y)
+ Data.Manifold.TreeCover: intersectShade's :: Refinable y => NonEmpty (Shade' y) -> Option (Shade' y)
- Data.Manifold.TreeCover: twigsWithEnvirons :: WithField ℝ Manifold x => ShadeTree x -> [(ShadeTree x, [ShadeTree x])]
+ Data.Manifold.TreeCover: twigsWithEnvirons :: WithField ℝ Manifold x => ShadeTree x -> [((Int, ShadeTree x), [(Int, ShadeTree x)])]
- Data.Manifold.TreeCover: type DifferentialEqn x y = Shade' (x, y) -> Shade' (LocalLinear x y)
+ Data.Manifold.TreeCover: type DifferentialEqn x y = Shade (x, y) -> Shade' (LocalLinear x y)

Files

Data/LinearMap/Category.hs view
@@ -70,6 +70,12 @@ identMat = DenseLinear $ HMat.ident n  where (Tagged n) = dimension :: Tagged v Int +-- | Coerce the matrix representations of two linear mappings; the result makes+--   sense iff the spaces are canonically isomorphic (certainly if they+--   are good instances of 'Data.Manifold.PseudoAffine.LocallyCoercible').+unsafeCoerceLinear :: Linear s a b -> Linear s c d+unsafeCoerceLinear (DenseLinear m) = DenseLinear m+ convertLinear :: ∀ v w s . ( FiniteDimensional v, FiniteDimensional w                            , Scalar v ~ s, Scalar w ~ s )                    => Isomorphism (->) (v:-*w) (Linear s v w)
Data/LinearMap/HerMetric.hs view
@@ -21,7 +21,7 @@   , toDualWith, fromDualWith   , metricSq, metricSq', metric, metric', metrics, metrics'   -- * Defining metrics-  , projector, projector'+  , projector, projector', projectors, projector's   , euclideanMetric'   -- * Metrics induce inner products   , spanHilbertSubspace@@ -35,8 +35,10 @@   , transformMetric, transformMetric', dualCoCoProduct   , dualiseMetric, dualiseMetric'   , recipMetric, recipMetric'+  -- ** Eigenvectors   , eigenSpan, eigenSpan'   , eigenCoSpan, eigenCoSpan'+  , eigenSystem, HasEigenSystem, EigenVector   , metriNormalise, metriNormalise'   , metriScale', metriScale   , adjoint@@ -55,6 +57,7 @@   , Stiefel1(..)   , linMapAsTensProd, linMapFromTensProd   , covariance+  , outerProducts   ) where      @@ -166,15 +169,25 @@ --   describing the ellipsoid span of the vectors /e/&#x2080; and 2&#x22c5;/e/&#x2081;. --   Metrics generated this way are positive definite if no negative coefficients have --   been introduced with the '*^' scaling operator or with '^-^'.+--   +--   Note: @projector a ^+^ projector b ^+^ ...@ is more efficiently written as+--   @projectors [a, b, ...]@ projector :: HasMetric v => DualSpace v -> HerMetric v-projector u = matrixMetric $ HMat.outer uDecomp uDecomp- where uDecomp = asPackedVector u+projector u = HerMetric . pure $ u ⊗ u  projector' :: HasMetric v => v -> HerMetric' v-projector' v = matrixMetric' $ HMat.outer vDecomp vDecomp- where vDecomp = asPackedVector v+projector' v = HerMetric' . pure $ v ⊗ v +-- | Efficient shortcut for the 'sumV' of multiple 'projector's.+projectors :: HasMetric v => [DualSpace v] -> HerMetric v+projectors [] = zeroV+projectors us = HerMetric . pure . outerProducts $ zip us us +projector's :: HasMetric v => [v] -> HerMetric' v+projector's [] = zeroV+projector's vs = HerMetric' . pure . outerProducts $ zip vs vs++ singularMetric :: forall v . HasMetric v => HerMetric v singularMetric = matrixMetric $ HMat.scale (1/0) (HMat.ident dim)  where (Tagged dim) = dimension :: Tagged v Int@@ -305,14 +318,17 @@   --- | The eigenbasis of a /positive definite/ metric, with each eigenvector scaled---   to the square root of the eigenvalue.+-- | The eigenbasis of a metric, with each eigenvector scaled to the+--   square root of the eigenvalue. If the metric is not positive+--   definite (i.e. if it has zero eigenvalues), then the 'eigenSpan'+--   will contain zero vectors. --    --   This constitutes, in a sense, --   a decomposition of a metric into a set of 'projector'' vectors. If those---   are 'sumV'ed again, the original metric is obtained. (This holds even for---   non-Hilbert/Banach spaces, even though the concept of eigenbasis and---   &#x201c;scaled length&#x201d; doesn't really makes sense then in the usual way!)+--   are 'sumV'ed again (use 'projectors's' for this), then the original metric+--   is obtained. (This holds even for non-Hilbert/Banach spaces,+--   although the concept of eigenbasis and+--   &#x201c;scaled length&#x201d; doesn't really make sense there.) eigenSpan :: (HasMetric v, Scalar v ~ ℝ) => HerMetric' v -> [v] eigenSpan (HerMetric' Nothing) = [] eigenSpan (HerMetric' (Just (DenseLinear m))) = map fromPackedVector eigSpan@@ -325,18 +341,117 @@  where (μs,vsm) = HMat.eigSH' m        eigSpan = zipWith (HMat.scale . sqrt) (HMat.toList μs) (HMat.toColumns vsm) +-- | The reciprocal-space counterparts of the nonzero-EV eigenvectors, as can+--   be obtained from 'eigenSpan'. The systems of vectors/dual vectors+--   behave as orthonormal groups WRT each other, i.e. for each @f@+--   in @'eigenCoSpan' m@ there will be exactly one @v@ in @'eigenSpan' m@+--   such that @f<.>^v ≡ 1@; the other @f<.>^v@ pairings are zero.+-- +--   Furthermore, @'metric' m f ≡ 1@ for each @f@ in the co-span, which might+--   be seen as the actual defining characteristic of these span/co-span systems. eigenCoSpan :: (HasMetric v, Scalar v ~ ℝ) => HerMetric' v -> [DualSpace v] eigenCoSpan (HerMetric' Nothing) = [] eigenCoSpan (HerMetric' (Just (DenseLinear m))) = map fromPackedVector eigSpan  where (μs,vsm) = HMat.eigSH' m-       eigSpan = zipWith (HMat.scale . recip . sqrt) (HMat.toList μs) (HMat.toColumns vsm)+       eigSpan = map (uncurry $ HMat.scale . recip . sqrt)+                 . filter ((>0) . fst)+                 $ zip (HMat.toList μs) (HMat.toColumns vsm) eigenCoSpan' :: (HasMetric v, Scalar v ~ ℝ) => HerMetric v -> [v] eigenCoSpan' (HerMetric Nothing) = [] eigenCoSpan' (HerMetric (Just (DenseLinear m))) = map fromPackedVector eigSpan  where (μs,vsm) = HMat.eigSH' m-       eigSpan = zipWith (HMat.scale . recip . sqrt) (HMat.toList μs) (HMat.toColumns vsm)+       eigSpan = map (uncurry $ HMat.scale . recip . sqrt)+                 . filter ((>0) . fst)+                 $ zip (HMat.toList μs) (HMat.toColumns vsm)  +class HasEigenSystem m where+  type EigenVector m :: *+  -- | Generalised combination of 'eigenSpan' and 'eigenCoSpan'; this will give a+  --   maximum spanning set of vector-covector pairs @(f,v)@ such that @f<.>^v ≡ 1@+  --   and @metric m f ≡ 1@, whereas all @f@ and @v'@ from different tuples+  --   are orthogonal.+  --   It also yields the /kernel/ of singular metric, spanned by a set of stiefel-manifold+  --   points, i.e. vectors of unspecified length that correspond to the eigenvalue 0.+  -- +  --   You may also consider this as a /factorisation/ of a linear operator+  --   @𝐴 : 𝑉 → 𝑉'@ into mappings @𝑅 : 𝑉 → ℝⁿ@ and @𝐿 : ℝⁿ → 𝑉'@ (or, equivalently+  --   because ℝⁿ is a Hilbert space, @𝑅' : ℝⁿ → V'@ and @𝐿' : V → ℝⁿ@, which+  --   gives you an SVD-style inverse).+  eigenSystem :: m -> ( [Stiefel1 (EigenVector m)]+                      , [(EigenVector m, DualSpace (EigenVector m))] )++instance (HasMetric v, Scalar v ~ ℝ) => HasEigenSystem (HerMetric' v) where+  type EigenVector (HerMetric' v) = v+  eigenSystem (HerMetric' Nothing) = (fmap Stiefel1 completeBasisValues, [])+  eigenSystem (HerMetric' (Just (DenseLinear m))) = concat***concat $ unzip eigSpan+   where (μs,vsm) = HMat.eigSH' m+         eigSpan = zipWith (\μ v+                    -> if μ>0+                        then let sμ = sqrt μ+                             in ([], [( fromPackedVector $ HMat.scale sμ v+                                      , fromPackedVector $ HMat.scale (recip sμ) v )])+                        else ([Stiefel1 $ fromPackedVector v], [])+                   ) (HMat.toList μs) (HMat.toColumns vsm)++instance (HasMetric v, Scalar v ~ ℝ) => HasEigenSystem (HerMetric v) where+  type EigenVector (HerMetric v) = DualSpace v+  eigenSystem (HerMetric Nothing) = (fmap Stiefel1 completeBasisValues, [])+  eigenSystem (HerMetric (Just (DenseLinear m))) = concat***concat $ unzip eigSpan+   where (μs,vsm) = HMat.eigSH' m+         eigSpan = zipWith (\μ v+                    -> if μ>0+                        then let sμ = sqrt μ+                             in ([], [( fromPackedVector $ HMat.scale sμ v+                                      , fromPackedVector $ HMat.scale (recip sμ) v )])+                        else ([Stiefel1 $ fromPackedVector v], [])+                   ) (HMat.toList μs) (HMat.toColumns vsm)++instance (HasMetric v, Scalar v ~ ℝ) => HasEigenSystem (HerMetric' v, HerMetric' v) where+  type EigenVector (HerMetric' v, HerMetric' v) = v+  eigenSystem (n, HerMetric' (Just (DenseLinear m))) | not $ null nSpan+                                      = (++nKernel).concat***concat $ unzip eigSpan+   where (μs,vsm) = HMat.eigSH' $ fromv2ℝn HMat.<> m HMat.<> fromℝn2v'+                    -- m :: v' -> v+         eigSpan = zipWith (\μ v+                    -> if μ>0+                        then let sμ = sqrt μ+                             in ([], [( fromPackedVector $+                                        fromℝn2v HMat.#> HMat.scale sμ v+                                      , fromPackedVector $+                                        fromℝn2v' HMat.#> HMat.scale (recip sμ) v )+                                      ])+                        else ([Stiefel1 $ fromPackedVector v], [])+                   ) (HMat.toList μs) (HMat.toColumns vsm)+         fromv2ℝn = HMat.fromRows $ map (asPackedVector . snd) nSpan+         fromℝn2v' = HMat.tr fromv2ℝn+         fromℝn2v = HMat.fromColumns $ map (asPackedVector . fst) nSpan+         (nKernel, nSpan) = eigenSystem n+  eigenSystem (_, HerMetric' Nothing) = (fmap Stiefel1 completeBasisValues, [])++instance (HasMetric v, Scalar v ~ ℝ) => HasEigenSystem (HerMetric v, HerMetric v) where+  type EigenVector (HerMetric v, HerMetric v) = DualSpace v+  eigenSystem (n, HerMetric (Just (DenseLinear m))) | not $ null nSpan+                                      = (++nKernel).concat***concat $ unzip eigSpan+   where (μs,vsm) = HMat.eigSH' $ fromv'2ℝn HMat.<> m HMat.<> fromℝn2v+                    -- m :: v -> v'+         eigSpan = zipWith (\μ v+                    -> if μ>0+                        then let sμ = sqrt μ+                             in ([], [( fromPackedVector $+                                        fromℝn2v' HMat.#> HMat.scale sμ v+                                      , fromPackedVector $+                                        fromℝn2v HMat.#> HMat.scale (recip sμ) v )+                                      ])+                        else ([Stiefel1 $ fromPackedVector v], [])+                   ) (HMat.toList μs) (HMat.toColumns vsm)+         fromv'2ℝn = HMat.fromRows $ map (asPackedVector . snd) nSpan+         fromℝn2v = HMat.tr fromv'2ℝn+         fromℝn2v' = HMat.fromColumns $ map (asPackedVector . fst) nSpan+         (nKernel, nSpan) = eigenSystem n+  eigenSystem (_, HerMetric Nothing) = (fmap Stiefel1 completeBasisValues, [])++ -- | Constraint that a space's scalars need to fulfill so it can be used for 'HerMetric'. type MetricScalar s = ( SmoothScalar s                       , Ord s  -- We really rather wouldn't require this...@@ -562,13 +677,11 @@ factoriseMetric :: ∀ v w . (HasMetric v, HasMetric w, Scalar v ~ ℝ, Scalar w ~ ℝ)                => HerMetric (v,w) -> (HerMetric v, HerMetric w) factoriseMetric (HerMetric Nothing) = (HerMetric Nothing, HerMetric Nothing)-factoriseMetric met = (sumV *** sumV) . unzip-                   $ (projector.fst &&& projector.snd) <$> eigenSpan' met+factoriseMetric met = (projectors *** projectors) . unzip $ eigenSpan' met  factoriseMetric' :: ∀ v w . (HasMetric v, HasMetric w, Scalar v ~ ℝ, Scalar w ~ ℝ)                => HerMetric' (v,w) -> (HerMetric' v, HerMetric' w)-factoriseMetric' met = (sumV *** sumV) . unzip-                   $ (projector'.fst &&& projector'.snd) <$> eigenSpan met+factoriseMetric' met = (projector's *** projector's) . unzip $ eigenSpan met  productMetric :: ∀ v w . (HasMetric v, HasMetric w, Scalar v ~ ℝ, Scalar w ~ ℝ)                => HerMetric v -> HerMetric w -> HerMetric (v,w)@@ -617,15 +730,16 @@  metricAsLength :: HerMetric ℝ -> ℝ metricAsLength m = case metricSq m 1 of-   o | o > 0    -> recip o-     | o < 0    -> error "Metric fails to be positive definite!"-     | o == 0   -> error "Trying to use zero metric as length."+   o | o > 0      -> sqrt $ recip o+     | o < 0      -> error "Metric fails to be positive definite!"+     | o == 0     -> error "Trying to use zero metric as length."+     | otherwise  -> error "Metric yields NaN."  metricFromLength :: ℝ -> HerMetric ℝ metricFromLength = projector . recip  metric'AsLength :: HerMetric' ℝ -> ℝ-metric'AsLength = recip . (`metric'`1)  -- do we really want `recip` here?+metric'AsLength = sqrt . (`metric'`1)   spanHilbertSubspace :: ∀ s v w@@ -678,7 +792,7 @@     | null eigSp  = showString "zeroV"     | otherwise   = showParen (p>5)                       . foldr1 ((.) . (.(" ^+^ "++)))-                      $ ((("projector "++).).showsPrec 6)<$>eigSp+                      $ ((("projector "++).).showsPrec 10)<$>eigSp    where eigSp = eigenSpan' m  instance (HasMetric v, Scalar v ~ Double, Show v) => Show (HerMetric' v) where@@ -686,7 +800,7 @@     | null eigSp  = showString "zeroV"     | otherwise   = showParen (p>5)                       . foldr1 ((.) . (.(" ^+^ "++)))-                      $ ((("projector' "++).).showsPrec 6)<$>eigSp+                      $ ((("projector' "++).).showsPrec 10)<$>eigSp    where eigSp = eigenSpan m  @@ -705,3 +819,27 @@                     => DualSpace v ⊗ w -> v:-*w linMapFromTensProd (DensTensProd m) = linear $                          asPackedVector >>> HMat.app m >>> fromPackedVector++++(⊗) :: (HasMetric v, FiniteDimensional w, Scalar v ~ s, Scalar w ~ s)+                    => w -> DualSpace v -> Linear s v w+w ⊗ v' = DenseLinear $ HMat.outer wDecomp v'Decomp+ where wDecomp = asPackedVector w+       v'Decomp = asPackedVector v'++outerProducts :: (HasMetric v, FiniteDimensional w, Scalar v ~ s, Scalar w ~ s)+                    => [(w, DualSpace v)] -> Linear s v w+outerProducts [] = zeroV+outerProducts pds = DenseLinear $ HMat.fromColumns (asPackedVector.fst<$>pds)+                          HMat.<> HMat.fromRows    (asPackedVector.snd<$>pds)++instance ∀ v w s . ( HasMetric v, FiniteDimensional w+                   , Show (DualSpace v), Show w, Scalar v ~ s, Scalar w ~ s )+    => Show (Linear s v w) where+  showsPrec p f = showParen (p>9) $ ("outerProducts "++)+        . shows [ (w, v' :: DualSpace v)+                | (v,v') <- zip completeBasisValues completeBasisValues+                , let w = f $ v ]+  +
Data/Manifold/PseudoAffine.hs view
@@ -32,6 +32,7 @@ {-# LANGUAGE FunctionalDependencies   #-} {-# LANGUAGE FlexibleContexts         #-} {-# LANGUAGE LiberalTypeSynonyms      #-}+{-# LANGUAGE DataKinds                #-} {-# LANGUAGE GADTs                    #-} {-# LANGUAGE RankNTypes               #-} {-# LANGUAGE TupleSections            #-}@@ -64,7 +65,7 @@             -- ** Local functions             , LocalLinear, LocalAffine             -- * Misc-            , palerp+            , palerp, LocallyCoercible(..)             ) where      @@ -78,6 +79,7 @@ import Data.Fixed  import Data.VectorSpace+import Data.Embedding import Data.LinearMap import Data.LinearMap.HerMetric import Data.LinearMap.Category@@ -219,6 +221,29 @@ class (PseudoAffine m, LinearManifold (Needle m), Interior m ~ m) => Manifold m instance (PseudoAffine m, LinearManifold (Needle m), Interior m ~ m) => Manifold m +++-- | Instances of this class must be diffeomorphic manifolds, and even have+--   /canonically isomorphic/ tangent spaces, so that+--   @'fromPackedVector' . 'asPackedVector' :: 'Needle' x -> 'Needle' ξ@+--   defines a meaningful “representational identity“ between these spaces.+class (PseudoAffine x, PseudoAffine ξ, Scalar (Needle x) ~ Scalar (Needle ξ))+         => LocallyCoercible x ξ where+  -- | Must be compatible with the canonical isomorphism on the tangent spaces,+  --   i.e.+  -- @+  -- locallyTrivialDiffeomorphism (p .+~^ 'fromPackedVector' v)+  --   ≡ locallyTrivialDiffeomorphism p .+~^ 'fromPackedVector' v+  -- @+  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) )@@ -268,8 +293,8 @@ 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'+euclideanMetric :: EuclidSpace x => proxy x -> Metric x+euclideanMetric _ = euclideanMetric'   -- | A co-needle can be understood as a “paper stack”, with which you can measure@@ -331,6 +356,14 @@   (.+~^) = (.+^) 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@@ -360,6 +393,10 @@                 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)@@ -379,6 +416,18 @@                 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@@ -388,6 +437,11 @@   (.+~^) = (.+^) 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
Data/Manifold/TreeCover.hs view
@@ -22,9 +22,12 @@ {-# LANGUAGE RankNTypes                 #-} {-# LANGUAGE TupleSections              #-} {-# LANGUAGE ParallelListComp           #-}+{-# LANGUAGE MonadComprehensions        #-} {-# LANGUAGE UnicodeSyntax              #-} {-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE PatternGuards              #-}+{-# LANGUAGE PatternSynonyms            #-}+{-# LANGUAGE ViewPatterns               #-} {-# LANGUAGE LambdaCase                 #-} {-# LANGUAGE TypeOperators              #-} {-# LANGUAGE ScopedTypeVariables        #-}@@ -35,26 +38,27 @@  module Data.Manifold.TreeCover (        -- * Shades -         Shade(..), Shade'(..), IsShade+         Shade(..), pattern(:±), Shade'(..), (|±|), IsShade        -- ** Lenses        , shadeCtr, shadeExpanse, shadeNarrowness        -- ** Construction-       , fullShade, fullShade', pointsShades+       , fullShade, fullShade', pointsShades, pointsCovers        -- ** Evaluation        , occlusion        -- ** Misc-       , factoriseShade, intersectShade's+       , factoriseShade, intersectShade's, Refinable, refineShade', convolveShade', coerceShade        -- * Shade trees-       , ShadeTree(..), fromLeafPoints-       -- * Simple view helpers-       , onlyNodes, onlyLeaves+       , ShadeTree(..), fromLeafPoints, onlyLeaves, indexShadeTree+       -- * View helpers+       , onlyNodes        -- ** Auxiliary types        , SimpleTree, Trees, NonEmptyTree, GenericTree(..)        -- * Misc        , sShSaw, chainsaw, HasFlatView(..), shadesMerge, smoothInterpolate        , twigsWithEnvirons, completeTopShading, flexTwigsShading        , WithAny(..), Shaded, stiAsIntervalMapping, spanShading-       , DifferentialEqn, filterDEqnSolution_static+       , constShaded, stripShadedUntopological+       , DifferentialEqn, filterDEqnSolution_loc        -- ** Triangulation-builders        , TriangBuild, doTriangBuild, singleFullSimplex, autoglueTriangulation        , AutoTriang, elementaryTriang, breakdownAutoTriang@@ -90,6 +94,7 @@ import Data.Manifold.PseudoAffine import Data.Function.Differentiable import Data.Function.Differentiable.Data+import Data.SetLike.Intersection      import Data.Embedding import Data.CoNat@@ -158,6 +163,7 @@   factoriseShade :: ( Manifold x, RealDimension (Scalar (Needle x))                     , Manifold y, RealDimension (Scalar (Needle y)) )                 => shade (x,y) -> (shade x, shade y)+  coerceShade :: (Manifold x, Manifold y, LocallyCoercible x y) => shade x -> shade y  instance IsShade Shade where   shadeCtr f (Shade c e) = fmap (`Shade`e) $ f c@@ -170,6 +176,8 @@          δinv = recipMetric δ   factoriseShade (Shade (x₀,y₀) δxy) = (Shade x₀ δx, Shade y₀ δy)    where (δx,δy) = factoriseMetric' δxy+  coerceShade (Shade x (HerMetric' δxym))+          = Shade (locallyTrivialDiffeomorphism x) (HerMetric' $ unsafeCoerceLinear<$>δxym)  shadeExpanse :: Functor f (->) (->) => (Metric' x -> f (Metric' x)) -> Shade x -> f (Shade x) shadeExpanse f (Shade c e) = fmap (Shade c) $ f e@@ -184,6 +192,8 @@            _               -> zeroV   factoriseShade (Shade' (x₀,y₀) δxy) = (Shade' x₀ δx, Shade' y₀ δy)    where (δx,δy) = factoriseMetric δxy+  coerceShade (Shade' x (HerMetric δxym))+          = Shade' (locallyTrivialDiffeomorphism x) (HerMetric $ unsafeCoerceLinear<$>δxym)  shadeNarrowness :: Functor f (->) (->) => (Metric x -> f (Metric x)) -> Shade' x -> f (Shade' x) shadeNarrowness f (Shade' c e) = fmap (Shade' c) $ f e@@ -202,6 +212,24 @@ fullShade' :: WithField ℝ Manifold x => x -> Metric x -> Shade' x fullShade' ctr expa = Shade' ctr expa ++-- | Span a 'Shade' from a center point and multiple deviation-vectors.+pattern (:±) :: () => WithField ℝ Manifold x => x -> [Needle x] -> Shade x+pattern x :± shs <- Shade x (eigenSpan -> shs)+ where x :± shs = fullShade x $ projector's shs+++-- | Similar to ':±', but instead of expanding the shade, each vector /restricts/ it.+--   Iff these form a orthogonal basis (in whatever sense applicable), then both+--   methods will be equivalent.+-- +--   Note that '|±|' is only possible, as such, in an inner-product space; in+--   general you need reciprocal vectors ('Needle'') to define a 'Shade''.+(|±|) :: WithField ℝ EuclidSpace x => x -> [Needle x] -> Shade' x+x |±| shs = Shade' x $ projectors [v^/(v<.>v) | v<-shs]+++ subshadeId' :: WithField ℝ Manifold x                    => x -> NonEmpty (Needle' x) -> x -> (Int, HourglassBulb) subshadeId' c expvs x = case x .-~. c of@@ -215,20 +243,40 @@                    --- | Attempt to find a 'Shade' that &#x201c;covers&#x201d; the given points.+-- | Attempt to find a 'Shade' that describes the distribution of given points. --   At least in an affine space (and thus locally in any manifold), this can be used to --   estimate the parameters of a normal distribution from which some points were---   sampled.+--   sampled. Note that some points will be &#x201c;outside&#x201d; of the shade,+--   as happens for a normal distribution with some statistical likelyhood.+--   (Use 'pointsCovers' if you need to prevent that.) --  --   For /nonconnected/ manifolds it will be necessary to yield separate shades --   for each connected component. And for an empty input list, there is no shade!---   Hence the list result.+--   Hence the result type is a list. pointsShades :: WithField ℝ Manifold x => [x] -> [Shade x] pointsShades = map snd . pointsShades' zeroV +-- | Like 'pointsShades', but ensure that all points are actually in+--   the shade, i.e. if @['Shade' x₀ ex]@ is the result then+--   @'metric' (recipMetric ex) (p-x₀) ≤ 1@ for all @p@ in the list.+pointsCovers :: ∀ x . WithField ℝ Manifold x => [x] -> [Shade x]+pointsCovers = map guaranteeIn . pointsShades' zeroV+ where guaranteeIn (ps, Shade x₀ ex) +          = case ps >>= \p -> let Option (Just v) = p.-~.x₀+                              in guard (metric ex' v > 1) >> [(p,projector' v)]+             of []   -> Shade x₀ ex+                outs -> guaranteeIn ( fst<$>outs+                                    , Shade x₀+                                         $ ex ^+^ sumV (snd<$>outs)+                                                    ^/ fromIntegral (2 * length outs) )+        where ex' = recipMetric ex+ pointsShade's :: WithField ℝ Manifold x => [x] -> [Shade' x] pointsShade's = map (\(Shade c e) -> Shade' c $ recipMetric e) . pointsShades +pointsCover's :: WithField ℝ Manifold x => [x] -> [Shade' x]+pointsCover's = map (\(Shade c e) -> Shade' c $ recipMetric e) . pointsCovers+ pseudoECM :: WithField ℝ Manifold x => NonEmpty x -> (x, ([x],[x])) pseudoECM (p₀ NE.:| psr) = foldl' ( \(acc, (rb,nr)) (i,p)                                   -> case p.-~.acc of @@ -245,7 +293,7 @@                            _ -> pointsShades' minExt inc'd                                   ++ pointsShades' minExt unreachable  where (ctr,(inc'd,unreachable)) = pseudoECM $ NE.fromList ps-       expa = ( (^+^minExt) . (^/ fromIntegral(length ps)) . sumV . map projector' )+       expa = ( (^+^minExt) . (^/ fromIntegral(length ps)) . projector's )               <$> mapM (.-~.ctr) ps         @@ -273,7 +321,7 @@                   = Just $ let cc = c₂ .+~^ v ^/ 2                                Option (Just cv₁) = c₁.-~.cc                                Option (Just cv₂) = c₂.-~.cc-                           in Shade cc . sumV $ [e₁, e₂] ++ (projector'<$>[cv₁, cv₂])+                           in Shade cc $ e₁ ^+^ e₂ ^+^ projector's [cv₁, cv₂]            | otherwise  = Nothing shadesMerge _ shs = shs @@ -365,21 +413,24 @@        uds = directionChoices hs  traverseDirectionChoices :: (WithField ℝ Manifold x, Hask.Applicative f)-               => (     (Needle' x, ShadeTree x)-                    -> [(Needle' x, ShadeTree x)]+               => (    (Int, (Needle' x, ShadeTree x))+                    -> [(Int, (Needle' x, ShadeTree x))]                     -> f (ShadeTree x) )                  -> [DBranch x]                  -> f [DBranch x]-traverseDirectionChoices f dbs = td [] (dbs >>=-                            \(DBranch ѧ (Hourglass τ β))-                              -> [(ѧ,τ), (negateV ѧ,β)])- where td pds ((ѧ,t):(v,b):vds)+traverseDirectionChoices f dbs+           = td [] . scanLeafNums 0+               $ dbs >>= \(DBranch ѧ (Hourglass τ β))+                              -> [(ѧ,τ), (negateV ѧ,β)]+ where td pds (ѧt@(_,(ѧ,_)):vb:vds)          = liftA3 (\t' b' -> (DBranch ѧ (Hourglass t' b') :))-             (f (ѧ,t) $ pds++(v,b):uds)-             (f (v,b) $ pds++(ѧ,t):uds)-             $ td ((ѧ,t):(v,b):pds) vds+             (f ѧt $ vb:uds)+             (f vb $ ѧt:uds)+             $ td (ѧt:vb:pds) vds         where uds = pds ++ vds        td _ _ = pure []+       scanLeafNums _ [] = []+       scanLeafNums i₀ ((v,t):vts) = (i₀, (v,t)) : scanLeafNums (i₀ + nLeaves t) vts   instance (NFData x, NFData (Needle' x)) => NFData (ShadeTree x) where@@ -419,14 +470,34 @@  -- | Build a quite nicely balanced tree from a cloud of points, on any real manifold. -- ---   Example: https://nbviewer.jupyter.org/github/leftaroundabout/manifolds/blob/master/test/generate-ShadeTrees.ipynb#pseudorandomCloudTree+--   Example: https://nbviewer.jupyter.org/github/leftaroundabout/manifolds/blob/master/test/Trees-and-Webs.ipynb#pseudorandomCloudTree --  -- <<images/examples/simple-2d-ShadeTree.png>> fromLeafPoints :: ∀ x. WithField ℝ Manifold x => [x] -> ShadeTree x fromLeafPoints = fromLeafPoints' sShIdPartition  +indexShadeTree :: ∀ x . WithField ℝ Manifold x+       => ShadeTree x -> Int -> Either Int ([ShadeTree x], x)+indexShadeTree _ i+    | i<0        = Left i+indexShadeTree sh@(PlainLeaves lvs) i = case length lvs of+  n | i<n       -> Right ([sh], lvs!!i)+    | otherwise -> Left $ i-n+indexShadeTree (DisjointBranches n brs) i+    | i<n        = foldl (\case +                             Left i' -> (`indexShadeTree`i')+                             result  -> return result+                         ) (Left i) brs+    | otherwise  = Left $ i-n+indexShadeTree sh@(OverlappingBranches n _ brs) i+    | i<n        = first (sh:) <$> foldl (\case +                             Left i' -> (`indexShadeTree`i')+                             result  -> return result+                         ) (Left i) (toList brs>>=toList)+    | otherwise  = Left $ i-n + fromFnGraphPoints :: ∀ x y . (WithField ℝ Manifold x, WithField ℝ Manifold y)                      => [(x,y)] -> ShadeTree (x,y) fromFnGraphPoints = fromLeafPoints' fg_sShIdPart@@ -521,7 +592,7 @@   trunks :: ∀ x. WithField ℝ Manifold x => ShadeTree x -> [Shade x]-trunks (PlainLeaves lvs) = pointsShades lvs+trunks (PlainLeaves lvs) = pointsCovers lvs trunks (DisjointBranches _ brs) = Hask.foldMap trunks brs trunks (OverlappingBranches _ sh _) = [sh] @@ -558,11 +629,19 @@       in overlappingBranches (fs sh) brs'  -intersectShade's :: ∀ y . WithField ℝ Manifold y => [Shade' y] -> Option (Shade' y)-intersectShade's [] = error "Global `Shade'` not implemented, so can't do intersection of zero co-shades."-intersectShade's (sh:shs) = Hask.foldrM inter2 sh shs- where inter2 :: Shade' y -> Shade' y -> Option (Shade' y)-       inter2 (Shade' c e) (Shade' ζ η)+-- | Class of manifolds which can use 'Shade'' as a basic set type.+--   This is easily possible for vector spaces with the default implementations.+class (WithField ℝ Manifold y) => Refinable y where+  -- | @a `subShade'` b ≡ True@ means @a@ is fully contained in @b@, i.e. from+  --   @'minusLogOcclusion'' a p < 1@ follows also @minusLogOcclusion' b p < 1@.+  subShade' :: Shade' y -> Shade' y -> Bool+  subShade' (Shade' ac ae) tsh = all ((<1) . minusLogOcclusion' tsh)+                                  [ ac.+~^σ*^v | σ<-[0,1], v<-eigenCoSpan' ae ]+  +  -- | Specialised intersection operation. If @p@ is in @a@ and @b@, then it is+  --   also in @refineShade' a b@. (The converse may not hold.)+  refineShade' :: Shade' y -> Shade' y -> Option (Shade' y)+  refineShade' (Shade' c e) (Shade' ζ η)            | μe < 1 && μη < 1  = return $ Shade' iCtr iExpa            | otherwise         = empty         where [c', ζ'] = [ ctr.+~^linearCombo@@ -588,42 +667,92 @@               μe = rcⰰ<.>^rc               μη = rζⰰ<.>^rζ               iExpa = (e^+^η)^/2 ^+^ projector rcⰰ^/(1-μe) ^+^ projector rζⰰ^/(1-μη)+  +  -- | If @p@ is in @a@ (red) and @δ@ is in @b@ (green),+  --   then @p.+~^δ@ is in @convolveShade' a b@ (blue).+  -- +--   Example: https://nbviewer.jupyter.org/github/leftaroundabout/manifolds/blob/master/test/ShadeCombinations.ipynb#shadeConvolutions+-- +-- <<images/examples/ShadeCombinations/2Dconvolution-skewed.png>>+  convolveShade' :: Shade' y -> Shade' (Needle y) -> Shade' y+  convolveShade' (Shade' y₀ ey) (Shade' δ₀ eδ)+          = Shade' (y₀.+~^δ₀)+                   ( projectors [ f ^* ζ crl+                                | (f,_) <- eδsp+                                | crl <- corelap ] )+   where (_,eδsp) = eigenSystem (ey,eδ)+         corelap = map (metric ey . snd) eδsp+         ζ = case filter (>0) corelap of+            [] -> const 0+            nzrelap+               -> let cre₁ = 1/minimum nzrelap+                      cre₂ =  maximum nzrelap+                      edgeFactor = sqrt ( (1 + cre₁)^2 + (1 + cre₂)^2 )+                                / (sqrt (1 + cre₁^2) + sqrt (1 + cre₂^2))+                  in \case+                        0  -> 0+                        sq -> edgeFactor / (recip sq + 1)+   +instance Refinable ℝ where+  refineShade' (Shade' cl el) (Shade' cr er)+         = case (metricSq el 1, metricSq er 1) of+             (0, _) -> return $ Shade' cr er+             (_, 0) -> return $ Shade' cl el+             (ql,qr) | ql>0, qr>0+                    -> let [rl,rr] = sqrt . recip <$> [ql,qr]+                           b = maximum $ zipWith (-) [cl,cr] [rl,rr]+                           t = minimum $ zipWith (+) [cl,cr] [rl,rr]+                       in guard (b<t) >>+                           let cm = (b+t)/2+                               rm = (t-b)/2+                           in return $ Shade' cm (projector $ recip rm)+--   convolveShade' (Shade' y₀ ey) (Shade' δ₀ eδ)+--          = case (metricSq ey 1, metricSq eδ 1) of+--              (wy,wδ) | wy>0, wδ>0+--                  -> Shade' (y₀.+~^δ₀)+--                            ( projector . recip+--                                   $ recip (sqrt wy) + recip (sqrt wδ) )+--              (_ , _) -> Shade' y₀ zeroV +instance (Refinable a, Refinable b) => Refinable (a,b)+  +                             +intersectShade's :: ∀ y . Refinable y => NonEmpty (Shade' y) -> Option (Shade' y)+intersectShade's (sh:|shs) = Hask.foldrM refineShade' sh shs -type DifferentialEqn x y = Shade' (x,y) -> Shade' (LocalLinear x y)  -filterDEqnSolution_loc :: ∀ x y . (WithField ℝ Manifold x, WithField ℝ Manifold y)-           => DifferentialEqn x y -> (Shade' (x,y), [Shade' (x,y)])-                   -> Option (Shade' y, LocalLinear x y)-filterDEqnSolution_loc f (shxy@(Shade' (x,y) expa), neighbours) = (,j₀) <$> yc++type DifferentialEqn x y = Shade (x,y) -> Shade' (LocalLinear x y)+++filterDEqnSolution_loc :: ∀ x y . (WithField ℝ Manifold x, Refinable y)+           => DifferentialEqn x y -> ((x, Shade' y), NonEmpty (x, Shade' y))+                   -> Option (Shade' y)+filterDEqnSolution_loc f ((x, shy@(Shade' y expay)), neighbours) = yc  where jShade@(Shade' j₀ jExpa) = f shxy-       marginδs :: [(Needle x, (Needle y, Metric y))]+       [shxy] = pointsCovers [ (xs, ys')+                             | (xs, Shade' ys yse) <- (x,shy):NE.toList neighbours+                             , δy <- eigenCoSpan' yse+                             , ys' <- [ys.+~^δy, ys.-~^δy] ]+       [Shade' _ expax] = pointsCover's $ x : (fst<$>NE.toList neighbours)+       marginδs :: NonEmpty (Needle x, (Needle y, Metric y))        marginδs = [ (δxm, (δym, expany))-                  | Shade' (xn, yn) expan <- neighbours-                  , let (Option (Just δx)) = x.-~.xn-                        (expanx, expany) = factoriseMetric expan-                        (Option (Just yc'n))-                               = covariance $ recipMetric' expan-                        xntoMarg = metriNormalise expanx δx-                        (Option (Just δxm))-                           = (xn .+~^ xntoMarg :: x) .-~. x-                        (Option (Just δym))-                           = (yn .+~^ (yc'n $ xntoMarg) :: y-                               ) .-~. y+                  | (xn, Shade' yn expany) <- neighbours+                  , let (Option (Just δxm)) = xn.-~.x+                        (Option (Just δym)) = yn.-~.y                   ]        back2Centre :: (Needle x, (Needle y, Metric y)) -> Shade' y        back2Centre (δx, (δym, expany))-            = Shade' (y.+~^δyb) . recipMetric-                $ recipMetric' expany-                  ^+^ recipMetric' (applyLinMapMetric jExpa δx')+            = convolveShade'+                (Shade' y expany)+                (Shade' δyb $ applyLinMapMetric jExpa δx')         where δyb = δym ^-^ (j₀ $ δx)               δx' = toDualWith expax δx        yc :: Option (Shade' y)        yc = intersectShade's $ back2Centre <$> marginδs-       (expax, expay) = factoriseMetric expa        xSpan = eigenCoSpan' expax  @@ -631,8 +760,8 @@ -- The simple list-yielding version (see rev. b4a427d59ec82889bab2fde39225b14a57b694df -- may well be more efficient than this version via a traversal. twigsWithEnvirons :: ∀ x. WithField ℝ Manifold x-    => ShadeTree x -> [(ShadeTree x, [ShadeTree x])]-twigsWithEnvirons = execWriter . traverseTwigsWithEnvirons (writer . (fst&&&pure))+    => ShadeTree x -> [((Int, ShadeTree x), [(Int, ShadeTree x)])]+twigsWithEnvirons = execWriter . traverseTwigsWithEnvirons (writer . (snd.fst&&&pure))  data OuterMaybeT f a = OuterNothing | OuterJust (f a) deriving (Hask.Functor) instance (Hask.Applicative f) => Hask.Applicative (OuterMaybeT f) where@@ -642,91 +771,73 @@  traverseTwigsWithEnvirons :: ∀ x f .             (WithField ℝ Manifold x, Hask.Applicative f)-    => ((ShadeTree x, [ShadeTree x]) -> f (ShadeTree x))+    => ( ((Int, ShadeTree x), [(Int, ShadeTree x)]) -> f (ShadeTree x))          -> ShadeTree x -> f (ShadeTree x)-traverseTwigsWithEnvirons f = fst . go []- where go :: [ShadeTree x] -> ShadeTree x -> (f (ShadeTree x), Bool)-       go _ (DisjointBranches nlvs djbs) = ( fmap (DisjointBranches nlvs)-                                               $ Hask.traverse (fst . go []) djbs-                                           , False )-       go envi ct@(OverlappingBranches nlvs rob@(Shade robc _) brs)+traverseTwigsWithEnvirons f = fst . go [] . (0,)+ where go :: [(Int, ShadeTree x)] -> (Int, ShadeTree x)+                          -> (f (ShadeTree x), Bool)+       go _ (i₀, DisjointBranches nlvs djbs) = ( fmap (DisjointBranches nlvs)+                                                   . Hask.traverse (fst . go [])+                                                   $ NE.zip ioffs djbs+                                               , False )+        where ioffs = NE.scanl (\i -> (+i) . nLeaves) i₀ djbs+       go envi ct@(i₀, (OverlappingBranches nlvs rob@(Shade robc _) brs))                 = ( case descentResult of                      OuterNothing -> f-                         $ purgeRemotes (ct, Hask.foldMap (twigProximæ robc) envi)+                         $ purgeRemotes+                            (ct, Hask.foldMap (\(io,te)+                                            -> first (+io) <$> twigProximæ robc te) envi)                      OuterJust dR -> fmap (OverlappingBranches nlvs rob . NE.fromList) dR                   , False )         where descentResult = traverseDirectionChoices tdc $ NE.toList brs-              tdc (vy, ty) alts = case go envi'' ty of+              tdc (io, (vy, ty)) alts = case go envi'' (i₀+io, ty) of                                    (_, True) -> OuterNothing                                    (down, _) -> OuterJust down-               where envi'' = filter (trunks >>> \(Shade ce _:_)+               where envi'' = filter (snd >>> trunks >>> \(Shade ce _:_)                                          -> let Option (Just δyenv) = ce.-~.robc                                                 qq = vy<.>^δyenv                                             in qq > -1 && qq < 5                                        ) envi'-                              ++ map snd alts+                              ++ map ((+i₀)***snd) alts               envi' = approach =<< envi-              approach apt@(OverlappingBranches _ (Shade envc _) _)-                  = twigsaveTrim hither apt+              approach (i₀e, apt@(OverlappingBranches _ (Shade envc _) _))+                  = first (+i₀e) <$> twigsaveTrim hither apt                where Option (Just δxenv) = robc .-~. envc                      hither (DBranch bdir (Hourglass bdc₁ bdc₂))-                       | bdir<.>^δxenv > 0  = [bdc₁]-                       | otherwise          = [bdc₂]+                       | bdir<.>^δxenv > 0  = [(0           , bdc₁)]+                       | otherwise          = [(nLeaves bdc₁, bdc₂)]               approach q = [q]-       go envi plvs@(PlainLeaves _) = (f $ purgeRemotes (plvs, envi), True)+       go envi plvs@(i₀, (PlainLeaves _))+                         = (f $ purgeRemotes (plvs, envi), True)        -       twigProximæ :: x -> ShadeTree x -> [ShadeTree x]-       twigProximæ x₀ (DisjointBranches _ djbs) = Hask.foldMap (twigProximæ x₀) djbs+       twigProximæ :: x -> ShadeTree x -> [(Int, ShadeTree x)]+       twigProximæ x₀ (DisjointBranches _ djbs)+               = Hask.foldMap (\(i₀,st) -> first (+i₀) <$> twigProximæ x₀ st)+                    $ NE.zip ioffs djbs+        where ioffs = NE.scanl (\i -> (+i) . nLeaves) 0 djbs        twigProximæ x₀ ct@(OverlappingBranches _ (Shade xb qb) brs)                    = twigsaveTrim hither ct         where Option (Just δxb) = x₀ .-~. xb               hither (DBranch bdir (Hourglass bdc₁ bdc₂))                  | bdir<.>^δxb > 0  = twigProximæ x₀ bdc₁-                 | otherwise        = twigProximæ x₀ bdc₂-       twigProximæ _ plainLeaves = [plainLeaves]+                 | otherwise        = first (+nLeaves bdc₁)+                                     <$> twigProximæ x₀ bdc₂+       twigProximæ _ plainLeaves = [(0, plainLeaves)]        -       twigsaveTrim :: (DBranch x -> [ShadeTree x])-                       -> ShadeTree x -> [ShadeTree x]+       twigsaveTrim :: (DBranch x -> [(Int,ShadeTree x)])+                       -> ShadeTree x -> [(Int,ShadeTree x)]        twigsaveTrim f ct@(OverlappingBranches _ _ dbs)-                 = case Hask.mapM (f >>> noLeaf) dbs of+                 = case Hask.mapM (\(i₀,dbr) -> noLeaf $ first(+i₀)<$>f dbr)+                                 $ NE.zip ioffs dbs of                       Just pqe -> Hask.fold pqe-                      _        -> [ct]-        where noLeaf [PlainLeaves _] = empty+                      _        -> [(0,ct)]+        where noLeaf [(_,PlainLeaves _)] = empty               noLeaf bqs = pure bqs+              ioffs = NE.scanl (\i -> (+i) . sum . fmap nLeaves . toList) 0 dbs        -       purgeRemotes :: (ShadeTree x, [ShadeTree x]) -> (ShadeTree x, [ShadeTree x])-       purgeRemotes (ctm@(OverlappingBranches _ sm@(Shade xm _) _), candidates)-                                       = (ctm, filter unobscured closeby)-        where closeby = filter proximate candidates-              proximate (OverlappingBranches _ sh@(Shade xh _) _)-                    = minusLogOcclusion sh xm * minusLogOcclusion sm xh-                       < 1024  -- = (2⋅4²)².  The four-radius occlusion occurs-                               -- if two 𝑟-sized shades have just enough space-                               -- to fit another 𝑟-shade between them; then-                               -- we don't consider the shades neighbours-                               -- anymore. A factor √2 for the discrepancy-                               -- between standard deviation and max distance.-              proximate _ = True-              unobscured ht@(OverlappingBranches _ (Shade xh _) _)-                     = all (don'tObscure (xh, onlyLeaves ht)) closeby-              don'tObscure (xh,lvsh) (OverlappingBranches _ sb@(Shade xb eb) _)-                          = vmc⋅vhc >= 0 || vm⋅vh >= 0-               where Option (Just vm) = pbm .-~. xb-                     Option (Just vh) = pbh .-~. xb-                     Option (Just vmc) = xm .-~. xb-                     Option (Just vhc) = xh .-~. xb-                     [pbm, pbh] = [ maximumBy (comparing $ \l ->-                                               let Option (Just w) = l.-~.xb-                                               in v⋅w ) lvs-                                  | lvs <- [lvsm, lvsh]-                                  | v <- [vhc, vmc] ]-                     (⋅) :: Needle x -> Needle x -> ℝ-                     v⋅w = toDualWith mb v <.>^ w-                     mb = recipMetric eb-              don'tObscure _ _ = True-              lvsm = onlyLeaves ctm-       purgeRemotes xyz = xyz-    +       purgeRemotes :: ((Int,ShadeTree x), [(Int,ShadeTree x)])+                    -> ((Int,ShadeTree x), [(Int,ShadeTree x)])+       purgeRemotes = id -- See 7d1f3a4 for the implementation; this didn't work reliable.       completeTopShading :: (WithField ℝ Manifold x, WithField ℝ Manifold y)                    => x`Shaded`y -> [Shade' (x,y)]@@ -734,7 +845,7 @@                      = pointsShade's $ (_topological &&& _untopological) <$> plvs completeTopShading (DisjointBranches _ bqs)                      = take 1 . completeTopShading =<< NE.toList bqs-completeTopShading t = pointsShade's . map (_topological &&& _untopological) $ onlyLeaves t+completeTopShading t = pointsCover's . map (_topological &&& _untopological) $ onlyLeaves t  flexTopShading :: ∀ x y f . ( WithField ℝ Manifold x, WithField ℝ Manifold y                             , Applicative f (->) (->) )@@ -769,25 +880,8 @@                   => (Shade' (x,y) -> f (x, (Shade' y, LocalLinear x y)))                       -> x`Shaded`y -> f (x`Shaded`y) flexTwigsShading f = traverseTwigsWithEnvirons locFlex- where locFlex :: ∀ μ . (x`Shaded`y, μ) -> f (x`Shaded`y)-       locFlex (lsh, _) = flexTopShading f lsh--filterDEqnSolution_static :: ∀ x y . (WithField ℝ Manifold x, WithField ℝ Manifold y)-           => DifferentialEqn x y-               -> x`Shaded`y -> Option (x`Shaded`y)-filterDEqnSolution_static deq tr = traverseTwigsWithEnvirons locSoltn tr- where locSoltn :: (x`Shaded`y, [x`Shaded`y]) -> Option (x`Shaded`y)-       locSoltn (local, environs) = do-            let enviShades = completeTopShading =<< environs-            flexed <- flexTopShading-                           (\oSh@(Shade' (ox,_) _) -> -                              (ox,) <$> filterDEqnSolution_loc deq (oSh, enviShades)-                           ) local-            top'@(Shade' (top'x,_) top'exp)-                     <- intersectShade's $ completeTopShading =<< [local, flexed]-            let (_, top'ySh) = factoriseShade top'-            j' <- covariance $ recipMetric' top'exp-            flexTopShading (const $ pure (top'x, (top'ySh, j'))) flexed+ where locFlex :: ∀ μ . ((Int, x`Shaded`y), μ) -> f (x`Shaded`y)+       locFlex ((_,lsh), _) = flexTopShading f lsh                   @@ -1085,7 +1179,7 @@ elementaryTriang :: ∀ n n' x . (KnownNat n', n~S n', WithField ℝ EuclidSpace x)                       => Simplex n x -> AutoTriang n x elementaryTriang t = AutoTriang (fullOpenSimplex m t >> return ())- where (Tagged m) = euclideanMetric :: Tagged x (Metric x)+ where m = euclideanMetric t  breakdownAutoTriang :: ∀ n n' x . (KnownNat n', n ~ S n') => AutoTriang n x -> [Simplex n x] breakdownAutoTriang (AutoTriang t) = doTriangBuild t@@ -1345,6 +1439,12 @@ shadeWithoutAnything :: Shade (x`WithAny`y) -> Shade x shadeWithoutAnything (Shade (WithAny _ b) e) = Shade b e +constShaded :: y -> ShadeTree x -> x`Shaded`y+constShaded y = unsafeFmapTree (WithAny y<$>) id (shadeWithAny y)++stripShadedUntopological :: x`Shaded`y -> ShadeTree x+stripShadedUntopological = unsafeFmapTree (fmap _topological) id shadeWithoutAnything+ -- | This is to 'ShadeTree' as 'Data.Map.Map' is to 'Data.Set.Set'. type x`Shaded`y = ShadeTree (x`WithAny`y) @@ -1380,7 +1480,7 @@  stiAsIntervalMapping :: (x ~ ℝ, y ~ ℝ)             => x`Shaded`y -> [(x, ((y, Diff y), Linear ℝ x y))]-stiAsIntervalMapping = twigsWithEnvirons >=> pure.fst >=> completeTopShading >=> pure.+stiAsIntervalMapping = twigsWithEnvirons >=> pure.snd.fst >=> completeTopShading >=> pure.              \(Shade' (xloc, yloc) shd)                  -> ( xloc, ( (yloc, recip $ metric shd (0,1))                             , case covariance (recipMetric' shd) of@@ -1404,7 +1504,7 @@  where addYs :: NonEmpty x -> NonEmpty (x`WithAny`y)        addYs l = foldr (NE.<|) (fmap ( WithAny ymid) l     )                                (fmap (`WithAny`xmid) yexamp)-          where [xsh@(Shade xmid _)] = pointsShades $ toList l+          where [xsh@(Shade xmid _)] = pointsCovers $ toList l                 Shade ymid yexpa = f xsh                 yexamp = [ ymid .+~^ σ*^δy                          | δy <- eigenSpan yexpa, σ <- [-1,1] ]
Data/Manifold/Types.hs view
@@ -54,7 +54,7 @@         , Cutplane(..)         , fathomCutDistance, sideOfCut         -- * Linear mappings-        , Linear, denseLinear+        , Linear, LocalLinear, denseLinear    ) where  
+ Data/Manifold/Web.hs view
@@ -0,0 +1,219 @@+-- |+-- Module      : Data.Manifold.Web+-- Copyright   : (c) Justus Sagemüller 2016+-- License     : GPL v3+-- +-- Maintainer  : (@) sagemueller $ geo.uni-koeln.de+-- Stability   : experimental+-- Portability : portable+-- +{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE UndecidableInstances       #-}+{-# LANGUAGE StandaloneDeriving         #-}+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveFoldable             #-}+{-# LANGUAGE DeriveTraversable          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE FunctionalDependencies     #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE GADTs                      #-}+{-# LANGUAGE RankNTypes                 #-}+{-# LANGUAGE TupleSections              #-}+{-# LANGUAGE ParallelListComp           #-}+{-# LANGUAGE UnicodeSyntax              #-}+{-# LANGUAGE ConstraintKinds            #-}+{-# LANGUAGE PatternGuards              #-}+{-# LANGUAGE PatternSynonyms            #-}+{-# LANGUAGE ViewPatterns               #-}+{-# LANGUAGE LambdaCase                 #-}+{-# LANGUAGE TypeOperators              #-}+{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE LiberalTypeSynonyms        #-}+{-# LANGUAGE RecordWildCards            #-}+{-# LANGUAGE DataKinds                  #-}+++module Data.Manifold.Web where+++import Data.List hiding (filter, all, elem, sum, foldr1)+import Data.Maybe+import qualified Data.Set as Set+import qualified Data.Vector as Arr+import qualified Data.Vector.Unboxed as UArr+import Data.List.NonEmpty (NonEmpty(..))+import Data.List.FastNub+import qualified Data.List.NonEmpty as NE+import Data.Semigroup+import Data.Ord (comparing)+import Control.DeepSeq++import Data.VectorSpace+import Data.AffineSpace+import Data.LinearMap+import Data.LinearMap.HerMetric+import Data.LinearMap.Category+import Data.AffineSpace+import Data.Basis+import Data.Complex hiding (magnitude)+import Data.Void+import Data.Tagged+import Data.Proxy++import Data.SimplicialComplex+import Data.Manifold.Types+import Data.Manifold.Types.Primitive ((^), empty)+import Data.Manifold.PseudoAffine+import Data.Function.Differentiable+import Data.Function.Differentiable.Data+import Data.Manifold.TreeCover+    +import Data.Embedding+import Data.CoNat++import qualified Prelude as Hask hiding(foldl, sum, sequence)+import qualified Control.Applicative as Hask+import qualified Control.Monad       as Hask hiding(forM_, sequence)+import Data.Functor.Identity+import Control.Monad.Trans.State+import Control.Monad.Trans.Writer+import Control.Monad.Trans.Maybe+import Control.Monad.Trans.Class+import qualified Data.Foldable       as Hask+import Data.Foldable (all, elem, toList, sum, foldr1)+import qualified Data.Traversable as Hask+import Data.Traversable (forM)++import qualified Numeric.LinearAlgebra.HMatrix as HMat++import Control.Category.Constrained.Prelude hiding+     ((^), all, elem, sum, forM, Foldable(..), foldr1, Traversable, traverse)+import Control.Arrow.Constrained+import Control.Monad.Constrained hiding (forM)+import Data.Foldable.Constrained+import Data.Traversable.Constrained (Traversable, traverse)++import GHC.Generics (Generic)+++type WebNodeId = Int+type NeighbourRefs = UArr.Vector WebNodeId++data PointsWeb :: * -> * -> * where+   PointsWeb :: {+       webNodeRsc :: ShadeTree x+     , webNodeAssocData :: Arr.Vector (y, NeighbourRefs)+     } -> PointsWeb x y+  deriving (Generic, Hask.Functor, Hask.Foldable, Hask.Traversable)++instance (NFData x, NFData (Needle' x), NFData y) => NFData (PointsWeb x y)++instance Foldable (PointsWeb x) (->) (->) where+  ffoldl = uncurry . Hask.foldl' . curry+  foldMap = Hask.foldMap+instance Traversable (PointsWeb x) (PointsWeb x) (->) (->) where+  traverse f (PointsWeb rsc asd)+           = fmap (PointsWeb rsc . (`Arr.zip`ngss) . Arr.fromList)+              . traverse f $ Arr.toList ys+   where (ys,ngss) = Arr.unzip asd++++fromWebNodes :: ∀ x y . WithField ℝ Manifold x+                    => (Shade x->Metric x) -> [(x,y)] -> PointsWeb x y+fromWebNodes mf = fromShaded mf . fromLeafPoints . map (uncurry WithAny . swap)++fromShadeTree_auto :: ∀ x . WithField ℝ Manifold x => ShadeTree x -> PointsWeb x ()+fromShadeTree_auto = fromShaded (recipMetric . _shadeExpanse) . constShaded ()++fromShadeTree :: ∀ x . WithField ℝ Manifold x+     => (Shade x -> Metric x) -> ShadeTree x -> PointsWeb x ()+fromShadeTree mf = fromShaded mf . constShaded ()++fromShaded :: ∀ x y . WithField ℝ Manifold x+     => (Shade x -> Metric x) -- ^ Local scalar-product generator. You can always+                              --   use @'recipMetric' . '_shadeExpanse'@ (but this+                              --   may give distortions compared to an actual+                              --   Riemannian metric).+     -> (x`Shaded`y)          -- ^ Source tree.+     -> PointsWeb x y+fromShaded metricf shd = PointsWeb shd' assocData + where shd' = stripShadedUntopological shd+       assocData = Hask.foldMap locMesh $ twigsWithEnvirons shd+       +       locMesh :: ((Int, ShadeTree (x`WithAny`y)), [(Int, ShadeTree (x`WithAny`y))])+                   -> Arr.Vector (y, NeighbourRefs)+       locMesh ((i₀, locT), neighRegions) = Arr.map findNeighbours locLeaves+        where locLeaves = Arr.map (first (+i₀)) . Arr.indexed . Arr.fromList+                                          $ onlyLeaves locT+              vicinityLeaves = Hask.foldMap+                                (\(i₀n, ngbR) -> Arr.map (first (+i₀n))+                                               . Arr.indexed+                                               . Arr.fromList+                                               $ onlyLeaves ngbR+                                ) neighRegions+              findNeighbours :: (Int, x`WithAny`y) -> (y, NeighbourRefs)+              findNeighbours (i, WithAny y x)+                         = (y, UArr.fromList $ fst<$>execState seek mempty)+               where seek = do+                        Hask.forM_ (locLeaves Arr.++ vicinityLeaves)+                                  $ \(iNgb, WithAny _ xNgb) ->+                           when (iNgb/=i) `id`do+                              let (Option (Just v)) = xNgb.-~.x+                              oldNgbs <- get+                              when (all (\(_,(_,nw)) -> visibleOverlap nw v) oldNgbs) `id`do+                                 let w = w₀ ^/ (w₀<.>^v)+                                      where w₀ = toDualWith locRieM v+                                 put $ (iNgb, (v,w))+                                       : [ neighbour+                                         | neighbour@(_,(nv,_))<-oldNgbs+                                         , visibleOverlap w nv+                                         ]+              +              visibleOverlap :: Needle' x -> Needle x -> Bool+              visibleOverlap w v = o < 1+               where o = w<.>^v+              +              locRieM :: Metric x+              locRieM = case pointsCovers . map _topological+                                  $ onlyLeaves locT+                                   ++ Hask.foldMap (onlyLeaves . snd) neighRegions of+                          [sh₀] -> metricf sh₀++indexWeb :: WithField ℝ Manifold x => PointsWeb x y -> WebNodeId -> Option (x,y)+indexWeb (PointsWeb rsc assocD) i+  | i>=0, i<Arr.length assocD+  , Right (_,x) <- indexShadeTree rsc i  = pure (x, fst (assocD Arr.! i))+  | otherwise                            = empty++webEdges :: ∀ x y . WithField ℝ Manifold x+            => PointsWeb x y -> [((x,y), (x,y))]+webEdges web@(PointsWeb rsc assoc) = (lookId***lookId) <$> toList allEdges+ where allEdges :: Set.Set (WebNodeId,WebNodeId)+       allEdges = Hask.foldMap (\(i,(_,ngbs))+                    -> Set.fromList [(min i i', max i i')+                                    | i'<-UArr.toList ngbs ]+                               ) $ Arr.indexed assoc+       lookId i | Option (Just xy) <- indexWeb web i  = xy+++localFocusWeb :: WithField ℝ Manifold x => PointsWeb x y -> PointsWeb x ((x,y), [(x,y)])+localFocusWeb (PointsWeb rsc asd) = PointsWeb rsc asd''+ where asd' = Arr.imap (\i (y,n) -> case indexShadeTree rsc i of+                                         Right (_,x) -> ((x,y),n) ) asd+       asd''= Arr.map (\(xy,n) ->+                       ((xy, [fst (asd' Arr.! j) | j<-UArr.toList n]), n)+                 ) asd'+++filterDEqnSolution_static :: (WithField ℝ Manifold x, Refinable y)+       => DifferentialEqn x y -> PointsWeb x (Shade' y) -> Option (PointsWeb x (Shade' y))+filterDEqnSolution_static f = localFocusWeb >>> Hask.traverse `id`+                   \((x,shy), ngbs) -> if null ngbs+                     then pure shy+                     else refineShade' shy+                            =<< filterDEqnSolution_loc f ((x,shy), NE.fromList ngbs)++
+ Data/SetLike/Intersection.hs view
@@ -0,0 +1,37 @@++-- |+-- Module      : Data.SetLike.Intersection+-- Copyright   : (c) Justus Sagemüller 2016+-- License     : GPL v3+-- +-- Maintainer  : (@) sagemueller $ geo.uni-koeln.de+-- Stability   : experimental+-- Portability : portable+-- +++module Data.SetLike.Intersection where++import Data.Semigroup+import qualified Data.List.NonEmpty as NE+import Data.List.NonEmpty (NonEmpty(..))+++newtype IntersectT s x = IntersectT { getIntersectors :: NonEmpty (s x) }+++singleIntersect :: s x -> IntersectT s x+singleIntersect = IntersectT . pure++rmTautologyIntersect ::+         (s x -> s x -> Option (s x)) -- ^ Subset-finder+      -> IntersectT s x -> IntersectT s x+rmTautologyIntersect smaller (IntersectT isoa) = IntersectT $ rti isoa+ where rti (s₀:|ss) = reduce [] ss+        where reduce [] [] = s₀:|[]+              reduce (sp₀:sp) [] = NE.cons s₀ $ rti (sp₀:|sp)+              reduce sp (s₁:sr) = case smaller s₀ s₁ of+               Option (Just si) -> rti $ si :| (sp ++ sr)+               Option Nothing   -> reduce (s₁:sp) sr+            +
Data/VectorSpace/FiniteDimensional.hs view
@@ -86,6 +86,12 @@   completeBasis :: Tagged v [Basis v]   completeBasis = liftA2 (\dim f -> f <$> [0 .. dim - 1]) dimension indexBasis   +  completeBasisValues :: [v]+  completeBasisValues = defCBVs+   where defCBVs :: ∀ v . FiniteDimensional v => [v]+         defCBVs = basisValue <$> cb+          where Tagged cb = completeBasis :: Tagged v [Basis v]+     asPackedVector :: v -> HMat.Vector (Scalar v)   asPackedVector v = HMat.fromList $ snd <$> decompose v   
+ images/examples/ShadeCombinations/2Dconvolution-skewed.png view

binary file changed (absent → 84463 bytes)

+ images/examples/cartesiandisk-2d-PointsWeb.png view

binary file changed (absent → 36607 bytes)

+ images/examples/normaldistrib-2d-PointsWeb.png view

binary file changed (absent → 203879 bytes)

+ images/examples/normaldistrib-2d-ShadeTree.png view

binary file changed (absent → 231921 bytes)

+ images/examples/simple-2d-PointsWeb.png view

binary file changed (absent → 101994 bytes)

manifolds.cabal view
@@ -1,5 +1,5 @@ Name:                manifolds-Version:             0.2.0.1+Version:             0.2.2.0 Category:            Math Synopsis:            Coordinate-free hypersurfaces Description:         Manifolds, a generalisation of the notion of &#x201c;smooth curves&#x201d; or surfaces,@@ -29,7 +29,8 @@ Maintainer:          (@) sagemueller $ geo.uni-koeln.de Build-Type:          Simple Cabal-Version:       >=1.10-Extra-Doc-Files:     images/examples/*.png+Extra-Doc-Files:     images/examples/*.png,+                     images/examples/ShadeCombinations/2Dconvolution-skewed.png  Source-Repository head     type: git@@ -64,6 +65,7 @@   Exposed-modules:   Data.Manifold                      Data.Manifold.PseudoAffine                      Data.Manifold.TreeCover+                     Data.Manifold.Web                      Data.SimplicialComplex                      Data.LinearMap.HerMetric                      Data.Function.Differentiable@@ -72,6 +74,7 @@                      Data.Manifold.Riemannian   Other-modules:   Data.List.FastNub                    Data.Manifold.Types.Primitive+                   Data.SetLike.Intersection                    Data.Manifold.Cone                    Data.CoNat                    Data.Embedding