Skip to content

Commit

Permalink
updating Hyperbolic
Browse files Browse the repository at this point in the history
  • Loading branch information
mateuszbaran committed Sep 7, 2023
1 parent 0b781ac commit 85549d8
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 55 deletions.
10 changes: 6 additions & 4 deletions ext/ManifoldsRecipesBaseExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ module ManifoldsRecipesBaseExt

if isdefined(Base, :get_extension)
using Manifolds
using Manifolds: TypeParameter

using Colors: RGBA
using RecipesBase: @recipe, @series
else
# imports need to be relative for Requires.jl-based workflows:
# https://github.com/JuliaArrays/ArrayInterface.jl/pull/387
using ..Manifolds
using ..Manifolds: TypeParameter

using ..RecipesBase: @recipe, @series
using ..Colors: RGBA
Expand All @@ -24,7 +26,7 @@ SURFACE_RESOLUTION_DEFAULT = 32
# Plotting Recipe – Poincaré Ball
#
@recipe function f(
M::Hyperbolic{2},
M::Hyperbolic{TypeParameter{Tuple{2}}},
pts::AbstractVector{P},
vecs::Union{AbstractVector{T},Nothing}=nothing;
circle_points=CIRCLE_DEFAULT_PLOT_POINTS,
Expand Down Expand Up @@ -87,7 +89,7 @@ end
# Plotting Recipe – Poincaré Half plane
#
@recipe function f(
M::Hyperbolic{2},
M::Hyperbolic{TypeParameter{Tuple{2}}},
pts::AbstractVector{P},
vecs::Union{AbstractVector{T},Nothing}=nothing;
geodesic_interpolation=-1,
Expand Down Expand Up @@ -133,7 +135,7 @@ end
# Plotting Recipe – Hyperboloid
#
@recipe function f(
M::Hyperbolic{2},
M::Hyperbolic{TypeParameter{Tuple{2}}},
pts::Union{AbstractVector{P},Nothing}=nothing,
vecs::Union{AbstractVector{T},Nothing}=nothing;
geodesic_interpolation=-1,
Expand Down Expand Up @@ -229,7 +231,7 @@ end
# Plotting Recipe – Sphere
#
@recipe function f(
M::Sphere{2,ℝ},
M::Sphere{TypeParameter{Tuple{2}},ℝ},
pts::Union{AbstractVector{P},Nothing}=nothing,
vecs::Union{AbstractVector{T},Nothing}=nothing;
geodesic_interpolation=-1,
Expand Down
43 changes: 32 additions & 11 deletions src/manifolds/Hyperbolic.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@doc raw"""
Hyperbolic{N} <: AbstractDecoratorManifold{ℝ}
Hyperbolic{T} <: AbstractDecoratorManifold{ℝ}
The hyperbolic space $\mathcal H^n$ represented by $n+1$-Tuples, i.e. embedded in the
[`Lorentz`](@ref)ian manifold equipped with the [`MinkowskiMetric`](@ref)
Expand Down Expand Up @@ -29,13 +29,18 @@ and the Poincaré half space model, see [`PoincareHalfSpacePoint`](@ref) and [`P
# Constructor
Hyperbolic(n)
Hyperbolic(n::Int; parameter::Symbol=:field)
Generate the Hyperbolic manifold of dimension `n`.
"""
struct Hyperbolic{N} <: AbstractDecoratorManifold{ℝ} end
struct Hyperbolic{T} <: AbstractDecoratorManifold{ℝ}
size::T
end

Hyperbolic(n::Int) = Hyperbolic{n}()
function Hyperbolic(n::Int; parameter::Symbol=:field)
size = wrap_type_parameter(parameter, (n,))
return Hyperbolic{typeof(size)}(size)
end

function active_traits(f, ::Hyperbolic, args...)
return merge_traits(IsIsometricEmbeddedManifold(), IsDefaultMetric(MinkowskiMetric()))
Expand Down Expand Up @@ -152,7 +157,7 @@ last entry, i.e. $p_n>0$
check_point(::Hyperbolic, ::Any)

@doc raw"""
check_vector(M::Hyperbolic{n}, p, X; kwargs... )
check_vector(M::Hyperbolic, p, X; kwargs... )
Check whether `X` is a tangent vector to `p` on the [`Hyperbolic`](@ref) `M`, i.e.
after [`check_point`](@ref)`(M,p)`, `X` has to be of the same dimension as `p`.
Expand All @@ -166,12 +171,13 @@ For a the Poincaré ball as well as the Poincaré half plane model, `X` has to b
check_vector(::Hyperbolic, ::Any, ::Any)

function check_vector(
M::Hyperbolic{N},
M::Hyperbolic,
p,
X::Union{PoincareBallTVector,PoincareHalfSpaceTVector};
kwargs...,
) where {N}
return check_point(Euclidean(N), X.value; kwargs...)
)
n = get_n(M)
return check_point(Euclidean(n), X.value; kwargs...)
end

# Define self conversions
Expand All @@ -195,7 +201,16 @@ function diagonalizing_projectors(M::Hyperbolic, p, X)
)
end

get_embedding(::Hyperbolic{N}) where {N} = Lorentz(N + 1, MinkowskiMetric())
function get_embedding(::Hyperbolic{TypeParameter{Tuple{n}}}) where {n}
return Lorentz(n + 1, MinkowskiMetric(); parameter=:type)
end
function get_embedding(M::Hyperbolic{Tuple{Int}})
n = get_n(M)
return Lorentz(n + 1, MinkowskiMetric())
end

get_n(::Hyperbolic{TypeParameter{Tuple{n}}}) where {n} = n
get_n(M::Hyperbolic{Tuple{Int}}) = get_parameter(M.size)[1]

embed(::Hyperbolic, p::AbstractArray) = p
embed(::Hyperbolic, p::AbstractArray, X::AbstractArray) = X
Expand Down Expand Up @@ -297,7 +312,7 @@ end
Return the dimension of the hyperbolic space manifold $\mathcal H^n$, i.e. $\dim(\mathcal H^n) = n$.
"""
manifold_dimension(::Hyperbolic{N}) where {N} = N
manifold_dimension(M::Hyperbolic) = get_n(M)

@doc raw"""
manifold_dimension(M::Hyperbolic)
Expand Down Expand Up @@ -342,7 +357,13 @@ the [`Lorentz`](@ref)ian manifold.
"""
project(::Hyperbolic, ::Any, ::Any)

Base.show(io::IO, ::Hyperbolic{N}) where {N} = print(io, "Hyperbolic($(N))")
function Base.show(io::IO, ::Hyperbolic{TypeParameter{Tuple{n}}}) where {n}
return print(io, "Hyperbolic($(n); parameter=:type)")
end
function Base.show(io::IO, M::Hyperbolic{Tuple{Int}})
n = get_n(M)
return print(io, "Hyperbolic($(n))")
end
for T in _HyperbolicTypes
@eval Base.show(io::IO, p::$T) = print(io, "$($T)($(p.value))")
end
Expand Down
16 changes: 9 additions & 7 deletions src/manifolds/HyperbolicHyperboloid.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@doc raw"""
change_representer(M::Hyperbolic{n}, ::EuclideanMetric, p, X)
change_representer(M::Hyperbolic, ::EuclideanMetric, p, X)
Change the Eucliden representer `X` of a cotangent vector at point `p`.
We only have to correct for the metric, which means that the sign of the last entry changes, since
Expand Down Expand Up @@ -262,7 +262,8 @@ function _get_basis(
return get_basis_orthonormal(M, p, ℝ)
end

function get_basis_orthonormal(M::Hyperbolic{n}, p, r::RealNumbers) where {n}
function get_basis_orthonormal(M::Hyperbolic, p, r::RealNumbers)
n = get_n(M)
V = [
_hyperbolize(M, p, [i == k ? one(eltype(p)) : zero(eltype(p)) for k in 1:n]) for
i in 1:n
Expand Down Expand Up @@ -364,8 +365,8 @@ i.e. $X_{n+1} = \frac{⟨\tilde p, Y⟩}{p_{n+1}}$, where $\tilde p = (p_1,\ldot
_hyperbolize(::Hyperbolic, p, Y) = vcat(Y, dot(p[1:(end - 1)], Y) / p[end])

@doc raw"""
inner(M::Hyperbolic{n}, p, X, Y)
inner(M::Hyperbolic{n}, p::HyperboloidPoint, X::HyperboloidTVector, Y::HyperboloidTVector)
inner(M::Hyperbolic, p, X, Y)
inner(M::Hyperbolic, p::HyperboloidPoint, X::HyperboloidTVector, Y::HyperboloidTVector)
Cmpute the inner product in the Hyperboloid model, i.e. the [`minkowski_metric`](@ref) in
the embedding. The formula reads
Expand Down Expand Up @@ -409,11 +410,12 @@ end

function Random.rand!(
rng::AbstractRNG,
M::Hyperbolic{N},
M::Hyperbolic,
pX;
vector_at=nothing,
σ=one(eltype(pX)),
) where {N}
σ::Real=one(eltype(pX)),
)
N = get_n(M)
if vector_at === nothing
a = randn(rng, N)
f = 1 + σ * abs(randn(rng))
Expand Down
28 changes: 16 additions & 12 deletions src/manifolds/HyperbolicPoincareBall.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@doc raw"""
change_representer(M::Hyperbolic{n}, ::EuclideanMetric, p::PoincareBallPoint, X::PoincareBallTVector)
change_representer(M::Hyperbolic, ::EuclideanMetric, p::PoincareBallPoint, X::PoincareBallTVector)
Since in the metric we have the term `` α = \frac{2}{1-\sum_{i=1}^n p_i^2}`` per element,
the correction for the gradient reads `` Y = \frac{1}{α^2}X``.
Expand All @@ -24,7 +24,7 @@ function change_representer!(
end

@doc raw"""
change_metric(M::Hyperbolic{n}, ::EuclideanMetric, p::PoincareBallPoint, X::PoincareBallTVector)
change_metric(M::Hyperbolic, ::EuclideanMetric, p::PoincareBallPoint, X::PoincareBallTVector)
Since in the metric we always have the term `` α = \frac{2}{1-\sum_{i=1}^n p_i^2}`` per element,
the correction for the metric reads ``Z = \frac{1}{α}X``.
Expand All @@ -43,7 +43,7 @@ function change_metric!(
return Y
end

function check_point(M::Hyperbolic{N}, p::PoincareBallPoint; kwargs...) where {N}
function check_point(M::Hyperbolic, p::PoincareBallPoint; kwargs...)
if !(norm(p.value) < 1)
return DomainError(
norm(p.value),
Expand All @@ -52,7 +52,8 @@ function check_point(M::Hyperbolic{N}, p::PoincareBallPoint; kwargs...) where {N
end
end

function check_size(M::Hyperbolic{N}, p::PoincareBallPoint) where {N}
function check_size(M::Hyperbolic, p::PoincareBallPoint)
N = get_n(M)
if size(p.value, 1) != N
!(norm(p.value) < 1)
return DomainError(
Expand All @@ -62,12 +63,8 @@ function check_size(M::Hyperbolic{N}, p::PoincareBallPoint) where {N}
end
end

function check_size(
M::Hyperbolic{N},
p::PoincareBallPoint,
X::PoincareBallTVector;
kwargs...,
) where {N}
function check_size(M::Hyperbolic, p::PoincareBallPoint, X::PoincareBallTVector; kwargs...)
N = get_n(M)
if size(X.value, 1) != N
return DomainError(
size(X.value, 1),
Expand Down Expand Up @@ -273,12 +270,19 @@ embed(::Hyperbolic, p::PoincareBallPoint) = p.value
embed!(::Hyperbolic, q, p::PoincareBallPoint) = copyto!(q, p.value)
embed(::Hyperbolic, p::PoincareBallPoint, X::PoincareBallTVector) = X.value
embed!(::Hyperbolic, Y, p::PoincareBallPoint, X::PoincareBallTVector) = copyto!(Y, X.value)
get_embedding(::Hyperbolic{n}, p::PoincareBallPoint) where {n} = Euclidean(n)

function get_embedding(::Hyperbolic{TypeParameter{Tuple{n}}}, ::PoincareBallPoint) where {n}
return Euclidean(n; parameter=:type)
end
function get_embedding(M::Hyperbolic{Tuple{Int}}, ::PoincareBallPoint)
n = get_n(M)
return Euclidean(n)
end

@doc raw"""
inner(::Hyperbolic, p::PoincareBallPoint, X::PoincareBallTVector, Y::PoincareBallTVector)
Compute the inner producz in the Poincaré ball model. The formula reads
Compute the inner product in the Poincaré ball model. The formula reads
````math
g_p(X,Y) = \frac{4}{(1-\lVert p \rVert^2)^2} ⟨X, Y⟩ .
````
Expand Down
24 changes: 18 additions & 6 deletions src/manifolds/HyperbolicPoincareHalfspace.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function check_point(M::Hyperbolic{N}, p::PoincareHalfSpacePoint; kwargs...) where {N}
function check_point(M::Hyperbolic, p::PoincareHalfSpacePoint; kwargs...)
if !(last(p.value) > 0)
return DomainError(
norm(p.value),
Expand All @@ -7,7 +7,8 @@ function check_point(M::Hyperbolic{N}, p::PoincareHalfSpacePoint; kwargs...) whe
end
end

function check_size(M::Hyperbolic{N}, p::PoincareHalfSpacePoint) where {N}
function check_size(M::Hyperbolic, p::PoincareHalfSpacePoint)
N = get_n(M)
if size(p.value, 1) != N
!(norm(p.value) < 1)
return DomainError(
Expand All @@ -18,11 +19,12 @@ function check_size(M::Hyperbolic{N}, p::PoincareHalfSpacePoint) where {N}
end

function check_size(
M::Hyperbolic{N},
M::Hyperbolic,
p::PoincareHalfSpacePoint,
X::PoincareHalfSpaceTVector;
kwargs...,
) where {N}
)
N = get_n(M)
if size(X.value, 1) != N
return DomainError(
size(X.value, 1),
Expand Down Expand Up @@ -210,11 +212,21 @@ embed(::Hyperbolic, p::PoincareHalfSpacePoint, X::PoincareHalfSpaceTVector) = X.
function embed!(::Hyperbolic, Y, p::PoincareHalfSpacePoint, X::PoincareHalfSpaceTVector)
return copyto!(Y, X.value)
end
get_embedding(::Hyperbolic{n}, p::PoincareHalfSpacePoint) where {n} = Euclidean(n)

function get_embedding(
::Hyperbolic{TypeParameter{Tuple{n}}},
::PoincareHalfSpacePoint,
) where {n}
return Euclidean(n; parameter=:type)
end
function get_embedding(M::Hyperbolic{Tuple{Int}}, ::PoincareHalfSpacePoint)
n = get_n(M)
return Euclidean(n)
end

@doc raw"""
inner(
::Hyperbolic{n},
::Hyperbolic,
p::PoincareHalfSpacePoint,
X::PoincareHalfSpaceTVector,
Y::PoincareHalfSpaceTVector
Expand Down
2 changes: 1 addition & 1 deletion src/manifolds/Lorentz.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ see [`minkowski_metric`](@ref) for the formula.
struct MinkowskiMetric <: LorentzMetric end

@doc raw"""
Lorentz{N} = MetricManifold{Euclidean{N,ℝ},LorentzMetric}
Lorentz{T} = MetricManifold{Euclidean{T,ℝ},LorentzMetric}
The Lorentz manifold (or Lorentzian) is a pseudo-Riemannian manifold.
Expand Down
Loading

0 comments on commit 85549d8

Please sign in to comment.