Tutorial: Erkunden der Quantenverschränkung mit Q#

In diesem Tutorial erfahren Sie, wie Sie ein Q#-Programm schreiben, mit dem Qubits bearbeitet und gemessen werden können. Darüber hinaus werden die Auswirkungen von Superposition und Verschränkung veranschaulicht.

  • 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.
  • Mit dem Messvorgang für ein Qubit wird ein binäres Ergebnis (0 oder 1) mit einer bestimmten Wahrscheinlichkeit erzeugt und der Qubit-Zustand aus der Superposition geändert.
  • Mehrere Qubits können so verschränkt werden, dass 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 bereiten Sie zwei Qubits in einem bestimmten Quantenzustand vor, erfahren, wie Sie mit Q# bei Qubits vorgehen, um ihren Zustand zu ändern, und veranschaulichen die Auswirkungen von Superposition und Verschränkung. Der Aufbau des Q#-Programms erfolgt Stück für Stück, um Zustände, Vorgänge und Messungen von Qubits zu demonstrieren.

Voraussetzungen

Um dieses Tutorial abzuschließen, benötigen Sie Folgendes:

In diesem Tutorial lernen Sie Folgendes:

  • Erstellen von Q#-Vorgängen, um ein Qubit zu messen und in einem gewünschten Zustand zu initialisieren
  • Erstellen von Qubits und Testen Ihres Programms
  • Setzen eines Qubits in Superposition
  • Verschränken eines Qubit-Paars

Erstellen eines neuen Notebooks in Ihrem Arbeitsbereich

  1. Melden Sie sich beim Azure-Portal an, und wählen Sie den Arbeitsbereich aus, den Sie im vorherigen Schritt erstellt haben.
  2. Wählen Sie auf dem linken Blatt Notebooks aus.
  3. Klicken Sie auf Meine Notebooks und dann auf Neu hinzufügen.
  4. Wählen Sie unter Kerneltyp die Option IQ# aus.
  5. Geben Sie einen Namen für die Datei ein, z. B. Entanglement.ipynb, und klicken Sie auf Datei erstellen.

Wenn Ihr neues Notebook geöffnet wird, wird der Code für die erste Zelle automatisch basierend auf Ihren Abonnement- und Arbeitsbereichsinformationen erstellt.

%azure.connect "/subscriptions/\<subscription ID>/\<resource group>/providers/Microsoft.Quantum/Workspaces/\<workspace>" \<location>

Hinweis

%azure.connect ist ein IQ#-Magic-Befehl, ein Befehlssatz, mit dem Aufgaben in Jupyter Notebooks optimiert werden können.

Wenn Sie diese Zelle ausführen, sollte sie sich bei Ihrem Abonnement authentifizieren und eine Liste der verfügbaren Anbieter und deren Ziele anzeigen.

Initialisieren eines Qubits mithilfe von Messungen

Der erste Schritt besteht darin, einen Q#-Vorgang zu definieren, der ein Qubit in einem bekannten Zustand initialisiert. Sie rufen diesen Vorgang auf, um ein Qubit auf einen klassischen Zustand festzulegen. Das bedeutet, dass entweder immer Zero oder immer One zurückgegeben wird. Zero und One sind Q#-Werte, die die beiden einzigen möglichen Ergebnisse der Messung eines Qubits darstellen.

Klicken Sie auf + Code, um eine neue Zelle hinzuzufügen, und fügen Sie den folgenden Code hinzu:

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

Hinweis

Die Namespaces Microsoft.Quantum.Intrinsic und Microsoft.Quantum.Canon, die von Vorgängen in diesem Code verwendet werden, werden automatisch in jeder Zelle eines Azure Quantum-Notebooks geöffnet.

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 mit dem Namen desired, der den gewünschten Zustand (0 oder 1) für das Qubit darstellt, und einen Typ Qubit.
  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.

Testen der Messung

Erstellen Sie als Nächstes einen weiteren Vorgang mit dem Namen TestBellState, um die Auswirkungen des SetQubitState-Vorgangs zu veranschaulichen.

Fügen Sie eine weitere neue Zelle und den folgenden Code hinzu:

operation TestBellState(count : Int, initial : Result) : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;

    // 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':
        if resultQ1 == One {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set numOnesQ2 += 1;
        }
    }

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

    // Return number of |0> states, number of |1> states
    Message("q1:Zero, One  q2:Zero, One");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

}

Beim TestBellState-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. Dies ist aufgrund der use-Anweisung erforderlich.
  5. Schließlich wird die Message-Funktion verwendet, um eine Meldung in der Konsole anzuzeigen, bevor die Ergebnisse zurückgeben werden.

Testen 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 TestBellState-Vorgang auszuführen, verwenden Sie den Magic-Befehl %simulate, um den Azure Quantum-Simulator für den vollständigen Zustand aufrufen. Sie müssen die Argumente count und initial angeben, z. B. count=1000 und initial=1. So wird das erste Qubit auf One initialisiert und jedes Qubit 1000-mal gemessen. Fügen Sie mit dem folgenden Befehl eine neue Zelle hinzu, und klicken Sie auf Alle ausführen:

%simulate TestBellState count=1000 initial=1

Sie sollten dann die folgende Ausgabe sehen:

q1:Zero, One  q2:Zero, One
(0, 1000, 1000, 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 die Zelle erneut mit initial=0 ausführen, sollten Sie beobachten, dass das erste Qubit ebenfalls jedes Mal Zero zurückgibt.

%simulate TestBellState count=1000 initial=0
q1:Zero, One q2:Zero, One
(1000, 0, 1000, 0)

Setzen eines Qubits in Superposition

Derzeit befinden sich die Qubits im Programm alle in einem klassischen Zustand, d. h., sie sind 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 verschränken, setzen Sie das erste Qubit in den Zustand Superposition, in dem eine Messung des Qubits Zero 50 % der Zeit und One 50 % der Zeit zurückgibt. Konzeptionell kann man sich das Qubit als eine lineare Kombination aller Zustände zwischen Zero und One vorstellen.

Um ein Qubit in die Superposition zu versetzen, stellt Q# den H-Vorgang (Hadamard) bereit. Denken Sie an den X-Vorgang aus der vorherigen Prozedur zum Initialisieren eines Qubits mithilfe der Messung, bei der ein Qubit von 0 in 1 (oder von 1 in 0) umgekehrt wurde. Im Rahmen des H-Vorgangs wird das Qubit halb umgekehrt und dadurch in einen Zustand versetzt, in dem 0 und 1 gleich wahrscheinlich sind. Bei der Messung sollte ein Qubit in Superposition ungefähr die gleiche Anzahl von Zero- und One-Ergebnissen zurückgeben.

Fügen Sie in der vorherigen Zelle mit dem TestBellState den H-Vorgang innerhalb der for-Schleife hinzu:

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

Initialisieren Sie das Qubit im %simulate-Befehl erneut auf 1, klicken Sie auf Alle ausführen, und Sie können die Ergebnisse des ersten Qubits in der Superposition sehen:

%simulate TestBellState count=1000 initial=1
q1:Zero, One  q2:Zero, One
(523, 477, 1000, 0)      // results will vary

Jedes Mal, wenn Sie das Programm ausführen, variieren die Ergebnisse für das erste Qubit geringfügig, liegen jedoch nahe bei 50 % One und 50 % Zero, während die Ergebnisse für das zweite Qubit die ganze Zeit Zero bleiben.

Q1:Zero/One  Q2:Zero/One
(510, 490, 1000, 0)

Beim Initialisieren des ersten Qubits mit Zero werden ähnliche Ergebnisse zurückgegeben.

%simulate TestBellState count=1000 initial=0
Q1:Zero/One  Q2:Zero/One
(504, 496, 1000, 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 in einem verschränkten Paar ausgeführt wird, wird auch für das andere 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 unmittelbar nach dem H-Vorgang der for-Schleife hinzu. Der TestBellState-Vorgang sollte nun wie folgt aussehen:

operation TestBellState(count : Int, initial : Result) : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;

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

        H(q1);
        CNOT(q1, q2);                   // added CNOT operation
        
        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

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

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

    // Return number of |0> states, number of |1> states
    Message("q1:Zero, One  q2:Zero, One");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

}

Klicken Sie auf Alle ausführen, um den aktualisierten Vorgang auszuführen. Dann sollten Sie Folgendes sehen:

Q1:Zero/One  Q2:Zero/One
(502, 498, 502, 498)      // actual results will vary

Die Statistiken für das erste Qubit haben sich nicht geändert (eine 50/50-Wahrscheinlichkeit von Zero oder 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 das Qubit initialisiert wird. Der CNOT-Vorgang hat die zwei Qubits verschränkt, sodass was immer mit dem einen von ihnen geschieht, auch mit dem anderen geschieht.

Voraussetzungen

In diesem Tutorial lernen Sie Folgendes:

  • Erstellen von Q#-Vorgängen, um ein Qubit zu messen und in einem gewünschten Zustand zu initialisieren
  • Erstellen von Qubits und Testen Ihres Programms
  • Setzen eines Qubits in Superposition
  • Verschränken eines Qubit-Paars

Initialisieren eines Qubits mithilfe von Messungen

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. Das bedeutet, dass entweder immer Zero oder immer One zurückgegeben wird. Zero und One sind Q#-Werte, die die beiden einzigen möglichen Ergebnisse der Messung eines Qubits darstellen.

Ersetzen Sie in Ihrem Projekt den Inhalt von Program.qs durch den folgenden Code:

   namespace Bell {
       open Microsoft.Quantum.Intrinsic;
       open 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 mit dem Namen desired, der den gewünschten Zustand (0 oder 1) für das Qubit darstellt, und einen Typ Qubit.
  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.

Testen der Messung

Erstellen Sie als Nächstes einen weiteren Vorgang mit dem Namen TestBellState, um die Auswirkungen des SetQubitState-Vorgangs zu veranschaulichen.

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

operation TestBellState(count : Int, initial : Result) : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;

    // 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' we saw:
        if resultQ1 == One {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set numOnesQ2 += 1;
        }
    }

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

    // Return times we saw |0>, times we saw |1>
    Message("q1:Zero, One  q2:Zero, One");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

}

Beim TestBellState-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. Dies ist aufgrund 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.

Führen Sie den Code in der Eingabeaufforderung aus

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, wenn Sie den Befehl dotnet run ausführen. Dies erfolgt durch eine Angabe in der Q#-Datei, indem Sie direkt vor dem auszuführenden Vorgang @EntryPoint() hinzufügen. In diesem Fall ist dies der Vorgang TestBellState.

Hinweis

@EntryPoint() ist nur für eigenständige Q#-Programme erforderlich. Wenn Sie ein Q#-Programm in Jupyter Notebooks ausführen oder ein Q#-Programm über eine Python- oder .NET-Hostdatei aufrufen, ist diese Angabe nicht erforderlich und löst ggf. einen Fehler aus.

Die Datei program.qs sollte jetzt wie folgt aussehen:

namespace Bell {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;

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

    @EntryPoint()
    operation TestBellState(count : Int, initial : Result) : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;

        // 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' we saw:
            if resultQ1 == One {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
        
    
        // Return times we saw |0>, times we saw |1>
        Message("q1:Zero, One  q2:Zero, One");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

    }
}

Zum Ausführen des Programms müssen Sie die Argumente count und initial aus der Eingabeaufforderung angeben. --count 1000 und --initial One initialisieren beispielsweise das erste Qubit in One und messen jedes Qubit 1.000 Mal. Führen Sie den folgenden Befehl aus:

dotnet run --count 1000 --initial One

Sie sollten die folgende Ausgabe sehen:

Q1:Zero/One  Q2:Zero/One
(0, 1000, 1000, 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.

Bei der Ausführung mit --initial Zero sollten Sie beobachten, dass das erste Qubit ebenfalls jedes Mal Zero zurückgibt.

dotnet run --count 1000 --initial Zero
Q1:Zero/One  Q2:Zero/One
(1000, 0, 1000, 0)

Setzen eines Qubits in Superposition

Derzeit befinden sich die Qubits im Programm alle in einem klassischen Zustand, d. h., sie sind 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 verschränken, versetzen Sie das erste Qubit in einen Superpositionszustand, wobei eine Messung des Qubits in 50 Prozent der Fälle Zero und 50 Prozent der Fälle One zurückgibt. 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. Denken Sie an den X-Vorgang aus der vorherigen Prozedur zum Initialisieren eines Qubits mithilfe der Messung, bei der ein Qubit von 0 in 1 (oder von 1 in 0) umgekehrt wurde. Im Rahmen des H-Vorgangs wird das Qubit halb umgekehrt und dadurch in einen Zustand versetzt, in dem 0 und 1 gleich wahrscheinlich sind. 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 TestBellState-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); 

Wenn Sie nun das Programm ausführen, sehen Sie die Ergebnisse des ersten Qubits in Superposition:

dotnet run --count 1000 --initial One
Q1:Zero/One  Q2:Zero/One
(523, 477, 1000, 0)      // results will vary

Bei jeder Ausführung des Programms variieren die Ergebnisse für das erste Qubit geringfügig, liegen aber meist in 50 Prozent der Fälle bei One und in 50 Prozent der Fälle bei Zero, während die Ergebnisse für das zweite Qubit immer Zero lauten.

dotnet run --count 1000 --initial One
Q1:Zero/One  Q2:Zero/One
(510, 490, 1000, 0)

Beim Initialisieren des ersten Qubits mit Zero werden ähnliche Ergebnisse zurückgegeben.

dotnet run --count 1000 --initial Zero
Q1:Zero/One  Q2:Zero/One
(504, 496, 1000, 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.

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

namespace Bell {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;

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

    @EntryPoint()
    operation TestBellState(count : Int, initial : Result) : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;

        // 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' we saw:
            if resultQ1 == One {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
        
    
        // Return times we saw |0>, times we saw |1>
        Message("q1:Zero, One  q2:Zero, One");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

    }
}

Beim Ausführen des Programms:

dotnet run --count 1000 --initial One
Q1:Zero/One  Q2:Zero/One
(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 zwei Qubits verschränkt, sodass jeder Vorgang, der für eins von Ihnen ausgeführt wird, auch für das andere ausgeführt wird.

Nächste Schritte

Machen Sie sich im Anschluss mit anderen Quantenalgorithmen und -techniken vertraut: