Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2202118
Implement interface to cupdlpx solver and required IO
mal84emma Oct 29, 2025
7b69035
Update tests
mal84emma Oct 29, 2025
b683654
Add to docs & add package dependency
mal84emma Oct 29, 2025
6416b71
Add comment for release notes
mal84emma Oct 29, 2025
e22f55c
Correction: add support for equality constraints (same l & u bounds)
mal84emma Oct 30, 2025
81b202b
Parameterize solution tolerance in tests to allow different standard …
mal84emma Oct 31, 2025
14883b5
Merge branch 'master' into master
FabianHofmann Dec 2, 2025
e2ed0d7
Improve cuPDLPx solver integration
FabianHofmann Dec 2, 2025
ee0b89a
Merge branch 'master' into master
FabianHofmann Dec 8, 2025
4127f8d
Merge branch 'master' into master
FabianHofmann Dec 14, 2025
b8501dd
Add cuPDLPx to package registry & update tests to use pattern for new…
mal84emma Jan 9, 2026
d0ee58c
Merge branch 'master' into master
mal84emma Jan 9, 2026
c43f616
Add dynamic checking of package version when setting xpress solver fe…
mal84emma Jan 9, 2026
a9d6fab
Merge branch 'master' into master
FabianHofmann Jan 15, 2026
5a44b79
make xpress import save; use GPU/CPU_SOL_TOL
FabianHofmann Jan 15, 2026
75b7b49
Merge branch 'master' into master
FabianHofmann Jan 16, 2026
a03e598
update docs
FabianHofmann Jan 16, 2026
747131d
Merge branch 'master' into master
FabianHofmann Jan 19, 2026
96d2c19
update gpu doc and remove cupdlx from solver deps
FabianHofmann Jan 19, 2026
d3ad89e
fix: handle None constraint matrix in to_cupdlpx
FabianHofmann Jan 19, 2026
b989790
doc: add experimental warning to GPU acceleration docs
FabianHofmann Jan 19, 2026
41e5192
Merge branch 'master' into master
FabianHofmann Jan 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

### Running Tests
```bash
# Run all tests
# Run all tests (excluding GPU tests by default)
pytest

# Run tests with coverage
Expand All @@ -17,8 +17,16 @@ pytest test/test_model.py

# Run a specific test function
pytest test/test_model.py::test_model_creation

# Run GPU tests (requires GPU hardware and cuPDLPx installation)
pytest --run-gpu

# Run only GPU tests
pytest -m gpu --run-gpu
```

**GPU Testing**: Tests that require GPU hardware (e.g., cuPDLPx solver) are automatically skipped by default since CI machines typically don't have GPUs. To run GPU tests locally, use the `--run-gpu` flag. The tests are automatically marked with `@pytest.mark.gpu` based on solver capabilities.

### Linting and Type Checking
```bash
# Run linter (ruff)
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ Fri 0 4
* [Cplex](https://www.ibm.com/de-de/analytics/cplex-optimizer)
* [MOSEK](https://www.mosek.com/)
* [COPT](https://www.shanshu.ai/copt)
* [cuPDLPx](https://github.com/MIT-Lu-Lab/cuPDLPx)

Note that these do have to be installed by the user separately.

Expand Down
49 changes: 49 additions & 0 deletions doc/contributing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ contributing code.
You are invited to submit pull requests / issues to our
`Github repository <https://github.com/pypsa/linopy>`_.

Development Setup
=================

For linting, formatting and checking your code contributions
against our guidelines (e.g. we use `Black <https://github.com/psf/black>`_ as code style
and use `pre-commit <https://pre-commit.com/index.html>`_:
Expand All @@ -19,6 +22,52 @@ and use `pre-commit <https://pre-commit.com/index.html>`_:
* To automatically activate ``pre-commit`` on every ``git commit``: Run ``pre-commit install``
* To manually run it: ``pre-commit run --all``

Running Tests
=============

Testing is essential for maintaining code quality. We use pytest as our testing framework.

Basic Testing
-------------

To run the test suite:

.. code-block:: bash

# Install development dependencies
pip install -e .[dev,solvers]

# Run all tests
pytest

# Run tests with coverage
pytest --cov=./ --cov-report=xml linopy --doctest-modules test

# Run a specific test file
pytest test/test_model.py

# Run a specific test function
pytest test/test_model.py::test_model_creation

GPU Testing
-----------

Tests for GPU-accelerated solvers (e.g., cuPDLPx) are automatically skipped by default since CI machines and most development environments don't have GPU hardware. This ensures tests pass in all environments.

To run GPU tests locally (requires GPU hardware and CUDA):

.. code-block:: bash

# Run all tests including GPU tests
pytest --run-gpu

# Run only GPU tests
pytest -m gpu --run-gpu

GPU tests are automatically detected based on solver capabilities - no manual marking is required. When you add a new GPU solver to linopy, tests using that solver will automatically be marked as GPU tests.

See the :doc:`gpu-acceleration` guide for more information about GPU solver setup and usage.

Contributing examples
=====================

Expand Down
117 changes: 117 additions & 0 deletions doc/gpu-acceleration.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
========================
GPU-Accelerated Solving
========================

.. warning::

This feature is **experimental** and not tested in CI due to the lack of GPU-enabled machines. Use with caution and please report any issues.

Linopy supports GPU-accelerated optimization solvers that can significantly speed up solving large-scale linear programming problems by leveraging the parallel processing capabilities of modern GPUs.

Supported GPU Solvers
=====================

cuPDLPx
-------

`cuPDLPx <https://github.com/MIT-Lu-Lab/cuPDLPx>`_ is an open-source, GPU-accelerated first-order solver developed by MIT. It implements a Primal-Dual hybrid gradient (PDHG) method optimized for GPUs.

To install it, you have to have the `CUDA Toolkit <https://developer.nvidia.com/cuda/toolkit>`_ installed requiring NVIDIA GPUs on your computer. Then, install with

.. code-block:: bash

# Install CUDA Toolkit first (if not already installed)
# Follow instructions at: https://developer.nvidia.com/cuda-downloads

# Install cuPDLPx
pip install cupdlpx>=0.1.2

**Features:**

- GPU-accelerated solving for large-scale linear programs
- Open source (Apache 2.0 license)
- Direct API integration with linopy
- Designed for problems with millions of variables and constraints

**Limitations:**

- Currently supports only Linear Programming (LP)
- Does not support Mixed-Integer Programming (MIP) or Quadratic Programming (QP)
- Lower numerical precision compared to CPU solvers (typical tolerance: ~2.5e-4 vs 1e-5)
- File I/O not currently supported through cuPDLPx API

For a complete list of cuPDLPx parameters, see the `cuPDLPx documentation <https://github.com/MIT-Lu-Lab/cuPDLPx/tree/main/python#parameters>`_.

Xpress with GPU Acceleration
-----------------------------

`FICO Xpress <https://www.fico.com/en/fico-xpress-trial-and-licensing-options>`_ version 9.8 and later includes GPU acceleration support for certain operations.

**Features:**

- Commercial solver with GPU support
- Supports LP, MIP, and QP
- Full-precision solving

Prerequisites
=============

Hardware Requirements
---------------------

GPU solvers require:

- NVIDIA GPU with CUDA support (compute capability 6.0 or higher recommended)
- Sufficient GPU memory for your problem size (varies by problem)
- PCIe 3.0 or higher for optimal data transfer

Software Requirements
---------------------

1. **CUDA Toolkit**: Most GPU solvers require CUDA 11.0 or later
2. **Compatible GPU drivers**: Match your CUDA version

Verifying Installation
======================

To verify that the GPU solvers are properly installed and detected:

.. code-block:: python

import linopy
from linopy.solver_capabilities import (
SolverFeature,
get_available_solvers_with_feature,
)

# Check available solvers
print("All available solvers:", linopy.available_solvers)

# Check GPU-accelerated solvers
gpu_solvers = get_available_solvers_with_feature(
SolverFeature.GPU_ACCELERATION, linopy.available_solvers
)
print("GPU solvers:", gpu_solvers)


By default, GPU tests are skipped in the test suite to support CI environments without GPUs. To run GPU tests locally:

.. code-block:: bash

# Run all tests including GPU tests
pytest --run-gpu

# Run only GPU tests
pytest -m gpu --run-gpu

# Run specific GPU test
pytest test/test_optimization.py -k cupdlpx --run-gpu


References
==========

- `cuPDLPx Repository <https://github.com/MIT-Lu-Lab/cuPDLPx>`_
- `cuPDLPx Python Documentation <https://github.com/MIT-Lu-Lab/cuPDLPx/tree/main/python>`_
- `CUDA Installation Guide <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html>`_
- `NVIDIA GPU Computing Resources <https://developer.nvidia.com/gpu-computing>`_
5 changes: 4 additions & 1 deletion doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ flexible data-handling features:
- Use **lazy operations** for large linear programs with
`dask <https://dask.org/>`__
- Choose from **different commercial and non-commercial solvers**
- Fast **import and export** a linear model using xarray’s netcdf IO
- Fast **import and export** a linear model using xarray's netcdf IO
- Support for **GPU-accelerated solving** for large-scale problems
- Support of various solvers
- `Cbc <https://projects.coin-or.org/Cbc>`__
- `GLPK <https://www.gnu.org/software/glpk/>`__
Expand All @@ -48,6 +49,7 @@ flexible data-handling features:
- `Cplex <https://www.ibm.com/de-de/analytics/cplex-optimizer>`__
- `MOSEK <https://www.mosek.com/>`__
- `COPT <https://www.shanshu.ai/copt>`__
- `cuPDLPx <https://github.com/MIT-Lu-Lab/cuPDLPx>`__ (GPU-accelerated)



Expand Down Expand Up @@ -116,6 +118,7 @@ This package is published under MIT license.
infeasible-model
solve-on-remote
solve-on-oetc
gpu-acceleration
migrating-from-pyomo
gurobi-double-logging

Expand Down
19 changes: 18 additions & 1 deletion doc/prerequisites.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,14 @@ Install a solver

Linopy won't work without a solver. Currently, the following solvers are supported:

CPU-based solvers
~~~~~~~~~~~~~~~~~

- `Cbc <https://projects.coin-or.org/Cbc>`__ - open source, free, fast
- `GLPK <https://www.gnu.org/software/glpk/>`__ - open source, free, not very fast
- `HiGHS <https://www.maths.ed.ac.uk/hall/HiGHS/>`__ - open source, free, fast
- `Gurobi <https://www.gurobi.com/>`__ - closed source, commercial, very fast
- `Xpress <https://www.fico.com/en/fico-xpress-trial-and-licensing-options>`__ - closed source, commercial, very fast
- `Xpress <https://www.fico.com/en/fico-xpress-trial-and-licensing-options>`__ - closed source, commercial, very fast (GPU acceleration available in v9.8+)
- `Cplex <https://www.ibm.com/de-de/analytics/cplex-optimizer>`__ - closed source, commercial, very fast
- `MOSEK <https://www.mosek.com/>`__
- `MindOpt <https://solver.damo.alibaba.com/doc/en/html/index.html>`__ -
Expand All @@ -54,6 +57,20 @@ We recommend to install the HiGHS solver if possible, which is free and open sou
pip install highspy


GPU-accelerated solvers
~~~~~~~~~~~~~~~~~~~~~~~

For large-scale optimization problems, GPU-accelerated solvers can provide significant performance improvements:

- `cuPDLPx <https://github.com/MIT-Lu-Lab/cuPDLPx>`__ - open source, GPU-accelerated first-order solver

**Note:** GPU solvers require compatible NVIDIA GPU hardware and CUDA installation. See the :doc:`gpu-acceleration` guide for detailed setup instructions.

.. code:: bash

pip install cupdlpx


For most of the other solvers, please click on the links to get further installation information.


Expand Down
1 change: 1 addition & 0 deletions doc/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Release Notes
* Fix compatibility for xpress versions below 9.6 (regression)
* Performance: Up to 50x faster ``repr()`` for variables/constraints via O(log n) label lookup and direct numpy indexing
* Performance: Up to 46x faster ``ncons`` property by replacing ``.flat.labels.unique()`` with direct counting
* Add support for GPU-accelerated solver [cuPDLPx](https://github.com/MIT-Lu-Lab/cuPDLPx)

Version 0.5.8
--------------
Expand Down
68 changes: 68 additions & 0 deletions linopy/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import logging
import shutil
import time
import warnings
from collections.abc import Callable
from io import BufferedWriter
from pathlib import Path
Expand All @@ -28,6 +29,7 @@
from linopy.objective import Objective

if TYPE_CHECKING:
from cupdlpx import Model as cupdlpxModel
from highspy.highs import Highs

from linopy.model import Model
Expand Down Expand Up @@ -852,6 +854,72 @@ def to_highspy(m: Model, explicit_coordinate_names: bool = False) -> Highs:
return h


def to_cupdlpx(m: Model, explicit_coordinate_names: bool = False) -> cupdlpxModel:
"""
Export the model to cupdlpx.

This function does not write the model to intermediate files but directly
passes it to cupdlpx.

cuPDLPx does not support named variables and constraints, so the
`explicit_coordinate_names` parameter is ignored.

Parameters
----------
m : linopy.Model
explicit_coordinate_names : bool, optional
Ignored. cuPDLPx does not support named variables/constraints.

Returns
-------
model : cupdlpx.Model
"""
import cupdlpx

if explicit_coordinate_names:
warnings.warn(
"cuPDLPx does not support named variables/constraints. "
"The explicit_coordinate_names parameter is ignored.",
UserWarning,
stacklevel=2,
)

# build model using canonical form matrices and vectors
# see https://github.com/MIT-Lu-Lab/cuPDLPx/tree/main/python#modeling
M = m.matrices
if M.A is None:
msg = "Model has no constraints, cannot export to cuPDLPx."
raise ValueError(msg)
A = M.A.tocsr() # cuPDLPx only supports CSR sparse matrix format
# linopy stores constraints as Ax ?= b and keeps track of inequality
# sense in M.sense. Convert to separate lower and upper bound vectors.
l = np.where(
np.logical_or(np.equal(M.sense, ">"), np.equal(M.sense, "=")),
M.b,
-np.inf,
)
u = np.where(
np.logical_or(np.equal(M.sense, "<"), np.equal(M.sense, "=")),
M.b,
np.inf,
)

cu_model = cupdlpx.Model(
objective_vector=M.c,
constraint_matrix=A,
constraint_lower_bound=l,
constraint_upper_bound=u,
variable_lower_bound=M.lb,
variable_upper_bound=M.ub,
)

# change objective sense
if m.objective.sense == "max":
cu_model.ModelSense = cupdlpx.PDLP.MAXIMIZE

return cu_model


def to_block_files(m: Model, fn: Path) -> None:
"""
Write out the linopy model to a block structured output.
Expand Down
3 changes: 3 additions & 0 deletions linopy/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
)
from linopy.io import (
to_block_files,
to_cupdlpx,
to_file,
to_gurobipy,
to_highspy,
Expand Down Expand Up @@ -1661,4 +1662,6 @@ def reset_solution(self) -> None:

to_highspy = to_highspy

to_cupdlpx = to_cupdlpx

to_block_files = to_block_files
Loading