Skip to content

Commit 4668895

Browse files
committed
[Utilities] simplify _dual_objective_value
1 parent 4a2641b commit 4668895

File tree

1 file changed

+56
-106
lines changed

1 file changed

+56
-106
lines changed

src/Utilities/results.jl

Lines changed: 56 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -52,112 +52,6 @@ end
5252

5353
# MOI.DualObjectiveValue
5454

55-
function _constraint_constant(
56-
model::MOI.ModelLike,
57-
ci::MOI.ConstraintIndex{
58-
<:MOI.AbstractVectorFunction,
59-
<:MOI.AbstractVectorSet,
60-
},
61-
::Type{T},
62-
) where {T}
63-
return MOI.constant(MOI.get(model, MOI.ConstraintFunction(), ci), T)
64-
end
65-
66-
function _constraint_constant(
67-
model::MOI.ModelLike,
68-
ci::MOI.ConstraintIndex{
69-
<:MOI.AbstractScalarFunction,
70-
<:MOI.AbstractScalarSet,
71-
},
72-
::Type{T},
73-
) where {T}
74-
return MOI.constant(MOI.get(model, MOI.ConstraintFunction(), ci), T) -
75-
MOI.constant(MOI.get(model, MOI.ConstraintSet(), ci))
76-
end
77-
78-
function _dual_objective_value(
79-
model::MOI.ModelLike,
80-
ci::MOI.ConstraintIndex,
81-
::Type{T},
82-
result_index::Integer,
83-
) where {T}
84-
return set_dot(
85-
_constraint_constant(model, ci, T),
86-
MOI.get(model, MOI.ConstraintDual(result_index), ci),
87-
MOI.get(model, MOI.ConstraintSet(), ci),
88-
)
89-
end
90-
91-
"""
92-
Given lower <= f(x) <= upper [dual], return the expression to be multiplied by
93-
the dual variable. This is one of the following cases:
94-
95-
1. f(x) - lower: if `lower > -Inf` and the lower bound is binding (either no
96-
`upper` or `dual > 0`)
97-
2. f(x) - upper: if `upper < Inf` and the upper bound is binding (either no
98-
`lower` or `dual < 0`)
99-
3. f(x): if `lower = -Inf` and `upper = Inf` or `dual = 0`
100-
"""
101-
function _constant_minus_bound(constant, lower, upper, dual)
102-
if isfinite(lower) && (!isfinite(upper) || dual > zero(dual))
103-
return constant - lower
104-
elseif isfinite(upper) && (!isfinite(lower) || dual < zero(dual))
105-
return constant - upper
106-
else
107-
return constant
108-
end
109-
end
110-
111-
function _dual_objective_value(
112-
model::MOI.ModelLike,
113-
ci::MOI.ConstraintIndex{<:MOI.AbstractScalarFunction,<:MOI.Interval},
114-
::Type{T},
115-
result_index::Integer,
116-
) where {T}
117-
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 = _constant_minus_bound(constant, set.lower, set.upper, dual)
121-
return set_dot(constant, dual, set)
122-
end
123-
124-
function _dual_objective_value(
125-
model::MOI.ModelLike,
126-
ci::MOI.ConstraintIndex{<:MOI.AbstractVectorFunction,<:MOI.HyperRectangle},
127-
::Type{T},
128-
result_index::Integer,
129-
) where {T}
130-
func_constant =
131-
MOI.constant(MOI.get(model, MOI.ConstraintFunction(), ci), T)
132-
set = MOI.get(model, MOI.ConstraintSet(), ci)
133-
dual = MOI.get(model, MOI.ConstraintDual(result_index), ci)
134-
constants = map(enumerate(func_constant)) do (i, c)
135-
return _constant_minus_bound(c, set.lower[i], set.upper[i], dual[i])
136-
end
137-
return set_dot(constants, dual, set)
138-
end
139-
140-
function _dual_objective_value(
141-
model::MOI.ModelLike,
142-
::Type{F},
143-
::Type{S},
144-
::Type{T},
145-
result_index::Integer,
146-
) where {T,F<:MOI.AbstractFunction,S<:MOI.AbstractSet}
147-
value = zero(T)
148-
if F == variable_function_type(S) && !_has_constant(S)
149-
return value # Shortcut
150-
end
151-
for ci in MOI.get(model, MOI.ListOfConstraintIndices{F,S}())
152-
value += _dual_objective_value(model, ci, T, result_index)
153-
end
154-
return value
155-
end
156-
157-
_has_constant(::Type{<:MOI.AbstractScalarSet}) = true
158-
_has_constant(::Type{<:MOI.AbstractVectorSet}) = false
159-
_has_constant(::Type{<:MOI.HyperRectangle}) = true
160-
16155
"""
16256
get_fallback(
16357
model::MOI.ModelLike,
@@ -192,6 +86,62 @@ function get_fallback(
19286
return value::T
19387
end
19488

89+
_has_constant(::Type{<:MOI.AbstractScalarSet}) = true
90+
_has_constant(::Type{<:MOI.AbstractVectorSet}) = false
91+
_has_constant(::Type{<:MOI.HyperRectangle}) = true
92+
93+
function _dual_objective_value(
94+
model::MOI.ModelLike,
95+
::Type{F},
96+
::Type{S},
97+
::Type{T},
98+
result_index::Integer,
99+
)::T where {T,F<:MOI.AbstractFunction,S<:MOI.AbstractSet}
100+
value = zero(T)
101+
if F == variable_function_type(S) && !_has_constant(S)
102+
return value # Shortcut
103+
end
104+
for ci in MOI.get(model, MOI.ListOfConstraintIndices{F,S}())
105+
constant = MOI.constant(MOI.get(model, MOI.ConstraintFunction(), ci), T)
106+
set = MOI.get(model, MOI.ConstraintSet(), ci)
107+
dual = MOI.get(model, MOI.ConstraintDual(result_index), ci)
108+
value += _dual_objective_dot(constant, dual, set)
109+
end
110+
return value
111+
end
112+
113+
_dual_objective_dot(x, y, set) = set_dot(x, y, set)
114+
115+
_dual_objective_dot(x, y, set::MOI.EqualTo) = (x - set.value) * y
116+
117+
_dual_objective_dot(x, y, set::MOI.LessThan) = (x - set.upper) * y
118+
119+
_dual_objective_dot(x, y, set::MOI.GreaterThan) = (x - set.lower) * y
120+
121+
function _dual_objective_dot(x, y, set::MOI.Interval)
122+
if isfinite(set.lower) && (!isfinite(set.upper) || y > zero(y))
123+
return (x - set.lower) * y
124+
elseif isfinite(upper) && (!isfinite(set.lower) || y < zero(y))
125+
return (x - set.upper) * y
126+
end
127+
return x * y
128+
end
129+
130+
function _dual_objective_dot(x, y, set::MOI.HyperRectangle)
131+
@assert length(x) == length(y) == MOI.dimension(set)
132+
ret = zero(eltype(x))
133+
for (xi, yi, li, ui) in zip(x, y, set.lower, set.upper)
134+
if isfinite(li) && (!isfinite(ui) || yi > zero(yi))
135+
ret += (xi - li) * yi
136+
elseif isfinite(upper) && (!isfinite(li) || yi < zero(yi))
137+
ret += (xi - ui) * yi
138+
else
139+
ret += xi * yi
140+
end
141+
end
142+
return ret
143+
end
144+
195145
# MOI.ConstraintPrimal
196146

197147
"""

0 commit comments

Comments
 (0)