Skip to content

Benchmark comparison vs polar-high (Polars-backed LP/MIP eDSL on HiGHS) — thoughts? #740

@MaykThewessen

Description

@MaykThewessen

A new modelling library, polar-high, was released recently by Juha Kiviluoma (Nodal-Tools Oy). It targets the same niche as linopy: an indexed LP/MIP eDSL on top of HiGHS, but uses a Polars-backed kernel instead of xarray.

The docs include a reproducible build / solve / memory comparison between polar-high, linopy, and Pyomo on indexed linear programs, all using HiGHS as the solver. The dense-LP test follows linopy's own benchmark, restricted to the linear case so polar-high can run it directly.

Dense LP — build-only headline (single-thread, HiGHS time-limited to ~1 µs to isolate modelling-layer cost)

dense LP build-only

At N=3000 (~18M variables):

Tool Total time Peak memory
polar-high (regular) 87 s 16.4 GB
polar-high (save_memory) 131 s 15.1 GB
linopy (io_api="lp") 300 s 23.7 GB

Network LP — irregular topology (N nodes, 5N edges, T=168, build-only, 1 thread)

network LP build-only

At N=10000 (~8.4M variables):

Tool Total time Peak memory
polar-high (regular) 51 s 11.5 GB
polar-high (save_memory) 94 s 12.2 GB
linopy (io_api="lp") 165 s 14.1 GB

Replication: linopy's original benchmark format (3-panel, full HiGHS solve included)

linopy-format replication

The replication is faithful: same dense LP, same closed-form optimum, HiGHS solves the same sparse matrix. linopy's published numbers reproduce within run-to-run noise.

Summary

Reported ~2.3-3.5x faster than linopy on the build path with ~30% lower peak memory. The Polars-backed lazy/columnar internals are the architectural source of the gap; linopy is xarray/dense-numpy by default.

Questions for the maintainers and community

  1. Methodology — The linopy column uses io_api="lp" because the benchmark's time_limit short-circuit interacts cleanly with that path. Would io_api="direct" materially change the picture on the build column?
  2. Architectural direction — Issues Polars support #510 (Polars support) and lp-polars IO API writes different models to lp which are incorrect #484 (lp-polars IO bugs) both touched a Polars path. Given the gap shown here, is a Polars-backed write path inside linopy worth revisiting? Or is the architectural distance from xarray too large?
  3. Cross-tool collaboration — Anyone here in contact with Juha / Nodal-Tools? A shared LP/MIP benchmark suite across linopy / polar-high / Pyomo (and ideally JuMP) would be useful for PyPSA-Eur-class workloads.

Not affiliated with Nodal-Tools, just a downstream PyPSA-Eur user who finds the numbers interesting.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions