From 1f63da3130f363067b3e97c96b809bb266b608af Mon Sep 17 00:00:00 2001 From: Tamas Hakkel Date: Thu, 6 Nov 2025 20:37:05 +0100 Subject: [PATCH] Defer loading OSQP for faster startup time --- src/functions/indPolyhedralOSQP.jl | 36 ++++++++++++++---------------- test/runtests.jl | 3 ++- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/functions/indPolyhedralOSQP.jl b/src/functions/indPolyhedralOSQP.jl index 6fb67d7f..99963497 100644 --- a/src/functions/indPolyhedralOSQP.jl +++ b/src/functions/indPolyhedralOSQP.jl @@ -1,24 +1,25 @@ # IndPolyhedral: OSQP implementation -using OSQP - -struct IndPolyhedralOSQP{R} <: IndPolyhedral +struct IndPolyhedralOSQP{R,M} <: IndPolyhedral l::AbstractVector{R} A::AbstractMatrix{R} u::AbstractVector{R} - mod::OSQP.Model - function IndPolyhedralOSQP{R}( + mod::M + function IndPolyhedralOSQP( l::AbstractVector{R}, A::AbstractMatrix{R}, u::AbstractVector{R} ) where R m, n = size(A) - mod = OSQP.Model() - if !all(l .<= u) - error("function is improper (are some bounds inverted?)") + mod = Base.invokelatest(Base.require(@__MODULE__, :OSQP)) do OSQP + mod = OSQP.Model() + if !all(l .<= u) + error("function is improper (are some bounds inverted?)") + end + OSQP.setup!(mod; P=SparseMatrixCSC{R}(I, n, n), l=l, A=sparse(A), u=u, verbose=false, + eps_abs=eps(R), eps_rel=eps(R), + eps_prim_inf=eps(R), eps_dual_inf=eps(R)) + mod end - OSQP.setup!(mod; P=SparseMatrixCSC{R}(I, n, n), l=l, A=sparse(A), u=u, verbose=false, - eps_abs=eps(R), eps_rel=eps(R), - eps_prim_inf=eps(R), eps_dual_inf=eps(R)) - new(l, A, u, mod) + new{R,typeof(mod)}(l, A, u, mod) end end @@ -28,11 +29,6 @@ is_proximable(::Type{<:IndPolyhedralOSQP}) = false # constructors -IndPolyhedralOSQP( - l::AbstractVector{R}, A::AbstractMatrix{R}, u::AbstractVector{R} -) where R = - IndPolyhedralOSQP{R}(l, A, u) - IndPolyhedralOSQP( l::AbstractVector{R}, A::AbstractMatrix{R}, u::AbstractVector{R}, xmin::AbstractVector{R}, xmax::AbstractVector{R} @@ -65,8 +61,10 @@ end function prox!(y, f::IndPolyhedralOSQP, x, gamma) R = eltype(x) - OSQP.update!(f.mod; q=-x) - results = OSQP.solve!(f.mod) + results = Base.invokelatest(Base.require(@__MODULE__, :OSQP)) do OSQP + OSQP.update!(f.mod; q=-x) + OSQP.solve!(f.mod) + end y .= results.x return R(0) end diff --git a/test/runtests.jl b/test/runtests.jl index 04474040..66315cd3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -114,7 +114,8 @@ function predicates_test(f) end @testset "Aqua" begin - Aqua.test_all(ProximalOperators; ambiguities=false) + Aqua.test_all(ProximalOperators; ambiguities=false, stale_deps=false, persistent_tasks=false) + Aqua.test_stale_deps(ProximalOperators, ignore=[:OSQP]) end @testset "Documentation" begin