Skip to content

Commit 495688e

Browse files
committed
Update set_dot for sets with non-zero constants
1 parent 4a2641b commit 495688e

File tree

2 files changed

+63
-106
lines changed

2 files changed

+63
-106
lines changed

src/Utilities/results.jl

Lines changed: 24 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,30 @@ function get_fallback(
19286
return value::T
19387
end
19488

89+
function _dual_objective_value(
90+
model::MOI.ModelLike,
91+
::Type{F},
92+
::Type{S},
93+
::Type{T},
94+
result_index::Integer,
95+
) where {T,F<:MOI.AbstractFunction,S<:MOI.AbstractSet}
96+
value = zero(T)
97+
if F == variable_function_type(S) && !_has_constant(S)
98+
return value
99+
end
100+
for ci in MOI.get(model, MOI.ListOfConstraintIndices{F,S}())
101+
constants = MOI.constant(MOI.get(model, MOI.ConstraintFunction(), ci), T)
102+
dual = MOI.get(model, MOI.ConstraintDual(result_index), ci)
103+
set = MOI.get(model, MOI.ConstraintSet(), ci)
104+
value += set_dot(constants, dual, set)
105+
end
106+
return value
107+
end
108+
109+
_has_constant(::Type{<:MOI.AbstractScalarSet}) = true
110+
_has_constant(::Type{<:MOI.AbstractVectorSet}) = false
111+
_has_constant(::Type{<:MOI.HyperRectangle}) = true
112+
195113
# MOI.ConstraintPrimal
196114

197115
"""

src/Utilities/set_dot.jl

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,27 @@ Return the scalar product between a number `x` of the set `set` and a number
2626
"""
2727
set_dot(x, y, ::MOI.AbstractScalarSet) = LinearAlgebra.dot(x, y)
2828

29+
function set_dot(
30+
x::Real,
31+
y::Real,
32+
set::Union{MOI.EqualTo,MOI.GreaterThan,MOI.LessThan},
33+
)
34+
return (x - MOI.constant(set)) * y
35+
end
36+
37+
function set_dot(
38+
x::Real,
39+
y::Real,
40+
set::MOI.Interval,
41+
)
42+
if isfinite(set.lower) && (!isfinite(set.upper) || y > zero(y))
43+
return (x - set.lower) * y
44+
elseif isfinite(upper) && (!isfinite(set.lower) || y < zero(y))
45+
return (x - set.upper) * y
46+
end
47+
return x * y
48+
end
49+
2950
function triangle_dot(
3051
x::AbstractVector{S},
3152
y::AbstractVector{T},
@@ -86,6 +107,24 @@ function set_dot(
86107
return x[1] * y[1] + x[2] * y[2] + triangle_dot(x, y, set.side_dimension, 2)
87108
end
88109

110+
function set_dot(
111+
x::AbstractVector{A},
112+
y::AbstractVector{B},
113+
set::MOI.HyperRectangle{C},
114+
) where {A,B,C}
115+
ret = zero(promote_type(A, B, C))
116+
for (xi, yi, li, ui) in zip(x, y, set.lower, set.upper)
117+
if isfinite(li) && (!isfinite(ui) || yi > zero(yi))
118+
ret += (xi - li) * yi
119+
elseif isfinite(upper) && (!isfinite(li) || yi < zero(yi))
120+
ret += (xi - ui) * yi
121+
else
122+
ret += xi * yi
123+
end
124+
end
125+
return ret
126+
end
127+
89128
"""
90129
dot_coefficients(a::AbstractVector, set::AbstractVectorSet)
91130

0 commit comments

Comments
 (0)