Skip to content

SciPy vs NumPy Linalg

SciPy's scipy.linalg extends NumPy's linear algebra capabilities.

Module Comparison

1. Basic Import

import numpy as np
from scipy import linalg

def main():
    A = np.array([[1, 2], [3, 4]])

    # Both modules provide similar functions
    det_np = np.linalg.det(A)
    det_sp = linalg.det(A)

    print(f"NumPy det: {det_np}")
    print(f"SciPy det: {det_sp}")

if __name__ == "__main__":
    main()

2. Key Differences

Feature numpy.linalg scipy.linalg
Scope Core operations Comprehensive
Decompositions Basic (SVD, QR, Cholesky) Extended (LU, Schur, Hessenberg)
Matrix functions None expm, logm, sqrtm
Special matrices Limited Extensive
LAPACK access Indirect Direct
Sparse support No Via scipy.sparse.linalg

3. When to Use Which

import numpy as np
from scipy import linalg

def main():
    A = np.array([[4, 2], [2, 5]])

    # NumPy: simple operations
    eigvals_np = np.linalg.eigvals(A)
    print(f"NumPy eigvals: {eigvals_np}")

    # SciPy: more control and options
    eigvals_sp = linalg.eigvals(A)
    print(f"SciPy eigvals: {eigvals_sp}")

if __name__ == "__main__":
    main()

Extended Functionality

1. Decompositions

import numpy as np
from scipy import linalg

def main():
    A = np.array([[1, 2, 3],
                  [4, 5, 6],
                  [7, 8, 10]])

    # LU decomposition (SciPy only)
    P, L, U = linalg.lu(A)

    print("P (permutation):")
    print(P)
    print()
    print("L (lower):")
    print(L)
    print()
    print("U (upper):")
    print(U)

if __name__ == "__main__":
    main()

2. Matrix Functions

import numpy as np
from scipy import linalg

def main():
    A = np.array([[1, 2], [0, 1]])

    # Matrix exponential (SciPy only)
    exp_A = linalg.expm(A)

    print("A =")
    print(A)
    print()
    print("exp(A) =")
    print(exp_A)

if __name__ == "__main__":
    main()

3. Special Solvers

import numpy as np
from scipy import linalg

def main():
    # Triangular system (SciPy provides specialized solver)
    U = np.array([[2, 1, 3],
                  [0, 4, 2],
                  [0, 0, 5]])
    b = np.array([10, 14, 15])

    # Specialized triangular solver
    x = linalg.solve_triangular(U, b)

    print(f"x = {x}")
    print(f"Verify U @ x = {U @ x}")

if __name__ == "__main__":
    main()

LAPACK and BLAS Access

1. Low-Level Routines

import numpy as np
from scipy import linalg

def main():
    # Access LAPACK routines directly
    A = np.array([[1, 2], [3, 4]], dtype=float)

    # Get LAPACK function for LU factorization
    getrf = linalg.get_lapack_funcs('getrf', (A,))

    lu, piv, info = getrf(A)
    print(f"LU result:\n{lu}")
    print(f"Pivot indices: {piv}")
    print(f"Info: {info}")

if __name__ == "__main__":
    main()

2. BLAS Operations

import numpy as np
from scipy import linalg

def main():
    # Access BLAS for optimized operations
    x = np.array([1, 2, 3], dtype=float)
    y = np.array([4, 5, 6], dtype=float)

    # Get BLAS dot product function
    ddot = linalg.get_blas_funcs('dot', (x, y))

    result = ddot(x, y)
    print(f"BLAS dot product: {result}")
    print(f"NumPy dot product: {np.dot(x, y)}")

if __name__ == "__main__":
    main()

Recommendation

1. Use NumPy When

  • Basic operations (det, inv, solve, eig)
  • Minimizing dependencies
  • Simple scripts

2. Use SciPy When

  • Advanced decompositions (LU, Schur, Hessenberg)
  • Matrix functions (expm, logm, sqrtm)
  • Specialized solvers (triangular, banded)
  • Maximum performance via LAPACK

3. General Advice

# Recommended import pattern
import numpy as np
from scipy import linalg

# Use scipy.linalg as default for comprehensive functionality