Skip to content

Commit

Permalink
Merge pull request #33 from JuliaManifolds/patches-for-0.8.0
Browse files Browse the repository at this point in the history
Patches for 0.8.0
  • Loading branch information
mateuszbaran authored Apr 4, 2020
2 parents 039807b + 3784062 commit ee1354c
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 51 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "ManifoldsBase"
uuid = "3362f125-f0bb-47a3-aa74-596ffd7ef2fb"
authors = ["Seth Axen <[email protected]>", "Mateusz Baran <[email protected]>", "Ronny Bergmann <[email protected]>", "Antoine Levitt <[email protected]>"]
version = "0.8.0"
version = "0.8.1"

[deps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Expand Down
4 changes: 2 additions & 2 deletions src/EmbeddedManifold.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ A type used to specify properties of an [`AbstractEmbeddedManifold`](@ref).
abstract type AbstractEmbeddingType end

"""
AbstractEmbeddedManifold{T<:AbstractEmbeddingType,𝔽} <: AbstractDecoratorManifold{𝔽}
AbstractEmbeddedManifold{𝔽,T<:AbstractEmbeddingType,𝔽} <: AbstractDecoratorManifold{𝔽}
An abstract type for embedded manifolds, which acts as an [`AbstractDecoratorManifold`](@ref).
The functions of the manifold that is embedded can hence be just passed on to the embedding.
Expand All @@ -20,7 +20,7 @@ abstract type AbstractEmbeddedManifold{𝔽,T<:AbstractEmbeddingType} <:
AbstractDecoratorManifold{𝔽} end

"""
DefaultEmbeddingType <: AbstractEmbeddingType
DefaultEmbeddingType <: AbstractEmbeddingType
A type of default embedding that does not have any special properties.
"""
Expand Down
41 changes: 23 additions & 18 deletions src/ManifoldsBase.jl
Original file line number Diff line number Diff line change
Expand Up @@ -737,8 +737,9 @@ shortest_geodesic(M::Manifold, p, q, T::AbstractVector) = geodesic(M, p, log(M,
vector_transport_along(M::Manifold, p, X, c)
vector_transport_along(M::Manifold, p, X, c, method::AbstractVectorTransportMethod)
Transport a vector `X` from a point `p` along the curve `c` such that `c(0)` is equal to `p`
to the point `c(1)` using the `method`, which defaults to [`ParallelTransport`](@ref).
Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
along the curve `c` such that `c(0)` is equal to `p` to the point `c(1)` using the `method`,
which defaults to [`ParallelTransport`](@ref).
"""
function vector_transport_along(M::Manifold, p, X, c)
return vector_transport_along(M, p, X, c, ParallelTransport())
Expand All @@ -753,9 +754,9 @@ end
vector_transport_along!(M::Manifold, Y, p, X, c)
vector_transport_along!(M::Manifold, Y, p, X, c, method::AbstractVectorTransportMethod)
Transport a vector `X` from a point `p` along the curve `c` such that `c(0)` is equal to `p`
to the point `c(1)` using the `method`, which defaults to [`ParallelTransport`](@ref).
The result is saved to `Y`.
Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
along the curve `c` such that `c(0)` is equal to `p` to the point `c(1)` using the `method`,
which defaults to [`ParallelTransport`](@ref). The result is saved to `Y`.
"""
function vector_transport_along!(M::Manifold, Y, p, X, c)
return vector_transport_along!(M, Y, p, X, c, ParallelTransport())
Expand Down Expand Up @@ -785,9 +786,10 @@ end
vector_transport_direction(M::Manifold, p, X, d)
vector_transport_direction(M::Manifold, p, X, d, method::AbstractVectorTransportMethod)
Transport a vector `X` from a point `p` in the direction indicated by the tangent vector `d`
at point `p`. By default, [`exp`](@ref) and [`vector_transport_to!`](@ref) are used with
the `method`, which defaults to [`ParallelTransport`](@ref).
Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
in the direction indicated by the tangent vector `d` at `p`. By default, [`exp`](@ref) and
[`vector_transport_to!`](@ref) are used with the `method`, which defaults
to [`ParallelTransport`](@ref).
"""
function vector_transport_direction(M::Manifold, p, X, d)
return vector_transport_direction(M, p, X, d, ParallelTransport())
Expand All @@ -808,10 +810,10 @@ end
vector_transport_direction!(M::Manifold, Y, p, X, d)
vector_transport_direction!(M::Manifold, Y, p, X, d, method::AbstractVectorTransportMethod)
Transport a vector `X` from a point `p` in the direction indicated by the tangent vector `d`
at point `p`. The result is saved to `Y`. By default, [`exp`](@ref) and
[`vector_transport_to!`](@ref) are used with the `method`, which defaults to
[`ParallelTransport`](@ref).
Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
in the direction indicated by the tangent vector `d` at `p`. By default, [`exp`](@ref) and
[`vector_transport_to!`](@ref) are used with the `method`, which defaults
to [`ParallelTransport`](@ref). The result is saved to `Y`.
"""
function vector_transport_direction!(M::Manifold, Y, p, X, d)
return vector_transport_direction!(M, Y, p, X, d, ParallelTransport())
Expand All @@ -832,7 +834,8 @@ end
vector_transport_to(M::Manifold, p, X, q)
vector_transport_to(M::Manifold, p, X, q, method::AbstractVectorTransportMethod)
Compute the vector transport of vector `X` at point `p` to point `q`.
Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
along the [`shortest_geodesic`](@ref) to the tangent space at another point `q`.
By default, the [`AbstractVectorTransportMethod`](@ref) `method` is
[`ParallelTransport`](@ref).
"""
Expand All @@ -849,19 +852,20 @@ end
vector_transport_to!(M::Manifold, Y, p, X, q)
vector_transport_to!(M::Manifold, Y, p, X, q, method::AbstractVectorTransportMethod)
Compute the vector transport of vector `X` at point `p` to point `q`.
The result is saved to `Y`. By default, the [`AbstractVectorTransportMethod`](@ref) `method`
is [`ParallelTransport`](@ref).
Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
along the [`shortest_geodesic`](@ref) to the tangent space at another point `q`.
By default, the [`AbstractVectorTransportMethod`](@ref) `method` is
[`ParallelTransport`](@ref). The result is saved to `Y`.
"""
function vector_transport_to!(M::Manifold, Y, p, q, X)
return vector_transport_to!(M, Y, p, q, X, ParallelTransport())
end
"""
vector_transport_to!(M::Manifold, Y, p, X, q, method::ProjectionTransport)
Transport a vector `X` from the tangent space at `p` on a [`Manifold`](@ref) `M` by
Transport a vector `X` from the tangent space at `p` on the [`Manifold`](@ref) `M` by
interpreting it as an element of the embedding and then projecting it onto the tangent space
at `q`. This method requires [`project`](@ref).
at `q`. This method requires [`project`](@ref project(M::Manifold, p, X)).
"""
function vector_transport_to!(M::Manifold, Y, p, X, q, ::ProjectionTransport)
return project!(M, Y, q, X)
Expand Down Expand Up @@ -977,6 +981,7 @@ export allocate,
manifold_dimension,
norm,
number_eltype,
number_of_coordinates,
number_system,
project,
project!,
Expand Down
15 changes: 8 additions & 7 deletions src/ValidationManifold.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
"""
ValidationManifold{M<:Manifold} <: Manifold
ValidationManifold{𝔽,M<:Manifold{𝔽}} <: AbstractDecoratorManifold{𝔽}
A manifold to encapsulate manifolds working on array representations of `MPoints` and
`TVectors` in a transparent way, such that for these manifolds it's not necessary to
introduce explicit types for the points and tangent vectors, but they are
A manifold to encapsulate manifolds working on array representations of [`MPoint`](@ref)s
and [`TVector`](@ref)s in a transparent way, such that for these manifolds it's not
necessary to introduce explicit types for the points and tangent vectors, but they are
encapsulated/stripped automatically when needed.
This manifold is a decorator for a manifold, i.e. it decorates a manifold `M` with types
points, vectors, and covectors.
This manifold is a decorator for a manifold, i.e. it decorates a [`Manifold`](@ref) `M`
with types points, vectors, and covectors.
"""
struct ValidationManifold{𝔽,M<:Manifold{𝔽}} <: AbstractDecoratorManifold{𝔽}
manifold::M
Expand Down Expand Up @@ -183,7 +183,8 @@ function get_basis(
kwargs...,
) where {𝔽}
is_manifold_point(M, p, true; kwargs...)
Ξ = invoke(get_basis, Tuple{ValidationManifold,Any,AbstractOrthogonalBasis}, M, p, B; kwargs...)
get_basis_invoke_types = Tuple{ValidationManifold,Any,Union{AbstractOrthogonalBasis,CachedBasis{𝔽,<:AbstractOrthogonalBasis{𝔽}}} where {𝔽}}
Ξ = invoke(get_basis, get_basis_invoke_types, M, p, B; kwargs...)
bvectors = get_vectors(M, p, Ξ)
N = length(bvectors)
for i = 1:N
Expand Down
53 changes: 41 additions & 12 deletions src/bases.jl
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ struct DiagonalizingBasisData{D,V,ET}
vectors::V
end

const DefaultOrDiagonalizingBasis =
Union{DefaultOrthonormalBasis,DiagonalizingOrthonormalBasis}
const DefaultOrDiagonalizingBasis{𝔽} =
Union{DefaultOrthonormalBasis{𝔽},DiagonalizingOrthonormalBasis{𝔽}}

"""
CachedBasis{𝔽,V,<:AbstractBasis{𝔽}} <: AbstractBasis{𝔽}
Expand Down Expand Up @@ -156,10 +156,6 @@ function get_vector end
const all_uncached_bases = Union{AbstractBasis, DefaultBasis, DefaultOrthogonalBasis, DefaultOrthonormalBasis}
const DISAMBIGUATION_BASIS_TYPES = [
CachedBasis,
CachedBasis{ℝ,<:AbstractBasis{ℝ}},
CachedBasis{ℂ,<:AbstractBasis{ℂ}},
CachedBasis{ℝ,<:AbstractOrthogonalBasis{ℝ}},
CachedBasis{ℝ,<:AbstractOrthonormalBasis{ℝ}},
DefaultBasis,
DefaultOrthonormalBasis,
DefaultOrthogonalBasis,
Expand All @@ -169,14 +165,20 @@ const DISAMBIGUATION_BASIS_TYPES = [
VeeOrthogonalBasis,
]

function allocate_result(M::Manifold, f::typeof(get_coordinates), p, X, B)
function allocate_result(
M::Manifold,
f::typeof(get_coordinates),
p,
X,
B::AbstractBasis,
)
T = allocate_result_type(M, f, (p, X))
return allocate(p, T, manifold_dimension(M))
return allocate(p, T, number_of_coordinates(M, B))
end

function allocate_result(M::Manifold, f::typeof(get_coordinates), p, X, B::CachedBasis)
T = allocate_result_type(M, f, (p, X))
return allocate(p, T, length(get_vectors(M, p, B)))
return allocate(p, T, number_of_coordinates(M, B))
end

@inline function allocate_result_type(
Expand Down Expand Up @@ -229,6 +231,10 @@ See also: [`get_coordinates`](@ref), [`get_vector`](@ref)
function get_basis(M::Manifold, p, B::AbstractBasis)
error("get_basis not implemented for manifold of type $(typeof(M)) a point of type $(typeof(p)) and basis of type $(typeof(B)).")
end
@decorator_transparent_signature get_basis(M::AbstractDecoratorManifold, p, B::AbstractBasis)
function decorator_transparent_dispatch(::typeof(get_basis), ::Manifold, args...)
return Val(:parent)
end

function get_basis(M::Manifold, p, B::DefaultOrthonormalBasis)
dim = manifold_dimension(M)
Expand Down Expand Up @@ -305,6 +311,11 @@ function get_basis(
error("get_basis with bases $(typeof(B)) only found $(K) orthonormal basis vectors, but manifold dimension is $(dim).")
end
end
for BT in DISAMBIGUATION_BASIS_TYPES
eval(quote
@decorator_transparent_signature get_basis(M::AbstractDecoratorManifold, p, B::$BT)
end)
end

"""
get_coordinates(M::Manifold, p, X, B::AbstractBasis)
Expand Down Expand Up @@ -354,11 +365,14 @@ end
function get_coordinates!(M::Manifold, Y, p, X, B::DefaultOrthogonalBasis)
return get_coordinates!(M, Y, p, X, DefaultOrthonormalBasis(number_system(B)))
end
function get_coordinates!(M::Manifold{𝔾}, Y, p, X, C::CachedBasis{𝔽,B,V}) where {B,V,𝔾,𝔽}
map!(vb -> conj(inner(M, p, X, vb)), Y, get_vectors(M, p, C))
function get_coordinates!(M::Manifold, Y, p, X, B::CachedBasis)
_get_coordinates!(M, number_system(M), Y, p, X, B, number_system(B))
end
function _get_coordinates!(M::Manifold, ::ComplexNumbers, Y, p, X, B::CachedBasis,::RealNumbers)
map!(vb -> conj(inner(M, p, X, vb)), Y, get_vectors(M, p, B))
return Y
end
function get_coordinates!(M::Manifold{𝔽}, Y, p, X, C::CachedBasis{𝔽,B,V}) where {B,V,𝔽}
function _get_coordinates!(M::Manifold, a::𝔽, Y, p, X, C::CachedBasis, b::𝔽) where {𝔽}
map!(vb -> real(inner(M, p, X, vb)), Y, get_vectors(M, p, C))
return Y
end
Expand Down Expand Up @@ -417,6 +431,7 @@ function get_vector!(M::Manifold, Y, p, X, B::CachedBasis)
# 2) guarantees a reasonable array type `Y`
# (for example scalar * `SizedValidation` is an `SArray`)
bvectors = get_vectors(M, p, B)
#print("hi.\nB:$(B)\n& X:$(X)\n\nyields\n $(bvectors).")
if _get_vector_cache_broadcast(bvectors[1]) === Val(false)
Xt = X[1] * bvectors[1]
copyto!(Y, Xt)
Expand Down Expand Up @@ -471,6 +486,20 @@ inverse.
hat(M::Manifold, p, X) = get_vector(M, p, X, VeeOrthogonalBasis())
hat!(M::Manifold, Y, p, X) = get_vector!(M, Y, p, X, VeeOrthogonalBasis())

"""
number_of_coordinates(M::Manifold, B::AbstractBasis)
Compute the number of coordinates in basis `B` of manifold `M`.
This also corresponds to the number of vectors represented by `B`,
or stored within `B` in case of a [`CachedBasis`](@ref).
"""
function number_of_coordinates(M::Manifold{𝔽}, B::AbstractBasis{𝔾}) where {𝔽,𝔾}
return div(manifold_dimension(M), real_dimension(𝔽)) * real_dimension(𝔾)
end
function number_of_coordinates(M::Manifold{𝔽}, B::AbstractBasis{𝔽}) where {𝔽}
return manifold_dimension(M)
end

"""
number_system(::AbstractBasis)
Expand Down
25 changes: 24 additions & 1 deletion src/numbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,23 @@ the fields [`RealNumbers`](@ref) (`ℝ` for short) and [`ComplexNumbers`](@ref)
abstract type AbstractNumbers end

"""
RealNumbers <: AbstractNumbers
ℝ = RealNumbers()
The field of real numbers.
"""
struct RealNumbers <: AbstractNumbers end

"""
ComplexNumbers <: AbstractNumbers
ℂ = ComplexNumbers()
The field of complex numbers.
"""
struct ComplexNumbers <: AbstractNumbers end

"""
QuaternionNumbers <: AbstractNumbers
ℍ = QuaternionNumbers()
The division algebra of quaternions.
Expand All @@ -33,14 +36,34 @@ const ℝ = RealNumbers()
const= ComplexNumbers()
const= QuaternionNumbers()

"""
_unify_number_systems(𝔽s::AbstractNumbers...)
Compute a number system that includes all given number systems (as sub-systems) and is
closed under addition and multiplication.
"""
function _unify_number_systems(a::AbstractNumbers, rest::AbstractNumbers...)
return _unify_number_systems(a, _unify_number_systems(rest...))
end
_unify_number_systems(𝔽::AbstractNumbers) = 𝔽
_unify_number_systems(r::RealNumbers, ::RealNumbers) = r
_unify_number_systems(::RealNumbers, c::ComplexNumbers) = c
_unify_number_systems(::RealNumbers, q::QuaternionNumbers) = q
_unify_number_systems(c::ComplexNumbers, ::RealNumbers) = c
_unify_number_systems(c::ComplexNumbers, ::ComplexNumbers) = c
_unify_number_systems(::ComplexNumbers, q::QuaternionNumbers) = q
_unify_number_systems(q::QuaternionNumbers, ::RealNumbers) = q
_unify_number_systems(q::QuaternionNumbers, ::ComplexNumbers) = q
_unify_number_systems(q::QuaternionNumbers, ::QuaternionNumbers) = q

Base.show(io::IO, ::RealNumbers) = print(io, "")
Base.show(io::IO, ::ComplexNumbers) = print(io, "")
Base.show(io::IO, ::QuaternionNumbers) = print(io, "")

@doc raw"""
real_dimension(𝔽::AbstractNumbers)
Return the real dimension $\dim_ℝ 𝔽$ of the [`AbstractNumbers`] system `𝔽`.
Return the real dimension $\dim_ℝ 𝔽$ of the [`AbstractNumbers`](@ref) system `𝔽`.
The real dimension is the dimension of a real vector space with which a number in `𝔽` can be
identified.
For example, [`ComplexNumbers`](@ref) have a real dimension of 2, and
Expand Down
17 changes: 13 additions & 4 deletions test/bases.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ ManifoldsBase.manifold_dimension(::ProjManifold) = 5
ManifoldsBase.get_vector(::ProjManifold, x, v, ::DefaultOrthonormalBasis) = reverse(v)

@testset "Dispatch" begin
@test ManifoldsBase.decorator_transparent_dispatch(
get_basis,
DefaultManifold(3),
[0.0, 0.0, 0.0],
DefaultBasis(),
) === Val(:parent)
@test ManifoldsBase.decorator_transparent_dispatch(
get_coordinates,
DefaultManifold(3),
Expand Down Expand Up @@ -200,6 +206,7 @@ DiagonalizingBasisProxy() = DiagonalizingOrthonormalBasis([1.0, 0.0, 0.0])
continue
end
v1 = log(M, pts[1], pts[2])
@test ManifoldsBase.number_of_coordinates(M, BT()) == 3

if BT != DiagonalizingBasisProxy
vb = get_coordinates(M, pts[1], v1, BT())
Expand Down Expand Up @@ -259,15 +266,17 @@ end
X = [1.2, 2.2im, 2.3im]
b = [Matrix{Float64}(I,3,3)[:,i] for i=1:3]
Bℝ = CachedBasis(DefaultOrthonormalBasis{ℝ}(),b)
aℝ = get_coordinates(M,p,X,Bℝ)
Yℝ = get_vector(M,p,aℝ,Bℝ)
aℝ = get_coordinates(M, p, X, Bℝ)
Yℝ = get_vector(M, p, aℝ, Bℝ)
@test Yℝ X
@test ManifoldsBase.number_of_coordinates(M, Bℝ) == 3

bℂ = [b...,(b.*1im)...]
Bℂ = CachedBasis(DefaultOrthonormalBasis{ℂ}(), bℂ)
aℂ = get_coordinates(M,p,X,Bℂ)
Yℂ = get_vector(M,p,aℂ,Bℂ)
aℂ = get_coordinates(M, p, X, Bℂ)
Yℂ = get_vector(M, p, aℂ, Bℂ)
@test Yℂ X
@test ManifoldsBase.number_of_coordinates(M, Bℂ) == 6
end

@testset "Basis show methods" begin
Expand Down
Loading

2 comments on commit ee1354c

@kellertuer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/12276

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.8.1 -m "<description of version>" ee1354cba6bea1310f8e2c85b579bbad261abf9c
git push origin v0.8.1

Please sign in to comment.