On this page:
2.1 The problem SCS solves
2.2 Cones
2.2.1 Box cones
2.2.2 Semidefinite cones
2.3 Building matrices and vectors
2.4 Modeling cookbook
2.4.1 Laying out A in cone-ordered row-blocks
2.4.2 Bounds and the absolute-value trick
2.4.3 Norms via the second-order cone
2.4.4 The epigraph trick for nonlinear objectives
2.4.5 Box-cone layout
2.4.6 Symmetric matrices and the svec scaling
2.5 Settings
2.6 Solving and reading results
2.6.1 Direct vs. indirect solver
2.6.2 Warm starting and re-solving
2.6.3 Troubleshooting and status
9.2.0.5

2 Guide🔗ℹ

2.1 The problem SCS solves🔗ℹ

SCS solves the convex quadratic cone program

minimize ½ xᵀPx + cᵀx
subject to Ax + s = b, sK

over the variable x ∈ ℝⁿ and slack s ∈ ℝᵐ, where P is symmetric positive semidefinite, A is m×n, and K is a closed convex cone. SCS simultaneously produces a solution to the dual problem; the dual variable is returned as scs-result-y. See the upstream algorithm notes for the precise primal/dual pair.

In Racket you supply A and the optional P as compressed-sparse-column matrices (scs:matrix / scs:sparse-matrix), b and c as vectors or lists, and K as a make-cone value, then call solve.

2.2 Cones🔗ℹ

The cone K is a Cartesian product of primitive cones. The rows of A (and the entries of b and s) must appear in this exact order, which is also the order of the make-cone keywords:

  • the zero cone #:zero equality rows (s = 0).

  • the positive orthant #:positive inequality rows (s ≥ 0).

  • the box cone #:box-lower / #:box-upper; see Box cones.

  • second-order (Lorentz) cones — #:soc, a list of block sizes; each block (t, u) satisfies ‖u‖₂ ≤ t.

  • positive semidefinite cones — #:psd, a list of matrix dimensions; see Semidefinite cones.

  • exponential cones — #:exp-primal / #:exp-dual counts of triples; the primal cone is the closure of {(x,y,z) : y·e^(x/y) ≤ z, y > 0}.

  • power cones — #:power, a list of parameters in [-1, 1] (negative values select the dual power cone).

This mirrors the cone ordering documented in the SCS cones reference.

2.2.1 Box cones🔗ℹ

The box cone is {(t, r) : t·l ≤ r ≤ t·u} with a leading scale variable t. To impose plain bounds l ≤ y ≤ u, arrange A and b so the first box row’s slack is a constant 1 (a row of zeros in A with the matching b entry equal to 1) and the remaining rows carry y. make-cone takes the bounds with #:box-lower and #:box-upper; their length is the number of box-constrained entries, and SCS’s bsize is that length plus one. Model predictive control is a worked example.

2.2.2 Semidefinite cones🔗ℹ

For a k×k symmetric matrix, the PSD cone slack is the lower triangle stacked column-wise with the off-diagonal entries scaled by √2; the block length is k(k+1)/2. So a 2×2 matrix [[a b] [b c]] is represented by (a, √2·b, c). #:psd takes the list of k values. See the cones reference and Semidefinite program.

2.3 Building matrices and vectors🔗ℹ

scs:matrix builds a matrix from a dense, row-major sequence of values:

(scs:matrix 3 2     ; 3 rows, 2 columns
            -1 1
             1 0
             0 1)

It also accepts a single list of rows, inferring the dimensions, which reads like a 2D literal:

(scs:matrix '((-1 1)
              ( 1 0)
              ( 0 1)))

scs:sparse-matrix builds one from explicit (row col value) triples, which is convenient for a quadratic P (supply only the upper triangle):

(scs:sparse-matrix 2 2
                   '(0 0 3)
                   '(0 1 -1)
                   '(1 1 2))

For data already in a scipy-style coordinate form, scs:coo-matrix takes three parallel sequences (rows cols vals) (vectors or lists), matching scipy.sparse.coo_matrix((data, (row, col))):

(scs:coo-matrix 2 2 '(0 0 1) '(0 1 1) '(3 -1 2))

All three return a CSC matrix suitable for #:A or #:P. The right-hand side b and objective c are passed to solve as plain vectors or lists.

2.4 Modeling cookbook🔗ℹ

Getting a problem into SCS’s standard form Ax + s = b, s ∈ K comes down to a handful of recurring moves. Each is used by one or more of the worked Examples.

2.4.1 Laying out A in cone-ordered row-blocks🔗ℹ

The rows of A (and the entries of b and s) must appear in the Cones order: zero rows, then positive, box, second-order, semidefinite, exponential, and power. Build A as a stack of row-blocks, one per primitive cone, in that order, and make make-cone’s keywords describe the same blocks. A slack lands in a given cone exactly when s = b − Ax restricted to that block satisfies the membership condition; a common idiom is an A = −I block with b = 0, which sets s = x on those rows so the variables themselves are constrained (Second-order cone, Exponential cone, Power cone).

2.4.2 Bounds and the absolute-value trick🔗ℹ

A two-sided bound l ≤ aᵀx ≤ u is two positive-orthant rows, aᵀx ≤ u and −aᵀx ≤ −l. The absolute-value trick models |aᵀx|: introduce an auxiliary t, add the two rows aᵀx − t ≤ 0 and −aᵀx − t ≤ 0 (so t ≥ |aᵀx|), and use t in the objective. This is how L1 penalties become cone programs in Lasso along a regularization path and Elastic net regression.

2.4.3 Norms via the second-order cone🔗ℹ

A Euclidean-norm bound ‖u‖₂ ≤ t is one second-order cone block over (t, u) (Second-order cone). To minimize a norm, bound it by a fresh variable t with ‖u‖₂ ≤ t and minimize t.

2.4.4 The epigraph trick for nonlinear objectives🔗ℹ

To minimize a convex function f(x) that is not already linear or quadratic, minimize a new variable t subject to the epigraph trick constraint f(x) ≤ t, then express that constraint with a cone. For x log x the epigraph is exponential-cone membership, which is how Maximum entropy maximizes entropy.

2.4.5 Box-cone layout🔗ℹ

The box cone carries a leading scale variable. To impose plain bounds l ≤ y ≤ u, pin that scale to 1 with a constant row (zeros in A, a 1 in b) and put y on the remaining rows; see Box cones and the worked Model predictive control.

2.4.6 Symmetric matrices and the svec scaling🔗ℹ

A semidefinite constraint X ⪰ 0 is one #:psd block whose slack is the √2-scaled lower-triangular vectorization of X; see Semidefinite cones and Semidefinite program.

2.5 Settings🔗ℹ

make-settings produces a settings value populated with SCS’s defaults, overridden by the keywords you pass. Unlike the C library, verbose? defaults to #f (libraries should be quiet). The most common knobs are the convergence tolerances #:eps-abs and #:eps-rel (SCS default 0.0001) and #:max-iters. See the upstream settings reference for the full list and defaults. Passing no #:settings to solve uses the defaults.

2.6 Solving and reading results🔗ℹ

solve returns an scs-result. Check solved? (true when the exit flag is 1, SCS_SOLVED); scs-result-status is the human-readable status string and scs-result-status-val the integer exit flag. The exit flags follow the SCS exit-flag reference: 1 solved, 2 solved-inaccurate, -1 unbounded, -2 infeasible, and -3 through -7 for the indeterminate/failed/interrupted and inaccurate-certificate cases.

The primal solution is scs-result-x, the dual is scs-result-y, and the slack is scs-result-s; scs-result-pobj and scs-result-dobj are the primal and dual objectives.

2.6.1 Direct vs. indirect solver🔗ℹ

By default solve uses the direct linear-system solver. Pass #:indirect? #t to use the indirect (conjugate-gradient) solver, which can scale better on very large sparse problems.

2.6.2 Warm starting and re-solving🔗ℹ

When a sequence of problems differs only in b or c, build a solver once with make-solver and re-solve it instead of rebuilding from scratch. solver-solve! returns an scs-result; it cold-starts the first time and warm-starts (reusing the previous iterate) on every call after that. solver-update! swaps in a new b and/or c (the matrices and cone are fixed):

(define s (make-solver #:A A #:b b #:c c #:cone cone))
(solver-solve! s)              ; cold start
(solver-update! s #:b b2)      ; only b changes
(solver-solve! s)              ; warm-started re-solve

solve is just make-solver followed by a single solver-solve!. Warm starting and re-solving, Lasso along a regularization path, and Model predictive control show the pattern. For full manual control over the workspace and solution buffers, the scs/foreign layer exposes the underlying scs-init / scs-update / scs-solve.

2.6.3 Troubleshooting and status🔗ℹ

When solved? is false, the exit flag says why, and the result still carries useful information:

  • Infeasible (flag -2): no x satisfies the constraints. SCS returns a certificate of infeasibility in scs-result-y (a dual ray); scs-result-x is not meaningful.

  • Unbounded (flag -1): the objective can be driven to −∞ within the constraints. The certificate is a primal ray in scs-result-x.

  • Inaccurate (flags 2, -6, -7): SCS hit its iteration or time limit with the residuals only partially converged. The iterate is usually close; loosen #:eps-abs / #:eps-rel to accept it, or raise #:max-iters / #:time-limit-secs to push further.

  • Indeterminate / failed (flags -3 through -5): the problem could not be classified, or setup failed.

A few common modeling mistakes produce a spurious infeasible or unbounded result rather than an error:

  • Cone-order mismatch. The rows of A must follow the Cones order and match make-cone’s keyword counts exactly. A miscounted block silently re-interprets later rows.

  • A missing box scale row. The box cone needs its leading scale entry pinned (see Box cones); omitting it changes the feasible set.

  • Wrong PSD scaling. Off-diagonal entries of a semidefinite block must be √2-scaled (see Semidefinite cones).

To see SCS’s own iteration log while diagnosing, pass (make-settings #:verbose? #t).