We have previously covered what an optimisation model is and what solver to choose. Here, we link both topics by introducing different software packages for the Python programming language that allow us to implement a given model formulation and hand it to a solver to find a solution.
Similar packages also exist for other programming languages, notably JuMP for Julia and OR-Tools for C++. Further, specialised tools come with their own domain specific languages, such as GAMS, AMPL, or AIMMS. Finally, solver vendors typically provide direct APIs that can be used without any intermediate modelling layer.
The common feature of all Python packages is the possibility to formulate the model in an abstract fashion and switch the solver simply by configuration. However, they differ in the set of solvers that are supported, the types of optimisation models that can be represented, or the syntax used. We present each package in order of appearance, noting the year of the first release and the number of downloads via the Python Package Index last month.
Established Packages
PuLP (2003, 3’423K) has been around the longest and is still popular. It is straightforward to use and supports MIP problems and works by writing the generated formulation to a file and calling the solver in a subprocess. The downside of this approach is that in-place updates of problems are not supported, and every resolve starts from scratch.
Pyomo (2008, 928K) offers an object-oriented approach to modelling and also supports block structures and some reformulations. It comes with many extensions, eg, for disjunctive programming or stochastic optimisation. Arbitrary nonlinear expressions are allowed (with solvers that support them, eg, IPOPT).
PICOS (2012, 12K) started out as an interface to conic solvers but also covers MIP models. It uses vectorised expressions based on NumPy and has special support for constructions relevant to quantum information science.
CVXPY (2013, 2’495K) implements so-called disciplined convex programming, and converts models into conic normal form, but also has support for integer variables. It can be used to add differentiable optimisation layers to neural networks via cvxpylayers.
Modern Alternatives
Python-mip (2018, 292K) is as easy to use as PuLP, but adds advanced features, such as in-place problem modification or solver callbacks. It also performs well in model generation benchmarks, at least when using PyPy, an alternative Python runtime with just-in-time compilation. Unfortunately, few solvers are supported, and the project is no longer actively maintained.

Linopy (2021, 104K) was created within the PyPSA project to support fast generation of large models in the context of power systems with vectorised operations. It uses xarray data structures to allow for explicit management of index dimensions and concise syntax. Beyond MIP problems, also quadratic expressions are supported.
Cutting Edge Development
GAMSPy (2023, 7K) provides Python-native modelling using the established GAMS engine as a backend. This is the only package in this list that is not an open-source project and requires a license.
PyOptInterface (2024, 4K) is a recently published package with a focus on performance, with a C++ backend. Besides MIP models and quadratic expressions, it also has an expression-based interface to IPOPT for nonlinear optimisation.
Pyoframe (2024, 1K) builds upon PyOptInterface and offers a modelling interface based on dataframes (eg, pandas or Polars), similar to linopy.
Conclusion
Which package to choose depends on the specific requirements of the task at hand and your preferences. To get started, PuLP or PyOptInterface are easy to use, with little boilerplate. If you prefer a popular package with a big community, Pyomo or CVXPY might be a better fit. If performance is important, linopy, CVXPY and PyOptInterface have a good track record. If the model is complex and highly structured, Pyomo can provide tools to organise the different components well. In summary, the ecosystem of modelling with Python is rich, with no clear winners and ongoing developments.


