Freigeben über


Tutorial: Erkunden der Quantenverschränkung mit Q#

In dieser Anleitung schreiben Sie ein Q# Programm, das zwei Qubits in einem bestimmten Quantenzustand vorbereitet, auf die Qubits wirkt, um sie miteinander zu verschränken, und Messungen durchführt, um die Auswirkungen von Superposition und Verschränkung zu veranschaulichen. Sie erstellen Ihr Q# Programm Stück für Stück, um Qubit-Zustände, Quantenvorgänge und Messungen einzuführen.

Bevor Sie beginnen, lesen Sie die folgenden Quantencomputing-Konzepte:

  • Klassische Bits enthalten einen einzelnen binären Wert, z. B. 0 oder 1, aber Qubits können sich in einer Oberposition der beiden Zustände 0 und 1 befinden. Jeder mögliche Qubit-Zustand wird durch eine Reihe von Wahrscheinlichkeitsamplitanten beschrieben.
  • Wenn Sie den Zustand eines Qubits messen, erhalten Sie immer 0 oder 1. Die Wahrscheinlichkeit jedes Ergebnisses wird durch die Wahrscheinlichkeitsamplituden bestimmt, die den Superpositionszustand definieren, wenn Sie eine Messung vornehmen.
  • Mehrere Qubits können so verschränkt werden, dass Sie sie nicht unabhängig voneinander beschreiben können. Wenn Sie einen Qubit in einem verangten Paar messen, erhalten Sie auch Informationen zum anderen Qubit, ohne es zu messen.

In diesem Tutorial erfahren Sie, wie:

  • Erstellen Sie Q# Vorgänge zum Initialisieren eines Qubits in einen gewünschten Zustand.
  • Setzen Sie ein Qubit in einen Superpositionszustand.
  • Verschränken eines Qubit-Paars
  • Messen Sie ein Qubit, und beobachten Sie die Ergebnisse.

Tipp

Wenn Sie Ihre Quantum Computing-Reise beschleunigen möchten, schauen Sie sich Code mit Azure Quantum an, einem einzigartigen Feature der Microsoft Quantum-Website. Hier können Sie integrierte Q# Beispiele oder Eigene Q# Programme ausführen, neuen Q# Code aus Ihren Eingabeaufforderungen generieren, Ihren Code in VS Code für das Web mit nur einem Klick öffnen und ausführen und Copilot Fragen zum Quanten computing stellen.

Voraussetzungen

Um das Codebeispiel mit Copilot für Azure Quantum auszuführen, müssen Sie über ein Microsoft-E-Mail-Konto (MSA) verfügen.

Weitere Informationen zu Copilot für Azure Quantum finden Sie unter Explore Azure Quantum.

Initialisieren eines Qubits in einen bekannten Zustand

Der erste Schritt besteht darin, einen Q# Vorgang zu definieren, der ein Qubit in einen gewünschten klassischen Zustand initialisiert, entweder 0 oder 1. Dieser Vorgang misst ein Qubit in einem allgemeinen Quantenzustand und gibt einen Q#Result Typwert von entweder Zero oder One zurück. Wenn sich das Messergebnis vom gewünschten Zustand unterscheidet, kippt der Vorgang den Zustand so, dass der Vorgang den gewünschten Zustand 100% der Zeit zurückgibt.

Öffnen Sie Copilot für Azure Quantum, löschen Sie den Standardcode, und kopieren Sie dann den folgenden Code in das Code-Editor-Fenster. Sie können diesen Code nicht allein ausführen, da er noch kein vollständiges Q# Programm ist.

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

Im Codebeispiel werden zwei Standardoperationen Q# und M eingeführt, die den Zustand eines Qubits transformieren.

Hier ist eine detaillierte Beschreibung der Funktionsweise des SetQubitState Vorgangs:

  1. Verwendet zwei Parameter: einen Result Typparameter mit dem Namen desired , der den gewünschten Zustand für das Qubit in (Zero oder One) und einen Qubit Typparameter darstellt.
  2. Führt einen Messvorgang aus, M bei dem der Zustand des Qubits (Zero oder One) gemessen und das Ergebnis mit dem Wert verglichen wird, den Sie für desired übergeben.
  3. Wenn das Messergebnis nicht mit dem Wert übereinstimmt desired, wird ein X Vorgang auf das Qubit angewendet. Dieser Vorgang kippt den Zustand des Qubits, sodass die Messwahrscheinlichkeit für Zero und One umgekehrt wird.

Schreiben eines Testvorgangs zum Testen des Bell-Zustands

Um den SetQubitState Vorgang in Ihrem Q# Programm aufzurufen, erstellen Sie einen anderen Vorgang mit dem Namen Main. Dieser Vorgang weist zwei Qubits zu, ruft SetQubitState auf, um das erste Qubit auf einen bekannten Zustand festzulegen, und misst dann die Qubits, um die Ergebnisse zu sehen.

Kopieren Sie den folgenden Code in das Code-Editor-Fenster nach dem SetQubitState Vorgang.

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 {
            numOnesQ1 += 1;
        }
        if resultQ2 == One {
            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 );
}

Im Code werden die Variablen bzw. die count Variablen festgelegt initial1000.One So wird das erste Qubit auf One initialisiert und jedes Qubit 1000-mal gemessen.

Der Main Vorgang führt die folgenden Aktionen aus:

  1. Legt Variablen für die Anzahl der Aufnahmen (count) und den anfänglichen Qubit-Zustand (One) fest.
  2. Ruft die use-Anweisung auf, um zwei Qubits zu initialisieren.
  3. Schleift das Experiment count Mal.
  4. In der Schleife werden Aufrufe SetQubitState zum Festlegen des angegebenen initial Werts für den ersten Qubit und dann erneut aufgerufen SetQubitState , um den zweiten Qubit auf den Zero Zustand festzulegen.
  5. Wendet in der Schleife den M Vorgang an, um die einzelnen Qubits zu messen, und speichert dann die Anzahl der Messungen für jeden zurückzugebenden OneQubit.
  6. Nach Abschluss der Schleife wird SetQubitState erneut aufgerufen, um die Qubits auf einen bekannten Zustand (Zero) zurückzusetzen. Sie müssen Qubits zurücksetzen, die Sie mit der use Anweisung zuordnen.
  7. Ruft die Message Funktion auf, um Die Ergebnisse im Ausgabefenster zu drucken.

Ausführen des Codes in Copilot für Azure Quantum

Bevor Sie Code für die Überlagerung und Verschränkung schreiben, testen Sie Ihr aktuelles Programm, um die Initialisierung und Messung der Qubits zu überprüfen.

Um Ihren Code als eigenständiges Programm auszuführen, muss der Q# Compiler in Copilot wissen, wo das Programm gestartet werden soll. Da Sie keinen Namespace angegeben haben, erkennt der Compiler den Standardeinstiegspunkt als Main Vorgang. Weitere Informationen finden Sie unter Projekte und implizite Namespaces.

Ihr Q# Programm sieht nun wie folgt aus:

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 {
            numOnesQ1 += 1;
        }
        if resultQ2 == One {
            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 );
}

Kopieren Sie das vollständige Codebeispiel, und fügen Sie es in das Codefenster "Copilot für Azure Quantum " ein, legen Sie den Schieberegler für die Anzahl der Aufnahmen auf "1" fest, und wählen Sie dann "Ausführen" aus. Die Ergebnisse werden im Histogramm und in den Feldern "Ergebnisse " angezeigt.

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

Ihr Programm ändert die Qubitzustände noch nicht, sodass die Messung des ersten Qubits immer zurückgegeben Onewird und der zweite Qubit immer zurückgegeben wird Zero.

Wenn Sie den Wert von initial auf Zero ändern und das Programm erneut ausführen, ergibt auch der erste Qubit immer Zero.

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

Platzieren eines Qubits in einen Superpositionszustand

Derzeit befinden sich die Qubits in Ihrem Programm in einem klassischen Zustand, entweder 1 oder 0, genau wie Bits auf einem normalen Computer. Um die Qubits zu verkoppeln, müssen Sie zuerst einen der Qubits in einen gleichen Superpositionszustand setzen. Die Messung eines Qubits in einem gleichmäßig verteilten Superpositionszustand hat eine 50%ige Chance, Zero zurückzugeben, und eine 50%ige Chance, One zurückzugeben.

Um ein Qubit in einen Superpositionszustand zu versetzen, verwenden Sie die Q#H-Operation (Hadamard-Operation). Der H Vorgang konvertiert ein Qubit, das sich in einem reinen Zero Zustand oder One zustand befindet, in eine Art halbwegs zustand zwischen Zero und One.

Ändern Sie den Code im Main-Vorgang. Setzen Sie den Anfangswert zurück, One und fügen Sie eine Zeile für den H Vorgang ein:

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); 
        ...

Führen Sie Ihr Programm erneut aus. Da sich der erste Qubit in einer gleichen Superposition befindet, wenn Sie es messen, erhalten Sie nahe ein 50/50-Ergebnis für Zero und One. Ihre Ausgabe sieht z. B. ähnlich wie folgt aus:

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

Jedes Mal, wenn Sie das Programm ausführen, variieren die Ergebnisse für das erste Qubit geringfügig, sind aber nahe 50% One und 50% Zero, während die Ergebnisse für den zweiten Qubit immer noch sind Zero.

Initialisieren Sie den ersten Qubit auf Zero anstelle von One und führen Sie das Programm erneut aus. Sie erhalten ähnliche Ergebnisse, da der H-Vorgang sowohl einen reinen Zero-Zustand als auch einen reinen One-Zustand in einen gleichmäßigen Superpositionszustand verwandelt.

Hinweis

Um zu sehen, wie sich die Superpositionsergebnisse über die Verteilung der Aufnahmen unterscheiden, verschieben Sie den Schieberegler in Copilot für Azure Quantum, und erhöhen Sie die Anzahl der Aufnahmen.

Verschränken zweier Qubits

Verangte Qubits sind korreliert, sodass sie nicht unabhängig voneinander beschrieben werden können. Wenn Sie den Zustand eines verangten Qubits messen, wissen Sie auch den Zustand des anderen Qubits, ohne ihn zu messen. In diesem Lernprogramm wird ein Beispiel mit zwei verangten Qubits verwendet, sie können aber auch drei oder mehr Qubits verangen.

Um einen verangten Zustand zu erstellen, verwenden Sie den Q#CNOTOder kontrolliert-NOT-Vorgang. Wenn Sie auf zwei Qubits anwenden CNOT , ist ein Qubit der Steuer-Qubit und der andere der Ziel-Qubit. Wenn der Zustand des Steuerelement-Qubits lautet One, kippt der CNOT Vorgang den Zustand des Ziel-Qubits. CNOT Andernfalls geschieht nichts mit den Qubits.

Fügen Sie den CNOT-Vorgang Ihrem Programm unmittelbar nach dem H-Vorgang hinzu. Ihr vollständiges Programm sieht wie folgt aus:

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 {
            numOnesQ1 += 1;
        }
        if resultQ2 == One {
            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 );
 }

Führen Sie das Programm aus und zeigen Sie die Ausgabe an. Ihre Ergebnisse variieren jedes Mal leicht, wenn Sie das Programm ausführen.

Q1 - Zeros: 502
Q1 - Ones: 498
Q2 - Zeros: 502
Q2 - Ones: 498

Die Statistiken für den ersten Qubit zeigen immer noch eine etwa 50%ige Wahrscheinlichkeit, sowohl One als auch Zero zu messen, aber die Messergebnisse für den zweiten Qubit sind jetzt nicht immer Zero. Jeder Qubit hat die gleiche Anzahl von Zero Ergebnissen und One Ergebnissen. Das Messergebnis für den zweiten Qubit entspricht immer dem Ergebnis für das erste Qubit, da die beiden Qubits verangt sind. Wenn das erste Qubit als Zero gemessen wird, muss das verschränkte Qubit auch Zero sein. Wenn der erste Qubit als One gemessen wird, muss auch der verschränkte Qubit One sein.

Voraussetzungen

Um das Codebeispiel in Ihrer lokalen Entwicklungsumgebung zu entwickeln und auszuführen, installieren Sie die folgenden Tools:

Erstellen einer neuen Q# Datei

  1. Öffnen Sie im VS Code das Menü "Datei ", und wählen Sie "Neue Textdatei " aus, um eine neue Datei zu erstellen.
  2. Speichern Sie die Datei unter dem Namen CreateBellStates.qs. In dieser Datei schreiben Sie den Q# Code für Ihr Programm.

Initialisieren eines Qubits in einen bekannten Zustand

Der erste Schritt besteht darin, einen Q# Vorgang zu definieren, der ein Qubit in einen gewünschten klassischen Zustand initialisiert, entweder 0 oder 1. Dieser Vorgang misst ein Qubit in einem allgemeinen Quantenzustand, der einen Typwert Q#Result von entweder Zero oder One zurückgibt. Wenn sich das Messergebnis vom gewünschten Zustand unterscheidet, kippt der Vorgang den Zustand so, dass der Vorgang den gewünschten Zustand 100% der Zeit zurückgibt.

Öffnen CreateBellStates.qs Sie den folgenden Code, und kopieren Sie den folgenden Code:

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

Im Codebeispiel werden zwei Standardoperationen Q# eingeführt, M die Xden Zustand eines Qubits transformieren.

Hier ist eine detaillierte Beschreibung der Funktionsweise des SetQubitState Vorgangs:

  1. Verwendet zwei Parameter: einen Result Typparameter mit dem Namen desired , der den gewünschten Zustand für das Qubit in (Zero oder One) und einen Qubit Typparameter darstellt.
  2. Führt einen Messvorgang aus, M, der den Zustand des Qubits (Zero oder One) misst und das Ergebnis mit dem Wert vergleicht, den Sie für desired übergeben.
  3. Wenn das Messergebnis nicht mit dem Wert übereinstimmt desired, wird ein X Vorgang auf das Qubit angewendet. Dieser Vorgang kippt den Zustand des Qubits, sodass die Messwahrscheinlichkeit für Zero und One umgekehrt wird.

Schreiben eines Testvorgangs zum Testen des Bell-Zustands

Um den SetQubitState Vorgang in Ihrem Q# Programm aufzurufen, erstellen Sie einen anderen Vorgang mit dem Namen Main. Dieser Vorgang weist zwei Qubits zu, ruft SetQubitState auf, um das erste Qubit in einen bekannten Zustand zu versetzen, und misst dann die Qubits, um die Ergebnisse zu sehen.

Fügen Sie der Datei CreateBellStates.qs nach dem Vorgang SetQubitState den folgenden Vorgang hinzu:

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 {
            numOnesQ1 += 1;
        }
        if resultQ2 == One {
            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 );
}

Im Code werden die Variablen bzw. die count Variablen festgelegt initial1000.One So wird das erste Qubit auf One initialisiert und jedes Qubit 1000-mal gemessen.

Der Main Vorgang führt die folgenden Aktionen aus:

  1. Legt Variablen für die Anzahl der Aufnahmen (count) und den anfänglichen Qubit-Zustand (One) fest.
  2. Ruft die use-Anweisung auf, um zwei Qubits zu initialisieren.
  3. Schleifen über das Experiment count Mal.
  4. In der Schleife wird SetQubitState aufgerufen, um den angegebenen initial Wert für den ersten Qubit festzulegen, und dann wird erneut SetQubitState aufgerufen, um den zweiten Qubit auf den Zero Zustand festzulegen.
  5. Wendet in der Schleife den M Vorgang an, um die einzelnen Qubits zu messen, und speichert dann die Anzahl der Messungen für jeden zurückzugebenden OneQubit.
  6. Nach Abschluss der Schleife wird SetQubitState erneut aufgerufen, um die Qubits auf einen bekannten Zustand (Zero) zurückzusetzen. Sie müssen Qubits zurücksetzen, die Sie mit der use Anweisung zuordnen.
  7. Ruft die Message Funktion auf, um Die Ergebnisse in der Konsole zu drucken.

Ausführen des Codes

Bevor Sie Code zur Überlagerung und Verschränkung schreiben, testen Sie Ihr aktuelles Programm, um die Initialisierung und Messung der Qubits zu überprüfen.

Um den Code als eigenständiges Programm auszuführen, muss der Q# Compiler wissen, wo das Programm gestartet werden soll. Da Sie keinen Namespace angegeben haben, erkennt der Compiler den Standardeinstiegspunkt als Main Vorgang. Weitere Informationen finden Sie unter Projekte und implizite Namespaces.

Ihre CreateBellStates.qs Datei sieht nun wie folgt aus:

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 {
            numOnesQ1 += 1;
        }
        if resultQ2 == One {
            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 );
}

Um das Programm auszuführen, wählen Sie den Befehl "Ausführen" aus der Codelinse aus, die dem Main Vorgang vorausgeht, oder drücken Sie STRG+F5. Das Programm führt den Main Vorgang im Standardsimulator aus.

Die Ausgabe wird in der Debugkonsole angezeigt.

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

Ihr Programm ändert die Qubitzustände noch nicht, sodass die Messung des ersten Qubits immer zurückgegeben Onewird und der zweite Qubit immer zurückgegeben wird Zero.

Wenn Sie den Wert von initial auf Zero ändern und das Programm erneut ausführen, gibt der erste Qubit immer Zero zurück.

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

Platzieren eines Qubits in einen Superpositionszustand

Derzeit befinden sich die Qubits in Ihrem Programm in einem klassischen Zustand, entweder 1 oder 0, genau wie Bits auf einem normalen Computer. Um die Qubits zu verkoppeln, müssen Sie zuerst einen der Qubits in einen gleichen Superpositionszustand setzen. Die Messung eines Qubits in einem Gleichgewichts-Superpositionszustand hat eine 50% Chance, Zero zurückzugeben, und eine 50% Chance, One zurückzugeben.

Um ein Qubit in einen Superpositionszustand zu versetzen, verwenden Sie die Hadamard-Operation Q#H. Der H Vorgang konvertiert ein Qubit, das sich in einem reinen Zero Zustand oder One zustand befindet, in eine Art halbwegs zustand zwischen Zero und One.

Ändern Sie den Main Code während des Vorgangs. Setzen Sie den Anfangswert zurück, One und fügen Sie eine Zeile für den H Vorgang ein:

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); 
        ...

Führen Sie Ihr Programm erneut aus. Da sich der erste Qubit in einer gleichen Superposition befindet, wenn Sie es messen, erhalten Sie nahe ein 50/50-Ergebnis für Zero und One. Ihre Ausgabe sieht z. B. ähnlich wie folgt aus:

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

Jedes Mal, wenn Sie das Programm ausführen, variieren die Ergebnisse für das erste Qubit geringfügig, sind aber nahe 50% One und 50% Zero, während die Ergebnisse für den zweiten Qubit immer noch sind Zero.

Initialisieren Sie den ersten Qubit auf Zero anstelle von One und führen Sie das Programm erneut aus. Sie erhalten ähnliche Ergebnisse, da der H Vorgang sowohl einen reinen Zero Zustand als auch einen reinen One Zustand in einen gleichwertigen Superpositionszustand verwandelt.

Verschränken zweier Qubits

Verangte Qubits sind korreliert, sodass sie nicht unabhängig voneinander beschrieben werden können. Wenn Sie den Zustand eines verangten Qubits messen, wissen Sie auch den Zustand des anderen Qubits, ohne ihn zu messen. In diesem Lernprogramm wird ein Beispiel mit zwei verangten Qubits verwendet, sie können aber auch drei oder mehr Qubits verangen.

Um einen verschränkten Zustand zu erstellen, verwenden Sie die Q#CNOT oder kontrollierten NOT-Operation. Wenn Sie auf zwei Qubits anwenden CNOT , ist ein Qubit der Steuer-Qubit und der andere der Ziel-Qubit. Wenn der Zustand des Steuerelement-Qubits lautet One, kippt der CNOT Vorgang den Zustand des Ziel-Qubits. CNOT Andernfalls geschieht nichts mit den Qubits.

Fügen Sie den CNOT-Vorgang Ihrem Programm unmittelbar nach dem H-Vorgang hinzu. Ihr vollständiges Programm sieht wie folgt aus:

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 {
            numOnesQ1 += 1;
        }
        if resultQ2 == One {
            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 );
}

Führen Sie das Programm aus und zeigen Sie die Ausgabe an. Ihre Ergebnisse unterscheiden sich leicht jedes Mal, wenn Sie das Programm ausführen.

Q1 - Zeros: 502
Q1 - Ones: 498
Q2 - Zeros: 502
Q2 - Ones: 498

Die Statistiken für den ersten Qubit zeigen immer noch etwa 50 % Chance, sowohl One als auch Zero zu messen, aber die Messergebnisse für den zweiten Qubit sind jetzt nicht immer Zero. Jeder Qubit hat die gleiche Anzahl von Zero Ergebnissen und One Ergebnissen. Das Messergebnis für den zweiten Qubit entspricht immer dem Ergebnis für das erste Qubit, da die beiden Qubits verangt sind. Wenn der erste Qubit als Zero gemessen wird, muss auch der verschränkte Qubit Zero sein. Wenn das erste Qubit als One gemessen wird, muss auch das verschränkte Qubit One sein.

Zeichnen des Häufigkeits histogramms

Führen Sie die folgenden Schritte aus, um ein Häufigkeits histogramm zu zeichnen, das die Verteilung der Ergebnisse anzeigt, wenn Sie ihr Programm mehrmals ausführen:

  1. Öffnen Sie Ihre CreateBellStates.qs Datei in VS Code.

  2. Öffnen Sie das Menü "Ansicht" , und wählen Sie "Befehlspalette" aus.

  3. Geben Sie Histogramm ein, um die Option QDK: Datei ausführen und Histogramm anzeigen aufzurufen. Oder wählen Sie den Histogrammbefehl aus der Codelinsenoption aus, die dem Main Vorgang vorausgeht. Geben Sie dann eine Anzahl von Aufnahmen ein (z. B. 100). Das Q# Histogramm öffnet sich in einem neuen Tab.

    Jeder Balken im Histogramm entspricht einem möglichen Ergebnis, wenn die Verschränkungsschaltung 1000 Mal läuft. Die Höhe eines Balkens stellt die Häufigkeit dar, mit der das Ergebnis auftritt. Das folgende Histogramm zeigt beispielsweise eine Verteilung mit 50 eindeutigen Ergebnissen. Beachten Sie, dass für jedes Ergebnis die Messergebnisse für das erste und das zweite Qubit immer gleich sind.

    Screenshot des Q# Histogrammfensters in Visual Studio Code.

    Tipp

    Um das Histogramm zu vergrößern, verwenden Sie das Maus-Bildlaufrad oder eine Trackpadgeste. Um das Diagramm zu verschieben, wenn Sie hineingezoomt sind, halten Sie Alt gedrückt, während Sie scrollen.

  4. Wählen Sie einen Balken aus, um den Prozentsatz der Gesamtzahl der Schüsse anzuzeigen, die zum Erreichen dieses Ergebnisses führten.

  5. Wählen Sie das Symbol "Einstellungen" oben links aus, um Visualisierungsoptionen anzuzeigen.

    Screenshot der Anzeigeeinstellungen für das Q# Histogrammfenster in Visual Studio Code.

  6. Führen Sie den Code erneut aus, aber diesmal mit 1000 Durchläufen. Da sich die Anzahl der Aufnahmen erhöht, nähert sich die Verteilung der Ergebnisse einer normalen Verteilung.

Sehen Sie sich weitere Q#-Tutorials an:

  • von Grover verwendet.
  • Quantum Fourier Transform untersucht, wie ein Q# Programm geschrieben wird, das direkt bestimmte Qubits adressiert.
  • Die Quantum Katas sind selbstgesteuerte Lernprogramme und Programmierübungen, die die Elemente von Quantencomputing und Q# Programmierung gleichzeitig lehren.