Source code for qrisp.block_encodings.constructors.from_array
# ********************************************************************************
# * Copyright (c) 2026 the Qrisp authors
# *
# * This program and the accompanying materials are made available under the
# * terms of the Eclipse Public License 2.0 which is available at
# * http://www.eclipse.org/legal/epl-2.0.
# *
# * This Source Code may also be made available under the following Secondary
# * Licenses when the conditions for such availability set forth in the Eclipse
# * Public License, v. 2.0 are satisfied: GNU General Public License, version 2
# * with the GNU Classpath Exception which is
# * available at https://www.gnu.org/software/classpath/license.html.
# *
# * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
# ********************************************************************************
"""Builds a BlockEncoding from a dense or sparse 2-D array via Pauli decomposition."""
from typing import Any, Union
import numpy.typing as npt
from scipy.sparse import csr_array, csr_matrix
from qrisp.block_encodings.block_encoding_base import BlockEncoding
from qrisp.block_encodings.constructors.from_operator import build_from_operator
from qrisp.operators import QubitOperator
MatrixType = Union[npt.NDArray[Any], csr_array, csr_matrix]
def build_from_array(cls: type[BlockEncoding], A: MatrixType) -> BlockEncoding:
r"""Constructs a BlockEncoding from a 2-D array.
Parameters
----------
cls : type[BlockEncoding]
The class on which this constructor is invoked.
A : ndarray | csr_array | csr_matrix
2-D array of shape ``(N,N,)`` for a power of two ``N``.
Returns
-------
BlockEncoding
A BlockEncoding representing the Hermitian part $(A+A^{\dagger})/2$.
Raises
------
ValueError
If ``A`` is not a 2-D square matrix.
ValueError
If the dimension of ``A`` is not a power of two.
Notes
-----
- Block encoding based on Pauli decomposition $O=\sum_i\alpha_i P_i$ where $\alpha_i$ are real positive coefficients
and $P_i$ are Pauli strings (including the respective sign).
- **Normalization**: The block-encoding normalization factor is $\alpha = \sum_i \alpha_i$.
Examples
--------
>>> import numpy as np
>>> from qrisp.block_encodings import BlockEncoding
>>> A = np.array([[0,1,0,1],[1,0,0,0],[0,0,1,0],[1,0,0,0]])
>>> B = BlockEncoding.from_array(A)
"""
shape = A.shape
# 1. Check if the array is 2D and square
if len(shape) != 2 or shape[0] != shape[1]:
raise ValueError(f"Array must be square (N, N), but got {shape}.")
# 2. Check if N is a power of two
N = shape[0]
if not (N > 0 and (N & (N - 1)) == 0):
raise ValueError(f"Size N={N} must be a power of two.")
O = QubitOperator.from_matrix(A, reverse_endianness=True)
return build_from_operator(cls, O)