共用方式為


教學課程:在 中實作量子隨機數產生器 Q#

在本教學課程中,您將瞭解如何撰寫基本量子程式 Q# ,以利用量子力學的本質來產生隨機數。

在此教學課程中,您需要:

  • 建立 Q# 程式。
  • 檢閱程式的主要元件 Q# 。
  • 定義問題的邏輯。
  • 結合傳統和量子作業來解決問題。
  • 使用量子位元與疊加來建置量子亂數產生器。

提示

如果您想要加速量子運算旅程,請參閱使用 Azure Quantum 撰寫程式代碼,這是 Azure Quantum 網站的獨特功能。 在這裡,您可以執行內Q#建範例或您自己的Q#程式、從提示產生新Q#程序代碼、在 VS Code for the Web開啟並執行程式碼,按兩下滑鼠,並詢問 Copilot 關於量子運算的任何問題。

必要條件

  • 若要在 Azure Quantum 的 Copilot 中執行程式代碼範例:

    • Microsoft (MSA) 電子郵件帳戶。
  • 若要在 Visual Studio Code 中開發和執行程式碼範例:

縮小問題的範圍

傳統電腦不會產生真正的亂數,而是產生出「偽亂數」。 偽亂數產生器會根據某個初始值 (稱為「種子」) 產生決定性的數字序列。 為了更精確地估計隨機值,此種子通常是 CPU 時鐘的目前時間。

另一方面,量子電腦可以產生真正的亂數。 這是因為疊加中的量子位元測量是概率流程。 測量的結果是隨機的,且無法預測結果。 這是量子亂數產生器的基本原則。

量子位是可以迭加的量子信息單位。 測量時,量子位只能處於 0 狀態或 1 狀態。 不過,在測量之前,量子位的狀態代表以測量方式讀取01的機率

首先在基礎狀態(例如零)配置量子位元。 隨機數產生器的第一 個步驟是使用 Hadamard 運算,將量子位放入相等迭加。 此狀態的測量會產生一個零或一個具有每個結果 50% 機率的零或一個,這是一個真正的隨機位。

在迭加中測量量子位之後,無法得知您取得的內容,而且每次叫用程式代碼時,結果都會是不同的值。 但是,您可以如何使用此行為來產生較大的亂數?

假設您重複該程序四次,產生此二進位數字序列:

$${0, 1, 1, 0}$$

如果您將這些位串連或結合成位元字串,則可以形成更大的數字。 在此範例中,位元序列 ${0110}$ 相當於十進位中的六。

$${0110_{\ binary} \equiv 6_{\ decimal}}$$

如果您多次重複此程式,便能結合多個位元來形成任何更大的數字。 使用此方法,您可以建立數位作為安全密碼,因為您可以確定沒有駭客可以判斷測量序列的結果。

定義亂數產生器邏輯

讓我們概述隨機數產生器的邏輯應該是什麼:

  1. max 定義為您想要產生的最大數字。
  2. 定義您必須產生的隨機位元數目。 這是藉由計算多少位 nBits來完成,您必須將整數表示為 max
  3. 產生長度為 nBits 的隨機位元字串。
  4. 如果位元字串代表的數字大於 max,則回到步驟三。
  5. 否則,程序即完成。 以整數形式傳回產生的數字。

舉例來說,讓我們將 max 設定為 12。 也就是說,12 是您想要作為密碼使用的最大數位。

您需要 ${\lfloor ln(12) / ln(2) + 1 \rfloor}$,或 4 位元來表示 0 與 12 之間的每個數字。 我們可以使用內建函式 BitSizeI,它會接受任何整數,並傳回代表它所需的位數。

假設您產生位元字串 ${1101_{\ binary}}$,這相當於 ${13_{\ decimal}}$。 因為 13 大於 12,所以您重複該程序。

接下來,您產生位元字串 ${0110_{\ binary}}$,這相當於 ${6_{\ decimal}}$。 因為 6 小於 12,所以程序完成。

量子隨機數產生器會傳回數位 6 作為密碼。 在實務上,通常會將較大的數字設定為最大值,因為只要嘗試所有可能的密碼,就能輕鬆破解較小的數字。 事實上,若要提高猜測或破解密碼的困難,您可以使用 ASCII 碼將二進位碼轉換成文字,並使用數字、符號和混合大小寫字母來產生密碼。

寫入隨機位產生器

第一個步驟是撰寫 Q# 產生隨機位的作業。 這項作業將是隨機數產生器的其中一個建置組塊。

operation GenerateRandomBit() : Result {
    // Allocate a qubit.
    use q = Qubit();

    // Set the qubit into superposition of 0 and 1 using the Hadamard 
    H(q);

    // At this point the qubit `q` has 50% chance of being measured in the
    // |0〉 state and 50% chance of being measured in the |1〉 state.
    // 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.
    // Qubits must be in the |0〉 state by the time they are released.
    Reset(q);

    // Return the result of the measurement.
    return result;
}

現在看看新的程序代碼。

  • 您可以定義 GenerateRandomBit 作業,其不會接受任何輸入,併產生 類型的 Result值。 型 Result 別代表度量的結果,而且可以有兩個可能的值: ZeroOne
  • 您可以使用 關鍵詞來配置單一量子位 use 。 配置時,量子位一律處於 |0} 狀態。
  • 您可以使用 H 作業將量子位放在相等迭加中。
  • 您可以使用 M 作業來測量量子位,並傳回測量值 (ZeroOne)。
  • 您可以使用 Reset 作業,將量子位重設為 |0} 狀態。

藉由將量子位置於迭加與 H 作業,並使用作業來測量, M 每次叫用程式代碼時,結果都會是不同的值。

使用 Bloch 球將程式 Q# 代碼可視化

在 Bloch 球體中,北極代表古典值 0 ,而南極則代表傳統值 1。 任何迭加都可以以球體上的點來表示(以箭號表示)。 箭號的結尾越接近極點,量子位在測量時會折迭到指派給該極點的傳統值機率越高。 例如,下圖中箭號所代表的量子位狀態,如果您測量值 0 ,則其機率較高。

此圖顯示高機率測量零的量子位狀態。

您可以使用此表示法,將程式代碼正在執行的動作視覺化:

  1. 首先,從以 |0} 狀態初始化的量子位開始,並套用H作業來建立相等迭加,其中 01 的機率相同。

    此圖顯示套用 hadamard 閘道來準備迭加中的量子位。
  2. 然後測量量子位並儲存輸出:

    顯示量子位測量並儲存輸出的圖表。

由於測量的結果是隨機的,且測量 01 的機率相同,因此您已取得完全隨機的位。 您可以多次呼叫此作業來建立整數。 例如,如果您呼叫作業三次以取得三個隨機位,您可以建置隨機 3 位數位(也就是介於 0 到 7 之間的隨機數)。

撰寫完整的隨機數產生器

  1. 首先,您必須將所需的命名空間從 Q# 標準連結庫匯入程式。 編譯程式 Q# 會自動載入許多常見的函式和作業,不過對於完整的隨機數產生器,您需要兩 Q# 個命名空間的一些額外函式和作業: Microsoft.Quantum.MathMicrosoft.Quantum.Convert

    import Microsoft.Quantum.Convert.*;
    import Microsoft.Quantum.Math.*;
    
  2. 接下來,您會定義 GenerateRandomNumberInRange 作業。 此作業會重複呼叫 GenerateRandomBit 作業,以建立位元字串。

    /// 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.MathBitSizeI式會將整數轉換成表示它所需的位數。
    • SampleRandomNumberInRange 作業會使用 for 迴圈來產生亂數,直到產生一個等於或小於 max 的亂數為止。 for 迴圈的運作方式與其他程式設計語言中的 for 迴圈完全相同。
    • 變數 bits 是可變動的變數。 可變變數是在計算期間可以變更的變數。 您可以使用 set 指示詞來變更可變變數的值。
    • ResultArrayAsInt 式會從預設 Microsoft.Quantum.Convert 命名空間將位字串轉換成正整數。
  3. 最後,您會將進入點新增至程式。 根據預設,編譯程式 Q# 會尋找 Main 作業,並開始在那裡處理。 它會呼叫 GenerateRandomNumberInRange 作業,以產生介於 0 到 100 之間的隨機數位。

    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);
    }
    

    let 指示詞宣告在計算期間不會變更的變數。 在這裡,您會將最大值定義為100。

    如需作業的詳細資訊 Main ,請參閱 進入點

  4. 隨機數產生器的完整程式碼如下所示:

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 a Hadamard operation
    H(q);

    // At this point the qubit `q` has 50% chance of being measured in the
    // |0〉 state and 50% chance of being measured in the |1〉 state.
    // 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.
    // Qubits must be in the |0〉 state by the time they are released.
    Reset(q);

    // Return the result of the measurement.
    return result;
}

執行隨機數產生器程式

您可以在 Azure Quantum 中的 Copilot 中,使用 Visual Studio Code 作為獨立Q#應用程式或使用 Python 主機程式來執行程式。

您可以使用 Azure Quantum 中的 Copilot 免費測試程式 Q# 代碼 - 您只需要Microsoft (MSA) 電子郵件帳戶。 如需 Azure Quantum 中 Copilot 的詳細資訊,請參閱 探索 Azure Quantum

  1. 在瀏覽器中開啟 Azure Quantum 中的 Copilot。

  2. 將下列程式代碼複製並貼到程式碼編輯器中。

    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);
    }
    
    /// # Summary
    /// 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;
    }
    
    /// # Summary
    /// Generates a random bit.
    operation GenerateRandomBit() : Result {
        // Allocate a qubit.
        use q = Qubit();
    
        // Set the qubit into superposition of 0 and 1 using the Hadamard 
        // operation `H`.
        H(q);
    
        // At this point the qubit `q` has 50% chance of being measured in the
        // |0〉 state and 50% chance of being measured in the |1〉 state.
        // 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.
        // Qubits must be in the |0〉 state by the time they are released.
        Reset(q);
    
        // Return the result of the measurement.
        return result;
    
        // Note that Qubit `q` is automatically released at the end of the block.
    }
    
    
  3. 選取要執行的拍攝次數,然後選取 [ 執行]。

  4. 結果會顯示在直方圖和 [結果] 欄位中。

  5. 選取 [說明程序代碼 ] 以提示 Copilot 向您說明程式代碼。

提示

從 Azure Quantum 中的 Copilot,您可以選取程式碼編輯器右上角的 VS Code 標誌按鈕,以在 Web 的 VS Code 中開啟程式。

注意

此代碼段目前未在任何可用的 Azure Quantum 硬體targets上執行,因為可呼叫者ResultArrayAsInt需要具有完整計算配置檔QPU。

探索其他 Q# 教學課程:

  • 量子糾纏 示範如何撰寫 Q# 程式,以操作和測量量子位,並示範迭加和糾纏的效果。
  • Grover 的搜尋演算法 示範如何撰寫 Q# 使用 Grover 搜尋演算法的程式。
  • Quantum Fourier Transforms 會探索如何撰寫 Q# 直接尋址特定量子位的程式。
  • Quantum Katas 是自我節奏的教學課程和程序設計練習,旨在同時教學量子運算和Q#程序設計元素。