Skip to main content

primalsolver

Python bindings for PrimalSolver — a dependency-free convex optimization solver in C99 (LP / QP / SOCP / SDP / exp-power / MIP).

The package ships a pre-built shared library (libprimal.dylib / .so / .dll) inside the wheel and calls it through ctypes: no C toolchain is needed to install, and the whole public API is exposed.

Upstream C library: https://github.com/c-vision/Primal. This package treats its sources as read-only input and never modifies them.

from primalsolver import Model, BK, SOLSTA

with Model(maxcon=2, maxvar=2) as m:
    m.obj([0, 1], [-3.0, -2.0])           # min -3 x0 - 2 x1
    m.a_ij(0, 0, 1.0); m.a_ij(0, 1, 1.0)  # x0 +  x1 <= 4
    m.a_ij(1, 0, 1.0); m.a_ij(1, 1, 3.0)  # x0 + 3x1 <= 6
    m.con_bounds(0, BK.UP, up=4.0)
    m.con_bounds(1, BK.UP, up=6.0)
    m.var_bounds(0, BK.RA, 0.0, 3.0)      # 0 <= x0 <= 3
    m.var_bounds(1, BK.RA, 0.0, 3.0)
    r = m.solve()

assert r.solsta == SOLSTA.OPTIMAL
print(r.x, r.objective)                    # [3.0, 1.0] -11.0

Requirements

  • Python >= 3.8, no runtime dependencies other than the standard library.
  • A platform wheel is provided per OS/arch (macOS, Linux, Windows). On a platform without a wheel you can build from source (see below).

Install

pip install primalsolver

Verify:

python -c "import primalsolver as ps; print(ps.version())"

Quickstart

Build and solve a model in code (above), or solve a model file — MPS, CPLEX LP, OPF and CBF are auto-detected by content/extension:

from primalsolver import Model, SOLSTA

with Model() as m:
    m.read("model.mps")
    r = m.solve()

print(r.solsta, r.x, r.objective)

The high-level Model covers the common path. Everything else is reachable through the generated low-level binding.

Full API (all 547 functions)

tools/gen_bindings.py parses the C header primal.h and emits src/primalsolver/_bindings.py with a ctypes signature for every PRIMAL_* function. _native.py applies them and re-exports them, so the entire surface is available:

import primalsolver as ps

ps.PRIMAL_getdualray(...)      # every PRIMAL_* is available at package level
ps.FUNCTIONS                    # name -> ctypes function object (547)
ps.MISSING                      # declared in the header but absent in the lib (empty = OK)
ps._native.optimize             # short aliases (PRIMAL_ removed) used by Model

Handles (PRIMALenv_t / PRIMALtask_t) are opaque C pointers: the functions that create/destroy them take a pointer to the handle, so pass ctypes.byref(...). Callback arguments are exposed as c_void_p; the two variadic functions (PRIMAL_echotask, PRIMAL_echoenv) are exposed without argtypes (ctypes cannot type C varargs) — pass explicit ctypes objects for the extra arguments.

Regenerate the binding after any change to primal.h:

python tools/gen_bindings.py

What is shipped

  • Wheel: only the primalsolver package — __init__.py, _native.py, the generated _bindings.py, the compiled library in _lib/, plus README.md and LICENSE.
  • Python examples live in ../python_examples/ (tracked in the C repository), not in this package. No test files are shipped.

Building from source

The C sources are read-only input; this project never modifies them. setup.py compiles the shared library into src/primalsolver/_lib/ before packaging.

Source directory resolution, in order:

  1. $PRIMAL_C_SRC — an explicit C checkout;
  2. csrc/ — a vendored snapshot (python sync_csrc.py), used by the sdist/CI;
  3. .. — the parent directory, i.e. the live C repository (default).

csrc/ is generated by sync_csrc.py and is gitignored: the C sources have a single home in the C repository. CI fetches them from github.com/c-vision/Primal and regenerates csrc/ before building.

Development install:

python -m venv .venv && . .venv/bin/activate
pip install -U pip setuptools wheel
pip install -e .
python -c "import primalsolver as ps; print(ps.version())"

Build a wheel locally (needs only setuptools + wheel, no build package):

python -m pip wheel . --no-build-isolation --no-deps -w dist

The wheel bundles a native library, so it is platform-specific: py3-none-<platform> (e.g. py3-none-macosx_11_0_arm64), never none-any.

Building the distribution wheels (all platforms)

Config lives in [tool.cibuildwheel] (pyproject.toml); cibuildwheel compiles inside each target environment (required for manylinux) and runs auditwheel / delocate. In CI the C sources are fetched from github.com/c-vision/Primal and vendored with sync_csrc.py before building (see .github/workflows/wheels.yml).

pip install cibuildwheel
python -m cibuildwheel --output-dir dist        # current platform
python -m cibuildwheel --platform <os> --output-dir dist

Notes:

  • macOS: set MACOSX_DEPLOYMENT_TARGET (e.g. 11.0) for older systems and codesign the dylib (codesign -s -); cibuildwheel handles delocate.
  • Windows: built with mingw-w64 (before-all = "choco install -y mingw") and -static so the DLL is standalone.
  • Linux: -pthread is linked (manylinux glibc < 2.34 keeps pthread in libpthread).

Release procedure

  1. Generate the vendored snapshot (makes the sdist self-contained; it is gitignored, not committed):

    python sync_csrc.py
    
  2. Regenerate the binding if primal.h changed:

    python tools/gen_bindings.py
    
  3. Bump the version — the single source of truth is __version__ in src/primalsolver/__init__.py (pyproject.toml reads it via dynamic = ["version"]).

  4. Check locally:

    pip install -e .
    python -c "import primalsolver as ps; print(ps.version())"
    python -m pip wheel . --no-build-isolation --no-deps -w dist
    
  5. Commit and tag (in the Python repository, never the C one):

    git add -A && git commit -m "release vX.Y.Z"
    git tag vX.Y.Z
    git push origin main --tags
    
  6. Publish: a Git tag triggers .github/workflows/wheels.yml, which builds the wheels + sdist and uploads them as artifacts. Publishing to PyPI runs only when a GitHub Release is published for that tag, using trusted publishing (OIDC, no API token stored).

    Prerequisites (one-time): register a PyPI trusted publisher for this repository and create a pypi environment in the GitHub repo settings.

    Manual/fallback publish (e.g. TestPyPI):

    pip install build twine
    python -m build
    twine check dist/*
    twine upload --repository testpypi dist/*   # then: twine upload dist/*
    

Repository layout

pyproject.toml          # metadata + cibuildwheel config
setup.py                # compiles the shared lib; forces the platform wheel tag
MANIFEST.in             # sdist contents (vendored csrc, no prebuilt binaries)
sync_csrc.py            # vendored C-source snapshot -> csrc/
tools/gen_bindings.py   # primal.h -> src/primalsolver/_bindings.py (547 fns)
csrc/                   # C-source snapshot (generated by sync_csrc.py; gitignored)
src/primalsolver/       # the installed package (__init__, _native, _bindings, _lib)
.github/workflows/wheels.yml

License

Apache-2.0, same as PrimalSolver. See LICENSE.

Metadata

Release files for primalsolver 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for primalsolver 0.1.0
File Size Uploaded
primalsolver-0.1.0.tar.gz 453.5 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for primalsolver 0.1.0
File Interpreter ABI Platform
primalsolver-0.1.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl Python 3 none Linux glibc 2.28+ x86-64, Linux glibc 2.17+ x86-64 Details
primalsolver-0.1.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64, Linux glibc 2.28+ ARM64 Details
primalsolver-0.1.0-py3-none-macosx_11_0_universal2.whl Python 3 none macOS 11.0+ universal2 (ARM64, x86-64) Details

Total release size: 3.3 MB

Release files / primalsolver-0.1.0.tar.gz

Download URL primalsolver-0.1.0.tar.gz
Size 453.5 kB
Tags Source
SHA-256 checksum
How to use checksums
2d3c1df91220884b383cebb1e6c015c4dec4cff94fb1d5b8d84bb6e14222d8df
BLAKE2b-256 checksum
How to use checksums
af1a855c4546a933f74fb6b189118189d9ee6848416b7d04f04bbcc5f272ffa0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.14

Release files / primalsolver-0.1.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL primalsolver-0.1.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 1.2 MB
Tags Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64 Python 3
SHA-256 checksum
How to use checksums
5e98a77620beec074b36119d1290618d24ad539b1567bc97201478e6bfa22f48
BLAKE2b-256 checksum
How to use checksums
9fef075025920f809520e2272eec284c70cc17822652c27f31046a10f69f1e67
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.14

Release files / primalsolver-0.1.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL primalsolver-0.1.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 1.2 MB
Tags Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64 Python 3
SHA-256 checksum
How to use checksums
6d5b3ba9c2f6d0a84cb69c0e2e1226f9729a91d413d43fe8c770443c7caeecee
BLAKE2b-256 checksum
How to use checksums
5ae157b9f899d2fefd80fe255e2cc4892fc6164c7cfbe783b5061507da6b7223
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.14

Release files / primalsolver-0.1.0-py3-none-macosx_11_0_universal2.whl

Download URL primalsolver-0.1.0-py3-none-macosx_11_0_universal2.whl
Size 392.5 kB
Tags Python 3 macOS 11.0+ universal2 (ARM64, x86-64)
SHA-256 checksum
How to use checksums
43950d2e2638c91e1f1f5af25e4225d594e4183b1fd8b675622ea87f9ab7b554
BLAKE2b-256 checksum
How to use checksums
b2490a5762069d74da9a78183beaaa1b5efd0e0fe59d35548a23f428903376a8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.14

Release history Release notifications | RSS feed

0.1.2

5 release files

0.1.1

5 release files

This release

0.1.0 This release

4 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page