Skip to content

Commit

Permalink
Add Scaled set
Browse files Browse the repository at this point in the history
  • Loading branch information
blegat committed Aug 25, 2023
1 parent ce536b2 commit 8d3e265
Show file tree
Hide file tree
Showing 24 changed files with 847 additions and 505 deletions.
2 changes: 1 addition & 1 deletion docs/src/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [`hessian_objective_structure`](@ref)
- Added new sets
- [`NormCone`](@ref) (#2119)
- [`ScaledPositiveSemidefiniteConeTriangle`](@ref) (#2154)
- `ScaledPositiveSemidefiniteConeTriangle` (#2154)

### Fixed

Expand Down
2 changes: 1 addition & 1 deletion docs/src/manual/standard_form.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,13 @@ The matrix-valued set types implemented in MathOptInterface.jl are:
| [`RootDetConeSquare(d)`](@ref MathOptInterface.RootDetConeSquare) | ``\{ (t,X) \in \mathbb{R}^{1+d^2} : t \le \det(X)^{1/d}, X \mbox{ is a PSD matrix} \}`` |
| [`PositiveSemidefiniteConeTriangle(d)`](@ref MathOptInterface.PositiveSemidefiniteConeTriangle) | ``\{ X \in \mathbb{R}^{d(d+1)/2} : X \mbox{ is the upper triangle of a PSD matrix} \}`` |
| [`PositiveSemidefiniteConeSquare(d)`](@ref MathOptInterface.PositiveSemidefiniteConeSquare) | ``\{ X \in \mathbb{R}^{d^2} : X \mbox{ is a PSD matrix} \}`` |
| [`ScaledPositiveSemidefiniteConeTriangle(d)`](@ref MathOptInterface.ScaledPositiveSemidefiniteConeTriangle) | ``\{ X \in \mathbb{R}^{d(d+1)/2} : X \mbox{ is a PSD matrix} \}`` |
| [`LogDetConeTriangle(d)`](@ref MathOptInterface.LogDetConeTriangle) | ``\{ (t,u,X) \in \mathbb{R}^{2+d(1+d)/2} : t \le u\log(\det(X/u)), X \mbox{ is the upper triangle of a PSD matrix}, u > 0 \}`` |
| [`LogDetConeSquare(d)`](@ref MathOptInterface.LogDetConeSquare) | ``\{ (t,u,X) \in \mathbb{R}^{2+d^2} : t \le u \log(\det(X/u)), X \mbox{ is a PSD matrix}, u > 0 \}`` |
| [`NormSpectralCone(r, c)`](@ref MathOptInterface.NormSpectralCone) | ``\{ (t, X) \in \mathbb{R}^{1 + r \times c} : t \ge \sigma_1(X), X \mbox{ is a } r\times c\mbox{ matrix} \}``
| [`NormNuclearCone(r, c)`](@ref MathOptInterface.NormNuclearCone) | ``\{ (t, X) \in \mathbb{R}^{1 + r \times c} : t \ge \sum_i \sigma_i(X), X \mbox{ is a } r\times c\mbox{ matrix} \}`` |
| [`HermitianPositiveSemidefiniteConeTriangle(d)`](@ref MathOptInterface.HermitianPositiveSemidefiniteConeTriangle) | The cone of Hermitian positive semidefinite matrices, with
`side_dimension` rows and columns. |
| [`Scaled(S)`](@ref MathOptInterface.Scaled) | The set `S` scaled so that [`Utilities.set_dot`](@ref MathOptInterface.Utilities.set_dot) corresponds to `LinearAlgebra.dot` |

Some of these cones can take two forms: `XXXConeTriangle` and `XXXConeSquare`.

Expand Down
2 changes: 1 addition & 1 deletion docs/src/reference/standard_form.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ SOS2
Indicator
Complements
HyperRectangle
Scaled
```

## Constraint programming sets
Expand Down Expand Up @@ -148,7 +149,6 @@ List of recognized matrix sets.
PositiveSemidefiniteConeTriangle
PositiveSemidefiniteConeSquare
HermitianPositiveSemidefiniteConeTriangle
ScaledPositiveSemidefiniteConeTriangle
LogDetConeTriangle
LogDetConeSquare
RootDetConeTriangle
Expand Down
4 changes: 2 additions & 2 deletions docs/src/submodules/Bridges/list_of_bridges.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ Bridges.Constraint.NormSpectralBridge
Bridges.Constraint.NormNuclearBridge
Bridges.Constraint.SquareBridge
Bridges.Constraint.HermitianToSymmetricPSDBridge
Bridges.Constraint.SymmetricMatrixScalingBridge
Bridges.Constraint.SymmetricMatrixInverseScalingBridge
Bridges.Constraint.SetDotScalingBridge
Bridges.Constraint.SetDotInverseScalingBridge
Bridges.Constraint.RootDetBridge
Bridges.Constraint.LogDetBridge
Bridges.Constraint.IndicatorActiveOnFalseBridge
Expand Down
9 changes: 3 additions & 6 deletions src/Bridges/Constraint/Constraint.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ include("bridges/split_complex_zeros.jl")
include("bridges/split_hyperrectangle.jl")
include("bridges/hermitian.jl")
include("bridges/square.jl")
include("bridges/symmetric_matrix_scaling.jl")
include("bridges/set_dot_scaling.jl")
include("bridges/table.jl")
include("bridges/vectorize.jl")
include("bridges/zero_one.jl")
Expand Down Expand Up @@ -109,11 +109,8 @@ function add_all_bridges(bridged_model, ::Type{T}) where {T}
MOI.Bridges.add_bridge(bridged_model, NormNuclearBridge{T})
MOI.Bridges.add_bridge(bridged_model, HermitianToSymmetricPSDBridge{T})
MOI.Bridges.add_bridge(bridged_model, SquareBridge{T})
MOI.Bridges.add_bridge(bridged_model, SymmetricMatrixScalingBridge{T})
MOI.Bridges.add_bridge(
bridged_model,
SymmetricMatrixInverseScalingBridge{T},
)
MOI.Bridges.add_bridge(bridged_model, SetDotScalingBridge{T})
MOI.Bridges.add_bridge(bridged_model, SetDotInverseScalingBridge{T})
MOI.Bridges.add_bridge(bridged_model, LogDetBridge{T})
MOI.Bridges.add_bridge(bridged_model, RootDetBridge{T})
MOI.Bridges.add_bridge(bridged_model, RSOCtoSOCBridge{T})
Expand Down
212 changes: 212 additions & 0 deletions src/Bridges/Constraint/bridges/set_dot_scaling.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
# Copyright (c) 2017: Miles Lubin and contributors
# Copyright (c) 2017: Google Inc.
#
# Use of this source code is governed by an MIT-style license that can be found
# in the LICENSE.md file or at https://opensource.org/licenses/MIT.

"""
SetDotScalingBridge{T,S,F,G} <: Bridges.Constraint.AbstractBridge
`SetDotScalingBridge` implements the reformulation from constraints
in `S` to constraints in [`MOI.Scaled{S}`](@ref MOI.Scaled).
## Source node
`SetDotScalingBridge` supports:
* `G` in `S`
## Target node
`SetDotScalingBridge` creates:
* `F` in [`MOI.Scaled{S}`](@ref MOI.Scaled)
"""
struct SetDotScalingBridge{T,S,F,G} <: SetMapBridge{T,MOI.Scaled{S},S,F,G}
constraint::MOI.ConstraintIndex{F,MOI.Scaled{S}}
end

const SetDotScaling{T,OT<:MOI.ModelLike} =
SingleBridgeOptimizer{SetDotScalingBridge{T},OT}

function concrete_bridge_type(
::Type{<:SetDotScalingBridge{T}},
G::Type{<:MOI.AbstractVectorFunction},
::Type{S},
) where {T,S<:MOI.AbstractVectorSet}
F = MOI.Utilities.promote_operation(
*,
T,
LinearAlgebra.Diagonal{T,Vector{T}},
G,
)
return SetDotScalingBridge{T,S,F,G}
end

function MOI.Bridges.map_set(
::Type{<:SetDotScalingBridge{T,S}},
set::S,
) where {T,S}
return MOI.Scaled(set)
end

function MOI.Bridges.inverse_map_set(
::Type{<:SetDotScalingBridge{T,S}},
set::MOI.Scaled{S},
) where {T,S}
return set.set
end

_length(f::MOI.AbstractVectorFunction) = MOI.output_dimension(f)
_length(f::AbstractVector) = length(f)

function _scale(::Type{T}, ::Type{S}, func) where {T,S}
set = MOI.Utilities.set_with_dimension(S, _length(func))
scale = MOI.Utilities.SetDotScalingVector{T}(set)
return MOI.Utilities.operate(*, T, LinearAlgebra.Diagonal(scale), func)
end

function _inverse_scale(::Type{T}, ::Type{S}, func) where {T,S}
set = MOI.Utilities.set_with_dimension(S, _length(func))
scale = MOI.Utilities.SetDotScalingVector{T}(set)
inv_scale = MOI.Utilities.lazy_map(T, inv, scale)
return MOI.Utilities.operate(*, T, LinearAlgebra.Diagonal(inv_scale), func)
end

function MOI.Bridges.map_function(
::Type{<:SetDotScalingBridge{T,S}},
func,
) where {T,S}
return _scale(T, S, func)
end

function MOI.Bridges.inverse_map_function(
::Type{<:SetDotScalingBridge{T,S}},
func,
) where {T,S}
return _inverse_scale(T, S, func)
end

# Since the map is a diagonal matrix `D`, it is symmetric so one would initially
# expect `adjoint_map_function` to be the same as `map_function`. However, the
# scalar product for the scaled PSD cone is `<x, y>_2 = x'y` but the scalar
# product for the PSD cone additionally scales the offdiagonal entries by `2`
# hence by `D^2` so `<x, y>_1 = x'D^2y`.
# So `<Dx, y>_2 = <x, D^(-1)y>_1` hence the adjoint of `D` is its inverse!
function MOI.Bridges.adjoint_map_function(
::Type{<:SetDotScalingBridge{T,S}},
func,
) where {T,S}
return _inverse_scale(T, S, func)
end

function MOI.Bridges.inverse_adjoint_map_function(
::Type{<:SetDotScalingBridge{T,S}},
func,
) where {T,S}
return _scale(T, S, func)
end

"""
SetDotInverseScalingBridge{T,S,F,G} <: Bridges.Constraint.AbstractBridge
`SetDotInverseScalingBridge` implements the reformulation from constraints
in the `MOI.Scaled{S}` to constraints in the `S`.
## Source node
`SetDotInverseScalingBridge` supports:
* `G` in [`MOI.Scaled{S}`](@ref MOI.Scaled)
## Target node
`SetDotInverseScalingBridge` creates:
* `F` in `S`
"""
struct SetDotInverseScalingBridge{T,S,F,G} <:
SetMapBridge{T,S,MOI.Scaled{S},F,G}
constraint::MOI.ConstraintIndex{F,S}
end

const SetDotInverseScaling{T,OT<:MOI.ModelLike} =
SingleBridgeOptimizer{SetDotInverseScalingBridge{T},OT}

function concrete_bridge_type(
::Type{<:SetDotInverseScalingBridge{T}},
G::Type{<:MOI.AbstractVectorFunction},
::Type{MOI.Scaled{S}},
) where {T,S<:MOI.AbstractVectorSet}
F = MOI.Utilities.promote_operation(
*,
T,
LinearAlgebra.Diagonal{T,Vector{T}},
G,
)
return SetDotInverseScalingBridge{T,S,F,G}
end

function MOI.Bridges.map_set(
::Type{<:SetDotInverseScalingBridge{T,S}},
set::MOI.Scaled{S},
) where {T,S}
return set.set
end

function MOI.Bridges.inverse_map_set(
::Type{<:SetDotInverseScalingBridge{T,S}},
set::S,
) where {T,S}
return MOI.Scaled(set)
end

function MOI.Bridges.map_function(
::Type{<:SetDotInverseScalingBridge{T,S}},
func,
) where {T,S}
return _inverse_scale(T, S, func)
end

function MOI.Bridges.inverse_map_function(
::Type{<:SetDotInverseScalingBridge{T,S}},
func,
) where {T,S}
return _scale(T, S, func)
end

function MOI.Bridges.adjoint_map_function(
::Type{<:SetDotInverseScalingBridge{T,S}},
func,
) where {T,S}
return _inverse_scale(T, S, func)
end

function MOI.Bridges.inverse_adjoint_map_function(
::Type{<:SetDotInverseScalingBridge{T,S}},
func,
) where {T,S}
return _scale(T, S, func)
end

# Since the set type is not defined, the default `MOI.supports_constraint`
# for `SetMapBridge` does not work
function MOI.supports_constraint(
::Type{<:SetDotScalingBridge},
::Type{<:MOI.AbstractVectorFunction},
S::Type{<:MOI.AbstractVectorSet},
)
return MOI.is_set_dot_scaled(S)
end

function MOI.supports_constraint(
::Type{<:SetDotInverseScalingBridge},
::Type{<:MOI.AbstractVectorFunction},
::Type{MOI.Scaled{S}},
) where {S<:MOI.AbstractVectorSet}
return true
end

# TODO remove in MOI v2
const SymmetricMatrixScalingBridge = SetDotScalingBridge
const SymmetricMatrixInverseScalingBridge = SetDotInverseScalingBridge
Loading

0 comments on commit 8d3e265

Please sign in to comment.