From 53f4e71f124dbe92ebba8a101444bcb22ab22766 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Thu, 18 Dec 2025 15:42:58 +1300 Subject: [PATCH] Change dual_check default to whether model is supported by Dualization --- src/Feasibility/analyze.jl | 43 ++++++++++---------------------------- src/Feasibility/structs.jl | 8 +++---- test/test_Numerical.jl | 1 - 3 files changed, 15 insertions(+), 37 deletions(-) diff --git a/src/Feasibility/analyze.jl b/src/Feasibility/analyze.jl index 65eccdb..18f6c60 100644 --- a/src/Feasibility/analyze.jl +++ b/src/Feasibility/analyze.jl @@ -12,27 +12,16 @@ function MathOptAnalyzer.analyze( dual_objective::Union{Nothing,Float64} = nothing, atol::Float64 = 1e-6, skip_missing::Bool = false, - dual_check = true, + dual_check::Bool = _can_dualize(model), ) - can_dualize = false - if dual_check - can_dualize = _can_dualize(model) - if !can_dualize - println( - "The model cannot be dualized. Automatically setting `dual_check = false`.", - ) - dual_check = false - end - end - - data = Data( - primal_point = primal_point, - dual_point = dual_point, - primal_objective = primal_objective, - dual_objective = dual_objective, - atol = atol, - skip_missing = skip_missing, - dual_check = dual_check, + data = Data(; + primal_point, + dual_point, + primal_objective, + dual_objective, + atol, + skip_missing, + dual_check, ) if data.primal_point === nothing @@ -423,24 +412,14 @@ function _last_dual_solution(model::MOI.ModelLike) end function _can_dualize(model::MOI.ModelLike) - types = MOI.get(model, MOI.ListOfConstraintTypesPresent()) - - for (F, S) in types + for (F, S) in MOI.get(model, MOI.ListOfConstraintTypesPresent()) if !Dualization.supported_constraint(F, S) return false end end - F = MOI.get(model, MOI.ObjectiveFunctionType()) - if !Dualization.supported_objective(F) return false end - - sense = MOI.get(model, MOI.ObjectiveSense()) - if sense == MOI.FEASIBILITY_SENSE - return false - end - - return true + return MOI.get(model, MOI.ObjectiveSense()) != MOI.FEASIBILITY_SENSE end diff --git a/src/Feasibility/structs.jl b/src/Feasibility/structs.jl index 90ef6f9..baf52b8 100644 --- a/src/Feasibility/structs.jl +++ b/src/Feasibility/structs.jl @@ -20,7 +20,7 @@ julia> data = MathOptAnalyzer.analyze( dual_objective::Union{Nothing, Float64} = nothing, atol::Float64 = 1e-6, skip_missing::Bool = false, - dual_check = true, + dual_check::Bool = true, ); ``` @@ -39,9 +39,9 @@ The additional parameters: - `atol`: The absolute tolerance for feasibility checking. - `skip_missing`: If `true`, constraints with missing variables in the provided point will be ignored. -- `dual_check`: If `true`, it will perform dual feasibility checking. Disabling - the dual check will also disable complementarity checking and dual objective - checks. +- `dual_check`: If `true`, it will perform dual feasibility checking if the + model is compatible with Dualization.jl. Disabling the dual check will also + disable complementarity checking and dual objective checks. """ struct Analyzer <: MathOptAnalyzer.AbstractAnalyzer end diff --git a/test/test_Numerical.jl b/test/test_Numerical.jl index 0a74f4f..45940ef 100644 --- a/test/test_Numerical.jl +++ b/test/test_Numerical.jl @@ -1546,7 +1546,6 @@ function test_dyn_range_objective() data, MathOptAnalyzer.Numerical.LargeDynamicRangeObjective, ) - @show ret @test length(ret) == 1 @test MathOptAnalyzer.variables(ret[], model) == [x, y] @test MathOptAnalyzer.values(ret[]) == [1e-4, 7e4]