Ćwiczenie — tworzenie różnych stanów superpozycji przy użyciu języka Q#

Ukończone

W poprzednich lekcjach przedstawiono superpozycję i notację Dirac. To już wystarczająco dużo teorii! Napiszmy kod, aby eksplorować superpozycję w języku Q#.

W tej lekcji utworzysz stany superpozycji kwantowej w języku Q# i zapoznasz się z rolą prawdopodobieństwa w wynikach pomiaru. Używasz również funkcji DumpMachine w języku Q#, aby sprawdzić, jak zmienia się stan systemu podczas obliczeń kwantowych.

Tworzenie nowego pliku języka Q#

  1. Otwórz program Visual Studio Code (VS Code).
  2. Otwórz menu Plik , a następnie wybierz pozycję Nowy plik tekstowy , aby utworzyć nowy plik.
  3. Zapisz plik jako Main.qs.

Wprowadzenie do superpozycji

Zacznijmy od prostego programu języka Q#, który używa kubitu w stanie superpozycji do generowania losowej wartości bitowej, 0 lub 1. W naszym kodzie używamy DumpMachine funkcji do wyświetlenia stanu kubitu w różnych punktach programu.

  1. Skopiuj i wklej następujący kod do pliku Main.qs :

    import Std.Diagnostics.*;
    
    operation Main() : Result {
        use q = Qubit();
        Message("Initialized qubit:");
        DumpMachine(); // First dump
        Message(" ");
        H(q);
        Message("Qubit after applying H:");
        DumpMachine(); // Second dump
        Message(" ");
        let randomBit = M(q);
        Message("Qubit after the measurement:");
        DumpMachine(); // Third dump
        Message(" ");
        Reset(q);
        Message("Qubit after resetting:");
        DumpMachine(); // Fourth dump
        Message(" ");
        return randomBit;
    }
    
  2. Aby uruchomić program w wbudowanym symulatorze, wybierz Uruchom soczewkę kodu powyżej Main operacji lub naciśnij Ctrl + F5. Dane wyjściowe są wyświetlane w konsoli debugowania.

  3. Sprawdź konsolę debug, aby znaleźć wynik pomiaru: albo Zero, albo One.

Funkcja DumpMachine tworzy tabelę informacji opisującą stan systemu kwantowego, który w tym przypadku jest pojedynczym kubitem. Informacje z DumpMachine obejmują amplitudę prawdopodobieństwa, prawdopodobieństwo pomiaru i fazę w radianach dla każdego stanu bazowego.

Kod wywołuje DumpMachine funkcję cztery razy:

  • Po przydzieleniu kubitu
  • Po wprowadzeniu kubitu do stanu superpozycji
  • Po zmierzeniu stanu kubitu
  • Po zresetowaniu kubitu

Przeanalizujmy dane wyjściowe z każdego wywołania do DumpMachine:

  • Zainicjowany kubit: Gdy przydzielasz kubit za pomocą instrukcji use, zawsze zaczyna on w stanie $|0\rangle$.

    Initialized qubit:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
       |0⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
    
  • Kubit po zastosowaniu H: Po zastosowaniu H operacji kubit jest w stanie równej superpozycji $|\psi\rangle=\frac1{\sqrt2} |0\rangle + \frac1{\sqrt2} |1\rangle$.

    Qubit after applying H:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
       |0⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
       |1⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
    
    
  • Kubit po pomiarze: Po zmierzeniu kubitu wynik to Zero lub One, a kubit jest w pełni w stanie mierzonym.

    Qubit after the measurement:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
       |1⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
    

    Uwaga

    Dane wyjściowe z DumpMachine po pomiarze mogą różnić się od przykładowych danych wyjściowych, ponieważ masz 50% szansę mierzenia każdego stanu. Prawdopodobieństwa wyników są deterministyczne, ale wynik indywidualnej miary nie jest.

  • Kubit po zresetowaniu: Operacja Reset resetuje kubit do stanu $|0\rangle$, aby można go było ponownie wykorzystać w przyszłych obliczeniach.

    Qubit after resetting:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
       |0⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
    

Eksplorowanie innych stanów superpozycji

Teraz, gdy już wiesz, jak zbadać stan systemu kubitów za pomocą DumpMachine, przyjrzyjmy się innym operacjom, które umieszczają system w różnych rodzajach stanów superpozycji.

Bieżący generator bitów losowych generuje wartość Zero lub One z prawdopodobieństwem 50%. W następnym przykładzie prawdopodobieństwo nie jest równe.

Skośny generator bitów losowych

Załóżmy, że chcesz utworzyć generator bitów losowych, który jest zróżnicowany, co oznacza, że prawdopodobieństwo uzyskania Zero różni się od prawdopodobieństwa uzyskania One.

Na przykład chcesz, aby wynik Zero z prawdopodobieństwem $P$ lub wynik One z prawdopodobieństwem $1 - P$. Oto prawidłowy stan kubitu, który generuje taki generator bitów losowych:

$$|\psi\rangle=\sqrt{P}|0\rangle+\sqrt{1 - P}|1\rangle$$

Dla tego stanu $|\psi\rangle$, $\alpha=\sqrt{P}$ i $\beta=\sqrt{1 - P}$ są amplitudami prawdopodobieństwa odpowiednio stanów bazowych $|0\rangle$ i $|1\rangle$.

Aby uzyskać ten stan, można sekwencyjnie zastosować operator $R_y(2\cos^{-1}\sqrt{P})$ do kubitu, który rozpoczyna się w stanie $|0\rangle$. Aby osiągnąć ten wynik w języku Q#, użyj elementu Ry z biblioteki standardowej.

Napiwek

Aby dowiedzieć się więcej na temat obliczeń matematycznych związanych z operacjami na jednym kubitie, zapoznaj się z samouczkiem Single-Kubit Gates w artykule Quantum Katas (Scenariusze Quantum Kata).

Aby utworzyć niesymetryczny stan superpozycji w języku Q#, wykonaj następujące kroki:

  1. Zastąp cały kod w pliku Main.qs poniższym przykładem, a następnie zapisz plik. W tym przykładzie wybrano wartość $\alpha$ jako około $\frac13$.

    import Std.Diagnostics.*;
    import Std.Math.*;
    
    operation Main() : Result {
        use q = Qubit();
        let P = 0.333333; // P is 1/3
        Ry(2.0 * ArcCos(Sqrt(P)), q);
        Message("The qubit is in the desired state.");
        DumpMachine(); // Dump the state of the qubit 
        Message("Your skewed random bit is:");
        let skewedrandomBit = M(q);
        Reset(q);
        return skewedrandomBit;
    }
    
  2. Aby uruchomić program w wbudowanym symulatorze, wybierz przycisk Uruchom nad kodem Main operacji lub naciśnij Ctrl + F5. Dane wyjściowe są wyświetlane w konsoli debugowania.

  3. Sprawdź dane wyjściowe z DumpMachine i wynik pomiaru. Na przykład dane wyjściowe są podobne do następujących:

    The qubit is in the desired state.
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
       |0⟩ |  0.5773+0.0000𝑖 |    33.3333% |   0.0000
       |1⟩ |  0.8165+0.0000𝑖 |    66.6667% |   0.0000
    
    Your skewed random bit is:
    
    One
    

Zwróć uwagę, że prawdopodobieństwo Zero wyniku pomiaru wynosi około 33,33%, a prawdopodobieństwo One wyniku wynosi około 66,67%. Ten generator bitów losowych ma tendencję w stronę One.

Uwaga

Dane wyjściowe wyniku pomiaru mogą różnić się od przykładowych danych wyjściowych, ponieważ generator bitów losowych jest probabilistyczny. Prawdopodobieństwa wyników są deterministyczne, ale wynik indywidualnej miary nie jest.

Superpozycja wielu kubitów

Do tej pory rozważaliśmy tylko systemy pojedynczego kubitu. Jednak dobry komputer kwantowy potrzebuje wielu kubitów do wykonywania przydatnych obliczeń. Jak działają stany kwantowe i superpozycja, gdy nasz system ma więcej niż jeden kubit?

Rozważmy na przykład system trzech kubitów. Każdy kubit może mieć wartość 0 lub 1 podczas ich mierzenia, więc istnieje osiem możliwych stanów, w których można znaleźć system:

$$|000 kąt\r,|001 kąt\r,|010 kąt\r,|011 kąt\r,|100 kąt\r,|101 kąt\r,|110 kąt\r,|111 kąt\r$$

Istnieje osiem możliwych stanów dla tego systemu, ponieważ każdy kubit może być niezależnie stanem 0 lub 1, gdy bierzemy pomiar. Ogólnie rzecz biorąc, liczba możliwych stanów jest równa $2^n$, gdzie $n$ jest liczbą kubitów.

Podobnie jak w przypadku pojedynczego kubitu, dowolny stan superpozycji dla systemu 3-kubitowego jest reprezentowany jako ważona suma tych ośmiu stanów, gdzie wagi są amplitudami prawdopodobieństwa:

$$|\psi\rangle=\alpha_0|000\rangle+\alpha_1|001\rangle+\alpha_2|010\rangle+\alpha_3|011\\ rangle+\alpha_4|100\rangle+\alpha_5|101\rangle+\alpha_6 |110\rangle+\alpha_7|111\rangle$$

Po raz kolejny amplitudy $\alpha_i$ to liczby złożone spełniające warunek $\sum\limits_{i=0}^{i=7}|\alpha_i|^2=1$.

Można na przykład umieścić kubity w jednolitej superpozycji, stosując je H do każdego kubitu. Następnie można użyć tej jednolitej superpozycji, aby utworzyć kwantowy generator liczb losowych, który generuje liczby trzy bitowe zamiast liczb jedno bitowych:

Stan podstawy Liczba
$\ket{000}$ 0
$\ket{001}$ 100
$\ket{010}$ 2
$\ket{011}$ 6
$\ket{100}$ 1
$\ket{101}$ 5
$\ket{110}$ 3
$\ket{111}$ 7

Uwaga

Standardowym sposobem na pisanie ciągów bitowych jest posiadanie najmniejszej cyfry po prawej stronie i największej cyfry po lewej stronie, podobnie jak w przypadku zwykłych liczb dziesiętnych. W języku Q# (i wielu innych językach programowania kwantowego) kolejność jest odwrócona, tak aby najmniejsza cyfra znajduje się po lewej stronie, a największa cyfra znajduje się po prawej stronie. DumpMachine Ponieważ funkcja wyświetla stany kwantowe w standardowej kolejności, liczby całkowite dziesiętne, które odpowiadają stanom, nie są uporządkowane sekwencyjnie z zakresu od 0 do $n-1$.

Aby utworzyć tego rodzaju generator liczb losowych, wykonaj następujące kroki:

  1. Zastąp kod w pliku Main.qs poniższym przykładem, a następnie zapisz plik:

    import Std.Diagnostics.*;
    import Std.Convert.*;
    
    operation Main() : Int {
        use qubits = Qubit[3];
        ApplyToEach(H, qubits);
        Message("The qubit register in a uniform superposition: ");
        DumpMachine();
        let result = MeasureEachZ(qubits);
        Message("Measuring the qubits collapses the superposition to a basis state.");
        DumpMachine();
        ResetAll(qubits);
        return ResultArrayAsInt(result);
    }
    
  2. Aby uruchomić program w wbudowanym symulatorze, wybierz przycisk Uruchom nad kodem Main operacji lub naciśnij Ctrl + F5. Dane wyjściowe są wyświetlane w konsoli debugowania.

  3. Sprawdź dane wyjściowe z DumpMachine i wynik pomiaru. Na przykład dane wyjściowe są podobne do następujących:

    The qubit register in a uniform superposition: 
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |000⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |001⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |010⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |011⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |100⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |101⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |110⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |111⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
    
    Measuring the qubits collapses the superposition to a basis state.
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |011⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
    
    6
    

    Uwaga

    Dane wyjściowe prawdopodobnie mają inny wynik niż przykładowe dane wyjściowe, ponieważ generator liczb losowych jest probabilistyczny. Prawdopodobieństwa wyników są deterministyczne, ale wynik indywidualnej miary nie jest.

Aby pracować z wieloma kubitami, kod języka Q# ma następujące modyfikacje:

  • Zmienna qubits reprezentuje teraz tablicę Qubit o długości trzy.
  • Operacje ApplyToEach i MeasureEachZ zastosowują operacje kwantowe do wielu kubitów za pomocą tylko jednej linii kodu. Biblioteki języka Q# oferują wiele funkcji i operacji, które upraszczają programowanie kwantowe.
  • Funkcja ResultArrayAsInt z Std.Convert biblioteki przekształca tablicę binarną Result w liczbę całkowitą dziesiętną.

Dane wyjściowe z DumpMachine pokazują, że akt pomiaru zwija stan superpozycji w jeden z ośmiu możliwych stanów bazowych, podobnie jak w przypadku pojedynczego kubitu. Jeśli na przykład otrzymasz wynik 6, oznacza to, że stan systemu zredukował się do $|011\rangle$.

Teraz przyjrzyjmy się bliżej temu, jak zmienia się system podczas mierzenia każdego kubitu. Poprzedni kod użył MeasureEachZ operacji do zmierzenia wszystkich trzech kubitów jednocześnie. Zamiast tego użyjemy for pętli, aby zmierzyć kubity pojedynczo i użyć DumpMachine do wyświetlenia stanu systemu po każdym pomiarze.

  1. Zastąp kod w pliku Main.qs poniższym przykładem, a następnie zapisz plik:

    import Std.Diagnostics.*;
    import Std.Convert.*;
    
    operation Main() : Int {
        use qubits = Qubit[3];
        ApplyToEach(H, qubits);
        Message("The qubit register is in a uniform superposition: ");
        DumpMachine();
        mutable results = [];
        for q in qubits {
            Message(" ");
            results += [M(q)];
            DumpMachine();
        }
        ResetAll(qubits);
        Message("Your random number is: ");
        return ResultArrayAsInt(results);
    }
    
  2. Aby uruchomić program w wbudowanym symulatorze, wybierz przycisk Uruchom nad kodem Main operacji lub naciśnij Ctrl + F5. Dane wyjściowe są wyświetlane w konsoli debugowania.

  3. Sprawdź dane wyjściowe z DumpMachine i wynik pomiaru.

Dane wyjściowe pokazują, jak każda kolejna miara zmienia stan kwantowy i w związku z tym prawdopodobieństwo uzyskania każdego wyniku. Przyjrzyjmy się na przykład każdej części danych wyjściowych w przypadku, gdy wynik to 5:

  • Przygotowanie stanu: system jest w stanie równej superpozycji po zastosowaniu H do każdego kubitu.

    The qubit register is in a uniform superposition: 
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |000⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |001⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |010⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |011⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |100⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |101⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |110⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |111⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
    
  • Pierwszy pomiar: Wynik jest One dla pierwszej miary, więc teraz jedynymi możliwymi stanami, w których system może się znajdować, są stany, w których najwięcej bitów po lewej stronie wynosi 1. Amplitudy stanów, w których najbardziej lewy kubit wynosi 0, zniknęły, a prawdopodobieństwo pozostałych możliwych stanów wzrasta z 12,5% do 25,0%, aby suma prawdopodobieństwa pozostała 100%.

     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |100⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
     |101⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
     |110⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
     |111⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
    
  • Drugi pomiar: Wynik jest Zero dla drugiej miary, więc teraz jedynymi możliwymi stanami, w których system może się znajdować, są stany, w których dwa najbardziej lewe bity to 10. Teraz pozostało nam tylko dwa możliwe wyniki, gdy mierzymy trzeci kubit z prawdopodobieństwem 50% dla każdego wyniku.

     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |100⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
     |101⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
    
  • Trzeci pomiar: W trzecim pomiarze wynik to One. System został w pełni zmierzony i w związku z tym nie jest już w stanie superpozycji, zgodnie z oczekiwaniami.

     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |101⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
    
    Your random number is: 
    
    5
    

Za pomocą języka Q#można utworzyć system kubitów, umieścić kubity w stanie superpozycji i sprawdzić, jak system zmienia się podczas stosowania operacji kwantowych lub wykonywania pomiarów.