Skip to content

Add tutorial accessing Linear and Nonlinear Constraints #156

Open
arnavk23 wants to merge 10 commits into
JuliaSmoothOptimizers:mainfrom
arnavk23:main
Open

Add tutorial accessing Linear and Nonlinear Constraints #156
arnavk23 wants to merge 10 commits into
JuliaSmoothOptimizers:mainfrom
arnavk23:main

Conversation

@arnavk23
Copy link
Copy Markdown
Contributor

New tutorial
Updates to tutorial

  • Tutorial name: Accessing Linear and Nonlinear Constraints (Linear API)
  • Confirm that either:
  • Confirm that you have used a tool such as [Grammarly] to verify that the text is correct.
  • Wait for the workflow, look at the preview, and confirm:
    • The preview has your tutorial listed.
    • The preview looks like what you want.

Adds a new tutorial demonstrating the "linear API" for separating and operating on linear vs nonlinear constraints, including a minimal manual NLPModel that exposes one linear and one nonlinear constraint and comparisons between jac_op!/mul! and jprod!/jtprod!.

julia> using NLPModelsTest, NLPModels, LinearOperators, LinearAlgebra

julia> list = NLPModelsTest.nlp_problems
10-element Vector{String}:
 "BROWNDEN"
 "HS5"
 "HS6"
 "HS10"
 "HS11"
 "HS13"
 "HS14"
 "LINCON"
 "LINSV"
 "MGH01Feas"

julia> nlp = eval(Symbol(list[7]))()
HS14{Float64, Vector{Float64}}
  Problem name: HS14_manual
                  All variables: ████████████████████ 2                     All constraints: ████████████████████ 2     
                           free: ████████████████████ 2                                free: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
                          lower: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                               lower: ██████████⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 1     
                          upper: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                               upper: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
                        low/upp: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                             low/upp: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
                          fixed: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                               fixed: ██████████⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 1     
                         infeas: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                              infeas: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
            nnzh: ( 33.33% sparsity)   2                              linear: ██████████⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 1     
                                                                                  nonlinear: ██████████⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 1     
                                                                        nnzj: (  0.00% sparsity)   4     
                                                                    lin_nnzj: (  0.00% sparsity)   2     
                                                                    nln_nnzj: (  0.00% sparsity)   2     

  Counters:
                            obj: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                                grad: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                                cons: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
                       cons_lin: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                            cons_nln: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                                jcon: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
                          jgrad: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                                 jac: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                             jac_lin: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
                        jac_nln: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                               jprod: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                           jprod_lin: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
                      jprod_nln: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                              jtprod: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                          jtprod_lin: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
                     jtprod_nln: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                                hess: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                               hprod: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     
                          jhess: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0                              jhprod: ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 0     

julia> x = nlp.meta.x0
2-element Vector{Float64}:
 2.0
 2.0 

julia> # Evaluate constraints

julia> c = zeros(nlp.meta.ncon)
2-element Vector{Float64}:
 0.0
 0.0

julia> cons!(nlp, x, c)
2-element Vector{Float64}:
 -2.0
 -4.0

julia> println("c = ", c)
c = [-2.0, -4.0]

julia> rows = zeros(Int, nlp.meta.nnzj)
4-element Vector{Int64}:
 0
 0
 0
 0

julia> cols = zeros(Int, nlp.meta.nnzj)
4-element Vector{Int64}:
 0
 0
 0
 0

julia> jac_structure!(nlp, rows, cols)
([1, 1, 2, 2], [1, 2, 1, 2])

julia> vals = zeros(Float64, nlp.meta.nnzj)
4-element Vector{Float64}:
 0.0
 0.0
 0.0
 0.0

julia> jac_coord!(nlp, x, vals)
4-element Vector{Float64}:
  1.0
 -2.0
 -1.0
 -4.0

julia> println("Jacobian nonzero pattern (first 10):")
Jacobian nonzero pattern (first 10):

julia> println(hcat(rows[1:min(end,10)], cols[1:min(end,10)], vals[1:min(end,10)]))
[1.0 1.0 1.0; 1.0 2.0 -2.0; 2.0 1.0 -1.0; 2.0 2.0 -4.0]

julia> Jv = zeros(nlp.meta.ncon)
2-element Vector{Float64}:
 0.0
 0.0

julia> Jtv = zeros(nlp.meta.nvar)
2-element Vector{Float64}:
 0.0
 0.0

julia> J = jac_op!(nlp, x, Jv, Jtv) # returns a LinearOperator representing the Jacobian
Linear operator
  nrow: 2
  ncol: 2
  eltype: Float64
  symmetric: false
  hermitian: false
  nprod:   0
  ntprod:  0
  nctprod: 0

julia> v = randn(nlp.meta.nvar)
2-element Vector{Float64}:
 -1.148989035446583
  0.6191152110586652

julia> Jv_op = similar(Jv)
2-element Vector{Float64}:
 5.0e-324
 1.93e-322

julia> mul!(Jv_op, J, v)               # operator-based product
2-element Vector{Float64}:
 -2.3872194575639134
 -1.3274718087880777

julia> Jv_direct = zeros(nlp.meta.ncon)
2-element Vector{Float64}:
 0.0
 0.0

julia> jprod!(nlp, x, v, Jv_direct)    # direct Jacobian-vector product API
2-element Vector{Float64}:
 -2.3872194575639134
 -1.3274718087880777 

julia> println("||J*v (op) - J*v (jprod!)|| = ", norm(Jv_op - Jv_direct))
||J*v (op) - J*v (jprod!)|| = 0.0

julia> w = randn(nlp.meta.ncon)
2-element Vector{Float64}:
 -1.5406083071808867
  0.8299103859626343

julia> Jt_w_op = zeros(nlp.meta.nvar)
2-element Vector{Float64}:
 0.0
 0.0

julia> mul!(Jt_w_op, adjoint(J), w)
2-element Vector{Float64}:
 -2.370518693143521
 -0.23842492948876393

julia> Jt_w_direct = zeros(nlp.meta.nvar)
2-element Vector{Float64}:
 0.0
 0.0

julia> jtprod!(nlp, x, w, Jt_w_direct)
2-element Vector{Float64}:
 -2.370518693143521
 -0.23842492948876393

julia> println("||J' * w (op) - J' * w (jtprod!)|| = ", norm(Jt_w_op - Jt_w_direct))
||J' * w (op) - J' * w (jtprod!)|| = 0.0

Copilot AI review requested due to automatic review settings May 26, 2026 14:20
Copy link
Copy Markdown
Contributor

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

Note

Copilot was unable to run its full agentic suite in this review.

Adds a new Julia tutorial demonstrating how to inspect and multiply by the constraint Jacobian using the NLPModels “linear API” and LinearOperators, along with a dedicated tutorial environment.

Changes:

  • Add a linear-api tutorial showing cons!, Jacobian sparsity/coords, and jac_op! usage
  • Add a Project.toml defining dependencies/compat for running the tutorial

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
tutorials/linear-api/index.jmd New tutorial content demonstrating Jacobian inspection and operator products
tutorials/linear-api/Project.toml New Julia tutorial environment with deps/compat bounds

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

Comment thread tutorials/linear-api/index.jmd Outdated
Comment thread tutorials/linear-api/index.jmd Outdated
Comment thread tutorials/linear-api/index.jmd Outdated
Comment thread tutorials/linear-api/index.jmd Outdated
Comment thread tutorials/linear-api/Project.toml
arnavk23 and others added 2 commits May 26, 2026 19:58
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@arnavk23
Copy link
Copy Markdown
Contributor Author

@tmigot Whenever you are free, please take a look. Thanks!

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 tutorial about the linear API

2 participants