qml.qsvt¶
- qsvt(A, poly, encoding_wires=None, block_encoding=None, **kwargs)[source]¶
Implements the Quantum Singular Value Transformation (QSVT) for a matrix or Hamiltonian
A
, using a polynomial defined bypoly
and a block encoding specified byblock_encoding
.\[\begin{split}\begin{pmatrix} A & * \\ * & * \\ \end{pmatrix} \xrightarrow{QSVT} \begin{pmatrix} \text{poly}(A) + i \dots & * \\ * & * \\ \end{pmatrix}\end{split}\]The polynomial transformation is encoded as the real part of the top left term after applying the operator.
This function calculates the required phase angles from the polynomial using
poly_to_angles()
.Note
The function
poly_to_angles
, used withinqsvt
, is not JIT-compatible, which preventspoly
from being traceable inqsvt
. However,A
is traceable and can be optimized by JIT within this function.- Parameters
A (Union[tensor_like, Operator]) – The matrix on which the QSVT will be applied. This can be an array or an object that has a Pauli representation. See
pauli_decompose()
.poly (tensor_like) – coefficients of the polynomial ordered from lowest to highest power
encoding_wires (Sequence[int]) – The qubit wires used for the block encoding. See Usage Details below for more information on
encoding_wires
depending on the block encoding used.block_encoding (str) –
Specifies the type of block encoding to use. Options include:
"prepselprep"
: Embeds the HamiltonianA
usingPrepSelPrep
. Default encoding for Hamiltonians."qubitization"
: Embeds the HamiltonianA
usingQubitization
."embedding"
: Embeds the matrixA
usingBlockEncode
. Template not hardware compatible. Default encoding for matrices."fable"
: Embeds the matrixA
usingFABLE
. Template hardware compatible.
- Returns
A quantum operator implementing QSVT on the matrix
A
with the specified encoding and projector phases.- Return type
(Operator)
See also
Example:
# P(x) = -x + 0.5 x^3 + 0.5 x^5 poly = np.array([0, -1, 0, 0.5, 0, 0.5]) hamiltonian = qml.dot([0.3, 0.7], [qml.Z(1), qml.X(1) @ qml.Z(2)]) dev = qml.device("default.qubit") @qml.qnode(dev) def circuit(): qml.qsvt(hamiltonian, poly, encoding_wires=[0], block_encoding="prepselprep") return qml.state() matrix = qml.matrix(circuit, wire_order=[0, 1, 2])()
>>> print(matrix[:4, :4].real) [[-0.1625 0. -0.3793 0. ] [ 0. -0.1625 0. 0.3793] [-0.3793 0. 0.1625 0. ] [ 0. 0.3793 0. 0.1625]]
Usage Details
If the input
A
is a Hamiltonian, the validblock_encoding
values are"prepselprep"
and"qubitization"
. In this case,encoding_wires
refers to thecontrol
parameter in the templatesPrepSelPrep
andQubitization
, respectively. These wires represent the auxiliary qubits necessary for the block encoding of the Hamiltonian. The number ofencoding_wires
required must be \(\lceil \log_2(m) \rceil\), where \(m\) is the number of terms in the Hamiltonian.# P(x) = -1 + 0.2 x^2 + 0.5 x^4 poly = np.array([-1, 0, 0.2, 0, 0.5]) hamiltonian = qml.dot([0.3, 0.4, 0.3], [qml.Z(2), qml.X(2) @ qml.Z(3), qml.X(2)]) dev = qml.device("default.qubit") @qml.qnode(dev) def circuit(): qml.qsvt(hamiltonian, poly, encoding_wires=[0, 1], block_encoding="prepselprep") return qml.state() matrix = qml.matrix(circuit, wire_order=[0, 1, 2, 3])()
>>> print(np.round(matrix[:4, :4], 4).real) [[-0.7158 0. 0. 0. ] [ 0. -0.975 0. 0. ] [ 0. 0. -0.7158 0. ] [ 0. -0. 0. -0.975 ]]
Alternatively, if the input
A
is a matrix, the valid values forblock_encoding
are"embedding"
and"fable"
. In this case, theencoding_wires
parameter corresponds to thewires
attribute in the templatesBlockEncode
andFABLE
, respectively. Note that for QSVT to work, the input matrix must be Hermitian.# P(x) = -1 + 0.2 x^2 + 0.5 x^4 poly = np.array([-0.1, 0, 0.2, 0, 0.5]) A = np.array([[-0.1, 0, 0, 0.1], [0, 0.2, 0, 0], [0, 0, -0.2, -0.2], [0.1, 0, -0.2, -0.1]]) dev = qml.device("default.qubit") @qml.qnode(dev) def circuit(): qml.qsvt(A, poly, encoding_wires=[0, 1, 2, 3, 4], block_encoding="fable") return qml.state() matrix = qml.matrix(circuit, wire_order=[0, 1, 2, 3, 4])()
>>> print(np.round(matrix[:4, :4], 4).real) [[-0.0954 0. -0.0056 -0.0054] [ 0. -0.0912 -0. -0. ] [-0.0056 0. -0.0788 0.0164] [-0.0054 -0. 0.0164 -0.0842]]
Note that for the FABLE block encoding to function correctly, it must comply with the following:
\[d \|A\|^2 \leq 1,\]where \(d\) is the maximum dimension of \(A\) and \(\|A\|\) is the 2-norm of \(A\). In the previous example this is satisfied since \(d = 4\) and \(\|A\|^2 = 0.2\):
>>> print(4* np.linalg.norm(A, ord='fro')**2) 0.8000000000000004