Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 59 additions & 20 deletions docs/src/apireference.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,47 +225,86 @@ constant(f::VectorOfVariables, T::DataType)

## Sets

List of recognized sets.

All sets are subtypes of [`AbstractSet`](@ref) and they should either be scalar
or vector sets.
```@docs
AbstractSet
Reals
Zeros
Nonnegatives
Nonpositives
AbstractScalarSet
AbstractVectorSet
```

Functions for getting properties of sets.
```@docs
dimension
constant(s::EqualTo)
```

### Scalar sets

List of recognized scalar sets.
```@docs
GreaterThan
LessThan
EqualTo
Interval
Integer
ZeroOne
Semicontinuous
Semiinteger
```


### Vector sets

List of recognized vector sets.
```@docs
Reals
Zeros
Nonnegatives
Nonpositives
SecondOrderCone
RotatedSecondOrderCone
GeometricMeanCone
ExponentialCone
DualExponentialCone
PowerCone
DualPowerCone
PositiveSemidefiniteConeTriangle
PositiveSemidefiniteConeSquare
LogDetConeTriangle
LogDetConeSquare
RootDetConeTriangle
RootDetConeSquare
Integer
ZeroOne
Semicontinuous
Semiinteger
SOS1
SOS2
IndicatorSet
```

Functions for getting and setting properties of sets.
### Matrix sets

Matrix sets are vectorized in order to be subtypes of
[`AbstractVectorSet`](@ref). For sets of symmetric matrices, storing both the
`(i, j)` and `(j, i)` elements is redundant so there exists the
[`AbstractSymmetricMatrixSetTriangle`](@ref) set to represent only the
vectorization of the upper triangular part of the matrix. When the matrix
of expressions constrained to be in the set is not symmetric and hence
the `(i, j)` and `(j, i)` elements should be constrained to be symmetric,
the [`AbstractSymmetricMatrixSetSquare`](@ref) set can be used. The
[`Bridges.SquareBridge`](@ref) can transform a set from the square form
to the [`triangular_form`](@ref) by adding appropriate constraints if
the `(i, j)` and `(j, i)` expressions are different.
```@docs
dimension
constant(s::EqualTo)
AbstractSymmetricMatrixSetTriangle
AbstractSymmetricMatrixSetSquare
side_dimension
triangular_form
```
List of recognized matrix sets.
```@docs
PositiveSemidefiniteConeTriangle
PositiveSemidefiniteConeSquare
LogDetConeTriangle
LogDetConeSquare
RootDetConeTriangle
RootDetConeSquare
```

## Sets

## Modifications

Functions for modifying objective and constraint functions.
Expand Down Expand Up @@ -379,7 +418,7 @@ Bridges.SplitIntervalBridge
Bridges.RSOCBridge
Bridges.QuadtoSOCBridge
Bridges.GeoMeanBridge
Bridges.SquarePSDBridge
Bridges.SquareBridge
Bridges.RootDetBridge
Bridges.LogDetBridge
Bridges.SOCtoPSDBridge
Expand Down
6 changes: 3 additions & 3 deletions src/Bridges/Bridges.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function full_bridge_optimizer(model::MOI.ModelLike, ::Type{T}) where T
add_bridge(bridged_model, SplitIntervalBridge{T})
add_bridge(bridged_model, QuadtoSOCBridge{T})
add_bridge(bridged_model, GeoMeanBridge{T})
add_bridge(bridged_model, SquarePSDBridge{T})
add_bridge(bridged_model, SquareBridge{T})
add_bridge(bridged_model, LogDetBridge{T})
add_bridge(bridged_model, RootDetBridge{T})
add_bridge(bridged_model, RSOCBridge{T})
Expand Down Expand Up @@ -74,8 +74,8 @@ include("quadtosocbridge.jl")
const QuadtoSOC{T, OT<:MOI.ModelLike} = SingleBridgeOptimizer{QuadtoSOCBridge{T}, OT}
include("geomeanbridge.jl")
const GeoMean{T, OT<:MOI.ModelLike} = SingleBridgeOptimizer{GeoMeanBridge{T}, OT}
include("squarepsdbridge.jl")
const SquarePSD{T, OT<:MOI.ModelLike} = SingleBridgeOptimizer{SquarePSDBridge{T}, OT}
include("square_bridge.jl")
const Square{T, OT<:MOI.ModelLike} = SingleBridgeOptimizer{SquareBridge{T}, OT}
include("detbridge.jl")
const LogDet{T, OT<:MOI.ModelLike} = SingleBridgeOptimizer{LogDetBridge{T}, OT}
const RootDet{T, OT<:MOI.ModelLike} = SingleBridgeOptimizer{RootDetBridge{T}, OT}
Expand Down
72 changes: 38 additions & 34 deletions src/Bridges/squarepsdbridge.jl → src/Bridges/square_bridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@
# In the last primal program, we have the variables Z = X + Xᵀ and a upper triangular matrix S such that X = Z + S - Sᵀ

"""
SquarePSDBridge{T}
SquareBridge{T, F<:MOI.AbstractVectorFunction,
G<:MOI.AbstractScalarFunction,
TT<:MOI.AbstractSymmetricMatrixSetTriangle,
ST<:MOI.AbstractSymmetricMatrixSetSquare} <: AbstractBridge

The `SquarePSDBridge` reformulates the constraint of a square matrix to be PSD
and symmetric, i.e. belongs to the [`MOI.PositiveSemidefiniteConeSquare`](@ref),
The `SquareBridge` reformulates the constraint of a square matrix to be in `ST`
to a list of equality constraints for pair or off-diagonal entries with
different expressions and a PSD constraint the upper triangular part of the
different expressions and a `TT` constraint the upper triangular part of the
matrix.

For instance, the constraint for the matrix
Expand All @@ -64,18 +66,20 @@ and the equality constraint between the off-diagonal entries (2, 3) and (3, 2)
the off-diagonal entries (1, 2) and (2, 1) or between (1, 3) and (3, 1) since
the expressions are the same.
"""
struct SquarePSDBridge{T, F<:MOI.AbstractVectorFunction,
G<:MOI.AbstractScalarFunction} <: AbstractBridge
struct SquareBridge{T, F<:MOI.AbstractVectorFunction,
G<:MOI.AbstractScalarFunction,
TT<:MOI.AbstractSymmetricMatrixSetTriangle,
ST<:MOI.AbstractSymmetricMatrixSetSquare} <: AbstractBridge
side_dimension::Int
psd::CI{F, MOI.PositiveSemidefiniteConeTriangle}
triangle::CI{F, TT}
sym::Vector{Pair{Tuple{Int, Int}, CI{G, MOI.EqualTo{T}}}}
end
function bridge_constraint(::Type{SquarePSDBridge{T, F, G}},
function bridge_constraint(::Type{SquareBridge{T, F, G, TT, ST}},
model::MOI.ModelLike, f::F,
s::MOI.PositiveSemidefiniteConeSquare) where {T, F, G}
s::ST) where {T, F, G, TT, ST}
f_scalars = MOIU.eachscalar(f)
sym = Pair{Tuple{Int, Int}, CI{G, MOI.EqualTo{T}}}[]
dim = s.side_dimension
dim = MOI.side_dimension(s)
upper_triangle_indices = Int[]
trilen = div(dim * (dim + 1), 2)
sizehint!(upper_triangle_indices, trilen)
Expand Down Expand Up @@ -109,57 +113,57 @@ function bridge_constraint(::Type{SquarePSDBridge{T, F, G}},
k += dim - j
end
@assert length(upper_triangle_indices) == trilen
psd = MOI.add_constraint(model, f_scalars[upper_triangle_indices],
MOI.PositiveSemidefiniteConeTriangle(dim))
return SquarePSDBridge(dim, psd, sym)
triangle = MOI.add_constraint(model, f_scalars[upper_triangle_indices], MOI.triangular_form(s))
return SquareBridge{T, F, G, TT, ST}(dim, triangle, sym)
end

function MOI.supports_constraint(::Type{SquarePSDBridge{T}},
function MOI.supports_constraint(::Type{SquareBridge{T}},
::Type{<:MOI.AbstractVectorFunction},
::Type{MOI.PositiveSemidefiniteConeSquare}) where T
::Type{<:MOI.AbstractSymmetricMatrixSetSquare}) where T
return true
end
function added_constraint_types(::Type{SquarePSDBridge{T, F, G}}) where {T, F, G}
return [(F, MOI.PositiveSemidefiniteConeTriangle), (G, MOI.EqualTo{T})]
function added_constraint_types(::Type{SquareBridge{T, F, G, TT, ST}}) where {T, F, G, TT, ST}
return [(F, TT), (G, MOI.EqualTo{T})]
end
function concrete_bridge_type(::Type{<:SquarePSDBridge{T}},
function concrete_bridge_type(::Type{<:SquareBridge{T}},
F::Type{<:MOI.AbstractVectorFunction},
::Type{MOI.PositiveSemidefiniteConeSquare}) where T
ST::Type{<:MOI.AbstractSymmetricMatrixSetSquare}) where T
S = MOIU.scalar_type(F)
G = MOIU.promote_operation(-, T, S, S)
SquarePSDBridge{T, F, G}
TT = MOI.triangular_form(ST)
SquareBridge{T, F, G, TT, ST}
end

# Attributes, Bridge acting as an model
function MOI.get(::SquarePSDBridge{T, F},
::MOI.NumberOfConstraints{F, MOI.PositiveSemidefiniteConeTriangle}) where {T, F}
function MOI.get(::SquareBridge{T, F, G, TT},
::MOI.NumberOfConstraints{F, TT}) where {T, F, G, TT}
return 1
end
function MOI.get(bridge::SquarePSDBridge{T, F, G},
function MOI.get(bridge::SquareBridge{T, F, G},
::MOI.NumberOfConstraints{G, MOI.EqualTo{T}}) where {T, F, G}
return length(bridge.sym)
end
function MOI.get(bridge::SquarePSDBridge{T, F},
::MOI.ListOfConstraintIndices{F, MOI.PositiveSemidefiniteConeTriangle}) where {T, F}
return [bridge.psd]
function MOI.get(bridge::SquareBridge{T, F, G, TT},
::MOI.ListOfConstraintIndices{F, TT}) where {T, F, G, TT}
return [bridge.triangle]
end
function MOI.get(bridge::SquarePSDBridge{T, F, G},
function MOI.get(bridge::SquareBridge{T, F, G},
::MOI.ListOfConstraintIndices{G, MOI.EqualTo{T}}) where {T, F, G}
return map(pair -> pair.second, bridge.sym)
end

# Indices
function MOI.delete(model::MOI.ModelLike, bridge::SquarePSDBridge)
MOI.delete(model, bridge.psd)
function MOI.delete(model::MOI.ModelLike, bridge::SquareBridge)
MOI.delete(model, bridge.triangle)
for pair in bridge.sym
MOI.delete(model, pair.second)
end
end

# Attributes, Bridge acting as a constraint
function MOI.get(model::MOI.ModelLike, attr::MOI.ConstraintPrimal,
bridge::SquarePSDBridge{T}) where T
tri = MOI.get(model, attr, bridge.psd)
bridge::SquareBridge{T}) where T
tri = MOI.get(model, attr, bridge.triangle)
dim = bridge.side_dimension
sqr = Vector{eltype(tri)}(undef, dim^2)
k = 0
Expand All @@ -172,15 +176,15 @@ function MOI.get(model::MOI.ModelLike, attr::MOI.ConstraintPrimal,
return sqr
end
function MOI.get(model::MOI.ModelLike, attr::MOI.ConstraintDual,
bridge::SquarePSDBridge)
tri = MOI.get(model, attr, bridge.psd)
bridge::SquareBridge)
tri = MOI.get(model, attr, bridge.triangle)
dim = bridge.side_dimension
sqr = Vector{eltype(tri)}(undef, dim^2)
k = 0
for j in 1:dim
for i in 1:j
k += 1
# The psd constraint uses only the upper triangular part
# The triangle constraint uses only the upper triangular part
if i == j
sqr[i + (j - 1) * dim] = tri[k]
else
Expand Down
8 changes: 4 additions & 4 deletions src/Utilities/results.jl
Original file line number Diff line number Diff line change
Expand Up @@ -407,8 +407,8 @@ function triangle_dot(x::Vector{S}, y::Vector{T}, dim::Int, offset::Int) where {
end

function set_dot(x::Vector, y::Vector,
set::MOI.PositiveSemidefiniteConeTriangle)
return triangle_dot(x, y, set.side_dimension, 0)
set::MOI.AbstractSymmetricMatrixSetTriangle)
return triangle_dot(x, y, MOI.side_dimension(set), 0)
end

function set_dot(x::Vector, y::Vector, set::MOI.RootDetConeTriangle)
Expand Down Expand Up @@ -441,9 +441,9 @@ function triangle_coefficients!(b::Vector{T}, dim::Int, offset::Int) where T
end
end

function dot_coefficients(a::Vector, set::MOI.PositiveSemidefiniteConeTriangle)
function dot_coefficients(a::Vector, set::MOI.AbstractSymmetricMatrixSetTriangle)
b = copy(a)
triangle_coefficients!(b, set.side_dimension, 0)
triangle_coefficients!(b, MOI.side_dimension(set), 0)
return b
end

Expand Down
Loading