| Copyright | (c) Justus Sagemüller 2015 |
|---|---|
| License | GPL v3 |
| Maintainer | (@) sagemueller $ geo.uni-koeln.de |
| Stability | experimental |
| Portability | portable |
| Safe Haskell | None |
| Language | Haskell2010 |
Data.Manifold.PseudoAffine
Contents
Description
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.
- class (PseudoAffine m, LinearManifold (Needle m)) => Manifold m
- class AdditiveGroup (Needle x) => Semimanifold x where
- class Semimanifold x => PseudoAffine x where
- type Metric x = HerMetric (Needle x)
- type Metric' x = HerMetric' (Needle x)
- euclideanMetric :: EuclidSpace x => Tagged x (Metric x)
- data Region s m
- data Differentiable s d c
- data PWDiffable s d c
- data RWDiffable s d c
- type RealDimension r = (PseudoAffine r, Needle r ~ r, HasMetric r, DualSpace r ~ r, Scalar r ~ r, RealFloat r)
- type AffineManifold m = (PseudoAffine m, AffineSpace m, Needle m ~ Diff m, LinearManifold (Diff m))
- type LinearManifold x = (PseudoAffine x, Needle x ~ x, HasMetric x)
- type WithField s c x = (c x, s ~ Scalar (Needle x))
- type HilbertSpace x = (LinearManifold x, InnerSpace x, Needle x ~ x, DualSpace x ~ x, Floating (Scalar x))
- type EuclidSpace x = (AffineManifold x, InnerSpace (Diff x), DualSpace (Diff x) ~ Diff x, Floating (Scalar (Diff x)))
- palerp :: (PseudoAffine x, VectorSpace (Needle x)) => x -> x -> Option (Scalar (Needle x) -> x)
Manifold class
class (PseudoAffine m, LinearManifold (Needle m)) => Manifold m Source
See Semimanifold and PseudoAffine for the methods.
Instances
| (PseudoAffine m, LinearManifold (Needle m)) => Manifold m |
class AdditiveGroup (Needle x) => Semimanifold x where Source
Minimal complete definition
Associated Types
The space of “natural” 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 space, 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 is in fact used somewhat synonymously).
Methods
(.+~^) :: x -> Needle x -> x infixl 6 Source
Generalised translation operation.
(.-~^) :: x -> Needle x -> x infixl 6 Source
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 scale down even faster:
as O (η²). For large vectors, it will however behave differently,
except in flat spaces (where all this should be equivalent to the AffineSpace
instance).
Instances
| Semimanifold Double | |
| Semimanifold Rational | |
| Semimanifold ℝP² | |
| Semimanifold S² | |
| Semimanifold S¹ | |
| Semimanifold S⁰ | |
| (PseudoAffine m, VectorSpace (Needle m), (~) * (Scalar (Needle m)) ℝ) => Semimanifold (CD¹ m) | |
| Semimanifold (ZeroDim k) | |
| (WithField k LinearManifold v, Real k) => Semimanifold (Stiefel1 v) | |
| AffineManifold x => Semimanifold (ShadeTree x) | Experimental. There might be a more powerful instance possible. |
| AffineManifold x => Semimanifold (Shade x) | |
| (Semimanifold a, Semimanifold b) => Semimanifold (a, b) | |
| (Semimanifold a, Semimanifold b, Semimanifold c) => Semimanifold (a, b, c) |
class Semimanifold x => PseudoAffine x where Source
This is the class underlying manifolds. (Manifold only adds an extra constraint that
would be circular if it was in a single class. You can always just use Manifold
as a constraint in your signatures, but you must define only PseudoAffine for
manifold types – the Manifold instance follows universally from this.)
The interface is almost identical to the better-known AffineSpace class, but unlike
in the mathematical definition of affine spaces 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).
Methods
(.-~.) :: x -> x -> Option (Needle x) infix 6 Source
The path reaching from one point to another.
Should only yield Nothing if the points are on disjoint segments of a
non–path-connected manifold. Otherwise, the identity
p .+~^ (q.-~.p) ≡ q
should hold, at least save for floating-point precision limits etc..
Instances
| PseudoAffine Double | |
| PseudoAffine Rational | |
| PseudoAffine ℝP² | |
| PseudoAffine S² | |
| PseudoAffine S¹ | |
| PseudoAffine S⁰ | |
| (PseudoAffine m, VectorSpace (Needle m), (~) * (Scalar (Needle m)) ℝ) => PseudoAffine (CD¹ m) | |
| PseudoAffine (ZeroDim k) | |
| (WithField k LinearManifold v, Real k) => PseudoAffine (Stiefel1 v) | |
| (PseudoAffine a, PseudoAffine b) => PseudoAffine (a, b) | |
| (PseudoAffine a, PseudoAffine b, PseudoAffine c) => PseudoAffine (a, b, c) |
type Metric x = HerMetric (Needle x) Source
The word “metric” is used in the sense as in general relativity. Cf. HerMetric.
type Metric' x = HerMetric' (Needle x) Source
euclideanMetric :: EuclidSpace x => Tagged x (Metric x) Source
Regions within a manifold
A pathwise connected subset of a manifold m, whose tangent space has scalar s.
Hierarchy of manifold-categories
Everywhere differentiable functions
data Differentiable s d c Source
The category of differentiable functions between manifolds over scalar s.
As you might guess, these offer automatic differentiation of sorts (basically, simple forward AD), but that's in itself is not really the killer feature here. More interestingly, we actually have the (à la Curry-Howard) proof built in: the function f has at x₀ derivative f'ₓ₀, if, for¹ ε>0, there exists δ such that |f x − (f x₀ + x⋅f'ₓ₀)| < ε for all |x − x₀| < δ.
Observe that, though this looks quite similar to the standard definition of differentiability, it is not equivalent thereto – in fact it does not prove any analytic properties at all. To make it equivalent, we need a lower bound on δ: simply δ gives us continuity, and for continuous differentiability, δ must grow at least like √ε for small ε. Neither of these conditions are enforced by the type system, but we do require them for any allowed values because these proofs are obviously tremendously useful – for instance, you can have a root-finding algorithm and actually be sure you get all solutions correctly, not just some that are (hopefully) the closest to some reference point you'd need to laborously define!
Unfortunately however, this also prevents doing any serious algebra etc. with the
category, because even something as simple as division necessary introduces singularities
where the derivatives must diverge.
Not to speak of many trigonometric e.g. trigonometric functions that
are undefined on whole regions. The PWDiffable and RWDiffable categories have explicit
handling for those issues built in; you may simply use these categories even when
you know the result will be smooth in your relevant domain (or must be, for e.g.
physics reasons).
¹(The implementation does not deal with ε and δ as difference-bounding reals, but rather as metric tensors that define a boundary by prohibiting the overlap from exceeding one; this makes the concept actually work on general manifolds.)
Instances
| MetricScalar s => Morphism (Differentiable s) | |
| MetricScalar s => PreArrow (Differentiable s) | |
| MetricScalar s => WellPointed (Differentiable s) | |
| MetricScalar s => CartesianAgent (Differentiable s) | |
| MetricScalar s => Category (Differentiable s) | |
| MetricScalar s => Cartesian (Differentiable s) | |
| MetricScalar s => HasAgent (Differentiable s) | |
| RealDimension s => EnhancedCat (RWDiffable s) (Differentiable s) | |
| RealDimension s => EnhancedCat (PWDiffable s) (Differentiable s) | |
| type UnitObject (Differentiable s) = ZeroDim s | |
| type PointObject (Differentiable s) x = () | |
| type Object (Differentiable s) o | |
| type PairObjects (Differentiable s) a b = () | |
| type AgentVal (Differentiable s) a v = GenericAgent (Differentiable s) a v |
Almost everywhere diff'able funcs
data PWDiffable s d c Source
Category of functions that almost everywhere have an open region in which they are continuously differentiable, i.e. PieceWiseDiff'able.
Instances
| RealDimension s => Morphism (PWDiffable s) | |
| RealDimension s => PreArrow (PWDiffable s) | |
| RealDimension s => WellPointed (PWDiffable s) | |
| RealDimension s => CartesianAgent (PWDiffable s) | |
| RealDimension s => Category (PWDiffable s) | |
| RealDimension s => Cartesian (PWDiffable s) | |
| RealDimension s => HasAgent (PWDiffable s) | |
| RealDimension s => EnhancedCat (RWDiffable s) (PWDiffable s) | |
| RealDimension s => EnhancedCat (PWDiffable s) (Differentiable s) | |
| type UnitObject (PWDiffable s) = ZeroDim s | |
| type PointObject (PWDiffable s) x = () | |
| type Object (PWDiffable s) o | |
| type PairObjects (PWDiffable s) a b = () | |
| type AgentVal (PWDiffable s) a v = GenericAgent (PWDiffable s) a v |
Region-wise defined diff'able funcs
data RWDiffable s d c Source
Category of functions that, where defined, have an open region in
which they are continuously differentiable. Hence RegionWiseDiff'able.
Basically these are the partial version of PWDiffable.
Though the possibility of undefined regions is of course not too nice
(we don't need Java to demonstrate this with its everywhere-looming null values...),
this category will propably be the “workhorse” for most serious
calculus applications, because it contains all the usual trig etc. functions
and of course everything algebraic you can do in the reals.
The easiest way to define ordinary functions in this category is hence
with its AgentValues, which have instances of the standard classes Num
through Floating. For instance, the following defines the binary entropy
as a differentiable function on the interval ]0,1[: (it will
actually know where it's defined and where not! – and I don't mean you
need to exhaustively isNaN-check all results...)
hb :: RWDiffable ℝ ℝ ℝ hb = alg (\p -> - p * logBase 2 p - (1-p) * logBase 2 (1-p) )
Instances
| RealDimension s => Morphism (RWDiffable s) | |
| RealDimension s => PreArrow (RWDiffable s) | |
| RealDimension s => WellPointed (RWDiffable s) | |
| RealDimension s => CartesianAgent (RWDiffable s) | |
| RealDimension s => Category (RWDiffable s) | |
| RealDimension s => Cartesian (RWDiffable s) | |
| RealDimension s => HasAgent (RWDiffable s) | |
| RealDimension s => EnhancedCat (RWDiffable s) (PWDiffable s) | |
| RealDimension s => EnhancedCat (RWDiffable s) (Differentiable s) | |
| type UnitObject (RWDiffable s) = ZeroDim s | |
| type PointObject (RWDiffable s) x = () | |
| type Object (RWDiffable s) o | |
| type PairObjects (RWDiffable s) a b = () | |
| type AgentVal (RWDiffable s) a v = GenericAgent (RWDiffable s) a v |
Helper constraints
type RealDimension r = (PseudoAffine r, Needle r ~ r, HasMetric r, DualSpace r ~ r, Scalar r ~ r, RealFloat r) Source
The RealFloat class plus manifold constraints.
type AffineManifold m = (PseudoAffine m, AffineSpace m, Needle m ~ Diff m, LinearManifold (Diff m)) Source
The AffineSpace class plus manifold constraints.
type LinearManifold x = (PseudoAffine x, Needle x ~ x, HasMetric x) Source
Basically just an “updated” version of the VectorSpace class.
Every vector space is a manifold, this constraint makes it explicit.
(Actually, LinearManifold is stronger than VectorSpace at the moment, since
HasMetric requires FiniteDimensional. This might be lifted in the future.)
type WithField s c x = (c 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
HilbertSpace 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 HilbertSpace x = (LinearManifold x, InnerSpace x, Needle x ~ x, DualSpace x ~ x, Floating (Scalar x)) Source
A Hilbert space is a complete inner product space. Being a vector space, it is also a manifold.
(Stricly speaking, that doesn't have much to do with the completeness criterion;
but since Manifolds are at the moment confined to finite dimension, they are in
fact (trivially) complete.)
type EuclidSpace x = (AffineManifold x, InnerSpace (Diff x), DualSpace (Diff x) ~ Diff x, Floating (Scalar (Diff x))) Source
An euclidean space is a real affine space whose tangent space is a Hilbert space.
Misc
palerp :: (PseudoAffine x, VectorSpace (Needle x)) => x -> x -> Option (Scalar (Needle x) -> x) Source
Interpolate between points, approximately linearly.