{"id":912,"library":"opt-einsum","title":"opt-einsum","description":"opt-einsum is a Python library that optimizes the contraction order of Einstein summation expressions, significantly reducing the execution time of einsum-like operations in various backends such as NumPy, Dask, PyTorch, TensorFlow, and JAX. It achieves this by finding efficient contraction paths, often dispatching operations to highly optimized routines like BLAS or cuBLAS. The library is currently at version 3.4.0 and is actively maintained, serving as the underlying optimization engine for `numpy.einsum(..., optimize=True)` and `torch.einsum` when installed.","status":"active","version":"3.4.0","language":"python","source_language":"en","source_url":"https://github.com/dgasmith/opt_einsum","tags":["einsum","tensor-contraction","optimization","numpy","pytorch","tensorflow","blas","jax","dask"],"install":[{"cmd":"pip install opt-einsum","lang":"bash","label":"PyPI"}],"dependencies":[{"reason":"Commonly used for array operations and a typical backend for einsum expressions.","package":"numpy","optional":false},{"reason":"Used as a backend for PyTorch tensors, offering optimized einsum for PyTorch.","package":"torch","optional":true},{"reason":"Used as a backend for TensorFlow tensors, offering optimized einsum.","package":"tensorflow","optional":true},{"reason":"Used as a backend for Dask arrays, enabling optimized einsum on larger-than-memory or distributed arrays.","package":"dask","optional":true},{"reason":"Used as a backend for CuPy arrays, enabling optimized einsum on GPUs.","package":"cupy","optional":true}],"imports":[{"note":"The primary function `contract` is a direct drop-in replacement for `np.einsum` with optimization.","wrong":"import opt_einsum as oe; oe.einsum(...)","symbol":"contract","correct":"from opt_einsum import contract"},{"note":"Used to inspect and pre-calculate the optimal contraction path for reuse.","symbol":"contract_path","correct":"from opt_einsum import contract_path"}],"quickstart":{"code":"import numpy as np\nfrom opt_einsum import contract\n\nN = 10\nC = np.random.rand(N, N)\nI = np.random.rand(N, N, N, N)\n\n# Using unoptimized numpy.einsum (for comparison)\n# result_np = np.einsum('pi,qj,ijkl,rk,sl->pqrs', C, C, I, C, C)\n\n# Using opt_einsum.contract for optimized performance\nresult_opt = contract('pi,qj,ijkl,rk,sl->pqrs', C, C, I, C, C)\n\nprint(f\"Optimized result shape: {result_opt.shape}\")","lang":"python","description":"This quickstart demonstrates how to use `opt_einsum.contract` as a drop-in replacement for `numpy.einsum` to automatically optimize the tensor contraction order and achieve significant performance improvements."},"warnings":[{"fix":"Replace `path=...` with `optimize=...` in calls to `opt_einsum.contract`.","message":"The `path` keyword argument in `opt_einsum.contract` has been changed to `optimize` to align more closely with NumPy's API. The `path` keyword will be deprecated in future versions.","severity":"breaking","affected_versions":">=3.4.0"},{"fix":"Always use `np.einsum(..., optimize=True)` or `opt_einsum.contract(...)` for performance-critical einsum operations.","message":"When using `numpy.einsum`, explicitly setting `optimize=True` (or a specific path strategy) is crucial for performance. Without `optimize`, `numpy.einsum` defaults to a left-to-right contraction order, which can be highly inefficient for complex expressions. `opt-einsum.contract` applies optimization by default.","severity":"gotcha","affected_versions":"All versions of NumPy and opt-einsum"},{"fix":"For complex or many-tensor contractions, prefer `optimize='auto'` (the default) or explicitly choose a heuristic path like `'greedy'` or `'random-greedy-128'` to balance path quality and computation time. Avoid `'optimal'` for expressions with more than a few tensors.","message":"Finding the truly optimal contraction path for an einsum expression is an NP-hard problem. While `opt-einsum` offers an 'optimal' strategy, it can scale factorially with the number of terms and quickly become intractable for many tensors. For larger expressions, heuristic algorithms like 'greedy' or 'random-greedy' are used.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Carefully consider the trade-off between memory usage and performance when setting `memory_limit`. Only use it if memory constraints are strict, and be aware of potential performance degradation.","message":"The `memory_limit` parameter in `opt_einsum.contract` can constrain the size of intermediate tensors. While useful for memory management, imposing a limit can make contractions exponentially slower to perform if it restricts the optimizer from finding the most efficient path. The default is `None`, meaning no memory limit.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure `numpy` is installed in the environment (e.g., `pip install numpy`) before using `opt-einsum` or any related functionality.","message":"`numpy` is a required dependency for `opt-einsum` and must be installed for `opt-einsum` functionality (and any `numpy.einsum` usage). The `ModuleNotFoundError` indicates `numpy` was not found in the environment.","severity":"breaking","affected_versions":"All versions"},{"fix":"Ensure `numpy` is installed in your Python environment, typically by running `pip install numpy`.","message":"The `opt-einsum` library requires `numpy` as a core dependency. A `ModuleNotFoundError` indicates that `numpy` is not installed in the environment, preventing the library from functioning.","severity":"breaking","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-05-12T21:14:57.692Z","next_check":"2026-06-27T00:00:00.000Z","problems":[{"fix":"Simplify the `einsum` expression, break it into smaller parts, or explore different optimization strategies (e.g., `optimize='greedy'`) if the default or `memory_limit` causes this. If using `contract_path`, inspect the `path_info` to understand the intermediate expression.","cause":"The optimized contraction path, especially when `memory_limit` is active or with very complex expressions, generates an intermediate `einsum` equation with more unique indices than available single lowercase letters (a-z), which some backends and `opt_einsum` itself enforce.","error":"ValueError: invalid subscript 'Ų' in einstein sum subscripts string, subscripts must be letters"},{"fix":"Uninstall and reinstall `opt_einsum` (`pip uninstall opt_einsum && pip install opt_einsum`). Ensure TensorFlow is correctly installed and accessible in the Python environment.","cause":"This error occurs when `opt_einsum` attempts to load its TensorFlow backend but cannot find the `tensorflow` module as expected, often due to an incomplete or corrupted `opt_einsum` installation or an environment issue.","error":"ImportError: cannot import name 'tensorflow' from 'opt_einsum.backends'"},{"fix":"To explicitly interact with the `opt_einsum` backend for PyTorch, use `import torch.backends.opt_einsum` directly. Alternatively, simply ensure `opt-einsum` is installed (`pip install opt-einsum`) for `torch.einsum` to leverage it automatically for optimization.","cause":"In some newer PyTorch versions, `torch.backends.opt_einsum` might not be directly exposed as a public attribute, even though `opt_einsum` can still be used as a backend for `torch.einsum` if installed.","error":"AttributeError: module 'torch.backends' has no attribute 'opt_einsum'"},{"cause":"This error typically occurs when `numpy.einsum` is called with `optimize=True`, which often delegates to `opt_einsum`'s path-finding algorithms. If the original `einsum` expression contains implicit summations or index patterns that the optimized path (which might use `tensordot`) cannot correctly interpret due to mismatching or implicitly summed axes, this error can arise.","error":"ValueError: axes don't match array"},{"cause":"When `numpy.einsum` with `optimize=True` tries to find an optimal contraction path, it might use intermediate operations like `tensordot` that do not inherently support certain implicit summations or index patterns as flexibly as the default `einsum` implementation, leading to axis mismatch errors.","error":"np.einsum('bdc,ac->ab', a, b, optimize=True) fails but works with optimize=False"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":null,"quickstart_tag":null,"pypi_latest":"3.4.0","cli_name":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":1.6,"disk_size":"18.3M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":1.6,"disk_size":"18.3M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.5,"import_time_s":0.02,"mem_mb":1.6,"disk_size":"19M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1.6,"disk_size":"19M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":1.7,"disk_size":"20.3M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":1.7,"disk_size":"20.3M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.6,"import_time_s":0.04,"mem_mb":1.7,"disk_size":"21M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.7,"disk_size":"21M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.4,"disk_size":"12.2M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.4,"disk_size":"12.2M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.5,"import_time_s":0.04,"mem_mb":1.4,"disk_size":"13M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.4,"disk_size":"13M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.6,"disk_size":"11.9M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.6,"disk_size":"11.8M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.5,"import_time_s":0.03,"mem_mb":1.4,"disk_size":"12M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.4,"disk_size":"12M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":1.5,"disk_size":"17.8M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":1.5,"disk_size":"17.8M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.7,"import_time_s":0.02,"mem_mb":1.5,"disk_size":"18M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1.5,"disk_size":"18M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":null,"tag_description":null,"results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}