Source code for sdplab.linalg.dense._kron

# Copyright 2026 Pavlo Pelikh
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import annotations

from functools import reduce
from typing import Sequence

from spacecore import Context, DenseArray


[docs] def kron_prod(ctx: Context, factors: Sequence[DenseArray]) -> DenseArray: r""" Return the left-folded Kronecker product. For matrices :math:`A_1,\ldots,A_n`, this computes .. math:: A_1 \otimes A_2 \otimes \cdots \otimes A_n. If ``A_i`` acts on a local vector space ``V_i``, the result acts on the tensor product space :math:`V_1 \otimes \cdots \otimes V_n`. """ return reduce(lambda a, b: ctx.ops.kron(a, b), factors)
[docs] def kron_sum(ctx: Context, blocks: DenseArray) -> DenseArray: r"""Return :math:`\mathcal{A}^\dagger y` for one-body blocks ``blocks``. If ``blocks[k]`` represents :math:`y_k \in \operatorname{Herm}(d)`, then ``blocks`` represents :math:`y = (y_0, \ldots, y_{N-1}) \in \operatorname{cod}(\mathcal{A})`. The result is the matrix in :math:`\operatorname{dom}(\mathcal{A})` .. math:: \mathcal{A}^\dagger y = y_0 \oplus \cdots \oplus y_{N-1} = \sum_k I \otimes \cdots \otimes y_k \otimes \cdots \otimes I. """ ops = ctx.ops dtype = ctx.dtype N, d = blocks.shape[:2] I = ops.eye(d, dtype=dtype) D = d ** N K = ops.zeros((D, D), dtype=dtype) for k in range(N): factors = [I] * N factors[k] = blocks[k] K = K + kron_prod(ctx, factors) return K