I guess the related code are at
function _dual_objective_value(
model::MOI.ModelLike,
::Type{F},
::Type{S},
::Type{T},
result_index::Integer,
)::T where {T,F<:MOI.AbstractFunction,S<:MOI.AbstractSet}
value = zero(T)
if F == variable_function_type(S) && !_variable_set_in_dual_objective(S)
# Early return. This is a constraint like x in R_+, so no contribution
# appears in the dual objective.
return value
end
for ci in MOI.get(model, MOI.ListOfConstraintIndices{F,S}())
constant = MOI.constant(MOI.get(model, MOI.ConstraintFunction(), ci), T)
set = MOI.get(model, MOI.ConstraintSet(), ci)
dual = MOI.get(model, MOI.ConstraintDual(result_index), ci)
value += _dual_objective_dot(constant, dual, set)
end
return value
end
and
function MOI.get(
model::Optimizer,
attr::MOI.ConstraintDual,
c::MOI.ConstraintIndex{MOI.ScalarAffineFunction{Float64},<:Any},
)
_throw_if_optimize_in_progress(model, attr)
MOI.check_result_index_bounds(model, attr)
valueP = Ref{Cdouble}()
row = Cint(_info(model, c).row - 1)
if model.has_infeasibility_cert
ret = GRBgetdblattrelement(model, "FarkasDual", row, valueP)
_check_ret(model, ret)
return -valueP[]
end
ret = GRBgetdblattrelement(model, "Pi", row, valueP)
_check_ret(model, ret)
return _dual_multiplier(model) * valueP[]
end
and (This is in reduced_cost)
function _farkas_variable_dual(model::Optimizer, col::Cint)
numnzP = Ref{Cint}()
ret = GRBgetvars(model, numnzP, C_NULL, C_NULL, C_NULL, col, 1)
_check_ret(model, ret)
vbeg = Vector{Cint}(undef, 2)
vind = Vector{Cint}(undef, numnzP[])
vval = Vector{Cdouble}(undef, numnzP[])
ret = GRBgetvars(model, numnzP, vbeg, vind, vval, col, 1)
_check_ret(model, ret)
λ = Vector{Cdouble}(undef, numnzP[])
ret = GRBgetdblattrlist(model, "FarkasDual", length(vind), vind, λ)
_check_ret(model, ret)
return λ' * vval
end
. So I’d like to ask:
- Do you loop over all constraints in the 2nd-stage subproblem and query the
FarkasDual constraint attribute element-wise, in order to calculate the Benders’ feasibility cut?
If so, I think it’s a bit of involved.