文章目录
- 1 安装
- Q#@VSCODE
- Q# @ Python
- Q# @ dotnet
- 2 创建贝尔态
- 3 量子计算基础
- 量子比特
- 量子门
- Dirac符号
- 4 语言特性
- 数据类型
- 特殊数据类型
- 控制结构与操作符
1 安装
Q#@VSCODE
目前,微软提供的QDK既可以作为一门独立语言运行,也可以嵌入Python或C#、F#等.NET语言进行工作。但无论在哪里工作,都必须安装.Net Core3.1。
如果使用VS Code,则在插件栏中搜索Microsoft Quantum Development Kit Preview,点击安装,下载Q#可能需要一点时间。
安装成功后,可以创建新项目:快捷键Ctrl
+Shift
+P
,输入“Q#:Create New Project
->选择Standalone console application
->在弹出的对话框中输入项目名称test
,然后创建。
在创建的test
文件夹中有一个Program.qs
文件,在终端中进入test
文件夹,然后输入dotnet run
,就可以运行这个Q#程序
PS E:\Code\test> dotnet run
Hello quantum world!
Q# @ Python
若希望通过Python运行Q#,最便捷的方式是通过conda
进行。
conda create -n qsharp -c microsoft qsharp notebook
conda activate qsharp
python -c "import qsharp"
create -n
用于创建环境,activate
用于激活环境,conda会自动下载需要的内容,进入环境之后,写一个示例程序Operation.qs
:
namespace Qrng {
open Microsoft.Quantum.Intrinsic;
operation qGenerator() : Result {
use q = Qubit(); // 设置一个Q比特
H(q);
let r = M(q); // 测量Q比特的值
Reset(q);
return r;
}
}
在相同的文件夹下进入python
,调用该文件
python
>>>import qsharp
>>>from Qrng import qGenerator()
>>> print(qGenerator.simulate())
0
>>> print(qGenerator.simulate())
0
>>> print(qGenerator.simulate())
1
Q# @ dotnet
首先下载Qsharp的模板,然后通过dotnet
命令创建新的Q#程序。
>dotnet new -i Microsoft.Quantum.ProjectTemplates
>dotnet new console -lang Q# -o runSayHello
>cd runsayHello
>dotnet run
Hello quantum world!
如果希望在C#等程序中调用Q#,则需要创建Q#库
>dotnet new classlib -lang Q# -o quantum
>dotnet new console -lang C# -o host
>cd host
>dotnet add refrence ../quantum/quantum.csproj
已将引用“..\quantum\quantum.csproj”添加到项目。
2 创建贝尔态
在命令行中输入
$ dotnet new console -lang Q# --output Bell
$ cd Bell
$ code .
其中,-lang Q#表示选择基于Q#语言的模板,code.表示使用vscode进行编辑。我们主要编辑的是Bell文件夹下的Program.qs。
namespace Bell {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;
//翻转量子比特
operation Set(Desired:Result, q1:Qubit):Unit{
if(Desired != M(q1)){
X(q1);
}
}
@EntryPoint() //入口标志
operation Test():Unit{
mutable numOnes = 0;
let count = 1000;
let initial = One;
use q = Qubit(){
for _ in 1..count {
Set(initial, q);
let res = M(q);
if(res==One){
set numOnes += 1;
}}
Set(Zero, q);}
Message($"num of 0s: {count-numOnes}, num of 1s: {numOnes}");
}
}
该程序可在命令行调用:
.\Bell>dotnet run
num of 0s: 0, num of 1s: 1000
也可在python中调用:
>>> import qsharp
Preparing Q# environment...
>>> from Bell import Test
>>> Test.simulate()
num of 0s: 0, num of 1s: 1000
()
>>>
入口函数当然可以拥有输入输出,且非常方便命令行的调用,例如下面的量子纠缠程序
namespace Bell {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;
operation Set(Desired:Result, q1:Qubit):Unit{
if(Desired != M(q1)){
X(q1); //X 表示Pauli矩阵X
}
}
@EntryPoint()
operation TestBellState(count : Int, initial : Result) : (Int, Int, Int) {
mutable numOnes = 0;
mutable agree = 0;
use (q0, q1) = (Qubit(), Qubit());
for test in 1..count {
Set(initial, q0);
Set(Zero, q1);
H(q0);
CNOT(q0, q1);
let res = M(q0);
if M(q1) == res {
set agree += 1;
}
if res == One {
set numOnes += 1;
}
}
Set(Zero, q0);
Set(Zero, q1);
Message("Test results (# of 0s, # of 1s, # of agreements)");
return (count-numOnes, numOnes, agree);
}
}
则在命令行中调用
>dotnet run --count 1000 --initial One
>(505, 495, 1000)
3 量子计算基础
量子比特
在Q#语言中,Qubit代表一个量子比特,尽管看上去只有Zero和One两种取值,但并非Bool型。之所以呈现出这两种取值,关键在于我们采取了测量操作,而在测量之前,量子比特实际上处于 ∣ 0 ⟩ |0\rangle ∣0⟩和 ∣ 1 ⟩ |1\rangle ∣1⟩的一种叠加状态。
在量子力学中,态矢等同于波函数,波函数则是Hilbert空间中的某一组正交基的线性组合,所以并不能等同于宏观世界的常量,亦即不遵守 ∣ 0 ⟩ + ∣ 1 ⟩ = ∣ 1 ⟩ |0\rangle+|1\rangle=|1\rangle ∣0⟩+∣1⟩=∣1⟩的运算方式。
所以,Zero和One也不能单纯地理解为 ∣ 0 ⟩ |0\rangle ∣0⟩和 ∣ 1 ⟩ |1\rangle ∣1⟩,而是需要在态叠加的基础上去理解,作为 ∣ 0 ⟩ |0\rangle ∣0⟩和 ∣ 1 ⟩ |1\rangle ∣1⟩的某种线性组合,即
One = [ 1 0 ] , Zero = [ 0 1 ] \text{One}=\begin{bmatrix}1 \\ 0\end{bmatrix},\text{Zero}=\begin{bmatrix}0 \\ 1\end{bmatrix} One=[10],Zero=[01]
而qubit的状态,便由One和Zero的线性组合组成,由于Hilbert空间连续,所以qubit的取值无穷多。但这并不意味着qubit和二维复空间一一对应,只有 L 2 L_2 L2范数为1的向量才能描述qubit的状态,即对于某一qubit,对于量子态 α ∣ 0 ⟩ + β ∣ 1 ⟩ \alpha|0\rangle+\beta|1\rangle α∣0⟩+β∣1⟩,有 α 2 + β 2 = 1 \alpha^2+\beta^2=1 α2+β2=1。
对于观测操作M()
之前的qubit,可能处于任何一种叠加状态,由于测量导致波包塌缩,从而被观测到确定的值。这就是广为流传到薛定谔的猫,当我们观测之前,猫处于一种死和活的叠加态。
量子门
谈及量子门之前,有必要回顾一下人所共知的逻辑门,其操作单元为bool型变量,其物理实现为门电路。
在python语言中,通过and,or,not
实现与或非的二元运算。这种二元运算满足对bool这种数据类型的封闭性——这也是量子门的运算所需要遵循的。
单个qubit的态矢量为 L 2 L_2 L2范数为1的二维列向量,从属于在二次酉群。所以量子门的作为矩阵形式存在时,其行列式d的绝对值为1。此外,量子门的物理意义是表示力学量的算符,由于量子力学要求算符具备幺正性质,所以其矩阵表达亦必为幺正矩阵,即其共轭转置矩阵与其逆矩阵相等。对于矩阵 S S S,其共轭转置矩阵表示为 S † S ^{\dagger} S†,则有 S S † = I SS ^{\dagger} = I SS†=I。
可见,单位矩阵天然满足这一要求,除此之外,通过求解狄拉克方程,可以得到基于Pauli矩阵的波函数表达形式,泡利矩阵显然可以作为量子门,其表达式为
P x = [ 0 1 1 0 ] , P y = [ 0 − i i 0 ] , P z = [ 1 0 0 − 1 ] P_x=\begin{bmatrix}0&1\\1&0\end{bmatrix},P_y=\begin{bmatrix}0&-i\\i&0\end{bmatrix},P_z=\begin{bmatrix}1&0\\0&-1\end{bmatrix} Px=[0110],Py=[0i−i0],Pz=[100−1]
可以证明,任意幺正矩阵均可分解成Pauli矩阵的形式:
U = e i α R z ( β ) R y ( γ ) R x ( δ ) U = e^{i\alpha}R_z(\beta)R_y(\gamma )R_x(\delta ) U=eiαRz(β)Ry(γ)Rx(δ)
其中,
R z ( β ) = e − i β Z / 2 = c o s β 2 I − i s i n β 2 Z = ∣ e − i β / 2 0 0 e i β / 2 2 ∣ R_z(\beta) = e^{-i\beta Z/2} = cos \frac{\beta}{2}I - isin{\frac {\beta}{2}}Z = \begin{vmatrix}e^{-i\beta/2} & 0 \\ 0 & e^{i\beta/2} {2}\end{vmatrix} Rz(β)=e−iβZ/2=cos2βI−isin2βZ=∣∣∣∣e−iβ/200eiβ/22∣∣∣∣
R y ( γ ) = e − i γ Y / 2 = c o s γ 2 I − i s i n γ 2 Y = ∣ c o s γ 2 − s i n γ 2 s i n γ 2 c o s γ 2 ∣ R_y(\gamma) = e^{-i\gamma Y/2} = cos \frac{\gamma}{2}I - isin{\frac {\gamma}{2}}Y = \begin{vmatrix}cos \frac{\gamma}{2} & -sin \frac{\gamma}{2}\\ sin \frac{\gamma}{2} & cos \frac{\gamma}{2}\end{vmatrix} Ry(γ)=e−iγY/2=cos2γI−isin2γY=∣∣∣∣cos2γsin2γ−sin2γcos2γ∣∣∣∣
R x ( δ ) = e − i δ X / 2 = c o s δ 2 I − i s i n δ 2 X = ∣ c o s δ 2 − i s i n δ 2 − i s i n δ 2 c o s δ 2 ∣ R_x(\delta) = e^{-i\delta X/2} = cos \frac{\delta}{2}I - isin{\frac {\delta}{2}}X = \begin{vmatrix}cos \frac{\delta}{2} & -i sin \frac{\delta}{2} \\ -isin \frac{\delta}{2} & cos \frac{\delta}{2}\end{vmatrix} Rx(δ)=e−iδX/2=cos2δI−isin2δX=∣∣∣∣cos2δ−isin2δ−isin2δcos2δ∣∣∣∣
正如量子比特与二维单位向量之间存在一一对应关系,量子门与幺正矩阵之间也存在一一对应关系。除了Pauli矩阵之外,还有一些常用的量子门
H
a
d
a
m
a
r
d
=
1
2
[
1
1
1
−
1
]
,
P
h
a
s
e
=
[
1
0
0
i
]
,
π
/
8
=
[
1
0
0
e
i
π
/
4
]
Hadamard=\frac{1}{\sqrt{2}}\begin{bmatrix}1&1\\1&-1\end{bmatrix},Phase=\begin{bmatrix}1&0\\0&i\end{bmatrix}, \pi/8=\begin{bmatrix}1&0\\0&e^{i\pi/4}\end{bmatrix}
Hadamard=2
在示例程序中所用到的H
,M
便都是量子门,在Q#标准库中封装了许多量子门,列如下:
名称 | 签名式 | 量子门矩阵 |
---|---|---|
X | (Qubit => () : Adjoint, Controlled) | [ 0 1 1 0 ] \begin{bmatrix}0&1\\1&0\end{bmatrix} [0110] |
Y | (Qubit => () : Adjoint, Controlled) | [ 0 − i i 0 ] \begin{bmatrix} 0&-i \\ i&0 \end{bmatrix} [0i−i0] |
Z | (Qubit => () : Adjoint, Controlled) | [ 1 0 0 − 1 ] \begin{bmatrix} 1&0 \\ 0&-1 \end{bmatrix} [100−1] |
H | (Qubit => () : Adjoint, Controlled) |
1
2
[
1
1
1
−
1
]
\frac {1} {\sqrt{2}} \begin{bmatrix} 1&1\\1&-1\end{bmatrix}
2
|
S | (Qubit => () : Adjoint, Controlled) | [ 1 0 0 i ] \begin{bmatrix} 1 \quad 0 \\ 0 \quad i \end{bmatrix} [100i] |
T | (Qubit => () : Adjoint, Controlled) | [ 1 0 0 e i π / 4 ] \begin{bmatrix} 1 \qquad 0 \\ 0 \quad e^{i \pi / 4} \end{bmatrix} [100eiπ/4] |
CNOT | ((Qubit, Qubit) => () : Adjoint, Controlled) | [ 1 0 0 0 0 1 0 0 0 0 1 1 0 1 0 ] \begin{bmatrix}1&0&0&0\\0&1&0&\\0&0&0&1\\1&0 &1&0\end{bmatrix} ⎣⎢⎢⎡100101000001010⎦⎥⎥⎤ |
SWAP | ((Qubit, Qubit) => () : Adjoint, Controlled) | [ 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 ] \begin{bmatrix}1 & 0 & 0 & 0 \\0 & 0 & 1 & 0 \\0 & 1 & 0 & 0 \\0 & 0 & 0 & 1\end{bmatrix} ⎣⎢⎢⎡1000001001000001⎦⎥⎥⎤ |
此外,由于量子态只有在被观测之后才有意义,所以Q#理所当然地提供了测量算符M
,
Dirac符号
量子论因Schrodinger方程而升级为量子力学,波动力学创建不久,海森堡等人便提出了量子力学的矩阵形式。两者殊途同归于Hilbert空间之中。Dirac符号充分利用了Hilbert空间的优良性质,并通过左矢(bra)右矢(ket)完美指代算符与共轭算符、行向量和列向量的变化关系。
∣ 0 ⟩ |0\rangle ∣0⟩和 ∣ 1 ⟩ |1\rangle ∣1⟩便是Dirac符号表述下的波函数,二者皆为右矢,可以理解为列向量。 ⟨ 0 ∣ \langle0| ⟨0∣和 ⟨ 1 ∣ \langle1| ⟨1∣则为左矢,可以理解为行向量。
运算 | 对应的矩阵运算 |
---|---|
Z ∗ Z ^* Z∗ | 复数 Z Z Z的共轭, ( 1 + i ) ∗ = ( 1 − i ) (1 + i) ^* = (1 - i) (1+i)∗=(1−i) |
⟨ φ ∥ ψ ⟩ \langle \varphi \| \psi \rangle ⟨φ∥ψ⟩ | 矢量内积 |
∥ φ ⟩ ⟨ ψ ∥ \| \varphi \rangle \langle \psi \| ∥φ⟩⟨ψ∥ | 矢量外积 |
∥ φ ⟩ ⨂ ∥ ψ ⟩ \| \varphi \rangle \bigotimes \| \psi \rangle ∥φ⟩⨂∥ψ⟩ | 张量积, ⨂ \bigotimes ⨂可省略 |
A ∗ A ^* A∗ | 矩阵的共轭 |
A T A ^{T} AT | 矩阵转置 |
A † A ^{\dagger} A† | 矩阵 A A A 的转置共轭, [ a b c d ] † = [ a ∗ c ∗ b ∗ d ∗ ] \begin{bmatrix} a&b\\c&d\end{bmatrix} ^\dagger = \begin{bmatrix} a^*&c^* \\b^*&d^*\end{bmatrix} [acbd]†=[a∗b∗c∗d∗] |
⟨ φ ∥ A ∥ ψ ⟩ \langle\varphi\|A\|\psi\rangle ⟨φ∥A∥ψ⟩ | ∥ φ ⟩ \|\varphi\rangle ∥φ⟩与 A ∥ ψ ⟩ A\|\psi\rangle A∥ψ⟩ 的内积,等价于 A † ∥ φ ⟩ A^{\dagger} \| \varphi \rangle A†∥φ⟩ 与 ∥ ψ ⟩ \| \psi \rangle ∥ψ⟩ 的内积 |
其中,张量积 ⨂ \bigotimes ⨂为
∣ α ⟩ ⨂ ∣ β ⟩ = [ α 1 ∣ β ⟩ α 2 ∣ β ⟩ ⋮ α N ∣ β ⟩ ] | \alpha \rangle \bigotimes | \beta \rangle = \begin{bmatrix} \alpha_{1} |\beta \rangle \\ \alpha_{2} |\beta \rangle \\ \vdots \\ \alpha_{N}|\beta \rangle \end{bmatrix} ∣α⟩⨂∣β⟩=⎣⎢⎢⎢⎡α1∣β⟩α2∣β⟩⋮αN∣β⟩⎦⎥⎥⎥⎤
4 语言特性
数据类型
Q#提供了一些基础数据类型,包括Int
、Double
、Bool
、String
等,其初始值分别为0,False
或空。BigInt
为任意大的数,基于.NET BigInteger
类型。
Q#还提供了序列(Range)、元组(Tuple)、数组(Array)和自定义数据类型,其使用方法如下:
let T = (T0, T1, ..., Tn) // ()表示元组,T0,T1可为不同类型
let (a,(b,c)) = (1,(2,3)); // 元组不支持下标索引,通过解构的方式赋值变量a = 1;b = 2;c = 3
let zeros = new Int[13]; // 数组用方括号表示,可用new定义,其数据类型可以为元组,默认初始化为0
let arr = [1; 2; 3; 4]; // 数组也可不用new直接定义
let arr = arr[1..2..4]; // 数组支持下标索引,且支持范围表达式,arr = [2; 4]
newtype TypeName = (T1,T2,...); //新定义数据类型,T1、T2可以是任意数据类型
Q#中的变量通过let
进行声明,编译器会自动根据其值判断数据类型。然而变量一经let,就是不可变的量了。即下列代码中的第三行会报错。
为了使变量变得名副其实,需要使用关键字mutable
对其进行声明。
let a = 1; // a的类型为Int
let b = (1,2); //b的类型为(Int,Int)
a = 2; //错误的表达式
let a = 2; //错误的表达式
mutable c = 1;
d = 2; //正确的表达式
特殊数据类型
除了以上这些常见的数据类型之外,Q#还提供了用于量子计算的数据类型
Qubit | 为qubit,只能通过使用operation 对其进行各种操作。 |
Q#中,qubit没有对应的字面量,将qubit或qubit数组绑定到一个符号上构成一个量子位表达式(Qubit expressions)。 | |
Pauli | 即Pauli 门,包括:PauliX 、PauliY 、PauliZ 和PauliI 。 |
上述四个值都是合法的泡利表达式,将这些值或这些值组成的数组绑定至一个符号上也构成合法的泡利表达式。 | |
Result | 表示测量结果,为枚举类型,包括One 和Zero ,代表
∥
1
⟩
\|1 \rangle
∥1⟩和
∥
0
⟩
\|0\rangle
∥0⟩ |
除此二者,还可将它们组成的数组绑定至一个符号。需要注意,One 并不等于整数1,两者之间不可直接转换,但是Zero 与0是相等的。 | |
operation | 可调用类型,用来定义和执行量子操作,相当于量子函数 |
function | 可调用类型,与operation 类似,相当于普通函数,不能进行量子操作 |
控制结构与操作符
Q#中的运算符并没有太多的花样
操作符 | 简介 | |
---|---|---|
-,~~~,! | 负数,按位取反,逻辑非 | |
-,/,*,^,% | 减法,除法,乘法,乘方,取模 | |
+ | 加,数组相加,字符串相加 | |
<<<,>>> | 算数右移,算数左移 | |
<,<=,>,>= | 小于,小于等于,大于,大于等于 | |
==,!= | 相等,不等 | |
&&&,^^^ ,\|\|\| | 按位与, 按位异或,按位或 | |
&&,\|\| | 逻辑与,逻辑或 |
Q#提供了常见的if-else和for语句,使用方法如下
//0 .. n-2为范围表达式(Range expressions),表示0,1,2...n-2
for (index in 0 .. n-2) {
set results[index] = Measure([PauliX], [qubits[index]]);
}
if (i == 1) {
X(target);
} elif (i == 2) {
Y(target);
} else {
Z(target);
}
此外,Q#还提供了Repeat-Until-Success循环,repeat
语句支持量子计算中的“repeat until success”
模型,包括repeat
、until
和fixup
关键字,repeat
为循环体,until
为循环条件。
repeat
语句的执行过程为:首先执行循环体,然后测试条件表达式是否为true
,如果为true
,则语句结束,如果为false
,则执行fixup
语句中的内容,然后重新开始repeat
语句的执行。需要注意的是,fixup
不可省略,如果fixup
代码块不做任何工作,只需写一个空的表达式()
即可。
下面的代码展示了repeat
语句的使用,该代码定义了量子门
V
3
=
I
+
2
i
Z
5
V_3=\frac{I+2iZ}{\sqrt{5}}
V3=5
using ancilla = Qubit[1] {
repeat {
let anc = ancilla[0];
H(anc);
T(anc);
CNOT(target,anc);
H(anc);
(Adjoint T)(anc);
H(anc);
T(anc);
H(anc);
CNOT(target,anc);
T(anc);
Z(target);
H(anc);
let result = M([anc],[PauliZ]);
} until result == Zero
fixup {
();//空语句
}
}
更多推荐
量子编程初步——Q#入门
发布评论