Zelfstudie: Een kwantumgenerator voor willekeurige getallen implementeren in Q#

Notitie

Quantum Development Kit Microsoft (klassieke QDK) wordt na 30 juni 2024 niet meer ondersteund. Als u een bestaande QDK-ontwikkelaar bent, raden we u aan over te stappen op de nieuwe Azure Quantum Development Kit (Moderne QDK) om door te gaan met het ontwikkelen van kwantumoplossingen. Zie Uw Q# code migreren naar de moderne QDK voor meer informatie.

Leer hoe u een eenvoudig kwantumprogramma schrijft dat Q# gebruikmaakt van de aard van kwantummechanica om een willekeurig getal te produceren.

In deze zelfstudie leert u het volgende:

  • Q# Een programma maken.
  • Bekijk de belangrijkste onderdelen van een Q# programma.
  • Definieer de logica van een probleem.
  • Combineer klassieke en kwantumbewerkingen om een probleem op te lossen.
  • Werken met qubits en superpositie om een kwantumgenerator van willekeurige getallen te maken.

Tip

Als u uw kwantumcomputingtraject wilt versnellen, raadpleegt u Code met Azure Quantum, een unieke functie van de Azure Quantum-website. Hier kunt u ingebouwde Q# voorbeelden of uw eigen Q# programma's uitvoeren, nieuwe Q# code genereren op basis van uw prompts, uw code openen en uitvoeren in VS Code voor het web met één klik en Copilot vragen stellen over kwantumcomputing.

Vereisten

Het probleem definiëren

Klassieke computers produceren geen willekeurige getallen, maar pseudorandom-getallen . Een pseudorandom-getalgenerator genereert een deterministische reeks getallen op basis van een beginwaarde, een seed genoemd. Voor een betere benadering van willekeurige waarden is deze seed vaak de huidige tijd van de CPU-klok.

Kwantumcomputers kunnen daarentegen echt willekeurige getallen genereren. Dit komt doordat het meten van een qubit in superpositie een probabilistisch proces is. Het resultaat van de meting is willekeurig en er is geen manier om het resultaat te voorspellen. Dit is het basisprincipe van kwantumgeneratoren voor willekeurige getallen.

Een qubit is een eenheid kwantuminformatie die zich in superpositie kan bevindt. Wanneer de meting wordt uitgevoerd, kan een qubit alleen de status 0 of 1 hebben. Vóór de meting vertegenwoordigt de toestand van de qubit echter de waarschijnlijkheid van het lezen van een 0 of een 1 met een meting.

U begint met het nemen van een qubit in een basisstatus, bijvoorbeeld nul. De eerste stap van de generator voor willekeurige getallen is het gebruik van een Hadamard-bewerking om de qubit in een gelijke superpositie te plaatsen. De meting van deze status resulteert in een nul of één met een kans van 50% van elk resultaat, een echt willekeurige bit.

Er is geen manier om te weten wat u krijgt na het meten van de qubit in superpositie, en het resultaat is een andere waarde telkens wanneer de code wordt aangeroepen. Maar hoe kunt u dit gedrag gebruiken om grotere willekeurige getallen te genereren?

Stel dat u het proces vier keer herhaalt, waarna deze reeks binaire cijfers wordt gegenereerd:

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

Als u deze bits samenvoegt of combineert in een bit-tekenreeks, kunt u een groter getal vormen. In dit voorbeeld is de bitreeks ${0110}$ gelijk aan zes in decimalen.

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

Als u dit proces vaak herhaalt, kunt u meerdere bits combineren om een groot getal te vormen. Nu kunt u uw meerdere met dat nummer als een veilig wachtwoord opgeven, omdat u er zeker van kunt zijn dat geen enkele hacker de resultaten van de volgorde van metingen kan bepalen.

De logica definiëren voor de generator voor willekeurige getallen

Laten we eens zien wat de logica van een generator voor willekeurige getallen moet zijn, op voorwaarde dat we een generator voor willekeurige bits hebben:

  1. Definieer max als het maximumaantal dat u wilt genereren.
  2. Definieer het aantal willekeurige bits dat u moet genereren. Dit wordt gedaan door het aantal bits te berekenen, nBits, dat we nodig hebben om gehele getallen uit te drukken tot max.
  3. Genereer een tekenreeks voor willekeurige bits die nBits in lengte is.
  4. Als de bit-tekenreeks een getal vormt dat groter is dan max, gaat u terug naar stap 3.
  5. Is dat niet het geval, dan is het proces voltooid. Retourneer het gegenereerde getal als een geheel getal.

Laten we bijvoorbeeld max instellen op 12. Dat wil gezegd dat 12 het grootste getal is dat u wilt gebruiken als een veilig wachtwoord.

U hebt ${\lfloor ln(12) / ln(2) + 1 \rfloor}$ of 4 bits nodig om een getal tussen 0 en 12 aan te geven. (Gemakshalve slaan we over hoe deze vergelijking wordt afgeleid.)

Stel dat u de bit-tekenreeks ${1101_{\ binary}}$ wilt genereren, wat gelijk is aan ${13_{\ decimal}}$. Omdat 13 groter is dan 12, herhaalt u het proces.

Vervolgens genereert u de bit-tekenreeks ${0110_{\ binary}}$, die gelijk is aan ${6_{\ decimal}}$. Omdat 6 kleiner is dan 12, is het proces voltooid.

De kwantumgenerator voor willekeurige getallen retourneert nummer 6 als uw wachtwoord. In de praktijk kunt u een groter getal instellen als maximum, omdat lagere getallen gemakkelijk te kraken zijn door gewoon alle mogelijke wachtwoorden te proberen. Om het lastiger te maken om uw wachtwoord te raden of te kraken, kunt u ASCII-code gebruiken om binair naar tekst te converteren en een wachtwoord te genereren met behulp van cijfers, symbolen en letters in meerdere letters.

Een generator voor willekeurige bits schrijven

De eerste stap is het schrijven van een Q# bewerking waarmee een willekeurige bit wordt gegenereerd. Deze bewerking is een van de bouwstenen van de generator voor willekeurige getallen.

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

Bekijk nu de nieuwe code.

  • U definieert de GenerateRandomBit bewerking, die geen invoer nodig heeft en een waarde van het type Resultproduceert. Het Result type vertegenwoordigt het resultaat van een meting en kan twee mogelijke waarden hebben: Zero of One.
  • U wijst één qubit toe met het use trefwoord. Wanneer deze wordt toegewezen, bevindt een qubit zich altijd in de Zero status.
  • U gebruikt de H bewerking om de qubit in een gelijke superpositie te plaatsen.
  • U gebruikt de M bewerking om de qubit te meten en de gemeten waarde (Zero of One) als resultaat te geven.
  • U gebruikt de Reset bewerking om de qubit opnieuw in te stellen op de status |0〉.

Door de qubit in superpositie te plaatsen bij de H bewerking en deze te meten met de M bewerking, is het resultaat elke keer dat de code wordt aangeroepen een andere waarde.

Visualiseer de Q# code met de Bloch-bol

In de Blochbol vertegenwoordigt de noordpool de klassieke waarde 0 en de zuidpool de klassieke waarde 1. Elke superpositie kan worden weergegeven met een punt op de bol (aangeduid met een pijl). Hoe dichter het einde van de pijl bij een pool is, hoe groter de kans is dat de qubit bij meting uiteenvalt in de klassieke waarde die aan die pool is toegewezen. De qubitstatus die wordt vertegenwoordigd door de pijl in de volgende afbeelding, heeft bijvoorbeeld een hogere kans om de waarde 0 te geven als u deze meet.

Een diagram met een qubitstatus met een hoge waarschijnlijkheid dat nul wordt gemeten.

U kunt deze weergave gebruiken om te visualiseren wat de code doet:

  1. Begin eerst met een qubit die is geïnitialiseerd in de status 0 en pas een H bewerking toe om een gelijke superpositie te maken waarin de waarschijnlijkheden voor 0 en 1 hetzelfde zijn.

    Een diagram van de voorbereiding van een qubit in superpositie door de hadamard-poort toe te passen.
  2. Meet vervolgens de qubit en sla de uitvoer op:

    Een diagram met de meting van een qubit en het opslaan van de uitvoer.

Omdat het resultaat van de meting willekeurig is en de waarschijnlijkheid van het meten van 0 en 1 hetzelfde is, hebt u een volledig willekeurige bit verkregen. U kunt deze bewerking meerdere keren aanroepen om gehele getallen te maken. Als u de bewerking bijvoorbeeld drie keer aanroept om drie willekeurige bits te verkrijgen, kunt u willekeurige 3-bits getallen maken (dat wil gezegd, een willekeurig getal tussen 0 en 7).

Een volledige generator voor willekeurige getallen schrijven

  1. Eerst moet u de vereiste Q# naamruimten toevoegen aan het programma. Voor de volledige generator voor willekeurige getallen moet u drie Q# naamruimten opnemen: Microsoft.Quantum.Math, Microsoft.Quantum.Intrinsicen Microsoft.Quantum.Convert.

    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Math;
    
  2. Vervolgens definieert u de GenerateRandomNumberInRange bewerking. Met deze bewerking wordt herhaaldelijk de bewerking GenerateRandomBit aangeroepen om een bit-tekenreeks te maken.

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

    Laten we nog even de nieuwe code controleren.

    • U moet het aantal bits berekenen dat nodig is om gehele getallen uit te drukken tot max. De BitSizeI functie uit de Microsoft.Quantum.Math naamruimte converteert een geheel getal naar het aantal bits dat nodig is om dit weer te geven.
    • De bewerking SampleRandomNumberInRange maakt gebruik van een for-lus om willekeurige getallen te genereren totdat er één wordt gegenereerd die gelijk is aan of kleiner is dan max. De for lus werkt precies hetzelfde als een for lus in andere programmeertalen.
    • De variabele bits is een veranderlijke variabele. Een veranderlijke variabele kan tijdens de berekening worden gewijzigd. U kunt met de set-instructie de waarde van een veranderlijke variabele wijzigen.
    • De ResultArrayAsInt functie is afkomstig uit de Microsoft.Quantum.Convert naamruimte. Met deze functie wordt de bit-tekenreeks geconverteerd naar een positief geheel getal.
  3. Ten slotte voegt u een toegangspunt toe. In dit voorbeeld is de Main bewerking het toegangspunt van het programma. De bewerking wordt aangeroepen GenerateRandomNumberInRange om een willekeurig getal tussen 0 en 100 te genereren.

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

    De let-instructie declareert variabelen die niet worden gewijzigd tijdens de berekening. Hier definiëren we de maximumwaarde als 100.

  4. De volledige code voor de generator voor willekeurige getallen is als volgt:

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

Het generatorprogramma voor willekeurige getallen uitvoeren

U kunt het programma uitvoeren in Copilot in Azure Quantum en in Visual Studio Code als zelfstandige Q# toepassing of met behulp van een Python-hostprogramma.

U kunt uw Q# code gratis testen met de Copilot in Azure Quantum. U hebt alleen een E-mailaccount van Microsoft (MSA) nodig. Zie Azure Quantum verkennen voor meer informatie over de Copilot in Azure Quantum.

  1. Open de Copilot in Azure Quantum in uw browser.

  2. Kopieer en plak de volgende code in de code-editor.

    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. Selecteer het aantal opnamen dat u wilt uitvoeren en klik op Uitvoeren.

  4. De resultaten worden weergegeven in het histogram en in de velden Resultaten .

  5. Klik op Code uitleggen om Copilot te vragen de code aan u uit te leggen.

Tip

Vanuit Copilot in Azure Quantum kunt u uw programma openen in vs code voor het web door te klikken op de knop VS Code-logo in de rechterhoek van de code-editor.

Notitie

Dit codefragment wordt momenteel niet uitgevoerd op beschikbare Azure Quantum-hardware targets, omdat voor het aanroepen een ResultArrayAsInt QPU met een volledig rekenprofiel is vereist.

Volgende stappen

Q# Andere zelfstudies verkennen:

  • Kwantumverstrengeling laat zien hoe u een Q# programma schrijft dat qubits manipuleert en meet en de effecten van superpositie en verstrengeling demonstreert.
  • Het zoekalgoritmen van Grover laten zien hoe u een Q# programma schrijft dat gebruikmaakt van het zoekalgoritmen van Grover.
  • Quantum Fourier Transforms verkent hoe u een Q# programma schrijft dat rechtstreeks betrekking heeft op specifieke qubits.
  • De Quantum Katas zijn zelfstudies in eigen tempo en programmeeroefeningen die gericht zijn op het tegelijkertijd aanleren van de elementen van kwantumcomputing en Q# programmeren.