Skip to content

Commit

Permalink
Add general and special linear groups (#249)
Browse files Browse the repository at this point in the history
* Add group_log! default implementation

* Add solver for inverting geodesic

* Add implementation of 2x2 exp

* Add GeneralLinear

* Move docstring

* Rename file

* Add ApproximateInverseRetraction

* Add NLsolve to extras

* Run formatter

* Revert "Add implementation of 2x2 exp"

This reverts commit d0daf0e.

* Used StaticArrays's 2x2 exp

* Add section to docs

* Remove GLInvariantMetric

The general case is domain-specific and difficult to generalize for complex matrices.

* Don't return twice

* Use correct signature for inner

* Add mul!_safe

* Add realify and complexify

* Add utility for checking normality

* Use existing methods

* Generalize (un)realify

* Don't overwrite method

* Reimplement logarithm

* Use correct tangent space representation

* Compute more efficiently for normal matrix.

* Add inplace log_safe!

* Make General Linear an embedded manifold

* Add more projection methods

* Add NLsolve to tests

* Add tests for general linear group

* Test complex general linear group

* Run JuliaFormatter

* Add special linear group

* Remove unnecessary overload

* Use actions of differentials

This are no-ops, but they are essentially cost-free and make the function still work if we ever change conventions.

* Error for log between disconnected submanifolds

* More efficiently adjust sign of determinant

* Implement projections on SL(n)

* Fix check

* Use correct signature

* Revert "Add inplace log_safe!"

This reverts commit 2ec98d3.

* Fix calling project!

* Copy if needs no projection

* Remove unnecessary re-definition

* Add log_safe!

* Use log_safe! and disallow Number

* Use log_safe!

* Remove unused allocation

* Override Euclidean distance

* Increase tolerance of checks

* Decrease size of matrix

* Resolve ambiguities

* Restrict type definition of group_log!

* Run formatter

* Add back missing type params

* Increase tolerance for log_safe! tests

* Resolve ambiguities

* Move utils tests

* Move configurable parameters to struct

* Add tests for ApproximateInverseRetraction

* Add docstrings

* Remove unnecessary types

* Refactor to use NLsolveInverseRetraction

* Fixes and improvements to docstrings

* Fix docstring

* Make nlsolve function non-allocating

* Make tests more reliably pass

* Run formatter

* Add TODO note on future approach

* Increment allowed ambiguities

PowerManifold's overload of inverse_retract causes ambiguities with new NLsolveInverseRetraction.

* More generally project to U(n) x S^+

* Add additional to-do

* Simplify log logic

* Add tests for isnormal

* Add tests for (un)realify

* Fix tests

* Decrease tolerance of matrix log tests

* Run tests on GL+

* Test exp and log

* Test remaining cases

* Run formatter

* Use references in docstring

* Concretely type kwargs

* Apply suggestions from code review

Co-authored-by: Ronny Bergmann <[email protected]>

* Use correct inheritance

* Use backticks for equations instead of dollar signs

* Simplify

* Rewrap docstring

* Use loops instead of broadcast

* Test OutOfInjectivityRadiusError thrown

* Make matrix exactly hermitian

* Add tests for default metric dispatch

* Run formatter

* Remove todo

* Increment version number

Co-authored-by: Ronny Bergmann <[email protected]>
  • Loading branch information
sethaxen and kellertuer authored Mar 22, 2021
1 parent ef966a4 commit b3d7787
Show file tree
Hide file tree
Showing 17 changed files with 1,329 additions and 20 deletions.
5 changes: 3 additions & 2 deletions 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 <[email protected]>", "Mateusz Baran <[email protected]>", "Ronny Bergmann <[email protected]>", "Antoine Levitt <[email protected]>"]
version = "0.4.17"
version = "0.4.18"

[deps]
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
Expand Down Expand Up @@ -48,6 +48,7 @@ ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
Gtk = "4c0ca9eb-093a-5379-98c5-f87ac0bbbf44"
ImageIO = "82e4d734-157c-48bb-816b-45c225c6df19"
ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1"
NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee"
Expand All @@ -59,4 +60,4 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
VisualRegressionTests = "34922c18-7c2a-561c-bac1-01e79b2c4c92"

[targets]
test = ["Test", "Colors", "DoubleFloats", "FiniteDiff", "ForwardDiff", "Gtk", "ImageIO", "ImageMagick", "OrdinaryDiffEq", "Plots", "PyPlot", "Quaternions", "QuartzImageIO", "RecipesBase", "ReverseDiff", "VisualRegressionTests"]
test = ["Test", "Colors", "DoubleFloats", "FiniteDiff", "ForwardDiff", "Gtk", "ImageIO", "ImageMagick", "OrdinaryDiffEq", "NLsolve", "Plots", "PyPlot", "Quaternions", "QuartzImageIO", "RecipesBase", "ReverseDiff", "VisualRegressionTests"]
16 changes: 16 additions & 0 deletions docs/src/manifolds/group.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,22 @@ Pages = ["groups/circle_group.jl"]
Order = [:type, :function]
```

### General linear group

```@autodocs
Modules = [Manifolds]
Pages = ["groups/general_linear.jl"]
Order = [:type, :function]
```

### Special linear group

```@autodocs
Modules = [Manifolds]
Pages = ["groups/special_linear.jl"]
Order = [:type, :function]
```

### Special orthogonal group

```@autodocs
Expand Down
6 changes: 6 additions & 0 deletions docs/src/misc/internals.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,16 @@ This page documents the internal types and methods of `Manifolds.jl`'s that migh
```@docs
Manifolds.eigen_safe
Manifolds.find_pv
Manifolds.isnormal
Manifolds.log_safe
Manifolds.log_safe!
Manifolds.mul!_safe
Manifolds.nzsign
Manifolds.realify
Manifolds.realify!
Manifolds.size_to_tuple
Manifolds.select_from_tuple
Manifolds.unrealify!
Manifolds.usinc
Manifolds.usinc_from_cos
Manifolds.vec2skew!
Expand Down
12 changes: 12 additions & 0 deletions src/Manifolds.jl
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ include("manifolds/VectorBundle.jl")
include("distributions.jl")
include("projected_distribution.jl")

include("approx_inverse_retraction.jl")

# It's included early to ensure visibility of `Identity`
include("groups/group.jl")

Expand Down Expand Up @@ -182,6 +184,8 @@ include("groups/array_manifold.jl")
include("groups/product_group.jl")
include("groups/semidirect_product_group.jl")

include("groups/general_linear.jl")
include("groups/special_linear.jl")
include("groups/translation_group.jl")
include("groups/special_orthogonal.jl")
include("groups/circle_group.jl")
Expand Down Expand Up @@ -230,6 +234,11 @@ function __init__()
include("ode.jl")
end

@require NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" begin
using .NLsolve: NLsolve
include("nlsolve.jl")
end

@require Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" begin
using .Test: Test
include("tests/tests_general.jl")
Expand Down Expand Up @@ -346,6 +355,7 @@ export AbstractRetractionMethod,
ProductRetraction,
PowerRetraction
export AbstractInverseRetractionMethod,
ApproximateInverseRetraction,
LogarithmicInverseRetraction,
QRInverseRetraction,
PolarInverseRetraction,
Expand Down Expand Up @@ -471,6 +481,7 @@ export AbstractGroupAction,
ActionDirection,
AdditionOperation,
CircleGroup,
GeneralLinear,
GroupManifold,
GroupOperationAction,
Identity,
Expand All @@ -485,6 +496,7 @@ export AbstractGroupAction,
RotationAction,
SemidirectProductGroup,
SpecialEuclidean,
SpecialLinear,
SpecialOrthogonal,
TranslationGroup,
TranslationAction
Expand Down
104 changes: 104 additions & 0 deletions src/approx_inverse_retraction.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
"""
ApproximateInverseRetraction <: AbstractInverseRetractionMethod
An abstract type for representing approximate inverse retraction methods.
"""
abstract type ApproximateInverseRetraction <: AbstractInverseRetractionMethod end

"""
NLsolveInverseRetraction{T<:AbstractRetractionMethod,TV,TK} <:
ApproximateInverseRetraction
An inverse retraction method for approximating the inverse of a retraction using `NLsolve`.
# Constructor
NLsolveInverseRetraction(
method::AbstractRetractionMethod[, X0];
project_tangent=false,
project_point=false,
nlsolve_kwargs...,
)
Constructs an approximate inverse retraction for the retraction `method` with initial guess
`X0`, defaulting to the zero vector. If `project_tangent` is `true`, then the tangent
vector is projected before the retraction using `project`. If `project_point` is `true`,
then the resulting point is projected after the retraction. `nlsolve_kwargs` are keyword
arguments passed to `NLsolve.nlsolve`.
"""
struct NLsolveInverseRetraction{TR<:AbstractRetractionMethod,TV,TK} <:
ApproximateInverseRetraction
retraction::TR
X0::TV
project_tangent::Bool
project_point::Bool
nlsolve_kwargs::TK
function NLsolveInverseRetraction(m, X0, project_point, project_tangent, nlsolve_kwargs)
isdefined(Manifolds, :NLsolve) ||
@warn "To use NLsolveInverseRetraction, NLsolve must be loaded using `using NLsolve`."
return new{typeof(m),typeof(X0),typeof(nlsolve_kwargs)}(
m,
X0,
project_point,
project_tangent,
nlsolve_kwargs,
)
end
end
function NLsolveInverseRetraction(
m,
X0=nothing;
project_tangent::Bool=false,
project_point::Bool=false,
nlsolve_kwargs...,
)
return NLsolveInverseRetraction(m, X0, project_point, project_tangent, nlsolve_kwargs)
end

@decorator_transparent_signature inverse_retract(
M::AbstractDecoratorManifold,
p,
q,
m::NLsolveInverseRetraction,
)

@decorator_transparent_signature inverse_retract!(
M::AbstractDecoratorManifold,
X,
p,
q,
m::NLsolveInverseRetraction,
)

@doc raw"""
inverse_retract(M, p, q method::NLsolveInverseRetraction; kwargs...)
Approximate the inverse of the retraction specified by `method.retraction` from `p` with
respect to `q` on the [`Manifold`](@ref) `M` using NLsolve. This inverse retraction is
not guaranteed to succeed and probably will not unless `q` is close to `p` and the initial
guess `X0` is close.
If the solver fails to converge, an [`OutOfInjectivityRadiusError`](@ref) is raised.
See [`NLsolveInverseRetraction`](@ref) for configurable parameters.
"""
inverse_retract(::Manifold, p, q, ::NLsolveInverseRetraction; kwargs...)

function inverse_retract!(M::Manifold, X, p, q, method::NLsolveInverseRetraction; kwargs...)
X0 = method.X0 === nothing ? zero_tangent_vector(M, p) : method.X0
res = _inverse_retract_nlsolve(
M,
p,
q,
method.retraction,
X0,
method.project_tangent,
method.project_point,
method.nlsolve_kwargs;
kwargs...,
)
if !res.f_converged
@debug res
throw(OutOfInjectivityRadiusError())
end
return copyto!(X, res.zero)
end
2 changes: 1 addition & 1 deletion src/groups/circle_group.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,4 @@ function group_log(G::CircleGroup, q)
end
end

group_log!(G::CircleGroup, X, q) = (X .= group_log(G, q))
group_log!(G::CircleGroup, X::AbstractVector, q::AbstractVector) = (X .= group_log(G, q))
Loading

2 comments on commit b3d7787

@sethaxen
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
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/32525

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

Please sign in to comment.