In this tutorial, we will see how to run code on IBM Q devices directly from within ProjectQ. All that is needed is an IBM Q Experience user account. To sign up, visit https://quantumexperience.ng.bluemix.net/.
ProjectQ supports two IBM Q devices called ibmqx4
and ibmqx5
which feature 5 and 16 qubits, respectively. Let us start with entangling the qubits of the 5-qubit device:
First, we import all necessary operations (Entangle
, measurement), the back-end (IBMBackend
), and the main compiler engine (MainEngine
). The Entangle operation is defined as a Hadamard gate on the first qubit (creates an equal superposition of |0> and |1>), followed by controlled NOT gates acting on all other qubits controlled on the first.
In [ ]:
%matplotlib inline
import matplotlib.pyplot as plt
In [1]:
import projectq.setups.ibm
from projectq.backends import IBMBackend
from projectq.ops import Measure, Entangle, All
from projectq import MainEngine
Next, we instantiate a main compiler engine using the IBM Q back-end and the predefined compiler engines which take care of the qubit placement, translation of operations, etc.:
In [2]:
eng = MainEngine(IBMBackend(use_hardware=True, num_runs=1024,
verbose=False, device='ibmqx4'),
engine_list=projectq.setups.ibm.get_engine_list())
If use_hardware
is set to False
, it will use the IBM Q simulator instead. num_runs
specifies the number of samples to collect for statistics, verbose=True
would output additional information which may be helpful for debugging, and the device parameter lets users choose between the two devices ("ibmqx4" and "ibmqx5").
With our compiler set up, we can now allocate our qubits, entangle them, measure the outcome, and then flush the entire circuit down the compilation pipeline such that it is executed (and measurements are registered). Note that there are many jobs queued for execution on the IBM Q device and, as a result, our execution times out. We will learn how to retrieve our results despite this time out.
In [3]:
def run_entangle(eng, num_qubits):
# allocate a quantum register of 5 qubits
qureg = eng.allocate_qureg(num_qubits)
# entangle the qureg
Entangle | qureg
# measure; should be all-0 or all-1
All(Measure) | qureg
# run the circuit
eng.flush()
# access the probabilities via the back-end:
# results = eng.backend.get_probabilities(qureg)
# for state in results:
# print("Measured {} with p = {}.".format(state, results[state]))
# or plot them directly:
histogram(eng.backend, qureg)
plt.show()
# return one (random) measurement outcome.
return [int(q) for q in qureg]
run_entangle(eng, num_qubits=5) # run it
In order to still retrieve all results at a later point in time, one can simply re-run the entire program using a slightly modified back-end:
In [4]:
eng = MainEngine(IBMBackend(use_hardware=True, num_runs=1024,
verbose=False, device='ibmqx4',
retrieve_execution="5b557df2306393003b746da2"), # provide job ID
engine_list=projectq.setups.ibm.get_engine_list())
run_entangle(eng, num_qubits=5)
Out[4]:
If you have access to the 16-qubit device as well, you can also use ProjectQ to run your quantum programs on this device. ProjectQ contains a 2D grid mapper, which takes care of the mapping for you. We only have to change two things in order to use the 16-qubit chip as opposed to the 5-qubit chip:
1) Import the new 16-qubit setup which contains the compiler engines for this device
2) Modify the device parameter in the IBMBackend to "ibmqx5"
Therefore, in order to entangle more than 5 qubits, we can simply write
In [5]:
import projectq.setups.ibm16 # import setup which contains the grid mapper
eng = MainEngine(IBMBackend(use_hardware=True, num_runs=1024,
verbose=False, device='ibmqx5'), # use ibmqx5 now
engine_list=projectq.setups.ibm16.get_engine_list()) # note: ibm16 setup
and then re-run the example from before via run_entangle(eng, num_qubits)
. If an execution times out, it can also be retrieved at a later point by providing the additional retrieve_execution="execution_id"
parameter to the IBMBackend (but this time with device='ibmqx5'
).
In [6]:
run_entangle(eng, num_qubits=8)
Out[6]: