Executing Quantum Circuits

One can excute CUDA Quantum kernels via the sample and observe function calls.

Quantum states collapse upon measurement and hence need to be sampled from many times to gather statistics. The CUDA Quantum sample call enables this:

Sample

[3]:
import cudaq

qubit_count = 2

# Define the simulation target.
cudaq.set_target("qpp-cpu")

# Define a quantum kernel function.
kernel = cudaq.make_kernel()

# Allocate our `qubit_count` to the kernel.
qubits = kernel.qalloc(qubit_count)

# 2-qubit GHZ state.
kernel.h(qubits[0])
for i in range(1, qubit_count):
    kernel.cx(qubits[0], qubits[i])

# If we dont specify measurements, all qubits are measured in
# the Z-basis by default.
kernel.mz(qubits)

result = cudaq.sample(kernel, shots_count=1000)

result.dump()
{ 00:490 11:510 }

In simulation mode, the quantum state is built once and then sampled from \(s\) times where \(s\) equals the shots_count . In hardware execution mode, the quantum state collapses upon measurement and hence needs to be rebuilt over and over again.

Observe

observe allows us to gather qubit statistics and calculate expectation values. We must supply a spin operator in the form of a hamiltonian from which we would like to calculate \(\bra{\psi}H\ket{\psi}\).

[32]:
import cudaq
from cudaq import spin

qubit_count = 2

# Define the simulation target.
cudaq.set_target("qpp-cpu")

# Define a quantum kernel function.
kernel = cudaq.make_kernel()

# Allocate our `qubit_count` to the kernel.
qubits = kernel.qalloc(qubit_count)

# 2-qubit GHZ state.
kernel.h(qubits[0])

for i in range(1, qubit_count):
    kernel.cx(qubits[0], qubits[i])

# Define a Hamiltonian in terms of Pauli Spin operators.
hamiltonian = spin.z(0) + spin.y(1) + spin.x(0) * spin.z(0)

# Compute the expectation value given the state prepared by the kernel.
result = cudaq.observe(kernel, hamiltonian).expectation()

print('<H> =', result)
<H> = 0.0