@dpo Thanks for the pointer TRON. Here’s a quick comparison between TRON (projected second-order descent) vs ECOS (primal-dual interior). The ECOS experiment uses a small custom wrapper around the ECOS.jl solver to translate the box-constrained solver into the second-order cone program
minimize t subj to Ax+r=b, (r,t) in SOC, 0 ≤ x ≤ u.
Here’s the setup:
using JSOSolvers, NLPModels
using ECOSProblems # https://github.com/mpf/ECOSProblems.jl
using BenchmarkTools
using LinearAlgebra
global_logger(NullLogger())
m, n = 10000, 10
A = randn(m, n); x = randn(n); b = A*x;
bl = zeros(n); bu = ones(n)
And here are the benchmarks, which shows a clear advantage to TRON:
julia> @benchmark ECOSProblems.lsbox($A, $b, $bu, verbose=0)
BenchmarkTools.Trial:
memory estimate: 11.10 MiB
allocs estimate: 495
--------------
minimum time: 250.028 ms (0.00% GC)
median time: 253.803 ms (0.00% GC)
mean time: 254.501 ms (0.43% GC)
maximum time: 260.866 ms (1.62% GC)
--------------
samples: 20
evals/sample: 1
julia> @benchmark tron(LLSModel($A, $b, lvar=$bl, uvar=$bu))
BenchmarkTools.Trial:
memory estimate: 6.73 MiB
allocs estimate: 1758
--------------
minimum time: 4.248 ms (0.00% GC)
median time: 5.061 ms (0.00% GC)
mean time: 5.958 ms (15.21% GC)
maximum time: 12.798 ms (53.19% GC)
--------------
samples: 840
The solutions are close:
julia> xecos = ECOSProblems.lsbox(A, b, bu, verbose=0)[1];
julia> xtron = (tron(LLSModel(A, b, lvar=bl, uvar=bu))).solution;
julia> println(norm(xecos-xtron,Inf))
1.2407727578850336e-6
As @dpo suggested, further improvements are likely possible with some tweaks to the TRON interface.
However, the ECOS experiment probably could be significantly improved by taking advantage of the very few number of columns in A
:
- factor A = QR
- apply ECOS to the equivalent problem
minimize t - <A'b,x> subj to (||Rx||,t) in rotated SOC, 0 ≤ x ≤ u,
which has a much smaller dual space.