Creating Quantum Programs
The HQS Noise App can create quantum programs to time propagate a spin state. The
QuantumProgram
will initialize a spin state on a quantum computer, time propagate the spin state
with a quantum algorithm and measure the values of spin observables. The initialization and measured
operators are defined by the user. The creation of quantum programs specifically for mixed systems is
discussed in more detail in the System Bath section.
The QuantumProgram
s can then be simulated using the Backend
class of the qoqo-QuEST package.
CNOT Algorithm
The QuantumProgram
s can be constructed using different algorithms. One choice offered by the HQS Noise App
is a parity-based algorithm, which we call the CNOT algorithm. It trotterizes the time evolution by
separating a Hamiltonian into a sum over Pauli-products. The time evolution under each Pauli-product
is simulated by:
- Rotating all involved qubits into the \(Z\) basis (by applying the Hadamard gate for \(X\) and
a
RotateX
for \(Y\). - Encoding the total parity of the involved qubits in the last involved qubits with the help of a chain of CNOT operations.
- Applying a
RotateZ
operation on the last qubit, rotating by twice the prefactor of thePauliProduct
. - Undoing the CNOT chain and basis rotations.
For the example of simulating \(\exp(-\textrm{i} g \sigma^x_0\sigma^x_2)\), the circuit looks like:
0 -H---o-------------------o----H--------
1 -----|-------------------|-------------
2 -H---x----RotateZ(2g)----x----H--------
An example of creating a circuit of a previously defined Hamiltonian and device is:
from hqs_noise_app import HqsNoiseApp
from struqture_py import spins
from qoqo import devices, noise_models
# define hamiltonian (transverse Ising Hamiltonian, with spin_coupling=0)
number_spins = 3
hamiltonian = spins.PauliHamiltonian()
for site in range(number_spins):
hamiltonian.set("{}Z".format(site), 1.0)
# Setting up the device.
single_qubit_gates = ["RotateX", "RotateZ", "RotateY"]
two_qubit_gates = ["CNOT"]
gate_times = 1.0
damping = 1e-3
device = devices.AllToAllDevice(
number_spins, single_qubit_gates, two_qubit_gates, gate_times
)
# While the noise model is not needed to generate the quantum program, it will be
# required when simulating the quantum program.
noise_model = noise_models.ContinuousDecoherenceModel().add_damping_rate(
[0, 1, 2], damping
)
# Create the quantum program. The function HqsNoiseApp() uses the CNOT algorithm by default
trotter_timestep=0.01
operators = []
operator_names = []
for i in range(number_spins):
operator = spins.PauliOperator()
operator.set(spins.PauliProduct().z(i), -0.5)
operator.set(spins.PauliProduct(), 0.5)
operators.append(operator)
operator_names.append("population_site_{}".format(i))
initialisation = [0.0 for _ in range(number_spins)]
noise_app_sc = HqsNoiseApp()
quantum_program = noise_app_sc.quantum_program(
hamiltonian, trotter_timestep, initialisation, operators, operator_names, device
)
# Printing the circuits of the QuantumProgram:
print(quantum_program.measurement().circuits())
QSWAP Algorithm
The QSWAP algorithm trotterizes the time evolution into sequences of nearest-neighbour interactions and quantum-state swaps. Using this approach, a quantum simulation of arbitrary two-body interactions can always be generated with linear depth. For the example of simulating arbitrary operation \(O_{02} = \exp(-\textrm{i} I_0I_2)\), the circuit looks like:
0 -----x-------------------x-----
SWAP SWAP
1 -----x--------x----------x-----
Operation 02
2 --------------x----------------
An example of creating a circuit from a previously defined Hamiltonian and device is:
from hqs_noise_app import HqsNoiseApp
from struqture_py import spins
from qoqo import devices, noise_models
# define hamiltonian (transverse Ising Hamiltonian, with spin_coupling=0)
number_spins = 3
hamiltonian = spins.PauliHamiltonian()
for site in range(number_spins):
hamiltonian.set("{}Z".format(site), 1.0)
# Setting up the device.
single_qubit_gates = ["RotateX", "RotateZ", "RotateY"]
two_qubit_gates = ["CNOT"]
gate_times = 1.0
damping = 1e-3
device = devices.AllToAllDevice(
number_spins, single_qubit_gates, two_qubit_gates, gate_times
)
# While the noise model is not needed to generate the quantum program, it will be
# required when simulating the quantum program.
noise_model = noise_models.ContinuousDecoherenceModel().add_damping_rate(
[0, 1, 2], damping
)
# Create circuit. The function HqsNoiseApp() uses the CNOT algorithm per default
trotter_timestep=0.01
operators = []
operator_names = []
for i in range(number_spins):
operator = spins.PauliOperator()
operator.set(spins.PauliProduct().z(i), -0.5)
operator.set(spins.PauliProduct(), 0.5)
operators.append(operator)
operator_names.append("population_site_{}".format(i))
initialisation = [0.0 for _ in range(number_spins)]
noise_app_sc = HqsNoiseApp()
noise_app_sc.algorithm = "QSWAP"
quantum_program = noise_app_sc.quantum_program(
hamiltonian, trotter_timestep, initialisation, operators, operator_names, device
)
# Printing the circuits of the QuantumProgram:
print(quantum_program.measurement().circuits())
System-Bath CNOT Algorithm
This is used for system-bath Hamiltonians. It assumes all-to-all connectivity. The creation of
Hamiltonians and circuits specific for mixed systems is discussed in more detail in the System
Bath section. The system-bath version of the CNOT algorithm tries to minimize bath
qubit rotations when performing XX or ZX type interactions between system and bath qubits. The
reason for this is to minimize large-angle rotations on bath qubits ,which we assume have stronger noise
than system qubits. This is possible for the relevant cases of XX and ZX type of interaction between
the system and the bath. Here, for the simulation of an a XX interaction between the spin qubit s
and the bath qubit
b1
, \(\exp(-\textrm{i} g \sigma^x_{s}\sigma^x_{b1})\), the circuit is chosen to be:
s -----o----RotateX(2g)----o-----
b0 -----|-------------------|-----
b1 -----x-------------------x-----
An example of creating a quantum program from a previously defined Hamiltonian (hamiltonian
) and a given device is:
logical_to_physical_system = {0: 0, 1: 1, 2: 3}
logical_to_physical_bath = {0: 4, 1: 5, 2: 7}
bath_qubit_connectivity = {0: [4, 5], 1: [5, 6], 3: [7, 8]}
noise_app_sc = HqsNoiseApp()
noise_app_sc.use_bath_as_control = False
quantum_program = noise_app_sc.system_bath_quantum_program(
hamiltonian,
trotter_timestep,
initialisation,
operators,
operator_names,
device,
logical_to_physical_system,
logical_to_physical_bath,
bath_qubit_connectivity,
)
The use_bath_as_control
option is to use bath qubits as control when solving system-bath
problems and interacting between system and bath qubits with CNOT operations as shown in the
circuit example above (affects the noise model, see examples).
System-Bath QSWAP Algorithm
The system-bath QSWAP algorithm trotterizes the time evolution into a sequence of nearest-neighbour
interactions in the system and following quantum-state SWAPs. It is assumed that each system
spin can have a nearest-neighbour bath qubit below and above (assuming 2D architecture). The bath
spins are not swapped. As the circuit is built, new system qubits are added to the circuit as
needed. So if we have a mixed system input with 1 system and 4 bath spins, the final circuit will have
6 qubits ordered as [bath0, bath1, system0, system1, bath3, bath4]. Here, simulating the original
model cross-coupling between spin-qubit s
and bath qubit b1
, \(\exp(-\textrm{i} g
\sigma^x_{s}\sigma^x_{b1})\), looks like this:
s0 -x---------------------------x-
SWAP SWAP
s1 -x---o----RotateX(2g)----o---x-
| |
b1 -----x-------------------x-----
An example of creating a quantum program from a Hamiltonian (H_mixed
) and a given device is:
trotter_timestep=0.01
quantum_program_mixed = noise_app.system_bath_quantum_program(
H_mixed, trotter_timestep, initialisation, operators, operator_names, device, None, None, None
)