Source code for PhaseEstimation.general

"""Module for generic functions for other modules"""
import pennylane as qml
from pennylane import numpy as np
import jax
import jax.numpy as jnp

from typing import List, Tuple, Union
from numbers import Number


[docs]def linalgeigh(mat_H: List[List[Number]]) -> Tuple[int, List[Number]]: """ Apply jax np.linalg.eigh on a matrix, to be jitted Parameters ---------- mat_H : np.ndarray Input matrix to apply np.linalg.eigh Returns ------- np.ndarray Array of eigenvalues (not sorted) np.ndarray Array of relative eigenvectors """ # Compute eigenvalues and eigenvectors eigval, eigvec = jnp.linalg.eigh(mat_H) return eigval, eigvec
j_linalgeigh = jax.jit(linalgeigh)
[docs]def geteigvals( qml_H: qml.ops.qubit.hamiltonian.Hamiltonian, states: List[int] ) -> List[Number]: """ Function for getting the energy values of an Ising Hamiltonian using the jitted jnp.linalg.eigh function Parameters ---------- qml_H : pennylane.ops.qubit.hamiltonian.Hamiltonian Pennylane Hamiltonian of the state states : list List of energy levels desired Returns ------- list List of energy values """ # Get the matricial for of the hamiltonian # and convert it to float32 # This type of hamiltonians are always real mat_H = np.real(qml.matrix(qml_H)).astype(np.single) # Compute sorted eigenvalues with jitted function eigvals = jnp.sort(j_linalgeigh(mat_H)[0]) return [eigvals[k] for k in states]
[docs]def get_H_eigval_eigvec( qml_H: qml.ops.qubit.hamiltonian.Hamiltonian, en_lvl: int ) -> Tuple[List[List[Number]], Number, List[Number]]: """ Function for getting the energy value and state of an Ising Hamiltonian using the jitted jnp.linalg.eigh function Parameters ---------- qml_H : pennylane.ops.qubit.hamiltonian.Hamiltonian Pennylane Hamiltonian of the state en_lvl : int Energy level desired Returns ------- np.ndarray Matricial encoding of the Hamiltonian float Value of the energy level np.ndarray Eigenstate of the energy level """ # Get the matricial for of the hamiltonian # and convert it to float32 # This type of hamiltonians are always real mat_H = np.real(qml.matrix(qml_H)).astype(np.single) # Compute sorted eigenvalues with jitted function eigvals, eigvecs = j_linalgeigh(mat_H) psi = eigvecs[:, jnp.argsort(eigvals)[en_lvl]] en = jnp.sort(eigvals)[en_lvl] return mat_H, en, psi
[docs]def psi_outer(psi: List[Number]) -> List[List[Number]]: return jnp.outer(jnp.conj(psi), psi)
j_psi_outer = jax.jit(psi_outer) jv_psi_outer = jax.jit(jax.vmap(psi_outer))
[docs]def get_VQE_params( qml_H: qml.ops.qubit.hamiltonian.Hamiltonian, ) -> Tuple[List[List[Number]], Number]: """ Function for getting all the training parameter for the VQE algorithm Parameters ---------- qml_H : pennylane.ops.qubit.hamiltonian.Hamiltonian Pennylane Hamiltonian of the state Returns ------- np.ndarray Matricial encoding of the Hamiltonian float Ground-state energy value """ # Get the matricial for of the hamiltonian # and convert it to float32 # This type of hamiltonians are always real mat_H = np.real(qml.matrix(qml_H)).astype(np.single) # Compute sorted eigenvalues with jitted function eigvals = j_linalgeigh(mat_H)[0] en0 = jnp.sort(eigvals)[0] return jnp.array([mat_H]), en0
[docs]def get_VQD_params( qml_H: qml.ops.qubit.hamiltonian.Hamiltonian, beta: Number ) -> Tuple[List[List[Number]], List[List[Number]], Number]: """ Function for getting all the training parameter for the VQD algorithm for finding the first excited state Parameters ---------- qml_H : pennylane.ops.qubit.hamiltonian.Hamiltonian Pennylane Hamiltonian of the Ising Model Returns ------- np.ndarray Matricial encoding of the Hamiltonian np.ndarray Effective Hamiltonian of VQD algorithm float Excited-state energy value """ # Get the matricial for of the hamiltonian # and convert it to float32 # This type of hamiltonians are always real mat_H = np.real(qml.matrix(qml_H)).astype(np.single) # Compute sorted eigenvalues with jitted function eigvals, eigvecs = j_linalgeigh(mat_H) psi0 = eigvecs[:, jnp.argsort(eigvals)[0]] en_ex = jnp.sort(eigvals)[1] return jnp.array([mat_H]), jnp.array([mat_H + beta * j_psi_outer(psi0)]), en_ex
[docs]def paraanti(x): return 1.05 * np.sqrt((x - 0.5) * (x - 0.1))
[docs]def paraferro(x): return ((1 - x) / x) * (1 - np.sqrt((1 - 3 * x + 4 * x * x) / (1 - x)))
[docs]def b1(x): return 1.05 * (x - 0.5)
[docs]def peshel_emery(x): y = (1 / (4 * x)) - x y[y > 2] = 2 return y
[docs]def simple_to_idx(simple: int, side: int) -> Union[int, None]: if simple <= 2 * side - 1: if simple <= side: return simple else: return side * (simple % side + 1) return None