Självstudie: Implementera en kvantgenerator för slumptal i Q#

I den här självstudien lär du dig att skriva ett grundläggande kvantprogram som Q# utnyttjar kvantmekanikens natur för att skapa ett slumpmässigt tal.

I den här självstudien kommer vi att:

  • Skapa ett Q# program.
  • Granska huvudkomponenterna i ett Q# program.
  • Definiera logiken för ett problem.
  • Kombinera klassiska åtgärder och kvantåtgärder för att lösa ett problem.
  • Arbeta med qubitar och superposition för att skapa en slumpgenerator för kvanttal.

Dricks

Om du vill påskynda din kvantberäkningsresa kan du kolla in Kod med Azure Quantum, en unik funktion på Azure Quantum-webbplatsen. Här kan du köra inbyggda Q# exempel eller egna Q# program, generera ny Q# kod från dina frågor, öppna och köra koden i VS Code för webben med ett klick och ställa frågor till Copilot om kvantberäkning.

Förutsättningar

Definiera problemet

Klassiska datorer producerar inte slumpmässiga tal, utan snarare pseudorandomnummer . En pseudorandomtalgenerator genererar en deterministisk sekvens med tal baserat på ett initialt värde, kallat seed. För att ge tal som är mer slumpmässiga utgörs seed oftast av den aktuella tiden från CPU-klockan.

Kvantdatorer kan å andra sidan generera verkligt slumpmässiga tal. Det beror på att mätningen av en kvantbit i superposition är en probabilistisk process. Resultatet av mätningen är slumpmässigt och det finns inget sätt att förutsäga resultatet. Detta är den grundläggande principen för kvant slumptalsgeneratorer.

En kvantbit är en enhet med kvantinformation som kan finnas i superposition. När den mäts kan en kvantbit bara vara i tillståndet 0 eller 1 . Före mätningen representerar kvantbitens tillstånd dock sannolikheten att läsa antingen 0 eller 1 med en mätning.

Du börjar med att ta en kvantbit i ett bastillstånd, till exempel noll. Det första steget i slumptalsgeneratorn är att använda en Hadamard-åtgärd för att placera kvantbiten i en lika stor superposition. Mätningen av det här tillståndet resulterar i en nolla eller en med 50 % sannolikhet för varje utfall, en verkligt slumpmässig bit.

Det finns inget sätt att veta vad du får efter mätningen av kvantbiten i superposition, och resultatet är ett annat värde varje gång koden anropas. Men hur kan du använda det här beteendet för att generera större slumpmässiga tal?

Anta att du upprepar processen fyra gånger och genererar den här sekvensen med binära siffror:

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

Om du sammanfogar, eller kombinerar, dessa bitar till en bitsträng kan du skapa ett större tal. I det här exemplet motsvarar bitsekvensen ${0110}$ talet sex i decimalsystemet.

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

Om du upprepar den här processen många gånger kan du kombinera flera bitar för att bilda ett stort tal. Med den här metoden kan du skapa ett tal som ska användas som ett säkert lösenord, eftersom du kan vara säker på att ingen hackare kan fastställa resultatet av måttsekvensen.

Definiera logiken för slumptalsgeneratorn

Nu ska vi beskriva logiken för en slumptalsgenerator:

  1. Definiera max som det högsta antal som du vill generera.
  2. Definiera antalet slumpmässiga bitar som du behöver generera. Detta görs genom att beräkna hur många bitar, nBits, du behöver uttrycka heltal upp till max.
  3. Generera en slumpmässig bitsträng som har längden nBits.
  4. Om bitsträngen representerar ett tal som är större än max går du tillbaka till steg tre.
  5. I annat fall är processen slutförd. Returnera det genererade talet som ett heltal.

Som exempel anger vi max till 12. Det vill: 12 är det största talet som du vill använda som lösenord.

Du behöver ${\lfloor ln(12) / ln(2) + 1 \rfloor}$, eller 4 bitar för att representera ett tal mellan 0 och 12. Vi kan använda den inbyggda funktionen BitSizeI, som tar alla heltal och returnerar det antal bitar som krävs för att representera den.

Anta att du genererar bitsträngen ${1101_{\ binary}}$, som motsvarar ${13_{\ decimal}}$. Eftersom 13 är större än 12 upprepar du processen.

Sedan generar du bitsträngen ${0110_{\ binary}}$, som motsvarar ${6_{\ decimal}}$. Eftersom 6 är mindre än 12 är processen slutförd.

Kvantgeneratorn för slumptal returnerar nummer 6 som lösenord. I praktiken anger du ett större tal som högsta eftersom lägre tal är lätta att knäcka genom att bara prova alla möjliga lösenord. För att öka svårigheten att gissa eller knäcka lösenordet kan du använda ASCII-kod för att konvertera binär till text och generera ett lösenord med hjälp av siffror, symboler och gemener.

Skriva en slumpmässig bitgenerator

Det första steget är att skriva en Q# åtgärd som genererar en slumpmässig bit. Den här åtgärden är en av byggstenarna i slumptalsgeneratorn.

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

Ta nu en titt på ny kod.

  • Du definierar åtgärden GenerateRandomBit , som inte tar några indata och genererar ett värde av typen Result. Typen Result representerar resultatet av en mätning och kan ha två möjliga värden: Zero eller One.
  • Du allokerar en enda qubit med nyckelordet use . När den allokeras är en qubit alltid i tillståndet |0〉.
  • Du använder åtgärden H för att placera kvantbiten i en lika stor superposition.
  • Du använder åtgärden M för att mäta kvantbiten, returnera det uppmätta värdet (Zero eller One).
  • Du använder åtgärden Reset för att återställa kvantbiten till tillståndet |0〉.

Genom att placera kvantbiten i superposition med H åtgärden och mäta den med M åtgärden blir resultatet ett annat värde varje gång koden anropas.

Visualisera Q# koden med Bloch-sfären

I Bloch-sfären representerar nordpolen det klassiska värdet 0 och sydpolen det klassiska värdet 1. Alla superpositioner kan representeras av en punkt på sfären (visas med en pil). Ju närmare pilen är en pol, desto högre är sannolikheten att kvantbiten minimeras till det klassiska värde som tilldelades till polen när den mättes. Till exempel har kvantbitstillståndet som representeras av pilen i följande bild en högre sannolikhet att ge värdet 0 om du mäter det.

Ett diagram som visar ett qubittillstånd med hög sannolikhet att mäta noll.

Du kan använda den här representationen för att visualisera vad koden gör:

  1. Börja först med en qubit som initierats i tillståndet |0〉 och tillämpa en H åtgärd för att skapa en lika stor superposition där sannolikheterna för 0 och 1 är desamma.

    Ett diagram som visar förberedelsen av en qubit i superposition genom att tillämpa hadamardporten.
  2. Mät sedan kvantbiten och spara utdata:

    Ett diagram som visar mätningen av en kvantbit och sparar utdata.

Eftersom resultatet av mätningen är slumpmässigt och sannolikheten för att mäta 0 och 1 är densamma har du fått en helt slumpmässig bit. Du kan anropa den här åtgärden flera gånger för att skapa heltal. Om du till exempel anropar åtgärden tre gånger för att hämta tre slumpmässiga bitar kan du skapa slumpmässiga 3-bitars tal (det vill säga ett slumpmässigt tal mellan 0 och 7).

Skriva en fullständig slumptalsgenerator

  1. Först måste du importera de nödvändiga namnrymderna från Q# standardbiblioteket till programmet. Kompilatorn Q# läser in många vanliga funktioner och åtgärder automatiskt, men för den fullständiga slumptalsgeneratorn behöver du ytterligare funktioner och åtgärder från två Q# namnområden: Microsoft.Quantum.Mathoch Microsoft.Quantum.Convert.

    import Microsoft.Quantum.Convert.*;
    import Microsoft.Quantum.Math.*;
    
  2. Därefter definierar du åtgärden GenerateRandomNumberInRange . Den här åtgärden anropar åtgärden GenerateRandomBit upprepade gånger för att bygga en sträng med bitar.

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

    Vi tar och går igenom den nya koden.

    • Du måste beräkna antalet bitar som behövs för att uttrycka heltal upp till max. Funktionen BitSizeI från Microsoft.Quantum.Math namnområdet konverterar ett heltal till det antal bitar som behövs för att representera det.
    • Åtgärden SampleRandomNumberInRange använder en for-loop för att generera slumpmässiga tal tills den genererar ett som är lika med eller mindre än max. Loopen for fungerar exakt på samma sätt som en for loop i andra programmeringsspråk.
    • Variabeln bits är en föränderlig variabel. Föränderliga variabler kan ändras under beräkningen. Du kan använda direktivet set för att ändra värdet för en föränderlig variabel.
    • Funktionen ResultArrayAsInt , från standardnamnområdet Microsoft.Quantum.Convert , konverterar bitsträngen till ett positivt heltal.
  3. Slutligen lägger du till en startpunkt i programmet. Som standard Q# letar kompilatorn efter en Main åtgärd och börjar bearbeta där. Den anropar GenerateRandomNumberInRange åtgärden för att generera ett slumpmässigt tal mellan 0 och 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);
    }
    

    Direktivet let deklarerar variabler som inte ändras under beräkningen. Här definierar du det maximala värdet som 100.

    Mer information om åtgärden finns i Main Startpunkter.

  4. Den fullständiga koden för slumptalsgeneratorn är följande:

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

Kör slumptalsgeneratorprogrammet

Du kan köra programmet i Copilot i Azure Quantum och i Visual Studio Code som ett fristående Q# program eller med hjälp av ett Python-värdprogram.

Du kan testa din Q# kod med Copilot i Azure Quantum kostnadsfritt – allt du behöver är ett Microsoft-e-postkonto (MSA). Mer information om Copilot i Azure Quantum finns i Utforska Azure Quantum.

  1. Öppna Copilot i Azure Quantum i webbläsaren.

  2. Kopiera och klistra in följande kod i kodredigeraren.

    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. Välj antalet skott som ska köras och välj Kör.

  4. Resultaten visas i histogrammet och i fälten Resultat .

  5. Välj Förklara kod för att uppmana Copilot att förklara koden för dig.

Dricks

Från Copilot i Azure Quantum kan du öppna programmet i VS Code for the Web genom att välja VS Code-logotypknappen i det högra hörnet i kodredigeraren.

Kommentar

Det här kodfragmentet körs för närvarande inte på någon tillgänglig Azure Quantum-maskinvara targetseftersom anropsbar ResultArrayAsInt kräver en QPU med fullständig beräkningsprofil.

Utforska andra Q# självstudier:

  • Kvantsammanflätning visar hur du skriver ett Q# program som manipulerar och mäter kvantbitar och visar effekterna av superposition och sammanflätning.
  • Grover sökalgoritm visar hur du skriver ett Q# program som använder Grover sökalgoritm.
  • Quantum Fourier Transforms utforskar hur du skriver ett Q# program som direkt adresserar specifika kvantbitar.
  • Quantum Katas är självstudier och programmeringsövningar som syftar till att lära ut elementen i kvantberäkning och Q# programmering på samma gång.