# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)<br>Chapter 3 Exercise Solutions
----
> Copyright (c) Sarah Kaiser and Chris Granade.
> Code sample from the book "Learn Quantum Computing with Python and Q#" by
> Sarah Kaiser and Chris Granade, published by Manning Publications Co.
> Book ISBN 9781617296130.
> Code licensed under the MIT License.

### Preamble


```python
import numpy as np
```

### Exercise 3.1 

**In Chapter 2, we saw that unitary matrices play the same role in quantum computing that _truth tables_ play in classical computing.
We can use that to figure out what the matrix 𝑋 has to look like in order to represent the quantum NOT operation, `x`.
Let's start by making a table of what the matrix 𝑋 has to do to each input state in order to represent what the `x` instruction does:**

| Input | Output |
|---|---|
| \|0⟩ | \|1⟩
| \|1⟩ | \|0⟩


**This table tells us that if we multiply the matrix 𝑋 by the vector |0⟩, we need to get |1⟩, and similarly that 𝑋|1⟩ = |0⟩.
Either by using NumPy or by hand, check that the matrix**

\begin{align}
X = \left(\begin{matrix}
    0 & 1 \\
    1 & 0
\end{matrix}\right)
\end{align}

**matches what we have in our truth table above.**

We can start by defining two variables, `ket0` and `ket1`, to store the vectors representing |0⟩ and |1⟩, respectively.


```python
ket0 = np.array([
    [1],
    [0]
])
ket1 = np.array([
    [0],
    [1]
])
```

Next, we can define a variable to store the matrix $X$.


```python
X = np.array([
    [0, 1],
    [1, 0]
])
```

Now, we can verify that `X @ ket0` is the same as `ket1` and vice versa:


```python
X @ ket0
```




    array([[0],
           [1]])




```python
X @ ket1
```




    array([[1],
           [0]])



----
### Exercise 3.2

**Try using what we learned about vectors in the previous chapter to verify that |0⟩ = (|\+⟩ + |−⟩) / √2, either by hand or using Python.**

*HINT*: recall that |+⟩ = (|0⟩ + |1⟩) / √2 and that |−⟩ = (|0⟩ − |1⟩) / √2.

As before,it's helpful to start by defining variables to represent the vectors |+⟩ and |−⟩.


```python
ket_plus = np.array([
    [1],
    [1]
]) / np.sqrt(2)
ket_minus = np.array([
    [1],
    [-1]
]) / np.sqrt(2)
```

Using these new variables, it's easy to verify that $|0\rangle = (|+\rangle + |-\rangle) / \sqrt{2}$.


```python
(ket_plus + ket_minus) / np.sqrt(2)
```




    array([[1.],
           [0.]])



----
### Exercise 3.3

<strong>
    <ul>
        <li>Calculate what the probability of getting the measurement outcome |−⟩ when measuring the |0⟩ state in the |−⟩ direction.
        <li>Also calculate what the probability of getting the |−⟩ measurement outcome with the input state of |1⟩.
    </ul>
</strong>


```python
ket0 = np.array([
    [1],
    [0]
])
ket1 = np.array([
    [0],
    [1]
])
```


```python
ket_plus = np.array([
    [1],
    [1]
]) / np.sqrt(2)
ket_minus = np.array([
    [1],
    [-1]
]) / np.sqrt(2)
```

With these variables defined, it's easy to compute Born's rule, $\Pr(- | 0) = |\langle - | 0 \rangle|^2$ by computing the inner product of $|-\rangle$ with $|0\rangle$ and taking the absolute value squared of the result.


```python
np.abs(ket_minus.conj().transpose() @ ket0) ** 2
```




    array([[0.5]])



Similarly, we can compute $\Pr(- | 1)$ using the same technique.


```python
np.abs(ket_minus.conj().transpose() @ ket1) ** 2
```




    array([[0.5]])



----
### Exercise 3.4

**If you had the ciphertext `10100101` and the key `00100110`, what was the message that was originally sent?**


```python
ciphertext = [bit == '1' for bit in '10100101']
key = [bit == '1' for bit in '00100110']
```


```python
plaintext = [cipher_bit ^ key_bit for (cipher_bit, key_bit) in zip(ciphertext, key)]
```


```python
"".join("1" if bit else "0" for bit in plaintext)
```




    '10000011'



a0177c6f7058b10038ef902059a8d5990d25127e
ipynb
Jupyter Notebook
ch03/ch03-exercise-solutions.ipynb
jmgimeno/learn-qc-with-python-and-qsharp
9b3c4bba9cf5c09df089be9efb9ac0ea57dfc0ac
MIT
ch03/ch03-exercise-solutions.ipynb
jmgimeno/learn-qc-with-python-and-qsharp
9b3c4bba9cf5c09df089be9efb9ac0ea57dfc0ac
MIT
ch03/ch03-exercise-solutions.ipynb
jmgimeno/learn-qc-with-python-and-qsharp
9b3c4bba9cf5c09df089be9efb9ac0ea57dfc0ac
MIT
Qwen/Qwen-72B
1. YES
2. YES