From 6725ad5248d145c762d6743f966ea36527c721d5 Mon Sep 17 00:00:00 2001 From: Bill Ticehurst Date: Thu, 2 May 2024 19:06:14 -0700 Subject: [PATCH] Use markdown-it and katex (#1438) This addresses #845 Previously we used 'marked' and 'mathjax' in the playground, but 'markdown-it' and 'katex' in VS Code - the latter being what VS Code uses for its Markdown and LaTeX rendering in file previews, Jupyter notebooks, etc. This converts the playground, and the kata content generation, to use markdown-it and katex, and removes 'marked' and 'mathjax' from the repo. Note that KaTeX is more strict that MathJax that the LaTeX is well formed. This is probably a _good thing_ while we're authoring content. I did need to clean up quite a bit of LaTeX in testing this, and there's probably quite a bit more elsewhere to go over. (In general our LaTeX is often in poor shape. We might want to look into any 'linting' options for it). Feel free to skip the .md files and focus on the code initially. I also significantly revamped how we render markdown in a Preact components. This has led to much cleaner code, and deleting a lot of useRef and useEffect and dangerouslySetInnerHtml code, and the need to re-typeset content. (Esp. see kata.tsx and docs.tsx). --------- Co-authored-by: Mariia Mykhailova --- .../cartesian_to_polar/solution.md | 2 +- katas/content/complex_arithmetic/index.md | 2 +- .../powers_of_i/solution.md | 31 +- katas/content/deutsch_algo/index.md | 2 +- katas/content/deutsch_jozsa/index.md | 4 +- .../content/getting_started/media/Coding.svg | 6 +- .../content/linear_algebra/addition/index.md | 2 +- .../linear_algebra/addition/solution.md | 4 +- katas/content/linear_algebra/adjoint/index.md | 2 +- .../content/linear_algebra/conjugate/index.md | 2 +- katas/content/linear_algebra/index.md | 140 ++++---- .../linear_algebra/inner_product/index.md | 2 +- .../linear_algebra/inner_product/solution.md | 6 +- katas/content/linear_algebra/inverse/index.md | 2 +- .../linear_algebra/inverse/solution.md | 4 +- .../linear_algebra/multiplication/index.md | 2 +- .../linear_algebra/multiplication/solution.md | 4 +- .../linear_algebra/normalized_vector/index.md | 2 +- .../normalized_vector/solution.md | 2 +- .../linear_algebra/outer_product/index.md | 2 +- .../linear_algebra/outer_product/solution.md | 10 +- .../scalar_multiplication/index.md | 2 +- .../scalar_multiplication/solution.md | 4 +- .../linear_algebra/tensor_product/index.md | 2 +- .../linear_algebra/tensor_product/solution.md | 18 +- .../content/linear_algebra/transpose/index.md | 2 +- .../anti_controlled_gate/solution.md | 20 +- .../arbitrary_controls/solution.md | 2 +- .../multi_qubit_gates/compound_gate/index.md | 18 +- .../compound_gate/solution.md | 30 +- .../controlled_rotation/solution.md | 2 +- .../fredkin_gate/solution.md | 36 +- katas/content/multi_qubit_gates/index.md | 150 ++++----- .../preparing_bell_state/index.md | 2 +- .../multi_qubit_gates/qubit_swap/index.md | 4 +- .../relative_phase_minusone/solution.md | 8 +- .../toffoli_gate/solution.md | 33 +- .../content/multi_qubit_measurements/index.md | 59 ++-- katas/content/multi_qubit_systems/index.md | 74 ++--- .../prepare_basis_state/index.md | 4 +- .../prepare_basis_state/solution.md | 4 +- .../prepare_superposition/index.md | 6 +- .../prepare_superposition/solution.md | 10 +- .../prepare_with_complex/index.md | 6 +- .../prepare_with_complex/solution.md | 14 +- .../prepare_with_real/index.md | 6 +- .../prepare_with_real/solution.md | 4 +- katas/content/oracles/index.md | 6 +- katas/content/qec_shor/index.md | 4 +- katas/content/qubit/index.md | 44 +-- katas/content/random_numbers/index.md | 6 +- .../random_numbers/random_bit/solution.md | 10 +- .../amplitude_change/solution.md | 22 +- .../basis_change/solution.md | 20 +- .../complex_phase/solution.md | 10 +- .../global_phase_i/index.md | 4 +- .../global_phase_i/solution.md | 6 +- .../global_phase_minusone/solution.md | 4 +- katas/content/single_qubit_gates/index.md | 88 ++--- .../single_qubit_gates/phase_i/solution.md | 10 +- .../prepare_arbitrary_state/solution.md | 8 +- .../prepare_rotated_state/solution.md | 6 +- .../single_qubit_gates/sign_flip/solution.md | 20 +- .../sign_flip_on_zero/index.md | 2 +- .../sign_flip_on_zero/solution.md | 8 +- .../single_qubit_gates/state_flip/solution.md | 18 +- .../three_quarters_pi_phase/index.md | 2 +- .../three_quarters_pi_phase/solution.md | 8 +- .../single_qubit_gates/y_gate/index.md | 4 +- .../single_qubit_gates/y_gate/solution.md | 6 +- .../distinguish_orthogonal_states_1/index.md | 2 +- .../solution.md | 2 +- .../single_qubit_measurements/index.md | 24 +- .../all_basis_vectors/solution.md | 15 +- .../superposition/all_bell_states/solution.md | 2 +- .../superposition/bell_state/solution.md | 18 +- .../controlled_rotation/solution.md | 8 +- .../superposition/even_odd/solution.md | 46 +-- .../solution.md | 4 +- .../solution.md | 2 +- .../superposition/minus_state/solution.md | 2 +- .../superposition/plus_state/solution.md | 2 +- .../solution.md | 4 +- .../unequal_superposition/solution.md | 10 +- npm/qsharp/generate_katas_content.js | 26 +- npm/qsharp/ux/estimatesPanel.tsx | 3 +- npm/qsharp/ux/index.ts | 1 + npm/qsharp/ux/reTable.tsx | 18 +- npm/qsharp/ux/renderers.tsx | 32 ++ package-lock.json | 22 +- package.json | 4 +- playground/build.js | 18 +- playground/public/index.html | 18 +- playground/public/katas.html | 42 +++ playground/src/docs.tsx | 21 +- playground/src/kata.tsx | 312 ++++++++---------- playground/src/kataViewer.ts | 144 ++++++++ playground/src/main.tsx | 20 +- playground/src/state.tsx | 12 +- playground/src/tsconfig.json | 7 +- vscode/build.mjs | 14 +- vscode/src/webview/webview.tsx | 15 +- 102 files changed, 1084 insertions(+), 855 deletions(-) create mode 100644 npm/qsharp/ux/renderers.tsx create mode 100644 playground/public/katas.html create mode 100644 playground/src/kataViewer.ts diff --git a/katas/content/complex_arithmetic/cartesian_to_polar/solution.md b/katas/content/complex_arithmetic/cartesian_to_polar/solution.md index da25f486e5..641f9b4cdc 100644 --- a/katas/content/complex_arithmetic/cartesian_to_polar/solution.md +++ b/katas/content/complex_arithmetic/cartesian_to_polar/solution.md @@ -13,7 +13,7 @@ $$ re^{i \theta} = r \cos \theta + i r \sin \theta $$ For two complex numbers to be equal, their real and imaginary parts have to be equal. This gives us the following system of equations: -$$ \begin{cases} a = r \cos \theta \\\\ b = r \sin \theta \end{cases} $$ +$$ \begin{cases} a = r \cos \theta \\ b = r \sin \theta \end{cases} $$ To calculate $\theta$, we can divide the second equation by the first one to get diff --git a/katas/content/complex_arithmetic/index.md b/katas/content/complex_arithmetic/index.md index 07c619c62d..11fe678c81 100644 --- a/katas/content/complex_arithmetic/index.md +++ b/katas/content/complex_arithmetic/index.md @@ -39,7 +39,7 @@ $$i+i=2i$$ $$i-i=0$$ -$$-1 \\cdot i=-i$$ +$$-1 \cdot i=-i$$ $$(-i)^{2} = -1$$ diff --git a/katas/content/complex_arithmetic/powers_of_i/solution.md b/katas/content/complex_arithmetic/powers_of_i/solution.md index 5e3ef14947..19b3a405fb 100644 --- a/katas/content/complex_arithmetic/powers_of_i/solution.md +++ b/katas/content/complex_arithmetic/powers_of_i/solution.md @@ -10,9 +10,34 @@ For an even exponent $n$ that is not divisible by 4 you'll have $i^n = i^2 = -1. Here is the complete pattern that arises when raising $i$ to non-negative powers. Note that it is periodic with period $4$. -|Power of $i$ | $i^0$ | $i^1$ | $i^2$ | $i^3$ | $i^4$ | $i^5$ | $i^6$ | $i^7$ | $i^8$ | $\dots$ | -|----|----|----|----|----|----|----|----|----|----|----| -|Result | $1$ | $i$ | $-1$ | $-i$ | $1$ | $i$ | $-1$ | $-i$ | $1$ | $\dots$ | + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Power of $i$ $i^0$ $i^1$ $i^2$ $i^3$ $i^4$ $i^5$ $i^6$ $i^7$ $i^8$ $\dots$
Result $1$ $i$ $-1$ $-i$ $1$ $i$ $-1$ $-i$ $1$ $\dots$
> `%` is the Q# modulo operator which returns the remainder of a division. For example, `7%2` gives $1$, because $1$ is the remainder of dividing $7$ by $2$. > We can use this operator to determine if the exponent $n$ is divisible by $4$. diff --git a/katas/content/deutsch_algo/index.md b/katas/content/deutsch_algo/index.md index 0b3e917224..496e20d635 100644 --- a/katas/content/deutsch_algo/index.md +++ b/katas/content/deutsch_algo/index.md @@ -24,7 +24,7 @@ This kata introduces you to Deutsch algorithm - the single-qubit variant of Deut "title": "The Problem" }) -You are given a classical function that takes one bit as an input and returns one bit: $f(x): \\{0, 1\\} \to \\{0, 1\\}$. You are guaranteed that the function $f$ is +You are given a classical function that takes one bit as an input and returns one bit: $f(x): \{0, 1\} \to \{0, 1\}$. You are guaranteed that the function $f$ is - either *constant* (returns the same value for all inputs) - or *variable* (returns different values for different inputs). diff --git a/katas/content/deutsch_jozsa/index.md b/katas/content/deutsch_jozsa/index.md index 01b4d368bf..2954abda9b 100644 --- a/katas/content/deutsch_jozsa/index.md +++ b/katas/content/deutsch_jozsa/index.md @@ -26,7 +26,7 @@ This kata introduces you to Deutsch-Jozsa algorithm - one of the most famous alg "title": "The Problem" }) -You are given a classical function that takes an $N$-bit string as an input and returns one bit: $f(x): \\{0, 1\\}^N \to \\{0, 1\\}$. You are guaranteed that the function $f$ is +You are given a classical function that takes an $N$-bit string as an input and returns one bit: $f(x): \{0, 1\}^N \to \{0, 1\}$. You are guaranteed that the function $f$ is - either *constant* (returns the same value for all inputs) - or *balanced* (returns value $0$ for half of the inputs and $1$ for the other half of the inputs). @@ -235,7 +235,7 @@ The last demo in this kata shows you how to combine the oracles you've seen so f }) To wrap up our discussion in this kata, let's take a look at a problem solved using a similar approach - the Bernstein-Vazirani algorithm. -In this problem, you are also given an oracle implementing an $N$-bit function $f(x): \\{0, 1\\}^N \to \\{0, 1\\}$. +In this problem, you are also given an oracle implementing an $N$-bit function $f(x): \{0, 1\}^N \to \{0, 1\}$. However, this time the function is guaranteed to be a *scalar product function*, that is, there exists an $N$-bit string $s$ that allows the following representation ($\cdot$ is bitwise inner product of integers modulo $2$): diff --git a/katas/content/getting_started/media/Coding.svg b/katas/content/getting_started/media/Coding.svg index 400274bb4b..c69f1402ef 100644 --- a/katas/content/getting_started/media/Coding.svg +++ b/katas/content/getting_started/media/Coding.svg @@ -1,6 +1,6 @@ - + @@ -18,10 +18,6 @@ - - - - diff --git a/katas/content/linear_algebra/addition/index.md b/katas/content/linear_algebra/addition/index.md index a16ed730f6..bf7284d3b7 100644 --- a/katas/content/linear_algebra/addition/index.md +++ b/katas/content/linear_algebra/addition/index.md @@ -2,6 +2,6 @@ **Goal:** Return the sum of the following two matrices: -$$\begin{bmatrix} 1 & 2 \\\ 3 & 4 \end{bmatrix} + \begin{bmatrix} 5 & 6 \\\ 7 & 8 \end{bmatrix}$$ +$$\begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} + \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix}$$ > In this and the next few tasks, the matrices are represented as Q# `Double[][]` type, two-dimensional arrays of floating-point numbers. Make sure the constants you use in the return array are floating-point rather than integers. diff --git a/katas/content/linear_algebra/addition/solution.md b/katas/content/linear_algebra/addition/solution.md index 483318c561..73252354d9 100644 --- a/katas/content/linear_algebra/addition/solution.md +++ b/katas/content/linear_algebra/addition/solution.md @@ -1,6 +1,6 @@ Following the definition, the sum of two matrices is a matrix of element-wise sums of matrix elements: -$$\begin{bmatrix} 1 & 2 \\\ 3 & 4 \end{bmatrix} + \begin{bmatrix} 5 & 6 \\\ 7 & 8 \end{bmatrix} = $$ -$$= \begin{bmatrix} 1 + 5 & 2 + 6 \\\ 3 + 7 & 4 + 8 \end{bmatrix} = \begin{bmatrix} 6 & 8 \\\ 10 & 12 \end{bmatrix}$$ +$$\begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} + \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} = $$ +$$= \begin{bmatrix} 1 + 5 & 2 + 6 \\ 3 + 7 & 4 + 8 \end{bmatrix} = \begin{bmatrix} 6 & 8 \\ 10 & 12 \end{bmatrix}$$ @[solution]({"id": "linear_algebra__addition_solution", "codePath": "Solution.qs"}) diff --git a/katas/content/linear_algebra/adjoint/index.md b/katas/content/linear_algebra/adjoint/index.md index feeb135b80..f8eb6586ef 100644 --- a/katas/content/linear_algebra/adjoint/index.md +++ b/katas/content/linear_algebra/adjoint/index.md @@ -2,4 +2,4 @@ **Goal:** Return the adjoint of the following matrix: -$$\begin{bmatrix} 1 + 5i & 2 \\\ 3 - 6i & 4i \end{bmatrix}$$ +$$\begin{bmatrix} 1 + 5i & 2 \\ 3 - 6i & 4i \end{bmatrix}$$ diff --git a/katas/content/linear_algebra/conjugate/index.md b/katas/content/linear_algebra/conjugate/index.md index c9c86d0e2c..b416bea146 100644 --- a/katas/content/linear_algebra/conjugate/index.md +++ b/katas/content/linear_algebra/conjugate/index.md @@ -2,6 +2,6 @@ **Goal:** Return the conjugate of the following matrix: -$$\begin{bmatrix} 1 + 5i & 2 \\\ 3 - 6i & 4i \end{bmatrix}$$ +$$\begin{bmatrix} 1 + 5i & 2 \\ 3 - 6i & 4i \end{bmatrix}$$ > In this and the next few tasks, the matrices are represented as Q# `Complex[][]` type, two-dimensional arrays of complex numbers. If you need a refresher on how to work with this data type, check out Complex Arithmetic kata. diff --git a/katas/content/linear_algebra/index.md b/katas/content/linear_algebra/index.md index c81b10c7aa..7175090a91 100644 --- a/katas/content/linear_algebra/index.md +++ b/katas/content/linear_algebra/index.md @@ -30,16 +30,16 @@ This kata doesn't come close to covering the full breadth of the topic, but it s A **matrix** is set of numbers arranged in a rectangular grid. Here is a $2$ by $2$ matrix: $$A = -\begin{bmatrix} 1 & 2 \\\ 3 & 4 \end{bmatrix}$$ +\begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix}$$ $A_{i,j}$ refers to the element in row $i$ and column $j$ of matrix $A$ (all indices are 0-based). In the above example, $A_{0,1} = 2$. An $n \times m$ matrix will have $n$ rows and $m$ columns: $$\begin{bmatrix} - x_{0,0} & x_{0,1} & \dotsb & x_{0,m-1} \\\\ - x_{1,0} & x_{1,1} & \dotsb & x_{1,m-1} \\\\ - \vdots & \vdots & \ddots & \vdots \\\\ + x_{0,0} & x_{0,1} & \dotsb & x_{0,m-1} \\ + x_{1,0} & x_{1,1} & \dotsb & x_{1,m-1} \\ + \vdots & \vdots & \ddots & \vdots \\ x_{n-1,0} & x_{n-1,1} & \dotsb & x_{n-1,m-1} \end{bmatrix}$$ @@ -50,13 +50,13 @@ $$\begin{bmatrix} 3 \end{bmatrix} = 3$$ Quantum computing uses complex-valued matrices: the elements of a matrix can be complex numbers. This, for example, is a valid complex-valued matrix: $$\begin{bmatrix} - 1 & i \\\\ + 1 & i \\ -2i & 3 + 4i \end{bmatrix}$$ Finally, a **vector** is an $n \times 1$ matrix. Here, for example, is a $3 \times 1$ vector: -$$V = \begin{bmatrix} 1 \\\ 2i \\\ 3 + 4i \end{bmatrix}$$ +$$V = \begin{bmatrix} 1 \\ 2i \\ 3 + 4i \end{bmatrix}$$ Since vectors always have a width of $1$, vector elements are sometimes written using only one index. In the above example, $V_0 = 1$ and $V_1 = 2i$. @@ -68,21 +68,21 @@ Since vectors always have a width of $1$, vector elements are sometimes written The easiest matrix operation is **matrix addition**. Matrix addition works between two matrices of the same size, and adds each number from the first matrix to the number in the same position in the second matrix: $$\begin{bmatrix} - x_{0,0} & x_{0,1} & \dotsb & x_{0,m-1} \\\\ - x_{1,0} & x_{1,1} & \dotsb & x_{1,m-1} \\\\ - \vdots & \vdots & \ddots & \vdots \\\\ + x_{0,0} & x_{0,1} & \dotsb & x_{0,m-1} \\ + x_{1,0} & x_{1,1} & \dotsb & x_{1,m-1} \\ + \vdots & \vdots & \ddots & \vdots \\ x_{n-1,0} & x_{n-1,1} & \dotsb & x_{n-1,m-1} \end{bmatrix} +$$ $$+ \begin{bmatrix} - y_{0,0} & y_{0,1} & \dotsb & y_{0,m-1} \\\\ - y_{1,0} & y_{1,1} & \dotsb & y_{1,m-1} \\\\ - \vdots & \vdots & \ddots & \vdots \\\\ + y_{0,0} & y_{0,1} & \dotsb & y_{0,m-1} \\ + y_{1,0} & y_{1,1} & \dotsb & y_{1,m-1} \\ + \vdots & \vdots & \ddots & \vdots \\ y_{n-1,0} & y_{n-1,1} & \dotsb & y_{n-1,m-1} \end{bmatrix} =$$ $$= \begin{bmatrix} - x_{0,0} + y_{0,0} & x_{0,1} + y_{0,1} & \dotsb & x_{0,m-1} + y_{0,m-1} \\\\ - x_{1,0} + y_{1,0} & x_{1,1} + y_{1,1} & \dotsb & x_{1,m-1} + y_{1,m-1} \\\\ - \vdots & \vdots & \ddots & \vdots \\\\ + x_{0,0} + y_{0,0} & x_{0,1} + y_{0,1} & \dotsb & x_{0,m-1} + y_{0,m-1} \\ + x_{1,0} + y_{1,0} & x_{1,1} + y_{1,1} & \dotsb & x_{1,m-1} + y_{1,m-1} \\ + \vdots & \vdots & \ddots & \vdots \\ x_{n-1,0} + y_{n-1,0} & x_{n-1,1} + y_{n-1,1} & \dotsb & x_{n-1,m-1} + y_{n-1,m-1} \end{bmatrix}$$ @@ -112,15 +112,15 @@ The next matrix operation is **scalar multiplication** - multiplying the entire $$a \cdot \begin{bmatrix} - x_{0,0} & x_{0,1} & \dotsb & x_{0,m-1} \\\\ - x_{1,0} & x_{1,1} & \dotsb & x_{1,m-1} \\\\ - \vdots & \vdots & \ddots & \vdots \\\\ + x_{0,0} & x_{0,1} & \dotsb & x_{0,m-1} \\ + x_{1,0} & x_{1,1} & \dotsb & x_{1,m-1} \\ + \vdots & \vdots & \ddots & \vdots \\ x_{n-1,0} & x_{n-1,1} & \dotsb & x_{n-1,m-1} \end{bmatrix} = \begin{bmatrix} - a \cdot x_{0,0} & a \cdot x_{0,1} & \dotsb & a \cdot x_{0,m-1} \\\\ - a \cdot x_{1,0} & a \cdot x_{1,1} & \dotsb & a \cdot x_{1,m-1} \\\\ - \vdots & \vdots & \ddots & \vdots \\\\ + a \cdot x_{0,0} & a \cdot x_{0,1} & \dotsb & a \cdot x_{0,m-1} \\ + a \cdot x_{1,0} & a \cdot x_{1,1} & \dotsb & a \cdot x_{1,m-1} \\ + \vdots & \vdots & \ddots & \vdots \\ a \cdot x_{n-1,0} & a \cdot x_{n-1,1} & \dotsb & a \cdot x_{n-1,m-1} \end{bmatrix}$$ @@ -155,20 +155,20 @@ $$C_{i,j} = A_{i,0} \cdot B_{0,j} + A_{i,1} \cdot B_{1,j} + \dotsb + A_{i,m-1} \ Here is a small example: $$\begin{bmatrix} - 1 & 2 & 3 \\\\ + 1 & 2 & 3 \\ 4 & 5 & 6 \end{bmatrix} \begin{bmatrix} - 1 \\\\ - 2 \\\\ + 1 \\ + 2 \\ 3 \end{bmatrix} = \begin{bmatrix} - 1 \cdot 1 + 2 \cdot 2 + 3 \cdot 3 \\\\ + 1 \cdot 1 + 2 \cdot 2 + 3 \cdot 3 \\ 4 \cdot 1 + 5 \cdot 2 + 6 \cdot 3 \end{bmatrix} = \begin{bmatrix} - 14 \\\\ + 14 \\ 32 \end{bmatrix}$$ @@ -186,9 +186,9 @@ An **identity matrix** $I_n$ is a special $n \times n$ matrix which has $1$s on $$I_n = \begin{bmatrix} - 1 & 0 & \dotsb & 0 \\\\ - 0 & 1 & \dotsb & 0 \\\\ - \vdots & \vdots & \ddots & \vdots \\\\ + 1 & 0 & \dotsb & 0 \\ + 0 & 1 & \dotsb & 0 \\ + \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \dotsb & 1 \end{bmatrix}$$ @@ -251,9 +251,9 @@ Given an $n \times m$ matrix $A$, its transpose is the $m \times n$ matrix $A^T$ $$A = \begin{bmatrix} - x_{0,0} & x_{0,1} & \dotsb & x_{0,m-1} \\\\ - x_{1,0} & x_{1,1} & \dotsb & x_{1,m-1} \\\\ - \vdots & \vdots & \ddots & \vdots \\\\ + x_{0,0} & x_{0,1} & \dotsb & x_{0,m-1} \\ + x_{1,0} & x_{1,1} & \dotsb & x_{1,m-1} \\ + \vdots & \vdots & \ddots & \vdots \\ x_{n-1,0} & x_{n-1,1} & \dotsb & x_{n-1,m-1} \end{bmatrix}$$ @@ -261,29 +261,29 @@ then: $$A^T = \begin{bmatrix} - x_{0,0} & x_{1,0} & \dotsb & x_{n-1,0} \\\\ - x_{0,1} & x_{1,1} & \dotsb & x_{n-1,1} \\\\ - \vdots & \vdots & \ddots & \vdots \\\\ + x_{0,0} & x_{1,0} & \dotsb & x_{n-1,0} \\ + x_{0,1} & x_{1,1} & \dotsb & x_{n-1,1} \\ + \vdots & \vdots & \ddots & \vdots \\ x_{0,m-1} & x_{1,m-1} & \dotsb & x_{n-1,m-1} \end{bmatrix}$$ For example: $$\begin{bmatrix} - 1 & 2 \\\\ - 3 & 4 \\\\ + 1 & 2 \\ + 3 & 4 \\ 5 & 6 \end{bmatrix}^T = \begin{bmatrix} - 1 & 3 & 5 \\\\ + 1 & 3 & 5 \\ 2 & 4 & 6 \end{bmatrix}$$ A **symmetric** matrix is a square matrix which equals its own transpose: $A = A^T$. To put it another way, it has reflection symmetry (hence the name) across the main diagonal. For example, the following matrix is symmetric: $$\begin{bmatrix} - 1 & 2 & 3 \\\\ - 2 & 4 & 5 \\\\ + 1 & 2 & 3 \\ + 2 & 4 & 5 \\ 3 & 5 & 6 \end{bmatrix}$$ @@ -310,9 +310,9 @@ The next important single-matrix operation is the **matrix conjugate**, denoted $$A = \begin{bmatrix} - x_{0,0} & x_{0,1} & \dotsb & x_{0,m-1} \\\\ - x_{1,0} & x_{1,1} & \dotsb & x_{1,m-1} \\\\ - \vdots & \vdots & \ddots & \vdots \\\\ + x_{0,0} & x_{0,1} & \dotsb & x_{0,m-1} \\ + x_{1,0} & x_{1,1} & \dotsb & x_{1,m-1} \\ + \vdots & \vdots & \ddots & \vdots \\ x_{n-1,0} & x_{n-1,1} & \dotsb & x_{n-1,m-1} \end{bmatrix}$$ @@ -320,13 +320,13 @@ Then: $$\overline{A} = \begin{bmatrix} - \overline{x}\_{0,0} & \overline{x}\_{0,1} & \dotsb & \overline{x}\_{0,m-1} \\\\ - \overline{x}\_{1,0} & \overline{x}\_{1,1} & \dotsb & \overline{x}\_{1,m-1} \\\\ - \vdots & \vdots & \ddots & \vdots \\\\ - \overline{x}\_{n-1,0} & \overline{x}\_{n-1,1} & \dotsb & \overline{x}\_{n-1,m-1} + \overline x_{0,0} & \overline x_{0,1} & \dotsb & \overline x_{0,m-1} \\ + \overline x_{1,0} & \overline x_{1,1} & \dotsb & \overline x_{1,m-1} \\ + \vdots & \vdots & \ddots & \vdots \\ + \overline x_{n-1,0} & \overline x_{n-1,1} & \dotsb & \overline x_{n-1,m-1} \end{bmatrix}$$ -> As a reminder, a conjugate of a complex number $x = a + bi$ is $\overline{x} = a - bi$. +> As a reminder, a conjugate of a complex number $x = a + bi$ is $\overline x = a - bi$. The conjugate of a matrix product equals to the product of conjugates of the matrices: @@ -352,7 +352,7 @@ The final important single-matrix operation is a combination of the previous two A matrix is known as **Hermitian** or **self-adjoint** if it equals its own adjoint: $A = A^\dagger$. For example, the following matrix is Hermitian: $$\begin{bmatrix} - 1 & i \\\\ + 1 & i \\ -i & 2 \end{bmatrix}$$ @@ -382,11 +382,11 @@ $$(AB)^\dagger = B^\dagger A^\dagger$$ Is this matrix unitary? $$A = \begin{bmatrix} - \frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} \\\\ + \frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} \\ \frac{i}{\sqrt{2}} & \frac{-i}{\sqrt{2}} \end{bmatrix} = \frac{1}{\sqrt{2}} \begin{bmatrix} - 1 & 1 \\\\ + 1 & 1 \\ i & -i \end{bmatrix}$$ @@ -397,23 +397,23 @@ To check whether the input matrix is unitary, we will need to perform the follow 1. Calculate the adjoint of the input matrix $A^\dagger$. $$A^\dagger = \frac{1}{\sqrt{2}} \begin{bmatrix} - 1 & -i \\\\ + 1 & -i \\ 1 & i \end{bmatrix}$$ 2. Multiply it by the input matrix. $$AA^\dagger = \frac12 \begin{bmatrix} - 1 & 1 \\\\ + 1 & 1 \\ i & -i \end{bmatrix} \begin{bmatrix} - 1 & -i \\\\ + 1 & -i \\ 1 & i \end{bmatrix} = \frac12 \begin{bmatrix} - 1 \cdot 1 + 1 \cdot 1 & 1 \cdot (-i) + 1 \cdot i \\\\ + 1 \cdot 1 + 1 \cdot 1 & 1 \cdot (-i) + 1 \cdot i \\ i \cdot 1 + (-i) \cdot 1 & i \cdot (-i) + (-i) \cdot i \end{bmatrix} = \begin{bmatrix} - 1 & 0 \\\\ + 1 & 0 \\ 0 & 1 \end{bmatrix}$$ @@ -501,25 +501,25 @@ Given $n \times m$ matrix $A$ and $k \times l$ matrix $B$, their tensor product $$A \otimes B = \begin{bmatrix} - A_{0,0} \cdot B & A_{0,1} \cdot B & \dotsb & A_{0,m-1} \cdot B \\\\ - A_{1,0} \cdot B & A_{1,1} \cdot B & \dotsb & A_{1,m-1} \cdot B \\\\ - \vdots & \vdots & \ddots & \vdots \\\\ + A_{0,0} \cdot B & A_{0,1} \cdot B & \dotsb & A_{0,m-1} \cdot B \\ + A_{1,0} \cdot B & A_{1,1} \cdot B & \dotsb & A_{1,m-1} \cdot B \\ + \vdots & \vdots & \ddots & \vdots \\ A_{n-1,0} \cdot B & A_{n-1,1} \cdot B & \dotsb & A_{n-1,m-1} \cdot B \end{bmatrix} =$$ $$= \begin{bmatrix} - A_{0,0} \cdot \begin{bmatrix}B_{0,0} & \dotsb & B_{0,l-1} \\\ \vdots & \ddots & \vdots \\\ B_{k-1,0} & \dotsb & b_{k-1,l-1} \end{bmatrix} & \dotsb & - A_{0,m-1} \cdot \begin{bmatrix}B_{0,0} & \dotsb & B_{0,l-1} \\\ \vdots & \ddots & \vdots \\\ B_{k-1,0} & \dotsb & B_{k-1,l-1} \end{bmatrix} \\\\ - \vdots & \ddots & \vdots \\\\ - A_{n-1,0} \cdot \begin{bmatrix}B_{0,0} & \dotsb & B_{0,l-1} \\\ \vdots & \ddots & \vdots \\\ B_{k-1,0} & \dotsb & B_{k-1,l-1} \end{bmatrix} & \dotsb & - A_{n-1,m-1} \cdot \begin{bmatrix}B_{0,0} & \dotsb & B_{0,l-1} \\\ \vdots & \ddots & \vdots \\\ B_{k-1,0} & \dotsb & B_{k-1,l-1} \end{bmatrix} + A_{0,0} \cdot \begin{bmatrix}B_{0,0} & \dotsb & B_{0,l-1} \\ \vdots & \ddots & \vdots \\ B_{k-1,0} & \dotsb & b_{k-1,l-1} \end{bmatrix} & \dotsb & + A_{0,m-1} \cdot \begin{bmatrix}B_{0,0} & \dotsb & B_{0,l-1} \\ \vdots & \ddots & \vdots \\ B_{k-1,0} & \dotsb & B_{k-1,l-1} \end{bmatrix} \\ + \vdots & \ddots & \vdots \\ + A_{n-1,0} \cdot \begin{bmatrix}B_{0,0} & \dotsb & B_{0,l-1} \\ \vdots & \ddots & \vdots \\ B_{k-1,0} & \dotsb & B_{k-1,l-1} \end{bmatrix} & \dotsb & + A_{n-1,m-1} \cdot \begin{bmatrix}B_{0,0} & \dotsb & B_{0,l-1} \\ \vdots & \ddots & \vdots \\ B_{k-1,0} & \dotsb & B_{k-1,l-1} \end{bmatrix} \end{bmatrix} =$$ $$= \begin{bmatrix} - A_{0,0} \cdot B_{0,0} & \dotsb & A_{0,0} \cdot B_{0,l-1} & \dotsb & A_{0,m-1} \cdot B_{0,0} & \dotsb & A_{0,m-1} \cdot B_{0,l-1} \\\\ - \vdots & \ddots & \vdots & \dotsb & \vdots & \ddots & \vdots \\\\ - A_{0,0} \cdot B_{k-1,0} & \dotsb & A_{0,0} \cdot B_{k-1,l-1} & \dotsb & A_{0,m-1} \cdot B_{k-1,0} & \dotsb & A_{0,m-1} \cdot B_{k-1,l-1} \\\\ - \vdots & \vdots & \vdots & \ddots & \vdots & \vdots & \vdots \\\\ - A_{n-1,0} \cdot B_{0,0} & \dotsb & A_{n-1,0} \cdot B_{0,l-1} & \dotsb & A_{n-1,m-1} \cdot B_{0,0} & \dotsb & A_{n-1,m-1} \cdot B_{0,l-1} \\\\ - \vdots & \ddots & \vdots & \dotsb & \vdots & \ddots & \vdots \\\\ + A_{0,0} \cdot B_{0,0} & \dotsb & A_{0,0} \cdot B_{0,l-1} & \dotsb & A_{0,m-1} \cdot B_{0,0} & \dotsb & A_{0,m-1} \cdot B_{0,l-1} \\ + \vdots & \ddots & \vdots & \dotsb & \vdots & \ddots & \vdots \\ + A_{0,0} \cdot B_{k-1,0} & \dotsb & A_{0,0} \cdot B_{k-1,l-1} & \dotsb & A_{0,m-1} \cdot B_{k-1,0} & \dotsb & A_{0,m-1} \cdot B_{k-1,l-1} \\ + \vdots & \vdots & \vdots & \ddots & \vdots & \vdots & \vdots \\ + A_{n-1,0} \cdot B_{0,0} & \dotsb & A_{n-1,0} \cdot B_{0,l-1} & \dotsb & A_{n-1,m-1} \cdot B_{0,0} & \dotsb & A_{n-1,m-1} \cdot B_{0,l-1} \\ + \vdots & \ddots & \vdots & \dotsb & \vdots & \ddots & \vdots \\ A_{n-1,0} \cdot B_{k-1,0} & \dotsb & A_{n-1,0} \cdot B_{k-1,l-1} & \dotsb & A_{n-1,m-1} \cdot B_{k-1,0} & \dotsb & A_{n-1,m-1} \cdot B_{k-1,l-1} \end{bmatrix}$$ diff --git a/katas/content/linear_algebra/inner_product/index.md b/katas/content/linear_algebra/inner_product/index.md index 3b23fc47a4..e545ce1a41 100644 --- a/katas/content/linear_algebra/inner_product/index.md +++ b/katas/content/linear_algebra/inner_product/index.md @@ -2,4 +2,4 @@ **Goal:** Return the inner product $\langle V , W \rangle$ of the following vectors: -$$V = \begin{bmatrix} -6 \\\ 9i \end{bmatrix}, W = \begin{bmatrix} 3 \\\ -8 \end{bmatrix}$$ +$$V = \begin{bmatrix} -6 \\ 9i \end{bmatrix}, W = \begin{bmatrix} 3 \\ -8 \end{bmatrix}$$ diff --git a/katas/content/linear_algebra/inner_product/solution.md b/katas/content/linear_algebra/inner_product/solution.md index 391dc8e78c..fe778f94b2 100644 --- a/katas/content/linear_algebra/inner_product/solution.md +++ b/katas/content/linear_algebra/inner_product/solution.md @@ -1,15 +1,15 @@ $$\langle V, W \rangle = V^\dagger W = \begin{bmatrix} - -6 \\\\ + -6 \\ 9i \end{bmatrix}^\dagger \begin{bmatrix} - 3 \\\\ + 3 \\ -8 \end{bmatrix} = \begin{bmatrix} -6 & -9i \end{bmatrix} \begin{bmatrix} - 3 \\\\ + 3 \\ -8 \end{bmatrix} = (-6) \cdot 3 + (-9i) \cdot (-8) = -18 + 72i$$ diff --git a/katas/content/linear_algebra/inverse/index.md b/katas/content/linear_algebra/inverse/index.md index 7c4b5ebbf5..4a5b42b158 100644 --- a/katas/content/linear_algebra/inverse/index.md +++ b/katas/content/linear_algebra/inverse/index.md @@ -2,7 +2,7 @@ **Goal:** Return the inverse of the following matrix: -$$\begin{bmatrix} 1 & 2 \\\ 3 & 4 \end{bmatrix}$$ +$$\begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix}$$
Need a hint? diff --git a/katas/content/linear_algebra/inverse/solution.md b/katas/content/linear_algebra/inverse/solution.md index e5783cc605..a5ed5fcc1e 100644 --- a/katas/content/linear_algebra/inverse/solution.md +++ b/katas/content/linear_algebra/inverse/solution.md @@ -1,12 +1,12 @@ We will follow the algorithm described in the [Wikipedia article](https://en.wikipedia.org/wiki/Invertible_matrix#Inversion_of_2_%C3%97_2_matrices) for $2 \times 2$ matrices: -$$ A = \begin{bmatrix} a & b \\\ c & d \end{bmatrix} $$ +$$ A = \begin{bmatrix} a & b \\ c & d \end{bmatrix} $$ Then the determinant of the matrix is defined as $$ |A| = a \cdot d - b \cdot c = 1 \cdot 4 - 2 \cdot 3 = -2$$ And the inverse of the matrix is -$$A^{-1} = \frac{1}{|A|} \cdot \begin{bmatrix} d & -b \\\ -c & a \end{bmatrix} = -\frac12 \begin{bmatrix} 4 & -2 \\\ -3 & 1 \end{bmatrix} = \begin{bmatrix} -2 & 1 \\\ \frac32 & -\frac12 \end{bmatrix}$$ +$$A^{-1} = \frac{1}{|A|} \cdot \begin{bmatrix} d & -b \\ -c & a \end{bmatrix} = -\frac12 \begin{bmatrix} 4 & -2 \\ -3 & 1 \end{bmatrix} = \begin{bmatrix} -2 & 1 \\ \frac32 & -\frac12 \end{bmatrix}$$ @[solution]({"id": "linear_algebra__inverse_solution", "codePath": "Solution.qs"}) diff --git a/katas/content/linear_algebra/multiplication/index.md b/katas/content/linear_algebra/multiplication/index.md index f93c9e1542..5aaa35d115 100644 --- a/katas/content/linear_algebra/multiplication/index.md +++ b/katas/content/linear_algebra/multiplication/index.md @@ -2,4 +2,4 @@ **Goal:** Return the product of the following two matrices: -$$\begin{bmatrix} 1 & 2 \\\ 3 & 4 \end{bmatrix} \cdot \begin{bmatrix} 5 & 6 \\\ 7 & 8 \end{bmatrix}$$ +$$\begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} \cdot \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix}$$ diff --git a/katas/content/linear_algebra/multiplication/solution.md b/katas/content/linear_algebra/multiplication/solution.md index e26292851f..16e210ffe3 100644 --- a/katas/content/linear_algebra/multiplication/solution.md +++ b/katas/content/linear_algebra/multiplication/solution.md @@ -1,6 +1,6 @@ Following the definition, we can calculate the product of these two matrices as follows: -$$\begin{bmatrix} 1 & 2 \\\ 3 & 4 \end{bmatrix} \cdot \begin{bmatrix} 5 & 6 \\\ 7 & 8 \end{bmatrix} = $$ -$$= \begin{bmatrix} 1 \cdot 5 + 2 \cdot 7 & 1 \cdot 6 + 2 \cdot 8 \\\ 3 \cdot 5 + 4 \cdot 7 & 3 \cdot 6 + 4 \cdot 8 \end{bmatrix} = \begin{bmatrix} 19 & 22 \\\ 43 & 50 \end{bmatrix}$$ +$$\begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} \cdot \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} = $$ +$$= \begin{bmatrix} 1 \cdot 5 + 2 \cdot 7 & 1 \cdot 6 + 2 \cdot 8 \\ 3 \cdot 5 + 4 \cdot 7 & 3 \cdot 6 + 4 \cdot 8 \end{bmatrix} = \begin{bmatrix} 19 & 22 \\ 43 & 50 \end{bmatrix}$$ @[solution]({"id": "linear_algebra__multiplication_solution", "codePath": "Solution.qs"}) diff --git a/katas/content/linear_algebra/normalized_vector/index.md b/katas/content/linear_algebra/normalized_vector/index.md index 1ef5e746e2..287072d878 100644 --- a/katas/content/linear_algebra/normalized_vector/index.md +++ b/katas/content/linear_algebra/normalized_vector/index.md @@ -2,6 +2,6 @@ **Goal:** Return the normalized vector $V$, defined as $\frac{V}{||V||}$, where -$$V = \begin{bmatrix} -6 \\\ 8i \end{bmatrix}$$ +$$V = \begin{bmatrix} -6 \\ 8i \end{bmatrix}$$ > Vectors are $n \times 1$ matrices, so in this exercise the result is represented as a two-dimensional array of complex numbers, with two rows each containing exactly one element. Vectors are commonly represented as one-dimensional arrays. diff --git a/katas/content/linear_algebra/normalized_vector/solution.md b/katas/content/linear_algebra/normalized_vector/solution.md index ec6eeb1848..7fc0064a9d 100644 --- a/katas/content/linear_algebra/normalized_vector/solution.md +++ b/katas/content/linear_algebra/normalized_vector/solution.md @@ -4,6 +4,6 @@ $$||V|| = \sqrt{\langle V , V \rangle} = \sqrt{-6 \cdot (-6) + (-8i) \cdot 8i} = Then the normalized vector can be obtained by dividing each element of the original vector by its norm: -$$\frac{V}{||V||} = \begin{bmatrix} -0.6 \\\ 0.8i \end{bmatrix}$$ +$$\frac{V}{||V||} = \begin{bmatrix} -0.6 \\ 0.8i \end{bmatrix}$$ @[solution]({"id": "linear_algebra__normalized_vector_solution", "codePath": "Solution.qs"}) diff --git a/katas/content/linear_algebra/outer_product/index.md b/katas/content/linear_algebra/outer_product/index.md index 3f21a6f41b..fdd5ae25fd 100644 --- a/katas/content/linear_algebra/outer_product/index.md +++ b/katas/content/linear_algebra/outer_product/index.md @@ -2,4 +2,4 @@ **Goal:** Return the outer product $VW^\dagger$ of the following vectors: -$$V = \begin{bmatrix} -3i \\\ 9 \end{bmatrix}, W = \begin{bmatrix} 9i \\\ 2 \end{bmatrix}$$ +$$V = \begin{bmatrix} -3i \\ 9 \end{bmatrix}, W = \begin{bmatrix} 9i \\ 2 \end{bmatrix}$$ diff --git a/katas/content/linear_algebra/outer_product/solution.md b/katas/content/linear_algebra/outer_product/solution.md index c63d66e74b..f295d6318c 100644 --- a/katas/content/linear_algebra/outer_product/solution.md +++ b/katas/content/linear_algebra/outer_product/solution.md @@ -1,13 +1,13 @@ -$$\begin{bmatrix} -3i \\\ 9 \end{bmatrix} -\begin{bmatrix} 9i \\\ 2 \end{bmatrix}^\dagger = -\begin{bmatrix} -3i \\\ 9 \end{bmatrix} +$$\begin{bmatrix} -3i \\ 9 \end{bmatrix} +\begin{bmatrix} 9i \\ 2 \end{bmatrix}^\dagger = +\begin{bmatrix} -3i \\ 9 \end{bmatrix} \begin{bmatrix} -9i & 2 \end{bmatrix} = \begin{bmatrix} - (-3i) \cdot (-9i) & (-3i) \cdot 2 \\\\ + (-3i) \cdot (-9i) & (-3i) \cdot 2 \\ 9 \cdot (-9i) & 9 \cdot 2 \end{bmatrix} = \begin{bmatrix} - -27 & -6i \\\\ + -27 & -6i \\ -81i & 18 \end{bmatrix}$$ diff --git a/katas/content/linear_algebra/scalar_multiplication/index.md b/katas/content/linear_algebra/scalar_multiplication/index.md index c41a719cc4..4f8f0029ba 100644 --- a/katas/content/linear_algebra/scalar_multiplication/index.md +++ b/katas/content/linear_algebra/scalar_multiplication/index.md @@ -2,4 +2,4 @@ **Goal:** Return the result of multiplying the following matrix by the scalar: -$$0.5 \cdot \begin{bmatrix} 1 & 2 \\\ 3 & 4 \end{bmatrix}$$ +$$0.5 \cdot \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix}$$ diff --git a/katas/content/linear_algebra/scalar_multiplication/solution.md b/katas/content/linear_algebra/scalar_multiplication/solution.md index be279c2500..09fb6ff4b6 100644 --- a/katas/content/linear_algebra/scalar_multiplication/solution.md +++ b/katas/content/linear_algebra/scalar_multiplication/solution.md @@ -1,6 +1,6 @@ We can again follow the definition given: to calculate the product of a number and a matrix, multiply each matrix element by that number. -$$0.5 \cdot \begin{bmatrix} 1 & 2 \\\ 3 & 4 \end{bmatrix} = -= \begin{bmatrix} 0.5 \cdot 1 & 0.5 \cdot 2 \\\ 0.5 \cdot 3 & 0.5 \cdot 4\end{bmatrix} = \begin{bmatrix} 0.5 & 1 \\\ 1.5 & 2 \end{bmatrix}$$ +$$0.5 \cdot \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} = += \begin{bmatrix} 0.5 \cdot 1 & 0.5 \cdot 2 \\ 0.5 \cdot 3 & 0.5 \cdot 4\end{bmatrix} = \begin{bmatrix} 0.5 & 1 \\ 1.5 & 2 \end{bmatrix}$$ @[solution]({"id": "linear_algebra__scalar_multiplication_solution", "codePath": "Solution.qs"}) diff --git a/katas/content/linear_algebra/tensor_product/index.md b/katas/content/linear_algebra/tensor_product/index.md index c31a1c82a5..9f69b7853b 100644 --- a/katas/content/linear_algebra/tensor_product/index.md +++ b/katas/content/linear_algebra/tensor_product/index.md @@ -2,6 +2,6 @@ **Goal:** Return the tensor product of the following two matrices: -$$\begin{bmatrix} 1 & 2 \\\ 3 & 4 \end{bmatrix} \otimes \begin{bmatrix} 5 & 6 \\\ 7 & 8 \end{bmatrix}$$ +$$\begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} \otimes \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix}$$ > In this task we're using real-valued matrices represented as Q# `Double[][]` type again for simplicity. diff --git a/katas/content/linear_algebra/tensor_product/solution.md b/katas/content/linear_algebra/tensor_product/solution.md index 5309f239f4..ab561b79d6 100644 --- a/katas/content/linear_algebra/tensor_product/solution.md +++ b/katas/content/linear_algebra/tensor_product/solution.md @@ -1,18 +1,18 @@ -$$\begin{bmatrix} 1 & 2 \\\ 3 & 4 \end{bmatrix} \otimes \begin{bmatrix} 5 & 6 \\\ 7 & 8 \end{bmatrix} = +$$\begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} \otimes \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} = \begin{bmatrix} - 1 \cdot \begin{bmatrix} 5 & 6 \\\ 7 & 8 \end{bmatrix} & 2 \cdot \begin{bmatrix} 5 & 6 \\\ 7 & 8 \end{bmatrix} \\\\ - 3 \cdot \begin{bmatrix} 5 & 6 \\\ 7 & 8 \end{bmatrix} & 4 \cdot \begin{bmatrix} 5 & 6 \\\ 7 & 8 \end{bmatrix} + 1 \cdot \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} & 2 \cdot \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} \\ + 3 \cdot \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} & 4 \cdot \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} \end{bmatrix} =$$ $$=\begin{bmatrix} - 1 \cdot 5 & 1 \cdot 6 & 2 \cdot 5 & 2 \cdot 6 \\\\ - 1 \cdot 7 & 1 \cdot 8 & 2 \cdot 7 & 2 \cdot 8 \\\\ - 3 \cdot 5 & 3 \cdot 6 & 4 \cdot 5 & 4 \cdot 6 \\\\ + 1 \cdot 5 & 1 \cdot 6 & 2 \cdot 5 & 2 \cdot 6 \\ + 1 \cdot 7 & 1 \cdot 8 & 2 \cdot 7 & 2 \cdot 8 \\ + 3 \cdot 5 & 3 \cdot 6 & 4 \cdot 5 & 4 \cdot 6 \\ 3 \cdot 7 & 3 \cdot 8 & 4 \cdot 7 & 4 \cdot 8 \end{bmatrix} = \begin{bmatrix} - 5 & 6 & 10 & 12 \\\\ - 7 & 8 & 14 & 16 \\\\ - 15 & 18 & 20 & 24 \\\\ + 5 & 6 & 10 & 12 \\ + 7 & 8 & 14 & 16 \\ + 15 & 18 & 20 & 24 \\ 21 & 24 & 28 & 32 \end{bmatrix}$$ diff --git a/katas/content/linear_algebra/transpose/index.md b/katas/content/linear_algebra/transpose/index.md index 3ddf432135..ed29df6eef 100644 --- a/katas/content/linear_algebra/transpose/index.md +++ b/katas/content/linear_algebra/transpose/index.md @@ -2,4 +2,4 @@ **Goal:** Return the transpose of the following matrix: -$$\begin{bmatrix} 1 & 2 \\\ 3 & 4 \end{bmatrix}$$ +$$\begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix}$$ diff --git a/katas/content/multi_qubit_gates/anti_controlled_gate/solution.md b/katas/content/multi_qubit_gates/anti_controlled_gate/solution.md index e71bb1565c..e42d241280 100644 --- a/katas/content/multi_qubit_gates/anti_controlled_gate/solution.md +++ b/katas/content/multi_qubit_gates/anti_controlled_gate/solution.md @@ -2,21 +2,21 @@ In vector form the transformation we need is: $$ -\begin{bmatrix}\color{blue}\alpha\\\ \color{blue}\beta\\\ \gamma\\\ \delta\\\ \end{bmatrix} +\begin{bmatrix}\color{blue}\alpha\\ \color{blue}\beta\\ \gamma\\ \delta \end{bmatrix} \rightarrow -\begin{bmatrix} \color{red}\beta\\\ \color{red}\alpha\\\ \gamma\\\ \delta\\\ \end{bmatrix} +\begin{bmatrix} \color{red}\beta\\ \color{red}\alpha\\ \gamma\\ \delta \end{bmatrix} $$ This can be represented by a matrix: $$ -U = \begin{bmatrix}0 & 1 & 0 & 0\\\ 1 & 0 & 0 & 0\\\ 0 & 0 & 1 & 0\\\ 0 & 0 & 0 & 1\\\ \end{bmatrix} +U = \begin{bmatrix}0 & 1 & 0 & 0\\ 1 & 0 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1 \end{bmatrix} $$ We remember a two-qubit gate with a similar matrix representation - the $CNOT$ gate: $$ CNOT = - \begin{bmatrix}1 & 0 & 0 & 0\\\ 0 & 1 & 0 & 0\\\ 0 & 0 & 0 & 1\\\ 0 & 0 & 1 & 0\\\ \end{bmatrix} + \begin{bmatrix}1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1\\ 0 & 0 & 1 & 0 \end{bmatrix} $$ We need a way to transform the $CNOT$ gate into the unitary transformation represented by $U$. @@ -27,13 +27,13 @@ We validate that composition of $I \otimes X$ and the $CNOT$ gate produces the r $$ (I \otimes X)\cdot CNOT = \left( -\begin{bmatrix}1 & 0 \\\ 0 & 1 \\\ \end{bmatrix}\otimes -\begin{bmatrix} 0 & 1 \\\ 1 & 0 \\\ \end{bmatrix} +\begin{bmatrix}1 & 0 \\ 0 & 1 \end{bmatrix}\otimes +\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} \right) \cdot -\begin{bmatrix}1 & 0 & 0 & 0\\\ 0 & 1 & 0 & 0\\\ 0 & 0 & 0 & 1\\\ 0 & 0 & 1 & 0\\\ \end{bmatrix}= -\begin{bmatrix}0 & 1 & 0 & 0\\\ 1 & 0 & 0 & 0\\\ 0 & 0 & 0 & 1\\\ 0 & 0 & 1 & 0\\\ \end{bmatrix} -\begin{bmatrix} 1 & 0 & 0 & 0\\\ 0 & 1 & 0 & 0\\\ 0 & 0 & 0 & 1\\\ 0 & 0 & 1 & 0\\\ \end{bmatrix}= -\begin{bmatrix} 0 & 1 & 0 & 0\\\ 1 & 0 & 0 & 0\\\ 0 & 0 & 1 & 0\\\ 0 & 0 & 0 & 1\\\ \end{bmatrix}= +\begin{bmatrix}1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1\\ 0 & 0 & 1 & 0 \end{bmatrix}= +\begin{bmatrix}0 & 1 & 0 & 0\\ 1 & 0 & 0 & 0\\ 0 & 0 & 0 & 1\\ 0 & 0 & 1 & 0 \end{bmatrix} +\begin{bmatrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1\\ 0 & 0 & 1 & 0 \end{bmatrix}= +\begin{bmatrix} 0 & 1 & 0 & 0\\ 1 & 0 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}= U $$ diff --git a/katas/content/multi_qubit_gates/arbitrary_controls/solution.md b/katas/content/multi_qubit_gates/arbitrary_controls/solution.md index 3b90a07579..74fe1c53f6 100644 --- a/katas/content/multi_qubit_gates/arbitrary_controls/solution.md +++ b/katas/content/multi_qubit_gates/arbitrary_controls/solution.md @@ -3,7 +3,7 @@ We are asked to perform an $X$ gate on the `target` qubit controlled by the stat If the `controlBits` mask consists of all `true` values, we can use a familiar `Controlled X` gate. What can we do if the mask has some `false` values in it? Turns out we can transform the state of the control qubits depending on the corresponding elements of `controlBits`: if the element is `false`, we apply an $X$ gate to the corresponding qubit in the `controls` array. After this, `Controlled X` gate will apply an $X$ gate in the exact case that we want. -Finally, we'll need to remember to undo (\"uncompute\") the first step, otherwise our controlled gate will affect the state of the control qubits as well as the state of the target. +Finally, we'll need to remember to undo ("uncompute") the first step, otherwise our controlled gate will affect the state of the control qubits as well as the state of the target. As you can see in the first cell below, this can take quite some coding. diff --git a/katas/content/multi_qubit_gates/compound_gate/index.md b/katas/content/multi_qubit_gates/compound_gate/index.md index 20d834aaad..45a38009e8 100644 --- a/katas/content/multi_qubit_gates/compound_gate/index.md +++ b/katas/content/multi_qubit_gates/compound_gate/index.md @@ -1,17 +1,17 @@ -**Inputs:** $3$ qubits in an arbitrary superposition state $|\\psi\\rangle$, stored in an array of length $3$. +**Inputs:** $3$ qubits in an arbitrary superposition state $|\psi\rangle$, stored in an array of length $3$. **Goal:** Apply the following matrix to the system. This matrix can be represented as applying $3$ single-qubit gates. $$ Q = \begin{bmatrix} -0 & -i & 0 & 0 & 0 & 0 & 0 & 0 \\\ -i & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\ -0 & 0 & 0 & -i & 0 & 0 & 0 & 0 \\\ -0 & 0 & i & 0 & 0 & 0 & 0 & 0 \\\ -0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\\ -0 & 0 & 0 & 0 & -1 & 0 & 0 & 0 \\\ -0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\\ +0 & -i & 0 & 0 & 0 & 0 & 0 & 0 \\ +i & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ +0 & 0 & 0 & -i & 0 & 0 & 0 & 0 \\ +0 & 0 & i & 0 & 0 & 0 & 0 & 0 \\ +0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ +0 & 0 & 0 & 0 & -1 & 0 & 0 & 0 \\ +0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ 0 & 0 & 0 & 0 & 0 & 0 & -1 & 0 \end{bmatrix} $$ @@ -21,4 +21,4 @@ $$
Need a hint?

Start by noticing that the top right and bottom left quadrants of the matrix are filled with $0$s, and the bottom right quadrant equals to the top left one, multiplied by $i$. Does this look like a tensor product of a 1-qubit and 2-qubit matrices? Which ones?

-
\ No newline at end of file + diff --git a/katas/content/multi_qubit_gates/compound_gate/solution.md b/katas/content/multi_qubit_gates/compound_gate/solution.md index bb4b4a8917..8caf7eba23 100644 --- a/katas/content/multi_qubit_gates/compound_gate/solution.md +++ b/katas/content/multi_qubit_gates/compound_gate/solution.md @@ -2,8 +2,8 @@ One way to represent a multi-qubit transformation is to use the tensor product o $$ Z \otimes X = -\begin{bmatrix} 1 & 0 \\\ 0 & -1 \end{bmatrix} \otimes \begin{bmatrix} 0 & 1 \\\ 1 & 0 \end{bmatrix} = -\begin{bmatrix} 0 & 1 & 0 & 0 \\\ 1 & 0 & 0 & 0 \\\ 0 & 0 & 0 & -1 \\\ 0 & 0 & -1 & 0 \end{bmatrix} +\begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix} \otimes \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} = +\begin{bmatrix} 0 & 1 & 0 & 0 \\ 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & -1 \\ 0 & 0 & -1 & 0 \end{bmatrix} $$ With this in mind, let's see how to reverse engineer the target matrix above to find the 3 gates which, acting on individual qubits, together form the target transformation. @@ -12,21 +12,21 @@ Start by noticing that the top right and bottom left quadrants of the target mat $$ Q = -\begin{bmatrix} 1 & 0 \\\ 0 & i \end{bmatrix} \otimes +\begin{bmatrix} 1 & 0 \\ 0 & i \end{bmatrix} \otimes \begin{bmatrix} - 0 & -i & 0 & 0 \\\ - i & 0 & 0 & 0 \\\ - 0 & 0 & 0 & -i \\\ + 0 & -i & 0 & 0 \\ + i & 0 & 0 & 0 \\ + 0 & 0 & 0 & -i \\ 0 & 0 & i & 0 \end{bmatrix} = \begin{bmatrix} - 0 & -i & 0 & 0 & 0 & 0 & 0 & 0 \\\ - i & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\ - 0 & 0 & 0 & -i & 0 & 0 & 0 & 0 \\\ - 0 & 0 & i & 0 & 0 & 0 & 0 & 0 \\\ - 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\\ - 0 & 0 & 0 & 0 & -1 & 0 & 0 & 0 \\\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\\ + 0 & -i & 0 & 0 & 0 & 0 & 0 & 0 \\ + i & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & -i & 0 & 0 & 0 & 0 \\ + 0 & 0 & i & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 0 & -1 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ 0 & 0 & 0 & 0 & 0 & 0 & -1 & 0 \end{bmatrix} $$ @@ -35,8 +35,8 @@ Now the $4 \times 4$ matrix has all $0$s in the top right and bottom left quadra $$ Q = -\begin{bmatrix} 1 & 0 \\\ 0 & i \end{bmatrix} \otimes \begin{bmatrix} 1 & 0 \\\ 0 & 1 \end{bmatrix} \otimes -\begin{bmatrix} 0 & -i \\\ i & 0 \end{bmatrix} = S \otimes I \otimes Y +\begin{bmatrix} 1 & 0 \\ 0 & i \end{bmatrix} \otimes \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} \otimes +\begin{bmatrix} 0 & -i \\ i & 0 \end{bmatrix} = S \otimes I \otimes Y $$ @[solution]({ diff --git a/katas/content/multi_qubit_gates/controlled_rotation/solution.md b/katas/content/multi_qubit_gates/controlled_rotation/solution.md index 9b7d161771..e2cfa7104d 100644 --- a/katas/content/multi_qubit_gates/controlled_rotation/solution.md +++ b/katas/content/multi_qubit_gates/controlled_rotation/solution.md @@ -3,7 +3,7 @@ In Q# the `Rx` intrinsic gate takes the angle $\theta$ and the target qubit as i A matrix representation of this operation would be: $$ -\begin{bmatrix} 1 & 0 & 0 & 0 \\\ 0 & 1 & 0 & 0 \\\ 0 & 0 & \cos\frac{\theta}{2} & -i\sin\frac{\theta}{2} \\\ 0 & 0 & -i\sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{bmatrix} +\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & \cos\frac{\theta}{2} & -i\sin\frac{\theta}{2} \\ 0 & 0 & -i\sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{bmatrix} $$ The parameters of the new gate are changed a bit: diff --git a/katas/content/multi_qubit_gates/fredkin_gate/solution.md b/katas/content/multi_qubit_gates/fredkin_gate/solution.md index 2d27ac1cf3..427c310b89 100644 --- a/katas/content/multi_qubit_gates/fredkin_gate/solution.md +++ b/katas/content/multi_qubit_gates/fredkin_gate/solution.md @@ -1,17 +1,41 @@ -This is essentially bookwork, because there is only one gate that performs this state change (and the task title already gave it away!) +This is essentially bookwork, because there is only one gate that performs this state change (and the task title already gave it away!) The Fredkin gate is also known as the controlled $SWAP$ gate: $$ -\begin{bmatrix} 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\\ 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\\ 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0\\\ 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0\\\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\\\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0\\\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0\\\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1\\\ \end{bmatrix} +\begin{bmatrix} +1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ +0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ +0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ +0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ +0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ +0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ +0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ +0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 +\end{bmatrix} $$ and our initial state is: $$ -\begin{bmatrix} \alpha\\\ \beta\\\ \gamma\\\ \delta\\\ \epsilon\\\ \zeta\\\ \eta\\\ \theta\\\ \end{bmatrix} +\begin{bmatrix} +\alpha \\ \beta \\ \gamma \\ \delta \\ \epsilon \\ \zeta \\ \eta \\ \theta +\end{bmatrix} $$ So we have: $$ -\begin{bmatrix} 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\\ 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\\ 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0\\\ 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0\\\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\\\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0\\\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0\\\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1\\\ \end{bmatrix} -\begin{bmatrix} \alpha\\\ \beta\\\ \gamma\\\ \delta\\\ \epsilon\\\ \color{blue}\zeta\\\ \color{blue}\eta\\\ \theta\\\ \end{bmatrix} = -\begin{bmatrix} \alpha\\\ \beta\\\ \gamma\\\ \delta\\\ \epsilon\\\ \color{red}\eta\\\ \color{red}\zeta\\\ \theta\\\ \end{bmatrix} = +\begin{bmatrix} +1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ +0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ +0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ +0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ +0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ +0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ +0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ +0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 +\end{bmatrix} +\begin{bmatrix} +\alpha \\ \beta \\ \gamma \\ \delta \\ \epsilon \\ \color{blue}\zeta \\ \color{blue}\eta \\ \theta +\end{bmatrix} = +\begin{bmatrix} +\alpha \\ \beta \\ \gamma \\ \delta \\ \epsilon \\ \color{red}\eta \\ \color{red}\zeta \\ \theta +\end{bmatrix} = \alpha |000\rangle + \beta |001\rangle + \gamma |010\rangle + \delta |011\rangle + \epsilon |100\rangle + {\color{red}\eta}|101\rangle + {\color{red}\zeta}|110\rangle + \theta|111\rangle $$ diff --git a/katas/content/multi_qubit_gates/index.md b/katas/content/multi_qubit_gates/index.md index 9a63f0eae0..762dff23cc 100644 --- a/katas/content/multi_qubit_gates/index.md +++ b/katas/content/multi_qubit_gates/index.md @@ -27,7 +27,7 @@ This kata continues the introduction to quantum gates, focusing on applying quan As a reminder, single-qubit gates are represented by $2\times2$ unitary matrices. The effect of a gate applied to a qubit can be calculated by multiplying the corresponding matrix by the state vector of the qubit to get the resulting state vector. -Multi-qubit gates are represented by $2^N\\times2^N$ matrices, where $N$ is the number of qubits the gate operates on. To apply this gate, you multiply the matrix by the state vector of the $N$-qubit quantum system. +Multi-qubit gates are represented by $2^N\times2^N$ matrices, where $N$ is the number of qubits the gate operates on. To apply this gate, you multiply the matrix by the state vector of the $N$-qubit quantum system. ## Applying Gates to a Part of the System @@ -39,11 +39,11 @@ If you want to apply an $X$ gate to the first qubit of the system and do nothing $$ X \otimes I = -\begin{bmatrix} 0 & 1 \\\ 1 & 0 \end{bmatrix} \otimes \begin{bmatrix} 1 & 0 \\\ 0 & 1 \end{bmatrix} = +\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} \otimes \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} = \begin{bmatrix} - 0 & 0 & 1 & 0 \\\ - 0 & 0 & 0 & 1 \\\ - 1 & 0 & 0 & 0 \\\ + 0 & 0 & 1 & 0 \\ + 0 & 0 & 0 & 1 \\ + 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \end{bmatrix} $$ @@ -53,11 +53,11 @@ For example, applying the $X$ gate to the first qubit and the $H$ gate to the se $$ X \otimes H = -\begin{bmatrix} 0 & 1 \\\ 1 & 0 \end{bmatrix} \otimes \frac{1}{\sqrt{2}}\begin{bmatrix} 1 & 1 \\\ 1 & -1 \end{bmatrix} = +\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} \otimes \frac{1}{\sqrt{2}}\begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix} = \frac{1}{\sqrt{2}}\begin{bmatrix} - 0 & 0 & 1 & 1 \\\ - 0 & 0 & 1 & -1 \\\ - 1 & 1 & 0 & 0 \\\ + 0 & 0 & 1 & 1 \\ + 0 & 0 & 1 & -1 \\ + 1 & 1 & 0 & 0 \\ 1 & -1 & 0 & 0 \end{bmatrix} $$ @@ -86,7 +86,7 @@ It can be less straightforward when a multi-qubit gate is applied to a subset of Our first proper multi-qubit gate is the $CNOT$ ("controlled NOT") gate. The $CNOT$ gate is a two-qubit gate, with one qubit referred to as the **control** qubit, and the other qubit as the **target** qubit (usually the first qubit is the control, and the second qubit is the target). -$CNOT$ acts as a conditional gate of sorts: if the control qubit is in state $|1\\rangle$, it applies the $X$ gate to the target qubit, otherwise it does nothing. +$CNOT$ acts as a conditional gate of sorts: if the control qubit is in state $|1\rangle$, it applies the $X$ gate to the target qubit, otherwise it does nothing. > If the system is in a superposition of several basis states, the effects of the gate will be a linear combination of the effects of it acting separately on each of the basis states. > This will be the case for all quantum gates you'll encounter later that are specified in terms of basis states: since all unitary gates are linear, it is sufficient to define their effect on the basis states, and use linearity to figure out their effect on any state. @@ -100,7 +100,7 @@ $CNOT$ acts as a conditional gate of sorts: if the control qubit is in state $|1 $CNOT$ - $\begin{bmatrix} 1 & 0 & 0 & 0 \\\ 0 & 1 & 0 & 0 \\\ 0 & 0 & 0 & 1 \\\ 0 & 0 & 1 & 0 \end{bmatrix}$ + $\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \end{bmatrix}$ $CNOT|\psi\rangle = \alpha|00\rangle + \beta|01\rangle + \delta|10\rangle + \gamma|11\rangle$ $$CNOT|00\rangle = |00\rangle$$ @@ -214,18 +214,18 @@ Let's consider ket-bra representation of the $CNOT$ gate: $$CNOT =$$ $$= |00\rangle\langle00| + |01\rangle\langle01| + |10\rangle\langle11| + |11\rangle\langle10| =$$ $$= -\begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 0 \end{bmatrix}\begin{bmatrix} 1 & 0 & 0 & 0 \end{bmatrix} + -\begin{bmatrix} 0 \\\ 1 \\\ 0 \\\ 0 \end{bmatrix}\begin{bmatrix} 0 & 1 & 0 & 0 \end{bmatrix} + -\begin{bmatrix} 0 \\\ 0 \\\ 1 \\\ 0 \end{bmatrix}\begin{bmatrix} 0 & 0 & 0 & 1 \end{bmatrix} + -\begin{bmatrix} 0 \\\ 0 \\\ 0 \\\ 1 \end{bmatrix}\begin{bmatrix} 0 & 0 & 1 & 0 \end{bmatrix} = +\begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix}\begin{bmatrix} 1 & 0 & 0 & 0 \end{bmatrix} + +\begin{bmatrix} 0 \\ 1 \\ 0 \\ 0 \end{bmatrix}\begin{bmatrix} 0 & 1 & 0 & 0 \end{bmatrix} + +\begin{bmatrix} 0 \\ 0 \\ 1 \\ 0 \end{bmatrix}\begin{bmatrix} 0 & 0 & 0 & 1 \end{bmatrix} + +\begin{bmatrix} 0 \\ 0 \\ 0 \\ 1 \end{bmatrix}\begin{bmatrix} 0 & 0 & 1 & 0 \end{bmatrix} = $$ $$= -\begin{bmatrix} 1 & 0 & 0 & 0 \\\ 0 & 0 & 0 & 0 \\\ 0 & 0 & 0 & 0 \\\ 0 & 0 & 0 & 0 \\\ \end{bmatrix} + -\begin{bmatrix} 0 & 0 & 0 & 0 \\\ 0 & 1 & 0 & 0 \\\ 0 & 0 & 0 & 0 \\\ 0 & 0 & 0 & 0 \\\ \end{bmatrix} + -\begin{bmatrix} 0 & 0 & 0 & 0 \\\ 0 & 0 & 0 & 0 \\\ 0 & 0 & 0 & 1 \\\ 0 & 0 & 0 & 0 \\\ \end{bmatrix} + -\begin{bmatrix} 0 & 0 & 0 & 0 \\\ 0 & 0 & 0 & 0 \\\ 0 & 0 & 0 & 0 \\\ 0 & 0 & 1 & 0 \\\ \end{bmatrix} = +\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \end{bmatrix} + +\begin{bmatrix} 0 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \end{bmatrix} + +\begin{bmatrix} 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 0 & 0 \end{bmatrix} + +\begin{bmatrix} 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix} = $$ -$$=\begin{bmatrix} 1 & 0 & 0 & 0 \\\ 0 & 1 & 0 & 0 \\\ 0 & 0 & 0 & 1 \\\ 0 & 0 & 1 & 0 \\\ \end{bmatrix}$$ +$$=\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \\ \end{bmatrix}$$ This representation can be used to carry out calculations in Dirac notation without ever switching back to matrix representation: @@ -238,13 +238,13 @@ $$=|00\rangle(0) + |01\rangle(0) + |10\rangle(0) + |11\rangle(1) = |11\rangle$$ > Notice how a lot of the inner product terms turn out to equal 0, and our expression is easily simplified. We have expressed the $CNOT$ gate in terms of outer product of computational basis states, which are orthonormal, and apply it to another computational basis state, so the individual inner products are going to always be 0 or 1. -In general case, a $4\\times4$ matrix that describes a 2-qubit gate +In general case, a $4 \times 4$ matrix that describes a 2-qubit gate $$A = \begin{bmatrix} - a_{00} & a_{01} & a_{02} & a_{03} \\\ - a_{10} & a_{11} & a_{12} & a_{13} \\\ - a_{20} & a_{21} & a_{22} & a_{23} \\\ - a_{30} & a_{31} & a_{32} & a_{33} \\\ + a_{00} & a_{01} & a_{02} & a_{03} \\ + a_{10} & a_{11} & a_{12} & a_{13} \\ + a_{20} & a_{21} & a_{22} & a_{23} \\ + a_{30} & a_{31} & a_{32} & a_{33} \\ \end{bmatrix} $$ @@ -315,7 +315,7 @@ The $SWAP$ gate acts on two qubits, and, as the name implies, swaps their quantu $SWAP$ - $\begin{bmatrix} 1 & 0 & 0 & 0 \\\ 0 & 0 & 1 & 0 \\\ 0 & 1 & 0 & 0 \\\ 0 & 0 & 0 & 1 \end{bmatrix}$ + $\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}$ $SWAP|\psi\rangle = \alpha|00\rangle + \gamma|01\rangle + \beta|10\rangle + \delta|11\rangle$ $$SWAP|00\rangle = |00\rangle$$ @@ -369,13 +369,13 @@ $$= x_{000}|000\rangle + x_{001}|001\rangle + x_{010}|010\rangle + x_{011}|011\r $CINOT$ can also be represented in matrix form as a $2^3 \times 2^3$ matrix: $$ \begin{bmatrix} - 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\ - 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\\ - 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\\ - 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\\ - 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\\ - 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\\ + 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \end{bmatrix} $$ @@ -383,20 +383,20 @@ $$ Applying $CINOT$ to $|\psi\rangle$ gives us $$ CINOT \begin{bmatrix} - 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\ - 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\\ - 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\\ - 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\\ - 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\\ - 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\\ + 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \end{bmatrix} \begin{bmatrix} - x_{000} \\\ x_{001} \\\ x_{010} \\\ x_{011} \\\ x_{100} \\\ x_{101} \\\ x_{110} \\\ x_{111} + x_{000} \\ x_{001} \\ x_{010} \\ x_{011} \\ x_{100} \\ x_{101} \\ x_{110} \\ x_{111} \end{bmatrix} = \begin{bmatrix} - x_{000} \\\ x_{001} \\\ x_{010} \\\ x_{011} \\\ x_{101} \\\ x_{100} \\\ x_{111} \\\ x_{110} + x_{000} \\ x_{001} \\ x_{010} \\ x_{011} \\ x_{101} \\ x_{100} \\ x_{111} \\ x_{110} \end{bmatrix} $$ @@ -410,7 +410,7 @@ However, as $N$ gets larger, creating a full size matrix can be extremely unwiel These can be represented as applying the following gates on the 3 qubits. -1. $SWAP \otimes I$ +1. $\text{SWAP} \otimes I$ $$ x_{000}|000\rangle + x_{001}|001\rangle + x_{100}|010\rangle + x_{101}|011\rangle + @@ -421,10 +421,10 @@ $$ $$ x_{000}|000\rangle + x_{001}|001\rangle + x_{101}|010\rangle + x_{100}|011\rangle + -x_{010}|100\\rangle + x_{011}|101\rangle + x_{111}|110\rangle + x_{110}|111\rangle +x_{010}|100\rangle + x_{011}|101\rangle + x_{111}|110\rangle + x_{110}|111\rangle $$ -3. $SWAP \otimes I$ +3. $\text{SWAP} \otimes I$ $$ x_{000}|000\rangle + x_{001}|001\rangle + x_{010}|010\rangle + x_{011}|011\rangle + @@ -441,18 +441,18 @@ $$CINOT = (SWAP \otimes I)(I \otimes CNOT)(SWAP \otimes I)$$ > We can also spell out all gates applied explicitly (this makes for a much longer code, though): > > ```qsharp -operation CINOT (qs: Qubit[]) : Unit { - // First step - SWAP(qs[0], qs[1]); - I(qs[2]); - // Second step - I(qs[0]); - CNOT(qs[1], qs[2]); - // Third step - SWAP(qs[0], qs[1]); - I(qs[2]); -} -``` +> operation CINOT (qs: Qubit[]) : Unit { +> // First step +> SWAP(qs[0], qs[1]); +> I(qs[2]); +> // Second step +> I(qs[0]); +> CNOT(qs[1], qs[2]); +> // Third step +> SWAP(qs[0], qs[1]); +> I(qs[2]); +> } +> ``` @[section]({ "id": "multi_qubit_gates__controlled_gates", @@ -462,7 +462,7 @@ operation CINOT (qs: Qubit[]) : Unit { **Controlled gates** are a class of gates derived from other gates as follows: they act on a control qubit and a target qubit, just like the $CNOT$ gate. A controlled-$U$ gate applies the $U$ gate to the target qubit if the control qubit is in state $|1\rangle$, and does nothing otherwise. -Given a gate $U = \begin{bmatrix} \alpha & \beta \\\ \gamma & \delta \end{bmatrix}$, its controlled version looks like this: +Given a gate $U = \begin{bmatrix} \alpha & \beta \\ \gamma & \delta \end{bmatrix}$, its controlled version looks like this: @@ -475,9 +475,9 @@ Given a gate $U = \begin{bmatrix} \alpha & \beta \\\ \gamma & \delta \end{bmatri - + - + - + - + @@ -167,10 +167,10 @@ $$X = |0\rangle\langle1| + |1\rangle\langle0|$$ $$ |0\rangle\langle1| + |1\rangle\langle0| = -\begin{bmatrix} 1 \\\ 0 \end{bmatrix}\begin{bmatrix} 0 & 1 \end{bmatrix} + -\begin{bmatrix} 0 \\\ 1 \end{bmatrix}\begin{bmatrix} 1 & 0 \end{bmatrix} = -\begin{bmatrix} 0 & 1 \\\ 0 & 0 \end{bmatrix} + \begin{bmatrix} 0 & 0 \\\ 1 & 0 \end{bmatrix} = -\begin{bmatrix} 0 & 1 \\\ 1 & 0 \end{bmatrix} +\begin{bmatrix} 1 \\ 0 \end{bmatrix}\begin{bmatrix} 0 & 1 \end{bmatrix} + +\begin{bmatrix} 0 \\ 1 \end{bmatrix}\begin{bmatrix} 1 & 0 \end{bmatrix} = +\begin{bmatrix} 0 & 1 \\ 0 & 0 \end{bmatrix} + \begin{bmatrix} 0 & 0 \\ 1 & 0 \end{bmatrix} = +\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} $$ This representation can be used to carry out calculations in Dirac notation without ever switching back to matrix representation: @@ -184,7 +184,7 @@ $$X|0\rangle = \big(|0\rangle\langle1| + |1\rangle\langle0|\big)|0\rangle = |0\r > Two vectors are orthogonal to each other if their inner product equals $0$. This means that $\langle0|1\rangle = \langle 1|0\rangle = 0$. In general case, a matrix -$$A = \begin{bmatrix} a_{00} & a_{01} \\\ a_{10} & a_{11} \end{bmatrix}$$ +$$A = \begin{bmatrix} a_{00} & a_{01} \\ a_{10} & a_{11} \end{bmatrix}$$ will have the following ket-bra representation: $$A = a_{00} |0\rangle\langle0| + a_{01} |0\rangle\langle1| + a_{10} |1\rangle\langle0| + a_{11} |1\rangle\langle1|$$ @@ -250,7 +250,7 @@ The Pauli gates, named after - + @@ -57,9 +52,9 @@ export function ReTable(props: { <> {entry.description}
-
) : ( @@ -81,9 +76,10 @@ export function ReTable(props: {
    {reportData.assumptions.map((assumption) => ( -
  • ))}
diff --git a/npm/qsharp/ux/renderers.tsx b/npm/qsharp/ux/renderers.tsx new file mode 100644 index 0000000000..eb436cdcab --- /dev/null +++ b/npm/qsharp/ux/renderers.tsx @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { createElement } from "preact"; + +// Default renderer to be replaced before components are first used. +// Expectation is that this will convert markdown and/or LaTeX to HTML. +let theRenderer = function (input: string): string { + const err = "ERROR: Rendered has not been set"; + console.error(err); + return err + ". " + input; +}; + +export function setRenderer(renderer: (input: string) => string) { + theRenderer = renderer; +} + +export function Markdown(props: { + markdown: string; + className?: string; + tagName?: string; +}) { + const tag = props.tagName || "div"; + const nodeProps = { + className: props.className, + dangerouslySetInnerHTML: { + __html: theRenderer(props.markdown), + }, + }; + + return createElement(tag, nodeProps); +} diff --git a/package-lock.json b/package-lock.json index 8b74c916a9..55bad42d61 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@microsoft/quantum-viz.js": "^1.0.5", "@parcel/watcher": "^2.4.1", "@types/chai": "^4.3.8", - "@types/markdown-it": "^13.0.6", + "@types/markdown-it": "^13.0.7", "@types/mocha": "^10.0.2", "@types/node": "^18.17", "@types/vscode": "^1.83.0", @@ -34,8 +34,6 @@ "events": "^3.3.0", "github-markdown-css": "^5.3.0", "markdown-it": "^13.0.2", - "marked": "^9.1.2", - "mathjax": "^3.2.2", "mocha": "^10.2.0", "modern-normalize": "^2.0.0", "monaco-editor": "^0.44.0", @@ -4426,24 +4424,6 @@ "markdown-it": "bin/markdown-it.js" } }, - "node_modules/marked": { - "version": "9.1.6", - "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz", - "integrity": "sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q==", - "dev": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 16" - } - }, - "node_modules/mathjax": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/mathjax/-/mathjax-3.2.2.tgz", - "integrity": "sha512-Bt+SSVU8eBG27zChVewOicYs7Xsdt40qm4+UpHyX7k0/O9NliPc+x77k1/FEsPsjKPZGJvtRZM1vO+geW0OhGw==", - "dev": true - }, "node_modules/mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", diff --git a/package.json b/package.json index a9945e739b..b4a0c3f590 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "@microsoft/quantum-viz.js": "^1.0.5", "@parcel/watcher": "^2.4.1", "@types/chai": "^4.3.8", - "@types/markdown-it": "^13.0.6", + "@types/markdown-it": "^13.0.7", "@types/mocha": "^10.0.2", "@types/node": "^18.17", "@types/vscode": "^1.83.0", @@ -39,8 +39,6 @@ "events": "^3.3.0", "github-markdown-css": "^5.3.0", "markdown-it": "^13.0.2", - "marked": "^9.1.2", - "mathjax": "^3.2.2", "mocha": "^10.2.0", "modern-normalize": "^2.0.0", "monaco-editor": "^0.44.0", diff --git a/playground/build.js b/playground/build.js index 2f4f381ebe..4329e570f0 100644 --- a/playground/build.js +++ b/playground/build.js @@ -9,6 +9,8 @@ import { fileURLToPath } from "node:url"; import { build, context } from "esbuild"; +import { copyKatex } from "../vscode/build.mjs"; + const thisDir = dirname(fileURLToPath(import.meta.url)); const libsDir = join(thisDir, "..", "node_modules"); @@ -33,9 +35,11 @@ const buildOptions = { join(thisDir, "src/main.tsx"), join(thisDir, "src/compiler-worker.ts"), join(thisDir, "src/language-service-worker.ts"), + join(thisDir, "src/kataViewer.ts"), ], outdir, bundle: true, + platform: "browser", target: ["es2020", "chrome64", "edge79", "firefox62", "safari11.1"], define: { "import.meta.url": "document.URL" }, sourcemap: "linked", @@ -54,19 +58,7 @@ function copyLibs() { mkdirSync(monacoDest, { recursive: true }); cpSync(monacoBase, monacoDest, { recursive: true }); - let mathjaxBase = join(libsDir, `mathjax/es5`); - let mathjaxDest = join(thisDir, `public/libs/mathjax`); - - console.log("Copying the Mathjax files over from: " + mathjaxBase); - mkdirSync(mathjaxDest, { recursive: true }); - cpSync(mathjaxBase, mathjaxDest, { recursive: true }); - - let githubMarkdown = join( - libsDir, - "github-markdown-css/github-markdown-light.css", - ); - let githubMarkdownDest = join(thisDir, "public/libs/github-markdown.css"); - copyFileSync(githubMarkdown, githubMarkdownDest); + copyKatex(join(thisDir, "public/libs/katex"), true); copyWasmToPlayground(); } diff --git a/playground/public/index.html b/playground/public/index.html index b665b05ab5..62ffcd0197 100644 --- a/playground/public/index.html +++ b/playground/public/index.html @@ -16,24 +16,10 @@ rel="icon" href="data:image/gif;base64,R0lGODlhEAAQAAAAACwAAAAAEAAQAAACDvAxdbn9YZSTVntx1qcAADs=" /> - + + Q# playground - - diff --git a/playground/public/katas.html b/playground/public/katas.html new file mode 100644 index 0000000000..2b0a3f8814 --- /dev/null +++ b/playground/public/katas.html @@ -0,0 +1,42 @@ + + + + + + Katas MathJax review + + + + +
+

Azure Quantum Katas

+

+ This is a very basic rendering of the Azure Quantum Katas using MathJax + for content review purposes +

+ + + + + + diff --git a/playground/src/docs.tsx b/playground/src/docs.tsx index bc95158625..517c3ae79e 100644 --- a/playground/src/docs.tsx +++ b/playground/src/docs.tsx @@ -1,9 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { useEffect, useRef } from "preact/hooks"; -import markdownit from "markdown-it"; import { IDocFile } from "qsharp-lang"; +import { Markdown } from "qsharp-lang/ux"; export function getNamespaces( documentation: Map | undefined, @@ -20,7 +19,6 @@ export function getNamespaces( export function processDocumentFiles( docFiles: IDocFile[], ): Map { - const md = markdownit(); const contentByNamespace = new Map(); const regex = new RegExp("^qsharp.namespace: Microsoft.Quantum.(.+)$", "m"); @@ -32,16 +30,15 @@ export function processDocumentFiles( // The next line contains "Zero-width space" unicode character // to allow line breaks before the period. const newNamespace = "… " + match[1].replace(".", "​."); - const newContent = md.render(doc.contents); if (contentByNamespace.has(newNamespace)) { const existingContent = contentByNamespace.get(newNamespace)!; contentByNamespace.set( newNamespace, - existingContent + "\n
\n
\n" + newContent, + existingContent + "\n
\n
\n" + doc.contents, ); } else { - contentByNamespace.set(newNamespace, newContent); + contentByNamespace.set(newNamespace, doc.contents); } } return contentByNamespace; @@ -51,15 +48,7 @@ export function DocumentationDisplay(props: { currentNamespace: string; documentation: Map | undefined; }) { - const docsDiv = useRef(null); + const docsMd = props.documentation?.get(props.currentNamespace) ?? ""; - useEffect(() => { - if (!docsDiv.current || !props.documentation) return; - docsDiv.current.innerHTML = props.documentation.get( - props.currentNamespace, - )!; - MathJax.typeset(); - }, [props.currentNamespace]); - - return
; + return ; } diff --git a/playground/src/kata.tsx b/playground/src/kata.tsx index 2b04c8cbad..d391214db3 100644 --- a/playground/src/kata.tsx +++ b/playground/src/kata.tsx @@ -1,202 +1,180 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { useEffect, useRef, useState } from "preact/hooks"; +import { useState } from "preact/hooks"; import { CompilerState, ExplainedSolution, ICompilerWorker, ILanguageServiceWorker, type Kata, - Lesson, QscEventTarget, Question, VSDiagnostic, + KataSection, } from "qsharp-lang"; import { Editor, getProfile } from "./editor.js"; import { OutputTabs } from "./tabs.js"; +import { Markdown } from "qsharp-lang/ux"; -function ExplainedSolutionAsHtml(solution: ExplainedSolution): string { - let html = "
"; - html += `πŸ’‘ Solution`; - for (const item of solution.items) { - switch (item.type) { - case "example": - case "solution": - html += `
${item.code}
`; - break; - case "text-content": - html += `
${item.asHtml}
`; - break; - } - } - html += `
`; - return html; -} - -function LessonAsHtml(lesson: Lesson): string { - let html = ""; - for (const item of lesson.items) { - switch (item.type) { - case "example": - html += `
${item.code}
`; - break; - case "text-content": - html += `
${item.asHtml}
`; - break; - case "question": - html += QuestionAsHtml(item); - break; - } - } - return html; -} - -function QuestionAsHtml(question: Question): string { - let html = "

❓ Question:

"; - html += `
${question.description.asHtml}
`; - html += "
"; - html += "
"; - html += "πŸ’‘ Answer"; - for (const item of question.answer.items) { - switch (item.type) { - case "example": - html += `
${item.code}
`; - break; - case "text-content": - html += `
${item.asHtml}
`; - break; - } - } - html += "
"; - html += "
"; - return html; -} - -export function Kata(props: { +type Props = { kata: Kata; compiler: ICompilerWorker; compiler_worker_factory: () => ICompilerWorker; compilerState: CompilerState; onRestartCompiler: () => void; languageService: ILanguageServiceWorker; -}) { - const kataContent = useRef(null); - const itemContent = useRef<(HTMLDivElement | null)[]>([]); - - // Need to keep around QscEventTargets around on re-render unless the Kata changes. - const lastKata = useRef(); - const handlerMap = useRef(); - if (lastKata.current !== props.kata) { - lastKata.current = props.kata; +}; - // This gives an extra EventTarget we don't need for 'reading' types, but that's fine. - handlerMap.current = props.kata.sections.map( - () => new QscEventTarget(true), - ); - } - const itemEvtHandlers = handlerMap.current || []; +function ExplainedSolutionElem(props: { solution: ExplainedSolution }) { + return ( +
+ {"πŸ’‘ Solution"} + {props.solution.items.map((item) => { + switch (item.type) { + case "example": + case "solution": + return ( +
+                {item.code}
+              
+ ); + case "text-content": + return ; + } + })} +
+ ); +} - const [shotError, setShotError] = useState( - undefined, +function QuestionElem(props: { question: Question }) { + return ( + <> +

{"❓ Question:"}

+ +
+ + {"πŸ’‘ Answer"} + + {props.question.answer.items.map((item) => { + switch (item.type) { + case "example": + return ( +
+                  {item.code}
+                
+ ); + case "text-content": + return ; + } + })} +
+ ); +} + +function LessonElem(props: Props & { section: KataSection }) { + if (props.section.type !== "lesson") throw "Invalid section type"; + const lesson = props.section; - useEffect(() => { - // MathJax rendering inside of React components seems to mess them up a bit, - // so we'll take control of it here and ensure the contents are replaced. - if (!kataContent.current) return; + return ( +
+
+

+ {"πŸ“– Lesson: "} + {lesson.title} +

+
+
+ {lesson.items.map((item) => { + switch (item.type) { + case "example": + return ( +
+                  {item.code}
+                
+ ); + case "text-content": + return ; + case "question": + return ; + } + })} +
+
+ ); +} - props.kata.sections.forEach((section, idx) => { - const parentDiv = itemContent.current[idx]; - let titlePrefix = "πŸ›"; - if (section.type === "exercise") { - titlePrefix = "⌨ Exercise: "; - const descriptionDiv = parentDiv?.querySelector( - ".exercise-description", - ); - if (!descriptionDiv) - throw new Error("exercise-description div not found"); - descriptionDiv.innerHTML = section.description.asHtml; - const solutionDiv = parentDiv?.querySelector(".exercise-solution"); - if (!solutionDiv) throw new Error("exercise-solution div not found"); - solutionDiv.innerHTML = ExplainedSolutionAsHtml( - section.explainedSolution, - ); - } else if (section.type === "lesson") { - titlePrefix = "πŸ“– Lesson: "; - const contentDiv = parentDiv?.querySelector(".kata-text-content"); - if (!contentDiv) throw new Error("kata-text-content div not found"); - contentDiv.innerHTML = LessonAsHtml(section); - } else { - throw new Error(`Unexpected section`); - } +function ExerciseElem(props: Props & { section: KataSection }) { + if (props.section.type !== "exercise") throw "Invalid section type"; + const exercise = props.section; - const titleDiv = parentDiv?.querySelector(".section-title"); - if (!titleDiv) throw new Error("section-title div not found"); - titleDiv.innerHTML = `

${titlePrefix} ${section.title}

`; - }); - // In case we're now rendering less items than before, be sure to truncate - itemContent.current.length = props.kata.sections.length; + const [shotError, setShotError] = useState(); + const [evtHandler] = useState(() => new QscEventTarget(true)); - MathJax.typeset(); - }, [props.kata]); + return ( +
+
+

+ {"⌨ Exercise: "} + {exercise.title} +

+
+ +
+ ({})} + setHir={() => ({})} + setQir={() => ({})} + activeTab="results-tab" + languageService={props.languageService} + > + setShotError(diag)} + ast="" + hir="" + qir="" + activeTab="results-tab" + setActiveTab={() => undefined} + > +
+ +
+ ); +} +export function Kata(props: Props) { return (
-
-

- {props.kata.sections.map((section, idx) => { - if (section.type === "lesson") { - return ( -
(itemContent.current[idx] = elem)}> -
-
-
- ); - } else if (section.type === "exercise") { - return ( -
(itemContent.current[idx] = elem)}> -
-
-
- ({})} - setHir={() => ({})} - setQir={() => ({})} - activeTab="results-tab" - languageService={props.languageService} - > - setShotError(diag)} - ast="" - hir="" - qir="" - activeTab="results-tab" - setActiveTab={() => undefined} - > -
-
-
- ); - } - })} + {props.kata.sections.map((section) => + section.type === "lesson" ? ( + + ) : ( + + ), + )}
); } diff --git a/playground/src/kataViewer.ts b/playground/src/kataViewer.ts new file mode 100644 index 0000000000..8cefcb6b87 --- /dev/null +++ b/playground/src/kataViewer.ts @@ -0,0 +1,144 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { ExplainedSolutionItem, Kata, getAllKatas } from "qsharp-lang"; + +(window as any).MathJax = { + loader: { load: ["[tex]/physics", "[tex]/color"] }, + tex: { + packages: { "[+]": ["physics", "color"] }, + inlineMath: [ + ["$", "$"], + ["\\(", "\\)"], + ], + formatError: (jax: any, err: any) => { + console.log("LaTeX processing error occurred. ", err, jax); + const errorNode = document.createElement("div"); + errorNode.innerText = `LaTeX processing error: ${err.message}.\nLaTeX: ${jax.latex}\n\n`; + errorNode.style.fontSize = "20px"; + errorNode.style.color = "red"; + document.querySelector("#errors")?.appendChild(errorNode); + window.scroll(0, 0); + jax.formatError(err); + }, + }, + startup: { + pageReady: async () => { + await onload(); + return (window as any).MathJax.startup.defaultPageReady(); + }, + }, +}; + +async function onload() { + const katas = await getAllKatas(); + + const indexDiv = document.createElement("div"); + document.body.appendChild(indexDiv); + const indexKatas = document.createElement("ul"); + indexDiv.appendChild(indexKatas); + + katas.forEach((kata) => { + const kataLi = document.createElement("li"); + kataLi.innerHTML = `
${kata.title}`; + indexKatas.appendChild(kataLi); + + document.body.appendChild(getKataDiv(kata, indexKatas)); + }); + document.querySelectorAll("details").forEach((item) => (item.open = true)); + document + .querySelectorAll("code") + .forEach((item) => (item.className = "qsharp")); + (window as any).hljs.highlightAll(); +} + +function getKataDiv(kata: Kata, index: HTMLElement) { + const kataDiv = document.createElement("div"); + const kataHeader = document.createElement("h1"); + kataHeader.innerText = kata.title; + kataHeader.id = `kata-${kata.id}`; + kataDiv.appendChild(kataHeader); + + const sectionIndex = document.createElement("ul"); + index.appendChild(sectionIndex); + + kata.sections.forEach((section) => { + const sectionDiv = document.createElement("div"); + const sectionHeader = document.createElement("h2"); + sectionHeader.innerText = section.title; + const sectionId = `section-${section.id}`; + sectionHeader.id = sectionId; + sectionDiv.appendChild(sectionHeader); + + const sectionLi = document.createElement("li"); + sectionLi.innerHTML = `${section.title}`; + sectionIndex.appendChild(sectionLi); + + if (section.type === "lesson") { + section.items.forEach((item) => { + switch (item.type) { + case "text-content": { + const content = document.createElement("div"); + content.innerHTML = item.asHtml; + sectionDiv.appendChild(content); + break; + } + case "question": { + const questionHeader = document.createElement("h3"); + questionHeader.innerHTML = `Question`; + sectionDiv.appendChild(questionHeader); + const questionBody = document.createElement("div"); + questionBody.innerHTML = item.description.asHtml; + sectionDiv.appendChild(questionBody); + const answerHeader = document.createElement("h3"); + answerHeader.innerHTML = `Answer`; + sectionDiv.appendChild(answerHeader); + item.answer.items.forEach((item) => addContent(item, sectionDiv)); + break; + } + case "example": { + const code = document.createElement("pre"); + code.innerHTML = `${item.code}`; + sectionDiv.appendChild(code); + break; + } + } + }); + } else { + // Exercise + const exerciseHeader = document.createElement("h3"); + exerciseHeader.innerHTML = `Exercise: ${section.title}`; + sectionDiv.appendChild(exerciseHeader); + const exerciseDesc = document.createElement("div"); + exerciseDesc.innerHTML = section.description.asHtml; + sectionDiv.appendChild(exerciseDesc); + + const codeDiv = document.createElement("pre"); + codeDiv.innerHTML = `${section.placeholderCode}`; + sectionDiv.appendChild(codeDiv); + + const solutionHeader = document.createElement("h4"); + solutionHeader.innerHTML = `Solution`; + sectionDiv.appendChild(solutionHeader); + + section.explainedSolution.items.forEach((item) => + addContent(item, sectionDiv), + ); + } + kataDiv.appendChild(sectionDiv); + }); + return kataDiv; +} + +function addContent(item: ExplainedSolutionItem, sectionDiv: HTMLDivElement) { + if (item.type === "text-content") { + const contentDiv = document.createElement("div"); + contentDiv.innerHTML = item.asHtml; + sectionDiv.appendChild(contentDiv); + } else { + // example or solution + const codeDiv = document.createElement("pre"); + codeDiv.innerHTML = `${item.code}`; + sectionDiv.appendChild(codeDiv); + } +} diff --git a/playground/src/main.tsx b/playground/src/main.tsx index f357a8a0e5..b0a98964a9 100644 --- a/playground/src/main.tsx +++ b/playground/src/main.tsx @@ -37,6 +37,18 @@ import { monacoPositionToLsPosition, } from "./utils.js"; +// Set up the Markdown renderer with KaTeX support +import mk from "@vscode/markdown-it-katex"; +import markdownIt from "markdown-it"; +import { setRenderer } from "qsharp-lang/ux"; + +const md = markdownIt("commonmark"); +md.use((mk as any).default, { + enableMathBlockInHtml: true, + enableMathInlineInHtml: true, +}); // Not sure why it's not using the default export automatically :-/ +setRenderer((input: string) => md.render(input)); + export type ActiveTab = "results-tab" | "ast-tab" | "hir-tab" | "qir-tab"; const basePath = (window as any).qscBasePath || ""; @@ -45,14 +57,6 @@ const modulePath = basePath + "libs/qsharp/qsc_wasm_bg.wasm"; const compilerWorkerPath = basePath + "libs/compiler-worker.js"; const languageServiceWorkerPath = basePath + "libs/language-service-worker.js"; -declare global { - const MathJax: { - typeset: () => void; - typesetPromise: (nodes: HTMLElement[]) => Promise; - typesetClear: (nodes: HTMLElement[]) => void; - }; -} - function telemetryHandler({ id, data }: { id: string; data?: any }) { // NOTE: This is for demo purposes. Wire up to the real telemetry library. console.log(`Received telemetry event: "%s" with payload: %o`, id, data); diff --git a/playground/src/state.tsx b/playground/src/state.tsx index 5730eb5418..8203ae01cd 100644 --- a/playground/src/state.tsx +++ b/playground/src/state.tsx @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { useEffect, useRef } from "preact/hooks"; import { Dump } from "qsharp-lang"; +import { Markdown } from "qsharp-lang/ux"; function probability(real: number, imag: number) { return real * real + imag * imag; @@ -18,14 +18,6 @@ function formatComplex(real: number, imag: number) { } export function StateTable(props: { dump: Dump; latexDump: string }) { - const mjRender = useRef(null); - useEffect(() => { - if (!mjRender.current) return; - MathJax.typesetClear([mjRender.current]); - mjRender.current.innerHTML = props.latexDump; - MathJax.typesetPromise([mjRender.current]); - }, [props.latexDump]); - return (
$$ \begin{bmatrix} - 1 & 0 & 0 & 0 \\\ - 0 & 1 & 0 & 0 \\\ - 0 & 0 & \alpha & \beta \\\ + 1 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 \\ + 0 & 0 & \alpha & \beta \\ 0 & 0 & \gamma & \delta \end{bmatrix} $$ @@ -494,13 +494,13 @@ Here, for example, is the Controlled $SWAP$, or **Fredkin gate**: $$ \begin{bmatrix} - 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\ - 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\\ - 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\\ - 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\\ - 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\ - 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\\ - 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\\ + 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \end{bmatrix} $$ @@ -553,13 +553,13 @@ The simplest example of this is the **Toffoli gate**, or $CCNOT$ (controlled con $$ \begin{bmatrix} - 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\ - 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\\ - 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\\ - 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\\ - 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\ - 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\\ + 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \end{bmatrix} $$ diff --git a/katas/content/multi_qubit_gates/preparing_bell_state/index.md b/katas/content/multi_qubit_gates/preparing_bell_state/index.md index f6cdf47ad7..9ab52f6a47 100644 --- a/katas/content/multi_qubit_gates/preparing_bell_state/index.md +++ b/katas/content/multi_qubit_gates/preparing_bell_state/index.md @@ -1,3 +1,3 @@ **Input:** Two qubits in state $|00\rangle$, stored in an array of length 2. -**Goal:** Transform the system into the Bell state $\ket{\Phi^+} = \frac{1}{\sqrt{2}}\big(|00\rangle + |11\rangle\big)$. \ No newline at end of file +**Goal:** Transform the system into the Bell state $\ket{\Phi^+} = \frac{1}{\sqrt{2}}\big(|00\rangle + |11\rangle\big)$. diff --git a/katas/content/multi_qubit_gates/qubit_swap/index.md b/katas/content/multi_qubit_gates/qubit_swap/index.md index a08c05f0b0..70fe149bfb 100644 --- a/katas/content/multi_qubit_gates/qubit_swap/index.md +++ b/katas/content/multi_qubit_gates/qubit_swap/index.md @@ -1,6 +1,6 @@ **Inputs:** -1. $N$ qubits in an arbitrary state $|\\psi\\rangle$, stored in an array of length $N$. +1. $N$ qubits in an arbitrary state $|\psi\rangle$, stored in an array of length $N$. 2. Integers `index1` and `index2` such that $0 \le \text{index1} < \text{index2} \le N - 1$. -**Goal:** Swap the states of the qubits at the given indices. \ No newline at end of file +**Goal:** Swap the states of the qubits at the given indices. diff --git a/katas/content/multi_qubit_gates/relative_phase_minusone/solution.md b/katas/content/multi_qubit_gates/relative_phase_minusone/solution.md index b94bb4f436..e38e98af1b 100644 --- a/katas/content/multi_qubit_gates/relative_phase_minusone/solution.md +++ b/katas/content/multi_qubit_gates/relative_phase_minusone/solution.md @@ -1,9 +1,9 @@ Firstly we notice that we are dealing with an unentangled pair of qubits. -In vector form the transformation we need is +In vector form the transformation we need is $$ -\frac{1}{2}\begin{bmatrix}1\\\ 1\\\ 1\\\ 1\\\ \end{bmatrix} -\rightarrow -\frac{1}{2}\begin{bmatrix}1\\\ 1\\\ 1\\\ -1\\\ \end{bmatrix} +\frac{1}{2}\begin{bmatrix}1 \\ 1 \\ 1 \\ 1 \end{bmatrix} +\rightarrow +\frac{1}{2}\begin{bmatrix}1 \\ 1 \\ 1 \\ -1 \end{bmatrix} $$ All that needs to happen to change the input into the goal is that the $|11\rangle$ basis state needs to have its sign flipped. diff --git a/katas/content/multi_qubit_gates/toffoli_gate/solution.md b/katas/content/multi_qubit_gates/toffoli_gate/solution.md index ca10d8aaa8..67015b2f2b 100644 --- a/katas/content/multi_qubit_gates/toffoli_gate/solution.md +++ b/katas/content/multi_qubit_gates/toffoli_gate/solution.md @@ -1,18 +1,41 @@ This is essentially bookwork, because there is only one gate that performs this state change (and the task title already gave it away!) The Toffoli gate is: $$ - \begin{bmatrix}1 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\\ 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\\ 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0\\\ 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0\\\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\\\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0\\\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1\\\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0\\\ \end{bmatrix} + \begin{bmatrix} + 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 + \end{bmatrix} $$ and our initial state is: $$ -\begin{bmatrix} \alpha\\\ \beta\\\ \gamma\\\ \delta\\\ \epsilon\\\ \zeta\\\ \eta\\\ \theta\\\ \end{bmatrix} +\begin{bmatrix} \alpha \\ \beta \\ \gamma \\ \delta \\ \epsilon \\ \zeta \\ \eta \\ \theta +\end{bmatrix} $$ So we have: $$ - \begin{bmatrix}1 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\\ 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\\ 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0\\\ 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0\\\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\\\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0\\\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1\\\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0\\\ \end{bmatrix} - \begin{bmatrix}\alpha\\\ \beta\\\ \gamma\\\ \delta\\\ \epsilon\\\ \zeta\\\ \color{blue}\eta\\\ \color{blue}\theta\\\ \end{bmatrix}= - \begin{bmatrix}\alpha\\\ \beta\\\ \gamma\\\ \delta\\\ \epsilon\\\ \zeta\\\ \color{red}\theta\\\ \color{red}\eta\\\ \end{bmatrix}= + \begin{bmatrix} + 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 + \end{bmatrix} + \begin{bmatrix} + \alpha \\ \beta \\ \gamma \\ \delta \\ \epsilon \\ \zeta \\ \color{blue}\eta \\ \color{blue}\theta + \end{bmatrix}= + \begin{bmatrix} + \alpha \\ \beta \\ \gamma \\ \delta \\ \epsilon \\ \zeta \\ \color{red}\theta \\ \color{red}\eta + \end{bmatrix}= \alpha |000\rangle + \beta |001\rangle + \gamma |010\rangle + \delta |011\rangle + \epsilon |100\rangle + \zeta|101\rangle + {\color{red}\theta}|110\rangle + {\color{red}\eta}|111\rangle $$ diff --git a/katas/content/multi_qubit_measurements/index.md b/katas/content/multi_qubit_measurements/index.md index 5cee9e6559..ac4c9ca9ec 100644 --- a/katas/content/multi_qubit_measurements/index.md +++ b/katas/content/multi_qubit_measurements/index.md @@ -22,9 +22,6 @@ This will include measuring a single qubit in a multi-qubit system, as well as m - Single and multi-qubit gates - Single-qubit system measurements -$\renewcommand{\ket}[1]{\left\lvert#1\right\rangle}$ -$\renewcommand{\bra}[1]{\left\langle#1\right\rvert}$ - ## Types of Measurements There are several types of measurements you can perform on an $n$-qubit system ($n>1$): @@ -40,15 +37,15 @@ We will discuss these concepts in the same order as in the list above. "title": "Full Measurements: Measurements in Multi-Qubit Bases" }) -Consider a system consisting of $n\geq1$ qubits. The wave function of such a system belongs to a vector space of dimension $2^n$. Thus, the vector space is spanned by an orthogonal basis, such as the computational basis which consists of the vectors $|0\dotsc0\rangle, \dotsc, |1\dotsc 1\rangle$. For generality, we consider an arbitrary orthonormal basis, which we denote by $\\{ |b_0\rangle, |b_1\rangle, \dotsc, |b_{2^n-1}\rangle \\}$. +Consider a system consisting of $n\geq1$ qubits. The wave function of such a system belongs to a vector space of dimension $2^n$. Thus, the vector space is spanned by an orthogonal basis, such as the computational basis which consists of the vectors $|0\dotsc0\rangle, \dotsc, |1\dotsc 1\rangle$. For generality, we consider an arbitrary orthonormal basis, which we denote by $\{ |b_0\rangle, |b_1\rangle, \dotsc, |b_{2^n-1}\rangle \}$. Then, the state $|\psi\rangle$ of the multi-qubit system can be expressed as a linear combination of the $2^n$ basis vectors $|b_i\rangle$. That is, there exist complex numbers $c_0,c_1,\dotsc, c_{2^n-1}$ such that $$ -|\psi\rangle = \sum_{i=0}^{2^n-1} c_i|b_i\rangle \equiv \begin{pmatrix} c_0 \\\ c_1 \\\ \vdots \\\ c_{2^n-1} \end{pmatrix} +|\psi\rangle = \sum_{i=0}^{2^n-1} c_i|b_i\rangle \equiv \begin{pmatrix} c_0 \\ c_1 \\ \vdots \\ c_{2^n-1} \end{pmatrix} $$ -In line with the usual convention, we choose the wave function to be normalized, so that $|c_0|^2 + \dotsc + |c_{2^n-1}|^2 =1$. Then, a quantum measurement in the basis $\\{ |b_0\rangle, |b_1\rangle, \dotsc, |b_{2^n-1}\rangle \\}$ satisfies the following rules: +In line with the usual convention, we choose the wave function to be normalized, so that $|c_0|^2 + \dotsc + |c_{2^n-1}|^2 =1$. Then, a quantum measurement in the basis $\{ |b_0\rangle, |b_1\rangle, \dotsc, |b_{2^n-1}\rangle \}$ satisfies the following rules: - The measurement outcome $b_i$ occurs with probability $|c_i|^2$. - Whenever the measurement outcome is $b_i$, the wave function collapses to the state $|b_i\rangle$. That is, the post-measurement state of the system is equal to $|b_i\rangle$. @@ -113,7 +110,7 @@ The wave function $|\psi\rangle$ is normalized, since $\left(\frac{1}{3}\right)^ You are given a two-qubit system in the following state: $$\ket \psi = \frac{2}{3}\ket {00} + \frac{1}{3} \ket {01} + \frac{2}{3}\ket {11}$$ -If all the qubits are measured simultaneously in the Pauli X basis, that is, in the $\\{ \ket{++}, \ket{+-}, \ket{-+}, \ket{--}\\}$ basis, what are the outcome probabilities? +If all the qubits are measured simultaneously in the Pauli X basis, that is, in the $\{ \ket{++}, \ket{+-}, \ket{-+}, \ket{--}\}$ basis, what are the outcome probabilities?
Analytical Solution @@ -213,7 +210,7 @@ In practice, this is implemented by measuring all the qubits one after another. This can be generalized to measurements in other bases, such as the 2-qubit Pauli X basis $\ket{++}, \ket{+-}, \ket{-+}, \ket{--}$, and the bases for larger numbers of qubits. -> Note that measurement of all qubits sequentially can only be done in orthogonal bases $\\{ \ket{b_i}\\}$, such that each $\ket{b_i}$ is a **tensor product state**. That is, each $\ket{b_i}$ must be of the form $\ket{v_0} \otimes \ket{v_1} \dotsc \otimes \ket{v_{n-1}}$, with each $\ket{v_j}$ being a single-qubit basis state. +> Note that measurement of all qubits sequentially can only be done in orthogonal bases $\{ \ket{b_i}\}$, such that each $\ket{b_i}$ is a **tensor product state**. That is, each $\ket{b_i}$ must be of the form $\ket{v_0} \otimes \ket{v_1} \dotsc \otimes \ket{v_{n-1}}$, with each $\ket{v_j}$ being a single-qubit basis state. For example, for the two-qubit Pauli X basis $\ket{++}, \ket{+-}, \ket{-+}, \ket{--}$ each basis state is a tensor product of states $\ket{+}$ and $\ket{-}$, which form a single-qubit basis state. > > Measuring in orthogonal bases which contain states which are not tensor product states, such as the Bell basis, are trickier to implement, and require appropriate unitary rotations in addition to measuring all qubits one after another. @@ -258,7 +255,7 @@ For a system with $n>1$ qubits, it is possible to measure $m Here $\ket{\phi_A}$ and $\ket{\phi_B}$ are wave functions that describe parts $A$ and $B$, respectively. If it is not possible to express $\ket \psi$ in such a form, then we say that system A is entangled with system B. -Consider a measurement on the subsystem $A$ of a separable state. Let the measurement be done in a basis $\\{ \ket{b_0},\dotsc,\ket{b_{2^m-1}}\\}$. According to the projection formalism, a projection operator $P_i = \ket{b_i}\bra{b_i} \otimes \mathbb{1}$ is chosen randomly. The corresponding post-measurement state of the system is then given by +Consider a measurement on the subsystem $A$ of a separable state. Let the measurement be done in a basis $\{ \ket{b_0},\dotsc,\ket{b_{2^m-1}}\}$. According to the projection formalism, a projection operator $P_i = \ket{b_i}\bra{b_i} \otimes \mathbb{1}$ is chosen randomly. The corresponding post-measurement state of the system is then given by $$\ket{\psi}_{i} \equiv \frac{P_i \ket{\psi}}{\big|P_i \ket{\psi}\big|} = \frac{\ket{b_i}\bra{b_i}\phi_A\rangle \otimes \ket {\phi_B}}{\big|\ket{b_i}\bra{b_i}\phi_A\rangle \otimes \ket {\phi_B}\big|}=$$ @@ -449,9 +446,9 @@ For single-qubit systems, any measurement corresponding to an orthogonal basis c For example, consider the computational basis measurement, which can result in outcomes `Zero` or `One` corresponding to states $\ket 0$ and $\ket 1$. This measurement is associated with the Pauli Z operator, which is given by -$$Z = \begin{pmatrix} 1 & 0 \\\ 0 & -1\end{pmatrix} = \ket{0}\bra{0} - \ket{1}\bra{1}$$ +$$Z = \begin{pmatrix} 1 & 0 \\ 0 & -1\end{pmatrix} = \ket{0}\bra{0} - \ket{1}\bra{1}$$ -The $Z$ operator has two eigenvalues, $1$ and $-1$, with corresponding eigenvectors $\ket{0}$ and $\ket{1}$. A $Z$-measurement is then a measurement in the $\\{\ket{0},\ket{1}\\}$ basis, with the measurement outcomes being $1$ and $-1$, respectively. In Q#, by convention, an eigenvalue of $1$ corresponds to a `Result` of `Zero`, while an eigenvalue of $-1$ corresponds to a `Result` of `One`. +The $Z$ operator has two eigenvalues, $1$ and $-1$, with corresponding eigenvectors $\ket{0}$ and $\ket{1}$. A $Z$-measurement is then a measurement in the $\{\ket{0},\ket{1}\}$ basis, with the measurement outcomes being $1$ and $-1$, respectively. In Q#, by convention, an eigenvalue of $1$ corresponds to a `Result` of `Zero`, while an eigenvalue of $-1$ corresponds to a `Result` of `One`. Similarly, one can implement measurements corresponding to the Pauli X and Y operators. We summarize the various properties below: @@ -505,17 +502,17 @@ Joint measurements are a generalization of this principle for multi-qubit matric The simplest joint measurement is a parity measurement. A parity measurement treats computational basis vectors differently depending on whether the number of 1s in the basis vector is even or odd. -For example, the operator $Z\otimes Z$, or $ZZ$ in short, is the parity measurement operator for a two-qubit system. The eigenvalues $1$ and $-1$ correspond to the subspaces spanned by basis vectors $\\{ |00\rangle, |11\rangle \\}$ and $\\{ |01\rangle, |10\rangle \\}$, respectively. That is, when a $ZZ$ measurement results in a `Zero` (i.e., the eigenvalue $+1$), the post-measurement state is a superposition of only those computational basis vectors which have an even number of 1s. On the other hand, a result of `One` corresponds to a post-measurement state with only computational basis vectors which have an odd number of 1s. +For example, the operator $Z\otimes Z$, or $ZZ$ in short, is the parity measurement operator for a two-qubit system. The eigenvalues $1$ and $-1$ correspond to the subspaces spanned by basis vectors $\{ |00\rangle, |11\rangle \}$ and $\{ |01\rangle, |10\rangle \}$, respectively. That is, when a $ZZ$ measurement results in a `Zero` (i.e., the eigenvalue $+1$), the post-measurement state is a superposition of only those computational basis vectors which have an even number of 1s. On the other hand, a result of `One` corresponds to a post-measurement state with only computational basis vectors which have an odd number of 1s. > Let's see what happens to various two-qubit states after the parity measurement. The $Z \otimes Z$ matrix for two qubits is: > >$$ Z \otimes Z = \begin{bmatrix} - 1 & 0 & 0 & 0 \\\ - 0 & -1 & 0 & 0 \\\ - 0 & 0 & -1 & 0 \\\ - 0 & 0 & 0 & 1 \\\ + 1 & 0 & 0 & 0 \\ + 0 & -1 & 0 & 0 \\ + 0 & 0 & -1 & 0 \\ + 0 & 0 & 0 & 1 \end{bmatrix} $$ > @@ -523,13 +520,13 @@ $$ > >$$ \begin{bmatrix} - 1 & 0 & 0 & 0 \\\ - 0 & -1 & 0 & 0 \\\ - 0 & 0 & -1 & 0 \\\ - 0 & 0 & 0 & 1 \\\ + 1 & 0 & 0 & 0 \\ + 0 & -1 & 0 & 0 \\ + 0 & 0 & -1 & 0 \\ + 0 & 0 & 0 & 1 \end{bmatrix} -\begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 0 \end{bmatrix} = -\begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 0 \end{bmatrix} +\begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix} = +\begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix} $$ > >Comparing this to the characteristic equation for eigenvectors of $Z \otimes Z$ given by @@ -542,13 +539,13 @@ it is easy to see that $|00\rangle$ belongs to the $+1$ eigenspace, hence the $Z > >$$ \begin{bmatrix} - 1 & 0 & 0 & 0 \\\ - 0 & -1 & 0 & 0 \\\ - 0 & 0 & -1 & 0 \\\ - 0 & 0 & 0 & 1 \\\ + 1 & 0 & 0 & 0 \\ + 0 & -1 & 0 & 0 \\ + 0 & 0 & -1 & 0 \\ + 0 & 0 & 0 & 1 \end{bmatrix} -\begin{bmatrix} \alpha \\\ 0 \\\ 0 \\\ \beta \end{bmatrix} = -\begin{bmatrix} \alpha \\\ 0 \\\ 0 \\\ \beta \end{bmatrix} +\begin{bmatrix} \alpha \\ 0 \\ 0 \\ \beta \end{bmatrix} = +\begin{bmatrix} \alpha \\ 0 \\ 0 \\ \beta \end{bmatrix} $$ > >So this state also belongs to the $+1$ eigenspace, and measuring it will return `Zero` and leave the state unchanged. Similarly, we can verify that an $\alpha |01\rangle + \beta |10\rangle$ state belongs to the $-1$ eigenspace, and measuring it will return `One` without changing the state. @@ -570,7 +567,7 @@ Similarly, a parity measurement on a higher number of qubits can be implemented }) Joint measurement is a generalization of the measurement in the computational basis. -Pauli measurements can also be generalized to a larger number of qubits. A multi-qubit Pauli measurement corresponds to an operator $M_1 \otimes \dotsc \otimes M_n$, with each $M_i$ being from the set of gates $\\{X,Y,Z,I\\}$. If at least one of the operators is not the identity matrix, then the measurement can result in two outcomes: a `Result` of `Zero` corresponding to eigenvalue $+1$ and a `Result` of `One` corresponding to the eigenvalue $-1$. The corresponding projection operators are the projections onto the corresponding eigenspaces. +Pauli measurements can also be generalized to a larger number of qubits. A multi-qubit Pauli measurement corresponds to an operator $M_1 \otimes \dotsc \otimes M_n$, with each $M_i$ being from the set of gates $\{X,Y,Z,I\}$. If at least one of the operators is not the identity matrix, then the measurement can result in two outcomes: a `Result` of `Zero` corresponding to eigenvalue $+1$ and a `Result` of `One` corresponding to the eigenvalue $-1$. The corresponding projection operators are the projections onto the corresponding eigenspaces. For example, a Pauli/joint measurement corresponding to the $X\otimes Z$ operator can be characterized as follows:
diff --git a/katas/content/multi_qubit_systems/index.md b/katas/content/multi_qubit_systems/index.md index 2efa8043d7..9f0e9aaee9 100644 --- a/katas/content/multi_qubit_systems/index.md +++ b/katas/content/multi_qubit_systems/index.md @@ -33,7 +33,7 @@ Let's start by examining a system of two classical bits. Each bit can be in two A system of $N$ qubits can also be in any of the $2^N$ classical states, but, unlike the classical bits, it can also be in a **superposition** of all these states. Similarly to single-qubit systems, a state of an $N$-qubit system can be represented as a complex vector of size $2^N$: -$$\begin{bmatrix} x_0 \\\ x_1 \\\ \vdots \\\ x_{2^N-1}\end{bmatrix}$$ +$$\begin{bmatrix} x_0 \\ x_1 \\ \vdots \\ x_{2^N-1}\end{bmatrix}$$ ## Basis States @@ -42,23 +42,19 @@ The computational basis for an $N$-qubit system is a set of $2^N$ vectors, in ea For example, this is the **computational basis** for a two-qubit system: -$$\begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 0 \end{bmatrix}, -\begin{bmatrix} 0 \\\ 1 \\\ 0 \\\ 0 \end{bmatrix}, -\begin{bmatrix} 0 \\\ 0 \\\ 1 \\\ 0 \end{bmatrix}, -\begin{bmatrix} 0 \\\ 0 \\\ 0 \\\ 1 \end{bmatrix}$$ +$$\begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix}, +\begin{bmatrix} 0 \\ 1 \\ 0 \\ 0 \end{bmatrix}, +\begin{bmatrix} 0 \\ 0 \\ 1 \\ 0 \end{bmatrix}, +\begin{bmatrix} 0 \\ 0 \\ 0 \\ 1 \end{bmatrix}$$ It is easy to see that these vectors form an orthonormal basis. Note that each of these basis states can be represented as a tensor product of some combination of single-qubit basis states:
- - - - + + + +
$\begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 0 \end{bmatrix} = -\begin{bmatrix} 1 \\\ 0 \end{bmatrix} \otimes \begin{bmatrix} 1 \\\ 0 \end{bmatrix}$$\begin{bmatrix} 0 \\\ 1 \\\ 0 \\\ 0 \end{bmatrix} = -\begin{bmatrix} 1 \\\ 0 \end{bmatrix} \otimes \begin{bmatrix} 0 \\\ 1 \end{bmatrix}$$\begin{bmatrix} 0 \\\ 0 \\\ 1 \\\ 0 \end{bmatrix} = -\begin{bmatrix} 0 \\\ 1 \end{bmatrix} \otimes \begin{bmatrix} 1 \\\ 0 \end{bmatrix}$$\begin{bmatrix} 0 \\\ 0 \\\ 0 \\\ 1 \end{bmatrix} = -\begin{bmatrix} 0 \\\ 1 \end{bmatrix} \otimes \begin{bmatrix} 0 \\\ 1 \end{bmatrix}$$\begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix} = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \otimes \begin{bmatrix} 1 \\ 0 \end{bmatrix}$$\begin{bmatrix} 0 \\ 1 \\ 0 \\ 0 \end{bmatrix} = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \otimes \begin{bmatrix} 0 \\ 1 \end{bmatrix}$$\begin{bmatrix} 0 \\ 0 \\ 1 \\ 0 \end{bmatrix} = \begin{bmatrix} 0 \\ 1 \end{bmatrix} \otimes \begin{bmatrix} 1 \\ 0 \end{bmatrix}$$\begin{bmatrix} 0 \\ 0 \\ 0 \\ 1 \end{bmatrix} = \begin{bmatrix} 0 \\ 1 \end{bmatrix} \otimes \begin{bmatrix} 0 \\ 1 \end{bmatrix}$
@@ -67,20 +63,20 @@ Any two-qubit system can be expressed as some linear combination of those tensor Similar logic applies to systems of more than two qubits. In general case, $$ -\begin{bmatrix} x_0 \\\ x_1 \\\ \vdots \\\ x_{2^N-1} \end{bmatrix} = -x_0 \begin{bmatrix} 1 \\\ 0 \\\ \vdots \\\ 0 \end{bmatrix} + -x_1 \begin{bmatrix} 0 \\\ 1 \\\ \vdots \\\ 0 \end{bmatrix} + \dotsb + -x_{2^N-1} \begin{bmatrix} 0 \\\ 0 \\\ \vdots \\\ 1 \end{bmatrix} +\begin{bmatrix} x_0 \\ x_1 \\ \vdots \\ x_{2^N-1} \end{bmatrix} = +x_0 \begin{bmatrix} 1 \\ 0 \\ \vdots \\ 0 \end{bmatrix} + +x_1 \begin{bmatrix} 0 \\ 1 \\ \vdots \\ 0 \end{bmatrix} + \dotsb + +x_{2^N-1} \begin{bmatrix} 0 \\ 0 \\ \vdots \\ 1 \end{bmatrix} $$ The coefficients of the basis vectors define how "close" is the system state to the corresponding basis vector. > Just like with single-qubit systems, there exist other orthonormal bases states for multi-qubit systems. An example for a two-qubit system is the **Bell basis**: > -> $$\frac{1}{\sqrt{2}}\begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 1 \end{bmatrix}, -\frac{1}{\sqrt{2}}\begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ -1 \end{bmatrix}, -\frac{1}{\sqrt{2}}\begin{bmatrix} 0 \\\ 1 \\\ 1 \\\ 0 \end{bmatrix}, -\frac{1}{\sqrt{2}}\begin{bmatrix} 0 \\\ 1 \\\ -1 \\\ 0 \end{bmatrix}$$ +> $$\frac{1}{\sqrt{2}}\begin{bmatrix} 1 \\ 0 \\ 0 \\ 1 \end{bmatrix}, +\frac{1}{\sqrt{2}}\begin{bmatrix} 1 \\ 0 \\ 0 \\ -1 \end{bmatrix}, +\frac{1}{\sqrt{2}}\begin{bmatrix} 0 \\ 1 \\ 1 \\ 0 \end{bmatrix}, +\frac{1}{\sqrt{2}}\begin{bmatrix} 0 \\ 1 \\ -1 \\ 0 \end{bmatrix}$$ > > You can check that these vectors are normalized, and orthogonal to each other, and that any two-qubit state can be expressed as a linear combination of these vectors. The vectors of Bell basis, however, can not be represented as tensor products of single-qubit basis states. @@ -92,8 +88,8 @@ The coefficients of the basis vectors define how "close" is the system state to Sometimes the global state of a multi-qubit system can be separated into the states of individual qubits or subsystems. To do this, you would express the vector state of the global system as a tensor product of the vectors representing each individual qubit/subsystem. Here is an example of a two-qubit state: $$ -\begin{bmatrix} \frac{1}{\sqrt{2}} \\\ 0 \\\ \frac{1}{\sqrt{2}} \\\ 0 \end{bmatrix} = -\begin{bmatrix} \frac{1}{\sqrt{2}} \\\ \frac{1}{\sqrt{2}} \end{bmatrix} \otimes \begin{bmatrix} 1 \\\ 0 \end{bmatrix} +\begin{bmatrix} \frac{1}{\sqrt{2}} \\ 0 \\ \frac{1}{\sqrt{2}} \\ 0 \end{bmatrix} = +\begin{bmatrix} \frac{1}{\sqrt{2}} \\ \frac{1}{\sqrt{2}} \end{bmatrix} \otimes \begin{bmatrix} 1 \\ 0 \end{bmatrix} $$ You can see that the first qubit is in state $\frac{1}{\sqrt{2}}\big(|0\rangle + |1\rangle\big)$ and the second qubit is in state $|0\rangle$. The multi-qubit states that allow such representation are known as **separable states**, or product states, because you can separate the global state into the tensor product of individual subsystems. @@ -102,8 +98,8 @@ You can see that the first qubit is in state $\frac{1}{\sqrt{2}}\big(|0\rangle + Show that the state is separable: $$ -\frac{1}{2} \begin{bmatrix} 1 \\\ i \\\ -i \\\ 1 \end{bmatrix} = -\begin{bmatrix} ? \\\ ? \end{bmatrix} \otimes \begin{bmatrix} ? \\\ ? \end{bmatrix} +\frac{1}{2} \begin{bmatrix} 1 \\ i \\ -i \\ 1 \end{bmatrix} = +\begin{bmatrix} ? \\ ? \end{bmatrix} \otimes \begin{bmatrix} ? \\ ? \end{bmatrix} $$
@@ -111,15 +107,15 @@ $$ To separate the state into a tensor product of two single-qubit states, we need to represent it in the following way: $$ -\begin{bmatrix} \alpha \gamma \\\ \alpha \delta \\\ \beta \gamma \\\ \beta \delta \end{bmatrix} = -\begin{bmatrix} \alpha \\\ \beta \end{bmatrix} \otimes \begin{bmatrix} \gamma \\\ \delta \end{bmatrix} +\begin{bmatrix} \alpha \gamma \\ \alpha \delta \\ \beta \gamma \\ \beta \delta \end{bmatrix} = +\begin{bmatrix} \alpha \\ \beta \end{bmatrix} \otimes \begin{bmatrix} \gamma \\ \delta \end{bmatrix} $$ This brings us to a system of equations: $$ \begin{cases} -\alpha\gamma = \frac{1}{2} \\\ \alpha\delta = \frac{i}{2} \\\ \beta \gamma = \frac{-i}{2} \\\ \beta \delta = \frac{1}{2} +\alpha\gamma = \frac{1}{2} \\ \alpha\delta = \frac{i}{2} \\ \beta \gamma = \frac{-i}{2} \\ \beta \delta = \frac{1}{2} \end{cases} $$ @@ -128,8 +124,8 @@ Solving this system of equations gives us the answer: $$\alpha = \frac{1}{\sqrt2}, \beta = \frac{-i}{\sqrt2}, \gamma = \frac{1}{\sqrt2}, \delta = \frac{i}{\sqrt2}$$ $$ -\frac{1}{2} \begin{bmatrix} 1 \\\ i \\\ -i \\\ 1 \end{bmatrix} = -\frac{1}{\sqrt2} \begin{bmatrix} 1 \\\ -i \end{bmatrix} \otimes \frac{1}{\sqrt2} \begin{bmatrix} 1 \\\ i \end{bmatrix} +\frac{1}{2} \begin{bmatrix} 1 \\ i \\ -i \\ 1 \end{bmatrix} = +\frac{1}{\sqrt2} \begin{bmatrix} 1 \\ -i \end{bmatrix} \otimes \frac{1}{\sqrt2} \begin{bmatrix} 1 \\ i \end{bmatrix} $$ Note that finding such representation is not always possible, as you will see in the next exercise. @@ -139,7 +135,7 @@ Note that finding such representation is not always possible, as you will see in Is this state separable? -$$\frac{1}{\sqrt{2}}\begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 1 \end{bmatrix}$$ +$$\frac{1}{\sqrt{2}}\begin{bmatrix} 1 \\ 0 \\ 0 \\ 1 \end{bmatrix}$$
Solution @@ -147,7 +143,7 @@ Let's assume that this state is separable and write down the system of equations $$ \begin{cases} -\alpha\gamma = \frac{1}{\sqrt2} \\\ \alpha\delta = 0 \\\ \beta \gamma = 0 \\\ \beta \delta = \frac{1}{\sqrt2} +\alpha\gamma = \frac{1}{\sqrt2} \\ \alpha\delta = 0 \\ \beta \gamma = 0 \\ \beta \delta = \frac{1}{\sqrt2} \end{cases} $$ @@ -155,7 +151,7 @@ Now let's multiply the first and the last equations, and the second and the thir $$ \begin{cases} -\alpha\beta\gamma\delta = \frac{1}{2} \\\ \alpha\beta\gamma\delta = 0 +\alpha\beta\gamma\delta = \frac{1}{2} \\ \alpha\beta\gamma\delta = 0 \end{cases} $$ @@ -193,11 +189,11 @@ Just like with single qubits, Dirac notation provides a useful shorthand for wri As we've seen earlier, multi-qubit systems have their own canonical bases, and the basis states can be represented as tensor products of single-qubit basis states. Any multi-qubit system can be represented as a linear combination of these basis states: $$ -\begin{bmatrix} x_0 \\\ x_1 \\\ x_2 \\\ x_3 \end{bmatrix} = -x_0\begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 0 \end{bmatrix} + -x_1\begin{bmatrix} 0 \\\ 1 \\\ 0 \\\ 0 \end{bmatrix} + -x_2\begin{bmatrix} 0 \\\ 0 \\\ 1 \\\ 0 \end{bmatrix} + -x_3\begin{bmatrix} 0 \\\ 0 \\\ 0 \\\ 1 \end{bmatrix} = +\begin{bmatrix} x_0 \\ x_1 \\ x_2 \\ x_3 \end{bmatrix} = +x_0\begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix} + +x_1\begin{bmatrix} 0 \\ 1 \\ 0 \\ 0 \end{bmatrix} + +x_2\begin{bmatrix} 0 \\ 0 \\ 1 \\ 0 \end{bmatrix} + +x_3\begin{bmatrix} 0 \\ 0 \\ 0 \\ 1 \end{bmatrix} = x_0|0\rangle \otimes |0\rangle + x_1|0\rangle \otimes |1\rangle + x_2|1\rangle \otimes |0\rangle + @@ -222,7 +218,7 @@ $$|i_0\rangle \otimes |i_1\rangle \otimes \dotsb \otimes |i_n\rangle = |i_0i_1.. Using this notation simplifies our example: $$ -\begin{bmatrix} x_0 \\\ x_1 \\\ x_2 \\\ x_3 \end{bmatrix} = +\begin{bmatrix} x_0 \\ x_1 \\ x_2 \\ x_3 \end{bmatrix} = x_0|00\rangle + x_1|01\rangle + x_2|10\rangle + x_3|11\rangle $$ diff --git a/katas/content/multi_qubit_systems/prepare_basis_state/index.md b/katas/content/multi_qubit_systems/prepare_basis_state/index.md index 6e6c932834..280ef14c15 100644 --- a/katas/content/multi_qubit_systems/prepare_basis_state/index.md +++ b/katas/content/multi_qubit_systems/prepare_basis_state/index.md @@ -1,3 +1,3 @@ -**Input:** A two-qubit system in the basis state $|00\rangle = \begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 0 \end{bmatrix}$. +**Input:** A two-qubit system in the basis state $|00\rangle = \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix}$. -**Goal:** Transform the system into the basis state $|11\rangle = \begin{bmatrix} 0 \\\ 0 \\\ 0 \\\ 1 \end{bmatrix}$. +**Goal:** Transform the system into the basis state $|11\rangle = \begin{bmatrix} 0 \\ 0 \\ 0 \\ 1 \end{bmatrix}$. diff --git a/katas/content/multi_qubit_systems/prepare_basis_state/solution.md b/katas/content/multi_qubit_systems/prepare_basis_state/solution.md index a220494a7e..db1555508a 100644 --- a/katas/content/multi_qubit_systems/prepare_basis_state/solution.md +++ b/katas/content/multi_qubit_systems/prepare_basis_state/solution.md @@ -1,8 +1,8 @@ ο»ΏThe starting state can be represented as follows: -$$ \begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 0 \end{bmatrix} = |0\rangle \otimes |0\rangle $$ +$$ \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix} = |0\rangle \otimes |0\rangle $$ The goal state can be represented as follows: -$$ \begin{bmatrix} 0 \\\ 0 \\\ 0 \\\ 1 \end{bmatrix} = |1\rangle \otimes |1\rangle $$ +$$ \begin{bmatrix} 0 \\ 0 \\ 0 \\ 1 \end{bmatrix} = |1\rangle \otimes |1\rangle $$ Applying an **X** gate to a qubit in the $|0\rangle$ state transforms the qubit state into the $|1\rangle$ state. So, if we apply the **X** gate on the first qubit and the second qubit, we get the desired state. diff --git a/katas/content/multi_qubit_systems/prepare_superposition/index.md b/katas/content/multi_qubit_systems/prepare_superposition/index.md index a5295a64ad..22e56805f9 100644 --- a/katas/content/multi_qubit_systems/prepare_superposition/index.md +++ b/katas/content/multi_qubit_systems/prepare_superposition/index.md @@ -1,8 +1,8 @@ -**Input:** A two-qubit system in the basis state $|00\rangle = \begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 0 \end{bmatrix}$. +**Input:** A two-qubit system in the basis state $|00\rangle = \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix}$. -**Goal:** Transform the system into the state $\frac{1}{\sqrt2}\big(|00\rangle - |01\rangle\big) = \frac{1}{\sqrt2}\begin{bmatrix} 1 \\\ -1 \\\ 0 \\\ 0 \end{bmatrix}$. +**Goal:** Transform the system into the state $\frac{1}{\sqrt2}\big(|00\rangle - |01\rangle\big) = \frac{1}{\sqrt2}\begin{bmatrix} 1 \\ -1 \\ 0 \\ 0 \end{bmatrix}$.
Need a hint? - Represent the target state as a tensor product $|0\rangle \otimes \frac{1}{\sqrt2}\big(|0\rangle - |1\rangle\big) = \begin{bmatrix} 1 \\\ 0 \end{bmatrix} \otimes \frac{1}{\sqrt2}\begin{bmatrix} 1 \\\ -1 \end{bmatrix}$. + Represent the target state as a tensor product $|0\rangle \otimes \frac{1}{\sqrt2}\big(|0\rangle - |1\rangle\big) = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \otimes \frac{1}{\sqrt2}\begin{bmatrix} 1 \\ -1 \end{bmatrix}$.
diff --git a/katas/content/multi_qubit_systems/prepare_superposition/solution.md b/katas/content/multi_qubit_systems/prepare_superposition/solution.md index 35d3638ee8..ccfd637db8 100644 --- a/katas/content/multi_qubit_systems/prepare_superposition/solution.md +++ b/katas/content/multi_qubit_systems/prepare_superposition/solution.md @@ -1,16 +1,16 @@ ο»ΏWe begin in the same state as the previous exercise: -$$ \begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 0 \end{bmatrix} = \begin{bmatrix} 1 \\\ 0 \end{bmatrix} \otimes \begin{bmatrix} 1 \\\ 0 \end{bmatrix} = |0\rangle \otimes |0\rangle$$ +$$ \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix} = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \otimes \begin{bmatrix} 1 \\ 0 \end{bmatrix} = |0\rangle \otimes |0\rangle$$ The goal state can be separated as follows: -$$ \frac{1}{\sqrt2} \begin{bmatrix} 1 \\\ -1 \\\ 0 \\\ 0 \end{bmatrix} = \begin{bmatrix} 1 \\\ 0 \end{bmatrix} \otimes \frac{1}{\sqrt2}\begin{bmatrix} 1 \\\ -1 \end{bmatrix} = |0\rangle \otimes \frac{1}{\sqrt2}\big(|0\rangle - |1\rangle\big)$$ +$$ \frac{1}{\sqrt2} \begin{bmatrix} 1 \\ -1 \\ 0 \\ 0 \end{bmatrix} = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \otimes \frac{1}{\sqrt2}\begin{bmatrix} 1 \\ -1 \end{bmatrix} = |0\rangle \otimes \frac{1}{\sqrt2}\big(|0\rangle - |1\rangle\big)$$ -This means that the first qubit is already in the state we want it to be, but the second qubit needs to be transformed from the $ \begin{bmatrix} 1 \\\ 0 \end{bmatrix} $ into $ \frac{1}{\sqrt{2}}\begin{bmatrix} 1 \\\ -1\end{bmatrix}$ state. +This means that the first qubit is already in the state we want it to be, but the second qubit needs to be transformed from the $ \begin{bmatrix} 1 \\ 0 \end{bmatrix} $ into $ \frac{1}{\sqrt{2}}\begin{bmatrix} 1 \\ -1\end{bmatrix}$ state. First, we apply the **X** gate to the second qubit; this performs the following transformation: -$$ X |0\rangle = \begin{bmatrix}0 & 1 \\\ 1 & 0 \end{bmatrix} \cdot \begin{bmatrix}1 \\\ 0 \end{bmatrix} = \begin{bmatrix} 0 \\\ 1 \end{bmatrix} = |1\rangle $$ +$$ X |0\rangle = \begin{bmatrix}0 & 1 \\ 1 & 0 \end{bmatrix} \cdot \begin{bmatrix}1 \\ 0 \end{bmatrix} = \begin{bmatrix} 0 \\ 1 \end{bmatrix} = |1\rangle $$ Second, we apply the **H** gate to the second qubit; this transforms its state into the desired one: -$$ H|1\rangle = \frac{1}{\sqrt2}\begin{bmatrix} 1 & 1 \\\ 1 & -1 \end{bmatrix} \cdot \begin{bmatrix} 0 \\\ 1 \end{bmatrix} = \frac{1}{\sqrt2}\begin{bmatrix} 1 \\\ -1 \end{bmatrix}$$ +$$ H|1\rangle = \frac{1}{\sqrt2}\begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix} \cdot \begin{bmatrix} 0 \\ 1 \end{bmatrix} = \frac{1}{\sqrt2}\begin{bmatrix} 1 \\ -1 \end{bmatrix}$$ @[solution]({ "id": "multi_qubit_systems__prepare_superposition_solution", diff --git a/katas/content/multi_qubit_systems/prepare_with_complex/index.md b/katas/content/multi_qubit_systems/prepare_with_complex/index.md index 343d0bc03a..3640c32d1d 100644 --- a/katas/content/multi_qubit_systems/prepare_with_complex/index.md +++ b/katas/content/multi_qubit_systems/prepare_with_complex/index.md @@ -1,9 +1,9 @@ -**Input:** A two-qubit system in the basis state $|00\rangle = \begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 0 \end{bmatrix}$. +**Input:** A two-qubit system in the basis state $|00\rangle = \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix}$. -**Goal:** Transform the system into the state $\frac{1}{2}\big(|00\rangle + e^{i\pi/4}|01\rangle + e^{i\pi/2}|10\rangle + e^{3i\pi/4}|11\rangle\big) = \frac{1}{2}\begin{bmatrix} 1 \\\ e^{i\pi/4} \\\ e^{i\pi/2} \\\ e^{3i\pi/4} \end{bmatrix}$. +**Goal:** Transform the system into the state $\frac{1}{2}\big(|00\rangle + e^{i\pi/4}|01\rangle + e^{i\pi/2}|10\rangle + e^{3i\pi/4}|11\rangle\big) = \frac{1}{2}\begin{bmatrix} 1 \\ e^{i\pi/4} \\ e^{i\pi/2} \\ e^{3i\pi/4} \end{bmatrix}$.
Need a hint? - Represent the target state as a tensor product $\frac{1}{\sqrt2}\big(|0\rangle + e^{i\pi/2}|1\rangle\big) \otimes \frac{1}{\sqrt2}\big(|0\rangle + e^{i\pi/4}|1\rangle\big) = \frac{1}{\sqrt2} \begin{bmatrix} 1 \\\ e^{i\pi/2} \end{bmatrix} \otimes \frac{1}{\sqrt2}\begin{bmatrix} 1 \\\ e^{i\pi/4} \end{bmatrix}$. + Represent the target state as a tensor product $\frac{1}{\sqrt2}\big(|0\rangle + e^{i\pi/2}|1\rangle\big) \otimes \frac{1}{\sqrt2}\big(|0\rangle + e^{i\pi/4}|1\rangle\big) = \frac{1}{\sqrt2} \begin{bmatrix} 1 \\ e^{i\pi/2} \end{bmatrix} \otimes \frac{1}{\sqrt2}\begin{bmatrix} 1 \\ e^{i\pi/4} \end{bmatrix}$.
diff --git a/katas/content/multi_qubit_systems/prepare_with_complex/solution.md b/katas/content/multi_qubit_systems/prepare_with_complex/solution.md index fd4124d942..96162bf8c0 100644 --- a/katas/content/multi_qubit_systems/prepare_with_complex/solution.md +++ b/katas/content/multi_qubit_systems/prepare_with_complex/solution.md @@ -1,24 +1,24 @@ ο»ΏThe start state is the same as the previous exercises: -$$ \begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 0 \end{bmatrix} = \begin{bmatrix} 1 \\\ 0 \end{bmatrix} \otimes \begin{bmatrix} 1 \\\ 0 \end{bmatrix} = |0\rangle \otimes |0\rangle $$ +$$ \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix} = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \otimes \begin{bmatrix} 1 \\ 0 \end{bmatrix} = |0\rangle \otimes |0\rangle $$ The goal state, factored as a tensor product, looks like this (remember that $e^{3i\pi/4} = e^{i\pi/4} e^{i\pi/2}$): $$ -\frac{1}{2}\begin{bmatrix} 1 \\\ e^{i\pi/4} \\\ e^{i\pi/2} \\\ e^{3i\pi/4} \end{bmatrix} = -\frac{1}{\sqrt2} \begin{bmatrix} 1 \\\ e^{i\pi/2} \end{bmatrix} \otimes \frac{1}{\sqrt2}\begin{bmatrix} 1 \\\ e^{i\pi/4} \end{bmatrix} = +\frac{1}{2}\begin{bmatrix} 1 \\ e^{i\pi/4} \\ e^{i\pi/2} \\ e^{3i\pi/4} \end{bmatrix} = +\frac{1}{\sqrt2} \begin{bmatrix} 1 \\ e^{i\pi/2} \end{bmatrix} \otimes \frac{1}{\sqrt2}\begin{bmatrix} 1 \\ e^{i\pi/4} \end{bmatrix} = \frac{1}{\sqrt2}\big(|0\rangle + e^{i\pi/2}|1\rangle\big) \otimes \frac{1}{\sqrt2}\big(|0\rangle + e^{i\pi/4}|1\rangle\big) $$ We will again need to adjust the states of both qubits independently. -For the first qubit, we'll start by applying the **H** gate, getting the state $\frac{1}{\sqrt2} \begin{bmatrix} 1 \\\ 1 \end{bmatrix}$, as we've seen in the previous task. Afterwards we'll apply the **S** gate with the following result: +For the first qubit, we'll start by applying the **H** gate, getting the state $\frac{1}{\sqrt2} \begin{bmatrix} 1 \\ 1 \end{bmatrix}$, as we've seen in the previous task. Afterwards we'll apply the **S** gate with the following result: -$$ \begin{bmatrix} 1 & 0 \\\ 0 & i \end{bmatrix} \cdot \frac{1}{\sqrt2} \begin{bmatrix} 1 \\\ 1 \end{bmatrix} = \frac{1}{\sqrt2} \begin{bmatrix} 1 \\\ i \end{bmatrix}$$ +$$ \begin{bmatrix} 1 & 0 \\ 0 & i \end{bmatrix} \cdot \frac{1}{\sqrt2} \begin{bmatrix} 1 \\ 1 \end{bmatrix} = \frac{1}{\sqrt2} \begin{bmatrix} 1 \\ i \end{bmatrix}$$ If we recall that $i = e^{i\pi/2}$, we can write the final state of the first qubit as: -$$ \frac{1}{\sqrt2} \begin{bmatrix} 1 \\\ e^{i\pi/2} \end{bmatrix} $$ +$$ \frac{1}{\sqrt2} \begin{bmatrix} 1 \\ e^{i\pi/2} \end{bmatrix} $$ For the second qubit. we'll apply the **H** gate, followed by the **T** gate, with the following result: -$$ \begin{bmatrix} 1 & 0 \\\ 0 & e^{i\pi/4} \end{bmatrix} \cdot \frac{1}{\sqrt2} \begin{bmatrix} 1 \\\ 1 \end{bmatrix} = \frac{1}{\sqrt2} \begin{bmatrix} 1 \\\ e^{i\pi/4} \end{bmatrix} $$ +$$ \begin{bmatrix} 1 & 0 \\ 0 & e^{i\pi/4} \end{bmatrix} \cdot \frac{1}{\sqrt2} \begin{bmatrix} 1 \\ 1 \end{bmatrix} = \frac{1}{\sqrt2} \begin{bmatrix} 1 \\ e^{i\pi/4} \end{bmatrix} $$ @[solution]({ "id": "multi_qubit_systems__prepare_with_complex_solution", diff --git a/katas/content/multi_qubit_systems/prepare_with_real/index.md b/katas/content/multi_qubit_systems/prepare_with_real/index.md index 46f834f5f2..1c47480691 100644 --- a/katas/content/multi_qubit_systems/prepare_with_real/index.md +++ b/katas/content/multi_qubit_systems/prepare_with_real/index.md @@ -1,9 +1,9 @@ -**Input:** A two-qubit system in the basis state $|00\rangle = \begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 0 \end{bmatrix}$. +**Input:** A two-qubit system in the basis state $|00\rangle = \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix}$. -**Goal:** Transform the system into the state $\frac{1}{2}\big(|00\rangle - |01\rangle + |10\rangle - |11\rangle\big) = \frac{1}{2}\begin{bmatrix} 1 \\\ -1 \\\ 1 \\\ -1 \end{bmatrix}$. +**Goal:** Transform the system into the state $\frac{1}{2}\big(|00\rangle - |01\rangle + |10\rangle - |11\rangle\big) = \frac{1}{2}\begin{bmatrix} 1 \\ -1 \\ 1 \\ -1 \end{bmatrix}$.
Need a hint? - Represent the target state as a tensor product $\frac{1}{\sqrt2}\big(|0\rangle + |1\rangle\big) \otimes \frac{1}{\sqrt2}\big(|0\rangle - |1\rangle\big) = \frac{1}{\sqrt2} \begin{bmatrix} 1 \\\ 1 \end{bmatrix} \otimes \frac{1}{\sqrt2}\begin{bmatrix} 1 \\\ -1 \end{bmatrix}$. + Represent the target state as a tensor product $\frac{1}{\sqrt2}\big(|0\rangle + |1\rangle\big) \otimes \frac{1}{\sqrt2}\big(|0\rangle - |1\rangle\big) = \frac{1}{\sqrt2} \begin{bmatrix} 1 \\ 1 \end{bmatrix} \otimes \frac{1}{\sqrt2}\begin{bmatrix} 1 \\ -1 \end{bmatrix}$.
diff --git a/katas/content/multi_qubit_systems/prepare_with_real/solution.md b/katas/content/multi_qubit_systems/prepare_with_real/solution.md index 1b3b0613cd..ab0c8dd382 100644 --- a/katas/content/multi_qubit_systems/prepare_with_real/solution.md +++ b/katas/content/multi_qubit_systems/prepare_with_real/solution.md @@ -1,10 +1,10 @@ ο»ΏAgain, to start we will represent the goal state as a tensor product of single-qubit states; this gives us the following representation: -$$ \frac{1}{2}\big(|00\rangle - |01\rangle + |10\rangle - |11\rangle\big) = \frac{1}{2}\begin{bmatrix} 1 \\\ -1 \\\ 1 \\\ -1 \end{bmatrix} = \frac{1}{\sqrt2} \begin{bmatrix} 1 \\\ 1 \end{bmatrix} \otimes \frac{1}{\sqrt2}\begin{bmatrix} 1 \\\ -1 \end{bmatrix} = \frac{1}{\sqrt2}\big(|0\rangle + |1\rangle\big) \otimes \frac{1}{\sqrt2}\big(|0\rangle - |1\rangle\big) $$ +$$ \frac{1}{2}\big(|00\rangle - |01\rangle + |10\rangle - |11\rangle\big) = \frac{1}{2}\begin{bmatrix} 1 \\ -1 \\ 1 \\ -1 \end{bmatrix} = \frac{1}{\sqrt2} \begin{bmatrix} 1 \\ 1 \end{bmatrix} \otimes \frac{1}{\sqrt2}\begin{bmatrix} 1 \\ -1 \end{bmatrix} = \frac{1}{\sqrt2}\big(|0\rangle + |1\rangle\big) \otimes \frac{1}{\sqrt2}\big(|0\rangle - |1\rangle\big) $$ This time we need to transform both the first and the second qubits. Let's start with the first qubit. Applying the **H** gate transforms its state as follows: -$$ H|0\rangle = \frac{1}{\sqrt2}\begin{bmatrix} 1 & 1 \\\ 1 & -1 \end{bmatrix} \cdot \begin{bmatrix} 1 \\\ 0 \end{bmatrix} = \frac{1}{\sqrt2} \begin{bmatrix} 1 \\\ 1 \end{bmatrix} = \frac{1}{\sqrt2}\big(|0\rangle + |1\rangle\big)$$ +$$ H|0\rangle = \frac{1}{\sqrt2}\begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix} \cdot \begin{bmatrix} 1 \\ 0 \end{bmatrix} = \frac{1}{\sqrt2} \begin{bmatrix} 1 \\ 1 \end{bmatrix} = \frac{1}{\sqrt2}\big(|0\rangle + |1\rangle\big)$$ For the second qubit we can use the same transformation we've seen in the "Prepare a Superposition of Two Basis States" exercise; this will give the desired end state. diff --git a/katas/content/oracles/index.md b/katas/content/oracles/index.md index a620fffcc2..7a0c355048 100644 --- a/katas/content/oracles/index.md +++ b/katas/content/oracles/index.md @@ -55,7 +55,7 @@ An oracle in the quantum world is a "black box" operation that is used as input Many quantum algorithms assume an oracle implementation of some classical function as input, but this is a very strong assumption - sometimes implementing the oracle for a function is a lot more complex than the algorithm that will use this oracle! In this kata, you will learn the properties of quantum oracles and how to implement them. -A quantum oracle implements a function $f: \\{0,1\\}^n \rightarrow \\{0,1\\}^m$, where the input is $n$-bits of the form $x = (x_{0}, x_{1}, \dots, x_{n-1})$. In most commonly used cases $m=1$, that is, the function can return values $0$ or $1$. In this kata, we will focus on this class of functions. +A quantum oracle implements a function $f: \{0,1\}^n \rightarrow \{0,1\}^m$, where the input is $n$-bits of the form $x = (x_{0}, x_{1}, \dots, x_{n-1})$. In most commonly used cases $m=1$, that is, the function can return values $0$ or $1$. In this kata, we will focus on this class of functions. Quantum oracles operate on qubit arrays (and can take classical parameters as well). The classical input is encoded into the state of an $n$-qubit register: $$|\vec{x}\rangle = |x_0\rangle \otimes |x_1\rangle \otimes ... \otimes |x_{n-1}\rangle,$$ @@ -73,7 +73,7 @@ There are two types of quantum oracles: phase oracles and marking oracles. Let' "title": "Phase Oracles" }) -For a function $f: \\{0,1\\}^n \rightarrow \\{0,1\\}$, the phase oracle $U_{\text{phase}}$ encodes the values of the function $f$ in the *relative phases* of basis states. When provided an input basis state $|\vec{x}\rangle$, it flips the sign of that state if $f(x)=1$: +For a function $f: \{0,1\}^n \rightarrow \{0,1\}$, the phase oracle $U_{\text{phase}}$ encodes the values of the function $f$ in the *relative phases* of basis states. When provided an input basis state $|\vec{x}\rangle$, it flips the sign of that state if $f(x)=1$: $$U_{phase} |\vec{x}\rangle = (-1)^{f(x)}|\vec{x}\rangle$$ @@ -186,7 +186,7 @@ $$U_{mark} |x\rangle |-\rangle = \frac1{\sqrt2} \big(U_{mark}|x\rangle|0\rangle $$= \frac1{\sqrt2} \big(|x\rangle|0\oplus f(x)\rangle - |x\rangle |1\oplus f(x)\rangle\big) =$$ $$=\begin{cases} -\frac1{\sqrt2} \big(|x\rangle|0\rangle - |x\rangle |1\rangle\big) = |x\rangle|-\rangle \text{ if } f(x) = 0 \\\\ +\frac1{\sqrt2} \big(|x\rangle|0\rangle - |x\rangle |1\rangle\big) = |x\rangle|-\rangle \text{ if } f(x) = 0 \\ \frac1{\sqrt2} \big(|x\rangle|1\rangle - |x\rangle |0\rangle\big) = -|x\rangle|-\rangle \text{ if } f(x) = 1 \end{cases}=$$ diff --git a/katas/content/qec_shor/index.md b/katas/content/qec_shor/index.md index 909bb268ec..d7ccc512ff 100644 --- a/katas/content/qec_shor/index.md +++ b/katas/content/qec_shor/index.md @@ -71,7 +71,7 @@ We introduced the single-qubit measurements in different Pauli bases in the Meas and then the general case of joint measurements in the Measurements in Multi-Qubit Systems kata. Let's take a closer look at the kinds of joint measurements we'll be using in this kata. -A multi-qubit Pauli measurement on $n$ qubits corresponds to an operator $M_1 \otimes \dotsc \otimes M_n$, with each $M_j$ being from the set of gates $\\{X,Y,Z,I\\}$, and at least one of the $M_j$ is not the identity matrix. (If $M_j = I$, you can think of it as qubit $j$ not being involved in the measurement.) The measurement can produce one of the two outcomes: `Zero` corresponding to eigenvalue $+1$ of this operator, or `One` corresponding to the eigenvalue $-1$. The corresponding projection operators are the projections onto the corresponding eigenspaces. The operator $M_1 \otimes \dotsc \otimes M_n$ is referred to as the _measurement basis_. +A multi-qubit Pauli measurement on $n$ qubits corresponds to an operator $M_1 \otimes \dotsc \otimes M_n$, with each $M_j$ being from the set of gates $\{X,Y,Z,I\}$, and at least one of the $M_j$ is not the identity matrix. (If $M_j = I$, you can think of it as qubit $j$ not being involved in the measurement.) The measurement can produce one of the two outcomes: `Zero` corresponding to eigenvalue $+1$ of this operator, or `One` corresponding to the eigenvalue $-1$. The corresponding projection operators are the projections onto the corresponding eigenspaces. The operator $M_1 \otimes \dotsc \otimes M_n$ is referred to as the _measurement basis_. For example, the first two joint measurements we'll encounter later in this kata are two-qubit measurements in $ZZ$ and $XX$ bases. They can be described as follows: @@ -214,7 +214,7 @@ However, if a $Z$ error happens on any one of these qubits, we won't be able to "title": "Phase Flip Code" }) -What kind of code could detect and correct a $Z$ error? We detected an $X$ error using the fact that in the $\\{\ket{0}, \ket{1}\\}$ basis the error changed the basis state. Similarly, we can detect a $Z$ error using the $\\{\ket{+}, \ket{-}\\}$ basis, in which the $Z$ gate converts $\ket{+}$ to $\ket{-}$ and vice versa, acting as a basis change operation. +What kind of code could detect and correct a $Z$ error? We detected an $X$ error using the fact that in the $\{\ket{0}, \ket{1}\}$ basis the error changed the basis state. Similarly, we can detect a $Z$ error using the $\{\ket{+}, \ket{-}\}$ basis, in which the $Z$ gate converts $\ket{+}$ to $\ket{-}$ and vice versa, acting as a basis change operation. Based on this idea, we can construct the **phase flip code** that uses the following encoding: diff --git a/katas/content/qubit/index.md b/katas/content/qubit/index.md index 6984646d1e..379d11f14d 100644 --- a/katas/content/qubit/index.md +++ b/katas/content/qubit/index.md @@ -35,7 +35,7 @@ The basic building block of a classical computer is the bit - a single memory ce The state of a qubit is represented by a complex vector of size 2: -$$\begin{bmatrix} \alpha \\\ \beta \end{bmatrix}$$ +$$\begin{bmatrix} \alpha \\ \beta \end{bmatrix}$$ Here $\alpha$ and $\beta$ are complex numbers. $\alpha$ represents how "close" the qubit is to state $0$, and $\beta$ represents how "close" the qubit is to state $1$. This vector is normalized: $|\alpha|^2 + |\beta|^2 = 1$. $\alpha$ and $\beta$ are known as the probability amplitudes of states $0$ and $1$, respectively. @@ -44,18 +44,18 @@ $\alpha$ and $\beta$ are known as the probability amplitudes of states $0$ and $ A qubit in state $0$ would be represented by the following vector: -$$\begin{bmatrix} 1 \\\ 0 \end{bmatrix}$$ +$$\begin{bmatrix} 1 \\ 0 \end{bmatrix}$$ Likewise, a qubit in state $1$ would be represented by this vector: -$$\begin{bmatrix} 0 \\\ 1 \end{bmatrix}$$ +$$\begin{bmatrix} 0 \\ 1 \end{bmatrix}$$ -Note that you can use scalar multiplication and vector addition to express any qubit state $\begin{bmatrix} \alpha \\\ \beta \end{bmatrix}$ as a sum of these two vectors with certain weights $\alpha$ and $\beta$, known as linear combination. +Note that you can use scalar multiplication and vector addition to express any qubit state $\begin{bmatrix} \alpha \\ \beta \end{bmatrix}$ as a sum of these two vectors with certain weights $\alpha$ and $\beta$, known as linear combination. $$ -\begin{bmatrix} \alpha \\\ \beta \\end{bmatrix} = -\begin{bmatrix} \alpha \\\ 0 \end{bmatrix} + \begin{bmatrix} 0 \\\ \beta \\end{bmatrix} = -\alpha \cdot \begin{bmatrix} 1 \\\ 0 \end{bmatrix} + \beta \cdot \begin{bmatrix} 0 \\\ 1 \end{bmatrix} +\begin{bmatrix} \alpha \\ \beta \end{bmatrix} = +\begin{bmatrix} \alpha \\ 0 \end{bmatrix} + \begin{bmatrix} 0 \\ \beta \end{bmatrix} = +\alpha \cdot \begin{bmatrix} 1 \\ 0 \end{bmatrix} + \beta \cdot \begin{bmatrix} 0 \\ 1 \end{bmatrix} $$ Because of this, qubit states $0$ and $1$ are known as basis states. These two vectors have two properties. @@ -63,31 +63,31 @@ Because of this, qubit states $0$ and $1$ are known as basis states. These two v 1. They are normalized. $$ -\langle \begin{bmatrix} 1 \\\ 0 \end{bmatrix} , \begin{bmatrix} 1 \\\ 0 \end{bmatrix} \rangle = -\langle \begin{bmatrix} 0 \\\ 1 \end{bmatrix} , \begin{bmatrix} 0 \\\ 1 \end{bmatrix} \rangle = 1 +\langle \begin{bmatrix} 1 \\ 0 \end{bmatrix} , \begin{bmatrix} 1 \\ 0 \end{bmatrix} \rangle = +\langle \begin{bmatrix} 0 \\ 1 \end{bmatrix} , \begin{bmatrix} 0 \\ 1 \end{bmatrix} \rangle = 1 $$ 2. They are orthogonal to each other. $$ -\langle \begin{bmatrix} 1 \\\ 0 \end{bmatrix} , \begin{bmatrix} 0 \\\ 1 \end{bmatrix} \rangle = -\langle \begin{bmatrix} 0 \\\ 1 \end{bmatrix} , \begin{bmatrix} 1 \\\ 0 \end{bmatrix} \\rangle = 0 +\langle \begin{bmatrix} 1 \\ 0 \end{bmatrix} , \begin{bmatrix} 0 \\ 1 \end{bmatrix} \rangle = +\langle \begin{bmatrix} 0 \\ 1 \end{bmatrix} , \begin{bmatrix} 1 \\ 0 \end{bmatrix} \rangle = 0 $$ > As a reminder, $\langle V , W \rangle$ is the inner product of $V$ and $W$. -This means that these vectors form an **orthonormal basis**. The basis of $\begin{bmatrix} 1 \\\ 0 \end{bmatrix}$ and $\begin{bmatrix} 0 \\\ 1 \end{bmatrix}$ is called the **computational basis**, also known as the **canonical basis**. +This means that these vectors form an **orthonormal basis**. The basis of $\begin{bmatrix} 1 \\ 0 \end{bmatrix}$ and $\begin{bmatrix} 0 \\ 1 \end{bmatrix}$ is called the **computational basis**, also known as the **canonical basis**. > There exist other orthonormal bases, for example, the **Hadamard basis**, formed by the vectors > -> $$\begin{bmatrix} \frac{1}{\sqrt{2}} \\\ \frac{1}{\sqrt{2}} \end{bmatrix} \text{ and } \begin{bmatrix} \frac{1}{\sqrt{2}} \\\ -\frac{1}{\sqrt{2}} \end{bmatrix}$$ +> $$\begin{bmatrix} \frac{1}{\sqrt{2}} \\ \frac{1}{\sqrt{2}} \end{bmatrix} \text{ and } \begin{bmatrix} \frac{1}{\sqrt{2}} \\ -\frac{1}{\sqrt{2}} \end{bmatrix}$$ > > You can check that these vectors are normalized, and orthogonal to each other. Any qubit state can be expressed as a linear combination of these vectors: > > $$ -> \begin{bmatrix} \alpha \\\ \beta \end{bmatrix} = -> \frac{\alpha + \beta}{\sqrt{2}} \begin{bmatrix} \frac{1}{\sqrt{2}} \\\ \frac{1}{\sqrt{2}} \end{bmatrix} + -> \frac{\alpha - \beta}{\sqrt{2}} \begin{bmatrix} \frac{1}{\sqrt{2}} \\\ -\frac{1}{\sqrt{2}} \end{bmatrix} +> \begin{bmatrix} \alpha \\ \beta \end{bmatrix} = +> \frac{\alpha + \beta}{\sqrt{2}} \begin{bmatrix} \frac{1}{\sqrt{2}} \\ \frac{1}{\sqrt{2}} \end{bmatrix} + +> \frac{\alpha - \beta}{\sqrt{2}} \begin{bmatrix} \frac{1}{\sqrt{2}} \\ -\frac{1}{\sqrt{2}} \end{bmatrix} > $$ > > The Hadamard basis is widely used in quantum computing, for example, in the BB84 quantum key distribution protocol. @@ -101,14 +101,14 @@ Dirac notation is a shorthand notation that eases writing quantum states and com - - + +
$$|0\rangle = \begin{bmatrix} 1 \\\ 0 \end{bmatrix}$$$$|1\rangle = \begin{bmatrix} 0 \\\ 1 \end{bmatrix}$$$$|0\rangle = \begin{bmatrix} 1 \\ 0 \end{bmatrix}$$$$|1\rangle = \begin{bmatrix} 0 \\ 1 \end{bmatrix}$$
These two kets represent basis states, so they can be used to represent any other state: -$$\begin{bmatrix} \alpha \\\ \beta \end{bmatrix} = \alpha|0\rangle + \beta|1\rangle$$ +$$\begin{bmatrix} \alpha \\ \beta \end{bmatrix} = \alpha|0\rangle + \beta|1\rangle$$ Dirac notation is not only restricted to vectors $0$ and $1$; it can be used to represent any vector, similar to how variable names are used in algebra. For example, we can call the state above "the state $\psi$" and write it as: @@ -134,13 +134,13 @@ We will learn more about Dirac notation in the next katas, as we introduce quant "title": "Relative and Global Phase" }) -Complex numbers have a parameter called the phase. If a complex number $z = x + iy$ is written in polar form $z = re^{i\theta}$, its phase is $\theta$, where $\theta = \atan2(y, x)$. +Complex numbers have a parameter called the phase. If a complex number $z = x + iy$ is written in polar form $z = re^{i\theta}$, its phase is $\theta$, where $\theta = atan2(y, x)$. > `atan2` is a useful function available in most programming languages. It takes two arguments and returns an angle $\theta$ > between $-\pi$ and $\pi$ that has $\cos \theta = x$ and $\sin \theta = y$. Unlike using $\tan^{-1}(\frac{y}{x})$, `atan2` computes > the correct quadrant for the angle, since it preserves information about the signs of both sine and cosine of the angle. -The probability amplitudes $\alpha$ and $\beta$ are complex numbers, therefore $\alpha$ and $\beta$ have a phase. For example, consider a qubit in state $\frac{1 + i}{2}|0\rangle + \frac{1 - i}{2}|1\rangle$. If you do the math, you see that the phase of $|0\rangle$ is $\atan2(\frac12, \frac12) = \frac{\pi}{4}$, and the phase of $|1\rangle$ is $\atan2(\frac12, -\frac12) = -\frac{\pi}{4}$. The difference between these two phases is known as **relative phase**. +The probability amplitudes $\alpha$ and $\beta$ are complex numbers, therefore $\alpha$ and $\beta$ have a phase. For example, consider a qubit in state $\frac{1 + i}{2}|0\rangle + \frac{1 - i}{2}|1\rangle$. If you do the math, you see that the phase of $|0\rangle$ is $atan2(\frac12, \frac12) = \frac{\pi}{4}$, and the phase of $|1\rangle$ is $atan2(\frac12, -\frac12) = -\frac{\pi}{4}$. The difference between these two phases is known as **relative phase**. Multiplying the state of the entire system by $e^{i\theta}$ doesn't affect the relative phase: $\alpha|0\rangle + \beta|1\rangle$ has the same relative phase as $e^{i\theta}\big(\alpha|0\rangle + \beta|1\rangle\big)$. In the second expression, $\theta$ is known as the system's **global phase**. @@ -168,7 +168,7 @@ Before we continue, let's learn some techniques to visualize the quantum state o Let's start with a simple scenario: a program that acts on a single qubit. The state of the quantum system used by this program can be represented as a complex vector of length 2, or, using Dirac notation, -$$\begin{bmatrix} \alpha \\\ \beta \end{bmatrix} = \alpha|0\rangle + \beta|1\rangle$$ +$$\begin{bmatrix} \alpha \\ \beta \end{bmatrix} = \alpha|0\rangle + \beta|1\rangle$$ If this program runs on a physical quantum system, there is no way to get the information about the values of $\alpha$ and $\beta$ at a certain point of the program execution from a single observation. You would need to run the program repeatedly up to this point, perform a measurement on the system, and aggregate the results of multiple measurements to estimate $\alpha$ and $\beta$. diff --git a/katas/content/random_numbers/index.md b/katas/content/random_numbers/index.md index baad4b2f61..43610606f2 100644 --- a/katas/content/random_numbers/index.md +++ b/katas/content/random_numbers/index.md @@ -21,11 +21,11 @@ The quantum algorithm for random number generation is one of the simplest applic @[section]({"id": "random_numbers__introduction", "title": "Introduction"}) -Recall from the Qubit kata that a qubit state $|\psi\rangle$ is defined via the basis states $|0\rangle$ and $|1\rangle$ as $|\psi\rangle = \begin{bmatrix} \alpha \\\ \beta \end{bmatrix} = \alpha|0\rangle + \beta|1\rangle$, where $|\alpha|^2 + |\beta|^2 = 1$. +Recall from the Qubit kata that a qubit state $|\psi\rangle$ is defined via the basis states $|0\rangle$ and $|1\rangle$ as $|\psi\rangle = \begin{bmatrix} \alpha \\ \beta \end{bmatrix} = \alpha|0\rangle + \beta|1\rangle$, where $|\alpha|^2 + |\beta|^2 = 1$. -We call $\alpha$ and $\beta$ the probability amplitudes of states $|0\rangle$ and $|1\rangle$, respectively. When $|\psi\rangle$ is measured in the $\\{|0\rangle, |1\rangle\\}$ basis (the computational basis), the probabilities of the outcomes are defined based on the state amplitudes: there is a $|\alpha|^2$ probability that the measurement result will be $0$, and a $|\beta|^2$ probability that the measurement result will be $1$. +We call $\alpha$ and $\beta$ the probability amplitudes of states $|0\rangle$ and $|1\rangle$, respectively. When $|\psi\rangle$ is measured in the $\{|0\rangle, |1\rangle\}$ basis (the computational basis), the probabilities of the outcomes are defined based on the state amplitudes: there is a $|\alpha|^2$ probability that the measurement result will be $0$, and a $|\beta|^2$ probability that the measurement result will be $1$. -> For example, a qubit in state $\begin{bmatrix} \frac{1}{\sqrt{2}} \\\ \frac{1}{\sqrt{2}} \end{bmatrix}$ will yield measurement results $0$ or $1$ with equal probability, while a qubit in state $\begin{bmatrix} \frac{1}{2} \\\ \frac{\sqrt3}{2} \end{bmatrix}$ will yield measurement result $0$ only 25% of the time, and $1$ 75% of the time. +> For example, a qubit in state $\begin{bmatrix} \frac{1}{\sqrt{2}} \\ \frac{1}{\sqrt{2}} \end{bmatrix}$ will yield measurement results $0$ or $1$ with equal probability, while a qubit in state $\begin{bmatrix} \frac{1}{2} \\ \frac{\sqrt3}{2} \end{bmatrix}$ will yield measurement result $0$ only 25% of the time, and $1$ 75% of the time. This knowledge is sufficient to implement a simple random number generator! diff --git a/katas/content/random_numbers/random_bit/solution.md b/katas/content/random_numbers/random_bit/solution.md index 9bb578034a..4cdfe5cbfb 100644 --- a/katas/content/random_numbers/random_bit/solution.md +++ b/katas/content/random_numbers/random_bit/solution.md @@ -1,16 +1,16 @@ -The state of single qubit can be represented as a two-dimensional column vector $\begin{bmatrix} \alpha \\\ \beta \end{bmatrix}$, where $\alpha$ and $\beta$ are complex numbers that satisfy $|\alpha|^2 + |\beta|^2 = 1$. When we measure the qubit, we get either 0 with probability $|\alpha|^2$ or 1 with probability $|\beta|^2$. Essentially we can control probability of measurement outcome by setting the right amplitudes of basis states. +The state of single qubit can be represented as a two-dimensional column vector $\begin{bmatrix} \alpha \\ \beta \end{bmatrix}$, where $\alpha$ and $\beta$ are complex numbers that satisfy $|\alpha|^2 + |\beta|^2 = 1$. When we measure the qubit, we get either 0 with probability $|\alpha|^2$ or 1 with probability $|\beta|^2$. Essentially we can control probability of measurement outcome by setting the right amplitudes of basis states. When we allocate the qubit in Q#, amplitudes $\alpha$ and $\beta$ are 1 and 0, respectively. Now our goal is set equal amplitudes for $\alpha$ and $\beta$ for absolute randomness. We can achieve that by simply applying Hadamard gate to the initial state $|0\rangle$: $$ H|0\rangle = \frac{1}{\sqrt{2}} -\begin{bmatrix} 1 & 1 \\\ 1 & -1 \end{bmatrix} -\begin{bmatrix} 1 \\\ 0 \end{bmatrix} = +\begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix} +\begin{bmatrix} 1 \\ 0 \end{bmatrix} = \frac{1}{\sqrt{2}} -\begin{bmatrix} 1 \cdot 1 + 1 \cdot 0 \\\ 1 \cdot 1 + (-1) \cdot 0 \end{bmatrix} = +\begin{bmatrix} 1 \cdot 1 + 1 \cdot 0 \\ 1 \cdot 1 + (-1) \cdot 0 \end{bmatrix} = \frac{1}{\sqrt{2}} -\begin{bmatrix} 1 \\\ 1 \end{bmatrix} +\begin{bmatrix} 1 \\ 1 \end{bmatrix} $$ Now, both 0 and 1 measurement outcomes occur with equal probability of $|\frac{1}{\sqrt{2}}|^2 = \frac{1}{2}$. diff --git a/katas/content/single_qubit_gates/amplitude_change/solution.md b/katas/content/single_qubit_gates/amplitude_change/solution.md index 3bc695e5a5..0bf6085ad3 100644 --- a/katas/content/single_qubit_gates/amplitude_change/solution.md +++ b/katas/content/single_qubit_gates/amplitude_change/solution.md @@ -4,18 +4,18 @@ As a reminder, $$ R_{y}(\theta) = -\begin{bmatrix}\cos \frac{\theta}{2} & -\sin \frac{\theta}{2}\\\ \sin \frac{\theta}{2} & \cos \frac{\theta}{2}\end{bmatrix} +\begin{bmatrix}\cos \frac{\theta}{2} & -\sin \frac{\theta}{2}\\ \sin \frac{\theta}{2} & \cos \frac{\theta}{2}\end{bmatrix} $$ Let's see its effect on the $|0\rangle$ state: $$ R_y(\theta)|0\rangle = -\begin{bmatrix}\cos \frac{\theta}{2} & -\sin \frac{\theta}{2}\\\ \sin \frac{\theta}{2} & \cos \frac{\theta}{2} \end{bmatrix} -\begin{bmatrix}1\\\ 0\\\ \end{bmatrix}= -\begin{bmatrix}\cos \frac{\theta}{2}\cdot1 - \sin \frac{\theta}{2}\cdot0\\\ \sin \frac{\theta}{2}\cdot1 + \cos \frac{\theta}{2}\cdot0 +\begin{bmatrix}\cos \frac{\theta}{2} & -\sin \frac{\theta}{2}\\ \sin \frac{\theta}{2} & \cos \frac{\theta}{2} \end{bmatrix} +\begin{bmatrix}1\\ 0\\ \end{bmatrix}= +\begin{bmatrix}\cos \frac{\theta}{2}\cdot1 - \sin \frac{\theta}{2}\cdot0\\ \sin \frac{\theta}{2}\cdot1 + \cos \frac{\theta}{2}\cdot0 \end{bmatrix}= -\begin{bmatrix}\cos \frac{\theta}{2}\\\ \sin \frac{\theta}{2}\end{bmatrix}= +\begin{bmatrix}\cos \frac{\theta}{2}\\ \sin \frac{\theta}{2}\end{bmatrix}= \cos\frac{\theta}{2} |0\rangle + \sin\frac{\theta}{2} |1\rangle $$ @@ -25,12 +25,12 @@ Since $\cos \frac{\pi}{3} = 0.5$ and $\sin \frac{\pi}{3} = 0.8660$, working to 4 $$ R_{y}(\theta) |\psi\rangle= - \begin{bmatrix}\cos \frac{\theta}{2} & -\sin \frac{\theta}{2}\\\ \sin \frac{\theta}{2} & \cos \frac{\theta}{2} \end{bmatrix} - \begin{bmatrix}\beta\\\ \gamma\\\ \end{bmatrix}= - \begin{bmatrix}\cos \frac{\theta}{2}\cdot\beta - \sin \frac{\theta}{2}\cdot\gamma\\\ \sin \frac{\theta}{2}\cdot\beta +\cos \frac{\theta}{2}\cdot\gamma \end{bmatrix}= - \begin{bmatrix} 0.6\cdot\cos \frac{\pi}{3} -0.8\cdot\sin \frac{\pi}{3}\\\0.6\cdot\sin \frac{\pi}{3} +0.8\cdot\cos \frac{\pi}{3}\end{bmatrix}= - \begin{bmatrix}0.3 - 0.6928\\\ 0.5196 + 0.4\end{bmatrix}= -\begin{bmatrix}-0.3928\\\ 0.9196\\\ \end{bmatrix} + \begin{bmatrix}\cos \frac{\theta}{2} & -\sin \frac{\theta}{2}\\ \sin \frac{\theta}{2} & \cos \frac{\theta}{2} \end{bmatrix} + \begin{bmatrix}\beta\\ \gamma\\ \end{bmatrix}= + \begin{bmatrix}\cos \frac{\theta}{2}\cdot\beta - \sin \frac{\theta}{2}\cdot\gamma\\ \sin \frac{\theta}{2}\cdot\beta +\cos \frac{\theta}{2}\cdot\gamma \end{bmatrix}= + \begin{bmatrix} 0.6\cdot\cos \frac{\pi}{3} -0.8\cdot\sin \frac{\pi}{3}\\0.6\cdot\sin \frac{\pi}{3} +0.8\cdot\cos \frac{\pi}{3}\end{bmatrix}= + \begin{bmatrix}0.3 - 0.6928\\ 0.5196 + 0.4\end{bmatrix}= +\begin{bmatrix}-0.3928\\ 0.9196\\ \end{bmatrix} $$ Notice that we used $\frac{\theta}{2} = \alpha$; this means that in the Q# code we need to pass the angle $\theta = 2\alpha$. diff --git a/katas/content/single_qubit_gates/basis_change/solution.md b/katas/content/single_qubit_gates/basis_change/solution.md index 7ec2bd2a84..5fa9563624 100644 --- a/katas/content/single_qubit_gates/basis_change/solution.md +++ b/katas/content/single_qubit_gates/basis_change/solution.md @@ -3,17 +3,17 @@ We can recognize that the Hadamard gate changes states $|0\rangle$ and $|1\rangl As a reminder, the Hadamard gate is defined by the following matrix: $$ -\frac{1}{\sqrt{2}}\begin{bmatrix}1 & 1 \\\1 & -1\end{bmatrix} +\frac{1}{\sqrt{2}}\begin{bmatrix}1 & 1 \\1 & -1\end{bmatrix} $$ For example, we can work out $H|1\rangle$ as follows: $$ H|1\rangle= -\frac{1}{\sqrt{2}}\begin{bmatrix} 1 & 1 \\\1 & -1\end{bmatrix} -\begin{bmatrix} 0\\\ 1\end{bmatrix}= -\frac{1}{\sqrt{2}}\begin{bmatrix}1 \cdot 0 + 1 \cdot 1 \\\1 \cdot 0 + (-1) \cdot 1\end{bmatrix}= -\frac{1}{\sqrt{2}}\begin{bmatrix}1\\\ -1\\\ \end{bmatrix}= +\frac{1}{\sqrt{2}}\begin{bmatrix} 1 & 1 \\1 & -1\end{bmatrix} +\begin{bmatrix} 0\\ 1\end{bmatrix}= +\frac{1}{\sqrt{2}}\begin{bmatrix}1 \cdot 0 + 1 \cdot 1 \\1 \cdot 0 + (-1) \cdot 1\end{bmatrix}= +\frac{1}{\sqrt{2}}\begin{bmatrix}1\\ -1\\ \end{bmatrix}= \frac{1}{\sqrt{2}} \big(|0\rangle - |1\rangle\big) = |-\rangle $$ @@ -21,12 +21,12 @@ Similarly, we can consider the effect of the Hadamard gate on the superposition $$ H|\psi⟩ = -\frac{1}{\sqrt{2}}\begin{bmatrix} 1 & 1 \\\ 1 & -1 \end{bmatrix} - \begin{bmatrix} \alpha\\\ \beta\\\ \end{bmatrix} = -\frac{1}{\sqrt{2}}\begin{bmatrix} \alpha + \beta\\\ \alpha - \beta\\\ \end{bmatrix}= -0.7071\begin{bmatrix} 1.4\\\ -0.2\\\ \end{bmatrix} = +\frac{1}{\sqrt{2}}\begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix} + \begin{bmatrix} \alpha\\ \beta\\ \end{bmatrix} = +\frac{1}{\sqrt{2}}\begin{bmatrix} \alpha + \beta\\ \alpha - \beta\\ \end{bmatrix}= +0.7071\begin{bmatrix} 1.4\\ -0.2\\ \end{bmatrix} = \begin{bmatrix} - 0.98994\\\ -0.14142\\\ \end{bmatrix} = + 0.98994\\ -0.14142\\ \end{bmatrix} = 0.9899|0\rangle - 0.1414|1\rangle $$ diff --git a/katas/content/single_qubit_gates/complex_phase/solution.md b/katas/content/single_qubit_gates/complex_phase/solution.md index 299549c6d2..219f7198af 100644 --- a/katas/content/single_qubit_gates/complex_phase/solution.md +++ b/katas/content/single_qubit_gates/complex_phase/solution.md @@ -2,17 +2,17 @@ We know that: $$ R1(\alpha)= - \begin{bmatrix}1 & 0\\\0 & \color{red}{e^{i\alpha}}\end{bmatrix} + \begin{bmatrix}1 & 0 \\ 0 & \color{red}{e^{i\alpha}}\end{bmatrix} $$ So we have: $$ R1(\beta |0\rangle + \gamma |1\rangle) = - \begin{bmatrix}1 & 0 \\\0 & \color{red}{e^{i\alpha}} \end{bmatrix} - \begin{bmatrix}\beta\\\ \gamma\\\ \end{bmatrix}= -\begin{bmatrix}1 \cdot \beta + 0 \cdot \gamma\\\ 0 \cdot \beta + {\color{red}{e^{i\alpha}}} \cdot \gamma\end{bmatrix}= - \begin{bmatrix}\beta\\\ {\color{red}{e^{i\alpha}}}\gamma\end{bmatrix}= + \begin{bmatrix}1 & 0 \\ 0 & \color{red}{e^{i\alpha}} \end{bmatrix} + \begin{bmatrix}\beta \\ \gamma \\ \end{bmatrix}= +\begin{bmatrix}1 \cdot \beta + 0 \cdot \gamma \\ 0 \cdot \beta + {\color{red}{e^{i\alpha}}} \cdot \gamma \end{bmatrix}= + \begin{bmatrix}\beta \\ {\color{red}{e^{i\alpha}}} \gamma \end{bmatrix}= \beta |0\rangle + {\color{red}{e^{i\alpha}}} \gamma |1\rangle $$ diff --git a/katas/content/single_qubit_gates/global_phase_i/index.md b/katas/content/single_qubit_gates/global_phase_i/index.md index 10999c503a..8dbd008a04 100644 --- a/katas/content/single_qubit_gates/global_phase_i/index.md +++ b/katas/content/single_qubit_gates/global_phase_i/index.md @@ -1,3 +1,3 @@ -**Input:** A qubit in an arbitrary state $|\\psi\\rangle = \\alpha|0\\rangle + \\beta|1\\rangle$. +**Input:** A qubit in an arbitrary state $|\psi\rangle = \alpha|0\rangle + \beta|1\rangle$. -**Goal:** Use several Pauli gates to change the qubit state to $i|\\psi\\rangle = i\\alpha|0\\rangle + i\\beta|1\\rangle$. \ No newline at end of file +**Goal:** Use several Pauli gates to change the qubit state to $i|\psi\rangle = i\alpha|0\rangle + i\beta|1\rangle$. diff --git a/katas/content/single_qubit_gates/global_phase_i/solution.md b/katas/content/single_qubit_gates/global_phase_i/solution.md index b7d2f9a733..0fa0d25801 100644 --- a/katas/content/single_qubit_gates/global_phase_i/solution.md +++ b/katas/content/single_qubit_gates/global_phase_i/solution.md @@ -1,9 +1,9 @@ We need to apply a gate which applies a global phase of $i$, i.e. $|\psi\rangle \rightarrow i|\psi\rangle$. -The matrix representation of such a gate is $\begin{bmatrix} i & 0 \\\ 0 & i \end{bmatrix} = i\begin{bmatrix} 1 & 0 \\\ 0 & 1 \end{bmatrix} = iI$. +The matrix representation of such a gate is $\begin{bmatrix} i & 0 \\ 0 & i \end{bmatrix} = i\begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} = iI$. Since we are restricted to the Pauli gates, we use the property that a product of any two distinct Pauli gates equals the third gate with a $+i$ or a $-i$ global phase, therefore the product of all three Pauli gates is $XYZ = iI$. $$ -\begin{bmatrix} 0 & 1 \\\ 1 & 0 \end{bmatrix}\begin{bmatrix} 0 & -i \\\ i & 0 \end{bmatrix}\begin{bmatrix} 1 & 0 \\\ 0 & -1 \end{bmatrix} = -\begin{bmatrix} i & 0 \\\ 0 & i \end{bmatrix} +\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix}\begin{bmatrix} 0 & -i \\ i & 0 \end{bmatrix}\begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix} = +\begin{bmatrix} i & 0 \\ 0 & i \end{bmatrix} $$ > Remember the rightmost gates in mathematical notation are applied first in Q# code. Hence we first apply the $Z$ gate, followed by the $Y$ gate, and finally the $X$ gate. diff --git a/katas/content/single_qubit_gates/global_phase_minusone/solution.md b/katas/content/single_qubit_gates/global_phase_minusone/solution.md index a295bc51a5..28c955d1a4 100644 --- a/katas/content/single_qubit_gates/global_phase_minusone/solution.md +++ b/katas/content/single_qubit_gates/global_phase_minusone/solution.md @@ -10,7 +10,7 @@ To do that, we utilize a sequence of gates. The Pauli Z gate followed by the Pau $$ Z = - \begin{bmatrix}1 & 0 \\\ 0 & -1 \end{bmatrix} + \begin{bmatrix}1 & 0 \\ 0 & -1 \end{bmatrix} $$ 2. **Apply the Pauli X gate**: The X gate flips the $|0\rangle$ and $|1\rangle$ basis states, converting our $\beta |0\rangle - \gamma |1\rangle$ state to $\beta |1\rangle - \gamma |0\rangle$. @@ -19,7 +19,7 @@ To do that, we utilize a sequence of gates. The Pauli Z gate followed by the Pau $$ X = - \begin{bmatrix}0 & 1 \\\1 & 0\end{bmatrix} + \begin{bmatrix}0 & 1 \\ 1 & 0\end{bmatrix} $$ 3. **Repeat the Z and X gates**: Applying the Z gate again will multiply the $|1\rangle$ state (that used to be $|0\rangle$), converting our state $\beta |1\rangle - \gamma |0\rangle$ to $- \beta |1\rangle - \gamma |0\rangle$. Finally, the second X gate will restore the original basis states, but now with both amplitudes having acquired an additional phase of $-1$. This means our state has been multiplied by $-1$, achieving the required global phase change. diff --git a/katas/content/single_qubit_gates/index.md b/katas/content/single_qubit_gates/index.md index 0e41691d47..bdbdcbe9a5 100644 --- a/katas/content/single_qubit_gates/index.md +++ b/katas/content/single_qubit_gates/index.md @@ -32,24 +32,24 @@ As a quick reminder, a unitary matrix is a square matrix whose inverse is its ad Single-qubit gates are represented by $2 \times 2$ matrices. Our example for this section, the $X$ gate, is represented by the following matrix: -$$\begin{bmatrix} 0 & 1 \\\ 1 & 0 \end{bmatrix}$$ +$$\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix}$$ You may recall that the state of a qubit is represented by a vector of size $2$. You can apply a gate to a qubit by multiplying the gate's matrix by the qubit's state vector. The result will be another vector, representing the new state of the qubit. For example, applying the $X$ gate to the computational basis states looks like this: $$ X|0\rangle = -\begin{bmatrix} 0 & 1 \\\ 1 & 0 \end{bmatrix} -\begin{bmatrix} 1 \\\ 0 \end{bmatrix} = -\begin{bmatrix} 0 \cdot 1 + 1 \cdot 0 \\\ 1 \cdot 1 + 0 \cdot 0 \end{bmatrix} = -\begin{bmatrix} 0 \\\ 1 \end{bmatrix} +\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} +\begin{bmatrix} 1 \\ 0 \end{bmatrix} = +\begin{bmatrix} 0 \cdot 1 + 1 \cdot 0 \\ 1 \cdot 1 + 0 \cdot 0 \end{bmatrix} = +\begin{bmatrix} 0 \\ 1 \end{bmatrix} $$ $$ X|1\rangle = -\begin{bmatrix} 0 & 1 \\\ 1 & 0 \end{bmatrix} -\begin{bmatrix} 0 \\\ 1 \end{bmatrix} = -\begin{bmatrix} 0 \cdot 0 + 1 \cdot 1 \\\ 1 \cdot 0 + 0 \cdot 1 \end{bmatrix} = -\begin{bmatrix} 1 \\\ 0 \end{bmatrix} +\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} +\begin{bmatrix} 0 \\ 1 \end{bmatrix} = +\begin{bmatrix} 0 \cdot 0 + 1 \cdot 1 \\ 1 \cdot 0 + 0 \cdot 1 \end{bmatrix} = +\begin{bmatrix} 1 \\ 0 \end{bmatrix} $$ The general case: @@ -58,10 +58,10 @@ $$|\psi\rangle = \alpha|0\rangle + \beta|1\rangle$$ $$ X|\psi\rangle = -\begin{bmatrix} 0 & 1 \\\ 1 & 0 \end{bmatrix} -\begin{bmatrix} \alpha \\\ \beta \end{bmatrix} = -\begin{bmatrix} 0 \cdot \alpha + 1 \cdot \beta \\\ 1 \cdot \alpha + 0 \cdot \beta \end{bmatrix} = -\begin{bmatrix} \beta \\\ \alpha \end{bmatrix} +\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} +\begin{bmatrix} \alpha \\ \beta \end{bmatrix} = +\begin{bmatrix} 0 \cdot \alpha + 1 \cdot \beta \\ 1 \cdot \alpha + 0 \cdot \beta \end{bmatrix} = +\begin{bmatrix} \beta \\ \alpha \end{bmatrix} $$ > If you need a reminder of what $|0\rangle$, $|1\rangle$, and $|\psi\rangle$ mean, you can review the section on Dirac notation in "The Qubit" kata. @@ -72,7 +72,7 @@ Applying several quantum gates in sequence is equivalent to performing several o For example, if you have gates $A$ and $B$ and a qubit in state $|\psi\rangle$, the result of applying $A$ followed by $B$ to that qubit would be $B\big(A|\psi\rangle\big)$ (the gate closest to the qubit state gets applied first). Matrix multiplication is associative, so this is equivalent to multiplying the $B$ matrix by the $A$ matrix, producing a compound gate of the two, and then applying that to the qubit: $\big(BA\big)|\psi\rangle$. ->Note that matrix multiplication isn’t commutative, thus $(BA) \neq \(AB)$. +>Note that matrix multiplication isn’t commutative, thus $(BA) \neq (AB)$. All quantum gates are reversible - there is another gate which will undo any given gate's transformation, returning the qubit to its original state. This means that when dealing with quantum gates, information about qubit states is never lost, as opposed to classical logic gates, some of which destroy information. @@ -82,38 +82,38 @@ Quantum gates are represented by unitary matrices, so the inverse of a gate is i There is a simple way to find out what a gate does to the two computational basis states $|0\rangle$ and $|1\rangle$. Consider an arbitrary gate: -$$A = \begin{bmatrix} \epsilon & \zeta \\\ \eta & \mu \end{bmatrix}$$ +$$A = \begin{bmatrix} \epsilon & \zeta \\ \eta & \mu \end{bmatrix}$$ Watch what happens when we apply it to these states: $$ A|0\rangle = -\begin{bmatrix} \epsilon & \zeta \\\ \eta & \mu \end{bmatrix} -\begin{bmatrix} 1 \\\ 0 \end{bmatrix} = -\begin{bmatrix} \epsilon \cdot 1 + \zeta \cdot 0 \\\ \eta \cdot 1 + \mu \cdot 0 \end{bmatrix} = -\begin{bmatrix} \epsilon \\\ \eta \end{bmatrix} = \epsilon|0\rangle + \eta|1\rangle +\begin{bmatrix} \epsilon & \zeta \\ \eta & \mu \end{bmatrix} +\begin{bmatrix} 1 \\ 0 \end{bmatrix} = +\begin{bmatrix} \epsilon \cdot 1 + \zeta \cdot 0 \\ \eta \cdot 1 + \mu \cdot 0 \end{bmatrix} = +\begin{bmatrix} \epsilon \\ \eta \end{bmatrix} = \epsilon|0\rangle + \eta|1\rangle $$ $$ A|1\rangle = -\begin{bmatrix} \epsilon & \zeta \\\ \eta & \mu \end{bmatrix} -\begin{bmatrix} 0 \\\ 1 \end{bmatrix} = -\begin{bmatrix} \epsilon \cdot 0 + \zeta \cdot 1 \\\ \eta \cdot 0 + \mu \cdot 1 \end{bmatrix} = -\begin{bmatrix} \zeta \\\ \mu \end{bmatrix} = \zeta|0\rangle + \mu|1\rangle +\begin{bmatrix} \epsilon & \zeta \\ \eta & \mu \end{bmatrix} +\begin{bmatrix} 0 \\ 1 \end{bmatrix} = +\begin{bmatrix} \epsilon \cdot 0 + \zeta \cdot 1 \\ \eta \cdot 0 + \mu \cdot 1 \end{bmatrix} = +\begin{bmatrix} \zeta \\ \mu \end{bmatrix} = \zeta|0\rangle + \mu|1\rangle $$ Notice that applying the gate to the $|0\rangle$ state transforms it into the state written as the first column of the gate's matrix. Likewise, applying the gate to the $|1\rangle$ state transforms it into the state written as the second column. This holds true for any quantum gate, including, of course, the $X$ gate: -$$X = \begin{bmatrix} 0 & 1 \\\ 1 & 0 \end{bmatrix}$$ +$$X = \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix}$$ -$$X|0\rangle = \begin{bmatrix} 0 \\\ 1 \end{bmatrix} = |1\rangle$$ +$$X|0\rangle = \begin{bmatrix} 0 \\ 1 \end{bmatrix} = |1\rangle$$ -$$X|1\rangle = \begin{bmatrix} 1 \\\ 0 \end{bmatrix} = |0\rangle$$ +$$X|1\rangle = \begin{bmatrix} 1 \\ 0 \end{bmatrix} = |0\rangle$$ Once you understand how a gate affects the computational basis states, you can easily find how it affects any state. Recall that any qubit state vector can be written as a linear combination of the basis states: -$$|\psi\rangle = \begin{bmatrix} \alpha \\\ \beta \end{bmatrix} = \alpha|0\rangle + \beta|1\rangle$$ +$$|\psi\rangle = \begin{bmatrix} \alpha \\ \beta \end{bmatrix} = \alpha|0\rangle + \beta|1\rangle$$ Because matrix multiplication distributes over addition, once you know how a gate affects those two basis states, you can calculate how it affects any state: @@ -138,19 +138,19 @@ Some examples:
Bra
$|0\rangle = \begin{bmatrix} 1 \\\ 0 \end{bmatrix}$$|0\rangle = \begin{bmatrix} 1 \\ 0 \end{bmatrix}$ $\langle0| = \begin{bmatrix} 1 & 0 \end{bmatrix}$
$|1\rangle = \begin{bmatrix} 0 \\\ 1 \end{bmatrix}$$|1\rangle = \begin{bmatrix} 0 \\ 1 \end{bmatrix}$ $\langle1| = \begin{bmatrix} 0 & 1 \end{bmatrix}$
$|i\rangle = \begin{bmatrix} \frac{1}{\sqrt{2}} \\\ \frac{i}{\sqrt{2}} \end{bmatrix}$$|i\rangle = \begin{bmatrix} \frac{1}{\sqrt{2}} \\ \frac{i}{\sqrt{2}} \end{bmatrix}$ $\langle i| = \begin{bmatrix} \frac{1}{\sqrt{2}} & -\frac{i}{\sqrt{2}} \end{bmatrix}$
$|\psi\rangle = \begin{bmatrix} \alpha \\\ \beta \end{bmatrix}$$|\psi\rangle = \begin{bmatrix} \alpha \\ \beta \end{bmatrix}$ $\langle\psi| = \begin{bmatrix} \overline{\alpha} & \overline{\beta} \end{bmatrix}$
$Y$$\begin{bmatrix} 0 & -i \\\ i & 0 \end{bmatrix}$$\begin{bmatrix} 0 & -i \\ i & 0 \end{bmatrix}$ $i(|1\rangle\langle0| - |0\rangle\langle1|)$ $Y|\psi\rangle = i\big(\alpha|1\rangle - \beta|0\rangle\big)$ @@ -278,7 +278,7 @@ The Pauli gates, named after Trigonometric functions are available in Q# via the `Microsoft.Quantum.Math` namespace. In this case we will need ArcTan2. diff --git a/katas/content/single_qubit_gates/sign_flip/solution.md b/katas/content/single_qubit_gates/sign_flip/solution.md index ec734615fd..2c15ec8d2d 100644 --- a/katas/content/single_qubit_gates/sign_flip/solution.md +++ b/katas/content/single_qubit_gates/sign_flip/solution.md @@ -5,18 +5,18 @@ As a reminder, the Pauli Z gate is defined by the following matrix: $$ Z = - \begin{bmatrix}1 & 0\\\0 & -1 \end{bmatrix} + \begin{bmatrix}1 & 0 \\ 0 & -1 \end{bmatrix} $$ Let's see its effect on the only computational basis state that it changes, $|1\rangle$: $$ Z|1\rangle = - \begin{bmatrix} 1 & 0\\\0 & -1 \end{bmatrix} - \begin{bmatrix}0\\\ 1\\\ \end{bmatrix}= -\begin{bmatrix}1 \cdot 0 + 0 \cdot1\\\0 \cdot 1 + (-1) \cdot 1\\\ \end{bmatrix}= -\begin{bmatrix}0\\\ -1\\\ \end{bmatrix}= - -\begin{bmatrix}0\\\ 1\\\ \end{bmatrix}= + \begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix} + \begin{bmatrix}0 \\ 1 \end{bmatrix}= +\begin{bmatrix}1 \cdot 0 + 0 \cdot1 \\ 0 \cdot 1 + (-1) \cdot 1 \end{bmatrix}= +\begin{bmatrix}0 \\ -1 \end{bmatrix}= + -\begin{bmatrix}0 \\ 1 \end{bmatrix}= -|1\rangle $$ @@ -24,10 +24,10 @@ In general applying the Z gate to a single qubit superposition state $|\psi\rang $$ Z|\psi\rangle = - \begin{bmatrix}1 & 0 \\\0 & -1\end{bmatrix} - \begin{bmatrix}\alpha\\\ \beta\\\ \end{bmatrix}= -\begin{bmatrix}1\cdot\alpha + 0\cdot\beta\\\0\cdot\alpha + (-1)\cdot\beta\\\ \end{bmatrix}= - \begin{bmatrix}\alpha\\\ -\beta\\\ \end{bmatrix}= + \begin{bmatrix}1 & 0 \\ 0 & -1 \end{bmatrix} + \begin{bmatrix}\alpha \\ \beta \end{bmatrix}= +\begin{bmatrix}1\cdot\alpha + 0\cdot\beta \\ 0\cdot\alpha + (-1)\cdot\beta \end{bmatrix}= + \begin{bmatrix}\alpha \\ -\beta \end{bmatrix}= \alpha |0\rangle -\beta |1\rangle $$ diff --git a/katas/content/single_qubit_gates/sign_flip_on_zero/index.md b/katas/content/single_qubit_gates/sign_flip_on_zero/index.md index 349711df30..201f60b89a 100644 --- a/katas/content/single_qubit_gates/sign_flip_on_zero/index.md +++ b/katas/content/single_qubit_gates/sign_flip_on_zero/index.md @@ -2,4 +2,4 @@ **Goal:** Use several Pauli gates to change the qubit state to $- \alpha|0\rangle + \beta|1\rangle$, i.e., apply the transformation represented by the following matrix: -$$\begin{bmatrix} -1 & 0 \\\ 0 & 1 \end{bmatrix}$$ +$$\begin{bmatrix} -1 & 0 \\ 0 & 1 \end{bmatrix}$$ diff --git a/katas/content/single_qubit_gates/sign_flip_on_zero/solution.md b/katas/content/single_qubit_gates/sign_flip_on_zero/solution.md index 44a1588c4f..5b7ad6440b 100644 --- a/katas/content/single_qubit_gates/sign_flip_on_zero/solution.md +++ b/katas/content/single_qubit_gates/sign_flip_on_zero/solution.md @@ -1,12 +1,12 @@ -The first thing to notice is that the gate $\begin{bmatrix} -1 & 0 \\\ 0 & 1 \end{bmatrix}$ is quite similar to the Pauli $Z$ gate $\begin{bmatrix} 1 & 0 \\\ 0 & -1 \end{bmatrix}$. +The first thing to notice is that the gate $\begin{bmatrix} -1 & 0 \\ 0 & 1 \end{bmatrix}$ is quite similar to the Pauli $Z$ gate $\begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix}$. The only difference being that the negative phase is applied on the $|0\rangle$ instead of $|1\rangle$. Hence we can simulate this gate by switching $|0\rangle$ and $|1\rangle$ states, applying the Pauli $Z$ gate and switching them back. The Pauli $X$ gate is the perfect gate to flip the state of the qubit and to undo the action afterwards. -Hence we can express the $Z_0 = \begin{bmatrix} -1 & 0 \\\ 0 & 1 \end{bmatrix}$ matrix as +Hence we can express the $Z_0 = \begin{bmatrix} -1 & 0 \\ 0 & 1 \end{bmatrix}$ matrix as $$ Z_0 = -\begin{bmatrix} -1 & 0 \\\ 0 & 1 \end{bmatrix} = -\begin{bmatrix} 0 & 1 \\\ 1 & 0 \end{bmatrix} \begin{bmatrix} 1 & 0 \\\ 0 & -1 \end{bmatrix} \begin{bmatrix} 0 & 1 \\\ 1 & 0 \end{bmatrix} = +\begin{bmatrix} -1 & 0 \\ 0 & 1 \end{bmatrix} = +\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} \begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix} \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} = XZX $$ diff --git a/katas/content/single_qubit_gates/state_flip/solution.md b/katas/content/single_qubit_gates/state_flip/solution.md index 55f19d46a9..73592b9364 100644 --- a/katas/content/single_qubit_gates/state_flip/solution.md +++ b/katas/content/single_qubit_gates/state_flip/solution.md @@ -4,17 +4,17 @@ As a reminder, the Pauli $X$ gate is defined by the following matrix: $$ X = -\begin{bmatrix} 0 & 1 \\\ 1 & 0 \end{bmatrix} +\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} $$ We can see how it affects, for example, the basis state $|0\rangle$: $$ X|0\rangle = -\begin{bmatrix} 0 & 1 \\\ 1 & 0 \end{bmatrix} -\begin{bmatrix} 1 \\\ 0 \end{bmatrix} = -\begin{bmatrix} 0 \cdot 1 + 1 \cdot 0 \\\ 1 \cdot 1 + 0 \cdot 0 \end{bmatrix}= -\begin{bmatrix} 0 \\\1 \end{bmatrix}= +\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} +\begin{bmatrix} 1 \\ 0 \end{bmatrix} = +\begin{bmatrix} 0 \cdot 1 + 1 \cdot 0 \\ 1 \cdot 1 + 0 \cdot 0 \end{bmatrix}= +\begin{bmatrix} 0 \\1 \end{bmatrix}= |1\rangle $$ @@ -22,10 +22,10 @@ Similarly, we can consider the effect of the $X$ gate on the superposition state $$ X|\psi\rangle = -\begin{bmatrix} 0 & 1 \\\1 & 0\end{bmatrix} -\begin{bmatrix}0.6 \\\0.8 \end{bmatrix}= -\begin{bmatrix} 0 \cdot 0.6 + 1 \cdot 0.8 \\\1 \cdot 0.6 + 0 \cdot 0.8\end{bmatrix}= -\begin{bmatrix}0.8 \\\0.6\end{bmatrix}= +\begin{bmatrix} 0 & 1 \\1 & 0\end{bmatrix} +\begin{bmatrix}0.6 \\ 0.8 \end{bmatrix}= +\begin{bmatrix} 0 \cdot 0.6 + 1 \cdot 0.8 \\ 1 \cdot 0.6 + 0 \cdot 0.8 \end{bmatrix}= +\begin{bmatrix}0.8 \\ 0.6 \end{bmatrix}= 0.8|0\rangle + 0.6|1\rangle $$ diff --git a/katas/content/single_qubit_gates/three_quarters_pi_phase/index.md b/katas/content/single_qubit_gates/three_quarters_pi_phase/index.md index 8303d34492..17389798e0 100644 --- a/katas/content/single_qubit_gates/three_quarters_pi_phase/index.md +++ b/katas/content/single_qubit_gates/three_quarters_pi_phase/index.md @@ -2,4 +2,4 @@ **Goal:** Use several phase shift gates to apply the transformation represented by the following matrix to the given qubit: -$$\begin{bmatrix} 1 & 0 \\\ 0 & e^{3i\pi/4} \end{bmatrix}$$ \ No newline at end of file +$$\begin{bmatrix} 1 & 0 \\ 0 & e^{3i\pi/4} \end{bmatrix}$$ diff --git a/katas/content/single_qubit_gates/three_quarters_pi_phase/solution.md b/katas/content/single_qubit_gates/three_quarters_pi_phase/solution.md index 1ed3900d50..094ed3045a 100644 --- a/katas/content/single_qubit_gates/three_quarters_pi_phase/solution.md +++ b/katas/content/single_qubit_gates/three_quarters_pi_phase/solution.md @@ -1,9 +1,9 @@ -The three-fourths phase gate above can be expressed as a product of two canonical gates - the $T$ gate is $\begin{bmatrix} 1 & 0 \\\ 0 & e^{i\pi/4} \end{bmatrix}$ and the $S$ gate is $\begin{bmatrix} 1 & 0 \\\ 0 & e^{i\pi/2} \end{bmatrix}$. +The three-fourths phase gate above can be expressed as a product of two canonical gates - the $T$ gate is $\begin{bmatrix} 1 & 0 \\ 0 & e^{i\pi/4} \end{bmatrix}$ and the $S$ gate is $\begin{bmatrix} 1 & 0 \\ 0 & e^{i\pi/2} \end{bmatrix}$. $$ -\begin{bmatrix} 1 & 0 \\\ 0 & e^{i3\pi/4} \end{bmatrix} = -\begin{bmatrix} 1 & 0 \\\ 0 & e^{i\pi/4} \end{bmatrix} \begin{bmatrix} 1 & 0 \\\ 0 & e^{i\pi/2} \end{bmatrix} = -\begin{bmatrix} 1 & 0 \\\ 0 & e^{i\pi/4} \end{bmatrix} \begin{bmatrix} 1 & 0 \\\ 0 & i \end{bmatrix} = +\begin{bmatrix} 1 & 0 \\ 0 & e^{i3\pi/4} \end{bmatrix} = +\begin{bmatrix} 1 & 0 \\ 0 & e^{i\pi/4} \end{bmatrix} \begin{bmatrix} 1 & 0 \\ 0 & e^{i\pi/2} \end{bmatrix} = +\begin{bmatrix} 1 & 0 \\ 0 & e^{i\pi/4} \end{bmatrix} \begin{bmatrix} 1 & 0 \\ 0 & i \end{bmatrix} = TS $$ diff --git a/katas/content/single_qubit_gates/y_gate/index.md b/katas/content/single_qubit_gates/y_gate/index.md index 60da97dcd1..aa7347bedd 100644 --- a/katas/content/single_qubit_gates/y_gate/index.md +++ b/katas/content/single_qubit_gates/y_gate/index.md @@ -1,3 +1,3 @@ -**Input:** A qubit in an arbitrary state $|\\psi\\rangle = \\alpha|0\\rangle + \\beta|1\\rangle$. +**Input:** A qubit in an arbitrary state $|\psi\rangle = \alpha|0\rangle + \beta|1\rangle$. -**Goal:** Apply the Y gate to the qubit, i.e., transform the given state into $i\\alpha|1\\rangle - i\\beta|0\\rangle$. \ No newline at end of file +**Goal:** Apply the Y gate to the qubit, i.e., transform the given state into $i\alpha|1\rangle - i\beta|0\rangle$. diff --git a/katas/content/single_qubit_gates/y_gate/solution.md b/katas/content/single_qubit_gates/y_gate/solution.md index bd6319968a..fb473d8724 100644 --- a/katas/content/single_qubit_gates/y_gate/solution.md +++ b/katas/content/single_qubit_gates/y_gate/solution.md @@ -1,9 +1,9 @@ -We have to do exactly what the task asks us to do: apply the Pauli gate $Y=\\begin{bmatrix} 0 & -i \\\\ i & 0 \\end{bmatrix}$. +We have to do exactly what the task asks us to do: apply the Pauli gate $Y=\begin{bmatrix} 0 & -i \\ i & 0 \end{bmatrix}$. This has the effect of turning $|\psi\rangle = \alpha|0\rangle + \beta|1\rangle$ into $Y|\psi\rangle = i\alpha|1\rangle - i\beta|0\rangle$, which in matrix form looks as follows: $$ -\begin{bmatrix} 0 & -i \\\ i & 0 \end{bmatrix} \begin{bmatrix} \alpha \\\ \beta \end{bmatrix} = -\begin{bmatrix} -i\beta \\\ i\alpha \end{bmatrix} +\begin{bmatrix} 0 & -i \\ i & 0 \end{bmatrix} \begin{bmatrix} \alpha \\ \beta \end{bmatrix} = +\begin{bmatrix} -i\beta \\ i\alpha \end{bmatrix} $$ @[solution]({ diff --git a/katas/content/single_qubit_measurements/distinguish_orthogonal_states_1/index.md b/katas/content/single_qubit_measurements/distinguish_orthogonal_states_1/index.md index 6a23d78d9f..1ddf0905c2 100644 --- a/katas/content/single_qubit_measurements/distinguish_orthogonal_states_1/index.md +++ b/katas/content/single_qubit_measurements/distinguish_orthogonal_states_1/index.md @@ -4,5 +4,5 @@
Need a hint? -A suitable $R_y$ rotation can be used to go from the computational basis $\\{ \ket 0, \ket 1 \\}$ to the $\\{ \ket{\psi_+}, \ket{\psi_-} \\}$ basis and vice versa. +A suitable $R_y$ rotation can be used to go from the computational basis $\{ \ket 0, \ket 1 \}$ to the $\{ \ket{\psi_+}, \ket{\psi_-} \}$ basis and vice versa.
diff --git a/katas/content/single_qubit_measurements/distinguish_orthogonal_states_2/solution.md b/katas/content/single_qubit_measurements/distinguish_orthogonal_states_2/solution.md index 21ae49a421..2e48fd9b63 100644 --- a/katas/content/single_qubit_measurements/distinguish_orthogonal_states_2/solution.md +++ b/katas/content/single_qubit_measurements/distinguish_orthogonal_states_2/solution.md @@ -1,4 +1,4 @@ -We can distinguish between the states $\ket{A}$ and $\ket B$ if we implement a measurement in the $\\{ \ket{A}, \ket{B}\\}$ basis. +We can distinguish between the states $\ket{A}$ and $\ket B$ if we implement a measurement in the $\{ \ket{A}, \ket{B}\}$ basis. We can notice that the $R_x$ rotation gate with $\theta = 2 \alpha$ is an appropriate transformation which maps the $\ket 0 $ state to the $\ket A$ state, and the $\ket 1$ state to the $\ket B$ state: diff --git a/katas/content/single_qubit_measurements/index.md b/katas/content/single_qubit_measurements/index.md index 8e19cef33f..ba415f5da0 100644 --- a/katas/content/single_qubit_measurements/index.md +++ b/katas/content/single_qubit_measurements/index.md @@ -68,7 +68,7 @@ The outcomes of computational basis measurements and their probabilities are sum ## πŸ”Ž Analyze The qubit is in the following state: -$$\ket \psi = 0.6 \ket 0 + 0.8 \ket 1 = \begin{bmatrix} 0.6 \\\ 0.8\end{bmatrix}$$ +$$\ket \psi = 0.6 \ket 0 + 0.8 \ket 1 = \begin{bmatrix} 0.6 \\ 0.8 \end{bmatrix}$$ If this qubit is measured in the computational basis, what are the outcome probabilities? @@ -129,7 +129,7 @@ It is also possible to implement measurements in other orthogonal bases, such as The eigenvalues of a Pauli matrix are $\pm 1$, with one eigenvector corresponding to each eigenvalue. For any chosen Pauli basis, the `Measure` operation returns `Zero` if the measurement outcome corresponds to the eigenvalue $+1$, and returns `One` if the measurement outcome corresponds to the eigenvalue $-1$. As in the case of the computational basis measurements, the wave function of the qubit collapses to the corresponding state after the measurement is executed. -The probabilities of the outcomes are defined using a similar rule: to measure a state $\ket \psi$ in a Pauli basis $\\{ \ket {b_0}, \ket {b_1} \\}$, we represent it as a linear combination of the basis vectors +The probabilities of the outcomes are defined using a similar rule: to measure a state $\ket \psi$ in a Pauli basis $\{ \ket {b_0}, \ket {b_1} \}$, we represent it as a linear combination of the basis vectors $$\ket \psi = c_0 \ket {b_0} + c_1 \ket {b_1}$$ The probabilities of outcomes $\ket{b_0}$ and $\ket{b_1}$ will be defined as $|c_0|^2$, and $|c_1|^2$, respectively. @@ -154,7 +154,7 @@ It is possible to measure a qubit in orthogonal bases other than the Pauli bases $$ \ket \psi = c_0 \ket {b_0} + c_1 \ket {b_1}. $$ -The rule for obtaining the probabilities of measurement outcomes is exactly the same as that for the computational basis measurement. For a measurement in a $\\{ b_0, b_1\\}$ basis we get +The rule for obtaining the probabilities of measurement outcomes is exactly the same as that for the computational basis measurement. For a measurement in a $\{ b_0, b_1\}$ basis we get - Outcome $b_0$ with probability $|c_0|^2$ and the post-measurement qubit state of $\ket {b_0}$ - Outcome $b_1$ with probability $|c_1|^2$ and the post-measurement qubit state of $\ket {b_1}$ @@ -182,7 +182,7 @@ As before, the assumption of $\ket \psi$ being normalized is important, since it > As you may recall, a global phase is said to be hidden or unobservable. This is explained by the fact that global phases have no impact on quantum measurements. For example, consider two isolated qubits which are in (normalized) states $\ket \psi$ and $e^{i\theta}\ket \psi$. -If both are measured in an orthogonal basis $\\{ \ket{b_0},\ket{b_1}\\}$, the probabilities of measuring $b_0$ or $b_1$ are identical in both cases, since $|\bra{b_i}\ket{\psi}|^2 = |\bra{b_i}e^{i\theta}\ket{\psi}|^2 $. +If both are measured in an orthogonal basis $\{ \ket{b_0},\ket{b_1}\}$, the probabilities of measuring $b_0$ or $b_1$ are identical in both cases, since $|\bra{b_i}\ket{\psi}|^2 = |\bra{b_i}e^{i\theta}\ket{\psi}|^2 $. Similarly, for either qubit, if $b_i$ is the measurement outcome, the post-measurement state of the qubit is $\ket{b_i}$. Hence, the measurements are independent of the global phase $\theta$. ## Measurements as Projection Operations @@ -196,10 +196,10 @@ $$ As the name implies, orthogonal projection operators project the state of the qubit onto an orthogonal subspace. Using the ket-bra representation, one can represent a projection matrix in the Dirac notation. For example, one may construct a projector onto the $\ket{0}$ subspace as: $$ -P = \ket 0 \bra 0 \equiv \begin{bmatrix} 1 & 0 \\\ 0 & 0\end{bmatrix}. +P = \ket 0 \bra 0 \equiv \begin{bmatrix} 1 & 0 \\ 0 & 0 \end{bmatrix}. $$ -A measurement in an orthogonal basis $\\{ \ket{b_0}, \ket{b_1}\\}$ is described by a pair of projectors $P_0 = \ket{b_0}\bra{b_0}$ and $P_1 = \ket{b_1}\bra{b_1}$. Since $\ket{b_0}$ and $\ket{b_1}$ are orthogonal, their projectors are also orthogonal, i.e., $P_0 P_1 = P_1 P_0 = 0$. The rules for measurements in this basis can then be summarized as follows: +A measurement in an orthogonal basis $\{ \ket{b_0}, \ket{b_1}\}$ is described by a pair of projectors $P_0 = \ket{b_0}\bra{b_0}$ and $P_1 = \ket{b_1}\bra{b_1}$. Since $\ket{b_0}$ and $\ket{b_1}$ are orthogonal, their projectors are also orthogonal, i.e., $P_0 P_1 = P_1 P_0 = 0$. The rules for measurements in this basis can then be summarized as follows: - Measuring a qubit in a state $\ket \psi$ is done by picking one of these projection operators at random. - Projector $P_0$ is chosen with probability $|P_0 \ket{\psi}|^2$, and the projector $P_1$ is chosen with probability $|P_1\ket{\psi}|^2.$ @@ -226,7 +226,7 @@ Although the projector formalism for single-qubit systems may seem superfluous, In the previous section, we discussed measurements in Pauli bases using the built-in `Measure` operation. We will now show that it is always possible to measure a qubit in any orthogonal basis using just unitary rotation matrices and computation basis measurements. -Consider a state $ \ket \psi = c_0 \ket {b_0} + c_1 \ket {b_1} $ which we would like to measure in an orthonormal basis $\\{ \ket{b_0}, \ket{b_1}\\}$. First, we construct the following unitary matrix: +Consider a state $ \ket \psi = c_0 \ket {b_0} + c_1 \ket {b_1} $ which we would like to measure in an orthonormal basis $\{ \ket{b_0}, \ket{b_1}\}$. First, we construct the following unitary matrix: $$ U = \ket{0} \bra{b_0} + \ket{1} \bra{b_1} $$ @@ -244,7 +244,7 @@ $$U\ket{b_1} = \ket{1}$$ $$U^\dagger \ket{0} = \ket{b_0}$$ $$U^\dagger \ket{1} = \ket{b_1}$$ -In order to implement a measurement in the $\\{ \ket{b_0}, \ket{b_1} \\}$ basis, we do the following: +In order to implement a measurement in the $\{ \ket{b_0}, \ket{b_1} \}$ basis, we do the following: 1. Apply $U$ to $\ket \psi$. The resulting state is $U\ket \psi = c_0 \ket 0 + c_1 \ket 1 $. @@ -282,12 +282,12 @@ This procedure can be used to distinguish arbitrary orthogonal states as well, a $$ We can now construct the two projectors $P_{\pm i}$ onto states $\ket {\pm i}$ as follows: - $$P_{i} = \ket{i}\bra{i} = \frac{1}{2} \begin{bmatrix} 1 \\\\ i \end{bmatrix} \begin{bmatrix} 1 & -i \end{bmatrix} = \frac{1}{2} \begin{bmatrix}1 & -i \\\\ i & 1\end{bmatrix},$$ - $$P_{-i} = \ket{-i}\bra{-i} = \frac{1}{2} \begin{bmatrix} 1 \\\\ -i \end{bmatrix} \begin{bmatrix} 1 & i \end{bmatrix} = \frac{1}{2} \begin{bmatrix}1 & i \\\\ -i & 1\end{bmatrix}.$$ + $$P_{i} = \ket{i}\bra{i} = \frac{1}{2} \begin{bmatrix} 1 \\ i \end{bmatrix} \begin{bmatrix} 1 & -i \end{bmatrix} = \frac{1}{2} \begin{bmatrix}1 & -i \\ i & 1 \end{bmatrix},$$ + $$P_{-i} = \ket{-i}\bra{-i} = \frac{1}{2} \begin{bmatrix} 1 \\ -i \end{bmatrix} \begin{bmatrix} 1 & i \end{bmatrix} = \frac{1}{2} \begin{bmatrix}1 & i \\ -i & 1 \end{bmatrix}.$$ Recalling that the probabilities of measuring $\pm i$ are equal to the norm of the vectors $P_{\pm i}\ket \psi$, we now apply $P_{\pm i}$ to $\ket \psi$: - $$P_{+i} \ket \psi = \frac{1}{2} \begin{bmatrix}1 & -i \\\\ i & 1\end{bmatrix} \begin{bmatrix} 0.6 \\\\ 0.8 \end{bmatrix} = \frac{1}{2} \begin{bmatrix} 0.6 - 0.8i \\\\ 0.8 + 0.6i \end{bmatrix},$$ - $$P_{-i} \ket \psi = \frac{1}{2} \begin{bmatrix}1 & i \\\\ -i & 1\end{bmatrix} \begin{bmatrix} 0.6 \\\\ 0.8 \end{bmatrix} = \frac{1}{2} \begin{bmatrix} 0.6 + 0.8i \\\\ 0.8 - 0.6i \end{bmatrix}.$$ + $$P_{+i} \ket \psi = \frac{1}{2} \begin{bmatrix}1 & -i \\ i & 1\end{bmatrix} \begin{bmatrix} 0.6 \\ 0.8 \end{bmatrix} = \frac{1}{2} \begin{bmatrix} 0.6 - 0.8i \\ 0.8 + 0.6i \end{bmatrix},$$ + $$P_{-i} \ket \psi = \frac{1}{2} \begin{bmatrix}1 & i \\ -i & 1\end{bmatrix} \begin{bmatrix} 0.6 \\ 0.8 \end{bmatrix} = \frac{1}{2} \begin{bmatrix} 0.6 + 0.8i \\ 0.8 - 0.6i \end{bmatrix}.$$ Hence, the probabilities of measuring $\pm i$, which we denote by $p(\pm i)$, are: $$p(+i) = |P_{+i} \ket \psi|^2 = \frac{1}{4}(|0.6 - 0.8i|^2 + |0.8 + 0.6i|^2) = \frac{1}{2},$$ diff --git a/katas/content/superposition/all_basis_vectors/solution.md b/katas/content/superposition/all_basis_vectors/solution.md index 8d4c9bfc09..5a2ab11c5c 100644 --- a/katas/content/superposition/all_basis_vectors/solution.md +++ b/katas/content/superposition/all_basis_vectors/solution.md @@ -2,16 +2,15 @@ As we've seen in the 'Superposition of all basis vectors on two qubits' task, to 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) \\\\ + 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) \\\\ + &= \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. diff --git a/katas/content/superposition/all_bell_states/solution.md b/katas/content/superposition/all_bell_states/solution.md index 6867dab105..536abe0c6c 100644 --- a/katas/content/superposition/all_bell_states/solution.md +++ b/katas/content/superposition/all_bell_states/solution.md @@ -48,7 +48,7 @@ The final sequence of steps is as follows: Let's take a closer look at the unitary transformation $\text{CNOT}\cdot(H \otimes I)$ discussed in task 6 (see equation 6.1). -$$\frac{1}{\sqrt2} \begin{bmatrix} 1 & 0 & 1 & 0 \\\ 0 & 1 & 0 & 1 \\\ 0 & 1 & 0 & -1 \\\ \underset{|\Phi^{+}\rangle}{\underbrace{1}} & \underset{|\Psi^{+}\rangle}{\underbrace{0}} & \underset{|\Phi^{-}\rangle}{\underbrace{-1}} & \underset{|\Psi^{-}\rangle}{\underbrace{0}} \end{bmatrix}$$ +$$\frac{1}{\sqrt2} \begin{bmatrix} 1 & 0 & 1 & 0 \\ 0 & 1 & 0 & 1 \\ 0 & 1 & 0 & -1 \\ \underset{|\Phi^{+}\rangle}{\underbrace{1}} & \underset{|\Psi^{+}\rangle}{\underbrace{0}} & \underset{|\Phi^{-}\rangle}{\underbrace{-1}} & \underset{|\Psi^{-}\rangle}{\underbrace{0}} \end{bmatrix}$$ Notice that each of the columns in the unitary matrix corresponds to one of the Bell states. diff --git a/katas/content/superposition/bell_state/solution.md b/katas/content/superposition/bell_state/solution.md index 05326a4397..37897a62bf 100644 --- a/katas/content/superposition/bell_state/solution.md +++ b/katas/content/superposition/bell_state/solution.md @@ -23,7 +23,7 @@ How can we do this? We can take advantage of controlled gates, specifically the [controlled NOT gate](https://en.wikipedia.org/wiki/Controlled_NOT_gate), also referred to as $CNOT$. This gate acts on two qubits, hence it is represented as a $4 \times 4$ unitary matrix. The $CNOT$ gate changes the target qubit from state $|0\rangle$ to $|1\rangle$ and vice versa when the control qubit is $|1\rangle$ and does nothing to the target qubit when the control qubit is $|0\rangle$. The control qubit always remains unchanged. -$$\text{CNOT} = \begin{bmatrix} 1 & 0 & 0 & 0 \\\ 0 & 1 & 0 & 0 \\\ 0 & 0 & 0 & 1 \\\ 0 & 0 & 1 & 0 \end{bmatrix}$$ +$$\text{CNOT} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \end{bmatrix}$$ If we apply the CNOT gate to the state $\frac{1}{\sqrt2} (|00\rangle + |10\rangle)$, taking the first qubit as the control and the second one as target, we'll get exactly the desired goal state. @@ -33,18 +33,18 @@ Steps required to reach goal state: In matrix representation we can represent this operation as a product of two $4 \times 4$ matrices, with the matrix corresponding to the first step being the tensor product of a Hadamard gate on the first qubit and identity gate on the second qubit. -$$H \otimes I = \frac{1}{\sqrt2} \begin{bmatrix} 1 & 1 \\\ 1 & -1 \end{bmatrix} \otimes \begin{bmatrix} 1 & 0 \\\ 0 & 1 \end{bmatrix} = -\frac{1}{\sqrt2}\begin{bmatrix} 1 & 0 & 1 & 0 \\\ 0 & 1 & 0 & 1 \\\ 1 & 0 & -1 & 0 \\\ 0 & 1 & 0 & -1 \end{bmatrix}$$ +$$H \otimes I = \frac{1}{\sqrt2} \begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix} \otimes \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} = +\frac{1}{\sqrt2}\begin{bmatrix} 1 & 0 & 1 & 0 \\ 0 & 1 & 0 & 1 \\ 1 & 0 & -1 & 0 \\ 0 & 1 & 0 & -1 \end{bmatrix}$$ -$$\underset{\text{CNOT}}{\underbrace{\begin{bmatrix} 1 & 0 & 0 & 0 \\\ 0 & 1 & 0 & 0 \\\ 0 & 0 & 0 & 1 \\\ 0 & 0 & 1 & 0 \end{bmatrix}}} +$$\underset{\text{CNOT}}{\underbrace{\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \end{bmatrix}}} \cdot -\underset{H \otimes I}{\underbrace{\frac{1}{\sqrt2} \begin{bmatrix} 1 & 0 & 1 & 0 \\\ 0 & 1 & 0 & 1 \\\ 1 & 0 & -1 & 0 \\\ 0 & 1 & 0 & -1 \end{bmatrix}}} +\underset{H \otimes I}{\underbrace{\frac{1}{\sqrt2} \begin{bmatrix} 1 & 0 & 1 & 0 \\ 0 & 1 & 0 & 1 \\ 1 & 0 & -1 & 0 \\ 0 & 1 & 0 & -1 \end{bmatrix}}} \cdot -\underset{|0\rangle}{\underbrace{ \begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 0 \end{bmatrix}}} -= \frac{1}{\sqrt2} \begin{bmatrix} 1 & 0 & 1 & 0 \\\ 0 & 1 & 0 & 1 \\\ 0 & 1 & 0 & -1 \\\ 1 & 0 & -1 & 0 \end{bmatrix} +\underset{|0\rangle}{\underbrace{ \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix}}} += \frac{1}{\sqrt2} \begin{bmatrix} 1 & 0 & 1 & 0 \\ 0 & 1 & 0 & 1 \\ 0 & 1 & 0 & -1 \\ 1 & 0 & -1 & 0 \end{bmatrix} \cdot -\begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 0 \end{bmatrix} -= \underset{goal}{\underbrace{ \frac{1}{\sqrt2} \begin{bmatrix} 1 \\\ 0 \\\ 0 \\\ 1 \end{bmatrix}}} +\begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix} += \underset{goal}{\underbrace{ \frac{1}{\sqrt2} \begin{bmatrix} 1 \\ 0 \\ 0 \\ 1 \end{bmatrix}}} \label{6.1} \tag{6.1} $$ diff --git a/katas/content/superposition/controlled_rotation/solution.md b/katas/content/superposition/controlled_rotation/solution.md index 9485e16b97..13a0ce77ac 100644 --- a/katas/content/superposition/controlled_rotation/solution.md +++ b/katas/content/superposition/controlled_rotation/solution.md @@ -4,18 +4,18 @@ In this case, our state can be represented as $\frac{1}{\sqrt{2}} \big( |0\rangl We see that the relative weights of $|0\rangle$ and $|1\rangle$ states of the first qubit are both $\frac12$ (the squares of their amplitudes in the decomposition above). This means that we can do the first step by applying the $H$ gate to the first qubit, which gives the $\frac{1}{\sqrt{2}}|00\rangle + \frac{1}{\sqrt{2}}|10\rangle$ state. In matrix form this will look as follows: -$$ H \otimes I = \frac{1}{\sqrt{2}} \begin{bmatrix}1 & 0 & 1 & 0 \\\ 0 & 1 & 0 & 1 \\\ 1 & 0 & -1 & 0 \\\ 0 & 1 & 0 & -1 \end{bmatrix} \cdot -\begin{bmatrix}1 \\\ 0 \\\0 \\\ 0 \end{bmatrix} = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 \\\ 0 \\\ 1 \\\0 \end{bmatrix} = \frac{1}{\sqrt{2}} \big( |0\rangle + |1\rangle \big) \otimes |0\rangle$$ +$$ H \otimes I = \frac{1}{\sqrt{2}} \begin{bmatrix}1 & 0 & 1 & 0 \\ 0 & 1 & 0 & 1 \\ 1 & 0 & -1 & 0 \\ 0 & 1 & 0 & -1 \end{bmatrix} \cdot +\begin{bmatrix} 1 \\ 0 \\0 \\ 0 \end{bmatrix} = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 \\ 0 \\ 1 \\0 \end{bmatrix} = \frac{1}{\sqrt{2}} \big( |0\rangle + |1\rangle \big) \otimes |0\rangle$$ Now the first term of the state $\frac{1}{\sqrt2}|00\rangle$ matches that of the goal state, and we need to convert the second term $\frac{1}{\sqrt2}|10\rangle$ to $|1\rangle \otimes \frac{1}{\sqrt2}(|0\rangle+|1\rangle)$. To do this, we use the controlled $H$ gate. The matrix representation of the controlled $H$ gate is similar to the $CNOT$ gate, however the bottom right block of the matrix is not an $X$ gate but the $H$ gate: -$$\text{Controlled } H = \begin{bmatrix}1 & 0 & 0 & 0 \\\ 0 & 1 & 0 & 0 \\\ 0 & 0 & \frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} \\\ 0 & 0 & \frac{1}{\sqrt{2}} & -\frac{1}{\sqrt{2}} \end{bmatrix}$$ +$$\text{Controlled } H = \begin{bmatrix}1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & \frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} \\ 0 & 0 & \frac{1}{\sqrt{2}} & -\frac{1}{\sqrt{2}} \end{bmatrix}$$ When this is applied to our current state, we get our goal state: -$$\text{Controlled } H \cdot \frac{1}{\sqrt{2}} \begin{bmatrix} 1 \\\ 0 \\\ 1 \\\0 \end{bmatrix} = \begin{bmatrix}\frac{1}{\sqrt{2}} \\\ 0 \\\ \frac{1}{2} \\\ \frac{1}{2} \end{bmatrix} = \frac{1}{\sqrt{2}}|00\rangle+\frac{1}{2}|10\rangle+\frac{1}{2}|11\rangle $$ +$$\text{Controlled } H \cdot \frac{1}{\sqrt{2}} \begin{bmatrix} 1 \\ 0 \\ 1 \\0 \end{bmatrix} = \begin{bmatrix}\frac{1}{\sqrt{2}} \\ 0 \\ \frac{1}{2} \\ \frac{1}{2} \end{bmatrix} = \frac{1}{\sqrt{2}}|00\rangle+\frac{1}{2}|10\rangle+\frac{1}{2}|11\rangle $$ @[solution]({ "id": "superposition__controlled_rotation_solution", diff --git a/katas/content/superposition/even_odd/solution.md b/katas/content/superposition/even_odd/solution.md index b485760095..a94409877c 100644 --- a/katas/content/superposition/even_odd/solution.md +++ b/katas/content/superposition/even_odd/solution.md @@ -2,34 +2,40 @@ Let’s look at some examples of basis states to illustrate the binary numbering 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 = true` and the right column - the basis states that form the required superposition state for `isEven = false`. -| even | odd | -| -------- | ------- | -| **0**0 | **0**1 | -| **1**0 | **1**1 | + + + + +
evenodd
00 01
10 11
If we do the same basis state split for $N = 3$ qubits, the pattern becomes more obvious. -| even | odd | -| -------- | ------- | -| **00**0 | **00**1 | -| **01**0 | **01**1 | -| **10**0 | **10**1 | -| **11**0 | **11**1 | + + + + + + +
evenodd
000 001
010 011
100 101
110 111
The two leftmost qubits go through all possible basis states for `isEven = true` and for `isEven = false`, and the rightmost qubit stays in the $|0\rangle$ state for `isEven = true` and in the $|1\rangle$ state for `isEven = false`. A quick sanity check for $N = 4$ qubits re-confirms the pattern. -| even | odd | -| --------- | -------- | -| **000**0 | **000**1 | -| **001**0 | **001**1 | -| **010**0 | **010**1 | -| **011**0 | **011**1 | -| **100**0 | **100**1 | -| **101**0 | **101**1 | -| **110**0 | **110**1 | -| **111**0 | **111**1 | + + + + + + + + + + + + + +
evenodd
0000 0001
0010 0011
0100 0101
0110 0111
1000 1001
1010 1011
1100 1101
1110 1111
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. diff --git a/katas/content/superposition/even_sup_two_qubits_complex_phases/solution.md b/katas/content/superposition/even_sup_two_qubits_complex_phases/solution.md index 85c7e74260..4b4b76d6c9 100644 --- a/katas/content/superposition/even_sup_two_qubits_complex_phases/solution.md +++ b/katas/content/superposition/even_sup_two_qubits_complex_phases/solution.md @@ -36,7 +36,7 @@ $$ Next lets take a look at our basic gates, in particular the Pauli Z gate: -$$Z = \begin{bmatrix} 1 & 0 \\\ 0 & -1 \end{bmatrix}$$ +$$Z = \begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix}$$ If it is applied to the state $\frac{1}{\sqrt2} \big(|0\rangle + |1\rangle\big)$, it will leave the basis state $|0\rangle$ unchanged and will map $|1\rangle$ to $-|1\rangle$. Thus, @@ -46,7 +46,7 @@ So the Z gate is the answers to the question of how to do the conversion 5.3. Looking for another gate to address the conversion 5.4, we find the S gate: -$$S = \begin{bmatrix} 1 & 0 \\\ 0 & i \end{bmatrix}$$ +$$S = \begin{bmatrix} 1 & 0 \\ 0 & i \end{bmatrix}$$ If it is applied to the state $\frac{1}{\sqrt2} \big(|0\rangle + |1\rangle\big)$, it will leave the basis state $|0\rangle$ unchanged and will map $|1\rangle$ to $i|1\rangle$. Thus, diff --git a/katas/content/superposition/even_sup_two_qubits_phase_flip/solution.md b/katas/content/superposition/even_sup_two_qubits_phase_flip/solution.md index 3b04107b80..7ee4cefb2f 100644 --- a/katas/content/superposition/even_sup_two_qubits_phase_flip/solution.md +++ b/katas/content/superposition/even_sup_two_qubits_phase_flip/solution.md @@ -1,7 +1,7 @@ Here we start with the end state of the previous task $\frac{1}{2} \big(|00\rangle + |01\rangle + |10\rangle + |11\rangle\big)$. Looking at the desired state, the phase of the $|11\rangle$ state is flipped ($+$ changed to a $-$). A regular phase flip on one qubit can be done using a Z gate: -$$\begin{bmatrix} 1 & 0 \\\ 0 & -1 \end{bmatrix}$$ +$$\begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix}$$ This gate will perform a phase flip only on the $|1\rangle$ state: $$Z(\alpha|0\rangle + \beta|1\rangle) = \alpha|0\rangle - \beta|1\rangle$$ diff --git a/katas/content/superposition/minus_state/solution.md b/katas/content/superposition/minus_state/solution.md index 72105a1d96..1686220b45 100644 --- a/katas/content/superposition/minus_state/solution.md +++ b/katas/content/superposition/minus_state/solution.md @@ -2,7 +2,7 @@ As we've seen in the previous task, the Hadamard gate maps the basis state $|0\r If our qubit was already in the $|1\rangle$ state, we would simply apply the Hadamard gate to prepare the required $|-\rangle$ state. Fortunately, there is another operation we can use to change the state $|0\rangle$ to $|1\rangle$, namely the X gate: -$$X = \begin{bmatrix} 0 & 1 \\\ 1 & 0 \end{bmatrix}$$ +$$X = \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix}$$ This gate transforms $|0\rangle \longmapsto |1\rangle$ and $|1\rangle \longmapsto |0\rangle$. X is another one of the built-in gates in Q# from the `Microsoft.Quantum.Intrinsic` namespace. diff --git a/katas/content/superposition/plus_state/solution.md b/katas/content/superposition/plus_state/solution.md index 96e914345e..abf9f4e9cd 100644 --- a/katas/content/superposition/plus_state/solution.md +++ b/katas/content/superposition/plus_state/solution.md @@ -1,6 +1,6 @@ When you start learning the basic quantum gates, one of the first gates described will be the Hadamard gate: -$$H = \frac{1}{\sqrt2} \begin{bmatrix} 1 & 1 \\\ 1 & -1 \end{bmatrix}$$ +$$H = \frac{1}{\sqrt2} \begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix}$$ This gate converts $|0\rangle$ into $|+\rangle = \frac{1}{\sqrt{2}} \big(|0\rangle + |1\rangle\big)$ and $|1\rangle$ into $|βˆ’\rangle = \frac{1}{\sqrt{2}} \big(|0\rangle - |1\rangle\big)$. The first of these transformations is exactly the one we're looking for! diff --git a/katas/content/superposition/three_states_two_qubits_phases/solution.md b/katas/content/superposition/three_states_two_qubits_phases/solution.md index 965b281a05..790832b5af 100644 --- a/katas/content/superposition/three_states_two_qubits_phases/solution.md +++ b/katas/content/superposition/three_states_two_qubits_phases/solution.md @@ -4,9 +4,9 @@ First, we want to transform the $|01\rangle$ state to the $\omega |01\rangle = e Using the [$R_1$](https://learn.microsoft.com/qsharp/api/qsharp-lang/microsoft.quantum.intrinsic/r1) gate, we can change a qubit state from $|1\rangle$ to $e^{i\theta}|1\rangle$ without changing the $|0\rangle$ state. Indeed, here is the effect of the $R_1$ gate on the $|0\rangle$ and the $|1\rangle$ states: -$$ R_1 |0\rangle = \begin{bmatrix} 1 & 0 \\\\ 0 & e^{i\theta} \end{bmatrix} \cdot \begin{bmatrix} 1 \\\\ 0 \end{bmatrix} = \begin{bmatrix} 1 \\\\ 0 \end{bmatrix} = |0\rangle $$ +$$ R_1 |0\rangle = \begin{bmatrix} 1 & 0 \\ 0 & e^{i\theta} \end{bmatrix} \cdot \begin{bmatrix} 1 \\ 0 \end{bmatrix} = \begin{bmatrix} 1 \\ 0 \end{bmatrix} = |0\rangle $$ -$$ R_1 |1\rangle = \begin{bmatrix} 1 & 0 \\\\ 0 & e^{i\theta} \end{bmatrix} \cdot \begin{bmatrix} 0 \\\\ 1 \end{bmatrix} = \begin{bmatrix} 0 \\\\ e^{i\theta} \end{bmatrix} = e^{i\theta}|1\rangle $$ +$$ R_1 |1\rangle = \begin{bmatrix} 1 & 0 \\ 0 & e^{i\theta} \end{bmatrix} \cdot \begin{bmatrix} 0 \\ 1 \end{bmatrix} = \begin{bmatrix} 0 \\ e^{i\theta} \end{bmatrix} = e^{i\theta}|1\rangle $$ When we apply the $R_1$ gate to the second qubit, this will only affect the $|01\rangle$ term, which is exactly what we want. Knowing this, we just need the right value for $\theta$, which in this case is $\frac{2\pi}{3}$. diff --git a/katas/content/superposition/unequal_superposition/solution.md b/katas/content/superposition/unequal_superposition/solution.md index 61604fc99f..b25b7614f8 100644 --- a/katas/content/superposition/unequal_superposition/solution.md +++ b/katas/content/superposition/unequal_superposition/solution.md @@ -1,16 +1,16 @@ We want to convert the $\ket{0}$ state to a parameterized superposition of $\ket{0}$ and $\ket{1}$, which suggests that we are looking for some kind of a rotation operation. There are three main gates that implement rotations around various axes of the Bloch Sphere: -- $R_x(\theta) = \begin{bmatrix} \cos\frac{\theta}{2} & -i\sin\frac{\theta}{2} \\\ -i\sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{bmatrix}$ -- $R_y(\theta) = \begin{bmatrix} \cos\frac{\theta}{2} & -\sin\frac{\theta}{2} \\\ \sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{bmatrix}$ -- $R_z(\theta) = \begin{bmatrix} e^{-i\theta/2} & 0 \\\ 0 & e^{i\theta/2} \end{bmatrix}$ +- $R_x(\theta) = \begin{bmatrix} \cos\frac{\theta}{2} & -i\sin\frac{\theta}{2} \\ -i\sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{bmatrix}$ +- $R_y(\theta) = \begin{bmatrix} \cos\frac{\theta}{2} & -\sin\frac{\theta}{2} \\ \sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{bmatrix}$ +- $R_z(\theta) = \begin{bmatrix} e^{-i\theta/2} & 0 \\ 0 & e^{i\theta/2} \end{bmatrix}$ If we were to apply the $R_x$ gate to a qubit in the $|0\rangle$ state, we would introduce complex coefficients to the amplitudes, which is clearly not what we're looking for. Similarly, the $R_z$ gate introduces only a global phase when applied to $|0\rangle$ state, so we can rule it out as well. This leaves only the $R_y$ as a starting point for the solution. Applying the $R_y$ gate to the $|0\rangle$ state, we get: $$R_y(\theta) |0\rangle = -\begin{bmatrix} \cos\frac{\theta}{2} & -\sin\frac{\theta}{2} \\\ \sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{bmatrix} \begin{bmatrix} 1 \\\ 0 \end{bmatrix} = -\begin{bmatrix} \cos\frac{\theta}{2} \\\ \sin\frac{\theta}{2} \end{bmatrix} = \cos\frac{\theta}{2}|0\rangle + \sin\frac{\theta}{2}|1\rangle$$ +\begin{bmatrix} \cos\frac{\theta}{2} & -\sin\frac{\theta}{2} \\ \sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{bmatrix} \begin{bmatrix} 1 \\ 0 \end{bmatrix} = +\begin{bmatrix} \cos\frac{\theta}{2} \\ \sin\frac{\theta}{2} \end{bmatrix} = \cos\frac{\theta}{2}|0\rangle + \sin\frac{\theta}{2}|1\rangle$$ Therefore, applying the $R_y(2\alpha)$ gate to $|0\rangle$ is the solution to our problem. diff --git a/npm/qsharp/generate_katas_content.js b/npm/qsharp/generate_katas_content.js index 342c08bae0..08ad3e05c2 100644 --- a/npm/qsharp/generate_katas_content.js +++ b/npm/qsharp/generate_katas_content.js @@ -19,7 +19,21 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { basename, dirname, join, relative, sep } from "node:path"; import { fileURLToPath } from "node:url"; -import { marked } from "marked"; +import mdit from "markdown-it"; +const md = mdit("commonmark").disable(["escape"]); + +// Set up the Markdown renderer with KaTeX support for validation +import mk from "@vscode/markdown-it-katex"; +const mdValidator = mdit("commonmark"); +const katexOpts = { + enableMathBlockInHtml: true, + enableMathInlineInHtml: true, + throwOnError: true, +}; +// @ts-expect-error: This isn't typed correctly for some reason +mdValidator.use(mk.default, katexOpts); + +const validate = true; // Consider making this a command-line option const scriptDirPath = dirname(fileURLToPath(import.meta.url)); const katasContentPath = join(scriptDirPath, "..", "..", "katas", "content"); @@ -249,7 +263,15 @@ function createExample(baseFolderPath, properties) { } function createTextContent(markdown) { - const html = marked(markdown); + if (validate) { + try { + mdValidator.render(markdown); + } catch (e) { + console.log("LaTeX validation error: ", e); + } + } + + const html = md.render(markdown); return { type: "text-content", asHtml: html, asMarkdown: markdown }; } diff --git a/npm/qsharp/ux/estimatesPanel.tsx b/npm/qsharp/ux/estimatesPanel.tsx index 4f7093bc3e..8904dcbf65 100644 --- a/npm/qsharp/ux/estimatesPanel.tsx +++ b/npm/qsharp/ux/estimatesPanel.tsx @@ -13,7 +13,6 @@ export function EstimatesPanel(props: { colors: string[]; runNames: string[]; calculating: boolean; - renderer: (input: string) => string; onRowDeleted: (rowId: string) => void; }) { const [estimate, setEstimate] = useState(null); @@ -77,7 +76,7 @@ export function EstimatesPanel(props: { Resource Estimates - + )} diff --git a/npm/qsharp/ux/index.ts b/npm/qsharp/ux/index.ts index b8127db3da..aedfce7f3a 100644 --- a/npm/qsharp/ux/index.ts +++ b/npm/qsharp/ux/index.ts @@ -19,3 +19,4 @@ export { ScatterChart } from "./scatterChart.js"; export { EstimatesOverview } from "./estimatesOverview.js"; export { EstimatesPanel } from "./estimatesPanel.js"; export { Circuit, CircuitPanel } from "./circuit.js"; +export { setRenderer, Markdown } from "./renderers.js"; diff --git a/npm/qsharp/ux/reTable.tsx b/npm/qsharp/ux/reTable.tsx index fa6596bdf1..87bb062b1c 100644 --- a/npm/qsharp/ux/reTable.tsx +++ b/npm/qsharp/ux/reTable.tsx @@ -4,11 +4,9 @@ import { useState } from "preact/hooks"; import { SingleEstimateResult } from "./data.js"; import { CreateReport } from "./report.js"; +import { Markdown } from "./renderers.js"; -export function ReTable(props: { - mdRenderer: (input: string) => string; - estimatesData: SingleEstimateResult; -}) { +export function ReTable(props: { estimatesData: SingleEstimateResult }) { const [showDetail, setShowDetail] = useState(false); const toggleDetail = () => { setShowDetail(!showDetail); @@ -45,9 +43,6 @@ export function ReTable(props: { if (typeof value === "object") { value = JSON.stringify(value); } - const renderedExplanation = { - __html: props.mdRenderer(entry.explanation), - }; return (
{entry.label}
@@ -67,7 +59,7 @@ export function StateTable(props: { dump: Dump; latexDump: string }) { })}
-
+

); diff --git a/playground/src/tsconfig.json b/playground/src/tsconfig.json index 6a829dfdcd..a569184815 100644 --- a/playground/src/tsconfig.json +++ b/playground/src/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { - "module": "NodeNext", - "moduleResolution": "NodeNext", + "module": "es2020", + "moduleResolution": "bundler", "target": "ES2020", "noEmit": true, "lib": ["DOM", "ES2020"], @@ -11,6 +11,7 @@ "jsx": "react-jsx", "jsxImportSource": "preact", "skipLibCheck": true, - "customConditions": ["browser"] // Required as 'node' is automatically added also. + "customConditions": ["browser"], // Required as 'node' is automatically added also. + "types": [] } } diff --git a/vscode/build.mjs b/vscode/build.mjs index 8b0381122c..7ce44728e6 100644 --- a/vscode/build.mjs +++ b/vscode/build.mjs @@ -61,9 +61,14 @@ export function copyWasmToVsCode() { copyFileSync(qsharpWasm, join(qsharpDest, "qsc_wasm_bg.wasm")); } -function copyKatex() { +/** + * + * @param {string} [destDir] + * @param {boolean} [useLightTheme] + */ +export function copyKatex(destDir, useLightTheme) { let katexBase = join(libsDir, `katex/dist`); - let katexDest = join(thisDir, `out/katex`); + let katexDest = destDir ?? join(thisDir, `out/katex`); console.log("Copying the Katex files over from: " + katexBase); mkdirSync(katexDest, { recursive: true }); @@ -73,8 +78,11 @@ function copyKatex() { ); // Also copy the GitHub markdown CSS + const cssFileName = useLightTheme + ? "github-markdown-light.css" + : "github-markdown.css"; copyFileSync( - join(libsDir, "github-markdown-css/github-markdown.css"), + join(libsDir, `github-markdown-css/${cssFileName}`), join(katexDest, "github-markdown.css"), ); diff --git a/vscode/src/webview/webview.tsx b/vscode/src/webview/webview.tsx index 783d51c2e2..9e2d78e809 100644 --- a/vscode/src/webview/webview.tsx +++ b/vscode/src/webview/webview.tsx @@ -11,6 +11,7 @@ import { CircuitProps, EstimatesPanel, Histogram, + setRenderer, type ReData, } from "qsharp-lang/ux"; import { HelpPage } from "./help"; @@ -19,13 +20,12 @@ import { HelpPage } from "./help"; // @ts-ignore - there are no types for this import mk from "@vscode/markdown-it-katex"; import markdownIt from "markdown-it"; -const md = markdownIt(); -md.use(mk); - -function markdownRenderer(input: string) { - // For some reason all the escape characters are doubled in the estimate data sample input - return md.render(input.replace(/\\\\/g, "\\")); -} +const md = markdownIt("commonmark", { html: true, breaks: true }); +md.use(mk, { + enableMathBlockInHtml: true, + enableMathInlineInHtml: true, +}); +setRenderer((input: string) => md.render(input)); window.addEventListener("message", onMessage); window.addEventListener("load", main); @@ -169,7 +169,6 @@ function App({ state }: { state: State }) {