From c0a3103f9b3725d3d01a6f3227abd1196a3a7a96 Mon Sep 17 00:00:00 2001 From: Mateusz Baran Date: Fri, 6 Oct 2023 21:40:52 +0200 Subject: [PATCH 1/5] Alternative fix to extra allocations in get_gradient! from Jacobian --- src/plans/nonlinear_least_squares_plan.jl | 22 ++++++++++++++++------ src/solvers/LevenbergMarquardt.jl | 5 +++-- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/plans/nonlinear_least_squares_plan.jl b/src/plans/nonlinear_least_squares_plan.jl index 69ae0dfee4..179d4b6d1c 100644 --- a/src/plans/nonlinear_least_squares_plan.jl +++ b/src/plans/nonlinear_least_squares_plan.jl @@ -70,6 +70,21 @@ function get_cost( return 1//2 * norm(residual_values)^2 end +function get_gradient_from_Jacobian!( + M::AbstractManifold, + X, + nlso::NonlinearLeastSquaresObjective{InplaceEvaluation}, + p, + Jval=zeros(nlso.num_components, manifold_dimension(M)), +) + basis_p = _maybe_get_basis(M, p, nlso.jacobian_tangent_basis) + nlso.jacobian!!(M, Jval, p; basis_domain=basis_p) + residual_values = zeros(nlso.num_components) + nlso.f(M, residual_values, p) + get_vector!(M, X, p, transpose(Jval) * residual_values, basis_p) + return X +end + function get_gradient( M::AbstractManifold, nlso::NonlinearLeastSquaresObjective{AllocatingEvaluation}, p ) @@ -101,12 +116,7 @@ end function get_gradient!( M::AbstractManifold, X, nlso::NonlinearLeastSquaresObjective{InplaceEvaluation}, p ) - basis_p = _maybe_get_basis(M, p, nlso.jacobian_tangent_basis) - Jval = zeros(nlso.num_components, manifold_dimension(M)) - nlso.jacobian!!(M, Jval, p; basis_domain=basis_p) - residual_values = zeros(nlso.num_components) - nlso.f(M, residual_values, p) - get_vector!(M, X, p, transpose(Jval) * residual_values, basis_p) + get_gradient_from_Jacobian!(M, X, nlso, p) return X end diff --git a/src/solvers/LevenbergMarquardt.jl b/src/solvers/LevenbergMarquardt.jl index 5a4405fa1b..6457daa61d 100644 --- a/src/solvers/LevenbergMarquardt.jl +++ b/src/solvers/LevenbergMarquardt.jl @@ -206,8 +206,9 @@ function initialize_solver!( dmp::DefaultManoptProblem{mT,<:NonlinearLeastSquaresObjective{InplaceEvaluation}}, lms::LevenbergMarquardtState, ) where {mT<:AbstractManifold} - get_objective(dmp).f(get_manifold(dmp), lms.residual_values, lms.p) - lms.X = get_gradient(dmp, lms.p) + M = get_manifold(dmp) + get_objective(dmp).f(M, lms.residual_values, lms.p) + get_gradient_from_Jacobian!(M, lms.X, get_objective(dmp), lms.p, lms.jacF) return lms end From 328786877a80b31745e5548882cd47c0c28e0457 Mon Sep 17 00:00:00 2001 From: Mateusz Baran Date: Fri, 6 Oct 2023 22:11:00 +0200 Subject: [PATCH 2/5] docs --- src/plans/nonlinear_least_squares_plan.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/plans/nonlinear_least_squares_plan.jl b/src/plans/nonlinear_least_squares_plan.jl index 179d4b6d1c..d517ffa058 100644 --- a/src/plans/nonlinear_least_squares_plan.jl +++ b/src/plans/nonlinear_least_squares_plan.jl @@ -70,6 +70,18 @@ function get_cost( return 1//2 * norm(residual_values)^2 end +""" + get_gradient_from_Jacobian!( + M::AbstractManifold, + X, + nlso::NonlinearLeastSquaresObjective{InplaceEvaluation}, + p, + Jval=zeros(nlso.num_components, manifold_dimension(M)), + ) + +Compute gradient of [`NonlinearLeastSquaresObjective`](@ref) `nlso` at point `p` in place of +`X`, with temporary Jacobian stored in the optional argument `Jval`. +""" function get_gradient_from_Jacobian!( M::AbstractManifold, X, From 0eddfce842707103ff5f9fc5f0947fe4cb0d2e62 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Sat, 7 Oct 2023 09:27:44 +0200 Subject: [PATCH 3/5] add new function to docs. --- docs/src/plans/objective.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/src/plans/objective.md b/docs/src/plans/objective.md index a359477542..8ebe00d2e2 100644 --- a/docs/src/plans/objective.md +++ b/docs/src/plans/objective.md @@ -130,6 +130,12 @@ and internally get_gradient_function ``` +#### Internal Helpers + +```@docs +get_gradient_from_Jacobian! +``` + ### Subgradient Objective ```@docs From 60ad5f7758ae8f276bfea0e4e2ea83effa8d0b72 Mon Sep 17 00:00:00 2001 From: Mateusz Baran Date: Sat, 7 Oct 2023 20:16:38 +0200 Subject: [PATCH 4/5] add some tests --- test/solvers/test_Levenberg_Marquardt.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/solvers/test_Levenberg_Marquardt.jl b/test/solvers/test_Levenberg_Marquardt.jl index 295393b854..0bedb88d38 100644 --- a/test/solvers/test_Levenberg_Marquardt.jl +++ b/test/solvers/test_Levenberg_Marquardt.jl @@ -217,6 +217,7 @@ end X_r2 = similar(x0) get_gradient!(p_r2, X_r2, x0) @test isapprox(X_r2, [270.3617451389837, 677.6730784956912]) + @test isapprox(get_gradient(p_r2, x0), [270.3617451389837, 677.6730784956912]) p_r2_mut = DefaultManoptProblem( M, @@ -228,6 +229,7 @@ end X_r2 = similar(x0) get_gradient!(p_r2_mut, X_r2, x0) @test isapprox(X_r2, [270.3617451389837, 677.6730784956912]) + @test isapprox(get_gradient(p_r2_mut, x0), [270.3617451389837, 677.6730784956912]) @testset "errors" begin @test_throws ArgumentError LevenbergMarquardtState( From b3e9c882e7f7748faf7ffb660ef5b4ae457c90e8 Mon Sep 17 00:00:00 2001 From: Mateusz Baran Date: Sun, 8 Oct 2023 14:39:56 +0200 Subject: [PATCH 5/5] bump version --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index dbfe0ebc66..3f105e765e 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Manopt" uuid = "0fc0a36d-df90-57f3-8f93-d78a9fc72bb5" authors = ["Ronny Bergmann "] -version = "0.4.37" +version = "0.4.38" [deps] ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"