練習 (第 2 部分) - 建立量子亂數產生器
在本單元中,您將實作量子隨機數產生器的第二部分。 您可以組合多個隨機位元以形成更大的隨機數。 此部分建立在您在上一個單元中已建立的隨機位元產生器之上。
結合多個隨機位元以形成較大的數字
在上一個單元中,您建立了一個隨機位元生成器,將量子位元置於量子疊加狀態,然後測量該量子位元以生成隨機位元值,可能是 0 或 1,每种結果的機率均為 50%。 該位的值確實是隨機的,無法提前知道測量結果是什麼。 但是,您可以如何使用此行為來產生較大的亂數?
如果您重複此程序四次,則可能會產生下列二進位數字序列:
$${0,1,1,0}$$
如果將這些位組合成一個位串,那麼您可以形成一個更大的數字。 在此範例中,二進位的位序列 ${0110}$ 相當於十進位的數字 6。
$${0110_{\ binary} \equiv 6_{\ decimal}}$$
要產生任意大的隨機數,只需重複此過程多次即可。 然後,將所有位元組合成一個二進位數,並將該二進位數轉換為十進位數。
定義亂數產生器邏輯
在撰寫 Q# 程式碼之前,讓我們先概述產生隨機數的邏輯:
- 定義
max為您要產生的最大十進位數。 - 確定產生
max所需的nBits隨機位元數。 - 產生長度為
nBits的隨機位元字串。 - 如果位字串代表大於
max的數字,則返回上一步。 - 否則,程序即完成。 將產生的數字傳回為十進位整數。
例如,讓我們定義 max 為 12。 也就是說,12 是隨機數產生器應輸出的最大數字。
使用下列方程式來判斷以二進位表示數字 12 所需的位元數:
$${\lfloor ln(12) / ln(2) + 1 \rfloor}$$
根據這個方程,您需要 4 位來表示 0 到 12 之間的數字。
例如,假設您產生隨機位元四次,並取得位元字串 ${1101_{\ binary}}$。 此二進位值等於十進位數的 13。 因為 13 大於 12,所以您重複該程序。
接下來,您產生位字串 ${0110_{\ 二進位}}$,它等於 ${6_{\ 十進制}}$。 因為 6 小於 12,所以程序完成。
量子隨機數產生器會傳回數位 6。
在 Q 中創建一個完整的隨機數生成器#
在這裡,您將擴展 Main.qs 上一課中的文件以構建您的隨機數生成器。
匯入必要的程式庫
首先,從 Q# 標準程式庫匯入命名空間,其中包含撰寫程式所需的函式和作業。 Q# 編譯器會自動載入許多常見的函式和作業。 但針對量子隨機數產生器,您需要兩個 Q# 命名空間的一些其他函式和作業: Microsoft.Quantum.Math 和 Microsoft.Quantum.Convert。
將下列import指示詞複製並貼上至您的Main.qs檔案開頭:
import Std.Convert.*;
import Std.Math.*;
注意
您可以使用 Std 代替 Microsoft.Quantum 從標準程式庫匯入函數和操作。
將 Main 作業重新命名為 GenerateRandomBit
隨機數產生器程式使用您在上一個單元中編寫的運算來 Main 產生隨機位元。 將作業重新命名 Main 為 , GenerateRandomBit 讓此作業具有更具描述性的名稱,而且不是程式的進入點。
將以下程式碼複製並貼上到 Main.qs:
import Std.Convert.*;
import Std.Math.*;
operation GenerateRandomBit() : Result {
// Allocate a qubit.
use q = Qubit();
// Set the qubit into superposition of 0 and 1 using the Hadamard
H(q);
// Measure the qubit and store the result.
let result = M(q);
// Reset qubit to the |0〉 state.
Reset(q);
// Return the result of the measurement.
return result;
}
定義隨機數產生器作業
建立名為 GenerateRandomNumberInRange的新作業。 此作業會重複呼叫 GenerateRandomBit 作業,以建立位元字串。
複製下列程式碼,並將其直接放在 GenerateRandomBit 操作之前的 Main.qs 檔案中。
/// Generates a random number between 0 and `max`.
operation GenerateRandomNumberInRange(max : Int) : Int {
// Determine the number of bits needed to represent `max` and store it
// in the `nBits` variable. Then generate `nBits` random bits which will
// represent the generated random number.
mutable bits = [];
let nBits = BitSizeI(max);
for idxBit in 1..nBits {
set bits += [GenerateRandomBit()];
}
let sample = ResultArrayAsInt(bits);
// Return random number if it's within the requested range.
// Generate it again if it's outside the range.
return sample > max ? GenerateRandomNumberInRange(max) | sample;
}
以下是程式碼 GenerateRandomNumberInRange的概述:
- 從
Std.Math函式庫中呼叫BitSizeI函式來計算表示儲存在max中的整數所需的位元數。 - 使用
for迴圈來產生等於nBits的隨機位數。 呼叫您的GenerateRandomBit作業來產生隨機位元。 - 在
for的循環中,使用set語句將bits變數更新為每個新的隨機位元。 變數bits是可變變量,這意味著 的bits值可以在計算過程中發生變化。 - 從
Std.Convert函式庫呼叫ResultArrayAsInt函數,將bits中的位元陣列轉換為儲存在sample的正整數。 - 在陳述式中
return,檢查sample是否大於max。 如果sample大於max,則再次呼叫GenerateRandomNumberInRange並重新開始。 否則,傳回儲存在sample中的隨機數。
新增輸入點
最後,將入口點操作新增至程式碼,以便編譯器可以執行您的程式。 根據預設,Q# 編譯器會尋找 Main 作業,並用 Main 作為進入點,無論 Main 位於檔案的何處。 在這裡,操作將一個值設定為 max,並呼叫 GenerateRandomNumberInRange 操作以產生一個介於 0 和 max之間的隨機數。
例如,若要產生 0 到 100 之間的隨機數,請將下列程式碼複製到檔案 Main.qs 中:
operation Main() : Int {
let max = 100;
Message($"Generating a random number between 0 and {max}: ");
// Generate random number in the 0..max range.
return GenerateRandomNumberInRange(max);
}
最終程式
以下是您在 Main.qs 中的程式的完整 Q# 程式碼:
import Std.Convert.*;
import Std.Math.*;
operation Main() : Int {
let max = 100;
Message($"Generating a random number between 0 and {max}: ");
// Generate random number in the 0..max range.
return GenerateRandomNumberInRange(max);
}
/// Generates a random number between 0 and `max`.
operation GenerateRandomNumberInRange(max : Int) : Int {
// Determine the number of bits needed to represent `max` and store it
// in the `nBits` variable. Then generate `nBits` random bits which will
// represent the generated random number.
mutable bits = [];
let nBits = BitSizeI(max);
for idxBit in 1..nBits {
set bits += [GenerateRandomBit()];
}
let sample = ResultArrayAsInt(bits);
// Return random number if it's within the requested range.
// Generate it again if it's outside the range.
return sample > max ? GenerateRandomNumberInRange(max) | sample;
}
operation GenerateRandomBit() : Result {
// Allocate a qubit.
use q = Qubit();
// Set the qubit into superposition of 0 and 1 using the Hadamard operation
H(q);
// Measure the qubit value using the `M` operation, and store the
// measurement value in the `result` variable.
let result = M(q);
// Reset qubit to the |0〉 state.
Reset(q);
// Return the result of the measurement.
return result;
}
執行程式
試試您的新量子隨機數生成器!
若要執行您的程式,請從 Main 作業上方的命令清單中選擇 Run 程式碼鏡頭。 或者,按 Ctrl + F5。 您的輸出會顯示在偵錯控制台中。 多次運行該程序並注意結果如何變化。
恭喜! 您在 Q# 中建立了真正的隨機量子數產生器。
額外練習
嘗試修改程序,使其也要求產生的隨機數大於某個最小正數, min而不是零。