Skip to main content

Unified Python framework for Linear Assignment Problem solvers

Project description

py-lap-solver

A unified Python framework for Linear Assignment Problem (LAP) solvers.

Overview

py-lap-solver provides a common interface for multiple LAP solver implementations, ranging from pure Python (scipy) to optimized C++ implementations with OpenMP and CUDA support.

The Linear Assignment Problem seeks to find an optimal assignment between two sets given a cost matrix, minimizing (or maximizing) the total cost of the assignment.

Installation

Install from pypi

pip install py-lap-solver

Or install from source

git clone git@github.com:nikitapond/py-lap-solver.git

# Install the package in editable mode
pip install -e .

# Install with development dependencies
pip install -e ".[dev]"

Features

  • Unified Interface: Common API across all solver implementations
  • Multiple Backends:
    • ScipySolver: Pure Python implementation using scipy's Hungarian algorithm
    • BatchedScipySolver: C++ implementation with OpenMP parallelization for batch processing
    • Lap1015Solver: Highly optimized C++ implementation (shortest augmenting path algorithm)
  • Batch Processing: Solve multiple LAP instances efficiently with OpenMP parallelization
  • Flexible Input: Support for square and rectangular cost matrices
  • Optional GPU Support: CUDA support in LAP1015 (not yet fully exposed in Python bindings)

Quick Start

Using the Solver Registry (Recommended)

The easiest way to use the solvers is through the pre-configured Solvers registry:

from py_lap_solver.solvers import Solvers
import numpy as np

# Create a batch of cost matrices
batch_matrices = np.random.rand(100, 500, 500)

# Use the fastest available solver with OpenMP parallelization
# This will give you ~6x speedup over sequential processing
assignments = Solvers.BatchedScipyOMP.batch_solve(batch_matrices)

# For single problems, use the standard scipy solver
cost_matrix = np.random.rand(500, 500)
single_assignment = Solvers.Scipy.solve_single(cost_matrix)

Available solvers in the registry:

  • Solvers.Scipy - Pure Python scipy implementation (always available)
  • Solvers.BatchedScipyOMP - C++ scipy with OpenMP batch parallelization
  • Solvers.BatchedScipySequential - C++ scipy without parallelization
  • Solvers.Lap1015OMP - LAP1015 algorithm with OpenMP (limited benefit)
  • Solvers.Lap1015Sequential - LAP1015 algorithm without OpenMP

Manual Configuration

You can also instantiate solvers directly with custom parameters:

from py_lap_solver.solvers import ScipySolver, BatchedScipySolver, Lap1015Solver
import numpy as np

# Use scipy solver (always available)
scipy_solver = ScipySolver()
assignments = scipy_solver.solve_single(cost_matrix)

# Use batched scipy solver with runtime OpenMP control
if BatchedScipySolver.is_available():
    # Create solver with OpenMP enabled (default)
    batch_solver_omp = BatchedScipySolver(use_openmp=True)

    # Create solver without OpenMP for comparison
    batch_solver_seq = BatchedScipySolver(use_openmp=False)

    batch_matrices = np.random.rand(10, 100, 100)
    fast_assignments = batch_solver_omp.batch_solve(batch_matrices)  # ~6x faster
    slow_assignments = batch_solver_seq.batch_solve(batch_matrices)

# Use LAP1015 solver
if Lap1015Solver.is_available():
    # Note: OpenMP provides minimal benefit for LAP1015 due to algorithm structure
    lap_solver = Lap1015Solver(use_openmp=False)
    assignments = lap_solver.solve_single(cost_matrix)

Return Format

All solvers return assignments in a consistent format:

  • Single problem: 1D array of shape (N,) where result[i] is the column assigned to row i
  • Batch problem: 2D array of shape (B, N) where result[b, i] is the column assigned to row i in batch b
  • Unassigned rows are marked with -1 (or custom unassigned_value)
import numpy as np
from py_lap_solver.solvers import Solvers

cost_matrix = np.array([[1, 2], [3, 4]])
assignments = Solvers.Scipy.solve_single(cost_matrix)
# assignments = [1, 0]  (row 0 -> col 1, row 1 -> col 0)

Building with C++ Extensions

To enable the optimized C++ solvers, you need CMake and build tools:

# Install build dependencies
pip install scikit-build-core pybind11

# Build and install with C++ extensions
pip install -e . --no-build-isolation

# On macOS, you may need to install libomp for OpenMP support
brew install libomp

OpenMP Runtime Control

All C++ solvers support runtime OpenMP control through the use_openmp parameter:

from py_lap_solver.solvers import BatchedScipySolver
import numpy as np

# Create solver with OpenMP enabled
solver_parallel = BatchedScipySolver(use_openmp=True)

# Create solver without OpenMP
solver_sequential = BatchedScipySolver(use_openmp=False)

batch = np.random.rand(100, 500, 500)

# Parallel: ~126ms for 100 matrices
assignments_fast = solver_parallel.batch_solve(batch)

# Sequential: ~762ms for 100 matrices
assignments_slow = solver_sequential.batch_solve(batch)

Why OpenMP Helps for Batched Scipy but Not LAP1015:

  • BatchedScipySolver: Each matrix in the batch is independent → perfect parallelization with #pragma omp parallel for
  • LAP1015Solver: Complex intra-matrix data dependencies → synchronization barriers dominate, killing performance

Recommended Usage Patterns

from py_lap_solver.solvers import Solvers
import numpy as np

# Pattern 1: Batch processing (FAST - use OpenMP)
batch_matrices = np.random.rand(1000, 100, 100)
assignments = Solvers.BatchedScipyOMP.batch_solve(batch_matrices)

# Pattern 2: Single large problem (no parallelization benefit)
single_matrix = np.random.rand(5000, 5000)
assignment = Solvers.Scipy.solve_single(single_matrix)  # or BatchedScipySequential

# Pattern 3: Many small problems in a loop
for i in range(1000):
    matrix = generate_matrix()
    # BAD: Calling solve_single in a loop
    result = Solvers.Scipy.solve_single(matrix)

# Better: Batch them together
all_matrices = np.array([generate_matrix() for _ in range(1000)])
results = Solvers.BatchedScipyOMP.batch_solve(all_matrices)  # 6x faster!

Development

Installation

# Install with development dependencies (includes black, ruff, pytest)
pip install -e ".[dev]"

Code Formatting and Linting

The project uses black for code formatting and ruff for linting. A Makefile is provided for convenience:

# Format code with black
make format

# Lint code with ruff
make lint

# Auto-fix linting issues
make lint-fix

# Run all checks
make check

# Format, lint-fix, check, and test in one command
make all

Or use the tools directly:

# Format code
black src/ tests/

# Lint code
ruff check src/ tests/

# Auto-fix linting issues
ruff check --fix src/ tests/

Testing

# Run tests with pytest
pytest tests/

# Or use make
make test

License

MIT

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

py_lap_solver-0.1.4.tar.gz (90.2 kB view details)

Uploaded Source

Built Distributions

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

py_lap_solver-0.1.4-cp312-cp312-win_amd64.whl (232.1 kB view details)

Uploaded CPython 3.12Windows x86-64

py_lap_solver-0.1.4-cp312-cp312-manylinux_2_28_x86_64.whl (352.2 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ x86-64

py_lap_solver-0.1.4-cp312-cp312-macosx_11_0_arm64.whl (438.6 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

py_lap_solver-0.1.4-cp312-cp312-macosx_10_9_x86_64.whl (498.7 kB view details)

Uploaded CPython 3.12macOS 10.9+ x86-64

py_lap_solver-0.1.4-cp311-cp311-win_amd64.whl (231.9 kB view details)

Uploaded CPython 3.11Windows x86-64

py_lap_solver-0.1.4-cp311-cp311-manylinux_2_28_x86_64.whl (350.7 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64

py_lap_solver-0.1.4-cp311-cp311-macosx_11_0_arm64.whl (439.3 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

py_lap_solver-0.1.4-cp311-cp311-macosx_10_9_x86_64.whl (498.4 kB view details)

Uploaded CPython 3.11macOS 10.9+ x86-64

py_lap_solver-0.1.4-cp310-cp310-win_amd64.whl (229.7 kB view details)

Uploaded CPython 3.10Windows x86-64

py_lap_solver-0.1.4-cp310-cp310-manylinux_2_28_x86_64.whl (348.3 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.28+ x86-64

py_lap_solver-0.1.4-cp310-cp310-macosx_11_0_arm64.whl (435.8 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

py_lap_solver-0.1.4-cp310-cp310-macosx_10_9_x86_64.whl (495.1 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

py_lap_solver-0.1.4-cp39-cp39-win_amd64.whl (230.1 kB view details)

Uploaded CPython 3.9Windows x86-64

py_lap_solver-0.1.4-cp39-cp39-manylinux_2_28_x86_64.whl (348.6 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.28+ x86-64

py_lap_solver-0.1.4-cp39-cp39-macosx_11_0_arm64.whl (436.0 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

py_lap_solver-0.1.4-cp39-cp39-macosx_10_9_x86_64.whl (495.2 kB view details)

Uploaded CPython 3.9macOS 10.9+ x86-64

py_lap_solver-0.1.4-cp38-cp38-win_amd64.whl (229.7 kB view details)

Uploaded CPython 3.8Windows x86-64

py_lap_solver-0.1.4-cp38-cp38-manylinux_2_28_x86_64.whl (347.6 kB view details)

Uploaded CPython 3.8manylinux: glibc 2.28+ x86-64

py_lap_solver-0.1.4-cp38-cp38-macosx_11_0_arm64.whl (435.6 kB view details)

Uploaded CPython 3.8macOS 11.0+ ARM64

py_lap_solver-0.1.4-cp38-cp38-macosx_10_9_x86_64.whl (494.8 kB view details)

Uploaded CPython 3.8macOS 10.9+ x86-64

File details

Details for the file py_lap_solver-0.1.4.tar.gz.

File metadata

  • Download URL: py_lap_solver-0.1.4.tar.gz
  • Upload date:
  • Size: 90.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for py_lap_solver-0.1.4.tar.gz
Algorithm Hash digest
SHA256 7dbe63835276aa10f00cfadb772a1db507e3c84ffa765a04f3b692e4d658870b
MD5 47e541b20a7576c1d8a16a5760ae8418
BLAKE2b-256 29e27969402f59360378fa5bbd978daf8999155e78de823614546d8af80c2683

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 db80e51589ae9e8efd62fb3eb2e78440a083fd7cbc87c5c981b6e72064c5ee3e
MD5 76723b4d04209b3b85f74dcd936ca6d5
BLAKE2b-256 27c7b8e7fa26b679211399a11f1612ace8a51b55fadcd822f218050dde93c2a8

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp312-cp312-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp312-cp312-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 49aa90ce1b0f22edc3562f73197791f55db93a363e495a9ddd203ab486217c3a
MD5 28b6bc5dad73c1df006e4a221f2e21d6
BLAKE2b-256 ba68cee363ee62116ef434303904eb214f9c7e8d0105ca6d11fc47a8a08808bb

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ed590252ea003c5407a0435a58310cd04df95cc1c111f214d14c0bc9145564bd
MD5 9b06517addfed09cc74a1bf5098f3e8a
BLAKE2b-256 550ebe0eb1b43a46cd96c8d374ee2da12a94d220eef679c54040793eb3d53cfd

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp312-cp312-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 ab03a22d9c18bcc5354ef6480d181c09595a78fc6ee7032c52d16cf77b347ac2
MD5 89ea62d1c8a0f942e74bb0f507411b3e
BLAKE2b-256 cc56316be003890351d7476607bff624cd807c545907017f065609efca5b33ad

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 4679e743eb66686f1a4467b1a95e33aeb8d3b9f87c5828ca6c80a086933e0c59
MD5 4fed394ccc04c5aacc0cbfcc0ebb7b98
BLAKE2b-256 b9b790a4c95a5518240c75edbbbee68a0c45484c8907e6df4c60e70557ec1067

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp311-cp311-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1be4949b3b18e472ce3a437c07a2a1578eb5afd0d2c39705baacb79067fb2bea
MD5 b54071811d732ca18dd53300bf62cf1f
BLAKE2b-256 60321daacd125502a9850266b772ed971f11aeb6244c0027a378a079919c712b

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 09c478b5f5f65bb88fb9801d2b2831b7a49a974bf9e705432f1db0ec802d5bfd
MD5 deda702140105e76728ac717399d4272
BLAKE2b-256 b2ce019e318013df1998517b75f83ff5a90ffdacf1f603176e9d44b3dd583278

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp311-cp311-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 275b173dc3ce7d54eba9e7bef6a522136a31c8feede9e35a7825bb005212b6d7
MD5 677e3bf662ebde62785a13129298fae7
BLAKE2b-256 31972d1887e02d347ff7e2866fcb9ac9cf0c321579b713e059d82d99ae67fe1e

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 eac215511e852ed343dc0a8800d0aecc51f3acaf79a377369b0969e05d124a35
MD5 e87d8a6991ad8bfad7822f7e6a022277
BLAKE2b-256 fecf118fef05ef09a257e73d57c2c314ed827c187c2f2647666cc84de438c40f

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp310-cp310-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp310-cp310-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 4ac37ea62b130b192389964515215c6aec004bc3680623c14968697b97ef076c
MD5 6563729edb424f653b05aa3447ccdbc6
BLAKE2b-256 7fcd9f9bef9b4210eb53a3156fc6b5c0dd037d98a181b85c51d91369298bd5ac

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 45887820765f2eb9b2e984e008794ac27f1fbd8071dacf3ad1999ad7db18c966
MD5 288387af6720a80457d619e6f25b6e64
BLAKE2b-256 7ae55ba26dcfdfae48eb20ca9dd15865c1ed7adacbb2967a33bbe44673db3fdb

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 e81877de210ce8b46221926c9fe3bd1b8411880191753514b31fbaaf096989e3
MD5 8946cbcbd8de19e5b08ec40eaacecf3e
BLAKE2b-256 4db955a94b77376ec3fc93b47c18b96dc023ad6b4f3e704c73416dba147bc6ad

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp39-cp39-win_amd64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 3ff68e13f45b7173b5374e3f4a3f0cee02346ffd2ba7a950b464ff9037f1ab14
MD5 5dbe6d41e3f8907d36568d4089a38905
BLAKE2b-256 455312114ddbd8d9be44eb3c15bb42b0628ff8bb22185384b635d34fb27f1211

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp39-cp39-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp39-cp39-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 50c1f1a9a3b2e05763e00eff08c5ecca8aeeef7a4ded52ccda77862593aefc33
MD5 9b215e0c3608a4fb3a8bc9d90919ba8e
BLAKE2b-256 a3c7cb0472a0828813a14f6765874ff23fc023bb101359f69937912804708ec9

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ecadb3e7c20d7516accdc44491bf4f12948327c1633fbd02afe463d7601de0fd
MD5 6a60a6f11be86a70baa1306e0971ade9
BLAKE2b-256 3dcc43fbd5ea79b74d9b75ede31a6ab2df595ba556e6c27a80ed4d0c68025833

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp39-cp39-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 5bc2d91625f6b80224980605ff096f828a21f7696e8723229bc6303b29556ac6
MD5 33e02518e95c20bb90118ef6ee7e817e
BLAKE2b-256 23f86b3fea5dc025121b86a5e975115639df6dd0ba85098b5b52660ce2725de3

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp38-cp38-win_amd64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 5df64e87fe1d416bebe1ecc5bfec1642064f44c70fdf9ca0aeaaec26405f0353
MD5 0afbba78785b6a918190162f6be9ee7f
BLAKE2b-256 cc4fdb603d9756971930e713e56f7ba59ac00591d4b71569ed8b375bcc61acbe

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp38-cp38-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp38-cp38-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 0a6bc9146159942cf1ae56a7bd2dea3cb78da530c840619e5366fec5e95933ca
MD5 5307a80e3fb35e1cc42fd3d0b9f37dba
BLAKE2b-256 53692a43654700819cd683af4fc0d23fbdfa6d9f55d21324d0a312dcdfb3bdd9

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp38-cp38-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6a5c63fab829181701ca2c3275ac7b023a7f60c2a6c829dffe49b441c0d2ee28
MD5 26aa02a0bf6d12f0462f99c09a50b8c9
BLAKE2b-256 22b81b5e7aa615bf7f93480877fc4d12b6f131060cb0b42c9988fde8219579a7

See more details on using hashes here.

File details

Details for the file py_lap_solver-0.1.4-cp38-cp38-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for py_lap_solver-0.1.4-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 60e66fe45430870dde90fd33d33b1c8de89fa1550693ec2748d7db8029081f05
MD5 c16f415738cf9f2289a8f8369e95f3cf
BLAKE2b-256 ef241fe8f9624ec6e444051e0ab6352ea274cc24ab77fbb95dae964bfa94dcac

See more details on using hashes here.

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