Skip to content

Commit af74c47

Browse files
committed
Add Variable.ZerosBridge
1 parent 4e2c0b5 commit af74c47

File tree

7 files changed

+110
-7
lines changed

7 files changed

+110
-7
lines changed

src/Bridges/Constraint/bridge.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ These can be obtained using `MOI.NumberOfConstraints` and `MOI.ListOfConstraintI
66
Attributes of the bridged model such as `MOI.ConstraintDual` and `MOI.ConstraintPrimal`, can be obtained using the bridge in place of the constraint index.
77
These calls are used by the `AbstractBridgeOptimizer` to communicate with the bridge so they should be implemented by the bridge.
88
"""
9-
abstract type AbstractBridge end
9+
abstract type AbstractBridge <: MOIB.AbstractBridge end
1010

1111
"""
1212
bridge_constraint(BT::Type{<:AbstractBridge}, model::MOI.ModelLike,
@@ -47,7 +47,10 @@ MOI.get(::AbstractBridge, ::MOI.NumberOfConstraints) = 0
4747
A `Vector{ConstraintIndex{F,S}}` with indices of all constraints of
4848
type `F`-in`S` created by the bride `b` in the model (i.e., of length equal to the value of `NumberOfConstraints{F,S}()`).
4949
"""
50-
MOI.get(::AbstractBridge, ::MOI.ListOfConstraintIndices{F, S}) where {F, S} = CI{F, S}[]
50+
function MOI.get(::AbstractBridge,
51+
::MOI.ListOfConstraintIndices{F, S}) where {F, S}
52+
return MOI.ConstraintIndex{F, S}[]
53+
end
5154

5255
"""
5356
MOI.supports_constraint(BT::Type{<:AbstractBridge}, F::Type{<:MOI.AbstractFunction}, S::Type{<:MOI.AbstractSet})::Bool

src/Bridges/Variable/Variable.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@ include("bridge.jl")
1212
include("single_bridge_optimizer.jl")
1313

1414
# Variable bridges
15+
include("zeros.jl")
16+
const Zeros{T, OT<:MOI.ModelLike} = SingleBridgeOptimizer{ZerosBridge{T}, OT}
1517
include("flip_sign.jl")
1618
const NonposToNonneg{T, OT<:MOI.ModelLike} = SingleBridgeOptimizer{NonposToNonnegBridge{T}, OT}
1719
include("vectorize.jl")
1820
const Vectorize{T, OT<:MOI.ModelLike} = SingleBridgeOptimizer{VectorizeBridge{T}, OT}
1921

2022
function add_all_bridges(bridged_model, T::Type)
23+
MOIB.add_bridge(bridged_model, ZerosBridge{T})
2124
MOIB.add_bridge(bridged_model, NonposToNonnegBridge{T})
2225
MOIB.add_bridge(bridged_model, VectorizeBridge{T})
2326
return

src/Bridges/Variable/bridge.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
abstract type AbstractBridge end
1+
abstract type AbstractBridge <: MOIB.AbstractBridge end
22

33
struct IndexInVector
44
value::Int
@@ -29,6 +29,11 @@ The number of constraints of the type `F`-in-`S` created by the bridge `b` in th
2929
"""
3030
MOI.get(b::AbstractBridge, ::MOI.NumberOfConstraints) = 0
3131

32+
function MOI.get(::AbstractBridge,
33+
::MOI.ListOfConstraintIndices{F, S}) where {F, S}
34+
return MOI.ConstraintIndex{F, S}[]
35+
end
36+
3237
"""
3338
supports_constrained_variables(::Type{<:AbstractBridge},
3439
::Type{<:MOI.AbstractSet})::Bool

src/Bridges/Variable/single_bridge_optimizer.jl

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ function add_key_for_bridge(map::Map, bridge::AbstractBridge,
6363
push!(map.index_in_vector_of_variables, 0)
6464
push!(map.bridges, bridge)
6565
push!(map.sets, typeof(set))
66-
push!(map.unbridged_function, unbridged_map(bridge, variable))
66+
mapping = unbridged_map(bridge, variable)
67+
if mapping !== nothing
68+
push!(map.unbridged_function, mapping)
69+
end
6770
return variable, MOI.ConstraintIndex{MOI.SingleVariable, typeof(set)}(index)
6871
end
6972
function add_keys_for_bridge(map::Map, bridge::AbstractBridge,
@@ -82,13 +85,30 @@ function add_keys_for_bridge(map::Map, bridge::AbstractBridge,
8285
push!(map.sets, nothing)
8386
end
8487
for i in 1:MOI.dimension(set)
85-
push!(map.unbridged_function, unbridged_map(bridge, variables[i],
86-
IndexInVector(i)))
88+
mapping = unbridged_map(bridge, variables[i], IndexInVector(i))
89+
if mapping !== nothing
90+
push!(map.unbridged_function, mapping)
91+
end
8792
end
8893
index = first(variables).value
8994
return variables, MOI.ConstraintIndex{MOI.VectorOfVariables, typeof(set)}(index)
9095
end
9196
end
97+
function function_for(map::Map, ci::MOI.ConstraintIndex{MOI.SingleVariable})
98+
return MOI.SingleVariable(MOI.VariableIndex(ci.value))
99+
end
100+
function function_for(map::Map, ci::MOI.ConstraintIndex{MOI.VectorOfVariables})
101+
variables = MOI.VariableIndex[]
102+
for i in ci.value:-1:-length(map.bridges)
103+
vi = MOI.VariableIndex(i)
104+
if bridge_index(map, vi) == -ci.value
105+
push!(variables, vi)
106+
else
107+
break
108+
end
109+
end
110+
return MOI.VectorOfVariables(variables)
111+
end
92112
function Base.iterate(map::Map, state=1)
93113
while state length(map.bridges) && map.bridges[state] === nothing
94114
state += 1

src/Bridges/Variable/zeros.jl

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
"""
2+
ZerosBridge{T} <: Bridges.Variable.AbstractBridge
3+
4+
Transforms constrained variables in [`MathOptInterface.Zeros`](@ref) zeros,
5+
which ends up creating no variables in the underlying model.
6+
The bridged variables are therefore similar to parameters with zero values.
7+
Parameters with non-zero value can be created with constrained variables in
8+
[`MOI.EqualTo`](@ref) by combining a [`VectorizeBridge`](@ref) and this bridge.
9+
The dual values cannot be determined by the bridged hence they are determined
10+
by the bridged optimizer using [`MathOptInterface.Utilities.get_fallback`](@ref).
11+
"""
12+
struct ZerosBridge{T} <: AbstractBridge
13+
n::Int # Number of variables
14+
end
15+
function bridge_constrained_variables(::Type{ZerosBridge{T}},
16+
model::MOI.ModelLike,
17+
set::MOI.Zeros) where T
18+
return ZerosBridge{T}(MOI.dimension(set))
19+
end
20+
21+
function supports_constrained_variables(
22+
::Type{<:ZerosBridge}, ::Type{MOI.Zeros})
23+
return true
24+
end
25+
function MOIB.added_constrained_variable_types(::Type{<:ZerosBridge})
26+
return Tuple{DataType}[]
27+
end
28+
function MOIB.added_constraint_types(::Type{<:ZerosBridge})
29+
return Tuple{DataType, DataType}[]
30+
end
31+
32+
# Attributes, Bridge acting as a model
33+
MOI.get(bridge::ZerosBridge, ::MOI.NumberOfVariables) = 0
34+
function MOI.get(bridge::ZerosBridge, ::MOI.ListOfVariableIndices)
35+
return MOI.VariableIndex[]
36+
end
37+
38+
# Attributes, Bridge acting as a constraint
39+
40+
function MOI.get(::MOI.ModelLike, ::MOI.ConstraintPrimal,
41+
bridge::ZerosBridge{T}) where T
42+
return zeros(T, bridge.n)
43+
end
44+
MOIB.needs_fallback(::MOI.ModelLike, ::MOI.ConstraintDual, ::ZerosBridge) = true
45+
46+
function MOI.get(::MOI.ModelLike, ::MOI.VariablePrimal,
47+
::ZerosBridge{T}, ::IndexInVector) where T
48+
return zero(T)
49+
end
50+
51+
function MOIB.bridged_function(::ZerosBridge{T}, ::IndexInVector) where T
52+
return zero(MOI.ScalarAffineFunction{T})
53+
end
54+
function unbridged_map(::ZerosBridge, ::MOI.VariableIndex,
55+
::IndexInVector)
56+
return nothing
57+
end

src/Bridges/bridge.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
abstract type AbstractBridge end
2+
3+
function needs_fallback(::MOI.ModelLike, ::MOI.AbstractConstraintAttribute,
4+
::AbstractBridge)
5+
return false
6+
end
7+
18
"""
29
added_constraint_types(BT::Type{<:Variable.AbstractBridge})::Bool
310

src/Bridges/bridge_optimizer.jl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,15 @@ function MOI.get(b::AbstractBridgeOptimizer,
328328
attr::MOI.AbstractConstraintAttribute, ci::CI)
329329
if is_bridged(b, typeof(ci))
330330
MOI.throw_if_not_valid(b, ci)
331-
func = MOI.get(b, attr, bridge(b, ci))
331+
br = bridge(b, ci)
332+
if attr isa MOI.ConstraintFunction && br isa Variable.AbstractBridge
333+
return Variable.function_for(Variable.bridges(b), ci)
334+
end
335+
if needs_fallback(b, attr, br)
336+
func = MOIU.get_fallback(b, attr, ci)
337+
else
338+
func = MOI.get(b, attr, br)
339+
end
332340
else
333341
func = MOI.get(b.model, attr, ci)
334342
end

0 commit comments

Comments
 (0)