@@ -108,6 +108,28 @@ function _dual_objective_value(
108108 return set_dot (constant, dual, set)
109109end
110110
111+ function _dual_objective_value (
112+ model:: MOI.ModelLike ,
113+ ci:: MOI.ConstraintIndex{<:MOI.AbstractVectorFunction,<:MOI.HyperRectangle} ,
114+ :: Type{T} ,
115+ result_index:: Integer ,
116+ ) where {T}
117+ func_constant = MOI. constant (MOI. get (model, MOI. ConstraintFunction (), ci), T)
118+ set = MOI. get (model, MOI. ConstraintSet (), ci)
119+ dual = MOI. get (model, MOI. ConstraintDual (result_index), ci)
120+ constant = map (eachindex (func_constant)) do i
121+ func_constant[i] - if dual[i] < zero (dual[i])
122+ # The dual is negative so it is in the dual of the MOI.LessThan cone
123+ # hence the upper bound of the Interval set is tight
124+ set. upper[i]
125+ else
126+ # the lower bound is tight
127+ set. lower[i]
128+ end
129+ end
130+ return set_dot (constant, dual, set)
131+ end
132+
111133function _dual_objective_value (
112134 model:: MOI.ModelLike ,
113135 :: Type{F} ,
@@ -116,23 +138,18 @@ function _dual_objective_value(
116138 result_index:: Integer ,
117139) where {T,F<: MOI.AbstractFunction ,S<: MOI.AbstractSet }
118140 value = zero (T)
141+ if F == variable_function_type (S) && ! _has_constant (S)
142+ return value # Shortcut
143+ end
119144 for ci in MOI. get (model, MOI. ListOfConstraintIndices {F,S} ())
120145 value += _dual_objective_value (model, ci, T, result_index)
121146 end
122147 return value
123148end
124149
125- function _dual_objective_value (
126- :: MOI.ModelLike ,
127- :: Type{MOI.VectorOfVariables} ,
128- :: Type{<:MOI.AbstractVectorSet} ,
129- :: Type{T} ,
130- :: Integer ,
131- ) where {T}
132- # No constant in the function nor set so no contribution to the dual
133- # objective value.
134- return zero (T)
135- end
150+ _has_constant (:: Type{<:MOI.AbstractScalarSet} ) = true
151+ _has_constant (:: Type{<:MOI.AbstractVectorSet} ) = false
152+ _has_constant (:: Type{<:MOI.HyperRectangle} ) = true
136153
137154"""
138155 get_fallback(
0 commit comments