From 31e9e8e7288e8ce371aa0974e93d685edada05c8 Mon Sep 17 00:00:00 2001 From: Maxence Gollier Date: Tue, 16 Sep 2025 16:37:15 -0400 Subject: [PATCH 1/4] fix sub_kwargs --- src/R2N.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/R2N.jl b/src/R2N.jl index e1304725..127f3a54 100644 --- a/src/R2N.jl +++ b/src/R2N.jl @@ -134,7 +134,7 @@ For advanced usage, first define a solver "R2NSolver" to preallocate the memory - `γ::T = T(3)`: regularization parameter multiplier, σ := σ/γ when the iteration is very successful and σ := σγ when the iteration is unsuccessful; - `θ::T = 1/(1 + eps(T)^(1 / 5))`: is the model decrease fraction with respect to the decrease of the Cauchy model; - `m_monotone::Int = 1`: monotonicity parameter. By default, R2N is monotone but the non-monotone variant will be used if `m_monotone > 1`; -- `sub_kwargs::Dict{Symbol}`: a dictionary containing the keyword arguments to be sent to the subsolver. The solver will fail if invalid keyword arguments are provided to the subsolver. +- `sub_kwargs::NamedTuple`: a named tuple containing the keyword arguments to be sent to the subsolver. The solver will fail if invalid keyword arguments are provided to the subsolver. The algorithm stops either when `√(ξₖ/νₖ) < atol + rtol*√(ξ₀/ν₀) ` or `ξₖ < 0` and `√(-ξₖ/νₖ) < neg_tol` where ξₖ := f(xₖ) + h(xₖ) - φ(sₖ; xₖ) - ψ(sₖ; xₖ), and √(ξₖ/νₖ) is a stationarity measure. @@ -174,7 +174,7 @@ function R2N( selected = pop!(kwargs_dict, :selected, 1:(nlp.meta.nvar)) x0 = pop!(kwargs_dict, :x0, nlp.meta.x0) reg_nlp = RegularizedNLPModel(nlp, h, selected) - sub_kwargs = pop!(kwargs_dict, :sub_kwargs, Dict{Symbol, Any}()) + sub_kwargs = pop!(kwargs_dict, :sub_kwargs, NamedTuple()) return R2N( reg_nlp, x = x0, @@ -226,7 +226,7 @@ function SolverCore.solve!( γ::T = T(3), β::T = 1 / eps(T), θ::T = 1/(1 + eps(T)^(1 / 5)), - sub_kwargs::Dict{Symbol} = Dict(), + sub_kwargs::NamedTuple = NamedTuple(), ) where {T, V, G} reset!(stats) @@ -365,11 +365,11 @@ function SolverCore.solve!( solver.subpb.model.σ = σk isa(solver.subsolver, R2DHSolver) && (solver.subsolver.D.d[1] = 1/ν₁) if isa(solver.subsolver, R2Solver) #FIXME - sub_kwargs[:ν] = ν₁ + solve!(solver.subsolver, solver.subpb, solver.substats; x = s1, ν = ν₁, atol = sub_atol, sub_kwargs...) else - sub_kwargs[:σk] = σk + solve!(solver.subsolver, solver.subpb, solver.substats; x = s1, σk = σk, atol = sub_atol, sub_kwargs...) end - solve!(solver.subsolver, solver.subpb, solver.substats; x = s1, atol = sub_atol, sub_kwargs...) + s .= solver.substats.solution From 5cfecd3d7246f7a0f223c6492cfc2db51a1207df Mon Sep 17 00:00:00 2001 From: Maxence Gollier Date: Tue, 16 Sep 2025 16:39:52 -0400 Subject: [PATCH 2/4] add sub_kwargs for TR --- src/TR_alg.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/TR_alg.jl b/src/TR_alg.jl index e53b7f89..b8f6c274 100644 --- a/src/TR_alg.jl +++ b/src/TR_alg.jl @@ -131,6 +131,7 @@ For advanced usage, first define a solver "TRSolver" to preallocate the memory u - `γ::T = T(3)`: trust-region radius parameter multiplier. Must satisfy `γ > 1`. The trust-region radius is updated as Δ := Δ*γ when the iteration is very successful and Δ := Δ/γ when the iteration is unsuccessful; - `χ::F = NormLinf(1)`: norm used to define the trust-region;` - `subsolver::S = R2Solver`: subsolver used to solve the subproblem that appears at each iteration. +- `sub_kwargs::NamedTuple`: a named tuple containing the keyword arguments to be sent to the subsolver. The solver will fail if invalid keyword arguments are provided to the subsolver. The algorithm stops either when `√(ξₖ/νₖ) < atol + rtol*√(ξ₀/ν₀) ` or `ξₖ < 0` and `√(-ξₖ/νₖ) < neg_tol` where ξₖ := f(xₖ) + h(xₖ) - φ(sₖ; xₖ) - ψ(sₖ; xₖ), and √(ξₖ/νₖ) is a stationarity measure. @@ -199,6 +200,7 @@ function SolverCore.solve!( η1::T = √√eps(T), η2::T = T(0.9), γ::T = T(3), + sub_kwargs::NamedTuple = NamedTuple(), ) where {T, G, V} reset!(stats) @@ -353,6 +355,7 @@ function SolverCore.solve!( x = s, atol = stats.iter == 0 ? 1e-5 : max(sub_atol, min(1e-2, sqrt_ξ1_νInv)), Δk = ∆_effective / 10, + sub_kwargs... ) else solve!( @@ -362,6 +365,7 @@ function SolverCore.solve!( x = s, atol = stats.iter == 0 ? 1e-5 : max(sub_atol, min(1e-2, sqrt_ξ1_νInv)), ν = ν₁, + sub_kwargs... ) end end From 1ddd977c4c63c54c2adb26a70dca06f4e6c894a1 Mon Sep 17 00:00:00 2001 From: Maxence Gollier Date: Wed, 17 Sep 2025 11:24:49 -0400 Subject: [PATCH 3/4] give an example in namedtuple docstring --- src/R2N.jl | 2 +- src/TR_alg.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/R2N.jl b/src/R2N.jl index 127f3a54..75cd16c7 100644 --- a/src/R2N.jl +++ b/src/R2N.jl @@ -134,7 +134,7 @@ For advanced usage, first define a solver "R2NSolver" to preallocate the memory - `γ::T = T(3)`: regularization parameter multiplier, σ := σ/γ when the iteration is very successful and σ := σγ when the iteration is unsuccessful; - `θ::T = 1/(1 + eps(T)^(1 / 5))`: is the model decrease fraction with respect to the decrease of the Cauchy model; - `m_monotone::Int = 1`: monotonicity parameter. By default, R2N is monotone but the non-monotone variant will be used if `m_monotone > 1`; -- `sub_kwargs::NamedTuple`: a named tuple containing the keyword arguments to be sent to the subsolver. The solver will fail if invalid keyword arguments are provided to the subsolver. +- `sub_kwargs::NamedTuple = NamedTuple()`: a named tuple containing the keyword arguments to be sent to the subsolver. The solver will fail if invalid keyword arguments are provided to the subsolver. For example, if the subsolver is `R2Solver`, you can pass `sub_kwargs = (max_iter = 100, σmin = 1e-6,)`. The algorithm stops either when `√(ξₖ/νₖ) < atol + rtol*√(ξ₀/ν₀) ` or `ξₖ < 0` and `√(-ξₖ/νₖ) < neg_tol` where ξₖ := f(xₖ) + h(xₖ) - φ(sₖ; xₖ) - ψ(sₖ; xₖ), and √(ξₖ/νₖ) is a stationarity measure. diff --git a/src/TR_alg.jl b/src/TR_alg.jl index b8f6c274..631a62e7 100644 --- a/src/TR_alg.jl +++ b/src/TR_alg.jl @@ -131,7 +131,7 @@ For advanced usage, first define a solver "TRSolver" to preallocate the memory u - `γ::T = T(3)`: trust-region radius parameter multiplier. Must satisfy `γ > 1`. The trust-region radius is updated as Δ := Δ*γ when the iteration is very successful and Δ := Δ/γ when the iteration is unsuccessful; - `χ::F = NormLinf(1)`: norm used to define the trust-region;` - `subsolver::S = R2Solver`: subsolver used to solve the subproblem that appears at each iteration. -- `sub_kwargs::NamedTuple`: a named tuple containing the keyword arguments to be sent to the subsolver. The solver will fail if invalid keyword arguments are provided to the subsolver. +- `sub_kwargs::NamedTuple = NamedTuple()`: a named tuple containing the keyword arguments to be sent to the subsolver. The solver will fail if invalid keyword arguments are provided to the subsolver. For example, if the subsolver is `R2Solver`, you can pass `sub_kwargs = (max_iter = 100, σmin = 1e-6,)`. The algorithm stops either when `√(ξₖ/νₖ) < atol + rtol*√(ξ₀/ν₀) ` or `ξₖ < 0` and `√(-ξₖ/νₖ) < neg_tol` where ξₖ := f(xₖ) + h(xₖ) - φ(sₖ; xₖ) - ψ(sₖ; xₖ), and √(ξₖ/νₖ) is a stationarity measure. From 5800371f1dbce7c9a8db54a0eb4552011c925efc Mon Sep 17 00:00:00 2001 From: Maxence Gollier Date: Wed, 17 Sep 2025 15:57:41 -0400 Subject: [PATCH 4/4] fix memory bug in AL --- src/AL_alg.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AL_alg.jl b/src/AL_alg.jl index ef652c26..6d3f3fb6 100644 --- a/src/AL_alg.jl +++ b/src/AL_alg.jl @@ -155,7 +155,7 @@ function ALSolver(reg_nlp::AbstractRegularizedNLPModel{T, V}; kwargs...) where { cx = V(undef, ncon) y = V(undef, ncon) has_bnds = has_bounds(nlp) - sub_model = AugLagModel(nlp, V(undef, ncon), T(0), x, T(0), V(undef, ncon)) + sub_model = AugLagModel(nlp, V(undef, ncon), T(0), x, T(0), cx) sub_problem = RegularizedNLPModel(sub_model, reg_nlp.h, reg_nlp.selected) sub_solver = R2Solver(reg_nlp; kwargs...) sub_stats = RegularizedExecutionStats(sub_problem)