diff --git a/Project.toml b/Project.toml index 7802b1bd8..c4f7a26b2 100644 --- a/Project.toml +++ b/Project.toml @@ -96,9 +96,9 @@ NonlinearSolveSpectralMethods = "1" OrdinaryDiffEqTsit5 = "1.1.0" PETSc = "0.3" Pkg = "1.10" +PolyesterForwardDiff = "0.1" PrecompileTools = "1.2" Preferences = "1.4" -PolyesterForwardDiff = "0.1" Random = "1.10" ReTestItems = "1.24" Reexport = "1.2" diff --git a/lib/NonlinearSolveFirstOrder/Project.toml b/lib/NonlinearSolveFirstOrder/Project.toml index 94ab4fdbc..63f9f55eb 100644 --- a/lib/NonlinearSolveFirstOrder/Project.toml +++ b/lib/NonlinearSolveFirstOrder/Project.toml @@ -13,6 +13,7 @@ FiniteDiff = "6a86dc24-6348-571c-b903-95158fe2bd41" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" +LineSearch = "87fe0de2-c867-4266-b59a-2f0a94fc965b" MaybeInplace = "bb5d69b7-63fc-4a16-80bd-7e42200c7bdb" NonlinearSolveBase = "be0214bd-f91f-a760-ac4e-3421ce2b2da0" PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" diff --git a/lib/NonlinearSolveFirstOrder/src/NonlinearSolveFirstOrder.jl b/lib/NonlinearSolveFirstOrder/src/NonlinearSolveFirstOrder.jl index 145468122..1f480fb4b 100644 --- a/lib/NonlinearSolveFirstOrder/src/NonlinearSolveFirstOrder.jl +++ b/lib/NonlinearSolveFirstOrder/src/NonlinearSolveFirstOrder.jl @@ -8,6 +8,7 @@ using Setfield: @set! using ADTypes: ADTypes using ArrayInterface: ArrayInterface using LinearAlgebra: LinearAlgebra, Diagonal, dot, diagind +using LineSearch: BackTracking using StaticArraysCore: SArray using CommonSolve: CommonSolve @@ -19,7 +20,7 @@ using NonlinearSolveBase: NonlinearSolveBase, AbstractNonlinearSolveAlgorithm, AbstractDampingFunctionCache, AbstractTrustRegionMethod, AbstractTrustRegionMethodCache, Utils, InternalAPI, get_timer_output, @static_timeit, - update_trace!, L2_NORM, + update_trace!, L2_NORM, NonlinearSolvePolyAlgorithm, NewtonDescent, DampedNewtonDescent, GeodesicAcceleration, Dogleg using SciMLBase: SciMLBase, AbstractNonlinearProblem, NLStats, ReturnCode, @@ -36,6 +37,8 @@ include("levenberg_marquardt.jl") include("trust_region.jl") include("pseudo_transient.jl") +include("poly_algs.jl") + include("solve.jl") @setup_workload begin @@ -100,4 +103,7 @@ export RadiusUpdateSchemes export GeneralizedFirstOrderAlgorithm +# Polyalgorithms +export RobustMultiNewton + end diff --git a/lib/NonlinearSolveFirstOrder/src/poly_algs.jl b/lib/NonlinearSolveFirstOrder/src/poly_algs.jl new file mode 100644 index 000000000..06dcc1c5a --- /dev/null +++ b/lib/NonlinearSolveFirstOrder/src/poly_algs.jl @@ -0,0 +1,44 @@ +""" + RobustMultiNewton( + ::Type{T} = Float64; + concrete_jac = nothing, + linsolve = nothing, + autodiff = nothing, vjp_autodiff = nothing, jvp_autodiff = nothing + ) + +A polyalgorithm focused on robustness. It uses a mixture of Newton methods with different +globalizing techniques (trust region updates, line searches, etc.) in order to find a +method that is able to adequately solve the minimization problem. + +Basically, if this algorithm fails, then "most" good ways of solving your problem fail and +you may need to think about reformulating the model (either there is an issue with the model, +or more precision / more stable linear solver choice is required). + +### Arguments + + - `T`: The eltype of the initial guess. It is only used to check if some of the algorithms + are compatible with the problem type. Defaults to `Float64`. +""" +function RobustMultiNewton( + ::Type{T} = Float64; + concrete_jac = nothing, + linsolve = nothing, + autodiff = nothing, vjp_autodiff = nothing, jvp_autodiff = nothing +) where {T} + common_kwargs = (; concrete_jac, linsolve, autodiff, vjp_autodiff, jvp_autodiff) + if T <: Complex # Let's atleast have something here for complex numbers + algs = ( + NewtonRaphson(; common_kwargs...), + ) + else + algs = ( + TrustRegion(; common_kwargs...), + TrustRegion(; common_kwargs..., radius_update_scheme = RUS.Bastin), + NewtonRaphson(; common_kwargs...), + NewtonRaphson(; common_kwargs..., linesearch = BackTracking()), + TrustRegion(; common_kwargs..., radius_update_scheme = RUS.NLsolve), + TrustRegion(; common_kwargs..., radius_update_scheme = RUS.Fan) + ) + end + return NonlinearSolvePolyAlgorithm(algs) +end diff --git a/src/NonlinearSolve.jl b/src/NonlinearSolve.jl index 3aa4cac22..4c44cc972 100644 --- a/src/NonlinearSolve.jl +++ b/src/NonlinearSolve.jl @@ -25,7 +25,7 @@ using StaticArraysCore: StaticArray # Default Algorithm using NonlinearSolveFirstOrder: NewtonRaphson, TrustRegion, LevenbergMarquardt, GaussNewton, - RUS + RUS, RobustMultiNewton using NonlinearSolveQuasiNewton: Broyden, Klement using SimpleNonlinearSolve: SimpleBroyden, SimpleKlement @@ -125,8 +125,7 @@ end @reexport using LinearSolve # Poly Algorithms -export NonlinearSolvePolyAlgorithm, - RobustMultiNewton, FastShortcutNonlinearPolyalg, FastShortcutNLLSPolyalg +export NonlinearSolvePolyAlgorithm, FastShortcutNonlinearPolyalg, FastShortcutNLLSPolyalg # Extension Algorithms export LeastSquaresOptimJL, FastLevenbergMarquardtJL, NLsolveJL, NLSolversJL, diff --git a/src/poly_algs.jl b/src/poly_algs.jl index 31c16917f..3b13ba84f 100644 --- a/src/poly_algs.jl +++ b/src/poly_algs.jl @@ -1,48 +1,3 @@ -""" - RobustMultiNewton( - ::Type{T} = Float64; - concrete_jac = nothing, - linsolve = nothing, - autodiff = nothing, vjp_autodiff = nothing, jvp_autodiff = nothing - ) - -A polyalgorithm focused on robustness. It uses a mixture of Newton methods with different -globalizing techniques (trust region updates, line searches, etc.) in order to find a -method that is able to adequately solve the minimization problem. - -Basically, if this algorithm fails, then "most" good ways of solving your problem fail and -you may need to think about reformulating the model (either there is an issue with the model, -or more precision / more stable linear solver choice is required). - -### Arguments - - - `T`: The eltype of the initial guess. It is only used to check if some of the algorithms - are compatible with the problem type. Defaults to `Float64`. -""" -function RobustMultiNewton( - ::Type{T} = Float64; - concrete_jac = nothing, - linsolve = nothing, - autodiff = nothing, vjp_autodiff = nothing, jvp_autodiff = nothing -) where {T} - common_kwargs = (; concrete_jac, linsolve, autodiff, vjp_autodiff, jvp_autodiff) - if T <: Complex # Let's atleast have something here for complex numbers - algs = ( - NewtonRaphson(; common_kwargs...), - ) - else - algs = ( - TrustRegion(; common_kwargs...), - TrustRegion(; common_kwargs..., radius_update_scheme = RUS.Bastin), - NewtonRaphson(; common_kwargs...), - NewtonRaphson(; common_kwargs..., linesearch = BackTracking()), - TrustRegion(; common_kwargs..., radius_update_scheme = RUS.NLsolve), - TrustRegion(; common_kwargs..., radius_update_scheme = RUS.Fan) - ) - end - return NonlinearSolvePolyAlgorithm(algs) -end - """ FastShortcutNonlinearPolyalg( ::Type{T} = Float64;