API Reference

Solver

The main entry point for solving conic optimization problems.

ConicIP.conicIPFunction

conicIP(Q, c, A, b, conedims, G, d; kktsolver = defaultkktsolver, optTol = 1e-6, DTB = 0.01, verbose = true, maxRefinementSteps = 3, maxIters = 100, cache_nestodd = false, infeasTol = 1e-7, infeasAbsTol = 1e-9, staticReg = 0.0, certFallback = true, certFallbackIters = 50, refinementThreshold = optTol/1e7)

Interior point solver for the system

minimize    ½yᵀQy - cᵀy
s.t         Ay >= b
            Gy  = d

c, b, d are vectors (or any AbstractVector)

cone_dims is an array of tuples (Cone Type, Dimension)

e.g. [("R",2),("Q",4)] means
(y₁, y₂)          in  R+
(y₃, y₄, y₅, y₆)  in  Q

SDP Cones are NOT supported and purely experimental at this point.

Returns a Solution whose status is one of

  • :Optimalmax(rDu, rPr, rCp, rEq) < optTol.
  • :Infeasible / :Unbounded — a ray passed a screen and was accepted by the corresponding validator; has_certificate is then true.
  • :AlmostInfeasible / :AlmostUnbounded — set only at loop exhaustion, when the best iterate carries a ray that validates at 100*infeasTol but not at infeasTol. The best iterate is retained.
  • :Abandoned — iteration limit reached with no verdict.
  • :Error — nonfinite residuals, or a KKT factorization failure (the reason is recorded in sol.message). Rank-deficient G handed directly to conicIP typically lands here; use preprocess_conicIP to trim redundant rows first. staticReg regularizes only the Q block of the KKT system and cannot repair a rank-deficient G.

Structurally degenerate inputs are handled exactly before any factorization: an all-zero row of G is deflated (dᵢ = 0) or answered with a certified :Infeasible (dᵢ ≠ 0), and a variable absent from Q, A, and G is deflated (cⱼ = 0) or answered with a certified :Unbounded (cⱼ ≠ 0).

Selected keyword arguments:

  • infeasTol — infeasibility-certificate tolerance, decoupled from optTol.
  • infeasAbsTol — absolute tolerance for certificate validation.
  • staticReg — static KKT regularization scale; 0 (default) disables it. preprocess_conicIP enables it when it detects rank deficiency.
  • certFallback — enable fallback certificate solve on stall.

The parameter solve3x3gen allows the passing of a custom solver for the KKT System, as follows

julia> L = solve3x3gen(F,F⁻ᵀ,Q,A,G)

Then this

julia> (a,b,c) = L(y,w,v)

solves the system
┌             ┐ ┌   ┐   ┌   ┐
│ Q   G'  -A' │ │ a │ = │ y │
│ G           │ │ b │   │ w │
│ A       FᵀF │ │ c │   │ v │
└             ┘ └   ┘   └   ┘

We can also wrap a 2x2 solver using pivot3gen(solve2x2gen) The 2x2 solves the system

julia> L = solve2x2gen(F,F⁻ᵀ,Q,A,G)

Then this

julia> (a,b) = L(y,w)

solves the system

┌                     ┐ ┌   ┐   ┌   ┐
│ Q + Aᵀinv(FᵀF)A  G' │ │ a │ = │ y │
│ G                   │ │ b │   │ w │
└                     ┘ └   ┘   └   ┘
source
ConicIP.preprocess_conicIPFunction

ConicIP with preprocessing to ensure the following rank constraints

Primal equailty constraints : Gx = d Rank condition : rank(G) = size(G,1)

Dual equality constraints : [ Q A' G'] = c Rank condition : rank([Q A' G']) = size(Q,1)

Inconsistent data is reported with a certificate whenever one can be constructed and verified against the original problem data:

  • Gy = d inconsistent → :Infeasible with a Farkas ray (w,v)
  • c ∉ range([Q Aᵀ Gᵀ]):Unbounded with a recession ray y

Rank deficiency that is not an inconsistency is handled by opting into conicIP's static KKT regularization rather than by perturbing Q.

source

Solution

The solver returns a Solution struct containing primal/dual variables, status, and convergence information.

ConicIP.SolutionType
Solution

Return type of conicIP and preprocess_conicIP.

Fields

  • y::Vector{Float64} – primal variables
  • w::Vector{Float64} – dual variables for equality constraints (Gy = d)
  • v::Vector{Float64} – dual variables for inequality constraints (Ay ≥_K b)
  • s::Vector{Float64} – cone slack variables (Ay - s = b, s ∈ K)
  • status::Symbol:Optimal, :Infeasible, :Unbounded, :AlmostInfeasible, :AlmostUnbounded, :Abandoned, or :Error
  • Iter::Integer – number of interior-point iterations
  • Mu::Real – final complementarity gap parameter
  • prFeas::Real – primal feasibility residual
  • duFeas::Real – dual feasibility residual
  • muFeas::Real – complementarity residual
  • pobj::Real – primal objective value
  • dobj::Real – dual objective value
  • has_certificate::Bool – the returned vectors carry a verified ray certifying infeasibility or unboundedness (see the table below)

Field conventions by status

statusywvspobj/dobjhas_certificate
:Optimalsolutiondual (eq)dual (ineq), ∈ Kslack, ∈ Krealfalse
:Infeasible with rayall NaNray ray ∈ Kall NaNNaNtrue
:Unbounded with rayray ȳall NaNall NaNA*ȳNaNtrue
:Infeasible/:Unbounded without rayall NaNall NaNall NaNall NaNNaNfalse
:Abandoned, :AlmostInfeasible, :AlmostUnbounded, :Errorbest iteratebest iteratebest iteratebest iteratebest iteratefalse

The infeasibility ray is normalized so that dᵀw̄ - bᵀv̄ = -1 with Gᵀw̄ - Aᵀv̄ ≈ 0; the unboundedness ray is normalized so that cᵀȳ = +1 with Qȳ ≈ 0, Gȳ ≈ 0 and Aȳ ∈ K. See validate_infeasibility_certificate and validate_unboundedness_certificate.

A 12-argument constructor is provided which defaults has_certificate to false.

source

Key fields:

FieldTypeDescription
yMatrixPrimal variables
wMatrixDual variables for equality constraints (Gy = d)
vMatrixDual variables for inequality constraints (Ay ≥ b)
statusSymbolTermination status (see below)
pobjRealPrimal objective value
dobjRealDual objective value
prFeasRealPrimal feasibility residual
duFeasRealDual feasibility residual
muFeasRealComplementarity residual
IterIntegerNumber of iterations
MuRealFinal barrier parameter

Status values:

StatusMeaning
:OptimalConverged to an optimal solution
:InfeasibleProblem is primal infeasible (validated Farkas ray when has_certificate)
:UnboundedProblem is dual infeasible / primal unbounded (validated recession ray when has_certificate)
:AlmostInfeasibleIteration limit with a near-validating infeasibility candidate (no certificate)
:AlmostUnboundedIteration limit with a near-validating unboundedness candidate (no certificate)
:AbandonedSolver stalled (step size too small or numerical issues)
:ErrorSolver encountered an error

See Troubleshooting Solver Output in the Mathematical Background for guidance on non-optimal statuses.

Certificate Validation

Infeasibility and unboundedness claims are backed by rays validated against the original problem data. See The Certificate Pipeline in the Mathematical Background.

ConicIP.CertificateCheckType
CertificateCheck

Verdict returned by the certificate validators.

Fields

  • valid::Bool – all checks passed
  • farkas_residual::Float64 – ‖·‖_∞ of the linear residual of the ray
  • separation::Float64 – the (pre-normalization) separation value; must be > 0
  • cone_margin::Float64 – blockwise minimum cone margin of the ray (≥ 0 if in K)
  • finite::Bool – the candidate ray had only finite entries
source
ConicIP.cone_marginFunction
cone_margin(x, cone_dims)

Blockwise minimum margin of x with respect to the cone K described by cone_dims. Nonnegative iff x ∈ K; the magnitude measures the distance to the boundary (violation depth when negative).

Per block:

"R"  minimum(x[I])
"Q"  x[I][1] - ‖x[I][2:end]‖
"S"  eigmin(Symmetric(mat(x[I])))

Returns +Inf when there are no blocks.

source
ConicIP.validate_infeasibility_certificateFunction
validate_infeasibility_certificate(Q, c, A, b, cone_dims, G, d, w, v;
                                   abstol, reltol)

Validate (w,v) as a Farkas ray proving primal infeasibility of {y : Ay ≥_K b, Gy = d}. A valid ray satisfies

Gᵀw̄ - Aᵀv̄ ≈ 0,    v̄ ∈ K,    dᵀw̄ - bᵀv̄ = -1

Returns (check::CertificateCheck, w̄, v̄) with the ray normalized so that dᵀw̄ - bᵀv̄ = -1. If the separation -(dᵀw - bᵀv) is nonpositive, or the candidate has nonfinite entries, the verdict is invalid and the candidates are returned unchanged (no normalization).

source
ConicIP.validate_unboundedness_certificateFunction
validate_unboundedness_certificate(Q, c, A, b, cone_dims, G, d, y;
                                   abstol, reltol)

Validate y as a recession ray proving ½yᵀQy - cᵀy is unbounded below over the feasible set. A valid ray satisfies

Qȳ ≈ 0,    Gȳ ≈ 0,    Aȳ ∈ K,    cᵀȳ = +1

so that the objective decreases without bound along ȳ. Returns (check::CertificateCheck, ȳ) with the ray normalized so that cᵀȳ = +1. If the separation cᵀy is nonpositive, or the candidate has nonfinite entries, the verdict is invalid and the candidate is returned unchanged.

source

When the iterate loop exhausts with evidence of a ray, the solver can recover a certificate by solving an auxiliary min-norm QP:

ConicIP.fallback_infeasibility_rayFunction
fallback_infeasibility_ray(Q, c, A, b, cone_dims, G, d;
                           kktsolver = default_kktsolver, maxIters = 50)

Solve the minimum-norm Farkas auxiliary QP and return a candidate infeasibility ray (w, v), or nothing if the auxiliary solve does not reach :Optimal (which includes the common case that the original problem is feasible, making the auxiliary problem infeasible).

The returned pair is not validated and not normalized — pass it to validate_infeasibility_certificate.

source
ConicIP.fallback_unbounded_rayFunction
fallback_unbounded_ray(Q, c, A, b, cone_dims, G, d;
                       kktsolver = default_kktsolver, maxIters = 50)

Solve the minimum-norm recession auxiliary QP and return a candidate unboundedness ray y, or nothing if the auxiliary solve does not reach :Optimal (in particular when no recession ray exists).

The Qy = 0 rows are omitted when Q is identically zero, which keeps the auxiliary system at its smallest for the LP case. The returned ray is not validated and not normalized — pass it to validate_unboundedness_certificate.

source

JuMP / MathOptInterface

ConicIP.OptimizerType
Optimizer(; kwargs...)

MathOptInterface optimizer wrapping the ConicIP interior-point solver. Use as a JuMP solver via Model(ConicIP.Optimizer).

Options

Settable as constructor keywords or through MOI.RawOptimizerAttribute / JuMP's set_attribute:

  • verbose::Bool – print solver iterations (default: false)
  • optTol::Float64 – optimality tolerance (default: 1e-6)
  • maxIters::Int – maximum iterations (default: 100)
  • infeasTol::Float64 – infeasibility/unboundedness certificate tolerance (default: 1e-7)
  • kktsolver"auto" (default; picks by cone mix and sparsity via choose_kktsolver), "qr", "sparse", "2x2", or a solver function
  • preprocess::Bool – remove redundant equality rows via preprocess_conicIP before solving (default: true)
  • plus infeasAbsTol, DTB, maxRefinementSteps, staticReg, certFallback, certFallbackIters, cache_nestodd — forwarded to conicIP

MOI.Silent is supported and overrides verbose.

Supported Constraints

  • Vector: Zeros, Nonnegatives, Nonpositives, SecondOrderCone, PositiveSemidefiniteConeTriangle
  • Scalar: EqualTo, GreaterThan, LessThan
source

KKT Solver Functions

Three built-in KKT solvers are provided, and the default picks among them automatically per problem. See the KKT Solvers guide for detailed usage and custom solver development.

ConicIP.choose_kktsolverFunction
choose_kktsolver(Q, A, G, cone_dims; nnz_per_col_max = 10, size_min = 1000)

Pick a KKT solver from the problem's cone mix, size, and sparsity (issue #10). Returns one of the solver constructors, chosen by:

  1. any SDP cone ⇒ kktsolver_qr — the dense double-QR method is the numerically robust choice for the dense SDP scaling blocks;
  2. n + m + p < size_minkktsolver_qr — dense factorization wins at small sizes and matches the historical default exactly;
  3. average structural nonzeros per column of [Q; A; G] above nnz_per_col_maxkktsolver_qr — sparse-typed but dense-ish data (e.g. many small SOCs with a 10%-dense A) factors faster densely;
  4. otherwise ⇒ kktsolver_sparse.

The decision is by structural nonzero counts, never by storage type.

source
ConicIP.kktsolver_qrFunction

Solves the 3x3 system

┌             ┐ ┌    ┐   ┌   ┐
│ Q   G'  -A' │ │ y' │ = │ y │
│ G           │ │ w' │   │ w │
│ A       FᵀF │ │ v' │   │ v │
└             ┘ └    ┘   └   ┘

by the double QR method described in CVXOPT http://www.seas.ucla.edu/~vandenbe/publications/coneprog.pdf section 10.2

source
ConicIP.kktsolver_sparseFunction

Solves the 3x3 system

┌             ┐ ┌    ┐   ┌   ┐
│ Q   G'  -A' │ │ y' │ = │ y │
│ G           │ │ w' │   │ w │
│ A       FᵀF │ │ v' │   │ v │
└             ┘ └    ┘   └   ┘

By lifting the large diagonal plus rank 3 blocks of FᵀF

Intelligently chooses between solve3x3gensparselift and solve3x3gensparsedense by approximating the number of non-zeros in both and choosing the form with more sparsity. The former is better for large second order cones, while the latter is better if the constraints are the product of many small cones.

source
ConicIP.kktsolver_2x2Function

Solves the 2x2 system

┌                   ┐ ┌    ┐   ┌   ┐
│ Q + A'F⁻¹F⁻ᵀA  G' │ │ y' │ = │ y │
│ G                 │ │ w' │   │ w │
└                   ┘ └    ┘   └   ┘
source
ConicIP.pivotFunction
pivot(kktsolver_2x2)

Wrap a 2-by-2 KKT solver into a 3-by-3 solver by pivoting on the third component. The inner solver handles the Schur complement system; pivot reconstructs the full solution.

See also conicIP for the KKT solver interface specification.

source

Block Diagonal Matrices

The Nesterov-Todd scaling matrix is represented as a block diagonal matrix where each block corresponds to a cone in the cone specification.

ConicIP.BlockType
Block(size::Int)
Block(Blk::Vector)

Block diagonal matrix type. Each diagonal block can be a different matrix type (Diagonal, SymWoodbury, VecCongurance, or dense Matrix).

Used internally to represent the Nesterov-Todd scaling matrix, where each block corresponds to a cone in the cone specification.

Supports arithmetic (*, +, -, inv, adjoint, ^), conversion to sparse and Matrix, and block-wise function application via broadcastf.

Indexing

  • B[i] returns the i-th diagonal block
  • B[i] = M sets the i-th diagonal block
source
ConicIP.block_idxFunction
block_idx(A::Block)

Return a vector of UnitRange{Int} giving the row/column index ranges for each diagonal block of A.

source
ConicIP.broadcastfFunction
broadcastf(op, A::Block)
broadcastf(op, A::Block, B::Block)
broadcastf(op, A::Block, x::Union{Vector,Matrix})

Apply function op block-wise to the diagonal blocks of A (and optionally B or the corresponding segments of x).

source

Utilities

ConicIP.IdFunction
Id(n)

Create an n-by-n identity matrix as Diagonal(ones(n)).

source
ConicIP.VecConguranceType
VecCongurance(R)

Linear operator representing a congruence transform in vectorized form. The action W * x computes vecm(R' * mat(x) * R).

Used internally as the Nesterov-Todd scaling matrix for semidefinite cones.

source
ConicIP.matFunction
mat(x)

Convert a vectorized symmetric matrix (scaled lower-triangular form) back to a full symmetric matrix. Inverse of vecm.

source
ConicIP.mat!Function
mat!(Z, x)

In-place mat: fill the symmetric matrix Z from the vectorized form x. Z must be ord(x) square.

source
ConicIP.vecmFunction
vecm(Z)

Vectorize a symmetric matrix Z into scaled lower-triangular form. Off-diagonal entries are scaled by √2 so that dot(vecm(X), vecm(Y)) == tr(X*Y). Inverse of mat.

source
ConicIP.vecm!Function
vecm!(x, Z)

In-place vecm: write the vectorized form of the symmetric matrix Z into x, which must have length n(n+1)/2.

source
ConicIP.imcolsFunction

imcols(A, b, ϵ = 1e-8)

Removes redundant inequalities in a system of equations

Ax = b

and checks if the equations are consistent. Returns (R, consistent) where R are the indices of a maximal independent row set.

source

Internal

These functions are implementation details and not part of the public API.

ConicIP.inv_adjoint!Function
inv_adjoint!(dest::Block, src::Block)

Compute adjoint(inv(src)) block-wise, reusing the dest Block shell. Avoids allocating two intermediate Blocks for inv(F)'.

source
ConicIP.pivotgenFunction

Wrapper around solve2xegen to solve 3x3 systems by pivoting on the third component.

source
ConicIP._psd_moi_vecm_infoFunction

Return (perm, is_offdiag) where perm[moi_k] is the vecm position for MOI triangle position moi_k, and is_offdiag[moi_k] is true when position moi_k corresponds to an off-diagonal entry.

source
ConicIP._psd_vecm_to_moiFunction

Convert a vector from vecm order (solver convention) to MOI triangle order, dividing off-diagonal entries by √2.

source
ConicIP._psd_scale_input!Function

Reorder rows of Ai and entries of bi from MOI triangle order to vecm order, and scale off-diagonal rows by √2.

source