BlockEncoding.kron#

BlockEncoding.kron(other: BlockEncoding) BlockEncoding[source]#

Returns a BlockEncoding of the Kronecker product (tensor product) of two operators.

This method implements the operator \(A \otimes B\), where \(A\) and \(B\) are the operators encoded by the respective instances. Following the construction in Chapter 10.2 in Dalzell et al., the resulting BlockEncoding is formed by the tensor product of the underlying unitaries, \(U_A \otimes U_B\).

Parameters:
otherBlockEncoding

The BlockEncoding instance to be tensored.

Returns:
BlockEncoding

A new BlockEncoding representing the tensor product \(A \otimes B\).

Notes

  • Normalization: The normalization factors (\(\alpha\)) are combined multiplicatively.

  • The kron operator maps the operands of self to the first set of operands and the operands of other to the remaining operands in a single unified unitary.

  • The kron operator should be used sparingly, primarily to combine a few block encodings.

  • A more qubit-efficient implementation of the Kronecker product can be found in this paper and will be implemented in future updates.

Examples

Example 1:

Define two block-encodings and perform their Kronecker product.

from qrisp import *
from qrisp.block_encodings import BlockEncoding
from qrisp.operators import X, Y, Z

H1 = X(0)*X(1) + 0.2*Y(0)*Y(1)
H2 = Z(0)*Z(1) + X(2)

BE1 = BlockEncoding.from_operator(H1)
BE2 = BlockEncoding.from_operator(H2)

BE_composed = BE1.kron(BE2)

n1 = H1.find_minimal_qubit_amount()
n2 = H2.find_minimal_qubit_amount()

def operand_prep():
    qv1 = QuantumVariable(n1)
    qv2 = QuantumVariable(n2)
    return qv1, qv2

@terminal_sampling
def main(BE):
    return BE.apply_rus(operand_prep)()

result = main(BE_composed)
print("Result from BE1.kron(BE2): ", result)

Example 2:

Perform multiple Kronecker products of block-encodings in sequence.

from qrisp import *
from qrisp.operators import X, Y, Z

H1 = X(0)*X(1)
H2 = Z(0)*Z(1)
H3 = Y(0)*Y(1)

BE1 = BlockEncoding.from_operator(H1)
BE2 = BlockEncoding.from_operator(H2)
BE3 = BlockEncoding.from_operator(H3)

# Compose BE1 with the composition of BE2 and BE3
BE_composed = BE1.kron(BE2.kron(BE3))

n1 = H1.find_minimal_qubit_amount()
n2 = H2.find_minimal_qubit_amount()
n3 = H3.find_minimal_qubit_amount()

def operand_prep():
    qv1 = QuantumVariable(n1)
    qv2 = QuantumVariable(n2)
    qv3 = QuantumVariable(n3)
    return qv1, qv2, qv3

@terminal_sampling
def main(BE):
    return BE.apply_rus(operand_prep)()

result = main(BE_composed)
print("Result from BE1.kron(BE2.kron(BE3)): ", result)