<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Quantum Computing on Ping Zhou’s Personal Blog</title>
    <link>/quantum/</link>
    <description>Recent content in Quantum Computing on Ping Zhou’s Personal Blog</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Fri, 07 Jan 2022 00:00:00 +0000</lastBuildDate>
    <atom:link href="/quantum/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>量子信息的不可克隆性 (2)</title>
      <link>/quantum/no-clone-theorem-2/</link>
      <pubDate>Fri, 07 Jan 2022 00:00:00 +0000</pubDate>
      <guid>/quantum/no-clone-theorem-2/</guid>
      <description>&lt;p&gt;
接前文，继续聊量子信息的不可克隆性这个话题。在前文中，我们用最简单的CNOT门为例子，演示了为什么CNOT量子电路只能复制经典信息，而并不能复制处于一般态的量子位。今天把这个讨论扩展到一般的情况，来证明 &lt;b&gt;&lt;b&gt;复制量子态的机器不可能存在&lt;/b&gt;&lt;/b&gt; 。
&lt;/p&gt;

&lt;p&gt;
基本思路是用反证法。假设我们有个能复制一个量子位的机器，那么这个机器构成的系统，至少包含这些部分：
&lt;/p&gt;
&lt;ol class=&#34;org-ol&#34;&gt;
&lt;li&gt;被克隆的量子位， \(|\psi\rangle = \alpha|0\rangle + \beta|1\rangle\)&lt;/li&gt;
&lt;li&gt;辅助量子位， \(|\phi\rangle\)&lt;/li&gt;
&lt;li&gt;机器本身的状态 \(|A\rangle\) ，初始状态用 \(|A_i\rangle\) 表示&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
既然这个机器是量子电路构成的，这个“克隆”过程也必然是一个幺正变换。把这个幺正变换记作U，那么我们要达到的是这样的一个变换过程：
&lt;/p&gt;

\begin{matrix}
U |\psi\rangle |\phi\rangle |A_i\rangle \rightarrow |\psi\rangle |\psi\rangle |A_{f\psi}\rangle
\end{matrix}

&lt;p&gt;
也就是输入的 \(|\psi\rangle\) 被复制成了2个，而机器的状态由初始的 \(|A_i\rangle\) 变成了某个终态，这个终态必然是依赖于输入 \(|\psi\rangle\) ，所以记作 \(|A_{f\psi}\rangle\) 。
&lt;/p&gt;

&lt;p&gt;
显然，如果输入是 \(|0\rangle\) 或 \(|1\rangle\) 的话，我们有：
&lt;/p&gt;

\begin{matrix}
U |0\rangle |\phi\rangle |A_i\rangle \rightarrow |0\rangle |0\rangle |A_{f0}\rangle \\
U |1\rangle |\phi\rangle |A_i\rangle \rightarrow |1\rangle |1\rangle |A_{f1}\rangle \\
\end{matrix}

&lt;p&gt;
那么如果输入是一般的量子态呢？也就是
&lt;/p&gt;

&lt;p&gt;
\(|\psi\rangle = \alpha|0\rangle + \beta|1\rangle\) 
&lt;/p&gt;

&lt;p&gt;
把它代入到前面的变换过程里：
&lt;/p&gt;

\begin{matrix}
U |\psi\rangle |\phi\rangle |A_i\rangle \\
= U (\alpha|0\rangle + \beta|1\rangle) |\phi\rangle |A_i\rangle \\
\rightarrow \alpha U |0\rangle |\phi\rangle |A_{f0}\rangle + \beta U |1\rangle |\phi\rangle |A_{f1}\rangle \\
= \alpha |0\rangle |0\rangle |A_{f0}\rangle + \beta |1\rangle |1\rangle |A_{f1}\rangle \\
= \alpha |00\rangle |A_{f0}\rangle + \beta |11\rangle |A_{f1}\rangle \\
\end{matrix}

&lt;p&gt;
但是，这是不是我们想要的“克隆”效果呢？显然不是啊！我们要的“克隆”变换，变换后的状态应该是这样的：
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子信息的不可克隆性 (1)</title>
      <link>/quantum/no-clone-theorem-1/</link>
      <pubDate>Mon, 03 Jan 2022 00:00:00 +0000</pubDate>
      <guid>/quantum/no-clone-theorem-1/</guid>
      <description>&lt;p&gt;
如果你关注过量子通信或量子信息的动态，应该会经常听到量子信息的“不可克隆性”这个概念。那么这个概念是怎么来的？今天就来聊一聊。
&lt;/p&gt;

&lt;p&gt;
先从一个简单的例子出发。从以前对CNOT门的讨论，它似乎可以用来“复制”信息：
&lt;/p&gt;


&lt;div id=&#34;org656ed6e&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/no-clone-cnot.jpg&#34; alt=&#34;no-clone-cnot.jpg&#34; width=&#34;240px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
看起来当辅助量子位是 \(|0\rangle\) 的时候，输出就得到了两个 \(|x\rangle\) ，真的是这样吗？
&lt;/p&gt;

&lt;p&gt;
实际上，CNOT门只能复制经典信息（也就是输入为 \(|0\rangle\) 或 \(|1\rangle\) 的情况）。如果输入是一般状态 \(|\psi\rangle=a|0\rangle+b|1\rangle\) ，CNOT并不能复制它！
&lt;/p&gt;

&lt;p&gt;
咱们来具体推导一下。首先在输入端，要复制的量子位是 \(a|0\rangle+b|1\rangle\) ，辅助量子位 \(|0\rangle\) ，合起来输入端状态就是
&lt;/p&gt;

\begin{matrix}
(a|0\rangle + b|1\rangle)|0\rangle = a|00\rangle + b|10\rangle
\end{matrix}

&lt;p&gt;
CNOT的作用是当第一个量子位为1的时候翻转第二个量子位，所以我们在输出端得到的状态是
&lt;/p&gt;

\begin{matrix}
a|00\rangle + b|11\rangle &amp; (1) \\
\end{matrix}

&lt;p&gt;
但是，我们要的是在输出端复制 \(|\psi\rangle\) ，也就是在输出端得到 \(|\psi\rangle|\psi\rangle\) ，这个状态展开写就是这样：
&lt;/p&gt;

\begin{matrix}
|\psi\rangle|\psi\rangle = (a|0\rangle+b|1\rangle)(a|0\rangle+b|1\rangle) &amp; \\
= a^2|00\rangle + ab|01\rangle + ab|10\rangle + b^2|11\rangle &amp; (2) \\
\end{matrix}

&lt;p&gt;
比较一下(1)和(2)，只有当 \(ab=0\) ，也就是要复制的量子位为 \(|0\rangle\) 或 \(|1\rangle\) 时，这两个式子才有可能相等，而在一般情况下，(1)和(2)不可能相等。
&lt;/p&gt;

&lt;p&gt;
这个推导告诉我们，CNOT组成的“复制”电路，只能复制经典比特，不能复制处于一般态的量子位。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>脆弱的量子位：聊聊为什么量子计算机这么难造</title>
      <link>/quantum/why-quantum-is-hard/</link>
      <pubDate>Sat, 13 Nov 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/why-quantum-is-hard/</guid>
      <description>&lt;p&gt;
之前聊了不少量子计算的算法，今天换个话题，回到量子计算的一个根本问题，聊聊为什么量子计算机这么难制造。
&lt;/p&gt;

&lt;p&gt;
经典计算机里的晶体管，工作时状态是确定的0或1，这样的可靠性是因为晶体管的状态并不取决于单个电子，而是许多电子的平均。这样一来，即使有少数电子的状态受到干扰翻转了（例如电子在线路中逃逸了），也不影响整个晶体管的状态。这也是经典计算机能可靠工作的关键。
&lt;/p&gt;

&lt;p&gt;
举个例子来说，假如一个经典计算机里的比特由3个电子的状态表示，每个电子可能处于两种状态之一，记作 \(|\uparrow\rangle\) 和 \(|\downarrow\rangle\) 。在工作的时候，假如某个电子发生了翻转：
&lt;/p&gt;

\begin{matrix}
|\uparrow\uparrow\uparrow\rangle \Rightarrow |\uparrow\downarrow\uparrow\rangle
\end{matrix}

&lt;p&gt;
这种情况并不会造成经典比特的翻转。实际情况里，一个经典比特会由多得多的电子状态来表示，少数电子造成翻转的可能性就更小了，由此保证了经典计算机的可靠性。
&lt;/p&gt;

&lt;p&gt;
但是，这个性质也决定了经典计算机的『经典』特性，使它无法表现出『量子』的一面。
&lt;/p&gt;

&lt;p&gt;
设想一下，假如我们想用两个经典比特构造一个量子相干态：
&lt;/p&gt;

\begin{matrix}
|\uparrow\uparrow\uparrow\rangle |\downarrow\downarrow\uparrow\rangle
 + |\downarrow\downarrow\downarrow\rangle |\uparrow\uparrow\uparrow\rangle 
\end{matrix}

&lt;p&gt;
在逻辑上，这个状态可以写成
&lt;/p&gt;

\begin{matrix}
|L\rangle = |1\rangle |0\rangle + |0\rangle |1\rangle
\end{matrix}

&lt;p&gt;
假如某个电子翻转了，例如第一个晶体管的状态从 \(|\uparrow\uparrow\uparrow\rangle\) 变成了 \(|\uparrow\uparrow\downarrow\rangle\) ，物理状态发生了变化，但逻辑状态没有变：
&lt;/p&gt;

\begin{matrix}
|P\rangle = |\uparrow\uparrow\uparrow\rangle |\downarrow\downarrow\uparrow\rangle
 + |\downarrow\downarrow\downarrow\rangle
 |\uparrow\uparrow\uparrow\rangle \\
\Rightarrow
|\uparrow\uparrow\downarrow\rangle |\downarrow\downarrow\uparrow\rangle
 + |\downarrow\downarrow\downarrow\rangle |\uparrow\uparrow\uparrow\rangle \\
\\
|L\rangle = |1\rangle |0\rangle + |0\rangle |1\rangle \\
\Rightarrow |1\rangle |0\rangle + |0\rangle |1\rangle
\end{matrix}

&lt;p&gt;
您可能会问：这不挺好么？物理上虽然有电子发生了翻转，但逻辑上就像什么也没发生一样！
&lt;/p&gt;</description>
    </item>
    <item>
      <title>用量子搜索加速『NP完全』问题？</title>
      <link>/quantum/quantum_search_np/</link>
      <pubDate>Tue, 26 Oct 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/quantum_search_np/</guid>
      <description>&lt;p&gt;
最近和量子搜索干上了 :-) 聊聊另一个量子搜索的应用——加速NP完全问题的求解。
&lt;/p&gt;

&lt;p&gt;
学计算机朋友的应该都听说过『NP完全问题』。
&lt;/p&gt;

&lt;p&gt;
所谓NP完全问题（NP-complete problems），不是指某一个，而是指一类问题，它们的共同特征是，可以快速验证给定的答案是否正确（verify the solution），但是要找到正确的答案（find the solutions）则很难，目前还没有找到高效（多项式复杂度）的算法。并且这一类问题是可以互相转化的，也就是说如果某一个NP完全问题找到了高效的求解算法，那么所有其他的NP完全问题也都能够高效求解了。
&lt;/p&gt;

&lt;p&gt;
哈密尔顿回路问题（Hamilton cycle problem）就是一个NP完全问题。这个问题是说，给你一个图（有向或无向都可），请你找到一个访问图中所有顶点各一次的回路。这个问题又称为“旅行推销员问题”。
&lt;/p&gt;

&lt;p&gt;
用数学语言来分析，假设这个图有n个顶点 \(v_1, v_2, \dots, v_n\) ，我们要找的是一个包含n个顶点，也就是长度为n的路径。为方便讨论，我们假设允许顶点重复，那么把所有可能的长度为n的路径列出来，总共有 \(n^n\) 种可能，所以整个搜索空间有 \(n^n = 2^{n \log n}\) 个状态。哈密尔顿回路问题，就是要在这个搜索空间里找出符合条件的答案。
&lt;/p&gt;

&lt;p&gt;
显然，给定一个路径，我们很容易就能判断它是否是哈密尔顿回路，但是要从给定的图找到一个哈密尔顿回路，目前还没有发现高效（多项式）的算法。在经典计算机上，寻找哈密尔顿回路的复杂度是：
&lt;/p&gt;

\begin{matrix}
O(2^{n \lceil \log n \rceil})
\end{matrix}

&lt;p&gt;
那么在量子计算机上，是否可以做的更好呢？答案是肯定的。量子计算机可以对这个问题实现平方根（square root）加速：
&lt;/p&gt;

\begin{matrix}
O(2^{n \lceil \log n \rceil / 2})
\end{matrix}

&lt;p&gt;
接下来看看量子计算机是怎么做到的。
&lt;/p&gt;

&lt;p&gt;
首先我们得有个函数判断给定的路径是否是哈密尔顿回路：
&lt;/p&gt;

\begin{matrix}
f(v_1 v_2 \dots v_n) = \left\{
\begin{array}{ll}
1 &amp;&amp; v_1 v_2 \dots v_n \verb= is a Hamilton cycle= \\
0 &amp;&amp; otherwise
\end{array}
\right.
\end{matrix}

&lt;p&gt;
然后，把路径 \(v_1 v_2 \dots v_n\) 看作是量子电路的一个状态 \(|v\rangle\) 。比如，给某个顶点编号1到n，那么每个状态就是由n个1到n的数字来组成。显然要用二进制表示这样的状态，需要的肯定不止n比特，而是需要 \(n\log n\) 比特。因此在量子电路里需要 \(n\log n\) 个量子位来表示状态。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子搜索问题的扩展：量子计数</title>
      <link>/quantum/quantum_counting/</link>
      <pubDate>Tue, 19 Oct 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/quantum_counting/</guid>
      <description>&lt;p&gt;
前文&lt;a href=&#34;../grovers_algorithm_1/&#34;&gt;《量子搜索》&lt;/a&gt;讨论了Grover算法，今天来讨论量子搜索的一个扩展问题——量子计数。
&lt;/p&gt;

&lt;p&gt;
在量子搜索里，我们有一个搜索空间以及一个判断函数f，给定一个状态，f告诉我们它是不是要找的目标状态。Grover算法把f包装成一个G变换，经过多次迭代后测量，可以以任意高的概率得到答案（目标状态）。
&lt;/p&gt;

&lt;p&gt;
量子计数的问题和搜索有点类似，但它关注的是答案（目标状态）的数量：已知在N个项的搜索空间里有若干个（M个）答案，但是答案的数量M未知，如何高效的确定有多少个答案（也就是M的值）？
&lt;/p&gt;

&lt;p&gt;
如果用经典计算机来解决这个问题，就必须遍历整个搜索空间，也就是要查询 \(O(N)\) 次。
&lt;/p&gt;

&lt;p&gt;
如果用量子计算机的话，我们只需要用 \(O(\sqrt N)\) 次查询。相对经典计算机，这是一个多项式级别的加速（polynomial improvement）。之前讨论的&lt;a href=&#34;../shor_algorithm_1_rsa/&#34;&gt;Shor算法&lt;/a&gt;对因式分解问题有指数级加速，量子计数相比没那么耀眼，但也是一个显著的进步了。
&lt;/p&gt;

&lt;p&gt;
量子计数算法的思路其实很简单：把Grover算法中的G变换看作是相位估计里的U，放到量子相位估计电路里，根据估计出来的相位，就能得到目标状态的数量（M的值）。
&lt;/p&gt;

&lt;p&gt;
在&lt;a href=&#34;../grovers_algorithm_2/&#34;&gt;《Grover算法的可视化》&lt;/a&gt;一文中，我们知道G变换其实是一个旋转变换，画个图理解一下：
&lt;/p&gt;


&lt;div id=&#34;orgd92629e&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/quantum_counting_grover.jpg&#34; alt=&#34;quantum_counting_grover.jpg&#34; width=&#34;320px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
在这个图里， \(|\alpha\rangle\) 表示所有非目标状态的叠加，而 \(|\beta\rangle\) 是所有目标状态的叠加。显然它们互相是正交的，如果用它们作为两个轴张成一个平面，那么Grover算法里的G变换就是把输入向量 \(|\psi\rangle\) 朝着 \(|\beta\rangle\) 轴旋转一个角度 \(\theta\) 。因此G变换可以写成这样的矩阵：
&lt;/p&gt;

\begin{bmatrix}
\cos\theta &amp;&amp; -sin\theta \\
\sin\theta &amp;&amp; \cos\theta
\end{bmatrix}

&lt;p&gt;
不难证明， \(|\alpha\rangle\) 和 \(|\beta\rangle\) 是G的两个本征向量，并且它们对应的本征值分别是 \(e^{i\theta}\) 和 \(e^{i(2\pi-\theta)}\) 。如果你有兴趣，可以拿纸笔验证一下。:-) 总之，这个G变换可以作为量子相位估计里的U来使用。
&lt;/p&gt;

&lt;p&gt;
把Grover算法里的G变换放到量子相位估计里：
&lt;/p&gt;


&lt;div id=&#34;org52fbffd&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/quantum_counting_circuit.jpg&#34; alt=&#34;quantum_counting_circuit.jpg&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
假设搜索空间大小N可以用n位二进制数表示，这里输入用了n+1位，也就是把搜索空间扩大了一倍。为什么要这么做呢？
&lt;/p&gt;

&lt;p&gt;
还记得前文讨论Grover算法有个特殊情况吗？就是目标状态（答案）的数量M超过N的一半，这种情况下Grover算法的性能反而会变差，因为每次旋转的角度太大了，转过头了。解决的办法，就是把搜索空间扩大一倍，确保目标状态的数量少于搜索空间的一半。这里用了同样的思路，因为我们不知道M是多少，干脆先在输入端把N扩大成2N，确保M少于搜索空间的一半。
&lt;/p&gt;

&lt;p&gt;
另一个寄存器需要的量子位数目t，是由我们需要的精度和成功率来决定。例如，假如我们需要相位估计达到m比特的精度，并且成功率大于 \(1-\epsilon\) ，那么t可以这样估算：
&lt;/p&gt;

\begin{matrix}
t = m + \lceil \log (2+\frac{1}{2\epsilon}) \rceil
\end{matrix}

&lt;p&gt;
运行这个电路，在右边测量得到相位估计的结果，也就是 \(\theta\) 的近似值。
&lt;/p&gt;

&lt;p&gt;
而根据Grover算法的原理和G变换的性质，我们知道：
&lt;/p&gt;

\begin{matrix}
\sin \frac{\theta}{2} = \sqrt \frac{M}{2N}
\end{matrix}

&lt;p&gt;
因此：
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子相位估计的应用：求解幺正变换的平方根</title>
      <link>/quantum/square_root_of_unitary/</link>
      <pubDate>Fri, 27 Aug 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/square_root_of_unitary/</guid>
      <description>&lt;p&gt;
在前文&lt;a href=&#34;../phase-estimation/&#34;&gt;《量子相位估计》&lt;/a&gt;里，我们讨论了量子相位估计算法，它也是很多量子算法能有指数级加速的关键。今天来讨论量子相位估计的另一个应用：求解给定幺正变换的平方根。
&lt;/p&gt;

&lt;p&gt;
假如我们有一个幺正变换 \(U\) ，求解它的k次方 \(U^k\) 很容易，只要把k个 \(U\) 连起来就行，但是如果要求它的平方根 \(U^{1/2}\) 呢？事情就没那么简单了。今天来讨论一下，如何利用量子相位估计来求给定幺正变换的平方根，或者说，构造一个新的幺正变换，使它的平方等于给定的幺正变换。
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;先回顾一下什么是量子相位估计。&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
假如我们有一个幺正算符 \(U\) ， \(|u\rangle\) 是它的一个本征矢量，对应的本征值是 \(e^{i\phi}\) （ \(\phi\) 在0到 \(2\pi\) 之间）：
&lt;/p&gt;

\begin{matrix}
U|u\rangle = e^{i\phi}|u\rangle
\end{matrix}

&lt;p&gt;
&#34;量子相位估计&#34;问题，就是从幺正算符 \(U\) 和 \(|u\rangle\) ，估算相应的本征值 \(e^{i\phi}\) 里的相位 \(\phi\) 。
&lt;/p&gt;

&lt;p&gt;
量子相位估计的电路如下，输入 \(|u\rangle\) 是U的一个本征向量，在输出端测量，就能得到其本征值的相位 \(\psi=\phi/2\pi\) 的 &lt;b&gt;n位二进制近似&lt;/b&gt; 。
&lt;/p&gt;


&lt;div id=&#34;org072ec78&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/phase_estimation_simplified.jpg&#34; alt=&#34;phase_estimation_simplified.jpg&#34; width=&#34;400px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
你可能注意到，这里的输入 \(|u\rangle\) 是U的 &lt;b&gt;一个&lt;/b&gt; 本征向量。但是，U可能有很多个本征向量，对不对？
&lt;/p&gt;

&lt;p&gt;
如果这个相位估计电路输入的不是某一个本征向量，而是U所有本征向量的叠加呢？右边输出会得到什么？也就是说，如果左边的输入是U的所有本征向量 \(|u_j\rangle\) 的叠加：
&lt;/p&gt;

\begin{matrix}
|\psi\rangle = \sum_j \alpha_j |u_j\rangle
\end{matrix}

&lt;p&gt;
猜猜右边会得到啥？
&lt;/p&gt;


&lt;div id=&#34;orgca53643&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/phase_estimation_simplified_generic.jpg&#34; alt=&#34;phase_estimation_simplified_generic.jpg&#34; width=&#34;400px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
答案很容易猜到，既然左边的输入是本征向量的叠加，那么右边的输出，就是对应的相位估计结果的叠加：
&lt;/p&gt;

\begin{matrix}
U|\psi\rangle = \sum_j \alpha_j e^{i\phi_j} |u_j\rangle
\end{matrix}

&lt;p&gt;
也就是说，如果在右边测量，会得到某一个本征向量 \(|u_j\rangle\) 的相位估计，其概率取决于它在输入的叠加态里的强度 \(|\alpha_i|^2\) 。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子计算里用到的一些数学概念</title>
      <link>/quantum/theory-and-concepts/</link>
      <pubDate>Sat, 14 Aug 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/theory-and-concepts/</guid>
      <description>&lt;div id=&#34;outline-container-org490c832&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org490c832&#34;&gt;线性独立&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org490c832&#34;&gt;
&lt;p&gt;
如果一组矢量 \(|\alpha_1\rangle, \dots, \alpha_m\rangle\) 满足：
&lt;/p&gt;

\begin{matrix}
c_1|\alpha_1\rangle + c_2|\alpha_2\rangle + \dots + c_m|\alpha_m\rangle = 0
\end{matrix}

&lt;p&gt;
当且仅当
&lt;/p&gt;
\begin{matrix}
c_1 = c_2 = \dots = c_m = 0
\end{matrix}

&lt;p&gt;
那么称这组矢量就是线性独立的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orge59fc26&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orge59fc26&#34;&gt;内积&lt;/h2&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org41177cb&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org41177cb&#34;&gt;模&lt;/h2&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org6ac3171&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org6ac3171&#34;&gt;柯西-施瓦茨不等式&lt;/h2&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orgf84e054&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgf84e054&#34;&gt;正交归一&lt;/h2&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org7f5d1bf&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org7f5d1bf&#34;&gt;维数&lt;/h2&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org69620db&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org69620db&#34;&gt;Gram-Schmidt分解，构造正交归一基方法&lt;/h2&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org46e0339&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org46e0339&#34;&gt;线性算符&lt;/h2&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org7c50986&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org7c50986&#34;&gt;线性算符之积&lt;/h2&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org97b4127&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org97b4127&#34;&gt;完备性关系&lt;/h2&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org34cc317&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org34cc317&#34;&gt;线性算符的矩阵表示&lt;/h2&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org9335b58&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org9335b58&#34;&gt;Pauli矩阵&lt;/h2&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org647d2c6&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org647d2c6&#34;&gt;投影算符&lt;/h2&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orgc59f7e9&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgc59f7e9&#34;&gt;多维子空间中的投影算符&lt;/h2&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org97bd8d9&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org97bd8d9&#34;&gt;本征值，本征矢量&lt;/h2&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org3be5f31&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org3be5f31&#34;&gt;厄米算符(Hermitian?)&lt;/h2&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org32ce75a&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org32ce75a&#34;&gt;逆算符&lt;/h2&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org7973c34&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org7973c34&#34;&gt;幺正算符&lt;/h2&gt;
&lt;/div&gt;</description>
    </item>
    <item>
      <title>量子相位估计 Phase Estimation</title>
      <link>/quantum/phase-estimation/</link>
      <pubDate>Mon, 26 Jul 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/phase-estimation/</guid>
      <description>&lt;p&gt;
之前的Shor算法系列，其实还有个相关的坑，就是“量子相位估计” (Phase Estimation)，今天也来填一下。:-)
&lt;/p&gt;

&lt;div id=&#34;outline-container-orgfdf32e5&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgfdf32e5&#34;&gt;什么是“量子相位估计”？&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgfdf32e5&#34;&gt;
&lt;p&gt;
假如我们有一个幺正算符 \(U\) ，他的本征矢量是 \(|u\rangle\) ，本征值是 \(e^{i\phi}\) （ \(\phi\) 在0到 \(2\pi\) 之间）。
&lt;/p&gt;

&lt;p&gt;
&#34;量子相位估计“问题，就是从幺正算符 \(U\) 和它的本征矢量 \(|u\rangle\) ，估算它的本征值 \(e^{i\phi}\) 里的相位 \(\phi\) ：
&lt;/p&gt;

&lt;p&gt;
Estimate phase \(\phi\) of an eigenvalue of an unitary operator \(U\), given its eigenvector \(|u\rangle\).
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orgb6aaa96&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgb6aaa96&#34;&gt;量子相位估计算法&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgb6aaa96&#34;&gt;
&lt;p&gt;
既然幺正算符 \(U\) 的本征矢量是 \(|u\rangle\) ，并且其对应的本征值是 \(e^{i\phi}\) ，那么根据本征矢量的定义：
&lt;/p&gt;

\begin{matrix}
U|u\rangle = e^{i\phi}|u\rangle
\end{matrix}

&lt;p&gt;
那么如果对 \(|u\rangle\) 进行多次U变换，不难推导出：
&lt;/p&gt;

\begin{matrix}
U^k|u\rangle = e^{ik\phi}|u\rangle
\end{matrix}

&lt;p&gt;
所以多次对 \(|u\rangle\) 进行 \(U\) 变换，得到的状态仍然是 \(|u\rangle\) ，只不过给它增加了一个全局相位。
&lt;/p&gt;

&lt;p&gt;
我们可以从 \(U\) 制备出一组（n个）这样的幺正变换： \(U, U^2, U^4, U^8, \dots, U^{2^{n-1}}\)
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子傅里叶变换详解 (3) 电路实现</title>
      <link>/quantum/qft-3/</link>
      <pubDate>Mon, 12 Jul 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/qft-3/</guid>
      <description>&lt;p&gt;
今天来填个坑 :-) 前面Shor算法系列里大量用到的“量子傅立叶变换”，具体要怎么实现？这次来详细讨论一下。
&lt;/p&gt;

&lt;div id=&#34;outline-container-org338c92b&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org338c92b&#34;&gt;量子傅立叶变换&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org338c92b&#34;&gt;
&lt;p&gt;
&lt;a href=&#34;../qft-1/&#34;&gt;前文&lt;/a&gt;说过，量子傅立叶变换QFT是这么一块电路：
&lt;/p&gt;


&lt;div id=&#34;orgef810d9&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/qft_box.jpg&#34; alt=&#34;qft_box.jpg&#34; width=&#34;560px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
同样根据&lt;a href=&#34;../qft-1/&#34;&gt;前文&lt;/a&gt;，当输入n个量子位的基态 \(|j\rangle\) 时，输出可以写成：
&lt;/p&gt;

\begin{matrix}
QFT|j\rangle = \\
\frac{1}{\sqrt{2^n}} \otimes_{l=1}^n \left[ |0\rangle + e^{2\pi ij/2^l} |1\rangle \right] \\
= \frac{1}{\sqrt{2^n}}
\left( |0\rangle + e^{2\pi i 0.j_0}|1\rangle \right)
\left( |0\rangle + e^{2\pi i 0.j_1j_0}|1\rangle \right)
\dots
\left( |0\rangle + e^{2\pi i 0.j_{n-1}j_{n-2}\dots j_0}|1\rangle \right) \\
\end{matrix}

&lt;p&gt;
我们的任务是用基本量子电路门构造这样的变换。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org2214a2e&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org2214a2e&#34;&gt;基本构件：受控旋转门&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org2214a2e&#34;&gt;
&lt;p&gt;
就像搭积木一样，量子傅立叶变换的电路是由很多基本组件构成的。其中最重要的一个组件是“受控旋转门” \(R_k\) ：
&lt;/p&gt;


&lt;div id=&#34;orgf20cc67&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/qft_rk.jpg&#34; alt=&#34;qft_rk.jpg&#34; width=&#34;160px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这个量子门和CNOT门差不多，有一个控制输入，当控制输入是 \(|0\rangle\) 的时候，输入状态原样输出；而如果控制输入是 \(|1\rangle\) ，就对输入状态绕Z轴旋转一定的角度。旋转多少角度呢？这是由门的参数k决定的，具体来说就是 \(2\pi/2^k\) 。换句话说， \(R_k\) 的作用就是当控制输入为 \(|1\rangle\) 时，给输入作这样的一个变换：
&lt;/p&gt;

\begin{bmatrix}
1 &amp; 0 \\
0 &amp; e^{\frac{2\pi i}{2^k}}
\end{bmatrix}
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org7dbb425&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org7dbb425&#34;&gt;量子傅立叶变换电路&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org7dbb425&#34;&gt;
&lt;p&gt;
有了受控旋转门 \(R_k\) ，接下来我们就可以来搭建量子傅里叶变换电路了！
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子算法之Simon问题</title>
      <link>/quantum/simons_problem/</link>
      <pubDate>Wed, 07 Jul 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/simons_problem/</guid>
      <description>&lt;p&gt;
随手翻到一个Simon问题，今天就来聊聊它。Simon问题和之前讨论的Deutsch问题有点类似，也是一个用量子计算机能够达到指数级加速的问题。
&lt;/p&gt;

&lt;div id=&#34;outline-container-org466d1ff&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org466d1ff&#34;&gt;什么是Simon问题？&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org466d1ff&#34;&gt;
&lt;p&gt;
和Deutsch问题类似，假设有人给我们一个函数f(x)，内部实现未知，只知道它输入n位二进制数，输出也是n位二进制数。用数学语言描述就是这样：
&lt;/p&gt;

\begin{matrix}
f: \{ 0,1 \}^n \rightarrow \{ 0,1 \}^n
\end{matrix}

&lt;p&gt;
然后又知道存在某个数a，使得 \(f(y)=f(x)\) 当且仅当 \(y=x \oplus a\) ，这个a也称作函数f(x)的周期。为方便讨论，假设a不是0。
&lt;/p&gt;

&lt;p&gt;
Simon问题要解决的，就是求解这个周期a的值。
&lt;/p&gt;

&lt;p&gt;
在经典计算机上，这是一个困难的问题。因为f(x)是未知的，我们能做的就是从0到 \(2^n-1\) 中，每次选一个数作为输入计算f(x)，直到发现重复的输出。最坏情况下，需要遍历超过一半的输入，即 \(2^{n-1}+1\) 次。根据Birthday Paradox，这个问题在经典计算机上需要的查询次数（时间复杂度）是 \(O(2^{n/2})\) 。
&lt;/p&gt;

&lt;p&gt;
而在量子计算机上，我们只需要运行电路 \(O(n)\) 次就能以任意高的成功率得到结果。相对经典计算机，这是 &lt;b&gt;指数级别&lt;/b&gt; 的加速！
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orgae168f1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgae168f1&#34;&gt;Simon问题的量子算法&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgae168f1&#34;&gt;
&lt;p&gt;
和之前的其他量子算法一样，首先我们得把函数f(x)包装成可逆变换 \(U_f\) ：
&lt;/p&gt;


&lt;div id=&#34;org2a3e2d0&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/simon_uf.jpg&#34; alt=&#34;simon_uf.jpg&#34; width=&#34;240px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
然后放到Simon问题的量子电路里：
&lt;/p&gt;

&lt;div id=&#34;org3c1c036&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/simon_circuit.jpg&#34; alt=&#34;simon_circuit.jpg&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
接下来我们来详细分析一下这个量子算法的过程。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org8c8e485&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;org8c8e485&#34;&gt;t0时刻&lt;/h3&gt;
&lt;div class=&#34;outline-text-3&#34; id=&#34;text-org8c8e485&#34;&gt;
&lt;p&gt;
第一个寄存器经过n位的H变换，变成 \(|0\rangle\) 到 \(|2^n-1\rangle\) 的叠加态，即 \(\frac{1}{2^{n/2}}\sum_{x=0}^{2^n-1}|x\rangle\) 。
&lt;/p&gt;

&lt;p&gt;
第二个寄存器状态是 \(|0\rangle\) 。
&lt;/p&gt;

&lt;p&gt;
所以合起来，t0时刻的状态是 \(\frac{1}{2^{n/2}}\sum_{x=0}^{2^n-1}|x\rangle|0\rangle\)
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orgde1d063&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;orgde1d063&#34;&gt;t1时刻&lt;/h3&gt;
&lt;div class=&#34;outline-text-3&#34; id=&#34;text-orgde1d063&#34;&gt;
&lt;p&gt;
经过 \(U_f\) 变换，两个寄存器进入纠缠态，第一个寄存器还是 \(\frac{1}{2^{n/2}}\sum_{x=0}^{2^n-1}|x\rangle\) ，第二个寄存器变成了 \(|f(x)\rangle\) 。所以系统状态是：
&lt;/p&gt;

&lt;p&gt;
\(\frac{1}{2^{n/2}}\sum_{x=0}^{2^n-1}|x\rangle|f(x)\rangle\) 
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orgf6d728e&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;orgf6d728e&#34;&gt;t2时刻&lt;/h3&gt;
&lt;div class=&#34;outline-text-3&#34; id=&#34;text-orgf6d728e&#34;&gt;
&lt;p&gt;
对第二个寄存器进行测量，使它坍缩到某个值 \(z=f(x_0)\) 。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>实战：用Cirq实现量子因式分解算法</title>
      <link>/quantum/shor_impl_cirq/</link>
      <pubDate>Fri, 02 Jul 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/shor_impl_cirq/</guid>
      <description>&lt;p&gt;
前面的“量子因式分解系列”讨论了Shor算法和它的量子电路，今天切换到编程模式，用谷歌的Cirq框架来实现Shor算法，并用它来解决简单的因式分解问题。
&lt;/p&gt;

&lt;div id=&#34;outline-container-orgf5e259a&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgf5e259a&#34;&gt;导入依赖包&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgf5e259a&#34;&gt;
&lt;p&gt;
首先还是导入需要的包：
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-python&#34;&gt;&lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; fractions
&lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; math
&lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; random
&lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; sympy
&lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; cirq
&lt;span style=&#34;font-weight: bold;&#34;&gt;from&lt;/span&gt; cirq.contrib.svg &lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; SVGCircuit
&lt;span style=&#34;font-weight: bold;&#34;&gt;from&lt;/span&gt; typing &lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; Callable, List, Optional, Sequence, Union
%matplotlib inline
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org343ecb1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org343ecb1&#34;&gt;指数取模运算&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org343ecb1&#34;&gt;
&lt;p&gt;
还记得Shor算法的量子电路吗？
&lt;/p&gt;

&lt;div id=&#34;orgece4048&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/shor2_uf3.png&#34; alt=&#34;shor2_uf3.png&#34; width=&#34;400px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
首先，我们需要一个“指数取模”的量子变换 \(U_f\) :
&lt;/p&gt;

\begin{matrix}
U_f |x\rangle|y\rangle \rightarrow |x\rangle|ya^x \mod N\rangle
\end{matrix}

&lt;p&gt;
它的输入 \(|x\rangle|y\rangle\) ，输出是 \(|x\rangle|ya^x \mod N\rangle\) 。
&lt;/p&gt;

&lt;p&gt;
在Cirq里面怎么实现这个变换呢？一种办法是按照我之前的文章《聊聊量子因式分解算法的实现》，从加法器和乘法器开始，逐层往上实现。这个工程量就大了，我们也没有真的量子计算机可以跑不是？另一种方法是，利用Cirq框架提供的ArithmeticOperation接口，用经典计算来模拟这个变换：
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-python&#34;&gt;&lt;span style=&#34;font-weight: bold;&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;mod_pow&lt;/span&gt;(a:&lt;span style=&#34;font-weight: bold;&#34;&gt;int&lt;/span&gt;, x:&lt;span style=&#34;font-weight: bold;&#34;&gt;int&lt;/span&gt;, N:&lt;span style=&#34;font-weight: bold;&#34;&gt;int&lt;/span&gt;, y:&lt;span style=&#34;font-weight: bold;&#34;&gt;int&lt;/span&gt;=1) -&amp;gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;int&lt;/span&gt;:
    &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;p&lt;/span&gt; = y
    &lt;span style=&#34;font-weight: bold;&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;font-weight: bold;&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;range&lt;/span&gt;(x):
        &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;p&lt;/span&gt; = (p * a) % N
        &lt;span style=&#34;font-weight: bold;&#34;&gt;return&lt;/span&gt; p

&lt;span style=&#34;font-weight: bold;&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;ModularExp&lt;/span&gt;(cirq.ArithmeticOperation):
    &lt;span style=&#34;font-weight: bold;&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;__init__&lt;/span&gt;(
        &lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;,
        y: Sequence[cirq.Qid],
        x: Union[&lt;span style=&#34;font-weight: bold;&#34;&gt;int&lt;/span&gt;, Sequence[cirq.Qid]],
        a: &lt;span style=&#34;font-weight: bold;&#34;&gt;int&lt;/span&gt;,
        N: &lt;span style=&#34;font-weight: bold;&#34;&gt;int&lt;/span&gt;,
    ) -&amp;gt; &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;None&lt;/span&gt;:
        &lt;span style=&#34;font-weight: bold;&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;len&lt;/span&gt;(y) &amp;lt; N.bit_length():
            &lt;span style=&#34;font-weight: bold;&#34;&gt;raise&lt;/span&gt; &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;ValueError&lt;/span&gt;(
                f&lt;span style=&#34;font-style: italic;&#34;&gt;&#39;Register with &lt;/span&gt;{&lt;span style=&#34;font-weight: bold;&#34;&gt;len&lt;/span&gt;(y)}&lt;span style=&#34;font-style: italic;&#34;&gt; qubits is too small for N &lt;/span&gt;{N}&lt;span style=&#34;font-style: italic;&#34;&gt;&#39;&lt;/span&gt;
            )
        &lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;y&lt;/span&gt; = y
        &lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;x&lt;/span&gt; = x
        &lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;a&lt;/span&gt; = a
        &lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;N&lt;/span&gt; = N

    &lt;span style=&#34;font-weight: bold;&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;registers&lt;/span&gt;(&lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;) -&amp;gt; Sequence[Union[&lt;span style=&#34;font-weight: bold;&#34;&gt;int&lt;/span&gt;, Sequence[cirq.Qid]]]:
        &lt;span style=&#34;font-weight: bold;&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;.y, &lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;.x, &lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;.a, &lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;.N

    &lt;span style=&#34;font-weight: bold;&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;with_registers&lt;/span&gt;(
        &lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;,
        *new_registers: Union[&lt;span style=&#34;font-weight: bold;&#34;&gt;int&lt;/span&gt;, Sequence[&lt;span style=&#34;font-style: italic;&#34;&gt;&#39;cirq.Qid&#39;&lt;/span&gt;]],
    ) -&amp;gt; &lt;span style=&#34;font-style: italic;&#34;&gt;&#39;ModularExp&#39;&lt;/span&gt;:
        &lt;span style=&#34;font-weight: bold;&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;len&lt;/span&gt;(new_registers) != 4:
            &lt;span style=&#34;font-weight: bold;&#34;&gt;raise&lt;/span&gt; &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;ValueError&lt;/span&gt;(
                f&lt;span style=&#34;font-style: italic;&#34;&gt;&#39;Expected 4 registers (y, x, a, &#39;&lt;/span&gt;
                f&lt;span style=&#34;font-style: italic;&#34;&gt;&#39;N), but got &lt;/span&gt;{&lt;span style=&#34;font-weight: bold;&#34;&gt;len&lt;/span&gt;(new_registers)}&lt;span style=&#34;font-style: italic;&#34;&gt;&#39;&lt;/span&gt;
            )
        &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;y&lt;/span&gt;, &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;x&lt;/span&gt;, &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;a&lt;/span&gt;, &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;N&lt;/span&gt; = new_registers
        &lt;span style=&#34;font-weight: bold;&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;isinstance&lt;/span&gt;(y, Sequence):
            &lt;span style=&#34;font-weight: bold;&#34;&gt;raise&lt;/span&gt; &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;ValueError&lt;/span&gt;(f&lt;span style=&#34;font-style: italic;&#34;&gt;&#39;y must be a qubit register, got &lt;/span&gt;{&lt;span style=&#34;font-weight: bold;&#34;&gt;type&lt;/span&gt;(y)}&lt;span style=&#34;font-style: italic;&#34;&gt;&#39;&lt;/span&gt;)
        &lt;span style=&#34;font-weight: bold;&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;isinstance&lt;/span&gt;(a, &lt;span style=&#34;font-weight: bold;&#34;&gt;int&lt;/span&gt;):
            &lt;span style=&#34;font-weight: bold;&#34;&gt;raise&lt;/span&gt; &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;ValueError&lt;/span&gt;(f&lt;span style=&#34;font-style: italic;&#34;&gt;&#39;a must be a classical constant, got &lt;/span&gt;{&lt;span style=&#34;font-weight: bold;&#34;&gt;type&lt;/span&gt;(a)}&lt;span style=&#34;font-style: italic;&#34;&gt;&#39;&lt;/span&gt;)
        &lt;span style=&#34;font-weight: bold;&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;isinstance&lt;/span&gt;(N, &lt;span style=&#34;font-weight: bold;&#34;&gt;int&lt;/span&gt;):
            &lt;span style=&#34;font-weight: bold;&#34;&gt;raise&lt;/span&gt; &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;ValueError&lt;/span&gt;(f&lt;span style=&#34;font-style: italic;&#34;&gt;&#39;N must be a classical constant, got &lt;/span&gt;{&lt;span style=&#34;font-weight: bold;&#34;&gt;type&lt;/span&gt;(N)}&lt;span style=&#34;font-style: italic;&#34;&gt;&#39;&lt;/span&gt;)
        &lt;span style=&#34;font-weight: bold;&#34;&gt;return&lt;/span&gt; ModularExp(y, x, a, N)

    &lt;span style=&#34;font-weight: bold;&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;apply&lt;/span&gt;(&lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;, *register_values: &lt;span style=&#34;font-weight: bold;&#34;&gt;int&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;int&lt;/span&gt;:
        &lt;span style=&#34;font-weight: bold;&#34;&gt;assert&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;len&lt;/span&gt;(register_values) == 4
        &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;y&lt;/span&gt;, &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;x&lt;/span&gt;, &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;a&lt;/span&gt;, &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;N&lt;/span&gt; = register_values
        &lt;span style=&#34;font-weight: bold;&#34;&gt;if&lt;/span&gt; y &amp;gt;= N:
            &lt;span style=&#34;font-weight: bold;&#34;&gt;return&lt;/span&gt; y
        &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;# &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;return (y * a ** x) % N
&lt;/span&gt;        &lt;span style=&#34;font-weight: bold;&#34;&gt;return&lt;/span&gt; mod_pow(a=a, x=x, N=N, y=y)

    &lt;span style=&#34;font-weight: bold;&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;_circuit_diagram_info_&lt;/span&gt;(
        &lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;,
        args: cirq.CircuitDiagramInfoArgs,
    ) -&amp;gt; cirq.CircuitDiagramInfo:
        &lt;span style=&#34;font-weight: bold;&#34;&gt;assert&lt;/span&gt; args.known_qubits &lt;span style=&#34;font-weight: bold;&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;None&lt;/span&gt;
        &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;wire_symbols&lt;/span&gt;: List[&lt;span style=&#34;font-weight: bold;&#34;&gt;str&lt;/span&gt;] = []
        &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;t&lt;/span&gt;, &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;e&lt;/span&gt; = 0, 0
        &lt;span style=&#34;font-weight: bold;&#34;&gt;for&lt;/span&gt; qubit &lt;span style=&#34;font-weight: bold;&#34;&gt;in&lt;/span&gt; args.known_qubits:
            &lt;span style=&#34;font-weight: bold;&#34;&gt;if&lt;/span&gt; qubit &lt;span style=&#34;font-weight: bold;&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;.y:
                &lt;span style=&#34;font-weight: bold;&#34;&gt;if&lt;/span&gt; t == 0:
                    &lt;span style=&#34;font-weight: bold;&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;isinstance&lt;/span&gt;(&lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;.x, Sequence):
                        &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;e_str&lt;/span&gt; = &lt;span style=&#34;font-style: italic;&#34;&gt;&#39;e&#39;&lt;/span&gt;
                    &lt;span style=&#34;font-weight: bold;&#34;&gt;else&lt;/span&gt;:
                        &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;e_str&lt;/span&gt; = &lt;span style=&#34;font-weight: bold;&#34;&gt;str&lt;/span&gt;(&lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;.x)
                    wire_symbols.append(f&lt;span style=&#34;font-style: italic;&#34;&gt;&#39;ModularExp(t*&lt;/span&gt;{&lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;.a}&lt;span style=&#34;font-style: italic;&#34;&gt;**&lt;/span&gt;{e_str}&lt;span style=&#34;font-style: italic;&#34;&gt; % &lt;/span&gt;{&lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;.N}&lt;span style=&#34;font-style: italic;&#34;&gt;)&#39;&lt;/span&gt;)
                &lt;span style=&#34;font-weight: bold;&#34;&gt;else&lt;/span&gt;:
                    wire_symbols.append(&lt;span style=&#34;font-style: italic;&#34;&gt;&#39;t&#39;&lt;/span&gt; + &lt;span style=&#34;font-weight: bold;&#34;&gt;str&lt;/span&gt;(t))
                &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;t&lt;/span&gt; += 1
            &lt;span style=&#34;font-weight: bold;&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;isinstance&lt;/span&gt;(&lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;.x, Sequence) &lt;span style=&#34;font-weight: bold;&#34;&gt;and&lt;/span&gt; qubit &lt;span style=&#34;font-weight: bold;&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;.x:
                wire_symbols.append(&lt;span style=&#34;font-style: italic;&#34;&gt;&#39;e&#39;&lt;/span&gt; + &lt;span style=&#34;font-weight: bold;&#34;&gt;str&lt;/span&gt;(e))
                &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;e&lt;/span&gt; += 1
        &lt;span style=&#34;font-weight: bold;&#34;&gt;return&lt;/span&gt; cirq.CircuitDiagramInfo(wire_symbols=&lt;span style=&#34;font-weight: bold;&#34;&gt;tuple&lt;/span&gt;(wire_symbols))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
利用cirq.ArithmeticOperation接口，模拟实现一个指数取模变换ModularExp，这其中的核心就是apply函数：
&lt;/p&gt;</description>
    </item>
    <item>
      <title>聊聊量子因式分解算法的实现</title>
      <link>/quantum/shor_impl_thoughts/</link>
      <pubDate>Tue, 22 Jun 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/shor_impl_thoughts/</guid>
      <description>&lt;p&gt;
在前面的Shor算法系列中，我讨论了用量子计算进行因式分解的思路。但是这些基本上都是理论上的推导，实际要实现量子因式分解，有哪些难点？解决的思路又是什么？今天就来聊聊我的实现方法。
&lt;/p&gt;

&lt;div id=&#34;outline-container-org46e806b&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org46e806b&#34;&gt;Shor算法实现的难点：指数取模&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org46e806b&#34;&gt;
&lt;p&gt;
在Shor算法中，我们用量子计算来寻找函数 \(f(x)=a^x \mod N\) 的周期（order），并且这一步也是Shor算法中唯一的『量子』部分。
&lt;/p&gt;


&lt;div id=&#34;org9fed0f4&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/shor2_uf3.png&#34; alt=&#34;shor2_uf3.png&#34; width=&#34;400px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
为什么Shor算法这么设计？因为“order finding”这一步目前还没有找到高效的经典算法，而量子计算机则可以用多项式代价求解。
&lt;/p&gt;

&lt;p&gt;
问题来了，这个电路看起来也太『简单』了吧！这么难的一个问题，这样几个电路块就解决了？
&lt;/p&gt;

&lt;p&gt;
实际上，为了方便讨论算法，上面的这个电路图作了大量的抽象，其中关键的一步，就是把函数 \(f(x)\) 包装成了一个计算『指数取模』的可逆变换 \(U_f\) 。有了这样一个可逆变换，我们才能给它输入 \(2^n\) 个基态的叠加态，实现对经典算法的指数级加速。
&lt;/p&gt;

&lt;p&gt;
这个 \(U_f\) 变换有2个寄存器，分别都是n个量子位：
&lt;/p&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;第一个是寄存器 \(|x\rangle\) ，就是要对a取的指数，&lt;/li&gt;
&lt;li&gt;第二个是寄存器是辅助的 \(|1\rangle\) （注意，这也是个n量子位的寄存器）。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
在另一端， \(U_f\) 输出 \(|x\rangle\) ，以及 \(|a^x \mod N\rangle\) 。
&lt;/p&gt;

&lt;p&gt;
那这个『指数取模』可逆变换 \(U_f\) 怎么实现呢？
&lt;/p&gt;

&lt;p&gt;
一个偷懒的方法是，用经典电路实现这样一个变换，把它接入到量子电路里。但是，我们给它的输入是 \(2^n\) 个基态的叠加态，而这个经典电路一次只能计算一个f(x)值，遇到这种叠加态的输入就傻眼了：这不还是 \(O(2^n)\) 的时间复杂度么？运行这样的电路，等于只是用经典电路模拟了Shor算法而已。
&lt;/p&gt;

&lt;p&gt;
所以，这个『指数取模』可逆变换 \(U_f\) 必须是『量子』的，不能用经典电路来实现。这也是Shor算法实现中的一个主要的挑战和难点。
&lt;/p&gt;

&lt;p&gt;
接下来，我会用自顶向下的方式，逐个分解讨论。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orgbf97dc2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgbf97dc2&#34;&gt;量子指数取模&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgbf97dc2&#34;&gt;
&lt;p&gt;
这个『量子指数取模』变换的实现，其实方法不止一种，这里结合我对相关论文的理解，提出我的一个实现方法。
&lt;/p&gt;

&lt;p&gt;
首先， \(a^x \mod N\) 里面，N是给定的数，a是每次运行电路前随机选定的一个数，所以运行时候也是已知的，这两个都可以看作是已知的常量。
&lt;/p&gt;

&lt;p&gt;
然后，变量x是n位二进制数，而我们知道n位二进制数可以表示成这样的形式：
&lt;/p&gt;

\begin{matrix}
x = \left( x_{n-1} x_{n-2} \dots x_0 \right)_2  \\
 = x_{n-1}2^{n-1} + x_{n-2}2^{n-2} \dots x_02^0 \\
\end{matrix}

&lt;p&gt;
其中的 \(x_{n-1}, x_{n-2}, \dots x_0\) 都是0或1。因为x是用在a的指数上， \(a^x \mod N\) 也可以写成：
&lt;/p&gt;</description>
    </item>
    <item>
      <title>用Lisp可视化量子因式分解Shor算法的例子</title>
      <link>/quantum/lisp_shor_example/</link>
      <pubDate>Fri, 11 Jun 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/lisp_shor_example/</guid>
      <description>&lt;p&gt;
在前文中我初步尝试了Lisp的数值计算和绘图功能，本着“拿着锤子找钉子”的精神，这次我们来搞个实际的应用，用Lisp来演示和可视化量子因式分解算法（Shor​算法）。
&lt;/p&gt;

&lt;p&gt;
首先还是引用numcl和vgplot包：
&lt;/p&gt;
&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-lisp&#34;&gt;(ql:quickload &lt;span style=&#34;font-weight: bold;&#34;&gt;:numcl&lt;/span&gt;)
(ql:quickload &lt;span style=&#34;font-weight: bold;&#34;&gt;:vgplot&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
假设我们要分解的数是N（前文的例子中N=21），Shor算法需要先在1到N-1之间随机选一个与N互质的数a，然后用量子计算求解函数 \(f(x)=a^x \mod N\) 的周期r。要可视化这个求解的过程，我们得先知道r，所以先写个辅助函数：
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-lisp&#34;&gt;(&lt;span style=&#34;font-weight: bold;&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;a-x-mod-N&lt;/span&gt; (a x N)
  (mod (expt a x) N))

&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;;; &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;Find order for function f(x)=a^x mod N
&lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;;; &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;also returns the &#34;modulo sequence&#34; of the function.
&lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;;; &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;E.g. a=11, N=21 -&amp;gt; returns order r=6 and sequence (1 11 16 8 4 2)
&lt;/span&gt;(&lt;span style=&#34;font-weight: bold;&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;shor-find-mods&lt;/span&gt; (a N)
  (&lt;span style=&#34;font-weight: bold;&#34;&gt;labels&lt;/span&gt; ((next-mod (a x N mods)
             (&lt;span style=&#34;font-weight: bold;&#34;&gt;let&lt;/span&gt; ((r (a-x-mod-n a x N)))
               (&lt;span style=&#34;font-weight: bold;&#34;&gt;if&lt;/span&gt; (equal r (car mods))  &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;; check if the mod sequence is repeating
&lt;/span&gt;                   mods                  &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;; stop when mod sequence starts repeating
&lt;/span&gt;                   (next-mod a           &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;; otherwise continue with a^(x+1) mod N
&lt;/span&gt;                             (+ 1 x)
                             N
                             (append mods (list r)))))))
    (&lt;span style=&#34;font-weight: bold;&#34;&gt;let&lt;/span&gt; ((mod-seq (next-mod a 0 N nil)))
      &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;;; &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&#34;values&#34; returns multiple values
&lt;/span&gt;      &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;;; &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;By default the first value is used, but caller can get other values using
&lt;/span&gt;      &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;;; &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;multiple-value-bind:
&lt;/span&gt;      &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;;; &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;(multiple-value-bind (a b) (foo))
&lt;/span&gt;      (values (length mod-seq) mod-seq))))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;code&gt;a-x-mod-N&lt;/code&gt; 函数很简单，就是返回 \(a^x \mod N\) 的值。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子计算会终结现在的密码体系吗？(6) 实战篇</title>
      <link>/quantum/shor_algorithm_6/</link>
      <pubDate>Mon, 07 Jun 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/shor_algorithm_6/</guid>
      <description>&lt;p&gt;
量子计算机解决因式分解问题的Shor算法，前面讨论了许多背后的数学原理，未免有点抽象，今天用一个简单的例子来实际演示一下，相信可以对Shor算法有更直观的认识。
&lt;/p&gt;

&lt;div id=&#34;outline-container-org219f682&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org219f682&#34;&gt;因式分解问题：N=21&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org219f682&#34;&gt;
&lt;p&gt;
人肉计算，数字不能用的太大 :-) 这里就假设我们要分解N=21这个数，以它为例子。
&lt;/p&gt;

&lt;p&gt;
根据Shor算法，首先我们要在1到N之间选个随机数a，然后看a和N是否互质：
&lt;/p&gt;

&lt;p&gt;
如果a和N不互质， \(GCD(a, N) \ne 1\) ，那么我们很走运， \(GCD(a, N)\) 就是N的因子之一，问题解决。
&lt;/p&gt;

&lt;p&gt;
如果a和N互质，比如说a=11，继续下一步，用量子计算机寻找函数 \(f(x)=a^x \mod N\) 的周期r，也就是使得 \(1=a^r \mod N\) 的最小正整数r。
&lt;/p&gt;

&lt;p&gt;
在这个例子里，假设我们挑选的随机数a=11，所以我们要找的是这个函数的周期：
&lt;/p&gt;

\begin{matrix}
f(x)=11^x \mod 21
\end{matrix}

&lt;p&gt;
我们简单算一下就可以知道，这个函数的周期是6:
&lt;/p&gt;

&lt;table border=&#34;2&#34; cellspacing=&#34;0&#34; cellpadding=&#34;6&#34; rules=&#34;groups&#34; frame=&#34;hsides&#34;&gt;


&lt;colgroup&gt;
&lt;col  class=&#34;org-right&#34; /&gt;

&lt;col  class=&#34;org-right&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-right&#34;&gt;\(x\)&lt;/th&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-right&#34;&gt;\(f(x)=11^x \mod 21\)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;0&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;1&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;11&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;2&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;16&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;3&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;8&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;4&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;5&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;6&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;&amp;#x2026;&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;&amp;#x2026;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
但是在这个例子中，函数周期是未知的，需要用量子计算机来求解。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orgf711af0&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgf711af0&#34;&gt;找函数周期&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgf711af0&#34;&gt;
&lt;p&gt;
前文已经讨论过，量子计算寻找函数周期的电路长这样：
&lt;/p&gt;


&lt;div id=&#34;org528cc5f&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/shor2_uf3.png&#34; alt=&#34;shor2_uf3.png&#34; width=&#34;400px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这里面的2个寄存器，分别需要多少个量子位呢？
&lt;/p&gt;

&lt;p&gt;
一般的规则是，寄存器能表达的最大二进制数q，应该不小于N的平方： \(N^2 \le q \le 2N^2\) （这个规则是从概率推导出来的，具体可参见相关教科书）。因此，量子位的数目n，应该不小于 \(\log N^2\) 。在这个例子里面，N=21 ，所以每个寄存器需要9个量子位， \(q=2^9=512\) 。
&lt;/p&gt;

&lt;p&gt;
经过 \(U_f\) 后，我们其实就不关心第2个寄存器 \(|\beta\rangle\) 的状态了，换句话说我们『丢弃』了第2个寄存器。但在量子计算中，『丢弃』实际上也意味着一种『隐性的测量』（implicit measurement），所以，可以认为 \(|\beta\rangle\) 隐性的坍缩到了某个值z。
&lt;/p&gt;

&lt;p&gt;
而这时候的第1个寄存器 \(|\alpha\rangle\) ，必然处于使得 \(11^x \mod 21 = z\) 的所有 \(|x\rangle\) 的叠加态。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子计算会终结现在的密码体系吗？(5.3) 补充证明</title>
      <link>/quantum/shor_algorithm_5.3/</link>
      <pubDate>Fri, 04 Jun 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/shor_algorithm_5.3/</guid>
      <description>&lt;p&gt;
在前文『&lt;a href=&#34;shor_algorithm_5.../2/&#34;&gt;(5.2) Shor算法详解&lt;/a&gt;』中，我留了一个尾巴需要补充证明，今天就来填上这个坑，把补丁补上。
&lt;/p&gt;

&lt;p&gt;
在前文讨论概率的推导过程中，有一步看起来不起眼，就是我们需要保证 \(\alpha\) 在0到 \(\pi/2\) 之间（其中 \(\alpha = \frac{A+1}{2} |\theta|\) ）。
&lt;/p&gt;

&lt;p&gt;
但这一步其实很重要，为什么呢？因为只有保证 \(\alpha\) 在0到 \(\pi/2\) 之间，我们才能说 \(\sin \alpha \ge 2\alpha / \pi\) ：
&lt;/p&gt;


&lt;div id=&#34;org1d2c816&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/sin_x.png&#34; alt=&#34;sin_x.png&#34; width=&#34;400px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
如果 \(\alpha\) 超过了 \(\pi/2\) ，这个性质就不成立了。而这个不等式，是后面我们推导出 \(|\tilde f(y)|^2\) ，也就是Shor算法成功概率的前提。
&lt;/p&gt;

&lt;p&gt;
回顾一下， \(\theta = 2\pi \frac{ry \mod q}{q}\) ，并且y满足不等式 \(|ry \mod q| \le r/2\) 。
&lt;/p&gt;

&lt;p&gt;
我们想要的不等式是：
&lt;/p&gt;

\begin{matrix}
\alpha = \frac{A+1}{2} \vert \theta \vert \le \frac{\pi}{2}
\end{matrix}

&lt;p&gt;
怎样才能证明这个不等式呢？
&lt;/p&gt;

&lt;p&gt;
我自己研究了一下，应该可以这样证明。
&lt;/p&gt;

&lt;p&gt;
首先来看一下A是怎么计算的。如果我们把 \(l, l+r, \dots, l+Ar\) 画在数轴上，大致是这样的：
&lt;/p&gt;


&lt;div id=&#34;org1bc6cab&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/shor_l_Ar_q.png&#34; alt=&#34;shor_l_Ar_q.png&#34; width=&#34;400px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
所以A的意义是在0到q-1之间，去掉开头的offset和最后的余数t，中间能容纳A个完整的周期（A+1个数据点）。不难得出： \(A=\lfloor \frac{q-l-1}{r} \rfloor - 1\)  。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子计算会终结现在的密码体系吗？(5.2) Shor算法详解</title>
      <link>/quantum/shor_algorithm_5.2/</link>
      <pubDate>Mon, 31 May 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/shor_algorithm_5.2/</guid>
      <description>&lt;p&gt;
前文『&lt;a href=&#34;shor_algorithm_5.../1/&#34;&gt;5.1 Shor算法详解&lt;/a&gt;』讨论了在简化条件下，QFT如何提取函数周期信息，但是如果简化条件不满足呢？今天接着这个话题继续讨论。推导过程较长，涉及的知识点也比较多，我会根据我的学习经验，尽可能写的简明易懂。
&lt;/p&gt;

&lt;div id=&#34;outline-container-org5549726&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org5549726&#34;&gt;回顾：简化条件&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org5549726&#34;&gt;
&lt;p&gt;
在前文中，我们构造周期函数 \(f(x)\) 的可逆变换 \(U_f\) ，给它制备适当的输入：
&lt;/p&gt;


&lt;div id=&#34;orgb237942&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/shor2_uf2.png&#34; alt=&#34;shor2_uf2.png&#34; width=&#34;320px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
在输出端测量 \(|\beta\rangle\) ，使得它坍缩到某个值z，这时 \(\alpha\) 就会坍缩到 \(|l\rangle, |l+r\rangle, |l+2r\rangle, \dots, |l+Ar\rangle\) 的叠加态：
&lt;/p&gt;

\begin{matrix}
|\alpha\rangle = \frac{1}{\sqrt{A+1}} \sum_{j=0}^{A}|jr+l\rangle
\end{matrix}

&lt;p&gt;
其中\(l\) 称为offset，是满足 \(a^l \mod N = z\) 的最小整数。假设 \(|\alpha\rangle\) 有n个量子位，那么A就是在0到 \(2^n-1\) 之间有多少个周期。
&lt;/p&gt;

&lt;p&gt;
接下来的关键一步，是对 \(|\alpha\rangle\) 作量子傅立叶变换，从中提取函数周期信息。
&lt;/p&gt;

&lt;p&gt;
在前文中，我们假设了一个简化条件，即 \(q=2^n\) 能被函数周期 \(r\) 整除。【注：这里勘误一下，前文中把简化条件写成了“ \(2^n-1\) 能被 \(r\) 整除”，这是笔误】
&lt;/p&gt;

&lt;p&gt;
在这个简化条件下， \(|\alpha\rangle\) 经过量子傅里叶变换(QFT)后再测量，会得到某个值 \(y=k\frac{q}{r}\) ，而这个y值与 \(q=2^n\) 之间的比值，等于某个整数k与周期r的比值，即 \(\frac{y}{q} = \frac{k}{r}\) 。这里y和q都是已知的，化简后得到的分数，其分母就是可能的 \(r\) 值。
&lt;/p&gt;

&lt;p&gt;
那么，如果这个简化条件不成立呢？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org60c3f03&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org60c3f03&#34;&gt;简化条件不成立？&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org60c3f03&#34;&gt;
&lt;p&gt;
还是从QFT前的状态开始推导，QFT的作用是什么？
&lt;/p&gt;

&lt;p&gt;
和前文一样，我们知道把QFT作用在任意态 \(|\psi\rangle\) 上：
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子计算会终结现在的密码体系吗？(5.1) Shor算法详解</title>
      <link>/quantum/shor_algorithm_5.1/</link>
      <pubDate>Thu, 27 May 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/shor_algorithm_5.1/</guid>
      <description>&lt;p&gt;
在前文“回到Shor算法”中我们用QFT提取函数周期信息，但是​这个过程的原理是什么？本文接着详解……
&lt;/p&gt;

&lt;div id=&#34;outline-container-orge1a0d5d&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orge1a0d5d&#34;&gt;Shor算法关键：如何用QFT提取函数周期信息？&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orge1a0d5d&#34;&gt;
&lt;p&gt;
用量子计算机求解Order Finding问题，实质上是要找到函数 \(f(x)=a^x \mod N\) 的周期。
&lt;/p&gt;

&lt;p&gt;
Shor算法的第一步，是构造函数f(x)对应的可逆变换 \(U_f\) （这里的 \(|x\rangle, |y\rangle\) 都是多个量子位组成的寄存器）：
&lt;/p&gt;


&lt;div id=&#34;org081553e&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/shor2_uf.png&#34; alt=&#34;shor2_uf.png&#34; width=&#34;280px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
然后给它制备输入： 
&lt;/p&gt;


&lt;div id=&#34;org5e7ea0b&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/shor2_uf2.png&#34; alt=&#34;shor2_uf2.png&#34; width=&#34;320px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
在输出端测量 \(|\beta\rangle\) ，使得它坍缩到某个值z，这时 \(\alpha\) 就会坍缩到 \(|l\rangle, |l+r\rangle, |l+2r\rangle, \dots, |l+Ar\rangle\) 的叠加态：
&lt;/p&gt;

\begin{matrix}
|\alpha\rangle = \frac{1}{\sqrt{A+1}} \sum_{j=0}^{A}|jr+l\rangle
\end{matrix}

&lt;p&gt;
其中\(l\) 称为offset，是满足 \(a^l \mod N = z\) 的最小整数。假设 \(|\alpha\rangle\) 有n个量子位，那么A就是在0到 \(2^n-1\) 之间有多少个周期。
&lt;/p&gt;

&lt;p&gt;
这里面， \(l, j\) 都是未知的，并且每次运行这个电路都有可能不同，不能直接从中导出周期r。所以下一步我们要做的，就是用量子傅立叶变换从中提取出有用的周期信息。
&lt;/p&gt;

&lt;p&gt;
接下来关键一步： &lt;b&gt;如果我们对 \(|\alpha\rangle\) 做量子傅立叶变换，会发生什么？&lt;/b&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org7c7d04f&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org7c7d04f&#34;&gt;先考虑一个简化情况&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org7c7d04f&#34;&gt;
&lt;p&gt;
先考虑一个简化情况：
&lt;/p&gt;

&lt;p&gt;
如果 \(2^n\) 能被 \(r\) 整除，那么我们定义 \(m=2^n/r\) ，显然 \(A=m-1\) ，并且 \(A+1=m=\frac{2^n}{r}\) 。
&lt;/p&gt;

&lt;p&gt;
那么这时的 \(|\alpha\rangle\) 可以写成：
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子傅里叶变换详解 (2) 逆傅里叶变换</title>
      <link>/quantum/qft-2/</link>
      <pubDate>Wed, 26 May 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/qft-2/</guid>
      <description>&lt;p&gt;
既然有『量子傅立叶变换』，那么自然也有它的逆变换，今天就来聊聊这个话题。
&lt;/p&gt;

&lt;div id=&#34;outline-container-org4d68a61&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org4d68a61&#34;&gt;量子傅立叶变换和逆变换&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org4d68a61&#34;&gt;
&lt;p&gt;
前文说过，对于任意状态 \(|\psi\rangle\) ：
&lt;/p&gt;

\begin{matrix}
|\psi\rangle = \sum_{j=0}^{N-1}f(j)|j\rangle &amp; (N=2^n)
\end{matrix}

&lt;p&gt;
对它进行量子傅立叶变换QFT后，会得到一个新状态：
&lt;/p&gt;

\begin{matrix}
|\tilde\psi\rangle = QFT|\psi\rangle = \sum_{k=0}^{N-1}\tilde f(k)|k\rangle, \\\
\\\
\tilde f(k) = \frac{1}{\sqrt{N}} \sum_{j=0}^{N-1} e^{2\pi ijk/N} f(j) \\\
= \frac{1}{\sqrt{N}} \sum_{j=0}^{N-1} \omega^{jk} f(j) &amp; (\omega=e^{2\pi i/N}) \\\
\end{matrix}

&lt;p&gt;
那么量子傅里叶逆变换 \(QFT^{-1}\) 是什么样的？
&lt;/p&gt;

&lt;p&gt;
很简单，其实就是把e的指数加个负号：
&lt;/p&gt;

\begin{matrix}
|\phi\rangle = \sum_{k=0}^{N-1} \tilde f(k) |k\rangle \\\
\\\
QFT^{-1} |\phi\rangle = \sum_{j=0}^{N-1} g(j) |j\rangle \\\
\\\
g(j) = \frac{1}{\sqrt{N}} \sum_{k=0}^{N} \omega^{-jk} \tilde f(k) \\\
\end{matrix}

&lt;p&gt;
可以看到，量子傅立叶逆变换和QFT非常相似，唯一的区别就是e的指数上多了个负号。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>试用国产超导量子计算云平台ScQ</title>
      <link>/quantum/scq-getting-started/</link>
      <pubDate>Fri, 21 May 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/scq-getting-started/</guid>
      <description>&lt;p&gt;
最近中科院物理所发布了一个量子计算云平台ScQ，是一个10量子位的超导量子计算机，可以在云端免费用。看到这个新闻很兴奋，忍不住马上去试用了一下。
&lt;/p&gt;

&lt;p&gt;
点击云平台的链接（&lt;a href=&#34;http://q.iphy.ac.cn/&#34;&gt;http://q.iphy.ac.cn/&lt;/a&gt;），进去以后是这样的：
&lt;/p&gt;


&lt;div id=&#34;orge2f3aa1&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2021-05-21_09-43-59_screenshot.png&#34; alt=&#34;2021-05-21_09-43-59_screenshot.png&#34; width=&#34;720px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
点击&#34;Try ScQ Cloud&#34;，进入量子电路页面：
&lt;/p&gt;


&lt;div id=&#34;orgf6ce444&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2021-05-21_09-57-27_screenshot.png&#34; alt=&#34;2021-05-21_09-57-27_screenshot.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
先来试试精度，用2个量子比特，测量它们的初始状态（应该都是0）：
&lt;/p&gt;


&lt;div id=&#34;org329f785&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2021-05-21_09-59-09_screenshot.png&#34; alt=&#34;2021-05-21_09-59-09_screenshot.png&#34; width=&#34;600px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&#34;org4044efb&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2021-05-21_09-59-52_screenshot.png&#34; alt=&#34;2021-05-21_09-59-52_screenshot.png&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
点击Submit，让我耐心等待结果：
&lt;/p&gt;

&lt;div id=&#34;orgb3255c2&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2021-05-21_10-00-25_screenshot.png&#34; alt=&#34;2021-05-21_10-00-25_screenshot.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
然后结果是这样：
&lt;/p&gt;


&lt;div id=&#34;orgbfd37ac&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2021-05-21_10-01-35_screenshot.png&#34; alt=&#34;2021-05-21_10-01-35_screenshot.png&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
测量100次，96%情况下符合预期（00 ），有3%的情况下第2个量子位测到1…
&lt;/p&gt;

&lt;p&gt;
试试H门产生叠加态：
&lt;/p&gt;


&lt;div id=&#34;org173671b&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2021-05-21_10-10-09_screenshot.png&#34; alt=&#34;2021-05-21_10-10-09_screenshot.png&#34; width=&#34;320px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;



&lt;div id=&#34;org22391dd&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2021-05-21_10-09-49_screenshot.png&#34; alt=&#34;2021-05-21_10-09-49_screenshot.png&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
预期是4个状态各25%，这个误差有点高……感觉可能我的取样次数（100）太少，增加到1000次，结果就好了很多：
&lt;/p&gt;


&lt;div id=&#34;orgcf851cc&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2021-05-21_10-14-30_screenshot.png&#34; alt=&#34;2021-05-21_10-14-30_screenshot.png&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;p&gt;
再来试试Deutsch算法：f(x)=x, 预期输出1 (balanced)
&lt;/p&gt;


&lt;div id=&#34;org5182a52&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2021-05-21_10-43-29_screenshot.png&#34; alt=&#34;2021-05-21_10-43-29_screenshot.png&#34; width=&#34;320px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
取样1000次，92%的情况下得到正确的结果。
&lt;/p&gt;

&lt;div id=&#34;org673c238&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2021-05-21_10-19-50_screenshot.png&#34; alt=&#34;2021-05-21_10-19-50_screenshot.png&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
取样10000次，正确率达到接近97%：
&lt;/p&gt;


&lt;div id=&#34;orga8f1344&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2021-05-21_10-30-10_screenshot.png&#34; alt=&#34;2021-05-21_10-30-10_screenshot.png&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
第一次试用国产量子计算云平台的感受：
&lt;/p&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;用户体验不错，界面直观易用，一键就可开始搭建电路&lt;/li&gt;
&lt;li&gt;目前只支持10个量子位和基本的量子逻辑门，功能还比较有限&lt;/li&gt;
&lt;li&gt;从我运行的结果看，误差还是有点高&lt;/li&gt;
&lt;li&gt;提交电路后，有时候会返回运行错误，需要重试&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
为国产量子计算平台的进展感到高兴，希望将来能看到更多的消息！
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子傅里叶变换详解 (1) 输入输出解读</title>
      <link>/quantum/qft-1/</link>
      <pubDate>Mon, 17 May 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/qft-1/</guid>
      <description>&lt;p&gt;
之前的Shor算法系列，讲了利用量子傅立叶变换QFT来提取函数周期信息。这次歪个楼，聊聊量子傅立叶变换。
&lt;/p&gt;

&lt;p&gt;
假如我们用n个量子位搭了一个QFT电路（后文会讲到如何实现），如何解读它的输入和输出呢？
&lt;/p&gt;


&lt;div id=&#34;orgc041aa2&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/qft_nbit.png&#34; alt=&#34;qft_nbit.png&#34; width=&#34;520px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
假设我们的电路输入状态是某个基态 \(|j\rangle\) ，它是由n个量子位组成的，我们把它展开成二进制表示的话：
&lt;/p&gt;

\begin{matrix}
|j\rangle = |j_{n-1}j_{n-2}\dots j_0\rangle \\\
j = j_{n-1}2^{n-1} + j_{n-2}2^{n-2} + \dots + j_0 2^0
\end{matrix}

&lt;p&gt;
经过QFT，我们得到一个新的状态：
&lt;/p&gt;

\begin{matrix}
QFT|j\rangle = \frac{1}{\sqrt{2^n-1}} \sum_{k=0}^{2^n-1} \omega^{jk} |k\rangle \\\
= \frac{1}{\sqrt{2^n}} \sum_{k=0}^{2^n-1} e^{2\pi ijk/2^n} |k\rangle
\end{matrix}

&lt;p&gt;
其中每个分量k的相位  \(e^{2\pi ijk/2^n}\) 。而因为其中的 \(k\) 也是一个n位二进制数，也就是说：
&lt;/p&gt;

\begin{matrix}
k = k_{n-1}2^{n-1} + k_{n-2}2^{n-2} + \dots + k_0 2^0
\end{matrix}

&lt;p&gt;
那么这个相位里，是把k除以 \(2^n\) ，我们把k的二进制展开代入进去就变成了这样：
&lt;/p&gt;

\begin{matrix}
k / 2^n = \frac{k_{n-1}}{2^1} + \frac{k_{n-2}}{2^2} + \dots + \frac{k_0}{2^n}
\end{matrix}

&lt;p&gt;
等一下，这个式子是不是似曾相识？
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子计算会终结现在的密码体系吗？(5) 回到Shor算法</title>
      <link>/quantum/shor_algorithm_5/</link>
      <pubDate>Mon, 17 May 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/shor_algorithm_5/</guid>
      <description>&lt;div id=&#34;outline-container-org422dc20&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org422dc20&#34;&gt;上文回顾：量子傅立叶变换&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org422dc20&#34;&gt;
&lt;p&gt;
量子傅立叶变换是Shor算法的核心步骤之一。今天我们回到Shor算法，看看如何用量子傅立叶变换来求解Order Finding和函数周期问题。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org65eb077&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org65eb077&#34;&gt;Shor算法第一步&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org65eb077&#34;&gt;
&lt;p&gt;
用量子计算机求解Order Finding问题，实质上是要找到函数 \(f(x)=a^x \mod N\) 的周期。
&lt;/p&gt;

&lt;p&gt;
Shor算法的第一步，是构造函数f(x)对应的可逆变换 \(U_f\) （这里的 \(|x\rangle, |y\rangle\) 都是多个量子位组成的寄存器）：
&lt;/p&gt;


&lt;div id=&#34;orgb0312d3&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/shor2_uf.png&#34; alt=&#34;shor2_uf.png&#34; width=&#34;280px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
然后给它制备输入： 
&lt;/p&gt;


&lt;div id=&#34;orgac78b98&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/shor2_uf2.png&#34; alt=&#34;shor2_uf2.png&#34; width=&#34;320px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
在输出端测量 \(|\beta\rangle\) ，使得它坍缩到某个值z，这时 \(\alpha\) 就会坍缩到 \(|l\rangle, |l+r\rangle, |l+2r\rangle, \dots, |l+Ar\rangle\) 的叠加态：
&lt;/p&gt;

\begin{matrix}
|\alpha\rangle = \frac{1}{\sqrt{A+1}} \sum_{j=0}^{A}|jr+l\rangle
\end{matrix}

&lt;p&gt;
其中\(l\) 称为offset，是满足 \(a^l \mod N = z\) 的最小整数。假设 \(|\alpha\rangle\) 有n个量子位，那么A就是在0到 \(q=2^n\) 之间有多少个周期。
&lt;/p&gt;

&lt;p&gt;
这里面， \(l, j\) 都是未知的，并且每次运行这个电路都有可能不同，不能直接从中导出周期r。所以下一步我们要做的，就是用量子傅立叶变换从中提取出有用的周期信息。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orgaadb9fd&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgaadb9fd&#34;&gt;Shor算法的关键：用量子傅立叶变换提取周期信息&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgaadb9fd&#34;&gt;
&lt;p&gt;
接着上一步：如果我们对 \(|\alpha\rangle\) 做量子傅立叶变换，会发生什么？
&lt;/p&gt;


&lt;div id=&#34;org1df3b24&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/shor2_uf3.png&#34; alt=&#34;shor2_uf3.png&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
节省大家时间，先把答案放在这里，如果你有兴趣可以看我后文的推导。
&lt;/p&gt;

&lt;p&gt;
如果我们对 \(|\alpha\rangle\) 做量子傅立叶变换，然后对它测量，得到某个值y，那么这个y值与 \(q=2^n\) 之间的比值，会非常接近某个整数k与周期r的比值。
&lt;/p&gt;

\begin{matrix}
\frac{y}{q} = \frac{y}{2^n} \approx \frac{k}{r} &amp;&amp; (q=2^n) \\\
\end{matrix}

&lt;p&gt;
好了，到了这一步，q是已知的（n个量子位， \(q=2^n\) ），y是测量得到的，也就是说左边这个分数是已知的。这个不等式告诉我们：测量得到的y，与q的比值，是 \(\frac{k}{r}\) 的一个 &lt;b&gt;近似估计&lt;/b&gt; 。我们知道r小于N（N是要分解的数），所以右边是一个分母小于N的分数。如果我们能从左边 \(\frac{y}{q}\) 估计出一个和它很接近，并且分母小于N的分数，那这个分数的分母就有可能是我们要找的周期r！然后我们要做的就是对这个候选的r进行验证，如果它确实是函数f(x)的周期，那么问题解决，否则就重新运行Shor算法电路。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子计算会终结现在的密码体系吗？(4) 量子傅立叶变换</title>
      <link>/quantum/shor_algorithm_4_qft/</link>
      <pubDate>Mon, 03 May 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/shor_algorithm_4_qft/</guid>
      <description>&lt;div id=&#34;outline-container-orgb11a93e&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgb11a93e&#34;&gt;上文回顾：Shor算法初探&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgb11a93e&#34;&gt;
&lt;p&gt;
用量子计算机求解Order Finding问题，其实就是要找到函数 \(f(x)=a^x \mod N\) 的周期。在上文中我们已经看到，如果我们把f(x)包装成量子变换 \(U_f\) ，然后把它的输入x制备成叠加态，在输出端就能得到 \(|l\rangle, |l+r\rangle, |l+2r\rangle, \dots\) 的叠加态。但是这个叠加态并不能直接告诉我们周期（r）是什么，我们还需要对它做更多的处理才能提取出有用的信息。这个处理过程，就是 &lt;b&gt;量子傅里叶变换&lt;/b&gt; 。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org322fbb2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org322fbb2&#34;&gt;离散傅里叶变换（DFT）&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org322fbb2&#34;&gt;
&lt;p&gt;
先复习一下傅里叶变换…
&lt;/p&gt;

&lt;p&gt;
我们有一个N维的矢量 \(\{f(0), f(1), \dots, f(N-1)\}\) ， 其中每个分量f(j)都是复数。
&lt;/p&gt;

&lt;p&gt;
离散傅里叶变换会把它变成一个新的矢量： \(\{ \tilde{f}(0), \tilde{f}(1), \dots, \tilde{f}(N-1) \}\)
&lt;/p&gt;

&lt;p&gt;
其中每个分量 \(\tilde{f}(k)\) 是这样计算的：
&lt;/p&gt;

\begin{matrix}
\tilde{f}(k) = \frac{1}{\sqrt{N}} \sum_{j=0}^{N-1} e^{2\pi ijk/N}f(j)
\end{matrix}

&lt;p&gt;
如果我们记 \(\omega = e^{2 \pi i/N}\) ，那么上面的定义可以简写成：
&lt;/p&gt;

\begin{matrix}
\tilde{f}(k) = \frac{1}{\sqrt{N}} \sum_{j=0}^{N-1} \omega^{jk}f(j)
\end{matrix}

&lt;p&gt;
学过信号处理的朋友应该很熟悉这个吧！
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;其他相关性质&lt;/b&gt; 也复习一下：
&lt;/p&gt;

&lt;p&gt;
根据定义， \(e^{ix} = \cos x + i\sin x\) 。
&lt;/p&gt;

&lt;p&gt;
所以 \(\omega^N = e^{2 \pi i} = \cos 2\pi + i\sin 2\pi = 1\) 。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子计算会终结现在的密码体系吗？(3) Shor算法初探</title>
      <link>/quantum/shor_algorithm_3/</link>
      <pubDate>Thu, 29 Apr 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/shor_algorithm_3/</guid>
      <description>&lt;div id=&#34;outline-container-orgaab5bcb&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgaab5bcb&#34;&gt;上文回顾：因式分解问题可以转化为Order Finding&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgaab5bcb&#34;&gt;
&lt;p&gt;
在&lt;a href=&#34;../shor_algorithm_2_order_finding/&#34;&gt;上文&lt;/a&gt;中，我们分析了为什么因式分解问题可以转化为Order Finding，因此如果能高效求解Order Finding，也就能高效解决因式分解问题。
&lt;/p&gt;

&lt;p&gt;
所谓Order Finding问题，就是已知互质的两个数a和N，求满足 \(a^r=1 \mod N\) 的最小正整数r。
&lt;/p&gt;

&lt;p&gt;
这个问题可以进一步归纳为一个周期求解问题：假如我们定义函数 \(f(x)=a^x \mod N\) ，那么 \(f(x)=f(x+r)\) ，因此这个函数的值是以r为周期的。我们要找的r，就是这个函数的周期。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org745c008&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org745c008&#34;&gt;用量子计算机解决因式分解问题：Shor算法&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org745c008&#34;&gt;
&lt;p&gt;
Shor算法是Peter Shor在1994年提出的一种量子计算算法，可以在多项式时间内求解因式分解问题。
&lt;/p&gt;

&lt;p&gt;
要完整理解这个算法涉及的知识面很多，容易迷失在细节里。我的经验是，先从高层次出发，理解它的总体思路，然后对其中的重要步骤逐一分解研究。
&lt;/p&gt;

&lt;p&gt;
Shor算法求解因式分解问题的过程，分为『经典』部分和『量子』部分：
&lt;/p&gt;

&lt;ol class=&#34;org-ol&#34;&gt;
&lt;li&gt;『经典部分』假设要分解的数为N；&lt;/li&gt;
&lt;li&gt;『经典部分』如果N是偶数，或者N是某个质数的幂，那么已经找到了它的因子，问题解决；&lt;/li&gt;
&lt;li&gt;『经典部分』在2到N-1之间，随机选一个与N互质的数，即 \(GCD(a, N)=1\) ；&lt;/li&gt;
&lt;li&gt;&lt;b&gt;『量子部分』&lt;/b&gt; 计算a对N模的order，即满足 \(a^r \mod N=1\) 的最小正整数r；&lt;/li&gt;
&lt;li&gt;『经典部分』如果r是奇数，回到步骤3重新选a；&lt;/li&gt;
&lt;li&gt;『经典部分』如果r是偶数，计算 \(GCD(a^{r/2}+1, N)\), \(GCD(a^{r/2}-1, N)\), 两者中必有N的非平凡因子。&lt;/li&gt;
&lt;/ol&gt;


&lt;div id=&#34;org0a1e246&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/shor1.png&#34; alt=&#34;shor1.png&#34; width=&#34;400px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这就是Shor算法解决因式分解问题的总体思路！
&lt;/p&gt;

&lt;p&gt;
这其中，只有第4步Order Finding需要用到量子计算，因此Shor算法的核心，就是用量子计算机找到a对N模的order。接下来我们来看一下，量子计算机是如何解决Order Finding问题的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org465c84d&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org465c84d&#34;&gt;用量子计算机求解Order Finding问题&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org465c84d&#34;&gt;
&lt;p&gt;
用量子计算机求解Order Finding问题，实质上是要找到函数 \(f(x)=a^x \mod N\) 的周期。看过我之前文章的朋友可能会想到，首先我们要考虑如何将这个函数整合到我们的量子电路里，也就是把它转换成一个量子电路能用的变换 \(U_f\) 。
&lt;/p&gt;

&lt;p&gt;
为了避免迷失在实现细节里（后文会讨论 \(U_f\) 的实现），咱们先假设已经有了这样一个可逆变换 \(U_f\) ：
&lt;/p&gt;


&lt;div id=&#34;orgc7dab4c&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/shor2_uf.png&#34; alt=&#34;shor2_uf.png&#34; width=&#34;280px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这个变换使用2个量子寄存器x和y。这两个寄存器都是由多个量子位构成的，可以把它们看作是多个量子位构成的二进制数。
\(U_f\) 的作用是：
&lt;/p&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;输入 \(|x\rangle\) 和 \(|y\rangle\)&lt;/li&gt;
&lt;li&gt;输出 \(|x\rangle\) 和 \(|y f(x)\rangle = |y a^x \mod N\rangle\)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
还记得我们是如何解决Deutsch问题的吗？我们给 \(U_f\) 输入叠加态，然后在输出端经过一些变换就能得到函数的性质。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子计算会终结现在的密码体系吗？(2) 因式分解和Order Finding问题</title>
      <link>/quantum/shor_algorithm_2_order_finding/</link>
      <pubDate>Mon, 26 Apr 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/shor_algorithm_2_order_finding/</guid>
      <description>&lt;div id=&#34;outline-container-org956d49f&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org956d49f&#34;&gt;上文回顾：RSA公钥加密算法&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org956d49f&#34;&gt;
&lt;p&gt;
在&lt;a href=&#34;../shor_algorithm_1_rsa/&#34;&gt;上文&lt;/a&gt;中我们讲了以RSA为代表的公钥加密算法，以及为什么其安全性的核心是因式分解问题。
&lt;/p&gt;


&lt;div id=&#34;orgf410b0a&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/RSA.png&#34; alt=&#34;RSA.png&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
那么为什么量子计算机能高效求解因式分解问题呢？这是因为，因式分解可以转化为Order Finding或函数周期求解问题，而这类问题，正是量子计算机所能高效求解的！
&lt;/p&gt;

&lt;p&gt;
下面我们就来看一下，如何将因式分解问题转化为Order Finding问题。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org08c4968&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org08c4968&#34;&gt;Order Finding问题&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org08c4968&#34;&gt;
&lt;p&gt;
给定两个互质的数N和a，求使得 \(a^r=1 \mod N\) 的最小整数r，这就是所谓的Order Finding问题。求出的r，称为&#34;the order of a modulo N&#34;。
&lt;/p&gt;

&lt;p&gt;
如果 \(a^r=1 \mod N\) ，那么很显然 \(a^{2r}, a^{3r}, \dots\) 也对N取模为1。
&lt;/p&gt;

&lt;p&gt;
进一步推论，如果a的幂取任意整数 \(x=jr+l\) ，那么 \(a^x=a^{jr+l}=a^{jr}a^l=a^l \mod N\) ， 同理可知 \(a^{x+r} = a^xa^r = a^x \mod N\) 。
&lt;/p&gt;

&lt;p&gt;
因此如果我们定义一个函数 \(f(x)=a^x \mod N\) ，那么这个函数的值其实是 &lt;b&gt;以r为周期的&lt;/b&gt; ，即 \(f(x)=f(x+r)\) 。因此Order Finding问题就相当于找到这个函数f(x)的周期。
&lt;/p&gt;

&lt;p&gt;
例如N=15，a=7，那么 \(f(x)=7^x \mod 15\) 函数的值：
&lt;/p&gt;

&lt;table border=&#34;2&#34; cellspacing=&#34;0&#34; cellpadding=&#34;6&#34; rules=&#34;groups&#34; frame=&#34;hsides&#34;&gt;
&lt;caption class=&#34;t-above&#34;&gt;&lt;span class=&#34;table-number&#34;&gt;Table 1:&lt;/span&gt; \(f(x)=7^x \mod 15\)&lt;/caption&gt;

&lt;colgroup&gt;
&lt;col  class=&#34;org-left&#34; /&gt;

&lt;col  class=&#34;org-right&#34; /&gt;

&lt;col  class=&#34;org-right&#34; /&gt;

&lt;col  class=&#34;org-right&#34; /&gt;

&lt;col  class=&#34;org-right&#34; /&gt;

&lt;col  class=&#34;org-right&#34; /&gt;

&lt;col  class=&#34;org-right&#34; /&gt;

&lt;col  class=&#34;org-right&#34; /&gt;

&lt;col  class=&#34;org-left&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-left&#34;&gt;\(x\)&lt;/th&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-right&#34;&gt;0&lt;/th&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-right&#34;&gt;1&lt;/th&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-right&#34;&gt;2&lt;/th&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-right&#34;&gt;3&lt;/th&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-right&#34;&gt;4&lt;/th&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-right&#34;&gt;5&lt;/th&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-right&#34;&gt;6&lt;/th&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-left&#34;&gt;\(\dots\)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&#34;org-left&#34;&gt;\(f(x)\)&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;1&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;7&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;4&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;13&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;1&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;7&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;4&lt;/td&gt;
&lt;td class=&#34;org-left&#34;&gt;\(\dots\)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
不难看出，7对15模的order是4，因此这个函数的值是以4为周期不断重复。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子计算会终结现在的密码体系吗？(1) RSA公钥算法</title>
      <link>/quantum/shor_algorithm_1_rsa/</link>
      <pubDate>Tue, 20 Apr 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/shor_algorithm_1_rsa/</guid>
      <description>&lt;div id=&#34;outline-container-org249abfb&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org249abfb&#34;&gt;公钥加密系统&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org249abfb&#34;&gt;
&lt;p&gt;
关于量子计算，很多人可能都听说过这个耸人听闻的说法：有了量子计算机之后，现在的密码就都不安全了，因为量子计算机可以轻易破解它们。真的有这么夸张吗？实际上，量子计算机威胁的主要是基于『大数分解』的一类加密算法，其中最广泛使用的就是RSA。
&lt;/p&gt;

&lt;p&gt;
RSA (Rivest–Shamir–Adleman) 是目前广泛使用的一种公钥加密系统（RSA是三位设计者的名字首字母的组合）。所谓公钥加密系统，就是说它里面的密码是分为可以公开的『公钥』和必须保密的『私钥』。公钥和私钥是成对的，用一个公钥加密的信息，只能用它对应的私钥来解密。为什么要这么设计呢？
&lt;/p&gt;

&lt;p&gt;
我们知道，两个人之间要实现保密通信，最简单直接的办法是互相约定一个密码，用这个密码来加密他们之间传递的信息，甲方用它来加密，乙方用同样的密码来解密。这种密码又叫做『对称密码』，因为加密和解密使用相同的密码。但是问题来了，甲方和乙方怎样才能『约定』这个共享的通信密码呢？如果直接把这个通信密码发过去，中间被人窃听了，别人知道了通信密码，那后面的通信岂不就是在网上裸奔了吗？
&lt;/p&gt;

&lt;p&gt;
这时候就需要公钥加密算法来帮忙了：
&lt;/p&gt;
&lt;ol class=&#34;org-ol&#34;&gt;
&lt;li&gt;甲方生成一对公钥和私钥，然后把公钥发给乙方。&lt;/li&gt;
&lt;li&gt;乙方生成要共享的通信密码，用甲方提供的公钥来加密，然后把这个加密后的通信密码发回给甲方。&lt;/li&gt;
&lt;li&gt;甲方收到乙方的回复，用它的私钥来解密，得到共享的通信密码。&lt;/li&gt;
&lt;li&gt;甲方和乙方都有了通信密码，就可以放心的通信了。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
这个过程中，即使有人在中间窃听，因为信息是用甲方的公钥加密的，只有拥有私钥的甲方能解密，窃听的人就是截获了信息也无法得到通信密码，所以不用担心通信密码泄露的问题。
&lt;/p&gt;

&lt;p&gt;
可见，公钥加密系统保证了通信双方『约定通信密码』这个步骤的安全。没有这个保证，通信的双方就无法安全的建立联系，更不用说安全的通信了。除此之外，公钥加密系统还是电子签名，电子证书等许多网络安全技术的基础。这也是为什么说以RSA为代表的公钥加密系统是当前网络通信和安全的基石之一。如果RSA的安全性受到量子计算机的挑战，那么基于RSA的很多通信协议，认证服务等等都会变得不安全，这个影响还是挺大的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org23fa711&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org23fa711&#34;&gt;RSA的工作原理&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org23fa711&#34;&gt;
&lt;p&gt;
为什么量子计算机被认为会威胁到RSA公钥加密体系呢？要回答这个问题，需要先了解一下RSA的工作原理。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org5388a25&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;org5388a25&#34;&gt;生成公钥私钥&lt;/h3&gt;
&lt;div class=&#34;outline-text-3&#34; id=&#34;text-org5388a25&#34;&gt;
&lt;p&gt;
RSA生成公钥和私钥的流程大致是这样：
&lt;/p&gt;

&lt;div id=&#34;org54be60d&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/RSA.png&#34; alt=&#34;RSA.png&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
首先随机选两个很大的质数（p, q），然后用它们计算两个乘积：
&lt;/p&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;\(N=pq\)&lt;/li&gt;
&lt;li&gt;\(\phi(N)=(p-1)(q-1)\)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
其中的 \(\phi(N)\) 也被称为『欧拉函数』，它的意思是“小于等于N并且与N互质的正整数的个数”。例如，如果某个数p是质数，那么显然有 \(\phi(p)=p-1\) 。为什么要用这个欧拉函数，后面会看到。
&lt;/p&gt;

&lt;p&gt;
然后，随机选一个与 \(\phi(N)\) 互质的奇数e，计算它对于 \(\phi(N)\) 的『模逆』d，也就是找到某个正整数d，使得\(ed = 1 \mod \phi(N)\) ，这个数d可以用欧几里德算法高效计算出来。
&lt;/p&gt;

&lt;p&gt;
最后，把e和N拼在一起，组成公钥P，而d和N拼在一起，组成私钥S。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org8a8b5ae&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;org8a8b5ae&#34;&gt;加密和解密过程&lt;/h3&gt;
&lt;div class=&#34;outline-text-3&#34; id=&#34;text-org8a8b5ae&#34;&gt;
&lt;p&gt;
有了公钥和私钥后，可以用公钥加密，然后用对应的私钥解密（下图左边是加密过程，右边是解密过程）：
&lt;/p&gt;


&lt;div id=&#34;org820d1e2&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/RSA2.png&#34; alt=&#34;RSA2.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
我们把要加密的消息看作是一个固定长度的二进制数M，加密的时候，我们用公钥里的e和N，对M求e次幂，然后对N取模，得到加密后的消息E(M)：
&lt;/p&gt;

&lt;p&gt;
\[
M^e \mod N \to E(M)
\]
&lt;/p&gt;

&lt;p&gt;
解密的方式和加密类似，但使用的是私钥里的d和N，对收到的消息E(M)求d次幂，然后对N取模，就能解密出原来的消息M。
&lt;/p&gt;

&lt;p&gt;
\[
E(M)^d \mod N \to M
\]
&lt;/p&gt;

&lt;p&gt;
如果你对RSA算法的数学原理感兴趣，可以参阅本文最后的分析。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org4236628&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org4236628&#34;&gt;RSA安全性的关键：因式分解&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org4236628&#34;&gt;
&lt;p&gt;
RSA如何保证加密后信息的安全性？或者说，它安全性的关键点在哪里？从上面的过程不难看出，RSA安全性的关键点在于N是否被分解。想象一下：假如我们能够把N分解回p和q，那么就可以知道 \(\phi(N)=(p-1)(q-1)\) ，再加上公钥里的e，用欧几里德算法把d也算出来，这样私钥也有了，整个加密过程就被攻破了！
&lt;/p&gt;

&lt;p&gt;
好在，因式分解问题目前在经典计算机上还没有找到高效的算法（现有的算法都是指数级时间复杂度），因此只要N足够大，就可以保证加密后的消息无法在合理的时间内被破解，使得破解失去意义。
&lt;/p&gt;

&lt;p&gt;
量子计算机对RSA的威胁就在于，它能实现高效的因式分解（多项式时间复杂度），这就是为什么我们说量子计算机对现有网络通信和安全会构成一定的挑战。当然，凡事有矛必有盾，一方面现在的量子计算机还远远没有达到能破解RSA的程度，另一方面，也已经有不基于因式分解的公钥加密算法，以及抗量子计算的密码研究。因此可以说，挑战是存在的，但过于夸大量子计算的作用也没有必要。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orgaa21aca&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgaa21aca&#34;&gt;总结&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgaa21aca&#34;&gt;
&lt;p&gt;
现在我们理解了RSA的工作原理，以及为什么它的安全性取决于因式分解的难度。那么接下来的问题是，为什么量子计算能高效计算因式分解呢？实际上，量子计算机解决的是Order Finding问题（或者说函数周期求解问题），在下一篇里，我们来看看因式分解是如何转化为Order Finding/函数周期求解问题的。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Understanding the Power of Quantum Computing 1: Deutsch Problem</title>
      <link>/quantum/understand-quantum-computing-1bit-deutsch/</link>
      <pubDate>Thu, 01 Apr 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/understand-quantum-computing-1bit-deutsch/</guid>
      <description>&lt;div id=&#34;outline-container-orgc224b09&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgc224b09&#34;&gt;Introduction&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgc224b09&#34;&gt;
&lt;p&gt;
Quantum computing is one of the hottest topic these days. You might have already heard about hypes like &#34;quantum supremacy&#34;. But why quantum computers can be faster on solving some problems? And how does it work behind the scene?
&lt;/p&gt;

&lt;p&gt;
In this article I&#39;m going to use a simple problem (the Deutsch Problem) as an example and walk you through the process.
&lt;/p&gt;

&lt;p&gt;
Ok, let&#39;s get started.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org9d8fef8&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org9d8fef8&#34;&gt;Terms and Basic Concepts&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org9d8fef8&#34;&gt;
&lt;p&gt;
Before we start discussing the problem, let&#39;s first review some basic terms and concepts.
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Understanding the Power of Quantum Computing 2: Extending Deutsch Problem to 2-bits</title>
      <link>/quantum/understand-quantum-computing-2bit-deutsch/</link>
      <pubDate>Thu, 01 Apr 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/understand-quantum-computing-2bit-deutsch/</guid>
      <description>&lt;div id=&#34;outline-container-org2ab4354&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org2ab4354&#34;&gt;Two-Bit Deutsch Problem&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org2ab4354&#34;&gt;
&lt;p&gt;
My &lt;a href=&#34;../understand-quantum-computing-1bit-deutsch/&#34;&gt;previous article&lt;/a&gt; discussed Deutsch Problem in its simplest form - determine attribute of an unknown 1-bit function. Now what if we extend the function to having 2-bit input?
&lt;/p&gt;

&lt;p&gt;
\[
f(x_0, x_1) \to \{0, 1\}
\]
&lt;/p&gt;

&lt;p&gt;
For 2-bit functions, there are 4 possible inputs: 00, 01, 10, 11. Outputs of the function are still 1-bit. So the truth table of the function will be like this:
&lt;/p&gt;

&lt;table border=&#34;2&#34; cellspacing=&#34;0&#34; cellpadding=&#34;6&#34; rules=&#34;groups&#34; frame=&#34;hsides&#34;&gt;


&lt;colgroup&gt;
&lt;col  class=&#34;org-right&#34; /&gt;

&lt;col  class=&#34;org-left&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-right&#34;&gt;input&lt;/th&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-left&#34;&gt;output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;00&lt;/td&gt;
&lt;td class=&#34;org-left&#34;&gt;0 or 1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;01&lt;/td&gt;
&lt;td class=&#34;org-left&#34;&gt;0 or 1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;10&lt;/td&gt;
&lt;td class=&#34;org-left&#34;&gt;0 or 1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;11&lt;/td&gt;
&lt;td class=&#34;org-left&#34;&gt;0 or 1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
We define the attribute of the function in a similar way as 1-bit Deutsh Problem.
If the function returns a constant value regardless of the input, we call it &lt;b&gt;constant&lt;/b&gt;. Apparently there are 2 &lt;b&gt;constant&lt;/b&gt; functions (always return 0, or always return 1).
&lt;/p&gt;</description>
    </item>
    <item>
      <title>聊聊量子搜索算法(Grover算法) - 2</title>
      <link>/quantum/grovers_algorithm_2/</link>
      <pubDate>Tue, 26 Jan 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/grovers_algorithm_2/</guid>
      <description>&lt;p&gt;
在&lt;a href=&#34;../grovers_algorithm_1/&#34;&gt;上文&lt;/a&gt;中我们讨论了量子搜索算法的实现，其中的关键是用G变换多次迭代，逐渐逼近答案，最后在输出端测量得到结果。
那么为什么多次重复G变换能达到这样的效果呢？Grover算法的查询次数是\(O(\sqrt{N})\)，这个\(O(\sqrt{N})\)又是怎么来的呢？本文接着上一篇继续讨论这些问题。
&lt;/p&gt;

&lt;div id=&#34;outline-container-org8c71905&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org8c71905&#34;&gt;Grover算法的图像化&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org8c71905&#34;&gt;
&lt;p&gt;
要理解Grover算法的原理，最直观的方法是把它图像化，从几何意义来理解。
&lt;/p&gt;

&lt;p&gt;
回顾一下上文的量子搜索电路：
&lt;/p&gt;


&lt;div id=&#34;org508a8e5&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/Quantum Search - Grover&#39;s Algorithm.png&#34; alt=&#34;Quantum Search - Grover&#39;s Algorithm.png&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
我们的电路有n个搜索用的量子比特，可以表示\(N=2^{n}\)个基态，对应搜索空间0到N-1的编号。为方便讨论，我们用\(|0\rangle, |1\rangle, |2\rangle, |3\rangle, \dots, |N-1\rangle\)来表示这些基态。
&lt;/p&gt;

&lt;p&gt;
假定在这N个编号中，有M个是符合条件的答案。在上文的讨论中我们假定M=1，也就是只有1个符合条件的编号，这里我们把它扩展到更普遍的情况，M可以大于1，也就是可以有多个符合条件的答案。因此不符合条件（也就是让判断函数f返回0）的编号有N-M个。
&lt;/p&gt;

&lt;p&gt;
我们把所有 &lt;b&gt;&lt;b&gt;不符合条件&lt;/b&gt;&lt;/b&gt; 的N-M个基态叠加在一起，组成一个叠加态的状态向量，把它记作\(|\alpha\rangle\)。
&lt;/p&gt;

&lt;p&gt;
类似的，把所有 &lt;b&gt;&lt;b&gt;符合条件&lt;/b&gt;&lt;/b&gt; 的M个状态叠加在一起，组成一个状态向量，把它记作\(|\beta\rangle\)。
&lt;/p&gt;

&lt;p&gt;
显然，上面这两个向量\(|\alpha\rangle\)，\(|\beta\rangle\)是正交的。因此我们可以用它们作轴，张成一个二维平面。
&lt;/p&gt;

&lt;p&gt;
然后我们在这个平面里，考察前面G变换公式里的\(|\psi\rangle\)，这是一个所有基态无差别叠加的状态，那么这个\(|\psi\rangle\)在这个二维平面里，可以写成：
&lt;/p&gt;

\begin{matrix}
|\psi\rangle=\sqrt{\frac{N-M}{N}}|\alpha\rangle + \sqrt{\frac{M}{N}}|\beta\rangle
\end{matrix}

&lt;p&gt;
这个\(|\psi\rangle\)向量，和\(|\alpha\rangle\)轴之间的夹角，我们记作\(\frac{\theta}{2}\)，如下图所示：
&lt;/p&gt;

&lt;div id=&#34;orgcdefa41&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/Quantum Search - Grover&#39;s Algorithm Visualized1.png&#34; alt=&#34;Quantum Search - Grover&#39;s Algorithm Visualized1.png&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
根据简单的三角函数，我们很容易得到：
&lt;/p&gt;

\begin{matrix}
\cos\frac{\theta}{2} = \sqrt{\frac{N-M}{N}} &amp;&amp;
\sin\frac{\theta}{2} = \sqrt{\frac{M}{N}}
\end{matrix}

&lt;p&gt;
继续分析G变换。从上文我们知道，G变换可以写成：
&lt;/p&gt;

&lt;p&gt;
\[
G=(2|\psi\rangle \langle\psi|-I)O
\]
&lt;/p&gt;

&lt;p&gt;
我们先从O（Oracle）变换看起。O变换干了什么呢？它是把输入的状态\(|x\rangle\)变成\((-1)^{f(x)} |x\rangle\)。如果f(x)=1，那么它就给输出加上一个-1的相位，否则不变。那么这个操作在二维平面图中，实际上就是把输入的向量对\(|\alpha\rangle\)轴做了一个 &lt;b&gt;&lt;b&gt;反射&lt;/b&gt;&lt;/b&gt; 。
&lt;/p&gt;

&lt;div id=&#34;org4d6d924&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/Quantum Search - Grover&#39;s Algorithm Visualized2.png&#34; alt=&#34;Quantum Search - Grover&#39;s Algorithm Visualized2.png&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;</description>
    </item>
    <item>
      <title>聊聊量子搜索算法(Grover算法) - 1</title>
      <link>/quantum/grovers_algorithm_1/</link>
      <pubDate>Mon, 25 Jan 2021 00:00:00 +0000</pubDate>
      <guid>/quantum/grovers_algorithm_1/</guid>
      <description>&lt;p&gt;
今天来聊一下量子计算里面的一个经典算法：量子搜索算法（Grover算法）。
&lt;/p&gt;

&lt;div id=&#34;outline-container-orgf4fd029&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgf4fd029&#34;&gt;搜索问题&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgf4fd029&#34;&gt;
&lt;p&gt;
假设我们有N个无结构的元素，比如很多指纹信息，我们的任务是从中找出符合某些要求的元素。为方便讨论，我们给这些元素编号，从0开始一直到N-1，并且其中只有1个符合我们要找的条件。如果我们用经典计算机来搜索的话，只能一个一个元素的试，看它是否符合要求，因此需要试的次数为\(O(N)\)。但是如果使用量子计算机，只需要试\(O(\sqrt{N})\)次数就可以找到。和经典计算机相比，虽然这不是指数级别的加速，但也相当可观了，尤其是如果“判断元素是否符合要求”这个操作很费力的话，减少判断次数的收益也会很大。
&lt;/p&gt;

&lt;p&gt;
这个问题可以进一步抽象：我们有N个数（元素编号），这里为了方便讨论，假设\(N=2^{n}\)，即编号可以用一个n位二进制数来表示。然后我们有一个判断函数f，给它输入编号x（n位二进制数），它判断该编号对应的元素是否符合要求，如果符合就返回1，否则返回0。
&lt;/p&gt;

&lt;p&gt;
\[
f : \{0, 1\}^{n} \rightarrow \{0, 1\}
\]
&lt;/p&gt;

&lt;p&gt;
你可能会问：我都知道判断函数f了，为什么还需要查询呢？这里需要分清“找到符合条件的元素”和“判断元素是否符合条件”的区别。前者是“搜索”，而后者是“检验”。还是拿指纹做例子：警察在犯罪现场发现了嫌疑人的指纹，但是光有指纹并不能找到对应的嫌疑人，需要拿着指纹去和指纹库里的样本比对。这个“找到对应嫌疑人”的过程就是搜索，而“和指纹库里的样本进行比对”的过程就是检验，也就是前面说的判断函数f。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orgfec9176&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgfec9176&#34;&gt;量子搜索算法(Grover算法)&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgfec9176&#34;&gt;
&lt;p&gt;
定义了搜索问题，接下来讨论量子搜索算法。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org23b2745&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;org23b2745&#34;&gt;量子搜索电路&lt;/h3&gt;
&lt;div class=&#34;outline-text-3&#34; id=&#34;text-org23b2745&#34;&gt;
&lt;p&gt;
量子搜索算法（Grover算法）是一个迭代的过程，主要思路是从初始状态出发，重复进行多次变换，让系统越来越接近目标状态，最后进行测量，就能以很高的概率得到正确结果。
&lt;/p&gt;

&lt;p&gt;
量子搜索的电路图长这样：
&lt;/p&gt;


&lt;div id=&#34;org7fab32a&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/Quantum Search - Grover&#39;s Algorithm.png&#34; alt=&#34;Quantum Search - Grover&#39;s Algorithm.png&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
整个算法大致分成这样几步：
&lt;/p&gt;

&lt;ol class=&#34;org-ol&#34;&gt;
&lt;li&gt;在输入端，我们需要准备一组量子比特，包括n个用来搜索的\(|0\rangle\)，以及用于操作辅助量子比特的工作区（workspace）。这些辅助量子比特相当于程序里的临时变量，因此我们不用关心工作区的内部操作，只需要讨论前面的n个搜索用的量子比特。&lt;/li&gt;

&lt;li&gt;计算的第一步，用H门把这n个量子比特从初始的\(|0\rangle\)变成无差别叠加态，也就是把\(|0\dots0\rangle\)变成\(\frac{1}{N}\sum_{x=0}^{N-1}|x\rangle\)（其中\(N=2^{n}\)）。&lt;/li&gt;

&lt;li&gt;然后，对这些量子比特进行G变换（后面会详细介绍），这个过程反复迭代多次。&lt;/li&gt;

&lt;li&gt;最后在输出端测量，得到结果（n位二进制数）。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
你可能会问，这个算法里的第3步里，需要多少次迭代（重复多少次G变换）呢？
&lt;/p&gt;

&lt;p&gt;
答案是重复\(O(\sqrt{N})\)次后，我们就能以很高的概率得到正确结果。这个结果是怎么来的？后文分析原理的时候会详细讨论。现在先看看G变换里面是啥。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org64baf22&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;org64baf22&#34;&gt;G变换&lt;/h3&gt;
&lt;div class=&#34;outline-text-3&#34; id=&#34;text-org64baf22&#34;&gt;
&lt;p&gt;
我们把量子搜索算法里每次迭代的过程称为G变换，这个G变换内部又分成4个步骤。
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;&lt;b&gt;G变换的第一步：Oracle&lt;/b&gt;&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
首先要做什么？看过我之前文章的读者应该能猜到，要把判断函数f包装成量子计算机能用的可逆变换。套路和Deutsch问题类似，在输入的量子比特\(|x\rangle\)之外，增加一个辅助量子比特\(|y\rangle=\frac{1}{\sqrt{2}}(|0\rangle - |1\rangle)\)，然后在输出端，原样输出\(|x\rangle\)，外加输出\(|y \oplus f(x)\rangle\)。我们把这个变换称作Oracle，简称O变换：
&lt;/p&gt;

&lt;p&gt;
\[
O|x\rangle|y\rangle = |x\rangle |y \oplus f(x)\rangle =  |x\rangle \frac{1}{\sqrt{2}}(|0 \oplus f(x)\rangle - |1 \oplus f(x)\rangle)
\]
&lt;/p&gt;

&lt;p&gt;
(其中的\(\oplus\)表示异或)
&lt;/p&gt;

&lt;p&gt;
我们知道判断函数f(x)的输出是0或者1，那么如果f(x)=1，上面右边就是\(|x\rangle \frac{1}{\sqrt{2}}(|0\rangle - |1\rangle)\)，也就是\(|x\rangle |y\rangle\)；而如果f(x)=1的话，上面右边就变成了\(|x\rangle \frac{1}{\sqrt{2}}(|1\rangle - |0\rangle)\)，也就是\(-|x\rangle |y\rangle\)。这样一来，f(x)的输出就变成了相位：\(|x\rangle |y\rangle\)前面的正负号。所以Oracle变换可以写成：
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子神经网络</title>
      <link>/quantum/20201213_quantum_neural_network_mnist/</link>
      <pubDate>Sun, 13 Dec 2020 00:00:00 +0000</pubDate>
      <guid>/quantum/20201213_quantum_neural_network_mnist/</guid>
      <description>&lt;p&gt;
上次讨论了量子机器学习框架TensorFlow Quantum的Hello World，这次看一下另一个应用：量子神经网络。
&lt;/p&gt;

&lt;p&gt;
注：本文根据TensorFlow Quantum的MNIST示例整理：&lt;a href=&#34;https://www.tensorflow.org/quantum/tutorials/mnist&#34;&gt;https://www.tensorflow.org/quantum/tutorials/mnist&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
这个示例是基于谷歌在2018年发表的一篇论文&#34;Classification with Quantum Neural Networks on Near Term Processors&#34;。
在这篇论文中，作者Farhi等人提出了将量子电路和神经网络的结合起来实现二元分类的一种方案，主要思路是这样：
&lt;/p&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;将训练输入看作是二进制的字串，把其中每个比特转换成量子比特，例如0对应 \(|0\rangle\) ，1对应 \(|1\rangle\) ；&lt;/li&gt;
&lt;li&gt;创建一个量子电路，输入端有N+1个量子比特，其中N个量子比特对应输入的字串长度，另有一个read out量子比特，用来输出分类结果；&lt;/li&gt;
&lt;li&gt;量子电路内部，用一组带参数的门连接起来，具体用什么门以及如何连接，似乎没有特别的要求，在文章里作者经过试验选用了带参数的XX和ZZ门。每个门带有一个控制参数（例如 \({XX}^\alpha\) ）。如果量子电路有32个这样的门，那么就有32个参数需要学习；&lt;/li&gt;
&lt;li&gt;把量子电路作为神经网络的一层，输入训练集和标签，学习控制参数。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
整个训练过程大致如下：
&lt;/p&gt;

&lt;p&gt;
把量子电路看作神经网络的一层，那么输入训练集里的字串，从它的read out那里读出分类结果，和训练标签比较，产生loss，然后反馈给神经网络进行梯度下降。经过训练，模型会学习到一组量子电路的参数，用这组参数控制量子电路，就能对未知的输入作出准确的分类预测。
&lt;/p&gt;


&lt;div id=&#34;org4f505df&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2020/12/QNN-MNIST.png&#34; alt=&#34;QNN-MNIST.png&#34; width=&#34;500px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
论文原文在这里：&lt;a href=&#34;https://arxiv.org/pdf/1802.06002.pdf&#34;&gt;https://arxiv.org/pdf/1802.06002.pdf&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
这个思路看起来不难，可以用TensorFlow Quantum实现，实际上整个示例，模型部分是很简单的，主要工作在于数据处理。
&lt;/p&gt;

&lt;p&gt;
因为目前的量子计算机和模拟器，对于量子比特的数量和量子电路的深度都有一定的限制，例如MNIST里的图片都是28x28，即使转换成黑白图像，也需要784个量子比特来代表输入，这显然是不现实的。所以在这个示例里，MNIST图像先要降低分辨率，然后要去掉重复，再去掉矛盾的标签，等等，经过一番处理，才能把输入送入模型进行训练。
&lt;/p&gt;

&lt;p&gt;
接下来我们来看一下具体的代码。首先还是先引入要用的包。
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-python&#34;&gt;&lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; tensorflow &lt;span style=&#34;font-weight: bold;&#34;&gt;as&lt;/span&gt; tf
&lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; tensorflow_quantum &lt;span style=&#34;font-weight: bold;&#34;&gt;as&lt;/span&gt; tfq

&lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; cirq
&lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; sympy
&lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; numpy &lt;span style=&#34;font-weight: bold;&#34;&gt;as&lt;/span&gt; np
&lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; seaborn &lt;span style=&#34;font-weight: bold;&#34;&gt;as&lt;/span&gt; sns
&lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; collections

&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;# &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;visualization tools
&lt;/span&gt;%matplotlib inline
&lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; matplotlib.pyplot &lt;span style=&#34;font-weight: bold;&#34;&gt;as&lt;/span&gt; plt
&lt;span style=&#34;font-weight: bold;&#34;&gt;from&lt;/span&gt; cirq.contrib.svg &lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; SVGCircuit
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
读入数据，把每个像素从0-255转换为0-1之间的浮点数：
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子机器学习：TensorFlow Quantum入门</title>
      <link>/quantum/20201127_quantum_machine_learning_tensorflow_quantum_cn/</link>
      <pubDate>Fri, 27 Nov 2020 00:00:00 +0000</pubDate>
      <guid>/quantum/20201127_quantum_machine_learning_tensorflow_quantum_cn/</guid>
      <description>&lt;p&gt;
注：转载请注明作者，本文也发布在作者的个人公众号上。
&lt;/p&gt;

&lt;p&gt;
相关代码请见&lt;a href=&#34;https://github.com/zhoupingjay/quantum/blob/main/Getting-Started-With-TensorFlow-Quantum-CN.ipynb&#34;&gt;作者的Github&lt;/a&gt;。
&lt;/p&gt;

&lt;div id=&#34;outline-container-org80c9b43&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org80c9b43&#34;&gt;TensorFlow Quantum&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org80c9b43&#34;&gt;
&lt;p&gt;
&lt;a href=&#34;https://www.tensorflow.org/quantum&#34;&gt;TensorFlow Quantum&lt;/a&gt; (TFQ) 是谷歌在2020年发布的 &lt;b&gt;量子机器学习框架&lt;/b&gt; ，它能够帮助开发者方便的创建经典+量子结合的混合机器学习模型。量子+机器学习，两个热门的名词结合在一起，听上去很酷！但是你可能会问，这个框架是如何把经典和量子世界结合起来的呢？所谓的”经典-量子混合模型“又是如何工作的？在这个笔记里，我会结合谷歌的&#34;&lt;a href=&#34;https://www.tensorflow.org/quantum/tutorials/hello_many_worlds&#34;&gt;Hello, many world&lt;/a&gt;&#34;示例，实际讲解一下在TFQ下量子机器学习模型的搭建和工作原理。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orged7291b&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orged7291b&#34;&gt;基本概念&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orged7291b&#34;&gt;
&lt;p&gt;
要理解TFQ的代码，首先需要了解一些量子计算的基本概念。
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org7e653e9&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;org7e653e9&#34;&gt;量子比特和状态向量&lt;/h3&gt;
&lt;div class=&#34;outline-text-3&#34; id=&#34;text-org7e653e9&#34;&gt;
&lt;p&gt;
你可能在很多地方已经听到过量子比特（Qubit）的概念。一个经典比特在任意时刻只能处于两个状态中的一个，而量子比特则可以处于两个状态的叠加态：
&lt;/p&gt;

&lt;p&gt;
\(|\psi\rangle = \alpha|0\rangle + \beta|1\rangle\) 
&lt;/p&gt;

&lt;p&gt;
其中， \(\alpha\) 和 \(\beta\) 都是复数，并且 \(|\alpha|^2+|\beta|^2=1\) 。如果我们对这个量子比特进行测量，得到两个状态的概率分别是 \(|\alpha|^2\) 和 \(|\beta|^2\) 。
&lt;/p&gt;

&lt;p&gt;
因此，一个量子比特的状态可以用一个**状态向量**来表示：
&lt;/p&gt;

\begin{matrix}
\begin{pmatrix}
\alpha \\
\beta
\end{pmatrix} 
\end{matrix}

&lt;p&gt;
如果我们的系统里有多个量子比特，每个量子比特有相应的状态向量，那么这个系统的状态向量就是这些量子比特的**张量积**（tensor product）。例如一个系统有两个量子比特 \(\begin{pmatrix}\alpha_1 \\ \beta_1\end{pmatrix}\)  和  \(\begin{pmatrix}\alpha_2 \\ \beta_2\end{pmatrix}\) ，那么这个系统的状态向量就是：
&lt;/p&gt;

&lt;p&gt;
\(\begin{pmatrix}\alpha_1 \\ \beta_1\end{pmatrix}
\otimes
\begin{pmatrix}\alpha_2 \\ \beta_2\end{pmatrix} =
\begin{pmatrix}
\alpha_1\alpha_2 \\
\alpha_1\beta_2 \\
\beta_1\alpha_2 \\
\beta_1\beta_2
\end{pmatrix}\) 
&lt;/p&gt;

&lt;p&gt;
在谷歌的量子计算框架[&lt;a href=&#34;https://github.com/quantumlib/Cirq&#34;&gt;Cirq&lt;/a&gt;]里，模拟器运行的结果里有一个 &lt;code&gt;final_state&lt;/code&gt; 成员，这就是系统的状态向量。详细信息请参见我的[&lt;a href=&#34;https://github.com/zhoupingjay/quantum/blob/main/Quantum-Teleportation.ipynb&#34;&gt;另一篇笔记&lt;/a&gt;]。
&lt;/p&gt;

&lt;p&gt;
量子比特另外一种重要的表示方法是 &lt;b&gt;Bloch球&lt;/b&gt; （Bloch Sphere）。每一个量子比特都可以表示为Bloch球面上的一个向量：
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Machine Learning Meets Quantum: Getting Started with TensorFlow Quantum</title>
      <link>/quantum/20201123_machine_learning_meets_quantum_getting_started_with_tensorflow_quantum/</link>
      <pubDate>Mon, 23 Nov 2020 00:00:00 +0000</pubDate>
      <guid>/quantum/20201123_machine_learning_meets_quantum_getting_started_with_tensorflow_quantum/</guid>
      <description>&lt;p&gt;
Source: &lt;a href=&#34;https://github.com/zhoupingjay/quantum/blob/main/Getting-Started-With-TensorFlow-Quantum.ipynb&#34;&gt;My notebook&lt;/a&gt;
&lt;/p&gt;

&lt;div id=&#34;outline-container-orgedd2036&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgedd2036&#34;&gt;Introduction&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgedd2036&#34;&gt;
&lt;p&gt;
Earlier this year, Google announced &lt;a href=&#34;https://www.tensorflow.org/quantum&#34;&gt;TensorFlow Quantum&lt;/a&gt;. It&#39;s a framework for building &lt;b&gt;Hybrid Quantum-Classical Machine Learning models&lt;/b&gt;. So now we are entering the era of &lt;b&gt;Quantum Machine Learning&lt;/b&gt; - sounds exciting!
&lt;/p&gt;

&lt;p width=&#34;480px&#34;&gt;
&lt;a href=&#34;https://github.com/tensorflow/quantum/blob/master/docs/images/logo/tf_quantum_circle.jpg?raw=true&#34; width=&#34;480px&#34;&gt;TensorFlow Quantum logo&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
You may wonder how these two very different worlds work together, and what these hybrid ML models look like.
In this notebook, I&#39;m going to walk you through the &#34;&lt;a href=&#34;https://www.tensorflow.org/quantum/tutorials/hello_many_worlds&#34;&gt;Hello, many world&lt;/a&gt;&#34; example to explain the basic ideas of building quantum-classical hybrid ML model and how it works on a real problem.
&lt;/p&gt;</description>
    </item>
    <item>
      <title>用Cirq模拟量子隐形传态过程</title>
      <link>/quantum/20201028_cirq_quantum_teleportation/</link>
      <pubDate>Wed, 28 Oct 2020 00:00:00 +0000</pubDate>
      <guid>/quantum/20201028_cirq_quantum_teleportation/</guid>
      <description>&lt;p&gt;
这里我们用谷歌的Cirq框架来模拟量子隐形传态的过程：Alice这里有一个量子比特 \(|\psi\rangle\) ，通过量子隐形传态电路，把状态传送到Bob那里。
&lt;/p&gt;

&lt;p&gt;
关于量子隐形传态的原理，请参见&lt;a href=&#34;https://mp.weixin.qq.com/s?__biz=MzI4ODYxNDY5NA==&amp;amp;mid=2247484394&amp;amp;idx=1&amp;amp;sn=e167ed2e9427fe35ed5a0bc320b19a45&amp;amp;chksm=ec3af3a3db4d7ab5281f3d17ce86cd56e9043316667c9f51d23643cbd444b02535f2faf26cc1&amp;amp;scene=178&amp;amp;cur_album_id=1504407355969617921#rd&#34;&gt;我的相关文章&lt;/a&gt;。
&lt;/p&gt;

&lt;div id=&#34;outline-container-orgab0d979&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgab0d979&#34;&gt;制备纠缠态的量子比特&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgab0d979&#34;&gt;
&lt;p&gt;
要在Alice和Bob之间实现量子隐形传态，首先需要用到一对纠缠态的量子比特。这可以通过一个H门和一个CNOT门来实现：
&lt;/p&gt;


&lt;div id=&#34;orgf5ffa5f&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/Entanglement.svg&#34; alt=&#34;Entanglement.svg&#34; class=&#34;org-svg&#34; width=&#34;320px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
为简化后面的量子电路，可以把这里的H门和CNOT门包装成一个自定义的复合门，这样也方便以后重用。我们把这个自定义门起名叫“纠缠门”（EntangleGate）。
&lt;/p&gt;


&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-python&#34;&gt;&lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; cirq
&lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; numpy &lt;span style=&#34;font-weight: bold;&#34;&gt;as&lt;/span&gt; np

&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;# &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&amp;#21019;&amp;#24314;&amp;#19968;&amp;#20010;&amp;#33258;&amp;#23450;&amp;#20041;&amp;#38376; - &amp;#8220;&amp;#32416;&amp;#32544;&amp;#38376;&amp;#8221;&amp;#65292;&amp;#36755;&amp;#20837;2&amp;#20010;&amp;#37327;&amp;#23376;&amp;#27604;&amp;#29305;
&lt;/span&gt;&lt;span style=&#34;font-weight: bold;&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;EntangleGate&lt;/span&gt;(cirq.ops.gate_features.TwoQubitGate):
    &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;# &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&amp;#20869;&amp;#37096;&amp;#23601;&amp;#26159;&amp;#19968;&amp;#20010;H&amp;#38376;&amp;#21644;&amp;#19968;&amp;#20010;CNOT&amp;#38376;
&lt;/span&gt;    &lt;span style=&#34;font-weight: bold;&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;_decompose_&lt;/span&gt;(&lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;, qubits):
        &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;q0&lt;/span&gt;, &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;q1&lt;/span&gt; = qubits
        &lt;span style=&#34;font-weight: bold;&#34;&gt;yield&lt;/span&gt; cirq.H(q0),
        &lt;span style=&#34;font-weight: bold;&#34;&gt;yield&lt;/span&gt; cirq.CNOT(q0, q1)

    &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;# &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&amp;#25171;&amp;#21360;&amp;#30340;&amp;#26102;&amp;#20505;&amp;#22914;&amp;#20309;&amp;#26174;&amp;#31034;&amp;#36825;&amp;#20010;&amp;#38376;&amp;#65311;
&lt;/span&gt;    &lt;span style=&#34;font-weight: bold;&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;_circuit_diagram_info_&lt;/span&gt;(&lt;span style=&#34;font-weight: bold;&#34;&gt;self&lt;/span&gt;, args):
        &lt;span style=&#34;font-weight: bold;&#34;&gt;return&lt;/span&gt; cirq.protocols.CircuitDiagramInfo(wire_symbols=(&lt;span style=&#34;font-style: italic;&#34;&gt;&#39;E&#39;&lt;/span&gt;, &lt;span style=&#34;font-style: italic;&#34;&gt;&#39;E&#39;&lt;/span&gt;))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
试验一下这个自定义门：
&lt;/p&gt;</description>
    </item>
    <item>
      <title>瞬间移动？传送门？“量子隐形传态”是怎么回事？</title>
      <link>/quantum/20201015_quantum_teleportation/</link>
      <pubDate>Thu, 15 Oct 2020 00:00:00 +0000</pubDate>
      <guid>/quantum/20201015_quantum_teleportation/</guid>
      <description>&lt;p&gt;
&lt;b&gt;&lt;b&gt;注：&lt;/b&gt;&lt;/b&gt; 本文也发布在作者的个人公众号上，转载请注明作者。
&lt;/p&gt;

&lt;p&gt;
说起“ &lt;b&gt;量子隐形传态&lt;/b&gt; ”（ &lt;b&gt;Quantum Teleportation&lt;/b&gt; ），你会想到什么？传送门？瞬间移动？是不是感觉很科幻？其实，量子隐形传态是已经被实验证实的现象，所以理论上说是可以用来制造传送门的……今天我们就来聊聊，量子隐形传态到底是怎么回事。
&lt;/p&gt;

&lt;p&gt;
既然叫“隐形传态”，那么必然有发送方和接收方。这里我们给发送方起名叫Alice，接收方起名叫Bob。假设Alice那边需要传送的量子比特是 \(|\Psi\rangle\) = \((\alpha|0\rangle + \beta |1\rangle)\) 。我们的目标是在Bob那端得到一个和 \(|\Psi\rangle\) 状态完全一样的量子比特。
&lt;/p&gt;

&lt;p&gt;
量子隐形传态需要用到 &lt;b&gt;&lt;b&gt;量子纠缠&lt;/b&gt;&lt;/b&gt; ，我在&lt;a href=&#34;https://www.yuque.com/order66/xu52cg/lct5do&#34;&gt;这篇专栏文章&lt;/a&gt;里有介绍。简单的说，Alice和Bob之间要准备一对纠缠态的量子比特 \(|\Phi_0\Phi_1\rangle\) ：
 \(|\Phi\rangle\) = \(|\Phi_0\Phi_1\rangle\) = \((\frac{1}{\sqrt{2}}|00\rangle + \frac{1}{\sqrt{2}}|11\rangle)\) 
这两个纠缠态的量子比特，Alice和Bob各拿其中一个，Bob可以在很远的地方，只要两个量子比特仍然处于纠缠态，隐形传态就能进行。
&lt;/p&gt;

&lt;p&gt;
好了，准备工作完成，我们可以来搭电路了！
&lt;/p&gt;

&lt;p&gt;
Alice这边的电路长这样：
&lt;/p&gt;


&lt;div id=&#34;orgbc2c076&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2020/10/image.png&#34; alt=&#34;image.png&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
老规矩，我们分时序来分析：
&lt;/p&gt;

&lt;p&gt;
t0:
&lt;/p&gt;

&lt;p&gt;
\(|\Psi\rangle |\Phi\rangle = (\alpha|0\rangle + \beta |1\rangle)  (\frac{1}{\sqrt{2}}|00\rangle + \frac{1}{\sqrt{2}}|11\rangle)\)
&lt;/p&gt;

&lt;p&gt;
，展开成
&lt;/p&gt;

\begin{matrix}
\frac{\alpha}{\sqrt{2}}|000\rangle + \frac{\beta}{\sqrt{2}}|100\rangle +
\frac{\alpha}{\sqrt{2}}|011\rangle +
\frac{\beta}{\sqrt{2}}|111\rangle 
\end{matrix}

&lt;p&gt;
t1:  \(|\Psi\rangle\) 和 \(|\Phi_0\rangle\) 经过CNOT门，系统状态变成了
&lt;/p&gt;

\begin{matrix}
\frac{\alpha}{\sqrt{2}}|000\rangle + \frac{\beta}{\sqrt{2}}|110\rangle +
\frac{\alpha}{\sqrt{2}}|011\rangle +
\frac{\beta}{\sqrt{2}}|101\rangle
\end{matrix}

&lt;p&gt;
t2:  \(|\Psi\rangle\) 再经过一个H门，前面我们说过，H门会把 \(|0\rangle\) 变成 \(\frac{1}{\sqrt{2}}(|0\rangle + |1\rangle)\) ，把 \(|1\rangle\) 变成 \(\frac{1}{\sqrt{2}}(|0\rangle - |1\rangle)\) 。那么把这个替换上面的 \(|\Psi\rangle\) ，系统状态变成了：
&lt;/p&gt;</description>
    </item>
    <item>
      <title>超越时空的联系 – 量子纠缠是怎么回事</title>
      <link>/quantum/20200922_quantum_entanglement/</link>
      <pubDate>Tue, 22 Sep 2020 00:00:00 +0000</pubDate>
      <guid>/quantum/20200922_quantum_entanglement/</guid>
      <description>&lt;p&gt;
所谓“遇事不决，量子力学”，“量子纠缠”是量子力学中的一个重要现象，也是科幻故事中经常用到的填坑大杀器。实际上，量子纠缠是真实的物理现象，也是实现量子通信的核心之一。今天我们就来聊聊量子纠缠是怎么回事。
&lt;/p&gt;

&lt;p&gt;
假设我们有2个量子比特A和B，初始状态都是\(|0\rangle\)，然后搭一个简单的电路：
&lt;/p&gt;



&lt;div id=&#34;org84c2c09&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2020/09/image-8.png&#34; alt=&#34;image-8.png&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
只需要一个H门和一个CNOT门，就能让A和B之间形成量子纠缠！
&lt;/p&gt;

&lt;p&gt;
不信？我们来分析一下。
&lt;/p&gt;

&lt;p&gt;
t0时刻，两个量子比特都是 \(|0\rangle\) ，整个系统的状态是 \(|00\rangle\) 。
&lt;/p&gt;

&lt;p&gt;
t1时刻，A经过H门后变成了相干态 \(\frac{1}{\sqrt{2}}(|0\rangle + |1\rangle)\) ，而B不变还是 \(|0\rangle\) ，整个系统状态变成 \(\frac{1}{\sqrt{2}}(|00\rangle + |10\rangle)\) 。
&lt;/p&gt;

&lt;p&gt;
t2时刻，经过一个CNOT门。CNOT意思是“Controlled NOT”，就是说当A是1的话，B就取反，否则B不变。因为这里A已经是相干态（ \(|0\rangle\) 和 \(|1\rangle\) 的叠加），那么经过这个CNOT门以后，A如果是 \(|0\rangle\) ，那么B不变还是 \(|0\rangle\) ，而A如果是 \(|1\rangle\) ，那么B就从 \(|0\rangle\) 变成 \(|1\rangle\) 。所以整个系统经过这个CNOT门后，就变成了这样一个状态：
&lt;/p&gt;

&lt;p&gt;
\(\frac{1}{\sqrt{2}}(|00\rangle + |11\rangle)\)
&lt;/p&gt;

&lt;p&gt;
看出什么没有？在这个状态下，A和B要么都是 \(|0\rangle\) ，要么都是 \(|1\rangle\) ！也就是说，如果我们测量A得到0，那么我们知道B测量得到肯定也是0，反之如果我们测量A得到1，那么B肯定也是1。通过这个电路，我们把A和B两个量子比特的状态“纠缠”在了一起，这个状态就叫做“ &lt;b&gt;纠缠态&lt;/b&gt; ”。
&lt;/p&gt;

&lt;p&gt;
这时候，如果我们把A和B分开，A和B之间还会处于纠缠态吗？答案是肯定的，只要它们没有退相干，A和B仍然处于会量子纠缠状态。即使我们把B送到银河系的另一端，它们仍然会“纠缠”在一起。甚至，如果我们对其中之一做进一步的量子变换，只要不导致退相干，它们之间仍然会保持纠缠态！
&lt;/p&gt;

&lt;p&gt;
这就是量子纠缠的原理，是不是挺简单的？:-)
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;&lt;b&gt;常见误解：量子纠缠能实现超光速通信？&lt;/b&gt;&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
信息的传递不可能超光速，否则会导致因果律的崩溃。表面上看，一端的测量会导致另一端的状态坍缩，这个作用是“瞬时”的，但是实际上这个动作没有在两端之间传递任何信息，因为测量得到0和1完全是随机的。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>用谷歌Cirq模拟双比特Deutsch问题</title>
      <link>/quantum/20200913_cirq_2_bit_deutsch_problem/</link>
      <pubDate>Sun, 13 Sep 2020 00:00:00 +0000</pubDate>
      <guid>/quantum/20200913_cirq_2_bit_deutsch_problem/</guid>
      <description>&lt;div id=&#34;outline-container-org573ec2b&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org573ec2b&#34;&gt;谷歌量子计算框架Cirq&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org573ec2b&#34;&gt;
&lt;p&gt;
Cirq是谷歌开发的开源量子计算框架，它让开发者能够方便的用Python搭建量子电路。您可能会问，我没有量子计算机，如何运行我设计的电路呢？别急，Cirq内置了模拟器，您在自己的电脑上就可以模拟您设计的量子电路。如果想在真实的量子计算机上运行，Cirq也提供了相应的接口。
&lt;/p&gt;

&lt;p&gt;
Cirq的源码：&lt;a href=&#34;https://github.com/quantumlib/Cirq&#34;&gt;https://github.com/quantumlib/Cirq&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Cirq的安装，最简单的方法是用pip：
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-shell&#34;&gt;python -m pip install --upgrade pip
python -m pip install cirq
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
安装完成，您就可以在电脑上模拟量子计算了！
&lt;/p&gt;

&lt;p&gt;
接下来进入实战，我们要用Cirq来模拟双比特Deutsch问题。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org1972d38&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org1972d38&#34;&gt;回顾一下双比特Deutsch问题&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org1972d38&#34;&gt;
&lt;p&gt;
回顾一下双比特Deutsch问题：有人给你一个函数f，不告诉你它内部是怎么运作的，只知道它输入2个比特，输出1个比特，并且f有可能是常量函数（无论什么输入，输出总是0或者总是1），也有可能是平衡函数（对所有可能的输入，一半的情况下输出0，另一半情况输出1）。我们只能通过对f的查询，来判断f的性质。在上文我们讨论过，这样的函数f总共有8种可能（2个常量函数，6个平衡函数）。所以，提问的人实际上是从这8个可能的f函数中，随机抽一个给我们来判断。
&lt;/p&gt;


&lt;div id=&#34;org275c147&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2-bit deutsch.svg&#34; alt=&#34;2-bit deutsch.svg&#34; class=&#34;org-svg&#34; width=&#34;400px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
我们知道量子计算里，每个这样的函数f，都可以包装成相应的可逆变换Uf。所以在量子计算环境下，提问的人实际上是把这8种可能的函数f包装成8个Uf，从里面随机抽一个作为黑盒给我们，让我们判断相应的函数f的性质。
&lt;/p&gt;

&lt;p&gt;
所以要模拟双比特Deutsch问题，我们首先要从提问者的角度，把这8个可能的Uf准备出来。
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;&lt;b&gt;我们从一个简单的例子出发：&lt;/b&gt;&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
假如有这样一个平衡函数函数f，它在输入是00或01的情况下输出0，其余情况下输出1，我们把它和相应的Uf输出列在下面的表里：
&lt;/p&gt;

&lt;table border=&#34;2&#34; cellspacing=&#34;0&#34; cellpadding=&#34;6&#34; rules=&#34;groups&#34; frame=&#34;hsides&#34;&gt;


&lt;colgroup&gt;
&lt;col  class=&#34;org-right&#34; /&gt;

&lt;col  class=&#34;org-right&#34; /&gt;

&lt;col  class=&#34;org-left&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-right&#34;&gt;输入 (x0x1)&lt;/th&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-right&#34;&gt;\[f(x_0x_1)\]&lt;/th&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-left&#34;&gt;\[y\oplus f(x_0x_1)\]&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;00&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;0&lt;/td&gt;
&lt;td class=&#34;org-left&#34;&gt;y&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;01&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;0&lt;/td&gt;
&lt;td class=&#34;org-left&#34;&gt;y&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;10&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;1&lt;/td&gt;
&lt;td class=&#34;org-left&#34;&gt;y取反&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;11&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;1&lt;/td&gt;
&lt;td class=&#34;org-left&#34;&gt;y取反&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
从上面这个表中可以看出，Uf的第三个输出端，其状态取决于第一个输入：
&lt;/p&gt;

&lt;p&gt;
如果x0=1，那么在第三个输出端输出，反之如果x0=1，那么就输出。这在量子电路里，就是一个简单的CNOT门：CNOT(x0, y)。所以对于上面这个表里的f函数，包装成相应的Uf内部就是一个简单的CNOT门实现。
&lt;/p&gt;


&lt;div id=&#34;orgbdef2a6&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2-bit deutsch 2.svg&#34; alt=&#34;2-bit deutsch 2.svg&#34; class=&#34;org-svg&#34; width=&#34;400px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;b&gt;&lt;b&gt;以此类推，对每一个函数f，我们都可以用量子电路来实现相应的Uf。&lt;/b&gt;&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
我们把这些Uf放在一个池子里，模拟的时候从里面随机选一个，作为提问者的问题。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orgec21bbd&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgec21bbd&#34;&gt;用Cirq模拟双比特Deutsch问题&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgec21bbd&#34;&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-org88730e1&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;org88730e1&#34;&gt;首先我们要导入Cirq包：&lt;/h3&gt;
&lt;div class=&#34;outline-text-3&#34; id=&#34;text-org88730e1&#34;&gt;
&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-python&#34;&gt;&lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; cirq
&lt;span style=&#34;font-weight: bold;&#34;&gt;import&lt;/span&gt; random
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org084b69d&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;org084b69d&#34;&gt;然后生成这个Uf池子：&lt;/h3&gt;
&lt;div class=&#34;outline-text-3&#34; id=&#34;text-org084b69d&#34;&gt;
&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-python&#34;&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;q0&lt;/span&gt;, &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;q1&lt;/span&gt;, &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;q2&lt;/span&gt; = cirq.LineQubit.&lt;span style=&#34;font-weight: bold;&#34;&gt;range&lt;/span&gt;(3)
&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;constant&lt;/span&gt; = [[], [cirq.X(q2)]]
&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;balanced&lt;/span&gt; = [[cirq.CNOT(q0, q2)],
            [cirq.CNOT(q1, q2)],
            [cirq.CNOT(q0, q2), cirq.CNOT(q1, q2)],
            [cirq.CNOT(q0, q2), cirq.X(q2)],
            [cirq.CNOT(q1, q2), cirq.X(q2)],
            [cirq.CNOT(q0, q2), cirq.CNOT(q1, q2), cirq.X(q2)]]

&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;Uf_pool&lt;/span&gt; = [
    [],            &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;# &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&amp;#24120;&amp;#37327;&amp;#20989;&amp;#25968;: f(x0x1) = 0
&lt;/span&gt;    [cirq.X(q2)],  &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;# &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&amp;#24120;&amp;#37327;&amp;#20989;&amp;#25968;: f(x0x1) = 1
&lt;/span&gt;
    [cirq.CNOT(q0, q2)], &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;# &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&amp;#24179;&amp;#34913;&amp;#20989;&amp;#25968;: f(00/01)=0, f(10/11)=1
&lt;/span&gt;    [cirq.CNOT(q1, q2)], &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;# &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&amp;#24179;&amp;#34913;&amp;#20989;&amp;#25968;
&lt;/span&gt;    [cirq.CNOT(q0, q2), cirq.CNOT(q1, q2)], &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;# &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&amp;#24179;&amp;#34913;&amp;#20989;&amp;#25968;
&lt;/span&gt;    [cirq.CNOT(q0, q2), cirq.X(q2)],        &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;# &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&amp;#24179;&amp;#34913;&amp;#20989;&amp;#25968;
&lt;/span&gt;    [cirq.CNOT(q1, q2), cirq.X(q2)],        &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;# &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&amp;#24179;&amp;#34913;&amp;#20989;&amp;#25968;
&lt;/span&gt;    [cirq.CNOT(q0, q2), cirq.CNOT(q1, q2), cirq.X(q2)] &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;# &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&amp;#24179;&amp;#34913;&amp;#20989;&amp;#25968;
&lt;/span&gt;]
&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;Uf_attributes&lt;/span&gt; = [
    &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;constant&#34;&lt;/span&gt;,
    &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;constant&#34;&lt;/span&gt;,
    &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;balanced&#34;&lt;/span&gt;,
    &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;balanced&#34;&lt;/span&gt;,
    &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;balanced&#34;&lt;/span&gt;,
    &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;balanced&#34;&lt;/span&gt;,
    &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;balanced&#34;&lt;/span&gt;,
    &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;balanced&#34;&lt;/span&gt;,
]
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org9e5053b&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;org9e5053b&#34;&gt;根据Uf生成量子电路&lt;/h3&gt;
&lt;div class=&#34;outline-text-3&#34; id=&#34;text-org9e5053b&#34;&gt;
&lt;p&gt;
接下来，我们要写一个函数，根据提问者给出的Uf，生成相应的量子电路。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>量子计算编程实战 – 双比特Deutsch问题</title>
      <link>/quantum/20200904_2_bit_deutsch_problem/</link>
      <pubDate>Fri, 04 Sep 2020 00:00:00 +0000</pubDate>
      <guid>/quantum/20200904_2_bit_deutsch_problem/</guid>
      <description>&lt;p&gt;
在上一篇 “一文看懂量子计算机的威力 – 从Deutsch问题说起” 中，我们看到了量子计算机只需一次查询就可以判断函数的特性。但是在那个例子中，我们讨论的是一个简单的单比特函数，如果把输入扩展到多比特，量子计算机是否仍然只需要一次查询呢？今天我们就结合谷歌的Cirq框架，看看量子计算的 &lt;b&gt;指数级&lt;/b&gt; 加速。
&lt;/p&gt;

&lt;div id=&#34;outline-container-org001b0f5&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org001b0f5&#34;&gt;双比特Deutsch问题&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org001b0f5&#34;&gt;
&lt;p&gt;
首先和上次一样，假设我们有个函数f，但这次函数f输入2个比特，输出1个比特。这个函数f对我们是黑盒，我们不知道这个函数内部是怎么运作的，只能通过喂给它不同的输入，观察输出。因为输入有2个比特，因此共有4种可能的输入00，01，10，11。
&lt;/p&gt;

&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;如果f无论什么输入，输出始终是0或者1，我们称它为“常量”函数，记作 \(f_0\) 或者 \(f_1\) ;&lt;/li&gt;
&lt;li&gt;如果f的输出，0和1各占一半，我们称它为“平衡”函数。平衡函数有多少种可能呢？这个问题就相当于说，我们在下面表中的4个输出位置，需要填两个0和两个1，有几种填法？用简单的排列组合可以知道，一共有6种，也就是说一共有6个“平衡”函数。&lt;/li&gt;
&lt;/ul&gt;

&lt;table border=&#34;2&#34; cellspacing=&#34;0&#34; cellpadding=&#34;6&#34; rules=&#34;groups&#34; frame=&#34;hsides&#34;&gt;


&lt;colgroup&gt;
&lt;col  class=&#34;org-right&#34; /&gt;

&lt;col  class=&#34;org-left&#34; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;输入&lt;/td&gt;
&lt;td class=&#34;org-left&#34;&gt;输出&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;---&lt;/td&gt;
&lt;td class=&#34;org-left&#34;&gt;---&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;00&lt;/td&gt;
&lt;td class=&#34;org-left&#34;&gt;0或者1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;01&lt;/td&gt;
&lt;td class=&#34;org-left&#34;&gt;0或者1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;10&lt;/td&gt;
&lt;td class=&#34;org-left&#34;&gt;0或者1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-right&#34;&gt;11&lt;/td&gt;
&lt;td class=&#34;org-left&#34;&gt;0或者1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;当然，函数f也有可能既不是常量，也不是平衡的，例如上面的表里面，输出栏里可以填上三个0。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
&lt;b&gt;双比特Deutsch问题是问，假如我们已经知道函数f要么是常量，要么是平衡的，如何判断它是常量还是平衡的呢？&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
对于n比特输入，经典计算机需要至少查询一半可能的输入，也就是 \(2^{n-1}+1\) 次（在这个例子里n=2，所以需要查询3次）。显然随着输入比特数的增加，计算复杂性（需要查询的次数）是指数上升的。而 &lt;b&gt;&lt;b&gt;如果用量子计算机，无论输入n有多大，我们始终只需要对函数f进行一次查询！&lt;/b&gt;&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
怎么做到呢？套路和上次一样，引入一个辅助输入y，把函数f包装成量子比特版本Uf：
&lt;/p&gt;

\begin{matrix}
U_f |x_0\rangle |x_1\rangle |y\rangle
\to 
|x_0\rangle |x_1\rangle |y \oplus f(x_0x_1)\rangle 
\end{matrix}

&lt;p&gt;
然后在两边加上Hadamard门，电路也和上次的单比特电路差不多：
&lt;/p&gt;


&lt;div id=&#34;org5540850&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2020/09/image-1.png&#34; alt=&#34;image-1.png&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
猜猜看在输出端测量，我们会得到啥？
&lt;/p&gt;

&lt;p&gt;
这里先把结论放在这里 &lt;b&gt;：如果输出端得到的是全0，那么函数f一定是常量函数，反之它就是平衡函数。&lt;/b&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org6cda474&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org6cda474&#34;&gt;原理解析&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org6cda474&#34;&gt;
&lt;p&gt;
下面我们做一些推导，可以帮助您理解其中的原理。如果您不感兴趣，可以直接跳到下一篇的实战部分。其实推导并不难，不要被公式吓到 :-)
&lt;/p&gt;

&lt;p&gt;
为便于分析，我在前面的电路图中标出了时间（t0, t1, t2, t3)。
&lt;/p&gt;

&lt;p&gt;
在 &lt;b&gt;时间t0&lt;/b&gt; ，电路的状态是 \(|0\rangle|0\rangle|1\rangle\) 。
&lt;/p&gt;

&lt;p&gt;
在 &lt;b&gt;时间t1&lt;/b&gt; ，前两个量子比特都处于 \(\frac{1}{\sqrt{2}}(|0\rangle+|1\rangle)\) 状态，第三个处于 \(\frac{1}{\sqrt{2}}(|0\rangle-|1\rangle)\) 状态。如果我们把前两个量子比特放一起考虑，相当于把他们的状态做一个卷积，也就是：
&lt;/p&gt;

\begin{matrix}
\frac{1}{\sqrt{2}}(|0\rangle+|1\rangle) \otimes \frac{1}{\sqrt{2}}(|0\rangle+|1\rangle)
=
\frac{1}{2}(|00\rangle + |01\rangle + |10\rangle + |11\rangle)
\end{matrix}

&lt;p&gt;
加上第三个辅助量子比特，整个电路的状态就是
&lt;/p&gt;</description>
    </item>
    <item>
      <title>理解量子计算机的威力：Deutsch问题</title>
      <link>/quantum/deutsch-problem-1-cn/</link>
      <pubDate>Sat, 01 Aug 2020 00:00:00 +0000</pubDate>
      <guid>/quantum/deutsch-problem-1-cn/</guid>
      <description>&lt;div id=&#34;outline-container-org1e3ef9e&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org1e3ef9e&#34;&gt;简介&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org1e3ef9e&#34;&gt;
&lt;p&gt;
量子计算是现在的热门话题之一，很多人可能听说过诸如“量子霸权”之类的名词，那么量子计算为什么会被认为有可能比经典计算机更快呢？这里就从最简单的Deutsch问题入手，解析量子计算的一些基本思路，相信看完后你会对量子计算的潜力有更直观的认识。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orgfbdada2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgfbdada2&#34;&gt;一些术语和基础概念&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgfbdada2&#34;&gt;
&lt;p&gt;
首先要先解释一下后面讨论中用到的一些术语和基础知识。
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;量子比特（Qubit）&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
我们知道，一个经典比特（bit）只能表示两种状态（0或者1）。而一个量子比特除了 \(|0\rangle\) 和 \(|1\rangle\) 之外，还可以处于一种叫相干态（superposition）的状态，即“同时”处于 \(|0\rangle\) 和 \(|1\rangle\) 两种状态。这可以用 \(\alpha|0\rangle + \beta|1\rangle\) 来表示（ \(\alpha\) 和 \(\beta\) 都是复数）。一个常见的例子是 \(\frac{1}{\sqrt{2}}(|0\rangle+|1\rangle)\) ，测量得到0和1的概率分别是50%。
&lt;/p&gt;

&lt;p&gt;
量子计算电路里常见的几种门（变换）：
&lt;/p&gt;

&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;I：Identity变换，简单说就是啥也不变，输入啥输出也是啥。&lt;/li&gt;
&lt;li&gt;H: Hadamard门，在这个例子里主要作用是制备相干态，因为H门可以把 \(|0\rangle\) 变成 \(\frac{1}{\sqrt{2}}(|0\rangle+|1\rangle)\) ，而把 \(|1\rangle\) 变成 \(\frac{1}{\sqrt{2}}(|0\rangle-|1\rangle)\) 。另外H变换还有个特性，就是HH=I，两个H变换互相抵消。&lt;/li&gt;
&lt;li&gt;Z：输入 \(|x\rangle\) ，输出 \((-1)^x|x\rangle\) ，例如输入 \(|0\rangle\) ，输出 \(|0\rangle\) ，而输入是 \(|1\rangle\) 的话，输出是 \(-|1\rangle\) 。&lt;/li&gt;
&lt;li&gt;X：简单说就是将输入取反，输入 \(|0\rangle\) 的话，输出 \(|1\rangle\) ，而输入 \(|1\rangle\) ，则输出 \(|0\rangle\) 。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
另外，还有两个特性后面会用到：
&lt;/p&gt;

\begin{matrix}
HZH=X \\
HIH=I
\end{matrix}

&lt;p&gt;
好了，需要了解的基础知识就这么些，接下来我们来看量子计算是如何加速Deutsch问题的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org1692a91&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org1692a91&#34;&gt;问题的提出：如何判断单比特函数的性质？&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org1692a91&#34;&gt;
&lt;p&gt;
假设我们有个函数f，输入和输出都是1个比特： \(y=f(x)\) ： 
&lt;/p&gt;

&lt;div id=&#34;org613d2ab&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/deutsch-fx.png&#34; alt=&#34;deutsch-fx.png&#34; width=&#34;320px&#34; /&gt;
&lt;/p&gt;</description>
    </item>
    <item>
      <title>看懂量子计算机的威力 - 从Deutsch问题说起</title>
      <link>/quantum/20200801_quantum_computing_deustch_problem/</link>
      <pubDate>Sat, 01 Aug 2020 00:00:00 +0000</pubDate>
      <guid>/quantum/20200801_quantum_computing_deustch_problem/</guid>
      <description>&lt;div id=&#34;outline-container-orgc2fd301&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgc2fd301&#34;&gt;简介&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgc2fd301&#34;&gt;
&lt;p&gt;
量子计算是现在的热门话题之一，很多人可能听说过诸如“量子霸权”之类的名词，那么量子计算为什么会被认为有可能比经典计算机更快呢？这里就从最简单的Deutsch问题入手，解析量子计算的一些基本思路，相信看完后你会对量子计算的潜力有更直观的认识。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org777f262&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org777f262&#34;&gt;一些术语和基础&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org777f262&#34;&gt;
&lt;p&gt;
首先要先解释一下后面讨论中用到的一些术语和基础知识。
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;量子比特（Qubit）&lt;/b&gt; ：我们知道，一个经典比特（bit）只能表示两种状态（0或者1）。而一个量子比特除了 \(|0\rangle\) 和 \(|1\rangle\) 之外，还可以处于一种叫相干态（superposition）的状态，即“同时”处于 \(|0\rangle\) 和 \(|1\rangle\) 两种状态。这可以用 \(\alpha|0\rangle + \beta|1\rang\) 来表示（ \(\alpha\) 和 \(\beta\) 都是复数）。一个常见的例子是 \(\frac{1}{\sqrt{2}}(|0\rangle+|1\rangle)\) ，测量得到0和1的概率分别是50%。
&lt;/p&gt;

&lt;p&gt;
量子计算电路里常见的几种门（变换）：
&lt;/p&gt;

&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;I：Identity变换，简单说就是啥也不变，输入啥输出也是啥。&lt;/li&gt;
&lt;li&gt;H: Hadamard门，在这个例子里主要作用是制备相干态，因为H门可以把 \(|0\rangle\) 变成 \(\frac{1}{\sqrt{2}}(|0\rangle+|1\rangle)\) ，而把 \(|1\rangle\) 变成 \(\frac{1}{\sqrt{2}}(|0\rangle-|1\rangle)\) 。另外H变换还有个特性，就是HH=I，两个H变换互相抵消。&lt;/li&gt;
&lt;li&gt;Z：输入 \(|x\rangle\) ，输出 \((-1)^x|x\rangle\) ，例如输入 \(|0\rangle\) ，输出 \(|0\rangle\) ，而输入是 \(|1\rangle\) 的话，输出是 \(-|1\rangle\) 。&lt;/li&gt;
&lt;li&gt;X：简单说就是将输入取反，输入 \(|0\rangle\) 的话，输出 \(|1\rangle\) ，而输入 \(|1\rangle\) ，则输出 \(|0\rangle\) 。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
另外，还有两个特性后面会用到：
&lt;/p&gt;

&lt;p&gt;
\(HZH=X\) 
\(HIH=I\) 
&lt;/p&gt;

&lt;p&gt;
好了，需要了解的基础知识就这么些，接下来我们来看量子计算是如何加速Deutsch问题的。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org274a03c&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org274a03c&#34;&gt;问题的提出：如何判断单比特函数的性质？&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org274a03c&#34;&gt;
&lt;p&gt;
假设我们有个函数f，输入和输出都是1个比特： \(y=f(x)\) ：
&lt;/p&gt;


&lt;div id=&#34;org67c8860&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2020/08/image-300x66.png&#34; alt=&#34;image-300x66.png&#34; width=&#34;320px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
因为输入和输出都只有1个比特，这个函数无非就是这4种可能：
&lt;/p&gt;

&lt;ol class=&#34;org-ol&#34;&gt;
&lt;li&gt;\(f(x)=0\) ，即不管x是0还是1，f(x)总是0，我们记作 \(f_0\)&lt;/li&gt;
&lt;li&gt;\(f(x)=1\) ，即不管x是0还是1，f(x)总是1，我们记作 \(f_1\)&lt;/li&gt;
&lt;li&gt;\(f(x)=x\) ，即f(x)输出比特和输入比特相同，我们记作 \(f_x\)&lt;/li&gt;
&lt;li&gt;\(f(x) = \bar{x}\) ，即f(x)输出比特与输入比特相反，我们记作 \(f_\bar{x}\)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
前两种可能，我们称为“常量”函数（constant），因为他们的输出是常量；而后两种我们称为“平衡”函数（balanced），因为他们所有可能的输出中间，0和1各占一半。
&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
