diff --git a/.github/workflows/format_check.yml b/.github/workflows/format_check.yml index c4482c2..c0435ca 100644 --- a/.github/workflows/format_check.yml +++ b/.github/workflows/format_check.yml @@ -18,7 +18,7 @@ jobs: shell: julia --color=yes {0} run: | using Pkg - Pkg.add(PackageSpec(name="JuliaFormatter", version="1")) + Pkg.add(PackageSpec(name="JuliaFormatter", version="2")) using JuliaFormatter format(".", verbose=true) out = String(read(Cmd(`git diff`))) diff --git a/Project.toml b/Project.toml index 8bc5e08..0a4e80b 100644 --- a/Project.toml +++ b/Project.toml @@ -1,14 +1,16 @@ name = "DSDP" uuid = "2714ae6b-e930-5b4e-9c21-d0bacf577842" -repo = "https://github.com/jump-dev/DSDP.jl.git" version = "0.2.1" +repo = "https://github.com/jump-dev/DSDP.jl.git" [deps] +CEnum = "fa961155-64e5-5f13-b03f-caf6b980ea82" DSDP_jll = "1065e140-e56c-5613-be8b-7480bf7138df" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" [compat] +CEnum = "0.5.0" DSDP_jll = "0.0.1" MathOptInterface = "1" julia = "1.10" diff --git a/gen/Project.toml b/gen/Project.toml new file mode 100644 index 0000000..87e6020 --- /dev/null +++ b/gen/Project.toml @@ -0,0 +1,6 @@ +[deps] +Clang = "40e3b903-d033-50b4-a0cc-940c62c95e31" +DSDP_jll = "1065e140-e56c-5613-be8b-7480bf7138df" + +[compat] +Clang = "0.17" diff --git a/gen/gen.jl b/gen/gen.jl new file mode 100644 index 0000000..dafeddd --- /dev/null +++ b/gen/gen.jl @@ -0,0 +1,33 @@ +# Copyright (c) 2019 Mathieu Besançon, Oscar Dowson, and 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. + +import Clang +import DSDP_jll + +dir = joinpath(DSDP_jll.artifact_dir, "include") +Clang.Generators.create_context( + joinpath.(dir, ["dsdp5.h"]), + [Clang.Generators.get_default_args(); "-I$dir"], + Clang.Generators.load_options(joinpath(@__DIR__, "generate.toml")), +) |> Clang.Generators.build! + +filename = joinpath(@__DIR__, "..", "src", "libdsdp.jl") +contents = read(filename, String) +for cone in ["DSDP", "SDPCone", "LPCone", "BCone"] + global contents = replace( + contents, + "const $(cone)_C = Cvoid\n\n" => "", + "const $(cone) = Ptr{$(cone)_C}\n\n" => "", + "::$(cone)," => "::Ptr{Cvoid},", + "::$(cone))" => "::Ptr{Cvoid})", + "{$(cone)}" => "{Ptr{Cvoid}}", + ) +end +contents = replace(contents, r"const .+?\n\n" => "") +contents = replace(contents, r"# Skipping.+" => "") +for _ in 1:10 + global contents = replace(contents, "\n\n\n" => "\n\n") +end +write(filename, contents) diff --git a/gen/generate.toml b/gen/generate.toml new file mode 100644 index 0000000..db46d2e --- /dev/null +++ b/gen/generate.toml @@ -0,0 +1,13 @@ +[general] +library_name = "libdsdp" +output_file_path = "src/libdsdp.jl" +print_using_CEnum = false +prologue_file_path = "gen/prologue.jl" +use_deterministic_symbol = true + +[codegen] +opaque_as_mutable_struct = false +use_ccall_macro = true + +[codegen.macro] +macro_mode = "basic" diff --git a/gen/prologue.jl b/gen/prologue.jl new file mode 100644 index 0000000..3123837 --- /dev/null +++ b/gen/prologue.jl @@ -0,0 +1,7 @@ +# Copyright (c) 2022: Joey Huchette, Benoît Legat, and 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. + +# Disable JuliaFormatter for this file. +#!format:off diff --git a/src/DSDP.jl b/src/DSDP.jl index 41399b9..2bda23f 100644 --- a/src/DSDP.jl +++ b/src/DSDP.jl @@ -5,84 +5,15 @@ module DSDP -import DSDP_jll +using CEnum: @cenum +using DSDP_jll: libdsdp +import LinearAlgebra +import MathOptInterface as MOI -using LinearAlgebra +include("libdsdp.jl") -macro dsdp_ccall(f, args...) - quote - # QuoteNode prevents the interpretion of the symbol - # and leave it as a symbol - info = - ccall(($(QuoteNode(f)), DSDP_jll.libdsdp), Cint, $(esc.(args)...)) - if !iszero(info) - error("DSDP call $($(QuoteNode(f))) returned nonzero status $info.") - end - end -end - -const DSDPT = Ptr{Nothing} - -include("dsdp5_enums.jl") -include("dsdp5_API.jl") - -include("lpcone.jl") -function CreateLPCone(dsdp::DSDPT) - lpcone = Ref{LPCone.LPConeT}() - @dsdp_ccall DSDPCreateLPCone (DSDPT, Ref{LPCone.LPConeT}) dsdp lpcone - return lpcone[] -end - -include("sdpcone.jl") -function CreateSDPCone(dsdp::DSDPT, n::Integer) - sdpcone = Ref{SDPCone.SDPConeT}() - @dsdp_ccall DSDPCreateSDPCone (DSDPT, Cint, Ref{SDPCone.SDPConeT}) dsdp n sdpcone - return sdpcone[] -end - -include("bcone.jl") -function CreateBCone(dsdp::DSDPT) - bcone = Ref{BCone.BConeT}() - @dsdp_ccall DSDPCreateBCone (DSDPT, Ref{BCone.BConeT}) dsdp bcone - return bcone[] -end - -# Writes to `input.sdpa` -function PrintData( - dsdp::DSDPT, - sdpcone::SDPCone.SDPConeT, - lpcone::LPCone.LPConeT, -) - @dsdp_ccall DSDPPrintData (DSDPT, SDPCone.SDPConeT, LPCone.LPConeT) dsdp sdpcone lpcone -end - -function PrintSolution( - fp::Libc.FILE, - dsdp::DSDPT, - sdpcone::SDPCone.SDPConeT, - lpcone::LPCone.LPConeT, -) - @dsdp_ccall DSDPPrintSolution ( - Ptr{Cvoid}, - DSDPT, - SDPCone.SDPConeT, - LPCone.LPConeT, - ) fp dsdp sdpcone lpcone -end - -function PrintSolution( - dsdp::DSDPT, - sdpcone::SDPCone.SDPConeT, - lpcone::LPCone.LPConeT, -) - # See https://discourse.julialang.org/t/access-c-stdout-in-julia/24187/2 - stdout = Libc.FILE(Libc.RawFD(1), "w") - return PrintSolution(stdout, dsdp, sdpcone, lpcone) -end - -#function PrintSolution(arg1, arg2::DSDPT, arg3::SDPCone.SDPConeT, arg4::LPCone.LPConeT) -# @dsdp_ccall DSDPPrintSolution (Ptr{FILE}, DSDP, SDPCone.SDPConeT, LPCone.LPConeT) arg1 arg2 arg3 arg4 -#end +# This one is named poorly in the upstream C API +const DSDPSetReuseMatrix = DSDPReuseMatrix include("MOI_wrapper.jl") diff --git a/src/MOI_wrapper.jl b/src/MOI_wrapper.jl index c895e8e..9a607a3 100644 --- a/src/MOI_wrapper.jl +++ b/src/MOI_wrapper.jl @@ -3,11 +3,19 @@ # 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. -import MathOptInterface as MOI +macro _check(expr) + @assert expr.head == :call + msg = "Error calling $(expr.args[1])" + return quote + if (ret = $(esc(expr))) != 0 + error($msg) + end + end +end mutable struct Optimizer <: MOI.AbstractOptimizer - dsdp::DSDPT - lpcone::LPCone.LPConeT + dsdp::Ptr{Cvoid} + lpcone::Ptr{Cvoid} objective_constant::Cdouble objective_sign::Int b::Vector{Cdouble} @@ -21,7 +29,7 @@ mutable struct Optimizer <: MOI.AbstractOptimizer # Otherwise, `blk[i]` is the **number** of SDP blocks before + 1 # and hence the index in `sdpdrows`, `sdpdcols` and `sdpdcoefs`. blk::Vector{Int} - sdpcone::SDPCone.SDPConeT + sdpcone::Ptr{Nothing} # Sum of length of diagonal blocks nlpdrows::Int lpdvars::Vector{Int} @@ -33,10 +41,10 @@ mutable struct Optimizer <: MOI.AbstractOptimizer sdpdcoefs::Vector{Vector{Vector{Cdouble}}} y::Vector{Cdouble} silent::Bool - options::Dict{Symbol,Any} + options::Dict{String,Any} function Optimizer() - optimizer = new( + model = new( C_NULL, C_NULL, 0.0, @@ -51,179 +59,161 @@ mutable struct Optimizer <: MOI.AbstractOptimizer Int[], Cdouble[], Vector{Int}[], - Vector{Cdouble}[], + Vector{Vector{Cdouble}}[], Cdouble[], false, - Dict{Symbol,Any}(), + Dict{String,Any}(), ) - finalizer(_free, optimizer) - return optimizer + finalizer(MOI.empty!, model) + return model end end -varmap(optimizer::Optimizer, vi::MOI.VariableIndex) = optimizer.varmap[vi.value] +Base.cconvert(::Type{Ptr{Cvoid}}, x::Optimizer) = x -MOI.supports(::Optimizer, ::MOI.Silent) = true - -function MOI.set(optimizer::Optimizer, ::MOI.Silent, value::Bool) - optimizer.silent = value - return -end +Base.unsafe_convert(::Type{Ptr{Cvoid}}, x::Optimizer) = x.dsdp -MOI.get(optimizer::Optimizer, ::MOI.Silent) = optimizer.silent +# MOI.Silent -MOI.get(::Optimizer, ::MOI.SolverName) = "DSDP" +MOI.supports(::Optimizer, ::MOI.Silent) = true -function MOI.empty!(optimizer::Optimizer) - _free(optimizer) - optimizer.objective_constant = 0 - optimizer.objective_sign = 1 - empty!(optimizer.b) - empty!(optimizer.blockdims) - empty!(optimizer.varmap) - empty!(optimizer.blk) - optimizer.nlpdrows = 0 - empty!(optimizer.lpdvars) - empty!(optimizer.lpdrows) - empty!(optimizer.lpcoefs) - empty!(optimizer.sdpdinds) - empty!(optimizer.sdpdcoefs) - empty!(optimizer.y) +function MOI.set(model::Optimizer, ::MOI.Silent, value::Bool) + model.silent = value return end -function MOI.is_empty(optimizer::Optimizer) - return iszero(optimizer.objective_constant) && - isone(optimizer.objective_sign) && - isempty(optimizer.b) && - isempty(optimizer.blockdims) && - isempty(optimizer.varmap) && - isempty(optimizer.blk) && - iszero(optimizer.nlpdrows) && - isempty(optimizer.lpdvars) && - isempty(optimizer.lpdrows) && - isempty(optimizer.lpcoefs) && - isempty(optimizer.sdpdinds) && - isempty(optimizer.sdpdcoefs) -end - -function _free(m::Optimizer) - if m.dsdp != C_NULL - #Destroy(m.dsdp) - m.dsdp = C_NULL - m.lpcone = C_NULL - m.sdpcone = C_NULL - end - return -end +MOI.get(model::Optimizer, ::MOI.Silent) = model.silent -# Taken from src/solver/dsdpsetup.c -const gettable_options = Dict( - # Stopping parameters - :MaxIts => 500, - :GapTolerance => 1.0e-7, # 100<=nconstrs<=3000 => 1e-6, nconstrs>3000 => 5e-6 - :PNormTolerance => 1.0e30, - :DualBound => 1.0e20, - :StepTolerance => 5.0e-2, - :RTolerance => 1.0e-6, - :PTolerance => 1.0e-4, - # Solver options - :MaxTrustRadius => 1.0e10, - :BarrierParameter => -1.0, - :PotentialParameter => 5.0, # nconstrs>100 => 3.0 - :PenaltyParameter => 1.0e8, - :ReuseMatrix => 4, # 100 7, nconstrs>1000 => 10 - :YBounds => (-1e7, 1e7), -) -# TODO -# UsePenalty(dsdp,0) -# UseDynamicRho(dsdp,1) -# DSDPLogInfoAllow(iloginfo,0) -# DSDPSetFixedVariable[s] -# DSDPSetDualLowerBound - -const options = Dict( - # Solver options - :R0 => -1.0, - :ZBar => 1e10, -) +# MOI.SolverName -const options_setters = Dict{Symbol,Function}() - -abstract type Option <: MOI.AbstractOptimizerAttribute end - -abstract type GettableOption <: Option end - -MOI.supports(solver::Optimizer, ::Option) = true +MOI.get(::Optimizer, ::MOI.SolverName) = "DSDP" -function MOI.set(m::Optimizer, o::Option, val) - # Need to set it in the dictionary so that it is also used when init! is called again - _dict_set!(m.options, o, val) - _call_set!(m.dsdp, o, val)r +# Empty + +function MOI.empty!(model::Optimizer) + if model.dsdp != C_NULL + @_check DSDPDestroy(model) + model.dsdp = C_NULL + model.lpcone = C_NULL + model.sdpcone = C_NULL + end + model.objective_constant = 0 + model.objective_sign = 1 + empty!(model.b) + empty!(model.blockdims) + empty!(model.varmap) + empty!(model.blk) + model.nlpdrows = 0 + empty!(model.lpdvars) + empty!(model.lpdrows) + empty!(model.lpcoefs) + empty!(model.sdpdinds) + empty!(model.sdpdcoefs) + empty!(model.y) return end -MOI.get(m::Optimizer, o::Option) = _dict_get(m.options, o) - -function MOI.get(m::Optimizer, o::GettableOption) - if m.dsdp == C_NULL - return _dict_get(m.options, o) - end - # May be different from _dict_get for ReuseMatrix, GapTolerance and PotentialParameter since it depends on nconstrs - return _call_get(m.dsdp, o) +function MOI.is_empty(model::Optimizer) + return iszero(model.objective_constant) && + isone(model.objective_sign) && + isempty(model.b) && + isempty(model.blockdims) && + isempty(model.varmap) && + isempty(model.blk) && + iszero(model.nlpdrows) && + isempty(model.lpdvars) && + isempty(model.lpdrows) && + isempty(model.lpcoefs) && + isempty(model.sdpdinds) && + isempty(model.sdpdcoefs) +end + +# MOI.RawOptimizerAttribute + +function MOI.supports(model::Optimizer, attr::MOI.RawOptimizerAttribute) + return attr.name in ( + "MaxIts", + "GapTolerance", + "PNormTolerance", + "DualBound", + "StepTolerance", + "RTolerance", + "PTolerance", + "MaxTrustRadius", + "BarrierParameter", + "PotentialParameter", + "PenaltyParameter", + "ReuseMatrix", + "R0", + "ZBar", + ) end -for (param, default) in gettable_options - getter = Symbol("Get" * string(param)) - @eval begin - struct $param <: GettableOption end - function _call_get(dsdp, ::$param) - return $getter(dsdp) - end +function MOI.get(model::Optimizer, attr::MOI.RawOptimizerAttribute) + if !MOI.supports(model, attr) + throw(MOI.UnsupportedAttribute(attr)) end + return get(model, attr.name, nothing) end -for option in keys(options) - @eval begin - struct $option <: Option end +function MOI.set(model::Optimizer, attr::MOI.RawOptimizerAttribute, value) + if !MOI.supports(model, attr) + throw(MOI.UnsupportedAttribute(attr)) end + model.options[attr.name] = value + return end -for (param, default) in Iterators.flatten((options, gettable_options)) - setter = Symbol("Set" * string(param)) - sym = QuoteNode(param) - @eval begin - options_setters[$sym] = $setter - function _dict_set!(options, ::$param, val) - return options[$sym] = val - end - function _dict_get(options, ::$param) - return get(options, $sym, $default) - end - function _call_set!(dsdp, ::$param, val) - return $setter(dsdp, val) - end +function _set_inner_option(model, name, value) + if name == "MaxIts" + @_check DSDPSetMaxIts(model, value) + elseif name == "GapTolerance" + @_check DSDPSetGapTolerance(model, value) + elseif name == "PNormTolerance" + @_check DSDPSetPNormTolerance(model, value) + elseif name == "DualBound" + @_check DSDPSetDualBound(model, value) + elseif name == "StepTolerance" + @_check DSDPSetStepTolerance(model, value) + elseif name == "RTolerance" + @_check DSDPSetRTolerance(model, value) + elseif name == "PTolerance" + @_check DSDPSetPTolerance(model, value) + elseif name == "MaxTrustRadius" + @_check DSDPSetMaxTrustRadius(model, value) + elseif name == "BarrierParameter" + @_check DSDPSetBarrierParameter(model, value) + elseif name == "PotentialParameter" + @_check DSDPSetPotentialParameter(model, value) + elseif name == "PenaltyParameter" + @_check DSDPSetPenaltyParameter(model, value) + elseif name == "ReuseMatrix" + @_check DSDPSetReuseMatrix(model, value) + elseif name == "R0" + @_check DSDPSetR0(model, value) + else + @assert name == "ZBar" + @_check DSDPSetZBar(model, value) end + return end +# MOI.supports + +MOI.supports(::Optimizer, ::MOI.ObjectiveSense) = true + function MOI.supports( ::Optimizer, - ::Union{ - MOI.ObjectiveSense, - MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Cdouble}}, - }, + ::MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Cdouble}}, ) return true end MOI.supports_add_constrained_variables(::Optimizer, ::Type{MOI.Reals}) = false -const SupportedSets = - Union{MOI.Nonnegatives,MOI.PositiveSemidefiniteConeTriangle} - function MOI.supports_add_constrained_variables( ::Optimizer, - ::Type{<:SupportedSets}, + ::Type{<:Union{MOI.Nonnegatives,MOI.PositiveSemidefiniteConeTriangle}}, ) return true end @@ -236,36 +226,26 @@ function MOI.supports_constraint( return true end -function new_block(optimizer::Optimizer, set::MOI.Nonnegatives) - push!(optimizer.blockdims, -MOI.dimension(set)) - blk = length(optimizer.blockdims) +function _new_block(model::Optimizer, set::MOI.Nonnegatives) + push!(model.blockdims, -MOI.dimension(set)) + blk = length(model.blockdims) for i in 1:MOI.dimension(set) - push!(optimizer.varmap, (blk, i, i)) + push!(model.varmap, (blk, i, i)) end return end -function new_block( - optimizer::Optimizer, - set::MOI.PositiveSemidefiniteConeTriangle, -) - push!(optimizer.blockdims, set.side_dimension) - blk = length(optimizer.blockdims) +function _new_block(model::Optimizer, set::MOI.PositiveSemidefiniteConeTriangle) + push!(model.blockdims, set.side_dimension) + blk = length(model.blockdims) for j in 1:set.side_dimension for i in 1:j - push!(optimizer.varmap, (blk, i, j)) + push!(model.varmap, (blk, i, j)) end end return end -function _add_constrained_variables(optimizer::Optimizer, set::SupportedSets) - offset = length(optimizer.varmap) - new_block(optimizer, set) - ci = MOI.ConstraintIndex{MOI.VectorOfVariables,typeof(set)}(offset + 1) - return [MOI.VariableIndex(i) for i in offset .+ (1:MOI.dimension(set))], ci -end - function _error(start, stop) return error( start, @@ -274,13 +254,12 @@ function _error(start, stop) ) end -# Copied from CSDP.jl -function constrain_variables_on_creation( - dest::MOI.ModelLike, +function _constrain_variables_on_creation( + dest::Optimizer, src::MOI.ModelLike, index_map::MOI.Utilities.IndexMap, ::Type{S}, -) where {S<:SupportedSets} +) where {S<:Union{MOI.Nonnegatives,MOI.PositiveSemidefiniteConeTriangle}} for ci_src in MOI.get(src, MOI.ListOfConstraintIndices{MOI.VectorOfVariables,S}()) f_src = MOI.get(src, MOI.ConstraintFunction(), ci_src) @@ -294,81 +273,69 @@ function constrain_variables_on_creation( "Cannot copy constraint `$(ci_src)` as variables constrained on creation because some variables of the function `$(f_src)` are in another constraint as well.", "to bridge constraints having the same variables by creating slack variables.", ) - else - set = MOI.get(src, MOI.ConstraintSet(), ci_src)::S - vis_dest, ci_dest = _add_constrained_variables(dest, set) - index_map[ci_src] = ci_dest - for (vi_src, vi_dest) in zip(f_src.variables, vis_dest) - index_map[vi_src] = vi_dest - end + end + set = MOI.get(src, MOI.ConstraintSet(), ci_src)::S + offset = length(dest.varmap) + _new_block(dest, set) + index_map[ci_src] = + MOI.ConstraintIndex{MOI.VectorOfVariables,S}(offset + 1) + for (i, vi_src) in enumerate(f_src.variables) + index_map[vi_src] = MOI.VariableIndex(offset + i) end end return end -function _setcoefficient!( - m::Optimizer, +function _set_coefficient( + model::Optimizer, coef, constr::Integer, blk::Integer, i::Integer, j::Integer, ) - if m.blockdims[blk] < 0 + if model.blockdims[blk] < 0 @assert i == j - push!(m.lpdvars, constr + 1) - push!(m.lpdrows, m.blk[blk] + i - 1) # -1 because indexing starts at 0 in DSDP - push!(m.lpcoefs, coef) + push!(model.lpdvars, constr + 1) + push!(model.lpdrows, model.blk[blk] + i - 1) # -1 because indexing starts at 0 in DSDP + push!(model.lpcoefs, coef) else - sdp = m.blk[blk] - push!(m.sdpdinds[end][sdp], i + (j - 1) * m.blockdims[blk] - 1) + sdp = model.blk[blk] + push!(model.sdpdinds[end][sdp], i + (j - 1) * model.blockdims[blk] - 1) if i != j coef /= 2 end - push!(m.sdpdcoefs[end][sdp], coef) + push!(model.sdpdcoefs[end][sdp], coef) end return end -# Loads objective coefficient α * vi -function load_objective_term!( - optimizer::Optimizer, - index_map, - α, - vi::MOI.VariableIndex, -) - blk, i, j = varmap(optimizer, vi) - coef = optimizer.objective_sign * α - _setcoefficient!(optimizer, coef, 0, blk, i, j) - return -end - -function _set_A_matrices(m::Optimizer, i) - for (blk, blkdim) in zip(m.blk, m.blockdims) +function _set_A_matrices(model::Optimizer, i) + for (blk, blkdim) in zip(model.blk, model.blockdims) if blkdim > 0 - SDPCone.SetASparseVecMat( - m.sdpcone, + @_check SDPConeSetASparseVecMat( + model.sdpcone, blk - 1, i, blkdim, 1.0, 0, - m.sdpdinds[end][blk], - m.sdpdcoefs[end][blk], - length(m.sdpdcoefs[end][blk]), + model.sdpdinds[end][blk], + model.sdpdcoefs[end][blk], + length(model.sdpdcoefs[end][blk]), ) end end return end -function _new_A_matrix(m::Optimizer) - push!(m.sdpdinds, Vector{Cint}[]) - push!(m.sdpdcoefs, Vector{Cdouble}[]) - for i in eachindex(m.blockdims) - if m.blockdims[i] >= 0 - push!(m.sdpdinds[end], Cint[]) - push!(m.sdpdcoefs[end], Cdouble[]) +function _new_A_matrix(model::Optimizer) + push!(model.sdpdinds, Vector{Cint}[]) + push!(model.sdpdcoefs, Vector{Cdouble}[]) + for i in eachindex(model.blockdims) + if model.blockdims[i] >= 0 + push!(model.sdpdinds[end], Cint[]) + push!(model.sdpdcoefs[end], Cdouble[]) end end return @@ -376,11 +343,11 @@ end # Largely inspired from CSDP.jl function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike) - MOI.empty!(dest) + @assert MOI.is_empty(dest) index_map = MOI.Utilities.IndexMap() # Step 1) Compute the dimensions of what needs to be allocated - constrain_variables_on_creation(dest, src, index_map, MOI.Nonnegatives) - constrain_variables_on_creation( + _constrain_variables_on_creation(dest, src, index_map, MOI.Nonnegatives) + _constrain_variables_on_creation( dest, src, index_map, @@ -393,21 +360,9 @@ function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike) "to bridge free variables into `x - y` where `x` and `y` are nonnegative.", ) end - cis_src = MOI.get( - src, - MOI.ListOfConstraintIndices{ - MOI.ScalarAffineFunction{Cdouble}, - MOI.EqualTo{Cdouble}, - }(), - ) - if isempty(cis_src) - throw( - ArgumentError("DSDP does not support problems with no constraint."), - ) - end - dest.b = Vector{Cdouble}(undef, length(cis_src)) - _free(dest) - dest.nlpdrows = 0 + F, S = MOI.ScalarAffineFunction{Cdouble}, MOI.EqualTo{Float64} + cis_src = MOI.get(src, MOI.ListOfConstraintIndices{F,S}()) + resize!(dest.b, length(cis_src)) dest.blk = zero(dest.blockdims) num_sdp = 0 for i in 1:length(dest.blockdims) @@ -419,63 +374,44 @@ function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike) dest.blk[i] = num_sdp end end - dest.lpdvars = Int[] - dest.lpdrows = Int[] - dest.lpcoefs = Cdouble[] - dest.dsdp = Create(length(dest.b)) + # Create a new solver object with the correct number of constraints. + p = Ref{Ptr{Cvoid}}() + @_check DSDPCreate(length(dest.b), p) + dest.dsdp = p[] for (option, value) in dest.options - options_setters[option](dest.dsdp, value) - end - if !iszero(num_sdp) - dest.sdpcone = CreateSDPCone(dest.dsdp, num_sdp) - for i in eachindex(dest.blockdims) - if dest.blockdims[i] < 0 - continue + _set_inner_option(dest, option, value) + end + if num_sdp > 0 + sdpcone = Ref{Ptr{Cvoid}}() + @_check DSDPCreateSDPCone(dest, num_sdp, sdpcone) + dest.sdpcone = sdpcone[] + for (i, blk_dim) in enumerate(dest.blockdims) + if blk_dim < 0 + continue # It's an LP block end blk = dest.blk[i] - SDPCone.SetBlockSize(dest.sdpcone, blk - 1, dest.blockdims[i]) - # TODO what does this `0` mean ? - SDPCone.SetSparsity(dest.sdpcone, blk - 1, 0) - SDPCone.SetStorageFormat(dest.sdpcone, blk - 1, UInt8('U')) + @_check SDPConeSetBlockSize(dest.sdpcone, blk - 1, blk_dim) + @_check SDPConeSetStorageFormat(dest.sdpcone, blk - 1, UInt8('U')) end end - for constr in eachindex(dest.b) - # TODO in examples/readsdpa.c line 162, - # -0.0 is used instead of 0.0 if the dual obj is <= 0., check if it has impact - SetY0(dest.dsdp, constr, 0.0) - end - # TODO ComputeY0 as in examples/readsdpa.c - empty!(dest.y) for (k, ci_src) in enumerate(cis_src) - func = MOI.get(src, MOI.CanonicalConstraintFunction(), ci_src) - set = MOI.get(src, MOI.ConstraintSet(), ci_src) - if !iszero(MOI.constant(func)) - throw( - MOI.ScalarFunctionConstantNotZero{ - Cdouble, - MOI.ScalarAffineFunction{Cdouble}, - MOI.EqualTo{Cdouble}, - }( - MOI.constant(func), - ), - ) + f = MOI.get(src, MOI.CanonicalConstraintFunction(), ci_src) + s = MOI.get(src, MOI.ConstraintSet(), ci_src) + f_k = MOI.constant(f) + if !iszero(f_k) + throw(MOI.ScalarFunctionConstantNotZero{Cdouble,F,S}(f_k)) end - SetDualObjective(dest.dsdp, k, MOI.constant(set)) + @_check DSDPSetDualObjective(dest, k, MOI.constant(s)) _new_A_matrix(dest) - for t in func.terms + for t in f.terms if !iszero(t.coefficient) - blk, i, j = varmap(dest, index_map[t.variable]) - _setcoefficient!(dest, t.coefficient, k, blk, i, j) + blk, i, j = dest.varmap[index_map[t.variable].value] + _set_coefficient(dest, t.coefficient, k, blk, i, j) end end _set_A_matrices(dest, k) - dest.b[k] = MOI.constant(set) - index_map[ci_src] = MOI.ConstraintIndex{ - MOI.ScalarAffineFunction{Cdouble}, - MOI.EqualTo{Cdouble}, - }( - k, - ) + dest.b[k] = MOI.constant(s) + index_map[ci_src] = MOI.ConstraintIndex{F,S}(k) end # Throw error for variable attributes MOI.Utilities.pass_attributes(dest, src, index_map, vis_src) @@ -483,176 +419,162 @@ function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike) MOI.Utilities.pass_attributes(dest, src, index_map, cis_src) # Pass objective attributes and throw error for other ones model_attributes = MOI.get(src, MOI.ListOfModelAttributesSet()) + obj_attr = MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Cdouble}}() for attr in model_attributes - if attr != MOI.ObjectiveSense() && - attr != MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Cdouble}}() + if attr != MOI.ObjectiveSense() && attr != obj_attr throw(MOI.UnsupportedAttribute(attr)) end end - # We make sure to set `objective_sign` first before setting the objective if MOI.ObjectiveSense() in model_attributes - # DSDP convention is MIN so we reverse the sign of coef if it is MAX sense = MOI.get(src, MOI.ObjectiveSense()) dest.objective_sign = sense == MOI.MIN_SENSE ? 1 : -1 end - if MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Cdouble}}() in - model_attributes - func = MOI.get( - src, - MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Cdouble}}(), - ) - obj = MOI.Utilities.canonical(func) + if obj_attr in model_attributes + obj = MOI.Utilities.canonical(MOI.get(src, obj_attr)) dest.objective_constant = obj.constant _new_A_matrix(dest) for term in obj.terms if !iszero(term.coefficient) - load_objective_term!( - dest, - index_map, - term.coefficient, - index_map[term.variable], - ) + vi = index_map[term.variable] + blk, i, j = dest.varmap[vi.value] + coef = dest.objective_sign * term.coefficient + _set_coefficient(dest, coef, 0, blk, i, j) end end _set_A_matrices(dest, 0) end # Pass info to `dest.dsdp` if !isempty(dest.lpdvars) - dest.lpcone = CreateLPCone(dest.dsdp) - LPCone.SetDataSparse( - dest.lpcone, - dest.nlpdrows, + lpcone = Ref{Ptr{Cvoid}}() + @_check DSDPCreateLPCone(dest, lpcone) + dest.lpcone = lpcone[] + nnzin, row, aval = _build_lp( length(dest.b) + 1, dest.lpdvars, dest.lpdrows, dest.lpcoefs, ) + @_check LPConeSetData(dest.lpcone, dest.nlpdrows, nnzin, row, aval) end - Setup(dest.dsdp) + @_check DSDPSetup(dest) return index_map end -function MOI.optimize!(m::Optimizer) - Solve(m.dsdp) - # Calling `ComputeX` not right after `Solve` seems to sometime cause segfaults or weird Heisenbug's - # let's call it directly what `DSDP/examples/readsdpa.c` does - ComputeX(m.dsdp) - m.y = zeros(Cdouble, length(m.b)) - GetY(m.dsdp, m.y) - map!(-, m.y, m.y) # The primal objective is Max in SDOI but Min in DSDP +function _build_lp(nvars, lpdvars, lpdrows, lpcoefs) + @assert length(lpdvars) == length(lpdrows) == length(lpcoefs) + nzin = zeros(Cint, nvars) + n = length(lpdvars) + for var in lpdvars + nzin[var] += 1 + end + nnzin = Cint[zero(Cint); cumsum(nzin)] + @assert nnzin[end] == n + idx = map(var -> Int[], 1:nvars) + for (i, var) in enumerate(lpdvars) + push!(idx[var], i) + end + row = Vector{Cint}(undef, n) + aval = Vector{Cdouble}(undef, n) + for var in 1:nvars + sort!(idx[var]; by = i -> lpdrows[i]) + row[(nnzin[var]+1):(nnzin[var+1])] = lpdrows[idx[var]] + aval[(nnzin[var]+1):(nnzin[var+1])] = lpcoefs[idx[var]] + end + return nnzin, row, aval +end + +function MOI.optimize!(model::Optimizer) + @_check DSDPSetStandardMonitor(model, !model.silent ? 1 : 0) + @_check DSDPSolve(model) + # Calling `DSDPComputeX` not right after `DSDPSolve` seems to sometime cause + # segfaults or weird Heisenbug's. Let's call it directly after, like + # `DSDP/examples/readsdpa.c` does + @_check DSDPComputeX(model) + resize!(model.y, length(model.b)) + @_check DSDPGetY(model, model.y, length(model.y)) return end -function MOI.get(m::Optimizer, ::MOI.RawStatusString) - if m.dsdp == C_NULL +function MOI.get(model::Optimizer, ::MOI.RawStatusString) + if model.dsdp == C_NULL return "`optimize!` not called" end - status = StopReason(m.dsdp) - if status == DSDP_CONVERGED - return "Converged" - elseif status == DSDP_INFEASIBLE_START - return "Infeasible start" - elseif status == DSDP_SMALL_STEPS - return "Small steps" - elseif status == DSDP_INDEFINITE_SCHUR_MATRIX - return "Indefinite Schur matrix" - elseif status == DSDP_MAX_IT - return "Max iteration" - elseif status == DSDP_NUMERICAL_ERROR - return "Numerical error" - elseif status == DSDP_UPPERBOUND - return "Upperbound" - elseif status == DSDP_USER_TERMINATION - return "User termination" - elseif status == CONTINUE_ITERATING - return "Continue iterating" - end - return error("Internal library error: status=$status") -end - -function MOI.get(m::Optimizer, ::MOI.TerminationStatus) - if m.dsdp == C_NULL + stop = Ref{DSDPTerminationReason}() + @_check DSDPStopReason(model, stop) + return string(stop[]) +end + +const _TERMINATION_REASON_MAP = Dict( + DSDP_INFEASIBLE_START => MOI.OTHER_ERROR, + DSDP_SMALL_STEPS => MOI.SLOW_PROGRESS, + DSDP_INDEFINITE_SCHUR_MATRIX => MOI.NUMERICAL_ERROR, + DSDP_MAX_IT => MOI.ITERATION_LIMIT, + DSDP_NUMERICAL_ERROR => MOI.NUMERICAL_ERROR, + DSDP_UPPERBOUND => MOI.OBJECTIVE_LIMIT, + DSDP_USER_TERMINATION => MOI.INTERRUPTED, + CONTINUE_ITERATING => MOI.OTHER_ERROR, +) + +const _SOLUTION_TYPE_MAP = Dict( + DSDP_PDUNKNOWN => ( + MOI.OTHER_ERROR, + MOI.UNKNOWN_RESULT_STATUS, + MOI.UNKNOWN_RESULT_STATUS, + ), + DSDP_PDFEASIBLE => + (MOI.OPTIMAL, MOI.FEASIBLE_POINT, MOI.FEASIBLE_POINT), + # DSDP_UNBOUNDED means that (D) is unbounded, so (P) is infeasible + DSDP_UNBOUNDED => (MOI.INFEASIBLE, MOI.NO_SOLUTION, MOI.NO_SOLUTION), + # DSDP_INFEASIBLE means that (D) is infeasible + DSDP_INFEASIBLE => (MOI.DUAL_INFEASIBLE, MOI.NO_SOLUTION, MOI.NO_SOLUTION), +) + +function MOI.get(model::Optimizer, ::MOI.TerminationStatus) + if model.dsdp == C_NULL return MOI.OPTIMIZE_NOT_CALLED end - status = StopReason(m.dsdp) - if status == DSDP_CONVERGED - sol_status = GetSolutionType(m.dsdp) - if sol_status == DSDP_PDFEASIBLE - return MOI.OPTIMAL - elseif sol_status == DSDP_UNBOUNDED - return MOI.INFEASIBLE - elseif sol_status == DSDP_INFEASIBLE - return MOI.DUAL_INFEASIBLE - elseif sol_status == DSDP_PDUNKNOWN - return MOI.OTHER_ERROR - else - error("Internal library error: status=$sol_status") - end - elseif status == DSDP_INFEASIBLE_START - return MOI.OTHER_ERROR - elseif status == DSDP_SMALL_STEPS - return MOI.SLOW_PROGRESS - elseif status == DSDP_INDEFINITE_SCHUR_MATRIX - return MOI.NUMERICAL_ERROR - elseif status == DSDP_MAX_IT - return MOI.ITERATION_LIMIT - elseif status == DSDP_NUMERICAL_ERROR - return MOI.NUMERICAL_ERROR - elseif status == DSDP_UPPERBOUND - return MOI.OBJECTIVE_LIMIT - elseif status == DSDP_USER_TERMINATION - return MOI.INTERRUPTED - elseif status == CONTINUE_ITERATING - return MOI.OTHER_ERROR - end - return error("Internal library error: status=$status") -end - -function MOI.get(m::Optimizer, attr::MOI.PrimalStatus) - if attr.result_index > MOI.get(m, MOI.ResultCount()) - return MOI.NO_SOLUTION - end - status = GetSolutionType(m.dsdp) - if status == DSDP_PDUNKNOWN - return MOI.UNKNOWN_RESULT_STATUS - elseif status == DSDP_PDFEASIBLE - return MOI.FEASIBLE_POINT - elseif status == DSDP_UNBOUNDED - return MOI.INFEASIBLE_POINT - elseif status == DSDP_INFEASIBLE - return MOI.INFEASIBILITY_CERTIFICATE + stop = Ref{DSDPTerminationReason}() + @_check DSDPStopReason(model, stop) + if stop[] == DSDP_CONVERGED + sol = Ref{DSDPSolutionType}() + @_check DSDPGetSolutionType(model, sol) + return _SOLUTION_TYPE_MAP[sol[]][1] end - return error("Internal library error: status=$status") + return _TERMINATION_REASON_MAP[stop[]] end -function MOI.get(m::Optimizer, attr::MOI.DualStatus) - if attr.result_index > MOI.get(m, MOI.ResultCount()) +function MOI.get(model::Optimizer, attr::MOI.PrimalStatus) + if attr.result_index > MOI.get(model, MOI.ResultCount()) return MOI.NO_SOLUTION end - status = GetSolutionType(m.dsdp) - if status == DSDP_PDUNKNOWN - return MOI.UNKNOWN_RESULT_STATUS - elseif status == DSDP_PDFEASIBLE - return MOI.FEASIBLE_POINT - elseif status == DSDP_UNBOUNDED - return MOI.INFEASIBILITY_CERTIFICATE - elseif status == DSDP_INFEASIBLE - return MOI.INFEASIBLE_POINT - else - error("Internal library error: status=$status") + sol = Ref{DSDPSolutionType}() + @_check DSDPGetSolutionType(model, sol) + return _SOLUTION_TYPE_MAP[sol[]][2] +end + +function MOI.get(model::Optimizer, attr::MOI.DualStatus) + if attr.result_index > MOI.get(model, MOI.ResultCount()) + return MOI.NO_SOLUTION end + sol = Ref{DSDPSolutionType}() + @_check DSDPGetSolutionType(model, sol) + return _SOLUTION_TYPE_MAP[sol[]][3] end -MOI.get(m::Optimizer, ::MOI.ResultCount) = m.dsdp == C_NULL ? 0 : 1 +MOI.get(model::Optimizer, ::MOI.ResultCount) = model.dsdp == C_NULL ? 0 : 1 -function MOI.get(m::Optimizer, attr::MOI.ObjectiveValue) - MOI.check_result_index_bounds(m, attr) - return m.objective_sign * GetPPObjective(m.dsdp) + m.objective_constant +function MOI.get(model::Optimizer, attr::MOI.ObjectiveValue) + MOI.check_result_index_bounds(model, attr) + ret = Ref{Cdouble}() + @_check DSDPGetPPObjective(model, ret) + return model.objective_sign * ret[] + model.objective_constant end -function MOI.get(m::Optimizer, attr::MOI.DualObjectiveValue) - MOI.check_result_index_bounds(m, attr) - return m.objective_sign * GetDDObjective(m.dsdp) + m.objective_constant +function MOI.get(model::Optimizer, attr::MOI.DualObjectiveValue) + MOI.check_result_index_bounds(model, attr) + ret = Ref{Cdouble}() + @_check DSDPGetDDObjective(model, ret) + return model.objective_sign * ret[] + model.objective_constant end abstract type LPBlock <: AbstractMatrix{Cdouble} end @@ -663,7 +585,7 @@ Base.size(x::Union{LPBlock,SDPBlock}) = (x.dim, x.dim) function Base.getindex(x::LPBlock, i, j) if i == j - return get_array(x)[x.offset+i] + return _get_array(x)[x.offset+i] else return zero(Cdouble) end @@ -673,89 +595,111 @@ function Base.getindex(x::SDPBlock, i, j) if i > j return getindex(x, j, i) else - return get_array(x)[MOI.Utilities.trimap(i, j)] + return _get_array(x)[MOI.Utilities.trimap(i, j)] end end -include("blockdiag.jl") +abstract type AbstractBlockMatrix{T} <: AbstractMatrix{T} end + +function Base.size(bm::AbstractBlockMatrix) + n = mapreduce( + blk -> LinearAlgebra.checksquare(block(bm, blk)), + +, + 1:nblocks(bm); + init = 0, + ) + return (n, n) +end + +function Base.getindex(bm::AbstractBlockMatrix, i::Integer, j::Integer) + (i < 0 || j < 0) && throw(BoundsError(i, j)) + for k in 1:nblocks(bm) + blk = block(bm, k) + n = size(blk, 1) + if i <= n && j <= n + return blk[i, j] + elseif i <= n || j <= n + return 0 + else + i -= n + j -= n + end + end + i, j = (i, j) .+ size(bm) + throw(BoundsError(i, j)) +end + +Base.getindex(A::AbstractBlockMatrix, I::Tuple) = getindex(A, I...) abstract type BlockMat <: AbstractBlockMatrix{Cdouble} end -nblocks(x::BlockMat) = length(x.optimizer.blk) +nblocks(x::BlockMat) = length(x.model.blk) struct LPXBlock <: LPBlock - lpcone::LPCone.LPConeT + lpcone::Ptr{Cvoid} dim::Int offset::Int end -function get_array(x::LPXBlock) - return LPCone.GetXArray(x.lpcone) +function _get_array(x::LPXBlock) + xout = Ref{Ptr{Cdouble}}() + n = Ref{Cint}() + @_check LPConeGetXArray(x.lpcone, xout, n) + return unsafe_wrap(Array, xout[], n[]) end struct SDPXBlock <: SDPBlock - sdpcone::SDPCone.SDPConeT + sdpcone::Ptr{Nothing} dim::Int blockj::Int end -#get_array(x::SDPXBlock) = SDPCone.GetXArray(x.sdpcone, x.blockj - 1) -function get_array(x::SDPXBlock) - v = SDPCone.GetXArray(x.sdpcone, x.blockj - 1) +function _get_array(x::SDPXBlock) + xmat = Ref{Ptr{Cdouble}}() + nn = Ref{Cint}() + @_check SDPConeGetXArray(x.sdpcone, x.blockj - 1, xmat, nn) + v = unsafe_wrap(Array, xmat[], nn[]) return [v[i+(j-1)*x.dim] for j in 1:x.dim for i in 1:j] end -struct XBlockMat <: BlockMat - optimizer::Optimizer -end - -function block(x::XBlockMat, i) - if x.optimizer.blockdims[i] < 0 - LPXBlock( - x.optimizer.lpcone, - abs(x.optimizer.blockdims[i]), - x.optimizer.blk[i], - ) - else - SDPXBlock( - x.optimizer.sdpcone, - x.optimizer.blockdims[i], - x.optimizer.blk[i], - ) +function block(model::Optimizer, i) + if model.blockdims[i] < 0 + return LPXBlock(model.lpcone, abs(model.blockdims[i]), model.blk[i]) end + return SDPXBlock(model.sdpcone, model.blockdims[i], model.blk[i]) end -struct PrimalSolutionMatrix <: MOI.AbstractModelAttribute end - -MOI.is_set_by_optimize(::PrimalSolutionMatrix) = true - -MOI.get(optimizer::Optimizer, ::PrimalSolutionMatrix) = XBlockMat(optimizer) - -struct DualSolutionVector <: MOI.AbstractModelAttribute end - -MOI.is_set_by_optimize(::DualSolutionVector) = true - -function MOI.get(optimizer::Optimizer, ::DualSolutionVector) - return optimizer.y -end - -function block( - optimizer::Optimizer, - ci::MOI.ConstraintIndex{MOI.VectorOfVariables}, +function MOI.get( + model::Optimizer, + attr::MOI.VariablePrimal, + vi::MOI.VariableIndex, ) - return optimizer.varmap[ci.value][1] + MOI.check_result_index_bounds(model, attr) + blk, i, j = model.varmap[vi.value] + return block(model, blk)[i, j] end -function vectorize_block(M, blk::Integer, ::Type{MOI.Nonnegatives}) - return diag(block(M, blk)) +function MOI.get( + model::Optimizer, + attr::MOI.ConstraintPrimal, + ci::MOI.ConstraintIndex{MOI.VectorOfVariables,MOI.Nonnegatives}, +) + MOI.check_result_index_bounds(model, attr) + blk = model.varmap[ci.value][1] + return LinearAlgebra.diag(block(model, blk)) end -function vectorize_block( - M::AbstractMatrix{Cdouble}, - blk::Integer, - ::Type{MOI.PositiveSemidefiniteConeTriangle}, +function MOI.get( + model::Optimizer, + attr::MOI.ConstraintPrimal, + ci::MOI.ConstraintIndex{ + MOI.VectorOfVariables, + MOI.PositiveSemidefiniteConeTriangle, + }, ) - B = block(M, blk) + MOI.check_result_index_bounds(model, attr) + blk = model.varmap[ci.value][1] + B = block(model, blk) d = LinearAlgebra.checksquare(B) n = MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(d)) v = Vector{Cdouble}(undef, n) @@ -771,41 +715,13 @@ function vectorize_block( end function MOI.get( - optimizer::Optimizer, - attr::MOI.VariablePrimal, - vi::MOI.VariableIndex, -) - MOI.check_result_index_bounds(optimizer, attr) - blk, i, j = varmap(optimizer, vi) - return block(MOI.get(optimizer, PrimalSolutionMatrix()), blk)[i, j] -end - -function MOI.get( - optimizer::Optimizer, - attr::MOI.ConstraintPrimal, - ci::MOI.ConstraintIndex{MOI.VectorOfVariables,S}, -) where {S<:SupportedSets} - MOI.check_result_index_bounds(optimizer, attr) - return vectorize_block( - MOI.get(optimizer, PrimalSolutionMatrix()), - block(optimizer, ci), - S, - ) -end - -#function MOI.get(optimizer::Optimizer, attr::MOI.ConstraintDual, -# ci::MOI.ConstraintIndex{MOI.VectorOfVariables, S}) where S<:SupportedSets -# MOI.check_result_index_bounds(optimizer, attr) -# return vectorize_block(MOI.get(optimizer, DualSlackMatrix()), block(optimizer, ci), S) -#end -function MOI.get( - optimizer::Optimizer, + model::Optimizer, attr::MOI.ConstraintDual, ci::MOI.ConstraintIndex{ MOI.ScalarAffineFunction{Cdouble}, MOI.EqualTo{Cdouble}, }, ) - MOI.check_result_index_bounds(optimizer, attr) - return -MOI.get(optimizer, DualSolutionVector())[ci.value] + MOI.check_result_index_bounds(model, attr) + return model.y[ci.value] end diff --git a/src/bcone.jl b/src/bcone.jl deleted file mode 100644 index ac01804..0000000 --- a/src/bcone.jl +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2022: Joey Huchette, Benoît Legat, and 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. - -export BCone - -module BCone - -import ..@dsdp_ccall -const BConeT = Ptr{Nothing} - -function AllocateBounds(bcone::BConeT, arg2::Integer) - @dsdp_ccall BConeAllocateBounds (BConeT, Cint) bcone arg2 -end - -function SetLowerBound(bcone::BConeT, arg2::Integer, arg3::Cdouble) - @dsdp_ccall BConeSetLowerBound (BConeT, Cint, Cdouble) bcone arg2 arg3 -end - -function SetUpperBound(bcone::BConeT, arg2::Integer, arg3::Cdouble) - @dsdp_ccall BConeSetUpperBound (BConeT, Cint, Cdouble) bcone arg2 arg3 -end - -function SetPSlackVariable(bcone::BConeT, arg2::Integer) - @dsdp_ccall BConeSetPSlackVariable (BConeT, Cint) bcone arg2 -end - -function SetPSurplusVariable(bcone::BConeT, arg2::Integer) - @dsdp_ccall BConeSetPSurplusVariable (BConeT, Cint) bcone arg2 -end - -function ScaleBarrier(bcone::BConeT, arg2::Cdouble) - @dsdp_ccall BConeScaleBarrier (BConeT, Cdouble) bcone arg2 -end - -function View(bcone::BConeT) - @dsdp_ccall BConeView (BConeT,) bcone -end - -function SetXArray(bcone::BConeT, arg2::Vector{Cdouble}, arg3::Integer) - @dsdp_ccall BConeSetXArray (BConeT, Ptr{Cdouble}, Cint) bcone arg2 arg3 -end - -function CopyX( - bcone::BConeT, - arg2::Vector{Cdouble}, - arg3::Vector{Cdouble}, - arg4::Integer, -) - @dsdp_ccall BConeCopyX (BConeT, Ptr{Cdouble}, Ptr{Cdouble}, Cint) bcone arg2 arg3 arg4 -end - -end diff --git a/src/blockdiag.jl b/src/blockdiag.jl deleted file mode 100644 index 83ad513..0000000 --- a/src/blockdiag.jl +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (c) 2022: Joey Huchette, Benoît Legat, and 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. - -abstract type AbstractBlockMatrix{T} <: AbstractMatrix{T} end - -function nblocks end -function block end - -function Base.size(bm::AbstractBlockMatrix) - n = mapreduce( - blk -> LinearAlgebra.checksquare(block(bm, blk)), - +, - 1:nblocks(bm); - init = 0, - ) - return (n, n) -end -function Base.getindex(bm::AbstractBlockMatrix, i::Integer, j::Integer) - (i < 0 || j < 0) && throw(BoundsError(i, j)) - for k in 1:nblocks(bm) - blk = block(bm, k) - n = size(blk, 1) - if i <= n && j <= n - return blk[i, j] - elseif i <= n || j <= n - return 0 - else - i -= n - j -= n - end - end - i, j = (i, j) .+ size(bm) - throw(BoundsError(i, j)) -end -Base.getindex(A::AbstractBlockMatrix, I::Tuple) = getindex(A, I...) diff --git a/src/dsdp5_API.jl b/src/dsdp5_API.jl deleted file mode 100644 index 99f94a0..0000000 --- a/src/dsdp5_API.jl +++ /dev/null @@ -1,424 +0,0 @@ -# Copyright (c) 2022: Joey Huchette, Benoît Legat, and 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. - -# Julia wrapper for header: include/dsdp5.h -# Automatically generated using Clang.jl wrap_c, version 0.0.0 - -function LogInfoAllow(i::Integer) - @dsdp_ccall DSDPLogInfoAllow (Cint, Ptr{Cchar}) i C_NULL -end - -function SetConvergenceFlag(dsdp::DSDPT, arg2::DSDPTerminationReason) - @dsdp_ccall DSDPSetConvergenceFlag (DSDPT, DSDPTerminationReason) dsdp arg2 -end - -function Create(m::Integer) - dsdp = Ref{DSDPT}() - @dsdp_ccall DSDPCreate (Cint, Ref{DSDPT}) m dsdp - return dsdp[] -end - -function Setup(dsdp::DSDPT) - @dsdp_ccall DSDPSetup (DSDPT,) dsdp -end - -function Solve(dsdp::DSDPT) - @dsdp_ccall DSDPSolve (DSDPT,) dsdp -end - -function ComputeX(dsdp::DSDPT) - @dsdp_ccall DSDPComputeX (DSDPT,) dsdp -end - -function ComputeAndFactorS(dsdp::DSDPT) - psdefinite = Ref{DSDPTruth}() - GC.@preserve psdefinite dsdp begin - @dsdp_ccall DSDPComputeAndFactorS (DSDPT, Ref{DSDPTruth}) dsdp psdefinite - return psdefinite[] - end -end - -function Destroy(dsdp::DSDPT) - @dsdp_ccall DSDPDestroy (DSDPT,) dsdp -end - -function SetDualObjective(dsdp::DSDPT, arg2::Integer, arg3::Cdouble) - @dsdp_ccall DSDPSetDualObjective (DSDPT, Cint, Cdouble) dsdp arg2 arg3 -end - -function AddObjectiveConstant(dsdp::DSDPT, arg2::Cdouble) - @dsdp_ccall DSDPAddObjectiveConstant (DSDPT, Cdouble) dsdp arg2 -end - -function GetDObjective(dsdp::DSDPT) - dobj = Ref{Cdouble}() - @dsdp_ccall DSDPGetDObjective (DSDPT, Ref{Cdouble}) dsdp dobj - return dobj[] -end - -function GetDDObjective(dsdp::DSDPT) - ddobj = Ref{Cdouble}() - @dsdp_ccall DSDPGetDDObjective (DSDPT, Ref{Cdouble}) dsdp ddobj - return ddobj[] -end - -function GetPObjective(dsdp::DSDPT) - pobj = Ref{Cdouble}() - @dsdp_ccall DSDPGetPObjective (DSDPT, Ptr{Cdouble}) dsdp pobj - return pobj[] -end - -function GetPPObjective(dsdp::DSDPT) - ppobj = Ref{Cdouble}() - @dsdp_ccall DSDPGetPPObjective (DSDPT, Ptr{Cdouble}) dsdp ppobj - return ppobj[] -end - -function GetDualityGap(dsdp::DSDPT) - dgap = Ref{Cdouble}() - @dsdp_ccall DSDPGetDualityGap (DSDPT, Ptr{Cdouble}) dsdp dgap - return dgap[] -end - -function GetScale(dsdp::DSDPT) - scale = Ref{Cdouble}() - @dsdp_ccall DSDPGetScale (DSDPT, Ref{Cdouble}) dsdp scale - return scale[] -end - -function SetScale(dsdp::DSDPT, scale::Cdouble) - @dsdp_ccall DSDPSetScale (DSDPT, Cdouble) dsdp scale -end - -function GetPenaltyParameter(dsdp::DSDPT) - pp = Ref{Cdouble}() - @dsdp_ccall DSDPGetPenaltyParameter (DSDPT, Ref{Cdouble}) dsdp pp - return pp[] -end - -function GetPenalty(dsdp::DSDPT, arg2::Vector{Cdouble}) - @dsdp_ccall DSDPGetPenalty (DSDPT, Ptr{Cdouble}) dsdp arg2 -end - -function CopyB(dsdp::DSDPT, arg2::Vector{Cdouble}, arg3::Integer) - @dsdp_ccall DSDPCopyB (DSDPT, Ptr{Cdouble}, Cint) dsdp arg2 arg3 -end - -function SetR0(dsdp::DSDPT, arg2::Cdouble) - @dsdp_ccall DSDPSetR0 (DSDPT, Cdouble) dsdp arg2 -end - -function GetR(dsdp::DSDPT, arg2::Vector{Cdouble}) - @dsdp_ccall DSDPGetR (DSDPT, Ptr{Cdouble}) dsdp arg2 -end - -function SetRTolerance(dsdp::DSDPT, arg2::Cdouble) - @dsdp_ccall DSDPSetRTolerance (DSDPT, Cdouble) dsdp arg2 -end - -function GetRTolerance(dsdp::DSDPT) - rtol = Ref{Cdouble}() - @dsdp_ccall DSDPGetRTolerance (DSDPT, Ref{Cdouble}) dsdp rtol - return rtol[] -end - -function SetY0(dsdp::DSDPT, arg2::Integer, arg3::Cdouble) - @dsdp_ccall DSDPSetY0 (DSDPT, Cint, Cdouble) dsdp arg2 arg3 -end - -function GetY(dsdp::DSDPT, y::Vector{Cdouble}) - @dsdp_ccall DSDPGetY (DSDPT, Ptr{Cdouble}, Cint) dsdp pointer(y) length(y) -end - -function GetYMakeX(dsdp::DSDPT, arg2, arg3::Integer) - @dsdp_ccall DSDPGetYMakeX (DSDPT, Ptr{Cdouble}, Cint) dsdp arg2 arg3 -end - -function GetDYMakeX(dsdp::DSDPT, arg2, arg3::Integer) - @dsdp_ccall DSDPGetDYMakeX (DSDPT, Ptr{Cdouble}, Cint) dsdp arg2 arg3 -end - -function GetMuMakeX(dsdp::DSDPT, arg2::Vector{Cdouble}) - @dsdp_ccall DSDPGetMuMakeX (DSDPT, Ptr{Cdouble}) dsdp arg2 -end - -function GetBarrierParameter(dsdp::DSDPT) - bp = Ref{Cdouble}() - @dsdp_ccall DSDPGetBarrierParameter (DSDPT, Ptr{Cdouble}) dsdp bp - return bp[] -end - -function SetBarrierParameter(dsdp::DSDPT, arg2::Cdouble) - @dsdp_ccall DSDPSetBarrierParameter (DSDPT, Cdouble) dsdp arg2 -end - -function SetReuseMatrix(dsdp::DSDPT, arg2::Integer) - @dsdp_ccall DSDPReuseMatrix (DSDPT, Cint) dsdp arg2 -end - -function GetReuseMatrix(dsdp::DSDPT) - reuse = Ref{Cint}() - @dsdp_ccall DSDPGetReuseMatrix (DSDPT, Ref{Cint}) dsdp reuse - return reuse[] -end - -function GetDimension(dsdp::DSDPT, arg2::Vector{Cdouble}) - @dsdp_ccall DSDPGetDimension (DSDPT, Ptr{Cdouble}) dsdp arg2 -end - -function SetMaxIts(dsdp::DSDPT, arg2::Integer) - @dsdp_ccall DSDPSetMaxIts (DSDPT, Cint) dsdp arg2 -end - -function GetMaxIts(dsdp::DSDPT) - maxits = Ref{Cint}() - @dsdp_ccall DSDPGetMaxIts (DSDPT, Ref{Cint}) dsdp maxits - return maxits[] -end - -function SetStepTolerance(dsdp::DSDPT, steptol::Cdouble) - @assert steptol > 0 - @dsdp_ccall DSDPSetStepTolerance (DSDPT, Cdouble) dsdp arg2 -end - -function GetStepTolerance(dsdp::DSDPT) - steptol = Ref{Cdouble}() - @dsdp_ccall DSDPGetStepTolerance (DSDPT, Ref{Cdouble}) dsdp steptol - return steptol[] -end - -function SetGapTolerance(dsdp::DSDPT, arg2::Cdouble) - @dsdp_ccall DSDPSetGapTolerance (DSDPT, Cdouble) dsdp arg2 -end - -function GetGapTolerance(dsdp::DSDPT) - gaptol = Ref{Cdouble}() - @dsdp_ccall DSDPGetGapTolerance (DSDPT, Ref{Cdouble}) dsdp gaptol - return gaptol[] -end - -function SetPNormTolerance(dsdp::DSDPT, pnormtol::Real) - @assert pnormtol > 0 - @dsdp_ccall DSDPSetPNormTolerance (DSDPT, Cdouble) dsdp pnormtol -end - -function GetPNormTolerance(dsdp::DSDPT) - pnormtol = Ref{Cdouble}() - @dsdp_ccall DSDPGetPNormTolerance (DSDPT, Ref{Cdouble}) dsdp pnormtol - return pnormtol[] -end - -function SetDualBound(dsdp::DSDPT, arg2::Cdouble) - @dsdp_ccall DSDPSetDualBound (DSDPT, Cdouble) dsdp arg2 -end - -function GetDualBound(dsdp::DSDPT) - dualb = Ref{Cdouble}() - @dsdp_ccall DSDPGetDualBound (DSDPT, Ref{Cdouble}) dsdp dualb - return dualb[] -end - -function SetPTolerance(dsdp::DSDPT, arg2::Cdouble) - @dsdp_ccall DSDPSetPTolerance (DSDPT, Cdouble) dsdp arg2 -end - -function GetPTolerance(dsdp::DSDPT) - ptol = Ref{Cdouble}() - @dsdp_ccall DSDPGetPTolerance (DSDPT, Ref{Cdouble}) dsdp ptol - return ptol[] -end - -function GetPInfeasibility(dsdp::DSDPT, arg2::Vector{Cdouble}) - @dsdp_ccall DSDPGetPInfeasibility (DSDPT, Ptr{Cdouble}) dsdp arg2 -end - -function SetMaxTrustRadius(dsdp::DSDPT, maxtrust::Cdouble) - @dsdp_ccall DSDPSetMaxTrustRadius (DSDPT, Cdouble) dsdp maxtrust -end - -function GetMaxTrustRadius(dsdp::DSDPT) - maxtrust = Ref{Cdouble}() - @dsdp_ccall DSDPGetMaxTrustRadius (DSDPT, Ptr{Cdouble}) dsdp maxtrust - return maxtrust[] -end - -function StopReason(dsdp::DSDPT) - stop = Ref{DSDPTerminationReason}() - @dsdp_ccall DSDPStopReason (DSDPT, Ref{DSDPTerminationReason}) dsdp stop - return stop[] -end - -function GetSolutionType(dsdp::DSDPT) - sol = Ref{DSDPSolutionType}() - @dsdp_ccall DSDPGetSolutionType (DSDPT, Ref{DSDPSolutionType}) dsdp sol - return sol[] -end - -function SetPotentialParameter(dsdp::DSDPT, pp::Real) - @dsdp_ccall DSDPSetPotentialParameter (DSDPT, Cdouble) dsdp pp -end - -function GetPotentialParameter(dsdp::DSDPT) - pp = Ref{Cdouble}() - @dsdp_ccall DSDPGetPotentialParameter (DSDPT, Ref{Cdouble}) dsdp pp - return pp[] -end - -function UseDynamicRho(dsdp::DSDPT, arg2::Integer) - @dsdp_ccall DSDPUseDynamicRho (DSDPT, Cint) dsdp arg2 -end - -function GetPotential(dsdp::DSDPT, arg2::Vector{Cdouble}) - @dsdp_ccall DSDPGetPotential (DSDPT, Ptr{Cdouble}) dsdp arg2 -end - -function UseLAPACKForSchur(dsdp::DSDPT, arg2::Integer) - @dsdp_ccall DSDPUseLAPACKForSchur (DSDPT, Cint) dsdp arg2 -end - -function GetNumberOfVariables(dsdp::DSDPT) - n = Ref{Cint}(0) - @dsdp_ccall DSDPGetNumberOfVariables (DSDPT, Ref{Cint}) dsdp n - return n[] -end - -function GetFinalErrors(dsdp::DSDPT) - err = zeros(Cdouble, 6) - @dsdp_ccall DSDPGetFinalErrors (DSDPT, Ptr{Cdouble}) dsdp err - return err -end - -function GetGapHistory(dsdp::DSDPT, arg2::Vector{Cdouble}, arg3::Integer) - @dsdp_ccall DSDPGetGapHistory (DSDPT, Ptr{Cdouble}, Cint) dsdp arg2 arg3 -end - -function GetRHistory(dsdp::DSDPT, arg2::Vector{Cdouble}, arg3::Integer) - @dsdp_ccall DSDPGetRHistory (DSDPT, Ptr{Cdouble}, Cint) dsdp arg2 arg3 -end - -function GetIts(dsdp::DSDPT) - its = Ref{Cint}() - @dsdp_ccall DSDPGetIts (DSDPT, Ptr{Cint}) dsdp its - return its[] -end - -function GetPnorm(dsdp::DSDPT, arg2::Vector{Cdouble}) - @dsdp_ccall DSDPGetPnorm (DSDPT, Ptr{Cdouble}) dsdp arg2 -end - -function GetStepLengths( - dsdp::DSDPT, - arg2::Vector{Cdouble}, - arg3::Vector{Cdouble}, -) - @dsdp_ccall DSDPGetStepLengths (DSDPT, Ptr{Cdouble}, Ptr{Cdouble}) dsdp arg2 arg3 -end - -function SetMonitor(dsdp::DSDPT, arg2, arg3) - @dsdp_ccall DSDPSetMonitor (DSDPT, DSDPT, DSDPT) dsdp arg2 arg3 -end - -function SetStandardMonitor(dsdp::DSDPT, arg2::Integer) - @dsdp_ccall DSDPSetStandardMonitor (DSDPT, Cint) dsdp arg2 -end - -function SetFileMonitor(dsdp::DSDPT, arg2::Integer) - @dsdp_ccall DSDPSetFileMonitor (DSDPT, Cint) dsdp arg2 -end - -function SetPenaltyParameter(dsdp::DSDPT, arg2::Cdouble) - @dsdp_ccall DSDPSetPenaltyParameter (DSDPT, Cdouble) dsdp arg2 -end - -function UsePenalty(dsdp::DSDPT, arg2::Integer) - @dsdp_ccall DSDPUsePenalty (DSDPT, Cint) dsdp arg2 -end - -function PrintLogInfo(arg1::Integer) - @dsdp_ccall DSDPPrintLogInfo (Cint,) arg1 -end - -function ComputeMinimumXEigenvalue(dsdp::DSDPT, arg2::Vector{Cdouble}) - @dsdp_ccall DSDPComputeMinimumXEigenvalue (DSDPT, Ptr{Cdouble}) dsdp arg2 -end - -function GetTraceX(dsdp::DSDPT, sdpcone::Vector{Cdouble}) - @dsdp_ccall DSDPGetTraceX (DSDPT, Ptr{Cdouble}) dsdp sdpcone -end - -function SetZBar(dsdp::DSDPT, arg2::Cdouble) - @dsdp_ccall DSDPSetZBar (DSDPT, Cdouble) dsdp arg2 -end - -function SetDualLowerBound(dsdp::DSDPT, arg2::Cdouble) - @dsdp_ccall DSDPSetDualLowerBound (DSDPT, Cdouble) dsdp arg2 -end - -function GetDataNorms(dsdp::DSDPT, arg2::NTuple{3,Cdouble}) - @dsdp_ccall DSDPGetDataNorms (DSDPT, NTuple{3,Cdouble}) dsdp arg2 -end - -function GetYMaxNorm(dsdp::DSDPT, arg2::Vector{Cdouble}) - @dsdp_ccall DSDPGetYMaxNorm (DSDPT, Ptr{Cdouble}) dsdp arg2 -end - -function BoundDualVariables(dsdp::DSDPT, arg2::Cdouble, arg3::Cdouble) - @dsdp_ccall DSDPBoundDualVariables (DSDPT, Cdouble, Cdouble) dsdp arg2 arg3 -end - -function SetYBounds(dsdp::DSDPT, ylow::Cdouble, yhigh::Cdouble) - @dsdp_ccall DSDPSetYBounds (DSDPT, Cdouble, Cdouble) dsdp ylow yhigh -end - -function GetYBounds(dsdp::DSDPT) - ylow = Ref{Cdouble}() - yhigh = Ref{Cdouble}() - @dsdp_ccall DSDPGetYBounds (DSDPT, Ref{Cdouble}, Ref{Cdouble}) dsdp ylow yhigh - return ylow[], yhigh[] -end - -function SetFixedVariable(dsdp::DSDPT, arg2::Integer, arg3::Cdouble) - @dsdp_ccall DSDPSetFixedVariable (DSDPT, Cint, Cdouble) dsdp arg2 arg3 -end - -function SetFixedVariables( - dsdp::DSDPT, - arg2::Vector{Cdouble}, - arg3::Vector{Cdouble}, - arg4::Vector{Cdouble}, - arg5::Integer, -) - @dsdp_ccall DSDPSetFixedVariables ( - DSDPT, - Ptr{Cdouble}, - Ptr{Cdouble}, - Ptr{Cdouble}, - Cint, - ) dsdp arg2 arg3 arg4 arg5 -end - -function GetFixedYX(dsdp::DSDPT, arg2::Integer, arg3::Vector{Cdouble}) - @dsdp_ccall DSDPGetFixedYX (DSDPT, Cint, Ptr{Cdouble}) dsdp arg2 arg3 -end - -function View(dsdp::DSDPT) - @dsdp_ccall DSDPView (DSDPT,) dsdp -end - -function PrintOptions() - return ccall((:DSDPPrintOptions, libdsdp), Cint, ()) -end - -function SetOptions(dsdp::DSDPT, arg2::Vector{Cstring}, arg3::Integer) - @dsdp_ccall DSDPSetOptions (DSDPT, Ptr{Cstring}, Cint) dsdp arg2 arg3 -end - -function ReadOptions(dsdp::DSDPT, arg2::Vector{UInt8}) - @dsdp_ccall DSDPReadOptions (DSDPT, Ptr{UInt8}) dsdp arg2 -end - -function SetDestroyRoutine(dsdp::DSDPT, arg2, arg3) - @dsdp_ccall DSDPSetDestroyRoutine (DSDPT, DSDPT, DSDPT) dsdp arg2 arg3 -end diff --git a/src/dsdp5_enums.jl b/src/dsdp5_enums.jl deleted file mode 100644 index c0ae8c2..0000000 --- a/src/dsdp5_enums.jl +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2022: Joey Huchette, Benoît Legat, and 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. - -# Automatically generated using Clang.jl wrap_c, version 0.0.0 - -const DSDPTruth = Cuint - -# begin enum DSDPTerminationReason -const DSDPTerminationReason = Cint -const DSDP_CONVERGED = DSDPTerminationReason(1) # Good news: Solution found -const DSDP_INFEASIBLE_START = DSDPTerminationReason(-6) # The initial points y and r imply that S is not positive -const DSDP_SMALL_STEPS = DSDPTerminationReason(-2) # Short step lengths created by numerical difficulties prevent progress -const DSDP_INDEFINITE_SCHUR_MATRIX = DSDPTerminationReason(-8) # Theoretically this matrix is positive definite -const DSDP_MAX_IT = DSDPTerminationReason(-3) # Reached maximum number of iterations -const DSDP_NUMERICAL_ERROR = DSDPTerminationReason(-9) # Another numerical error occurred. Check solution -const DSDP_UPPERBOUND = DSDPTerminationReason(5) # Objective (DD) big enough to stop -const DSDP_USER_TERMINATION = DSDPTerminationReason(7) # DSDP didn't stop it, did you? -const CONTINUE_ITERATING = DSDPTerminationReason(0) # Don't Stop -# end enum DSDPTerminationReason - -# begin enum DSDPSolutionType -const DSDPSolutionType = Cuint # converged -const DSDP_PDUNKNOWN = DSDPSolutionType(0) # Not sure whether (D) or (P) is feasible, check y bounds -const DSDP_PDFEASIBLE = DSDPSolutionType(1) # Both (D) and (P) are feasible and bounded -const DSDP_UNBOUNDED = DSDPSolutionType(3) # (D) is unbounded and (P) is infeasible -const DSDP_INFEASIBLE = DSDPSolutionType(4) # (D) in infeasible and (P) is unbounded -# end enum DSDPSolutionType - -# begin enum DSDPDualFactorMatrix -const DSDPDualFactorMatrix = Cuint -const DUAL_FACTOR = DSDPDualFactorMatrix(1) # First instance for dual variable S -const PRIMAL_FACTOR = DSDPDualFactorMatrix(2) # Second instance used to compute X -# end enum DSDPDualFactorMatrix - -# begin enum DSDPPenalty -const DSDPPenalty = Cuint -const DSDPAlways = DSDPPenalty(1) -const DSDPNever = DSDPPenalty(2) -const DSDPInfeasible = DSDPPenalty(0) -# end enum DSDPPenalty diff --git a/src/libdsdp.jl b/src/libdsdp.jl new file mode 100644 index 0000000..595e4bc --- /dev/null +++ b/src/libdsdp.jl @@ -0,0 +1,703 @@ +# Copyright (c) 2022: Joey Huchette, Benoît Legat, and 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. + +# Disable JuliaFormatter for this file. +#!format:off + +function DSDPError(arg1, arg2, arg3) + @ccall libdsdp.DSDPError(arg1::Ptr{Cchar}, arg2::Cint, arg3::Ptr{Cchar})::Cvoid +end + +function DSDPSetBarrierParameter(arg1, arg2) + @ccall libdsdp.DSDPSetBarrierParameter(arg1::Ptr{Cvoid}, arg2::Cdouble)::Cint +end + +function DSDPGetBarrierParameter(arg1, arg2) + @ccall libdsdp.DSDPGetBarrierParameter(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +@cenum DSDPTruth::UInt32 begin + DSDP_FALSE = 0 + DSDP_TRUE = 1 +end + +@cenum DSDPDualFactorMatrix::UInt32 begin + DUAL_FACTOR = 1 + PRIMAL_FACTOR = 2 +end + +@cenum DSDPPenalty::UInt32 begin + DSDPAlways = 1 + DSDPNever = 2 + DSDPInfeasible = 0 +end + +@cenum DSDPSolutionType::UInt32 begin + DSDP_PDUNKNOWN = 0 + DSDP_PDFEASIBLE = 1 + DSDP_UNBOUNDED = 3 + DSDP_INFEASIBLE = 4 +end + +@cenum DSDPTerminationReason::Int32 begin + DSDP_CONVERGED = 1 + DSDP_INFEASIBLE_START = -6 + DSDP_SMALL_STEPS = -2 + DSDP_INDEFINITE_SCHUR_MATRIX = -8 + DSDP_MAX_IT = -3 + DSDP_NUMERICAL_ERROR = -9 + DSDP_UPPERBOUND = 5 + DSDP_USER_TERMINATION = 7 + CONTINUE_ITERATING = 0 +end + +function DSDPSetConvergenceFlag(arg1, arg2) + @ccall libdsdp.DSDPSetConvergenceFlag(arg1::Ptr{Cvoid}, arg2::DSDPTerminationReason)::Cint +end + +function DSDPTime(arg1) + @ccall libdsdp.DSDPTime(arg1::Ptr{Cdouble})::Cvoid +end + +function DSDPLogInfoAllow(arg1, arg2) + @ccall libdsdp.DSDPLogInfoAllow(arg1::Cint, arg2::Ptr{Cchar})::Cint +end + +function DSDPMemoryLog() + @ccall libdsdp.DSDPMemoryLog()::Cvoid +end + +function DSDPEventLogBegin(arg1) + @ccall libdsdp.DSDPEventLogBegin(arg1::Cint)::Cint +end + +function DSDPEventLogEnd(arg1) + @ccall libdsdp.DSDPEventLogEnd(arg1::Cint)::Cint +end + +function DSDPEventLogRegister(arg1, arg2) + @ccall libdsdp.DSDPEventLogRegister(arg1::Ptr{Cchar}, arg2::Ptr{Cint})::Cint +end + +function DSDPEventLogInitialize() + @ccall libdsdp.DSDPEventLogInitialize()::Cint +end + +function DSDPEventLogSummary() + @ccall libdsdp.DSDPEventLogSummary()::Cint +end + +function DSDPMMalloc(arg1, arg2, arg3) + @ccall libdsdp.DSDPMMalloc(arg1::Ptr{Cchar}, arg2::Csize_t, arg3::Ptr{Ptr{Cvoid}})::Cint +end + +function DSDPFFree(arg1) + @ccall libdsdp.DSDPFFree(arg1::Ptr{Ptr{Cvoid}})::Cint +end + +function DSDPCreate(arg1, arg2) + @ccall libdsdp.DSDPCreate(arg1::Cint, arg2::Ptr{Ptr{Cvoid}})::Cint +end + +function DSDPSetup(arg1) + @ccall libdsdp.DSDPSetup(arg1::Ptr{Cvoid})::Cint +end + +function DSDPSolve(arg1) + @ccall libdsdp.DSDPSolve(arg1::Ptr{Cvoid})::Cint +end + +function DSDPComputeX(arg1) + @ccall libdsdp.DSDPComputeX(arg1::Ptr{Cvoid})::Cint +end + +function DSDPComputeAndFactorS(arg1, arg2) + @ccall libdsdp.DSDPComputeAndFactorS(arg1::Ptr{Cvoid}, arg2::Ptr{DSDPTruth})::Cint +end + +function DSDPDestroy(arg1) + @ccall libdsdp.DSDPDestroy(arg1::Ptr{Cvoid})::Cint +end + +function DSDPCreateBCone(arg1, arg2) + @ccall libdsdp.DSDPCreateBCone(arg1::Ptr{Cvoid}, arg2::Ptr{Ptr{Cvoid}})::Cint +end + +function BConeAllocateBounds(arg1, arg2) + @ccall libdsdp.BConeAllocateBounds(arg1::Ptr{Cvoid}, arg2::Cint)::Cint +end + +function BConeSetLowerBound(arg1, arg2, arg3) + @ccall libdsdp.BConeSetLowerBound(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cdouble)::Cint +end + +function BConeSetUpperBound(arg1, arg2, arg3) + @ccall libdsdp.BConeSetUpperBound(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cdouble)::Cint +end + +function BConeSetPSlackVariable(arg1, arg2) + @ccall libdsdp.BConeSetPSlackVariable(arg1::Ptr{Cvoid}, arg2::Cint)::Cint +end + +function BConeSetPSurplusVariable(arg1, arg2) + @ccall libdsdp.BConeSetPSurplusVariable(arg1::Ptr{Cvoid}, arg2::Cint)::Cint +end + +function BConeScaleBarrier(arg1, arg2) + @ccall libdsdp.BConeScaleBarrier(arg1::Ptr{Cvoid}, arg2::Cdouble)::Cint +end + +function BConeView(arg1) + @ccall libdsdp.BConeView(arg1::Ptr{Cvoid})::Cint +end + +function BConeSetXArray(arg1, arg2, arg3) + @ccall libdsdp.BConeSetXArray(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble}, arg3::Cint)::Cint +end + +function BConeCopyX(arg1, arg2, arg3, arg4) + @ccall libdsdp.BConeCopyX(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble}, arg3::Ptr{Cdouble}, arg4::Cint)::Cint +end + +function DSDPBoundDualVariables(arg1, arg2, arg3) + @ccall libdsdp.DSDPBoundDualVariables(arg1::Ptr{Cvoid}, arg2::Cdouble, arg3::Cdouble)::Cint +end + +function DSDPSetYBounds(arg1, arg2, arg3) + @ccall libdsdp.DSDPSetYBounds(arg1::Ptr{Cvoid}, arg2::Cdouble, arg3::Cdouble)::Cint +end + +function DSDPGetYBounds(arg1, arg2, arg3) + @ccall libdsdp.DSDPGetYBounds(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble}, arg3::Ptr{Cdouble})::Cint +end + +function DSDPCreateLPCone(arg1, arg2) + @ccall libdsdp.DSDPCreateLPCone(arg1::Ptr{Cvoid}, arg2::Ptr{Ptr{Cvoid}})::Cint +end + +function LPConeSetData(arg1, arg2, arg3, arg4, arg5) + @ccall libdsdp.LPConeSetData(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Ptr{Cint}, arg4::Ptr{Cint}, arg5::Ptr{Cdouble})::Cint +end + +function LPConeSetData2(arg1, arg2, arg3, arg4, arg5) + @ccall libdsdp.LPConeSetData2(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Ptr{Cint}, arg4::Ptr{Cint}, arg5::Ptr{Cdouble})::Cint +end + +function LPConeGetData(arg1, arg2, arg3, arg4) + @ccall libdsdp.LPConeGetData(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Ptr{Cdouble}, arg4::Cint)::Cint +end + +function LPConeScaleBarrier(arg1, arg2) + @ccall libdsdp.LPConeScaleBarrier(arg1::Ptr{Cvoid}, arg2::Cdouble)::Cint +end + +function LPConeGetXArray(arg1, arg2, arg3) + @ccall libdsdp.LPConeGetXArray(arg1::Ptr{Cvoid}, arg2::Ptr{Ptr{Cdouble}}, arg3::Ptr{Cint})::Cint +end + +function LPConeGetSArray(arg1, arg2, arg3) + @ccall libdsdp.LPConeGetSArray(arg1::Ptr{Cvoid}, arg2::Ptr{Ptr{Cdouble}}, arg3::Ptr{Cint})::Cint +end + +function LPConeGetDimension(arg1, arg2) + @ccall libdsdp.LPConeGetDimension(arg1::Ptr{Cvoid}, arg2::Ptr{Cint})::Cint +end + +function LPConeView(lpcone) + @ccall libdsdp.LPConeView(lpcone::Ptr{Cvoid})::Cint +end + +function LPConeView2(lpcone) + @ccall libdsdp.LPConeView2(lpcone::Ptr{Cvoid})::Cint +end + +function LPConeCopyS(arg1, arg2, arg3) + @ccall libdsdp.LPConeCopyS(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble}, arg3::Cint)::Cint +end + +function DSDPCreateSDPCone(arg1, arg2, arg3) + @ccall libdsdp.DSDPCreateSDPCone(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Ptr{Ptr{Cvoid}})::Cint +end + +function SDPConeSetBlockSize(arg1, arg2, arg3) + @ccall libdsdp.SDPConeSetBlockSize(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint)::Cint +end + +function SDPConeGetBlockSize(arg1, arg2, arg3) + @ccall libdsdp.SDPConeGetBlockSize(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Ptr{Cint})::Cint +end + +function SDPConeSetStorageFormat(arg1, arg2, arg3) + @ccall libdsdp.SDPConeSetStorageFormat(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cchar)::Cint +end + +function SDPConeGetStorageFormat(arg1, arg2, arg3) + @ccall libdsdp.SDPConeGetStorageFormat(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Ptr{Cchar})::Cint +end + +function SDPConeCheckStorageFormat(arg1, arg2, arg3) + @ccall libdsdp.SDPConeCheckStorageFormat(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cchar)::Cint +end + +function SDPConeSetSparsity(arg1, arg2, arg3) + @ccall libdsdp.SDPConeSetSparsity(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint)::Cint +end + +function SDPConeView(arg1) + @ccall libdsdp.SDPConeView(arg1::Ptr{Cvoid})::Cint +end + +function SDPConeView2(arg1) + @ccall libdsdp.SDPConeView2(arg1::Ptr{Cvoid})::Cint +end + +function SDPConeView3(arg1) + @ccall libdsdp.SDPConeView3(arg1::Ptr{Cvoid})::Cint +end + +function SDPConeSetASparseVecMat(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) + @ccall libdsdp.SDPConeSetASparseVecMat(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Cint, arg5::Cdouble, arg6::Cint, arg7::Ptr{Cint}, arg8::Ptr{Cdouble}, arg9::Cint)::Cint +end + +function SDPConeSetADenseVecMat(arg1, arg2, arg3, arg4, arg5, arg6, arg7) + @ccall libdsdp.SDPConeSetADenseVecMat(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Cint, arg5::Cdouble, arg6::Ptr{Cdouble}, arg7::Cint)::Cint +end + +function SDPConeSetARankOneMat(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) + @ccall libdsdp.SDPConeSetARankOneMat(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Cint, arg5::Cdouble, arg6::Cint, arg7::Ptr{Cint}, arg8::Ptr{Cdouble}, arg9::Cint)::Cint +end + +function SDPConeSetConstantMat(arg1, arg2, arg3, arg4, arg5) + @ccall libdsdp.SDPConeSetConstantMat(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Cint, arg5::Cdouble)::Cint +end + +function SDPConeSetZeroMat(arg1, arg2, arg3, arg4) + @ccall libdsdp.SDPConeSetZeroMat(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Cint)::Cint +end + +function SDPConeSetIdentity(arg1, arg2, arg3, arg4, arg5) + @ccall libdsdp.SDPConeSetIdentity(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Cint, arg5::Cdouble)::Cint +end + +function SDPConeViewDataMatrix(arg1, arg2, arg3) + @ccall libdsdp.SDPConeViewDataMatrix(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint)::Cint +end + +function SDPConeMatrixView(arg1, arg2) + @ccall libdsdp.SDPConeMatrixView(arg1::Ptr{Cvoid}, arg2::Cint)::Cint +end + +function SDPConeAddASparseVecMat(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) + @ccall libdsdp.SDPConeAddASparseVecMat(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Cint, arg5::Cdouble, arg6::Cint, arg7::Ptr{Cint}, arg8::Ptr{Cdouble}, arg9::Cint)::Cint +end + +function SDPConeAddADenseVecMat(arg1, arg2, arg3, arg4, arg5, arg6, arg7) + @ccall libdsdp.SDPConeAddADenseVecMat(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Cint, arg5::Cdouble, arg6::Ptr{Cdouble}, arg7::Cint)::Cint +end + +function SDPConeAddConstantMat(arg1, arg2, arg3, arg4, arg5) + @ccall libdsdp.SDPConeAddConstantMat(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Cint, arg5::Cdouble)::Cint +end + +function SDPConeAddIdentity(arg1, arg2, arg3, arg4, arg5) + @ccall libdsdp.SDPConeAddIdentity(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Cint, arg5::Cdouble)::Cint +end + +function SDPConeAddARankOneMat(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) + @ccall libdsdp.SDPConeAddARankOneMat(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Cint, arg5::Cdouble, arg6::Cint, arg7::Ptr{Cint}, arg8::Ptr{Cdouble}, arg9::Cint)::Cint +end + +function SDPConeAddSparseVecMat(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) + @ccall libdsdp.SDPConeAddSparseVecMat(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Cint, arg5::Cint, arg6::Ptr{Cint}, arg7::Ptr{Cdouble}, arg8::Cint)::Cint +end + +function SDPConeAddDenseVecMat(arg1, arg2, arg3, arg4, arg5, arg6) + @ccall libdsdp.SDPConeAddDenseVecMat(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Cint, arg5::Ptr{Cdouble}, arg6::Cint)::Cint +end + +function SDPConeSetSparseVecMat(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) + @ccall libdsdp.SDPConeSetSparseVecMat(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Cint, arg5::Cint, arg6::Ptr{Cint}, arg7::Ptr{Cdouble}, arg8::Cint)::Cint +end + +function SDPConeSetDenseVecMat(arg1, arg2, arg3, arg4, arg5, arg6) + @ccall libdsdp.SDPConeSetDenseVecMat(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Cint, arg5::Ptr{Cdouble}, arg6::Cint)::Cint +end + +function SDPConeSetXMat(arg1, arg2, arg3) + @ccall libdsdp.SDPConeSetXMat(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint)::Cint +end + +function SDPConeSetXArray(arg1, arg2, arg3, arg4, arg5) + @ccall libdsdp.SDPConeSetXArray(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Ptr{Cdouble}, arg5::Cint)::Cint +end + +function SDPConeGetXArray(arg1, arg2, arg3, arg4) + @ccall libdsdp.SDPConeGetXArray(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Ptr{Ptr{Cdouble}}, arg4::Ptr{Cint})::Cint +end + +function SDPConeRestoreXArray(arg1, arg2, arg3, arg4) + @ccall libdsdp.SDPConeRestoreXArray(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Ptr{Ptr{Cdouble}}, arg4::Ptr{Cint})::Cint +end + +function SDPConeCheckData(arg1) + @ccall libdsdp.SDPConeCheckData(arg1::Ptr{Cvoid})::Cint +end + +function SDPConeRemoveDataMatrix(arg1, arg2, arg3) + @ccall libdsdp.SDPConeRemoveDataMatrix(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint)::Cint +end + +function SDPConeGetNumberOfBlocks(arg1, arg2) + @ccall libdsdp.SDPConeGetNumberOfBlocks(arg1::Ptr{Cvoid}, arg2::Ptr{Cint})::Cint +end + +function SDPConeComputeS(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) + @ccall libdsdp.SDPConeComputeS(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cdouble, arg4::Ptr{Cdouble}, arg5::Cint, arg6::Cdouble, arg7::Cint, arg8::Ptr{Cdouble}, arg9::Cint)::Cint +end + +function SDPConeComputeX(arg1, arg2, arg3, arg4, arg5) + @ccall libdsdp.SDPConeComputeX(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Ptr{Cdouble}, arg5::Cint)::Cint +end + +function SDPConeAddADotX(arg1, arg2, arg3, arg4, arg5, arg6, arg7) + @ccall libdsdp.SDPConeAddADotX(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cdouble, arg4::Ptr{Cdouble}, arg5::Cint, arg6::Ptr{Cdouble}, arg7::Cint)::Cint +end + +function SDPConeViewX(arg1, arg2, arg3, arg4, arg5) + @ccall libdsdp.SDPConeViewX(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cint, arg4::Ptr{Cdouble}, arg5::Cint)::Cint +end + +function SDPConeSetLanczosIterations(arg1, arg2) + @ccall libdsdp.SDPConeSetLanczosIterations(arg1::Ptr{Cvoid}, arg2::Cint)::Cint +end + +function SDPConeScaleBarrier(arg1, arg2, arg3) + @ccall libdsdp.SDPConeScaleBarrier(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cdouble)::Cint +end + +function SDPConeXVMultiply(arg1, arg2, arg3, arg4, arg5) + @ccall libdsdp.SDPConeXVMultiply(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Ptr{Cdouble}, arg4::Ptr{Cdouble}, arg5::Cint)::Cint +end + +function SDPConeComputeXV(arg1, arg2, arg3) + @ccall libdsdp.SDPConeComputeXV(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Ptr{Cint})::Cint +end + +function SDPConeAddXVAV(arg1, arg2, arg3, arg4, arg5, arg6) + @ccall libdsdp.SDPConeAddXVAV(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Ptr{Cdouble}, arg4::Cint, arg5::Ptr{Cdouble}, arg6::Cint)::Cint +end + +function SDPConeUseLAPACKForDualMatrix(arg1, arg2) + @ccall libdsdp.SDPConeUseLAPACKForDualMatrix(arg1::Ptr{Cvoid}, arg2::Cint)::Cint +end + +function DSDPSetDualObjective(arg1, arg2, arg3) + @ccall libdsdp.DSDPSetDualObjective(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cdouble)::Cint +end + +function DSDPAddObjectiveConstant(arg1, arg2) + @ccall libdsdp.DSDPAddObjectiveConstant(arg1::Ptr{Cvoid}, arg2::Cdouble)::Cint +end + +function DSDPGetDObjective(arg1, arg2) + @ccall libdsdp.DSDPGetDObjective(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPGetDDObjective(arg1, arg2) + @ccall libdsdp.DSDPGetDDObjective(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPGetPObjective(arg1, arg2) + @ccall libdsdp.DSDPGetPObjective(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPGetPPObjective(arg1, arg2) + @ccall libdsdp.DSDPGetPPObjective(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPGetDualityGap(arg1, arg2) + @ccall libdsdp.DSDPGetDualityGap(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPGetScale(arg1, arg2) + @ccall libdsdp.DSDPGetScale(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPSetScale(arg1, arg2) + @ccall libdsdp.DSDPSetScale(arg1::Ptr{Cvoid}, arg2::Cdouble)::Cint +end + +function DSDPGetPenaltyParameter(arg1, arg2) + @ccall libdsdp.DSDPGetPenaltyParameter(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPGetPenalty(arg1, arg2) + @ccall libdsdp.DSDPGetPenalty(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPCopyB(arg1, arg2, arg3) + @ccall libdsdp.DSDPCopyB(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble}, arg3::Cint)::Cint +end + +function DSDPSetR0(arg1, arg2) + @ccall libdsdp.DSDPSetR0(arg1::Ptr{Cvoid}, arg2::Cdouble)::Cint +end + +function DSDPGetR(arg1, arg2) + @ccall libdsdp.DSDPGetR(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPSetRTolerance(arg1, arg2) + @ccall libdsdp.DSDPSetRTolerance(arg1::Ptr{Cvoid}, arg2::Cdouble)::Cint +end + +function DSDPGetRTolerance(arg1, arg2) + @ccall libdsdp.DSDPGetRTolerance(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPSetY0(arg1, arg2, arg3) + @ccall libdsdp.DSDPSetY0(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cdouble)::Cint +end + +function DSDPGetY(arg1, arg2, arg3) + @ccall libdsdp.DSDPGetY(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble}, arg3::Cint)::Cint +end + +function DSDPGetYMakeX(arg1, arg2, arg3) + @ccall libdsdp.DSDPGetYMakeX(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble}, arg3::Cint)::Cint +end + +function DSDPGetDYMakeX(arg1, arg2, arg3) + @ccall libdsdp.DSDPGetDYMakeX(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble}, arg3::Cint)::Cint +end + +function DSDPGetMuMakeX(arg1, arg2) + @ccall libdsdp.DSDPGetMuMakeX(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPReuseMatrix(arg1, arg2) + @ccall libdsdp.DSDPReuseMatrix(arg1::Ptr{Cvoid}, arg2::Cint)::Cint +end + +function DSDPGetReuseMatrix(arg1, arg2) + @ccall libdsdp.DSDPGetReuseMatrix(arg1::Ptr{Cvoid}, arg2::Ptr{Cint})::Cint +end + +function DSDPGetDimension(arg1, arg2) + @ccall libdsdp.DSDPGetDimension(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPSetMaxIts(arg1, arg2) + @ccall libdsdp.DSDPSetMaxIts(arg1::Ptr{Cvoid}, arg2::Cint)::Cint +end + +function DSDPGetMaxIts(arg1, arg2) + @ccall libdsdp.DSDPGetMaxIts(arg1::Ptr{Cvoid}, arg2::Ptr{Cint})::Cint +end + +function DSDPSetStepTolerance(arg1, arg2) + @ccall libdsdp.DSDPSetStepTolerance(arg1::Ptr{Cvoid}, arg2::Cdouble)::Cint +end + +function DSDPGetStepTolerance(arg1, arg2) + @ccall libdsdp.DSDPGetStepTolerance(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPSetGapTolerance(arg1, arg2) + @ccall libdsdp.DSDPSetGapTolerance(arg1::Ptr{Cvoid}, arg2::Cdouble)::Cint +end + +function DSDPGetGapTolerance(arg1, arg2) + @ccall libdsdp.DSDPGetGapTolerance(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPSetPNormTolerance(arg1, arg2) + @ccall libdsdp.DSDPSetPNormTolerance(arg1::Ptr{Cvoid}, arg2::Cdouble)::Cint +end + +function DSDPGetPNormTolerance(arg1, arg2) + @ccall libdsdp.DSDPGetPNormTolerance(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPSetDualBound(arg1, arg2) + @ccall libdsdp.DSDPSetDualBound(arg1::Ptr{Cvoid}, arg2::Cdouble)::Cint +end + +function DSDPGetDualBound(arg1, arg2) + @ccall libdsdp.DSDPGetDualBound(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPSetPTolerance(arg1, arg2) + @ccall libdsdp.DSDPSetPTolerance(arg1::Ptr{Cvoid}, arg2::Cdouble)::Cint +end + +function DSDPGetPTolerance(arg1, arg2) + @ccall libdsdp.DSDPGetPTolerance(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPGetPInfeasibility(arg1, arg2) + @ccall libdsdp.DSDPGetPInfeasibility(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPSetMaxTrustRadius(arg1, arg2) + @ccall libdsdp.DSDPSetMaxTrustRadius(arg1::Ptr{Cvoid}, arg2::Cdouble)::Cint +end + +function DSDPGetMaxTrustRadius(arg1, arg2) + @ccall libdsdp.DSDPGetMaxTrustRadius(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPStopReason(arg1, arg2) + @ccall libdsdp.DSDPStopReason(arg1::Ptr{Cvoid}, arg2::Ptr{DSDPTerminationReason})::Cint +end + +function DSDPGetSolutionType(arg1, arg2) + @ccall libdsdp.DSDPGetSolutionType(arg1::Ptr{Cvoid}, arg2::Ptr{DSDPSolutionType})::Cint +end + +function DSDPSetPotentialParameter(arg1, arg2) + @ccall libdsdp.DSDPSetPotentialParameter(arg1::Ptr{Cvoid}, arg2::Cdouble)::Cint +end + +function DSDPGetPotentialParameter(arg1, arg2) + @ccall libdsdp.DSDPGetPotentialParameter(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPUseDynamicRho(arg1, arg2) + @ccall libdsdp.DSDPUseDynamicRho(arg1::Ptr{Cvoid}, arg2::Cint)::Cint +end + +function DSDPGetPotential(arg1, arg2) + @ccall libdsdp.DSDPGetPotential(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPUseLAPACKForSchur(arg1, arg2) + @ccall libdsdp.DSDPUseLAPACKForSchur(arg1::Ptr{Cvoid}, arg2::Cint)::Cint +end + +function DSDPGetNumberOfVariables(arg1, arg2) + @ccall libdsdp.DSDPGetNumberOfVariables(arg1::Ptr{Cvoid}, arg2::Ptr{Cint})::Cint +end + +function DSDPGetFinalErrors(arg1, arg2) + @ccall libdsdp.DSDPGetFinalErrors(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPGetGapHistory(arg1, arg2, arg3) + @ccall libdsdp.DSDPGetGapHistory(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble}, arg3::Cint)::Cint +end + +function DSDPGetRHistory(arg1, arg2, arg3) + @ccall libdsdp.DSDPGetRHistory(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble}, arg3::Cint)::Cint +end + +function DSDPGetIts(arg1, arg2) + @ccall libdsdp.DSDPGetIts(arg1::Ptr{Cvoid}, arg2::Ptr{Cint})::Cint +end + +function DSDPGetPnorm(arg1, arg2) + @ccall libdsdp.DSDPGetPnorm(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPGetStepLengths(arg1, arg2, arg3) + @ccall libdsdp.DSDPGetStepLengths(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble}, arg3::Ptr{Cdouble})::Cint +end + +function DSDPSetMonitor(arg1, arg2, arg3) + @ccall libdsdp.DSDPSetMonitor(arg1::Ptr{Cvoid}, arg2::Ptr{Cvoid}, arg3::Ptr{Cvoid})::Cint +end + +function DSDPSetStandardMonitor(arg1, arg2) + @ccall libdsdp.DSDPSetStandardMonitor(arg1::Ptr{Cvoid}, arg2::Cint)::Cint +end + +function DSDPSetFileMonitor(arg1, arg2) + @ccall libdsdp.DSDPSetFileMonitor(arg1::Ptr{Cvoid}, arg2::Cint)::Cint +end + +function DSDPSetPenaltyParameter(arg1, arg2) + @ccall libdsdp.DSDPSetPenaltyParameter(arg1::Ptr{Cvoid}, arg2::Cdouble)::Cint +end + +function DSDPUsePenalty(arg1, arg2) + @ccall libdsdp.DSDPUsePenalty(arg1::Ptr{Cvoid}, arg2::Cint)::Cint +end + +function DSDPPrintLogInfo(arg1) + @ccall libdsdp.DSDPPrintLogInfo(arg1::Cint)::Cint +end + +function DSDPComputeMinimumXEigenvalue(arg1, arg2) + @ccall libdsdp.DSDPComputeMinimumXEigenvalue(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPGetTraceX(dsdp, arg2) + @ccall libdsdp.DSDPGetTraceX(dsdp::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPSetZBar(arg1, arg2) + @ccall libdsdp.DSDPSetZBar(arg1::Ptr{Cvoid}, arg2::Cdouble)::Cint +end + +function DSDPSetDualLowerBound(arg1, arg2) + @ccall libdsdp.DSDPSetDualLowerBound(arg1::Ptr{Cvoid}, arg2::Cdouble)::Cint +end + +function DSDPGetDataNorms(arg1, arg2) + @ccall libdsdp.DSDPGetDataNorms(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function DSDPGetYMaxNorm(arg1, arg2) + @ccall libdsdp.DSDPGetYMaxNorm(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble})::Cint +end + +function SDPConeUseFullSymmetricFormat(arg1, arg2) + @ccall libdsdp.SDPConeUseFullSymmetricFormat(arg1::Ptr{Cvoid}, arg2::Cint)::Cint +end + +function SDPConeUsePackedFormat(arg1, arg2) + @ccall libdsdp.SDPConeUsePackedFormat(arg1::Ptr{Cvoid}, arg2::Cint)::Cint +end + +function DSDPSetFixedVariable(arg1, arg2, arg3) + @ccall libdsdp.DSDPSetFixedVariable(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Cdouble)::Cint +end + +function DSDPSetFixedVariables(arg1, arg2, arg3, arg4, arg5) + @ccall libdsdp.DSDPSetFixedVariables(arg1::Ptr{Cvoid}, arg2::Ptr{Cdouble}, arg3::Ptr{Cdouble}, arg4::Ptr{Cdouble}, arg5::Cint)::Cint +end + +function DSDPGetFixedYX(arg1, arg2, arg3) + @ccall libdsdp.DSDPGetFixedYX(arg1::Ptr{Cvoid}, arg2::Cint, arg3::Ptr{Cdouble})::Cint +end + +function DSDPView(arg1) + @ccall libdsdp.DSDPView(arg1::Ptr{Cvoid})::Cint +end + +# no prototype is found for this function at dsdp5.h:206:12, please use with caution +function DSDPPrintOptions() + @ccall libdsdp.DSDPPrintOptions()::Cint +end + +function DSDPPrintData(arg1, arg2, arg3) + @ccall libdsdp.DSDPPrintData(arg1::Ptr{Cvoid}, arg2::Ptr{Cvoid}, arg3::Ptr{Cvoid})::Cint +end + +function DSDPPrintSolution(arg1, arg2, arg3, arg4) + @ccall libdsdp.DSDPPrintSolution(arg1::Ptr{Libc.FILE}, arg2::Ptr{Cvoid}, arg3::Ptr{Cvoid}, arg4::Ptr{Cvoid})::Cint +end + +function DSDPSetOptions(arg1, arg2, arg3) + @ccall libdsdp.DSDPSetOptions(arg1::Ptr{Cvoid}, arg2::Ptr{Ptr{Cchar}}, arg3::Cint)::Cint +end + +function DSDPReadOptions(arg1, arg2) + @ccall libdsdp.DSDPReadOptions(arg1::Ptr{Cvoid}, arg2::Ptr{Cchar})::Cint +end + +function DSDPSetDestroyRoutine(arg1, arg2, arg3) + @ccall libdsdp.DSDPSetDestroyRoutine(arg1::Ptr{Cvoid}, arg2::Ptr{Cvoid}, arg3::Ptr{Cvoid})::Cint +end diff --git a/src/lpcone.jl b/src/lpcone.jl deleted file mode 100644 index 4e58b20..0000000 --- a/src/lpcone.jl +++ /dev/null @@ -1,126 +0,0 @@ -# Copyright (c) 2022: Joey Huchette, Benoît Legat, and 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. - -export LPCone - -module LPCone - -import ..@dsdp_ccall -const LPConeT = Ptr{Nothing} - -function buildlp(nvars, lpdvars, lpdrows, lpcoefs) - @assert length(lpdvars) == length(lpdrows) == length(lpcoefs) - nzin = zeros(Cint, nvars) - n = length(lpdvars) - for var in lpdvars - nzin[var] += 1 - end - nnzin = Cint[zero(Cint); cumsum(nzin)] - @assert nnzin[end] == n - idx = map(var -> Int[], 1:nvars) - for (i, var) in enumerate(lpdvars) - push!(idx[var], i) - end - row = Vector{Cint}(undef, n) - aval = Vector{Cdouble}(undef, n) - for var in 1:nvars - sort!(idx[var]; by = i -> lpdrows[i]) - row[(nnzin[var]+1):(nnzin[var+1])] = lpdrows[idx[var]] - aval[(nnzin[var]+1):(nnzin[var+1])] = lpcoefs[idx[var]] - end - return nnzin, row, aval -end - -# This function is not part of DSDP API -function SetDataSparse( - lpcone::LPConeT, - n::Integer, - nvars, - lpdvars, - lpdrows, - lpcoefs, -) - return SetData(lpcone, n, buildlp(nvars, lpdvars, lpdrows, lpcoefs)...) -end - -function SetData( - lpcone::LPConeT, - n::Integer, - nnzin::Vector{Cint}, - row::Vector{Cint}, - aval::Vector{Cdouble}, -) - @assert length(row) == length(aval) - @dsdp_ccall LPConeSetData ( - LPConeT, - Cint, - Ptr{Cint}, - Ptr{Cint}, - Ptr{Cdouble}, - ) lpcone n nnzin row aval -end - -function SetData2( - arg1::LPConeT, - arg2::Integer, - arg3::Vector{Cint}, - arg4::Vector{Cint}, - arg5::Vector{Cdouble}, -) - @dsdp_ccall LPConeSetData2 ( - LPConeT, - Cint, - Ptr{Cint}, - Ptr{Cint}, - Ptr{Cdouble}, - ) arg1 arg2 arg3 arg4 arg5 -end - -function GetData( - arg1::LPConeT, - arg2::Integer, - arg3::Vector{Cdouble}, - arg4::Integer, -) - @dsdp_ccall LPConeGetData (LPConeT, Cint, Ptr{Cdouble}, Cint) arg1 arg2 arg3 arg4 -end - -function ScaleBarrier(arg1::LPConeT, arg2::Cdouble) - @dsdp_ccall LPConeScaleBarrier (LPConeT, Cdouble) arg1 arg2 -end - -function GetXArray(lpcone::LPConeT) - xout = Ref{Ptr{Cdouble}}() - n = Ref{Cint}() - @dsdp_ccall LPConeGetXArray (LPConeT, Ptr{Ptr{Cdouble}}, Ptr{Cint}) lpcone xout n - return unsafe_wrap(Array, xout[], n[]) -end - -function GetSArray(lpcone::LPConeT) - sout = Ref{Ptr{Cdouble}}() - n = Ref{Cint}() - @dsdp_ccall LPConeGetSArray (LPConeT, Ref{Ptr{Cdouble}}, Ref{Cint}) lpcone sout n - return unsafe_wrap(Array, sout[], n[]) -end - -function GetDimension(arg1::LPConeT) - dim = Ref{Cint}() - @dsdp_ccall LPConeGetDimension (LPConeT, Ref{Cint}) arg1 dim - return dim[] -end - -function View(lpcone::LPConeT) - @dsdp_ccall LPConeView (LPConeT,) lpcone -end - -function View2(lpcone::LPConeT) - @dsdp_ccall LPConeView2 (LPConeT,) lpcone -end - -function CopyS(arg1::LPConeT, arg2::Vector{Cdouble}, arg3::Integer) - @dsdp_ccall LPConeCopyS (LPConeT, Ptr{Cdouble}, Cint) arg1 arg2 arg3 -end - -end diff --git a/src/sdpcone.jl b/src/sdpcone.jl deleted file mode 100644 index 8500452..0000000 --- a/src/sdpcone.jl +++ /dev/null @@ -1,495 +0,0 @@ -# Copyright (c) 2022: Joey Huchette, Benoît Legat, and 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. - -export SDPCone - -module SDPCone - -import ..@dsdp_ccall - -const SDPConeT = Ptr{Nothing} - -function SetBlockSize(sdpcone::SDPConeT, i::Integer, j::Integer) - @dsdp_ccall SDPConeSetBlockSize (SDPConeT, Cint, Cint) sdpcone i j -end - -function GetBlockSize(sdpcone::SDPConeT, arg2::Integer) - n = Ref{Cint}() - @dsdp_ccall SDPConeGetBlockSize (SDPConeT, Cint, Ref{Cint}) sdpcone arg2 n - return n[] -end - -function SetStorageFormat(sdpcone::SDPConeT, arg2::Integer, arg3::UInt8) - @dsdp_ccall SDPConeSetStorageFormat (SDPConeT, Cint, UInt8) sdpcone arg2 arg3 -end - -function GetStorageFormat(sdpcone::SDPConeT, arg2::Integer) - format = Ref{Cchar}() - @dsdp_ccall SDPConeGetStorageFormat (SDPConeT, Cint, Ref{Cchar}) sdpcone arg2 format - return format[] -end - -function CheckStorageFormat(sdpcone::SDPConeT, arg2::Integer, arg3::UInt8) - @dsdp_ccall SDPConeCheckStorageFormat (SDPConeT, Cint, UInt8) sdpcone arg2 arg3 -end - -function SetSparsity(sdpcone::SDPConeT, arg2::Integer, arg3::Integer) - @dsdp_ccall SDPConeSetSparsity (SDPConeT, Cint, Cint) sdpcone arg2 arg3 -end - -function View(sdpcone::SDPConeT) - @dsdp_ccall SDPConeView (SDPConeT,) sdpcone -end - -function View2(sdpcone::SDPConeT) - @dsdp_ccall SDPConeView2 (SDPConeT,) sdpcone -end - -function View3(sdpcone::SDPConeT) - @dsdp_ccall SDPConeView3 (SDPConeT,) sdpcone -end - -function SetASparseVecMat( - sdpcone::SDPConeT, - blockj::Integer, - vari::Integer, - n::Integer, - alpha::Cdouble, - ishift::Integer, - ind::Union{Ptr{Cint},Vector{Cint}}, - val::Union{Ptr{Cdouble},Vector{Cdouble}}, - nnz::Integer, -) - @dsdp_ccall SDPConeSetASparseVecMat ( - SDPConeT, - Cint, - Cint, - Cint, - Cdouble, - Cint, - Ptr{Cint}, - Ptr{Cdouble}, - Cint, - ) sdpcone blockj vari n alpha ishift ind val nnz -end - -function SetADenseVecMat( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Integer, - arg4::Integer, - arg5::Cdouble, - arg6::Vector{Cdouble}, - arg7::Integer, -) - @dsdp_ccall SDPConeSetADenseVecMat ( - SDPConeT, - Cint, - Cint, - Cint, - Cdouble, - Ptr{Cdouble}, - Cint, - ) sdpcone arg2 arg3 arg4 arg5 arg6 arg7 -end - -function SetARankOneMat( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Integer, - arg4::Integer, - arg5::Cdouble, - arg6::Integer, - arg7::Vector{Cint}, - arg8::Vector{Cdouble}, - arg9::Integer, -) - @dsdp_ccall SDPConeSetARankOneMat ( - SDPConeT, - Cint, - Cint, - Cint, - Cdouble, - Cint, - Ptr{Cint}, - Ptr{Cdouble}, - Cint, - ) sdpcone arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 -end - -function SetConstantMat( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Integer, - arg4::Integer, - arg5::Cdouble, -) - @dsdp_ccall SDPConeSetConstantMat (SDPConeT, Cint, Cint, Cint, Cdouble) sdpcone arg2 arg3 arg4 arg5 -end - -function SetZeroMat( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Integer, - arg4::Integer, -) - @dsdp_ccall SDPConeSetZeroMat (SDPConeT, Cint, Cint, Cint) sdpcone arg2 arg3 arg4 -end - -function SetIdentity( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Integer, - arg4::Integer, - arg5::Cdouble, -) - @dsdp_ccall SDPConeSetIdentity (SDPConeT, Cint, Cint, Cint, Cdouble) sdpcone arg2 arg3 arg4 arg5 -end - -function ViewDataMatrix(sdpcone::SDPConeT, arg2::Integer, arg3::Integer) - @dsdp_ccall SDPConeViewDataMatrix (SDPConeT, Cint, Cint) sdpcone arg2 arg3 -end - -function MatrixView(sdpcone::SDPConeT, arg2::Integer) - @dsdp_ccall SDPConeMatrixView (SDPConeT, Cint) sdpcone arg2 -end - -function AddASparseVecMat( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Integer, - arg4::Integer, - arg5::Cdouble, - arg6::Integer, - arg7::Union{Ptr{Cint},Vector{Cint}}, - arg8::Union{Ptr{Cdouble},Vector{Cdouble}}, - arg9::Integer, -) - @dsdp_ccall SDPConeAddASparseVecMat ( - SDPConeT, - Cint, - Cint, - Cint, - Cdouble, - Cint, - Ptr{Cint}, - Ptr{Cdouble}, - Cint, - ) sdpcone arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 -end - -function AddADenseVecMat( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Integer, - arg4::Integer, - arg5::Cdouble, - arg6::Vector{Cdouble}, - arg7::Integer, -) - @dsdp_ccall SDPConeAddADenseVecMat ( - SDPConeT, - Cint, - Cint, - Cint, - Cdouble, - Ptr{Cdouble}, - Cint, - ) sdpcone arg2 arg3 arg4 arg5 arg6 arg7 -end - -function AddConstantMat( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Integer, - arg4::Integer, - arg5::Cdouble, -) - @dsdp_ccall SDPConeAddConstantMat (SDPConeT, Cint, Cint, Cint, Cdouble) sdpcone arg2 arg3 arg4 arg5 -end - -function AddIdentity( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Integer, - arg4::Integer, - arg5::Cdouble, -) - @dsdp_ccall SDPConeAddIdentity (SDPConeT, Cint, Cint, Cint, Cdouble) sdpcone arg2 arg3 arg4 arg5 -end - -function AddARankOneMat( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Integer, - arg4::Integer, - arg5::Cdouble, - arg6::Integer, - arg7::Vector{Cint}, - arg8::Vector{Cdouble}, - arg9::Integer, -) - @dsdp_ccall SDPConeAddARankOneMat ( - SDPConeT, - Cint, - Cint, - Cint, - Cdouble, - Cint, - Ptr{Cint}, - Ptr{Cdouble}, - Cint, - ) sdpcone arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 -end - -function AddSparseVecMat( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Integer, - arg4::Integer, - arg5::Integer, - arg6::Vector{Cint}, - arg7::Vector{Cdouble}, - arg8::Integer, -) - @dsdp_ccall SDPConeAddSparseVecMat ( - SDPConeT, - Cint, - Cint, - Cint, - Cint, - Ptr{Cint}, - Ptr{Cdouble}, - Cint, - ) sdpcone arg2 arg3 arg4 arg5 arg6 arg7 arg8 -end - -function AddDenseVecMat( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Integer, - arg4::Integer, - arg5::Vector{Cdouble}, - arg6::Integer, -) - @dsdp_ccall SDPConeAddDenseVecMat ( - SDPConeT, - Cint, - Cint, - Cint, - Ptr{Cdouble}, - Cint, - ) sdpcone arg2 arg3 arg4 arg5 arg6 -end - -function SetSparseVecMat( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Integer, - arg4::Integer, - arg5::Integer, - arg6::Vector{Cint}, - arg7::Vector{Cdouble}, - arg8::Integer, -) - @dsdp_ccall SDPConeSetSparseVecMat ( - SDPConeT, - Cint, - Cint, - Cint, - Cint, - Ptr{Cint}, - Ptr{Cdouble}, - Cint, - ) sdpcone arg2 arg3 arg4 arg5 arg6 arg7 arg8 -end - -function SetDenseVecMat( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Integer, - arg4::Integer, - arg5::Vector{Cdouble}, - arg6::Integer, -) - @dsdp_ccall SDPConeSetDenseVecMat ( - SDPConeT, - Cint, - Cint, - Cint, - Ptr{Cdouble}, - Cint, - ) sdpcone arg2 arg3 arg4 arg5 arg6 -end - -function SetXMat(sdpcone::SDPConeT, arg2::Integer, arg3::Integer) - @dsdp_ccall SDPConeSetXMat (SDPConeT, Cint, Cint) sdpcone arg2 arg3 -end - -function SetXArray( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Integer, - arg4::Vector{Cdouble}, - arg5::Integer, -) - @dsdp_ccall SDPConeSetXArray (SDPConeT, Cint, Cint, Ptr{Cdouble}, Cint) sdpcone arg2 arg3 arg4 arg5 -end - -function GetXArray(sdpcone::SDPConeT, blockj::Integer) - xmat = Ref{Ptr{Cdouble}}() - nn = Ref{Cint}() - @dsdp_ccall SDPConeGetXArray (SDPConeT, Cint, Ref{Ptr{Cdouble}}, Ref{Cint}) sdpcone blockj xmat nn - return unsafe_wrap(Array, xmat[], nn[]) -end - -function RestoreXArray( - sdpcone::SDPConeT, - arg2::Integer, - arg3, - arg4::Vector{Cint}, -) - @dsdp_ccall SDPConeRestoreXArray ( - SDPConeT, - Cint, - Ptr{Ptr{Cdouble}}, - Ptr{Cint}, - ) sdpcone arg2 arg3 arg4 -end - -function CheckData(sdpcone::SDPConeT) - @dsdp_ccall SDPConeCheckData (SDPConeT,) sdpcone -end - -function RemoveDataMatrix(sdpcone::SDPConeT, arg2::Integer, arg3::Integer) - @dsdp_ccall SDPConeRemoveDataMatrix (SDPConeT, Cint, Cint) sdpcone arg2 arg3 -end - -function GetNumberOfBlocks(sdpcone::SDPConeT) - num = Ref{Cint}() - @dsdp_ccall SDPConeGetNumberOfBlocks (SDPConeT, Ref{Cint}) sdpcone num - return num[] -end - -function ComputeS( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Cdouble, - arg4, - arg5::Integer, - arg6::Cdouble, - arg7::Integer, - arg8::Vector{Cdouble}, - arg9::Integer, -) - @dsdp_ccall SDPConeComputeS ( - SDPConeT, - Cint, - Cdouble, - Ptr{Cdouble}, - Cint, - Cdouble, - Cint, - Ptr{Cdouble}, - Cint, - ) sdpcone arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 -end - -function ComputeX(sdpcone::SDPConeT, blockj::Integer, n::Integer, nn::Integer) - xmat = zeros(Cdouble, nn) - @dsdp_ccall SDPConeComputeX (SDPConeT, Cint, Cint, Ptr{Cdouble}, Cint) sdpcone blockj n xmat nn - return xmat -end - -function AddADotX( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Cdouble, - arg4::Vector{Cdouble}, - arg5::Integer, - arg6::Vector{Cdouble}, - arg7::Integer, -) - @dsdp_ccall SDPConeAddADotX ( - SDPConeT, - Cint, - Cdouble, - Ptr{Cdouble}, - Cint, - Ptr{Cdouble}, - Cint, - ) sdpcone arg2 arg3 arg4 arg5 arg6 arg7 -end - -function ViewX( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Integer, - arg4::Vector{Cdouble}, - arg5::Integer, -) - @dsdp_ccall SDPConeViewX (SDPConeT, Cint, Cint, Ptr{Cdouble}, Cint) sdpcone arg2 arg3 arg4 arg5 -end - -function SetLanczosIterations(sdpcone::SDPConeT, arg2::Integer) - @dsdp_ccall SDPConeSetLanczosIterations (SDPConeT, Cint) sdpcone arg2 -end - -function ScaleBarrier(sdpcone::SDPConeT, arg2::Integer, arg3::Cdouble) - @dsdp_ccall SDPConeScaleBarrier (SDPConeT, Cint, Cdouble) sdpcone arg2 arg3 -end - -function XVMultiply( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Vector{Cdouble}, - arg4::Vector{Cdouble}, -) - n = length(arg3) - @assert n == length(arg4) - @dsdp_ccall SDPConeXVMultiply ( - SDPConeT, - Cint, - Ptr{Cdouble}, - Ptr{Cdouble}, - Cint, - ) sdpcone arg2 pointer(arg3) pointer(arg4) n -end - -function ComputeXV(sdpcone::SDPConeT, arg2::Integer) - derror = Ref{Cint}() - @dsdp_ccall SDPConeComputeXV (SDPConeT, Cint, Ref{Cint}) sdpcone arg2 derror - return derror[] -end - -function AddXVAV( - sdpcone::SDPConeT, - arg2::Integer, - arg3::Vector{Cdouble}, - arg5::Vector{Cdouble}, -) - @dsdp_ccall SDPConeAddXVAV ( - SDPConeT, - Cint, - Ptr{Cdouble}, - Cint, - Ptr{Cdouble}, - Cint, - ) sdpcone arg2 pointer(arg3) length(arg3) pointer(arg5) length(arg5) -end - -function UseLAPACKForDualMatrix(sdpcone::SDPConeT, arg2::Integer) - @dsdp_ccall SDPConeUseLAPACKForDualMatrix (SDPConeT, Cint) sdpcone arg2 -end - -function UseFullSymmetricFormat(sdpcone::SDPConeT, arg2::Integer) - @dsdp_ccall SDPConeUseFullSymmetricFormat (SDPConeT, Cint) sdpcone arg2 -end - -function UsePackedFormat(sdpcone::SDPConeT, arg2::Integer) - @dsdp_ccall SDPConeUsePackedFormat (SDPConeT, Cint) sdpcone arg2 -end - -end diff --git a/test/MOI_wrapper.jl b/test/MOI_wrapper.jl index 5006afd..4203c24 100644 --- a/test/MOI_wrapper.jl +++ b/test/MOI_wrapper.jl @@ -24,7 +24,7 @@ function test_solver_name() @test MOI.get(DSDP.Optimizer(), MOI.SolverName()) == "DSDP" end -function test_options() +function test_bad_options() param = MOI.RawOptimizerAttribute("bad_option") err = MOI.UnsupportedAttribute(param) @test_throws err MOI.set( @@ -39,17 +39,18 @@ function test_runtests() MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()), MOI.instantiate(DSDP.Optimizer; with_bridge_type = Float64), ) + MOI.set(model, MOI.RawOptimizerAttribute("PTolerance"), 1e-8) # `Variable.ZerosBridge` makes dual needed by some tests fail. MOI.Bridges.remove_bridge( model.optimizer, MOI.Bridges.Variable.ZerosBridge{Float64}, ) - MOI.set(model, MOI.Silent(), true) + # MOI.set(model, MOI.Silent(), true) MOI.Test.runtests( model, MOI.Test.Config(; rtol = 1e-2, - atol = 1e-2, + atol = 1e-1, exclude = Any[ MOI.ConstraintBasisStatus, MOI.VariableBasisStatus, @@ -58,26 +59,11 @@ function test_runtests() ], ); exclude = Regex[ - # ArgumentError: DSDP does not support problems with no constraint. - # See https://github.com/jump-dev/MathOptInterface.jl/issues/1741#issuecomment-1057286739 - r"test_modification_set_singlevariable_lessthan$", - r"test_solve_optimize_twice$", - r"test_solve_result_index$", - r"test_objective_ObjectiveFunction_constant$", - r"test_objective_ObjectiveFunction_VariableIndex$", + # Error solving with empty problem r"test_objective_FEASIBILITY_SENSE_clears_objective$", - r"test_modification_transform_singlevariable_lessthan$", - r"test_modification_delete_variables_in_a_batch$", - r"test_modification_delete_variable_with_single_variable_obj$", - r"test_modification_const_scalar_objective$", - r"test_modification_coef_scalar_objective$", r"test_attribute_RawStatusString$", r"test_attribute_SolveTimeSec$", r"test_objective_ObjectiveFunction_blank$", - r"test_objective_ObjectiveFunction_duplicate_terms$", - r"test_solve_TerminationStatus_DUAL_INFEASIBLE$", - r"test_DualObjectiveValue_Max_VariableIndex_LessThan$", - r"test_DualObjectiveValue_Min_VariableIndex_GreaterThan$", # TODO investigate # Expression: MOI.get(model, MOI.TerminationStatus()) == config.infeasible_status # Evaluated: MathOptInterface.OPTIMAL == MathOptInterface.INFEASIBLE @@ -102,11 +88,8 @@ function test_runtests() r"test_conic_NormOneCone_VectorOfVariables$", r"test_conic_linear_VectorAffineFunction$", r"test_conic_linear_VectorAffineFunction_2$", - r"test_conic_linear_VectorOfVariables_2$", r"test_constraint_ScalarAffineFunction_Interval$", - r"test_conic_HermitianPositiveSemidefiniteConeTriangle_1$", r"test_constraint_PrimalStart_DualStart_SecondOrderCone$", - r"test_HermitianPSDCone_basic$", # Incorrect objective # See https://github.com/jump-dev/MathOptInterface.jl/issues/1759 r"test_linear_integration$", @@ -117,15 +100,6 @@ function test_runtests() # TODO: inaccurate solution r"test_linear_HyperRectangle_VectorAffineFunction$", r"test_linear_HyperRectangle_VectorOfVariables$", - r"test_HermitianPSDCone_min_t$", - r"test_NormNuclearCone_VectorAffineFunction_with_transform$", - r"test_NormNuclearCone_VectorAffineFunction_without_transform$", - r"test_NormNuclearCone_VectorOfVariables_with_transform$", - r"test_NormNuclearCone_VectorOfVariables_without_transform$", - r"test_NormSpectralCone_VectorAffineFunction_with_transform$", - r"test_NormSpectralCone_VectorAffineFunction_without_transform$", - r"test_NormSpectralCone_VectorOfVariables_with_transform$", - r"test_NormSpectralCone_VectorOfVariables_without_transform$", r"test_conic_GeometricMeanCone_VectorAffineFunction$", r"test_conic_GeometricMeanCone_VectorAffineFunction_2$", r"test_conic_GeometricMeanCone_VectorAffineFunction_3$", @@ -156,12 +130,6 @@ function test_runtests() r"test_conic_SecondOrderCone_Nonnegatives$", r"test_conic_SecondOrderCone_Nonpositives$", r"test_conic_SecondOrderCone_VectorAffineFunction$", - r"test_conic_SecondOrderCone_negative_initial_bound$", - r"test_conic_SecondOrderCone_negative_post_bound$", - r"test_conic_SecondOrderCone_negative_post_bound_2$", - r"test_conic_SecondOrderCone_negative_post_bound_3$", - r"test_conic_SecondOrderCone_no_initial_bound$", - r"test_conic_SecondOrderCone_nonnegative_initial_bound$", r"test_quadratic_constraint_integration$", r"test_linear_variable_open_intervals$", r"test_conic_SecondOrderCone_out_of_order$", @@ -170,6 +138,26 @@ function test_runtests() return end +function test_moi(tol = 1e-6) + model = MOI.Utilities.Model{Float64}() + X, _ = MOI.add_constrained_variables( + model, + MOI.PositiveSemidefiniteConeTriangle(2), + ) + c = MOI.add_constraint(model, 1.0 * X[2], MOI.EqualTo(1.0)) + obj = 1.0 * X[1] + 1.0 * X[3] + MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE) + MOI.set(model, MOI.ObjectiveFunction{typeof(obj)}(), obj) + dsdp = DSDP.Optimizer() + MOI.copy_to(dsdp, model) + MOI.optimize!(dsdp) + @test MOI.get(dsdp, MOI.ObjectiveValue()) ≈ 2 rtol = tol + @test MOI.get(dsdp, MOI.DualObjectiveValue()) ≈ 2 rtol = tol + @test MOI.get.(dsdp, MOI.VariablePrimal(), X) ≈ [1, 1, 1] rtol = tol + @test MOI.get(dsdp, MOI.ConstraintDual(), c) ≈ 2 rtol = tol + return +end + end # module TestDSDP.runtests() diff --git a/test/build.jl b/test/build.jl deleted file mode 100644 index a6b0f54..0000000 --- a/test/build.jl +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2022: Joey Huchette, Benoît Legat, and 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. - -@testset "LPConeSetData doc example" begin - lpdvars = Cint[3, 3, 2, 2, 1, 3, 1, 1] - lpdrows = Cint[2, 0, 1, 0, 0, 1, 1, 2] - lpcoefs = Cdouble[-1, 2, 3, 4, 6, 7, 10, 12] - nnzin, row, aval = LPCone.buildlp(3, lpdvars, lpdrows, lpcoefs) - @test nnzin isa Vector{Cint} - @test nnzin == [0, 3, 5, 8] - @test row isa Vector{Cint} - @test row == [0, 1, 2, 0, 1, 0, 1, 2] - @test aval isa Vector{Cdouble} - @test aval == [6, 10, 12, 4, 3, 2, 7, -1] -end diff --git a/test/c_api.jl b/test/c_api.jl new file mode 100644 index 0000000..d8d933c --- /dev/null +++ b/test/c_api.jl @@ -0,0 +1,243 @@ +# Copyright (c) 2022: Joey Huchette, Benoît Legat, and 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. + +module Test_c_api + +using DSDP +using Test + +function di(u, v) + u, v = max(u, v), min(u, v) + return div((u - Cint(1)) * u, Cint(2)) + (v - Cint(1)) +end +di(u) = di(u, u) + +signz(t) = t < 0 ? -1 : 1 + +# Apply the Goemens and Williamson randomized cut algorithm to the SDP relaxation of the max-cut problem +function MaxCutRandomized(sdpcone, nnodes::Integer) + ymin = Cdouble(0) + vv = Vector{Cdouble}(undef, nnodes) + tt = Vector{Cdouble}(undef, nnodes) + cc = Vector{Cdouble}(undef, nnodes + 2) + derror = Ref{Cint}() + DSDP.SDPConeComputeXV(sdpcone, 0, derror) + @assert derror[] == 0 + for i in 1:nnodes + for j in eachindex(vv) + dd = rand() - 0.5 + vv[j] = tan(π * dd) + end + DSDP.SDPConeXVMultiply(sdpcone, 0, vv, tt, nnodes) + map!(signz, tt, tt) + map!(zero, cc, cc) + DSDP.SDPConeAddXVAV(sdpcone, 0, tt, nnodes, cc, nnodes + 2) + if cc[1] < ymin + ymin = cc[1] + end + end + return ymin +end + +function maxcut(nnodes, edges) + nedges = length(edges) + p = Ref{Ptr{Cvoid}}() + DSDP.DSDPCreate(nnodes, p) + dsdp = p[] + DSDP.DSDPCreateSDPCone(dsdp, 1, p) + sdpcone = p[] + DSDP.SDPConeSetBlockSize(sdpcone, 0, nnodes) + # Formulate the problem from the data + # Diagonal elements equal 1.0 + # Create Constraint matrix A_i for i=1, ..., nnodes. + # that has a single nonzero element. + diag = ones(Cdouble, nnodes) + N = Cint(1):Cint(nnodes) + iptr = di.(N) + for i in 1:nnodes + DSDP.DSDPSetDualObjective(dsdp, i, 1.0) + DSDP.SDPConeSetASparseVecMat( + sdpcone, + 0, + i, + nnodes, + 1.0, + 0, + pointer(iptr, i), + pointer(diag, i), + 1, + ) + end + # C matrix is the Laplacian of the adjacency matrix + # Also compute a feasible initial point y such that S >= 0 + yy = zeros(nnodes) + indd = zeros(Cint, nnodes + nedges) + val = zeros(nnodes + nedges) + indd[nedges .+ (1:nnodes)] = iptr + tval = 0.0 + for (i, (u, v, w)) in enumerate(edges) + indd[i] = di(u, v) + tval += abs(w) + val[i] = w / 4 + val[nedges+u] -= w / 4 + val[nedges+v] -= w / 4 + yy[u] -= abs(w / 2) + yy[v] -= abs(w / 2) + end + DSDP.SDPConeSetASparseVecMat( + sdpcone, + 0, + 0, + nnodes, + 1.0, + 0, + pointer(indd), + pointer(val), + nedges, + ) + DSDP.SDPConeAddASparseVecMat( + sdpcone, + 0, + 0, + nnodes, + 1.0, + 0, + pointer(indd, nedges + 1), + pointer(val, nedges + 1), + nnodes, + ) + # Initial Point + DSDP.DSDPSetR0(dsdp, 0.0) + DSDP.DSDPSetZBar(dsdp, 10 * tval + 1.0) + for i in 1:nnodes + DSDP.DSDPSetY0(dsdp, i, 10 * yy[i]) + end + # Get read to go + DSDP.DSDPSetGapTolerance(dsdp, 0.001) + DSDP.DSDPSetPotentialParameter(dsdp, 5) + DSDP.DSDPSetReuseMatrix(dsdp, 0) + DSDP.DSDPSetPNormTolerance(dsdp, 1.0) + #info = TCheckArgs(dsdp,argc,argv) + DSDP.DSDPSetStandardMonitor(dsdp, 0) + DSDP.DSDPSetup(dsdp) + DSDP.DSDPSolve(dsdp) + stop = Ref{DSDP.DSDPTerminationReason}() + DSDP.DSDPStopReason(dsdp, stop) + reason = stop[] + @test reason != DSDP.DSDP_INFEASIBLE_START + ret = Ref{Cdouble}() + DSDP.DSDPGetDObjective(dsdp, ret) + @test ret[] ≈ -9.250079 rtol = 1e-7 + DSDP.DSDPGetDDObjective(dsdp, ret) + @test ret[] ≈ -9.250079 rtol = 1e-7 + DSDP.DSDPGetPObjective(dsdp, ret) + @test ret[] ≈ 1e10 + DSDP.DSDPGetPPObjective(dsdp, ret) + @test ret[] ≈ -9.240522 rtol = 1e-7 + DSDP.DSDPGetDualityGap(dsdp, ret) + @test ret[] ≈ 0.009557113 rtol = 1e-7 + # Randomized solution strategy + @test MaxCutRandomized(sdpcone, nnodes) ≈ -9.25 + return DSDP.DSDPDestroy(dsdp) +end + +function test_sdp(tol = 1e-6) + p = Ref{Ptr{Cvoid}}() + DSDP.DSDPCreate(1, p) + dsdp = p[] + DSDP.DSDPCreateSDPCone(dsdp, 1, p) + sdpcone = p[] + DSDP.SDPConeSetBlockSize(sdpcone, 0, 2) + DSDP.SDPConeSetSparsity(sdpcone, 0, 0) + DSDP.SDPConeSetStorageFormat(sdpcone, 0, UInt8('U')) + DSDP.DSDPSetY0(dsdp, 1, 0.0) + DSDP.DSDPSetDualObjective(dsdp, 1, 1.0) + DSDP.SDPConeSetASparseVecMat(sdpcone, 0, 1, 2, 1.0, 0, Int32[2], [0.5], 1) + DSDP.SDPConeSetASparseVecMat( + sdpcone, + 0, + 0, + 2, + 1.0, + 0, + Int32[0, 3], + [1.0, 1.0], + 2, + ) + DSDP.DSDPSetup(dsdp) + DSDP.DSDPSolve(dsdp) + DSDP.DSDPComputeX(dsdp) + ret = Ref{Cint}() + DSDP.DSDPGetIts(dsdp, ret) + @test ret[] == 10 + derr = zeros(Cdouble, 6) + DSDP.DSDPGetFinalErrors(dsdp, derr) + @test derr != zeros(Cdouble, 6) # To check that it's not just the allocated vector and we actually got the errors + @test derr ≈ zeros(Cdouble, 6) atol = tol + # P Infeasible: derr[1] + # D Infeasible: derr[3] + # Minimal P Eigenvalue: derr[2] + # Minimal D Eigenvalue: 0.00, see `DSDP` source in `examples/readsdpa.c` + # Relative P - D Objective values: derr[5] + # Relative X Dot S: %4.2e: derr[6] + stop = Ref{DSDP.DSDPTerminationReason}() + DSDP.DSDPStopReason(dsdp, stop) + @test stop[] == 1 + sol = Ref{DSDP.DSDPSolutionType}() + DSDP.DSDPGetSolutionType(dsdp, sol) + @test sol[] == 1 + ret = Ref{Cdouble}() + DSDP.DSDPGetDObjective(dsdp, ret) + @test ret[] ≈ 2 rtol = tol + DSDP.DSDPGetPObjective(dsdp, ret) + @test ret[] ≈ 2 rtol = tol + xmat = Ref{Ptr{Cdouble}}() + nn = Ref{Cint}() + DSDP.SDPConeGetXArray(sdpcone, 0, xmat, nn) + @test unsafe_wrap(Array, xmat[], nn[]) ≈ [1, 0, 1, 1] rtol = tol + num = Ref{Cint}() + DSDP.DSDPGetNumberOfVariables(dsdp, num) + @test num[] == 1 + DSDP.SDPConeGetNumberOfBlocks(sdpcone, num) + @test num[] == 1 + y = zeros(Cdouble, 1) + DSDP.DSDPGetY(dsdp, y, 1) + @test y[1] ≈ 2 rtol = tol + return +end + +@testset "SDP example" begin + test_sdp() +end + +@testset "DSDP MaxCut example" begin + nnodes = 6 + edges = [ + (1, 2, 0.3) + (1, 4, 2.7) + (1, 6, 1.5) + (2, 3, -1.0) + (2, 5, 1.45) + (3, 4, -0.2) + (4, 5, 1.2) + (5, 6, 2.1) + ] + maxcut(nnodes, edges) +end + +@testset "LPConeSetData doc example" begin + lpdvars = Cint[3, 3, 2, 2, 1, 3, 1, 1] + lpdrows = Cint[2, 0, 1, 0, 0, 1, 1, 2] + lpcoefs = Cdouble[-1, 2, 3, 4, 6, 7, 10, 12] + nnzin, row, aval = DSDP._build_lp(3, lpdvars, lpdrows, lpcoefs) + @test nnzin isa Vector{Cint} + @test nnzin == [0, 3, 5, 8] + @test row isa Vector{Cint} + @test row == [0, 1, 2, 0, 1, 0, 1, 2] + @test aval isa Vector{Cdouble} + @test aval == [6, 10, 12, 4, 3, 2, 7, -1] +end + +end # module diff --git a/test/maxcut.jl b/test/maxcut.jl deleted file mode 100644 index cd496a2..0000000 --- a/test/maxcut.jl +++ /dev/null @@ -1,155 +0,0 @@ -# Copyright (c) 2022: Joey Huchette, Benoît Legat, and 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. - -function di(u, v) - u, v = max(u, v), min(u, v) - return div((u - Cint(1)) * u, Cint(2)) + (v - Cint(1)) -end -di(u) = di(u, u) - -signz(t) = t < 0 ? -1 : 1 - -# Apply the Goemens and Williamson randomized cut algorithm to the SDP relaxation of the max-cut problem -function MaxCutRandomized(sdpcone::SDPCone.SDPConeT, nnodes::Integer) - ymin = Cdouble(0) - - vv = Vector{Cdouble}(undef, nnodes) - tt = Vector{Cdouble}(undef, nnodes) - cc = Vector{Cdouble}(undef, nnodes + 2) - SDPCone.ComputeXV(sdpcone, 0) - for i in 1:nnodes - for j in eachindex(vv) - dd = rand() - 0.5 - vv[j] = tan(π * dd) - end - SDPCone.XVMultiply(sdpcone, 0, vv, tt) - map!(signz, tt, tt) - map!(zero, cc, cc) - SDPCone.AddXVAV(sdpcone, 0, tt, cc) - if cc[1] < ymin - ymin = cc[1] - end - end - return ymin -end - -function maxcut(nnodes, edges) - nedges = length(edges) - dsdp = DSDP.Create(nnodes) - sdpcone = DSDP.CreateSDPCone(dsdp, 1) - - SDPCone.SetBlockSize(sdpcone, 0, nnodes) - - # Formulate the problem from the data - # Diagonal elements equal 1.0 - # Create Constraint matrix A_i for i=1, ..., nnodes. - # that has a single nonzero element. - diag = ones(Cdouble, nnodes) - N = Cint(1):Cint(nnodes) - iptr = di.(N) - - for i in 1:nnodes - DSDP.SetDualObjective(dsdp, i, 1.0) - SDPCone.SetASparseVecMat( - sdpcone, - 0, - i, - nnodes, - 1.0, - 0, - pointer(iptr, i), - pointer(diag, i), - 1, - ) - end - - # C matrix is the Laplacian of the adjacency matrix - # Also compute a feasible initial point y such that S >= 0 - yy = zeros(nnodes) - indd = zeros(Cint, nnodes + nedges) - val = zeros(nnodes + nedges) - indd[nedges.+(1:nnodes)] = iptr - tval = 0.0 - for (i, (u, v, w)) in enumerate(edges) - indd[i] = di(u, v) - tval += abs(w) - val[i] = w / 4 - val[nedges+u] -= w / 4 - val[nedges+v] -= w / 4 - yy[u] -= abs(w / 2) - yy[v] -= abs(w / 2) - end - - SDPCone.SetASparseVecMat( - sdpcone, - 0, - 0, - nnodes, - 1.0, - 0, - pointer(indd), - pointer(val), - nedges, - ) - SDPCone.AddASparseVecMat( - sdpcone, - 0, - 0, - nnodes, - 1.0, - 0, - pointer(indd, nedges + 1), - pointer(val, nedges + 1), - nnodes, - ) - - # Initial Point - DSDP.SetR0(dsdp, 0.0) - DSDP.SetZBar(dsdp, 10 * tval + 1.0) - for i in 1:nnodes - DSDP.SetY0(dsdp, i, 10 * yy[i]) - end - - # Get read to go - DSDP.SetGapTolerance(dsdp, 0.001) - DSDP.SetPotentialParameter(dsdp, 5) - DSDP.SetReuseMatrix(dsdp, 0) - DSDP.SetPNormTolerance(dsdp, 1.0) - #info = TCheckArgs(dsdp,argc,argv) - - DSDP.SetStandardMonitor(dsdp, 0) - - DSDP.Setup(dsdp) - - DSDP.Solve(dsdp) - reason = DSDP.StopReason(dsdp) - - @test reason != DSDP.DSDP_INFEASIBLE_START - @test DSDP.GetDObjective(dsdp) ≈ -9.250079 rtol = 1e-7 - @test DSDP.GetDDObjective(dsdp) ≈ -9.250079 rtol = 1e-7 - @test DSDP.GetPObjective(dsdp) ≈ 1e10 - @test DSDP.GetPPObjective(dsdp) ≈ -9.240522 rtol = 1e-7 - @test DSDP.GetDualityGap(dsdp) ≈ 0.009557113 rtol = 1e-7 - - # Randomized solution strategy - @test MaxCutRandomized(sdpcone, nnodes) ≈ -9.25 - - return DSDP.Destroy(dsdp) -end - -@testset "DSDP MaxCut example" begin - nnodes = 6 - edges = [ - (1, 2, 0.3) - (1, 4, 2.7) - (1, 6, 1.5) - (2, 3, -1.0) - (2, 5, 1.45) - (3, 4, -0.2) - (4, 5, 1.2) - (5, 6, 2.1) - ] - maxcut(nnodes, edges) -end diff --git a/test/options.jl b/test/options.jl deleted file mode 100644 index 53c29f6..0000000 --- a/test/options.jl +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2022: Joey Huchette, Benoît Legat, and 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. - -using MathOptInterface -const MOI = MathOptInterface - -@testset "Options" begin - optimizer = MOI.Utilities.CachingOptimizer( - MOI.Utilities.Model{Float64}(), - DSDP.Optimizer(), - ) - x, cx = MOI.add_constrained_variables(optimizer, MOI.Nonnegatives(1)) - MOI.add_constraint(optimizer, 1.0x[1], MOI.EqualTo(1.0)) - MOI.Utilities.attach_optimizer(optimizer) - for (option, default) in - Iterators.flatten((DSDP.options, DSDP.gettable_options)) - @eval begin - @test MOI.get($optimizer, DSDP.$option()) == $default - end - end -end diff --git a/test/runtests.jl b/test/runtests.jl index 6b67cf2..49f9e16 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -3,11 +3,5 @@ # 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. -using DSDP -using Test - -include("maxcut.jl") -include("sdp.jl") -include("build.jl") -include("options.jl") +include("c_api.jl") include("MOI_wrapper.jl") diff --git a/test/sdp.jl b/test/sdp.jl deleted file mode 100644 index 717459a..0000000 --- a/test/sdp.jl +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright (c) 2022: Joey Huchette, Benoît Legat, and 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. - -using Test, DSDP - -function test_sdp(tol = 1e-6) - dsdp = DSDP.Create(1) - sdpcone = DSDP.CreateSDPCone(dsdp, 1) - DSDP.SDPCone.SetBlockSize(sdpcone, 0, 2) - DSDP.SDPCone.SetSparsity(sdpcone, 0, 0) - DSDP.SDPCone.SetStorageFormat(sdpcone, 0, UInt8('U')) - DSDP.SetY0(dsdp, 1, 0.0) - DSDP.SetDualObjective(dsdp, 1, 1.0) - DSDP.SDPCone.SetASparseVecMat(sdpcone, 0, 1, 2, 1.0, 0, Int32[2], [0.5], 1) - DSDP.SDPCone.SetASparseVecMat( - sdpcone, - 0, - 0, - 2, - 1.0, - 0, - Int32[0, 3], - [1.0, 1.0], - 2, - ) - DSDP.Setup(dsdp) - DSDP.Solve(dsdp) - DSDP.ComputeX(dsdp) - @test DSDP.GetIts(dsdp) == 10 - derr = DSDP.GetFinalErrors(dsdp) - @test derr != zeros(Cdouble, 6) # To check that it's not just the allocated vector and we actually got the errors - @test derr ≈ zeros(Cdouble, 6) atol = tol - - # P Infeasible: derr[1] - # D Infeasible: derr[3] - # Minimal P Eigenvalue: derr[2] - # Minimal D Eigenvalue: 0.00, see `DSDP` source in `examples/readsdpa.c` - # Relative P - D Objective values: derr[5] - # Relative X Dot S: %4.2e: derr[6] - - @test DSDP.StopReason(dsdp) == 1 - @test DSDP.GetSolutionType(dsdp) == 1 - @test DSDP.GetDObjective(dsdp) ≈ 2 rtol = tol - @test DSDP.GetPObjective(dsdp) ≈ 2 rtol = tol - @test DSDP.SDPCone.GetXArray(sdpcone, 0) ≈ [1, 0, 1, 1] rtol = tol - @test DSDP.GetNumberOfVariables(dsdp) == 1 - @test DSDP.SDPCone.GetNumberOfBlocks(sdpcone) == 1 - y = zeros(Cdouble, 1) - DSDP.GetY(dsdp, y) - @test y[1] ≈ 2 rtol = tol - return -end - -import MathOptInterface as MOI - -function test_moi(tol = 1e-6) - model = MOI.Utilities.Model{Float64}() - X, _ = MOI.add_constrained_variables( - model, - MOI.PositiveSemidefiniteConeTriangle(2), - ) - c = MOI.add_constraint(model, 1.0 * X[2], MOI.EqualTo(1.0)) - obj = 1.0 * X[1] + 1.0 * X[3] - MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE) - MOI.set(model, MOI.ObjectiveFunction{typeof(obj)}(), obj) - dsdp = DSDP.Optimizer() - MOI.copy_to(dsdp, model) - MOI.optimize!(dsdp) - @test MOI.get(dsdp, MOI.ObjectiveValue()) ≈ 2 rtol = tol - @test MOI.get(dsdp, MOI.DualObjectiveValue()) ≈ 2 rtol = tol - @test MOI.get.(dsdp, MOI.VariablePrimal(), X) ≈ [1, 1, 1] rtol = tol - @test MOI.get(dsdp, MOI.ConstraintDual(), c) ≈ 2 rtol = tol - return -end - -@testset "SDP example" begin - test_sdp() - test_moi() -end