From 388ff3f9687c63b64b222731e64fde9ef2ccfe43 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Mon, 4 Nov 2024 19:52:23 +0100 Subject: [PATCH 01/43] Sketch a first few ideas. --- docs/src/tutorials/transition.md | 11 +++++-- src/LieGroups.jl | 6 +++- src/group_operations/power_operation.jl | 31 +++++++++++++++++++ src/group_operations/product_operation.jl | 19 ++++++++++++ .../semidirect_product_operation.jl | 5 +++ 5 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 src/group_operations/power_operation.jl create mode 100644 src/group_operations/product_operation.jl create mode 100644 src/group_operations/semidirect_product_operation.jl diff --git a/docs/src/tutorials/transition.md b/docs/src/tutorials/transition.md index 71728583..b1bc9279 100644 --- a/docs/src/tutorials/transition.md +++ b/docs/src/tutorials/transition.md @@ -47,6 +47,11 @@ The list is alphabetical, but first lists types, then functions | `translate_diff(G, g, X, c)` | [`diff_left_compose`](@ref)`(G, g, h, X)`, [`diff_right_compose`](@ref)`(G, g, h, X)` | for compose ``g∘h`` the functions now specify whether the derivative is taken w.r.t. to the left (`g`) or right (`h`) argument | |`VeeOrthogonalBasis` | [`LieAlgebraOrthogonalBasis`](@ref) | | -# Notable changes - -* The [`GeneralLinearGroup`](@ref) (formerly `GeneralLinear`) switched to using its Lie algebra to represent tangent vectors. +# Further notable changes + +1. The [`GeneralLinearGroup`](@ref) (formerly `GeneralLinear`) switched to using its Lie algebra to represent tangent vectors. +2. Formerly, both a power of LieGroups as well as a LieGroup on the power manifold was possible. This is now unified to the latter, + the operation for power manifolds can hence stay the same as for the single manifold. +3. Formerly, product manifolds were stored as a [`ProductManifold`](@ref) of Lie groups and an indicator for the group operation, that the direct product should be used. This is switched to (as for the last point) internally only store a [`ProductManifold`](@ref) as well as a (new) [`ProductGroupOperation`](@ref) that specifies one group operation for every factor. +4. both the last two points achieve one unified modelling aspect of Lie groups: They are now always a Riemannian manifold `M` together with a group operation `op`, +but a Lie group does not store another Lie group (or product of them) internally. diff --git a/src/LieGroups.jl b/src/LieGroups.jl index 1b7d8ee8..754909f9 100644 --- a/src/LieGroups.jl +++ b/src/LieGroups.jl @@ -27,6 +27,9 @@ include("Lie_algebra/Lie_algebra_interface.jl") # Generic Operations include("group_operations/addition_operation.jl") include("group_operations/multiplication_operation.jl") +include("group_operations/power_operation.jl") +include("group_operations/product_operation.jl") +include("group_operations/semidirect_product_operation.jl") # Actions include("group_actions/group_action_interface.jl") @@ -37,6 +40,7 @@ include("groups/translation_group.jl") include("groups/general_linear_group.jl") export LieGroup, LieAlgebra +export PowerLieGroup export LieAlgebraOrthogonalBasis # # @@ -54,7 +58,7 @@ export AbstractLeftGroupActionType, AbstractRightGroupActionType export LeftGroupOperation, RightGroupOperation export InverseLeftGroupOperation, InverseRightGroupOperation export GroupOperationAction - +export ProductGroupAction # # # Specific groups diff --git a/src/group_operations/power_operation.jl b/src/group_operations/power_operation.jl new file mode 100644 index 00000000..d43715e2 --- /dev/null +++ b/src/group_operations/power_operation.jl @@ -0,0 +1,31 @@ +# +# +# Lie groups over a power manifold work as large products, where on every factor +# the same group operation is used. Hence we also only need one group operation, +# we can recognize power Lie groups when the manifold is a power manifold. + +""" + PowerLieGroup(G::LieGroup, size::Int...; kwargs...) + PowerLieGroup(M::AbstractManifold, op::AbstractGroupOperation, size:Int...; kwargs...) + (L::LueGroup)^(n...) = PowerLieGroup(L, n...) + +Generate the [`LieGroup`](@ref) of the `n`-th power of a Lie group `G` or manifold `M`. +If passed a Lie group `G`, the group operation is the same as on `G`, but applied elementwise. + +The keyword arguments `kwargs...` are passed on to the constructor of the [`PowerManifold`](@exref). +""" +PowerLieGroup(::AbstractManifold, size::Int...; kwargs...) + +function PowerLieGroup(L::LieGroup, size::Int...; kwargs...) + pM = Manifolds.PowerManifold(L.manifold, size; kwargs...) + return LieGroup(pM, L.op) +end + +function PowerLieGroup( + M::AbstractManifold, op::AbstractGroupOperation, size::Int...; kwargs... +) + pM = Manifolds.PowerManifold(M, size; kwargs...) + return LieGroup(pM, L.op) +end + +Base.:^(L::LieGroup, n...) = PowerLieGroup(L, n...) diff --git a/src/group_operations/product_operation.jl b/src/group_operations/product_operation.jl new file mode 100644 index 00000000..11832872 --- /dev/null +++ b/src/group_operations/product_operation.jl @@ -0,0 +1,19 @@ +# +# +# Together with a product group operation, that is a tuple of operations, +# One for each factor, we define the product operation as acting element wise. + +""" + ProductOperation{O} <: AbstractGroupOperation + +A struct do model a tuple of group operations, one for each factor of a product group, +that together forms a new group operation. + +# Constructor + + ProductOperation(O...) +""" +struct ProductOperation{OTM<:Tuple} <: AbstractGroupOperation + operations::OTM +end +ProductOperation(operations::AbstractGroupOperation...) = ProductOperation(operations) diff --git a/src/group_operations/semidirect_product_operation.jl b/src/group_operations/semidirect_product_operation.jl new file mode 100644 index 00000000..2dc70b32 --- /dev/null +++ b/src/group_operations/semidirect_product_operation.jl @@ -0,0 +1,5 @@ + +# +# +# Semidirect product groups – model semidirect products of rwo Lie groups +# From 24c5e4e92c1c25b25d027a9e230cd07138fc2515 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Tue, 5 Nov 2024 09:12:45 +0100 Subject: [PATCH 02/43] Fix Test. --- src/LieGroups.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/LieGroups.jl b/src/LieGroups.jl index 754909f9..247f1e9b 100644 --- a/src/LieGroups.jl +++ b/src/LieGroups.jl @@ -58,7 +58,6 @@ export AbstractLeftGroupActionType, AbstractRightGroupActionType export LeftGroupOperation, RightGroupOperation export InverseLeftGroupOperation, InverseRightGroupOperation export GroupOperationAction -export ProductGroupAction # # # Specific groups From 9529e56ac4713717ddc5e220fc1a81d5d4ed4ad1 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Wed, 6 Nov 2024 20:35:29 +0100 Subject: [PATCH 03/43] I think it has become too late for me to be clever enough to make the dispatch for this show method to work. --- .../config/vocabularies/LieGroups/accept.txt | 3 +-- src/LieGroups.jl | 7 ++++--- .../power_group.jl} | 20 +++++++++++-------- .../product_group.jl} | 0 .../semidirect_product_group.jl} | 0 src/interface.jl | 13 ++++++++++-- .../LieGroupsTestSuite.jl | 8 ++++---- test/groups/test_power_group.jl | 15 ++++++++++++++ test/groups/test_product_group.jl | 7 +++++++ test/groups/test_semidirect_product_group.jl | 7 +++++++ test/runtests.jl | 9 +++++++++ 11 files changed, 70 insertions(+), 19 deletions(-) rename src/{group_operations/power_operation.jl => groups/power_group.jl} (71%) rename src/{group_operations/product_operation.jl => groups/product_group.jl} (100%) rename src/{group_operations/semidirect_product_operation.jl => groups/semidirect_product_group.jl} (100%) create mode 100644 test/groups/test_power_group.jl create mode 100644 test/groups/test_product_group.jl create mode 100644 test/groups/test_semidirect_product_group.jl mode change 100644 => 100755 test/runtests.jl diff --git a/docs/styles/config/vocabularies/LieGroups/accept.txt b/docs/styles/config/vocabularies/LieGroups/accept.txt index 043f7a7c..0224dd2f 100644 --- a/docs/styles/config/vocabularies/LieGroups/accept.txt +++ b/docs/styles/config/vocabularies/LieGroups/accept.txt @@ -1,5 +1,4 @@ -julia -Julia +[jJ]ulia LieGroups.jl Lie algebra Lie algebras diff --git a/src/LieGroups.jl b/src/LieGroups.jl index 247f1e9b..a32415c5 100644 --- a/src/LieGroups.jl +++ b/src/LieGroups.jl @@ -27,14 +27,15 @@ include("Lie_algebra/Lie_algebra_interface.jl") # Generic Operations include("group_operations/addition_operation.jl") include("group_operations/multiplication_operation.jl") -include("group_operations/power_operation.jl") -include("group_operations/product_operation.jl") -include("group_operations/semidirect_product_operation.jl") # Actions include("group_actions/group_action_interface.jl") include("group_actions/group_operation_action.jl") +# Meta Lie groups +include("groups/power_group.jl") +include("groups/product_group.jl") +include("groups/semidirect_product_group.jl") # Lie groups include("groups/translation_group.jl") include("groups/general_linear_group.jl") diff --git a/src/group_operations/power_operation.jl b/src/groups/power_group.jl similarity index 71% rename from src/group_operations/power_operation.jl rename to src/groups/power_group.jl index d43715e2..6245776b 100644 --- a/src/group_operations/power_operation.jl +++ b/src/groups/power_group.jl @@ -4,7 +4,7 @@ # the same group operation is used. Hence we also only need one group operation, # we can recognize power Lie groups when the manifold is a power manifold. -""" +@doc """ PowerLieGroup(G::LieGroup, size::Int...; kwargs...) PowerLieGroup(M::AbstractManifold, op::AbstractGroupOperation, size:Int...; kwargs...) (L::LueGroup)^(n...) = PowerLieGroup(L, n...) @@ -16,16 +16,20 @@ The keyword arguments `kwargs...` are passed on to the constructor of the [`Powe """ PowerLieGroup(::AbstractManifold, size::Int...; kwargs...) -function PowerLieGroup(L::LieGroup, size::Int...; kwargs...) - pM = Manifolds.PowerManifold(L.manifold, size; kwargs...) - return LieGroup(pM, L.op) -end - function PowerLieGroup( M::AbstractManifold, op::AbstractGroupOperation, size::Int...; kwargs... ) - pM = Manifolds.PowerManifold(M, size; kwargs...) - return LieGroup(pM, L.op) + pM = Manifolds.PowerManifold(M, size...; kwargs...) + return LieGroup(pM, op) +end +function PowerLieGroup(L::LieGroup, size::Int...; kwargs...) + return PowerLieGroup(L.manifold, L.op, size...; kwargs...) end Base.:^(L::LieGroup, n...) = PowerLieGroup(L, n...) + +function show(io::IO, G::LieGroup{𝔽,O,<:ManifoldsBase.AbstractPowerManifold}) where {𝔽,O} + M = G.manifold.manifold + size = get_parameter(G.manifold.size) + return print(io, "PowerLieGroup($(M), $(G.op), $(join(size, ", ")))") +end diff --git a/src/group_operations/product_operation.jl b/src/groups/product_group.jl similarity index 100% rename from src/group_operations/product_operation.jl rename to src/groups/product_group.jl diff --git a/src/group_operations/semidirect_product_operation.jl b/src/groups/semidirect_product_group.jl similarity index 100% rename from src/group_operations/semidirect_product_operation.jl rename to src/groups/semidirect_product_group.jl diff --git a/src/interface.jl b/src/interface.jl index 45f79fe8..3d5dfaf7 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -10,6 +10,15 @@ on elements of a Lie group ``$(_math(:G))``. """ abstract type AbstractGroupOperation end +@doc """ + AbstractLieGroup{𝔽,O<:AbstractGroupOperation,M<:ManifoldsBase.AbstractManifold{𝔽}} <: AbstractManifold{𝔽} + +Represent a Lie group ``$(_math(:G))`` with a group operation `O=```$(_math(:∘))`` on a manifold `M=```$(_math(:M))``. +""" +abstract type AbstractLieGroup{ + 𝔽,O<:AbstractGroupOperation,M<:ManifoldsBase.AbstractManifold{𝔽} +} <: ManifoldsBase.AbstractManifold{𝔽} end + """ LieAlgebraOrthogonalBasis{𝔽} <: ManifoldsBase.AbstractOrthogonalBasis{𝔽,ManifoldsBase.TangentSpaceType} @@ -30,7 +39,7 @@ function LieAlgebraOrthogonalBasis(𝔽::ManifoldsBase.AbstractNumbers=ℝ) end """ - LieGroup{𝔽, O<:AbstractGroupOperation, M<:AbstractManifold{𝔽}} + LieGroup{𝔽, O<:AbstractGroupOperation, M<:AbstractManifold{𝔽}} <: LieGroup{𝔽,O,M} <: AbstractLieGroup{𝔽,O,M} Represent a Lie Group ``$(_math(:G))``. @@ -53,7 +62,7 @@ Lie groups are named after the Norwegian mathematician [Marius Sophus Lie](https Generate a Lie group based on a manifold `M` and a group operation `op`, where vectors by default are stored in the Lie Algebra. """ struct LieGroup{𝔽,O<:AbstractGroupOperation,M<:ManifoldsBase.AbstractManifold{𝔽}} <: - ManifoldsBase.AbstractManifold{𝔽} + AbstractLieGroup{𝔽,O,M} manifold::M op::O end diff --git a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl index 8982496e..57d766aa 100644 --- a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl +++ b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl @@ -710,8 +710,8 @@ Possible properties are * `:Functions` is a vector of all defined functions for `G` Note that if `f` is in `:Functions`, and `f!` makes sense, for example for `compose`, it is assumed that both are defined. -* `:Points` is a vector of at least three points on `G`, the first is not allowed to be the identity numerically -* `:Vectors` is a vector of at least 3 elements from the Lie algebra `𝔀` og `G` +* `:Points` is a vector of at least 2 points on `G`, the first is not allowed to be the identity numerically +* `:Vectors` is a vector of at least 2 elements from the Lie algebra `𝔀` og `G` * `:Mutating` is a boolean (`true` by default) whether to test the mutating variants of functions or not. * `:Name` is a name of the test. If not provided, defaults to `"\$G"` * `:Rng` is a random number generator, if provided, the random functions are tested with this generator as well @@ -734,9 +734,9 @@ function test_lie_group(G::LieGroup, properties::Dict, expectations::Dict=Dict() mutating = get(properties, :Mutating, true) functions = get(properties, :Functions, Function[]) points = get(properties, :Points, []) - @assert length(points) > 2 + @assert length(points) > 1 vectors = get(properties, :Vectors, []) - @assert length(vectors) > 2 + @assert length(vectors) > 1 test_name = get(properties, :Name, "$G") @testset "$(test_name)" begin # Call function tests based on their presence in alphabetical order diff --git a/test/groups/test_power_group.jl b/test/groups/test_power_group.jl new file mode 100644 index 00000000..0d81f4cb --- /dev/null +++ b/test/groups/test_power_group.jl @@ -0,0 +1,15 @@ +using LieGroups, Test, ManifoldsBase + +s = joinpath(@__DIR__, "LieGroupsTestSuite.jl") +!(s in LOAD_PATH) && (push!(LOAD_PATH, s)) +using LieGroupsTestSuite + +@testset "Generic power Lie group" begin + M = LieGroupsTestSuite.DummyManifold() + op = LieGroupsTestSuite.DummyOperation() + G = LieGroup(M, op) + pG = G^3 + rs = "PowerLieGroup(LieGroupsTestSuite.DummyManifold(), LieGroupsTestSuite.DummyOperation(), 3)" + + # test_lie_group(G, properties, expectations) +end diff --git a/test/groups/test_product_group.jl b/test/groups/test_product_group.jl new file mode 100644 index 00000000..8f5b33dd --- /dev/null +++ b/test/groups/test_product_group.jl @@ -0,0 +1,7 @@ +using LieGroups, Test, ManifoldsBase + +s = joinpath(@__DIR__, "LieGroupsTestSuite.jl") +!(s in LOAD_PATH) && (push!(LOAD_PATH, s)) +using LieGroupsTestSuite + +@testset "Generic product Lie group" begin end diff --git a/test/groups/test_semidirect_product_group.jl b/test/groups/test_semidirect_product_group.jl new file mode 100644 index 00000000..dbec9d2f --- /dev/null +++ b/test/groups/test_semidirect_product_group.jl @@ -0,0 +1,7 @@ +using LieGroups, Test, ManifoldsBase + +s = joinpath(@__DIR__, "LieGroupsTestSuite.jl") +!(s in LOAD_PATH) && (push!(LOAD_PATH, s)) +using LieGroupsTestSuite + +@testset "Generic semidirect product Lie group" begin end diff --git a/test/runtests.jl b/test/runtests.jl old mode 100644 new mode 100755 index bd027224..8615bc45 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,3 +1,7 @@ +#!/usr/bin/env julia --optimize=0 +# +# + using LieGroups, Test s = joinpath(@__DIR__, "LieGroupsTestSuite.jl") @@ -22,6 +26,11 @@ end include_test("actions/test_operation_action.jl") end @testset "Lie Groups" begin + @testset "Meta Lie Groups" begin + include_test("groups/test_power_group.jl") + include_test("groups/test_product_group.jl") + include_test("groups/test_semidirect_product_group.jl") + end include_test("groups/test_general_linear_group.jl") include_test("groups/test_translation_group.jl") end From e302ade00dd3310cf8c6e889a65e405a012d66c1 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Wed, 6 Nov 2024 20:53:07 +0100 Subject: [PATCH 04/43] add entry to news. --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index 9a91f7fe..6320faf3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -15,6 +15,7 @@ Everything denoted by β€œformerly” refers to the previous name in [`Manifolds. * `LieGroup` (formerly `GroupManifold`) as well as the concrete groups * `TranslationGroup` * `GeneralLinearGroup` (formerly `GeneralLinear`) + * `PowerLieGroup` (formerly `PowerGroup`) * `AbstractGroupOperation` as well as its concrete subtypes * `AdditionGroupOperation` (formerly `AdditionOperation`) * `AbstractGroupActionType` with its 2 specific (new) abstract subtypes From 15cae9a4d3194515ff88d38869f98a7d812e73fb Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Tue, 12 Nov 2024 16:44:16 +0100 Subject: [PATCH 05/43] Define nice constructor for product and a show method. --- src/LieGroups.jl | 4 ++- src/groups/product_group.jl | 64 +++++++++++++++++++++++++++++++++++++ src/interface.jl | 13 ++------ 3 files changed, 69 insertions(+), 12 deletions(-) diff --git a/src/LieGroups.jl b/src/LieGroups.jl index a32415c5..dd636625 100644 --- a/src/LieGroups.jl +++ b/src/LieGroups.jl @@ -41,8 +41,9 @@ include("groups/translation_group.jl") include("groups/general_linear_group.jl") export LieGroup, LieAlgebra -export PowerLieGroup +export PowerLieGroup, ProductLieGroup export LieAlgebraOrthogonalBasis +export Γ—, ^ # # # Group Operations @@ -59,6 +60,7 @@ export AbstractLeftGroupActionType, AbstractRightGroupActionType export LeftGroupOperation, RightGroupOperation export InverseLeftGroupOperation, InverseRightGroupOperation export GroupOperationAction +export ProductOperation # # # Specific groups diff --git a/src/groups/product_group.jl b/src/groups/product_group.jl index 11832872..ec5c1a0d 100644 --- a/src/groups/product_group.jl +++ b/src/groups/product_group.jl @@ -12,8 +12,72 @@ that together forms a new group operation. # Constructor ProductOperation(O...) + Γ—(O...) = ProductOperation(O...) """ struct ProductOperation{OTM<:Tuple} <: AbstractGroupOperation operations::OTM end ProductOperation(operations::AbstractGroupOperation...) = ProductOperation(operations) + +@doc raw""" + cross(O1, O2) + O1 Γ— O2 + O1 Γ— O2 Γ— O3 Γ— ... + +Return the [`ProductOperation`](@ref) For two [AbstractGroupOperation`](@ref) `O1` and `O2`, +where for the case that one of them is a [`ProductOperation`](@ref) itself, +the other is either prepended (if `O1` is a product) or appenden (if `O2` is). +If both are product operations, they are combined into one, keeping the order of operations. + +For the case that more than two are concatenated with `Γ—` this is iterated. +""" +cross(::AbstractGroupOperation...) +function LinearAlgebra.cross(O1::AbstractGroupOperation, O2::AbstractGroupOperation) + return ProductOperation(O1, O2) +end +function LinearAlgebra.cross(P::ProductOperation, O::AbstractGroupOperation) + return ProductOperation(P.operations..., O) +end +function LinearAlgebra.cross(O::AbstractGroupOperation, P::ProductOperation) + return ProductOperation(O, P.operations...) +end +function LinearAlgebra.cross(P1::ProductOperation, P2::ProductOperation) + return ProductOperation(P1.operations..., P2.operations...) +end + +""" + ProductLieGroup(L1, L2, ...) + +Return the [`LieGroup`](@ref) of the product of Lie groups `L1` and `L2`, +or manifolds `M1` and `M2` with group operations `op1` and `op2`. + +Alternatively, the short hand `L1 Γ— L2` can be used. +""" +function ProductLieGroup(L1::LieGroup, L2::LieGroup) + return LieGroup(L1.manifold Γ— L2.manifold, L1.op Γ— L2.op) +end + +@doc raw""" + cross(L1, L2) + L1 Γ— L2 + L1 Γ— L2 Γ— L3 Γ— ... + +Return the [`ProductLieGroup`](@ref) For two [`LieGroups`](@ref) `L1` and `L2`, +where for the case that one of them is a [`ProductLieGroup`](@ref) itself, +the other is either prepended (if `L1` is a product) or appenden (if `L2` is). +If both are product Lie groups, they are combined into one, keeping the order of operations. + +For the case that more than two are concatenated with `Γ—` this is iterated. +""" +cross(::LieGroup...) +function LinearAlgebra.cross(L1::LieGroup, L2::LieGroup) + return ProductLieGroup(L1, L2) +end + +function show( + io::IO, G::L +) where {𝔽,O<:ProductOperation,TM<:ManifoldsBase.ProductManifold,L<:LieGroup{𝔽,O,TM}} + M = G.manifold.manifolds + ops = G.op.operations + return print(io, "ProductLieGroup($(join(M, " Γ— ")), $(join(ops, " Γ— ")))") +end diff --git a/src/interface.jl b/src/interface.jl index 3d5dfaf7..45bb5e92 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -10,15 +10,6 @@ on elements of a Lie group ``$(_math(:G))``. """ abstract type AbstractGroupOperation end -@doc """ - AbstractLieGroup{𝔽,O<:AbstractGroupOperation,M<:ManifoldsBase.AbstractManifold{𝔽}} <: AbstractManifold{𝔽} - -Represent a Lie group ``$(_math(:G))`` with a group operation `O=```$(_math(:∘))`` on a manifold `M=```$(_math(:M))``. -""" -abstract type AbstractLieGroup{ - 𝔽,O<:AbstractGroupOperation,M<:ManifoldsBase.AbstractManifold{𝔽} -} <: ManifoldsBase.AbstractManifold{𝔽} end - """ LieAlgebraOrthogonalBasis{𝔽} <: ManifoldsBase.AbstractOrthogonalBasis{𝔽,ManifoldsBase.TangentSpaceType} @@ -39,7 +30,7 @@ function LieAlgebraOrthogonalBasis(𝔽::ManifoldsBase.AbstractNumbers=ℝ) end """ - LieGroup{𝔽, O<:AbstractGroupOperation, M<:AbstractManifold{𝔽}} <: LieGroup{𝔽,O,M} <: AbstractLieGroup{𝔽,O,M} + LieGroup{𝔽, O<:AbstractGroupOperation, M<:AbstractManifold{𝔽}} <: LieGroup{𝔽,O,M} <: AbstractManifold{𝔽} Represent a Lie Group ``$(_math(:G))``. @@ -62,7 +53,7 @@ Lie groups are named after the Norwegian mathematician [Marius Sophus Lie](https Generate a Lie group based on a manifold `M` and a group operation `op`, where vectors by default are stored in the Lie Algebra. """ struct LieGroup{𝔽,O<:AbstractGroupOperation,M<:ManifoldsBase.AbstractManifold{𝔽}} <: - AbstractLieGroup{𝔽,O,M} + ManifoldsBase.AbstractManifold{𝔽} manifold::M op::O end From 774edf8f02a9950bd7b3717a11f2c0fc04a6e90f Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Tue, 12 Nov 2024 17:17:43 +0100 Subject: [PATCH 06/43] Start test suite for product. --- src/groups/power_group.jl | 14 +++---- src/groups/product_group.jl | 31 ++++++++-------- .../LieGroupsTestSuite.jl | 2 - test/groups/test_product_group.jl | 37 ++++++++++++++++++- 4 files changed, 57 insertions(+), 27 deletions(-) diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index 6245776b..8598749c 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -1,8 +1,6 @@ # # -# Lie groups over a power manifold work as large products, where on every factor -# the same group operation is used. Hence we also only need one group operation, -# we can recognize power Lie groups when the manifold is a power manifold. +# Power Lie groups: work element wise @doc """ PowerLieGroup(G::LieGroup, size::Int...; kwargs...) @@ -22,13 +20,15 @@ function PowerLieGroup( pM = Manifolds.PowerManifold(M, size...; kwargs...) return LieGroup(pM, op) end -function PowerLieGroup(L::LieGroup, size::Int...; kwargs...) - return PowerLieGroup(L.manifold, L.op, size...; kwargs...) +function PowerLieGroup(G::LieGroup, size::Int...; kwargs...) + return PowerLieGroup(G.manifold, G.op, size...; kwargs...) end -Base.:^(L::LieGroup, n...) = PowerLieGroup(L, n...) +Base.:^(G::LieGroup, n...) = PowerLieGroup(G, n...) -function show(io::IO, G::LieGroup{𝔽,O,<:ManifoldsBase.AbstractPowerManifold}) where {𝔽,O} +function Base.show( + io::IO, G::LieGroup{𝔽,O,<:ManifoldsBase.AbstractPowerManifold} +) where {𝔽,O} M = G.manifold.manifold size = get_parameter(G.manifold.size) return print(io, "PowerLieGroup($(M), $(G.op), $(join(size, ", ")))") diff --git a/src/groups/product_group.jl b/src/groups/product_group.jl index ec5c1a0d..c505bf18 100644 --- a/src/groups/product_group.jl +++ b/src/groups/product_group.jl @@ -46,37 +46,36 @@ function LinearAlgebra.cross(P1::ProductOperation, P2::ProductOperation) end """ - ProductLieGroup(L1, L2, ...) + ProductLieGroup(G, H, ...) -Return the [`LieGroup`](@ref) of the product of Lie groups `L1` and `L2`, -or manifolds `M1` and `M2` with group operations `op1` and `op2`. +Return the [`LieGroup`](@ref) of the product of Lie groups `G` and `H`. -Alternatively, the short hand `L1 Γ— L2` can be used. +Alternatively, the short hand `G Γ— H` can be used. """ -function ProductLieGroup(L1::LieGroup, L2::LieGroup) - return LieGroup(L1.manifold Γ— L2.manifold, L1.op Γ— L2.op) +function ProductLieGroup(G::LieGroup, H::LieGroup) + return LieGroup(G.manifold Γ— H.manifold, G.op Γ— H.op) end @doc raw""" - cross(L1, L2) - L1 Γ— L2 - L1 Γ— L2 Γ— L3 Γ— ... + cross(G, H) + G Γ— H + G1 Γ— G2 Γ— G3 Γ— ... -Return the [`ProductLieGroup`](@ref) For two [`LieGroups`](@ref) `L1` and `L2`, +Return the [`ProductLieGroup`](@ref) For two [`LieGroups`](@ref) `G` and `H`, where for the case that one of them is a [`ProductLieGroup`](@ref) itself, -the other is either prepended (if `L1` is a product) or appenden (if `L2` is). +the other is either prepended (if `H` is a product) or appenden (if `G` is). If both are product Lie groups, they are combined into one, keeping the order of operations. For the case that more than two are concatenated with `Γ—` this is iterated. """ cross(::LieGroup...) -function LinearAlgebra.cross(L1::LieGroup, L2::LieGroup) - return ProductLieGroup(L1, L2) +function LinearAlgebra.cross(G::LieGroup, H::LieGroup) + return ProductLieGroup(G, H) end -function show( - io::IO, G::L -) where {𝔽,O<:ProductOperation,TM<:ManifoldsBase.ProductManifold,L<:LieGroup{𝔽,O,TM}} +function Base.show( + io::IO, G::LieGroup{𝔽,<:ProductOperation,<:ManifoldsBase.ProductManifold} +) where {𝔽} M = G.manifold.manifolds ops = G.op.operations return print(io, "ProductLieGroup($(join(M, " Γ— ")), $(join(ops, " Γ— ")))") diff --git a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl index 57d766aa..2c574bea 100644 --- a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl +++ b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl @@ -734,9 +734,7 @@ function test_lie_group(G::LieGroup, properties::Dict, expectations::Dict=Dict() mutating = get(properties, :Mutating, true) functions = get(properties, :Functions, Function[]) points = get(properties, :Points, []) - @assert length(points) > 1 vectors = get(properties, :Vectors, []) - @assert length(vectors) > 1 test_name = get(properties, :Name, "$G") @testset "$(test_name)" begin # Call function tests based on their presence in alphabetical order diff --git a/test/groups/test_product_group.jl b/test/groups/test_product_group.jl index 8f5b33dd..0e176ec7 100644 --- a/test/groups/test_product_group.jl +++ b/test/groups/test_product_group.jl @@ -1,7 +1,40 @@ using LieGroups, Test, ManifoldsBase -s = joinpath(@__DIR__, "LieGroupsTestSuite.jl") +s = joinpath(@__DIR__, "..", "LieGroupsTestSuite.jl") !(s in LOAD_PATH) && (push!(LOAD_PATH, s)) using LieGroupsTestSuite -@testset "Generic product Lie group" begin end +@testset "Generic product Lie group" begin + M = LieGroupsTestSuite.DummyManifold() + op = LieGroupsTestSuite.DummyOperation() + G = LieGroup(M, op) + G2 = G Γ— G + + properties = Dict( + :Name => "The Product Manifold", + # :Rng => Random.MersenneTwister(), + :Functions => [ + # compose, + # conjugate, + # diff_conjugate, + # diff_inv, + # diff_left_compose, + # diff_right_compose, + # exp, + # hat, + # inv, + # inv_left_compose, + # inv_right_compose, + # is_identity, + # lie_bracket, + # log, + #rand, + show, + #vee, + ], + ) + expectations = Dict( + :repr => "ProductLieGroup(LieGroupsTestSuite.DummyManifold() Γ— LieGroupsTestSuite.DummyManifold(), LieGroupsTestSuite.DummyOperation() Γ— LieGroupsTestSuite.DummyOperation())", + ) + test_lie_group(G2, properties, expectations) +end From 6068f0aeb3b645a682e0cec1276d9ef974edb395 Mon Sep 17 00:00:00 2001 From: Mateusz Baran Date: Tue, 12 Nov 2024 17:24:21 +0100 Subject: [PATCH 07/43] fix show for power group --- src/groups/power_group.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index 8598749c..0ad23dc8 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -28,8 +28,8 @@ Base.:^(G::LieGroup, n...) = PowerLieGroup(G, n...) function Base.show( io::IO, G::LieGroup{𝔽,O,<:ManifoldsBase.AbstractPowerManifold} -) where {𝔽,O} +) where {𝔽,O<:AbstractGroupOperation} M = G.manifold.manifold - size = get_parameter(G.manifold.size) + size = Manifolds.get_parameter(G.manifold.size) return print(io, "PowerLieGroup($(M), $(G.op), $(join(size, ", ")))") end From b90fee55f4b3961bc2a693e1ae206e3b3a2a31e0 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Tue, 12 Nov 2024 17:30:37 +0100 Subject: [PATCH 08/43] setup power lie group test suite. --- test/groups/test_power_group.jl | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/test/groups/test_power_group.jl b/test/groups/test_power_group.jl index 0d81f4cb..6720e708 100644 --- a/test/groups/test_power_group.jl +++ b/test/groups/test_power_group.jl @@ -1,6 +1,6 @@ using LieGroups, Test, ManifoldsBase -s = joinpath(@__DIR__, "LieGroupsTestSuite.jl") +s = joinpath(@__DIR__, "..", "LieGroupsTestSuite.jl") !(s in LOAD_PATH) && (push!(LOAD_PATH, s)) using LieGroupsTestSuite @@ -8,8 +8,33 @@ using LieGroupsTestSuite M = LieGroupsTestSuite.DummyManifold() op = LieGroupsTestSuite.DummyOperation() G = LieGroup(M, op) - pG = G^3 - rs = "PowerLieGroup(LieGroupsTestSuite.DummyManifold(), LieGroupsTestSuite.DummyOperation(), 3)" + pG = G^2 - # test_lie_group(G, properties, expectations) + properties = Dict( + :Name => "The Power Manifold", + # :Rng => Random.MersenneTwister(), + :Functions => [ + # compose, + # conjugate, + # diff_conjugate, + # diff_inv, + # diff_left_compose, + # diff_right_compose, + # exp, + # hat, + # inv, + # inv_left_compose, + # inv_right_compose, + # is_identity, + # lie_bracket, + # log, + # rand, + show, + #vee, + ], + ) + expectations = Dict( + :repr => "PowerLieGroup(LieGroupsTestSuite.DummyManifold(), LieGroupsTestSuite.DummyOperation(), 2)", + ) + test_lie_group(pG, properties, expectations) end From 5172b3bdaa86b6b16b199766e8435ab65d14aa00 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Tue, 12 Nov 2024 17:41:04 +0100 Subject: [PATCH 09/43] increase test coverage. --- test/groups/test_product_group.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/groups/test_product_group.jl b/test/groups/test_product_group.jl index 0e176ec7..0040036e 100644 --- a/test/groups/test_product_group.jl +++ b/test/groups/test_product_group.jl @@ -37,4 +37,12 @@ using LieGroupsTestSuite :repr => "ProductLieGroup(LieGroupsTestSuite.DummyManifold() Γ— LieGroupsTestSuite.DummyManifold(), LieGroupsTestSuite.DummyOperation() Γ— LieGroupsTestSuite.DummyOperation())", ) test_lie_group(G2, properties, expectations) + + @testset "Product Operation generators" begin + op2 = LieGroupsTestSuite.DummySecondOperation() + O1 = op Γ— op2 + O2 = op2 Γ— op + @test (O1 Γ— op) == (op Γ— O2) + @test (O1 Γ— O2) == (op Γ— op2 Γ— op2 Γ— op) + end end From 9366f9daa1a000473050461bbd37be50af115fa8 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Wed, 13 Nov 2024 21:02:47 +0100 Subject: [PATCH 10/43] Initial sketch of semidirect products --- docs/make.jl | 3 + docs/src/groups/power_group.md | 7 ++ docs/src/groups/product_group.md | 7 ++ docs/src/groups/semidirect_product_group.md | 7 ++ src/LieGroups.jl | 6 +- src/groups/power_group.jl | 2 +- src/groups/product_group.jl | 32 +++--- src/groups/semidirect_product_group.jl | 103 ++++++++++++++++++++ 8 files changed, 148 insertions(+), 19 deletions(-) create mode 100644 docs/src/groups/power_group.md create mode 100644 docs/src/groups/product_group.md create mode 100644 docs/src/groups/semidirect_product_group.md diff --git a/docs/make.jl b/docs/make.jl index fdaf427d..b2c66e37 100755 --- a/docs/make.jl +++ b/docs/make.jl @@ -125,6 +125,9 @@ makedocs(; "Lie groups" => [ "List of Lie groups" => "groups/index.md", "General Linear" => "groups/general_linear.md", + "power group" => "groups/power_group.md", + "product group" => "groups/product_group.md", + "Semidirect product group" => "groups/semidirect_product_group.md", "Translation group" => "groups/translation.md", ], "Interfaces" => [ diff --git a/docs/src/groups/power_group.md b/docs/src/groups/power_group.md new file mode 100644 index 00000000..ac8efefe --- /dev/null +++ b/docs/src/groups/power_group.md @@ -0,0 +1,7 @@ +# The power Lie group + +```@autodocs +Modules = [LieGroups] +Pages = ["groups/power_group.jl"] +Order = [:type, :function] +``` \ No newline at end of file diff --git a/docs/src/groups/product_group.md b/docs/src/groups/product_group.md new file mode 100644 index 00000000..3587ea8c --- /dev/null +++ b/docs/src/groups/product_group.md @@ -0,0 +1,7 @@ +# The product Lie group + +```@autodocs +Modules = [LieGroups] +Pages = ["groups/product_group.jl"] +Order = [:type, :function] +``` \ No newline at end of file diff --git a/docs/src/groups/semidirect_product_group.md b/docs/src/groups/semidirect_product_group.md new file mode 100644 index 00000000..06cf0861 --- /dev/null +++ b/docs/src/groups/semidirect_product_group.md @@ -0,0 +1,7 @@ +# The semidirect product Lie group + +```@autodocs +Modules = [LieGroups] +Pages = ["groups/semidirect_product_group.jl"] +Order = [:type, :function] +``` \ No newline at end of file diff --git a/src/LieGroups.jl b/src/LieGroups.jl index dd636625..0f849248 100644 --- a/src/LieGroups.jl +++ b/src/LieGroups.jl @@ -41,9 +41,9 @@ include("groups/translation_group.jl") include("groups/general_linear_group.jl") export LieGroup, LieAlgebra -export PowerLieGroup, ProductLieGroup +export PowerLieGroup, ProductLieGroup, SemidirectProductLieGroup export LieAlgebraOrthogonalBasis -export Γ—, ^ +export Γ—, ^, ⋉, β‹Š # # # Group Operations @@ -51,6 +51,7 @@ export AbstractGroupOperation, Identity export AdditionGroupOperation export AbstractMultiplicationGroupOperation export MatrixMultiplicationGroupOperation +export ProductGroupOperation, SemidirectProductGroupOperation # # @@ -60,7 +61,6 @@ export AbstractLeftGroupActionType, AbstractRightGroupActionType export LeftGroupOperation, RightGroupOperation export InverseLeftGroupOperation, InverseRightGroupOperation export GroupOperationAction -export ProductOperation # # # Specific groups diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index 0ad23dc8..7120280e 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -10,7 +10,7 @@ Generate the [`LieGroup`](@ref) of the `n`-th power of a Lie group `G` or manifold `M`. If passed a Lie group `G`, the group operation is the same as on `G`, but applied elementwise. -The keyword arguments `kwargs...` are passed on to the constructor of the [`PowerManifold`](@exref). +The keyword arguments `kwargs...` are passed on to the constructor of the [`PowerManifold`](@extref `ManifoldsBase.PowerManifold`). """ PowerLieGroup(::AbstractManifold, size::Int...; kwargs...) diff --git a/src/groups/product_group.jl b/src/groups/product_group.jl index c505bf18..a545b0f2 100644 --- a/src/groups/product_group.jl +++ b/src/groups/product_group.jl @@ -4,28 +4,30 @@ # One for each factor, we define the product operation as acting element wise. """ - ProductOperation{O} <: AbstractGroupOperation + ProductGroupOperation{O} <: AbstractGroupOperation A struct do model a tuple of group operations, one for each factor of a product group, that together forms a new group operation. # Constructor - ProductOperation(O...) - Γ—(O...) = ProductOperation(O...) + ProductGroupOperation(O...) + Γ—(O...) = ProductGroupOperation(O...) """ -struct ProductOperation{OTM<:Tuple} <: AbstractGroupOperation +struct ProductGroupOperation{OTM<:Tuple} <: AbstractGroupOperation operations::OTM end -ProductOperation(operations::AbstractGroupOperation...) = ProductOperation(operations) +function ProductGroupOperation(operations::AbstractGroupOperation...) + return ProductGroupOperation(operations) +end @doc raw""" cross(O1, O2) O1 Γ— O2 O1 Γ— O2 Γ— O3 Γ— ... -Return the [`ProductOperation`](@ref) For two [AbstractGroupOperation`](@ref) `O1` and `O2`, -where for the case that one of them is a [`ProductOperation`](@ref) itself, +Return the [`ProductGroupOperation`](@ref) For two [AbstractGroupOperation`](@ref) `O1` and `O2`, +where for the case that one of them is a [`ProductGroupOperation`](@ref) itself, the other is either prepended (if `O1` is a product) or appenden (if `O2` is). If both are product operations, they are combined into one, keeping the order of operations. @@ -33,16 +35,16 @@ For the case that more than two are concatenated with `Γ—` this is iterated. """ cross(::AbstractGroupOperation...) function LinearAlgebra.cross(O1::AbstractGroupOperation, O2::AbstractGroupOperation) - return ProductOperation(O1, O2) + return ProductGroupOperation(O1, O2) end -function LinearAlgebra.cross(P::ProductOperation, O::AbstractGroupOperation) - return ProductOperation(P.operations..., O) +function LinearAlgebra.cross(P::ProductGroupOperation, O::AbstractGroupOperation) + return ProductGroupOperation(P.operations..., O) end -function LinearAlgebra.cross(O::AbstractGroupOperation, P::ProductOperation) - return ProductOperation(O, P.operations...) +function LinearAlgebra.cross(O::AbstractGroupOperation, P::ProductGroupOperation) + return ProductGroupOperation(O, P.operations...) end -function LinearAlgebra.cross(P1::ProductOperation, P2::ProductOperation) - return ProductOperation(P1.operations..., P2.operations...) +function LinearAlgebra.cross(P1::ProductGroupOperation, P2::ProductGroupOperation) + return ProductGroupOperation(P1.operations..., P2.operations...) end """ @@ -74,7 +76,7 @@ function LinearAlgebra.cross(G::LieGroup, H::LieGroup) end function Base.show( - io::IO, G::LieGroup{𝔽,<:ProductOperation,<:ManifoldsBase.ProductManifold} + io::IO, G::LieGroup{𝔽,<:ProductGroupOperation,<:ManifoldsBase.ProductManifold} ) where {𝔽} M = G.manifold.manifolds ops = G.op.operations diff --git a/src/groups/semidirect_product_group.jl b/src/groups/semidirect_product_group.jl index 2dc70b32..de966d39 100644 --- a/src/groups/semidirect_product_group.jl +++ b/src/groups/semidirect_product_group.jl @@ -3,3 +3,106 @@ # # Semidirect product groups – model semidirect products of rwo Lie groups # +""" + SemidirectProductGroupOperation{O1,O2,A} <: AbstractGroupOperation + +A struct to model a semidirect Lie group product. + +Let ``($(_tex(:Cal, "N")), β‹„)`` and ``($(_tex(:Cal, "H")), ⋆)`` be two Lie groups +with group operations ``β‹„`` and ``⋆``, respectively, as well as +a (left) group action +``Οƒ: $(_tex(:Cal, "H"))Γ—$(_tex(:Cal, "N")) β†’ $(_tex(:Cal, "N"))``, cf [`AbstractLeftGroupActionType`](#ref). +We use here as well use the notation ``Οƒ_h: $(_tex(:Cal, "N")) β†’ $(_tex(:Cal, "N"))`` as a family of maps on ``$(_tex(:Cal, "N"))`` + +Then we define a group operation ``∘`` on the product manifold $(_tex(:Cal, "N"))Γ—$(_tex(:Cal, "H")) by + +```math + (n_1,h_1) ∘ (n_2,h_2) := (n_1 β‹„ Οƒ_{h_1}(n_2), h_1 ⋆ h_2) +``` + +and similarly for a right group action, for example ``Ο„_h = (Οƒ_h)^{-1}`` + a group operation on $(_tex(:Cal, "H"))Γ—$(_tex(:Cal, "N")) + +```math + (h_1,n_1) ∘ (h_2,n_2) := (h_1 ⋆ h_2, Ο„_{h_2}(n_1) β‹„ n_1). +``` + +See [HilgertNeeb:2012; Definition 9.2.22](@cite) for more details. + +# Constructor + + SemidirectProductGroupOperation(op1::AbstractGroupOperation, op2::AbstractGroupOperation, action=LeftGroupOperation()) + op1 β‹Š op2 + op1 ⋉ op2 + +Create a `SemidirectProductGroupOperation` for [`AbstractGroupOperation`](@ref) `op1=```β‹„`` and `pΓΌ2=```⋆`` +together with an [`AbstractGroupActionType`](@ref) `action` that defaults to the [`LeftGroupOperation`](@ref), which yields the corresponding [`GroupOperationAction`](@ref), +that is where the action is given by the group operation of ``$(_tex(:Cal, "H"))`` acting on ``$(_tex(:Cal, "N"))``. +The first shorthand `op1 β‹Š op2` is a short form for this. + +For the second form, use for example the [`RightGroupOperation`](@ref) to also have the [`GroupOperationAction`](@ref) mentioned. +""" +struct SemidirectProductGroupOperation{ + O1<:AbstractGroupOperation,O2<:AbstractGroupOperation,A<:AbstractGroupActionType +} <: AbstractGroupOperation + op1::O1 + op2::O2 + action::A + function SemidirectProductGroupOperation( + op1::O1, op2::O2; action::A=LeftGroupOperation() + ) where { + O1<:AbstractGroupOperation,O2<:AbstractGroupOperation,A<:AbstractGroupActionType + } + return SemidirectProductGroupOperation{O1,O2,A}(op1, op2, action) + end +end + +""" + op1 β‹Š op2 + +For two [`AbstractGroupOperation`](@ref), generate the [`SemidirectProductGroupOperation`](@ref)`(op1, op2; action=`[`LeftGroupOperation`](@ref)`())` +""" +function β‹Š(op1::O1, op2::O2) where {O1<:AbstractGroupOperation,O2<:AbstractGroupOperation} + return SemidirectProductGroupOperation(op1, op2; action=LeftGroupOperation()) +end + +""" + op1 ⋉ op2 + +For two [`AbstractGroupOperation`](@ref), generate the [`SemidirectProductGroupOperation`](@ref)`(op1, op2; action=`[`RightGroupOperation`](@ref)`())` +""" +function ⋉(op1::O1, op2::O2) where {O1<:AbstractGroupOperation,O2<:AbstractGroupOperation} + return SemidirectProductGroupOperation(op1, op2; action=RightGroupOperation()) +end + +""" + SemidirectProductLieGroup(N::LieGroup, H::LieGroup; action=LeftGroupOperation()) + +Generate the semidirect product Lie Group ``$(_tex(:Cal, "G")) = N β‹Š H`` for an [`AbstractLeftGroupActionType`](@ref), +and ``$(_tex(:Cal, "G")) = N ⋉ H`` for an [`AbstractRightGroupActionType`](@ref), + +see [`SemidirectProductGroupOperation`](@ref) for the group operation definition as well as [HilgertNeeb:2012; Definition 9.2.22](@cite) for more details. +""" +function SemidirectProductLieGroup(N::LieGroup, H::LieGroup; action=LeftGroupOperation()) + return LieGroup( + N.manifold Γ— H.manifold, SemidirectProductGroupOperation(N.op, H.op; action=action) + ) +end + +""" + L1 β‹Š L2 + +For two [`LieGroups`](@ref), generate the [`SemidirectProductLieGroup`](@ref)`(L1, L2; action=`[`LeftGroupOperation`](@ref)`())` +""" +function β‹Š(L1::LieGroup, L2::LieGroup) + return SemidirectProductLieGroup(L1, L2; action=LeftGroupOperation()) +end + +""" + L1 ⋉ L2 + +For two [`LieGroups`](@ref), generate the [`SemidirectProductLieGroup`](@ref)`(L1, L2; action=`[`RightGroupOperation`](@ref)`())` +""" +function ⋉(L1::LieGroup, L2::LieGroup) + return SemidirectProductLieGroup(L1, L2; action=RightGroupOperation()) +end From 7c2dde3396b45369f7959fe1e6ab0ad2ffe93ac7 Mon Sep 17 00:00:00 2001 From: Mateusz Baran Date: Fri, 15 Nov 2024 10:40:54 +0100 Subject: [PATCH 11/43] add type in function --- src/groups/semidirect_product_group.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/groups/semidirect_product_group.jl b/src/groups/semidirect_product_group.jl index de966d39..935ec81a 100644 --- a/src/groups/semidirect_product_group.jl +++ b/src/groups/semidirect_product_group.jl @@ -76,14 +76,18 @@ function ⋉(op1::O1, op2::O2) where {O1<:AbstractGroupOperation,O2<:AbstractGro end """ - SemidirectProductLieGroup(N::LieGroup, H::LieGroup; action=LeftGroupOperation()) + SemidirectProductLieGroup( + N::LieGroup, H::LieGroup; action::AbstractGroupActionType=LeftGroupOperation() + ) Generate the semidirect product Lie Group ``$(_tex(:Cal, "G")) = N β‹Š H`` for an [`AbstractLeftGroupActionType`](@ref), and ``$(_tex(:Cal, "G")) = N ⋉ H`` for an [`AbstractRightGroupActionType`](@ref), see [`SemidirectProductGroupOperation`](@ref) for the group operation definition as well as [HilgertNeeb:2012; Definition 9.2.22](@cite) for more details. """ -function SemidirectProductLieGroup(N::LieGroup, H::LieGroup; action=LeftGroupOperation()) +function SemidirectProductLieGroup( + N::LieGroup, H::LieGroup; action::AbstractGroupActionType=LeftGroupOperation() +) return LieGroup( N.manifold Γ— H.manifold, SemidirectProductGroupOperation(N.op, H.op; action=action) ) From 145028532f70d28e6edb42076bdf68dbdf6f8ff3 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Fri, 15 Nov 2024 12:15:29 +0100 Subject: [PATCH 12/43] A bit of renaming for actions. --- NEWS.md | 8 +- src/LieGroups.jl | 4 +- src/group_actions/group_action_interface.jl | 29 +++-- src/group_actions/group_operation_action.jl | 133 +++++++++----------- src/groups/semidirect_product_group.jl | 45 +++---- test/actions/test_operation_action.jl | 4 +- test/groups/test_translation_group.jl | 8 +- 7 files changed, 107 insertions(+), 124 deletions(-) diff --git a/NEWS.md b/NEWS.md index 6320faf3..2539dc7d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -22,10 +22,10 @@ Everything denoted by β€œformerly” refers to the previous name in [`Manifolds. * `AbstractLeftGroupActionType` * `AbstractRightGroupActionType` * For the group operation actions there are now - * `LeftGroupOperation` (formerly `LeftForwardAction`) - * `RightGroupOperation` (formerly `RightBackwardAction`) - * `InverseLeftGroupOperation` (formerly `RightForwardAction`) - * `InverseRightGroupOperation` (formerly `LeftBackwardAction`) + * `LeftGroupOperationAction` (formerly `LeftForwardAction`) + * `RightGroupOperationAction` (formerly `RightBackwardAction`) + * `InverseLeftGroupOperationActionAction` (formerly `RightForwardAction`) + * `InverseRightGroupOperationActionAction` (formerly `LeftBackwardAction`) * `LieAlgebraOrthogonalBasis` (replaces `VeeOrthogonalBasis`, which is still available in `ManifoldsBase.jl`) * `Identity` * `apply`and `apply!` diff --git a/src/LieGroups.jl b/src/LieGroups.jl index 0f849248..d1724c02 100644 --- a/src/LieGroups.jl +++ b/src/LieGroups.jl @@ -58,8 +58,8 @@ export ProductGroupOperation, SemidirectProductGroupOperation # Group Actions export AbstractGroupActionType, AbstractGroupAction export AbstractLeftGroupActionType, AbstractRightGroupActionType -export LeftGroupOperation, RightGroupOperation -export InverseLeftGroupOperation, InverseRightGroupOperation +export LeftGroupOperationAction, RightGroupOperationAction +export InverseLeftGroupOperationActionAction, InverseRightGroupOperationActionAction export GroupOperationAction # # diff --git a/src/group_actions/group_action_interface.jl b/src/group_actions/group_action_interface.jl index 73d3eb79..2915bcea 100644 --- a/src/group_actions/group_action_interface.jl +++ b/src/group_actions/group_action_interface.jl @@ -5,7 +5,7 @@ @doc """ AbstractGroupActionType -An abstract supertype for group actions. +An abstract supertype for group action types. """ abstract type AbstractGroupActionType end @@ -85,17 +85,28 @@ $(_note_action_argument_order) """ abstract type AbstractRightGroupActionType <: AbstractGroupActionType end -@doc """ - AbstractGroupAction{T<:AbstractGroupActionType, L<:LieGroup, M<:AbstractManifold} +""" + LieGroupOperationAction{T<:AbstractLeftGroupActionType,G<:LieGroup} <: AbstractGroupAction{T,G,G} -An abstract group action of [`AbstractGroupActionType`](@ref) `T` of a [`LieGroup`](@ref) of type `L` +A group action of [`AbstractGroupActionType`](@ref) `T` of a [`LieGroup`](@ref) of type `L` acting on an $(_link(:AbstractManifold)) of type `M`. +# Fields + +* `type::T`: The type of the group action. +* `group::L`: The group acting. +* `manifold::M`: The manifold the group acts upon. + See [HilgertNeeb:2012; Section 9.1.3](@cite) for more details. + """ -abstract type AbstractGroupAction{ - T<:AbstractGroupActionType,L<:LieGroup,M<:AbstractManifold -} end +struct GroupAction{T<:AbstractGroupActionType, L<:LieGroup, M<:Manifold} + type::T + group::L + manifold::M +end + + function base_lie_group end @doc """ @@ -104,14 +115,14 @@ function base_lie_group end Return the [`LieGroup`](@ref) of the [`AbstractGroupAction`](@ref) specifying the action. """ -base_lie_group(::AbstractGroupAction) +base_lie_group(A::GroupAction) = A.group @doc """ base_manifold(A::AbstractGroupAction) Return the $(_link(:AbstractManifold)) the group action acts upon. """ -ManifoldsBase.base_manifold(::AbstractGroupAction) +ManifoldsBase.base_manifold(A::GroupOperationAction) = A.manifold # # diff --git a/src/group_actions/group_operation_action.jl b/src/group_actions/group_operation_action.jl index 6796bb5c..c9480477 100644 --- a/src/group_actions/group_operation_action.jl +++ b/src/group_actions/group_operation_action.jl @@ -1,5 +1,5 @@ """ - LeftGroupOperation <: AbstractLeftGroupActionType + LeftGroupOperationAction <: AbstractLeftGroupActionType A type for the [`AbstractLeftGroupActionType`](@ref) when acting on the group itself from the left, that is @@ -8,12 +8,12 @@ from the left, that is Οƒ_h(g) = Οƒ(h,g) = h$(_math(:∘))g ``` -for its inverse ``(Οƒ_h)^{-1}`` see [`InverseLeftGroupOperation`](@ref). +for its inverse ``(Οƒ_h)^{-1}`` see [`InverseLeftGroupOperationActionAction`](@ref). """ -struct LeftGroupOperation <: AbstractLeftGroupActionType end +struct LeftGroupOperationAction <: AbstractLeftGroupActionType end """ - RightGroupOperation <: AbstractRightGroupActionType + RightGroupOperationAction <: AbstractRightGroupActionType A type for the [`AbstractLeftGroupActionType`](@ref) when acting on the group itself gfrom the right @@ -22,15 +22,15 @@ gfrom the right Οƒ_h(g) = Οƒ(h,g) = g$(_math(:∘))h ``` -for its inverse ``(Οƒ_h)^{-1}`` see [`InverseRightGroupOperation`](@ref). +for its inverse ``(Οƒ_h)^{-1}`` see [`InverseRightGroupOperationActionAction`](@ref). """ -struct RightGroupOperation <: AbstractLeftGroupActionType end +struct RightGroupOperationAction <: AbstractLeftGroupActionType end """ - InverseLeftGroupOperation <: AbstractRightGroupActionType + InverseLeftGroupOperationActionAction <: AbstractRightGroupActionType A type for the [`AbstractLeftGroupActionType`](@ref) when acting on the group itself -given by the inverse of a [`LeftGroupOperation`](@ref) ``Οƒ_h`` as +given by the inverse of a [`LeftGroupOperationAction`](@ref) ``Οƒ_h`` as ```math Ο„_h(g) $(_tex(:def)) Οƒ_h^{-1}(g) = Οƒ(h^{-1},g) = h^{-1}$(_math(:∘))g @@ -41,18 +41,18 @@ properties yield that is is an [`AbstractRightGroupActionType`](@ref), since $(_note(:LeftInverseActionIsRight)) -for its inverse ``(Οƒ_h)^{-1}`` see [`InverseLeftGroupOperation`](@ref). +for its inverse ``(Οƒ_h)^{-1}`` see [`InverseLeftGroupOperationActionAction`](@ref). !!! note Some literature also calls this by itself _the_ right group operation action. """ -struct InverseLeftGroupOperation <: AbstractRightGroupActionType end +struct InverseLeftGroupOperationActionAction <: AbstractRightGroupActionType end """ - InverseRightGroupOperation <: AbstractLeftGroupActionType + InverseRightGroupOperationActionAction <: AbstractLeftGroupActionType A type for the [`AbstractLeftGroupActionType`](@ref) when acting on the group itself -given by the inverse of a [`RightGroupOperation`](@ref) ``Οƒ_h`` as +given by the inverse of a [`RightGroupOperationAction`](@ref) ``Οƒ_h`` as ```math Ο„_h(g) $(_tex(:def)) Οƒ_h^{-1}(g) = Οƒ(h^{-1},g) = g$(_math(:∘))h^{-1} @@ -63,27 +63,14 @@ properties yield that is is an [`AbstractLeftGroupActionType`](@ref), since $(_note(:RightInverseActionIsLeft)) -for its inverse ``(Οƒ_h)^{-1}`` see [`InverseLeftGroupOperation`](@ref). +for its inverse ``(Οƒ_h)^{-1}`` see [`InverseLeftGroupOperationActionAction`](@ref). """ -struct InverseRightGroupOperation <: AbstractLeftGroupActionType end +struct InverseRightGroupOperationActionAction <: AbstractLeftGroupActionType end -""" - GroupOperationAction{T<:AbstractLeftGroupActionType,G<:LieGroup} <: AbstractGroupAction{T,G,G} - -The [`AbstractGroupAction`](@ref). - -""" -struct GroupOperationAction{T<:AbstractGroupActionType,G<:LieGroup} <: - AbstractGroupAction{T,G,G} - type::T - group::G -end - -base_lie_group(A::GroupOperationAction) = A.group - -ManifoldsBase.base_manifold(A::GroupOperationAction) = A.group _doc_apply_groupop = """ + apply( (G,A), g, h) + apply(A::GroupOperationAction, g, h) apply!(A::GroupOperationAction, k, g, h) @@ -97,16 +84,16 @@ apply(A::GroupOperationAction, g, h) @doc "$(_doc_apply_groupop)" apply!(A::GroupOperationAction, k, g, h) -function apply!(A::GroupOperationAction{LeftGroupOperation}, k, g, h) +function apply!(A::GroupOperationAction{LeftGroupOperationAction}, k, g, h) return compose!(A.group, k, g, h) #apply/compose g from left end -function apply!(A::GroupOperationAction{RightGroupOperation}, k, g, h) +function apply!(A::GroupOperationAction{RightGroupOperationAction}, k, g, h) return compose!(A.group, k, h, g) #apply/compose g from right end -function apply!(A::GroupOperationAction{InverseLeftGroupOperation}, k, g, h) +function apply!(A::GroupOperationAction{InverseLeftGroupOperationActionAction}, k, g, h) return inv_left_compose!(A.group, k, g, h) #apply/compose inv(g) from left end -function apply!(A::GroupOperationAction{InverseRightGroupOperation}, k, g, h) +function apply!(A::GroupOperationAction{InverseRightGroupOperationActionAction}, k, g, h) return inv_right_compose!(A.group, k, g, h) #apply/compose inv(g) from right end @@ -117,10 +104,10 @@ _doc_diff_apply_groupop = """ For the group operation action ``Οƒ_g(p)``, compute the differential ``D_p Οƒ_g(p): T_p$(_math(:G)) β†’ T_{Οƒ_g(p)}$(_math(:G))``, that is -* for the [`LeftGroupOperation`](@ref) this calls [`diff_right_compose`](@ref)`(G, g, p, X)`, since here ``Οƒ_g(p) = g$(_math(:∘))p`` -* for the [`RightGroupOperation`](@ref) this calls [`diff_left_compose`](@ref)`(G, p, g, X)`, since here ``Οƒ_g(p) = p$(_math(:∘))g`` -* for the [`InverseLeftGroupOperation`](@ref) this calls [`diff_right_compose`](@ref) with ``g^{-1}``, since here ``Οƒ_g(p) = g^{-1}$(_math(:∘))p`` -* for the [`InverseRightGroupOperation`](@ref) this calls [`diff_left_compose`](@ref) with ``g^{-1}``, since here ``Οƒ_g(p) = p$(_math(:∘))g^{-1}`` +* for the [`LeftGroupOperationAction`](@ref) this calls [`diff_right_compose`](@ref)`(G, g, p, X)`, since here ``Οƒ_g(p) = g$(_math(:∘))p`` +* for the [`RightGroupOperationAction`](@ref) this calls [`diff_left_compose`](@ref)`(G, p, g, X)`, since here ``Οƒ_g(p) = p$(_math(:∘))g`` +* for the [`InverseLeftGroupOperationActionAction`](@ref) this calls [`diff_right_compose`](@ref) with ``g^{-1}``, since here ``Οƒ_g(p) = g^{-1}$(_math(:∘))p`` +* for the [`InverseRightGroupOperationActionAction`](@ref) this calls [`diff_left_compose`](@ref) with ``g^{-1}``, since here ``Οƒ_g(p) = p$(_math(:∘))g^{-1}`` """ @doc "$(_doc_diff_apply_groupop)" diff_apply(A::GroupOperationAction, g, p, X) @@ -128,16 +115,16 @@ diff_apply(A::GroupOperationAction, g, p, X) @doc "$(_doc_diff_apply_groupop)" diff_apply!(A::GroupOperationAction, Y, g, p, X) -function diff_apply!(A::GroupOperationAction{LeftGroupOperation}, Y, g, p, X) +function diff_apply!(A::GroupOperationAction{LeftGroupOperationAction}, Y, g, p, X) return diff_right_compose!(A.group, Y, g, p, X) end -function diff_apply!(A::GroupOperationAction{RightGroupOperation}, Y, g, p, X) +function diff_apply!(A::GroupOperationAction{RightGroupOperationAction}, Y, g, p, X) return diff_left_compose!(A.group, Y, p, g, X) end -function diff_apply!(A::GroupOperationAction{InverseLeftGroupOperation}, Y, g, p, X) +function diff_apply!(A::GroupOperationAction{InverseLeftGroupOperationActionAction}, Y, g, p, X) return diff_right_compose!(A.group, Y, inv(A.group, g), p, X) end -function diff_apply!(A::GroupOperationAction{InverseRightGroupOperation}, Y, g, p, X) +function diff_apply!(A::GroupOperationAction{InverseRightGroupOperationActionAction}, Y, g, p, X) return diff_left_compose!(A.group, Y, p, inv(A.group, g), X) end @@ -148,10 +135,10 @@ _doc_diff_group_apply_groupop = """ Compute the differential ``D_g Οƒ_g(p): $(_math(:𝔀)) β†’ $(_math(:𝔀))`` of a group operation action, that is -* for the [`LeftGroupOperation`](@ref) this calls [`diff_left_compose`](@ref)`(G, g, p, X)`, since here ``Οƒ_g(p) = g$(_math(:∘))p`` -* for the [`RightGroupOperation`](@ref) this calls [`diff_right_compose`](@ref)`(G, p, g, X)`, since here ``Οƒ_g(p) = p$(_math(:∘))g`` -* for the [`InverseLeftGroupOperation`](@ref) this calls [`diff_left_compose`](@ref) with ``g^{-1}``, since here ``Οƒ_g(p) = g^{-1}$(_math(:∘))p`` together with [`diff_inv`](@ref) -* for the [`InverseRightGroupOperation`](@ref) this calls [`diff_right_compose`](@ref) with ``g^{-1}``, since here ``Οƒ_g(p) = p$(_math(:∘))g^{-1}`` together with [`diff_inv`](@ref) +* for the [`LeftGroupOperationAction`](@ref) this calls [`diff_left_compose`](@ref)`(G, g, p, X)`, since here ``Οƒ_g(p) = g$(_math(:∘))p`` +* for the [`RightGroupOperationAction`](@ref) this calls [`diff_right_compose`](@ref)`(G, p, g, X)`, since here ``Οƒ_g(p) = p$(_math(:∘))g`` +* for the [`InverseLeftGroupOperationActionAction`](@ref) this calls [`diff_left_compose`](@ref) with ``g^{-1}``, since here ``Οƒ_g(p) = g^{-1}$(_math(:∘))p`` together with [`diff_inv`](@ref) +* for the [`InverseRightGroupOperationActionAction`](@ref) this calls [`diff_right_compose`](@ref) with ``g^{-1}``, since here ``Οƒ_g(p) = p$(_math(:∘))g^{-1}`` together with [`diff_inv`](@ref) """ @doc "$(_doc_diff_apply_groupop)" @@ -160,17 +147,17 @@ diff_group_apply(A::GroupOperationAction, g, p, X) @doc "$(_doc_diff_apply_groupop)" diff_group_apply!(A::GroupOperationAction, Y, g, p, X) -function diff_group_apply!(A::GroupOperationAction{LeftGroupOperation}, Y, g, p, X) +function diff_group_apply!(A::GroupOperationAction{LeftGroupOperationAction}, Y, g, p, X) return diff_left_compose!(A.group, Y, g, p, X) end -function diff_group_apply!(A::GroupOperationAction{RightGroupOperation}, Y, g, p, X) +function diff_group_apply!(A::GroupOperationAction{RightGroupOperationAction}, Y, g, p, X) return diff_right_compose!(A.group, Y, p, g, X) end -function diff_group_apply!(A::GroupOperationAction{InverseLeftGroupOperation}, Y, g, p, X) +function diff_group_apply!(A::GroupOperationAction{InverseLeftGroupOperationActionAction}, Y, g, p, X) diff_inv!(A.group, Y, g, X) return diff_left_compose!(A.group, Y, inv(A.group, g), p, Y) end -function diff_group_apply!(A::GroupOperationAction{InverseRightGroupOperation}, Y, g, p, X) +function diff_group_apply!(A::GroupOperationAction{InverseRightGroupOperationActionAction}, Y, g, p, X) diff_inv!(A.group, Y, g, X) return diff_right_compose!(A.group, Y, p, inv(A.group, g), Y) end @@ -184,62 +171,62 @@ inverse operation. Base.inv(A::GroupOperationAction) = GroupOperationAction(inv(A.type), A.group) """ - inv(::LeftGroupOperation) + inv(::LeftGroupOperationAction) -Return the inverse of the [`LeftGroupOperation`](@ref), that is the [`InverseLeftGroupOperation`](@ref). +Return the inverse of the [`LeftGroupOperationAction`](@ref), that is the [`InverseLeftGroupOperationActionAction`](@ref). """ -Base.inv(::LeftGroupOperation) = InverseLeftGroupOperation() +Base.inv(::LeftGroupOperationAction) = InverseLeftGroupOperationActionAction() """ - inv(::RightGroupOperation) + inv(::RightGroupOperationAction) -Return the inverse of the [`RightGroupOperation`](@ref), that is the [`InverseRightGroupOperation`](@ref). +Return the inverse of the [`RightGroupOperationAction`](@ref), that is the [`InverseRightGroupOperationActionAction`](@ref). """ -Base.inv(::RightGroupOperation) = InverseRightGroupOperation() +Base.inv(::RightGroupOperationAction) = InverseRightGroupOperationActionAction() """ - inv(::InverseLeftGroupOperation) + inv(::InverseLeftGroupOperationActionAction) -Return the inverse of the [`InverseLeftGroupOperation`](@ref), that is the [`LeftGroupOperation`](@ref). +Return the inverse of the [`InverseLeftGroupOperationActionAction`](@ref), that is the [`LeftGroupOperationAction`](@ref). """ -Base.inv(::InverseLeftGroupOperation) = LeftGroupOperation() +Base.inv(::InverseLeftGroupOperationActionAction) = LeftGroupOperationAction() """ - inv(::InverseRightGroupOperation) + inv(::InverseRightGroupOperationActionAction) -Return the inverse of the [`InverseRightGroupOperation`](@ref), that is the [`RightGroupOperation`](@ref). +Return the inverse of the [`InverseRightGroupOperationActionAction`](@ref), that is the [`RightGroupOperationAction`](@ref). """ -Base.inv(::InverseRightGroupOperation) = RightGroupOperation() +Base.inv(::InverseRightGroupOperationActionAction) = RightGroupOperationAction() function Base.show(io::IO, A::GroupOperationAction) return print(io, "GroupOperationAction($(A.type), $(A.group))") end """ - switch(::LeftGroupOperation) + switch(::LeftGroupOperationAction) -Return the [`RightGroupOperation`](@ref), that is, +Return the [`RightGroupOperationAction`](@ref), that is, turns ``Οƒ_g = g$(_math(:∘))h`` into ``Ο„_g(h) = h$(_math(:∘))g`` """ -switch(::LeftGroupOperation) = RightGroupOperation() +switch(::LeftGroupOperationAction) = RightGroupOperationAction() """ - switch(::RightGroupOperation) + switch(::RightGroupOperationAction) -Return the [`LeftGroupOperation`](@ref), that is, +Return the [`LeftGroupOperationAction`](@ref), that is, turns ``Οƒ_g = h$(_math(:∘))g`` into ``Ο„_g(h) = g$(_math(:∘))h`` """ -switch(::RightGroupOperation) = LeftGroupOperation() +switch(::RightGroupOperationAction) = LeftGroupOperationAction() """ - switch(::InverseLeftGroupOperation) + switch(::InverseLeftGroupOperationActionAction) -Return the [`InverseRightGroupOperation`](@ref), that is, +Return the [`InverseRightGroupOperationActionAction`](@ref), that is, turns ``Οƒ_g = g^{-1}$(_math(:∘))h`` into ``Ο„_g(h) = h$(_math(:∘))g^{-1}`` """ -switch(::InverseLeftGroupOperation) = InverseRightGroupOperation() +switch(::InverseLeftGroupOperationActionAction) = InverseRightGroupOperationActionAction() """ - switch(::InverseRightGroupOperation) + switch(::InverseRightGroupOperationActionAction) -Return the [`InverseLeftGroupOperation`](@ref), that is, +Return the [`InverseLeftGroupOperationActionAction`](@ref), that is, turns ``Οƒ_g = h$(_math(:∘))g^{-1}`` into ``Ο„_g(h) = g^{-1}$(_math(:∘))h`` """ -switch(::InverseRightGroupOperation) = InverseLeftGroupOperation() +switch(::InverseRightGroupOperationActionAction) = InverseLeftGroupOperationActionAction() diff --git a/src/groups/semidirect_product_group.jl b/src/groups/semidirect_product_group.jl index de966d39..cb6c877c 100644 --- a/src/groups/semidirect_product_group.jl +++ b/src/groups/semidirect_product_group.jl @@ -31,25 +31,23 @@ See [HilgertNeeb:2012; Definition 9.2.22](@cite) for more details. # Constructor - SemidirectProductGroupOperation(op1::AbstractGroupOperation, op2::AbstractGroupOperation, action=LeftGroupOperation()) - op1 β‹Š op2 - op1 ⋉ op2 + SemidirectProductGroupOperation(op1::AbstractGroupOperation, op2::AbstractGroupOperation, action) Create a `SemidirectProductGroupOperation` for [`AbstractGroupOperation`](@ref) `op1=```β‹„`` and `pΓΌ2=```⋆`` -together with an [`AbstractGroupActionType`](@ref) `action` that defaults to the [`LeftGroupOperation`](@ref), which yields the corresponding [`GroupOperationAction`](@ref), +together with an [`AbstractGroupActionType`](@ref) `action` that defaults to the [`LeftGroupOperationAction`](@ref), which yields the corresponding [`GroupOperationAction`](@ref), that is where the action is given by the group operation of ``$(_tex(:Cal, "H"))`` acting on ``$(_tex(:Cal, "N"))``. The first shorthand `op1 β‹Š op2` is a short form for this. -For the second form, use for example the [`RightGroupOperation`](@ref) to also have the [`GroupOperationAction`](@ref) mentioned. +For the second form, use for example the [`RightGroupOperationAction`](@ref) to also have the [`GroupOperationAction`](@ref) mentioned. """ struct SemidirectProductGroupOperation{ O1<:AbstractGroupOperation,O2<:AbstractGroupOperation,A<:AbstractGroupActionType } <: AbstractGroupOperation op1::O1 op2::O2 - action::A + action_type::A function SemidirectProductGroupOperation( - op1::O1, op2::O2; action::A=LeftGroupOperation() + op1::O1, op2::O2; action::A=LeftGroupOperationAction() ) where { O1<:AbstractGroupOperation,O2<:AbstractGroupOperation,A<:AbstractGroupActionType } @@ -57,33 +55,20 @@ struct SemidirectProductGroupOperation{ end end -""" - op1 β‹Š op2 - -For two [`AbstractGroupOperation`](@ref), generate the [`SemidirectProductGroupOperation`](@ref)`(op1, op2; action=`[`LeftGroupOperation`](@ref)`())` -""" -function β‹Š(op1::O1, op2::O2) where {O1<:AbstractGroupOperation,O2<:AbstractGroupOperation} - return SemidirectProductGroupOperation(op1, op2; action=LeftGroupOperation()) -end - -""" - op1 ⋉ op2 - -For two [`AbstractGroupOperation`](@ref), generate the [`SemidirectProductGroupOperation`](@ref)`(op1, op2; action=`[`RightGroupOperation`](@ref)`())` -""" -function ⋉(op1::O1, op2::O2) where {O1<:AbstractGroupOperation,O2<:AbstractGroupOperation} - return SemidirectProductGroupOperation(op1, op2; action=RightGroupOperation()) -end +# LeftSemidirectProductLieGroup +# RightSemidirectProductLieGroup +# default_left_action(L1,L2) +# default_right_action(L1,L2) """ - SemidirectProductLieGroup(N::LieGroup, H::LieGroup; action=LeftGroupOperation()) + SemidirectProductLieGroup(N::LieGroup, H::LieGroup; action=LeftGroupOperationAction()) Generate the semidirect product Lie Group ``$(_tex(:Cal, "G")) = N β‹Š H`` for an [`AbstractLeftGroupActionType`](@ref), and ``$(_tex(:Cal, "G")) = N ⋉ H`` for an [`AbstractRightGroupActionType`](@ref), see [`SemidirectProductGroupOperation`](@ref) for the group operation definition as well as [HilgertNeeb:2012; Definition 9.2.22](@cite) for more details. """ -function SemidirectProductLieGroup(N::LieGroup, H::LieGroup; action=LeftGroupOperation()) +function SemidirectProductLieGroup(N::LieGroup, H::LieGroup; action=LeftGroupOperationAction()) return LieGroup( N.manifold Γ— H.manifold, SemidirectProductGroupOperation(N.op, H.op; action=action) ) @@ -92,17 +77,17 @@ end """ L1 β‹Š L2 -For two [`LieGroups`](@ref), generate the [`SemidirectProductLieGroup`](@ref)`(L1, L2; action=`[`LeftGroupOperation`](@ref)`())` +For two [`LieGroups`](@ref), generate the [`SemidirectProductLieGroup`](@ref)`(L1, L2; action=`[`LeftGroupOperationAction`](@ref)`())` """ function β‹Š(L1::LieGroup, L2::LieGroup) - return SemidirectProductLieGroup(L1, L2; action=LeftGroupOperation()) + return SemidirectProductLieGroup(L1, L2; action=LeftGroupOperationAction()) end """ L1 ⋉ L2 -For two [`LieGroups`](@ref), generate the [`SemidirectProductLieGroup`](@ref)`(L1, L2; action=`[`RightGroupOperation`](@ref)`())` +For two [`LieGroups`](@ref), generate the [`SemidirectProductLieGroup`](@ref)`(L1, L2; action=`[`RightGroupOperationAction`](@ref)`())` """ function ⋉(L1::LieGroup, L2::LieGroup) - return SemidirectProductLieGroup(L1, L2; action=RightGroupOperation()) + return SemidirectProductLieGroup(L1, L2; action=RightGroupOperationAction()) end diff --git a/test/actions/test_operation_action.jl b/test/actions/test_operation_action.jl index 8cacc84f..de9b9414 100644 --- a/test/actions/test_operation_action.jl +++ b/test/actions/test_operation_action.jl @@ -5,8 +5,8 @@ s = joinpath(@__DIR__, "..", "LieGroupsTestSuite.jl") using LieGroupsTestSuite @testset "Group Operation as a Group Action" begin - a1 = RightGroupOperation() - a2 = LeftGroupOperation() + a1 = RightGroupOperationAction() + a2 = LeftGroupOperationAction() @test switch(a1) == a2 @test switch(a2) == a1 a3 = inv(a1) diff --git a/test/groups/test_translation_group.jl b/test/groups/test_translation_group.jl index 9ff55e41..6784d7af 100644 --- a/test/groups/test_translation_group.jl +++ b/test/groups/test_translation_group.jl @@ -56,10 +56,10 @@ begin @testset "Translation group operation action" begin # A first group action Test for t in [ - RightGroupOperation(), - LeftGroupOperation(), - InverseLeftGroupOperation(), - InverseRightGroupOperation(), + RightGroupOperationAction(), + LeftGroupOperationAction(), + InverseLeftGroupOperationActionAction(), + InverseRightGroupOperationActionAction(), ] A = GroupOperationAction(t, G) properties2[:Name] = "with $A" From 99caf4f4e49c20385d9a94864e778d7012ce1169 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Fri, 15 Nov 2024 16:19:58 +0100 Subject: [PATCH 13/43] Refactor actions and define semidirect product Lie groups thoroughly. --- src/group_actions/group_action_interface.jl | 92 ++++++++----- src/group_actions/group_operation_action.jl | 69 +++++----- src/groups/semidirect_product_group.jl | 136 +++++++++++++++----- 3 files changed, 198 insertions(+), 99 deletions(-) diff --git a/src/group_actions/group_action_interface.jl b/src/group_actions/group_action_interface.jl index 2915bcea..6dd41062 100644 --- a/src/group_actions/group_action_interface.jl +++ b/src/group_actions/group_action_interface.jl @@ -5,7 +5,7 @@ @doc """ AbstractGroupActionType -An abstract supertype for group action types. +An abstract supertype for group action types, which are used within a [`GroupAction`](@ref). """ abstract type AbstractGroupActionType end @@ -86,10 +86,23 @@ $(_note_action_argument_order) abstract type AbstractRightGroupActionType <: AbstractGroupActionType end """ - LieGroupOperationAction{T<:AbstractLeftGroupActionType,G<:LieGroup} <: AbstractGroupAction{T,G,G} + GroupAction{T<:GroupActionType, L<:LieGroup, M<:AbstractManifold} + +Specify a group action of [`AbstractGroupActionType`](@ref) `T` of a [`LieGroup`](@ref) `G` acting on `M`. + +Let ``$(_math(:M))`` be a $(_link(:AbstractManifold)) and ``$(_math(:G))`` be a [`LieGroup`](@ref) woth group operation ``$(_math(:∘))``. + +A (smooth) action of the group ``$(_math(:G))`` on the manifold ``$(_math(:M))`` is a map + +```math +Οƒ: $(_math(:G)) Γ— $(_math(:M)) β†’ $(_math(:M)) +``` + +with the properties + +* ``Οƒ($(_math(:e)), p) = p`` holds for all ``p ∈ $(_math(:M))`` +* ``Οƒ(g, Οƒ(h, p)) = Οƒ(g$(_math(:∘))h, p)`` holds for all ``g,h ∈ $(_math(:G))``, ``p ∈ $(_math(:M))`` -A group action of [`AbstractGroupActionType`](@ref) `T` of a [`LieGroup`](@ref) of type `L` -acting on an $(_link(:AbstractManifold)) of type `M`. # Fields @@ -100,7 +113,7 @@ acting on an $(_link(:AbstractManifold)) of type `M`. See [HilgertNeeb:2012; Section 9.1.3](@cite) for more details. """ -struct GroupAction{T<:AbstractGroupActionType, L<:LieGroup, M<:Manifold} +struct GroupAction{T<:AbstractGroupActionType,L<:LieGroup,M<:ManifoldsBase.AbstractManifold} type::T group::L manifold::M @@ -110,15 +123,15 @@ end function base_lie_group end @doc """ - base_lie_group(A::AbstractGroupAction) + base_lie_group(A::GroupAction) -Return the [`LieGroup`](@ref) of the [`AbstractGroupAction`](@ref) +Return the [`LieGroup`](@ref) of the [`GroupAction`](@ref) specifying the action. """ base_lie_group(A::GroupAction) = A.group @doc """ - base_manifold(A::AbstractGroupAction) + base_manifold(A::GroupAction) Return the $(_link(:AbstractManifold)) the group action acts upon. """ @@ -129,8 +142,8 @@ ManifoldsBase.base_manifold(A::GroupOperationAction) = A.manifold # Functions _doc_apply = """ - apply(A::AbstractGroupAction{T, L, M}, g, p) - apply!(A::AbstractGroupAction{T, L, M}, q, g, p) + apply(A::GroupAction{T, L, M}, g, p) + apply!(A::GroupAction{T, L, M}, q, g, p) Apply the group action induced by ``g ∈ $(_math(:G))`` to ``p ∈ $(_math(:M))``, where the kind of group action is indicated by the [`AbstractGroupActionType`](@ref) `T`. @@ -140,20 +153,36 @@ This can be perfomed in-place of `q`. # function apply end # un-comment the preceding line and remove this, once GroupManifolds no longer exists in Manifolds.jl @doc "$(_doc_apply)" -function apply(A::AbstractGroupAction, g, p) +function apply(A::GroupAction, g, p) q = allocate_result(base_manifold(A), apply, g, p) apply!(A, q, g, p) return q end +""" + default_left_action(G::LieGroup, M::AbstractManifold) + +Return the default left action for a Lie group `G` acting on a manifold `M`. +""" +default_left_action(N::LieGroup, M::AbstractManifold) + +""" + default_right_action(G::LieGroup, M::AbstractManifold) + +Return the default right action for a Lie group `G` acting on a manifold `M`. +""" +default_right_action(N::LieGroup, M::AbstractManifold) + # Define `function apply! end` here as well # un-comment (remove this comment) when removing this function from Manifolds.jl @doc "$(_doc_apply)" -apply!(A::AbstractGroupAction, q, g, p) +apply!(A::GroupAction, q, g, p) + + _doc_diff_apply = """ - diff_apply(A::AbstractGroupAction{T, L, M}, g, p, X) - diff_apply!(A::AbstractGroupAction{T, L, M}, Y, g, p, X) + diff_apply(A::GroupAction{T, L, M}, g, p, X) + diff_apply!(A::GroupAction{T, L, M}, Y, g, p, X) Compute the differential ``D_p Οƒ_g(p): T_p$(_math(:M)) β†’ T_{Οƒ_g(p)}$(_math(:M))``, where for a left group action we have ``Οƒ_g(p) = Οƒ(g,p)``, for a right action ``Οƒ_g(p) = Οƒ(p, g)``. @@ -161,7 +190,7 @@ where for a left group action we have ``Οƒ_g(p) = Οƒ(g,p)``, for a right action function diff_apply end @doc "$(_doc_diff_apply)" -function diff_apply(A::AbstractGroupAction, g, p, X) +function diff_apply(A::GroupAction, g, p, X) Y = allocate_result(base_manifold(A), apply_diff_group, p, g, X) diff_apply!(A, Y, g, p, X) return Y @@ -169,11 +198,11 @@ end function diff_apply! end @doc "$(_doc_diff_apply)" -diff_apply!(A::AbstractGroupAction, q, g, p) +diff_apply!(A::GroupAction, q, g, p) _doc_diff_group_apply = """ - diff_group_apply(A::AbstractGroupAction{T, L, M}, g, p, X) - diff_group_apply!(A::AbstractGroupAction{T, L, M}, Y, g, p, X) + diff_group_apply(A::GroupAction{T, L, M}, g, p, X) + diff_group_apply!(A::GroupAction{T, L, M}, Y, g, p, X) Compute the differential ``D_g Οƒ_g(p): $(_math(:𝔀)) β†’ $(_math(:𝔀))``, where we use the short hand notation ``Οƒ_p(g) = Οƒ(g,p)`` for a left action, @@ -182,7 +211,7 @@ and for a right action ``Οƒ_p(g) = Οƒ(p, g)``. function diff_group_apply end @doc "$(_doc_diff_group_apply)" -function diff_group_apply(A::AbstractGroupAction, g, p, X) +function diff_group_apply(A::GroupAction, g, p, X) Y = allocate_result(base_manifold(A), apply, g, p, X) diff_group_apply!(A, Y, g, p, X) return Y @@ -190,33 +219,38 @@ end function diff_group_apply! end @doc "$(_doc_diff_group_apply)" -diff_group_apply!(A::AbstractGroupAction, q, g, p) +diff_group_apply!(A::GroupAction, q, g, p) @doc """ - inv(A::AbstractGroupAction{T}) + inv(A::GroupAction{T}) -Return the tuple representing the inverse of an [`AbstractGroupAction`](@ref) of [`AbstractGroupActionType`](@ref) `T`. +Return the [`GroupAction`](@ref) representing the inverse of an [`GroupAction`](@ref) of [`AbstractGroupActionType`](@ref) `T`. This is usually done by returning the group action with the inverse type of `T`. """ -Base.inv(::AbstractGroupAction) +Base.inv(A::GroupAction) = GroupAction(inv(A.type), A.group) -@doc """ - inv(T::AbstractGroupActionType) +""" + inv(::AbstractGroupActionType) -Return the type representing the inverse of an [`AbstractGroupActionType`](@ref). +return the inverse group operation action, that is, use the type representing the +inverse operation. """ Base.inv(::AbstractGroupActionType) +function Base.show(io::IO, A::GroupAction) + return print(io, "GroupAction($(A.type), $(A.group))") +end + function switch end @doc """ - switch(A::AbstractGroupAction{T}) + switch(A::GroupAction{T}) -Return the group operation action representing the similar [`AbstractGroupAction`](@ref) of [`AbstractGroupActionType`](@ref) `T` +Return the group operation action representing the similar [`GroupAction`](@ref) of [`AbstractGroupActionType`](@ref) `T` but acting from the other side. It switches left to right and vice versa. This is done by returning the group action with the β€œswitched” type of `T`. """ -switch(::AbstractGroupAction) +switch(A::GroupAction) = GroupAction(switch(A.type), A.group) @doc """ switch(T::AbstractGroupActionType) diff --git a/src/group_actions/group_operation_action.jl b/src/group_actions/group_operation_action.jl index c9480477..d46da798 100644 --- a/src/group_actions/group_operation_action.jl +++ b/src/group_actions/group_operation_action.jl @@ -69,37 +69,47 @@ struct InverseRightGroupOperationActionAction <: AbstractLeftGroupActionType end _doc_apply_groupop = """ - apply( (G,A), g, h) - - apply(A::GroupOperationAction, g, h) - apply!(A::GroupOperationAction, k, g, h) + apply(A::GroupAction, g, h) + apply!(A::GroupAction, k, g, h) apply the stored group operation action, using [`compose`](@ref) ``$(_math(:∘))``. this can be done in-place of `k`. """ @doc "$(_doc_apply_groupop)" -apply(A::GroupOperationAction, g, h) +apply(A::GroupAction, g, h) @doc "$(_doc_apply_groupop)" -apply!(A::GroupOperationAction, k, g, h) +apply!(A::GroupAction, k, g, h) -function apply!(A::GroupOperationAction{LeftGroupOperationAction}, k, g, h) +function apply!(A::GroupAction{LeftGroupOperationAction}, k, g, h) return compose!(A.group, k, g, h) #apply/compose g from left end -function apply!(A::GroupOperationAction{RightGroupOperationAction}, k, g, h) +function apply!(A::GroupAction{RightGroupOperationAction}, k, g, h) return compose!(A.group, k, h, g) #apply/compose g from right end -function apply!(A::GroupOperationAction{InverseLeftGroupOperationActionAction}, k, g, h) +function apply!(A::GroupAction{InverseLeftGroupOperationActionAction}, k, g, h) return inv_left_compose!(A.group, k, g, h) #apply/compose inv(g) from left end -function apply!(A::GroupOperationAction{InverseRightGroupOperationActionAction}, k, g, h) +function apply!(A::GroupAction{InverseRightGroupOperationActionAction}, k, g, h) return inv_right_compose!(A.group, k, g, h) #apply/compose inv(g) from right end +""" + default_left_action(N::LieGroup, H::LieGroup) + +""" +default_left_action(N::LieGroup, H::LieGroup) + +""" + default_left_action(N::LieGroup, H::LieGroup) + +""" +default_left_action(N::LieGroup, H::LieGroup) + _doc_diff_apply_groupop = """ - diff_apply(A::GroupOperationAction, g, p, X) + diff_apply(A::GroupAction, g, p, X) For the group operation action ``Οƒ_g(p)``, compute the differential ``D_p Οƒ_g(p): T_p$(_math(:G)) β†’ T_{Οƒ_g(p)}$(_math(:G))``, that is @@ -110,27 +120,27 @@ For the group operation action ``Οƒ_g(p)``, compute the differential * for the [`InverseRightGroupOperationActionAction`](@ref) this calls [`diff_left_compose`](@ref) with ``g^{-1}``, since here ``Οƒ_g(p) = p$(_math(:∘))g^{-1}`` """ @doc "$(_doc_diff_apply_groupop)" -diff_apply(A::GroupOperationAction, g, p, X) +diff_apply(A::GroupAction, g, p, X) @doc "$(_doc_diff_apply_groupop)" -diff_apply!(A::GroupOperationAction, Y, g, p, X) +diff_apply!(A::GroupAction, Y, g, p, X) -function diff_apply!(A::GroupOperationAction{LeftGroupOperationAction}, Y, g, p, X) +function diff_apply!(A::GroupAction{LeftGroupOperationAction}, Y, g, p, X) return diff_right_compose!(A.group, Y, g, p, X) end -function diff_apply!(A::GroupOperationAction{RightGroupOperationAction}, Y, g, p, X) +function diff_apply!(A::GroupAction{RightGroupOperationAction}, Y, g, p, X) return diff_left_compose!(A.group, Y, p, g, X) end -function diff_apply!(A::GroupOperationAction{InverseLeftGroupOperationActionAction}, Y, g, p, X) +function diff_apply!(A::GroupAction{InverseLeftGroupOperationActionAction}, Y, g, p, X) return diff_right_compose!(A.group, Y, inv(A.group, g), p, X) end -function diff_apply!(A::GroupOperationAction{InverseRightGroupOperationActionAction}, Y, g, p, X) +function diff_apply!(A::GroupAction{InverseRightGroupOperationActionAction}, Y, g, p, X) return diff_left_compose!(A.group, Y, p, inv(A.group, g), X) end _doc_diff_group_apply_groupop = """ - diff_group_apply(A::GroupOperationAction, g, p, X) + diff_group_apply(A::GroupAction, g, p, X) Compute the differential ``D_g Οƒ_g(p): $(_math(:𝔀)) β†’ $(_math(:𝔀))`` of a group operation action, that is @@ -142,34 +152,26 @@ that is """ @doc "$(_doc_diff_apply_groupop)" -diff_group_apply(A::GroupOperationAction, g, p, X) +diff_group_apply(A::GroupAction, g, p, X) @doc "$(_doc_diff_apply_groupop)" -diff_group_apply!(A::GroupOperationAction, Y, g, p, X) +diff_group_apply!(A::GroupAction, Y, g, p, X) -function diff_group_apply!(A::GroupOperationAction{LeftGroupOperationAction}, Y, g, p, X) +function diff_group_apply!(A::GroupAction{LeftGroupOperationAction}, Y, g, p, X) return diff_left_compose!(A.group, Y, g, p, X) end -function diff_group_apply!(A::GroupOperationAction{RightGroupOperationAction}, Y, g, p, X) +function diff_group_apply!(A::GroupAction{RightGroupOperationAction}, Y, g, p, X) return diff_right_compose!(A.group, Y, p, g, X) end -function diff_group_apply!(A::GroupOperationAction{InverseLeftGroupOperationActionAction}, Y, g, p, X) +function diff_group_apply!(A::GroupAction{InverseLeftGroupOperationActionAction}, Y, g, p, X) diff_inv!(A.group, Y, g, X) return diff_left_compose!(A.group, Y, inv(A.group, g), p, Y) end -function diff_group_apply!(A::GroupOperationAction{InverseRightGroupOperationActionAction}, Y, g, p, X) +function diff_group_apply!(A::GroupAction{InverseRightGroupOperationActionAction}, Y, g, p, X) diff_inv!(A.group, Y, g, X) return diff_right_compose!(A.group, Y, p, inv(A.group, g), Y) end -""" - inv(::GroupOperationAction) - -return the inverse group operation action, that is, use the type representing the -inverse operation. -""" -Base.inv(A::GroupOperationAction) = GroupOperationAction(inv(A.type), A.group) - """ inv(::LeftGroupOperationAction) @@ -195,9 +197,6 @@ Return the inverse of the [`InverseRightGroupOperationActionAction`](@ref), that """ Base.inv(::InverseRightGroupOperationActionAction) = RightGroupOperationAction() -function Base.show(io::IO, A::GroupOperationAction) - return print(io, "GroupOperationAction($(A.type), $(A.group))") -end """ switch(::LeftGroupOperationAction) diff --git a/src/groups/semidirect_product_group.jl b/src/groups/semidirect_product_group.jl index 73cb91b4..40e33f01 100644 --- a/src/groups/semidirect_product_group.jl +++ b/src/groups/semidirect_product_group.jl @@ -4,92 +4,158 @@ # Semidirect product groups – model semidirect products of rwo Lie groups # """ - SemidirectProductGroupOperation{O1,O2,A} <: AbstractGroupOperation + LeftSemidirectProductGroupOperation{O1,O2,A} <: AbstractGroupOperation A struct to model a semidirect Lie group product. Let ``($(_tex(:Cal, "N")), β‹„)`` and ``($(_tex(:Cal, "H")), ⋆)`` be two Lie groups -with group operations ``β‹„`` and ``⋆``, respectively, as well as -a (left) group action +with group operations ``β‹„`` and ``⋆``, respectively, as well as a group action ``Οƒ: $(_tex(:Cal, "H"))Γ—$(_tex(:Cal, "N")) β†’ $(_tex(:Cal, "N"))``, cf [`AbstractLeftGroupActionType`](#ref). + We use here as well use the notation ``Οƒ_h: $(_tex(:Cal, "N")) β†’ $(_tex(:Cal, "N"))`` as a family of maps on ``$(_tex(:Cal, "N"))`` Then we define a group operation ``∘`` on the product manifold $(_tex(:Cal, "N"))Γ—$(_tex(:Cal, "H")) by ```math - (n_1,h_1) ∘ (n_2,h_2) := (n_1 β‹„ Οƒ_{h_1}(n_2), h_1 ⋆ h_2) + (h_1,n_1) ∘ (h_2,n_2) := (h_1 ⋆ h_2, Ο„_{h_2}(n_1) β‹„ n_1). ``` -and similarly for a right group action, for example ``Ο„_h = (Οƒ_h)^{-1}`` - a group operation on $(_tex(:Cal, "H"))Γ—$(_tex(:Cal, "N")) +See [HilgertNeeb:2012; Definition 9.2.22](@cite), second definition for more details. + +# Constructor + + LeftSemidirectProductGroupOperation( + op1::AbstractGroupOperation, + op2::AbstractGroupOperation, + action::AbstractGroupActionType + ) + +# Parameters + +* `op1::AbstractGroupOperation`: The group operation ``β‹„`` on ``$(_tex(:Cal, "H"))`` +* `op2::AbstractGroupOperation`: The group operation ``⋆`` on ``$(_tex(:Cal, "N"))`` +* `action::AbstractGroupActionType` The group action ``Οƒ`` of ``$(_tex(:Cal, "H"))`` on ``$(_tex(:Cal, "N"))`` + +""" +struct LeftSemidirectProductGroupOperation{ + O1<:AbstractGroupOperation,O2<:AbstractGroupOperation,A<:AbstractGroupActionType +} <: AbstractGroupOperation + op1::O1 + op2::O2 + action_type::A + function LeftSemidirectProductGroupOperation( + op1::O1, op2::O2, action::A) where { + O1<:AbstractGroupOperation,O2<:AbstractGroupOperation,A<:AbstractGroupActionType + } + return LeftSemidirectProductGroupOperation{O1,O2,A}(op1, op2, action) + end +end + +""" + RightSemidirectProductGroupOperation{O1,O2,A} <: AbstractGroupOperation + +A struct to model a semidirect Lie group product. + +Let ``($(_tex(:Cal, "N")), β‹„)`` and ``($(_tex(:Cal, "H")), ⋆)`` be two Lie groups +with group operations ``β‹„`` and ``⋆``, respectively, as well as a group action +``Οƒ: $(_tex(:Cal, "H"))Γ—$(_tex(:Cal, "N")) β†’ $(_tex(:Cal, "N"))``, cf [`AbstractGroupActionType`](#ref). + +We use here as well use the notation ``Οƒ_h: $(_tex(:Cal, "N")) β†’ $(_tex(:Cal, "N"))`` as a family of maps on ``$(_tex(:Cal, "N"))`` + +Then we define a group operation ``∘`` on the product manifold $(_tex(:Cal, "N"))Γ—$(_tex(:Cal, "H")) by ```math - (h_1,n_1) ∘ (h_2,n_2) := (h_1 ⋆ h_2, Ο„_{h_2}(n_1) β‹„ n_1). + (n_1,h_1) ∘ (n_2,h_2) := (n_1 β‹„ Οƒ_{h_1}(n_2), h_1 ⋆ h_2) ``` -See [HilgertNeeb:2012; Definition 9.2.22](@cite) for more details. +See [HilgertNeeb:2012; Definition 9.2.22](@cite), first definition for more details. # Constructor - SemidirectProductGroupOperation(op1::AbstractGroupOperation, op2::AbstractGroupOperation, action) + RightSemidirectProductGroupOperation( + op1::AbstractGroupOperation, + op2::AbstractGroupOperation, + action::AbstractGroupActionType + ) + +# Parameters -Create a `SemidirectProductGroupOperation` for [`AbstractGroupOperation`](@ref) `op1=```β‹„`` and `pΓΌ2=```⋆`` -together with an [`AbstractGroupActionType`](@ref) `action` that defaults to the [`LeftGroupOperationAction`](@ref), which yields the corresponding [`GroupOperationAction`](@ref), -that is where the action is given by the group operation of ``$(_tex(:Cal, "H"))`` acting on ``$(_tex(:Cal, "N"))``. -The first shorthand `op1 β‹Š op2` is a short form for this. +* `op1::AbstractGroupOperation`: The group operation ``⋆`` on ``$(_tex(:Cal, "N"))`` +* `op2::AbstractGroupOperation`: The group operation ``β‹„`` on ``$(_tex(:Cal, "H"))`` +* `action::AbstractGroupActionType`: The group action ``Οƒ`` of ``$(_tex(:Cal, "H"))`` on ``$(_tex(:Cal, "N"))`` -For the second form, use for example the [`RightGroupOperationAction`](@ref) to also have the [`GroupOperationAction`](@ref) mentioned. """ -struct SemidirectProductGroupOperation{ +struct RightSemidirectProductGroupOperation{ O1<:AbstractGroupOperation,O2<:AbstractGroupOperation,A<:AbstractGroupActionType } <: AbstractGroupOperation op1::O1 op2::O2 action_type::A - function SemidirectProductGroupOperation( - op1::O1, op2::O2; action::A=LeftGroupOperationAction() + function RightSemidirectProductGroupOperation( + op1::O1, op2::O2, action::A ) where { O1<:AbstractGroupOperation,O2<:AbstractGroupOperation,A<:AbstractGroupActionType } - return SemidirectProductGroupOperation{O1,O2,A}(op1, op2, action) + return RightSemidirectProductGroupOperation{O1,O2,A}(op1, op2, action) end end - -# LeftSemidirectProductLieGroup -# RightSemidirectProductLieGroup -# default_left_action(L1,L2) -# default_right_action(L1,L2) """ - SemidirectProductLieGroup(N::LieGroup, H::LieGroup; action=LeftGroupOperationAction()) + LeftSemidirectProductLieGroup(N::LieGroup, H::LieGroup, action=default_left_action(N,H)) -Generate the semidirect product Lie Group ``$(_tex(:Cal, "G")) = N β‹Š H`` for an [`AbstractLeftGroupActionType`](@ref), -and ``$(_tex(:Cal, "G")) = N ⋉ H`` for an [`AbstractRightGroupActionType`](@ref), +Generate the semidirect product Lie Group ``$(_tex(:Cal, "G")) = N ⋉ H`` for an [`AbstractLeftGroupActionType`](@ref) +using the [`LeftSemidirectProductGroupOperation`](@ref) for the group operation definition +as well as [HilgertNeeb:2012; Definition 9.2.22](@cite), second definition, for more details. -see [`SemidirectProductGroupOperation`](@ref) for the group operation definition as well as [HilgertNeeb:2012; Definition 9.2.22](@cite) for more details. +The short form `N `[`⋉`](@ref ⋉(L1::LieGroup, L2::LieGroup))` H` can be used if the +corresponding [`default_left_action`](@ref)`(N,H)` is the one you want to use. """ -function SemidirectProductLieGroup( - N::LieGroup, H::LieGroup; action::AbstractGroupActionType=LeftGroupOperation() +function LeftSemidirectProductLieGroup( + N::LieGroup, + H::LieGroup, + action::AbstractGroupActionType=default_left_action(N,H), ) return LieGroup( - N.manifold Γ— H.manifold, SemidirectProductGroupOperation(N.op, H.op; action=action) + N.manifold Γ— H.manifold, LeftSemidirectProductGroupOperation(N.op, H.op, action) ) end """ - L1 β‹Š L2 + RightSemidirectProductLieGroup(N::LieGroup, H::LieGroup, action=default_right_action(N,H)) -For two [`LieGroups`](@ref), generate the [`SemidirectProductLieGroup`](@ref)`(L1, L2; action=`[`LeftGroupOperationAction`](@ref)`())` +Generate the semidirect product Lie Group ``$(_tex(:Cal, "G")) = N β‹Š H`` for an [`AbstractLeftGroupActionType`](@ref) +using the [`RightSemidirectProductGroupOperation`](@ref) for the group operation definition +as well as [HilgertNeeb:2012; Definition 9.2.22](@cite), first definition, for more details. + +The short form `N `[`β‹Š`](@ref β‹Š(L1::LieGroup, L2::LieGroup))` H` can be used if the +corresponding [`default_right_action`](@ref)`(N,H)` is the one you want to use. """ -function β‹Š(L1::LieGroup, L2::LieGroup) - return SemidirectProductLieGroup(L1, L2; action=LeftGroupOperationAction()) +function RightSemidirectProductLieGroup( + N::LieGroup, H::LieGroup; action::AbstractGroupActionType=default_right_action(N, H) +) + return LieGroup( + N.manifold Γ— H.manifold, RightSemidirectProductGroupOperation(N.op, H.op, action) + ) end """ L1 ⋉ L2 + ⋉(L1, L2) -For two [`LieGroups`](@ref), generate the [`SemidirectProductLieGroup`](@ref)`(L1, L2; action=`[`RightGroupOperationAction`](@ref)`())` +For two [`LieGroups`](@ref) `L1`, `L2`, generate the [`LeftSemidirectProductLieGroup`](@ref)`(L1, L2)`, +where the corresponding [`default_left_action`](@ref)`(L1, L2)` is used. """ function ⋉(L1::LieGroup, L2::LieGroup) return SemidirectProductLieGroup(L1, L2; action=RightGroupOperationAction()) end + +""" + L1 β‹Š L2 + β‹Š(L1, L2) + +For two [`LieGroups`](@ref) `L1`, `L2`, generate the [`RightSemidirectProductLieGroup`](@ref)`(L1, L2)`, +where the corresponding [`default_right_action`](@ref)`(L1, L2)` is used. +""" +function β‹Š(L1::LieGroup, L2::LieGroup) + return RightSemidirectProductLieGroup(L1, L2) +end From 1aee6cf1efb674fba44cb55114aa2b56921c0bb8 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Fri, 15 Nov 2024 17:18:58 +0100 Subject: [PATCH 14/43] Finish the initial sketch of Semidirect product Lie groups. --- NEWS.md | 4 +- docs/src/tutorials/transition.md | 10 +- src/LieGroups.jl | 6 +- src/group_actions/group_action_interface.jl | 48 ++++---- src/group_actions/group_operation_action.jl | 125 +++++--------------- src/groups/semidirect_product_group.jl | 46 +++++-- test/groups/test_translation_group.jl | 4 +- 7 files changed, 105 insertions(+), 138 deletions(-) diff --git a/NEWS.md b/NEWS.md index 2539dc7d..4430b78b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -24,8 +24,8 @@ Everything denoted by β€œformerly” refers to the previous name in [`Manifolds. * For the group operation actions there are now * `LeftGroupOperationAction` (formerly `LeftForwardAction`) * `RightGroupOperationAction` (formerly `RightBackwardAction`) - * `InverseLeftGroupOperationActionAction` (formerly `RightForwardAction`) - * `InverseRightGroupOperationActionAction` (formerly `LeftBackwardAction`) + * `InverseLeftGroupOperationAction` (formerly `RightForwardAction`) + * `InverseRightGroupOperationAction` (formerly `LeftBackwardAction`) * `LieAlgebraOrthogonalBasis` (replaces `VeeOrthogonalBasis`, which is still available in `ManifoldsBase.jl`) * `Identity` * `apply`and `apply!` diff --git a/docs/src/tutorials/transition.md b/docs/src/tutorials/transition.md index b1bc9279..df666198 100644 --- a/docs/src/tutorials/transition.md +++ b/docs/src/tutorials/transition.md @@ -22,12 +22,12 @@ The list is alphabetical, but first lists types, then functions | `Manifolds.jl` | `LieGroups.jl` | Comment | |:---------- |:---------- |:-------------- | | `AdditionOperation` | [`AdditionGroupOperation`](@ref) | | -| `LeftForwardAction` | [`LeftGroupOperation`](@ref) -| `RightBackwardAction` | [`RightGroupOperation`](@ref) | | -| `LeftBackwardAction` | [`InverseRightGroupOperation`](@ref) | note that this is now also aa [`AbstractLeftGroupActionType`](@ref) | +| `LeftForwardAction` | [`LeftGroupOperationAction`](@ref) +| `RightBackwardAction` | [`RightGroupOperationAction`](@ref) | | +| `LeftBackwardAction` | [`InverseRightGroupOperationAction`](@ref) | note that this is now also aa [`AbstractLeftGroupActionType`](@ref) | | | [`LieAlgebra`](@ref)`(G)` | new alias to emphasize its manifold- and vector structure as well as for a few dispatch methods. | | `GroupManifold(M, op)` | [`LieGroup`](@ref)`(M, op)` | | -| `RightForwardAction` | [`InverseLeftGroupOperation`](@ref) | note that this is an [`AbstractRightGroupActionType`](@ref) | +| `RightForwardAction` | [`InverseLeftGroupOperationAction`](@ref) | note that this is an [`AbstractRightGroupActionType`](@ref) | | `adjoint` | [`adjoint`](@ref) | now implemented with a default, when you provide [`diff_conjugate!`](@ref). | `apply_diff` | [`diff_apply`](@ref) | modifiers (diff) come first, consistent with [`ManifoldsDiff.jl`](https://juliamanifolds.github.io/ManifoldDiff.jl/stable/) | | `apply_diff_group` | [`diff_group_apply`](@ref) | modifiers (diff/group) come first, consistent with [`ManifoldsDiff.jl`](https://juliamanifolds.github.io/ManifoldDiff.jl/stable/) | @@ -52,6 +52,6 @@ The list is alphabetical, but first lists types, then functions 1. The [`GeneralLinearGroup`](@ref) (formerly `GeneralLinear`) switched to using its Lie algebra to represent tangent vectors. 2. Formerly, both a power of LieGroups as well as a LieGroup on the power manifold was possible. This is now unified to the latter, the operation for power manifolds can hence stay the same as for the single manifold. -3. Formerly, product manifolds were stored as a [`ProductManifold`](@ref) of Lie groups and an indicator for the group operation, that the direct product should be used. This is switched to (as for the last point) internally only store a [`ProductManifold`](@ref) as well as a (new) [`ProductGroupOperation`](@ref) that specifies one group operation for every factor. +3. Formerly, product manifolds were stored as a [`ProductManifold`](@extref) of Lie groups and an indicator for the group operation, that the direct product should be used. This is switched to (as for the last point) internally only store a [`ProductManifold`](@extref) as well as a (new) [`ProductGroupOperation`](@ref) that specifies one group operation for every factor. 4. both the last two points achieve one unified modelling aspect of Lie groups: They are now always a Riemannian manifold `M` together with a group operation `op`, but a Lie group does not store another Lie group (or product of them) internally. diff --git a/src/LieGroups.jl b/src/LieGroups.jl index d1724c02..56dadb7c 100644 --- a/src/LieGroups.jl +++ b/src/LieGroups.jl @@ -59,7 +59,7 @@ export ProductGroupOperation, SemidirectProductGroupOperation export AbstractGroupActionType, AbstractGroupAction export AbstractLeftGroupActionType, AbstractRightGroupActionType export LeftGroupOperationAction, RightGroupOperationAction -export InverseLeftGroupOperationActionAction, InverseRightGroupOperationActionAction +export InverseLeftGroupOperationAction, InverseRightGroupOperationAction export GroupOperationAction # # @@ -69,7 +69,9 @@ export TranslationGroup, GeneralLinearGroup export adjoint, adjoint!, apply, apply! export base_lie_group, base_manifold export compose, compose! -export det, +export default_left_action, + default_right_action, + det, diff_apply, diff_apply!, diff_group_apply, diff --git a/src/group_actions/group_action_interface.jl b/src/group_actions/group_action_interface.jl index 6dd41062..b28ff58e 100644 --- a/src/group_actions/group_action_interface.jl +++ b/src/group_actions/group_action_interface.jl @@ -119,24 +119,6 @@ struct GroupAction{T<:AbstractGroupActionType,L<:LieGroup,M<:ManifoldsBase.Abstr manifold::M end - - -function base_lie_group end -@doc """ - base_lie_group(A::GroupAction) - -Return the [`LieGroup`](@ref) of the [`GroupAction`](@ref) -specifying the action. -""" -base_lie_group(A::GroupAction) = A.group - -@doc """ - base_manifold(A::GroupAction) - -Return the $(_link(:AbstractManifold)) the group action acts upon. -""" -ManifoldsBase.base_manifold(A::GroupOperationAction) = A.manifold - # # # Functions @@ -159,6 +141,28 @@ function apply(A::GroupAction, g, p) return q end +# Define `function apply! end` here as well +# un-comment (remove this comment) when removing this function from Manifolds.jl +@doc "$(_doc_apply)" +apply!(A::GroupAction, q, g, p) + +function base_lie_group end +@doc """ + base_lie_group(A::GroupAction) + +Return the [`LieGroup`](@ref) of the [`GroupAction`](@ref) +specifying the action. +""" +base_lie_group(A::GroupAction) = A.group + +@doc """ + base_manifold(A::GroupAction) + +Return the $(_link(:AbstractManifold)) the group action acts upon. +""" +ManifoldsBase.base_manifold(A::GroupOperationAction) = A.manifold + +function default_left_action end """ default_left_action(G::LieGroup, M::AbstractManifold) @@ -166,6 +170,7 @@ Return the default left action for a Lie group `G` acting on a manifold `M`. """ default_left_action(N::LieGroup, M::AbstractManifold) +function default_right_action end """ default_right_action(G::LieGroup, M::AbstractManifold) @@ -173,13 +178,6 @@ Return the default right action for a Lie group `G` acting on a manifold `M`. """ default_right_action(N::LieGroup, M::AbstractManifold) -# Define `function apply! end` here as well -# un-comment (remove this comment) when removing this function from Manifolds.jl -@doc "$(_doc_apply)" -apply!(A::GroupAction, q, g, p) - - - _doc_diff_apply = """ diff_apply(A::GroupAction{T, L, M}, g, p, X) diff_apply!(A::GroupAction{T, L, M}, Y, g, p, X) diff --git a/src/group_actions/group_operation_action.jl b/src/group_actions/group_operation_action.jl index d46da798..54e8da45 100644 --- a/src/group_actions/group_operation_action.jl +++ b/src/group_actions/group_operation_action.jl @@ -8,7 +8,7 @@ from the left, that is Οƒ_h(g) = Οƒ(h,g) = h$(_math(:∘))g ``` -for its inverse ``(Οƒ_h)^{-1}`` see [`InverseLeftGroupOperationActionAction`](@ref). +for its inverse ``(Οƒ_h)^{-1}`` see [`InverseLeftGroupOperationAction`](@ref). """ struct LeftGroupOperationAction <: AbstractLeftGroupActionType end @@ -22,12 +22,12 @@ gfrom the right Οƒ_h(g) = Οƒ(h,g) = g$(_math(:∘))h ``` -for its inverse ``(Οƒ_h)^{-1}`` see [`InverseRightGroupOperationActionAction`](@ref). +for its inverse ``(Οƒ_h)^{-1}`` see [`InverseRightGroupOperationAction`](@ref). """ struct RightGroupOperationAction <: AbstractLeftGroupActionType end """ - InverseLeftGroupOperationActionAction <: AbstractRightGroupActionType + InverseLeftGroupOperationAction <: AbstractRightGroupActionType A type for the [`AbstractLeftGroupActionType`](@ref) when acting on the group itself given by the inverse of a [`LeftGroupOperationAction`](@ref) ``Οƒ_h`` as @@ -41,15 +41,15 @@ properties yield that is is an [`AbstractRightGroupActionType`](@ref), since $(_note(:LeftInverseActionIsRight)) -for its inverse ``(Οƒ_h)^{-1}`` see [`InverseLeftGroupOperationActionAction`](@ref). +for its inverse ``(Οƒ_h)^{-1}`` see [`InverseLeftGroupOperationAction`](@ref). !!! note Some literature also calls this by itself _the_ right group operation action. """ -struct InverseLeftGroupOperationActionAction <: AbstractRightGroupActionType end +struct InverseLeftGroupOperationAction <: AbstractRightGroupActionType end """ - InverseRightGroupOperationActionAction <: AbstractLeftGroupActionType + InverseRightGroupOperationAction <: AbstractLeftGroupActionType A type for the [`AbstractLeftGroupActionType`](@ref) when acting on the group itself given by the inverse of a [`RightGroupOperationAction`](@ref) ``Οƒ_h`` as @@ -63,24 +63,9 @@ properties yield that is is an [`AbstractLeftGroupActionType`](@ref), since $(_note(:RightInverseActionIsLeft)) -for its inverse ``(Οƒ_h)^{-1}`` see [`InverseLeftGroupOperationActionAction`](@ref). +for its inverse ``(Οƒ_h)^{-1}`` see [`InverseLeftGroupOperationAction`](@ref). """ -struct InverseRightGroupOperationActionAction <: AbstractLeftGroupActionType end - - -_doc_apply_groupop = """ - apply(A::GroupAction, g, h) - apply!(A::GroupAction, k, g, h) - -apply the stored group operation action, using [`compose`](@ref) ``$(_math(:∘))``. -this can be done in-place of `k`. -""" - -@doc "$(_doc_apply_groupop)" -apply(A::GroupAction, g, h) - -@doc "$(_doc_apply_groupop)" -apply!(A::GroupAction, k, g, h) +struct InverseRightGroupOperationAction <: AbstractLeftGroupActionType end function apply!(A::GroupAction{LeftGroupOperationAction}, k, g, h) return compose!(A.group, k, g, h) #apply/compose g from left @@ -88,86 +73,37 @@ end function apply!(A::GroupAction{RightGroupOperationAction}, k, g, h) return compose!(A.group, k, h, g) #apply/compose g from right end -function apply!(A::GroupAction{InverseLeftGroupOperationActionAction}, k, g, h) +function apply!(A::GroupAction{InverseLeftGroupOperationAction}, k, g, h) return inv_left_compose!(A.group, k, g, h) #apply/compose inv(g) from left end -function apply!(A::GroupAction{InverseRightGroupOperationActionAction}, k, g, h) +function apply!(A::GroupAction{InverseRightGroupOperationAction}, k, g, h) return inv_right_compose!(A.group, k, g, h) #apply/compose inv(g) from right end -""" - default_left_action(N::LieGroup, H::LieGroup) - -""" -default_left_action(N::LieGroup, H::LieGroup) - -""" - default_left_action(N::LieGroup, H::LieGroup) - -""" -default_left_action(N::LieGroup, H::LieGroup) - -_doc_diff_apply_groupop = """ - - diff_apply(A::GroupAction, g, p, X) - -For the group operation action ``Οƒ_g(p)``, compute the differential -``D_p Οƒ_g(p): T_p$(_math(:G)) β†’ T_{Οƒ_g(p)}$(_math(:G))``, that is - -* for the [`LeftGroupOperationAction`](@ref) this calls [`diff_right_compose`](@ref)`(G, g, p, X)`, since here ``Οƒ_g(p) = g$(_math(:∘))p`` -* for the [`RightGroupOperationAction`](@ref) this calls [`diff_left_compose`](@ref)`(G, p, g, X)`, since here ``Οƒ_g(p) = p$(_math(:∘))g`` -* for the [`InverseLeftGroupOperationActionAction`](@ref) this calls [`diff_right_compose`](@ref) with ``g^{-1}``, since here ``Οƒ_g(p) = g^{-1}$(_math(:∘))p`` -* for the [`InverseRightGroupOperationActionAction`](@ref) this calls [`diff_left_compose`](@ref) with ``g^{-1}``, since here ``Οƒ_g(p) = p$(_math(:∘))g^{-1}`` -""" -@doc "$(_doc_diff_apply_groupop)" -diff_apply(A::GroupAction, g, p, X) - -@doc "$(_doc_diff_apply_groupop)" -diff_apply!(A::GroupAction, Y, g, p, X) - function diff_apply!(A::GroupAction{LeftGroupOperationAction}, Y, g, p, X) return diff_right_compose!(A.group, Y, g, p, X) end function diff_apply!(A::GroupAction{RightGroupOperationAction}, Y, g, p, X) return diff_left_compose!(A.group, Y, p, g, X) end -function diff_apply!(A::GroupAction{InverseLeftGroupOperationActionAction}, Y, g, p, X) +function diff_apply!(A::GroupAction{InverseLeftGroupOperationAction}, Y, g, p, X) return diff_right_compose!(A.group, Y, inv(A.group, g), p, X) end -function diff_apply!(A::GroupAction{InverseRightGroupOperationActionAction}, Y, g, p, X) +function diff_apply!(A::GroupAction{InverseRightGroupOperationAction}, Y, g, p, X) return diff_left_compose!(A.group, Y, p, inv(A.group, g), X) end -_doc_diff_group_apply_groupop = """ - - diff_group_apply(A::GroupAction, g, p, X) - -Compute the differential ``D_g Οƒ_g(p): $(_math(:𝔀)) β†’ $(_math(:𝔀))`` of a group operation action, -that is - -* for the [`LeftGroupOperationAction`](@ref) this calls [`diff_left_compose`](@ref)`(G, g, p, X)`, since here ``Οƒ_g(p) = g$(_math(:∘))p`` -* for the [`RightGroupOperationAction`](@ref) this calls [`diff_right_compose`](@ref)`(G, p, g, X)`, since here ``Οƒ_g(p) = p$(_math(:∘))g`` -* for the [`InverseLeftGroupOperationActionAction`](@ref) this calls [`diff_left_compose`](@ref) with ``g^{-1}``, since here ``Οƒ_g(p) = g^{-1}$(_math(:∘))p`` together with [`diff_inv`](@ref) -* for the [`InverseRightGroupOperationActionAction`](@ref) this calls [`diff_right_compose`](@ref) with ``g^{-1}``, since here ``Οƒ_g(p) = p$(_math(:∘))g^{-1}`` together with [`diff_inv`](@ref) -""" - -@doc "$(_doc_diff_apply_groupop)" -diff_group_apply(A::GroupAction, g, p, X) - -@doc "$(_doc_diff_apply_groupop)" -diff_group_apply!(A::GroupAction, Y, g, p, X) - function diff_group_apply!(A::GroupAction{LeftGroupOperationAction}, Y, g, p, X) return diff_left_compose!(A.group, Y, g, p, X) end function diff_group_apply!(A::GroupAction{RightGroupOperationAction}, Y, g, p, X) return diff_right_compose!(A.group, Y, p, g, X) end -function diff_group_apply!(A::GroupAction{InverseLeftGroupOperationActionAction}, Y, g, p, X) +function diff_group_apply!(A::GroupAction{InverseLeftGroupOperationAction}, Y, g, p, X) diff_inv!(A.group, Y, g, X) return diff_left_compose!(A.group, Y, inv(A.group, g), p, Y) end -function diff_group_apply!(A::GroupAction{InverseRightGroupOperationActionAction}, Y, g, p, X) +function diff_group_apply!(A::GroupAction{InverseRightGroupOperationAction}, Y, g, p, X) diff_inv!(A.group, Y, g, X) return diff_right_compose!(A.group, Y, p, inv(A.group, g), Y) end @@ -175,28 +111,27 @@ end """ inv(::LeftGroupOperationAction) -Return the inverse of the [`LeftGroupOperationAction`](@ref), that is the [`InverseLeftGroupOperationActionAction`](@ref). +Return the inverse of the [`LeftGroupOperationAction`](@ref), that is the [`InverseLeftGroupOperationAction`](@ref). """ -Base.inv(::LeftGroupOperationAction) = InverseLeftGroupOperationActionAction() +Base.inv(::LeftGroupOperationAction) = InverseLeftGroupOperationAction() """ inv(::RightGroupOperationAction) -Return the inverse of the [`RightGroupOperationAction`](@ref), that is the [`InverseRightGroupOperationActionAction`](@ref). +Return the inverse of the [`RightGroupOperationAction`](@ref), that is the [`InverseRightGroupOperationAction`](@ref). """ -Base.inv(::RightGroupOperationAction) = InverseRightGroupOperationActionAction() +Base.inv(::RightGroupOperationAction) = InverseRightGroupOperationAction() """ - inv(::InverseLeftGroupOperationActionAction) + inv(::InverseLeftGroupOperationAction) -Return the inverse of the [`InverseLeftGroupOperationActionAction`](@ref), that is the [`LeftGroupOperationAction`](@ref). +Return the inverse of the [`InverseLeftGroupOperationAction`](@ref), that is the [`LeftGroupOperationAction`](@ref). """ -Base.inv(::InverseLeftGroupOperationActionAction) = LeftGroupOperationAction() +Base.inv(::InverseLeftGroupOperationAction) = LeftGroupOperationAction() """ - inv(::InverseRightGroupOperationActionAction) + inv(::InverseRightGroupOperationAction) -Return the inverse of the [`InverseRightGroupOperationActionAction`](@ref), that is the [`RightGroupOperationAction`](@ref). +Return the inverse of the [`InverseRightGroupOperationAction`](@ref), that is the [`RightGroupOperationAction`](@ref). """ -Base.inv(::InverseRightGroupOperationActionAction) = RightGroupOperationAction() - +Base.inv(::InverseRightGroupOperationAction) = RightGroupOperationAction() """ switch(::LeftGroupOperationAction) @@ -215,17 +150,17 @@ turns ``Οƒ_g = h$(_math(:∘))g`` into ``Ο„_g(h) = g$(_math(:∘))h`` switch(::RightGroupOperationAction) = LeftGroupOperationAction() """ - switch(::InverseLeftGroupOperationActionAction) + switch(::InverseLeftGroupOperationAction) -Return the [`InverseRightGroupOperationActionAction`](@ref), that is, +Return the [`InverseRightGroupOperationAction`](@ref), that is, turns ``Οƒ_g = g^{-1}$(_math(:∘))h`` into ``Ο„_g(h) = h$(_math(:∘))g^{-1}`` """ -switch(::InverseLeftGroupOperationActionAction) = InverseRightGroupOperationActionAction() +switch(::InverseLeftGroupOperationAction) = InverseRightGroupOperationAction() """ - switch(::InverseRightGroupOperationActionAction) + switch(::InverseRightGroupOperationAction) -Return the [`InverseLeftGroupOperationActionAction`](@ref), that is, +Return the [`InverseLeftGroupOperationAction`](@ref), that is, turns ``Οƒ_g = h$(_math(:∘))g^{-1}`` into ``Ο„_g(h) = g^{-1}$(_math(:∘))h`` """ -switch(::InverseRightGroupOperationActionAction) = InverseLeftGroupOperationActionAction() +switch(::InverseRightGroupOperationAction) = InverseLeftGroupOperationAction() diff --git a/src/groups/semidirect_product_group.jl b/src/groups/semidirect_product_group.jl index 40e33f01..3c175aa2 100644 --- a/src/groups/semidirect_product_group.jl +++ b/src/groups/semidirect_product_group.jl @@ -44,7 +44,8 @@ struct LeftSemidirectProductGroupOperation{ op2::O2 action_type::A function LeftSemidirectProductGroupOperation( - op1::O1, op2::O2, action::A) where { + op1::O1, op2::O2, action::A + ) where { O1<:AbstractGroupOperation,O2<:AbstractGroupOperation,A<:AbstractGroupActionType } return LeftSemidirectProductGroupOperation{O1,O2,A}(op1, op2, action) @@ -111,9 +112,7 @@ The short form `N `[`⋉`](@ref ⋉(L1::LieGroup, L2::LieGroup))` H` can be used corresponding [`default_left_action`](@ref)`(N,H)` is the one you want to use. """ function LeftSemidirectProductLieGroup( - N::LieGroup, - H::LieGroup, - action::AbstractGroupActionType=default_left_action(N,H), + N::LieGroup, H::LieGroup, action::AbstractGroupActionType=default_left_action(N, H) ) return LieGroup( N.manifold Γ— H.manifold, LeftSemidirectProductGroupOperation(N.op, H.op, action) @@ -131,7 +130,7 @@ The short form `N `[`β‹Š`](@ref β‹Š(L1::LieGroup, L2::LieGroup))` H` can be used corresponding [`default_right_action`](@ref)`(N,H)` is the one you want to use. """ function RightSemidirectProductLieGroup( - N::LieGroup, H::LieGroup; action::AbstractGroupActionType=default_right_action(N, H) + N::LieGroup, H::LieGroup, action::AbstractGroupActionType=default_right_action(N, H) ) return LieGroup( N.manifold Γ— H.manifold, RightSemidirectProductGroupOperation(N.op, H.op, action) @@ -146,7 +145,7 @@ For two [`LieGroups`](@ref) `L1`, `L2`, generate the [`LeftSemidirectProductLieG where the corresponding [`default_left_action`](@ref)`(L1, L2)` is used. """ function ⋉(L1::LieGroup, L2::LieGroup) - return SemidirectProductLieGroup(L1, L2; action=RightGroupOperationAction()) + return LeftSemidirectProductLieGroup(L1, L2, default_left_action(L1, L2)) end """ @@ -157,5 +156,38 @@ For two [`LieGroups`](@ref) `L1`, `L2`, generate the [`RightSemidirectProductLie where the corresponding [`default_right_action`](@ref)`(L1, L2)` is used. """ function β‹Š(L1::LieGroup, L2::LieGroup) - return RightSemidirectProductLieGroup(L1, L2) + return RightSemidirectProductLieGroup(L1, L2, default_right_action(L1, L2)) +end + +function Base.show(io::IO, LSDOp::LeftSemidirectProductGroupOperation) + return print( + io, + "LeftSemidirectProductGroupOperation($(LSDOp.op1), $(LSDOp.op2), $(LSDOp.action_type))", + ) +end +function Base.show(io::IO, RSDOp::RightSemidirectProductGroupOperation) + return print( + io, + "RightSemidirectProductGroupOperation($(RSDOp.op1), $(RSDOp.op2), $(RSDOp.action_type))", + ) +end +function Base.show( + io::IO, + LSDL::LieGroup{𝔽,<:LeftSemidirectProductGroupOperation,<:ManifoldsBase.ProductManifold}, +) where {𝔽} + L1 = LieGroup(LSDL.manifold[1], LSDL.op.op1) + L2 = LieGroup(LSDL.manifold[2], LSDL.op.op2) + at = LSDL.op.action_type + return print(io, "LeftSemidirectProductLieGroup($L1, $L2, $at)") +end +function Base.show( + io::IO, + RSDL::LieGroup{ + 𝔽,<:RightSemidirectProductGroupOperation,<:ManifoldsBase.ProductManifold + }, +) where {𝔽} + L1 = LieGroup(RSDL.manifold[1], RSDL.op.op1) + L2 = LieGroup(RSDL.manifold[2], RSDL.op.op2) + at = RSDL.op.action_type + return print(io, "RightSemidirectProductLieGroup($L1, $L2, $at)") end diff --git a/test/groups/test_translation_group.jl b/test/groups/test_translation_group.jl index 6784d7af..0451244e 100644 --- a/test/groups/test_translation_group.jl +++ b/test/groups/test_translation_group.jl @@ -58,8 +58,8 @@ begin for t in [ RightGroupOperationAction(), LeftGroupOperationAction(), - InverseLeftGroupOperationActionAction(), - InverseRightGroupOperationActionAction(), + InverseLeftGroupOperationAction(), + InverseRightGroupOperationAction(), ] A = GroupOperationAction(t, G) properties2[:Name] = "with $A" From 8615bff1cd4312ecb41c5694593abb145c38925c Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Fri, 15 Nov 2024 18:29:06 +0100 Subject: [PATCH 15/43] Start testing for semidirect. --- docs/src/tutorials/transition.md | 4 +- src/LieGroups.jl | 10 ++-- src/group_actions/group_action_interface.jl | 6 +-- src/group_actions/group_operation_action.jl | 15 ++++++ src/groups/semidirect_product_group.jl | 4 +- src/interface.jl | 4 +- .../LieGroupsTestSuite.jl | 21 +++----- test/groups/test_semidirect_product_group.jl | 52 ++++++++++++++++++- 8 files changed, 88 insertions(+), 28 deletions(-) diff --git a/docs/src/tutorials/transition.md b/docs/src/tutorials/transition.md index df666198..e0d34612 100644 --- a/docs/src/tutorials/transition.md +++ b/docs/src/tutorials/transition.md @@ -41,8 +41,8 @@ The list is alphabetical, but first lists types, then functions | `log(G, g, h)` | `log(`[`base_manifold`](@ref base_manifold(G::LieGroup))`(G), g, h)` | you can now access the previous defaults on the internal manifold whenever they do not agree with the invariant one | | `log_inv(G, g, h)` | [`log`](@ref log(G::LieGroup, g, h))`(G, g, h)` | the logarithmic map invariant to the group operation is the default on Lie groups here | | `log_lie(G, g)` | [`log`](@ref log(G::LieGroup, e::Identity, g))`(G, `[`Identity`](@ref)`(G), g)` | the (matrix) logarithm is now the one at the identity, since there it agrees with the invariant one | -| `switch_direction(A)` | [`inv`](@ref inv(::AbstractGroupAction))`(A)` | switches from an action to its inverse action (formerly the direction forward/backward, sometimes even left/right, do not confuse with the side left/right). | -| `switch_side(A)` | [`switch`](@ref switch(::AbstractGroupAction))`(A)` | switches from a left action to its corresponding right action. | +| `switch_direction(A)` | [`inv`](@ref inv(::GroupAction))`(A)` | switches from an action to its inverse action (formerly the direction forward/backward, sometimes even left/right, do not confuse with the side left/right). | +| `switch_side(A)` | [`switch`](@ref switch(::GroupAction))`(A)` | switches from a left action to its corresponding right action. | | `translate(G, g, h)` | [`compose`](@ref)`(G, g, h)` | unified to `compose` | | `translate_diff(G, g, X, c)` | [`diff_left_compose`](@ref)`(G, g, h, X)`, [`diff_right_compose`](@ref)`(G, g, h, X)` | for compose ``g∘h`` the functions now specify whether the derivative is taken w.r.t. to the left (`g`) or right (`h`) argument | |`VeeOrthogonalBasis` | [`LieAlgebraOrthogonalBasis`](@ref) | | diff --git a/src/LieGroups.jl b/src/LieGroups.jl index 56dadb7c..11e15c14 100644 --- a/src/LieGroups.jl +++ b/src/LieGroups.jl @@ -41,7 +41,8 @@ include("groups/translation_group.jl") include("groups/general_linear_group.jl") export LieGroup, LieAlgebra -export PowerLieGroup, ProductLieGroup, SemidirectProductLieGroup +export PowerLieGroup, ProductLieGroup +export LeftSemidirectProductLieGroup, RightSemidirectProductLieGroup export LieAlgebraOrthogonalBasis export Γ—, ^, ⋉, β‹Š # @@ -51,16 +52,17 @@ export AbstractGroupOperation, Identity export AdditionGroupOperation export AbstractMultiplicationGroupOperation export MatrixMultiplicationGroupOperation -export ProductGroupOperation, SemidirectProductGroupOperation +export ProductGroupOperation +export LeftSemidirectProductGroupOperation, RightSemidirectProductGroupOperation # # # Group Actions -export AbstractGroupActionType, AbstractGroupAction +export AbstractGroupActionType export AbstractLeftGroupActionType, AbstractRightGroupActionType export LeftGroupOperationAction, RightGroupOperationAction export InverseLeftGroupOperationAction, InverseRightGroupOperationAction -export GroupOperationAction +export GroupAction, GroupOperationAction # # # Specific groups diff --git a/src/group_actions/group_action_interface.jl b/src/group_actions/group_action_interface.jl index b28ff58e..5654d234 100644 --- a/src/group_actions/group_action_interface.jl +++ b/src/group_actions/group_action_interface.jl @@ -160,7 +160,7 @@ base_lie_group(A::GroupAction) = A.group Return the $(_link(:AbstractManifold)) the group action acts upon. """ -ManifoldsBase.base_manifold(A::GroupOperationAction) = A.manifold +ManifoldsBase.base_manifold(A::GroupAction) = A.manifold function default_left_action end """ @@ -225,7 +225,7 @@ diff_group_apply!(A::GroupAction, q, g, p) Return the [`GroupAction`](@ref) representing the inverse of an [`GroupAction`](@ref) of [`AbstractGroupActionType`](@ref) `T`. This is usually done by returning the group action with the inverse type of `T`. """ -Base.inv(A::GroupAction) = GroupAction(inv(A.type), A.group) +Base.inv(A::GroupAction) = GroupAction(inv(A.type), A.group, A.manifold) """ inv(::AbstractGroupActionType) @@ -236,7 +236,7 @@ inverse operation. Base.inv(::AbstractGroupActionType) function Base.show(io::IO, A::GroupAction) - return print(io, "GroupAction($(A.type), $(A.group))") + return print(io, "GroupAction($(A.type), $(A.group), $(A.manifold))") end function switch end diff --git a/src/group_actions/group_operation_action.jl b/src/group_actions/group_operation_action.jl index 54e8da45..dbc7af71 100644 --- a/src/group_actions/group_operation_action.jl +++ b/src/group_actions/group_operation_action.jl @@ -67,6 +67,21 @@ for its inverse ``(Οƒ_h)^{-1}`` see [`InverseLeftGroupOperationAction`](@ref). """ struct InverseRightGroupOperationAction <: AbstractLeftGroupActionType end +""" + GroupOperationAction(action::AbstractLeftGroupActionType, group::LieGroup) + +Return a [`GroupAction`](@ref) for an [`AbstractLeftGroupActionType`](@ref) `action` representing +the action of the group operation as an action of the group on itself. +""" +function GroupOperationAction(action::AbstractGroupActionType, G::LieGroup) + return GroupAction(action, G, G) +end +function Base.show( + io::IO, GA::GroupAction{A,G,G} +) where {A<:AbstractGroupActionType,G<:LieGroup} + return print(io, "GroupOperationAction($(GA.type), $(GA.group))") +end + function apply!(A::GroupAction{LeftGroupOperationAction}, k, g, h) return compose!(A.group, k, g, h) #apply/compose g from left end diff --git a/src/groups/semidirect_product_group.jl b/src/groups/semidirect_product_group.jl index 3c175aa2..08e4d6dc 100644 --- a/src/groups/semidirect_product_group.jl +++ b/src/groups/semidirect_product_group.jl @@ -48,7 +48,7 @@ struct LeftSemidirectProductGroupOperation{ ) where { O1<:AbstractGroupOperation,O2<:AbstractGroupOperation,A<:AbstractGroupActionType } - return LeftSemidirectProductGroupOperation{O1,O2,A}(op1, op2, action) + return new{O1,O2,A}(op1, op2, action) end end @@ -97,7 +97,7 @@ struct RightSemidirectProductGroupOperation{ ) where { O1<:AbstractGroupOperation,O2<:AbstractGroupOperation,A<:AbstractGroupActionType } - return RightSemidirectProductGroupOperation{O1,O2,A}(op1, op2, action) + return new{O1,O2,A}(op1, op2, action) end end diff --git a/src/interface.jl b/src/interface.jl index 45bb5e92..30cfffd9 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -434,7 +434,7 @@ both signatures are equivalent. The operation can be performed in-place of `c`. By default this function requires [`identity_element`](@ref)`(G)` and calls -the corresponding [`get_coordinates`](@extref `ManifoldsBase.get_coordinates-Tuple{AbstractManifold, Any, Any, ManifoldsBase.AbstractBasis}`) function +the corresponding [`get_coordinates`](@extref ManifoldsBase :jl:function:`ManifoldsBase.get_coordinates`) function of the Riemannian manifold the Lie group is build on. The inverse operation is [`get_vector`](@ref). @@ -472,7 +472,7 @@ both signatures are equivalend. The operation can be performed in-place of a tangent vector `X`. By default this function requires [`identity_element`](@ref)`(G)` and calls -the corresponding [`get_vector`](@extref ManifoldsBase.get_vector-Tuple{AbstractManifold, Any, Any, ManifoldsBase.AbstractBasis}) function +the corresponding [`get_vector`](@extref ManifoldsBase :jl:function:`ManifoldsBase.get_vectors`) function of the Riemannian manifold the Lie group is build on. The inverse operation is [`get_coordinates`](@ref). diff --git a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl index 2c574bea..1bff7974 100644 --- a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl +++ b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl @@ -23,7 +23,6 @@ struct DummySecondOperation <: AbstractGroupOperation end struct DummyManifold <: LieGroups.AbstractManifold{LieGroups.ℝ} end struct DummyActionType <: AbstractGroupActionType end const DummyLieGroup = LieGroup{LieGroups.ℝ,DummyOperation,DummyManifold} -struct DummyGroupAction <: AbstractGroupAction{DummyActionType,DummyLieGroup,DummyManifold} end # === Test single functions === # @@ -60,7 +59,7 @@ function test_adjoint(G::LieGroup, g, X; expected=missing, test_mutating::Bool=t end """ - test_apply(A::AbstractGroupAction, g, p; expected=missing) + test_apply(A::GroupAction, g, p; expected=missing) Test `apply`. @@ -68,9 +67,7 @@ Test `apply`. * `expected=missing`: the result of the application of the group action. * `test_mutating::Bool=true`: test the mutating functions """ -function test_apply( - A::AbstractGroupAction, g, p; expected=missing, test_mutating::Bool=true -) +function test_apply(A::GroupAction, g, p; expected=missing, test_mutating::Bool=true) @testset "apply" begin q1 = apply(A, g, p) M = base_manifold(A) @@ -175,7 +172,7 @@ end # # --- D """ - test_diff_apply(A::AbstractGroupAction, g, p, X; expected=missing) + test_diff_apply(A::GroupAction, g, p, X; expected=missing) Test `diff_apply`. @@ -184,7 +181,7 @@ Test `diff_apply`. * `test_mutating::Bool=true`: test the mutating functions """ function test_diff_apply( - A::AbstractGroupAction, g, p, X; expected=missing, test_mutating::Bool=true + A::GroupAction, g, p, X; expected=missing, test_mutating::Bool=true ) @testset "diff_apply" begin Y1 = diff_apply(A, g, p, X) @@ -202,7 +199,7 @@ function test_diff_apply( end """ - test_diff_apply(A::AbstractGroupAction, g, p, X; expected=missing) + test_diff_apply(A::GroupAction, g, p, X; expected=missing) Test `diff_group_apply`. @@ -211,7 +208,7 @@ Test `diff_group_apply`. * `test_mutating::Bool=true`: test the mutating functions """ function test_diff_group_apply( - A::AbstractGroupAction, g, p, X; expected=missing, test_mutating::Bool=true + A::GroupAction, g, p, X; expected=missing, test_mutating::Bool=true ) @testset "diff_group_apply" begin Y1 = diff_group_apply(A, g, p, X) @@ -690,7 +687,7 @@ For now this (only) checks that `"\$G"` yields the `repr_string`. Requires `show` (or `repr`) to be implemented. """ -function test_show(G::Union{AbstractGroupAction,LieGroup}, repr_string::AbstractString) +function test_show(G::Union{GroupAction,LieGroup}, repr_string::AbstractString) @testset "repr(G, g, h)" begin @test repr(G) == repr_string end @@ -884,9 +881,7 @@ Possible `expectations` are * `:manifold` is the `AbstractManifold` the action acts upon * `:repr` is a sting one gets from `repr(G)` """ -function test_group_action( - A::AbstractGroupAction, properties::Dict, expectations::Dict=Dict() -) +function test_group_action(A::GroupAction, properties::Dict, expectations::Dict=Dict()) a_tol = get(expectations, :atol, 1e-8) mutating = get(properties, :Mutating, true) functions = get(properties, :Functions, Function[]) diff --git a/test/groups/test_semidirect_product_group.jl b/test/groups/test_semidirect_product_group.jl index dbec9d2f..b27de5e6 100644 --- a/test/groups/test_semidirect_product_group.jl +++ b/test/groups/test_semidirect_product_group.jl @@ -1,7 +1,55 @@ using LieGroups, Test, ManifoldsBase -s = joinpath(@__DIR__, "LieGroupsTestSuite.jl") +s = joinpath(@__DIR__, "..", "LieGroupsTestSuite.jl") !(s in LOAD_PATH) && (push!(LOAD_PATH, s)) using LieGroupsTestSuite -@testset "Generic semidirect product Lie group" begin end +@testset "Generic semidirect product Lie group" begin + M = LieGroupsTestSuite.DummyManifold() + op1 = LieGroupsTestSuite.DummyOperation() + G1 = LieGroup(M, op1) + op2 = LieGroupsTestSuite.DummySecondOperation() + G2 = LieGroup(M, op2) + + fcts = [ + # compose, + # conjugate, + # diff_conjugate, + # diff_inv, + # diff_left_compose, + # diff_right_compose, + # exp, + # hat, + # inv, + # inv_left_compose, + # inv_right_compose, + # is_identity, + # lie_bracket, + # log, + # rand, + show, + #vee, + ] + + Gl = LeftSemidirectProductLieGroup(G1, G2, LeftGroupOperationAction()) + properties = Dict( + :Name => "The Power Manifold", + # :Rng => Random.MersenneTwister(), + :Functions => fcts, + ) + expectations = Dict( + :repr => "LeftSemidirectProductLieGroup($(G1), $(G2), LeftGroupOperationAction())" + ) + test_lie_group(Gl, properties, expectations) + + Gr = RightSemidirectProductLieGroup(G1, G2, RightGroupOperationAction()) + properties = Dict( + :Name => "The Power Manifold", + # :Rng => Random.MersenneTwister(), + :Functions => fcts, + ) + expectations = Dict( + :repr => "RightSemidirectProductLieGroup($(G1), $(G2), RightGroupOperationAction())" + ) + test_lie_group(Gr, properties, expectations) +end From ceb7dddb0a5f6554585b77ecb5e342defc5aae36 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Fri, 15 Nov 2024 18:38:39 +0100 Subject: [PATCH 16/43] document the new changes in the NEWS.md. --- NEWS.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/NEWS.md b/NEWS.md index 4430b78b..766681bd 100644 --- a/NEWS.md +++ b/NEWS.md @@ -15,9 +15,19 @@ Everything denoted by β€œformerly” refers to the previous name in [`Manifolds. * `LieGroup` (formerly `GroupManifold`) as well as the concrete groups * `TranslationGroup` * `GeneralLinearGroup` (formerly `GeneralLinear`) + * `LeftSemidirectProductLieGroup` (formerly `SemidirectProductGroup`) + * `⋉` (alias for `LeftSemidirectProductGroupOperation` when a `default_left_action(G,H)` is defined for the two groups) * `PowerLieGroup` (formerly `PowerGroup`) + * `ProductLieGroup` (formerly `ProductGroup`) + * `RightSemidirectProductLieGroup` + * `⋉` (alias for `RightSemidirectProductGroupOperation` when a `default_right_action(G,H)` is defined for the two groups) * `AbstractGroupOperation` as well as its concrete subtypes * `AdditionGroupOperation` (formerly `AdditionOperation`) + * `MultiplicationGroupOperation` (formerly `MultiplicationOperation`) + * `PowerGroupOperation` (formerly the Lie group was stored inside a power manifold) + * `ProductGroupOperation` (formerly the Lie groups were stored inside a product manifold) + * `LeftSemidirectProductGroupOperation` (this was formerly only implictly stored in the `SemidirectProductGroup`) + * `RightSemidirectProductGroupOperation` * `AbstractGroupActionType` with its 2 specific (new) abstract subtypes * `AbstractLeftGroupActionType` * `AbstractRightGroupActionType` From bc4f9d59c856c7ecf9a4e310bd3da0668256adcb Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Sat, 16 Nov 2024 20:39:12 +0100 Subject: [PATCH 17/43] Got a bit stuck on allocations and ambiguities. --- src/groups/power_group.jl | 100 ++++++++++++++++-- src/interface.jl | 6 ++ .../LieGroupsTestSuite.jl | 16 +-- test/groups/test_power_group.jl | 29 +++-- 4 files changed, 124 insertions(+), 27 deletions(-) diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index 7120280e..3ab9729b 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -3,29 +3,109 @@ # Power Lie groups: work element wise @doc """ - PowerLieGroup(G::LieGroup, size::Int...; kwargs...) - PowerLieGroup(M::AbstractManifold, op::AbstractGroupOperation, size:Int...; kwargs...) + PowerLieGroup(G::LieGroup, args...; kwargs...) + PowerLieGroup(M::AbstractManifold, op::AbstractGroupOperation, args...; kwargs...) (L::LueGroup)^(n...) = PowerLieGroup(L, n...) Generate the [`LieGroup`](@ref) of the `n`-th power of a Lie group `G` or manifold `M`. If passed a Lie group `G`, the group operation is the same as on `G`, but applied elementwise. -The keyword arguments `kwargs...` are passed on to the constructor of the [`PowerManifold`](@extref `ManifoldsBase.PowerManifold`). +Bot the arguments `args...` as well as the keyword arguments `kwargs...` are passed on to +the constructor of the [`PowerManifold`](@extref `ManifoldsBase.PowerManifold`). +This especially includes the `size` of the manifold and allows to specify a [`NestedPowerRepresentation`](@extref `ManifoldsBase.NestedPowerRepresentation`). + """ -PowerLieGroup(::AbstractManifold, size::Int...; kwargs...) +PowerLieGroup(::AbstractManifold, args...; kwargs...) -function PowerLieGroup( - M::AbstractManifold, op::AbstractGroupOperation, size::Int...; kwargs... -) - pM = Manifolds.PowerManifold(M, size...; kwargs...) +function PowerLieGroup(M::AbstractManifold, op::AbstractGroupOperation, args...; kwargs...) + pM = Manifolds.PowerManifold(M, args...; kwargs...) return LieGroup(pM, op) end -function PowerLieGroup(G::LieGroup, size::Int...; kwargs...) - return PowerLieGroup(G.manifold, G.op, size...; kwargs...) +function PowerLieGroup(G::LieGroup, args...; kwargs...) + return PowerLieGroup(G.manifold, G.op, args...; kwargs...) end Base.:^(G::LieGroup, n...) = PowerLieGroup(G, n...) +function compose!(PG::LieGroup{𝔽,Op,<:AbstractPowerManifold}, k, g, h) where {𝔽,Op} + PM = PG.manifold + rep_size = representation_size(PM) + G = LieGroup(PM.manifold, PG.op) + for i in get_iterator(PM) + compose!( + G, + ManifoldsBase._write(PM, rep_size, k, i), + ManifoldsBase._read(PM, rep_size, g, i), + ManifoldsBase._read(PM, rep_size, h, i), + ) + end + return k +end + +function ManifoldsBase.check_size( + PG::LieGroup{𝔽,Op,<:AbstractPowerManifold}, g +) where {𝔽,Op} + return ManifoldsBase.check_size(PG.manifold, g) +end +function ManifoldsBase.check_size( + PG::LieGroup{𝔽,Op,<:AbstractPowerManifold}, g, X +) where {𝔽,Op} + return ManifoldsBase.check_size(PG.manifold, g, X) +end + +function exp!(PG::LieGroup{𝔽,Op,<:AbstractPowerManifold}, h, g, X, t::Number=1) where {𝔽,Op} + PM = PG.manifold + rep_size = representation_size(PM) + G = LieGroup(PM.manifold, PG.op) + for i in get_iterator(PM) + exp!( + G, + ManifoldsBase._write(PM, rep_size, h, i), + ManifoldsBase._read(PM, rep_size, g, i), + ManifoldsBase._read(PM, rep_size, X, i), + ) + end + return h +end + +function identity_element!(PG::LieGroup{𝔽,Op,<:AbstractPowerManifold}, e) where {𝔽,Op} + PM = PG.manifold + rep_size = representation_size(PM) + G = LieGroup(PM.manifold, PG.op) + for i in get_iterator(PM) + identity_element!(G, ManifoldsBase._write(PM, rep_size, e, i)) + end + return e +end + +function inv!(PG::LieGroup{𝔽,Op,<:AbstractPowerManifold}, h, g) where {𝔽,Op} + PM = PG.manifold + rep_size = representation_size(PM) + G = LieGroup(PM.manifold, PG.op) + for i in get_iterator(PM) + inv!( + G, + ManifoldsBase._write(PM, rep_size, h, i), + ManifoldsBase._read(PM, rep_size, g, i), + ) + end + return h +end + +function log!(PG::LieGroup{𝔽,Op,<:AbstractPowerManifold}, X, g) where {𝔽,Op} + PM = PG.manifold + rep_size = representation_size(PM) + G = LieGroup(PM.manifold, PG.op) + for i in get_iterator(PM) + log!( + G, + ManifoldsBase._write(PM, rep_size, X, i), + ManifoldsBase._read(PM, rep_size, g, i), + ) + end + return X +end + function Base.show( io::IO, G::LieGroup{𝔽,O,<:ManifoldsBase.AbstractPowerManifold} ) where {𝔽,O<:AbstractGroupOperation} diff --git a/src/interface.jl b/src/interface.jl index 30cfffd9..2ccf0c26 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -139,6 +139,11 @@ function adjoint!(G::LieGroup, Y, g, X) return Y end +# Pass through for allocation +function ManifoldsBase.allocate_result(G::LieGroup, args...) + return ManifoldsBase.allocate_result(G.manifold, args...) +end + # # Allocation hints function ManifoldsBase.allocate_result(G::LieGroup, f::typeof(identity_element)) @@ -565,6 +570,7 @@ This can be done in-place of `h`, without side effects, that is you can do `inv! @doc "$_doc_inv" function Base.inv(G::LieGroup, g) + print(g) h = allocate_result(G, inv, g) return inv!(G, h, g) end diff --git a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl index 1bff7974..ba0ceac9 100644 --- a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl +++ b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl @@ -643,33 +643,33 @@ function test_rand( ) @testset "rand" begin g1 = rand(G) - @test is_point(G, g1) + @test is_point(G, g1; error=:error) if test_mutating g2 = copy(G, g) rand!(G, g2) - @test is_point(G, g2) + @test is_point(G, g2; error=:error) end X1 = rand(G; vector_at=g1) - @test is_vector(G, g1, X1) + @test is_vector(G, g1, X1; error=:error) if test_mutating X2 = zero_vector(LieAlgebra(G), g1) rand!(G, X2; vector_at=g1) - @test is_vector(G, g1, X2) + @test is_vector(G, g1, X2; error=:error) end if !ismissing(rng) g1 = rand(rng, G) - @test is_point(G, g1) + @test is_point(G, g1; error=:error) if test_mutating g2 = copy(G, g) rand!(rng, G, g2) - @test is_point(G, g2) + @test is_point(G, g2; error=:error) end X1 = rand(rng, G; vector_at=g1) - @test is_vector(G, g1, X1) + @test is_vector(G, g1, X1; error=:error) if test_mutating X2 = zero_vector(LieAlgebra(G), g1) rand!(rng, G, X2; vector_at=g1) - @test is_vector(G, g1, X2) + @test is_vector(G, g1, X2; error=:error) end end end diff --git a/test/groups/test_power_group.jl b/test/groups/test_power_group.jl index 6720e708..925b56d1 100644 --- a/test/groups/test_power_group.jl +++ b/test/groups/test_power_group.jl @@ -1,4 +1,4 @@ -using LieGroups, Test, ManifoldsBase +using LieGroups, Test, ManifoldsBase, Random s = joinpath(@__DIR__, "..", "LieGroupsTestSuite.jl") !(s in LOAD_PATH) && (push!(LOAD_PATH, s)) @@ -10,9 +10,21 @@ using LieGroupsTestSuite G = LieGroup(M, op) pG = G^2 - properties = Dict( - :Name => "The Power Manifold", - # :Rng => Random.MersenneTwister(), + properties1 = Dict(:Name => "The generic Power Manifold", :Functions => [show]) + expectations1 = Dict( + :repr => "PowerLieGroup(LieGroupsTestSuite.DummyManifold(), LieGroupsTestSuite.DummyOperation(), 2)", + ) + test_lie_group(pG, properties1, expectations1) + + # Explicit one to test element-wise methods + pG2 = PowerLieGroup(TranslationGroup(2), NestedPowerRepresentation(), 2) + g, h = [[1.0, 0.0], [0.0, 3.0]], [[0.0, 1.0], [2.0, 0.0]] + X, Y = [[0.0, 0.1], [0.2, 0.0]], [[0.1, 0.2], [0.0, 0.3]] + properties2 = Dict( + :Name => "The generic Power Manifold", + :Points => [g, h], + :Vectors => [X, Y], + :Rng => Random.MersenneTwister(), :Functions => [ # compose, # conjugate, @@ -28,13 +40,12 @@ using LieGroupsTestSuite # is_identity, # lie_bracket, # log, - # rand, - show, - #vee, + rand, + # vee, ], ) - expectations = Dict( + expectations2 = Dict( :repr => "PowerLieGroup(LieGroupsTestSuite.DummyManifold(), LieGroupsTestSuite.DummyOperation(), 2)", ) - test_lie_group(pG, properties, expectations) + test_lie_group(pG2, properties2, expectations2) end From 61886d5b9c7227006d7967f90b3d820ef9093c9b Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Thu, 21 Nov 2024 17:14:41 +0100 Subject: [PATCH 18/43] Introduce PowerGroupOperation to avoid ambiguities in dispatch. --- src/groups/power_group.jl | 87 ++++++++++++++++++++++----------- src/groups/product_group.jl | 4 +- src/interface.jl | 2 +- test/groups/test_power_group.jl | 4 +- 4 files changed, 64 insertions(+), 33 deletions(-) diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index 3ab9729b..46dadbf5 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -2,36 +2,52 @@ # # Power Lie groups: work element wise +@doc """ + PowerGroupOperation{O} <: AbstractGroupOperation + +A struct do model a that a certain group operation is applied element-wise on a [`PowerManifold`](@extref `ManifoldsBase.PowerManifold`). + +# Constructor + + PowerGroupOperation(o:O) +""" +struct PowerGroupOperation{O} <: AbstractGroupOperation + op::O +end + @doc """ PowerLieGroup(G::LieGroup, args...; kwargs...) - PowerLieGroup(M::AbstractManifold, op::AbstractGroupOperation, args...; kwargs...) + PowerLieGroup(M::AbstractManifold, op::PowerGroupOperation, args...; kwargs...) (L::LueGroup)^(n...) = PowerLieGroup(L, n...) Generate the [`LieGroup`](@ref) of the `n`-th power of a Lie group `G` or manifold `M`. -If passed a Lie group `G`, the group operation is the same as on `G`, but applied elementwise. +If passed a Lie group `G`, the group operation on the [`PowerLieGroup`](@ref) is the same as on `G`, +but applied elementwise. Internally, the corresponding [`PowerGroupOperation`](@ref) is created. +If you pass a manifold `M`, you have to provide the corresponding [`PowerGroupOperation`](@ref) yourself. Bot the arguments `args...` as well as the keyword arguments `kwargs...` are passed on to the constructor of the [`PowerManifold`](@extref `ManifoldsBase.PowerManifold`). This especially includes the `size` of the manifold and allows to specify a [`NestedPowerRepresentation`](@extref `ManifoldsBase.NestedPowerRepresentation`). - """ PowerLieGroup(::AbstractManifold, args...; kwargs...) -function PowerLieGroup(M::AbstractManifold, op::AbstractGroupOperation, args...; kwargs...) +function PowerLieGroup(M::AbstractManifold, op::PowerGroupOperation, args...; kwargs...) pM = Manifolds.PowerManifold(M, args...; kwargs...) return LieGroup(pM, op) end function PowerLieGroup(G::LieGroup, args...; kwargs...) - return PowerLieGroup(G.manifold, G.op, args...; kwargs...) + return PowerLieGroup(G.manifold, PowerGroupOperation(G.op), args...; kwargs...) end Base.:^(G::LieGroup, n...) = PowerLieGroup(G, n...) -function compose!(PG::LieGroup{𝔽,Op,<:AbstractPowerManifold}, k, g, h) where {𝔽,Op} +function compose!( + PG::LieGroup{𝔽,Op,M}, k, g, h +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} PM = PG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op) - for i in get_iterator(PM) + G = LieGroup(PM.manifold, PG.op.op) + for i in ManifoldsBase.get_iterator(PM) compose!( G, ManifoldsBase._write(PM, rep_size, k, i), @@ -43,46 +59,53 @@ function compose!(PG::LieGroup{𝔽,Op,<:AbstractPowerManifold}, k, g, h) where end function ManifoldsBase.check_size( - PG::LieGroup{𝔽,Op,<:AbstractPowerManifold}, g -) where {𝔽,Op} + PG::LieGroup{𝔽,Op,M}, g +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} return ManifoldsBase.check_size(PG.manifold, g) end function ManifoldsBase.check_size( - PG::LieGroup{𝔽,Op,<:AbstractPowerManifold}, g, X -) where {𝔽,Op} + PG::LieGroup{𝔽,Op,M}, g, X +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} return ManifoldsBase.check_size(PG.manifold, g, X) end -function exp!(PG::LieGroup{𝔽,Op,<:AbstractPowerManifold}, h, g, X, t::Number=1) where {𝔽,Op} +function ManifoldsBase.exp!( + PG::LieGroup{𝔽,Op,M}, h, g, X, t::Number=1 +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} PM = PG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op) - for i in get_iterator(PM) + G = LieGroup(PM.manifold, PG.op.op) + for i in ManifoldsBase.get_iterator(PM) exp!( G, ManifoldsBase._write(PM, rep_size, h, i), ManifoldsBase._read(PM, rep_size, g, i), ManifoldsBase._read(PM, rep_size, X, i), + t, ) end return h end -function identity_element!(PG::LieGroup{𝔽,Op,<:AbstractPowerManifold}, e) where {𝔽,Op} +function identity_element!( + PG::LieGroup{𝔽,Op,M}, e +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} PM = PG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op) - for i in get_iterator(PM) + G = LieGroup(PM.manifold, PG.op.op) + for i in ManifoldsBase.get_iterator(PM) identity_element!(G, ManifoldsBase._write(PM, rep_size, e, i)) end return e end -function inv!(PG::LieGroup{𝔽,Op,<:AbstractPowerManifold}, h, g) where {𝔽,Op} +function inv!( + PG::LieGroup{𝔽,Op,M}, h, g +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} PM = PG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op) - for i in get_iterator(PM) + G = LieGroup(PM.manifold, PG.op.op) + for i in ManifoldsBase.get_iterator(PM) inv!( G, ManifoldsBase._write(PM, rep_size, h, i), @@ -92,11 +115,13 @@ function inv!(PG::LieGroup{𝔽,Op,<:AbstractPowerManifold}, h, g) where {𝔽,O return h end -function log!(PG::LieGroup{𝔽,Op,<:AbstractPowerManifold}, X, g) where {𝔽,Op} +function ManifoldsBase.log!( + PG::LieGroup{𝔽,Op,M}, X, g +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} PM = PG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op) - for i in get_iterator(PM) + G = LieGroup(PM.manifold, PG.op.op) + for i in ManifoldsBase.get_iterator(PM) log!( G, ManifoldsBase._write(PM, rep_size, X, i), @@ -107,9 +132,15 @@ function log!(PG::LieGroup{𝔽,Op,<:AbstractPowerManifold}, X, g) where {𝔽,O end function Base.show( - io::IO, G::LieGroup{𝔽,O,<:ManifoldsBase.AbstractPowerManifold} -) where {𝔽,O<:AbstractGroupOperation} - M = G.manifold.manifold + io::IO, G::LieGroup{𝔽,Op,M} +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} + PM = G.manifold + POp = G.op + L = LieGroup(PM.manifold, POp.op) size = Manifolds.get_parameter(G.manifold.size) - return print(io, "PowerLieGroup($(M), $(G.op), $(join(size, ", ")))") + return print(io, "PowerLieGroup($L, $(join(size, ", ")))") +end + +function Base.show(io::IO, POp::PowerGroupOperation) + return print(io, "PowerGroupOperation($(POp.op))") end diff --git a/src/groups/product_group.jl b/src/groups/product_group.jl index a545b0f2..5ded7457 100644 --- a/src/groups/product_group.jl +++ b/src/groups/product_group.jl @@ -11,8 +11,8 @@ that together forms a new group operation. # Constructor - ProductGroupOperation(O...) - Γ—(O...) = ProductGroupOperation(O...) + ProductGroupOperation(o::O...) + Γ—(o::O...) = ProductGroupOperation(o...) """ struct ProductGroupOperation{OTM<:Tuple} <: AbstractGroupOperation operations::OTM diff --git a/src/interface.jl b/src/interface.jl index 2ccf0c26..c4545056 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -867,5 +867,5 @@ end function ManifoldsBase.zero_vector!( G::LieGroup{𝔽,O}, X, ::Identity{O} ) where {𝔽,O<:AbstractGroupOperation} - return zero_vector!(G, X, identity_element(G)) + return zero_vector!(G.manifold, X, identity_element(G)) end diff --git a/test/groups/test_power_group.jl b/test/groups/test_power_group.jl index 925b56d1..7660ce76 100644 --- a/test/groups/test_power_group.jl +++ b/test/groups/test_power_group.jl @@ -12,7 +12,7 @@ using LieGroupsTestSuite properties1 = Dict(:Name => "The generic Power Manifold", :Functions => [show]) expectations1 = Dict( - :repr => "PowerLieGroup(LieGroupsTestSuite.DummyManifold(), LieGroupsTestSuite.DummyOperation(), 2)", + :repr => "PowerLieGroup(LieGroup(LieGroupsTestSuite.DummyManifold(), LieGroupsTestSuite.DummyOperation()), 2)", ) test_lie_group(pG, properties1, expectations1) @@ -45,7 +45,7 @@ using LieGroupsTestSuite ], ) expectations2 = Dict( - :repr => "PowerLieGroup(LieGroupsTestSuite.DummyManifold(), LieGroupsTestSuite.DummyOperation(), 2)", + :repr => "PowerLieGroup(LieGroup(LieGroupsTestSuite.DummyManifold(), LieGroupsTestSuite.DummyOperation()), 2)", ) test_lie_group(pG2, properties2, expectations2) end From 3147e710a73f59c8f6bc4df20b2a28522c0e179b Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Thu, 21 Nov 2024 18:24:15 +0100 Subject: [PATCH 19/43] Resolve a few ambiguities. Still fighting allocation with Power manifold and rand. --- src/groups/power_group.jl | 34 +++++++++++++++++++++++++++------- src/interface.jl | 15 +++++++-------- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index 46dadbf5..74381ec8 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -17,7 +17,6 @@ end @doc """ PowerLieGroup(G::LieGroup, args...; kwargs...) - PowerLieGroup(M::AbstractManifold, op::PowerGroupOperation, args...; kwargs...) (L::LueGroup)^(n...) = PowerLieGroup(L, n...) Generate the [`LieGroup`](@ref) of the `n`-th power of a Lie group `G` or manifold `M`. @@ -31,17 +30,15 @@ This especially includes the `size` of the manifold and allows to specify a [`Ne """ PowerLieGroup(::AbstractManifold, args...; kwargs...) -function PowerLieGroup(M::AbstractManifold, op::PowerGroupOperation, args...; kwargs...) - pM = Manifolds.PowerManifold(M, args...; kwargs...) - return LieGroup(pM, op) -end function PowerLieGroup(G::LieGroup, args...; kwargs...) - return PowerLieGroup(G.manifold, PowerGroupOperation(G.op), args...; kwargs...) + M = G.manifold + pM = Manifolds.PowerManifold(M, args...; kwargs...) + return LieGroup(pM, PowerGroupOperation(G.op)) end Base.:^(G::LieGroup, n...) = PowerLieGroup(G, n...) -function compose!( +function _compose!( PG::LieGroup{𝔽,Op,M}, k, g, h ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} PM = PG.manifold @@ -63,6 +60,11 @@ function ManifoldsBase.check_size( ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} return ManifoldsBase.check_size(PG.manifold, g) end +function ManifoldsBase.check_size( + ::LieGroup{𝔽,Op,M}, ::Identity +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} + return nothing +end function ManifoldsBase.check_size( PG::LieGroup{𝔽,Op,M}, g, X ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} @@ -86,6 +88,24 @@ function ManifoldsBase.exp!( end return h end +function ManifoldsBase.exp!( + PG::LieGroup{𝔽,Op,M}, h, ::Identity{Op}, X, t::Number=1 +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} + PM = PG.manifold + rep_size = representation_size(PM) + G = LieGroup(PM.manifold, PG.op.op) + e_g = Identity(G) + for i in ManifoldsBase.get_iterator(PM) + exp!( + G, + ManifoldsBase._write(PM, rep_size, h, i), + e_g, + ManifoldsBase._read(PM, rep_size, X, i), + t, + ) + end + return h +end function identity_element!( PG::LieGroup{𝔽,Op,M}, e diff --git a/src/interface.jl b/src/interface.jl index c4545056..470bf12b 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -139,18 +139,16 @@ function adjoint!(G::LieGroup, Y, g, X) return Y end -# Pass through for allocation -function ManifoldsBase.allocate_result(G::LieGroup, args...) - return ManifoldsBase.allocate_result(G.manifold, args...) -end - # -# Allocation hints +# Allocation hints - mainly pass-through function ManifoldsBase.allocate_result(G::LieGroup, f::typeof(identity_element)) apf = ManifoldsBase.allocation_promotion_function(G, f, ()) rs = ManifoldsBase.representation_size(G) return ManifoldsBase.allocate_result_array(G, f, apf(Float64), rs) end +function ManifoldsBase.allocate_result(G::LieGroup, f::typeof(zero_vector), g) + return ManifoldsBase.allocate_result(G.manifold, f, g) +end @doc """ base_manifold(G::LieGroup) @@ -422,7 +420,9 @@ end # Fallback to a MethodError to avoid stack overflow @doc "$(_doc_exp_id)" -function ManifoldsBase.exp!(G::LieGroup, h, e::Identity, X, t::Number=1) +function ManifoldsBase.exp!( + G::LieGroup{𝔽,Op}, h, e::Identity{Op}, X, t::Number=1 +) where {𝔽,Op<:AbstractGroupOperation} throw(MethodError(exp!, (typeof(G), typeof(h), typeof(e), typeof(X), typeof(t)))) end @@ -570,7 +570,6 @@ This can be done in-place of `h`, without side effects, that is you can do `inv! @doc "$_doc_inv" function Base.inv(G::LieGroup, g) - print(g) h = allocate_result(G, inv, g) return inv!(G, h, g) end From 9e6bf9d43759a34f58685ab0ea690f2b4dfd2fc7 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Thu, 21 Nov 2024 18:41:03 +0100 Subject: [PATCH 20/43] fix rand allocation. --- src/interface.jl | 3 +++ test/groups/test_power_group.jl | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/interface.jl b/src/interface.jl index 470bf12b..0cf4a5bf 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -149,6 +149,9 @@ end function ManifoldsBase.allocate_result(G::LieGroup, f::typeof(zero_vector), g) return ManifoldsBase.allocate_result(G.manifold, f, g) end +function ManifoldsBase.allocate_result(G::LieGroup, f::typeof(rand)) + return ManifoldsBase.allocate_result(G.manifold, f) +end @doc """ base_manifold(G::LieGroup) diff --git a/test/groups/test_power_group.jl b/test/groups/test_power_group.jl index 7660ce76..53ae7189 100644 --- a/test/groups/test_power_group.jl +++ b/test/groups/test_power_group.jl @@ -21,7 +21,7 @@ using LieGroupsTestSuite g, h = [[1.0, 0.0], [0.0, 3.0]], [[0.0, 1.0], [2.0, 0.0]] X, Y = [[0.0, 0.1], [0.2, 0.0]], [[0.1, 0.2], [0.0, 0.3]] properties2 = Dict( - :Name => "The generic Power Manifold", + :Name => "The generic nested Power Manifold", :Points => [g, h], :Vectors => [X, Y], :Rng => Random.MersenneTwister(), From ebfdd4ce9bd4f729ed3c0a7bf7be26842a7b7430 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Thu, 21 Nov 2024 19:26:57 +0100 Subject: [PATCH 21/43] Fix allocations. --- src/groups/power_group.jl | 34 +++++++++++++++++++++++++++ src/interface.jl | 41 +++++++++++++++++++++------------ test/groups/test_power_group.jl | 8 +++---- 3 files changed, 64 insertions(+), 19 deletions(-) diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index 74381ec8..ccb40b85 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -134,6 +134,23 @@ function inv!( end return h end +function inv!( + PG::LieGroup{𝔽,Op,M}, h, ::Identity{Op} +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} + PM = PG.manifold + rep_size = representation_size(PM) + G = LieGroup(PM.manifold, PG.op.op) + e_g = Identity(G.op) + for i in ManifoldsBase.get_iterator(PM) + inv!(G, ManifoldsBase._write(PM, rep_size, h, i), e_g) + end + return h +end +function inv!( + ::LieGroup{𝔽,Op,M}, h::Identity{Op}, ::Identity{Op} +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} + return h +end function ManifoldsBase.log!( PG::LieGroup{𝔽,Op,M}, X, g @@ -150,6 +167,23 @@ function ManifoldsBase.log!( end return X end +function ManifoldsBase.log!( + PG::LieGroup{𝔽,Op,M}, X, ::Identity{Op}, g +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} + PM = PG.manifold + rep_size = representation_size(PM) + G = LieGroup(PM.manifold, PG.op.op) + e_g = Identity(G.op) + for i in ManifoldsBase.get_iterator(PM) + log!( + G, + ManifoldsBase._write(PM, rep_size, X, i), + e_g, + ManifoldsBase._read(PM, rep_size, g, i), + ) + end + return X +end function Base.show( io::IO, G::LieGroup{𝔽,Op,M} diff --git a/src/interface.jl b/src/interface.jl index 0cf4a5bf..a0937d1c 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -139,20 +139,6 @@ function adjoint!(G::LieGroup, Y, g, X) return Y end -# -# Allocation hints - mainly pass-through -function ManifoldsBase.allocate_result(G::LieGroup, f::typeof(identity_element)) - apf = ManifoldsBase.allocation_promotion_function(G, f, ()) - rs = ManifoldsBase.representation_size(G) - return ManifoldsBase.allocate_result_array(G, f, apf(Float64), rs) -end -function ManifoldsBase.allocate_result(G::LieGroup, f::typeof(zero_vector), g) - return ManifoldsBase.allocate_result(G.manifold, f, g) -end -function ManifoldsBase.allocate_result(G::LieGroup, f::typeof(rand)) - return ManifoldsBase.allocate_result(G.manifold, f) -end - @doc """ base_manifold(G::LieGroup) @@ -245,7 +231,7 @@ This can be done in-place of `k`. """ @doc "$(_doc_conjugate)" function conjugate(G::LieGroup, g, h) - k = ManifoldsBase.allocate_result(G, inv_right_compose, h, g) + k = ManifoldsBase.allocate_result(G, conjugate, h, g) return conjugate!(G, k, g, h) end @@ -585,6 +571,10 @@ function Base.inv(::LieGroup{𝔽,O}, e::Identity{O}) where {𝔽,O<:AbstractGro return e end +function inv!(G::LieGroup{𝔽,O}, q, ::Identity{O}) where {𝔽,O<:AbstractGroupOperation} + return identity_element!(G, q) +end + _doc_inv_left_compose = """ inv_left_compose(G::LieGroup, g, h) inv_left_compose!(G::LieGroup, k, g, h) @@ -871,3 +861,24 @@ function ManifoldsBase.zero_vector!( ) where {𝔽,O<:AbstractGroupOperation} return zero_vector!(G.manifold, X, identity_element(G)) end + +# +# Allocation hints - mainly pass-through, especially for power manifolds +function ManifoldsBase.allocate_result( + G::LieGroup, + f::Union{typeof(compose),typeof(inv),typeof(conjugate),typeof(exp)}, + args..., +) + return ManifoldsBase.allocate_result(G.manifold, ManifoldsBase.exp, args...) +end +function ManifoldsBase.allocate_result(G::LieGroup, f::typeof(log), args...) + return ManifoldsBase.allocate_result(G.manifold, f, args...) +end +function ManifoldsBase.allocate_result(G::LieGroup, f::typeof(zero_vector), g) + return ManifoldsBase.allocate_result(G.manifold, f, g) +end +function ManifoldsBase.allocate_result( + G::LieGroup, f::Union{typeof(rand),typeof(identity_element)} +) + return ManifoldsBase.allocate_result(G.manifold, f) +end diff --git a/test/groups/test_power_group.jl b/test/groups/test_power_group.jl index 53ae7189..aad3358e 100644 --- a/test/groups/test_power_group.jl +++ b/test/groups/test_power_group.jl @@ -26,20 +26,20 @@ using LieGroupsTestSuite :Vectors => [X, Y], :Rng => Random.MersenneTwister(), :Functions => [ - # compose, + compose, # conjugate, # diff_conjugate, # diff_inv, # diff_left_compose, # diff_right_compose, - # exp, + exp, # hat, - # inv, + inv, # inv_left_compose, # inv_right_compose, # is_identity, # lie_bracket, - # log, + log, rand, # vee, ], From b3591a5819cff79cd7f4fd907ff596a9b288d36b Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Sun, 24 Nov 2024 17:17:22 +0100 Subject: [PATCH 22/43] Continue power lie group interface. --- src/groups/power_group.jl | 88 +++++++++++++++++++++++++++++++++ test/groups/test_power_group.jl | 10 ++-- 2 files changed, 93 insertions(+), 5 deletions(-) diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index ccb40b85..ea02fde2 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -71,6 +71,94 @@ function ManifoldsBase.check_size( return ManifoldsBase.check_size(PG.manifold, g, X) end +function conjugate!( + PG::LieGroup{𝔽,Op,M}, h, g, k +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} + PM = PG.manifold + rep_size = representation_size(PM) + G = LieGroup(PM.manifold, PG.op.op) + for i in ManifoldsBase.get_iterator(PM) + conjugate!( + G, + ManifoldsBase._write(PM, rep_size, h, i), + ManifoldsBase._read(PM, rep_size, g, i), + ManifoldsBase._read(PM, rep_size, k, i), + ) + end + return h +end + +function diff_conjugate!( + PG::LieGroup{𝔽,Op,M}, Y, g, h, X +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} + PM = PG.manifold + rep_size = representation_size(PM) + G = LieGroup(PM.manifold, PG.op.op) + for i in ManifoldsBase.get_iterator(PM) + diff_conjugate!( + G, + ManifoldsBase._write(PM, rep_size, Y, i), + ManifoldsBase._read(PM, rep_size, g, i), + ManifoldsBase._read(PM, rep_size, h, i), + ManifoldsBase._read(PM, rep_size, X, i), + ) + end + return Y +end + +function diff_inv!( + PG::LieGroup{𝔽,Op,M}, Y, g, X +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} + PM = PG.manifold + rep_size = representation_size(PM) + G = LieGroup(PM.manifold, PG.op.op) + for i in ManifoldsBase.get_iterator(PM) + diff_inv!( + G, + ManifoldsBase._write(PM, rep_size, Y, i), + ManifoldsBase._read(PM, rep_size, g, i), + ManifoldsBase._read(PM, rep_size, X, i), + ) + end + return Y +end + +function diff_left_compose!( + PG::LieGroup{𝔽,Op,M}, Y, g, h, X +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} + PM = PG.manifold + rep_size = representation_size(PM) + G = LieGroup(PM.manifold, PG.op.op) + for i in ManifoldsBase.get_iterator(PM) + diff_left_compose!( + G, + ManifoldsBase._write(PM, rep_size, Y, i), + ManifoldsBase._read(PM, rep_size, g, i), + ManifoldsBase._read(PM, rep_size, h, i), + ManifoldsBase._read(PM, rep_size, X, i), + ) + end + return Y +end + +function diff_right_compose!( + PG::LieGroup{𝔽,Op,M}, Y, g, h, X +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} + PM = PG.manifold + rep_size = representation_size(PM) + G = LieGroup(PM.manifold, PG.op.op) + for i in ManifoldsBase.get_iterator(PM) + diff_right_compose!( + G, + ManifoldsBase._write(PM, rep_size, Y, i), + ManifoldsBase._read(PM, rep_size, g, i), + ManifoldsBase._read(PM, rep_size, h, i), + ManifoldsBase._read(PM, rep_size, X, i), + ) + end + return Y +end + function ManifoldsBase.exp!( PG::LieGroup{𝔽,Op,M}, h, g, X, t::Number=1 ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} diff --git a/test/groups/test_power_group.jl b/test/groups/test_power_group.jl index aad3358e..587eb112 100644 --- a/test/groups/test_power_group.jl +++ b/test/groups/test_power_group.jl @@ -27,11 +27,11 @@ using LieGroupsTestSuite :Rng => Random.MersenneTwister(), :Functions => [ compose, - # conjugate, - # diff_conjugate, - # diff_inv, - # diff_left_compose, - # diff_right_compose, + conjugate, + diff_conjugate, + diff_inv, + diff_left_compose, + diff_right_compose, exp, # hat, inv, From 238e2ffaa5b23221079cc37228816c5a44efec05 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Mon, 25 Nov 2024 09:19:40 +0100 Subject: [PATCH 23/43] Documentation update to specify changes. --- NEWS.md | 3 ++- docs/src/tutorials/transition.md | 3 +++ docs/styles/config/vocabularies/LieGroups/accept.txt | 3 ++- src/groups/power_group.jl | 6 +----- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/NEWS.md b/NEWS.md index 766681bd..d4a8af06 100644 --- a/NEWS.md +++ b/NEWS.md @@ -18,6 +18,7 @@ Everything denoted by β€œformerly” refers to the previous name in [`Manifolds. * `LeftSemidirectProductLieGroup` (formerly `SemidirectProductGroup`) * `⋉` (alias for `LeftSemidirectProductGroupOperation` when a `default_left_action(G,H)` is defined for the two groups) * `PowerLieGroup` (formerly `PowerGroup`) + * `PowerGroupOperation` to internally avoid ambiguities. Since the constructor always expects a Lie group, this is only necessary internally * `ProductLieGroup` (formerly `ProductGroup`) * `RightSemidirectProductLieGroup` * `⋉` (alias for `RightSemidirectProductGroupOperation` when a `default_right_action(G,H)` is defined for the two groups) @@ -26,7 +27,7 @@ Everything denoted by β€œformerly” refers to the previous name in [`Manifolds. * `MultiplicationGroupOperation` (formerly `MultiplicationOperation`) * `PowerGroupOperation` (formerly the Lie group was stored inside a power manifold) * `ProductGroupOperation` (formerly the Lie groups were stored inside a product manifold) - * `LeftSemidirectProductGroupOperation` (this was formerly only implictly stored in the `SemidirectProductGroup`) + * `LeftSemidirectProductGroupOperation` (this was formerly only implicitly stored in the `SemidirectProductGroup`) * `RightSemidirectProductGroupOperation` * `AbstractGroupActionType` with its 2 specific (new) abstract subtypes * `AbstractLeftGroupActionType` diff --git a/docs/src/tutorials/transition.md b/docs/src/tutorials/transition.md index e0d34612..134b546c 100644 --- a/docs/src/tutorials/transition.md +++ b/docs/src/tutorials/transition.md @@ -27,6 +27,9 @@ The list is alphabetical, but first lists types, then functions | `LeftBackwardAction` | [`InverseRightGroupOperationAction`](@ref) | note that this is now also aa [`AbstractLeftGroupActionType`](@ref) | | | [`LieAlgebra`](@ref)`(G)` | new alias to emphasize its manifold- and vector structure as well as for a few dispatch methods. | | `GroupManifold(M, op)` | [`LieGroup`](@ref)`(M, op)` | | +| `PowerGroup(M)` | [`PowerLieGroup`](@ref)`(G,n)` | The main change is, that the constructor now requires a Lie group to build the power Lie group; This also allows for `G^n`. The other two former constructors for nested and nested-replacing are no longer necessary. `PowerLieGroup` behaves exactly the same as [`PowerManifold`](@extref `ManifoldsBase.PowerManifold`). | +| `ProductGroup(M)` | [`ProductLieGroup`](@ref)`(G, H)` | The main change is, that the constructor now requires two Lie groups to build their product. This also allows for the short hand `GΓ—H` to generate this product. | +| `SemidirectProductGroup(G, H, a)` | [`LeftSemidirectProductLieGroup`](@ref)`(M1, M2, a)` | While this staid the same, there is now also the [`default_left_action`](@ref)`(G,H)`. When this agrees with `a` you can use the short hand `G⋉H` to generate this semidirect product. Analogously there now also exists the [`RightSemidirectProductLieGroup`](@ref)`(G,H)` with[`default_left_action`](@ref)`(G,H)` that allows for the short cut `Gβ‹ŠH` | | `RightForwardAction` | [`InverseLeftGroupOperationAction`](@ref) | note that this is an [`AbstractRightGroupActionType`](@ref) | | `adjoint` | [`adjoint`](@ref) | now implemented with a default, when you provide [`diff_conjugate!`](@ref). | `apply_diff` | [`diff_apply`](@ref) | modifiers (diff) come first, consistent with [`ManifoldsDiff.jl`](https://juliamanifolds.github.io/ManifoldDiff.jl/stable/) | diff --git a/docs/styles/config/vocabularies/LieGroups/accept.txt b/docs/styles/config/vocabularies/LieGroups/accept.txt index 0224dd2f..a670565e 100644 --- a/docs/styles/config/vocabularies/LieGroups/accept.txt +++ b/docs/styles/config/vocabularies/LieGroups/accept.txt @@ -4,4 +4,5 @@ Lie algebra Lie algebras Lie group Lie groups -Riemannian \ No newline at end of file +Riemannian +semidirect \ No newline at end of file diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index ea02fde2..3702c2fd 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -281,8 +281,4 @@ function Base.show( L = LieGroup(PM.manifold, POp.op) size = Manifolds.get_parameter(G.manifold.size) return print(io, "PowerLieGroup($L, $(join(size, ", ")))") -end - -function Base.show(io::IO, POp::PowerGroupOperation) - return print(io, "PowerGroupOperation($(POp.op))") -end +end \ No newline at end of file From 597281fa812ac853a5c9764538aaef5d2b675603 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Mon, 25 Nov 2024 09:21:45 +0100 Subject: [PATCH 24/43] runs format. --- src/groups/power_group.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index 3702c2fd..a38bb11c 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -281,4 +281,4 @@ function Base.show( L = LieGroup(PM.manifold, POp.op) size = Manifolds.get_parameter(G.manifold.size) return print(io, "PowerLieGroup($L, $(join(size, ", ")))") -end \ No newline at end of file +end From 1b8e5ee22c50b2324b3bfcdba8ca24a38b435c6f Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Mon, 25 Nov 2024 09:33:56 +0100 Subject: [PATCH 25/43] Fix a typo. --- docs/src/tutorials/transition.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/tutorials/transition.md b/docs/src/tutorials/transition.md index 134b546c..9269b8d7 100644 --- a/docs/src/tutorials/transition.md +++ b/docs/src/tutorials/transition.md @@ -29,7 +29,7 @@ The list is alphabetical, but first lists types, then functions | `GroupManifold(M, op)` | [`LieGroup`](@ref)`(M, op)` | | | `PowerGroup(M)` | [`PowerLieGroup`](@ref)`(G,n)` | The main change is, that the constructor now requires a Lie group to build the power Lie group; This also allows for `G^n`. The other two former constructors for nested and nested-replacing are no longer necessary. `PowerLieGroup` behaves exactly the same as [`PowerManifold`](@extref `ManifoldsBase.PowerManifold`). | | `ProductGroup(M)` | [`ProductLieGroup`](@ref)`(G, H)` | The main change is, that the constructor now requires two Lie groups to build their product. This also allows for the short hand `GΓ—H` to generate this product. | -| `SemidirectProductGroup(G, H, a)` | [`LeftSemidirectProductLieGroup`](@ref)`(M1, M2, a)` | While this staid the same, there is now also the [`default_left_action`](@ref)`(G,H)`. When this agrees with `a` you can use the short hand `G⋉H` to generate this semidirect product. Analogously there now also exists the [`RightSemidirectProductLieGroup`](@ref)`(G,H)` with[`default_left_action`](@ref)`(G,H)` that allows for the short cut `Gβ‹ŠH` | +| `SemidirectProductGroup(G, H, a)` | [`LeftSemidirectProductLieGroup`](@ref)`(G, H, a)` | While this staid the same, there is now also the [`default_left_action`](@ref)`(G,H)`. When this agrees with `a` you can use the short hand `G⋉H` to generate this semidirect product. Analogously there now also exists the [`RightSemidirectProductLieGroup`](@ref)`(G,H)` with[`default_left_action`](@ref)`(G,H)` that allows for the short cut `Gβ‹ŠH` | | `RightForwardAction` | [`InverseLeftGroupOperationAction`](@ref) | note that this is an [`AbstractRightGroupActionType`](@ref) | | `adjoint` | [`adjoint`](@ref) | now implemented with a default, when you provide [`diff_conjugate!`](@ref). | `apply_diff` | [`diff_apply`](@ref) | modifiers (diff) come first, consistent with [`ManifoldsDiff.jl`](https://juliamanifolds.github.io/ManifoldDiff.jl/stable/) | From 0680095a34fce93f58a29ab062599e2ebe821033 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Mon, 25 Nov 2024 18:52:50 +0100 Subject: [PATCH 26/43] starts product manifolds with an RecursiveArrayToolsExtension --- Project.toml | 7 ++++ ext/LieGroupsRecursiveArrayToolsExt.jl | 15 +++++++ src/groups/product_group.jl | 54 ++++++++++++++++++++++++++ test/groups/test_product_group.jl | 18 +++++---- 4 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 ext/LieGroupsRecursiveArrayToolsExt.jl diff --git a/Project.toml b/Project.toml index 95840f20..932911b2 100644 --- a/Project.toml +++ b/Project.toml @@ -9,11 +9,18 @@ Manifolds = "1cead3c2-87b3-11e9-0ccd-23c62b72b94e" ManifoldsBase = "3362f125-f0bb-47a3-aa74-596ffd7ef2fb" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +[weakdeps] +RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" + +[extensions] +LieGroupsRecursiveArrayToolsExt = "RecursiveArrayTools" + [compat] Aqua = "0.8" LinearAlgebra = "1.6" Manifolds = "0.10.5" ManifoldsBase = "0.15.20" +RecursiveArrayTools = "2, 3" Random = "1.6" Test = "1.6" julia = "1.6" diff --git a/ext/LieGroupsRecursiveArrayToolsExt.jl b/ext/LieGroupsRecursiveArrayToolsExt.jl new file mode 100644 index 00000000..3ff554d8 --- /dev/null +++ b/ext/LieGroupsRecursiveArrayToolsExt.jl @@ -0,0 +1,15 @@ +module LieGroupsRecursiveArrayToolsExt + +using LieGroups, ManifoldsBase, RecursiveArrayTools + +using LieGroups: identity_element, LieGroup + +function ManifoldsBase.allocate_result( + G::LieGroup{𝔽,Op,M}, ::typeof(identity_element) +) where {𝔽,Op,<:ManifoldsBase.ProductManifold} + M = base_manifold(G) + Ls = LieGroup.(M.manifolds, G.op.operations) + ps = ManifoldsBase.allocate_result.(Ls, Ref(identity_element)) + return ArrayPartition(ps...) +end +end diff --git a/src/groups/product_group.jl b/src/groups/product_group.jl index 5ded7457..0cbd440d 100644 --- a/src/groups/product_group.jl +++ b/src/groups/product_group.jl @@ -58,6 +58,48 @@ function ProductLieGroup(G::LieGroup, H::LieGroup) return LieGroup(G.manifold Γ— H.manifold, G.op Γ— H.op) end +function _compose!( + PrG::LieGroup{𝔽,Op,M}, k, g, h +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + map( + compose!, + LieGroup.(PrG.manifold.manifolds, PrG.op.operations), + submanifold_components(PrG.manifold, k), + submanifold_components(PrG.manifold, g), + submanifold_components(PrG.manifold, h), + ) + return k +end + +function ManifoldsBase.check_size( + PrG::LieGroup{𝔽,Op,M}, g +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + return ManifoldsBase.check_size(PrG.manifold, g) +end +function ManifoldsBase.check_size( + ::LieGroup{𝔽,Op,M}, ::Identity +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + return nothing +end +function ManifoldsBase.check_size( + PrG::LieGroup{𝔽,Op,M}, g, X +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + return ManifoldsBase.check_size(PrG.manifold, g, X) +end + +function conjugate!( + PrG::LieGroup{𝔽,Op,M}, k, g, h +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + map( + conjugate, + LieGroup.(PrG.manifold.manifolds, PrG.op.operations), + submanifold_components(PrG.manifold, k), + submanifold_components(PrG.manifold, g), + submanifold_components(PrG.manifold, h), + ) + return k +end + @doc raw""" cross(G, H) G Γ— H @@ -75,6 +117,18 @@ function LinearAlgebra.cross(G::LieGroup, H::LieGroup) return ProductLieGroup(G, H) end +function inv!( + PrG::LieGroup{𝔽,Op,M}, h, g +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + map( + inv!, + LieGroup.(PrG.manifold.manifolds, PrG.op.operations), + submanifold_components(M, h), + submanifold_components(M, g), + ) + return h +end + function Base.show( io::IO, G::LieGroup{𝔽,<:ProductGroupOperation,<:ManifoldsBase.ProductManifold} ) where {𝔽} diff --git a/test/groups/test_product_group.jl b/test/groups/test_product_group.jl index 0040036e..2a6d4a38 100644 --- a/test/groups/test_product_group.jl +++ b/test/groups/test_product_group.jl @@ -1,20 +1,21 @@ -using LieGroups, Test, ManifoldsBase +using LieGroups, Test, ManifoldsBase, RecursiveArrayTools s = joinpath(@__DIR__, "..", "LieGroupsTestSuite.jl") !(s in LOAD_PATH) && (push!(LOAD_PATH, s)) using LieGroupsTestSuite @testset "Generic product Lie group" begin - M = LieGroupsTestSuite.DummyManifold() - op = LieGroupsTestSuite.DummyOperation() - G = LieGroup(M, op) - G2 = G Γ— G + G = TranslationGroup(2) Γ— TranslationGroup(2) + g, h = ArrayPartition([1.0, 0.0], [0.0, 3.0]), ArrayPartition([0.0, 1.0], [2.0, 0.0]) + X, Y = ArrayPartition([0.0, 0.1], [0.2, 0.0]), ArrayPartition([0.1, 0.2], [0.0, 0.3]) properties = Dict( :Name => "The Product Manifold", # :Rng => Random.MersenneTwister(), + :Points => [g, h], + :Vectors => [X, Y], :Functions => [ - # compose, + compose, # conjugate, # diff_conjugate, # diff_inv, @@ -34,11 +35,12 @@ using LieGroupsTestSuite ], ) expectations = Dict( - :repr => "ProductLieGroup(LieGroupsTestSuite.DummyManifold() Γ— LieGroupsTestSuite.DummyManifold(), LieGroupsTestSuite.DummyOperation() Γ— LieGroupsTestSuite.DummyOperation())", + :repr => "ProductLieGroup(Euclidean(2; field=ℝ) Γ— Euclidean(2; field=ℝ), AdditionGroupOperation() Γ— AdditionGroupOperation())", ) - test_lie_group(G2, properties, expectations) + test_lie_group(G, properties, expectations) @testset "Product Operation generators" begin + op = LieGroupsTestSuite.DummyOperation() op2 = LieGroupsTestSuite.DummySecondOperation() O1 = op Γ— op2 O2 = op2 Γ— op From 459d526f5391ab19b1924e272ba96da1e91b0d9e Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Mon, 25 Nov 2024 21:01:46 +0100 Subject: [PATCH 27/43] Remove extension again, maybe not needed, implement first product functions. --- Project.toml | 9 +-- ext/LieGroupsRecursiveArrayToolsExt.jl | 15 ----- src/groups/power_group.jl | 86 +++++++++++++------------- src/groups/product_group.jl | 43 ++++++++++--- src/interface.jl | 3 +- test/groups/test_product_group.jl | 4 +- 6 files changed, 84 insertions(+), 76 deletions(-) delete mode 100644 ext/LieGroupsRecursiveArrayToolsExt.jl diff --git a/Project.toml b/Project.toml index 932911b2..1c05cfed 100644 --- a/Project.toml +++ b/Project.toml @@ -9,12 +9,6 @@ Manifolds = "1cead3c2-87b3-11e9-0ccd-23c62b72b94e" ManifoldsBase = "3362f125-f0bb-47a3-aa74-596ffd7ef2fb" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" -[weakdeps] -RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" - -[extensions] -LieGroupsRecursiveArrayToolsExt = "RecursiveArrayTools" - [compat] Aqua = "0.8" LinearAlgebra = "1.6" @@ -28,7 +22,8 @@ julia = "1.6" [extras] Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" Manifolds = "1cead3c2-87b3-11e9-0ccd-23c62b72b94e" +RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Test", "Aqua", "Manifolds"] +test = ["Test", "Aqua", "Manifolds", "RecursiveArrayTools"] diff --git a/ext/LieGroupsRecursiveArrayToolsExt.jl b/ext/LieGroupsRecursiveArrayToolsExt.jl deleted file mode 100644 index 3ff554d8..00000000 --- a/ext/LieGroupsRecursiveArrayToolsExt.jl +++ /dev/null @@ -1,15 +0,0 @@ -module LieGroupsRecursiveArrayToolsExt - -using LieGroups, ManifoldsBase, RecursiveArrayTools - -using LieGroups: identity_element, LieGroup - -function ManifoldsBase.allocate_result( - G::LieGroup{𝔽,Op,M}, ::typeof(identity_element) -) where {𝔽,Op,<:ManifoldsBase.ProductManifold} - M = base_manifold(G) - Ls = LieGroup.(M.manifolds, G.op.operations) - ps = ManifoldsBase.allocate_result.(Ls, Ref(identity_element)) - return ArrayPartition(ps...) -end -end diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index a38bb11c..7e5f170c 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -39,11 +39,11 @@ end Base.:^(G::LieGroup, n...) = PowerLieGroup(G, n...) function _compose!( - PG::LieGroup{𝔽,Op,M}, k, g, h + PoG::LieGroup{𝔽,Op,M}, k, g, h ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} - PM = PG.manifold + PM = PoG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op.op) + G = LieGroup(PM.manifold, PoG.op.op) for i in ManifoldsBase.get_iterator(PM) compose!( G, @@ -56,9 +56,9 @@ function _compose!( end function ManifoldsBase.check_size( - PG::LieGroup{𝔽,Op,M}, g + PoG::LieGroup{𝔽,Op,M}, g ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} - return ManifoldsBase.check_size(PG.manifold, g) + return ManifoldsBase.check_size(PoG.manifold, g) end function ManifoldsBase.check_size( ::LieGroup{𝔽,Op,M}, ::Identity @@ -66,17 +66,17 @@ function ManifoldsBase.check_size( return nothing end function ManifoldsBase.check_size( - PG::LieGroup{𝔽,Op,M}, g, X + PoG::LieGroup{𝔽,Op,M}, g, X ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} - return ManifoldsBase.check_size(PG.manifold, g, X) + return ManifoldsBase.check_size(PoG.manifold, g, X) end function conjugate!( - PG::LieGroup{𝔽,Op,M}, h, g, k + PoG::LieGroup{𝔽,Op,M}, h, g, k ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} - PM = PG.manifold + PM = PoG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op.op) + G = LieGroup(PM.manifold, PoG.op.op) for i in ManifoldsBase.get_iterator(PM) conjugate!( G, @@ -89,11 +89,11 @@ function conjugate!( end function diff_conjugate!( - PG::LieGroup{𝔽,Op,M}, Y, g, h, X + PoG::LieGroup{𝔽,Op,M}, Y, g, h, X ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} - PM = PG.manifold + PM = PoG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op.op) + G = LieGroup(PM.manifold, PoG.op.op) for i in ManifoldsBase.get_iterator(PM) diff_conjugate!( G, @@ -107,11 +107,11 @@ function diff_conjugate!( end function diff_inv!( - PG::LieGroup{𝔽,Op,M}, Y, g, X + PoG::LieGroup{𝔽,Op,M}, Y, g, X ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} - PM = PG.manifold + PM = PoG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op.op) + G = LieGroup(PM.manifold, PoG.op.op) for i in ManifoldsBase.get_iterator(PM) diff_inv!( G, @@ -124,11 +124,11 @@ function diff_inv!( end function diff_left_compose!( - PG::LieGroup{𝔽,Op,M}, Y, g, h, X + PoG::LieGroup{𝔽,Op,M}, Y, g, h, X ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} - PM = PG.manifold + PM = PoG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op.op) + G = LieGroup(PM.manifold, PoG.op.op) for i in ManifoldsBase.get_iterator(PM) diff_left_compose!( G, @@ -142,11 +142,11 @@ function diff_left_compose!( end function diff_right_compose!( - PG::LieGroup{𝔽,Op,M}, Y, g, h, X + PoG::LieGroup{𝔽,Op,M}, Y, g, h, X ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} - PM = PG.manifold + PM = PoG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op.op) + G = LieGroup(PM.manifold, PoG.op.op) for i in ManifoldsBase.get_iterator(PM) diff_right_compose!( G, @@ -160,11 +160,11 @@ function diff_right_compose!( end function ManifoldsBase.exp!( - PG::LieGroup{𝔽,Op,M}, h, g, X, t::Number=1 + PoG::LieGroup{𝔽,Op,M}, h, g, X, t::Number=1 ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} - PM = PG.manifold + PM = PoG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op.op) + G = LieGroup(PM.manifold, PoG.op.op) for i in ManifoldsBase.get_iterator(PM) exp!( G, @@ -177,11 +177,11 @@ function ManifoldsBase.exp!( return h end function ManifoldsBase.exp!( - PG::LieGroup{𝔽,Op,M}, h, ::Identity{Op}, X, t::Number=1 + PoG::LieGroup{𝔽,Op,M}, h, ::Identity{Op}, X, t::Number=1 ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} - PM = PG.manifold + PM = PoG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op.op) + G = LieGroup(PM.manifold, PoG.op.op) e_g = Identity(G) for i in ManifoldsBase.get_iterator(PM) exp!( @@ -196,11 +196,11 @@ function ManifoldsBase.exp!( end function identity_element!( - PG::LieGroup{𝔽,Op,M}, e + PoG::LieGroup{𝔽,Op,M}, e ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} - PM = PG.manifold + PM = PoG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op.op) + G = LieGroup(PM.manifold, PoG.op.op) for i in ManifoldsBase.get_iterator(PM) identity_element!(G, ManifoldsBase._write(PM, rep_size, e, i)) end @@ -208,11 +208,11 @@ function identity_element!( end function inv!( - PG::LieGroup{𝔽,Op,M}, h, g + PoG::LieGroup{𝔽,Op,M}, h, g ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} - PM = PG.manifold + PM = PoG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op.op) + G = LieGroup(PM.manifold, PoG.op.op) for i in ManifoldsBase.get_iterator(PM) inv!( G, @@ -223,11 +223,11 @@ function inv!( return h end function inv!( - PG::LieGroup{𝔽,Op,M}, h, ::Identity{Op} + PoG::LieGroup{𝔽,Op,M}, h, ::Identity{Op} ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} - PM = PG.manifold + PM = PoG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op.op) + G = LieGroup(PM.manifold, PoG.op.op) e_g = Identity(G.op) for i in ManifoldsBase.get_iterator(PM) inv!(G, ManifoldsBase._write(PM, rep_size, h, i), e_g) @@ -241,11 +241,11 @@ function inv!( end function ManifoldsBase.log!( - PG::LieGroup{𝔽,Op,M}, X, g + PoG::LieGroup{𝔽,Op,M}, X, g ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} - PM = PG.manifold + PM = PoG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op.op) + G = LieGroup(PM.manifold, PoG.op.op) for i in ManifoldsBase.get_iterator(PM) log!( G, @@ -256,11 +256,11 @@ function ManifoldsBase.log!( return X end function ManifoldsBase.log!( - PG::LieGroup{𝔽,Op,M}, X, ::Identity{Op}, g + PoG::LieGroup{𝔽,Op,M}, X, ::Identity{Op}, g ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} - PM = PG.manifold + PM = PoG.manifold rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PG.op.op) + G = LieGroup(PM.manifold, PoG.op.op) e_g = Identity(G.op) for i in ManifoldsBase.get_iterator(PM) log!( diff --git a/src/groups/product_group.jl b/src/groups/product_group.jl index 0cbd440d..8f37f0bc 100644 --- a/src/groups/product_group.jl +++ b/src/groups/product_group.jl @@ -90,12 +90,13 @@ end function conjugate!( PrG::LieGroup{𝔽,Op,M}, k, g, h ) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + PrM = PrG.manifold map( - conjugate, - LieGroup.(PrG.manifold.manifolds, PrG.op.operations), - submanifold_components(PrG.manifold, k), - submanifold_components(PrG.manifold, g), - submanifold_components(PrG.manifold, h), + conjugate!, + LieGroup.(PrM.manifolds, PrG.op.operations), + submanifold_components(PrM, k), + submanifold_components(PrM, g), + submanifold_components(PrM, h), ) return k end @@ -117,14 +118,40 @@ function LinearAlgebra.cross(G::LieGroup, H::LieGroup) return ProductLieGroup(G, H) end +function identity_element!( + PrG::LieGroup{𝔽,Op,M}, e +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + PrM = PrG.manifold + map( + identity_element!, + LieGroup.(PrM.manifolds, PrG.op.operations), + submanifold_components(PrG, e), + ) + return e +end + function inv!( PrG::LieGroup{𝔽,Op,M}, h, g ) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + PrM = PrG.manifold map( inv!, - LieGroup.(PrG.manifold.manifolds, PrG.op.operations), - submanifold_components(M, h), - submanifold_components(M, g), + LieGroup.(PrM.manifolds, PrG.op.operations), + submanifold_components(PrM, h), + submanifold_components(PrM, g), + ) + return h +end + +function inv!( + PrG::LieGroup{𝔽,Op,M}, h, ::Identity{Op} +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + PrM = PrG.manifold + map( + inv!, + LieGroup.(PrM.manifolds, PrG.op.operations), + submanifold_components(PrM, h), + Identity.(PrG.op.operations), ) return h end diff --git a/src/interface.jl b/src/interface.jl index a0937d1c..fb3ed1dc 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -880,5 +880,6 @@ end function ManifoldsBase.allocate_result( G::LieGroup, f::Union{typeof(rand),typeof(identity_element)} ) - return ManifoldsBase.allocate_result(G.manifold, f) + # both get a type allocated like rand + return ManifoldsBase.allocate_result(G.manifold, rand) end diff --git a/test/groups/test_product_group.jl b/test/groups/test_product_group.jl index 2a6d4a38..1648623b 100644 --- a/test/groups/test_product_group.jl +++ b/test/groups/test_product_group.jl @@ -16,14 +16,14 @@ using LieGroupsTestSuite :Vectors => [X, Y], :Functions => [ compose, - # conjugate, + conjugate, # diff_conjugate, # diff_inv, # diff_left_compose, # diff_right_compose, # exp, # hat, - # inv, + inv, # inv_left_compose, # inv_right_compose, # is_identity, From 7eec68f466bf162cfd9af1e9e86d0ff3427197ed Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Wed, 27 Nov 2024 11:42:23 +0100 Subject: [PATCH 28/43] Continue with a few more functions. --- src/groups/power_group.jl | 16 +---- src/groups/product_group.jl | 108 ++++++++++++++++++++++++++++-- test/groups/test_product_group.jl | 24 +++---- 3 files changed, 116 insertions(+), 32 deletions(-) diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index 7e5f170c..e69e3a65 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -176,6 +176,7 @@ function ManifoldsBase.exp!( end return h end + function ManifoldsBase.exp!( PoG::LieGroup{𝔽,Op,M}, h, ::Identity{Op}, X, t::Number=1 ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} @@ -240,21 +241,6 @@ function inv!( return h end -function ManifoldsBase.log!( - PoG::LieGroup{𝔽,Op,M}, X, g -) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} - PM = PoG.manifold - rep_size = representation_size(PM) - G = LieGroup(PM.manifold, PoG.op.op) - for i in ManifoldsBase.get_iterator(PM) - log!( - G, - ManifoldsBase._write(PM, rep_size, X, i), - ManifoldsBase._read(PM, rep_size, g, i), - ) - end - return X -end function ManifoldsBase.log!( PoG::LieGroup{𝔽,Op,M}, X, ::Identity{Op}, g ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} diff --git a/src/groups/product_group.jl b/src/groups/product_group.jl index 8f37f0bc..d4639bfd 100644 --- a/src/groups/product_group.jl +++ b/src/groups/product_group.jl @@ -118,6 +118,65 @@ function LinearAlgebra.cross(G::LieGroup, H::LieGroup) return ProductLieGroup(G, H) end +function diff_conjugate!( + PrG::LieGroup{𝔽,Op,M}, Y, g, h, X +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + PrM = PrG.manifold + map( + diff_conjugate!, + LieGroup.(PrM.manifolds, PrG.op.operations), + submanifold_components(PrG, Y), + submanifold_components(PrG, g), + submanifold_components(PrG, h), + submanifold_components(PrG, X), + ) + return Y +end + +function diff_inv!( + PrG::LieGroup{𝔽,Op,M}, Y, g, X +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + PrM = PrG.manifold + map( + diff_inv!, + LieGroup.(PrM.manifolds, PrG.op.operations), + submanifold_components(PrG, Y), + submanifold_components(PrG, g), + submanifold_components(PrG, X), + ) + return Y +end + +function diff_left_compose!( + PrG::LieGroup{𝔽,Op,M}, Y, g, h, X +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + PrM = PrG.manifold + map( + diff_left_compose!, + LieGroup.(PrM.manifolds, PrG.op.operations), + submanifold_components(PrG, Y), + submanifold_components(PrG, g), + submanifold_components(PrG, h), + submanifold_components(PrG, X), + ) + return Y +end + +function diff_right_compose!( + PrG::LieGroup{𝔽,Op,M}, Y, g, h, X +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + PrM = PrG.manifold + map( + diff_right_compose!, + LieGroup.(PrM.manifolds, PrG.op.operations), + submanifold_components(PrG, Y), + submanifold_components(PrG, g), + submanifold_components(PrG, h), + submanifold_components(PrG, X), + ) + return Y +end + function identity_element!( PrG::LieGroup{𝔽,Op,M}, e ) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} @@ -130,6 +189,32 @@ function identity_element!( return e end +function ManifoldsBase.exp!( + PrG::LieGroup{𝔽,Op,M}, h, ::Identity{Op}, X, t::Number=1 +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + PrM = PrG.manifold + map( + (M, h, e, X) -> exp!(M, h, e, X, t), # introduce a function with β€œhard coded” t + LieGroup.(PrM.manifolds, PrG.op.operations), + submanifold_components(PrM, h), + Identity.(PrG.op.operations), + submanifold_components(PrM, X), + ) + return h +end + +function identity_element!( + PrG::LieGroup{𝔽,Op,M}, e +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + PrM = PrG.manifold + map( + identity_element!, + LieGroup.(PrM.manifolds, PrG.op.operations), + submanifold_components(PrM, e), + ) + return e +end + function inv!( PrG::LieGroup{𝔽,Op,M}, h, g ) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} @@ -142,7 +227,6 @@ function inv!( ) return h end - function inv!( PrG::LieGroup{𝔽,Op,M}, h, ::Identity{Op} ) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} @@ -156,10 +240,24 @@ function inv!( return h end +function ManifoldsBase.log!( + PrG::LieGroup{𝔽,Op,M}, X, ::Identity{Op}, g +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + PrM = PrG.manifold + map( + log!, + LieGroup.(PrM.manifolds, PrG.op.operations), + submanifold_components(PrM, X), + Identity.(PrG.op.operations), + submanifold_components(PrM, g), + ) + return X +end + function Base.show( - io::IO, G::LieGroup{𝔽,<:ProductGroupOperation,<:ManifoldsBase.ProductManifold} -) where {𝔽} - M = G.manifold.manifolds + io::IO, G::LieGroup{𝔽,Op,M} +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + PrM = G.manifold.manifolds ops = G.op.operations - return print(io, "ProductLieGroup($(join(M, " Γ— ")), $(join(ops, " Γ— ")))") + return print(io, "ProductLieGroup($(join(PrM, " Γ— ")), $(join(ops, " Γ— ")))") end diff --git a/test/groups/test_product_group.jl b/test/groups/test_product_group.jl index 1648623b..fad20e1e 100644 --- a/test/groups/test_product_group.jl +++ b/test/groups/test_product_group.jl @@ -1,4 +1,4 @@ -using LieGroups, Test, ManifoldsBase, RecursiveArrayTools +using LieGroups, Test, ManifoldsBase, Random, RecursiveArrayTools s = joinpath(@__DIR__, "..", "LieGroupsTestSuite.jl") !(s in LOAD_PATH) && (push!(LOAD_PATH, s)) @@ -11,25 +11,25 @@ using LieGroupsTestSuite properties = Dict( :Name => "The Product Manifold", - # :Rng => Random.MersenneTwister(), + :Rng => Random.MersenneTwister(), :Points => [g, h], :Vectors => [X, Y], :Functions => [ compose, conjugate, - # diff_conjugate, - # diff_inv, - # diff_left_compose, - # diff_right_compose, - # exp, + diff_conjugate, + diff_inv, + diff_left_compose, + diff_right_compose, + exp, # hat, inv, - # inv_left_compose, - # inv_right_compose, - # is_identity, + inv_left_compose, + inv_right_compose, + is_identity, # lie_bracket, - # log, - #rand, + log, + rand, show, #vee, ], From 6c19040ce54a3174f6494a6e49d173db59af7215 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Wed, 27 Nov 2024 11:45:05 +0100 Subject: [PATCH 29/43] remove duplicate code. --- src/groups/product_group.jl | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/groups/product_group.jl b/src/groups/product_group.jl index d4639bfd..c8733e18 100644 --- a/src/groups/product_group.jl +++ b/src/groups/product_group.jl @@ -177,18 +177,6 @@ function diff_right_compose!( return Y end -function identity_element!( - PrG::LieGroup{𝔽,Op,M}, e -) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} - PrM = PrG.manifold - map( - identity_element!, - LieGroup.(PrM.manifolds, PrG.op.operations), - submanifold_components(PrG, e), - ) - return e -end - function ManifoldsBase.exp!( PrG::LieGroup{𝔽,Op,M}, h, ::Identity{Op}, X, t::Number=1 ) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} From 9e0fde35e2d0ccfe0a0655af1205cb42b7c9986b Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Wed, 27 Nov 2024 23:06:42 +0100 Subject: [PATCH 30/43] Activate more power tests (Power and product now only miss hat/vee and lie_bracket) --- test/groups/test_power_group.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/groups/test_power_group.jl b/test/groups/test_power_group.jl index 587eb112..ad06e536 100644 --- a/test/groups/test_power_group.jl +++ b/test/groups/test_power_group.jl @@ -35,9 +35,9 @@ using LieGroupsTestSuite exp, # hat, inv, - # inv_left_compose, - # inv_right_compose, - # is_identity, + inv_left_compose, + inv_right_compose, + is_identity, # lie_bracket, log, rand, From bf0b1815b68a978508cc526ee075365b1ce59a68 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Thu, 28 Nov 2024 11:08:25 +0100 Subject: [PATCH 31/43] Implement the last three functions, dispatch for Lie algebra not yet fully working. --- src/groups/power_group.jl | 46 +++++++++++++++++++++++++++++++ src/groups/product_group.jl | 42 ++++++++++++++++++++++++++++ test/groups/test_power_group.jl | 6 ++-- test/groups/test_product_group.jl | 6 ++-- 4 files changed, 94 insertions(+), 6 deletions(-) diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index e69e3a65..d1d7fa68 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -196,6 +196,21 @@ function ManifoldsBase.exp!( return h end +function hat!( + PoG::LieGroup{𝔽,Op,M}, X, c +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} + PM = PoG.manifold + rep_size = representation_size(PM.manifold) + dim = manifold_dimension(PM.manifold) + v_iter = 1 + G = LieGroup(PM.manifold, PoG.op.op) + for i in ManifoldsBase.get_iterator(PM) + hat!(G, ManifoldsBase._write(PM, rep_size, X, i), c[v_iter:(v_iter + dim - 1)]) + v_iter += dim + end + return X +end + function identity_element!( PoG::LieGroup{𝔽,Op,M}, e ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} @@ -241,6 +256,22 @@ function inv!( return h end +function lie_bracket!( + PoA::LieAlgebra{𝔽,<:LieGroup{𝔽,Op,M}}, Z, X, Y +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} + PM = PoA.manifold.manifold + rep_size = representation_size(PM) + 𝔀 = LieAlgebra(LieGroup(PM.manifold, PoA.manifold.op.op)) + for i in ManifoldsBase.get_iterator(PM) + lie_bracket!( + 𝔀, + ManifoldsBase._write(PM, rep_size, Z, i), + ManifoldsBase._read(PM, rep_size, X, i), + ManifoldsBase._read(PM, rep_size, Y, i), + ) + end +end + function ManifoldsBase.log!( PoG::LieGroup{𝔽,Op,M}, X, ::Identity{Op}, g ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} @@ -268,3 +299,18 @@ function Base.show( size = Manifolds.get_parameter(G.manifold.size) return print(io, "PowerLieGroup($L, $(join(size, ", ")))") end + +function vee!( + PoG::LieGroup{𝔽,Op,M}, c, X +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} + PM = PoG.manifold + rep_size = representation_size(PM.manifold) + dim = manifold_dimension(PM.manifold) + G = LieGroup(PM.manifold, PoG.op.op) + v_iter = 1 + for i in ManifoldsBase.get_iterator(PM) + vee!(G, view(c, v_iter:(v_iter + dim - 1)), ManifoldsBase._read(PM, rep_size, X, i)) + v_iter += dim + end + return c +end diff --git a/src/groups/product_group.jl b/src/groups/product_group.jl index c8733e18..0e214429 100644 --- a/src/groups/product_group.jl +++ b/src/groups/product_group.jl @@ -191,6 +191,21 @@ function ManifoldsBase.exp!( return h end +function hat!( + PrG::LieGroup{𝔽,Op,M}, X, c +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + PrM = PrG.manifold + dims = map(manifold_dimension, PrM.manifolds) + @assert length(c) == sum(dims) + dim_ranges = ManifoldsBase._get_dim_ranges(dims) + Prc = map(dr -> (@inbounds view(c, dr)), dim_ranges) + ts = ManifoldsBase.ziptuples(PM.manifolds, submanifold_components(PM, X), Prc) + map(ts) do t + return hat!(t...) + end + return X +end + function identity_element!( PrG::LieGroup{𝔽,Op,M}, e ) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} @@ -228,6 +243,20 @@ function inv!( return h end +function lie_bracket!( + PrA::LieAlgebra{𝔽,<:LieGroup{𝔽,Op,M}}, Z, X, Y +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + PrM = PrA.manifold.manifold + map( + lie_bracket!, + LieAlgebra.(LieGroup.(PrM.manifolds, PrA.op.operations)), + submanifold_components(PrM, Z), + submanifold_components(PrM, X), + submanifold_components(PrM, Y), + ) + return Z +end + function ManifoldsBase.log!( PrG::LieGroup{𝔽,Op,M}, X, ::Identity{Op}, g ) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} @@ -249,3 +278,16 @@ function Base.show( ops = G.op.operations return print(io, "ProductLieGroup($(join(PrM, " Γ— ")), $(join(ops, " Γ— ")))") end + +function vee!( + PrG::LieGroup{𝔽,Op,M}, c, X +) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} + PrM = PrG.manifold + map( + vee!, + LieGroup.(PrM.manifolds, PrG.op.operations), + submanifold_components(PrM, c), + submanifold_components(PrM, X), + ) + return X +end diff --git a/test/groups/test_power_group.jl b/test/groups/test_power_group.jl index ad06e536..250e0258 100644 --- a/test/groups/test_power_group.jl +++ b/test/groups/test_power_group.jl @@ -33,15 +33,15 @@ using LieGroupsTestSuite diff_left_compose, diff_right_compose, exp, - # hat, + hat, inv, inv_left_compose, inv_right_compose, is_identity, - # lie_bracket, + lie_bracket, log, rand, - # vee, + vee, ], ) expectations2 = Dict( diff --git a/test/groups/test_product_group.jl b/test/groups/test_product_group.jl index fad20e1e..1df26aad 100644 --- a/test/groups/test_product_group.jl +++ b/test/groups/test_product_group.jl @@ -22,16 +22,16 @@ using LieGroupsTestSuite diff_left_compose, diff_right_compose, exp, - # hat, + hat, inv, inv_left_compose, inv_right_compose, is_identity, - # lie_bracket, + lie_bracket, log, rand, show, - #vee, + vee, ], ) expectations = Dict( From e6b17decccf64f762c8ce88e7e4a82b6ac19ecef Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Thu, 28 Nov 2024 11:42:39 +0100 Subject: [PATCH 32/43] debug hat/vee. --- src/groups/product_group.jl | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/groups/product_group.jl b/src/groups/product_group.jl index 0e214429..9e1ad1d1 100644 --- a/src/groups/product_group.jl +++ b/src/groups/product_group.jl @@ -199,7 +199,8 @@ function hat!( @assert length(c) == sum(dims) dim_ranges = ManifoldsBase._get_dim_ranges(dims) Prc = map(dr -> (@inbounds view(c, dr)), dim_ranges) - ts = ManifoldsBase.ziptuples(PM.manifolds, submanifold_components(PM, X), Prc) + PrL = LieGroup.(PrM.manifolds, PrG.op.operations) + ts = ManifoldsBase.ziptuples(PrL, submanifold_components(PrM, X), Prc) map(ts) do t return hat!(t...) end @@ -283,11 +284,14 @@ function vee!( PrG::LieGroup{𝔽,Op,M}, c, X ) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} PrM = PrG.manifold - map( - vee!, - LieGroup.(PrM.manifolds, PrG.op.operations), - submanifold_components(PrM, c), - submanifold_components(PrM, X), - ) - return X + dims = map(manifold_dimension, PrM.manifolds) + @assert length(c) == sum(dims) + dim_ranges = ManifoldsBase._get_dim_ranges(dims) + Prc = map(dr -> (@inbounds view(c, dr)), dim_ranges) + PrL = LieGroup.(PrM.manifolds, PrG.op.operations) + ts = ManifoldsBase.ziptuples(PrL, Prc, submanifold_components(PrM, X)) + map(ts) do t + return vee!(t...) + end + return c end From 6fd33ee7c7fa924459de715b76fd1dffa0411dae Mon Sep 17 00:00:00 2001 From: Mateusz Baran Date: Thu, 28 Nov 2024 12:15:22 +0100 Subject: [PATCH 33/43] fix lie_bracket on new groups --- src/groups/power_group.jl | 3 ++- src/groups/product_group.jl | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index d1d7fa68..e82c5799 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -257,7 +257,7 @@ function inv!( end function lie_bracket!( - PoA::LieAlgebra{𝔽,<:LieGroup{𝔽,Op,M}}, Z, X, Y + PoA::LieAlgebra{𝔽,Op,<:LieGroup{𝔽,Op,M}}, Z, X, Y ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} PM = PoA.manifold.manifold rep_size = representation_size(PM) @@ -270,6 +270,7 @@ function lie_bracket!( ManifoldsBase._read(PM, rep_size, Y, i), ) end + return Z end function ManifoldsBase.log!( diff --git a/src/groups/product_group.jl b/src/groups/product_group.jl index 9e1ad1d1..dc3012dd 100644 --- a/src/groups/product_group.jl +++ b/src/groups/product_group.jl @@ -245,12 +245,12 @@ function inv!( end function lie_bracket!( - PrA::LieAlgebra{𝔽,<:LieGroup{𝔽,Op,M}}, Z, X, Y + PrA::LieAlgebra{𝔽,Op,<:LieGroup{𝔽,Op,M}}, Z, X, Y ) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} PrM = PrA.manifold.manifold map( lie_bracket!, - LieAlgebra.(LieGroup.(PrM.manifolds, PrA.op.operations)), + LieAlgebra.(LieGroup.(PrM.manifolds, PrA.manifold.op.operations)), submanifold_components(PrM, Z), submanifold_components(PrM, X), submanifold_components(PrM, Y), From 11ba1257d57d523f68369c677a18ca43dd3bad29 Mon Sep 17 00:00:00 2001 From: Mateusz Baran Date: Thu, 28 Nov 2024 14:36:30 +0100 Subject: [PATCH 34/43] small improvements --- NEWS.md | 2 +- docs/make.jl | 4 ++-- src/groups/power_group.jl | 14 +++++++------- src/groups/product_group.jl | 17 +++++++++-------- src/groups/semidirect_product_group.jl | 8 ++++++-- src/interface.jl | 2 +- 6 files changed, 26 insertions(+), 21 deletions(-) diff --git a/NEWS.md b/NEWS.md index d4a8af06..dfbb49ff 100644 --- a/NEWS.md +++ b/NEWS.md @@ -21,7 +21,7 @@ Everything denoted by β€œformerly” refers to the previous name in [`Manifolds. * `PowerGroupOperation` to internally avoid ambiguities. Since the constructor always expects a Lie group, this is only necessary internally * `ProductLieGroup` (formerly `ProductGroup`) * `RightSemidirectProductLieGroup` - * `⋉` (alias for `RightSemidirectProductGroupOperation` when a `default_right_action(G,H)` is defined for the two groups) + * `β‹Š` (alias for `RightSemidirectProductGroupOperation` when a `default_right_action(G,H)` is defined for the two groups) * `AbstractGroupOperation` as well as its concrete subtypes * `AdditionGroupOperation` (formerly `AdditionOperation`) * `MultiplicationGroupOperation` (formerly `MultiplicationOperation`) diff --git a/docs/make.jl b/docs/make.jl index b2c66e37..36d2a9f8 100755 --- a/docs/make.jl +++ b/docs/make.jl @@ -125,8 +125,8 @@ makedocs(; "Lie groups" => [ "List of Lie groups" => "groups/index.md", "General Linear" => "groups/general_linear.md", - "power group" => "groups/power_group.md", - "product group" => "groups/product_group.md", + "Power group" => "groups/power_group.md", + "Product group" => "groups/product_group.md", "Semidirect product group" => "groups/semidirect_product_group.md", "Translation group" => "groups/translation.md", ], diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index e82c5799..72b8cfe5 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -3,21 +3,21 @@ # Power Lie groups: work element wise @doc """ - PowerGroupOperation{O} <: AbstractGroupOperation + PowerGroupOperation{O<:AbstractGroupOperation} <: AbstractGroupOperation A struct do model a that a certain group operation is applied element-wise on a [`PowerManifold`](@extref `ManifoldsBase.PowerManifold`). # Constructor - PowerGroupOperation(o:O) + PowerGroupOperation(o::AbstractGroupOperation) """ -struct PowerGroupOperation{O} <: AbstractGroupOperation +struct PowerGroupOperation{O<:AbstractGroupOperation} <: AbstractGroupOperation op::O end @doc """ - PowerLieGroup(G::LieGroup, args...; kwargs...) - (L::LueGroup)^(n...) = PowerLieGroup(L, n...) + PowerLieGroup(G::LieGroup, args::Integer...; kwargs...) + (G::LieGroup)^(n) = PowerLieGroup(G, n) Generate the [`LieGroup`](@ref) of the `n`-th power of a Lie group `G` or manifold `M`. If passed a Lie group `G`, the group operation on the [`PowerLieGroup`](@ref) is the same as on `G`, @@ -32,11 +32,11 @@ PowerLieGroup(::AbstractManifold, args...; kwargs...) function PowerLieGroup(G::LieGroup, args...; kwargs...) M = G.manifold - pM = Manifolds.PowerManifold(M, args...; kwargs...) + pM = ManifoldsBase.PowerManifold(M, args...; kwargs...) return LieGroup(pM, PowerGroupOperation(G.op)) end -Base.:^(G::LieGroup, n...) = PowerLieGroup(G, n...) +Base.:^(G::LieGroup, n::Integer) = PowerLieGroup(G, n) function _compose!( PoG::LieGroup{𝔽,Op,M}, k, g, h diff --git a/src/groups/product_group.jl b/src/groups/product_group.jl index dc3012dd..20c83d0e 100644 --- a/src/groups/product_group.jl +++ b/src/groups/product_group.jl @@ -4,17 +4,18 @@ # One for each factor, we define the product operation as acting element wise. """ - ProductGroupOperation{O} <: AbstractGroupOperation + ProductGroupOperation{O<:<:NTuple{N,AbstractGroupOperation} where N} <: AbstractGroupOperation A struct do model a tuple of group operations, one for each factor of a product group, that together forms a new group operation. # Constructor - ProductGroupOperation(o::O...) - Γ—(o::O...) = ProductGroupOperation(o...) + ProductGroupOperation(o::AbstractGroupOperation...) + Γ—(o::AbstractGroupOperation...) = ProductGroupOperation(o...) """ -struct ProductGroupOperation{OTM<:Tuple} <: AbstractGroupOperation +struct ProductGroupOperation{OTM<:NTuple{N,AbstractGroupOperation} where {N}} <: + AbstractGroupOperation operations::OTM end function ProductGroupOperation(operations::AbstractGroupOperation...) @@ -22,13 +23,13 @@ function ProductGroupOperation(operations::AbstractGroupOperation...) end @doc raw""" - cross(O1, O2) + cross(O1::AbstractGroupOperation, O2::AbstractGroupOperation) O1 Γ— O2 O1 Γ— O2 Γ— O3 Γ— ... Return the [`ProductGroupOperation`](@ref) For two [AbstractGroupOperation`](@ref) `O1` and `O2`, where for the case that one of them is a [`ProductGroupOperation`](@ref) itself, -the other is either prepended (if `O1` is a product) or appenden (if `O2` is). +the other is either prepended (if `O1` is a product) or appended (if `O2` is). If both are product operations, they are combined into one, keeping the order of operations. For the case that more than two are concatenated with `Γ—` this is iterated. @@ -102,13 +103,13 @@ function conjugate!( end @doc raw""" - cross(G, H) + cross(G::LieGroup, H::LieGroup) G Γ— H G1 Γ— G2 Γ— G3 Γ— ... Return the [`ProductLieGroup`](@ref) For two [`LieGroups`](@ref) `G` and `H`, where for the case that one of them is a [`ProductLieGroup`](@ref) itself, -the other is either prepended (if `H` is a product) or appenden (if `G` is). +the other is either prepended (if `H` is a product) or appended (if `G` is). If both are product Lie groups, they are combined into one, keeping the order of operations. For the case that more than two are concatenated with `Γ—` this is iterated. diff --git a/src/groups/semidirect_product_group.jl b/src/groups/semidirect_product_group.jl index 08e4d6dc..092f0b44 100644 --- a/src/groups/semidirect_product_group.jl +++ b/src/groups/semidirect_product_group.jl @@ -102,7 +102,9 @@ struct RightSemidirectProductGroupOperation{ end """ - LeftSemidirectProductLieGroup(N::LieGroup, H::LieGroup, action=default_left_action(N,H)) + LeftSemidirectProductLieGroup( + N::LieGroup, H::LieGroup, action::AbstractGroupActionType=default_left_action(N, H) + ) Generate the semidirect product Lie Group ``$(_tex(:Cal, "G")) = N ⋉ H`` for an [`AbstractLeftGroupActionType`](@ref) using the [`LeftSemidirectProductGroupOperation`](@ref) for the group operation definition @@ -120,7 +122,9 @@ function LeftSemidirectProductLieGroup( end """ - RightSemidirectProductLieGroup(N::LieGroup, H::LieGroup, action=default_right_action(N,H)) + RightSemidirectProductLieGroup( + N::LieGroup, H::LieGroup, action::AbstractGroupActionType=default_right_action(N,H) + ) Generate the semidirect product Lie Group ``$(_tex(:Cal, "G")) = N β‹Š H`` for an [`AbstractLeftGroupActionType`](@ref) using the [`RightSemidirectProductGroupOperation`](@ref) for the group operation definition diff --git a/src/interface.jl b/src/interface.jl index fb3ed1dc..31036f64 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -30,7 +30,7 @@ function LieAlgebraOrthogonalBasis(𝔽::ManifoldsBase.AbstractNumbers=ℝ) end """ - LieGroup{𝔽, O<:AbstractGroupOperation, M<:AbstractManifold{𝔽}} <: LieGroup{𝔽,O,M} <: AbstractManifold{𝔽} + LieGroup{𝔽, O<:AbstractGroupOperation, M<:AbstractManifold{𝔽}} <: AbstractManifold{𝔽} Represent a Lie Group ``$(_math(:G))``. From e0006054d573298e3d4b8ef2d75a72994cf389ec Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Thu, 28 Nov 2024 17:25:19 +0100 Subject: [PATCH 35/43] add ain identity test and increase power code cov. --- src/groups/power_group.jl | 2 +- .../LieGroupsTestSuite.jl | 20 ++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index 72b8cfe5..7c1cbd7f 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -61,7 +61,7 @@ function ManifoldsBase.check_size( return ManifoldsBase.check_size(PoG.manifold, g) end function ManifoldsBase.check_size( - ::LieGroup{𝔽,Op,M}, ::Identity + ::LieGroup{𝔽,Op,M}, ::Identity{Op} ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} return nothing end diff --git a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl index ba0ceac9..675d6e5f 100644 --- a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl +++ b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl @@ -594,6 +594,20 @@ function test_inv(G::LieGroup, g; test_mutating::Bool=true, test_identity::Bool= end return nothing end + +""" + test_is_identity(G::LieGroup, g) + +Test that the `Identity` returns that `is_identity` is true and that it is a point +""" +function test_identity(G::LieGroup) + @testset "Identity" begin + e = Identity(G) + @test is_point(G, e) + @test is_identity(G, e) + end + return nothing +end # # # --- L @@ -830,7 +844,11 @@ function test_lie_group(G::LieGroup, properties::Dict, expectations::Dict=Dict() end if (inv in functions) test_inv(G, points[1]; test_mutating=mutating) - end # + end + if (is_identity in functions) + test_identity(G) + end + # # # --- L if (lie_bracket in functions) From 9801cd542f5963a9bd23b40fd806b73d98f0421c Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Thu, 28 Nov 2024 17:43:28 +0100 Subject: [PATCH 36/43] A bit more test coverage. --- src/groups/power_group.jl | 26 ++++++++++++++++++- .../LieGroupsTestSuite.jl | 6 ++++- test/groups/test_power_group.jl | 1 + 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index 7c1cbd7f..37228178 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -65,6 +65,13 @@ function ManifoldsBase.check_size( ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} return nothing end +function ManifoldsBase.check_size( + G::LieGroup{𝔽,Op,M}, e::Identity +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} + return DomainError( + "The Identity $e is not the identity of the group, expected $(Identity(G.op))." + ) +end function ManifoldsBase.check_size( PoG::LieGroup{𝔽,Op,M}, g, X ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} @@ -105,7 +112,24 @@ function diff_conjugate!( end return Y end - +function diff_conjugate!( + PoG::LieGroup{𝔽,Op,M}, Y, g, ::Identity{Op}, X +) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} + PM = PoG.manifold + rep_size = representation_size(PM) + G = LieGroup(PM.manifold, PoG.op.op) + e_g = Identity(G) + for i in ManifoldsBase.get_iterator(PM) + diff_conjugate!( + G, + ManifoldsBase._write(PM, rep_size, Y, i), + ManifoldsBase._read(PM, rep_size, g, i), + e_g, + ManifoldsBase._read(PM, rep_size, X, i), + ) + end + return Y +end function diff_inv!( PoG::LieGroup{𝔽,Op,M}, Y, g, X ) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} diff --git a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl index 675d6e5f..1b1a5315 100644 --- a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl +++ b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl @@ -603,8 +603,12 @@ Test that the `Identity` returns that `is_identity` is true and that it is a poi function test_identity(G::LieGroup) @testset "Identity" begin e = Identity(G) - @test is_point(G, e) + @test is_point(G, e; error=:error) @test is_identity(G, e) + e2 = Identity(DummyOperation) + @test !is_point(G, e2) + @test_throws DomainError !is_point(G, e2; error=:error) + @test !is_identity(G, e2) end return nothing end diff --git a/test/groups/test_power_group.jl b/test/groups/test_power_group.jl index 250e0258..88e35b2a 100644 --- a/test/groups/test_power_group.jl +++ b/test/groups/test_power_group.jl @@ -26,6 +26,7 @@ using LieGroupsTestSuite :Vectors => [X, Y], :Rng => Random.MersenneTwister(), :Functions => [ + adjoint, compose, conjugate, diff_conjugate, From d16f091928f941f30daecbf419bc6551aec7334f Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Thu, 28 Nov 2024 17:48:07 +0100 Subject: [PATCH 37/43] Remove a spurious function definition. --- src/groups/power_group.jl | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index 37228178..74989fc1 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -274,11 +274,6 @@ function inv!( end return h end -function inv!( - ::LieGroup{𝔽,Op,M}, h::Identity{Op}, ::Identity{Op} -) where {𝔽,Op<:PowerGroupOperation,M<:ManifoldsBase.AbstractPowerManifold} - return h -end function lie_bracket!( PoA::LieAlgebra{𝔽,Op,<:LieGroup{𝔽,Op,M}}, Z, X, Y From e52a71156d44f1c87113a44fc97a63b0ce479033 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Fri, 29 Nov 2024 20:42:49 +0100 Subject: [PATCH 38/43] Most of codecov. --- src/groups/semidirect_product_group.jl | 13 ------ .../LieGroupsTestSuite.jl | 40 ++++++++++++++++++- test/actions/test_action_interface.jl | 9 ++++- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/src/groups/semidirect_product_group.jl b/src/groups/semidirect_product_group.jl index 092f0b44..686358aa 100644 --- a/src/groups/semidirect_product_group.jl +++ b/src/groups/semidirect_product_group.jl @@ -162,19 +162,6 @@ where the corresponding [`default_right_action`](@ref)`(L1, L2)` is used. function β‹Š(L1::LieGroup, L2::LieGroup) return RightSemidirectProductLieGroup(L1, L2, default_right_action(L1, L2)) end - -function Base.show(io::IO, LSDOp::LeftSemidirectProductGroupOperation) - return print( - io, - "LeftSemidirectProductGroupOperation($(LSDOp.op1), $(LSDOp.op2), $(LSDOp.action_type))", - ) -end -function Base.show(io::IO, RSDOp::RightSemidirectProductGroupOperation) - return print( - io, - "RightSemidirectProductGroupOperation($(RSDOp.op1), $(RSDOp.op2), $(RSDOp.action_type))", - ) -end function Base.show( io::IO, LSDL::LieGroup{𝔽,<:LeftSemidirectProductGroupOperation,<:ManifoldsBase.ProductManifold}, diff --git a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl index 1b1a5315..e1d6754a 100644 --- a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl +++ b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl @@ -23,7 +23,7 @@ struct DummySecondOperation <: AbstractGroupOperation end struct DummyManifold <: LieGroups.AbstractManifold{LieGroups.ℝ} end struct DummyActionType <: AbstractGroupActionType end const DummyLieGroup = LieGroup{LieGroups.ℝ,DummyOperation,DummyManifold} - +LieGroups.switch(a::DummyActionType) = a # === Test single functions === # # @@ -336,6 +336,32 @@ function test_copyto(G::LieGroup, g) end end +# +# +# --- D +""" + test_diff_conjugate(A::GroupAction, g, p, X; expected=missing) + +Test `diff_conjugate` +""" +function test_diff_conjugate( + G::LieGroup, g, h, X; expected=missing, test_mutating::Bool=true +) + 𝔀 = LieAlgebra(G) + @testset "diff_conjugate" begin + Y1 = diff_conjugate(G, g, h, X) + @test is_point(𝔀, Y1; error=:error) + if test_mutating + Y2 = zero_vector(𝔀) + diff_conjugate!(G, Y2, g, h, X) + @test isapprox(𝔀, Y1, Y2) + end + if !ismissing(expected) + @test isapprox(𝔀, Y1, expected) + end + return nothing + end +end # # # --- E @@ -589,6 +615,11 @@ function test_inv(G::LieGroup, g; test_mutating::Bool=true, test_identity::Bool= e2 = copy(G, g) inv!(G, e2, e) @test is_identity(G, e2) + e3 = copy(G, g) + println(e3) + inv!(G, e3, e) # materialize identity + println(e3) + @test is_identity(G, e3) end end end @@ -779,6 +810,13 @@ function test_lie_group(G::LieGroup, properties::Dict, expectations::Dict=Dict() # # # --- D + if (diff_conjugate in functions) + v = get(expectations, :diff_conjugate, missing) + test_diff_conjugate( + G, points[1], points[2], vectors[1]; expected=v, test_mutating=mutating + ) + end + if (diff_inv in functions) v = get(expectations, :diff_inv, missing) test_diff_inv(G, points[1], vectors[1]; expected=v, test_mutating=mutating) diff --git a/test/actions/test_action_interface.jl b/test/actions/test_action_interface.jl index dee799a4..cf9fd9a1 100644 --- a/test/actions/test_action_interface.jl +++ b/test/actions/test_action_interface.jl @@ -4,4 +4,11 @@ s = joinpath(@__DIR__, "..", "LieGroupsTestSuite.jl") !(s in LOAD_PATH) && (push!(LOAD_PATH, s)) using LieGroupsTestSuite -@testset "Group Action Interface" begin end +@testset "Group Action Interface" begin + M = LieGroupsTestSuite.DummyManifold() + T = LieGroupsTestSuite.DummyActionType() + G = LieGroupsTestSuite.DummyLieGroup(M, LieGroupsTestSuite.DummyOperation()) + a = GroupAction(T, G, M) + @test repr(a) === "GroupAction($T, $G, $M)" + @test switch(T) == T +end From d3ababa2f84a6d102d518c05677d80f2016bc3f4 Mon Sep 17 00:00:00 2001 From: Mateusz Baran Date: Sat, 30 Nov 2024 10:58:39 +0100 Subject: [PATCH 39/43] minor improvements --- src/group_actions/group_action_interface.jl | 5 +++-- src/group_actions/group_operation_action.jl | 2 +- src/groups/power_group.jl | 4 ++-- src/groups/product_group.jl | 20 ++++++++++---------- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/group_actions/group_action_interface.jl b/src/group_actions/group_action_interface.jl index 5654d234..8ff72c04 100644 --- a/src/group_actions/group_action_interface.jl +++ b/src/group_actions/group_action_interface.jl @@ -90,7 +90,8 @@ abstract type AbstractRightGroupActionType <: AbstractGroupActionType end Specify a group action of [`AbstractGroupActionType`](@ref) `T` of a [`LieGroup`](@ref) `G` acting on `M`. -Let ``$(_math(:M))`` be a $(_link(:AbstractManifold)) and ``$(_math(:G))`` be a [`LieGroup`](@ref) woth group operation ``$(_math(:∘))``. +Let ``$(_math(:M))`` be a $(_link(:AbstractManifold)) and ``$(_math(:G))`` be a [`LieGroup`](@ref) +with group operation ``$(_math(:∘))``. A (smooth) action of the group ``$(_math(:G))`` on the manifold ``$(_math(:M))`` is a map @@ -129,7 +130,7 @@ _doc_apply = """ Apply the group action induced by ``g ∈ $(_math(:G))`` to ``p ∈ $(_math(:M))``, where the kind of group action is indicated by the [`AbstractGroupActionType`](@ref) `T`. -This can be perfomed in-place of `q`. +This can be performed in-place of `q`. """ # function apply end diff --git a/src/group_actions/group_operation_action.jl b/src/group_actions/group_operation_action.jl index dbc7af71..a08fe232 100644 --- a/src/group_actions/group_operation_action.jl +++ b/src/group_actions/group_operation_action.jl @@ -16,7 +16,7 @@ struct LeftGroupOperationAction <: AbstractLeftGroupActionType end RightGroupOperationAction <: AbstractRightGroupActionType A type for the [`AbstractLeftGroupActionType`](@ref) when acting on the group itself -gfrom the right +from the right. ```math Οƒ_h(g) = Οƒ(h,g) = g$(_math(:∘))h diff --git a/src/groups/power_group.jl b/src/groups/power_group.jl index 74989fc1..ccdcbb42 100644 --- a/src/groups/power_group.jl +++ b/src/groups/power_group.jl @@ -16,8 +16,8 @@ struct PowerGroupOperation{O<:AbstractGroupOperation} <: AbstractGroupOperation end @doc """ - PowerLieGroup(G::LieGroup, args::Integer...; kwargs...) - (G::LieGroup)^(n) = PowerLieGroup(G, n) + PowerLieGroup(G::LieGroup, args...; kwargs...) + (G::LieGroup)^(n::Integer) = PowerLieGroup(G, n) Generate the [`LieGroup`](@ref) of the `n`-th power of a Lie group `G` or manifold `M`. If passed a Lie group `G`, the group operation on the [`PowerLieGroup`](@ref) is the same as on `G`, diff --git a/src/groups/product_group.jl b/src/groups/product_group.jl index 20c83d0e..a27529a8 100644 --- a/src/groups/product_group.jl +++ b/src/groups/product_group.jl @@ -64,7 +64,7 @@ function _compose!( ) where {𝔽,Op<:ProductGroupOperation,M<:ManifoldsBase.ProductManifold} map( compose!, - LieGroup.(PrG.manifold.manifolds, PrG.op.operations), + map(LieGroup, PrG.manifold.manifolds, PrG.op.operations), submanifold_components(PrG.manifold, k), submanifold_components(PrG.manifold, g), submanifold_components(PrG.manifold, h), @@ -94,7 +94,7 @@ function conjugate!( PrM = PrG.manifold map( conjugate!, - LieGroup.(PrM.manifolds, PrG.op.operations), + map(LieGroup, PrM.manifolds, PrG.op.operations), submanifold_components(PrM, k), submanifold_components(PrM, g), submanifold_components(PrM, h), @@ -184,9 +184,9 @@ function ManifoldsBase.exp!( PrM = PrG.manifold map( (M, h, e, X) -> exp!(M, h, e, X, t), # introduce a function with β€œhard coded” t - LieGroup.(PrM.manifolds, PrG.op.operations), + map(LieGroup, PrM.manifolds, PrG.op.operations), submanifold_components(PrM, h), - Identity.(PrG.op.operations), + map(Identity, PrG.op.operations), submanifold_components(PrM, X), ) return h @@ -226,7 +226,7 @@ function inv!( PrM = PrG.manifold map( inv!, - LieGroup.(PrM.manifolds, PrG.op.operations), + map(LieGroup, PrM.manifolds, PrG.op.operations), submanifold_components(PrM, h), submanifold_components(PrM, g), ) @@ -238,9 +238,9 @@ function inv!( PrM = PrG.manifold map( inv!, - LieGroup.(PrM.manifolds, PrG.op.operations), + map(LieGroup, PrM.manifolds, PrG.op.operations), submanifold_components(PrM, h), - Identity.(PrG.op.operations), + map(Identity, PrG.op.operations), ) return h end @@ -251,7 +251,7 @@ function lie_bracket!( PrM = PrA.manifold.manifold map( lie_bracket!, - LieAlgebra.(LieGroup.(PrM.manifolds, PrA.manifold.op.operations)), + map(LieAlgebra, LieGroup.(PrM.manifolds, PrA.manifold.op.operations)), submanifold_components(PrM, Z), submanifold_components(PrM, X), submanifold_components(PrM, Y), @@ -265,9 +265,9 @@ function ManifoldsBase.log!( PrM = PrG.manifold map( log!, - LieGroup.(PrM.manifolds, PrG.op.operations), + map(LieGroup, PrM.manifolds, PrG.op.operations), submanifold_components(PrM, X), - Identity.(PrG.op.operations), + map(Identity, PrG.op.operations), submanifold_components(PrM, g), ) return X From c9d86076a43161f805d2d46a818d623a7a3caf61 Mon Sep 17 00:00:00 2001 From: Mateusz Baran Date: Sat, 30 Nov 2024 11:03:38 +0100 Subject: [PATCH 40/43] improve coverage --- src/group_actions/group_action_interface.jl | 2 +- test/actions/test_action_interface.jl | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/group_actions/group_action_interface.jl b/src/group_actions/group_action_interface.jl index 8ff72c04..badef955 100644 --- a/src/group_actions/group_action_interface.jl +++ b/src/group_actions/group_action_interface.jl @@ -249,7 +249,7 @@ Return the group operation action representing the similar [`GroupAction`](@ref) but acting from the other side. It switches left to right and vice versa. This is done by returning the group action with the β€œswitched” type of `T`. """ -switch(A::GroupAction) = GroupAction(switch(A.type), A.group) +switch(A::GroupAction) = GroupAction(switch(A.type), A.group, A.manifold) @doc """ switch(T::AbstractGroupActionType) diff --git a/test/actions/test_action_interface.jl b/test/actions/test_action_interface.jl index cf9fd9a1..1b7ef413 100644 --- a/test/actions/test_action_interface.jl +++ b/test/actions/test_action_interface.jl @@ -10,5 +10,6 @@ using LieGroupsTestSuite G = LieGroupsTestSuite.DummyLieGroup(M, LieGroupsTestSuite.DummyOperation()) a = GroupAction(T, G, M) @test repr(a) === "GroupAction($T, $G, $M)" - @test switch(T) == T + @test switch(T) === T + @test switch(a) === a end From 99193d896c2537f83ed837366b692334dbd924a8 Mon Sep 17 00:00:00 2001 From: Mateusz Baran Date: Sat, 30 Nov 2024 11:08:14 +0100 Subject: [PATCH 41/43] make a better action interface test --- test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl | 4 ++++ test/actions/test_action_interface.jl | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl index e1d6754a..8b265553 100644 --- a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl +++ b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl @@ -22,8 +22,12 @@ struct DummyOperation <: AbstractGroupOperation end struct DummySecondOperation <: AbstractGroupOperation end struct DummyManifold <: LieGroups.AbstractManifold{LieGroups.ℝ} end struct DummyActionType <: AbstractGroupActionType end +struct DummyLeftActionType <: AbstractLeftGroupActionType end +struct DummyRightActionType <: AbstractRightGroupActionType end const DummyLieGroup = LieGroup{LieGroups.ℝ,DummyOperation,DummyManifold} LieGroups.switch(a::DummyActionType) = a +LieGroups.switch(::DummyLeftActionType) = DummyRightActionType() +LieGroups.switch(::DummyRightActionType) = DummyLeftActionType() # === Test single functions === # # diff --git a/test/actions/test_action_interface.jl b/test/actions/test_action_interface.jl index 1b7ef413..85757c88 100644 --- a/test/actions/test_action_interface.jl +++ b/test/actions/test_action_interface.jl @@ -6,10 +6,10 @@ using LieGroupsTestSuite @testset "Group Action Interface" begin M = LieGroupsTestSuite.DummyManifold() - T = LieGroupsTestSuite.DummyActionType() + T = LieGroupsTestSuite.DummyLeftActionType() G = LieGroupsTestSuite.DummyLieGroup(M, LieGroupsTestSuite.DummyOperation()) a = GroupAction(T, G, M) @test repr(a) === "GroupAction($T, $G, $M)" - @test switch(T) === T - @test switch(a) === a + @test switch(T) === LieGroupsTestSuite.DummyRightActionType() + @test switch(a) === GroupAction(switch(T), G, M) end From 14550802df689951cabc9cc804696809209b4631 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Sat, 30 Nov 2024 13:36:46 +0100 Subject: [PATCH 42/43] fix a doc string. --- src/group_actions/group_operation_action.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/group_actions/group_operation_action.jl b/src/group_actions/group_operation_action.jl index a08fe232..e2719252 100644 --- a/src/group_actions/group_operation_action.jl +++ b/src/group_actions/group_operation_action.jl @@ -68,10 +68,10 @@ for its inverse ``(Οƒ_h)^{-1}`` see [`InverseLeftGroupOperationAction`](@ref). struct InverseRightGroupOperationAction <: AbstractLeftGroupActionType end """ - GroupOperationAction(action::AbstractLeftGroupActionType, group::LieGroup) + GroupOperationAction(action::AbstractGroupActionType, group::LieGroup) -Return a [`GroupAction`](@ref) for an [`AbstractLeftGroupActionType`](@ref) `action` representing -the action of the group operation as an action of the group on itself. +Return a [`GroupAction`](@ref) for an [`AbstractGroupActionType`](@ref) `action` +representing the group operation as an action of the group on itself. """ function GroupOperationAction(action::AbstractGroupActionType, G::LieGroup) return GroupAction(action, G, G) From c02a480f7ea228ebe51b88ddb10a2073aad18b29 Mon Sep 17 00:00:00 2001 From: Mateusz Baran Date: Sat, 30 Nov 2024 18:10:59 +0100 Subject: [PATCH 43/43] improve some docs --- src/groups/semidirect_product_group.jl | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/groups/semidirect_product_group.jl b/src/groups/semidirect_product_group.jl index 686358aa..43b2c1dc 100644 --- a/src/groups/semidirect_product_group.jl +++ b/src/groups/semidirect_product_group.jl @@ -1,7 +1,7 @@ # # -# Semidirect product groups – model semidirect products of rwo Lie groups +# Semidirect product groups – model semidirect products of two Lie groups # """ LeftSemidirectProductGroupOperation{O1,O2,A} <: AbstractGroupOperation @@ -10,14 +10,15 @@ A struct to model a semidirect Lie group product. Let ``($(_tex(:Cal, "N")), β‹„)`` and ``($(_tex(:Cal, "H")), ⋆)`` be two Lie groups with group operations ``β‹„`` and ``⋆``, respectively, as well as a group action -``Οƒ: $(_tex(:Cal, "H"))Γ—$(_tex(:Cal, "N")) β†’ $(_tex(:Cal, "N"))``, cf [`AbstractLeftGroupActionType`](#ref). +``Οƒ: $(_tex(:Cal, "H"))Γ—$(_tex(:Cal, "N")) β†’ $(_tex(:Cal, "N"))``, cf [`AbstractLeftGroupActionType`](@ref). -We use here as well use the notation ``Οƒ_h: $(_tex(:Cal, "N")) β†’ $(_tex(:Cal, "N"))`` as a family of maps on ``$(_tex(:Cal, "N"))`` +We use here as well use the notation ``Οƒ_h: $(_tex(:Cal, "N")) β†’ $(_tex(:Cal, "N"))`` +as a family of maps on ``$(_tex(:Cal, "N"))`` -Then we define a group operation ``∘`` on the product manifold $(_tex(:Cal, "N"))Γ—$(_tex(:Cal, "H")) by +Then we define a group operation ``∘`` on the product manifold ``$(_tex(:Cal, "N"))Γ—$(_tex(:Cal, "H"))`` by ```math - (h_1,n_1) ∘ (h_2,n_2) := (h_1 ⋆ h_2, Ο„_{h_2}(n_1) β‹„ n_1). + (h_1,n_1) ∘ (h_2,n_2) := (h_1 ⋆ h_2, Οƒ_{h_2}(n_1) β‹„ n_1). ``` See [HilgertNeeb:2012; Definition 9.2.22](@cite), second definition for more details. @@ -61,9 +62,10 @@ Let ``($(_tex(:Cal, "N")), β‹„)`` and ``($(_tex(:Cal, "H")), ⋆)`` be two Lie g with group operations ``β‹„`` and ``⋆``, respectively, as well as a group action ``Οƒ: $(_tex(:Cal, "H"))Γ—$(_tex(:Cal, "N")) β†’ $(_tex(:Cal, "N"))``, cf [`AbstractGroupActionType`](#ref). -We use here as well use the notation ``Οƒ_h: $(_tex(:Cal, "N")) β†’ $(_tex(:Cal, "N"))`` as a family of maps on ``$(_tex(:Cal, "N"))`` +We use here as well use the notation ``Οƒ_h: $(_tex(:Cal, "N")) β†’ $(_tex(:Cal, "N"))`` +as a family of maps on ``$(_tex(:Cal, "N"))`` -Then we define a group operation ``∘`` on the product manifold $(_tex(:Cal, "N"))Γ—$(_tex(:Cal, "H")) by +Then we define a group operation ``∘`` on the product manifold ``$(_tex(:Cal, "N"))Γ—$(_tex(:Cal, "H"))`` by ```math (n_1,h_1) ∘ (n_2,h_2) := (n_1 β‹„ Οƒ_{h_1}(n_2), h_1 ⋆ h_2)