<jupyter_start><jupyter_text>4.5 通用量子门<jupyter_code>import numpy as np
from functools import reduce
np.set_printoptions(4, suppress=True, linewidth=150)
# Vector in computational basis
vec0 = np.array([1, 0])
vec1 = np.array([0, 1])
# Matrices in computational basis
I = np.eye(2)
X = np.array([[0, 1], [1, 0]])
Z = np.array([[1, 0], [0, -1]])
H = 1/np.sqrt(2) * np.array([[1, 1], [1, -1]])
T = np.array([[1, 0], [0, np.exp(1j*np.pi/4)]])
S = T @ T
P0 = np.outer(vec0, vec0)
P1 = np.outer(vec1, vec1)<jupyter_output><empty_output><jupyter_text>练习 4.36 :::{admonition} 练习 4.36构造一个把双比特数 $x$ 和 $y$ 进行模 4 加的量子线路，即线路可以完成 $|x, y\rangle \rightarrow |x, (x+y) \text{ mod } 4\rangle$ 的变换。::: 我们定义下述四个单量子比特数 $a, b, c, d, e, f \in \{0, 1\}$，并定义 $|x\rangle = |ab\rangle, |y\rangle = |cd\rangle$。题目所要求的线路是从 $|abcd\rangle \rightarrow |abef\rangle$ 的变换。 题目要求的 $ef$ 是二进制下的 $(ab+cd) \text{ mod } 4$ (这里 $ab$ 表示的不是乘法，而是二进制数 $a \times 2 + b$)。根据进位原则，$$\begin{align*}f &= b \oplus d = (b + d) \text{ mod } 2 \\e &= a \oplus c \oplus (b \times d) = (a + c + b \times d) \text{ mod } 2\end{align*}$$这两步操作分别在下述线路图中用蓝色与橙色框表示。![ex-4.36.1](assets/ex-4.36.1.svg)  练习 4.37 :::{admonition} 练习 4.37求变换$$U = \frac{1}{2} \begin{bmatrix}1 & 1 & 1 & 1 \\1 & i & -1 & -i \\1 & -1 & 1 & -1 \\1 & -i & -1 & i\end{bmatrix}$$的一个两级酉矩阵分解。这是量子 Fourier 变换的一个特例，下一章将作仔细研究。::: **作为量子 Fourier 变换的分解** 我们采用图 5.1 的结论，可以立即得到待求的 $U$ 就是下述线路：![ex-4.37.1](assets/ex-4.37.1.svg) 用数学的语言表述的话，是$$U = \mathrm{SWAP} (I \otimes H) (I \otimes P_0 + S \otimes P_1) (H \otimes I)$$<jupyter_code>U = 0.5 * np.array([
    [1,   1,  1,   1],
    [1,  1j, -1, -1j],
    [1,  -1,  1,  -1],
    [1, -1j, -1,  1j]
])
swap = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]])
np.allclose(swap @ np.kron(I, H) @ (np.kron(I, P0) + np.kron(S, P1)) @ np.kron(H, I), U)<jupyter_output><empty_output><jupyter_text>上式中，受控 $S$ 算符和 SWAP 算符都是二级酉矩阵，但作用于单量子比特的 $H$ 算符则还需要进一步展开。因此，我们写出下述线路：![ex-4.37.2](assets/ex-4.37.2.svg) $U = U_1^\dagger U_2^\dagger U_3^\dagger U_4^\dagger U_5^\dagger U_6^\dagger$ 的每个矩阵可以写为$$\begin{alignat*}{20}U_1^\dagger &= \begin{bmatrix}1 & 0 & 0 & 0 \\0 & 0 & 1 & 0 \\0 & 1 & 0 & 0 \\0 & 0 & 0 & 1\end{bmatrix}, \quadU_2^\dagger &&= \begin{bmatrix}1/\sqrt{2} & 1/\sqrt{2} & 0 & 0 \\1/\sqrt{2} & -1/\sqrt{2} & 0 & 0 \\0 & 0 & 1 & 0 \\0 & 0 & 0 & 1\end{bmatrix}, \quadU_3^\dagger &&= \begin{bmatrix}1 & 0 & 0 & 0 \\0 & 1 & 0 & 0 \\0 & 0 & 1/\sqrt{2} & 1/\sqrt{2} \\0 & 0 & 1/\sqrt{2} & -1/\sqrt{2}\end{bmatrix} \\U_4^\dagger &= \begin{bmatrix}1 & 0 & 0 & 0 \\0 & 1 & 0 & 0 \\0 & 0 & 1 & 0 \\0 & 0 & 0 & i\end{bmatrix}, \quadU_5^\dagger &&= \begin{bmatrix}1/\sqrt{2} & 0 & 1/\sqrt{2} & 0 \\0 & 1 & 0 & 0 \\1/\sqrt{2} & 0 & -1/\sqrt{2} & 0 \\0 & 0 & 0 & 1\end{bmatrix}, \quadU_6^\dagger &&= \begin{bmatrix}1 & 0 & 0 & 0 \\0 & 1/\sqrt{2} & 0 & 1/\sqrt{2} \\0 & 0 & 1 & 0 \\0 & 1/\sqrt{2} & 0 & -1/\sqrt{2}\end{bmatrix}\end{alignat*}$$ 验证上述计算过程的代码如下：<jupyter_code>U_list_fourier = [
    swap,
    np.kron(P1, I) + np.kron(P0, H),
    np.kron(P0, I) + np.kron(P1, H),
    np.kron(I, P0) + np.kron(S, P1),
    np.kron(I, P1) + np.kron(H, P0),
    np.kron(I, P0) + np.kron(H, P1),
]
np.allclose(reduce(np.dot, U_list_fourier), U)<jupyter_output><empty_output><jupyter_text>--- **标准做法** 上面是从第 5 章已经知道答案的情况下，对答案进行验证的过程。但这一节所给的标准做法是不断地消去非对角元。这个过程是非常清晰的，可以通过简单的程序直接给出。需要指出，最后一个矩阵的处理方式会稍微有些特别。<jupyter_code>def generate_two_level_unitary(M, axis1, axis2):
    """
    Input unitary matrix M, and give the matrix element position
    you want to set U.dot(M)[axis1, axis2] == 0,
    Output the desired two-level unitary matrix U.
    """
    U = np.eye(M.shape[0], dtype=M.dtype)
    a = M[axis2, axis2]
    b = M[axis1, axis2]
    r = np.linalg.norm([a, b])
    U[axis1, axis1] = - a / r
    U[axis1, axis2] = b / r
    U[axis2, axis1] = np.conj(b) / r
    U[axis2, axis2] = np.conj(a) / r
    return U
def generate_two_level_decompose(M):
    """
    Input unitary matrix M
    Output two-level unitary matrix decomposition list U_list
    """
    dim = M.shape[0]
    M_proc = M
    U_list = []
    # first (d-2) columns: regular process
    for j in range(dim-2):
        for i in range(j+1, dim):
            U = generate_two_level_unitary(M_proc, i, j)
            U_list.append(U.conj().T)
            M_proc = U @ M_proc
    # last transformation: special treatment
    U_last = np.eye(dim, dtype=M_proc.dtype)
    U_last[-2:, -2:] = M_proc[-2:, -2:]
    U_list.append(U_last)
    return U_list<jupyter_output><empty_output><jupyter_text>下面的程序可以给出题目所要求的二级酉矩阵。该结果比较复杂，但也是正确的。<jupyter_code>U_list = generate_two_level_decompose(U)
np.allclose(reduce(np.dot, U_list), U)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.21870967741935485, 'fraction_numerical': 0.06408602150537634, 'mean_word_length': 3.167562724014337, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '428265', 'license': 'CC-BY-4.0', 'n_tokens_mistral': 2545, 'n_tokens_neox': 2495, 'n_words': 483, 'path': 'source/chap_04/sec_04_05.ipynb', 'repo_name': 'ajz34/QCQI_exercises', 'size': '4650'}