Skip to content

Commit 1061dbb

Browse files
authored
Merge pull request #1724 from JuliaRobotics/23Q2/enh/manopt
Riemannian Levenberg-Marquardt for parametric solver
2 parents 3eb8e47 + a8e8eaf commit 1061dbb

23 files changed

+553
-106
lines changed

NEWS.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ Alternatively, either use the Github Blame, or the Github `/compare/v0.18.0...v0
1111

1212
The list below highlights breaking changes according to normal semver workflow -- i.e. breaking changes go through at least one deprecatation (via warnings) on the dominant number in the version number. E.g. v0.18 -> v0.19 (warnings) -> v0.20 (breaking). Note that ongoing efforts are made to properly deprecate old code/APIs
1313

14+
# Changes in v0.34
15+
16+
- Start transition to Manopt.jl via Riemannian Levenberg Marquart.
17+
- Deprecate `AbstractRelativeRoots`.
18+
19+
# Changes in v0.33
20+
21+
- Upgrades for DFG using StructTypes.jl (serialization).
1422
# Changes in v0.32
1523

1624
- Major internal refactoring of `CommonConvWrapper` to avoid abstract field types, and better standardization; towards cleanup of internal multihypo handling and naming conventions.

Project.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ version = "0.34.0"
88
ApproxManifoldProducts = "9bbbb610-88a1-53cd-9763-118ce10c1f89"
99
BSON = "fbb218c0-5317-5bc6-957e-2ee96dd4b1f0"
1010
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
11+
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
1112
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
1213
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
1314
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
@@ -17,6 +18,7 @@ DistributedFactorGraphs = "b5cc3c7e-6572-11e9-2517-99fb8daf2f04"
1718
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
1819
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
1920
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
21+
FiniteDiff = "6a86dc24-6348-571c-b903-95158fe2bd41"
2022
FiniteDifferences = "26cc04aa-876d-5657-8c51-4c34ba976000"
2123
FunctionalStateMachine = "3e9e306e-7e3c-11e9-12d2-8f8f67a2f951"
2224
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
@@ -26,6 +28,7 @@ Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
2628
ManifoldDiff = "af67fdf4-a580-4b9f-bbec-742ef357defd"
2729
Manifolds = "1cead3c2-87b3-11e9-0ccd-23c62b72b94e"
2830
ManifoldsBase = "3362f125-f0bb-47a3-aa74-596ffd7ef2fb"
31+
Manopt = "0fc0a36d-df90-57f3-8f93-d78a9fc72bb5"
2932
MetaGraphs = "626554b9-1ddb-594c-aa3c-2596fe9399a5"
3033
NLSolversBase = "d41bc354-129a-5804-8e4c-c37616107c6c"
3134
NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56"
@@ -38,6 +41,7 @@ RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd"
3841
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
3942
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
4043
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
44+
SparseDiffTools = "47a9eef4-7e08-11e9-0b38-333d64bd3804"
4145
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
4246
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
4347
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
@@ -64,6 +68,7 @@ KernelDensityEstimate = "0.5.6"
6468
ManifoldDiff = "0.3"
6569
Manifolds = "0.8.15"
6670
ManifoldsBase = "0.13.12, 0.14"
71+
Manopt = "0.4.27"
6772
MetaGraphs = "0.7"
6873
NLSolversBase = "7.6"
6974
NLsolve = "3, 4"
@@ -87,10 +92,11 @@ Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c"
8792
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
8893
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
8994
Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
95+
LineSearches = "d3d80556-e9d4-5f37-9878-2ab0fcc64255"
9096
Manopt = "0fc0a36d-df90-57f3-8f93-d78a9fc72bb5"
9197
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
9298
Rotations = "6038ab10-8711-5258-84ad-4b1120ba62dc"
9399
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
94100

95101
[targets]
96-
test = ["DifferentialEquations", "Flux", "Graphs", "Manopt", "InteractiveUtils", "Interpolations", "Pkg", "Rotations", "Test"]
102+
test = ["DifferentialEquations", "Flux", "Graphs", "Manopt", "InteractiveUtils", "Interpolations", "LineSearches", "Pkg", "Rotations", "Test"]

src/Deprecated.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,29 @@ function solveGraphParametric2(
119119
return d, result, flatvar.idx, Σ
120120
end
121121

122+
123+
##==============================================================================
124+
## Deprecate code below before v0.35
125+
##==============================================================================
126+
127+
128+
129+
function _solveLambdaNumeric(
130+
fcttype::Union{F, <:Mixture{N_, F, S, T}},
131+
objResX::Function,
132+
residual::AbstractVector{<:Real},
133+
u0::AbstractVector{<:Real},
134+
islen1::Bool = false,
135+
) where {N_, F <: AbstractRelativeRoots, S, T}
136+
#
137+
138+
#
139+
r = NLsolve.nlsolve((res, x) -> res .= objResX(x), u0; inplace = true) #, ftol=1e-14)
140+
141+
#
142+
return r.zero
143+
end
144+
122145
##==============================================================================
123146
## Deprecate code below before v0.35
124147
##==============================================================================

src/Factors/EuclidDistance.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ $(TYPEDEF)
66
77
Default linear offset between two scalar variables.
88
"""
9-
struct EuclidDistance{T <: SamplableBelief} <: AbstractRelativeMinimize
9+
struct EuclidDistance{T <: SamplableBelief} <: AbstractManifoldMinimize # AbstractRelativeMinimize
1010
Z::T
1111
end
1212

src/Factors/GenericFunctions.jl

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,10 @@ export ManifoldFactor
6969
# For now, `Z` is on the tangent space in coordinates at the point used in the factor.
7070
# For groups just the lie algebra
7171
# As transition it will be easier this way, we can reevaluate
72-
struct ManifoldFactor{M <: AbstractManifold, T <: SamplableBelief} <:
73-
AbstractManifoldMinimize #AbstractFactor
72+
struct ManifoldFactor{
73+
M <: AbstractManifold,
74+
T <: SamplableBelief
75+
} <: AbstractManifoldMinimize
7476
M::M
7577
Z::T
7678
end
@@ -80,22 +82,21 @@ DFG.getManifold(f::ManifoldFactor) = f.M
8082
function getSample(cf::CalcFactor{<:ManifoldFactor{M, Z}}) where {M, Z}
8183
#TODO @assert dim == cf.factor.Z's dimension
8284
#TODO investigate use of SVector if small dims
83-
if M isa ManifoldKernelDensity
84-
ret = sample(cf.factor.Z.belief)[1]
85-
else
86-
ret = rand(cf.factor.Z)
87-
end
85+
# if M isa ManifoldKernelDensity
86+
# ret = sample(cf.factor.Z.belief)[1]
87+
# else
88+
# ret = rand(cf.factor.Z)
89+
# end
90+
91+
# ASSUME this function is only used for RelativeFactors which must use measurements as tangents
92+
ret = sampleTangent(cf.factor.M, cf.factor.Z)
8893
#return coordinates as we do not know the point here #TODO separate Lie group
8994
return ret
9095
end
9196

9297
# function (cf::CalcFactor{<:ManifoldFactor{<:AbstractDecoratorManifold}})(Xc, p, q)
93-
function (cf::CalcFactor{<:ManifoldFactor})(Xc, p, q)
94-
# function (cf::ManifoldFactor)(X, p, q)
95-
M = cf.manifold # .factor.M
96-
# M = cf.M
97-
X = hat(M, p, Xc)
98-
return distanceTangent2Point(M, X, p, q)
98+
function (cf::CalcFactor{<:ManifoldFactor})(X, p, q)
99+
return distanceTangent2Point(cf.manifold, X, p, q)
99100
end
100101

101102
## ======================================================================================

src/Factors/GenericMarginal.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"""
44
$(TYPEDEF)
55
"""
6-
mutable struct GenericMarginal <: AbstractRelativeRoots
6+
mutable struct GenericMarginal <: AbstractManifoldMinimize # AbstractRelativeRoots
77
Zij::Array{Float64, 1}
88
Cov::Array{Float64, 1}
99
W::Array{Float64, 1}

src/Factors/LinearRelative.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Default linear offset between two scalar variables.
1010
X_2 = X_1 + η_Z
1111
```
1212
"""
13-
struct LinearRelative{N, T <: SamplableBelief} <: AbstractRelativeMinimize
13+
struct LinearRelative{N, T <: SamplableBelief} <: AbstractManifoldMinimize # AbstractRelativeMinimize
1414
Z::T
1515
end
1616

src/IncrementalInference.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ include("CliqueStateMachine/services/CliqStateMachineUtils.jl")
213213
#EXPERIMENTAL parametric
214214
include("ParametricCSMFunctions.jl")
215215
include("ParametricUtils.jl")
216+
include("ParametricManoptDev.jl")
216217
include("services/MaxMixture.jl")
217218

218219
#X-stroke

src/ManifoldSampling.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,15 @@ function sampleTangent(x::ManifoldKernelDensity, p = mean(x))
2323
end
2424

2525
# Sampling Distributions
26-
function sampleTangent(M::AbstractManifold, z::Distribution, p, basis::AbstractBasis)
26+
# assumes M is a group and will break for Riemannian, but leaving that enhancement as TODO
27+
function sampleTangent(M::AbstractManifold, z::Distribution, p = getPointIdentity(M), basis::AbstractBasis = DefaultOrthogonalBasis())
2728
return get_vector(M, p, rand(z), basis)
2829
end
2930

3031
function sampleTangent(
3132
M::AbstractDecoratorManifold,
3233
z::Distribution,
33-
p = getPointIdentity(M),
34+
p = identity_element(M), #getPointIdentity(M),
3435
)
3536
return hat(M, p, rand(z, 1)[:]) #TODO find something better than (z,1)[:]
3637
end

src/ManifoldsExtentions.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,30 @@ function Manifolds.exp!(M::NPowerManifold, q, p, X)
8888
return q
8989
end
9090

91+
function Manifolds.compose!(M::NPowerManifold, x, p, q)
92+
rep_size = representation_size(M.manifold)
93+
for i in Manifolds.get_iterator(M)
94+
x[i] = compose(
95+
M.manifold,
96+
Manifolds._read(M, rep_size, p, i),
97+
Manifolds._read(M, rep_size, q, i),
98+
)
99+
end
100+
return x
101+
end
102+
103+
function Manifolds.allocate_result(M::NPowerManifold, f, x...)
104+
if length(x) == 0
105+
return [Manifolds.allocate_result(M.manifold, f) for _ in Manifolds.get_iterator(M)]
106+
else
107+
return copy(x[1])
108+
end
109+
end
110+
111+
function Manifolds.allocate_result(::NPowerManifold, ::typeof(get_vector), p, X)
112+
return copy(p)
113+
end
114+
91115
## ================================================================================================
92116
## ArrayPartition getPointIdentity (identity_element)
93117
## ================================================================================================

0 commit comments

Comments
 (0)