
void rondamNumber() { init(); QProg & random = CreateEmptyQProg(); //Create an empty program named etangle auto qbit0 = qAlloc(); auto qbit1 = qAlloc(); auto qbit2 = qAlloc(); auto qbit3 = qAlloc(); auto qbit4 = qAlloc(); auto qbit5 = qAlloc(); auto qbit6 = qAlloc(); // allocate 6 qubits auto cbit0 = cAlloc(); auto cbit1 = cAlloc(); auto cbit2 = cAlloc(); auto cbit3 = cAlloc(); auto cbit4 = cAlloc(); auto cbit5 = cAlloc(); auto cbit6 = cAlloc(); // allocate 7 cbits random << H(qbit0) << H(qbit1) << H(qbit2) << H(qbit3) << H(qbit4) << H(qbit5) << H(qbit6) << Measure(qbit0, cbit0) << Measure(qbit1, cbit1) << Measure(qbit2, cbit2) << Measure(qbit3, cbit3) << Measure(qbit4, cbit4) << Measure(qbit5, cbit5) << Measure(qbit6, cbit6); // Required quantum circuit. load(random); // And then load it into the quantum computer. run(); // simply run it. auto resultMap = getResultMap(); // you can get the result map, which save all the // measurement results in the classical register(CBit) auto Num000 = resultMap["c0"]; auto Num001 = resultMap["c1"]; auto Num010 = resultMap["c2"]; auto Num011 = resultMap["c3"]; auto Num101 = resultMap["c4"]; auto Num110 = resultMap["c5"]; auto Num111 = resultMap["c6"]; cout <<"The random number of this production is;" << Num000 << Num001 << Num010 << Num011 << Num101 << Num110 << Num111; finalize(); // Use finalize() to tell the quantum computer to stop. }
考虑函数:
$f:\{0,1\}^n \rightarrow \{0,1\} $
我们保证有如下两种可能性:
(1)$f$是常数的(Constant),即是对$x\in\{0,1\}^n $,都有$f(x)=0$或$f(x)=1$.
(2)$f$是平衡的(Balanced),对于输入的$x\in\{0,1\}^n $,$f(x)$出输出0和1的个数相同。
算法的目标:判断函数$f$是什么类型。
在最简单的情况下,最少也需要2次才能判断函数属于什么类型。因为需要第二个输出才能判断最终函数的类型。对于n位输入时,最坏的情况下需要次才能确认。
通过构造Oracle的方式,仅需运行一次就能确定函数属于哪一类。

第一步,制备n个工作(Working)比特到 $|0 \left. \right \rangle$态,与一个辅助(Ancillary)比特到 $|1 \left. \right \rangle$。第二步,所有比特都经过Hadamard变换,使系统处于叠加态上。
$$|0\left. \right \rangle^{\otimes_n}|1\left. \right \rangle\xrightarrow{H^{\otimes_{n+1}}}\frac{1}{ \sqrt{2^n}}\sum_{x=0}^{2^n-1}|x\left. \right \rangle{(\frac{|0\left. \right \rangle-|1\left. \right \rangle}{ \sqrt{2}})}$$
第三步,系统通过Oracle ,一种酉变换,满足:
$$U_f:|x\left. \right \rangle|y\left. \right \rangle \longrightarrow |x\left. \right \rangle|y\oplus f(x)\left. \right \rangle$$
这时候,系统状态为:
$$\frac{1}{\sqrt{2^n}}\sum_{x=0}^{2^n-1}|x\left. \right \rangle{(\frac{|0\left. \right \rangle-|1\left. \right \rangle}{ \sqrt{2}})}\xrightarrow{Oracle}\frac{1}{\sqrt{2^n}}\sum_{x=0}^{2^n-1} {(-1)^{f(x)}} |x\left. \right \rangle{(\frac{|0\left. \right \rangle-|1\left. \right \rangle}{ \sqrt{2}})}$$
当时$f(x)=1$,会使得$\frac{|0\left. \right \rangle-|1\left. \right \rangle }{\sqrt{2}} \longrightarrow \frac{|1\left. \right \rangle-|0\left. \right \rangle }{\sqrt{2}}$,发生相位的翻转。
第四步:去除辅助比特,执行Bell测量。如果输出全部为0,则是$f$是常数的,反之,这是平衡的。

/* Copyright (c) 2017-2018 Origin Quantum Computing. All Right Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "DJ_Algorithm.h" void DJ_Algorithm() { bool fx0 = 0, fx1 = 0; cout << "input the input function" << endl << "The function has a boolean input" << endl << "and has a boolean output" << endl << "f(0)= (0/1)?"; cin >> fx0; cout << "f(1)=(0/1)?"; cin >> fx1; vector<bool> oracle_function({ fx0,fx1 }); cout << "Programming the circuit..." << endl; init(); auto q1 = qAlloc(); auto q2 = qAlloc(); auto c1 = cAlloc(); Reset_Qubit(q1, false); Reset_Qubit(q2, true); append(Two_Qubit_DJ_Algorithm_Circuit(q1, q2, c1, oracle_function)); run(); //auto resultMap = getResultMap(); if (getCBitValue(c1) == false) { cout << "Constant function!"; } else if (getCBitValue(c1) == true) { cout << "Balanced function!"; } } QProg & Two_Qubit_DJ_Algorithm_Circuit( Qubit * qubit1, Qubit * qubit2, CBit * cbit, vector<bool> oracle_function) { auto &prog = CreateEmptyQProg(); //Firstly, create a circuit container prog << H(qubit1) << H(qubit2); // Perform Hadamard gate on all qubits if (oracle_function[0] == false && oracle_function[1] == false) // different oracle leads to different circuit // f(x) = oracle_function[x] { // f(x) = 0, do nothing } else if (oracle_function[0] == false && oracle_function[1] == true ) { // f(x) = x; prog << CNOT(qubit1, qubit2); } else if (oracle_function[0] == true && oracle_function[1] == false ) { // f(x) = x + 1; prog << RX(qubit2) << CNOT(qubit1, qubit2) << RX(qubit2); } else if (oracle_function[0] == true && oracle_function[1] == true ) { // f(x) = 1 prog << RX(qubit2); } // Finally, Hadamard the first qubit and measure it prog << H(qubit1) << Measure(qubit1, cbit); return prog; }
这是一个硬币(便士)反转的游戏,游戏由两个玩家和一个可翻转硬币组成。和以往的游戏一 样,玩家在游戏开始之前,彼此都可以接受任何的策略,但是游戏开始之后,彼此没有任何交流和通信。游戏开始之前,玩家彼此,而且双眼 被蒙住,不可以看到当前翻转投掷硬币的状态。考虑玩家P和Q,以及一枚初始化处于H面(数字1,表示H,国徽面是T面)的硬币,如下:

初始的硬币状态是朝上(H)。
P,Q共同可以翻转该硬币。每次翻转后,玩家不可以看自己翻转的情况。
每个玩家可以自由翻转或者不翻转。
翻转的顺序是:Q $\rightarrow $ P $\rightarrow $ Q。
游戏结束,如果硬币是H面,Q赢,如果是T面,P赢。
考虑编码硬币的两个状态,分别为:
$$H= \begin{pmatrix}0\\1\end{pmatrix} ,T= \begin{pmatrix}0\\1\end{pmatrix} $$
如上文,H和T分别表示硬币的正反面,下面给定翻转操作,F为翻转,I为不翻转,分别为:
$$ F=\begin{bmatrix}0&1\\1&0\end{bmatrix} , I=\begin{bmatrix}1&0\\0&1\end{bmatrix} $$
验证FH=T,FT=H,并且验证不翻转的情况:
$$ FH=\begin{bmatrix}0&1\\1&0\end{bmatrix}\begin{pmatrix}1\\0\end{pmatrix}=\begin{pmatrix}0\\1\end{pmatrix}=T ,FT=\begin{bmatrix}0&1\\1&0\end{bmatrix}\begin{pmatrix}0\\1\end{pmatrix}=\begin{pmatrix}1\\0\end{pmatrix}=H $$
$$ IH=\begin{bmatrix}1&0\\0&1\end{bmatrix} \begin{pmatrix}1\\0\end{pmatrix} = \begin{pmatrix}1\\0\end{pmatrix} =H,IT=\begin{bmatrix}1&0\\0&1\end{bmatrix} \begin{pmatrix}0\\1\end{pmatrix} = \begin{pmatrix}0\\1\end{pmatrix} =T $$
可见,F操作,可以翻转(Flip)硬币。在经典游戏中, 我们只限于使用F和I的翻转, 它可 以改变状态或保持状态,在量子世界中, 我们可有额外的操作, 数学上由酉矩阵(Unitary matrices) 表示。回顾基础部分所涉及到的叠加态(Superposition)的概念, 量子世界里,有办法将状态置于硬币正反面的一个叠加态(可以想象成硬币翻转的时候,处于在正面和反面的一个叠加态里)
这里,我们考虑一个酉矩阵U(Hadamard Gate),在游戏博弈的时候,P将采用这种翻转。
$$U=\frac{1}{ \sqrt{2}}\begin{bmatrix}1&1\\1&-1\end{bmatrix}$$
在回顾游戏的步骤,第一步初始化的硬币处于$H= \begin{pmatrix}0\\1\end{pmatrix}$,第二步P执行翻转,此处P执行U翻转,把状态置为:
$$UH=\frac{1}{ \sqrt{2}}\begin{bmatrix}1&1\\1&-1\end{bmatrix} \begin{pmatrix}0\\1\end{pmatrix}=\frac{1}{ \sqrt{2}}\begin{pmatrix}1\\1\end{pmatrix}=S^{HT}$$
第三步,Q执行翻转,可以看到出,无论Q执行X或者I操作,状态始终保持不变。最后一步,P在执行一次U操作,状态变化为:
$$US^{HT}=\frac{1}{2}\begin{bmatrix}1&1\\1&-1\end{bmatrix} \begin{pmatrix}1\\1\end{pmatrix}=\begin{pmatrix}0\\1\end{pmatrix}=H$$
状态恢复到H,所以Q一直赢得游戏。
1.定义随机数生产,生成随机数,模拟P是否选择翻转。
2.询问用户,需要多少“硬币”(状态),定义为N。
3.初始化N个比特。
4.模拟Q的第一步操作,对N个状态执行U门(Hadamard gate)。
5.模拟P对任意状态执行F或者I操作(采用随机数的结果作为选择依据)。
6.模拟Q最后一步操作。对所有状态执行U门操作。
测量,输出结果,得到结果为00…0,告知恭喜胜利!


(1)初始态:$|0\left. \right \rangle|\phi\left. \right \rangle|\Psi \left. \right \rangle$
(2)给辅助比特加Hadamard操作后,态演化为:
$\frac{1}{\sqrt{2} }{(|0\left. \right \rangle+|1\left. \right \rangle)}|\phi\left. \right \rangle|\Psi \left. \right \rangle$
(3)辅助量子比特对和进行控制交换操作后,态演化为:
$\frac{1}{\sqrt{2} }{(|0\left. \right \rangle |\phi\left. \right \rangle|\Psi \left. \right \rangle+|1\left. \right \rangle|\Psi\left. \right \rangle| \phi\left. \right \rangle)}$
(4)再次给辅助量子比特加Hadamard操作后,态演化为:
$\frac{1}{2}|0\left. \right \rangle{(|\phi\left. \right \rangle|\Psi \left. \right \rangle+|\Psi\left. \right \rangle| \phi\left. \right \rangle)} + \frac{1}{2}|1\left. \right \rangle{(|\phi\left. \right \rangle|\Psi \left. \right \rangle-|\Psi\left. \right \rangle| \phi\left. \right \rangle)}$
(5)对辅助比特进行测量,测量到和的概率分别为:
$p_0=\frac{1}{2}{(1+|\left \langle {\phi|\Psi} \right \rangle|^2)}$
$p_1=\frac{1}{2}{(1-|\left \langle {\phi|\Psi} \right \rangle|^2)}$
从而根据测量得到的$p_0$或$p_1$即可得到$|\left \langle {\phi|\Psi} \right \rangle|^2$,判断$|\phi \left. \right \rangle$和$|\Psi \left. \right \rangle$的接近程度。
下面是一份用QPanda实现的Swap Test操作的程序源码,其中$|\phi \left. \right \rangle$和$|\Psi \left. \right \rangle$均是单比特态;
QProg swaptest_QProg(vector<Qubit*> qVec, vector<CBit*> cVec, vector<double>& phi) { QProg swaptest_qprog = CreateEmptyQProg(); swaptest_qprog << H(qVec[0]); //initial state swaptest_qprog << RY(qVec[1], phi[0])<<RZ(qVec[1], phi[1]); swaptest_qprog << RY(qVec[2], phi[2]) << RZ(qVec[2], phi[3]); //control swap QCircuit controlswap = CreateEmptyCircuit(); controlswap << CNOT(qVec[1], qVec[2])<< CNOT(qVec[2], qVec[1])<<CNOT(qVec[1], qVec[2]); vector<Qubit*> qvtemp; qvtemp.push_back(qVec[0]); controlswap.setControl(qvtemp); swaptest_qprog << controlswap; swaptest_qprog <<H(qVec[0])<< Measure(qVec[0], cVec[0]); return swaptest_qprog; } void swaptest() { cout << "Swap Test Algorithm\n" << endl; cout << "Initialize phi" << endl; double theta1; double alpha1; double theta2; double alpha2; vector<double> phi; cout << "input theta1:" << endl; cin >> theta1; cout << "input alpha1:" << endl; cin >> alpha1; cout << "input theta2:" << endl; cin >> theta2; cout << "input alpha2:" << endl; cin >> alpha2; cout << "phi=" << cos(theta1 / 2) << "*|0>+" << exp(1i*alpha1)*sin(theta1 / 2) << "|1>" << endl; cout << "psi=" << cos(theta2 / 2) << "*|0>+" << exp(1i*alpha2)*sin(theta2 / 2) << "|1>" << endl; phi.push_back(theta1); phi.push_back(alpha1); phi.push_back(theta2); phi.push_back(alpha2); cout<<" Programming the circuit..." << endl; init(); vector<Qubit*> qVec; vector<CBit*> cVec; for (auto i = 0; i < 3 ; i++) { qVec.push_back(qAlloc()); } cVec.push_back(cAlloc()); double prob; size_t times=0; for (auto i = 0; i < 1000; i++) { if (swaptest1(qVec, cVec, phi)) { times++; } } prob = times*0.001; cout << "|<phi|psi>|^2=" << 1 - 2 * prob << endl; return; } bool swaptest1(vector<Qubit*> qVec, vector<CBit*> cVec, vector<double>& phi) { init(); auto bvAlgorithm = swaptest_QProg(qVec, cVec, phi); append(bvAlgorithm); run(); return getCBitValue(cVec[0]); }
[1].Nana Liu,Patrick Rebentrost,arXiv:1710.07405vl.
[2].CH Yu,F Gao,QY Wen.arXiv:1707.09524,2017.
[3].H.Buhrman,R.Cleve,J.Watrous,and R.de wolf, Quantum fingerprinting, Phys.Rev.Lett.87,167902.
给定一个方程:
$f:\{0,1\}^n\longrightarrow\{0,1\}^n$
存在$s\in\{0,1\}^n$,对所有的$x,y\in\{0,1\}^n$,满足下面的性质:
$f(x)=f(y)$当且仅当$x=y$或$x\oplus y=s$ (这里$\otimes$表示模2加。)
例:n=2的Simon问题,考虑2量子比特。注意,如果目标$s=0^n$,那这个函数是1对1(one-to-one)的, 此处不考虑。反之,则是一个二对一(two-to-one)的函数,几种情况如下图(函数值任意给定):
$x$ | $f(x)$ |
---|---|
00 | 1 |
01 | 1 |
10 | 0 |
11 | 0 |
$x$ | $f(x)$ |
---|---|
00 | 1 |
01 | 2 |
10 | 1 |
11 | 2 |
$x$ | $f(x)$ |
---|---|
00 | 1 |
01 | 3 |
10 | 3 |
11 | 1 |
在(1)很容易看出$f(00)=f(01)=1$,$f(10)=f(11)=0$,因此$00\oplus01=01$,$10\oplus11=01$,推出$s=01$。经典算法最低需要2次的才能确定,一般情况下,对于n比特的问题估计找到目标s最糟糕的情况下要消耗多达$2^{n-1}+1$次。 但是在量子算法里,1次就解决了这个问题。
Simon问题的量子Oracle(考虑s=11)
考虑n=2的Simon问题,此时需要2量子比特的变量和2量子比特的函数,合计需要4量子比特。
$|x_ox_1\left. \right \rangle|00\left. \right \rangle\xrightarrow{uf}|x_ox_1\left. \right \rangle|00\oplus f(x_0x_1)\left. \right \rangle=|x_0x_1\left. \right \rangle|f(x_0x_1)\left. \right \rangle$

上面的这个量子Oracle可以加入Hadamard门,对前两个量子比特做H操作,等价于:

$$|0000\left. \right \rangle \xrightarrow{H \otimes H \otimes I\otimes I}|++\left. \right \rangle|00\left. \right \rangle\xrightarrow{u_f} \frac{1}{2}{[(|00\left. \right \rangle+|11\left. \right \rangle)|1\left. \right \rangle +(|01\left. \right \rangle+|10\left. \right \rangle)|3\left. \right \rangle } \xrightarrow{H \otimes H \otimes I\otimes I}\frac{1}{2}{[(|00\left. \right \rangle+|11\left. \right \rangle)|1\left. \right \rangle +(|00\left. \right \rangle-|11\left. \right \rangle)|3\left. \right \rangle ]}$$
(注意:$|3\left. \right \rangle$是我定义的函数值)
因此,最下面的两个位分别对应了$|1\left. \right \rangle$和$|3\left. \right \rangle$,测量上面的两量子位,$|00\left. \right \rangle$和$|11\left. \right \rangle$则会被以50%的概率被观察到。
1. 初始化4个量子比特。
2. 创建线路图: q[0], q[1]分别做Hadamard操作。
3. 对q[0],q[2]和q[1], q[2]分别执行CNOT操作。
4. 对q[3]执行NOT操作。
5. 再对q[0],q[1]分别做Hadamard操作
6. 最后测量全部量子逻辑位,输出结果。
QPanda代码 (s=11)
QProg Simon_QProg(vector<Qubit*> qVec, vector<CBit*> cVec, vector<int> funvalue) { size_t length = cVec.size(); auto simon_qprog = CreateEmptyQProg(); for (auto i = 0; i < length; i++) { simon_qprog << H(qVec[i]); } simon_qprog << oraclefunc(qVec,funvalue); for (auto i = 0; i < length; i++) { simon_qprog << H(qVec[i]); } for (auto i = 0; i < length; i++) { simon_qprog << Measure(qVec[i],cVec[i]); } return simon_qprog; } //f(x),x is 2bits variable QCircuit oraclefunc(vector<Qubit*> qVec, vector<int> funvalue) { auto length = qVec.size() / 2; auto func = CreateEmptyCircuit(); for (auto i = 0; i < 4; i++) { func << controlfunc(qVec,i, funvalue[i]); } return func; } QCircuit controlfunc(vector<Qubit*> qVec,size_t index, int value) { auto length = qVec.size() / 2; auto cfunc = CreateEmptyCircuit(); vector<Qubit*> qvtemp; qvtemp.insert(qvtemp.begin(), qVec.begin(), qVec.begin() + length); if (index == 1) { cfunc << X(qVec[0]); } else if (index == 2) { cfunc << X(qVec[1]); } else if (index == 0) { cfunc << X(qVec[0]); cfunc << X(qVec[1]); } if (value == 1) { QGate temp = X(qVec[3]); temp.setControl(qvtemp); cfunc << temp; } else if (value == 2) { QGate temp1 = X(qVec[2]); temp1.setControl(qvtemp); cfunc << temp1; } else if (value == 3) { QGate temp2 = X(qVec[2]); temp2.setControl(qvtemp); cfunc << temp2; QGate temp3 = X(qVec[3]); temp3.setControl(qvtemp); cfunc << temp3; } if (index == 1) { cfunc << X(qVec[0]); } else if (index == 2) { cfunc << X(qVec[1]); } else if (index == 0) { cfunc << X(qVec[0]); cfunc << X(qVec[1]); } return cfunc; }

这里,测定结果得$|00\left. \right \rangle$的时候,表示没有得到任何的信息,当测量得到$|11\left. \right \rangle$的时候,就得到了s=11,也就是说Simon量子算法里面,0以外的获取s的概率为50%。

input:
考虑一个经典的布尔函数:
$f:\{0,1\}^n\longrightarrow\{0,1\}$
存在$s\in \{0,1\}^n$,再定义一个函数:
$f_s(x)=\left \langle {s,x} \right \rangle,x\in \{0,1\}^n$
s是一个未知的向量,通常称s为隐藏字符串(Hidden string),其中$\left \langle {s,x} \right \rangle$表示内积(inner product),定义为:
$\left \langle {s,x} \right \rangle=s_0x_0\oplus s_1x_1\oplus..\oplus s_nx_n$
(符号$\otimes$在所出现的量子算法文中都表示布尔加或模2加。):
Output:
算法目标:找到s.
由于对该函数的每个经典查询只能生成1位的信息, 而任意隐藏字符串 s 具有$n$位的信息, 所以经典查询复杂性是$O(n)$。
Bernstein-Vazirani的工作建立在Deutsch和Jozsa早期工作理论上来探索量子查询复杂度。他们对该领域的 贡献是一个用于隐藏字符串问题的量子算法, 该算法的非递归量子查询复杂度仅为1,同比经典情况$O(n)$。这一量子算法的真正突破在于加快查询复杂度, 而不是执行时间本身。
案例:考虑n=3时的Bernstein-Vazirani问题。变量是3比特时,二进制表示为$x_0x_1x_2$,常数s则表示为$s_0s_1s_2$,因此所求的常数s总共有8个。此时,问题函数描述如下:
$f_s(x_0x_1x_2)=s_0x_0\oplus s_1x_1 \oplus s_2x_2$
不难看出,对于经典算法而言,如果是$f_s(100)=s_0,f_s(010)=s_1,f_s(001)=s_2$, 那么最少也需要3次调用函数才可以确定常量$s=s_0s_1s_2$。但是对于量子算法而言,使用下面的量子Oracle计算,1次就可以决定$s=s_0s_1s_2$,其计算复杂度为$O(1)$。

分析上图:
$$|0\left. \right \rangle|1\left. \right \rangle\xrightarrow{H\otimes H\otimes H\otimes H} \frac{1}{ 2\sqrt{2}}\sum_{x=0}^{7}|X\left. \right \rangle\otimes {(\frac{|0\left. \right \rangle-|1\left. \right \rangle}{\sqrt{2}})} $$
$$\xrightarrow{uf}\frac{1}{ 2\sqrt{2}}\sum_{x=0}^{7}{(-1)^\left \langle {s,x} \right \rangle}|x\left. \right \rangle\otimes{(\frac{|0\left. \right \rangle-|1\left. \right \rangle}{\sqrt{2}})}$$
$$\xrightarrow{H\otimes H\otimes H\otimes H} \frac{1}{ 2\sqrt{2}}\sum_{x=0,y=0}^{7}{(-1)^{\left \langle {s,x} \right \rangle\otimes \left \langle {x,y} \right \rangle}} |y\left. \right \rangle\otimes{(\frac{|0\left. \right \rangle-|1\left. \right \rangle}{\sqrt{2}})}\Xi|s> \otimes{(\frac{|0\left. \right \rangle-|1\left. \right \rangle}{\sqrt{2}})}$$
不失一般性:
$$|0\left. \right \rangle^n|1\left. \right \rangle\xrightarrow{H^{\otimes(n+1)}}\frac{1}{\sqrt{2^n}}\sum_{x=0}^{2^n-1}|X\left. \right \rangle\otimes {(\frac{|0\left. \right \rangle-|1\left. \right \rangle}{\sqrt{2}})} $$
$$\xrightarrow{uf}\frac{1}{\sqrt{2^n}}\sum_{x=0}^{2^n-1}{(-1)^\left \langle {s,x} \right \rangle}|x\left. \right \rangle\otimes{(\frac{|0\left. \right \rangle-|1\left. \right \rangle}{\sqrt{2}})}$$
$$\xrightarrow{H^{\otimes(n+1)}} \frac{1}{ \sqrt{2^n}}\sum_{x=0,y=0}^{2^n-1}{(-1)^{\left \langle {s,x} \right \rangle\oplus \left \langle {x,y} \right \rangle}} |y\left. \right \rangle\otimes{(\frac{|0\left. \right \rangle-|1\left. \right \rangle}{\sqrt{2}})}\Xi|s\left. \right \rangle \otimes{(\frac{|0\left. \right \rangle-|1\left. \right \rangle}{\sqrt{2}})}$$
下面给出两组案例,分别是s=101和s=111

过程:略
量子语言 :
RX 3,"pi"
H 0
H 1
H 2
H 3
CNOT 0,3
CNOT 2,3
H 0
H 1
H 2
MEASURE 0,$0
MEASURE 1,$1
MEASURE 2,$2
这时,输出的结果,指代了s。通过验证,输出结果为:

线路图设计为:

测量结果:

量子语言 :
RX 3,"pi"
H 0
H 1
H 2
H 3
CNOT 0,3
CNOT 1,3
CNOT 2,3
H 0
H 1
H 2
MEASURE 0,$0
MEASURE 1,$1
MEASURE 2,$2
QProg BV_QProg(vector<Qubit*> qVec, vector<CBit*> cVec, vector<bool>& a, bool b) { if (qVec.size() != (a.size()+1)) { throw exception("error"); } size_t length = qVec.size(); QProg bv_qprog = CreateEmptyQProg(); bv_qprog << X(qVec[length - 1]); for (auto iter = qVec.begin(); iter != qVec.end(); iter++) { bv_qprog << H(*iter); } for (auto i=0;i<length-1;i++) { if (a[i]) { bv_qprog << CNOT(qVec[i], qVec[length - 1]); } } for (auto i = 0; i < length - 1; i++) { bv_qprog << H(qVec[i]); } for (auto i = 0; i < length - 1; i++) { bv_qprog << Measure(qVec[i], cVec[i]); } return bv_qprog; } void BernsteinVaziraniAlgorithm() { cout << "Bernstein Vazirani Algorithm\n" << endl; cout << "f(x)=a*x+b\n" << endl; cout << "input a" << endl; string stra; cin >> stra; vector<bool> a; for (auto iter = stra.begin(); iter != stra.end(); iter++) { if (*iter == '0') { a.push_back(0); } else { a.push_back(1); } } cout << "input b" << endl; bool b; cin >> b; cout << "a=\t" << stra << endl; cout << "b=\t" << b << endl; cout<<" Programming the circuit..." << endl; size_t qbitnum = a.size(); init(); vector<Qubit*> qVec; vector<CBit*> cVec; for (auto i = 0; i < qbitnum ; i++) { qVec.push_back(qAlloc()); cVec.push_back(cAlloc()); } qVec.push_back(qAlloc()); auto bvAlgorithm = BV_QProg(qVec, cVec, a, b); append(bvAlgorithm); run(); string measure; cout << "a=\t"; for (auto iter = cVec.begin(); iter != cVec.end(); iter++) { cout << getCBitValue(*iter); } cout << "\n"<<"b=\t" << b << endl; return; }
输入:一个n*n的矩阵A和一个n维向量b。
输出:n维向量x,满足Ax=b。

1.输入的矩阵,必须是adjoint矩阵,当A不是Hermitian时,需要构造成adjoint矩阵。算法的输入部分如图1中红色方框所标出。输入q[2]存放在底部寄存器中,输入A作为相位估计中酉算子的一个组成部分。
2.输出x的形式:算法的输出如红色部分标出(同一个寄存器)。底部寄存器存放的是一个蕴含了向量x的量子态。 此处不需要知道这个状态具体情况。

#include "HHL_Algorithm.h" void HHL_Algorithm() { map<string, bool> temp; int x0 = 0; int x1 = 0; for (size_t i = 0; i < 1000;i++) { temp = hhlalgorithm(); if (temp["c0"]) { if (temp["c1"]) { x1++; } else { x0++; } } } int sum = x0 + x1; cout << "prob0:" << x0*1.0/sum << endl; cout << "prob1:" << x1*1.0/sum << endl; } map<string, bool> hhlalgorithm() { init(); int qubitnum = 4; vector<Qubit*> qv; for (size_t i = 0; i < qubitnum; i++) { qv.push_back(qAlloc()); } vector<CBit*> cv; int cbitnum = 2; for (size_t i = 0; i < cbitnum; i++) { cv.push_back(cAlloc()); } auto hhlprog =CreateEmptyQProg(); hhlprog << RY(qv[3], PI / 2); // change vecotr b in equation Ax=b hhlprog << hhl(qv, cv); load(hhlprog); run(); auto resultMap = getResultMap(); finalize(); return resultMap; } int HHL_Test(int repeat) { try { init(); int qubitnum = 4; vector<Qubit*> qv; for (size_t i = 0u; i < qubitnum; i++) { qv.push_back(qAlloc()); } vector<CBit*> cv; int cbitnum = 2; for (size_t i = 0u; i < cbitnum; i++) { cv.push_back(cAlloc()); } auto hhlprog = CreateEmptyQProg(); hhlprog << RY(qv[3], PI / 2); hhlprog << hhl(qv, cv); load(hhlprog); int x0 = 0; int x1 = 1; for (size_t i = 0u; i < repeat; ++i) { run(); auto resultMap = getResultMap(); if (resultMap["c0"]) { if (resultMap["c1"]) { x1++; } else { x0++; } } } finalize(); cout << "x0: " << x0 << endl << "x1: " << x1 << endl; } catch (QPandaException &e) { cout << e.what(); return 1; } return 0; } QProg hhl(vector<Qubit*> qVec, vector<CBit*> cVec) { ClassicalCondition cc0=bind_a_cbit(cVec[0]); // meaningless sentence QCircuit ifcircuit = CreateEmptyCircuit(); QCircuit PSEcircuit = hhlPse(qVec);//PSE QCircuit CRot = CRotate(qVec);//control-lambda QCircuit PSEcircuitdag = hhlPse(qVec); //hhl circuit QProg PSEdagger = CreateEmptyQProg(); PSEdagger << PSEcircuitdag.dagger() << Measure(qVec[3], cVec[1]); QIfProg ifnode = CreateIfProg(cc0, &PSEdagger); QProg hhlProg = CreateEmptyQProg(); //hhlProg << PSEcircuit <<CRot<< Measure(qVec[0], cVec[0])<<ifnode; hhlProg << PSEcircuit << CRot << Measure(qVec[0], cVec[0]) << ifnode; return hhlProg; } QCircuit hhlPse(vector<Qubit*> qVec) { QCircuit PSEcircuit = CreateEmptyCircuit(); PSEcircuit << H(qVec[1]) << H(qVec[2]) << RZ(qVec[2], 0.75*PI); QGate gat1 = CU(PI, 1.5*PI, -0.5*PI, PI / 2, qVec[2], qVec[3]); QGate gat2 = CU(PI, 1.5*PI, -PI, PI / 2, qVec[1], qVec[3]); PSEcircuit << gat1 << RZ(qVec[1], 1.5*PI) << gat2; PSEcircuit << CNOT(qVec[1], qVec[2]) << CNOT(qVec[2], qVec[1]) << CNOT(qVec[1], qVec[2]); //PSEcircuit << gat1 << RZ_GATE(q1, 1.5*PI)<<gat2 ; QGate gat3 = CU(-0.25*PI, -0.5*PI, 0, 0, qVec[2], qVec[1]); PSEcircuit << H(qVec[2]) << gat3 << H(qVec[1]); //PSE over return PSEcircuit; } QCircuit CRotate(vectorqVec) { QCircuit CRot = CreateEmptyCircuit(); vector<Qubit *> controlVector; controlVector.push_back(qVec[1]); controlVector.push_back(qVec[2]); QGate gat4 = RY(qVec[0], PI); gat4.setControl(controlVector); QGate gat5 = RY(qVec[0], PI / 3); gat5.setControl(controlVector); QGate gat6 = RY(qVec[0], 0.679673818908); //arcsin(1/3) gat6.setControl(controlVector); CRot << X(qVec[1]) << gat4 << X(qVec[1]) << X(qVec[2]) << gat5 << X(qVec[2]) << gat6; //CRot << X(qVec[1]) << gat4 << X(qVec[1]); return CRot; }









1.真币的重量均等,假币的质量也均等,假币的质量比真币轻。
2.天平只给我们提供两个信息,平衡(两组币的重量相同)或倾斜。


线路说明:紫色的if表示的是测量判断,根据输出的经典信息来判断是否需要执行下一步的操作。上面线路图里判定条 件,如果输出为0的时候,则需要执行0 对应的操作,实际上就是从新执 行一遍量子线路,反之,执行$U_f$操作,$U_f$指代了错误币所在位置的控制非门,目标位最后一位。
QProg counterfeitCoin_QProg(vector<Qubit*> qVec, vector<CBit*> cVec, int position) { QProg prog = CreateEmptyQProg(); QProg endprog = CreateEmptyQProg(); QProg whileprog = CreateEmptyQProg(); QCircuit qcir = CreateEmptyCircuit(); ClassicalCondition cc = bind_a_cbit(cVec[cVec.size() - 1]); for (auto iter = qVec.begin(); iter != qVec.end() - 1; iter++) { qcir << H(*iter); endprog << H(*iter); } for (auto iter = qVec.begin(); iter != qVec.end() - 1; iter++) { endprog << Measure(*iter, cVec[iter - qVec.begin()]); } for (auto iter = qVec.begin(); iter != qVec.end() - 1; iter++) { qcir << CNOT(*iter, *(qVec.end() - 1)); } whileprog << qcir << Measure(qVec[qVec.size() - 1], cVec[cVec.size() - 1]); QWhileProg WhileNode = CreateWhileProg(cc, &whileprog); QIfProg ifnode = CreateIfProg(cc, &endprog); prog << qcir << Measure(qVec[qVec.size() - 1], cVec[cVec.size() - 1]) << WhileNode << X(qVec[qVec.size() - 1]) << H(qVec[qVec.size() - 1]) << CNOT(qVec[position], qVec[cVec.size() - 1]) << endprog; return prog; } void counterfeitCoinGame() { cout << "Counterfeit Coin Game Algorithm\n" << endl; cout << "eight coins ,one coin is counterfeit" << endl; cout << "choose the position of the counterfeit coin(0~7)" << endl; int position; cin >> position; cout<<" Programming the circuit..." << endl; init(); vector<Qubit*> qVec; vector<CBit*> cVec; for (auto i = 0; i < 9 ; i++) { qVec.push_back(qAlloc()); cVec.push_back(cAlloc()); } auto ccAlgorithm = counterfeitCoin_QProg(qVec, cVec, position); append(ccAlgorithm); bool isSuccess=true; run(); int itemp = 0; for (auto i = 0; i < cVec.size() - 1; i++) { if (getCBitValue(cVec[i])) { itemp++; } } if (itemp > 1) { for (auto i = 0; i < cVec.size() - 1; i++) { if (!getCBitValue(cVec[i])) { cout << "The position of counterfeit coin is :" << i << endl; } } } else { for (auto i = 0; i < cVec.size() - 1; i++) { if (getCBitValue(cVec[i])) { cout << "The position of counterfeit coin is :" << i << endl; } } } return; }
[1].https://en.wikipedia.org/wiki/Balance_puzzle
[2].《Quantum Counterfeit Coin Problems》