Självstudie: Utforska kvantsammanflätning med Q#

I den här självstudien skriver du ett Q# program som manipulerar och mäter kvantbitar och visar effekterna av superposition och sammanflätning. Du förbereder två kvantbitar i ett specifikt kvanttillstånd, lär dig hur du arbetar på kvantbitar med Q# för att ändra deras tillstånd och demonstrera effekterna av superposition och sammanflätning. Du skapar programmet Q# bit för bit för att introducera qubittillstånd, åtgärder och mått.

Här följer några viktiga begrepp att förstå innan du börjar:

  • Om klassiska bitar innehåller ett enda binärt värde, till exempel 0 eller 1, kan tillståndet för en kvantbit vara i en superposition av två kvanttillstånd, 0 och 1. Varje möjligt kvanttillstånd har en associerad sannolikhetsamplitude.
  • Mätningen av en kvantbit ger ett binärt resultat med viss sannolikhet och ändrar tillståndet för kvantbiten ur superposition.
  • Flera kvantbitar kan vara sammanflätade så att de inte kan beskrivas oberoende av varandra. Det vill säga, vad som än händer med en qubit i ett sammanflätat par händer också med den andra qubiten.

I den här självstudien får du lära dig att:

  • Skapa Q# åtgärder för att initiera en kvantbit till ett önskat tillstånd.
  • Placera en qubit i superposition.
  • Sammanfläta ett par kvantbitar.
  • Mät en qubit och observera resultatet.

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

Om du vill köra kodexemplet i Copilot för Azure Quantum behöver du:

  • Ett Microsoft-e-postkonto (MSA).

Mer information om Copilot finns i Utforska Azure Quantum.

Initiera en qubit till ett känt tillstånd

Det första steget är att definiera en Q# åtgärd som initierar en qubit till ett känt tillstånd. Den här åtgärden kan anropas för att ange en kvantbit till ett klassiskt tillstånd, vilket innebär att den, när den mäts, antingen returnerar Zero 100 % av tiden eller returnerar One 100 % av tiden. Mätning av en kvantbit returnerar en Q# typ Result, som bara kan ha värdet Zero eller One.

Öppna Copilot för Azure Quantum och kopiera följande kod till kodredigerarens fönster. Klicka inte på Kör än. Du kör koden senare i självstudien.

import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;

operation SetQubitState(desired : Result, target : Qubit) : Unit {
    if desired != M(target) {
        X(target);
    }
}

Kodexemplet introducerar två standardåtgärder och M X, som omvandlar tillståndet för en qubit.

Åtgärden SetQubitState :

  1. Tar två parametrar: en typ Result, med namnet desired, som representerar det önskade tillståndet för kvantbiten att vara i (Zero eller One) och en typ Qubit.
  2. Utför en mätningsåtgärd, M, som mäter tillståndet för qubiten (Zero eller One) och jämför resultatet med det värde som anges i desired.
  3. Om mätningen inte matchar det jämförda värdet körs en X åtgärd som vänder kvantbitens tillstånd till där sannolikheten för att en mätning returneras Zero och One återförs. På så sätt SetQubitState placeras alltid målkvabiten i önskat tillstånd.

Skriva en teståtgärd för att testa klocktillståndet

För att visa effekten av åtgärden SetQubitState skapar du sedan en annan åtgärd med namnet Main. Den här åtgärden allokerar två kvantbitar, anropar SetQubitState för att ange den första kvantbiten till ett känt tillstånd och mäter sedan kvantbitarna för att se resultatet.

Kopiera följande kod till kodredigerarens fönster under åtgärden SetQubitState .

operation Main() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = One;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
    

    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}

I koden anges variablerna count och initial till 1000 respektive One . Detta initierar den första qubiten till One och mäter varje qubit 1000 gånger.

Åtgärden Main:

  1. Anger variabler för räknaren och det inledande qubittillståndet.
  2. Anropar -instruktionen use för att initiera två kvantbitar.
  3. Loopar för count iterationer. För varje loop är det
    1. Anropar SetQubitState för att ange ett angivet initial värde för den första kvantbiten.
    2. Anropar SetQubitState igen för att ange den andra qubiten till ett Zero tillstånd.
    3. Använder åtgärden M för att mäta varje kvantbit.
    4. Lagrar antalet mått för varje kvantbit som returnerar One.
  4. När loopen har slutförts anropas SetQubitState den igen för att återställa kvantbitarna till ett känt tillstånd (Zero) så att andra kan allokera kvantbitarna i ett känt tillstånd. Återställning krävs av -instruktionen use .
  5. Slutligen använder den Message funktionen för att skriva ut resultat till Copilot-utdatafönstren innan resultatet returneras.

Kör koden i Copilot för Azure Quantum

Innan du går vidare till procedurerna för superposition och sammanflätning kan du testa koden fram till den här punkten för att se initieringen och mätningen av kvantbitarna.

För att kunna köra koden som ett fristående program Q# måste kompilatorn i Copilot veta var programmet ska startas. Eftersom inget namnområde har angetts identifierar kompilatorn standardinmatningspunkten som åtgärden Main . Mer information finns i Projekt och implicita namnområden.

Ditt Q# program hittills bör nu se ut så här:

import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;

operation SetQubitState(desired : Result, target : Qubit) : Unit {
    if desired != M(target) {
        X(target);
    }
}

operation Main() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = One;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
        
    
    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

}

Kopiera och klistra in det fullständiga kodexemplet i kodfönstret Copilot för Azure Quantum , ange bilden för antalet bilder till "1" och klicka på Kör. Resultaten visas i histogrammet och i fälten Resultat .

Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 1000
Q2 - Ones: 0

Eftersom kvantbitarna inte har manipulerats ännu har de behållit sina inledande värden: den första qubiten returnerar One varje gång och den andra qubiten returnerar Zero.

Om du ändrar värdet initial för till Zero och kör programmet igen bör du observera att den första kvantbiten också returneras Zero varje gång.

Q1 - Zeros: 1000
Q1 - Ones: 0
Q2 - Zeros: 1000
Q2 - Ones: 0

Dricks

Välj Ctrl-Z eller Redigera > Ångra och spara filen när du introducerar en teständring av koden innan du kör den igen.

Placera en qubit i superposition

För närvarande är kvantbitarna i programmet i ett klassiskt tillstånd, det vill säga de är antingen 1 eller 0. Du vet detta eftersom programmet initierar kvantbitarna till ett känt tillstånd och du inte har lagt till några processer för att manipulera dem. Innan du sammanflätar kvantbitarna placerar du den första kvantbiten i ett superpositionstillstånd, där ett mått på kvantbiten returnerar Zero ~50 % av tiden och One ~50 % av tiden. Konceptuellt kan kvantbiten anses ha samma sannolikhet att mäta antingen Zero eller One.

Om du vill placera en qubit i superposition Q# tillhandahåller Håtgärden , eller Hadamard. X Återkalla åtgärden från initialisera en qubit till en känd tillståndsprocedur tidigare, som vände en qubit från 0 till 1 (eller vice versa); åtgärden vänder kvantbiten H halvvägs till ett tillstånd med lika sannolikheter för Zero eller One. När den mäts bör en kvantbit i superposition returnera ungefär lika många Zero och One resultat.

Ändra koden i Main åtgärden genom att återställa det ursprungliga värdet till One och infoga en rad för H åtgärden:

for test in 1..count {
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        H(q1);                // Add the H operation after initialization and before measurement

        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2); 
        ...

Nu när du kör programmet kan du se resultatet av den första kvantbiten i superposition.

Q1 - Zeros: 523            // results vary
Q1 - Ones: 477
Q2 - Zeros: 1000
Q2 - Ones: 0

Varje gång du kör programmet varierar resultatet för den första kvantbiten något, men kommer att vara nära 50 % One och 50 % Zero, medan resultatet för den andra kvantbiten förblir Zero hela tiden.

Q1 - Zeros: 510           
Q1 - Ones: 490
Q2 - Zeros: 1000
Q2 - Ones: 0

När du initierar den första kvantbiten så Zero returneras liknande resultat.

Q1 - Zeros: 504           
Q1 - Ones: 496
Q2 - Zeros: 1000
Q2 - Ones: 0

Kommentar

Genom att flytta skjutreglaget i Copilot för Azure Quantum och öka antalet skott kan du se hur superpositionsresultaten varierar något jämfört med fördelningen av skotten.

Sammanfläta två kvantbitar

Som tidigare nämnts är sammanflätade kvantbitar anslutna så att de inte kan beskrivas oberoende av varandra. Det vill säga, vilken åtgärd som än händer med en qubit, händer också med den sammanflätade qubiten. På så sätt kan du känna till det resulterande tillståndet för en qubit utan att mäta den, bara genom att mäta tillståndet för den andra kvantbiten. (I det här exemplet används två kvantbitar, men det är också möjligt att sammanfläta tre eller fler kvantbitar).

För att aktivera sammanflätning Q# tillhandahåller åtgärden CNOT , som står för Controlled-NOT. Resultatet av att köra den här åtgärden på två kvantbitar är att vända den andra qubiten om den första qubiten är One.

Lägg till åtgärden i CNOT programmet direkt efter åtgärden H . Ditt fullständiga program bör se ut så här:

import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;

    operation SetQubitState(desired : Result, target : Qubit) : Unit {
        if desired != M(target) {
            X(target);
        }
    }

operation Main() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = Zero;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
    
        H(q1);            
        CNOT(q1, q2);      // Add the CNOT operation after the H operation

        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
    

    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

    }

Nu när du kör programmet bör du se något i stil med:

Q1 - Zeros: 502           // results will vary
Q1 - Ones: 498
Q2 - Zeros: 502
Q2 - Ones: 498

Observera att statistiken för den första kvantbiten inte har ändrats (det finns fortfarande en risk på ~50/50 för en Zero eller en One efter mätning), men mätresultatet för den andra kvantbiten är alltid detsamma som mätningen av den första kvantbiten, oavsett hur många gånger du kör programmet. Åtgärden CNOT har sammanflätat de två kvantbitarna, så att vad som än händer med den ena av dem, händer med den andra.

Förutsättningar

Så här utvecklar och kör du kodexemplet i din lokala utvecklingsmiljö:

Skapa en ny Q# fil

  1. Öppna Visual Studio Code och välj Fil > Ny textfil för att skapa en ny fil.
  2. Spara filen som CreateBellStates.qs. Den här filen innehåller Q# koden för ditt program.

Initiera en qubit till ett känt tillstånd

Det första steget är att definiera en Q# åtgärd som initierar en qubit till ett känt tillstånd. Den här åtgärden kan anropas för att ange en kvantbit till ett klassiskt tillstånd, vilket innebär att den antingen returnerar Zero 100 % av tiden eller returnerar One 100 % av tiden. Zero och One är Q# värden som representerar de enda två möjliga resultaten av en mätning av en kvantbit.

Öppna CreateBellStates.qs och kopiera följande kod:

import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;

operation SetQubitState(desired : Result, target : Qubit) : Unit {
    if desired != M(target) {
        X(target);
    }
}

Kodexemplet introducerar två standardåtgärder och M X, som omvandlar tillståndet för en qubit.

Åtgärden SetQubitState :

  1. Tar två parametrar: en typ Result, med namnet desired, som representerar det önskade tillståndet för kvantbiten att vara i (Zero eller One) och en typ Qubit.
  2. Utför en mätningsåtgärd, M, som mäter tillståndet för qubiten (Zero eller One) och jämför resultatet med det värde som anges i desired.
  3. Om mätningen inte matchar det jämförda värdet körs en X åtgärd som vänder kvantbitens tillstånd till där sannolikheten för att en mätning returneras Zero och One återförs. På så sätt SetQubitState placeras alltid målkvabiten i önskat tillstånd.

Skriva en teståtgärd för att testa klocktillståndet

För att visa effekten av åtgärden SetQubitState skapar du sedan en annan åtgärd med namnet Main. Den här åtgärden allokerar två kvantbitar, anropar SetQubitState för att ange den första kvantbiten till ett känt tillstånd och mäter sedan kvantbitarna för att se resultatet.

Lägg till följande åtgärd i CreateBellStates.qs filen efter åtgärden SetQubitState :

operation Main() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = One;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
    

    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}

I koden anges variablerna count och initial till 1000 respektive One . Det här steget initierar den första qubiten till One och mäter varje qubit 1000 gånger.

Åtgärden Main:

  1. Tar två parametrar: count, antalet gånger som en mätning ska köras och initial, det önskade tillståndet för att initiera kvantbiten.
  2. Anropar -instruktionen use för att initiera två kvantbitar.
  3. Loopar för count iterationer. För varje loop är det
    1. Anropar SetQubitState för att ange ett angivet initial värde för den första kvantbiten.
    2. Anropar SetQubitState igen för att ange den andra qubiten till ett Zero tillstånd.
    3. Använder åtgärden M för att mäta varje kvantbit.
    4. Lagrar antalet mått för varje kvantbit som returnerar One.
  4. När loopen har slutförts anropas SetQubitState den igen för att återställa kvantbitarna till ett känt tillstånd (Zero) så att andra kan allokera kvantbitarna i ett känt tillstånd. Återställning av kvantbiten krävs av -instruktionen use .
  5. Slutligen använder den Message funktionen för att skriva ut ett meddelande till konsolen innan resultatet returneras.

Kör koden

Innan du går vidare till procedurerna för superposition och sammanflätning testar du koden fram till den här punkten för att se initieringen och mätningen av kvantbitarna.

För att kunna köra koden som ett fristående program Q# måste kompilatorn veta var programmet ska startas. Eftersom inget namnområde har angetts identifierar kompilatorn standardinmatningspunkten som åtgärden Main . Mer information finns i Projekt och implicita namnområden.

  1. Din CreateBellStates.qs fil hittills bör nu se ut så här:

    import Microsoft.Quantum.Intrinsic.*;
    import Microsoft.Quantum.Canon.*;
    
    operation SetQubitState(desired : Result, target : Qubit) : Unit {
        if desired != M(target) {
            X(target);
        }
    }
    
    operation Main() : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;
        let count = 1000;
        let initial = One;
    
        // allocate the qubits
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
    
            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2);           
    
            // Count the number of 'Ones' returned:
            if resultQ1 == One {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
    
    
        // Display the times that |0> is returned, and times that |1> is returned
        Message($"Q1 - Zeros: {count - numOnesQ1}");
        Message($"Q1 - Ones: {numOnesQ1}");
        Message($"Q2 - Zeros: {count - numOnesQ2}");
        Message($"Q2 - Ones: {numOnesQ2}");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
    }
    
  2. Innan du kör programmet kontrollerar du att målprofilen är inställd på Obegränsad. Välj Visa –> Kommandopalett, sök efter QIR, väljQ# : Ange Azure Quantum QIR-målprofilen och välj Q#sedan : obegränsad.

    Kommentar

    Om målprofilen inte är inställd på Obegränsad får du ett fel när du kör programmet.

  3. Om du vill köra programmet väljer du Kör fil i listrutan uppspelningsikon längst upp till höger, väljer Kör från listan med kommandon som föregick Main åtgärden eller trycker på Ctrl+F5. Q# Programmet kör Main åtgärden på standardsimulatorn.

  4. Dina utdata visas i felsökningskonsolen.

    Q1 - Zeros: 0
    Q1 - Ones: 1000
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    

    Eftersom kvantbitarna inte har manipulerats ännu har de behållit sina inledande värden: den första qubiten returnerar One varje gång och den andra qubiten returnerar Zero.

  5. Om du ändrar värdet initial för till Zero och kör programmet igen bör du observera att den första kvantbiten också returneras Zero varje gång.

    Q1 - Zeros: 1000
    Q1 - Ones: 0
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    

Dricks

Välj Ctrl-Z eller Redigera > Ångra och spara filen när du introducerar en teständring av koden innan du kör den igen.

Placera en qubit i superposition

För närvarande är kvantbitarna i programmet i ett klassiskt tillstånd, det vill säga de är antingen 1 eller 0. Du vet detta eftersom programmet initierar kvantbitarna till ett känt tillstånd och du inte har lagt till några processer för att manipulera dem. Innan du sammanflätar kvantbitarna placerar du den första kvantbiten i ett superpositionstillstånd, där ett mått på kvantbiten returnerar Zero 50 % av tiden och One 50 % av tiden. Konceptuellt kan kvantbiten betraktas som halvvägs mellan Zero och One.

Om du vill placera en qubit i superposition Q# tillhandahåller Håtgärden , eller Hadamard. X Återkalla åtgärden från initialisera en qubit till en känd tillståndsprocedur tidigare, som vände en qubit från Zero till One (eller vice versa); H åtgärden vänder kvantbiten halvvägs till ett tillstånd med lika sannolikheter för Zero eller One. När den mäts bör en kvantbit i superposition returnera ungefär lika många Zero och One resultat.

  1. Ändra koden i Main åtgärden för att inkludera åtgärden H :

    for test in 1..count {
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
    
            H(q1);                // Add the H operation after initialization and before measurement
    
            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2); 
            ...
    
  2. Nu när du kör programmet kan du se resultatet av den första kvantbiten i superposition:

    Q1 - Zeros: 523            // results will vary
    Q1 - Ones: 477
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    
  3. Varje gång du kör programmet varierar resultatet för den första kvantbiten något, men kommer att vara nära 50 % One och 50 % Zero, medan resultatet för den andra kvantbiten förblir Zero hela tiden.

    Q1 - Zeros: 510           
    Q1 - Ones: 490
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    
  4. När du initierar den första kvantbiten så Zero returneras liknande resultat.

    Q1 - Zeros: 504           
    Q1 - Ones: 496
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    

Sammanfläta två kvantbitar

Som tidigare nämnts är sammanflätade kvantbitar anslutna så att de inte kan beskrivas oberoende av varandra. Det vill säga, vilken åtgärd som än händer med en qubit, händer också med den sammanflätade qubiten. På så sätt kan du känna till det resulterande tillståndet för en qubit utan att mäta den, bara genom att mäta tillståndet för den andra kvantbiten. (I det här exemplet används två kvantbitar, men det är också möjligt att sammanfläta tre eller fler kvantbitar).

För att aktivera sammanflätning Q# tillhandahåller åtgärden CNOT , som står för Controlled-NOT. Resultatet av att köra den här åtgärden på två kvantbitar är att vända den andra qubiten om den första qubiten är One.

  1. Lägg till åtgärden i CNOT programmet direkt efter åtgärden H . Ditt fullständiga program bör se ut så här:

    import Microsoft.Quantum.Intrinsic.*;
    import Microsoft.Quantum.Canon.*;
    
        operation SetQubitState(desired : Result, target : Qubit) : Unit {
            if desired != M(target) {
                X(target);
            }
        }
    
    operation Main() : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;
        let count = 1000;
        let initial = Zero;
    
        // allocate the qubits
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
    
            H(q1);            
            CNOT(q1, q2);      // Add the CNOT operation after the H operation
    
            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2);           
    
            // Count the number of 'Ones' returned:
            if resultQ1 == One {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
    
    
        // Display the times that |0> is returned, and times that |1> is returned
        Message($"Q1 - Zeros: {count - numOnesQ1}");
        Message($"Q1 - Ones: {numOnesQ1}");
        Message($"Q2 - Zeros: {count - numOnesQ2}");
        Message($"Q2 - Ones: {numOnesQ2}");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
    
        }
    
    
    Q1 - Zeros: 502           
    Q1 - Ones: 498       // results will vary
    Q2 - Zeros: 502
    Q2 - Ones: 498
    Result: "(502, 498, 502, 498)"
    

Statistiken för den första kvantbiten har inte ändrats (en 50/50-chans för en Zero eller en One efter mätning), men mätresultatet för den andra kvantbiten är alltid detsamma som mätningen av den första kvantbiten. Åtgärden CNOT sammanflätade de två kvantbitarna, så att vad som än händer med den ena av dem, händer med den andra.

Rita frekvens histogram

Nu ska vi visualisera fördelningen av resultat som hämtats från att köra kvantprogrammet flera gånger. Frekvens histogrammet hjälper till att visualisera sannolikhetsfördelningen för dessa resultat.

  1. Välj Visa –> Kommandopalett eller tryck på Ctrl+Skift+P och skriv "histogram" som ska ta upp Q#alternativet : Kör och visa histogram . Du kan också välja Histogram i listan med kommandon före Main. Välj det här alternativet för att öppna Q# histogramfönstret.

  2. Ange ett antal bilder för att köra programmet, till exempel 100 bilder, och tryck på Retur. Histogrammet visas i Q# histogramfönstret.

  3. Varje stapel i histogrammet motsvarar ett möjligt utfall och dess höjd representerar antalet gånger som resultatet observeras. I det här fallet finns det 50 olika unika resultat. Observera att för varje utfall är mätresultaten för den första och den andra kvantbiten alltid desamma.

    Skärmbild av Q# histogramfönstret i Visual Studio Code.

    Dricks

    Du kan zooma histogrammet med hjälp av musrullningshjulet eller en styrplatta. När du zoomar in kan du panorera diagrammet genom att trycka på Alt medan du rullar.

  4. Välj ett fält för att visa procentandelen av resultatet.

  5. Välj ikonen för inställningar längst upp till vänster för att visa alternativ. Du kan visa de 10 bästa resultaten, de 25 bästa resultaten eller alla resultat. Du kan också sortera resultaten från hög till låg eller låg till hög.

    Skärmbild av Q# histogramfönstret i Visual Studio Code som visar hur du visar inställningar.

Utforska andra Q# självstudier:

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