diff --git a/src/moi_nlp_model.jl b/src/moi_nlp_model.jl index 2e0469d..63e6745 100644 --- a/src/moi_nlp_model.jl +++ b/src/moi_nlp_model.jl @@ -59,6 +59,8 @@ function MathOptNLPModel(jmodel::JuMP.Model; hessian::Bool = true, name::String nnzj = nnzj, nnzh = nnzh, lin = collect(1:nlin), + lin_nnzj = lincon.nnzj, + nln_nnzj = nl_nnzj, minimize = objective_sense(jmodel) == MOI.MIN_SENSE, islp = (obj.type == "LINEAR") && (nnln == 0), name = name, @@ -99,55 +101,61 @@ function NLPModels.grad!(nlp::MathOptNLPModel, x::AbstractVector, g::AbstractVec return g end -function NLPModels.cons!(nlp::MathOptNLPModel, x::AbstractVector, c::AbstractVector) - increment!(nlp, :neval_cons) - if nlp.meta.nlin > 0 - coo_prod!( - nlp.lincon.jacobian.rows, - nlp.lincon.jacobian.cols, - nlp.lincon.jacobian.vals, - x, - view(c, nlp.meta.lin), - ) - end - if nlp.meta.nnln > 0 - MOI.eval_constraint(nlp.eval, view(c, nlp.meta.nln), x) - end +function NLPModels.cons_lin!(nlp::MathOptNLPModel, x::AbstractVector, c::AbstractVector) + increment!(nlp, :neval_cons_lin) + coo_prod!( + nlp.lincon.jacobian.rows, + nlp.lincon.jacobian.cols, + nlp.lincon.jacobian.vals, + x, + c, + ) return c end -function NLPModels.jac_structure!( +function NLPModels.cons_nln!(nlp::MathOptNLPModel, x::AbstractVector, c::AbstractVector) + increment!(nlp, :neval_cons_nln) + MOI.eval_constraint(nlp.eval, c, x) + return c +end + +function NLPModels.jac_lin_structure!( nlp::MathOptNLPModel, rows::AbstractVector{<:Integer}, cols::AbstractVector{<:Integer}, ) - if nlp.meta.nlin > 0 - rows[1:(nlp.lincon.nnzj)] .= nlp.lincon.jacobian.rows[1:(nlp.lincon.nnzj)] - cols[1:(nlp.lincon.nnzj)] .= nlp.lincon.jacobian.cols[1:(nlp.lincon.nnzj)] - end - if nlp.meta.nnln > 0 - jac_struct = MOI.jacobian_structure(nlp.eval) - for index = (nlp.lincon.nnzj + 1):(nlp.meta.nnzj) - row, col = jac_struct[index - nlp.lincon.nnzj] - rows[index] = nlp.meta.nlin + row - cols[index] = col - end - end + rows[1:(nlp.lincon.nnzj)] .= nlp.lincon.jacobian.rows[1:(nlp.lincon.nnzj)] + cols[1:(nlp.lincon.nnzj)] .= nlp.lincon.jacobian.cols[1:(nlp.lincon.nnzj)] return rows, cols end -function NLPModels.jac_coord!(nlp::MathOptNLPModel, x::AbstractVector, vals::AbstractVector) - increment!(nlp, :neval_jac) - if nlp.meta.nlin > 0 - vals[1:(nlp.lincon.nnzj)] .= nlp.lincon.jacobian.vals[1:(nlp.lincon.nnzj)] - end - if nlp.meta.nnln > 0 - MOI.eval_constraint_jacobian(nlp.eval, view(vals, (nlp.lincon.nnzj + 1):(nlp.meta.nnzj)), x) +function NLPModels.jac_nln_structure!( + nlp::MathOptNLPModel, + rows::AbstractVector{<:Integer}, + cols::AbstractVector{<:Integer}, +) + jac_struct = MOI.jacobian_structure(nlp.eval) + for index = 1:(nlp.meta.nln_nnzj) + row, col = jac_struct[index] + rows[index] = row + cols[index] = col end + return rows, cols +end + +function NLPModels.jac_lin_coord!(nlp::MathOptNLPModel, x::AbstractVector, vals::AbstractVector) + increment!(nlp, :neval_jac_lin) + vals[1:(nlp.lincon.nnzj)] .= nlp.lincon.jacobian.vals[1:(nlp.lincon.nnzj)] return vals end -function NLPModels.jprod!( +function NLPModels.jac_nln_coord!(nlp::MathOptNLPModel, x::AbstractVector, vals::AbstractVector) + increment!(nlp, :neval_jac_nln) + MOI.eval_constraint_jacobian(nlp.eval, vals, x) + return vals +end + +function NLPModels.jprod_lin!( nlp::MathOptNLPModel, x::AbstractVector, rows::AbstractVector{<:Integer}, @@ -155,20 +163,45 @@ function NLPModels.jprod!( v::AbstractVector, Jv::AbstractVector, ) - vals = jac_coord(nlp, x) - decrement!(nlp, :neval_jac) - jprod!(nlp, rows, cols, vals, v, Jv) + vals = jac_lin_coord(nlp, x) + decrement!(nlp, :neval_jac_lin) + jprod_lin!(nlp, rows, cols, vals, v, Jv) + return Jv +end + +function NLPModels.jprod_nln!( + nlp::MathOptNLPModel, + x::AbstractVector, + rows::AbstractVector{<:Integer}, + cols::AbstractVector{<:Integer}, + v::AbstractVector, + Jv::AbstractVector, +) + vals = jac_nln_coord(nlp, x) + decrement!(nlp, :neval_jac_nln) + jprod_nln!(nlp, rows, cols, vals, v, Jv) + return Jv +end + +function NLPModels.jprod_lin!( + nlp::MathOptNLPModel, + x::AbstractVector, + v::AbstractVector, + Jv::AbstractVector, +) + rows, cols = jac_lin_structure(nlp) + jprod_lin!(nlp, x, rows, cols, v, Jv) return Jv end -function NLPModels.jprod!( +function NLPModels.jprod_nln!( nlp::MathOptNLPModel, x::AbstractVector, v::AbstractVector, Jv::AbstractVector, ) - rows, cols = jac_structure(nlp) - jprod!(nlp, x, rows, cols, v, Jv) + rows, cols = jac_nln_structure(nlp) + jprod_nln!(nlp, x, rows, cols, v, Jv) return Jv end @@ -197,6 +230,56 @@ function NLPModels.jtprod!( return Jtv end +function NLPModels.jtprod_lin!( + nlp::MathOptNLPModel, + x::AbstractVector, + rows::AbstractVector{<:Integer}, + cols::AbstractVector{<:Integer}, + v::AbstractVector, + Jtv::AbstractVector, +) + vals = jac_lin_coord(nlp, x) + decrement!(nlp, :neval_jac_lin) + jtprod_lin!(nlp, rows, cols, vals, v, Jtv) + return Jtv +end + +function NLPModels.jtprod_lin!( + nlp::MathOptNLPModel, + x::AbstractVector, + v::AbstractVector, + Jtv::AbstractVector, +) + (rows, cols) = jac_lin_structure(nlp) + jtprod_lin!(nlp, x, rows, cols, v, Jtv) + return Jtv +end + +function NLPModels.jtprod_nln!( + nlp::MathOptNLPModel, + x::AbstractVector, + rows::AbstractVector{<:Integer}, + cols::AbstractVector{<:Integer}, + v::AbstractVector, + Jtv::AbstractVector, +) + vals = jac_nln_coord(nlp, x) + decrement!(nlp, :neval_jac_nln) + jtprod_nln!(nlp, rows, cols, vals, v, Jtv) + return Jtv +end + +function NLPModels.jtprod_nln!( + nlp::MathOptNLPModel, + x::AbstractVector, + v::AbstractVector, + Jtv::AbstractVector, +) + (rows, cols) = jac_nln_structure(nlp) + jtprod_nln!(nlp, x, rows, cols, v, Jtv) + return Jtv +end + # Uncomment when :JacVec becomes available in MOI. # # function NLPModels.jprod!(nlp :: MathOptNLPModel, x :: AbstractVector, v :: AbstractVector, Jv :: AbstractVector) diff --git a/src/moi_nls_model.jl b/src/moi_nls_model.jl index 1bec46a..29bf10b 100644 --- a/src/moi_nls_model.jl +++ b/src/moi_nls_model.jl @@ -64,6 +64,8 @@ function MathOptNLSModel(cmodel::JuMP.Model, F; hessian::Bool = true, name::Stri nnzj = cnnzj, nnzh = cnnzh, lin = collect(1:nlin), + lin_nnzj = lincon.nnzj, + nln_nnzj = nl_cnnzj, minimize = objective_sense(cmodel) == MOI.MIN_SENSE, islp = false, name = name, @@ -282,55 +284,61 @@ function NLPModels.grad!(nls::MathOptNLSModel, x::AbstractVector, g::AbstractVec return g end -function NLPModels.cons!(nls::MathOptNLSModel, x::AbstractVector, c::AbstractVector) - increment!(nls, :neval_cons) - if nls.meta.nlin > 0 - coo_prod!( - nls.lincon.jacobian.rows, - nls.lincon.jacobian.cols, - nls.lincon.jacobian.vals, - x, - view(c, nls.meta.lin), - ) - end - if nls.meta.nnln > 0 - MOI.eval_constraint(nls.ceval, view(c, nls.meta.nln), x) - end +function NLPModels.cons_lin!(nls::MathOptNLSModel, x::AbstractVector, c::AbstractVector) + increment!(nls, :neval_cons_lin) + coo_prod!( + nls.lincon.jacobian.rows, + nls.lincon.jacobian.cols, + nls.lincon.jacobian.vals, + x, + c, + ) return c end -function NLPModels.jac_structure!( +function NLPModels.cons_nln!(nls::MathOptNLSModel, x::AbstractVector, c::AbstractVector) + increment!(nls, :neval_cons_nln) + MOI.eval_constraint(nls.ceval, c, x) + return c +end + +function NLPModels.jac_lin_structure!( nls::MathOptNLSModel, rows::AbstractVector{<:Integer}, cols::AbstractVector{<:Integer}, ) - if nls.meta.nlin > 0 - rows[1:(nls.lincon.nnzj)] .= nls.lincon.jacobian.rows[1:(nls.lincon.nnzj)] - cols[1:(nls.lincon.nnzj)] .= nls.lincon.jacobian.cols[1:(nls.lincon.nnzj)] - end - if nls.meta.nnln > 0 - jac_struct = MOI.jacobian_structure(nls.ceval) - for index = (nls.lincon.nnzj + 1):(nls.meta.nnzj) - row, col = jac_struct[index - nls.lincon.nnzj] - rows[index] = nls.meta.nlin + row - cols[index] = col - end - end + rows[1:(nls.lincon.nnzj)] .= nls.lincon.jacobian.rows[1:(nls.lincon.nnzj)] + cols[1:(nls.lincon.nnzj)] .= nls.lincon.jacobian.cols[1:(nls.lincon.nnzj)] return rows, cols end -function NLPModels.jac_coord!(nls::MathOptNLSModel, x::AbstractVector, vals::AbstractVector) - increment!(nls, :neval_jac) - if nls.meta.nlin > 0 - vals[1:(nls.lincon.nnzj)] .= nls.lincon.jacobian.vals[1:(nls.lincon.nnzj)] - end - if nls.meta.nnln > 0 - MOI.eval_constraint_jacobian(nls.ceval, view(vals, (nls.lincon.nnzj + 1):(nls.meta.nnzj)), x) +function NLPModels.jac_nln_structure!( + nls::MathOptNLSModel, + rows::AbstractVector{<:Integer}, + cols::AbstractVector{<:Integer}, +) + jac_struct = MOI.jacobian_structure(nls.ceval) + for index = 1:(nls.meta.nln_nnzj) + row, col = jac_struct[index] + rows[index] = row + cols[index] = col end + return rows, cols +end + +function NLPModels.jac_lin_coord!(nls::MathOptNLSModel, x::AbstractVector, vals::AbstractVector) + increment!(nls, :neval_jac_lin) + vals[1:(nls.lincon.nnzj)] .= nls.lincon.jacobian.vals[1:(nls.lincon.nnzj)] return vals end -function NLPModels.jprod!( +function NLPModels.jac_nln_coord!(nls::MathOptNLSModel, x::AbstractVector, vals::AbstractVector) + increment!(nls, :neval_jac_nln) + MOI.eval_constraint_jacobian(nls.ceval, vals, x) + return vals +end + +function NLPModels.jprod_lin!( nls::MathOptNLSModel, x::AbstractVector, rows::AbstractVector{<:Integer}, @@ -338,20 +346,45 @@ function NLPModels.jprod!( v::AbstractVector, Jv::AbstractVector, ) - vals = jac_coord(nls, x) - decrement!(nls, :neval_jac) - jprod!(nls, rows, cols, vals, v, Jv) + vals = jac_lin_coord(nls, x) + decrement!(nls, :neval_jac_lin) + jprod_lin!(nls, rows, cols, vals, v, Jv) + return Jv +end + +function NLPModels.jprod_nln!( + nls::MathOptNLSModel, + x::AbstractVector, + rows::AbstractVector{<:Integer}, + cols::AbstractVector{<:Integer}, + v::AbstractVector, + Jv::AbstractVector, +) + vals = jac_nln_coord(nls, x) + decrement!(nls, :neval_jac_nln) + jprod_nln!(nls, rows, cols, vals, v, Jv) + return Jv +end + +function NLPModels.jprod_lin!( + nls::MathOptNLSModel, + x::AbstractVector, + v::AbstractVector, + Jv::AbstractVector, +) + rows, cols = jac_lin_structure(nls) + jprod_lin!(nls, x, rows, cols, v, Jv) return Jv end -function NLPModels.jprod!( +function NLPModels.jprod_nln!( nls::MathOptNLSModel, x::AbstractVector, v::AbstractVector, Jv::AbstractVector, ) - rows, cols = jac_structure(nls) - jprod!(nls, x, rows, cols, v, Jv) + rows, cols = jac_nln_structure(nls) + jprod_nln!(nls, x, rows, cols, v, Jv) return Jv end @@ -380,6 +413,56 @@ function NLPModels.jtprod!( return Jtv end +function NLPModels.jtprod_lin!( + nls::MathOptNLSModel, + x::AbstractVector, + rows::AbstractVector{<:Integer}, + cols::AbstractVector{<:Integer}, + v::AbstractVector, + Jtv::AbstractVector, +) + vals = jac_lin_coord(nls, x) + decrement!(nls, :neval_jac_lin) + jtprod_lin!(nls, rows, cols, vals, v, Jtv) + return Jtv +end + +function NLPModels.jtprod_lin!( + nls::MathOptNLSModel, + x::AbstractVector, + v::AbstractVector, + Jtv::AbstractVector, +) + (rows, cols) = jac_lin_structure(nls) + jtprod_lin!(nls, x, rows, cols, v, Jtv) + return Jtv +end + +function NLPModels.jtprod_nln!( + nls::MathOptNLSModel, + x::AbstractVector, + rows::AbstractVector{<:Integer}, + cols::AbstractVector{<:Integer}, + v::AbstractVector, + Jtv::AbstractVector, +) + vals = jac_nln_coord(nls, x) + decrement!(nls, :neval_jac_nln) + jtprod_nln!(nls, rows, cols, vals, v, Jtv) + return Jtv +end + +function NLPModels.jtprod_nln!( + nls::MathOptNLSModel, + x::AbstractVector, + v::AbstractVector, + Jtv::AbstractVector, +) + (rows, cols) = jac_nln_structure(nls) + jtprod_nln!(nls, x, rows, cols, v, Jtv) + return Jtv +end + # Uncomment when :JacVec becomes available in MOI. # # function NLPModels.jprod!(nls :: MathOptNLSModel, x :: AbstractVector, v :: AbstractVector, Jv :: AbstractVector)