Freigeben über


Tutorial: Erkunden der Quantenverschränkung mit Q#

In diesem Lernprogramm schreiben Sie ein Q# Programm, das Qubits bearbeitet und misst und die Auswirkungen von Überlagerung und Verschränkung veranschaulicht. Sie bereiten zwei Qubits in einem bestimmten Quantenzustand vor, lernen, wie Sie mit Qubits arbeiten, um Q# ihren Zustand zu ändern, und zeigen die Auswirkungen von Superposition und Veranglement. Sie erstellen Ihr Q# Programm Stück für Stück, um Qubit-Zustände, Vorgänge und Messungen einzuführen.

Im Folgenden sind einige wichtige Konzepte aufgeführt, die Sie verstehen sollten, bevor Sie beginnen:

  • Klassische Bits enthalten einen einzelnen binären Wert (0 oder 1). Der Zustand eines Qubits kann dagegen eine Superposition von zwei Quantenzuständen sein (also 0 und 1). Jeder mögliche Quantenzustand besitzt eine zugeordnete Wahrscheinlichkeitsamplitude.
  • Der Akt der Messung eines Qubits erzeugt ein binäres Ergebnis mit einer bestimmten Wahrscheinlichkeit und ändert den Zustand des Qubits außerhalb der Superposition.
  • Mehrere Qubits können verangt werden, sodass sie nicht unabhängig voneinander beschrieben werden können. Das bedeutet Folgendes: Was auch immer mit einem Qubit in einem verschränkten Paar geschieht, geschieht auch mit dem anderen Qubit.

In diesem Tutorial lernen Sie Folgendes:

  • Erstellen Sie Q# Vorgänge zum Initialisieren eines Qubits in einen gewünschten Zustand.
  • Setzen eines Qubits in Superposition
  • 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 Azure 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.

Voraussetzungen

Um das Codebeispiel im Copilot für Azure Quantum auszuführen, benötigen Sie Folgendes:

  • Ein Microsoft-E-Mail-Konto (MSA).

Weitere Informationen zum Copilot 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 einem bekannten Zustand initialisiert. Dieser Vorgang kann aufgerufen werden, um ein Qubit auf einen klassischen Zustand festzulegen, d. h., dass er bei Gemessen entweder 100 % der Zeit zurückgibt Zero oder 100 % der Zeit zurückgibt One . Das Messen eines Qubits gibt einen Q# Typ Resultzurück, der nur einen Wert oder OneZero einen Wert aufweisen kann.

Öffnen Sie den Copilot für Azure Quantum , und kopieren Sie den folgenden Code in das Code-Editor-Fenster. Klicken Sie noch nicht auf "Ausführen" . Sie führen den Code weiter unten im Lernprogramm aus.

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

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

Im Codebeispiel werden die beiden Standardvorgänge M und X eingeführt, die den Zustand eines Qubits transformieren.

Der SetQubitState-Vorgang:

  1. Verwendet zwei Parameter: einen Typ Result, benannt desired, der den gewünschten Zustand für das Qubit in (Zero oder One) und einen Typ Qubitdarstellt.
  2. Führt einen Messvorgang M aus, der den Zustand des Qubits misst (Zero oder One) und das Ergebnis mit dem in desired angegebenen Wert vergleicht.
  3. Wenn die Messung nicht mit dem verglichenen Wert übereinstimmt, führt sie einen Vorgang X aus, der den Zustand des Qubits so umdreht, dass die Wahrscheinlichkeiten einer Zero und One zurückgebenden Messung umgekehrt werden. Auf diese Weise versetzt SetQubitState das Zielqubit immer in den gewünschten Zustand.

Schreiben eines Testvorgangs zum Testen des Bell-Zustands

Erstellen Sie als Nächstes einen weiteren Vorgang mit dem Namen Main, um die Auswirkungen des SetQubitState-Vorgangs zu veranschaulichen. Dieser Vorgang weist zwei Qubits zu, ruft SetQubitState auf, um den ersten Qubit auf einen bekannten Zustand festzulegen, und misst dann die Qubits, um die Ergebnisse anzuzeigen.

Kopieren Sie den folgenden Code in das Code-Editor-Fenster unter 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 {
            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 );
}

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

Beim Main-Vorgang geschieht Folgendes:

  1. Legt Variablen für den Zähler und den anfänglichen Qubit-Zustand fest.
  2. Ruft die use-Anweisung auf, um zwei Qubits zu initialisieren.
  3. Führt Schleifendurchläufe für count Iterationen aus. Für jede Schleife wird
    1. SetQubitState aufgerufen, um einen angegebenen initial-Wert für das erste Qubit festzulegen.
    2. SetQubitState erneut aufgerufen, um das zweite Qubit in einen Zero-Zustand zu setzen.
    3. der M-Vorgang verwendet, um jedes Qubit zu messen.
    4. die Anzahl der Messungen für jedes Qubit gespeichert, das One zurückgibt.
  4. Nach dem Schleifendurchlauf wird SetQubitState erneut aufgerufen, um die Qubits in einen bekannten Zustand (Zero) zurückzusetzen, damit andere Benutzer die Qubits in einem bekannten Zustand zuordnen können. Das Zurücksetzen ist von der use Anweisung erforderlich.
  5. Schließlich wird die Message Funktion verwendet, um Ergebnisse in die Copilot-Ausgabefenster zu drucken, bevor die Ergebnisse zurückgegeben werden.

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

Bevor Sie mit den Verfahren für Die Überlagerung und Verschränkung fortfahren, können Sie den Code bis zu diesem Punkt testen, um die Initialisierung und Messung der Qubits zu sehen.

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

Ihr Q# Programm bis zu diesem Punkt sollte nun wie folgt aussehen:

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

}

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

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

Da die Qubits noch nicht bearbeitet wurden, haben sie ihre Anfangswerte beibehalten: Das erste Qubit gibt jedes Mal One zurück, und das zweite Qubit gibt Zero zurück.

Wenn Sie den Wert von initial "in Zero " ändern und das Programm erneut ausführen, sollten Sie beachten, dass auch das erste Qubit jedes Mal zurückgegeben wird Zero .

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

Tipp

Wählen Sie STRG-Z oder "Rückgängig bearbeiten>" aus, und speichern Sie die Datei immer dann, wenn Sie eine Teständerung an den Code vorführen, bevor Sie sie erneut ausführen.

Setzen eines Qubits in Superposition

Derzeit befinden sich alle Qubits im Programm in einem klassischen Zustand, d. h. entweder 1 oder 0. Sie wissen dies, da das Programm die Qubits in einem bekannten Zustand initialisiert und Sie keine Prozesse hinzugefügt haben, um sie zu bearbeiten. Bevor Sie die Qubits verkoppeln, setzen Sie den ersten Qubit in einen Superpositionszustand, in dem eine Messung des Qubits ~50% der Zeit und One ~50% der Zeit zurückgibt Zero . Konzeptionell kann das Qubit als gleiche Wahrscheinlichkeit für die Messung einer oder Onemehrerer Zero Qubits betrachtet werden.

Um ein Qubit in die Superposition zu versetzen, stellt Q# den H-Vorgang (Hadamard) bereit. Rufen Sie den X Vorgang von der Initialisierung eines Qubits in eine bekannte Zustandsprozedur früher zurück, die ein Qubit von 0 auf 1 gekippt hat (oder umgekehrt). Der H Vorgang kippt das Qubit halbway in einen Zustand gleicher Wahrscheinlichkeiten von Zero oder One. Bei der Messung sollte ein Qubit in Superposition ungefähr die gleiche Anzahl von Zero- und One-Ergebnissen zurückgeben.

Ändern Sie den Code im Main Vorgang, indem Sie den Anfangswert One zurücksetzen und eine Zeile für den H Vorgang einfügen:

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

Wenn Sie nun das Programm ausführen, können Sie die Ergebnisse des ersten Qubits in Der Superposition sehen.

Q1 - Zeros: 523            // results vary
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 jedoch nahe 50 % One und 50 % Zero, während die Ergebnisse für das zweite Qubit immer verbleiben Zero .

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

Das Initialisieren des ersten Qubits auf Zero gibt ähnliche Ergebnisse zurück.

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

Hinweis

Indem Sie den Schieberegler im Copilot für Azure Quantum bewegen und die Anzahl der Aufnahmen erhöhen, können Sie sehen, wie die Superpositionsergebnisse geringfügig über die Verteilung der Aufnahmen variieren.

Verschränken zweier Qubits

Wie bereits erwähnt, sind verschränkte Qubits so verbunden, dass sie nicht unabhängig voneinander beschrieben werden können. Das bedeutet Folgendes: Jeder Vorgang, der für ein Qubit ausgeführt wird, wird auch für das verschränkte Qubit ausgeführt. Dies ermöglicht es Ihnen, den resultierenden Zustand eines Qubits ohne Messung zu ermitteln, indem Sie nur den Zustand des anderen Qubits messen. (In diesem Beispiel werden zwei Qubits verwendet. Es ist jedoch auch möglich, drei oder mehr Qubits zu verschränken.)

Um die Verschränkung zu ermöglichen, wird von Q# der CNOT-Vorgang bereitgestellt, der für Controlled-NOT steht. Das Ergebnis des Ausführens dieses Vorgangs für zwei Qubits ist, dass das zweite Qubit umgekehrt wird, wenn das erste Qubit One ist.

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

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

    }

Wenn Sie nun das Programm ausführen, sollte folgendes angezeigt werden:

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

Beachten Sie, dass sich die Statistiken für den ersten Qubit nicht geändert haben (es gibt immer noch eine ~50/50 Chance einer Zero oder einer One nach der Messung), aber die Messergebnisse für das zweite Qubit sind immer identisch mit der Messung des ersten Qubits, unabhängig davon, wie oft Sie das Programm ausführen. Der CNOT-Vorgang hat die zwei Qubits verschränkt, sodass was immer mit dem einen von ihnen geschieht, auch mit dem anderen geschieht.

Voraussetzungen

So entwickeln und führen Sie das Codebeispiel in Ihrer lokalen Entwicklungsumgebung aus:

Erstellen einer neuen Q# Datei

  1. Öffnen Sie Visual Studio Code und wählen Sie Datei > Neue Textdatei aus, um eine neue Datei zu erstellen.
  2. Speichern Sie die Datei unter dem Namen CreateBellStates.qs. Diese Datei enthält 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 einem bekannten Zustand initialisiert. Dieser Vorgang kann aufgerufen werden, um ein Qubit auf einen klassischen Zustand festzulegen, was bedeutet, dass er entweder 100 % der Zeit zurückgibt Zero oder 100 % der Zeit zurückgibt One . Zero und One sind Q#-Werte, die die beiden einzigen möglichen Ergebnisse der Messung eines Qubits darstellen.

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

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

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

Im Codebeispiel werden die beiden Standardvorgänge M und X eingeführt, die den Zustand eines Qubits transformieren.

Der SetQubitState-Vorgang:

  1. Verwendet zwei Parameter: einen Typ Result, benannt desired, der den gewünschten Zustand für das Qubit in (Zero oder One) und einen Typ Qubitdarstellt.
  2. Führt einen Messvorgang M aus, der den Zustand des Qubits misst (Zero oder One) und das Ergebnis mit dem in desired angegebenen Wert vergleicht.
  3. Wenn die Messung nicht mit dem verglichenen Wert übereinstimmt, führt sie einen Vorgang X aus, der den Zustand des Qubits so umdreht, dass die Wahrscheinlichkeiten einer Zero und One zurückgebenden Messung umgekehrt werden. Auf diese Weise versetzt SetQubitState das Zielqubit immer in den gewünschten Zustand.

Schreiben eines Testvorgangs zum Testen des Bell-Zustands

Erstellen Sie als Nächstes einen weiteren Vorgang mit dem Namen Main, um die Auswirkungen des SetQubitState-Vorgangs zu veranschaulichen. Dieser Vorgang weist zwei Qubits zu, ruft SetQubitState auf, um den ersten Qubit auf einen bekannten Zustand festzulegen, und misst dann die Qubits, um die Ergebnisse anzuzeigen.

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

Im Code werden die Variablen bzw. die count Variablen festgelegt 1000 One.initial In diesem Schritt wird der erste Qubit initialisiert One und jeder Qubit 1000 mal misst.

Beim Main-Vorgang geschieht Folgendes:

  1. Verwendet zwei Parameter: count, die Anzahl der Ausführungen einer Messung, und initial, den gewünschten Zustand zum Initialisieren des Qubits.
  2. Ruft die use-Anweisung auf, um zwei Qubits zu initialisieren.
  3. Führt Schleifendurchläufe für count Iterationen aus. Für jede Schleife wird
    1. SetQubitState aufgerufen, um einen angegebenen initial-Wert für das erste Qubit festzulegen.
    2. SetQubitState erneut aufgerufen, um das zweite Qubit in einen Zero-Zustand zu setzen.
    3. der M-Vorgang verwendet, um jedes Qubit zu messen.
    4. die Anzahl der Messungen für jedes Qubit gespeichert, das One zurückgibt.
  4. Nach dem Schleifendurchlauf wird SetQubitState erneut aufgerufen, um die Qubits in einen bekannten Zustand (Zero) zurückzusetzen, damit andere Benutzer die Qubits in einem bekannten Zustand zuordnen können. Das Zurücksetzen des Qubits ist von der use Anweisung erforderlich.
  5. Schließlich wird die Message-Funktion verwendet, um eine Meldung in der Konsole auszugeben, bevor die Ergebnisse zurückgegeben werden.

Ausführen des Codes

Bevor Sie mit den Prozeduren für Superposition und Verschränkung fortfahren, testen Sie den Code bis zu diesem Punkt, um die Initialisierung und Messung der Qubits zu sehen.

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

  1. Ihre CreateBellStates.qs Datei bis zu diesem Punkt sollte nun wie folgt aussehen:

    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. Stellen Sie vor dem Ausführen des Programms sicher, dass das Zielprofil auf "Uneingeschränkt" festgelegt ist. Wählen Sie "Ansicht - Befehlspalette", suchen Sie nach QIR, wählen Sie : Q#Legen Sie das Azure Quantum QIR-Zielprofil fest, und wählen Sie dann : uneingeschränkt ausQ#.>

    Hinweis

    Wenn das Zielprofil nicht auf "Uneingeschränkt" festgelegt ist, wird beim Ausführen des Programms eine Fehlermeldung angezeigt.

  3. Um das Programm auszuführen, wählen Sie in der Dropdownliste "Wiedergabesymbol" oben rechts "Datei ausführenQ#" aus, wählen Sie "Ausführen" aus der Liste der Befehle vor dem Main Vorgang aus, oder drücken Sie STRG+F5. Das Programm führt den Main Vorgang im Standardsimulator aus.

  4. Die Ausgabe wird in der Debugkonsole angezeigt.

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

    Da die Qubits noch nicht bearbeitet wurden, haben sie ihre Anfangswerte beibehalten: Das erste Qubit gibt jedes Mal One zurück, und das zweite Qubit gibt Zero zurück.

  5. Wenn Sie den Wert von initial "in Zero " ändern und das Programm erneut ausführen, sollten Sie beachten, dass auch das erste Qubit jedes Mal zurückgegeben wird Zero .

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

Tipp

Wählen Sie STRG-Z oder "Rückgängig bearbeiten>" aus, und speichern Sie die Datei immer dann, wenn Sie eine Teständerung an den Code vorführen, bevor Sie sie erneut ausführen.

Setzen eines Qubits in Superposition

Derzeit befinden sich alle Qubits im Programm in einem klassischen Zustand, d. h. entweder 1 oder 0. Sie wissen dies, da das Programm die Qubits in einem bekannten Zustand initialisiert und Sie keine Prozesse hinzugefügt haben, um sie zu bearbeiten. Bevor Sie die Qubits verkoppeln, setzen Sie den ersten Qubit in einen Superpositionszustand, in dem eine Messung des Qubits 50 % der Zeit und One 50 % der Zeit zurückgibtZero. Konzeptuell können Sie sich das Qubit als Kombination von Zero und One vorstellen.

Um ein Qubit in die Superposition zu versetzen, stellt Q# den H-Vorgang (Hadamard) bereit. Rufen Sie den X Vorgang von der Initialisierung eines Qubits in eine bekannte Zustandsprozedur früher zurück, die einen Qubit von Zero ( One oder umgekehrt) gekippt hat; der H Vorgang kippt den Qubit halb in einen Zustand gleicher Wahrscheinlichkeit oder Zero One. Bei der Messung sollte ein Qubit in Superposition ungefähr die gleiche Anzahl von Zero- und One-Ergebnissen zurückgeben.

  1. Ändern Sie den Code im Main-Vorgang so, dass er den H-Vorgang einschließt:

    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. Wenn Sie nun das Programm ausführen, sehen Sie die Ergebnisse des ersten Qubits in Superposition:

    Q1 - Zeros: 523            // results will vary
    Q1 - Ones: 477
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    
  3. Jedes Mal, wenn Sie das Programm ausführen, variieren die Ergebnisse für das erste Qubit geringfügig, sind jedoch nahe 50 % One und 50 % Zero, während die Ergebnisse für das zweite Qubit immer verbleiben Zero .

    Q1 - Zeros: 510           
    Q1 - Ones: 490
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    
  4. Das Initialisieren des ersten Qubits auf Zero gibt ähnliche Ergebnisse zurück.

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

Verschränken zweier Qubits

Wie bereits erwähnt, sind verschränkte Qubits so verbunden, dass sie nicht unabhängig voneinander beschrieben werden können. Das bedeutet Folgendes: Jeder Vorgang, der für ein Qubit ausgeführt wird, wird auch für das verschränkte Qubit ausgeführt. Dies ermöglicht es Ihnen, den resultierenden Zustand eines Qubits ohne Messung zu ermitteln, indem Sie nur den Zustand des anderen Qubits messen. (In diesem Beispiel werden zwei Qubits verwendet. Es ist jedoch auch möglich, drei oder mehr Qubits zu verschränken.)

Um die Verschränkung zu ermöglichen, wird von Q# der CNOT-Vorgang bereitgestellt, der für Controlled-NOT steht. Das Ergebnis des Ausführens dieses Vorgangs für zwei Qubits ist, dass das zweite Qubit umgekehrt wird, wenn das erste Qubit One ist.

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

    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)"
    

Die Statistiken für das erste Qubit haben sich nicht geändert (eine Wahrscheinlichkeit von 50/50 für Zero oder One nach der Messung). Die Messergebnisse für das zweite Qubit sind jedoch immer identisch mit der Messung des ersten Qubits. Der CNOT Vorgang hat die beiden Qubits verangt, sodass alles, was mit einem von ihnen passiert, mit dem anderen passiert.

Zeichnen des Häufigkeits histogramms

Lassen Sie uns die Verteilung der Ergebnisse visualisieren, die aus der Ausführung des Quantenprogramms mehrmals erzielt werden. Das Häufigkeits histogramm hilft dabei, die Wahrscheinlichkeitsverteilung dieser Ergebnisse zu visualisieren.

  1. Wählen Sie "Ansicht"> aus, oder drücken Sie STRG+UMSCHALT+P, und geben Sie "Histogramm" ein, das die Q#Option "Datei ausführen" und "Histogramm" anzeigen soll. Sie können auch Histogramm aus der Liste der vorherigen MainBefehle auswählen. Wählen Sie diese Option aus, um das Q# Histogrammfenster zu öffnen.

  2. Geben Sie eine Reihe von Aufnahmen ein, um das Programm auszuführen, z. B. 100 Aufnahmen, und drücken Sie die EINGABETASTE. Das Histogramm wird im Q# Histogrammfenster angezeigt.

  3. Jeder Balken im Histogramm entspricht einem möglichen Ergebnis, und seine Höhe stellt die Anzahl der Beobachteten dar. In diesem Fall gibt es 50 verschiedene eindeutige Ergebnisse. 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

    Sie können das Histogramm mithilfe des Mausrads oder einer Trackpadgeste zoomen. Beim Vergrößern können Sie das Diagramm verschieben, indem Sie beim Scrollen ALT drücken.

  4. Wählen Sie einen Balken aus, um den Prozentsatz dieses Ergebnisses anzuzeigen.

  5. Wählen Sie das Symbol für die oberen linken Einstellungen aus, um Optionen anzuzeigen. Sie können top 10 Ergebnisse, top 25 Ergebnisse oder alle Ergebnisse anzeigen. Sie können die Ergebnisse auch von hoch bis niedrig oder niedrig bis hoch sortieren.

    Screenshot des Q# Histogrammfensters in Visual Studio Code, das zeigt, wie Einstellungen angezeigt werden.

Sehen Sie sich weitere Q#-Tutorials an: