Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

introduce invertible matrices (merely for completeness) #764

Merged
merged 6 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.10.5] – unreleased
## [0.10.5] - 2024-10-24

### Added

* the manifold `InvertibleMatrices` of invertible matrices

### Changed

* rewrote the `CONTRIBUTING.md` and adapt it to todays links and references.
* rewrote the `CONTRIBUTING.md` and adapt it to today's links and references.

## [0.10.4] - 2024-10-20

Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "Manifolds"
uuid = "1cead3c2-87b3-11e9-0ccd-23c62b72b94e"
authors = ["Seth Axen <seth.axen@gmail.com>", "Mateusz Baran <mateuszbaran89@gmail.com>", "Ronny Bergmann <manopt@ronnybergmann.net>", "Antoine Levitt <antoine.levitt@gmail.com>"]
version = "0.10.4"
version = "0.10.5"

[deps]
Einsum = "b7d42ee7-0b51-5a75-98ca-779d3107e4c0"
Expand Down
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ makedocs(;
"Hamiltonian" => "manifolds/hamiltonian.md",
"Hyperbolic space" => "manifolds/hyperbolic.md",
"Hyperrectangle" => "manifolds/hyperrectangle.md",
"Invertible matrices" => "manifolds/invertible.md",
"Lorentzian manifold" => "manifolds/lorentz.md",
"Multinomial doubly stochastic matrices" => "manifolds/multinomialdoublystochastic.md",
"Multinomial matrices" => "manifolds/multinomial.md",
Expand Down
2 changes: 1 addition & 1 deletion docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ If you use `Manifolds.jl` in your work, please cite the following
}
```

To refer to a certain version we recommend to also cite for example
To refer to a specific version, it is recommended to cite, for example,

```biblatex
@software{manifoldsjl-zenodo-mostrecent,
Expand Down
7 changes: 7 additions & 0 deletions docs/src/manifolds/invertible.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Invertible matrices

```@autodocs
Modules = [Manifolds]
Pages = ["manifolds/InvertibleMatrices.jl"]
Order = [:type, :function]
```
3 changes: 3 additions & 0 deletions docs/styles/config/vocabularies/Manifolds/accept.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
Grassmann
Riemannian
Stiefel
[sS]ymplectic
struct
6 changes: 4 additions & 2 deletions src/Manifolds.jl
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ include("manifolds/VectorFiber.jl")
include("manifolds/VectorBundle.jl")
include("groups/group.jl")

# Features I: Which are extended on Meta Manifolds
# Features I: Extending Meta Manifolds
include("statistics.jl")

# Meta Manifolds II: Products
Expand All @@ -415,7 +415,7 @@ METAMANIFOLDS = [
VectorBundle,
]

# Features II: That require metas
# Features II: That require MetaManifolds
include("atlases.jl")
include("differentiation/ode_callback.jl")
include("cotangent_space.jl")
Expand Down Expand Up @@ -443,6 +443,7 @@ include("manifolds/GeneralizedGrassmann.jl")
include("manifolds/GeneralizedStiefel.jl")
include("manifolds/Hyperbolic.jl")
include("manifolds/Hyperrectangle.jl")
include("manifolds/InvertibleMatrices.jl")
include("manifolds/MultinomialDoublyStochastic.jl")
include("manifolds/MultinomialSymmetric.jl")
include("manifolds/MultinomialSymmetricPositiveDefinite.jl")
Expand Down Expand Up @@ -681,6 +682,7 @@ export Euclidean,
HeisenbergGroup,
Hyperbolic,
Hyperrectangle,
InvertibleMatrices,
KendallsPreShapeSpace,
KendallsShapeSpace,
Lorentz,
Expand Down
116 changes: 116 additions & 0 deletions src/manifolds/InvertibleMatrices.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
@doc raw"""
InvertibleMatrices{𝔽,T} <: AbstractDecoratorManifold{𝔽}

The [`AbstractManifold`](@extref `ManifoldsBase.AbstractManifold`) ``\operatorname{Sym}(n)``
kellertuer marked this conversation as resolved.
Show resolved Hide resolved
consisting of the real- or complex-valued invertible matrices, that is the set

```math
\bigl\{p ∈ 𝔽^{n×n}\ \big|\ \det(p) \neq 0 \bigr\},
```
where the field ``𝔽 ∈ \{ ℝ, ℂ\}``.

# Constructor

InvertibleMatrices(n::Int, field::AbstractNumbers=ℝ)

Generate the manifold of ``n×n`` invertible matrices.
"""
struct InvertibleMatrices{𝔽,T} <: AbstractDecoratorManifold{𝔽}
size::T
end

function InvertibleMatrices(n::Int, field::AbstractNumbers=ℝ; parameter::Symbol=:type)
size = wrap_type_parameter(parameter, (n,))
return InvertibleMatrices{field,typeof(size)}(size)
end

function active_traits(f, ::InvertibleMatrices, args...)
return merge_traits(IsEmbeddedSubmanifold())
mateuszbaran marked this conversation as resolved.
Show resolved Hide resolved
end

function allocation_promotion_function(

Check warning on line 31 in src/manifolds/InvertibleMatrices.jl

View check run for this annotation

Codecov / codecov/patch

src/manifolds/InvertibleMatrices.jl#L31

Added line #L31 was not covered by tests
::InvertibleMatrices{ℂ,<:Any},
::typeof(get_vector),
args::Tuple,
)
return complex

Check warning on line 36 in src/manifolds/InvertibleMatrices.jl

View check run for this annotation

Codecov / codecov/patch

src/manifolds/InvertibleMatrices.jl#L36

Added line #L36 was not covered by tests
end

@doc raw"""
check_point(M::InvertibleMatrices{n,𝔽}, p; kwargs...)

Check whether `p` is a valid manifold point on the [`InvertibleMatrices`](@ref) `M`, i.e.
whether `p` is a symmetric matrix of size `(n,n)` with values from the corresponding
[`AbstractNumbers`](@extref ManifoldsBase number-system) `𝔽`.

The tolerance for the symmetry of `p` can be set using `kwargs...`.
"""
function check_point(M::InvertibleMatrices, p; kwargs...)
if det(p) == 0
return DomainError(
det(p),
"The point $(p) does not lie on $(M), since its determinant is zero and hence it is not invertible.",
)
end
return nothing
end

"""
check_vector(M::InvertibleMatrices{n,𝔽}, p, X; kwargs... )

Check whether `X` is a tangent vector to manifold point `p` on the
[`InvertibleMatrices`](@ref) `M`, which are all matrces of size ``n×n```
kellertuer marked this conversation as resolved.
Show resolved Hide resolved
its values have to be from the correct [`AbstractNumbers`](@extref ManifoldsBase number-system).
"""
function check_vector(M::InvertibleMatrices, p, X; kwargs...)
return nothing

Check warning on line 66 in src/manifolds/InvertibleMatrices.jl

View check run for this annotation

Codecov / codecov/patch

src/manifolds/InvertibleMatrices.jl#L65-L66

Added lines #L65 - L66 were not covered by tests
end

embed(::InvertibleMatrices, p) = p
embed(::InvertibleMatrices, p, X) = X

function get_embedding(::InvertibleMatrices{𝔽,TypeParameter{Tuple{n}}}) where {n,𝔽}
return Euclidean(n, n; field=𝔽)
end
function get_embedding(M::InvertibleMatrices{𝔽,Tuple{Int}}) where {𝔽}
n = get_parameter(M.size)[1]
return Euclidean(n, n; field=𝔽, parameter=:field)
end

"""
is_flat(::InvertibleMatrices)

Return true. [`InvertibleMatrices`](@ref) is a flat manifold.
"""
is_flat(M::InvertibleMatrices) = true

@doc raw"""
manifold_dimension(M::InvertibleMatrices{n,𝔽})

Return the dimension of the [`InvertibleMatrices`](@ref) matrix `M` over the number system
`𝔽`, which is the same dimension as its embedding, the [`Euclidean`](@ref)`(n,n)`.
kellertuer marked this conversation as resolved.
Show resolved Hide resolved
"""
function manifold_dimension(M::InvertibleMatrices{<:Any,𝔽}) where {𝔽}
return manifold_dimension(get_embedding(M))
end

function Base.show(io::IO, ::InvertibleMatrices{𝔽,TypeParameter{Tuple{n}}}) where {n,𝔽}
return print(io, "InvertibleMatrices($(n), $(𝔽))")
end
function Base.show(io::IO, M::InvertibleMatrices{𝔽,Tuple{Int}}) where {𝔽}
n = get_parameter(M.size)[1]
return print(io, "InvertibleMatrices($(n), $(𝔽); parameter=:field)")
end

@doc raw"""
Y = Weingarten(M::InvertibleMatrices, p, X, V)
Weingarten!(M::InvertibleMatrices, Y, p, X, V)

Compute the Weingarten map ``\mathcal W_p`` at `p` on the [`InvertibleMatrices`](@ref) `M` with respect to the
tangent vector ``X \in T_p\mathcal M`` and the normal vector ``V \in N_p\mathcal M``.

Since this a flat space by itself, the result is always the zero tangent vector.
"""
Weingarten(::InvertibleMatrices, p, X, V)

Weingarten!(::InvertibleMatrices, Y, p, X, V) = fill!(Y, 0)
36 changes: 36 additions & 0 deletions test/manifolds/invertible_matrices.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using LinearAlgebra, Manifolds, ManifoldsBase, Test

@testset "Invertible matrices" begin
M = InvertibleMatrices(3, ℝ)
A = [1.0 0.0 0.0; 0.0 1.0 0.0; 0.0 0.0 1.0]
B = [0.0 0.0 0.0; 0.0 1.0 0.0; 0.0 0.0 1.0]
Mc = InvertibleMatrices(3, ℂ)
Ac = [1.0im 0.0 0.0; 0.0 1.0 0.0; 0.0 0.0 1.0]
Bc = [0.0im 0.0 0.0; 0.0 1.0 0.0; 0.0 0.0 1.0]
@testset "Real invertible matrices" begin
@test repr(M) == "InvertibleMatrices(3, ℝ)"
M2 = InvertibleMatrices(3, ℝ; parameter=:field)
@test repr(M2) == "InvertibleMatrices(3, ℝ; parameter=:field)"
@test check_point(M, A) == nothing
@test_throws DomainError is_point(M, B; error=:error)
@test_throws ManifoldDomainError is_point(M, Ac; error=:error)
@test_throws ManifoldDomainError is_vector(M, A, Ac; error=:error)
@test is_flat(M)
@test typeof(get_embedding(M)) === Euclidean{TypeParameter{Tuple{3,3}},ℝ}
@test typeof(get_embedding(M2)) === Euclidean{Tuple{Int64,Int64},ℝ}
@test embed(M, A) === A
@test embed(M, A, A) === A
@test manifold_dimension(M) == 9
@test Weingarten(M, A, A, A) == zero(A)
end
@testset "Complex invertible matrices" begin
@test repr(Mc) == "InvertibleMatrices(3, ℂ)"
Mc2 = InvertibleMatrices(3, ℂ; parameter=:field)
@test repr(Mc2) == "InvertibleMatrices(3, ℂ; parameter=:field)"
@test manifold_dimension(Mc) == 2 * 3^2
@test check_point(Mc, Ac) == nothing
@test_throws DomainError is_point(Mc, Bc; error=:error)
@test_throws DomainError is_point(Mc, B; error=:error)
@test is_point(Mc, A; error=:error)
end
end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ end
include_test("manifolds/hamiltonian.jl")
include_test("manifolds/hyperbolic.jl")
include_test("manifolds/hyperrectangle.jl")
include_test("manifolds/invertible_matrices.jl")
include_test("manifolds/lorentz.jl")
include_test("manifolds/multinomial_doubly_stochastic.jl")
include_test("manifolds/multinomial_symmetric.jl")
Expand Down
Loading