# -*- coding: utf-8 -*-
# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Q#
#     language: qsharp
#     name: iqsharp
# ---

# # Superposition Kata Workbook, Part 2
#
# The [Superposition Kata Workbook, Part 1](./Workbook_Superposition.ipynb) includes the solutions of kata tasks 1 - 7.  Part 2 continues the explanations for the rest of the tasks.

# To begin, first prepare this notebook for execution (if you skip this step, you'll get "Syntax does not match any known patterns" error when you try to execute Q# code in the next cells):

%package Microsoft.Quantum.Katas::0.10.1911.1607

# > The package versions in the output of the cell above should always match. If you are running the Notebooks locally and the versions do not match, please install the IQ# version that matches the version of the `Microsoft.Quantum.Katas` package.
# > <details>
# > <summary><u>How to install the right IQ# version</u></summary>
# > For example, if the version of `Microsoft.Quantum.Katas` package above is 0.1.2.3, the installation steps are as follows:
# >
# > 1. Stop the kernel.
# > 2. Uninstall the existing version of IQ#:
# >        dotnet tool uninstall microsoft.quantum.iqsharp -g
# > 3. Install the matching version:
# >        dotnet tool install microsoft.quantum.iqsharp -g --version 0.1.2.3
# > 4. Reinstall the kernel:
# >        dotnet iqsharp install
# > 5. Restart the Notebook.
# > </details>
#

# ## <a name="greenberger-horne-zeilinger"></a> Task 8. Greenberger-Horne-Zellinger state.
#
# **Input:** $N$ ($N \ge 1$) qubits in the $|0 \dots 0\rangle$ state (stored in an array of length $N$).
#
# **Goal:**  Change the state of the qubits to the GHZ state $\frac{1}{\sqrt{2}} \big (|0\dots0\rangle + |1\dots1\rangle\big)$.

# ### Solution
#
# The single-qubit GHZ state is the plus state $\frac{1}{\sqrt{2}} \big (|0\rangle + |1\rangle\big)$ that we've discussed in [task 1](./Workbook_Superposition.ipynb#plus-state). As a reminder, that state is prepared by applying a Hadamard gate.
#
# The 2-qubit GHZ state is the Bell state $\frac{1}{\sqrt{2}} \big (|00\rangle + |11\rangle\big)$ that we've discussed in [task 6](./Workbook_Superposition.ipynb#bell-state). That state can been prepared using the following circuit:
#
# <img src="./img/Task6HadamardCNOTCircuit.png"/>
#
# The next one is the 3-qubit GHZ state:
# $$|GHZ\rangle = \frac{1}{\sqrt{2}} \big (|000\rangle + |111\rangle\big)$$
#
# Let's use the 2-qubit circuit as a building block to construct the circuit for 3 qubits. First, let's add a third qubit to the above circuit:
#
# <img src="./img/Task8Hadamardand3rdqubitircuit.png"/>
#
# Comparing the state prepared by this circuit with the desired end state, we see that they differ only in the third (rightmost) qubit:
#
# $$|\Phi^+\rangle |0\rangle = \frac{1}{\sqrt{2}} \big (|000\rangle + |11\color{red}0\rangle\big)$$
# $$|GHZ\rangle = \frac{1}{\sqrt{2}} \big (|000\rangle + |11\color{red}1\rangle\big)$$
#
#
# Applying a controlled NOT operation using the first (leftmost) qubit as the control bit and the third (rightmost) qubit as the target qubit allows us to fix this difference: 
#
# <table style="background-color: white; border:0 solid; tr  { background-color:white; }">
#     <col width=30%>
#     <col width=70%>
#         <td style="text-align:center; background-color:white; border:0"><img src="./img/Task8HadamardAndCNOTCircuit.png"/></td>
#         <td style="text-align:left; background-color:white; border:0"><img src="./img/Task8CNOTFlip.png"/></td>       
# </table>
#
# Similarly, the following circuit will prepare the GHZ state on four qubits $\frac{1}{\sqrt2} (|0000\rangle + |1111\rangle$:
# <img src="./img/Task84QubitCircuit.png"/>
#
# Thus we can come to the general solution: apply Hadamard gate to the first qubit and do a series of CNOT gates with the first qubit as control and each of the other qubits as targets.

# +
%kata T08_GHZ_State_Test

open Microsoft.Quantum.Arrays;

operation GHZ_State (qs : Qubit[]) : Unit {
    H(qs[0]);
    
    // Library function Rest returns all array elements except for the first one
    for (q in Rest(qs)) {
        CNOT(qs[0], q);
    }
}
# -

# [Return to task 8 of the Superposition kata.](./Superposition.ipynb#greenberger-horne-zeilinger)

# ## <a name="superposition-of-all-basis-vectors"></a>  Task 9. Superposition of all basis vectors.
#
# **Input:** $N$ ($N \ge 1$) qubits in the $|0 \dots 0\rangle$ state.
#
# **Goal:**  Change the state of the qubits to an equal superposition of all basis vectors $\frac{1}{\sqrt{2^N}} \big (|0 \dots 0\rangle + \dots + |1 \dots 1\rangle\big)$. 
#
# > For example, for $N = 2$ the final state should be  $\frac{1}{\sqrt{2}} \big (|00\rangle + |01\rangle + |10\rangle + |11\rangle\big)$.

# ### Solution
#
# As we've seen in [task 4](./Workbook_Superposition.ipynb#superposition-of-all-basis-vectors-on-two-qubits), to prepare a superposition of all basis vectors on 2 qubits we need to apply a Hadamard gate to each of the qubits.
#
# It seems that the solution for the general case might be to apply a Hadamard gate to every qubit as well. Let's check the first few examples:
#
# \begin{align*}
#    H|0\rangle &= \frac{1}{\sqrt2}\big(|0\rangle + |1\rangle\big)\\
#    H|0\rangle \otimes H|0\rangle &= \frac{1}{\sqrt2} \big(|0\rangle + |1\rangle\big) \otimes \frac{1}{\sqrt2} \big(|0\rangle + |1\rangle\big)\\   
#                &= \frac{1}{\sqrt{2^2}}\big(|00\rangle + |01\rangle+ |10\rangle+ |11\rangle\big)\\
#    H|0\rangle \otimes H|0\rangle \otimes H|0\rangle &= \frac{1}{\sqrt{2^2}}\big(|00\rangle + |01\rangle+ |10\rangle+ |11\rangle\big) \otimes \frac{1}{\sqrt2}\big(|0\rangle + |1\rangle\big)\\
#                &= \frac{1}{\sqrt{2^3}}\big(|000\rangle + |001\rangle + |010\rangle+ |100\rangle+ |110\rangle + |101\rangle+ |011\rangle+ |111\rangle\big)\\
#     \underset{N}{\underbrace{H|0\rangle \otimes \dots \otimes H|0\rangle}} 
#                &= \frac{1}{\sqrt{2^{N-1}}}  \big( |\underset{N-1}{\underbrace{0 \cdots 0}}\rangle + \cdots + |\underset{N-1}{\underbrace{1 \cdots 1}}\rangle \big) \otimes \frac{1}{\sqrt2}\big(|0\rangle + |1\rangle\big) = \\
#                &= \frac{1}{\sqrt{2^N}} \big( |\underset{N}{\underbrace{0 \cdots 0}}\rangle + \cdots + |\underset{N}{\underbrace{1 \cdots 1}}\rangle \big)\\    
# \end{align*}
#
# Thus, the solution requires us to iterate over the qubit array and to apply the Hadamard gate to each element as follows:

# +
%kata T09_AllBasisVectorsSuperposition_Test

operation AllBasisVectorsSuperposition (qs : Qubit[]) : Unit {
    for (q in qs) {
        H(q);
    }
}
# -

# [Return to task 9 of the Superposition kata.](./Superposition.ipynb#superposition-of-all-basis-vectors)

# ## <a name="superposition-of-all-even-or-all-odd-numbers"></a>Task 10. Superposition of all even or all odd numbers.
#
# **Inputs:** 
#
# 1. $N$ ($N \ge 1$) qubits in the $|0 \dots 0\rangle$ state (stored in an array of length $N$).
# 2. A boolean `isEven`.
#
# **Goal:**  Prepare a superposition of all *even* numbers if `isEven` is `true`, or of all *odd* numbers if `isEven` is `false`.  
# A basis state encodes an integer number using [big-endian](https://en.wikipedia.org/wiki/Endianness) binary notation: state $|01\rangle$ corresponds to the integer $1$, and state $|10 \rangle$ - to the integer $2$.  
#
# > For example, for $N = 2$ and `isEven = false` you need to prepare superposition $\frac{1}{\sqrt{2}} \big (|01\rangle + |11\rangle\big )$,  
# and for $N = 2$ and `isEven = true` - superposition $\frac{1}{\sqrt{2}} \big (|00\rangle + |10\rangle\big )$.
# </details>

# ### Solution
#
# Let’s look at some examples of basis states to illustrate the binary numbering system. 
#
# The 4 basis states on $N = 2$ qubits can be split in two columns, where the left column represents the basis states that form the required superposition state for `isEven = false` and the right column - the basis states that form the required superposition state for `isEven = true`:
#
# <img src="./img/Task10_1.png" width="400">
#  
# If we do the same basis state split for $N = 3$ qubits, the pattern becomes more obvious:
#  
# <img src="./img/Task10_2.png" width="400">

# The two leftmost qubits go through all possible basis states for `isEven = false` and for `isEven = true`, and the rightmost qubit stays in the $|1\rangle$ state for `isEven = false` and in the $|0\rangle$ state for `isEven = true`. 
#
# A quick sanity check for $N = 4$ qubits re-confirms the pattern:
#  
# <img src="./img/Task10_3.png" width="400">
#  
# Again, the three leftmost qubits go through all possible basis states in both columns, and the rightmost qubit stays in the same state in each column. 
#
# The solution is to put all qubits except the rightmost one into an equal superposition (similar to what we did in Task 9) and to set the rightmost qubit to $|0\rangle$ or $|1\rangle$ depending on the `isEven` flag, using the X operator to convert $|0\rangle$ to $|1\rangle$ if `isEven = false`.

# +
%kata T10_EvenOddNumbersSuperposition_Test

operation EvenOddNumbersSuperposition (qs : Qubit[], isEven : Bool) : Unit is Adj {
    let N = Length(qs);
    for (i in 0 .. N-2) {
        H(qs[i]);
    }
    // for odd numbers, flip the last bit to 1
    if (not isEven) {
        X(qs[N-1]);
    }
}
# -

# [Return to task 10 of the Superposition kata.](./Superposition.ipynb#superposition-of-all-even-or-all-odd-numbers)

# *Solutions to the rest of the tasks coming up soon...*

StarcoderdataJupyterScriptsDedupFiltered