Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Julia 0.7 #100

Merged
merged 17 commits into from
May 6, 2018
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions deps/build.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ using BinDeps

@BinDeps.setup

blasvendor = Base.BLAS.vendor()
using Compat.Libdl
using Compat.LinearAlgebra.BLAS
using Compat.Sys: isapple

blasvendor = BLAS.vendor()

direct = library_dependency("libscsdir", aliases=["libscsdir64"])
indirect = library_dependency("libscsindir", aliases=["libscsindir64"])

# TODO: Provide both libs in the "scs" Homebrew package.
# if is_apple()
# if Sys.isapple()
# using Homebrew
# provides(Homebrew.HB, "scs", [direct, indirect], os = :Darwin)
# end
Expand All @@ -35,7 +39,7 @@ prefix = joinpath(BinDeps.depsdir(direct), "usr")
srcdir = joinpath(BinDeps.depsdir(direct), "src", "scs-$version/")

ldflags = ""
if is_apple()
if isapple()
ldflags = "$ldflags -undefined suppress -flat_namespace"
end
cflags = "-DCOPYAMATRIX -DDLONG -DUSE_LAPACK -DCTRLC=1"
Expand Down
14 changes: 7 additions & 7 deletions src/MOIWrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ end
mutable struct SCSOptimizer <: MOI.AbstractOptimizer
cone::ConeData
maxsense::Bool
data::Union{Void, ModelData} # only non-Void between MOI.copy! and MOI.optimize!
data::Union{Nothing, ModelData} # only non-Void between MOI.copy! and MOI.optimize!
sol::MOISolution
function SCSOptimizer()
new(ConeData(), false, nothing, MOISolution())
Expand Down Expand Up @@ -169,7 +169,7 @@ function _scalecoef(rows, coef, minus, ::Type{MOI.PositiveSemidefiniteConeTriang
scaling = minus ? -1 : 1
scaling2 = rev ? scaling / √2 : scaling * √2
output = copy(coef)
diagidx = IntSet()
diagidx = BitSet()
for i in 1:d
push!(diagidx, trimap(i, i))
end
Expand Down Expand Up @@ -232,11 +232,11 @@ function MOIU.loadconstraint!(optimizer::SCSOptimizer, ci, f::MOI.VectorAffineFu
offset = constroffset(optimizer, ci)
rows = constrrows(s)
optimizer.cone.nrows[offset] = length(rows)
i = offset + rows
i = offset .+ rows
# The SCS format is b - Ax ∈ cone
# so minus=false for b and minus=true for A
optimizer.data.b[i] = scalecoef(rows, orderval(f.constant, s), false, s)
append!(optimizer.data.I, offset + orderidx(I, s))
append!(optimizer.data.I, offset .+ orderidx(I, s))
append!(optimizer.data.J, J)
append!(optimizer.data.V, scalecoef(I, V, true, s))
end
Expand Down Expand Up @@ -268,7 +268,7 @@ MOIU.canload(::SCSOptimizer, ::MOI.ObjectiveSense) = true
function MOIU.load!(::SCSOptimizer, ::MOI.ObjectiveSense, ::MOI.OptimizationSense) end
MOIU.canload(::SCSOptimizer, ::MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}) = true
function MOIU.load!(optimizer::SCSOptimizer, ::MOI.ObjectiveFunction, f::MOI.ScalarAffineFunction)
c0 = full(sparsevec(_varmap(f), f.coefficients, optimizer.data.n))
c0 = Vector(sparsevec(_varmap(f), f.coefficients, optimizer.data.n))
optimizer.data.objconstant = f.constant
optimizer.data.c = optimizer.maxsense ? -c0 : c0
end
Expand Down Expand Up @@ -352,7 +352,7 @@ end
function MOI.get(optimizer::SCSOptimizer, ::MOI.ConstraintPrimal, ci::CI{<:MOI.AbstractFunction, S}) where S <: MOI.AbstractSet
offset = constroffset(optimizer, ci)
rows = constrrows(optimizer, ci)
_unshift(optimizer, offset, unscalecoef(rows, reorderval(optimizer.sol.slack[offset + rows], S), S, length(rows)), S)
_unshift(optimizer, offset, unscalecoef(rows, reorderval(optimizer.sol.slack[offset .+ rows], S), S, length(rows)), S)
end

MOI.canget(optimizer::SCSOptimizer, ::MOI.DualStatus) = true
Expand All @@ -372,7 +372,7 @@ end
function MOI.get(optimizer::SCSOptimizer, ::MOI.ConstraintDual, ci::CI{<:MOI.AbstractFunction, S}) where S <: MOI.AbstractSet
offset = constroffset(optimizer, ci)
rows = constrrows(optimizer, ci)
unscalecoef(rows, reorderval(optimizer.sol.dual[offset + rows], S), S, length(rows))
unscalecoef(rows, reorderval(optimizer.sol.dual[offset .+ rows], S), S, length(rows))
end

MOI.canget(optimizer::SCSOptimizer, ::MOI.ResultCount) = true
Expand Down
30 changes: 25 additions & 5 deletions src/MPBWrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@
# MathProgBase.jl interface for the SCS.jl solver wrapper
#############################################################################

importall MathProgBase.SolverInterface
using Compat.LinearAlgebra: dot
using MathProgBase.SolverInterface

import MathProgBase.SolverInterface: ConicModel, LinearQuadraticModel,
getdual, getobjval, getsolution, getsolvetime, getvardual, loadproblem!,
numconstr, numvar, optimize!, setbvec!, setwarmstart!, status,
supportedcones

import Base.convert

# TODO: don't add to Base.convert!
Expand Down Expand Up @@ -145,14 +152,14 @@ function orderconesforscs(A_in, b_in, c_cones, v_cones)
A_t = spzeros(n,0)
b = zeros(0)
row_map_ind = zeros(Int, length(b_in))
row_map_type = Array{Symbol}(length(b_in))
row_map_type = Array{Symbol}(undef, length(b_in))
col_map_ind = zeros(Int, n)
col_map_type = Array{Symbol}(n)
col_map_type = Array{Symbol}(undef, n)

# First, count the total number of variables
num_vars = 0
for (cone, idxs) in v_cones
col_map_type[idxs] = cone
col_map_type[idxs] .= cone
num_vars += length(idxs)
end
@assert num_vars == n
Expand Down Expand Up @@ -429,10 +436,23 @@ function getvardual(m::SCSMathProgModel)
return dual
end

if VERSION >= v"0.7-"
function addoption!(m::SCSMathProgModel, option::Symbol, value)
nt = NamedTuple{(option,), Tuple{typeof(value)}}((value,))
m.options = pairs(merge(m.options.data, nt))
return m
end
else
function addoption!(m::SCSMathProgModel, option::Symbol, value)
push!(m.options, (option, value))
return m
end
end

# warmstart
# kwargs can be `primal_sol`, `dual_sol`, and `slack`
function setwarmstart!(m::SCSMathProgModel, primal_sol; kwargs...)
push!(m.options, (:warm_start, true))
addoption!(m, :warm_start, true)
m.primal_sol = primal_sol
for (k,v) in kwargs
setfield!(m, k, v)
Expand Down
6 changes: 4 additions & 2 deletions src/SCS.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ else
error("SCS not properly installed. Please run Pkg.build(\"SCS\") and restart julia")
end

import Base.Libdl: RTLD_LAZY, RTLD_DEEPBIND, RTLD_GLOBAL, dlopen
using Compat
using Compat.Libdl
using Compat.Sys: isunix

function __init__()
vnum = VersionNumber(SCS_version())
# default binaries need access to Julia's lapack symbols
if is_unix()
if isunix()
dlopen(Base.liblapack_name, RTLD_LAZY|RTLD_DEEPBIND|RTLD_GLOBAL)
end
depsdir = realpath(joinpath(dirname(@__FILE__),"..","deps"))
Expand Down
22 changes: 14 additions & 8 deletions src/c_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ macro compat_gc_preserve(args...)
vars = args[1:end-1]
body = args[end]
if VERSION > v"0.7.0-"
return esc(Expr(:macrocall, Expr(:., :Base, Base.Meta.quot(Symbol("@gc_preserve"))), __source__, args...))
return esc(Expr(:macrocall, Expr(:., :GC, Base.Meta.quot(Symbol("@preserve"))), __source__, args...))
else
return esc(body)
end
Expand Down Expand Up @@ -52,7 +52,13 @@ function SCS_solve(T::Union{Type{Direct}, Type{Indirect}},
cone = Ref(SCSCone(f, l, q, s, ep, ed, p))
info = Ref(SCSInfo())

if (:warm_start, true) in options && length(primal_sol) == n && length(dual_sol) == m && length(slack) == m
if VERSION >= v"0.7-"
ws = (:warm_start=>true) in options
else
ws = (:warm_start, true) in options
end

if ws && length(primal_sol) == n && length(dual_sol) == m && length(slack) == m
x = primal_sol
y = dual_sol
s = slack
Expand Down Expand Up @@ -82,26 +88,26 @@ for (T, lib) in zip([SCS.Direct, SCS.Indirect], [SCS.direct, SCS.indirect])
@eval begin
function SCS_init(::Type{$T}, data::Ref{SCSData}, cone::Ref{SCSCone}, info::Ref{SCSInfo})

p_work = ccall((:scs_init, $lib), Ptr{Void},
p_work = ccall((:scs_init, $lib), Ptr{Nothing},
(Ptr{SCSData}, Ptr{SCSCone}, Ptr{SCSInfo}),
data, cone, info)

return p_work
end

# solution struct is simple enough, we know it won't be modified by SCS so take by value
function SCS_solve(::Type{$T}, p_work::Ptr{Void}, data::Ref{SCSData}, cone::Ref{SCSCone}, solution::SCSSolution, info::Ref{SCSInfo})
function SCS_solve(::Type{$T}, p_work::Ptr{Nothing}, data::Ref{SCSData}, cone::Ref{SCSCone}, solution::SCSSolution, info::Ref{SCSInfo})

status = ccall((:scs_solve, $lib), Int,
(Ptr{Void}, Ptr{SCSData}, Ptr{SCSCone}, Ref{SCSSolution}, Ptr{SCSInfo}),
(Ptr{Nothing}, Ptr{SCSData}, Ptr{SCSCone}, Ref{SCSSolution}, Ptr{SCSInfo}),
p_work, data, cone, solution, info)

return status
end

function SCS_finish(::Type{$T}, p_work::Ptr{Void})
ccall((:scs_finish, $lib), Void,
(Ptr{Void}, ),
function SCS_finish(::Type{$T}, p_work::Ptr{Nothing})
ccall((:scs_finish, $lib), Nothing,
(Ptr{Nothing}, ),
p_work)
end
end
Expand Down
11 changes: 6 additions & 5 deletions src/types.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export SCSMatrix, SCSData, SCSSettings, SCSSolution, SCSInfo, SCSCone, SCSVecOrMatOrSparse
using Compat.SparseArrays

export SCSMatrix, SCSData, SCSSettings, SCSSolution, SCSInfo, SCSCone, SCSVecOrMatOrSparse

SCSVecOrMatOrSparse = Union{VecOrMat, SparseMatrixCSC{Float64,Int}}

Expand Down Expand Up @@ -67,10 +68,10 @@ struct SCSData
stgs::Ptr{SCSSettings}
end

struct SCSSolution
x::Ptr{Void}
y::Ptr{Void}
s::Ptr{Void}
@compat struct SCSSolution
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This @compat shouldn't be needed.

x::Ptr{Nothing}
y::Ptr{Nothing}
s::Ptr{Nothing}
end


Expand Down
4 changes: 2 additions & 2 deletions test/MPBWrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
include("mpb_linear.jl")
end

import SCS
using Compat.Pkg: dir
@testset "MathProgBase" begin
include(joinpath(Pkg.dir("MathProgBase"),"test","conicinterface.jl"))
include(joinpath(dir("MathProgBase"),"test","conicinterface.jl"))
coniclineartest(SCS.SCSSolver(), duals=true, tol=1e-2)
conicSOCtest(SCS.SCSSolver(), duals=true, tol=1e-2)
conicEXPtest(SCS.SCSSolver(), duals=true, tol=1e-2)
Expand Down
3 changes: 0 additions & 3 deletions test/direct.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
using SCS
using Base.Test

# Solve a trivial problem
A = reshape([1.0],(1,1))
solution = SCS_solve(SCS.Direct, 1, 1, A, [1.0], [1.0], 1, 0, Int[], Int[], 0, 0, Float64[]);
Expand Down
3 changes: 0 additions & 3 deletions test/indirect.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
using SCS
using Base.Test

# Solve a trivial problem
A = reshape([1.0],(1,1))
solution = SCS_solve(SCS.Indirect, 1, 1, A, [1.0], [1.0], 1, 0, Int[], Int[], 0, 0, Float64[]);
Expand Down
4 changes: 2 additions & 2 deletions test/mpb_linear.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
# Test the MathProgBase.jl interface for the SCS.jl solver wrapper
#############################################################################

using Base.Test
using MathProgBase
using SCS
using Compat.LinearAlgebra
using Compat.SparseArrays

solver = SCSSolver()
objtol = 1e-4
Expand Down
9 changes: 3 additions & 6 deletions test/options.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@
# Tests the ability to pass options
#############################################################################

using Base.Test
using MathProgBase.SolverInterface
using SCS

using MathProgBase

# The normal test
A = [1.0 1.0 0.0 0.0 0.0;
Expand All @@ -33,8 +30,8 @@ MathProgBase.optimize!(m)
@test isapprox(MathProgBase.getobjval(m), -99.0, atol=1e-5)

# With a warmstart from the eps = 1e-8 solution, solution should be extremely accurate even after 1 iteration
push!(m.options, (:warm_start, true))
push!(m.options, (:max_iters, 1))
SCS.addoption!(m, :warm_start, true)
SCS.addoption!(m, :max_iters, 1)
MathProgBase.optimize!(m)
@test isapprox(MathProgBase.getobjval(m), -99.0, atol=1e-5)

Expand Down
3 changes: 2 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Base.Test
using Compat.Test
using SCS

tests = ["direct.jl",
"indirect.jl",
Expand Down
639 changes: 612 additions & 27 deletions test/test_problems.jl

Large diffs are not rendered by default.