diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8517f10..ed76da2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,6 +32,13 @@ jobs: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - uses: julia-actions/cache@v1 + - name: dev + shell: julia --project=@. {0} + run: | + using Pkg + Pkg.add([ + PackageSpec(name="MathOptInterface", rev="bl/nonlinear_model"), + ]) - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 with: diff --git a/Project.toml b/Project.toml index b3919b8..c2b5857 100644 --- a/Project.toml +++ b/Project.toml @@ -3,6 +3,7 @@ uuid = "76087f3c-5699-56af-9a33-bf431cd00edd" version = "1.2.1" [deps] +ArrayDiff = "c45fa1ca-6901-44ac-ae5b-5513a4852d50" CEnum = "fa961155-64e5-5f13-b03f-caf6b980ea82" MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" NLopt_jll = "079eb43e-fd8e-5478-9966-2cf3e3edb778" diff --git a/ext/NLoptMathOptInterfaceExt.jl b/ext/NLoptMathOptInterfaceExt.jl index 050b86c..2552647 100644 --- a/ext/NLoptMathOptInterfaceExt.jl +++ b/ext/NLoptMathOptInterfaceExt.jl @@ -5,6 +5,7 @@ module NLoptMathOptInterfaceExt +import ArrayDiff import MathOptInterface as MOI import NLopt @@ -31,7 +32,7 @@ mutable struct Optimizer <: MOI.AbstractOptimizer variables::MOI.Utilities.VariablesContainer{Float64} starting_values::Vector{Union{Nothing,Float64}} nlp_data::MOI.NLPBlockData - nlp_model::Union{Nothing,MOI.Nonlinear.Model} + nlp_model::Union{Nothing,MOI.Nonlinear.Model,ArrayDiff.Model} ad_backend::MOI.Nonlinear.AbstractAutomaticDifferentiation sense::Union{Nothing,MOI.OptimizationSense} objective::Union{ @@ -598,7 +599,7 @@ function _init_nlp_model(model) if !(model.nlp_data.evaluator isa _EmptyNLPEvaluator) error("Cannot mix the new and legacy nonlinear APIs") end - model.nlp_model = MOI.Nonlinear.Model() + model.nlp_model = ArrayDiff.model(model.ad_backend) end return end diff --git a/test/MOI_wrapper.jl b/test/MOI_wrapper.jl index 63e38f6..a0d3a5c 100644 --- a/test/MOI_wrapper.jl +++ b/test/MOI_wrapper.jl @@ -361,6 +361,30 @@ function test_ListOfSupportedNonlinearOperators() return end +function test_ScalarNonlinearFunction_SymbolicMode() + # Test that the AutomaticDifferentiationBackend is used when building the + # evaluator. SymbolicMode is a built-in alternative to SparseReverseMode. + model = NLopt.Optimizer() + MOI.set(model, MOI.RawOptimizerAttribute("algorithm"), :LD_LBFGS) + MOI.set( + model, + MOI.AutomaticDifferentiationBackend(), + MOI.Nonlinear.SymbolicMode(), + ) + x = MOI.add_variable(model) + MOI.set(model, MOI.VariablePrimalStart(), x, 2.0) + # min (x - 1)^2 => x* = 1 + f = MOI.ScalarNonlinearFunction( + :^, + Any[MOI.ScalarNonlinearFunction(:-, Any[x, 1.0]), 2.0], + ) + MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE) + MOI.set(model, MOI.ObjectiveFunction{MOI.ScalarNonlinearFunction}(), f) + MOI.optimize!(model) + @test isapprox(MOI.get(model, MOI.VariablePrimal(), x), 1.0; atol = 1e-4) + return +end + end # module TestMOIWrapper.runtests()