Ć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! Przyjrzyjmy się superpozycji w języku Q#, pisząc kod.

W tej lekcji utworzysz superpozycję kwantową i poznasz prawdopodobieństwa w języku Q# przy użyciu DumpMachine funkcji . Funkcja DumpMachine zrzutuje informacje o bieżącym stanie systemu kwantowego w momencie, w którym jest wywoływana.

Tworzenie nowego pliku języka Q#

  1. Otwórz Visual Studio Code.
  2. W programie Visual Studio Code wybierz pozycję Plik nowy plik tekstowy i zapisz plik jako Main.qs>.
  3. Wybierz pozycję Widok —> paleta poleceń i wpisz Q#: Ustaw profil docelowy usługi Azure Quantum QIR. Naciśnij klawisz Enter.
  4. Wybierz pozycję Q#: Bez ograniczeń.

Wprowadzenie do superpozycji

Zacznijmy od prostego programu, który generuje losowy bit przy użyciu kubitu w superpozycji. Użyjesz DumpMachine funkcji , aby zobaczyć stan kubitu w różnych punktach programu.

  1. Dodaj następujący kod do pliku Main.qs :

    import Microsoft.Quantum.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;
    }
    

    Wywołujemy w nim funkcję DumpMachine cztery razy:

    • Po przydzieleniu kubitu.
    • Po wprowadzeniu kubitu w superpozycji.
    • Po zmierzeniu stanu kubitu.
    • Po zresetowaniu kubitu.

    Operację MResetZ podzieliliśmy na dwie: M oraz Reset. Zrobiliśmy to, by sprawdzić stan po każdym pomiarze.

  2. Aby uruchomić program w wbudowanym symulatorze, kliknij przycisk Uruchom powyżej operacji lub naciśnij Ctrl+F5.Main Dane wyjściowe zostaną wyświetlone w konsoli debugowania.

  3. Funkcja DumpMachine tworzy tabelę przedstawiająca informacje opisujące stan rejestru kubitów. W szczególności zawiera ona amplitudę prawdopodobieństwa, prawdopodobieństwo i fazę w radianach dla każdego stanu bazowego.

  4. Na końcu programu uzyskasz wynik Zero lub One. Przyjrzyjmy się poszczególnym krokom.

    1. Zainicjowany kubit: każdy kubit przydzielony za pomocą use instrukcji rozpoczyna się w stanie $|0\rangle$. A zatem funkcja DumpMachine podaje informacje, które odnoszą się do jednokubitowego rejestru w stanie $|0\rangle$.

      Initialized qubit:
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
         |0⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
      
    2. Kubit po zastosowaniu H: po zastosowaniu Hprzygotowujemy kubit w stanie superpozycji $|\psi\rangle=\frac1{\sqrt2} |0\rangle + \frac1{\sqrt2} |1\rangle$.

      Qubit after applying H:
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
         |0⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
         |1⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
      
    3. Kubit po pomiarze: po zmierzeniu i przechowywaniu wyniku, który może być wartością Zero lub One. Na przykład jeśli wynikowy stan to One, stan rejestrów zwinie się do $|1\rangle$ i nie jest już w superpozycji.

      Qubit after the measurement:
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
         |1⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
      
    4. Kubit po zresetowaniu: operacja Reset resetuje kubit do stanu $|0\rangle$. Należy pamiętać, że dla każdej operacji w języku Q# zawsze należy pozostawić używane kubity w stanie $|0\rangle$, aby nadawały się do użycia przez inne operacje.

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

    Uwaga

    Dane wyjściowe mogą się różnić, ponieważ generator liczb losowych jest probabilistyczny. Prawdopodobieństwa wyników nie są deterministyczne.

Eksplorowanie innych typów stanów superpozycji

Teraz, gdy wiesz, jak sprawdzić stan rejestru, możesz zobaczyć więcej operacji, które modyfikują stan kubitów i umieszczają je w superpozycji.

Popularny generator liczb losowych generuje wartość Zero lub One z prawdopodobieństwem 50%. Przyjrzyjmy się innemu przykładowi, który generuje liczby losowe z różnym prawdopodobieństwem.

Skośny generator bitów losowych

Załóżmy, że chcesz utworzyć generator bitów losowych, który jest niesymetryczny, czyli prawdopodobieństwo pobrania Zero różni się od prawdopodobieństwa uzyskania Onewartości .

Na przykład chcesz, aby wynik Zero z prawdopodobieństwem $P$ i wynikiem 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$$

Tutaj $\alpha=\sqrt{P}$ i $\beta=\sqrt{1-P}$ są amplitudami stanów bazowych $|0\rangle$ i $|1\rangle$, odpowiednio.

Ten stan można uzyskać sekwencyjnie stosując operator $R_y(2\arccos\sqrt{P})$ do kubitu w stanie $|0\rangle.$ Możesz osiągnąć ten wynik w języku Q#, używając operacji Ry w bibliotece 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).

  1. Zmodyfikuj plik Main.qs , tak jak w poniższym przykładzie, a następnie zapisz plik. W tym przykładzie wybrano wartość $\alpha$ jako około $\frac13$.

    import Microsoft.Quantum.Diagnostics.*;
    import Microsoft.Quantum.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.");
        Message("");
        DumpMachine(); // Dump the state of the qubit 
        Message("");
        Message("Your skewed random bit is:");
        let skewedrandomBit = M(q);
        Reset(q);
        return skewedrandomBit;
    }
    
  2. Aby uruchomić program w wbudowanym symulatorze, kliknij przycisk Uruchom powyżej operacji lub naciśnij Ctrl+F5.Main Dane wyjściowe zostaną wyświetlone w konsoli debugowania.

  3. Możesz zobaczyć, jak funkcja DumpMachine wyświetla stan oczekiwany po zastosowaniu operacji i wyświetla powiązane prawdopodobieństwa. Zwróć uwagę, że prawdopodobieństwo uzyskania wynosi około 33,33%, a prawdopodobieństwo uzyskania Zero One wynosi około 66,67%. W związku z tym generator bitów losowych jest niesymetryczny.

    The qubit is in the desired state.
    
    DumpMachine:
    
     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:
    Result: "One"
    

    Uwaga

    Dane wyjściowe mogą się różnić, ponieważ generator liczb losowych jest probabilistic. Prawdopodobieństwa wyników nie są deterministyczne.

Superpozycja wielu kubitów

Teraz przyjrzyjmy się superpozycji rejestru z wieloma kubitami. Jeśli na przykład rejestr składa się z trzech kubitów, może zawierać osiem stanów bazowych:

$$|000\rangle,|001\rangle,|010\rangle,|011\rangle,|100\rangle,|101\rangle, |110\rangle,|111\rangle $$

Czyli możesz wyrazić dowolny 3-kubitowy stan jako:

$$|\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$$

W tym miejscu $\alpha_i$ są liczbami złożonymi, które spełniają wartość $\sum|\alpha_i|^2=1$.

Można na przykład umieścić kubity w jednolitej superpozycji, stosując je H do każdego kubitu. Możesz użyć tej jednolitej superpozycji, aby utworzyć inną wersję kwantowego generatora liczb losowych, który generuje liczby 3-bitowe przez pomiar trzech kubitów w superpozycji zamiast jednego kubitu trzy razy.

Podstawa Liczba
$\ket{000}$ 0
$\ket{001}$ 1
$\ket{010}$ 2
$\ket{011}$ 3
$\ket{100}$ 100
$\ket{101}$ 5
$\ket{110}$ 6
$\ket{111}$ 7
  1. Zmodyfikuj plik Main.qs , tak jak w poniższym przykładzie, a następnie zapisz plik.

    import Microsoft.Quantum.Diagnostics.*;
    import Microsoft.Quantum.Math.*;
    import Microsoft.Quantum.Convert.*;
    import Microsoft.Quantum.Arrays.*;
    
    operation Main() : Int {
        use qubits = Qubit[3];
        ApplyToEach(H, qubits);
        Message("The qubit register in a uniform superposition: ");
        DumpMachine();
        let result = ForEach(M, qubits);
        Message("Measuring the qubits collapses the superposition to a basis state.");
        DumpMachine();
        ResetAll(qubits);
        return BoolArrayAsInt(ResultArrayAsBoolArray(result));
    }
    

    W tym miejscu zobaczysz trzy pojęcia:

    • Zmienna qubits reprezentuje teraz tablicę Qubit o długości trzy.
    • Operacje ApplyToEach i ForEach są przydatne do mierzenia i wykonywania działań na wielu kubitach, a także używają mniejszej ilości kodu. Biblioteki Q# oferują wiele rodzajów operacji i funkcji, które sprawiają, że pisanie programów kwantowych jest bardziej wydajne.
    • Funkcje BoolArrayAsInt i ResultArrayAsBoolArray z Microsoft.Quantum.Convert biblioteki przekształcają tablicę binarną Result zwracaną przez ForEach(M, qubits) element w liczbę całkowitą.
  2. Aby uruchomić program, kliknij przycisk Uruchom powyżej Main operacji lub naciśnij Ctrl+F5. Dane wyjściowe zostaną wyświetlone w konsoli debugowania.

  3. Przy użyciu funkcji DumpMachine można zobaczyć, jak czynność mierzenia trzech kubitów zwija stan rejestru do jednego z ośmiu możliwych stanów bazowych. Jeśli na przykład otrzymasz wynik 3, oznacza to, że stan rejestru zwinął się do $|110\rangle$.

    The qubit register in a uniform superposition:
    
    DumpMachine:
    
     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.
    
    DumpMachine:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |110⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
    
    Result: "3"
    

    Uwaga

    Dane wyjściowe mogą się różnić, ponieważ generator liczb losowych jest probabilistic. Prawdopodobieństwa wyników nie są deterministyczne.

  4. Operacja ForEach(M, qubit) mierzy każdy kubit po kolei, stopniowo zwijając stan. Można również zrzucić stany pośrednie po każdym pomiarze. W tym celu zmodyfikuj plik Main.qs , tak jak w poniższym przykładzie, a następnie zapisz plik.

    import Microsoft.Quantum.Diagnostics.*;
    import Microsoft.Quantum.Measurement.*;
    import Microsoft.Quantum.Math.*;
    import Microsoft.Quantum.Convert.*;
    
    operation Main() : Int {
        use qubits = Qubit[3];
        ApplyToEach(H, qubits);
        Message("The qubit register in a uniform superposition: ");
        DumpMachine();
        mutable results = [];
        for q in qubits {
            Message(" ");
            set results += [M(q)];
            DumpMachine();
        }
        Message(" ");
        Message("Your random number is: ");
        ResetAll(qubits);
        return BoolArrayAsInt(ResultArrayAsBoolArray(results));
    }
    
  5. W tym miejscu należy użyć pętli for do sekwencyjnego działania na każdym kubicie. Język Q# ma klasyczne funkcje sterowania przepływem, takie jak for pętle i if instrukcje, których można użyć do sterowania przepływem programu.

  6. Aby uruchomić program, kliknij pozycję Uruchom z listy poleceń powyżej Main operacji lub naciśnij Ctrl+F5.

  7. Można zobaczyć, jak każdy kolejny pomiar zmienia stan kwantowy, a w związku z tym prawdopodobieństwa uzyskania poszczególnych wyników. Jeśli na przykład wynik to liczba pięć, otrzymasz następujące dane wyjściowe. Przyjrzyjmy się krótko poszczególnym krokom:

    1. Przygotowanie stanu: po zastosowaniu H do każdego kubitu rejestru uzyskujemy jednolitą superpozycję.

      The qubit register in a uniform superposition: 
      
      DumpMachine:
      
       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
      
    2. Pierwsza miara: W pierwszym pomiarze wynik to One. W związku z tym wszystkie amplitudy stanów, których skrajny kubit z prawej strony to Zero, nie są już obecne. Te amplitudy to $|0\rangle=|000\rangle, |2\rangle=|010\rangle, |4\rangle=|100\rangle$ i $|6\rangle= |110\rangle$. Pozostałe amplitudy zwiększają się w celu spełnienia warunku normalizacji.

      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
       |001⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
       |011⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
       |101⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
       |111⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
      
    3. Drugi pomiar: W drugim pomiarze wynik to Zero. W związku z tym wszystkie amplitudy stanów, których drugi skrajny kubit z prawej strony (środkowy) to One, znikają. Te amplitudy to $|3\rangle=|011\rangle$ and $|7\rangle=|111\rangle$. Pozostałe amplitudy zwiększają się w celu spełnienia warunku normalizacji.

      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
       |001⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
       |101⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
      
    4. Trzeci pomiar: W trzecim pomiarze wynik to One. W związku z tym wszystkie amplitudy stanów, których kubit po lewej stronie jest Zero jasny. Jedynym zgodnym stanem jest $|5\rangle=|101\rangle$. Ten stan otrzymuje prawdopodobieństwo amplitudy wynoszące $1$.

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

    Uwaga

    Dane wyjściowe mogą się różnić, ponieważ generator liczb losowych jest probabilistic. Prawdopodobieństwa wyników nie są deterministyczne.