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

Update to OSQP version 0.6.0 #61

Merged
merged 5 commits into from
Sep 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ deps/build.log
.vscode/

Manifest.toml
.editorconfig
2 changes: 1 addition & 1 deletion deps/build.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const verbose = "--verbose" in ARGS
const prefix = Prefix(get([a for a in ARGS if a != "--verbose"], 1, joinpath(@__DIR__, "usr")))

# Current version
version = "0.5.0"
version = "0.6.0"

# Get current operating system
osqp_platform =
Expand Down
34 changes: 26 additions & 8 deletions src/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,37 @@ MOI.get(::Optimizer, ::MOI.SolverName) = "OSQP"

MOI.supports(::Optimizer, ::MOI.Silent) = true
function MOI.set(optimizer::Optimizer, ::MOI.Silent, value::Bool)
if optimizer.silent != value
optimizer.silent = value
if !MOI.is_empty(optimizer)
if optimizer.silent
OSQP.update_settings!(optimizer.inner; :verbose => false)
else
OSQP.update_settings!(optimizer.inner; :verbose => optimizer.settings[:verbose])
end
optimizer.silent = value
if !MOI.is_empty(optimizer)
if optimizer.silent
OSQP.update_settings!(optimizer.inner; :verbose => false)
else
OSQP.update_settings!(optimizer.inner; :verbose => optimizer.settings[:verbose])
end
end
end
MOI.get(optimizer::Optimizer, ::MOI.Silent) = optimizer.silent



MOI.supports(::Optimizer, ::MOI.TimeLimitSec) = true
function MOI.set(model::Optimizer, ::MOI.TimeLimitSec, limit::Real)
MOI.set(model, OSQPSettings.TimeLimit(), limit)
return
end

function MOI.set(model::Optimizer, attr::MOI.TimeLimitSec, ::Nothing)
delete!(model.settings, :time_limit)
OSQP.update_settings!(model.inner, time_limit=0.0)
return
end

function MOI.get(model::Optimizer, ::MOI.TimeLimitSec)
return get(model.settings, :time_limit, nothing)
end



hasresults(optimizer::Optimizer) = optimizer.hasresults

function MOI.empty!(optimizer::Optimizer)
Expand Down
5 changes: 3 additions & 2 deletions src/OSQP.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module OSQP

export OSQPMathProgBaseInterface
using SparseArrays
using LinearAlgebra


if isfile(joinpath(dirname(@__FILE__), "..", "deps", "deps.jl"))
Expand All @@ -19,8 +20,8 @@ function __init__()


depsdir = realpath(joinpath(dirname(@__FILE__), "..", "deps"))
if (vnum.major != 0 && vnum.minor != 4)
error("Current OSQP version installed is $(osqp_version()), but we require version 0.4.*. Delete the contents of the `$depsdir` directory except for the files `build.jl` and `.gitignore`, then rerun Pkg.build(\"OSQP\").")
if (vnum.major != 0 && vnum.minor != 6)
error("Current OSQP version installed is $(osqp_version()), but we require version 0.6.*. Delete the contents of the `$depsdir` directory except for the files `build.jl` and `.gitignore`, then rerun Pkg.build(\"OSQP\").")
end
end

Expand Down
2 changes: 1 addition & 1 deletion src/constants.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const QDLDL_SOLVER = 0
const MKL_PARDISO_SOLVER = 1

# Define OSQP infinity constants
const OSQP_INFTY = 1e20
const OSQP_INFTY = 1e30

# OSQP return values
# https://github.com/oxfordcontrol/osqp/blob/master/include/constants.h
Expand Down
18 changes: 13 additions & 5 deletions src/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ function setup!(model::OSQP.Model;
A = sparse(A)
end

# Constructing upper triangular from P
if !istriu(P)
P = triu(P)
end

# Convert lower and upper bounds from Julia infinity to OSQP infinity
u = min.(u, OSQP_INFTY)
l = max.(l, -OSQP_INFTY)
Expand Down Expand Up @@ -146,12 +151,16 @@ function setup!(model::OSQP.Model;
pointer(q),
pointer(l), pointer(u))


# Perform setup
model.workspace = ccall((:osqp_setup, OSQP.osqp), Ptr{OSQP.Workspace},
(Ptr{OSQP.Data}, Ptr{OSQP.Settings}), Ref(data), Ref(stgs))
workspace = Ref{Ptr{OSQP.Workspace}}()
exitflag = ccall((:osqp_setup, OSQP.osqp), Cc_int,
(Ptr{Ptr{OSQP.Workspace}}, Ptr{OSQP.Data}, Ptr{OSQP.Settings}),
workspace, Ref(data), Ref(stgs))
model.workspace = workspace[]
end

if model.workspace == C_NULL
if exitflag != 0
error("Error in OSQP setup")
end

Expand All @@ -160,8 +169,7 @@ end

function solve!(model::OSQP.Model, results::Results = Results())
ccall((:osqp_solve, OSQP.osqp), Cc_int,
(Ptr{OSQP.Workspace}, ),
model.workspace)
(Ptr{OSQP.Workspace}, ), model.workspace)
workspace = unsafe_load(model.workspace)
info = results.info
copyto!(info, unsafe_load(workspace.info))
Expand Down
4 changes: 1 addition & 3 deletions test/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,7 @@ function bridged_optimizer()
end

@testset "CachingOptimizer: unit" begin
excludes = [# TODO
"time_limit_sec",
# Quadratic constraints are not supported
excludes = [# Quadratic constraints are not supported
"solve_qcp_edge_cases",
# No method get(::Optimizer, ::MathOptInterface.ConstraintPrimal, ::MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64},MathOptInterface.Nonpositives})
"solve_duplicate_terms_vector_affine",
Expand Down
6 changes: 4 additions & 2 deletions test/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,16 @@ tol = 1e-5

model = OSQP.Model()
OSQP.setup!(model; P=problem[:P], q=problem[:q],
A=problem[:A], l=problem[:l], u=problem[:u], options...)
A=problem[:A], l=problem[:l], u=problem[:u], options...)
results = OSQP.solve!(model)


@test results.info.status == :Solved

# Ensure solver will time out
OSQP.update_settings!(model, time_limit=1e-6, max_iter=1000000, check_termination=0)
OSQP.update_settings!(model,
eps_abs=1e-20, eps_rel=1e-20,
time_limit=1e-6, max_iter=1000000, check_termination=0)

results_time_limit = OSQP.solve!(model)

Expand Down
4 changes: 2 additions & 2 deletions test/dual_infeasibility.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ function setup_dual_infeasibility()
options = Dict(:verbose => false,
:eps_abs => 1e-05,
:eps_rel => 1e-05,
:eps_prim_inf => 1e-18,
:eps_prim_inf => 1e-15,
:check_termination => 1)
return options
end
Expand Down Expand Up @@ -56,7 +56,7 @@ tol = 1e-5
OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...)

# Warm start to avoid infeasibility detection at first step
OSQP.warm_start!(model, x=[25.; 25], y=[-2.; -2; -2; -2])
OSQP.warm_start!(model, x=[50.; 30.], y=[-2.; -2; -2; -2])

results = OSQP.solve!(model)

Expand Down