linopy: Optimization with array-like variables and constraints
Linear
Integer
Non-linear
Optimization in
PYthon
linopy is an open-source python package that facilitates optimization with real world data. It builds a bridge between data analysis packages like xarray & pandas and problem solvers like cbc, gurobi (see the full list below). Linopy supports Linear, Integer, Mixed-Integer and Quadratic Programming while aiming to make linear programming in Python easy, highly-flexible and performant.
Benchmarks
linopy is designed to be fast and efficient. The following benchmark compares the performance of linopy with the alternative popular optimization packages.
Main features
linopy is heavily based on xarray which allows for many flexible data-handling features:
- Define (arrays of) continuous or binary variables with coordinates, e.g. time, consumers, etc.
- Apply arithmetic operations on the variables like adding, substracting, multiplying with all the broadcasting potentials of xarray
- Apply arithmetic operations on the linear expressions (combination of variables)
- Group terms of a linear expression by coordinates
- Get insight into the clear and transparent data model
- Modify and delete assigned variables and constraints on the fly
- Use lazy operations for large linear programs with dask
- Choose from different commercial and non-commercial solvers
- Fast import and export a linear model using xarray's netcdf IO
Installation
So far linopy is available on the PyPI repository
uv pip install linopy
or on conda-forge
conda install -c conda-forge linopy
In a Nutshell
Linopy aims to make optimization programs transparent and flexible. To illustrate its usage, let's consider a scenario where we aim to minimize the cost of buying apples and bananas over a week, subject to daily and weekly vitamin intake constraints.
>>> import pandas as pd
>>> import linopy
>>> m = linopy.Model()
>>> days = pd.Index(["Mon", "Tue", "Wed", "Thu", "Fri"], name="day")
>>> apples = m.add_variables(lower=0, name="apples", coords=[days])
>>> bananas = m.add_variables(lower=0, name="bananas", coords=[days])
>>> apples
Variable (day: 5)
-----------------
[Mon]: apples[Mon] ∈ [0, inf]
[Tue]: apples[Tue] ∈ [0, inf]
[Wed]: apples[Wed] ∈ [0, inf]
[Thu]: apples[Thu] ∈ [0, inf]
[Fri]: apples[Fri] ∈ [0, inf]
Add daily vitamin constraints
>>> m.add_constraints(3 * apples + 2 * bananas >= 8, name="daily_vitamins")
Constraint `daily_vitamins` (day: 5):
-------------------------------------
[Mon]: +3 apples[Mon] + 2 bananas[Mon] ≥ 8
[Tue]: +3 apples[Tue] + 2 bananas[Tue] ≥ 8
[Wed]: +3 apples[Wed] + 2 bananas[Wed] ≥ 8
[Thu]: +3 apples[Thu] + 2 bananas[Thu] ≥ 8
[Fri]: +3 apples[Fri] + 2 bananas[Fri] ≥ 8
Add weekly vitamin constraint
>>> m.add_constraints((3 * apples + 2 * bananas).sum() >= 50, name="weekly_vitamins")
Constraint `weekly_vitamins`
----------------------------
+3 apples[Mon] + 2 bananas[Mon] + 3 apples[Tue] ... +2 bananas[Thu] + 3 apples[Fri] + 2 bananas[Fri] ≥ 50
Define the prices of apples and bananas and the objective function
>>> apple_price = [1, 1.5, 1, 2, 1]
>>> banana_price = [1, 1, 0.5, 1, 0.5]
>>> m.objective = apple_price * apples + banana_price * bananas
Finally, we can solve the problem and get the optimal solution:
>>> m.solve()
>>> m.objective.value
17.166
... and display the solution as a pandas DataFrame
>>> m.solution.to_pandas()
apples bananas
day
Mon 2.667 0
Tue 0 4
Wed 0 9
Thu 0 4
Fri 0 4
Supported solvers
linopy supports the following solvers
Note that these do have to be installed by the user separately.
Development Setup
To set up a local development environment for linopy and to run the same tests that are run in the CI, you can run:
uv sync --extra dev --extra solvers
source .venv/bin/activate
pytest
The -e flag of the install command installs the linopy package in editable mode, which means that the virtualenv (and thus the tests) will run the code from your local checkout.
Citing Linopy
If you use Linopy in your research, please cite the following paper:
- Hofmann, F., (2023). Linopy: Linear optimization with n-dimensional labeled variables. Journal of Open Source Software, 8(84), 4823, https://doi.org/10.21105/joss.04823
A BibTeX entry for LaTeX users is
@article{Hofmann2023,
doi = {10.21105/joss.04823},
url = {https://doi.org/10.21105/joss.04823},
year = {2023}, publisher = {The Open Journal},
volume = {8},
number = {84},
pages = {4823},
author = {Fabian Hofmann},
title = {Linopy: Linear optimization with n-dimensional labeled variables},
journal = {Journal of Open Source Software}
}
License
Copyright 2021 Fabian Hofmann
This package is published under MIT license. See LICENSE.txt for details.
Metadata
Release files for linopy 0.10.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| linopy-0.10.0.tar.gz | 1.7 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| linopy-0.10.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.0 MB
Release files / linopy-0.10.0.tar.gz
| Download URL | linopy-0.10.0.tar.gz |
|---|---|
| Size | 1.7 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
71ecb6c888fb2c9f12ea6736c2a594a879edb0e72a5db808ad978c948ac976e0
|
|
BLAKE2b-256 checksum How to use checksums |
d2efda63a87cc78d7c8108e154904556f28acdec375e35c53f1f921cfe37426b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.
Transparency logRelease files / linopy-0.10.0-py3-none-any.whl
| Download URL | linopy-0.10.0-py3-none-any.whl |
|---|---|
| Size | 274.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9f22b6df039aad0fd3c26299c6cf3c957e4b20d88842069e4338800d9114e132
|
|
BLAKE2b-256 checksum How to use checksums |
ca3fefaf0032dac7d6d0512a98f329315c449ec5a533a647867c24af54f5e8b6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.
Transparency log