Sample Job

We take the same example (simple Bell pair circuit) in the Getting Started page to illustrate this case.

The Job is created from a circuit using the circuit’s to_job() method, which by default use SAMPLE processing type. It is then fed to the QPU’s submit method, which returns a Result object. In SAMPLE mode, this result can be iterated on, yielding the various “samples”, with each sample corresponding to a given bitstring (state) and its frequency of appearance (probability) upon conducting a Z measurement over the final state \(|\psi\rangle\). States with zero probability are not listed (one can set a threshold amp_threshold to filter out states below a certain probability amplitude).

from qat.lang.AQASM import Program, H, CNOT
from qat.qpus import get_default_qpu

# Create a circuit
qprog = Program()
qbits = qprog.qalloc(2)
H(qbits[0])
CNOT(qbits[0], qbits[1])
circuit = qprog.to_circ()

# Create a job
job = circuit.to_job() # no parameters, equivalent to "nbshots=0"

# Execute
result = get_default_qpu().submit(job)
for sample in result:
    print("State %s: probability %s, amplitude %s" % (sample.state, sample.probability, sample.amplitude))
State |00>: probability 0.4999999999999999, amplitude (0.7071067811865475+0j)
State |11>: probability 0.4999999999999999, amplitude (0.7071067811865475+0j)

Here, we also print the probability amplitude corresponding to each computational basis state. However, this piece of information is in general not available from an actual QPU, but merely from some classical simulators.

from qat.lang.AQASM import Program, H, CNOT
from qat.qpus import get_default_qpu

# Create a circuit
qprog = Program()
qbits = qprog.qalloc(2)
H(qbits[0])
CNOT(qbits[0], qbits[1])
circuit = qprog.to_circ()

# Create a job
job = circuit.to_job(nbshots=100)

# Execute
result = get_default_qpu().submit(job)
for sample in result:
    print("State %s: probability %s +/- %s" % (sample.state, sample.probability, sample.err))
State |00>: probability 0.54 +/- 0.050090826596203314
State |11>: probability 0.46 +/- 0.050090826596203314

We can see that the estimated probability of the states differs from the ideal one due to “shot noise”. The err field of the sample object contains the standard error of the mean on the appearance frequency of the state. It decreases as \(1/\sqrt{n_\mathrm{shots}}\).

Here, we decide to measure only the second qubit:

from qat.lang.AQASM import Program, H, CNOT
from qat.qpus import get_default_qpu

# Create a circuit
qprog = Program()
qbits = qprog.qalloc(2)
H(qbits[0])
CNOT(qbits[0], qbits[1])
circuit = qprog.to_circ()

# Create a job
job = circuit.to_job(nbshots=0, qubits=[1])

# Execute
result = get_default_qpu().submit(job)
for sample in result:
    print("State %s: probability %s +/- %s" % (sample.state, sample.probability, sample.err))
State |0>: probability 0.4999999999999999 +/- None
State |1>: probability 0.4999999999999999 +/- None

As expected, the probability of measuring “0” on the second qubit is the same as the probability of measuring “1”. Here, err is None because we took an infinite number of shots.