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: pushing a tag vX.Y.Z triggers .github/workflows/wheels.yml, which builds the wheels + sdist and uploads them as artifacts. Publishing to PyPI runs when a GitHub Release is published for that tag, using the repository secret PYPI_API_TOKEN (token auth).

    Prerequisites (one-time): add PYPI_API_TOKEN in the repo (Settings → Secrets and variables → Actions) with the PyPI API token.

    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.1

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.1
File Size Uploaded
primalsolver-0.1.1.tar.gz 453.1 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for primalsolver 0.1.1
File
primalsolver-0.1.1-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
primalsolver-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
primalsolver-0.1.1-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
primalsolver-0.1.1-py3-none-macosx_10_13_x86_64.whl Python 3 none macOS 10.13+ x86-64 Details

Total release size: 2.9 MB

Release files / primalsolver-0.1.1.tar.gz

Download URL primalsolver-0.1.1.tar.gz
Size 453.1 kB
Tags Source
SHA-256 checksum
How to use checksums
6fbf920efae4cbf99c9001c97eebba9dc08a54df15dba2d85bf19457a95e798d
BLAKE2b-256 checksum
How to use checksums
d8524a0f6461c81505afc2f8b7703927f56dafdda720ba1d5be72f47c6dc19ab
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / primalsolver-0.1.1-py3-none-win_amd64.whl

Download URL primalsolver-0.1.1-py3-none-win_amd64.whl
Size 458.4 kB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
9eda224204802de8d21230661f47019b3c3f8e56503f55c95860df882f242a8d
BLAKE2b-256 checksum
How to use checksums
e1ba96293eef9b96ec4934135d94cdbcab89d2c7990c403e700538deb4537004
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / primalsolver-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL primalsolver-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 398.4 kB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
f27a7bef2ae35f7dadd2e44fea6e7187177a30c113b2a8d2d0b79306f89a4119
BLAKE2b-256 checksum
How to use checksums
fb8551cb70715c3615410d21e6c613fd9cffcc7f532f586dc57403ca7020ba95
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / primalsolver-0.1.1-py3-none-macosx_11_0_arm64.whl

Download URL primalsolver-0.1.1-py3-none-macosx_11_0_arm64.whl
Size 817.8 kB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
e39df1f12f00ef4f2a409e9351243838a2c83cca91cf9d8e8afa864a25e04548
BLAKE2b-256 checksum
How to use checksums
15e64161dce4bcd4e0489c629d0759d36b7fc3435a8af4f9eb7e759a904b9927
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / primalsolver-0.1.1-py3-none-macosx_10_13_x86_64.whl

Download URL primalsolver-0.1.1-py3-none-macosx_10_13_x86_64.whl
Size 817.6 kB
Tags Python 3 macOS 10.13+ x86-64
SHA-256 checksum
How to use checksums
29263d15f3878197c56f253c8b995362198f1960656094935ca93a22e9cef9f4
BLAKE2b-256 checksum
How to use checksums
be048f0d72a77446278925df6d421c40210b85d16bbee9fe77c58fc35a312aee
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

0.1.2

5 release files

This release

0.1.1 This release

5 release files

0.1.0

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