Quantum Computing – How to start and how to say “Hello World!”

May 9, 2022

Introduction

In my previous post on Open Source and Quantum Computing Quantum Computing: Open Source from the Start we learned about Quantum Computing in general and how Open Source is used to provide access to this new computing paradigm.

This post will now focus on how to get started and provide a very easy guide to write your first quantum circuits. I will use the Qiskit framework for this, because it is very popular and it allows everyone to access real (IBM) quantum computers for free. 

The free tier does not give you access to newest machines and those with a high number of qubits, but there are 5 qubit systems that can be accessed without spending money. 

Another advantage of Qiskit is that it is based on Python which is well known and available on many systems.  Part one of this post will help to get Qiskit running on the local machine or on your favorite Kubernetes cluster to get started. In part two we will explore some simple quantum algorithms.

How do I get your hands dirty with quanta

The simplest way to start is using a pre-build container running on a local machine. This reduces the friction of handling package dependencies and does not interfere with the system python on your server. As I want to do this without elevated privileges, I use podman to start it (if you insist on “docker”, this is also possible):

$ podman run --rm -d -p 8888:8888  qiskit/jupyter:0.1

3db9162484ed174d4c62c0fb4810f14aade79375295fd2362d3d91dbeb46926d

Verify that the container runs:

$ podman ps
CONTAINER ID  IMAGE                         COMMAND            CREATED        STATUS            PORTS                   NAMES
3db9162484ed  docker.io/qiskit/jupyter:0.1  start-notebook.sh  8 minutes ago  Up 8 minutes ago  0.0.0.0:8888->8888/tcp  infallible_easley

To access the notebook, we need the correct token:

$ podman logs 3db9162484ed

Executing the command: jupyter notebook
[I 18:37:24.092 NotebookApp] Writing notebook server cookie secret to /home/jovyan/.local/share/jupyter/runtime/notebook_cookie_secret
[I 18:37:24.680 NotebookApp] JupyterLab extension loaded from /opt/conda/lib/python3.7/site-packages/jupyterlab
[I 18:37:24.680 NotebookApp] JupyterLab application directory is /opt/conda/share/jupyter/lab
[I 18:37:24.682 NotebookApp] Serving notebooks from local directory: /home/jovyan
[I 18:37:24.682 NotebookApp] The Jupyter Notebook is running at:
[I 18:37:24.682 NotebookApp] http://3db9162484ed:8888/?token=a3a6fd5d4b942ec12f696ddd5f275ad94c8ed4756685548a
[I 18:37:24.682 NotebookApp]  or http://127.0.0.1:8888/?token=a3a6fd5d4b942ec12f696ddd5f275ad94c8ed4756685548a
[I 18:37:24.682 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 18:37:24.685 NotebookApp] 
To access the notebook, open this file in a browser:
 file:///home/jovyan/.local/share/jupyter/runtime/nbserver-7-open.html
 Or copy and paste one of these URLs:
 http://3db9162484ed:8888/?token=a3a6fd5d4b942ec12f696ddd5f275ad94c8ed4756685548a
 or http://127.0.0.1:8888/?token=a3a6fd5d4b942ec12f696ddd5f275ad94c8ed4756685548a

Opening the URL “http://127.0.0.1:8888/?token=a3a6fd5d4b942ec12f696ddd5f275ad94c8ed4756685548a” gives us access to the notebook-server:

I can start a new work sheet:

And I am in:

Did I mention that I love podman? I can just use my normal user account and fire up containers!

But there is an even better way to get qiskit running if you have access to a k8s cluster:

Qiskit Playground as k8s operator

While it is relatively easy to run qiskit in a container on a local machine, not all organizations let their staff work with proper and capable workstations running a “real operating system” to do something like this locally. And some people don’t want to fiddle with the configuration of their classical computer to program quantum machines.

Wouldn’t it be nice if we could start a qiskit-enabled Jupyter notebook with a click of a button? 

For this we have the Qiskit playground operator!

https://operatorhub.io/operator/openshift-qiskit-operator

The administrator of your k8s cluster can install the operator directly from the operator hub. When you are using OpenShift the operator can be installed directly from the cluster console:

What does the operator do? It simply creates a CustomResourceDefinition (CRD) in K8s that can be managed from a namespace admin using kubectl:

$ kubectl get QiskitPlayground
NAME               AGE
qiskitplayground   423d

Creating a yaml file, a new instance can be launched:

$ cat sample.yaml
apiVersion: qiskit.ibm.com/v1alpha1
kind: QiskitPlayground
metadata:
 name: qiskitplayground-sample
 namespace: quantum
spec:
 image: 'qiskit/jupyter:0.1'
 imagePullPolicy: Always
 loadbalancer: false
 resources:
   limits:
     memory: 3G
     cpu: '1.5'
   requests:
     memory: 2G
     cpu: '1'
 
$ kubectl apply -f sample.yaml

In OpenShift you can just simply add an operator backed service from the console:

After clicking on “create” you can edit the options:

When the pod is launched, OpenShift displays the app in the topology and automatically assigns a route:

By clicking on the route, the new notebook opens in the browser:

Just click on the “Python 3” icon and you are ready to go! Now the fun can begin and we can start with part two of this post:

Writing your first qiskit code

Let’s start in our newly created Jupyter notebook with coding our first quantum circuit. At first we need to import some functions:

from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit

We will start with a very simple example: We just take one single qubit. For this we need to define a quantum and a classical register (for the measurement later on). 

qreg_q = QuantumRegister(1, 'q')
creg_c = ClassicalRegister(1, 'c')

Then we define the circuit. We start with the definition, and then we reset the qubit to the ground state |0>. Lastly, we measure it:

circuit = QuantumCircuit(qreg_q, creg_c)
circuit.reset(qreg_q[0])
circuit.measure(qreg_q[0], creg_c[0])

We can also visualize the circuit in the notebook:

circuit.draw('mpl')

Great. Our first circuit. Not very sophisticated and what would we expect for the result? We forced the qubit to the ground state and do immediately a measurement: This should be just 0, right? Let’s test this:

We can do this directly in the notebook with the build-in quantum simulator Qiskit “Aer”:

# Import Aer
from qiskit import Aer, transpile

We then define a backend and a simulator job: We will run the circuit 1024 times and evaluate the statistics. Remember: Quantum circuits incorporate randomness and we always need a statistical interpretation of the results!

backend_sim = Aer.get_backend('qasm_simulator')
job_sim = backend_sim.run(transpile(circuit, backend_sim), shots=1024)

The job is run asynchronously and here we can collect the results:

result_sim = job_sim.result()
counts = result_sim.get_counts(circuit)
print(counts) 

Output: {'0': 1024}

All 1024 shots resulted in a “0”. Perfectly as expected! We can also visualize the result:

from qiskit.visualization import plot_histogram
plot_histogram(counts)

Now let us change the circuit and introduce superposition. For this we can use the Hadamard-Gate operation, typically simply called “H”. It changes the qubit from the ground state |0> into the superposition

|????> = ( |0> +  |1>) / sqrt(2)

This should give us an even distribution of the |0> and the |1> state. Let’s do that in qiskit:

circuit = QuantumCircuit(qreg_q, creg_c)
circuit.reset(qreg_q[0])
# now Introduce Hadamard Gate;
circuit.h(qreg_q[0])
circuit.measure(qreg_q[0], creg_c[0])
circuit.draw('mpl')

Now we let it run in the simulator:

job_sim = backend_sim.run(transpile(circuit, backend_sim), shots=1024)
result_sim = job_sim.result()
counts = result_sim.get_counts(circuit)
plot_histogram(counts)

Cool! A nearly even distributen, but in the bounds of the statistical error a perfect result! But hey, we are on a simulator…

Now for the real thing. A “real” Quantum Computer!

IBM lets us access some of their smaller machines (up to 5 qubits) for free. There is also a pay-as-you- model for the larger systems, but for us 5 is more than enough. Remember: In our example we just used one single qubit!

Just go to https://quantum-computing.ibm.com/ and sign up for an account. There is good stuff over there, a graphical circuit composer, a notebook server, an interactive tutorial and much more! But we just want to have access to one of the smaller machines.

After login you are in a dashboard where you can access all your information:

At first copy the API token. We will need that to connect to the systems: Let us save it directly into the notebook:

from qiskit import IBMQ, assemble
IBMQ.save_account('<place_API_token_here>’)
provider = IBMQ.load_account()

Next, let us have a look at the available machines for us: Go to IBM Quantum systems and select  “Your systems”:

Just select on of them (I chose ibmq_quito):

backend = provider.backend.ibmq_quito
status = backend.status()
print(status.pending_jobs)


Output: 9

As systems are shared we can see here the pending jobs. So it can take a while until a job is finished. But hey, it’s for free!

Now let us prepare our last superpositioned circuit for this backend. On the real system we need to transpile the job for the backend and retrieve the data from the job queue:

transpiled = transpile(circuit, backend=backend)
job = backend.run(transpiled)
retrieved_job = backend.retrieve_job(job.job_id())
result = retrieved_job.result()
counts = result.get_counts(circuit)
plot_histogram(counts)

(This operation can take several minutes, since we have to wait until our job is queued.)

Voila! We got the same result (within the statistical error). But how do we know that we are on a “real” system? Let’s look again at our first much simpler circuit:

circuit = QuantumCircuit(qreg_q, creg_c)
circuit.reset(qreg_q[0])
circuit.measure(qreg_q[0], creg_c[0])
circuit.draw('mpl')

Now we wet this one run on the “real” backend:

transpiled = transpile(circuit, backend=backend)
job = backend.run(transpiled)
retrieved_job = backend.retrieve_job(job.job_id())
result = retrieved_job.result()
counts = result.get_counts(circuit)
plot_histogram(counts)

Huh! In general the expected result, but we have a small number of non-expected results. This is because a “real” quantum computer is not perfect. Sometimes the qubit flips the state or the measurement has errors. As this should not appear in the theory, we see here an artifact of non perfect qubits with our current technology.

Let us stop for the day, in a later post we will see how we can entangle qubits and also to do something useful with the current systems! Stay tuned.

If you want to save some typing time and work directly in the notebook, you can find it here:

https://github.com/iboernig/quantum-examples/blob/main/First_steps.ipynb

One reply on “Quantum Computing – How to start and how to say “Hello World!””

Leave a Reply

close

Subscribe to our newsletter.

Please select all the ways you would like to hear from Open Sourcerers:

You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.

We use Mailchimp as our newsletter platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.