練習,第 2 部分 - 建立量子亂數產生器
在本單元中,您會實作量子亂數產生器的第二個階段:結合多個隨機位元來形成更大的隨機數字。 此階段是以您在上一個單元中建立的隨機位元產生器為基礎。
結合多個隨機位元以形成較大的數字
在上一個單元中,您已建立隨機位元產生器,其會產生隨機位元,方法是將量子位元放入疊加並加以測量。
當您測量量子位元時,您會收到 0 或 1 的隨機位元,機率等於 50%。 此位元的值是真正隨機的,我們無法知道測量之後將會得到哪個數值。 但是,您可以如何使用此行為來產生較大的亂數?
假設您重複該程序四次,產生此二進位數字序列:
$${0, 1, 1, 0}$$
如果您將這些位串連或結合成位元字串,則可以形成更大的數字。 在此範例中,位元序列 ${0110}$ 相當於十進位中的六。
$${0110_{\ binary} \equiv 6_{\ decimal}}$$
如果您多次重複此程式,便能結合多個位元來形成任何更大的數字。
定義亂數產生器邏輯
首先來概述亂數產生器應有的邏輯,假設在前一個單元中已建立隨機位元產生器:
- 將
max
定義為您想要產生的最大數字。 - 定義您要產生的隨機位元數目,方法是計算若要表達最多
max
的整數所需的位元nBits
。 - 產生長度為
nBits
的隨機位元字串。 - 如果位元字串代表的數字大於
max
,則回到步驟三。 - 否則,程序即完成。 以整數形式傳回產生的數字。
舉例來說,讓我們將 max
設定為 12。 也就是說,12 是您想要從隨機數產生器取得的最大數。
您需要 ${\lfloor ln(12) / ln(2) + 1 \rfloor}$,或 4 位元來表示 0 與 12 之間的每個數字。 (為求簡單明瞭,我們會略過得到此方程式的方法。)
假設您產生位元字串 ${1101_{\ binary}}$,這相當於 ${13_{\ decimal}}$。 因為 13 大於 12,所以您重複該程序。
接下來,您產生位元字串 ${0110_{\ binary}}$,這相當於 ${6_{\ decimal}}$。 因為 6 小於 12,所以程序完成。
量子隨機數產生器會傳回數位 6。
建立完整的隨機數產生器
在這裡,您可以展開 Main.qs
檔案以建立較大的隨機數。
匯入必要的程式庫
首先,您必須將所需的命名空間從 Q# Standard 連結庫匯入程式。 Q# 編譯程式會自動載入許多常見的函式和作業,不過針對完整的量子隨機數產生器,您需要兩個 Q# 命名空間的一些額外函式和作業: Microsoft.Quantum.Math
和 Microsoft.Quantum.Convert
。
將下列 import
指示詞複製並貼到 Main.qs
檔案頂端:
import Microsoft.Quantum.Convert.*;
import Microsoft.Quantum.Math.*;
將 Main
作業重新命名為 GenerateRandomBit
針對完整的隨機數產生器,您將重複使用上一個單元中定義的作業。 不過,作業名稱 Main
是程式的進入點,而且應該是唯一的。 若要避免混淆,您必須將 Main
作業重新命名為 GenerateRandomBit
。
GenerateRandomBit
作業看起來應該像這樣:
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 is within the requested range.
// Generate it again if it is outside the range.
return sample > max ? GenerateRandomNumberInRange(max) | sample;
}
讓我們花一點時間檢閱新程式碼。
- 您必須計算表示整數上限
max
所需的位元數。 來自Microsoft.Quantum.Math
程式庫的BitSizeI
函式會將整數轉換成表示所需的位元數。 GenerateRandomNumberInRange
作業會使用for
迴圈來產生亂數,直到產生一個等於或小於max
的亂數為止。for
迴圈的運作方式與其他程式設計語言中的for
迴圈完全相同。- 變數
bits
是可變動的變數。 可變變數是在計算期間可以變更的變數。 您可以使用set
指示詞來變更可變變數的值。 ResultArrayAsInt
函式來自Microsoft.Quantum.Convert
程式庫。 此函式會將位元字串轉換成正整數。
新增輸入點
最後,您會將進入點新增至程式。 根據預設,無論作業位於何處,Q# 編譯流程會尋找 Main
作業並開始處理該作業。 作業會 Main
呼叫 GenerateRandomNumberInRange
作業,以產生介於 0 與 max
數字之間的隨機數。 在此範例中,您會將最大值定義為 100。
將下列程式碼複製並貼到 Main.qs
檔案中:
operation Main() : Int {
let max = 100;
Message($"Sampling a random number between 0 and {max}: ");
// Generate random number in the 0..max range.
return GenerateRandomNumberInRange(max);
}
最終程式
您的 Main.qs
檔案看起來應該像這樣:
import Microsoft.Quantum.Convert.*;
import Microsoft.Quantum.Math.*;
operation Main() : Int {
let max = 100;
Message($"Sampling 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 is within the requested range.
// Generate it again if it is 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;
}
執行程式
讓我們試試新的亂數產生器!
- 在執行程式之前,您必須將目標設定檔設為 [不受限制]。 選取 [檢視]>[命令選擇區]、搜尋 QIR,然後選取 [Q#:設定 Azure Quantum QIR 目標設定檔],然後選取 [Q#:不受限制]。
- 若要執行程式,請從
Main
作業上方命令清單中選取 [執行],或按 Ctrl+F5。 您的輸出會出現在偵錯控制台中。 - 再次執行程式以查看不同的結果。
注意
如果目標設定檔未設定為 [不受限制],當您執行程式時會收到錯誤。
恭喜! 現在,您已經知道如何結合傳統邏輯與 Q# 來建立量子亂數產生器。
額外練習
嘗試將程式修改為也要求產生的亂數大於最小數字 min
,而不是零。