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.3.tar.gz (89.8 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.3-cp312-cp312-win_amd64.whl (229.8 kB view details)

Uploaded CPython 3.12Windows x86-64

py_lap_solver-0.1.3-cp312-cp312-manylinux_2_28_x86_64.whl (350.5 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ x86-64

py_lap_solver-0.1.3-cp312-cp312-macosx_11_0_arm64.whl (437.3 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

py_lap_solver-0.1.3-cp312-cp312-macosx_10_9_x86_64.whl (497.3 kB view details)

Uploaded CPython 3.12macOS 10.9+ x86-64

py_lap_solver-0.1.3-cp311-cp311-win_amd64.whl (229.5 kB view details)

Uploaded CPython 3.11Windows x86-64

py_lap_solver-0.1.3-cp311-cp311-manylinux_2_28_x86_64.whl (349.0 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64

py_lap_solver-0.1.3-cp311-cp311-macosx_11_0_arm64.whl (438.0 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

py_lap_solver-0.1.3-cp311-cp311-macosx_10_9_x86_64.whl (496.9 kB view details)

Uploaded CPython 3.11macOS 10.9+ x86-64

py_lap_solver-0.1.3-cp310-cp310-win_amd64.whl (227.2 kB view details)

Uploaded CPython 3.10Windows x86-64

py_lap_solver-0.1.3-cp310-cp310-manylinux_2_28_x86_64.whl (346.6 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.28+ x86-64

py_lap_solver-0.1.3-cp310-cp310-macosx_11_0_arm64.whl (434.7 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

py_lap_solver-0.1.3-cp310-cp310-macosx_10_9_x86_64.whl (493.5 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

py_lap_solver-0.1.3-cp39-cp39-win_amd64.whl (227.6 kB view details)

Uploaded CPython 3.9Windows x86-64

py_lap_solver-0.1.3-cp39-cp39-manylinux_2_28_x86_64.whl (346.8 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.28+ x86-64

py_lap_solver-0.1.3-cp39-cp39-macosx_11_0_arm64.whl (435.0 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

py_lap_solver-0.1.3-cp39-cp39-macosx_10_9_x86_64.whl (493.6 kB view details)

Uploaded CPython 3.9macOS 10.9+ x86-64

py_lap_solver-0.1.3-cp38-cp38-win_amd64.whl (227.2 kB view details)

Uploaded CPython 3.8Windows x86-64

py_lap_solver-0.1.3-cp38-cp38-manylinux_2_28_x86_64.whl (346.0 kB view details)

Uploaded CPython 3.8manylinux: glibc 2.28+ x86-64

py_lap_solver-0.1.3-cp38-cp38-macosx_11_0_arm64.whl (434.6 kB view details)

Uploaded CPython 3.8macOS 11.0+ ARM64

py_lap_solver-0.1.3-cp38-cp38-macosx_10_9_x86_64.whl (493.3 kB view details)

Uploaded CPython 3.8macOS 10.9+ x86-64

File details

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

File metadata

  • Download URL: py_lap_solver-0.1.3.tar.gz
  • Upload date:
  • Size: 89.8 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.3.tar.gz
Algorithm Hash digest
SHA256 b4fb7b816e2adb0027ee38c8f5526a57029feab88332f262da1deed1caa9e6c6
MD5 21dfabd25609894dad9a841907397d8f
BLAKE2b-256 bf14264974691de9422bfd65774264d8d76dec7246e525ed5b6629d89a6baa11

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 ef78189ad3cf4cd9b666abb668079876c696455145a208513d3286f303f3ffad
MD5 14fb0857be7424262c21bc1290de1b99
BLAKE2b-256 bd258ce0345161cc969c2a37941a2d248db5c39d42920052e1e0e1ac6875a846

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp312-cp312-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 04c5219dc95c3075223123a4d57d79b997bae630064d7e808d43b68d6c223344
MD5 18f64e296a24a51a09204313bd71c7c9
BLAKE2b-256 9267a0601fd51bad9f3b1660c715413d6da4b5fc643c096712921f1bdcdd5b4e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c114b995e5fa2670dd6f080e27446067d32f4a8e6991f8f02468496c9c5c897d
MD5 7fd6b1f14fae37dbde0103d9f8022555
BLAKE2b-256 9e3dc43433f94ad6798d19a5600adb0e1acac550b0a330cbbc67c8a170aa7afa

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 7388ef464d857cf9542ab53f3228617b3bb5c0f84fe7cc12ea82e29316688dd4
MD5 46105134b1b7fae5d8fd6fc94cd996bb
BLAKE2b-256 f0603906d8e1fa9d16f005f1333982ef4ef2c1e50debb10d6d5c2d0e9d21bf4f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 22317bca6c173ac7fd3d5425dc9fa0e413d9e591d05460fc76923acd05fab3b1
MD5 5e85ef4e6c45b801c5dc2e2da781217a
BLAKE2b-256 d5426e7d79ec32ffa895fe3bfdccb9f0e04889c5b02fa4ebc61ef8bd50bd7eef

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a76e89b596899a92b7f7b3def9f1a3f4d49ef830d666ac51b458d27836ee638e
MD5 9043161c62e008303ef05984094067a5
BLAKE2b-256 2b28fd81ca2c37501af7af372c86a804560c4b7c53f979180356bc88bb725616

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9aabce867d3835fb829e672c40b89ddafde7de6d2045214b9d64afdc1aa8a5f4
MD5 4f6be55d96b1b3efa70b0860e6885616
BLAKE2b-256 3ddecfb5bab7588815d28df58961543f5a037ddf32bd2fdadf271c76071b4a4f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 7fbeb579721d1052e169ff25e8d83b7a5b0a0f5b4de2b8d3507b05d77dcdff32
MD5 6697b5d2712f128f66f013e141d10b28
BLAKE2b-256 8fed2b6c69bf704bfd60e28c3ec33d2b5fef58848bc914bc6dda0c249483925f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 ccb7f9b69c0459256c32a1002307e45711045bf99bfd5a6fdd7931770d21b73e
MD5 40c89930e777859a73e6fccfa814dd54
BLAKE2b-256 a1b26b471fec02192d7361ad24161938dab373f7b72ff313345626e62473131c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp310-cp310-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 aa8f3a9eb05d4464a1dc8f2e3be510ce0b97b5194691ceb13c3cd6ca16476bbd
MD5 12cba355b7fde23fb4869b0f06b9723a
BLAKE2b-256 4cc88821c5e2c3308cdca5b3d7b050784dd08ec984df99dd560eee24c50a36d8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b9bb434135872b1293150b020c5f3febdcbf6c28b9a4d761125b4221d13eecc5
MD5 75c51973298180ada463d05a572fd433
BLAKE2b-256 d0c5d6c7b927599c4f897e426d99eb0ed268b8c74372e8ba8f411a9c45e4fe70

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 4b840a0eb42dafcf8fc7b9dd4e4d87ffb59798283f0ff298bcb03648194f66bd
MD5 a13dbc6e6f0aed919d00766e1138768c
BLAKE2b-256 bde04c9a29ebb8226f16b46557fc53ae0a111192c56bd30a60ae52ed0eb7f3a0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 0a6c186adb57c6c980ee43e04bf2b967a3d9774149e8cbab14b73e7ec5a349b6
MD5 f2a9132b19234e37ad5e9a72e8cd424c
BLAKE2b-256 a59025bcacb4fdb7189c3152380fbec7386676acb117d9eea0465c18a215f7d0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp39-cp39-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 80dfbcef486b55e5e5a208d72ca7ddb8e1b78355463f486f65a603897d621a29
MD5 9920853976e6609864fed827c24b83aa
BLAKE2b-256 d8e2f938cad5f6e2ea6e62e5b49b72bb10d042400fd440c821cca40d97fa2f89

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 cc7de2e41f253cee426870e598dbc527c8d0592e6a6a8313f56cf2eafef593a3
MD5 ccdbcc2e8b257a55b35fa66c041220f0
BLAKE2b-256 ef6ca3044164e26d0d631daa8741e249b68c4c146500198811f9200edcdf6e1c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 d9215d4e2a4abd732dc9b3a310c88454fdf02dfab91fcf51b27afc9dfd07f456
MD5 2ff01bd66086d0f8451e72ac4f3bef11
BLAKE2b-256 a638e58d8cfb8bd3429cfac69425fa14e1282bf1227967c258256c859f2b50e1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 88654982d7e88bddd7dc40bc67e8856d1f369bc35255ec28c84015d2511ea116
MD5 da52478cbcd284d5a18c27250da6b1a6
BLAKE2b-256 1083b738a7a45b3e5fadb7bd589f7813796b7477f26d325dc3cfda4616c56403

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp38-cp38-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 919ebded79eb90be72585b6ad6d392f8e5151bb9e2b83b487945054922f4ca28
MD5 766785f5fd3fca486a5f82a8ea74fc5a
BLAKE2b-256 b5f7296a320190baba0cf514a922f86ef2530ffd60f44ab50842dad9cea1ca32

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7cf0b93ad2e6b53f45f6f7db28ae9ffef5ccf3e3e7eb12e410a75f2abaabf3de
MD5 32488f7da6417db8ba79c67080ab16c5
BLAKE2b-256 ea43b4e6878eaaeed07e2559548395219a9a6215b1199f9b0d6d956e201c548f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for py_lap_solver-0.1.3-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 32fa6a5e3c7816f80f26208853d3fa2f95b00a6ba68af3e242d7475bde9c6541
MD5 1335830616b43aeed7cd40a3477798b8
BLAKE2b-256 5b1c8836e8d52de4613c40165f26d7c282742990dce99955e8196aafe1d6bb76

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