TheAlgorithms/Python · error · ValueError

Expected the same number of rows for A and B. Instead found

Error message

Expected the same number of rows for A and B. Instead found A of size {shape_a} and B of size {shape_b}

What it means

Raised by schur_complement when the number of rows of block matrix A differs from the number of rows of block matrix B. The function computes C - B.T @ inv(A) @ B, which requires A (p x p) and B (p x q) to share the row dimension p; a mismatch means the blocks cannot form a valid 2x2 block matrix.

Source

Thrown at linear_algebra/src/schur_complement.py:40

    >>> import numpy as np
    >>> a = np.array([[1, 2], [2, 1]])
    >>> b = np.array([[0, 3], [3, 0]])
    >>> c = np.array([[2, 1], [6, 3]])
    >>> schur_complement(a, b, c)
    array([[ 5., -5.],
           [ 0.,  6.]])
    """
    shape_a = np.shape(mat_a)
    shape_b = np.shape(mat_b)
    shape_c = np.shape(mat_c)

    if shape_a[0] != shape_b[0]:
        msg = (
            "Expected the same number of rows for A and B. "
            f"Instead found A of size {shape_a} and B of size {shape_b}"
        )
        raise ValueError(msg)

    if shape_b[1] != shape_c[1]:
        msg = (
            "Expected the same number of columns for B and C. "
            f"Instead found B of size {shape_b} and C of size {shape_c}"
        )
        raise ValueError(msg)

    a_inv = pseudo_inv
    if a_inv is None:
        try:
            a_inv = np.linalg.inv(mat_a)
        except np.linalg.LinAlgError:
            raise ValueError(
                "Input matrix A is not invertible. Cannot compute Schur complement."
            )

    return mat_c - mat_b.T @ a_inv @ mat_b

View on GitHub (pinned to f5988cc097)

Solutions

  1. Check the shapes before calling: assert mat_a.shape[0] == mat_b.shape[0].
  2. Re-derive or re-slice B so it has exactly as many rows as A; if you have B.T stored, pass its transpose.
  3. Verify your block partition of the full matrix M = [[A, B], [B.T, C]] is consistent.

Example fix

# before
a = np.ones((2, 2)); b = np.ones((3, 2)); c = np.eye(2)
schur_complement(a, b, c)

# after
a = np.ones((2, 2)); b = np.ones((2, 2)); c = np.eye(2)
schur_complement(a, b, c)
Defensive patterns

Strategy: validation

Validate before calling

if mat_a.shape[0] != mat_b.shape[0]:
    raise ValueError(f"A rows {mat_a.shape[0]} != B rows {mat_b.shape[0]}")
result = schur_complement(mat_a, mat_b, mat_c)

Type guard

def blocks_row_aligned(a: np.ndarray, b: np.ndarray) -> bool:
    return a.ndim == 2 and b.ndim == 2 and a.shape[0] == b.shape[0]

Try / catch

try:
    schur_complement(a, b, c)
except ValueError as e:
    if "number of rows" in str(e):
        b = b[: a.shape[0]]  # only if truncation is semantically correct
        schur_complement(a, b, c)

Prevention

When it happens

Trigger: Calling schur_complement(a, b, c) with np.shape(mat_a)[0] != np.shape(mat_b)[0], e.g. A is 2x2 and B is 3x2 (error message reports the concrete shapes).

Common situations: Assembling blocks from separately computed matrices (e.g. covariance blocks estimated from data subsets with different sample counts), off-by-one slicing errors, or transposing B by mistake when constructing the partitioned matrix.

Related errors


AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14). Data as JSON: /api/errors/55601fd6e6facf3d. Report an issue: GitHub.