BlockEncoding.from_lcu#
- classmethod BlockEncoding.from_lcu(coeffs: ndarray[tuple[Any, ...], dtype[number]], unitaries: list[Callable[[...], Any]], num_ops: int = 1, is_hermitian: bool = False) BlockEncoding[source]#
Constructs a BlockEncoding using the Linear Combination of Unitaries (LCU) protocol.
For an LCU block encoding, consider a linear combination of unitaries:
\[O = \sum_{i=0}^{M-1} \alpha_i U_i\]where \(\alpha_i\) are real non-negative coefficients such that \(\sum_i \alpha_i = \alpha\), and \(U_i\) are unitaries acting on the same operand quantum variables.
The block encoding unitary is constructed via the LCU protocol:
\[U = \text{PREP} \cdot \text{SEL} \cdot \text{PREP}^{\dagger}\]where:
SEL (Select, in Qrisp: q_switch) applies each unitary \(U_i\) conditioned on the auxiliary variable state \(\ket{i}_a\):
\[\text{SEL} = \sum_{i=0}^{M-1} \ket{i}\bra{i} \otimes U_i\]PREP (Prepare) prepares the state representing the coefficients:
\[\text{PREP} \ket{0}_a = \sum_{i=0}^{M-1} \sqrt{\frac{\alpha_i}{\alpha}} \ket{i}_a\]- Parameters:
- coeffsArrayLike
1-D array of non-negative coefficients \(\alpha_i\).
- unitarieslist[Callable]
List of functions, where each
U(*operands)applies a unitary transformation in-place to the provided quantum variables. All functions must accept the same signature and operate on the same set of operands.- num_opsint
The number of operand quantum variables. The default is 1.
- is_hermitianbool
Indicates whether the block-encoding unitary is Hermitian. The default is False. Set to True, if all provided unitaries are Hermitian.
- Returns:
- BlockEncoding
A BlockEncoding using LCU.
- Raises:
- ValueError
If any entry in
coeffsis negative, as the LCU protocol only supports positive coefficients.
Notes
Normalization: The block-encoding normalization factor is \(\alpha = \sum_i \alpha_i\).
Examples
from qrisp import * from qrisp.block_encodings import BlockEncoding def f0(x): x-=1 def f1(x): x+=1 BE = BlockEncoding.from_lcu(np.array([1., 1.]), [f0, f1]) @terminal_sampling def main(): return BE.apply_rus(lambda : QuantumFloat(2))() main() # {1.0: 0.5, 3.0: 0.5}