Skip to content

add a ShiftedProximableQuadraticNLPModel#113

Open
MaxenceGollier wants to merge 11 commits intoJuliaSmoothOptimizers:mainfrom
MaxenceGollier:shifted-proximable-model
Open

add a ShiftedProximableQuadraticNLPModel#113
MaxenceGollier wants to merge 11 commits intoJuliaSmoothOptimizers:mainfrom
MaxenceGollier:shifted-proximable-model

Conversation

@MaxenceGollier
Copy link
Copy Markdown
Collaborator

@MaxenceGollier MaxenceGollier commented Mar 25, 2026

closes #112.

What is implemented

I implement a new type ShiftedProximableQuadraticNLPModel.
The documentation I add here is self-explanatory:

    subproblem = ShiftedProximableQuadraticNLPModel(reg_nlp, x; kwargs...)

Given a regularized NLP model `reg_nlp` representing the problem

    minimize f(x) + h(x),
  
construct a shifted quadratic model around `x`:

    minimize  φ(s; x) + ½ σ ‖s‖² + ψ(s; x),

where φ(s ; x) = f(x) + ∇f(x)ᵀs + ½ sᵀBs is a quadratic approximation of f about x,
ψ(s; x) is either h(x + s) or an approximation of h(x + s), ‖⋅‖ is the ℓ₂ norm and σ > 0 is the regularization parameter.

How do I implement it

I add an abstract type

abstract type AbstractShiftedProximableNLPModel{T, V} <: AbstractRegularizedNLPModel{T, V} end

as well as a mutable struct

mutable struct ShiftedProximableQuadraticNLPModel{T, V, M <: AbstractNLPModel{T, V}, H <: ShiftedProximalOperators.ShiftedProximableFunction, I, P <: AbstractRegularizedNLPModel{T, V}} <:
       AbstractShiftedProximableNLPModel{T, V}
  model::M
  h::H
  selected::I
  parent::P
end

where model represents φ(s; x) + ½ σ ‖s‖², h represents ψ and parent, the original problem.

Why do I implement it

  1. In RegularizedOptimization.jl, I want to construct the subproblem with a sparse Hessian to use here in my exact penalty solver. This allows me to make a different constructor, by overwriting ShiftedProximableQuadraticNLPModel where the Hessian is sparse. In the shift! function, I will be able to update the sparse Hessian as well by overwriting.
  2. In RegularizedOptimization.jl there is a ton of redundant code between each solver. For example, R2N defines
  φ1 = let ∇fk = ∇fk
    d -> dot(∇fk, d)
  end

  mk1 = let ψ = ψ
    d -> φ1(d) + ψ(d)::T
  end

and so does TR, TRDH, R2, R2DH, etc. When a step is accepted in each of those, there is a lot of noisy code as well. With this feature, we will now be able to simply call shift!(subproblem, x) when the step x is accepted.

How do I test it

I added unit tests here. I plan to make a draft PR in RegularizedOptimization.jl where I use this code.
Link to draft PR: JuliaSmoothOptimizers/RegularizedOptimization.jl#316.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new shifted subproblem model type to support regularized optimization workflows that build and update quadratic + prox subproblems around an iterate.

Changes:

  • Introduces AbstractShiftedProximableNLPModel and ShiftedProximableQuadraticNLPModel with shift!, obj, and σ helpers.
  • Wires the new implementation behind @require ShiftedProximalOperators and @require QuadraticModels.
  • Adds unit tests for construction, sigma handling, shifting behavior, and allocations.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 8 comments.

File Description
src/shiftedProximableNLPModel.jl Implements the new shifted quadratic + proximable subproblem model, including shift!, obj, and forwarding methods.
src/RegularizedProblems.jl Conditionally includes the new file when QuadraticModels and ShiftedProximalOperators are available.
test/rmodel_tests.jl Adds tests validating objective evaluation, sigma toggling, shifting, bounds shifting, and allocations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +115 to +122
σ_c = skip_sigma ? zero(σ_temp) : σ_temp
update_sigma!(reg_nlp, σ_c)

φs = cauchy ? dot(φ.data.c, s) + σ_c * dot(s, s)/2 : obj(φ, s)
ψs = ψ(s)

update_sigma!(reg_nlp, σ_temp) # restore original σ

Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

obj temporarily mutates the model’s σ via update_sigma! and then restores it. If obj(φ, s) or ψ(s) throws, σ will not be restored, leaving the model in a corrupted state (and it’s also not thread-safe). Consider avoiding mutation (e.g., compute with the current σ and subtract the sigma term when skip_sigma=true), or wrap the restore in a try/finally to guarantee restoration.

Suggested change
σ_c = skip_sigma ? zero(σ_temp) : σ_temp
update_sigma!(reg_nlp, σ_c)
φs = cauchy ? dot.data.c, s) + σ_c * dot(s, s)/2 : obj(φ, s)
ψs = ψ(s)
update_sigma!(reg_nlp, σ_temp) # restore original σ
if cauchy
# In the Cauchy case, construct the quadratic model explicitly using either
# the original σ or zero, depending on skip_sigma, without mutating σ.
σ_used = skip_sigma ? zero(σ_temp) : σ_temp
φs = dot.data.c, s) + σ_used * dot(s, s) / 2
else
# Use the current σ in the model for φ, and, if requested, subtract the
# σ contribution from the objective afterwards instead of mutating σ.
φs = obj(φ, s)
if skip_sigma
φs -= σ_temp * dot(s, s) / 2
end
end
ψs = ψ(s)

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

@MaxenceGollier MaxenceGollier Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not but I think @dpo will not agree because we might compute $$\lVert \cdot \rVert$$ twice.

@github-actions
Copy link
Copy Markdown
Contributor

Package name latest stable
RegularizedOptimization

@github-actions
Copy link
Copy Markdown
Contributor

Package name latest stable
RegularizedOptimization

@github-actions
Copy link
Copy Markdown
Contributor

Package name latest stable
RegularizedOptimization

@github-actions
Copy link
Copy Markdown
Contributor

Package name latest stable
RegularizedOptimization

@github-actions
Copy link
Copy Markdown
Contributor

Package name latest stable
RegularizedOptimization

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 25, 2026

Codecov Report

❌ Patch coverage is 98.27586% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 79.27%. Comparing base (85de184) to head (3fc6090).
⚠️ Report is 35 commits behind head on main.

Files with missing lines Patch % Lines
src/shiftedProximableNLPModel.jl 98.27% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main     #113       +/-   ##
===========================================
- Coverage   99.18%   79.27%   -19.92%     
===========================================
  Files          11       20        +9     
  Lines         369      521      +152     
===========================================
+ Hits          366      413       +47     
- Misses          3      108      +105     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link
Copy Markdown
Contributor

Package name latest stable
RegularizedOptimization

@github-actions
Copy link
Copy Markdown
Contributor

Package name latest stable
RegularizedOptimization

@MaxenceGollier MaxenceGollier marked this pull request as draft March 31, 2026 15:00
@MaxenceGollier MaxenceGollier marked this pull request as ready for review March 31, 2026 21:34
@github-actions
Copy link
Copy Markdown
Contributor

Package name latest stable
RegularizedOptimization

@github-actions
Copy link
Copy Markdown
Contributor

Package name latest stable
RegularizedOptimization

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add an AbstractShiftedProximableNLPModel

2 participants