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

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.2
File Size Uploaded
primalsolver-0.1.2.tar.gz 454.8 kB Details

Built distributions (wheels)

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

Total release size: 3.0 MB

Release files / primalsolver-0.1.2.tar.gz

Download URL primalsolver-0.1.2.tar.gz
Size 454.8 kB
Tags Source
SHA-256 checksum
How to use checksums
dd019a00c4b68e9ef9dba9164334099c3f6fc21afe2f7b26578b7b2fef64ef2f
BLAKE2b-256 checksum
How to use checksums
4af83a5d343a37ec1e5a4070d56be187bf29fd146e99e461054fb4d0a7f650fd
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.2-py3-none-win_amd64.whl

Download URL primalsolver-0.1.2-py3-none-win_amd64.whl
Size 460.4 kB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
64ce341f09e90761d4a3c763a8af8a4a4f084f7724072b1be6f2ec8d2d9b8baf
BLAKE2b-256 checksum
How to use checksums
c728161d0df597f9fd8524430aaf7dd127bc3eb6e5443dc829629dfdc66fb5a7
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.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL primalsolver-0.1.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 400.1 kB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
74298c8dc4c2a45cb743402b46d587e70a44bf6e31f97a291b5330242ccd736c
BLAKE2b-256 checksum
How to use checksums
c038f5a0a3c32243395b174b7d3aff44beacfa3a8022ed6bd72f653224ccdfb5
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.2-py3-none-macosx_11_0_arm64.whl

Download URL primalsolver-0.1.2-py3-none-macosx_11_0_arm64.whl
Size 821.3 kB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
52060e14483aea20c7d902e45171fca45fc29525c0f2a3b8324bd4c53123d49a
BLAKE2b-256 checksum
How to use checksums
8cab42a64838761389642b11f8e3156a43f377c8f0984ac2c6d3fb5d890cf8d6
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.2-py3-none-macosx_10_13_x86_64.whl

Download URL primalsolver-0.1.2-py3-none-macosx_10_13_x86_64.whl
Size 821.1 kB
Tags Python 3 macOS 10.13+ x86-64
SHA-256 checksum
How to use checksums
f107fd54be9244e2c223c6589683b025ca6c4a9c55f950284d87865455d4aefb
BLAKE2b-256 checksum
How to use checksums
b30bd3c8c97beced67d3e522232996fe96d89a701b886ab5f354f42a24fc14d7
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

This release

0.1.2 This release

5 release files

0.1.1

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