finds.dev← search

// the find

CPMpy/cpmpy

★ 376 · Python · Apache-2.0 · updated Sep 2026

Constraint Programming and Modeling library in Python, based on numpy, with direct solver access.

CPMpy is a Python constraint programming library that lets you model combinatorial problems (scheduling, packing, satisfaction) using numpy-style arrays of Boolean/integer variables, then hands the model off to whichever solver backend you want. It's aimed at people doing CP/optimization work in Python who want to swap between OR-Tools, Z3, SAT, ILP, and PB solvers without rewriting the model each time.

The solver-agnostic design is real, not just marketing - the same model runs against OR-Tools, Choco, Z3, Exact, PySAT, etc. via a common interface, and swapping solvers to compare runtime is a one-line change. Modeling with numpy arrays of decision variables means vectorized constraint construction (sum, elementwise comparisons) instead of Python loops, which matters once you're building models with thousands of variables. It ships genuinely useful tooling beyond the core solver - MUS/MCS/MARCO explanation extraction, parameter tuning, XCSP3 benchmarking support - that most CP libraries leave as an exercise for the user. Test coverage looks serious: dedicated fuzz-testing repo plus a real test suite per solver backend, not just smoke tests.

Several of the listed solvers (CPLEX, Gurobi, CP Optimizer, Hexaly) require commercial licenses, so the 'solver-agnostic' pitch partially depends on backends you can't actually use without paying - worth checking which free solvers cover your problem class before committing. It's an academic project (ERC grant funded, single lab primarily) rather than a company-backed library, so long-term maintenance and response time to issues will track a research group's priorities, not a support SLA. The flatten/decompose transformation layer that translates high-level global constraints down to each solver's native support is where correctness bugs in a library like this tend to hide, and it's not something you can easily audit as a user - you're trusting the fuzz-testing to have caught the edge cases. Global constraint decomposition also means the constraint you wrote isn't necessarily the constraint the solver sees, which can produce solve-time or propagation behavior that's surprising if you're used to a solver's native API.

View on GitHub →

// want more like this?

We dig through GitHub every week and send a few repos picked for what you actually care about — each with an honest take like this one.

Get finds in your inbox → Search again →