API reference

Top-level package

sedumipy: a MATLAB/Octave-free port of SeDuMi (SDP/SOCP interior-point solver), in pure Python (NumPy/SciPy) plus a small standalone C kernel library (libsedumi.so, via ctypes – see _native.py).

import sedumipy
x, y, info = sedumipy.sedumi(A, b, c, K)

is equivalent to original SeDuMi’s own [x,y,info] = sedumi(A,b,c,K). See sedumi.py’s own docstring for the exact scope (LP + second-order-cone + PSD cones) and CONTRIBUTING.md for the full project status.

sedumipy.sedumi(A, b, c, K: dict, pars: dict | None = None, **pars_kwargs)[source]

x, y, info = sedumi(A, b, c, K, pars=None, **pars_kwargs)

pars_kwargs lets individual options be overridden as keyword arguments (e.g. sedumi(A, b, c, K, eps=1e-9)) instead of building a pars dict by hand; entries in pars_kwargs win over the same key in pars when both are given. See checkpars.py for the full list of recognized pars fields and their defaults.

sedumipy.read_mat(path)[source]

(A, b, c, K, pars) = read_mat(path): loads a SeDuMi-style problem .mat file. A is returned exactly as stored (sparse or dense, whichever orientation the file used) – sedumi() accepts either. pars is {} if the file has no “pars” field (SeDuMi problem files saved from real examples, like vendor/sedumi-upstream/examples/*.mat, normally don’t).

A path (str/os.PathLike) ending in “.gz” is transparently gunzipped first – public SeDuMi-format problem collections such as DIMACS’s examples/dimacs/data//.mat.gz ship gzip-compressed, and scipy.io.loadmat’s own gzip auto-detection does not reliably trigger on every real .mat.gz file (confirmed against DIMACS’s own data: it raises “Unknown mat file type” on some of them despite the file being a perfectly valid gzip stream). Passing an already-open file-like object (e.g. from gzip.open() directly) is unaffected – scipy.io.loadmat has always accepted those.

sedumipy.write_solution_mat(path, x, y, info) → None[source]

write_solution_mat(path, x, y, info): saves sedumi()’s own return values (x, y, info) as a MATLAB struct-compatible .mat file, the layout original SeDuMi’s own examples/*.mat solution dumps use (a plain “x”/”y” vector plus an “info” struct).

sedumipy.read_sdpa(fname)[source]

(At, b, c, K) = read_sdpa(fname): see module docstring. fname is a path to an uncompressed SDPA sparse (.dat-s) file.

sedumipy.write_sdpa(fname, At, b, c, K, comment='sedumipy') → None[source]

write_sdpa(fname, At, b, c, K): writes (At, b, c, K) out as a sparse SDPA (.dat-s) file – the inverse of read_sdpa. LP-only (K.l) problems are written as a single diagonal block; K.q/K.r (SDPA has no second-order-cone block type) are rejected. Only the upper triangle of each PSD block is written, matching common SDPA sparse-format practice (see module docstring).

Solver driver

sedumipy.sedumi.sedumi(A, b, c, K: dict, pars: dict | None = None, **pars_kwargs)[source]

x, y, info = sedumi(A, b, c, K, pars=None, **pars_kwargs)

pars_kwargs lets individual options be overridden as keyword arguments (e.g. sedumi(A, b, c, K, eps=1e-9)) instead of building a pars dict by hand; entries in pars_kwargs win over the same key in pars when both are given. See checkpars.py for the full list of recognized pars fields and their defaults.

File I/O

Phase 4: .mat I/O for SeDuMi-style problem/solution files.

Not a port of any particular upstream .m file – original SeDuMi problems and solutions are just plain MATLAB structs/arrays saved with MATLAB’s own save, so there is no “reference .m implementation” to port here, unlike the rest of this package. This module exists so callers don’t have to hand-write scipy.io.loadmat/savemat plus the K-struct field unwrapping this port’s own tests already do ad hoc (see e.g. test_sedumi.py’s _load_K); it follows the same conventions those tests settled on.

Field-name conventions matched here (both are common in the wild, e.g. vendor/sedumi-upstream/examples/*.mat all use “At”):

  • the constraint matrix may be stored as “A” or “At” (SeDuMi’s own sedumi() accepts either orientation and disambiguates via shape – see pretransfo.py’s own (At,K) size check – so this module does too, simply forwarding whichever one it finds along with its name);

  • K’s fields arrive as a MATLAB struct (a (1,1) structured array once loaded via scipy.io.loadmat); scalar fields (“f”, “l”) are unwrapped to a plain Python int, everything else (K.q, K.r, K.s, K.xcomplex, …) to a flat NumPy array, exactly like checkpars.py/pretransfo.py already expect;

  • pars, if present, is unwrapped the same way test_sedumi.py’s _load_pars does (scalar-only fields, one MATLAB scalar per pars option – true of every pars field SeDuMi itself defines).

sedumipy.matio.read_mat(path)[source]

(A, b, c, K, pars) = read_mat(path): loads a SeDuMi-style problem .mat file. A is returned exactly as stored (sparse or dense, whichever orientation the file used) – sedumi() accepts either. pars is {} if the file has no “pars” field (SeDuMi problem files saved from real examples, like vendor/sedumi-upstream/examples/*.mat, normally don’t).

A path (str/os.PathLike) ending in “.gz” is transparently gunzipped first – public SeDuMi-format problem collections such as DIMACS’s examples/dimacs/data//.mat.gz ship gzip-compressed, and scipy.io.loadmat’s own gzip auto-detection does not reliably trigger on every real .mat.gz file (confirmed against DIMACS’s own data: it raises “Unknown mat file type” on some of them despite the file being a perfectly valid gzip stream). Passing an already-open file-like object (e.g. from gzip.open() directly) is unaffected – scipy.io.loadmat has always accepted those.

sedumipy.matio.write_solution_mat(path, x, y, info) → None[source]

write_solution_mat(path, x, y, info): saves sedumi()’s own return values (x, y, info) as a MATLAB struct-compatible .mat file, the layout original SeDuMi’s own examples/*.mat solution dumps use (a plain “x”/”y” vector plus an “info” struct).

Port of conversion/fromsdpa.m: reads an SDP problem from a sparse SDPA-formatted file (the format SDPLIB and most other public SDP benchmark collections use) into SeDuMi’s own (At, b, c, K) form.

At, b, c, K = read_sdpa("arch0.dat-s")
x, y, info = sedumipy.sedumi(At, b, c, K)

SDPA sparse format, in order: mDIM (m, the number of constraints), nBLOCK (the number of blocks), a line of nBLOCK block sizes (negative size n means n diagonal/LP variables, not a PSD block), the b vector (m entries), then one line per nonzero coefficient as “<matno> <blkno> <i> <j> <value>” – matno=0 is the cost matrix C, matno=1..m is constraint matrix A_matno; only the upper or lower triangle of each symmetric block needs to be given (both fromsdpa.m and this port mirror whichever triangle is present across the diagonal). SDPA’s own convention is to MAXIMIZE trace(C,X); SeDuMi minimizes, so C’s sign is flipped on the way in (and back on the way out, in write_sdpa).

write_sdpa (the inverse direction) is new functionality, not a port – original SeDuMi’s own conversion/writesdp.m instead writes the unrelated SDPpack format, not SDPA sparse. It’s the direct inverse of the reading convention above, verified by round-tripping through read_sdpa itself (tests/test_sdpa.py) as well as against a real Octave fromsdpa.m oracle.

sedumipy.sdpa.read_sdpa(fname)[source]

(At, b, c, K) = read_sdpa(fname): see module docstring. fname is a path to an uncompressed SDPA sparse (.dat-s) file.

sedumipy.sdpa.write_sdpa(fname, At, b, c, K, comment='sedumipy') → None[source]

write_sdpa(fname, At, b, c, K): writes (At, b, c, K) out as a sparse SDPA (.dat-s) file – the inverse of read_sdpa. LP-only (K.l) problems are written as a single diagonal block; K.q/K.r (SDPA has no second-order-cone block type) are rejected. Only the upper triangle of each PSD block is written, matching common SDPA sparse-format practice (see module docstring).

cvxpy interface

Solver options

Port of checkpars.m: fills in defaults for missing fields in the pars options dict. Pure dict manipulation, no cone math or C kernels – a direct, literal translation.

sedumipy.checkpars.checkpars(pars: dict | None = None) → dict[source]

pars = checkpars(pars): fills in defaults for missing fields in pars. Does not mutate the input dict (returns a new one), unlike checkpars.m which works on a copy-on-write MATLAB struct anyway.

Internals

Everything documented on the Internals page is a direct, module-per-.m-file port of SeDuMi’s own internals (interior-point iteration, cone math, symbolic/numeric factorization, …) and is not a stable public API – it is there for contributors reading or extending the port, not for end users. See Contributing for how these modules fit together.