Oktatóanyag: Kvantum véletlenszerű számgenerátor implementálása a Q#

Megjegyzés

A Microsoft Quantum Development Kit (klasszikus QDK) 2024. június 30. után már nem támogatott. Ha Ön már QDK-fejlesztő, javasoljuk, hogy váltson az új Azure-ra Quantum Development Kit (Modern QDK) a kvantummegoldások fejlesztésének folytatásához. További információ: A kód migrálása Q# a modern QDK-ba.

Megtudhatja, hogyan írhat olyan alapszintű kvantumprogramot, amely Q# a kvantummechanika természetét felhasználva véletlenszerű számot állít elő.

Az oktatóanyagban a következőket végezheti el:

  • Hozzon létre egy Q# programot.
  • Tekintse át a program fő összetevőit Q# .
  • Definiálja a probléma logikáját.
  • A klasszikus és kvantumműveletek kombinálásával megoldhatja a problémát.
  • Qubitek és a szuperpozíció használata kvantumos véletlenszám-generátor létrehozásához.

Tipp

Ha fel szeretné gyorsítani a kvantum-számítástechnika folyamatát, tekintse meg a Code with Azure Quantum (Kód az Azure Quantum használatával) című témakört, amely az Azure Quantum webhelyének egyedülálló funkciója. Itt futtathat beépített mintákat vagy saját Q# programokat, új Q# kódot hozhat létre az üzeneteiből, megnyithatja és futtathatja a kódot a WEBES VS Code-banQ# egy kattintással, és kérdéseket tehet fel a Copilotnak a kvantum-számítástechnikával kapcsolatban.

Előfeltételek

A probléma meghatározása

A klasszikus számítógépek nem véletlenszerű számokat, hanem pszeudo-számokat állítanak elő. A pszeudorandom számgenerátor egy determinisztikus számsorozatot hoz létre valamilyen kezdeti érték, úgynevezett mag alapján. Hogy minél jobban megközelítsük a véletlenszerű értékeket, a kiinduló érték a leggyakrabban a CPU órájának aktuális ideje lesz.

A kvantumszámítógépek viszont valóban véletlenszerű számokat hozhatnak létre. Ennek az az oka, hogy a qubit szuperpozícióban való mérése valószínűségi folyamat. A mérés eredménye véletlenszerű, és nincs mód az eredmény előrejelzésére. Ez a kvantum véletlenszám-generátorok alapelve.

A qubit a kvantuminformációk egysége, amely szuperpozícióban lehet. Mérés esetén a qubit csak 0 vagy 1 állapotban lehet. A mérés előtt azonban a qubit állapota a 0 vagy az 1 méréssel való beolvasásának valószínűségét jelenti.

Először egy alapállapotú qubitet vesz fel, például nullát. A véletlenszerű számgenerátor első lépése egy Hadamard-művelettel egyenlő szuperpozícióba helyezni a qubitet. Ennek az állapotnak a mérése nullát vagy 50%-os valószínűségű eredményt ad az egyes eredményeknek, egy igazán véletlenszerű bitet.

Nem lehet tudni, hogy mit kap a qubit szuperpozícióban való mérése után, és az eredmény minden alkalommal más érték, amikor meghívja a kódot. De hogyan használhatja ezt a viselkedést nagyobb véletlenszerű számok létrehozására?

Tegyük fel, hogy négyszer ismétli meg a folyamatot, így az alábbi bináris számjegyet kapja:

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

Ha összefűzi vagy kombinálja ezeket a biteket egy bitsztringbe, akkor egy nagyobb számot kap. Ebben a példában a ${0110}$ bitsorozat decimális formában a 6-nak felel meg.

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

Ha ezt a folyamatot többször is megismételi, több bitet is kombinálhat, hogy bármilyen nagy számot alkotjon. Most megadhatja felettesének ezt a számot biztonságos jelszóként, mivel biztos lehet benne, hogy egyetlen űrbeli hacker sem tudja meghatározni a mérések sorozatának eredményeit.

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

Vázoljuk fel a véletlenszerű számgenerátor logikáját, feltéve, hogy van egy véletlenszerű bitgenerátorunk:

  1. Adja meg max a létrehozni kívánt maximális számot.
  2. Adja meg a létrehozandó véletlenszerű bitek számát. Ezt úgy tehetjük meg, ha kiszámítjuk, hány bitet (nBits) kell egész számokban kifejeznünk max értékig mint felső határig.
  3. Generáljunk egy nBits hosszúságú véletlenszerű bitsztringet.
  4. Ha a bitsztring a max értékénél nagyobb szám, lépjünk vissza a harmadik lépéshez.
  5. Ellenkező esetben a folyamat befejeződött. A létrehozott számot adjuk vissza egész számként.

Példaként állítsuk be a max értékét 12-re. Vagyis a 12 a legnagyobb szám, amelyet biztonságos jelszóként szeretne használni.

${\lfloor ln(12) / ln(2) + 1 \rfloor}$ vagy 4 bit szükséges a 0 és 12 közötti szám megjelenítéséhez. (A rövidség kedvéért most nem tárgyaljuk ezt az egyenletet.)

Tegyük fel, hogy létrehozza a ${1101_{\ binary}}$ bites sztringet, amely ezzel egyenlő: ${13_{\ decimal}}$. Mivel a 13 nagyobb mint 12, megismételjük a folyamatot.

Tegyük fel, hogy létrehozza a ${0110_{\ binary}}$ bites sztringet, amely ezzel egyenlő: ${6_{\ decimal}}$. 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 jelszóként. A gyakorlatban egy nagyobb számot állítson be maximális értékként, mert az alacsonyabb számok könnyen feltörhetőek az összes lehetséges jelszó kipróbálásával. Sőt, a jelszó kitalálásának vagy feltörésének nehézségének növelése érdekében ASCII-kóddal szöveggé alakíthatja a bináris fájlokat, és számokkal, szimbólumokkal és vegyes nagybetűkkel hozhat létre jelszót.

Véletlenszerű bitgenerátor írása

Az első lépés egy Q# véletlenszerű bitet generáló művelet írása. Ez a művelet a véletlenszerű számgenerátor egyik építőeleme lesz.

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

Most tekintse meg az új kódot.

  • Ön határozza meg a GenerateRandomBit műveletet, amely nem vesz fel bemenetet, és típusértéket Resultállít elő. A Result típus egy mérés eredményét jelöli, és két lehetséges értékkel rendelkezhet: Zero vagy One.
  • Egyetlen qubitet foglal le a use kulcsszóval. Amikor le lesz foglalva, a qubit mindig állapotban Zero van.
  • A művelettel H a qubitet egyenlő szuperpozícióba helyezheti.
  • A művelettel M megmérheti a qubitet, és visszaadhatja a mért értéket (Zero vagy One).
  • A művelettel Reset visszaállíthatja a qubitet a(z) |0〉 állapotba.

Ha a qubitet szuperpozícióba helyezi a H művelettel, és a művelettel M méri, az eredmény minden egyes híváskor más érték lesz.

A kód vizualizációja Q# a Bloch-gömbdel

A Bloch-gömbön az északi pólus a 0 klasszikus értéket jelöli, a déli pólus pedig az 1 klasszikus értéket. Minden szuperpozíció megadható a gömb egyik pontjaként (ezt a nyíl jelzi). Minél közelebb van a nyíl hegye a pólushoz, annál nagyobb a valószínűsége, hogy a qubit a mérésekor a pólushoz hozzárendelt klasszikus értékkel esik egybe. Az alábbi ábrán látható nyíl által képviselt qubitállapot például nagyobb valószínűséggel adja meg a 0 értéket, ha megméri.

Egy qubit állapotot ábrázoló diagram, amelynek nagy a valószínűsége, hogy nullát mér.

Ezzel az ábrázolással megjelenítheti, hogy mit csinál a kód:

  1. Először kezdje a 0 állapotban inicializált qubittel, és alkalmazzon egy műveletet egy H egyenlőségi szuperpozíció létrehozásához, amelyben a 0 és az 1 valószínűsége megegyezik.

    Egy diagram, amely egy qubit szuperpozícióban való előkészítését mutatja be a hadamard kapu alkalmazásával.
  2. Ezután mérje meg a qubitet, és mentse a kimenetet:

    Egy qubit mérését és a kimenet mentését bemutató diagram.

Mivel a mérés eredménye véletlenszerű, és a 0 és az 1 mérés valószínűsége megegyezik, teljesen véletlenszerű bitet kapott. Ezt a műveletet többször is meghívhatja egész számok létrehozásához. Ha például háromszor hívja meg a műveletet három véletlenszerű bit beszerzéséhez, létrehozhat véletlenszerű 3 bites számokat (azaz egy 0 és 7 közötti véletlenszerű számot).

Teljes véletlenszerű számgenerátor írása

  1. Először hozzá kell adnia a szükséges Q# névtereket a programhoz. A teljes véletlenszerű számgenerátorhoz három Q# névteret kell tartalmaznia: Microsoft.Quantum.Math, Microsoft.Quantum.Intrinsic, és Microsoft.Quantum.Convert.

    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Math;
    
  2. Ezután definiálja a GenerateRandomNumberInRange műveletet. Ez a művelet többször meghívja a GenerateRandomBit műveletet a bitek sztringjének létrehozásához.

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

    Most vizsgáljuk meg az új kódot.

    • Ki kell számítania a legfeljebb egész számok kifejezéséhez szükséges bitek maxszámát. A BitSizeI névtérből származó Microsoft.Quantum.Math függvény egész számot alakít át a reprezentáláshoz szükséges bitek számává.
    • A SampleRandomNumberInRange művelet egy for hurkot használ arra, hogy véletlenszerű számokat generáljon egészen addig, amíg az kisebb vagy egyenlő nem lesz a max értékével. A for hurok pontosan ugyanúgy működik, mint a for többi programozási nyelv hurokja.
    • A változó bits egy mutable változó. A módosítható változó olyan, amely változhat a számítás közben. Ennek a módosítható változónak a módosításához a set direktívát használjuk.
    • A ResultArrayAsInt függvény a Microsoft.Quantum.Convert névtérből származik. Ez a függvény átalakítja a bitsztringet pozitív egész számmá.
  3. Végül hozzáad egy belépési pontot. Ebben a példában a Main művelet a program belépési pontja. Meghívja a GenerateRandomNumberInRange műveletet, hogy véletlenszerű számot hozzon létre 0 és 100 között.

        @EntryPoint()
        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);
        }
    

    A let direktíva olyan változókat deklarál, amelyek nem változnak a számítás során. Itt a maximális értéket 100-ként definiáljuk.

  4. A véletlenszerű számgenerátor teljes kódja a következő:

namespace QuantumRandomNumberGenerator {
    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Math;

    @EntryPoint()
    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 
        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;
    }
}

A véletlenszerű számgenerátor program futtatása

A programot futtathatja a Copilotban az Azure Quantumban, a Visual Studio Code-ban pedig önálló Q# alkalmazásként vagy Python-gazdagépprogram használatával.

A Q# kódot ingyenesen tesztelheti a Copilottal az Azure Quantum-ban – mindössze egy Microsoft(MSA) e-mail-fiókra van szüksége. További információ az Azure Quantum Copilotjáról: Az Azure Quantum felfedezése.

  1. Nyissa meg a Copilot az Azure Quantum-ban a böngészőben.

  2. Másolja és illessze be a következő kódot a kódszerkesztőbe.

    namespace Tutorial {
        open Microsoft.Quantum.Convert;
        open Microsoft.Quantum.Intrinsic;
        open Microsoft.Quantum.Math;
    
        @EntryPoint()
        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. Jelölje ki a futtatandó felvételek számát, majd kattintson a Futtatás gombra.

  4. Az eredmények a hisztogramban és az Eredmények mezőkben jelennek meg.

  5. A Kód magyarázata gombra kattintva kérje meg a Copilototot, hogy magyarázza el Önnek a kódot.

Tipp

Az Azure Quantum-ban a Copilotban megnyithatja a programot a VS Code for the Web alkalmazásban a kódszerkesztő jobb sarkában található VS Code embléma gombra kattintva.

Megjegyzés

Ez a kódrészlet jelenleg nem fut egyetlen elérhető Azure Quantum-hardveren targetssem, mivel a hívhatóhoz ResultArrayAsIntteljes számítási profillal rendelkező QPU szükséges.

Következő lépések

Ismerkedjen meg más Q# oktatóanyagokkal:

  • A kvantum-összefonódás bemutatja, hogyan írhat olyan Q# programot, amely a qubiteket manipulálja és méri, és bemutatja a szuperpozíció és az összefonódás hatásait.
  • A Grover keresési algoritmusa bemutatja, hogyan írhat olyan Q# programot, amely a Grover keresési algoritmusát használja.
  • A Quantum Fourier Transforms bemutatja, hogyan írhat olyan Q# programot, amely közvetlenül kezeli az adott qubiteket.
  • A Quantum Katas öngyors oktatóanyagok és programozási gyakorlatok, amelyek célja a kvantum-számítástechnika és Q# a programozás elemeinek egyidejű tanítása.