diff --git a/Exercises/Session 4 - Quantum Information.ipynb b/Exercises/Session 4 - Quantum Information.ipynb
new file mode 100644
index 0000000..5cbe3bd
--- /dev/null
+++ b/Exercises/Session 4 - Quantum Information.ipynb
@@ -0,0 +1,174 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "e4f44eb7",
+ "metadata": {},
+ "source": [
+ "
TMQS Workshop 2024 @ Zuse Institute Berlin
\n",
+ "Summer School on Tensor Methods for Quantum Simulation
\n",
+ "June 3 - 5, 2024
\n",
+ "$\\def\\tcoreleft{\\textcolor{MidnightBlue}{\\Huge⦸}}$\n",
+ "$\\def\\tcorecenter{\\textcolor{RedOrange}{\\Huge⦿}}$\n",
+ "$\\def\\tcoreright{\\textcolor{MidnightBlue}{\\Huge\\oslash}}$\n",
+ "\n",
+ "
\n",
+ " \n",
+ " $\\tcoreleft$ | \n",
+ " $-$ | \n",
+ " $\\tcoreleft$ | \n",
+ " $-$ | \n",
+ " $\\tcoreleft$ | \n",
+ " $-$ | \n",
+ " $\\cdots$ | \n",
+ " $-$ | \n",
+ " $\\tcorecenter$ | \n",
+ " $-$ | \n",
+ " $\\cdots$ | \n",
+ " $-$ | \n",
+ " $\\tcoreright$ | \n",
+ " $-$ | \n",
+ " $\\tcoreright$ | \n",
+ "
\n",
+ " \n",
+ " $\\tiny\\mid$ | \n",
+ " | \n",
+ " $\\tiny\\mid$ | \n",
+ " | \n",
+ " $\\tiny\\mid$ | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " $\\tiny\\mid$ | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " $\\tiny\\mid$ | \n",
+ " | \n",
+ " $\\tiny\\mid$ | \n",
+ "
\n",
+ "
\n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6f6cc702",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "74ce99d5-268a-4ad8-980b-de19d60b6be6",
+ "metadata": {},
+ "source": [
+ "## **Session 4 - Quantum Information**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e8441c54-ffd4-45b4-ab04-ff8cf85e6474",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a781c1c8",
+ "metadata": {},
+ "source": [
+ "## Exercise 4.1\n",
+ "\n",
+ "Which of the following are valid quantum states?\n",
+ "\n",
+ "$\\hspace{1cm}$$\\begin{pmatrix} 0 \\\\ 1\\end{pmatrix}$, $\\quad \\begin{pmatrix} 1 \\\\ 1\\end{pmatrix}$, $\\quad \\frac{1}{\\sqrt{2}}\\begin{pmatrix} 0 \\\\ -i\\end{pmatrix}$, $\\quad \\frac{1}{\\sqrt{3}}\\begin{pmatrix} 1 \\\\ 2\\end{pmatrix}$, $\\quad \\begin{pmatrix} \\sqrt{2/3} \\\\ i/\\sqrt{3}\\end{pmatrix}$\n",
+ "\n",
+ "What is the probability to measure $0$ and $1$ for the valid quantum states?"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6e1b9898-10a5-422d-8cdb-a8f42bdc01c4",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0e8243a2-a54e-4aaf-b460-f1f7f9e369b0",
+ "metadata": {},
+ "source": [
+ "## Exercise 4.2\n",
+ "\n",
+ "**a)**$\\quad$Write down the state vector of two quantum states \n",
+ "\n",
+ "$\\hspace{1cm}$$\\displaystyle|\\Psi_1\\rangle = \\alpha_1 |0\\rangle + \\beta_1 |1\\rangle \\quad $ and $\\quad |\\Psi_2\\rangle = \\alpha_2 |0\\rangle + \\beta_2 |1\\rangle$, \n",
+ "\n",
+ "$\\hspace{0.35cm}$$\\quad$i.e. the tensor product, in the computational basis. Write down the basis vectors of the composite system.\n",
+ "\n",
+ "**b)**$\\quad$Consider the $2$-qubit state \n",
+ "\n",
+ "$\\hspace{1cm}$$\\displaystyle|\\Psi\\rangle = \\frac{1}{\\sqrt{2}} |00\\rangle + \\frac{1}{2}|01\\rangle + \\frac{1}{2} |11\\rangle$. \n",
+ "\n",
+ "$\\hspace{0.35cm}$$\\quad$What is the state after a measurement of the first qubit where you obtain $|0\\rangle$?\n",
+ "\n",
+ "$\\hspace{0.35cm}$$\\quad$Is this an entangled state?\n",
+ "\n",
+ "$\\hspace{0.35cm}$$\\quad$*Hint:* Quantum states are normalized!"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "818bf57f-be0c-408a-9776-414578b7763a",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "bed85201-1bfb-45a2-a57a-44332f370276",
+ "metadata": {},
+ "source": [
+ "## Exercise 4.3\n",
+ "\n",
+ "Suppose you have $n + 1$ qubits. We will write $|\\vec{x}\\rangle$ to mean the $n$-qubit classical state given by the number $x$ in binary. For instance, if $n = 2$ then:\n",
+ "\n",
+ "$\\hspace{0.5cm}$$|\\vec{0}\\rangle = |00\\rangle , \\quad |\\vec{1}\\rangle = |01\\rangle, \\quad |\\vec{2}\\rangle = |10\\rangle, \\quad |\\vec{3}\\rangle = |11\\rangle$.\n",
+ "\n",
+ "Assume the qubits are in the state\n",
+ "\n",
+ "$\\hspace{0.5cm}$$\\displaystyle |\\Psi\\rangle = \\frac{1}{\\sqrt{2^n}} \\sum_{x=0}^{2^n -1} | \\vec{x} \\rangle \\otimes | x~\\text{mod}~2 \\rangle$.\n",
+ "\n",
+ "**a)**$\\quad$What is the resulting state if we measure the last qubit and obtain $|0\\rangle$?\n",
+ "\n",
+ "**b)**$\\quad$What is the resulting state if we measure the last qubit and obtain $|1\\rangle$?"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.11.8"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/Exercises/Session 5 - Quantum Computing.ipynb b/Exercises/Session 5 - Quantum Computing.ipynb
new file mode 100644
index 0000000..ec708cb
--- /dev/null
+++ b/Exercises/Session 5 - Quantum Computing.ipynb
@@ -0,0 +1,328 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "e4f44eb7",
+ "metadata": {},
+ "source": [
+ "TMQS Workshop 2024 @ Zuse Institute Berlin
\n",
+ "Summer School on Tensor Methods for Quantum Simulation
\n",
+ "June 3 - 5, 2024
\n",
+ "$\\def\\tcoreleft{\\textcolor{MidnightBlue}{\\Huge⦸}}$\n",
+ "$\\def\\tcorecenter{\\textcolor{RedOrange}{\\Huge⦿}}$\n",
+ "$\\def\\tcoreright{\\textcolor{MidnightBlue}{\\Huge\\oslash}}$\n",
+ "\n",
+ "
\n",
+ " \n",
+ " $\\tcoreleft$ | \n",
+ " $-$ | \n",
+ " $\\tcoreleft$ | \n",
+ " $-$ | \n",
+ " $\\tcoreleft$ | \n",
+ " $-$ | \n",
+ " $\\cdots$ | \n",
+ " $-$ | \n",
+ " $\\tcorecenter$ | \n",
+ " $-$ | \n",
+ " $\\cdots$ | \n",
+ " $-$ | \n",
+ " $\\tcoreright$ | \n",
+ " $-$ | \n",
+ " $\\tcoreright$ | \n",
+ "
\n",
+ " \n",
+ " $\\tiny\\mid$ | \n",
+ " | \n",
+ " $\\tiny\\mid$ | \n",
+ " | \n",
+ " $\\tiny\\mid$ | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " $\\tiny\\mid$ | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " $\\tiny\\mid$ | \n",
+ " | \n",
+ " $\\tiny\\mid$ | \n",
+ "
\n",
+ "
\n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6f6cc702",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "74ce99d5-268a-4ad8-980b-de19d60b6be6",
+ "metadata": {},
+ "source": [
+ "## **Session 5 - Quantum Computing**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e8441c54-ffd4-45b4-ab04-ff8cf85e6474",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "352b5d1e-a082-49c0-a29a-3c73d819a5a5",
+ "metadata": {},
+ "source": [
+ "## Exercise 5.1\n",
+ "\n",
+ "The qubit polar form is given by $|\\psi\\rangle = \\cos{\\frac{\\theta}{2}} |0\\rangle + e^{i \\varphi} \\sin{\\frac{\\theta}{2}} |1\\rangle$. \n",
+ "\n",
+ "The first two quantum logic gates, we consider in this exercise are the Hadamard gate $H$ and the phase shift gate $T$:\n",
+ "\n",
+ "$\\hspace{0.5cm}$$\\displaystyle H = \\frac{1}{\\sqrt{2}} \\begin{bmatrix} 1 & 1 \\\\ 1 & -1\\end{bmatrix} \\qquad $ and $ \\qquad \\displaystyle T = \\begin{bmatrix}1 & 0 \\\\ 0 & e^{i \\frac{\\pi}{4}}\\end{bmatrix}$\n",
+ "\n",
+ "When applied to a basis state $|0\\rangle$ or $|1\\rangle$, the Hadamard gate transforms the state as follows:\n",
+ "\n",
+ "$\\hspace{0.5cm}$$\\displaystyle H | 0 \\rangle = \\frac{1}{\\sqrt{2}} \\left( |0\\rangle + |1\\rangle\\right) \\qquad$ and $\\qquad \\displaystyle H | 1 \\rangle = \\frac{1}{\\sqrt{2}} \\left( |0\\rangle - |1\\rangle\\right)$\n",
+ "\n",
+ "The $T$ gate applies a phase factor to the state $|1\\rangle$, while leaving the state $|0\\rangle$ unchanged:\n",
+ "\n",
+ "$\\hspace{0.5cm}$$\\displaystyle T | 0 \\rangle = | 0 \\rangle \\qquad$ and $\\qquad \\displaystyle T | 1 \\rangle = e^{i \\frac{\\pi}{4}} | 1 \\rangle$\n",
+ "\n",
+ "**a)**$\\quad$ Import all necessary packages:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "4f9f119a-5785-4aaa-a65b-bed55c8656d0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from qiskit.visualization import *\n",
+ "from qiskit.quantum_info import Statevector\n",
+ "from qiskit import QuantumCircuit, transpile\n",
+ "from qiskit_aer import AerSimulator"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "47fc839a",
+ "metadata": {},
+ "source": [
+ "$\\hspace{0.8cm}$and create a quantum circuit consisting of one qubit by \n",
+ "\n",
+ "> qc = QuantumCircuit(1)\n",
+ "\n",
+ "$\\hspace{0.8cm}$Apply a Hadamard gate and a T gate:\n",
+ "\n",
+ "> qc.h(0), qc.t(0)\n",
+ "\n",
+ "$\\hspace{0.8cm}$Draw the quantum circuit using \n",
+ "\n",
+ "> qc.draw() \n",
+ "\n",
+ "$\\hspace{0.8cm}$and plot the Bloch vector of the quantum state at each stage using\n",
+ "\n",
+ "> plot_bloch_multivector(Statevector(qc))\n",
+ "\n",
+ "$\\hspace{0.8cm}$Write down the polar form of the quantum state at each step of the circuit.\n",
+ "\n",
+ "**b)**$\\quad$Now, we want to measure our qubit using\n",
+ "\n",
+ "> qc.measure_all()\n",
+ "\n",
+ "$\\hspace{0.8cm}$To do this, we choose a simulator backend, which is responsible for simulating the execution of the circuit. \n",
+ "\n",
+ "$\\hspace{0.8cm}$The simulator plays a crucial role in simulating the behavior of a quantum circuit. \n",
+ "\n",
+ "$\\hspace{0.8cm}$It allows you to run quantum circuits on a classical computer and obtain the expected outcomes of the circuit without requiring a physical quantum device. \n",
+ "\n",
+ "$\\hspace{0.8cm}$Here, we choose the qasm_simulator, which simulates the execution of the circuit using a classical computer and provides the measurement statistics:\n",
+ "\n",
+ "> backend = AerSimulator()\n",
+ "\n",
+ "$\\hspace{0.8cm}$We then transpile, i.e., optimize a quantum circuit for a specific backend, and execute the circuit on the simulator by passing the circuit to the run function.\n",
+ "\n",
+ "$\\hspace{0.8cm}$We also specify the number of shots to simulate, which determines the number of times the circuit is executed to obtain statistical results.\n",
+ "\n",
+ "> qc = transpile(qc, backend)\n",
+ "> \n",
+ "> job = backend.run(qc, shots=10000)\n",
+ "\n",
+ "$\\hspace{0.8cm}$Finally, we get the results of the simulation using the result method, and extract the measurement statistics using the get_counts method:\n",
+ "\n",
+ "> result = job.result()\n",
+ "\n",
+ "> counts = result.get_counts(qc)\n",
+ "\n",
+ "$\\hspace{0.8cm}$The measurement statistics represent the probabilities of observing each possible measurement outcome.\n",
+ "\n",
+ "$\\hspace{0.8cm}$They are obtained by running the circuit multiple times and counting the number of times each outcome is observed.\n",
+ "\n",
+ "$\\hspace{0.8cm}$The histogram of the counts data can be plotted by using\n",
+ "\n",
+ "> plot_histogram(counts)\n",
+ "\n",
+ "$\\hspace{0.8cm}$What happens if we measure the quantum state after the H gate, what if we measure after the T gate. Explain!\n",
+ "\n",
+ "**c)**$\\quad$How can we measure the relative phase $\\varphi$?\n",
+ "\n",
+ "$\\hspace{0.8cm}$*Hint:* We need just one additional gate.\n",
+ "\n",
+ "**d)**$\\quad$*extra task:* Show that any state $|\\psi\\rangle = \\alpha |0\\rangle + \\beta |1 \\rangle$ with $|\\alpha|^2 + |\\beta|^2 = 1$ can be written in the polar form (up to a global phase)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d980f769-6854-4d71-a713-e219ddea1f65",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ddf38779",
+ "metadata": {},
+ "source": [
+ "### Exercise 5.2\n",
+ "\n",
+ "Now, we want to construct some specific states. The quantum logic gates which come now into play are the Pauli-$Z$ gate, the Pauli-$X$ (NOT) gate, and the CNOT gate:\n",
+ "\n",
+ "$\\hspace{0.5cm}$$\\displaystyle Z = \\begin{bmatrix} 1 & 0 \\\\ 0 & -1\\end{bmatrix}$, $\\qquad \\displaystyle \\text{NOT} = \\begin{bmatrix} 0& 1\\\\ 1 & 0 \\end{bmatrix}$, $\\qquad \\displaystyle \\text{CNOT} = \\begin{bmatrix}1 & 0 & 0 & 0\\\\ 0 & 1 & 0 & 0 \\\\ 0 & 0 & 0& 1\\\\ 0 & 0 & 1 & 0 \\end{bmatrix}$\n",
+ "\n",
+ "The $Z$ gate flips the phase of the basis state $|1\\rangle$ while the NOT gate (sometimes called bit-flip) maps \n",
+ "$|0\\rangle$ to $|1\\rangle$ and $|1\\rangle$ to $|0\\rangle$.\n",
+ "\n",
+ "The CNOT (controlled NOT) gate acts on 2 qubits and performs the NOT operation on the second qubit only when the first qubit is $|1\\rangle$.\n",
+ "\n",
+ "
\n",
+ "\n",
+ "**a)**$\\quad$Construct the Bell state $\\displaystyle |\\Phi^+\\rangle = \\frac{|00\\rangle + |11\\rangle}{\\sqrt{2}} $. To do so, create a quantum circuit with two qubits and and use one Hadamard gate and one CNOT gate:\n",
+ "\n",
+ "> qc.cx(0,1)\n",
+ "\n",
+ "$\\hspace{0.8cm}$where the first argument is the control qubit. Draw the circuit, measure the final state, and plot the histogram\n",
+ "\n",
+ "**b)**$\\quad$How can we construct the other Bell states?\n",
+ "\n",
+ "$\\hspace{1cm}$$\\displaystyle|\\Phi^-\\rangle = \\frac{|00\\rangle - |11\\rangle}{\\sqrt{2}} $, $\\qquad \\displaystyle|\\Psi^+\\rangle = \\frac{|01\\rangle + |10\\rangle}{\\sqrt{2}} $, $\\qquad \\displaystyle|\\Psi^-\\rangle = \\frac{|01\\rangle - |10\\rangle}{\\sqrt{2}} $\n",
+ "\n",
+ "**c)**$\\quad$In quantum computing, oracles play a crucial role in many quantum algorithms. \n",
+ "\n",
+ "$\\hspace{0.8cm}$An oracle is a black box subroutine used to perform a specific computation on a quantum state. \n",
+ "\n",
+ "$\\hspace{0.8cm}$Find an oracle $U$, i.e., a unitary operation, acting on three qubits corresponding to the following truth table:\n",
+ "\n",
+ "| | Input | Output |\n",
+ "| -- | ----- | ------ |\n",
+ "| 0 | 000 | 000 |\n",
+ "| 1 | 001 | 001 |\n",
+ "| 2 | 010 | 011 |\n",
+ "| 3 | 011 | 010 |\n",
+ "| 4 | 100 | 111 |\n",
+ "| 5 | 101 | 110 |\n",
+ "| 6 | 110 | 100 |\n",
+ "| 7 | 111 | 101 |\n",
+ "\n",
+ "\n",
+ "$\\hspace{0.8cm}$Write down the matrix representation! What does the circuit look like?\n",
+ "\n",
+ "**d)**$\\quad$*extra task:* What kind of gate is expressed by the following circuit? Here, 'tdg' denotes the adjoint of the T gate."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "b5856bd8-fced-4218-bdc3-df61b56e5fdf",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " ┌───┐ \n",
+ "q_0: ───────────────────■─────────────────────■───────────■────┤ T ├────■──\n",
+ " │ │ ┌───┐ ┌─┴─┐ ┌┴───┴┐ ┌─┴─┐\n",
+ "q_1: ───────■───────────┼─────────■───────────┼───┤ T ├─┤ X ├─┤ Tdg ├─┤ X ├\n",
+ " ┌───┐┌─┴─┐┌─────┐┌─┴─┐┌───┐┌─┴─┐┌─────┐┌─┴─┐ ├───┤ ├───┤ └─────┘ └───┘\n",
+ "q_2: ┤ H ├┤ X ├┤ Tdg ├┤ X ├┤ T ├┤ X ├┤ Tdg ├┤ X ├─┤ T ├─┤ H ├──────────────\n",
+ " └───┘└───┘└─────┘└───┘└───┘└───┘└─────┘└───┘ └───┘ └───┘
"
+ ],
+ "text/plain": [
+ " ┌───┐ \n",
+ "q_0: ───────────────────■─────────────────────■───────────■────┤ T ├────■──\n",
+ " │ │ ┌───┐ ┌─┴─┐ ┌┴───┴┐ ┌─┴─┐\n",
+ "q_1: ───────■───────────┼─────────■───────────┼───┤ T ├─┤ X ├─┤ Tdg ├─┤ X ├\n",
+ " ┌───┐┌─┴─┐┌─────┐┌─┴─┐┌───┐┌─┴─┐┌─────┐┌─┴─┐ ├───┤ ├───┤ └─────┘ └───┘\n",
+ "q_2: ┤ H ├┤ X ├┤ Tdg ├┤ X ├┤ T ├┤ X ├┤ Tdg ├┤ X ├─┤ T ├─┤ H ├──────────────\n",
+ " └───┘└───┘└─────┘└───┘└───┘└───┘└─────┘└───┘ └───┘ └───┘ "
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "circuit = QuantumCircuit(3)\n",
+ "circuit.h(2)\n",
+ "circuit.cx(1,2)\n",
+ "circuit.tdg(2)\n",
+ "circuit.cx(0,2)\n",
+ "circuit.t(2)\n",
+ "circuit.cx(1,2)\n",
+ "circuit.tdg(2)\n",
+ "circuit.cx(0,2)\n",
+ "circuit.barrier()\n",
+ "circuit.t(1)\n",
+ "circuit.t(2)\n",
+ "circuit.barrier()\n",
+ "circuit.h(2)\n",
+ "circuit.cx(0,1)\n",
+ "circuit.barrier()\n",
+ "circuit.t(0)\n",
+ "circuit.tdg(1)\n",
+ "circuit.barrier()\n",
+ "circuit.cx(0,1)\n",
+ "circuit.draw(plot_barriers = False) "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c072e544-570f-4949-bd2b-d9c13df9bb23",
+ "metadata": {},
+ "source": [
+ "$\\hspace{0.8cm}$*Hint:* For states of the form $|11x\\rangle$, we have $|110\\rangle \\mapsto |111\\rangle$ and $|111\\rangle \\mapsto |110\\rangle$. What happens with quantum states of different form?"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.11.8"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/Exercises/Session 6 - Quantum Simulation.ipynb b/Exercises/Session 6 - Quantum Simulation.ipynb
new file mode 100644
index 0000000..952c935
--- /dev/null
+++ b/Exercises/Session 6 - Quantum Simulation.ipynb
@@ -0,0 +1,314 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "e4f44eb7",
+ "metadata": {},
+ "source": [
+ "TMQS Workshop 2024 @ Zuse Institute Berlin
\n",
+ "Summer School on Tensor Methods for Quantum Simulation
\n",
+ "June 3 - 5, 2024
\n",
+ "$\\def\\tcoreleft{\\textcolor{MidnightBlue}{\\Huge⦸}}$\n",
+ "$\\def\\tcorecenter{\\textcolor{RedOrange}{\\Huge⦿}}$\n",
+ "$\\def\\tcoreright{\\textcolor{MidnightBlue}{\\Huge\\oslash}}$\n",
+ "\n",
+ "
\n",
+ " \n",
+ " $\\tcoreleft$ | \n",
+ " $-$ | \n",
+ " $\\tcoreleft$ | \n",
+ " $-$ | \n",
+ " $\\tcoreleft$ | \n",
+ " $-$ | \n",
+ " $\\cdots$ | \n",
+ " $-$ | \n",
+ " $\\tcorecenter$ | \n",
+ " $-$ | \n",
+ " $\\cdots$ | \n",
+ " $-$ | \n",
+ " $\\tcoreright$ | \n",
+ " $-$ | \n",
+ " $\\tcoreright$ | \n",
+ "
\n",
+ " \n",
+ " $\\tiny\\mid$ | \n",
+ " | \n",
+ " $\\tiny\\mid$ | \n",
+ " | \n",
+ " $\\tiny\\mid$ | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " $\\tiny\\mid$ | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " $\\tiny\\mid$ | \n",
+ " | \n",
+ " $\\tiny\\mid$ | \n",
+ "
\n",
+ "
\n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6f6cc702",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "74ce99d5-268a-4ad8-980b-de19d60b6be6",
+ "metadata": {},
+ "source": [
+ "## **Session 6 - Quantum Simulation**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e8441c54-ffd4-45b4-ab04-ff8cf85e6474",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "352b5d1e-a082-49c0-a29a-3c73d819a5a5",
+ "metadata": {},
+ "source": [
+ "## Exercise 6.1\n",
+ "\n",
+ "Let us examine the quantum counterpart of a standard classical circuit. The *quantum full adder* (QFA) is the quantum analogue of a full-adder circuit used in classical computers to add up to three bits. Due to reversibility requirements, the QFA acts on four qubits: The input qubits are $\\ket{C_\\mathrm{in}}$, $\\ket{A}$, $\\ket{B}$, and $\\ket{0}$ and the output qubits are $\\ket{S}$, $\\ket{A}$, $\\ket{B}$, and $\\ket{C_\\mathrm{out}}$. The qubit $\\ket{C_\\mathrm{in}}$ is carried in from the previous (less-significant) stage of a multi-digit addition. The circuit produces the sum of the input qubits including a carry-out signal for the overflow into the next digit. \n",
+ "\n",
+ "The QFA algorithm is given by the following circuit:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "eb600b78-178c-4ab2-b25b-17a629e98a44",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " ┌───┐ \n",
+ "C_in: ────────────■──┤ X ├─────\n",
+ " │ └─┬─┘ \n",
+ " A: ──■────■────┼────┼────■──\n",
+ " │ ┌─┴─┐ │ │ ┌─┴─┐\n",
+ " B: ──■──┤ X ├──■────■──┤ X ├\n",
+ " ┌─┴─┐└───┘┌─┴─┐ └───┘\n",
+ " 0: ┤ X ├─────┤ X ├──────────\n",
+ " └───┘ └───┘
"
+ ],
+ "text/plain": [
+ " ┌───┐ \n",
+ "C_in: ────────────■──┤ X ├─────\n",
+ " │ └─┬─┘ \n",
+ " A: ──■────■────┼────┼────■──\n",
+ " │ ┌─┴─┐ │ │ ┌─┴─┐\n",
+ " B: ──■──┤ X ├──■────■──┤ X ├\n",
+ " ┌─┴─┐└───┘┌─┴─┐ └───┘\n",
+ " 0: ┤ X ├─────┤ X ├──────────\n",
+ " └───┘ └───┘ "
+ ]
+ },
+ "execution_count": 1,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "from qiskit import QuantumRegister, QuantumCircuit\n",
+ "\n",
+ "C_in = QuantumRegister(1, 'C_in')\n",
+ "A = QuantumRegister(1, 'A')\n",
+ "B = QuantumRegister(1, 'B')\n",
+ "Zero = QuantumRegister(1, '0')\n",
+ "\n",
+ "qc = QuantumCircuit(C_in, A, B, Zero)\n",
+ "\n",
+ "qc.ccx(1,2,3)\n",
+ "qc.cx(1,2)\n",
+ "qc.ccx(0,2,3)\n",
+ "qc.cx(2,0)\n",
+ "qc.cx(1,2)\n",
+ "qc.draw() "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9bfa9c5f-b45b-4c3d-9d8c-f07d41ce2a35",
+ "metadata": {},
+ "source": [
+ "**a)**$\\quad$Write down the corresponding truth table!\n",
+ "\n",
+ "**b**)$\\quad$The unitary operator of the QFA can be written as an MPO of the following form:\n",
+ "\n",
+ "$\\hspace{1cm}$$\\mathbf{G} = \\begin{bmatrix} \\sigma_x C_0 & I & \\sigma_x C_1\\end{bmatrix} \\otimes \\begin{bmatrix} C_0 & C_1 & 0 & 0 \\\\ 0 & C_0 & C_1 & 0 \\\\ 0 & 0 & C_0 & C_1 \\end{bmatrix} \\otimes \\begin{bmatrix} C_1 & 0 \\\\ C_0 & 0 \\\\ 0 & C_1 \\\\ 0 & C_0 \\end{bmatrix} \\otimes \\begin{bmatrix} I \\\\ \\sigma_x \\end{bmatrix}$,\n",
+ "\n",
+ "$\\hspace{0.8cm}$where the matrices in the core elements are given by\n",
+ "\n",
+ "$\\hspace{1cm}$$I = \\begin{pmatrix} 1 & 0 \\\\ 0 & 1 \\end{pmatrix}, \\quad \\sigma_x = \\begin{pmatrix} 0 & 1 \\\\ 1 & 0 \\end{pmatrix}, \\quad C_0 = \\begin{pmatrix} 1 & 0 \\\\ 0 & 0 \\end{pmatrix}, \\quad C_1 = \\begin{pmatrix} 0 & 0 \\\\ 0 & 1 \\end{pmatrix}$.\n",
+ "\n",
+ "$\\hspace{0.8cm}$Derive a canonical representation of the operator by contracting theMPO cores!\n",
+ "\n",
+ "**c**)$\\quad$*extra task:* Show that this representation is unitary. Show that $\\mathbf{G}$ actually represents the QFA!\n",
+ "\n",
+ "**d**)$\\quad$Implement a *quantum full ader network* (QFAN), i.e., a quantum circuit to add $n$-bit numbers, in Qiskit by coupling several QFAs:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "6b986e09-4215-440f-a577-8b84592a1b86",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " ┌───┐ ░ ░ ░ \n",
+ "q_0: ────────────■──┤ X ├──────░───────────────────────────░───────────────────────────░─\n",
+ " │ └─┬─┘ ░ ░ ░ \n",
+ "q_1: ──■────■────┼────┼────■───░───────────────────────────░───────────────────────────░─\n",
+ " │ ┌─┴─┐ │ │ ┌─┴─┐ ░ ░ ░ \n",
+ "q_2: ──■──┤ X ├──■────■──┤ X ├─░───────────────────────────░───────────────────────────░─\n",
+ " ┌─┴─┐└───┘┌─┴─┐ └───┘ ░ ┌───┐ ░ ░ \n",
+ "q_3: ┤ X ├─────┤ X ├───────────░─────────────■──┤ X ├──────░───────────────────────────░─\n",
+ " └───┘ └───┘ ░ │ └─┬─┘ ░ ░ \n",
+ "q_4: ──────────────────────────░───■────■────┼────┼────■───░───────────────────────────░─\n",
+ " ░ │ ┌─┴─┐ │ │ ┌─┴─┐ ░ ░ \n",
+ "q_5: ──────────────────────────░───■──┤ X ├──■────■──┤ X ├─░───────────────────────────░─\n",
+ " ░ ┌─┴─┐└───┘┌─┴─┐ └───┘ ░ ┌───┐ ░ \n",
+ "q_6: ──────────────────────────░─┤ X ├─────┤ X ├───────────░─────────────■──┤ X ├──────░─\n",
+ " ░ └───┘ └───┘ ░ │ └─┬─┘ ░ \n",
+ "q_7: ──────────────────────────░───────────────────────────░───■────■────┼────┼────■───░─\n",
+ " ░ ░ │ ┌─┴─┐ │ │ ┌─┴─┐ ░ \n",
+ "q_8: ──────────────────────────░───────────────────────────░───■──┤ X ├──■────■──┤ X ├─░─\n",
+ " ░ ░ ┌─┴─┐└───┘┌─┴─┐ └───┘ ░ \n",
+ "q_9: ──────────────────────────░───────────────────────────░─┤ X ├─────┤ X ├───────────░─\n",
+ " ░ ░ └───┘ └───┘ ░
"
+ ],
+ "text/plain": [
+ " ┌───┐ ░ ░ ░ \n",
+ "q_0: ────────────■──┤ X ├──────░───────────────────────────░───────────────────────────░─\n",
+ " │ └─┬─┘ ░ ░ ░ \n",
+ "q_1: ──■────■────┼────┼────■───░───────────────────────────░───────────────────────────░─\n",
+ " │ ┌─┴─┐ │ │ ┌─┴─┐ ░ ░ ░ \n",
+ "q_2: ──■──┤ X ├──■────■──┤ X ├─░───────────────────────────░───────────────────────────░─\n",
+ " ┌─┴─┐└───┘┌─┴─┐ └───┘ ░ ┌───┐ ░ ░ \n",
+ "q_3: ┤ X ├─────┤ X ├───────────░─────────────■──┤ X ├──────░───────────────────────────░─\n",
+ " └───┘ └───┘ ░ │ └─┬─┘ ░ ░ \n",
+ "q_4: ──────────────────────────░───■────■────┼────┼────■───░───────────────────────────░─\n",
+ " ░ │ ┌─┴─┐ │ │ ┌─┴─┐ ░ ░ \n",
+ "q_5: ──────────────────────────░───■──┤ X ├──■────■──┤ X ├─░───────────────────────────░─\n",
+ " ░ ┌─┴─┐└───┘┌─┴─┐ └───┘ ░ ┌───┐ ░ \n",
+ "q_6: ──────────────────────────░─┤ X ├─────┤ X ├───────────░─────────────■──┤ X ├──────░─\n",
+ " ░ └───┘ └───┘ ░ │ └─┬─┘ ░ \n",
+ "q_7: ──────────────────────────░───────────────────────────░───■────■────┼────┼────■───░─\n",
+ " ░ ░ │ ┌─┴─┐ │ │ ┌─┴─┐ ░ \n",
+ "q_8: ──────────────────────────░───────────────────────────░───■──┤ X ├──■────■──┤ X ├─░─\n",
+ " ░ ░ ┌─┴─┐└───┘┌─┴─┐ └───┘ ░ \n",
+ "q_9: ──────────────────────────░───────────────────────────░─┤ X ├─────┤ X ├───────────░─\n",
+ " ░ ░ └───┘ └───┘ ░ "
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "n = 3\n",
+ "qc = QuantumCircuit(3*n+1)\n",
+ "for i in range(n):\n",
+ " qc.ccx(3*i+1,3*i+2,3*i+3)\n",
+ " qc.cx(3*i+1,3*i+2)\n",
+ " qc.ccx(3*i+0,3*i+2,3*i+3)\n",
+ " qc.cx(3*i+2,3*i+0)\n",
+ " qc.cx(3*i+1,3*i+2)\n",
+ " qc.barrier()\n",
+ "qc.draw(fold=-1) "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "50a02475-3438-436c-b904-62da8707cc51",
+ "metadata": {},
+ "source": [
+ "$\\hspace{0.8cm}$Simulate the circuit for $n = 1, \\dots, 8$ with 1.000.000 shots after applying Hadamard gates to the qubits $|A_i\\rangle $ and $| B_i \\rangle$ of each QFA. Plot the relative computation time!\n",
+ "\n",
+ "**e**)$\\quad$Load the corresponding MPO representation ```scikit_tt.models``` by\n",
+ "\n",
+ "> import scikit_tt.models as mdl\n",
+ ">\n",
+ "> G = mdl.qfan(n)\n",
+ "\n",
+ "$\\hspace{0.8cm}$where ```n``` is the number of QFAs.\n",
+ "\n",
+ "$\\hspace{0.8cm}$The initial quantum state can be expressed as a rank-one tensor. Can you explain why? \n",
+ "\n",
+ "$\\hspace{0.8cm}$Use the following routine for construction."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "3b5ab505-6a59-4059-9d28-3c4b71247710",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from scikit_tt.tensor_train import TT\n",
+ "\n",
+ "def initial_state(n):\n",
+ " cores = [np.array([1,0]).reshape([1,2,1,1]) for _ in range(3*n+1)]\n",
+ " for i in range(n):\n",
+ " cores[3*i+1] = np.sqrt(0.5)*np.array([1,1]).reshape([1,2,1,1])\n",
+ " init = TT(cores)\n",
+ " return init"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "04dfd8d2-d44c-4db1-9791-04de8fec3b39",
+ "metadata": {},
+ "source": [
+ "$\\hspace{0.8cm}$Repeat the above experiment on a tensor-based level by computing the state tensor $\\mathbf{G} \\mathbf{\\Psi}$, where $\\mathbf{\\Psi}$ is the initial state.\n",
+ "\n",
+ "$\\hspace{0.8cm}$Use the sampling routine from ```scikit_tt.quantum_computation```:\n",
+ "\n",
+ "> from scikit_tt.quantum_computation import sampling\n",
+ ">\n",
+ "> samples, probabilities = sampling(G@init, list(np.arange(3*i+1)), 1000000)\n",
+ "\n",
+ "$\\hspace{0.8cm}$What do you observe?"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.11.8"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}