Linear System Solver¶
At each iteration \(k\) SCS solves the following set of linear equations:
for a particular right-hand side \(z^k \in \mathbf{R}^{n+m}\) (the presence of the diagonal scaling \(\rho\) terms is explained in Non-identity DR Scaling). Note that the matrix does not change from iteration to iteration, which is a major advantage of this approach. Moreover, this system can be solved approximately so long as the errors satisfy a summability condition, which permits the use of approximate solvers that can scale to very large problems.
Available linear solvers¶
Each of the below linear solvers is included in their own binary. If linking against SCS directly, then to switch between them you must compile and link against the right binary. If using SCS via one of the interfaces then you can choose between the different linear solvers using the appropriate settings.
Sparse direct method¶
The direct method is the default linear system solver in SCS and factorizes the above matrix using a sparse permuted LDL factorization. Then it solves the linear system at each iteration using the cached factors. Since the linear system is quasidefinite we have strong existence guarantees about the factorization. It relies on the external AMD and QDLDL packages.
Sparse indirect method¶
The indirect method solves the above linear system approximately with a ‘matrix-free’ method. To do this it first reduces the system to solving
then solves the positive definite system using using conjugate gradients. Each iteration of
CG requires one multiply each of sparse matrices \(P, A, A^\top\). The
system is solved up to some tolerance, which is tuned to ensure that the overall
algorithm converges. The tolerance decays with iteration \(k\) like
\(O(1/k^\gamma)\) where \(\gamma > 1\) and is determined by the constant
CG_RATE
(defaults to \(1.5\)).
The indirect method has the advantage of not requiring an expensive factorization but typically is slower on a per-iteration basis. In most cases the factorization is relatively cheap so the direct method is the default, however for very large problems the indirect solver can be faster.
Sparse GPU indirect method¶
The above linear solvers all run on CPU. We also have support for a GPU version of the indirect solver, where the matrix multiplies are all performed on the GPU.
Implementing a new linear solver¶
In order to implement you own linear system solver, you need to implement the
struct ScsLinSysWork
that contains the workspace your solver requires,
and implement the functions in include/linsys.h
as detailed below.
See linsys
directory for examples.
-
typedef struct SCS_LIN_SYS_WORK ScsLinSysWork¶
Struct containing linear system workspace. Implemented by linear solver.
Functions
-
ScsLinSysWork *scs_init_lin_sys_work(const ScsMatrix *A, const ScsMatrix *P, scs_float *rho_y_vec, scs_float rho_x)¶
Initialize
ScsLinSysWork
structure and perform any necessary preprocessing.- Parameters
A – A data matrix.
P – P data matrix.
rho_y_vec –
rho_y > 0
diagonal entries.rho_x –
rho_x > 0
float.
- Returns
Linear system solver workspace.
-
void scs_free_lin_sys_work(ScsLinSysWork *w)¶
Frees
ScsLinSysWork
structure and associated allocated memory.- Parameters
w – Linear system private workspace.
-
scs_int scs_solve_lin_sys(ScsLinSysWork *w, scs_float *b, const scs_float *s, scs_float tol)¶
Solves the linear system required by SCS at each iteration:
\[\begin{split} \begin{bmatrix} (\rho_x I + P) & A^\top \\ A & -\mathrm{diag}(\rho_y) \\ \end{bmatrix} x = b \end{split}\]for
x
. Overwritesb
with result.- Parameters
w – Linear system private workspace.
b – Right hand side, contains solution at the end.
s – Contains warm-start (may be NULL).
tol – Tolerance required for the system solve.
- Returns
status < 0 indicates failure.
-
void scs_update_lin_sys_rho_y_vec(ScsLinSysWork *w, scs_float *rho_y_vec)¶
Update the linsys workspace when
rho_y_vec
is changed. For example, a direct method for solving the linear system might need to update the factorization of the matrix.- Parameters
w – Linear system private workspace.
rho_y_vec –
rho_y
diagonal entries.
-
const char *scs_get_lin_sys_method(void)¶
Name of the linear solver.
- Returns
name of method.