From ac38f0d301b538c70dd49ca4cee2948a8bb385c0 Mon Sep 17 00:00:00 2001 From: Alexis Montoison Date: Wed, 22 Jan 2025 20:35:59 -0600 Subject: [PATCH 1/7] Support MOI.VectorNonlinearFunction --- src/MOI_wrapper.jl | 5 +++-- src/utils.jl | 15 ++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/MOI_wrapper.jl b/src/MOI_wrapper.jl index a0104fa..5659de5 100644 --- a/src/MOI_wrapper.jl +++ b/src/MOI_wrapper.jl @@ -79,12 +79,13 @@ end ### `supports_constraint` ### -MOI.supports_constraint(::Optimizer, ::Type{VI}, ::Type{<:ALS}) = true +MOI.supports_constraint(::Optimizer, ::Type{VI} , ::Type{<:ALS}) = true MOI.supports_constraint(::Optimizer, ::Type{SAF}, ::Type{<:ALS}) = true -MOI.supports_constraint(::Optimizer, ::Type{MOI.ScalarNonlinearFunction}, ::Type{<:ALS}) = true MOI.supports_constraint(::Optimizer, ::Type{VAF}, ::Type{<:VLS}) = true MOI.supports_constraint(::Optimizer, ::Type{SQF}, ::Type{<:ALS}) = true MOI.supports_constraint(::Optimizer, ::Type{VQF}, ::Type{<:VLS}) = true +MOI.supports_constraint(::Optimizer, ::Type{SNF}, ::Type{<:ALS}) = true +MOI.supports_constraint(::Optimizer, ::Type{VNF}, ::Type{<:VLS}) = true function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike) if !haskey(dest.options, "solver") diff --git a/src/utils.jl b/src/utils.jl index 423cefc..dc5290a 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -19,6 +19,11 @@ const SQF = MOI.ScalarQuadraticFunction{Float64} # ScalarQuadraticFunction{T}(a const VQF = MOI.VectorQuadraticFunction{Float64} # VectorQuadraticFunction{T}(affine_terms, quadratic_terms, constants) const QF = Union{SQF, VQF} +# ScalarNonlinearFunction and VectorNonlinearFunction +const SNF = MOI.ScalarNonlinearFunction +const VNF = MOI.VectorNonlinearFunction +const NF = Union{SNF, VNF} + # AffLinSets and VecLinSets const ALS = Union{ MOI.EqualTo{Float64}, @@ -375,11 +380,7 @@ function parser_MOI(moimodel, index_map, nvar) contypes = MOI.get(moimodel, MOI.ListOfConstraintTypesPresent()) for (F, S) in contypes - F <: AF || - F <: QF || - F == MOI.ScalarNonlinearFunction || - F == VI || - error("Function $F is not supported.") + F <: AF || F <: QF || F == NF || F == VI || error("Function $F is not supported.") S <: LS || error("Set $S is not supported.") conindices = MOI.get(moimodel, MOI.ListOfConstraintIndices{F, S}()) @@ -431,7 +432,7 @@ _nlp_model(::MOI.Nonlinear.Model, ::MOI.ModelLike, ::Type, ::Type) = false function _nlp_model( dest::MOI.Nonlinear.Model, src::MOI.ModelLike, - F::Type{<:Union{MOI.ScalarNonlinearFunction, MOI.VectorNonlinearFunction}}, + F::Type{<:NF}, S::Type, ) has_nonlinear = false @@ -460,7 +461,7 @@ function _nlp_model(model::MOI.ModelLike)::Union{Nothing, MOI.Nonlinear.Model} has_nonlinear |= _nlp_model(nlp_model, model, F, S) end F = MOI.get(model, MOI.ObjectiveFunctionType()) - if F <: MOI.ScalarNonlinearFunction + if F <: SNF MOI.Nonlinear.set_objective(nlp_model, MOI.get(model, MOI.ObjectiveFunction{F}())) has_nonlinear = true end From a0a514393807dadd85292a57f7895b2be7a54b4a Mon Sep 17 00:00:00 2001 From: Alexis Montoison Date: Wed, 22 Jan 2025 20:44:47 -0600 Subject: [PATCH 2/7] Fix utils.jl --- src/utils.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.jl b/src/utils.jl index dc5290a..9669874 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -380,7 +380,7 @@ function parser_MOI(moimodel, index_map, nvar) contypes = MOI.get(moimodel, MOI.ListOfConstraintTypesPresent()) for (F, S) in contypes - F <: AF || F <: QF || F == NF || F == VI || error("Function $F is not supported.") + F <: AF || F <: QF || F <: NF || F == VI || error("Function $F is not supported.") S <: LS || error("Set $S is not supported.") conindices = MOI.get(moimodel, MOI.ListOfConstraintIndices{F, S}()) From 6045989aef290d9d3e7683a91d6883c0a9ef01fa Mon Sep 17 00:00:00 2001 From: Alexis Montoison Date: Wed, 22 Jan 2025 21:24:14 -0600 Subject: [PATCH 3/7] Add a unit test for the support of VectorNonlinearFunction --- test/nlp_problems/nf.jl | 10 ++++++++++ test/runtests.jl | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 test/nlp_problems/nf.jl diff --git a/test/nlp_problems/nf.jl b/test/nlp_problems/nf.jl new file mode 100644 index 0000000..c1ab162 --- /dev/null +++ b/test/nlp_problems/nf.jl @@ -0,0 +1,10 @@ +function nf() + f(x::Vector{VariableRef}) = sqrt.(x) + g(x::Vector{VariableRef}) = x.^3 + h(x::Vector{VariableRef}) = sum(x.^4) + nlp = Model() + @variable(nlp, x[1:2]) + @constraint(nlp, f(x) .- g(x) in MOI.Nonnegatives(2)) + @objective(nlp, Max, h(x)) + return nlp +end diff --git a/test/runtests.jl b/test/runtests.jl index deae221..7125c6d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -5,7 +5,7 @@ using Test, Printf nlp_problems = setdiff(NLPModelsTest.nlp_problems, ["MGH01Feas"]) nls_problems = NLPModelsTest.nls_problems -extra_nlp_problems = ["nohesspb", "hs61", "hs100", "hs219", "quadcon", "operatorspb"] +extra_nlp_problems = ["nohesspb", "hs61", "hs100", "hs219", "quadcon", "operatorspb", "nf"] extra_nls_problems = ["nlsnohesspb", "HS30", "HS43", "MGH07", "nlsqc"] for problem in lowercase.(nlp_problems ∪ extra_nlp_problems) From c3e0882a8af167bf9f5adfa937597ccdbc6b4ce1 Mon Sep 17 00:00:00 2001 From: Alexis Montoison Date: Thu, 23 Jan 2025 10:11:26 -0600 Subject: [PATCH 4/7] Improve the error message for VectorNonlinearFunction --- src/MOI_wrapper.jl | 1 - src/utils.jl | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/MOI_wrapper.jl b/src/MOI_wrapper.jl index 5659de5..d0a1891 100644 --- a/src/MOI_wrapper.jl +++ b/src/MOI_wrapper.jl @@ -85,7 +85,6 @@ MOI.supports_constraint(::Optimizer, ::Type{VAF}, ::Type{<:VLS}) = true MOI.supports_constraint(::Optimizer, ::Type{SQF}, ::Type{<:ALS}) = true MOI.supports_constraint(::Optimizer, ::Type{VQF}, ::Type{<:VLS}) = true MOI.supports_constraint(::Optimizer, ::Type{SNF}, ::Type{<:ALS}) = true -MOI.supports_constraint(::Optimizer, ::Type{VNF}, ::Type{<:VLS}) = true function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike) if !haskey(dest.options, "solver") diff --git a/src/utils.jl b/src/utils.jl index 9669874..bafef54 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -380,7 +380,8 @@ function parser_MOI(moimodel, index_map, nvar) contypes = MOI.get(moimodel, MOI.ListOfConstraintTypesPresent()) for (F, S) in contypes - F <: AF || F <: QF || F <: NF || F == VI || error("Function $F is not supported.") + (F == VNF) && error("The function $F is not supported. Please use `.<=`, `.==`, and `.>=` in your constraints to ensure compatibility with ScalarAffineFunction.") + F <: AF || F <: QF || F == SNF || F == VI || error("Function $F is not supported.") S <: LS || error("Set $S is not supported.") conindices = MOI.get(moimodel, MOI.ListOfConstraintIndices{F, S}()) @@ -432,7 +433,7 @@ _nlp_model(::MOI.Nonlinear.Model, ::MOI.ModelLike, ::Type, ::Type) = false function _nlp_model( dest::MOI.Nonlinear.Model, src::MOI.ModelLike, - F::Type{<:NF}, + F::Type{SNF}, S::Type, ) has_nonlinear = false From c017174e38f7aba099480da836595e8bf6f94ff1 Mon Sep 17 00:00:00 2001 From: Alexis Montoison Date: Thu, 23 Jan 2025 10:13:43 -0600 Subject: [PATCH 5/7] Update nf.jl --- test/nlp_problems/nf.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/nlp_problems/nf.jl b/test/nlp_problems/nf.jl index c1ab162..18ae532 100644 --- a/test/nlp_problems/nf.jl +++ b/test/nlp_problems/nf.jl @@ -4,7 +4,7 @@ function nf() h(x::Vector{VariableRef}) = sum(x.^4) nlp = Model() @variable(nlp, x[1:2]) - @constraint(nlp, f(x) .- g(x) in MOI.Nonnegatives(2)) + @constraint(nlp, f(x) .- g(x) .>= 0) @objective(nlp, Max, h(x)) return nlp end From ecd6974073480296c71b1bb0cebce8d7e64ceb9a Mon Sep 17 00:00:00 2001 From: Alexis Montoison <35051714+amontoison@users.noreply.github.com> Date: Thu, 23 Jan 2025 13:40:22 -0600 Subject: [PATCH 6/7] Update src/utils.jl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Benoît Legat --- src/utils.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.jl b/src/utils.jl index bafef54..221789e 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -380,7 +380,7 @@ function parser_MOI(moimodel, index_map, nvar) contypes = MOI.get(moimodel, MOI.ListOfConstraintTypesPresent()) for (F, S) in contypes - (F == VNF) && error("The function $F is not supported. Please use `.<=`, `.==`, and `.>=` in your constraints to ensure compatibility with ScalarAffineFunction.") + (F == VNF) && error("The function $F is not supported. Please use `.<=`, `.==`, and `.>=` in your constraints to ensure compatibility with ScalarNonlinearFunction.") F <: AF || F <: QF || F == SNF || F == VI || error("Function $F is not supported.") S <: LS || error("Set $S is not supported.") From 5b8619a8340fe0618bbf77f887ebaf9d431a6ead Mon Sep 17 00:00:00 2001 From: Alexis Montoison <35051714+amontoison@users.noreply.github.com> Date: Thu, 23 Jan 2025 13:40:30 -0600 Subject: [PATCH 7/7] Update src/MOI_wrapper.jl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Benoît Legat --- src/MOI_wrapper.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MOI_wrapper.jl b/src/MOI_wrapper.jl index d0a1891..9ec6d2c 100644 --- a/src/MOI_wrapper.jl +++ b/src/MOI_wrapper.jl @@ -79,7 +79,7 @@ end ### `supports_constraint` ### -MOI.supports_constraint(::Optimizer, ::Type{VI} , ::Type{<:ALS}) = true +MOI.supports_constraint(::Optimizer, ::Type{VI}, ::Type{<:ALS}) = true MOI.supports_constraint(::Optimizer, ::Type{SAF}, ::Type{<:ALS}) = true MOI.supports_constraint(::Optimizer, ::Type{VAF}, ::Type{<:VLS}) = true MOI.supports_constraint(::Optimizer, ::Type{SQF}, ::Type{<:ALS}) = true