Udostępnij przez


Samouczek: eksplorowanie splątania kwantowego za pomocą polecenia Q#

W tym samouczku napiszesz program Q#, który przygotowuje dwa kubity w określonym stanie kwantowym, manipuluje kubitami w celu ich wzajemnego splątania i wykonuje pomiary, aby zademonstrować efekty superpozycji i splątania. Budujesz swój program Q# kawałek po kawałku, aby przedstawić stany kubitów, operacje kwantowe i pomiary.

Przed rozpoczęciem zapoznaj się z następującymi pojęciami dotyczącymi obliczeń kwantowych:

  • Bity klasyczne przechowują pojedynczą wartość binarną, taką jak 0 lub 1, ale kubity mogą znajdować się w superpozycji dwóch stanów, 0 i 1. Każdy możliwy stan kubitu jest opisany przez zestaw amplitud prawdopodobieństwa.
  • Podczas mierzenia stanu kubitu zawsze otrzymujesz wartość 0 lub 1. Prawdopodobieństwo każdego wyniku jest określane przez amplitudy prawdopodobieństwa, które definiują stan superpozycji podczas pomiaru.
  • Wiele kubitów można splątać w taki sposób, że nie można ich opisać niezależnie od siebie. Podczas mierzenia jednego kubitu w splątanej parze uzyskujesz również informacje o drugim kubitie bez mierzenia go.

W tym poradniku nauczysz się, jak:

  • Tworzenie Q# operacji w celu zainicjowania kubitu do żądanego stanu.
  • Umieść kubit w stanie superpozycji.
  • Splątanie pary kubitów.
  • Mierzenie kubitu i obserwowanie wyników.

Napiwek

Jeśli chcesz przyspieszyć swoją drogę do obliczeń kwantowych, sprawdź Code with Azure Quantum, unikatową funkcję witryny internetowej Microsoft Quantum. W tym miejscu możesz uruchamiać wbudowane Q# przykłady lub własne Q# programy, generować nowy Q# kod z zapytań, otwierać i uruchamiać kod w programie VS Code w wersji internetowej jednym kliknięciem i zadawać pytania Copilot dotyczące obliczeń kwantowych.

Wymagania wstępne

Aby uruchomić przykładowy kod z rozwiązaniem Copilot dla usługi Azure Quantum, musisz mieć konto e-mail firmy Microsoft (MSA).

Aby uzyskać więcej informacji na temat platformy Copilot dla usługi Azure Quantum, zobacz Eksplorowanie usługi Azure Quantum.

Inicjowanie kubitu do znanego stanu

Pierwszym krokiem Q# jest zdefiniowanie operacji, która inicjuje kubit do żądanego stanu klasycznego ( 0 lub 1). Ta operacja mierzy kubit w ogólnym stanie kwantowym, zwracając wartość typu Q#Result, która może być Zero lub One. Jeśli wynik pomiaru różni się od żądanego stanu, operacja zmienia stan tak, aby operacja zwracała żądany stan w 100% przypadków.

Otwórz narzędzie Copilot dla usługi Azure Quantum, wyczyść domyślny kod, a następnie skopiuj poniższy kod do okna edytora kodu. Nie można uruchomić tego kodu samodzielnie, ponieważ nie jest jeszcze kompletnym Q# programem.

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

W przykładzie kodu wprowadzono dwie standardowe operacje Q#, M i X, które przekształcają stan kubitu.

Poniżej przedstawiono szczegółowy opis SetQubitState działania operacji:

  1. Przyjmuje dwa parametry: parametr typu Result o nazwie desired, który reprezentuje żądany stan, w którym ma się znaleźć kubit (Zero lub One), oraz parametr typu Qubit.
  2. Wykonuje operację pomiaru , Mktóra mierzy stan kubitu (Zero lub One) i porównuje wynik z wartością przekazywaną dla desired.
  3. Jeśli wynik pomiaru nie jest zgodny z wartością parametru desired, X operacja zostanie zastosowana do kubitu. Ta operacja odwraca stan kubitu, tak że prawdopodobieństwa pomiaru dla Zero i One zostają zamienione.

Napisz operację testową do przetestowania stanu Bella

Aby wywołać operację SetQubitState w Q# programie, utwórz inną operację o nazwie Main. Ta operacja przydziela dwa kubity, wywołuje metodę SetQubitState ustawiania pierwszego kubitu na znany stan, a następnie mierzy kubity w celu wyświetlenia wyników.

Skopiuj następujący kod do okna edytora kodu po operacji 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 {
            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 );
}

W kodzie zmienne count i initial są ustawione odpowiednio na 1000 i One. Inicjuje to pierwszy kubit do One i mierzy każdy kubit 1000 razy.

Operacja Main wykonuje następujące czynności:

  1. Ustawia zmienne dla liczby zdjęć (count) i początkowego stanu kubitu (One).
  2. Wywołuje instrukcję use, aby zainicjować dwa kubity.
  3. Powtarza eksperyment count razy.
  4. W pętli wywołanie SetQubitState ustawia określoną initial wartość na pierwszym kubicie, a następnie wywołanie SetQubitState ponownie ustawia drugi kubit na stan Zero.
  5. W pętli stosuje operację M do mierzenia każdego kubitu, a następnie przechowuje liczbę pomiarów dla każdego kubitu, który zwraca wartość One.
  6. Po zakończeniu pętli ponownie wywołaj SetQubitState w celu zresetowania kubitów do znanego stanu (Zero). Musisz zresetować kubity, które przydzielasz instrukcją use.
  7. Wywołuje funkcję Message do wydrukowania wyników w oknie danych wyjściowych.

Uruchamianie kodu w narzędziu Copilot dla usługi Azure Quantum

Przed napisaniem kodu dla superpozycji i splątania przetestuj bieżący program, aby zobaczyć, jak przebiega inicjowanie i pomiar kubitów.

Aby uruchomić kod jako autonomiczny program, kompilator w Copilot musi wiedzieć, gdzie uruchomić program Q#. Ponieważ nie określono przestrzeni nazw, kompilator rozpoznaje domyślny punkt wejścia jako operację Main . Aby uzyskać więcej informacji, zobacz Projekty i niejawne przestrzenie nazw.

Twój Q# program wygląda teraz następująco:

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

Skopiuj i wklej kompletny przykładowy kod w oknie Copilot for Azure Quantum Code, ustaw suwak liczby zdjęć na wartość "1", a następnie wybierz pozycję Uruchom. Wyniki są wyświetlane w histogramie i w polach Wyniki .

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

Program nie modyfikuje jeszcze stanów kubitu, więc pomiar pierwszego kubitu zawsze zwraca wartość One, a drugi kubit zawsze zwraca wartość Zero.

Jeśli zmienisz wartość initialZero na i ponownie uruchomisz program, pierwszy kubit również zawsze zwraca wartość Zero.

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

Umieść kubit w stanie superpozycji

Obecnie kubity w programie są w stanie klasycznym ( 1 lub 0), podobnie jak bity na zwykłym komputerze. Aby splątać kubity, należy najpierw umieścić jeden z kubitów w stanie równej superpozycji. Pomiar kubitu w stanie równej superpozycji ma 50% szans na zwrócenie Zero i 50% szans na zwrócenie One.

Aby umieścić kubit w stanie superpozycji, użyj operacji Q#H, czyli operacji Hadamarda. Operacja H konwertuje kubit, który jest w stanie czystym Zero lub One na rodzaj stanu w połowie drogi między Zero i One.

Zmodyfikuj kod w operacji Main. Zresetuj wartość początkową na One i wstaw wiersz dla operacji 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); 
        ...

Uruchom ponownie program. Ponieważ pierwszy kubit znajduje się w równej superpozycji, gdy go mierzysz, zbliżasz się do wyniku 50/50 dla Zero i One. Na przykład dane wyjściowe wyglądają mniej więcej tak:

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

Za każdym razem, gdy uruchamiasz program, wyniki pierwszego kubitu różnią się nieznacznie, ale są zbliżone do 50% i 50% OneZero, podczas gdy wyniki drugiego kubitu są nadal zawsze Zero.

Zainicjuj pierwszy kubit jako Zero zamiast One, a następnie ponownie uruchom program. Otrzymujesz podobne wyniki, ponieważ H operacja zamienia zarówno czysty Zero stan, jak i czysty One stan na stan równej superpozycji.

Uwaga

Aby zobaczyć, jak wyniki superpozycji różnią się w zależności od rozkładu zdjęć, przesuń suwak w Copilot dla usługi Azure Quantum i zwiększ liczbę zdjęć.

Splątanie dwóch kubitów

Splątane kubity są skorelowane w taki sposób, że nie można ich opisać niezależnie od siebie. Podczas mierzenia stanu jednego splątanego kubitu znasz również stan drugiego kubitu bez mierzenia go. W tym samouczku użyto przykładu z dwoma splątanymi kubitami, ale możesz również splątać trzy lub więcej kubitów.

Aby utworzyć stan splątania, użyj operacji Q#CNOT, lub „Controlled-NOT”. W przypadku zastosowania CNOT do dwóch kubitów jeden kubit jest kubitem kontrolnym, a drugi to kubit docelowy. Jeśli stan kubitu sterującego to One, wtedy operacja CNOT przerzuca stan kubitu docelowego. CNOT W przeciwnym razie nie wpływa na kubity.

Dodaj operację CNOT do programu natychmiast po H operacji. Pełny program wygląda następująco:

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

Uruchom program i wyświetl dane wyjściowe. Wyniki nieznacznie różnią się za każdym razem, gdy uruchamiasz program.

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

Statystyki dla pierwszego kubitu nadal pokazują około 50% szansę na zmierzenie zarówno One jak i Zero, ale teraz wyniki pomiaru dla drugiego kubitu nie zawsze są Zero. Każdy kubit ma taką samą liczbę Zero wyników i One wyników. Wynik pomiaru drugiego kubitu jest zawsze taki sam jak wynik pierwszego kubitu, ponieważ dwa kubity są splątane. Jeśli pierwszy kubit jest mierzony jako Zero, wówczas splątany kubit również musi mieć wartość Zero. Jeśli pierwszy kubit jest mierzony jako One, wówczas splątany kubit również musi mieć wartość One.

Wymagania wstępne

Aby utworzyć i uruchomić przykładowy kod w lokalnym środowisku programistycznym, zainstaluj następujące narzędzia:

Tworzenie nowego Q# pliku

  1. W programie VS Code otwórz menu Plik i wybierz pozycję Nowy plik tekstowy , aby utworzyć nowy plik.
  2. Zapisz plik jako CreateBellStates.qs. Ten plik to miejsce, w którym piszesz Q# kod programu.

Inicjowanie kubitu do znanego stanu

Pierwszym krokiem Q# jest zdefiniowanie operacji, która inicjuje kubit do żądanego stanu klasycznego ( 0 lub 1). Ta operacja mierzy kubit w ogólnym stanie kwantowym, zwracając wartość typu Q#Result, która może być Zero lub One. Jeśli wynik pomiaru różni się od żądanego stanu, operacja zmienia stan tak, aby operacja zwracała żądany stan w 100% przypadków.

Otwórz CreateBellStates.qs i skopiuj następujący kod:

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

W przykładzie kodu wprowadzono dwie standardowe operacje Q#, M i X, które przekształcają stan kubitu.

Poniżej przedstawiono szczegółowy opis SetQubitState działania operacji:

  1. Przyjmuje dwa parametry: parametr typu Result o nazwie desired, który reprezentuje żądany stan, w którym ma się znaleźć kubit (Zero lub One), oraz parametr typu Qubit.
  2. Wykonuje operację pomiaru , Mktóra mierzy stan kubitu (Zero lub One) i porównuje wynik z wartością przekazywaną dla desired.
  3. Jeśli wynik pomiaru nie jest zgodny z wartością parametru desired, X operacja zostanie zastosowana do kubitu. Ta operacja odwraca stan kubitu, tak że prawdopodobieństwa pomiaru dla Zero i One zostają zamienione.

Napisz operację testową do przetestowania stanu Bella

Aby wywołać operację SetQubitState w Q# programie, utwórz inną operację o nazwie Main. Ta operacja przydziela dwa kubity, wywołuje metodę SetQubitState ustawiania pierwszego kubitu na znany stan, a następnie mierzy kubity w celu wyświetlenia wyników.

Dodaj następującą operację do CreateBellStates.qs pliku po SetQubitState operacji:

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

W kodzie zmienne count i initial są ustawione odpowiednio na 1000 i One. Inicjuje to pierwszy kubit do One i mierzy każdy kubit 1000 razy.

Operacja Main wykonuje następujące czynności:

  1. Ustawia zmienne dla liczby zdjęć (count) i początkowego stanu kubitu (One).
  2. Wywołuje instrukcję use, aby zainicjować dwa kubity.
  3. Powtarza eksperyment count razy.
  4. W pętli wywołanie SetQubitState ustawia określoną initial wartość na pierwszym kubicie, a następnie wywołanie SetQubitState ponownie ustawia drugi kubit na stan Zero.
  5. W pętli stosuje operację M do mierzenia każdego kubitu, a następnie przechowuje liczbę pomiarów dla każdego kubitu, który zwraca wartość One.
  6. Po zakończeniu pętli ponownie wywołaj SetQubitState w celu zresetowania kubitów do znanego stanu (Zero). Musisz zresetować kubity, które przydzielasz instrukcją use.
  7. Wywołuje funkcję Message, aby wyświetlić wyniki w konsoli.

Uruchamianie kodu

Przed napisaniem kodu dla superpozycji i splątania przetestuj bieżący program, aby zobaczyć, jak przebiega inicjowanie i pomiar kubitów.

Aby uruchomić kod jako autonomiczny program, kompilator musi wiedzieć, Q# gdzie uruchomić program. Ponieważ nie określono przestrzeni nazw, kompilator rozpoznaje domyślny punkt wejścia jako operację Main . Aby uzyskać więcej informacji, zobacz Projekty i niejawne przestrzenie nazw.

Plik CreateBellStates.qs wygląda teraz następująco:

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

Aby uruchomić program, wybierz polecenie Uruchom z CodeLens, który poprzedza operację Main, lub naciśnij Ctrl + F5. Program uruchamia operację Main w domyślnym symulatorze.

Dane wyjściowe są wyświetlane w konsoli debugowania.

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

Program nie modyfikuje jeszcze stanów kubitu, więc pomiar pierwszego kubitu zawsze zwraca wartość One, a drugi kubit zawsze zwraca wartość Zero.

Jeśli zmienisz wartość initialZero na i ponownie uruchomisz program, pierwszy kubit również zawsze zwraca wartość Zero.

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

Umieść kubit w stanie superpozycji

Obecnie kubity w programie są w stanie klasycznym ( 1 lub 0), podobnie jak bity na zwykłym komputerze. Aby splątać kubity, należy najpierw umieścić jeden z kubitów w stanie równej superpozycji. Pomiar kubitu w stanie równej superpozycji ma 50% szans na zwrócenie Zero i 50% szans na zwrócenie One.

Aby umieścić kubit w stanie superpozycji, użyj operacji Q#H, czyli operacji Hadamarda. Operacja H konwertuje kubit, który jest w stanie czystym Zero lub One na rodzaj stanu w połowie drogi między Zero i One.

Zmodyfikuj kod w operacji Main. Zresetuj wartość początkową na One i wstaw wiersz dla operacji 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); 
        ...

Uruchom ponownie program. Ponieważ pierwszy kubit znajduje się w równej superpozycji, gdy go mierzysz, otrzymasz wynik bliski 50/50 dla Zero i One. Na przykład dane wyjściowe wyglądają mniej więcej tak:

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

Za każdym razem, gdy uruchamiasz program, wyniki pierwszego kubitu różnią się nieznacznie, ale są zbliżone do 50% i 50% OneZero, podczas gdy wyniki drugiego kubitu są nadal zawsze Zero.

Pierwszy kubit zainicjuj jako Zero zamiast One i ponownie uruchom program. Otrzymujesz podobne wyniki, ponieważ H operacja zamienia zarówno czysty Zero stan, jak i czysty One stan na stan równej superpozycji.

Splątanie dwóch kubitów

Splątane kubity są skorelowane w taki sposób, że nie można ich opisać niezależnie od siebie. Podczas mierzenia stanu jednego splątanego kubitu znasz również stan drugiego kubitu bez mierzenia go. W tym samouczku użyto przykładu z dwoma splątanymi kubitami, ale możesz również splątać trzy lub więcej kubitów.

Aby utworzyć stan splątania, użyj operacji Q#CNOT, lub „Controlled-NOT”. W przypadku zastosowania CNOT do dwóch kubitów jeden kubit jest kubitem kontrolnym, a drugi to kubit docelowy. Jeśli stan kubitu sterującego to One, wtedy operacja CNOT przerzuca stan kubitu docelowego. CNOT W przeciwnym razie nie wpływa na kubity.

Dodaj operację CNOT do programu natychmiast po H operacji. Pełny program wygląda następująco:

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

Uruchom program i wyświetl dane wyjściowe. Wyniki nieznacznie różnią się za każdym razem, gdy uruchamiasz program.

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

Statystyki dla pierwszego kubitu nadal pokazują około 50% szansę na zmierzenie zarówno One jak i Zero, ale teraz wyniki pomiaru dla drugiego kubitu nie zawsze są Zero. Każdy kubit ma taką samą liczbę Zero wyników i One wyników. Wynik pomiaru drugiego kubitu jest zawsze taki sam jak wynik pierwszego kubitu, ponieważ dwa kubity są splątane. Jeśli pierwszy kubit jest mierzony jako Zero, wówczas splątany kubit również musi mieć wartość Zero. Jeśli pierwszy kubit jest mierzony jako One, wówczas splątany kubit również musi mieć wartość One.

Wykreśl histogram częstotliwości

Aby wykreślić histogram częstotliwości, który pokazuje rozkład wyników podczas wielokrotnego uruchamiania programu, wykonaj następujące kroki:

  1. CreateBellStates.qs Otwórz plik w programie VS Code.

  2. Otwórz menu Widok i wybierz pozycję Paleta poleceń.

  3. Wprowadź histogram, aby wyświetlić opcję QDK: Uruchom plik i pokaż histogram. Możesz też wybrać polecenie Histogram z opcji CodeLens, która poprzedza operację Main. Następnie wprowadź liczbę zdjęć (na przykład 100). Histogram Q# otwiera się na nowej karcie.

    Każdy pasek w histogramie odpowiada możliwemu wynikowi, gdy obwód splątania działa 1000 razy. Wysokość słupka reprezentuje liczbę wystąpień wyniku. Na przykład poniższy histogram przedstawia rozkład z 50 unikatowymi wynikami. Należy pamiętać, że dla każdego wyniku wyniki pomiaru dla pierwszego i drugiego kubitu są zawsze takie same.

    Zrzut ekranu przedstawiający okno histogramu Q# w programie Visual Studio Code.

    Napiwek

    Aby powiększyć histogram, użyj kółka przewijania myszy lub gestu klawiatury. Aby powięksić wykres, przytrzymaj Alt podczas przewijania.

  4. Wybierz pasek, aby wyświetlić procent wszystkich strzałów, które wygenerowały ten wynik.

  5. Wybierz ikonę ustawień w lewym górnym rogu, aby wyświetlić opcje wizualizacji.

    Zrzut ekranu przedstawiający ustawienia wyświetlania okna histogramu Q# w programie Visual Studio Code.

  6. Uruchom ponownie kod, ale tym razem w 1000 prób. Wraz ze wzrostem liczby zdjęć rozkład wyników zbliża się do normalnego rozkładu.

Zapoznaj się z innymi Q# samouczkami:

  • Algorytm wyszukiwania Grovera pokazuje, jak napisać Q# program korzystający z algorytmu wyszukiwania Grovera.
  • Quantum Fourier Transform bada sposób pisania Q# programu, który bezpośrednio dotyczy określonych kubitów.
  • Quantum Katas to samouczki samodzielne i ćwiczenia programistyczne, które uczą jednocześnie elementów obliczeń kwantowych i Q# programowania.