From 2e84ecde02c5197c1b48b6bb181d67a427ab0f73 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Fri, 29 Nov 2024 13:34:43 +1300 Subject: [PATCH] Add support for ConstraintPrimal of nonlinear constraints (#593) --- src/MOI_wrapper/MOI_nonlinear.jl | 23 ++++++++++++++++++++ test/MOI/MOI_wrapper.jl | 36 +++++++++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/MOI_wrapper/MOI_nonlinear.jl b/src/MOI_wrapper/MOI_nonlinear.jl index 976098c..3403e63 100644 --- a/src/MOI_wrapper/MOI_nonlinear.jl +++ b/src/MOI_wrapper/MOI_nonlinear.jl @@ -448,3 +448,26 @@ function MOI.set( model.name_to_constraint_index = nothing return end + +function MOI.get( + model::Optimizer, + attr::MOI.ConstraintPrimal, + c::MOI.ConstraintIndex{MOI.ScalarNonlinearFunction}, +) + _throw_if_optimize_in_progress(model, attr) + MOI.check_result_index_bounds(model, attr) + info = _info(model, c) + key = "X" + if attr.result_index > 1 + MOI.set( + model, + MOI.RawOptimizerAttribute("SolutionNumber"), + attr.result_index - 1, + ) + key = "Xn" + end + valueP = Ref{Cdouble}() + ret = GRBgetdblattrelement(model, key, Cint(info.resvar_index - 1), valueP) + _check_ret(model, ret) + return valueP[] +end diff --git a/test/MOI/MOI_wrapper.jl b/test/MOI/MOI_wrapper.jl index b8d43f5..361931a 100644 --- a/test/MOI/MOI_wrapper.jl +++ b/test/MOI/MOI_wrapper.jl @@ -69,9 +69,6 @@ function test_runtests() # Timeouts r"^test_nonlinear_expression_hs109$", r"^test_nonlinear_expression_hs110$", - # MOI.get(MOI.ObjectiveValue()) fails for NL objectives - r"^test_nonlinear_expression_quartic$", - r"^test_nonlinear_expression_overrides_objective$", # Nonlinear duals not computed r"^test_nonlinear_duals$", ], @@ -1478,6 +1475,39 @@ function test_scalar_quadratic_function_with_off_diag_in_scalar_nonlinear() return end +function test_multiple_solution_nonlinear_objective() + if !Gurobi._supports_nonlinear() + return + end + model = + MOI.Bridges.full_bridge_optimizer(Gurobi.Optimizer(GRB_ENV), Float64) + N = 30 + x = MOI.add_variables(model, N) + MOI.add_constraints(model, x, MOI.ZeroOne()) + MOI.set.(model, MOI.VariablePrimalStart(), x, 0.0) + item_weights = sin.(1:N) + MOI.add_constraint( + model, + MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(item_weights, x), 0.0), + MOI.LessThan(10.0), + ) + f = MOI.ScalarNonlinearFunction( + :+, + Any[MOI.ScalarNonlinearFunction(:exp, Any[x[i]]) for i in 1:N], + ) + MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE) + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + MOI.optimize!(model) + count = MOI.get(model, MOI.ResultCount()) + @test count > 1 + for i in 1:count + x_val = MOI.get.(model, MOI.VariablePrimal(i), x) + obj_val = MOI.get(model, MOI.ObjectiveValue(i)) + @test isapprox(obj_val, sum(exp.(x_val)); atol = 1e-6) + end + return +end + end # TestMOIWrapper TestMOIWrapper.runtests()