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

Anteckning

Microsoft Quantum Development Kit (klassisk QDK) stöds inte längre efter den 30 juni 2024. Om du är en befintlig QDK-utvecklare rekommenderar vi att du övergår till den nya Azure Quantum Development Kit (modern QDK) för att fortsätta utveckla kvantlösningar. Mer information finns i Migrera din Q# kod till modern QDK.

Lär dig att skriva ett grundläggande kvantprogram i Q# som utnyttjar kvantmekanikens natur för att skapa ett slumpmässigt tal.

I de här självstudierna får du:

  • 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.

Tips

Om du vill påskynda din resa för kvantberäkning kan du läsa Kod med Azure Quantum, en unik funktion på Webbplatsen för Azure Quantum. 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 pseudoslumptal . En pseudorandomtalsgenerator genererar en deterministisk sekvens med tal baserat på ett initialt värde, som kallas för ett startvärde. 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. Det här är den grundläggande principen för slumpgeneratorer för kvanttal.

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

Du börjar med att ta en qubit 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 slumptal?

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 antal. Nu kan du ge din överordnade med det numret som ett säkert lösenord, eftersom du kan vara säker på att ingen rymdhacker kan fastställa resultatet av sekvensen av mätningar.

Definiera logiken för slumptalsgeneratorn

Nu ska vi beskriva logiken för en slumptalsgenerator, förutsatt att vi har en slumpmässig bitgenerator:

  1. Definiera max som det maximala antal som du vill generera.
  2. Definiera antalet slumpmässiga bitar som du behöver generera. Detta görs genom beräkning av hur många bitar, nBits, vi måste uttrycka heltal för 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. 12 är alltså det största antalet som du vill använda som säkert 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. (För att hålla det här kortfattat hoppar vi över hur man deriverar den här ekvationen.)

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.

Slumptalsgeneratorn för kvanttal 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 ditt lösenord kan du faktiskt använda ASCII-kod för att konvertera binär kod 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 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 Zero .
  • 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 kvantbit 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 slumptal mellan 0 och 7).

Skriva en fullständig slumptalsgenerator

  1. Först måste du lägga till de nödvändiga Q# namnrymderna i programmet. För den fullständiga slumptalsgeneratorn måste du inkludera tre Q# namnrymder: Microsoft.Quantum.Math, Microsoft.Quantum.Intrinsicoch Microsoft.Quantum.Convert.

    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Intrinsic;
    open 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 kommer från Microsoft.Quantum.Convert namnområdet. Den här funktionen konverterar bitsträngen till ett positivt heltal.
  3. Slutligen lägger du till en startpunkt. I det här exemplet är åtgärden Main startpunkten för programmet. Den anropar GenerateRandomNumberInRange åtgärden för att generera ett slumpmässigt tal mellan 0 och 100.

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

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

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

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

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.

    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. Välj antalet bilder som ska köras och klicka på Kör.

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

  5. Klicka på Förklara kod för att uppmana Copilot att förklara koden för dig.

Tips

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

Anteckning

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.

Nästa steg

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ökalgoritmen visar hur du skriver ett Q# program som använder Grover-sökalgoritmen.
  • 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 samtidigt.