Samouczek: eksplorowanie splątania kwantowego za pomocą polecenia Q#
W tym samouczku napiszesz Q# program, który manipuluje kubitami i mierzy je oraz demonstruje skutki superpozycji i splątania. Przygotowujesz dwa kubity w określonym stanie kwantowym, dowiesz się, jak działać na kubitach Q# , aby zmienić ich stan, i zademonstrować skutki superpozycji i splątania. Program jest Q# kompilowany po kawałku, aby wprowadzić stany, operacje i pomiary kubitów.
Poniżej przedstawiono kilka kluczowych pojęć, które należy zrozumieć przed rozpoczęciem:
- Jeśli bity klasyczne przechowują pojedynczą wartość binarną, taką jak 0 lub 1, stan kubitu może być w superpozycji dwóch stanów kwantowych, 0 i 1. Każdy możliwy stan kwantowy ma skojarzona amplituda prawdopodobieństwa.
- Czynność pomiaru kubitu generuje wynik binarny z pewnym prawdopodobieństwem i zmienia stan kubitu poza superpozycję.
- Wiele kubitów można splątać w taki sposób, że nie można ich opisać niezależnie od siebie. Oznacza to, że cokolwiek się dzieje z jednym kubitem w splątanej parze również dzieje się z drugim kubitem.
Z tego samouczka dowiesz się, jak wykonywać następujące czynności:
- Tworzenie Q# operacji w celu zainicjowania kubitu do żądanego stanu.
- Umieść kubit w superpozycji.
- Splątanie pary kubitów.
- Mierzenie kubitu i obserwowanie wyników.
Napiwek
Jeśli chcesz przyspieszyć podróż obliczeń kwantowych, zapoznaj się z kodem w usłudze Azure Quantum, unikatową funkcją witryny internetowej Azure Quantum. W tym miejscu możesz uruchamiać wbudowane Q# przykłady lub własne Q# programy, generować nowy Q# kod z monitów, otwierać i uruchamiać kod w programie VS Code dla sieci Web jednym kliknięciem i zadawać Copilot wszelkie pytania dotyczące obliczeń kwantowych.
Wymagania wstępne
Aby uruchomić przykładowy kod w aplikacji Copilot dla usługi Azure Quantum, potrzebne są następujące elementy:
- Konto e-mail microsoft (MSA).
Aby uzyskać więcej informacji o copilot, zobacz Eksplorowanie usługi Azure Quantum.
Inicjowanie kubitu do znanego stanu
Pierwszym krokiem Q# jest zdefiniowanie operacji, która inicjuje kubit do znanego stanu. Tę operację można wywołać, aby ustawić kubit na stan klasyczny, co oznacza, że w przypadku pomiaru zwraca Zero
100% czasu lub zwraca One
100% czasu. Pomiar kubitu Q# zwraca typ Result
, który może mieć tylko wartość Zero
lub One
.
Otwórz narzędzie Copilot dla usługi Azure Quantum i skopiuj następujący kod do okna edytora kodu. Nie klikaj jeszcze przycisku Uruchom . W dalszej części samouczka uruchomisz kod.
import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
W przykładzie kodu wprowadzono dwie standardowe operacje i M
X
, które przekształcają stan kubitu.
SetQubitState
Operacja:
- Przyjmuje dwa parametry: typ
Result
o nazwiedesired
, który reprezentuje żądany stan kubitu, który ma być w (Zero
lubOne
) i typemQubit
. - Wykonuje operację pomiaru ,
M
która mierzy stan kubitu (Zero
lubOne
) i porównuje wynik z wartością określoną w .desired
- Jeśli pomiar nie jest zgodny z porównywaną wartością, uruchamia operację
X
, która przerzuca stan kubitu, gdzie prawdopodobieństwo zwracaniaZero
miary iOne
są odwrócone. W ten sposóbSetQubitState
zawsze umieszcza kubit docelowy w żądanym stanie.
Pisanie operacji testowej w celu przetestowania stanu dzwonka
Następnie, aby zademonstrować efekt SetQubitState
operacji, utwórz inną operację o nazwie Main
. Ta operacja przydzieli dwa kubity, wywołaj metodę SetQubitState
, aby ustawić pierwszy kubit do znanego stanu, a następnie zmierzy kubity, aby wyświetlić wyniki.
Skopiuj poniższy kod do okna edytora SetQubitState
kodu poniżej 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 {
set numOnesQ1 += 1;
}
if resultQ2 == One {
set 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 count
zmienne i initial
są ustawione odpowiednio na 1000
i One
. Inicjuje to pierwszy kubit do One
i mierzy każdy kubit 1000 razy.
Main
Operacja:
- Ustawia zmienne dla licznika i początkowy stan kubitu.
- Wywołuje instrukcję w
use
celu zainicjowania dwóch kubitów. - Pętle iteracji
count
. Dla każdej pętli- Wywołuje
SetQubitState
metodę ustawiania określonejinitial
wartości na pierwszym kubitie. - Wywołuje
SetQubitState
ponownie polecenie , aby ustawić drugi kubit naZero
stan. M
Używa operacji do mierzenia każdego kubitu.- Przechowuje liczbę pomiarów dla każdego kubitu, który zwraca wartość
One
.
- Wywołuje
- Po zakończeniu pętli wywołuje
SetQubitState
ponownie polecenie , aby zresetować kubity do znanego stanu (Zero
), aby umożliwić innym przydzielanie kubitów w znanym stanie. Zresetowanie jest wymagane przez instrukcjęuse
. - Na koniec używa
Message
funkcji do drukowania wyników w oknach danych wyjściowych Copilot przed zwróceniem wyników.
Uruchamianie kodu w copilot for Azure Quantum
Przed przejściem do procedur superpozycji i splątania można przetestować kod do tego momentu, aby zobaczyć inicjowanie i pomiar kubitów.
Aby uruchomić kod jako autonomiczny program, kompilator w Copilot 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.
Twój Q# program powinien teraz wyglądać następująco:
import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;
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 {
set numOnesQ1 += 1;
}
if resultQ2 == One {
set 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 slajd liczby zdjęć na wartość "1", a następnie kliknij przycisk Uruchom. Wyniki są wyświetlane w histogramie i w polach Wyniki .
Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 1000
Q2 - Ones: 0
Ponieważ kubity nie zostały jeszcze manipulowane, zachowały swoje początkowe wartości: pierwszy kubit zwraca One
za każdym razem, a drugi kubit zwraca wartość Zero
.
Jeśli zmienisz wartość initial
na Zero
i ponownie uruchomisz program, należy zauważyć, że pierwszy kubit zwraca Zero
również za każdym razem.
Q1 - Zeros: 1000
Q1 - Ones: 0
Q2 - Zeros: 1000
Q2 - Ones: 0
Napiwek
Zaznacz Ctrl-Z lub Edytuj > cofnij i zapisz plik za każdym razem, gdy wprowadzisz zmianę testu w kodzie przed ponownym uruchomieniem.
Umieszczanie kubitu w superpozycji
Obecnie kubity w programie są w stanie klasycznym, czyli są 1 lub 0. Wiesz, że to dlatego, że program inicjuje kubity do znanego stanu i nie dodano żadnych procesów do manipulowania nimi. Przed splątaniem kubitów należy umieścić pierwszy kubit w stanie superpozycji, gdzie pomiar kubitu zwraca Zero
ok. 50% czasu i One
ok. 50% czasu. Koncepcyjnie kubit można traktować jako równy prawdopodobieństwo pomiaru wartości Zero
lub One
.
Aby umieścić kubit w superpozycji, Q# zapewnia operację H
, lub Hadamard. X
Przypomnij sobie operację z inicjowania kubitu do znanej procedury stanu wcześniej, która przerzuciła kubit z zakresu od 0 do 1 (lub odwrotnie); H
operacja przerzuca kubit w połowie stanu równego prawdopodobieństwa Zero
lub One
. Po zmierzeniu kubit w superpozycji powinien zwrócić mniej więcej taką samą liczbę Zero
wyników i One
.
Zmodyfikuj kod w Main
operacji, resetując wartość początkową do One
i wstawiając wiersz dla H
operacji:
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);
...
Teraz po uruchomieniu programu można zobaczyć wyniki pierwszego kubitu w superpozycji.
Q1 - Zeros: 523 // results vary
Q1 - Ones: 477
Q2 - Zeros: 1000
Q2 - Ones: 0
Za każdym razem, gdy uruchamiasz program, wyniki pierwszego kubitu różnią się nieznacznie, ale będą się nieznacznie różnić od 50% do 50% i 50% One
Zero
, podczas gdy wyniki drugiego kubitu pozostają Zero
cały czas.
Q1 - Zeros: 510
Q1 - Ones: 490
Q2 - Zeros: 1000
Q2 - Ones: 0
Inicjowanie pierwszego kubitu w celu Zero
zwracania podobnych wyników.
Q1 - Zeros: 504
Q1 - Ones: 496
Q2 - Zeros: 1000
Q2 - Ones: 0
Uwaga
Przesuwając suwak w copilot dla usługi Azure Quantum i zwiększając liczbę zdjęć, możesz zobaczyć, jak wyniki superpozycji różnią się nieznacznie w zależności od rozkładu zdjęć.
Splątanie dwóch kubitów
Jak wspomniano wcześniej, splątane kubity są połączone w taki sposób, że nie można ich opisać niezależnie od siebie. Oznacza to, że niezależnie od operacji dzieje się z jednym kubitem, występuje również splątany kubit. Dzięki temu można znać stan wynikowy jednego kubitu bez mierzenia go, po prostu mierząc stan drugiego kubitu. (W tym przykładzie użyto dwóch kubitów; jednak istnieje również możliwość splątania co najmniej trzech kubitów).
Aby włączyć splątanie, Q# zapewnia operację CNOT
, która oznacza Controlled-NOT. Wynikiem uruchomienia tej operacji na dwóch kubitach jest przerzucanie drugiego kubitu, jeśli pierwszy kubit to One
.
Dodaj operację CNOT
do programu natychmiast po H
operacji. Pełny program powinien wyglądać następująco:
import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;
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 {
set numOnesQ1 += 1;
}
if resultQ2 == One {
set 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 );
}
Teraz po uruchomieniu programu powinny zostać wyświetlone następujące elementy:
Q1 - Zeros: 502 // results will vary
Q1 - Ones: 498
Q2 - Zeros: 502
Q2 - Ones: 498
Zwróć uwagę, że statystyki dla pierwszego kubitu nie uległy zmianie (nadal istnieje prawdopodobieństwo Zero
ok. 50/50 wartości lub One
po pomiarze), ale wyniki pomiaru dla drugiego kubitu są zawsze takie same jak pomiar pierwszego kubitu, niezależnie od tego, ile razy uruchamiasz program. Operacja CNOT
splątała dwa kubity, aby cokolwiek się z nimi stało, dzieje się z drugim.
Wymagania wstępne
Aby utworzyć i uruchomić przykładowy kod w lokalnym środowisku projektowym:
- Najnowsza wersja programu Visual Studio Code lub otwórz program VS Code w sieci Web.
- Najnowsza wersja rozszerzenia zestawu Azure Quantum Development Kit. Aby uzyskać szczegółowe informacje na temat instalacji, zobacz Instalowanie zestawu QDK w programie VS Code.
Tworzenie nowego Q# pliku
- Otwórz program Visual Studio Code i wybierz pozycję Plik > nowy plik tekstowy, aby utworzyć nowy plik.
- Zapisz plik jako
CreateBellStates.qs
. Ten plik będzie zawierać Q# kod programu.
Inicjowanie kubitu do znanego stanu
Pierwszym krokiem Q# jest zdefiniowanie operacji, która inicjuje kubit do znanego stanu. Tę operację można wywołać, aby ustawić kubit na stan klasyczny, co oznacza, że zwraca Zero
100% czasu lub zwraca One
100% czasu. Zero
i One
są Q# wartościami reprezentującymi tylko dwa możliwe wyniki pomiaru kubitu.
Otwórz CreateBellStates.qs
i skopiuj następujący kod:
import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
W przykładzie kodu wprowadzono dwie standardowe operacje i M
X
, które przekształcają stan kubitu.
SetQubitState
Operacja:
- Przyjmuje dwa parametry: typ
Result
o nazwiedesired
, który reprezentuje żądany stan kubitu, który ma być w (Zero
lubOne
) i typemQubit
. - Wykonuje operację pomiaru ,
M
która mierzy stan kubitu (Zero
lubOne
) i porównuje wynik z wartością określoną w .desired
- Jeśli pomiar nie jest zgodny z porównywaną wartością, uruchamia operację
X
, która przerzuca stan kubitu, gdzie prawdopodobieństwo zwracaniaZero
miary iOne
są odwrócone. W ten sposóbSetQubitState
zawsze umieszcza kubit docelowy w żądanym stanie.
Pisanie operacji testowej w celu przetestowania stanu dzwonka
Następnie, aby zademonstrować efekt SetQubitState
operacji, utwórz inną operację o nazwie Main
. Ta operacja przydziela dwa kubity, wywołaj metodę SetQubitState
, aby ustawić pierwszy kubit do znanego stanu, a następnie zmierzy kubity, aby wyświetlić wyniki.
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 {
set numOnesQ1 += 1;
}
if resultQ2 == One {
set 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 count
zmienne i initial
są ustawione odpowiednio na 1000
i One
. Ten krok inicjuje pierwszy kubit do One
i mierzy każdy kubit 1000 razy.
Main
Operacja:
- Przyjmuje dwa parametry:
count
, liczbę razy do uruchomienia pomiaru iinitial
, żądany stan inicjowania kubitu. - Wywołuje instrukcję w
use
celu zainicjowania dwóch kubitów. - Pętle iteracji
count
. Dla każdej pętli- Wywołuje
SetQubitState
metodę ustawiania określonejinitial
wartości na pierwszym kubitie. - Wywołuje
SetQubitState
ponownie polecenie , aby ustawić drugi kubit naZero
stan. M
Używa operacji do mierzenia każdego kubitu.- Przechowuje liczbę pomiarów dla każdego kubitu, który zwraca wartość
One
.
- Wywołuje
- Po zakończeniu pętli wywołuje
SetQubitState
ponownie polecenie , aby zresetować kubity do znanego stanu (Zero
), aby umożliwić innym przydzielanie kubitów w znanym stanie. Zresetowanie kubitu jest wymagane przez instrukcjęuse
. - Na koniec używa
Message
funkcji do drukowania komunikatu w konsoli przed zwróceniem wyników.
Uruchamianie kodu
Przed przejściem do procedur superpozycji i splątania przetestuj kod do tego momentu, aby zobaczyć 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
powinien teraz wyglądać następująco:import Microsoft.Quantum.Intrinsic.*; import Microsoft.Quantum.Canon.*; 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 { set numOnesQ1 += 1; } if resultQ2 == One { set 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 ); }
Przed uruchomieniem programu upewnij się, że profil docelowy ma ustawioną wartość Unrestricted. Wybierz pozycję Widok — paleta poleceń, wyszukaj pozycję QIR, wybierz pozycjęQ# : Ustaw profil docelowy usługi Azure Quantum QIR, a następnie wybierz pozycję Q#: nieograniczone.>
Uwaga
Jeśli profil docelowy nie jest ustawiony na Unrestricted, podczas uruchamiania programu zostanie wyświetlony błąd.
Aby uruchomić program, wybierz pozycję Uruchom Q# plik z listy rozwijanej ikona odtwarzania w prawym górnym rogu, wybierz pozycję Uruchom z listy poleceń poprzedzających
Main
operację 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
Ponieważ kubity nie zostały jeszcze manipulowane, zachowały swoje początkowe wartości: pierwszy kubit zwraca
One
za każdym razem, a drugi kubit zwraca wartośćZero
.Jeśli zmienisz wartość
initial
naZero
i ponownie uruchomisz program, należy zauważyć, że pierwszy kubit zwracaZero
również za każdym razem.Q1 - Zeros: 1000 Q1 - Ones: 0 Q2 - Zeros: 1000 Q2 - Ones: 0
Napiwek
Zaznacz Ctrl-Z lub Edytuj > cofnij i zapisz plik za każdym razem, gdy wprowadzisz zmianę testu w kodzie przed ponownym uruchomieniem.
Umieszczanie kubitu w superpozycji
Obecnie kubity w programie są w stanie klasycznym, czyli są 1 lub 0. Wiesz, że to dlatego, że program inicjuje kubity do znanego stanu i nie dodano żadnych procesów do manipulowania nimi. Przed splątaniem kubitów należy umieścić pierwszy kubit w stanie superpozycji, gdzie pomiar kubitu zwraca Zero
50% czasu i One
50% czasu. Koncepcyjnie kubit może być uważany za w połowie między i Zero
One
.
Aby umieścić kubit w superpozycji, Q# zapewnia operację H
, lub Hadamard. X
Przypomnij sobie operację z inicjalizacji kubitu do znanej procedury stanu wcześniej, która przerzuciła kubit z Zero
do One
(lub odwrotnie); H
operacja przerzuca kubit w połowie stanu równego prawdopodobieństwa Zero
lub One
. Po zmierzeniu kubit w superpozycji powinien zwrócić mniej więcej taką samą liczbę Zero
wyników i One
.
Zmodyfikuj
Main
kod w operacji, aby uwzględnić operację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); ...
Teraz po uruchomieniu programu można zobaczyć wyniki pierwszego kubitu w superpozycji:
Q1 - Zeros: 523 // results will vary Q1 - Ones: 477 Q2 - Zeros: 1000 Q2 - Ones: 0
Za każdym razem, gdy uruchamiasz program, wyniki pierwszego kubitu różnią się nieznacznie, ale będą się nieznacznie różnić od 50% do 50% i 50%
One
Zero
, podczas gdy wyniki drugiego kubitu pozostająZero
cały czas.Q1 - Zeros: 510 Q1 - Ones: 490 Q2 - Zeros: 1000 Q2 - Ones: 0
Inicjowanie pierwszego kubitu w celu
Zero
zwracania podobnych wyników.Q1 - Zeros: 504 Q1 - Ones: 496 Q2 - Zeros: 1000 Q2 - Ones: 0
Splątanie dwóch kubitów
Jak wspomniano wcześniej, splątane kubity są połączone w taki sposób, że nie można ich opisać niezależnie od siebie. Oznacza to, że niezależnie od operacji dzieje się z jednym kubitem, występuje również splątany kubit. Dzięki temu można znać stan wynikowy jednego kubitu bez mierzenia go, po prostu mierząc stan drugiego kubitu. (W tym przykładzie użyto dwóch kubitów; jednak istnieje również możliwość splątania co najmniej trzech kubitów).
Aby włączyć splątanie, Q# zapewnia operację CNOT
, która oznacza Controlled-NOT. Wynikiem uruchomienia tej operacji na dwóch kubitach jest przerzucanie drugiego kubitu, jeśli pierwszy kubit to One
.
Dodaj operację
CNOT
do programu natychmiast poH
operacji. Pełny program powinien wyglądać następująco:import Microsoft.Quantum.Intrinsic.*; import Microsoft.Quantum.Canon.*; 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 { set numOnesQ1 += 1; } if resultQ2 == One { set 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 ); }
Q1 - Zeros: 502 Q1 - Ones: 498 // results will vary Q2 - Zeros: 502 Q2 - Ones: 498 Result: "(502, 498, 502, 498)"
Statystyki dla pierwszego kubitu nie uległy zmianie (prawdopodobieństwo Zero
50/50 wartości lub One
po pomiarze), ale wyniki pomiaru drugiego kubitu są zawsze takie same jak pomiar pierwszego kubitu. Operacja CNOT
splątała dwa kubity, tak aby cokolwiek się z nimi dzieje, dzieje się z drugim.
Wykreślenie histogramu częstotliwości
Zwizualizujmy rozkład wyników uzyskanych z wielokrotnego uruchamiania programu kwantowego. Histogram częstotliwości pomaga wizualizować rozkład prawdopodobieństwa tych wyników.
Wybierz pozycję Widok —> Paleta poleceń lub naciśnij Ctrl+Shift+P, a następnie wpisz "histogram", który powinien wywołać Q#polecenie : Uruchom plik i wyświetlić opcję histogramu. Możesz również wybrać pozycję Histogram z listy poleceń poprzedzających
Main
polecenie . Wybierz tę opcję, aby otworzyć okno histogramu Q# .Wprowadź liczbę zdjęć do wykonania programu, na przykład 100 zdjęć, a następnie naciśnij Enter. Histogram jest wyświetlany w oknie histogramu Q# .
Każdy słupek w histogramie odpowiada możliwemu wynikowi, a jego wysokość reprezentuje liczbę obserwowanych wyników. W tym przypadku istnieje 50 różnych unikatowych wyników. Należy pamiętać, że dla każdego wyniku wyniki pomiaru dla pierwszego i drugiego kubitu są zawsze takie same.
Napiwek
Histogram można powiększyć za pomocą kółka przewijania myszy lub gestu klawiatury. Po powiększeniu wykres można przesuwać, naciskając Alt podczas przewijania.
Wybierz pasek, aby wyświetlić procent tego wyniku.
Wybierz ikonę ustawień w lewym górnym rogu, aby wyświetlić opcje. Możesz wyświetlić 10 pierwszych wyników, 25 pierwszych wyników lub wszystkie wyniki. Możesz również posortować wyniki z wysokiej do niskiej lub niskiej do wysokiej.
Powiązana zawartość
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 mające na celu nauczanie elementów obliczeń kwantowych i Q# programowania w tym samym czasie.