Skip to main content

Binary distribution of the CBC MILP solver (COIN-OR Branch and Cut)

Project description

cbcbox

cbcbox is a high-performance, self-contained Python distribution of the CBC MILP solver (COIN-OR Branch and Cut), built from the latest COIN-OR master branch.

On x86_64 (Linux, macOS, Windows) the wheel ships both a Haswell-optimised binary (AVX2/FMA, full -march=haswell ISA) for maximum speed and a generic build with runtime CPU dispatch for compatibility with any x86_64 machine — selected automatically. All dynamic dependencies (OpenBLAS, libgfortran, etc.) are bundled; no system libraries or separate installation steps are needed.

Highlights

  • Haswell-optimised & generic builds — on x86_64 Linux, macOS, and Windows the wheel ships two complete solver stacks: a Haswell build (-O3 -march=haswell, OpenBLAS AVX2/FMA kernel) for maximum throughput, and a generic build (DYNAMIC_ARCH runtime dispatch) for compatibility with any x86_64 CPU. The best available variant is selected automatically at import time (see Build variants).

  • Parallel branch-and-cut — built with --enable-cbc-parallel. Use -threads=N to distribute the search tree across N threads, giving significant speedups on multi-core machines for hard MIP instances.

  • AMD fill-reducing ordering — SuiteSparse AMD is compiled in, enabling the high-quality UniversityOfFlorida Cholesky factorization for Clp's barrier (interior point) solver. AMD reordering produces much less fill-in on large sparse problems than the built-in native Cholesky, making barrier substantially faster. Activate with -barrier -cholesky UniversityOfFlorida (see barrier usage).

Performance (x86_64)

Auto-updated by CI after each successful workflow run. Single-threaded solve time — lower is better.

No results yet — run the CI workflow to populate this section.

Build variants

On x86_64 Linux, macOS, and Windows, the wheel ships two complete sets of binaries:

Variant OpenBLAS kernel Clp SIMD Minimum CPU
generic DYNAMIC_ARCH (runtime dispatch) standard any x86_64
avx2 HASWELL (256-bit AVX2/FMA) -march=haswell -DCOIN_AVX2=4 (all Haswell ISA extensions + 4-double AVX2 layout) Haswell (2013+)

At import time cbcbox automatically selects avx2 when it is available and the running CPU supports AVX2; otherwise it falls back to generic.

You can override this selection with the CBCBOX_BUILD environment variable:

# Force generic (portable) build
CBCBOX_BUILD=generic python -m cbcbox mymodel.mps -solve -quit

# Force AVX2-optimised build (raises an error if not available)
CBCBOX_BUILD=avx2 python -m cbcbox mymodel.mps -solve -quit

When CBCBOX_BUILD is set, a short summary of the selected build is printed to stdout on every call — useful for tagging experiment results:

[cbcbox] CBCBOX_BUILD=avx2
[cbcbox]   binary  : .../cbcbox/cbc_dist_avx2/bin/cbc
[cbcbox]   lib dir : .../cbcbox/cbc_dist_avx2/lib
[cbcbox]   libs    : libCbc.so.3, libClp.so.3, libopenblas.so.0

Non-x86_64 platforms (Linux aarch64, macOS arm64) ship only the generic build. CBCBOX_BUILD=avx2 will raise a RuntimeError on those platforms.

Supported platforms

Platform Wheel tag
Linux x86_64 manylinux2014_x86_64
Linux aarch64 manylinux2014_aarch64
macOS arm64 (Apple Silicon) macosx_11_0_arm64
macOS x86_64 macosx_10_9_x86_64
Windows AMD64 win_amd64

Installation

Note: cbcbox is now available on PyPI — pip install cbcbox. Pre-built wheel artifacts are also available from the CI runs (see below).

Installing from a pre-built wheel (recommended)

  1. Go to the Actions tab of this repository.

  2. Open the latest successful workflow run.

  3. Download the artifact matching your platform:

    Artifact name Platform
    cibw-wheels-Linux-X64 Linux x86_64
    cibw-wheels-Linux-ARM64 Linux aarch64
    cibw-wheels-macOS-ARM64 macOS Apple Silicon
    cibw-wheels-macOS-X64 macOS x86_64
    cibw-wheels-Windows-X64 Windows AMD64
  4. Unzip the artifact and install the .whl file:

    pip install cbcbox-*.whl
    

Installing from PyPI

pip install cbcbox

Usage

Command line

Invoke the CBC solver directly via the Python module entry point:

python -m cbcbox mymodel.lp -solve -quit
python -m cbcbox mymodel.mps.gz -solve -quit
python -m cbcbox mymodel.mps -seconds 60 -timem elapsed -solve -quit
python -m cbcbox mymodel.mps -dualp pesteep -solve -quit

CBC accepts LP, MPS and compressed MPS (.mps.gz) files. Pass -help for the full list of options, or -quit to exit after solving.

Parallel branch-and-cut

This build includes parallel branch-and-cut (--enable-cbc-parallel). Use -threads=N to distribute the search tree across N threads:

python -m cbcbox mymodel.mps -threads=4 -timem elapsed -solve -quit

Use -timem elapsed when running parallel so that time limits and reported times reflect wall-clock seconds rather than CPU-time (which would be ~N× the wall time).

Memory tip: OpenBLAS spawns its own internal thread pool by default. When CBC is already using -threads N, this multiplies memory usage (N CBC threads × M OpenBLAS threads). On memory-constrained machines you can cap OpenBLAS to a single thread while keeping CBC parallelism:

OPENBLAS_NUM_THREADS=1 python -m cbcbox mymodel.mps -threads=4 -solve -quit

Barrier (interior-point) solver

Clp's barrier solver can be faster than simplex for large LP relaxations. This build includes SuiteSparse AMD, which enables the high-quality UniversityOfFlorida Cholesky factorization — significantly reducing fill-in compared to the built-in native Cholesky:

# Solve LP relaxation with barrier + AMD Cholesky, then crossover to simplex basis
python -m cbcbox mymodel.mps -barrier -cholesky UniversityOfFlorida -solve -quit

# Useful as a root-node strategy inside MIP (let CBC use simplex for B&B):
python -m cbcbox mymodel.mps -barrier -cholesky UniversityOfFlorida -solve -quit

Without AMD, only -cholesky native (less efficient) is available.

Python API

The package exposes helpers to locate the installed files:

import cbcbox
import subprocess

# Path to the cbc binary (cbc.exe on Windows).
cbcbox.cbc_bin_path()
# e.g. '/home/user/.venv/lib/python3.13/site-packages/cbcbox/cbc_dist/bin/cbc'

# Directory containing the static and dynamic libraries.
cbcbox.cbc_lib_dir()
# e.g. '.../cbcbox/cbc_dist/lib'

# Directory containing the COIN-OR C/C++ headers.
cbcbox.cbc_include_dir()
# e.g. '.../cbcbox/cbc_dist/include/coin'

# Run CBC programmatically.
result = subprocess.run(
    [cbcbox.cbc_bin_path(), "mymodel.mps", "-solve", "-quit"],
    capture_output=True, text=True,
)
print(result.stdout)

What is built

The build pipeline compiles all components from source inside the CI runner, in the following order:

Component Version / branch Purpose
Cbc master Branch-and-cut MIP solver
Cgl master Cut generation library
Clp master Simplex LP solver (used as the MIP node relaxation)
Osi master Open Solver Interface
CoinUtils master Utility library (shared by all COIN-OR packages)
Nauty 2.8.9 Symmetry detection for MIP presolve
AMD (SuiteSparse v7.12.2) v7.12.2 Sparse matrix fill-reducing ordering
OpenBLAS v0.3.31 Optimised BLAS/LAPACK for LP basis factorisation

On x86_64 Linux, macOS, and Windows the entire stack is compiled twice: once for the generic variant (OpenBLAS DYNAMIC_ARCH=1) and once for the avx2 variant (TARGET=HASWELL, CXXFLAGS=-O3 -march=haswell -DCOIN_AVX2=4). AMD and Nauty are built only once (they are pure combinatorial code with no BLAS dependency) and reused by both COIN-OR variants.

All COIN-OR components are linked into both static (.a) and shared (.so / .dylib) libraries on Linux and macOS. On Windows only shared libraries (.dll) are produced — MinGW's autotools does not support building static and DLL simultaneously. The shared libraries are patched with self-relative RPATHs and bundled inside the wheel, making them directly usable via cffi or ctypes without any system installation.

Wheel contents

The wheel installs under cbcbox/ inside the site-packages directory. On x86_64 Linux, macOS, and Windows it contains two dist trees; other platforms contain only cbc_dist/:

cbc_dist/           ← generic build (all platforms)
cbc_dist_avx2/      ← AVX2-optimised build (x86_64 Linux/macOS/Windows)
├── bin/
│   ├── cbc           # CBC MIP solver binary  (cbc.exe on Windows)
│   └── clp           # Clp LP solver binary   (clp.exe on Windows)
├── lib/
│   ├── libCbc.a / libCbc.so            # CBC solver
│   ├── libCbcSolver.a / libCbcSolver.so
│   ├── libClp.a / libClp.so            # Clp LP solver
│   ├── libCgl.a / libCgl.so            # Cut generation
│   ├── libOsi.a / libOsi.so            # Solver interface
│   ├── libOsiClp.a / libOsiClp.so      # Clp OSI binding
│   ├── libOsiCbc.a / libOsiCbc.so      # CBC OSI binding (where available)
│   ├── libCoinUtils.a / libCoinUtils.so
│   ├── libamd.a                        # AMD sparse ordering (static only, generic only)
│   ├── libsuitesparseconfig.a          # SuiteSparse config (static only, generic only)
│   ├── libnauty.a                      # Nauty (static only, generic only)
│   ├── libopenblas.a / libopenblas.so  # OpenBLAS BLAS/LAPACK
│   ├── pkgconfig/                      # .pc files for all libraries
│   └── <bundled runtime shared libs>   # Platform-specific — see below
└── include/
    ├── coin/      # COIN-OR headers (CoinUtils, Osi, Clp, Cgl, Cbc)
    ├── nauty/     # Nauty headers
    └── *.h        # SuiteSparse / AMD headers

Bundled dynamic libraries

Because the static COIN-OR libraries link to OpenBLAS, which in turn links to the Fortran runtime, the following shared libraries are bundled inside the wheel and their paths are rewritten so no system installation is required.

Linux (lib/ directory, RPATH set to $ORIGIN)

Library Description
libopenblas.so.0 OpenBLAS BLAS/LAPACK
libgfortran.so.5 GNU Fortran runtime
libquadmath.so.0 Quad-precision math (dependency of libgfortran)

macOS (lib/ directory, install names rewritten to @rpath/)

Library Description
libopenblas.dylib OpenBLAS BLAS/LAPACK
libgfortran.5.dylib GNU Fortran runtime
libgcc_s.1.1.dylib GCC runtime
libquadmath.0.dylib Quad-precision math

Windows (bin/ directory, DLLs placed next to the executable)

Library Description
libopenblas.dll OpenBLAS BLAS/LAPACK
libgfortran-5.dll GNU Fortran runtime
libgcc_s_seh-1.dll GCC SEH runtime
libquadmath-0.dll Quad-precision math
libstdc++-6.dll C++ standard library (MinGW64)
libwinpthread-1.dll POSIX thread emulation

CI / build pipeline

Wheels are built and tested automatically via GitHub Actions using cibuildwheel. The workflow (.github/workflows/wheel.yml) runs on five separate runners:

Runner Produces
ubuntu-latest manylinux2014_x86_64 wheel
ubuntu-24.04-arm manylinux2014_aarch64 wheel
macos-15 macosx_11_0_arm64 wheel
macos-15-intel macosx_10_9_x86_64 wheel
windows-latest win_amd64 wheel

After each wheel is built, the test suite in tests/ is run against the installed wheel to verify correctness.

Integration tests

The test suite (pytest) solves six MIP instances and checks the optimal objective values, in both single-threaded and parallel (3-thread) modes. On x86_64 Linux, macOS, and Windows each test is run twice — once against the generic binary and once against the avx2 binary — and a side-by-side performance comparison is recorded:

Instance Expected optimal Time limit
pp08a.mps.gz 7 350 300 s
sprint_hidden06_j.mps.gz 130 900 s
air04.mps.gz 56 137 600 s
air05.mps.gz 26 374 900 s
nw04.mps.gz 16 862 900 s
trd445c.mps.gz −153 419.078836 1200 s

Time limits are generous to avoid false failures on slow CI runners.

Publishing to PyPI

Note: cbcbox is not yet registered on PyPI. When ready, trigger the workflow manually and select pypi (or testpypi) in the Publish input. Trusted Publisher (OIDC) authentication is used — no API tokens are stored as secrets.

Performance results

Auto-updated by CI after each successful workflow run.

Summary

Geometric mean solve time (seconds) across all test instances.

1 thread

Platform generic (s) avx2 (s) avx2 speedup
Darwin arm64 59.27
Darwin x86_64 65.47 26.76 2.45×
Linux aarch64 69.96
Linux x86_64 80.15 23.02 3.48×
Windows AMD64 84.41 31.30 2.70×

3 threads

Platform generic (s) avx2 (s) avx2 speedup
Darwin arm64 61.56
Darwin x86_64 56.52 31.01 1.82×
Linux aarch64 54.73
Linux x86_64 62.75 23.06 2.72×
Windows AMD64 78.78 31.40 2.51×

Per-instance results

pp08a.mps.gz

Platform Build 1 thread (s) 3 threads (s) parallel speedup
Darwin arm64 generic 9.23 20.09 0.46×
Darwin x86_64 avx2 4.62 15.14 0.30×
Darwin x86_64 generic 9.68 6.04 1.60×
Linux aarch64 generic 8.99 5.94 1.51×
Linux x86_64 avx2 4.54 7.87 0.58×
Linux x86_64 generic 9.91 6.25 1.59×
Windows AMD64 avx2 5.27 8.50 0.62×
Windows AMD64 generic 12.42 23.73 0.52×

sprint_hidden06_j.mps.gz

Platform Build 1 thread (s) 3 threads (s) parallel speedup
Darwin arm64 generic 131.35 133.12 0.99×
Darwin x86_64 avx2 48.06 51.05 0.94×
Darwin x86_64 generic 181.43 160.84 1.13×
Linux aarch64 generic 220.56 197.30 1.12×
Linux x86_64 avx2 56.43 52.35 1.08×
Linux x86_64 generic 241.85 223.35 1.08×
Windows AMD64 avx2 93.15 90.44 1.03×
Windows AMD64 generic 236.73 219.65 1.08×

air04.mps.gz

Platform Build 1 thread (s) 3 threads (s) parallel speedup
Darwin arm64 generic 108.57 79.37 1.37×
Darwin x86_64 avx2 53.47 38.03 1.41×
Darwin x86_64 generic 120.39 90.08 1.34×
Linux aarch64 generic 139.44 78.35 1.78×
Linux x86_64 avx2 34.36 26.58 1.29×
Linux x86_64 generic 153.14 88.55 1.73×
Windows AMD64 avx2 43.04 35.10 1.23×
Windows AMD64 generic 152.94 85.43 1.79×

air05.mps.gz

Platform Build 1 thread (s) 3 threads (s) parallel speedup
Darwin arm64 generic 50.68 39.79 1.27×
Darwin x86_64 avx2 23.68 21.26 1.11×
Darwin x86_64 generic 55.30 42.54 1.30×
Linux aarch64 generic 51.07 34.31 1.49×
Linux x86_64 avx2 15.26 12.57 1.21×
Linux x86_64 generic 57.70 41.95 1.38×
Windows AMD64 avx2 21.51 17.45 1.23×
Windows AMD64 generic 56.58 39.68 1.43×

nw04.mps.gz

Platform Build 1 thread (s) 3 threads (s) parallel speedup
Darwin arm64 generic 34.55 36.89 0.94×
Darwin x86_64 avx2 12.19 14.08 0.87×
Darwin x86_64 generic 33.54 38.85 0.86×
Linux aarch64 generic 39.89 41.61 0.96×
Linux x86_64 avx2 14.17 14.62 0.97×
Linux x86_64 generic 57.55 54.46 1.06×
Windows AMD64 avx2 18.04 18.17 0.99×
Windows AMD64 generic 63.14 60.26 1.05×

trd445c.mps.gz

Platform Build 1 thread (s) 3 threads (s) parallel speedup
Darwin arm64 generic 188.06 174.70 1.08×
Darwin x86_64 avx2 107.14 101.04 1.06×
Darwin x86_64 generic 200.87 225.34 0.89×
Linux aarch64 generic 208.23 205.19 1.01×
Linux x86_64 avx2 78.25 74.74 1.05×
Linux x86_64 generic 217.43 216.19 1.01×
Windows AMD64 avx2 114.83 112.02 1.03×
Windows AMD64 generic 225.14 224.47 1.00×

License

CBC and all COIN-OR components are distributed under the Eclipse Public License 2.0. OpenBLAS is distributed under the BSD 3-Clause licence. SuiteSparse AMD is distributed under the BSD 3-Clause licence. Nauty is distributed under the Apache 2.0 licence.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cbcbox-2.903-py3-none-macosx_11_0_arm64.whl (64.4 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

File details

Details for the file cbcbox-2.903-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for cbcbox-2.903-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5aeb8acfe1ea7eca972e21eb10e07e827f059c51f561ef8abf56796c8e2581df
MD5 e9908d782a6924808d4b6c41b95100a8
BLAKE2b-256 7953b44261ac5fc7188b7932fe32e5a53dfdd347a26b3fa435d6f0beecb45c6a

See more details on using hashes here.

Provenance

The following attestation bundles were made for cbcbox-2.903-py3-none-macosx_11_0_arm64.whl:

Publisher: wheel.yml on h-g-s/cbcbox

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page