Skip to content

Commit

Permalink
introduce invertible matrices (merely for completeness) (#764)
Browse files Browse the repository at this point in the history
* introdice invertible matrices (merely for completeness)
* Fix two spurious places where I missed to remove the sym reference after copying from there.
* Increase test cov.
* Apply suggestions from code review

---------

Co-authored-by: Mateusz Baran <mateuszbaran89@gmail.com>
  • Loading branch information
kellertuer and mateuszbaran authored Oct 24, 2024
1 parent 45b9cfa commit c950edd
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 6 deletions.
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
106 changes: 106 additions & 0 deletions src/manifolds/InvertibleMatrices.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
@doc raw"""
InvertibleMatrices{𝔽,T} <: AbstractDecoratorManifold{𝔽}
The [`AbstractManifold`](@extref `ManifoldsBase.AbstractManifold`)
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())
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 an invertible matrix of size `(n,n)` with values from the corresponding
[`AbstractNumbers`](@extref ManifoldsBase number-system) `𝔽`.
"""
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 matrices of size ``n×n``
its values have to be from the correct [`AbstractNumbers`](@extref ManifoldsBase number-system).
"""
function check_vector(M::InvertibleMatrices, p, X; kwargs...)
return nothing
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; field=𝔽)`.
"""
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)
38 changes: 38 additions & 0 deletions test/manifolds/invertible_matrices.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
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_vector(M, A, A)
@test is_flat(M)
@test typeof(get_embedding(M)) ===
Euclidean{ManifoldsBase.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

2 comments on commit c950edd

@kellertuer
Copy link
Member Author

Choose a reason for hiding this comment

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

@JuliaRegistrator register

Release notes:

Added

  • the manifold InvertibleMatrices of invertible matrices

Changed

  • rewrote the CONTRIBUTING.md and adapt it to today's links and references.

@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/117970

Tagging

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.10.5 -m "<description of version>" c950eddda45af92758cfbd18a7a22e622c412d86
git push origin v0.10.5

Please sign in to comment.