Copyright | (c) Justus Sagemüller 2015 |
---|---|
License | GPL v3 |
Maintainer | (@) jsag $ hvl.no |
Stability | experimental |
Portability | portable |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
This is the second prototype of a manifold class. It appears to give considerable
advantages over Manifold
, so that class will probably soon be replaced
with the one we define here (though PseudoAffine
does not follow the standard notion
of a manifold very closely, it should work quite equivalently for pretty much all
Haskell types that qualify as manifolds).
Manifolds are interesting as objects of various categories, from continuous to diffeomorphic. At the moment, we mainly focus on region-wise differentiable functions, which are a promising compromise between flexibility of definition and provability of analytic properties. In particular, they are well-suited for visualisation purposes.
The classes in this module are mostly aimed at manifolds without boundary.
Manifolds with boundary (which we call MWBound
, never manifold!)
are more or less treated as a disjoint sum of the interior and the boundary.
To understand how this module works, best first forget about boundaries – in this case,
, Interior
x ~ xfromInterior
and toInterior
are trivial, and
.+~|
, |-~.
and betweenBounds
are irrelevant.
The manifold structure of the boundary itself is not considered at all here.
Synopsis
- class (OpenManifold m, ProjectableBoundary m, LSpace (Needle m)) => Manifold m
- class AdditiveGroup (Needle x) => Semimanifold x where
- type Needle x
- (.+~^) :: x -> Needle x -> x
- (.-~^) :: x -> Needle x -> x
- semimanifoldWitness :: SemimanifoldWitness x
- type Needle' x = DualVector (Needle x)
- class Semimanifold x => PseudoAffine x where
- (.-~.) :: x -> x -> Maybe (Needle x)
- (.-~!) :: x -> x -> Needle x
- pseudoAffineWitness :: PseudoAffineWitness x
- type LinearManifold m = (LinearSpace m, Manifold m)
- type ScalarManifold s = (Num' s, Manifold s, Manifold (ZeroDim s))
- class (Num s, LinearSpace s, FreeVectorSpace s, Dimensional 1 s) => Num' s
- type RealFrac' s = (Fractional' s, IEEE s, InnerSpace s)
- type RealFloat' s = (RealFrac' s, Floating s)
- type Num'' s = ScalarManifold s
- type RealFrac'' s = (RealFrac' s, ScalarManifold s)
- type RealFloat'' s = (RealFloat' s, SimpleSpace s, ScalarManifold s)
- newtype Local x = Local {
- getLocalOffset :: Needle x
- type Metric x = Norm (Needle x)
- type Metric' x = Variance (Needle x)
- type RieMetric x = x -> Metric x
- type RieMetric' x = x -> Metric' x
- data SemimanifoldWitness x where
- SemimanifoldWitness :: forall x. (Semimanifold (Needle x), Needle (Needle x) ~ Needle x) => SemimanifoldWitness x
- data PseudoAffineWitness x where
- PseudoAffineWitness :: forall x. PseudoAffine (Needle x) => SemimanifoldWitness x -> PseudoAffineWitness x
- type DualNeedleWitness x = DualSpaceWitness (Needle x)
- type WithField s c x = (c x, s ~ Scalar (Needle x), s ~ Scalar (Needle' x))
- type LocallyScalable s x = (PseudoAffine x, LSpace (Needle x), s ~ Scalar (Needle x), s ~ Scalar (Needle' x), Num' s)
- type LocalLinear x y = LinearMap (Scalar (Needle x)) (Needle x) (Needle y)
- type LocalBilinear x y = LinearMap (Scalar (Needle x)) (SymmetricTensor (Scalar (Needle x)) (Needle x)) (Needle y)
- type LocalAffine x y = (Needle y, LocalLinear x y)
- alerpB :: (AffineSpace x, VectorSpace (Diff x), Scalar (Diff x) ~ ℝ) => x -> x -> D¹ -> x
- palerp :: (PseudoAffine x, VectorSpace (Needle x)) => x -> x -> Maybe (Scalar (Needle x) -> x)
- palerpB :: (PseudoAffine x, VectorSpace (Needle x), Scalar (Needle x) ~ ℝ) => x -> x -> Maybe (D¹ -> x)
- class (Semimanifold x, Semimanifold ξ, LSpace (Needle x), LSpace (Needle ξ), Scalar (Needle x) ~ Scalar (Needle ξ)) => LocallyCoercible x ξ where
- locallyTrivialDiffeomorphism :: x -> ξ
- coerceNeedle :: Functor p => p (x, ξ) -> Needle x -+> Needle ξ
- coerceNeedle' :: Functor p => p (x, ξ) -> Needle' x -+> Needle' ξ
- coerceNorm :: Functor p => p (x, ξ) -> Metric x -> Metric ξ
- coerceVariance :: Functor p => p (x, ξ) -> Metric' x -> Metric' ξ
- oppositeLocalCoercion :: CanonicalDiffeomorphism ξ x
- data CanonicalDiffeomorphism a b where
- CanonicalDiffeomorphism :: LocallyCoercible a b => CanonicalDiffeomorphism a b
- class ImpliesMetric s where
- type MetricRequirement s x :: Constraint
- inferMetric :: (MetricRequirement s x, LSpace (Needle x)) => s x -> Metric x
- inferMetric' :: (MetricRequirement s x, LSpace (Needle x)) => s x -> Metric' x
- coerceMetric :: forall x ξ. (LocallyCoercible x ξ, LSpace (Needle ξ)) => RieMetric ξ -> RieMetric x
- coerceMetric' :: forall x ξ. (LocallyCoercible x ξ, LSpace (Needle ξ)) => RieMetric' ξ -> RieMetric' x
- class PseudoAffine m => Connected m where
Manifold class
class (OpenManifold m, ProjectableBoundary m, LSpace (Needle m)) => Manifold m Source #
See Semimanifold
and PseudoAffine
for the methods.
As a Manifold
we understand a pseudo-affine space whose Needle
space is a well-behaved vector space that is isomorphic to
all of the manifold's tangent spaces.
It must also be an instance of the SemimanifoldWithBoundary
class
with explicitly empty boundary (in other words, with no boundary).
Instances
(OpenManifold m, ProjectableBoundary m, LSpace (Needle m)) => Manifold m Source # | |
Defined in Data.Manifold.PseudoAffine |
class AdditiveGroup (Needle x) => Semimanifold x where #
Nothing
The space of “ways” starting from some reference point
and going to some particular target point. Hence,
the name: like a compass needle, but also with an actual length.
For affine spaces, Needle
is simply the space of
line segments (aka vectors) between two points, i.e. the same as Diff
.
The AffineManifold
constraint makes that requirement explicit.
This space should be isomorphic to the tangent space (and in fact serves an in many ways similar role), however whereas the tangent space of a manifold is really infinitesimally small, needles actually allow macroscopic displacements.
type Needle x = GenericNeedle x
(.+~^) :: x -> Needle x -> x infixl 6 #
Generalisation of the translation operation .+^
to possibly non-flat
manifolds, instead of affine spaces.
(.-~^) :: x -> Needle x -> x infixl 6 #
Shorthand for \p v -> p .+~^
, which should obey the asymptotic lawnegateV
v
p .-~^ v .+~^ v ≅ p
Meaning: if v
is scaled down with sufficiently small factors η, then
the difference (p.-~^v.+~^v) .-~. p
should eventually scale down even faster:
as O (η²). For large vectors, it may however behave differently,
except in flat spaces (where all this should be equivalent to the AffineSpace
instance).
Instances
type Needle' x = DualVector (Needle x) Source #
A co-needle can be understood as a “paper stack”, with which you can measure the length that a needle reaches in a given direction by counting the number of holes punched through them.
class Semimanifold x => PseudoAffine x where #
This is the class underlying what we understand as manifolds.
The interface is almost identical to the better-known
AffineSpace
class, but we don't require associativity of .+~^
with ^+^
– except in an asymptotic sense for small vectors.
That innocent-looking change makes the class applicable to vastly more general types:
while an affine space is basically nothing but a vector space without particularly
designated origin, a pseudo-affine space can have nontrivial topology on the global
scale, and yet be used in practically the same way as an affine space. At least the
usual spheres and tori make good instances, perhaps the class is in fact equivalent to
manifolds in their usual maths definition (with an atlas of charts: a family of
overlapping regions of the topological space, each homeomorphic to the Needle
vector space or some simply-connected subset thereof).
The Semimanifold
and PseudoAffine
classes can be anyclass
-derived
or empty-instantiated based on Generic
for product types (including newtypes) of
existing PseudoAffine
instances. For example, the definition
data Cylinder = CylinderPolar { zCyl :: !D¹, φCyl :: !S¹ } deriving (Generic, Semimanifold, PseudoAffine)
is equivalent to
data Cylinder = CylinderPolar { zCyl :: !D¹, φCyl :: !S¹ } data CylinderNeedle = CylinderPolarNeedle { δzCyl :: !(Needle D¹), δφCyl :: !(Needle S¹) } instance Semimanifold Cylinder where type Needle Cylinder = CylinderNeedle CylinderPolar z φ .+~^ CylinderPolarNeedle δz δφ = CylinderPolar (z.+~^δz) (φ.+~^δφ) instance PseudoAffine Cylinder where CylinderPolar z₁ φ₁ .-~. CylinderPolar z₀ φ₀ = CylinderPolarNeedle $ z₁.-~.z₀ * φ₁.-~.φ₀ CylinderPolar z₁ φ₁ .-~! CylinderPolar z₀ φ₀ = CylinderPolarNeedle (z₁.-~!z₀) (φ₁.-~.φ₀)
Nothing
(.-~.) :: x -> x -> Maybe (Needle x) infix 6 #
The path reaching from one point to another.
Should only yield Nothing
if the points are on disjoint segments
of a non–path-connected space.
For a connected manifold, you may define this method as
p.-~.q = pure (p.-~!q)
(.-~!) :: x -> x -> Needle x infix 6 #
Unsafe version of .-~.
. If the two points lie in disjoint regions,
the behaviour is undefined.
Whenever p
and q
lie in a connected region, the identity
p .+~^ (q.-~.p) ≡ q
should hold (up to possible floating point rounding etc.). Meanwhile, you will in general have
(p.+~^v).-~^v ≠ p
(though in many instances this is at least for sufficiently small v
approximately equal).
Instances
type LinearManifold m = (LinearSpace m, Manifold m) Source #
class (Num s, LinearSpace s, FreeVectorSpace s, Dimensional 1 s) => Num' s #
type RealFrac' s = (Fractional' s, IEEE s, InnerSpace s) #
type RealFloat' s = (RealFrac' s, Floating s) #
type Num'' s = ScalarManifold s Source #
type RealFrac'' s = (RealFrac' s, ScalarManifold s) Source #
type RealFloat'' s = (RealFloat' s, SimpleSpace s, ScalarManifold s) Source #
Type definitions
Needles
A point on a manifold, as seen from a nearby reference point.
Local | |
|
Metrics
type Metric x = Norm (Needle x) Source #
The word “metric” is used in the sense as in general relativity.
Actually this is just the type of scalar products on the tangent space.
The actual metric is the function x -> x -> Scalar (Needle x)
defined by
\p q -> m |$|
(p.-~!q)
type RieMetric x = x -> Metric x Source #
A Riemannian metric assigns each point on a manifold a scalar product on the tangent space. Note that this association is not continuous, because the charts/tangent spaces in the bundle are a priori disjoint. However, for a proper Riemannian metric, all arising expressions of scalar products from needles between points on the manifold ought to be differentiable.
type RieMetric' x = x -> Metric' x Source #
Constraints
data SemimanifoldWitness x where #
This is the reified form of the property that the interior of a semimanifold
is a manifold. These constraints would ideally be expressed directly as
superclass constraints, but that would require the UndecidableSuperclasses
extension, which is not reliable yet.
Also, if all those equality constraints are in scope, GHC tends to infer needlessly
complicated types like
, which is
the same as just Needle
(Needle
(Needle
x))
.Needle
x
SemimanifoldWitness :: forall x. (Semimanifold (Needle x), Needle (Needle x) ~ Needle x) => SemimanifoldWitness x |
data PseudoAffineWitness x where #
PseudoAffineWitness :: forall x. PseudoAffine (Needle x) => SemimanifoldWitness x -> PseudoAffineWitness x |
type DualNeedleWitness x = DualSpaceWitness (Needle x) Source #
type WithField s c x = (c x, s ~ Scalar (Needle x), s ~ Scalar (Needle' x)) Source #
Require some constraint on a manifold, and also fix the type of the manifold's
underlying field. For example, WithField ℝ
constrains
HilbertManifold
vv
to be a real (i.e., Double
-) Hilbert space.
Note that for this to compile, you will in
general need the -XLiberalTypeSynonyms
extension (except if the constraint
is an actual type class (like Manifold
): only those can always be partially
applied, for type
constraints this is by default not allowed).
type LocallyScalable s x = (PseudoAffine x, LSpace (Needle x), s ~ Scalar (Needle x), s ~ Scalar (Needle' x), Num' s) Source #
Local functions
type LocalBilinear x y = LinearMap (Scalar (Needle x)) (SymmetricTensor (Scalar (Needle x)) (Needle x)) (Needle y) Source #
type LocalAffine x y = (Needle y, LocalLinear x y) Source #
Misc
alerpB :: (AffineSpace x, VectorSpace (Diff x), Scalar (Diff x) ~ ℝ) => x -> x -> D¹ -> x #
Like alerp
, but actually restricted to the interval between the points.
palerp :: (PseudoAffine x, VectorSpace (Needle x)) => x -> x -> Maybe (Scalar (Needle x) -> x) #
Interpolate between points, approximately linearly. For points that aren't close neighbours (i.e. lie in an almost flat region), the pathway is basically undefined – save for its end points.
A proper, really well-defined (on global scales) interpolation
only makes sense on a Riemannian manifold, as Geodesic
.
palerpB :: (PseudoAffine x, VectorSpace (Needle x), Scalar (Needle x) ~ ℝ) => x -> x -> Maybe (D¹ -> x) #
Like palerp
, but actually restricted to the interval between the points,
with a signature like geodesicBetween
rather than alerp
.
class (Semimanifold x, Semimanifold ξ, LSpace (Needle x), LSpace (Needle ξ), Scalar (Needle x) ~ Scalar (Needle ξ)) => LocallyCoercible x ξ where Source #
Instances of this class must be diffeomorphic manifolds, and even have
canonically isomorphic tangent spaces, so that
defines a meaningful “representational identity“ between these spaces.fromPackedVector
. asPackedVector
:: Needle
x -> Needle
ξ
locallyTrivialDiffeomorphism :: x -> ξ Source #
Must be compatible with the isomorphism on the tangent spaces, i.e.
locallyTrivialDiffeomorphism (p .+~^ v)
≡ locallyTrivialDiffeomorphism p .+~^
coerceNeedle
v
coerceNeedle :: Functor p => p (x, ξ) -> Needle x -+> Needle ξ Source #
coerceNeedle' :: Functor p => p (x, ξ) -> Needle' x -+> Needle' ξ Source #
coerceNorm :: Functor p => p (x, ξ) -> Metric x -> Metric ξ Source #
coerceVariance :: Functor p => p (x, ξ) -> Metric' x -> Metric' ξ Source #
oppositeLocalCoercion :: CanonicalDiffeomorphism ξ x Source #
default oppositeLocalCoercion :: LocallyCoercible ξ x => CanonicalDiffeomorphism ξ x Source #
Instances
data CanonicalDiffeomorphism a b where Source #
CanonicalDiffeomorphism :: LocallyCoercible a b => CanonicalDiffeomorphism a b |
class ImpliesMetric s where Source #
type MetricRequirement s x :: Constraint Source #
type MetricRequirement s x = Semimanifold x
inferMetric :: (MetricRequirement s x, LSpace (Needle x)) => s x -> Metric x Source #
inferMetric' :: (MetricRequirement s x, LSpace (Needle x)) => s x -> Metric' x Source #
Instances
ImpliesMetric Norm Source # | |
Defined in Data.Manifold.PseudoAffine type MetricRequirement Norm x Source # inferMetric :: (MetricRequirement Norm x, LSpace (Needle x)) => Norm x -> Metric x Source # inferMetric' :: (MetricRequirement Norm x, LSpace (Needle x)) => Norm x -> Metric' x Source # | |
ImpliesMetric Shade Source # | |
Defined in Data.Manifold.Shade type MetricRequirement Shade x Source # inferMetric :: (MetricRequirement Shade x, LSpace (Needle x)) => Shade x -> Metric x Source # inferMetric' :: (MetricRequirement Shade x, LSpace (Needle x)) => Shade x -> Metric' x Source # | |
ImpliesMetric Shade' Source # | |
Defined in Data.Manifold.Shade type MetricRequirement Shade' x Source # inferMetric :: (MetricRequirement Shade' x, LSpace (Needle x)) => Shade' x -> Metric x Source # inferMetric' :: (MetricRequirement Shade' x, LSpace (Needle x)) => Shade' x -> Metric' x Source # |
coerceMetric :: forall x ξ. (LocallyCoercible x ξ, LSpace (Needle ξ)) => RieMetric ξ -> RieMetric x Source #
coerceMetric' :: forall x ξ. (LocallyCoercible x ξ, LSpace (Needle ξ)) => RieMetric' ξ -> RieMetric' x Source #
class PseudoAffine m => Connected m where Source #
A connected manifold is one where any point can be reached by translation from any other point.
Nothing
Instances
Connected ℝ² Source # | |
Connected ℝ³ Source # | |
Connected ℝ¹ Source # | |
Connected ℝ⁴ Source # | |
Connected S² Source # | |
Connected S¹ Source # | |
Connected ℝ Source # | |
Connected ℝP² Source # | |
Connected ℝP¹ Source # | |
Connected ℝP⁰ Source # | |
Connected ℝ⁰ Source # | |
(Connected x, Connected y, PseudoAffine (FibreBundle x y)) => Connected (FibreBundle x y) Source # | |
Defined in Data.Manifold.PseudoAffine (.−.) :: FibreBundle x y -> FibreBundle x y -> Needle (FibreBundle x y) Source # | |
(Connected x, Connected y) => Connected (x, y) Source # | |
Defined in Data.Manifold.PseudoAffine |
Orphan instances
PseudoAffine ℝP² Source # | |
Semimanifold ℝP² Source # | |
RealFloat' s => PseudoAffine (S²_ s) Source # | |
RealFloat' r => PseudoAffine (S¹_ r) Source # | |
RealFloat' r => PseudoAffine (S⁰_ r) Source # | |
RealFloat' s => Semimanifold (S²_ s) Source # | |
RealFloat' r => Semimanifold (S¹_ r) Source # | |
RealFloat' r => Semimanifold (S⁰_ r) Source # | |
(LinearSpace (a n), Needle (a n) ~ a n) => PseudoAffine (Point a n) Source # | |
(LinearSpace (a n), Needle (a n) ~ a n) => Semimanifold (Point a n) Source # | |