Welcome to a series on programming quantum computers. There's no shortage of hype around quantum computing on the internet, but I am going to still outline the propositions made by quantum computing in general, as well as how this pertains to us and programmers who intend to work with quantum computers, which we will be doing immediately in this series.
The subject matter of quantum physics in general is very advanced, complex, confusing, and complicated. I am not a quantum physics expert. Dare I suggest too, no one is a quantum physics expert, but there are people far more qualified than me to talk on the theories and physics side of things.
I will still outline some basics, but I highly encourage you to dive into the theory and conceptual side of quantum physics on your own because I really am not the best person to educate there. I am going to focus mainly on the programming and application side of things here.
That said, some basic foundation is required, so:
Quantum computers are machines that work with qubits (quantum bits) rather than regular bits.
A regular bit is a transistor that registers either a high or low voltage, which corresponds to 1 or 0 respectively. Through advances in technology over the years, we have bits that are nearly the size of atoms, which is absolutely incredible.
A quantum bit is a 2-state quantum "device." Many things can be used as qubits, such as a photon's horizontal and vertical polarization, or the spin up or spin down of an electron. What this means for us as computer scientists is that a qubit can be a 0, 1, or both.
Because...
Qubits also have 2 other very important properties:
You're going to be thinking that a lot, but these are the properties that make quantum computers very compelling to use for certain problems. Both superposition and entanglement seem like magic to me, but both are proven qualities of qubits.
Quantum computers wont be replacing classical computers. They're more likely to continue working alongside them, just as they are already doing today. As you will see, we tend use a classical computer to represent a quantum circuit to the quantum computer, the quantum computer runs some cycles on this circuit, and then reports back to us again with a classical bit response.
Quantum computers work very well for problems that exponentially explode.
Problems like logistics, such as the most ideal delivery route for trucks, or even concepts like planning for companies, where each choice branches out into new possible choices and opportunities.
This might still seem vague. Let's consider you're planning a charity dinner and you're attempting to seat people together who will keep eachother in good, donating, moods.
Let's pretend for now you just have 1 table with 5 seats. How many combinations do we have here? Well, it's 5x4x3x2x1, or 5 factorial, which is 120. This means there are 120 possible combinations.
What happens if we added... just one more seat? That'd be 6 factorial, which gives us 6x5-factorial, or 720. Just one more seat is 6x as many combinations.
What about 10 seats? That's 3,628,800 combinations.
Modeling is probably the most near-term real-world example that I see quantum computers being useful.
Classical computers can barely simulate many single molecules...and they do a very poor job of it (due to the issue of how many possibilities there are given a situation). You currently cant rely on a classical computer to do chemistry simulations reliably.
A quantum computer can actually model many molecules already today reliably, and it only gets better from here seemingly.
With classical computers:
n_states = 2 x n_bits
With quantum computers:
n_states = 2^n_bits
Being exponential like this gives us some phenomenal properties. This is why quantum computers can help us with heavy-optimization types of tasks, or just tasks that have many possibilities.
I think the simplest explanation of a quantum computer that I can come up with for now is that:
Classical computers can approximate and synthesize probability, they are not truly accurate and can never be with most tasks that use probability, unless of course you really can fit the entire range of possibilities into memory. Then you can get pretty close. But again, the probability space tends to explode as you add more variables.
Quantum computers do not model probability. They simply are the probability.
For this reason, quantum computers are also great for modeling things like molecules. With quantum computers, we could perform many chemistry experiments solely on quantum computers, which should significantly speed up many areas of research.
So these companies who have no doubt spent hundreds of millions of dollars on these quantum computers...what do they do with them?
It turns out, opening them up to the public, for free, is not uncommon.
Google, Microsoft, IBM, D-Wave, and I am sure many others all offer some form of cloud-based quantum computer access.
I checked into all of the providers that I knew about, and, surprisingly, found IBM's to be the easiest to get up and running with. You really can go from nothing to running on an actual quantum computer in a few minutes.
For free.
FREE.
I feel like making access to quantum computers free is like NASA letting people drive a Mars rover around Mars for free. It's insane!
... but we're currently at a stage with Quantum computers where the technology exists but no one really knows what all we can do here, or what will come of it.
So, let's take advantage of this absurd time and play with the bleeding edge of technology!
IBM has also done what I would call a phenomenal job with making both the tools as well as education available for free to anyone who is interested in diving in. I hope to continue this trend for them.
I am assuming you already have python installed and are beyond the python basics. If not, please start with the basics here: Python 3 programming basics tutorial.
pip install qiskit numpy jupyterlab matplotlib qiskit-ibmq-provider
I personally found that I had to force install qiskit-ibmq-provider
:
(on linux):
sudo pip3.7 install --upgrade --force-reinstall qiskit-ibmq-provider
Quantum computers essentially are different to their core, the "bit." Thus, as painful as it may be, we will be starting at the bit-level, the qubit.
We quite literally will be building out the "circuits" for our bits, creating various types of gates.
The following circuit appears to me to be the "hello_world" quantum circuit of choice for everyone, so I'll stick with it.
import qiskit as q
%matplotlib inline
circuit = q.QuantumCircuit(2,2) # 2 qubits, 2 classical bits
circuit.x(0) # "x" is a "not" gate. It flips the value. Starting value is a 0, so this flips to a 1.
circuit.cx(0, 1) #cnot, controlled not, Flips 2nd qubit's value if first qubit is 1
circuit.measure([0,1], [0,1]) # ([qbitregister], [classicalbitregister]) Measure qubit 0 and 1 to classical bits 0 and 1
circuit.draw() # text-based visualization. (pretty cool ...actually! Nice job whoever did this.)
circuit.draw(output="mpl") # matplotlib-based visualization.
Alright, we've built our quantum circuit. Time to run the circuit. This is a quantum computing tutorial, so let's go ahead and just get running something on a Quantum Computer out of the way so we can add this to our resume.
Head to Quantum-computing.ibm.com, create an account, and then you can click on the account icon at the top right (at least at the time of my writing this), then choose "my account"
From there, you can click "copy token" which will copy your token to clipboard, which we will use in a moment:
Once you've got your token, you're ready to try to connect to a quantum computer and run there.
Now you can connect with your token by doing:
IBMQ.save_account("TOKEN HERE")
I am going to store my token to a file so I dont accidentally share it, but you can just paste it right in here as a string. For me, however, I will do:
from qiskit import IBMQ
IBMQ.save_account(open("token.txt","r").read())
This saves on your actual machine, so you only need to do this once ever (unless your token changes), which is why I am getting the "Credentials already present" message. From then on, you can just do:
IBMQ.load_account()
IBMQ.providers()
provider = IBMQ.get_provider("ibm-q")
for backend in provider.backends():
try:
qubit_count = len(backend.properties().qubits)
except:
qubit_count = "simulated"
print(f"{backend.name()} has {backend.status().pending_jobs} queued and {qubit_count} qubits")
from qiskit.tools.monitor import job_monitor
backend = provider.get_backend("ibmq_london")
job = q.execute(circuit, backend=backend, shots=500)
job_monitor(job)
from qiskit.visualization import plot_histogram
from matplotlib import style
style.use("dark_background") # I am using dark mode notebook, so I use this to see the chart.
result = job.result()
counts = result.get_counts(circuit)
plot_histogram([counts], legend=['Device'])
So mostly we got 11 at the end of our test (each number corresponds to a bit value here), which was expected. Our default qubit value is 0, then we used a not game (.x
), which then made it a one. Then we applied an exclusive or, which would flip the 2nd (target qubit), if the first (the control qubit), was a 1. It was, so this is why our intended answer was indeed a 11. As you can see, however, we got some 01, 10, and some 00. What's this?
This is noise.
Expect noise, and rely on probability.
This is why we perform many "shots." Depending on the probability distribution possible for your output, you will want to perform a relevant number of "shots" to get the right answer.
Regardless, you did it! Time to update that resume to say "Quantum Programmer!"
Now, let's update this slightly. This is a pretty boring circuit.
circuit = q.QuantumCircuit(2,2) # 2 qbits, 2 classical bits.
circuit.h(0) # Hadamard gate, puts qubit 0 into superposition
circuit.cx(0, 1) #cnot, controlled not, Flips 2nd qubit's value if first qubit is 1
circuit.measure([0,1], [0,1]) # ([qbitregister], [classicalbitregister]) Measure qubit 0 and 1 to classical bits 0 and 1
This time we're adding circuit.h(0)
, which adds a Hadamard gate to qubit 0. This puts that qubit into superposition. How might this impact the measured output of 500 shots do you think?
circuit.draw(output="mpl")
backend = provider.get_backend("ibmq_london")
job = q.execute(circuit, backend=backend, shots=500)
job_monitor(job)
result = job.result()
counts = result.get_counts(circuit)
plot_histogram([counts], legend=['Device'])
Notice now that we get mostly 00 and 11 as results. There's some 01 and 10 as noise, but we see what we expect.
Recall the controlled not
gate will flip the target qubit (2nd one) if the control qubit (the first) is 1.
The 2nd qubit was 0 since it was never turned on, and the 1st qubit (qubit 0) was in superposition. Superposition means the qubit is in any of the possible states, but will collapse upon a single state when observed.
This is why we make many observations, so that we can see the actual distribution of outcomes.
Thus, we see close to a 50/50 split between 00 and 11 with this circuit. There's obviously noise too, but, in an ideal quantum computer, we'd only see 00 and 11.
As awesome as it really is to run on a quantum computer, it's fairly silly for us to just tinker around on a real quantum computer. Instead, we want to do most of our research and development work on a quantum simulator.
This saves us time (not waiting in a queue) along with getting out of the way for other people who have done their R&D locally and are now ready to test on the real thing.
To do R&D locally, it's quite simple. Rather than using an actual backend, we use a simulator. We could also use the simulator backend that IBM hosts.
from qiskit import Aer # simulator framework from qiskit
# will create a statevector of possibilities.
sim_backend = Aer.get_backend('qasm_simulator')
Can also iterate:
for backend in Aer.backends():
print(backend)
From: https://quantum-computing.ibm.com/jupyter/tutorial/advanced/aer/1_aer_provider.ipynb
We'll use the qasm_simulator
, since this most closely matches what we did above.
That said, when using simulators, we can use the unitary simulator if we would rather get something more like a matrix output. A statevector simulator will return a statevector. The Qasm sim returns the counts that we've seen so far.
Different outputs allow us different visualizations.
job = q.execute(circuit, backend=sim_backend, shots=500)
job_monitor(job)
result = job.result()
counts = result.get_counts(circuit)
plot_histogram([counts], legend=['Device'])
Notice we didn't get a perfect 50/50, but there was no 01 or 10. Why not? Well, the "simulator" simulates a perfect quantum machine. One day, we may reach a perfect quantum machine. For now, perfect quantum machines only exist in the sim.
Anyway, now you can try tinkering about in the simulator, then you can test your results for real on an actual quantum computer when you're ready.
I think that's enough for now! More to come in the future.
If you have questions, please come join us in the discord channel, otherwise I will see you in the next tutorial!
More resources: