教學課程:在 中實作 Quantum Fourier 轉換 Q#
本教學課程說明如何撰寫和模擬在個別量子位上運作的基本量子程式。
雖然 Q# 主要是建立為大規模量子程式的高階程序設計語言,但它也可以用來探索較低層級的量子程序設計,也就是直接尋址特定的量子位。 具體而言,本教學課程會進一步瞭解 Quantum Fourier Transform (QFT),這是許多較大量子演算法不可或缺的子程式。
在本教學課程中,您將瞭解如何:
- 在中 Q#定義量子作業。
- 撰寫 Quantum Fourier 轉換線路
- 模擬量子位配置到測量輸出的量子運算。
- 觀察量子系統的模擬 wavefunction 在整個作業中如何演進。
注意
這個較低層級的量子資訊處理檢視通常描述於量子電路,這代表系統特定量子位的循序應用網關或作業。 因此,您循序套用的單一和多量子位作業可以在電路圖中輕鬆表示。 例如,本教學課程中使用的完整三量子四進位量子轉換具有下列表示法作為線路:
提示
如果您想要加速量子運算旅程,請參閱使用 Azure Quantum 撰寫程式代碼,這是 Azure Quantum 網站的獨特功能。 在這裡,您可以執行內Q#建範例或您自己的Q#程式、從提示產生新Q#程序代碼、在 VS Code for the Web 中開啟並執行程式碼,按兩下滑鼠,並詢問 Copilot 關於量子運算的任何問題。
必要條件
最新版的 Visual Studio Code 或開啟 Web上的 VS Code。
最新版的 Azure Quantum Development Kit (QDK) 擴充功能。 如需安裝詳細資料,請參閱 設定 QDK 擴充功能。
如果您想要使用 Jupyter Notebook,您也需要安裝 Python 和 Jupyter 擴充功能,以及最新的
qsharp
Python 套件。 若要這樣做,請開啟終端機並執行下列命令:$ pip install --upgrade qsharp
建立新 Q# 檔案
- 在 VS Code 中,選取 [ 檔案 > 新文本檔]
- 將檔案儲存為 QFTcircuit.qs。 此檔案包含程式 Q# 程式代碼。
- 開啟 QFTcircuit.qs。
在中寫入 QFT 線路 Q#
本教學課程的第一個部分是由定義 Q# 作業 Main
所組成,其會在三個量子位上執行量子 Fourier 轉換。 函 DumpMachine
式可用來觀察三量子位系統的模擬 wavefunction 如何在整個作業中演進。 在本教學課程的第二個部分中,您會新增測量功能,並比較量子比特測量前後的狀態。
您可以逐步建置作業。 將下列各節中的程式代碼複製並貼到 QFTcircuit.qs 檔案中。
您可以檢視 此區段的完整 Q# 程式代碼 作為參考。
匯入必要的 Q# 連結庫
在您的 Q# 檔案內,匯入相關的 Microsoft.Quantum.*
命名空間。
import Microsoft.Quantum.Diagnostics.*;
import Microsoft.Quantum.Math.*;
import Microsoft.Quantum.Arrays.*;
// operations go here
使用自變數和傳回定義作業
接下來,定義 Main
作業:
operation Main() : Unit {
// do stuff
}
作業 Main()
永遠不會接受自變數,而且現在會傳回 Unit
物件,這類似於在 C# 或 Python 中傳回 void
空的 Tuple Tuple[()]
。
稍後,您可以修改作業以傳回度量結果的陣列。
配置量子位
在作業中 Q# ,使用 關鍵詞配置三個量子位的 use
緩存器。 使用 use
時,量子位會自動以 $\ket{0}$ 狀態配置。
use qs = Qubit[3]; // allocate three qubits
Message("Initial state |000>:");
DumpMachine();
如同實際的量子計算,Q# 不允許您直接存取量子位狀態。 不過,DumpMachine
作業會列印 target 計算機的目前狀態,因此它可以在與完整狀態模擬器搭配使用時提供偵錯和學習的寶貴見解。
套用單一量子位和受控制作業
接下來,您會套用組成作業本身的 Main
作業。
Q# 已在命名空間中包含 Microsoft.Quantum.Intrinsic
其中許多基本量子作業。
注意
請注意, Microsoft.Quantum.Intrinsic
未在其他命名空間的先前代碼段中匯入,因為編譯程式會自動載入所有 Q# 程式。
套用的第一個作業是第 H
一個量子位的 (Hadamard) 作業:
若要將作業套用至緩存器中的特定量子位(例如數位中的Qubit
單Qubit[]
一 ),請使用標準索引表示法。
因此,將 H
作業套用至緩存器 qs
的第一個量子位會採用下列格式:
H(qs[0]);
除了將 H
作業套用至個別量子位之外,QFT 線路主要包含受控 R1
旋轉。 一 R1(θ, <qubit>)
般作業會將量子位的 $\ket{0}$ 元件維持不變,同時將$e^{i\theta}$ 的旋轉套用至 $\ket{1}$ 元件。
Q# 可讓您輕鬆地在一或多個控制量子位上設定作業執行的條件。 一般而言,呼叫前面會加上 Controlled
,而作業自變數會變更,如下所示:
Op(<normal args>)
$\to$ Controlled Op([<control qubits>], (<normal args>))
請注意,控件量子位自變數必須是數位,即使它適用於單一量子位也一樣。
QFT 中的受控制作業是 R1
針對第一個量子位執行的作業(並由第二個和第三個量子位控制):
在您的 Q# 檔案中,使用下列語句呼叫這些作業:
Controlled R1([qs[1]], (PI()/2.0, qs[0]));
Controlled R1([qs[2]], (PI()/4.0, qs[0]));
函 PI()
式用來定義 pi 弧度的旋轉。
套用 SWAP 作業
將相關的 H
作業和受控制的旋轉套用至第二和第三個量子位之後,線路看起來會像這樣:
//second qubit:
H(qs[1]);
Controlled R1([qs[2]], (PI()/2.0, qs[1]));
//third qubit:
H(qs[2]);
最後,您會將作業套用至第一個和第三個 SWAP
量子位,以完成線路。 此作業是必要的,因為量子 Fourier 轉換會以反向順序輸出量子位,因此交換可讓子程式順暢地整合到較大的演算法中。
SWAP(qs[2], qs[0]);
現在,您已完成將量子 Fourier 轉換的量子位層級作業寫入您的 Q# 作業:
解除分配量子位
最後一個步驟是再次呼叫 DumpMachine()
以查看作業后狀態,以及解除分配量子位。 當您配置量子位時,量子位處於 $\ket{0}$ 狀態,且需要使用作業重設為其初始狀態 ResetAll
。
要求將所有量子位明確重設為 $\ket{0}$ 是 的基本功能 Q#,因為它可讓其他作業在開始使用這些相同量子位(稀缺資源)時精確地知道其狀態。 此外,重設它們可確保它們不會與系統中的任何其他量子位糾纏。 如果在 use
配置區塊結尾未執行重設,可能會擲回運行時錯誤。
將下列幾行新增至您的 Q# 檔案:
Message("After:");
DumpMachine();
ResetAll(qs); // deallocate qubits
完整的 QFT 作業
程式 Q# 已完成。 您的 QFTcircuit.qs 檔案現在看起來應該像這樣:
import Microsoft.Quantum.Diagnostics.*;
import Microsoft.Quantum.Math.*;
import Microsoft.Quantum.Arrays.*;
operation Main() : Unit {
use qs = Qubit[3]; // allocate three qubits
Message("Initial state |000>:");
DumpMachine();
//QFT:
//first qubit:
H(qs[0]);
Controlled R1([qs[1]], (PI()/2.0, qs[0]));
Controlled R1([qs[2]], (PI()/4.0, qs[0]));
//second qubit:
H(qs[1]);
Controlled R1([qs[2]], (PI()/2.0, qs[1]));
//third qubit:
H(qs[2]);
SWAP(qs[2], qs[0]);
Message("After:");
DumpMachine();
ResetAll(qs); // deallocate qubits
}
執行QFT線路
目前, Main
作業不會傳回任何值 - 作業會傳 Unit
回值。 稍後,您可以修改作業以傳回度量結果的陣列(Result[]
)。
- 在執行程式之前,請在 VS Code target 底部的狀態列中確認設定檔設定為 Q#:不受限制。 若要變更 target 配置檔,請選取 target 狀態列中的配置檔,然後從下拉功能表中選取 [不受限制 ]。 如果 target 配置檔未設定為 Unrestricted,則執行程式時會收到錯誤。
- 若要執行程式,請從右上方的播放圖示下拉式清單中選取 [執行檔案],或按 Q#。 程式會在預設模擬器上執行
Main()
作業。 - 和
Message
DumpMachine
輸出會出現在偵錯控制台中。
如果您對其他輸入狀態有何影響感到好奇,建議您在轉換之前嘗試套用其他量子位作業。
將度量新增至 QFT 線路
來自 DumpMachine
函式的顯示顯示了作業的結果,但不幸的是,量子力學的基石指出,真正的量子系統不能有這樣的 DumpMachine
函式。
相反地,資訊會透過測量來擷取,這通常不只會提供完整量子狀態的資訊,也可以大幅改變系統本身。
量子測量有許多種,但這裡的範例著重於最基本的:單一量子位的投影量值。 在指定基礎測量時(例如,計算基礎 $ { \ket, \ket{0}{1} } $),量子位狀態會投影到測量的基底狀態,因此會終結兩者之間的任何迭加。
修改 QFT 作業
若要在程式內 Q# 實作度量,請使用傳 M
回型別的 Result
作業。
首先,修改 Main
作業以傳回度量結果陣列, Result[]
而不是 Unit
。
operation Main() : Result[] {
定義和初始化 Result[]
陣列
配置量子位之前,請宣告並系結三個元素陣列(每個量子位各一個 Result
):
mutable resultArray = [Zero, size = 3];
關鍵詞 mutable
前置 resultArray
詞可讓您稍後在程式碼中修改變量,例如,新增您的度量結果時。
在迴圈中 for
執行測量,並將結果新增至陣列
在 QFT 轉換作業之後,插入下列程式代碼:
for i in IndexRange(qs) {
resultArray w/= i <- M(qs[i]);
}
IndexRange
在陣列上呼叫的函式(例如量子位數組)qs
會傳回陣列索引的範圍。
在這裡,它會在 for
迴圈中使用 M(qs[i])
語句來循序測量每個量子位。
然後,使用 update-and-reassign 語句,將每個測量 Result
型別 (或 Zero
) One
新增至 中 resultArray
對應的索引位置。
注意
此語句的語法對 是唯 Q#一的,但會對應至其他語言中所看到的類似變數重新指派 resultArray[i] <- M(qs[i])
,例如 F# 和 R。
關鍵詞 set
一律用來重新指派使用 系結的 mutable
變數。
返回 resultArray
測量完所有三個量子位,並將結果加至 resultArray
後,您就可以放心地重設和釋放量子位。 若要傳回度量,請插入:
return resultArray;
使用測量執行 QFT 線路
現在,變更函式的位置 DumpMachine
,以在測量前後輸出狀態。
您的最終程式 Q# 代碼看起來應該像這樣:
import Microsoft.Quantum.Diagnostics.*;
import Microsoft.Quantum.Math.*;
import Microsoft.Quantum.Arrays.*;
operation Main() : Result[] {
mutable resultArray = [Zero, size = 3];
use qs = Qubit[3];
//QFT:
//first qubit:
H(qs[0]);
Controlled R1([qs[1]], (PI()/2.0, qs[0]));
Controlled R1([qs[2]], (PI()/4.0, qs[0]));
//second qubit:
H(qs[1]);
Controlled R1([qs[2]], (PI()/2.0, qs[1]));
//third qubit:
H(qs[2]);
SWAP(qs[2], qs[0]);
Message("Before measurement: ");
DumpMachine();
for i in IndexRange(qs) {
resultArray w/= i <- M(qs[i]);
}
Message("After measurement: ");
DumpMachine();
ResetAll(qs);
Message("Post-QFT measurement results [qubit0, qubit1, qubit2]: ");
return resultArray;
}
提示
請記得在每次您引入程式碼變更之前儲存盤案,然後再再次執行。
- 在執行程式之前,請在 VS Code target 底部的狀態列中確認設定檔設定為 Q#:不受限制。 若要變更 target 配置檔,請選取 target 狀態列中的配置檔,然後從下拉功能表中選取 [不受限制 ]。 如果 target 配置檔未設定為 Unrestricted,則執行程式時會收到錯誤。
- 若要執行程式,請從右上方的播放圖示下拉式清單中選取 [ 執行 Q# 檔案 ],或按 Ctrl+5。 程式會在預設模擬器上執行
Main()
作業。 - 和
Message
DumpMachine
輸出會出現在偵錯控制台中。
您的輸出看起來應該如下所示:
Before measurement:
Basis | Amplitude | Probability | Phase
-----------------------------------------------
|000⟩ | 0.3536+0.0000𝑖 | 12.5000% | 0.0000
|001⟩ | 0.3536+0.0000𝑖 | 12.5000% | 0.0000
|010⟩ | 0.3536+0.0000𝑖 | 12.5000% | 0.0000
|011⟩ | 0.3536+0.0000𝑖 | 12.5000% | 0.0000
|100⟩ | 0.3536+0.0000𝑖 | 12.5000% | 0.0000
|101⟩ | 0.3536+0.0000𝑖 | 12.5000% | 0.0000
|110⟩ | 0.3536+0.0000𝑖 | 12.5000% | 0.0000
|111⟩ | 0.3536+0.0000𝑖 | 12.5000% | 0.0000
After measurement:
Basis | Amplitude | Probability | Phase
-----------------------------------------------
|010⟩ | 1.0000+0.0000𝑖 | 100.0000% | 0.0000
Post-QFT measurement results [qubit0, qubit1, qubit2]:
[Zero, One, Zero]
此輸出說明一些不同的事項:
- 當您比較傳回的結果與預先測量
DumpMachine
時,它顯然不會 不會 說明 QFT 后迭加與基礎狀態。 測量只會傳回單一基礎狀態,機率取決於系統波浪函數中該狀態的幅度。 - 從測量后,您會看到度量
DumpMachine
變更狀態本身,並將它從基礎狀態的初始迭加投影到對應至測量值的單一基礎狀態。
如果您多次重複此操作,您會看到結果統計數據開始呈現出量子傅立葉變換後的狀態的等權重疊加,這會導致每次測量產生隨機結果。 不過,除了效率低下,仍然不完善,這隻會重現基礎狀態的相對幅度,而不是它們之間的相對階段。 後者不是此範例中的問題,但如果對 QFT 提供比 $\ket{000}$更複雜的輸入,您會看到相對階段出現。
Q#使用作業來簡化 QFT 線路
如簡介中所述,大部分 Q#的權力都在於它可讓您抽象化處理個別量子位的憂慮。
事實上,如果您想要開發完整規模、適用的量子程式,擔心作業在 H
特定輪替之前或之後,只會減緩您的速度。 Azure Quantum 提供 ApplyQFT
作業,可供您使用並套用任意數目的量子位。
以下列方式取代第一個
H
作業到SWAP
作業的所有專案:ApplyQFT(qs);
您的程式代碼現在看起來應該像這樣
import Microsoft.Quantum.Diagnostics.*; import Microsoft.Quantum.Math.*; import Microsoft.Quantum.Arrays.*; operation Main() : Result[] { mutable resultArray = [Zero, size = 3]; use qs = Qubit[3]; //QFT: //first qubit: ApplyQFT(qs); Message("Before measurement: "); DumpMachine(); for i in IndexRange(qs) { resultArray w/= i <- M(qs[i]); } Message("After measurement: "); DumpMachine(); ResetAll(qs); Message("Post-QFT measurement results [qubit0, qubit1, qubit2]: "); return resultArray; }
Q#再次執行程式,並注意到輸出與之前相同。
若要查看使用 Q# 作業的實際優點,請將量子位數目變更為 以外的
3
專案:
mutable resultArray = [Zero, size = 4];
use qs = Qubit[4];
//...
因此,您可以針對任何指定數目的量子位套用適當的 QFT,而不必擔心在每個量子位上新增作業 H
和輪替。
相關內容
探索其他 Q# 教學課程:
- 量子隨機數產生器 示範如何撰寫程式 Q# ,以在迭加中產生量子位的隨機數。
- Grover 的搜尋演算法 示範如何撰寫 Q# 使用 Grover 搜尋演算法的程式。
- 量子糾纏 示範如何撰寫 Q# 程式,以操作和測量量子位,並示範迭加和糾纏的效果。
- Quantum Katas 是自我節奏的教學課程和程序設計練習,旨在同時教學量子運算和Q#程序設計元素。