Bramki jednokubitowe

Podstawowe bramki jednokubitowe

Znasz już bramkę Hadamarda, bramkę \(X\) oraz bramki rotacji (\(R_x\), \(R_y\), \(R_z\))

Dla przypomnienia :

Bramka \(X\):

\[ \textbf{X} = \begin{bmatrix} 0 \,\, 1 \\ 1 \,\, 0 \end{bmatrix} \]

\[ \textbf{X} \ket{0} = \begin{bmatrix} 0\,\, 1 \\ 1 \, 0 \end{bmatrix} \begin{bmatrix} 1 \\ 0 \end{bmatrix} = \begin{bmatrix} 0 \\ 1 \end{bmatrix} = \ket{1} \] oraz \[ \textbf{X} \ket{0} = \begin{bmatrix} 0\,\, 1 \\ 1 \, 0 \end{bmatrix} \begin{bmatrix} 0 \\ 1 \end{bmatrix} = \begin{bmatrix} 1 \\ 0 \end{bmatrix} = \ket{0} \]

Bramka \(H\):

\[ \textbf{H}= \frac{1}{\sqrt{2}}\begin{bmatrix} 1\,\,\,\,\,\,\, 1 \\ 1 \, -1 \end{bmatrix} \]

dla której

\[ \textbf{H} \ket{0} = \frac{1}{\sqrt{2}}\begin{bmatrix} 1\,\,\,\,\,\,\, 1 \\ 1 \, -1 \end{bmatrix} \begin{bmatrix} 1 \\ 0 \end{bmatrix} = \frac{1}{\sqrt{2}} \left( \ket{0} + \ket{1} \right) = \ket{+} \] oraz \[ \textbf{H} \ket{1} = \frac{1}{\sqrt{2}}\begin{bmatrix} 1\,\,\,\,\,\,\, 1 \\ 1 \, -1 \end{bmatrix} \begin{bmatrix} 0 \\ 1 \end{bmatrix} = \begin{bmatrix} 0 \\ 1 \end{bmatrix} = \frac{1}{\sqrt{2}} \left( \ket{0} - \ket{1} \right) = \ket{-} \]

Losowy bit

klasycznie

# generator liczb losowych
from random import randrange
''.join([str(randrange(2)) for i in range(8)])

lub

# mozna takze zrealizowac jako rzut monetą 

import random
for n in range(5):
    if random.random()<0.5:       #if the random number is less than 0.5 print heads
        print('HEADS')
    else:
        print('TAILS')

KWANTOWO

  • Użyj default.qubit jako klasyczny symulator w funkcji device

  • zmień funkcję qc w obwód kwantowy korzystając z dekoratora @qml.qnode

  • zdefinuj funkcję qc z jednym kubitem

  • na kubicie wykorzystaj bramkę Hadamarda

  • wyświetl stan po pomiarze pojedynczego kubitu

  • wyświetl prawdopodobieństwa otrzymania stanu 0 i 1

  • uruchom obwód 3 razy (do dev dodaj parametr , shots=3) i sprawdź wyniki otrzymywane przez metodę qml.counts() link

  • uruchom powyzszą prcedurę 100 razy

Do jakiego zdarzenia losowego podobne są wyniki?

Losowy bajt

  • bajt to 8 bitów - jaki zakres wartości jesteś w stanie przechowywać w 8 kubitach ?

  • wygeneruj losowy bajt z wykorzystaniem tylko bramki X

if randrange(2) == 0:
        qc.x(i)
  • wygeneruj losowy bajt z wykorzystaniem bramek hadamarda

  • wygeneruj 10 prób w pełni losowego bajtu - odkoduj wyniki w systemie int

  • oblicz różnicę dwóch bajtów dla których pierwsze cztery bity to 0, piąty bit pierwszego bajtu to 0 a drugiego bajtu to 1 . pozostałe bity są równe 1

Losowa liczba w zakresie 0-15

  • Za pomocą odpowiedniego obwodu kwantowego wylosuj liczbę z zakresu 0-15

  • Wykorzystaj 1000 wykonań modelu i narysuj histogram wyników dla poszczególnych liczb 0-15

Wartość oczekiwana operatora Z na obwodzie

Rozszerz wygenerowany obwód dla losowego bitu i dodaj parametryzowaną bramkę \(R_x\) z kątem ustawionym jako pi/4

Oblicz wartość oczekiwaną operatora \(<\sigma_z>\) wykorzystując qml.expval(qml.PauliZ(0))

Bramka (i operator) Z, w bazie obliczeniowej dany jest macierzą: \[ \textbf{Z} = \begin{bmatrix} 1 \,\,\,\,\,\,\,\, 0 \\ 0 \,\, -1 \end{bmatrix} \]

Operator ten mierzy różnicę pomiędzy prawdopodobieństwem, że kubit jest w stanie \(\ket{0}\) a prawdopodobieństwem, że jest w stanie \(\ket{1}\)

W ogólności wartość oczekiwana (wartość średnia wyniku pomiaru w bazie operatora Z) dana jest wzorem: \[ \textbf{<Z>} = \bra{\psi} \textbf{Z} \ket{\psi} \]

Niech \[ \ket{\psi} = \alpha\ket{0} + \beta\ket{1} \] wtedy \[ \bra{\psi} = \alpha^*\bra{0} + \beta^*\bra{1} \]

Możemy obliczyć: \[ \bra{\psi} \textbf{Z} \ket{\psi} = (\alpha^*\bra{0} + \beta^*\bra{1} ) \,\,\, Z \,\,\,(\alpha\ket{0} + \beta\ket{1}) = |\alpha|^2 - |\beta|^2 \] Czyli dla kubitu w stanie \(\ket{0}\) \[ \textbf{<Z>} = 1 \] Dla kubitu w stanie \(\ket{1}\) \[ \textbf{<Z>} = -1 \] Dla kubitu w superpozycji \(\ket{0} +\ket{1}\) \[ \textbf{<Z>} = 0 \]

Gra w obracanie monety

Wykorzystując powyżej zdefiniowane bramki możemy zrealizowa następującą grę:

W grze bierze udział dwóch graczy. Gracze dysponują monetą, której nie widzą w trakcie gry (np. jest zamknięta w pudełku). Natomiast wiedzą, że początkowo moneta ułożona jest orłem do góry (w stanie \(\ket{0}\)) Gra polega na wykonaniu trzech ruchów na przemian. Każdy ruch polega na odwróceniu monety bądź pozostawieniu jej w takim stanie w jakim była. Gracze nie wiedzą jaki ruch wykonuje przeciwnik. Po ostatnim ruchu pudełko zostaje otwarte i gracze sprawdzają w jakiej pozycji jest moneta. Pierwszy gracz wygrywa jeśli moneta jest w pozycji orła, a drugi jeśli przeciwnie.

Szansa wygranej wynosi dla każdego \(50\%\) i jak można sprawdzic nie istnieje strategia wygrywająca.

Zweryfikuj powyższy wynik wykorzystując obwód kwantowy.

def klasycze_strategie():
    wyniki = []
    for ruch_1 in ['I','X']:
        for ruch_2 in ['I','X']:
            for ruch_3 in ['I','X']:
                strategia = ruch_1 + ruch_2 + ruch_3
                ob = obwod(strategia)
                stats = sedzia(ob())
                wyniki.append((strategia, stats))
    return wyniki

Utwórz odpowiedni obwód parametryzowany stringiem “strategia” oraz dodaj funkcję sędziego.

Obracanie monety przypadek kwantowy

Możliwe operacje pozostawienia kubitu w takim samym stanie - bramka I, zmiany stanu na przeciwny bramka X.

Czyli pierwszy gracz ustala pierwszą bramkę, drugi drugą i ponownie pierwszy trzecią. Otwarcie pudełka to pomiar stanu kubitu.

Przeanalizuj wynik dla sekwencji I X I

A co jeśli pierwszy gracz wie, że działa na kubicie?

Czy może sprawic on, że wygra zawsze? (skoro wie, że działa na kubicie może użyc innych bramek)

zmodyfikuj kod obwodu i sprawdź strategię w której pierwszy gracz zawsze użyje dwóch bramek Hadamarda.


def kwantowa_strategia():
    wyniki = []
    for ruch_1 in ['H']:
        for ruch_2 in ['I','X']:
            for ruch_3 in ['H']:
                strategia = ruch_1 + ruch_2 + ruch_3
                ob = obwod(strategia)
                stats = sedzia(ob())
                wyniki.append((strategia, stats))
    return wyniki