2. gyakorlat – Kvantum véletlenszerű számgenerátor létrehozása

Befejeződött

Ebben az egységben valósítja meg a kvantum véletlenszám-generátor második részét. Több véletlenszerű bit kombinálásával nagyobb véletlenszerű számot hozhat létre. Ez a rész az előző leckében már létrehozott véletlenszerű bitgenerátorra épül.

Több véletlenszerű bit egyesítése nagyobb szám létrehozásához

Az előző leckében létrehozott egy véletlenszerű bitgenerátort, amely egy qubitet szuperpozíciós állapotba helyez, majd a qubitet 0 vagy 1 véletlenszerű bitérték létrehozására méri, mindegyik 50% valószínűséggel. Ennek a bitnek az értéke valóban véletlenszerű, nem lehet előre tudni, hogy mi lesz a mérési eredmény. De hogyan használhatja ezt a viselkedést nagyobb véletlenszerű számok létrehozására?

Ha négyszer ismétli meg a folyamatot, akkor létrehozhatja a bináris számjegyek sorozatát:

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

Ha ezeket a biteket egy bitsztringbe egyesíti, akkor nagyobb számot is létrehozhat. Ebben a példában a bináris ${0110}$ bitütemezése megegyezik a decimális 6-os számmal.

$${0110_{\ binary} \equiv 6_{\ decimális}}$$

Tetszőlegesen nagy véletlenszerű szám létrehozásához egyszerűen ismételje meg ezt a folyamatot többször. Ezután egyesítse az összes bitet bináris számmá, és konvertálja a bináris számot decimális számmá.

A véletlenszám-generáló logikájának meghatározása

A Q#-kód megírása előtt vázoljuk fel a logikát egy véletlenszerű szám létrehozásához:

  1. Adja meg max a létrehozni kívánt tizedesjegyek maximális számát.
  2. Határozza meg a létrehozáshoz nBitsszükséges véletlenszerű bitek maxszámát.
  3. Generáljunk egy nBits hosszúságú véletlenszerű bitsztringet.
  4. Ha a bitsztring nagyobb számot maxjelöl, térjen vissza az előző lépéshez.
  5. Ellenkező esetben a folyamat befejeződött. A generált számot decimális egész számként adja vissza.

Definiáljuk például a max értékét 12-nek. Vagyis a 12 a legnagyobb szám, amelyet a véletlenszerű számgenerátornak ki kell termelnie.

A következő egyenlet segítségével határozza meg a 12-es szám binárisban való megjelenítéséhez szükséges bitek számát:

$${\lfloor ln(12) / ln(2) + 1 \rfloor}$$

Az egyenlet szerint 4 bitre van szükség a 0 és 12 közötti szám megjelenítéséhez.

Tegyük fel például, hogy négyszer generál véletlenszerű bitet, és az eredmény a ${1101_{\ binary}}$ bitsztring lesz. Ez a bináris érték decimálisan 13-nak felel meg. Mivel a 13 nagyobb mint 12, megismételjük a folyamatot.

Ezután létrehozza a ${0110_{\ binary}}$ bitsztringet, ami megegyezik a ${6_{\ decimális rendszer}}$ értékkel. Mivel a 6 kisebb mint 12, a folyamat befejeződött.

A kvantum véletlenszerű számgenerátor a 6-os számot adja vissza.

Teljes véletlenszerű számgenerátor létrehozása a Q-ban#

Itt bővíti az előző leckéből származó Main.qs fájlt a véletlenszám-generátor létrehozásához.

Importálja a szükséges könyvtárakat

Először importálja a névtereket a Q#standard kódtárból, amely tartalmazza a program írásához szükséges függvényeket és műveleteket. A Q#-fordító számos gyakori függvényt és műveletet automatikusan betölt. A kvantum véletlenszerű számgenerátorhoz azonban további függvényekre és műveletekre van szükség két Q#-névtérből: Std.Math és Std.Convert.

Másolja és illessze be a következő import irányelveket a Main.qs fájl elején:

import Std.Convert.*;
import Std.Math.*;

Nevezze át a Main műveletet GenerateRandomBit-re

A véletlenszerű számgenerátor program az Main előző leckében írt műveletet használja véletlenszerű bit létrehozásához. Nevezze át a Main műveletet GenerateRandomBit úgy, hogy a műveletnek leíróbb neve legyen, és ne legyen a program belépési pontja.

Másolja és illessze be a következő kódot a következőbe 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;
}

A véletlenszerű számgenerátor műveletének meghatározása

Hozzon létre egy új, úgynevezett GenerateRandomNumberInRangeműveletet. Ez a művelet többször meghívja a GenerateRandomBit műveletet a bitek sztringjének létrehozásához.

Másolja ki a következő kódot, és helyezze közvetlenül a GenerateRandomBit művelet elé a Main.qs fájlban:

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

Íme a kód áttekintése a következőben: GenerateRandomNumberInRange.

  • Hívja meg a BitSizeI függvényt a Std.Math kódtárból a tárolt maxegész szám megjelenítéséhez szükséges bitek számának kiszámításához.
  • Használjon egy for hurkot, hogy véletlenszerű biteket generáljon, amelyek száma egyenlő nBits-tel. Hívja meg a GenerateRandomBit műveletet a véletlenszerű bitek létrehozásához.
  • A for cikluson belül használja az set utasítást a bits változó frissítésére minden új véletlenszerű bitnél. A változó bits egy módosítható változó, ami azt jelenti, hogy a számítás során az érték bits változhat.
  • Hívja meg a ResultArrayAsInt függvényt a Std.Convert kódtárból, hogy a bitek bits tömbje a benne tárolt samplepozitív egész számmá alakuljon.
  • Az return utasításban ellenőrizze, hogy sample nagyobb-e, mint max. Ha sample nagyobb, mint max, akkor hívja GenerateRandomNumberInRange újra, és kezdje újra. Ellenkező esetben adja vissza a megadott helyen tárolt samplevéletlenszerű számot.

Belépési pont hozzáadása

Végül adjon hozzá egy belépésipont-műveletet a kódhoz, hogy a fordító futtathassa a programot. Alapértelmezés szerint a Q#-fordító egy Main műveletet keres, és belépési pontként használja Main , függetlenül attól, hogy hol Main található a fájlban. Itt a Main művelet beállít egy értéket max , és meghívja a GenerateRandomNumberInRange műveletet, hogy véletlenszerű számot hozzon létre 0 és max0 között.

Ha például 0 és 100 közötti véletlenszerű számot szeretne létrehozni, másolja a következő kódot a Main.qs fájlba:

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

Végleges program

A program teljes Q#-kódja a következő helyen található Main.qs:

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

A program futtatása

Próbálja ki az új kvantum véletlenszerű számgenerátort!

A program futtatásához válassza a Kódlencse futtatása lehetőséget a művelet fölötti Main parancsok listájából. Vagy nyomja le a Ctrl + F5 billentyűkombinációt. A kimenet megjelenik a hibakeresési konzolon. Futtassa többször a programot, és figyelje meg, hogyan változik az eredmény.

Gratulálunk! Létrehozott egy igazán véletlenszerű kvantumszámgenerátort a Q#-ban.

Bónusz gyakorlat

Próbálja meg úgy módosítani a programot, hogy a generált véletlenszerű szám is nagyobb legyen, mint egy minimális pozitív szám, minnulla helyett.