Skip to main content

Linear optimization with N-D labeled arrays in Python

Project description

linopy: Optimization with array-like variables and constraints

PyPI License Tests doc codecov

        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.

Performance Benchmark

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

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:

python -m venv venv
source venv/bin/activate
pip install uv
uv pip install -e .[dev,solvers]
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:

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.

Project details


Download files

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

Source Distribution

linopy-0.6.3.tar.gz (1.3 MB view details)

Uploaded Source

Built Distribution

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

linopy-0.6.3-py3-none-any.whl (115.1 kB view details)

Uploaded Python 3

File details

Details for the file linopy-0.6.3.tar.gz.

File metadata

  • Download URL: linopy-0.6.3.tar.gz
  • Upload date:
  • Size: 1.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for linopy-0.6.3.tar.gz
Algorithm Hash digest
SHA256 3b7debf2d5d23a6aeca208253a60401cb19ab073f31429c727cbd0da6776db85
MD5 a4d24d2ff4a38bda9124eec0f0295a4b
BLAKE2b-256 d15a82af7ba72b9f907e1617bbad8f61b0209db208532b28c89b8035cd8037b0

See more details on using hashes here.

Provenance

The following attestation bundles were made for linopy-0.6.3.tar.gz:

Publisher: release.yml on PyPSA/linopy

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

File details

Details for the file linopy-0.6.3-py3-none-any.whl.

File metadata

  • Download URL: linopy-0.6.3-py3-none-any.whl
  • Upload date:
  • Size: 115.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for linopy-0.6.3-py3-none-any.whl
Algorithm Hash digest
SHA256 44c97b436f4364a98b457e52dc244d885536adc059c2c0905504b156dc09244b
MD5 375dcae371b95e4d588ea8cfdd7ecaac
BLAKE2b-256 5a1fc6e8c367f4eff530dc6e5f060db24393b6720e27207677f708ad5d66de0b

See more details on using hashes here.

Provenance

The following attestation bundles were made for linopy-0.6.3-py3-none-any.whl:

Publisher: release.yml on PyPSA/linopy

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