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
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ MutableArithmetics = "1"
OpenBLAS32_jll = "0.3.10"
Pkg = "1"
PrecompileTools = "1"
SCS_GPU_jll = "=3.2.9"
SCS_MKL_jll = "=3.2.9"
SCS_jll = "=3.2.9"
SCS_GPU_jll = "=300.200.900"
SCS_MKL_jll = "=300.200.900"
SCS_jll = "=300.200.900"
SparseArrays = "1"
Test = "1"
julia = "1.10"
Expand Down
10 changes: 10 additions & 0 deletions src/MOI_wrapper/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
include("scaled_psd_cone_bridge.jl")
include("hermitian_complex_psd_cone_bridge.jl")
include("scaled_complex_psd_cone_bridge.jl")
include("ScaledLogDetConeTriangle.jl")

MOI.Utilities.@product_of_sets(
_Cones,
Expand All @@ -18,6 +19,7 @@ MOI.Utilities.@product_of_sets(
MOI.DualExponentialCone,
MOI.PowerCone{T},
MOI.DualPowerCone{T},
ScaledLogDetConeTriangle,
)

struct _SetConstants{T}
Expand Down Expand Up @@ -139,6 +141,7 @@ function MOI.get(::Optimizer, ::MOI.Bridges.ListOfNonstandardBridges)
ScaledPSDConeBridge{Cdouble},
ScaledComplexPSDConeBridge{Cdouble},
HermitianComplexPSDConeBridge{Cdouble},
ScaledLogDetConeTriangleBridge{Cdouble},
]
end

Expand Down Expand Up @@ -251,6 +254,7 @@ function MOI.supports_constraint(
MOI.DualExponentialCone,
MOI.PowerCone{Cdouble},
MOI.DualPowerCone{Cdouble},
ScaledLogDetConeTriangle,
},
},
)
Expand Down Expand Up @@ -410,6 +414,12 @@ function MOI.optimize!(
MOI.DualPowerCone{Cdouble},
),
),
_map_sets(set -> set.side_dimension, T, Ab, ScaledLogDetConeTriangle),
T[], # nuc_m
T[], # nuc_n
T[], # ell1
T[], # sl_n
T[], # nuc_k
dest.sol.primal,
dest.sol.dual,
dest.sol.slack;
Expand Down
104 changes: 104 additions & 0 deletions src/MOI_wrapper/ScaledLogDetConeTriangle.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Copyright (c) 2014: SCS.jl contributors
#
# 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.

"""
struct ScaledLogDetConeTriangle <: MOI.AbstractVectorSet
side_dimension::Int
end

MOI: [t, u, x] in MOI.Scaled{MOI.LogDetConeTriangle}(n)
SCS: [-t, u, perm(x)] in SCS.ScaledLogDetConeTriangle(n)
"""
struct ScaledLogDetConeTriangle <: MOI.AbstractVectorSet
side_dimension::Int
end

function MOI.Utilities.set_with_dimension(::Type{ScaledLogDetConeTriangle}, dim)
return ScaledLogDetConeTriangle(div(-1 + isqrt(1 + 8 * dim), 2))
end

function MOI.dimension(set::ScaledLogDetConeTriangle)
return MOI.dimension(MOI.LogDetConeTriangle(set.side_dimension))
end

struct ScaledLogDetConeTriangleBridge{T,F} <:
MOI.Bridges.Constraint.SetMapBridge{
T,
ScaledLogDetConeTriangle,
MOI.Scaled{MOI.LogDetConeTriangle},
F,
F,
}
constraint::MOI.ConstraintIndex{F,ScaledLogDetConeTriangle}
end

function MOI.Bridges.Constraint.concrete_bridge_type(
::Type{ScaledLogDetConeTriangleBridge{T}},
::Type{F},
::Type{MOI.Scaled{MOI.LogDetConeTriangle}},
) where {T,F<:MOI.AbstractVectorFunction}
return ScaledLogDetConeTriangleBridge{T,F}
end

function MOI.Bridges.map_set(
::Type{<:ScaledLogDetConeTriangleBridge},
set::MOI.Scaled{MOI.LogDetConeTriangle},
)
return ScaledLogDetConeTriangle(set.set.side_dimension)
end

function MOI.Bridges.inverse_map_set(
::Type{<:ScaledLogDetConeTriangleBridge},
set::ScaledLogDetConeTriangle,
)
return MOI.Scaled(MOI.LogDetConeTriangle(set.side_dimension))
end

function _transform_function(
::Type{<:ScaledLogDetConeTriangleBridge{T}},
func,
moi_to_scs::Bool,
) where {T}
scalars = MOI.Utilities.eachscalar(func)
upper_to_lower, lower_to_upper =
_upper_to_lower_triangular_permutation(length(scalars) - 2)
p = moi_to_scs ? lower_to_upper : upper_to_lower
return MOI.Utilities.operate(
vcat,
T,
MOI.Utilities.operate(-, T, scalars[1]),
scalars[2],
scalars[p.+2],
)
end

# Map ConstraintFunction from MOI -> SCS
function MOI.Bridges.map_function(b::Type{<:ScaledLogDetConeTriangleBridge}, f)
return _transform_function(b, f, true)
end

# Used to map the ConstraintPrimal from SCS -> MOI
function MOI.Bridges.inverse_map_function(
b::Type{<:ScaledLogDetConeTriangleBridge},
f,
)
return _transform_function(b, f, false)
end

# Used to map the ConstraintDual from SCS -> MOI
function MOI.Bridges.adjoint_map_function(
b::Type{<:ScaledLogDetConeTriangleBridge},
f,
)
return _transform_function(b, f, false)
end

# Used to set ConstraintDualStart
function MOI.Bridges.inverse_adjoint_map_function(
b::Type{<:ScaledLogDetConeTriangleBridge},
f,
)
return _transform_function(b, f, true)
end
132 changes: 130 additions & 2 deletions src/c_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ mutable struct ScsCone{T} <: AbstractSCSType
ed::T
p::Ptr{Cdouble}
psize::T
d::Ptr{T}
dsize::T
nuc_m::Ptr{T}
nuc_n::Ptr{T}
nucsize::T
ell1::Ptr{T}
ell1_size::T
sl_n::Ptr{T}
sl_k::Ptr{T}
sl_size::T
end

mutable struct ScsSolution <: AbstractSCSType
Expand Down Expand Up @@ -136,6 +146,12 @@ struct _ScsDataWrapper{S,T}
ep::T
ed::T
p::Vector{Cdouble}
d::Vector{T}
nuc_m::Vector{T}
nuc_n::Vector{T}
ell1::Vector{T}
sl_n::Vector{T}
sl_k::Vector{T}
primal::Vector{Cdouble}
dual::Vector{Cdouble}
slack::Vector{Cdouble}
Expand Down Expand Up @@ -194,7 +210,8 @@ subject to A * x + s = b
s in K
```
where K is a product cone of
- zero cone

- zero cone `{ 0 }`
- positive orthant `{ x | x ≥ 0 }`
- box cone `{ (t,x) | t*l ≤ x ≤ t*u }`
- second-order cone (SOC) `{ (t,x) | ||x||_2 ≤ t }`
Expand All @@ -203,10 +220,15 @@ where K is a product cone of
- exponential cone `{ (x,y,z) | y e^(x/y) ≤ z, y > 0 }`
- power cone `{ (x,y,z) | x^a * y^(1-a) ≥ |z|, x ≥ 0, y ≥ 0 }`
- dual power cone `{ (u,v,w) | (u/a)^a * (v/(1-a))^(1-a) ≥ |w|, u ≥ 0, v ≥ 0 }`
- log determinant cone `{ (t, u, X) | t ≥ -u log(det(X / u)) }`
- nuclear norm cone `{ (t, X) | t ≥ ||X||_* }`
- L1-matrix norm cone `{ (t, X) | t ≥ Σᵢ|Xᵢⱼ| ∀j}`
- Ky-Fan norm cone `{ (t, X) | t ≥ Σᵏ λᵢ(X) }`

## Input arguments

The problem data are:

- `linear_solver`: a `LinearSolver` to use
- `m`: the number of affine constraints
- `n`: the number of variables
Expand All @@ -231,6 +253,12 @@ above by the following arguments.
- `ed`: the number of dual exponential cones
- `p`: the `Vector` of power cone parameters (±1, with negative values for the
dual cone)
- `d`: the `Vector` of log-det cone sizes
- `nuc_m`: the `Vector` of nuclear-norm row dimensions
- `nuc_n`: the `Vector` of nuclear-norm column dimensions
- `ell1`: the `Vector` of L1-matrix-norm sizes
- `sl_n`: the `Vector` of Ky-Fan norm cone sizes
- `sl_k`: the `Vector` of Ky-Fan norm cone constants

Provide a warm start to SCS by overriding:
- `primal_sol = zeros(n)`: a `Vector` to warmstart the primal variables,
Expand Down Expand Up @@ -290,6 +318,12 @@ function scs_solve(
ep::Integer,
ed::Integer,
p::Vector{Float64},
d::Vector{<:Integer},
nuc_m::Vector{<:Integer},
nuc_n::Vector{<:Integer},
ell1::Vector{<:Integer},
sl_n::Vector{<:Integer},
sl_k::Vector{<:Integer},
primal_sol::Vector{Float64} = zeros(n),
dual_sol::Vector{Float64} = zeros(m),
slack::Vector{Float64} = zeros(m);
Expand All @@ -308,6 +342,8 @@ function scs_solve(
end
primal_sol, dual_sol, slack = zeros(n), zeros(m), zeros(m)
end
@assert length(sl_n) == length(sl_k)
@assert length(nuc_m) == length(nuc_n)
T = scsint_t(linear_solver)
m, n, z, l, ep, ed = T(m), T(n), T(z), T(l), T(ep), T(ed)
Avalues, Arowval, Acolptr = _to_sparse(T, A)
Expand Down Expand Up @@ -338,6 +374,12 @@ function scs_solve(
ep,
ed,
p,
convert(Vector{T}, d),
convert(Vector{T}, nuc_m),
convert(Vector{T}, nuc_n),
convert(Vector{T}, ell1),
convert(Vector{T}, sl_n),
convert(Vector{T}, sl_k),
primal_sol,
dual_sol,
slack,
Expand Down Expand Up @@ -366,6 +408,16 @@ function _unsafe_scs_solve(model::_ScsDataWrapper{S,T}) where {S,T}
model.ed,
pointer(model.p),
length(model.p),
pointer(model.d),
length(model.d),
pointer(model.nuc_m),
pointer(model.nuc_n),
length(model.nuc_m),
pointer(model.ell1),
length(model.ell1),
pointer(model.sl_k),
pointer(model.sl_n),
length(model.sl_n),
)
scs_data = ScsData{T}(
model.m,
Expand Down Expand Up @@ -434,12 +486,82 @@ function scs_solve(
ep::Integer,
ed::Integer,
p::Vector{Float64},
# d::Vector{<:Integer}, # Skip this argument
# nuc_m::Vector{<:Integer}, # Skip this argument
# nuc_n::Vector{<:Integer}, # Skip this argument
# ell1::Vector{<:Integer}, # Skip this argument
# sl_n::Vector{<:Integer}, # Skip this argument
# sl_k::Vector{<:Integer}, # Skip this argument
primal_sol::Vector{Float64} = zeros(n),
dual_sol::Vector{Float64} = zeros(m),
slack::Vector{Float64} = zeros(m);
warm_start::Bool = false,
options...,
)
T = scsint_t(linear_solver)
return scs_solve(
linear_solver,
m,
n,
A,
P,
b,
c,
z,
l,
bu,
bl,
q,
s,
T[], # Default cs argument
ep,
ed,
p,
T[], # Default d argument
T[], # Default nuc_m argument
T[], # Default nuc_n argument
T[], # Default ell1 argument
T[], # Default sl_n argument
T[], # Default sl_k argument
primal_sol,
dual_sol,
slack;
warm_start,
options...,
)
end

function scs_solve(
linear_solver::Type{<:LinearSolver},
m::Integer,
n::Integer,
A,
P,
b::Vector{Float64},
c::Vector{Float64},
z::Integer,
l::Integer,
bu::Vector{Float64},
bl::Vector{Float64},
q::Vector{<:Integer},
s::Vector{<:Integer},
cs::Vector{<:Integer},
ep::Integer,
ed::Integer,
p::Vector{Float64},
# d::Vector{<:Integer}, # Skip this argument
# nuc_m::Vector{<:Integer}, # Skip this argument
# nuc_n::Vector{<:Integer}, # Skip this argument
# ell1::Vector{<:Integer}, # Skip this argument
# sl_n::Vector{<:Integer}, # Skip this argument
# sl_k::Vector{<:Integer}, # Skip this argument
primal_sol::Vector{Float64} = zeros(n),
dual_sol::Vector{Float64} = zeros(m),
slack::Vector{Float64} = zeros(m);
warm_start::Bool = false,
options...,
)
T = scsint_t(linear_solver)
return scs_solve(
linear_solver,
m,
Expand All @@ -454,10 +576,16 @@ function scs_solve(
bl,
q,
s,
Int[], # Default cs argument
cs,
ep,
ed,
p,
T[], # Default d argument
T[], # Default nuc_m argument
T[], # Default nuc_n argument
T[], # Default ell1 argument
T[], # Default sl_n argument
T[], # Default sl_k argument
primal_sol,
dual_sol,
slack;
Expand Down
Loading
Loading