<jupyter_start><jupyter_text>Hello Quantum - Qiskit Edition Chapter 1: Beginning with bits This is a Jupyter notebook, in which you will run some puzzles and learn about quantum computing. Don't worry if you've never used a Jupyter notebook before. It just means you'll see lots of grey boxes with code in, like the one below. These are known as cells.<jupyter_code>print("Hello! I'm a code cell")<jupyter_output><empty_output><jupyter_text>You'll need to run the cells to use the tutorial. To do this, click on the cell and press **Shift-Enter**. Get started by doing this for the cell below (it will take a second or two to run).<jupyter_code>print('Set up started...')
%matplotlib notebook
import engine
print('Set up complete!')<jupyter_output><empty_output><jupyter_text>The rest of the cells in this notebook will create puzzles for you to solve. So just go and run the cells for the puzzles you want to do.  Level 1 Intro* Normal computers are made of bits, and quantum computers are made of qubits.* Qubits are basically an upgraded version of bits, so let's make sure we understand basic bit-based programming first.* The defining feature of a bit is that it has two possible output values.* These are often called `1` and `0`, though we'll also be thinking of them as _on_ and _off_.* We use bits represent and process information, but for this we need lots of them,* To help you understand how to use bits, we'll give you one to play with.* The simplest thing you can do to a bit (other than leave it alone) is tghe `NOT` operation.* Try it out and see what happens. Exercise*  Use the `NOT` command 3 times on bit 0.<jupyter_code>initialize = []
success_condition = {}
allowed_gates = {'0': {'NOT': 3}, '1': {}, 'both': {}}
vi = [[1], False, False]
qubit_names = {'0':'the only bit', '1':None}
engine.run_game(initialize, success_condition, allowed_gates, vi, qubit_names)<jupyter_output><empty_output><jupyter_text>Outro* Here our bit was depicted by a circle that was either on (white) or off (black).* The effect of the `NOT` command was to turn it on and off.* This flips out bit between `0` and `1`.  Level 2 Intro* Now let's do the same thing to a different bit.* This will look the same as before. But because it is a different bit, it'll be in a different place. Exercise*  Turn the other bit on.<jupyter_code>initialize = []
success_condition = {}
allowed_gates = {'0': {}, '1': {'NOT': 0}, 'both': {}}
vi = [[], False, False]
qubit_names = {'0':'the bit on the left', '1':'the bit on the right'}
engine.run_game(initialize, success_condition, allowed_gates, vi, qubit_names)<jupyter_output><empty_output><jupyter_text>Outro* You've now mastered the NOT command: the most basic building block of computing.  Level 3 Intro* To really process information stored in bits, computers need more than just `NOT`s.* We need commands that let us manipulate some bits in a way that depends on other bits.* The simplest example is the controlled-`NOT`, or `CNOT`.* For this you need to choose one bit to be the _target_, and the other to be the _control_.* The `CNOT` then does a `NOT` on the target bit, but only if the control bit is on. Exercise* Use the `CNOT` to turn on bit 1.* **Note**: The `CNOT` acts on both bits, bit you still need to choose which will be the target bit.<jupyter_code>initialize = [['x', '0']]
success_condition = {'IZ': -1.0}
allowed_gates = {'0': {'CNOT': 0}, '1': {'CNOT': 0}, 'both': {}}
vi = [[], False, False]
qubit_names = {'0':'the bit on the left', '1':'the bit on the right'}
engine.run_game(initialize, success_condition, allowed_gates, vi, qubit_names)<jupyter_output><empty_output><jupyter_text>Level 4 Intro* Now do the same again, but also turn off the bit on the left. Exercise*  Use some CNOTs to turn bit 0 off and bit 1 on.<jupyter_code>initialize = [['x', '0']]
success_condition = {'ZI': 1.0, 'IZ': -1.0}
allowed_gates = {'0': {'CNOT': 0}, '1': {'CNOT': 0}, 'both': {}}
vi = [[], False, False]
qubit_names = {'0':'the bit on the left', '1':'the bit on the right'}
engine.run_game(initialize, success_condition, allowed_gates, vi, qubit_names)<jupyter_output><empty_output><jupyter_text>Outro* Well done!* These kind of manipulations are what all computing compiles down to* With more bits and a controlled-controlled-`NOT`, you can do everything from Tetris to self-driving cars.  Level 5 Intro* Qubits have some similarities to random bit values, so let's take a few exercises to look at them.* For a bit that will give us a `0` or `1` with equal probability, we'll use a grey circle. Exercise*  Make the bit on the right random using a CNOT.<jupyter_code>initialize = [['h', '0']]
success_condition = {'IZ': 0.0}
allowed_gates = {'0': {'CNOT': 0}, '1': {'CNOT': 0}, 'both': {}}
vi = [[], False, False]
qubit_names = {'0':'the bit on the left', '1':'the bit on the right'}
engine.run_game(initialize, success_condition, allowed_gates, vi, qubit_names)<jupyter_output><empty_output><jupyter_text>Outro* Well done!* If the left bit was off, the right bit stayed off. If the left bit was on, the right bit got switched on too.* So the random value of the left bit was copied over to the right by the `CNOT`.* In this case, despite the randomness, both bits will always output the same result.* But we could also create cases where they are independently random, or always have different results.* How can we keep track of this information?  Level 6 Intro* To keep track of correlations, we'll add another circle.* This doesn't represent a new bit. It simply tells us whether our two bits will agree or not.* It will be off when they agree, on when they don't, and grey when they aren't correlated Exercise*  Make the two bits always disagree<jupyter_code>initialize = [['h', '0']]
success_condition = {'ZZ': -1.0}
allowed_gates = {'0': {'NOT': 0, 'CNOT': 0}, '1': {'NOT': 0, 'CNOT': 0}, 'both': {}}
vi = [[], False, True]
qubit_names = {'0':'the bit on the left', '1':'the bit on the right'}
engine.run_game(initialize, success_condition, allowed_gates, vi, qubit_names)<jupyter_output><empty_output><jupyter_text>Level 7 Intro* Now you know pretty much need all you need to know about bits.* Let's have one more exercise before we move on. Exercise*  Turn on bit 1<jupyter_code>initialize = [['h', '1']]
success_condition = {'IZ': -1.0}
allowed_gates = {'0': {'NOT': 0, 'CNOT': 0}, '1': {'NOT': 0, 'CNOT': 0}, 'both': {}}
vi = [[], False, True]
qubit_names = {'0':'the bit on the left', '1':'the bit on the right'}
engine.run_game(initialize, success_condition, allowed_gates, vi, qubit_names)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11943473636225498, 'fraction_numerical': 0.012460112444917185, 'mean_word_length': 5.032997250229148, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '303920', 'license': 'Apache-2.0', 'n_tokens_mistral': 2075, 'n_tokens_neox': 1975, 'n_words': 950, 'path': '1_Bits.ipynb', 'repo_name': 'Maegner/Quantum_Programming_Tutorial', 'size': '6581'}