Simulating the theory on a quantum computer
In [1] and [2], algorithms for simulating lattice scalar field lattice on a quantum computer was introduced. This can serve as a first example of simulating general lattice field theory on quantum computers.
The Hamiltonian under consideration is given by:
Here and satisfy the commutation relation:
To simulate it on a quantum computer, we need to discretize it so that the lattice Hamiltonian takes the form:
The lattice field operators satisfy:
Rescaling with and makes the field and the conjugate momentum dimensionless.
def get_qubit_label(in_site_label: int, site_label: int, n_phi_qubit: int) -> int:
"""Converts a local qubit index to the full system's qubit index.
in_site_label: The qubit label on the local site.
site_label: The label of the site.
n_phi_qubit: Number of qubits assigned to each site.
"""
return n_phi_qubit * site_label + in_site_label
In QURI Algo, we can define a subclass of Problem
containing the parameters that characterize the system. So, we define DiscreteScalarField1D
that represents the discrete scalar field Hamiltonian in 1 spatial dimension.
from quri_algo.problem import HamiltonianInput
from dataclasses import dataclass, field
import numpy as np
@dataclass
class DiscreteScalarField1D(HamiltonianInput):
"""Represents the Hamiltonian of the 1D scalar field:
Hamiltonian given by:
H = 1/2 Π_j^2 + 1/2 mb^2 Φ_j^2 + 1/2 (Φ_j - Φ_{j+1})^2 + λ/4! Φ_j^4 + J_j Φ.
Note:
1D here means 1 spatial dimension.
Args:
n_state_qubit
n_discretize: Number of points discretizing the field.
n_phi_qubit: Number of qubits per site.
mb: Boson mass.
lam: coupling costant of the phi^4 term.
external_field: External field strength J.
"""
n_state_qubit: int = field(init=False)
n_discretize: int
n_phi_qubit: int
mb: float
lam: float
external_field: float = 0.0
def __post_init__(self) -> None:
self.n_state_qubit = self.n_discretize * self.n_phi_qubit
@property
def n_phi_dimension(self) -> int:
return 2**self.n_phi_qubit
@property
def delta_phi(self) -> float:
return np.sqrt(2 * np.pi * self.mb / self.n_phi_dimension)
Discrete scalar field
The discrete scalar field is designed to satisfy the quantization condition:
where with being the number of qubits assigned to site . The site index will be suppressed from now and we adopt the conventions:
The discrete field operator on the site can be expressed as:
which can be implemented as a QURI Parts Operator
.
from quri_parts.core.operator import Operator, pauli_label
def get_scalar_field_operator(
site_label: int, n_phi_qubit: int, mass: float
) -> Operator:
phi = Operator({})
delta_phi = np.sqrt(2 * np.pi * mass / 2**n_phi_qubit)
for q in range(n_phi_qubit):
coeff = - delta_phi * 2**(q) / 2
l = get_qubit_label(q, site_label, n_phi_qubit)
phi.add_term(pauli_label(f"Z {l}"), coeff)
return phi
Example: Check that the operator satisfies the field operator quantization condition.
from quri_parts.core.state import quantum_state
from quri_parts.qulacs.estimator import create_qulacs_general_vector_estimator
site_label = 0
n_qubits = 4
mb = 1
estimator = create_qulacs_general_vector_estimator()
field_op = get_scalar_field_operator(site_label, n_qubits, mb)
b = 0b0101
estimator(field_op, quantum_state(n_qubits, bits=b)), (b - (2**n_qubits - 1)/2) * np.sqrt(2 * np.pi * mb / 2**n_qubits)
(_Estimate(value=(-1.5666426716443749+0j), error=0.0), -1.566642671644375)
Discrete conjugate momentum
The discrete conjugate momentum is defined as
The terms is defined as ( is suppressed.)
The eigenstate of the conjugate momentum operator is defined as:
where is the eigenstate of the field operator so that
The transformation is harder to be represented as a qubit operator. Instead, it can be represented as
with and QFT corresponds to the quantum Fourier transform:
Quantum Fourier Transform
The quantum Fourier transform can be performed by the following circuit
where
and the controlled U gate can be decomposed into CNOTs and U gates as:
Here denotes the controlled qubit and denotes the target qubit. This can be implemented in QURI Parts as:
from quri_parts.circuit import QuantumCircuit, NonParametricQuantumCircuit, ImmutableBoundParametricQuantumCircuit
import numpy as np
def add_controlled_U1_gate(
circuit: QuantumCircuit, control: int, target: int, angle: float
) -> None:
circuit.add_U1_gate(control, angle/2)
circuit.add_CNOT_gate(control, target)
circuit.add_U1_gate(target, -angle/2)
circuit.add_CNOT_gate(control, target)
circuit.add_U1_gate(target, angle/2)
Then the QFT circuit can be implemented with:
def create_qft_gate(qubit_count: int) -> ImmutableBoundParametricQuantumCircuit:
circuit = QuantumCircuit(qubit_count)
for i in range(qubit_count//2):
circuit.add_SWAP_gate(i, qubit_count-i-1)
for target in range(qubit_count):
circuit.add_H_gate(target)
for l, control in enumerate(range(target+1, qubit_count)):
angle = 2 * np.pi/2**(l+2)
add_controlled_U1_gate(circuit, control, target, angle)
return circuit.freeze()
Example: execute the quantum Fourier transform
from quri_parts.qulacs.simulator import evaluate_state_to_vector
n_qubits = 4
n = 2**n_qubits
QFT = create_qft_gate(n_qubits)
for b in range(n):
qft_state = quantum_state(n_qubits, circuit=QFT, bits=b)
qft_state_vector = evaluate_state_to_vector(qft_state).vector
expected_qft_vector = np.array([np.exp(2j * np.pi / n * i * b) for i in range(n)]) / np.sqrt(n)
assert np.allclose(qft_state_vector, expected_qft_vector)