qrisp.gqsp.GQET#
- GQET(H: BlockEncoding | FermionicOperator | QubitOperator, p: ArrayLike, kind: Literal['Polynomial', 'Chebyshev'] = 'Polynomial', rescale: bool = True) BlockEncoding[source]#
Returns a BlockEncoding representing a polynomial transformation of the operator via Generalized Quantum Eigenvalue Transform.
For a block-encoded Hermitian operator \(H\) and a (complex) polynomial \(p(z)\), this method returns a BlockEncoding of the operator \(p(H)\).
The Quantum Eigenvalue Transform is described as follows:
Given a Hermitian operator \(H=\sum_i\lambda_i\ket{\lambda_i}\bra{\lambda_i}\) where \(\lambda_i\in\mathbb R\) are the eigenvalues for the eigenstates \(\ket{\lambda_i}\),
A quantum state \(\ket{\psi}=\sum_i\alpha_i\ket{\lambda_i}\) where \(\alpha_i\in\mathbb C\) are the amplitudes for the eigenstates \(\ket{\lambda_i}\),
A (complex) polynomial \(p(z)\),
this transformation prepares a state proportional to
\[p(H)\ket{\psi}=\sum_i p(\lambda_i)\ket{\lambda_i}\bra{\lambda_i}\sum_j\alpha_j\ket{\lambda_j}=\sum_i p(\lambda_i)\alpha_i\ket{\lambda_i}\]- Parameters:
- HBlockEncoding | FermionicOperator | QubitOperator
The Hermitian operator to be transformed.
- pArrayLike
1-D array containing the polynomial coefficients, ordered from lowest order term to highest.
- kind{“Polynomial”, “Chebyshev”}
The basis in which the coefficients are defined.
"Polynomial": \(p(x) = \sum c_i x^i\)"Chebyshev": \(p(x) = \sum c_i T_i(x)\), where \(T_i\) are Chebyshev polynomials of the first kind.
Default is
"Polynomial".- rescalebool
If True (default), the method returns a block-encoding of \(p(H)\). If False, the method returns a block-encoding of \(p(H/\alpha)\) where \(\alpha\) is the normalization factor for the block-encoding of the operator \(H\).
- Returns:
- BlockEncoding
A new BlockEncoding instance representing the transformed operator \(p(H)\).
Examples
Define a Heisenberg Hamiltonian and apply a polynomial \(p(H)\) to an initial system state.
from qrisp import * from qrisp.gqsp import * from qrisp.operators import X, Y, Z from qrisp.vqe.problems.heisenberg import create_heisenberg_init_function import numpy as np import networkx as nx def generate_1D_chain_graph(L): graph = nx.Graph() graph.add_edges_from([(k, (k+1)%L) for k in range(L-1)]) return graph # Define Heisenberg Hamiltonian L = 10 G = generate_1D_chain_graph(L) H = sum((X(i)*X(j) + Y(i)*Y(j) + Z(i)*Z(j)) for i,j in G.edges()) M = nx.maximal_matching(G) U0 = create_heisenberg_init_function(M) # Define initial state preparation function def psi_prep(): operand = QuantumVariable(H.find_minimal_qubit_amount()) U0(operand) return operand # Calculate the energy E = H.expectation_value(psi_prep, precision=0.001)() print(E)
Define a polynomial and use GQET to obtain a BlockEncoding of \(p(H)\).
poly = jnp.array([1., 2., 1.]) BE = GQET(H, poly, kind="Polynomial") def transformed_psi_prep(): operand = BE.apply_rus(psi_prep)() return operand
Calculate the expectation value of \(H\) for the transformed state \(p(H)\ket{\psi}\).
@jaspify(terminal_sampling=True) def main(): E = H.expectation_value(transformed_psi_prep, precision=0.001)() return E print(main()) # -16.67236953920006
Finally, we compare the quantum simulation to the classically calculated result:
# Calculate energy for |psi_0> H_arr = H.to_array() psi_0 = psi_prep().qs.statevector_array() E_0 = (psi_0.conj() @ H_arr @ psi_0).real print("E_0", E_0) # Calculate energy for |psi> = poly(H) |psi0> I = np.eye(H_arr.shape[0]) psi = (I + H_arr) @ (I + H_arr) @ psi_0 psi = psi / np.linalg.norm(psi) E = (psi.conj() @ H_arr @ psi).real print("E", E)