使用Qubits
現在已經看到了Q#語言的各種不同部分,讓我們深入瞭解它,並瞭解如何使用量子比特本身。
分配Qubits
首先,爲了獲得我們可以在Q#中使用的量子比特,我們在一個using
塊中分配量子比特:
using (register = Qubit[5]) {
// Do stuff...
}
以這種方式分配的任何量子位都以 狀態開始; 在上面的例子中, register
因此處於狀態
。 在using
塊的末尾,由該塊分配的任何量子位將立即解除分配,並且不能繼續使用。
警告
目標機器希望在取消分配之前,量子位立即處於 狀態,以便它們可以被重用並提供給其他using
塊進行分配。 儘可能使用單一操作將任何已分配的量子位返回到 。 如果需要, 重置操作可用於測量量子位,並使用該測量結果確保量子位返回到
。 這樣的測量將破壞剩餘量子的任何糾纏。
原始門
一旦分配,量子位就可以傳遞給功能和操作。 從某種意義上說,Q#程序可以用qubit來做這些,因爲可以採取的行動都被定義爲操作。 我們將在Primitive Operations和Functions中更詳細地看到這些操作,但現在我們提到一些可用於與量子比特交互的有用的基本操作。
首先,單Q位Pauli運算符X,Y和Z在Q#中由原始操作X
, Y
和Z
,每個(Qubit => () : Adjoint, Controlled)
類型爲(Qubit => () : Adjoint, Controlled)
。 正如原始操作和函數中所描述的那樣,我們可以將X看作是一個位翻轉操作或NOT門。 這讓我們可以爲 形成一些經典位串s:
operation PrepareBitString(bitstring : Bool[], register : Qubit[]) : () {
body {
let nQubits = Length(register);
for (idxQubit in 0..nQubits - 1) {
if (bitstring[idxQubit]) {
X(register[idxQubit]);
}
}
}
adjoint auto
controlled auto
controlled adjoint auto
}
operation Example() : () {
body {
using (register = Qubit[8]) {
PrepareBitString(
[true; true; false; false; true; false; false; true],
register
);
// 此時,register現在具有狀態 |11001001〉.
}
}
}
Tip
稍後,我們將看到更簡潔的書寫這種操作的方式,不需要手動流量控制。
我們還可以準備諸如 來表示的Hadamard變換H
H : (Qubit => () : Adjoint, Controlled)
:
operation PreparePlusMinusState(bitstring : Bool[], register : Qubit[]) : () {
body {
// First, get a computational basis state of the form
// |s_0 s_1 ... s_n〉 by using PrepareBitString, above.
PrepareBitString(bitstring, register);
// Next, we use that |+〉 = H|0〉 and |-〉 = H|1〉 to
// prepare the state we want.
for (idxQubit in 0..Length(register) - 1) {
H(register[idxQubit]);
}
}
}
測量
使用Measure
操作,這是一個內置的原始門,我們可以從Qubit
類型的對象中提取經典信息,並將經典值作爲結果賦值,其Result
保留爲Result
,表示結果不再是量子態。 Measure
的輸入是Bloch球體上的Pauli軸,由Pauli
類型的對象(例如PauliX
)和類型爲Qubit
的對象Qubit
。
一個簡單的例子是下面的操作,它在 ket0
狀態下創建一個量子位,然後對它應用一個Hadamard門H
,然後在PauliZ
基礎上測量結果。
operation MeasurementOneQubit () : Result {
body {
mutable result = Zero;
// The following using block creates a fresh qubit and initializes it
// in the |0〉 state.
using (qubits = Qubit[1]) {
let qubit = qubits[0];
// We apply a Hadamard operation H to the state, thereby creating the
// state 1/sqrt(2)(|0〉+|1〉).
H(qubit);
// Now we measure the qubit in Z-basis.
set result = M(qubit);
// As the qubit is now in an eigenstate of the measurement operator,
// we reset the qubit before releasing it.
if (result == One) {
X(qubit);
}
}
// Finally, we return the result of the measurement.
return result;
}
}
下面的操作給出了一個稍微複雜的例子,當以指定的泡Qubit[]
測量時,返回類型爲Qubit[]
的寄存器中所有量子位的布爾值爲true
狀態爲零,否則爲false
。
operation AllMeasurementsZero (qs : Qubit[], pauli : Pauli) : Bool {
body {
mutable value = true;
for (i in 0..Length(qs)-1) {
if ( Measure([pauli], [qs[i]]) == One ) {
set value = false;
}
}
return value;
}
}
Q#語言允許經典控制流對量子位測量結果的依賴性。 這反過來又能夠實現強大的概率小工具,可以降低實施單元的計算成本。 舉例來說,在Q#中實現所謂的Repeat-Until-Success很容易,這些概率電路在基本門電路方面具有預期的低成本,但真正的成本取決於實際運行和實際交錯各種可能的分支。
爲了促進Repeat-Until-Success(RUS)模式,Q#支持該構造
repeat {
statement1
}
until (expression)
fixup {
statement2
}
其中statement1
和statement2
可以是任何有效的Q#語句,並expression
任何有效的表達式,其計算結果爲Bool
類型的值。 在一個典型的用例中,下面的電路在Bloch球體上圍繞
無理軸進行旋轉。 這是通過使用已知的RUS模式完成的:
operation RUScircuit (qubit : Qubit) : () {
body {
using(ancillas = Qubit[2]) {
ApplyToEachA(H, ancillas);
mutable finished = false;
repeat {
(Controlled X)(ancillas, qubit);
S(qubit);
(Controlled X)(ancillas, qubit);
Z(qubit);
}
until(finished)
fixup {
if AllMeasurementsZero(ancillas, Xpauli) {
set finished = true;
}
}
}
}
}
此示例顯示了使用finished
的可變變量,該變量位於整個repeat-until-fixup循環的範圍內,並在循環之前初始化並在修正步驟中進行更新。
最後,我們給出一個RUS模式的例子來準備量子態 ,從 狀態開始。 另請參閱canon提供的單元測試示例 :
operation RepeatUntilSuccessStatePreparation( target : Qubit ) : () {
body {
using( qubits = Qubit[1] ) {
let ancilla = qubits[0];
H(ancilla);
repeat {
// We expect target and ancilla qubit to be in |+⟩ state.
AssertProb(
[PauliX], [target], Zero, 1.0,
"target qubit should be in the |+⟩ state", 1e-10 );
AssertProb(
[PauliX], [ancilla], Zero, 1.0,
"ancilla qubit should be in the |+⟩ state", 1e-10 );
(Adjoint T)(ancilla);
CNOT(target,ancilla);
T(ancilla);
// The probability of measuring |+⟩ state on ancilla is 3/4.
AssertProb(
[PauliX], [ancilla], Zero, ToDouble(3) / ToDouble(4),
"Error: the probability to measure |+⟩ in the first
ancilla must be 3/4",
1e-10);
// If we get measurement outcome Zero, we prepare the required state
let outcome = Measure([PauliX], [ancilla]);
}
until( outcome == Zero )
fixup {
// Bring ancilla and target back to |+⟩ state
if( outcome == One ) {
Z(ancilla);
X(target);
H(target);
}
}
// Return ancilla back to Zero state
H(ancilla);
}
}
}
此操作中顯示的顯着編程特性是涉及量子操作的循環的更復雜的fixup
部分,以及使用AssertProb
語句來確定在程序中某些指定點處測量量子態的概率。 另請參閱測試和調試以獲取有關Assert
和AssertProb
語句的更多信息。