Implementasyon sa Qiskit
Sa araling ito, ipapatupad natin ang ilan sa mga ideya mula sa aralin tungkol sa entanglement in action, gamit ang Qiskit.
# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util
_needed = {"qiskit": "qiskit", "qiskit_aer": "qiskit-aer"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
from qiskit import __version__
print(__version__)
2.1.1
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit_aer import AerSimulator
from qiskit.visualization import plot_histogram, array_to_latex
from qiskit.result import marginal_distribution
from qiskit.circuit.library import UGate
from math import pi
import random
Narito ang isang implementasyon ng teleportation protocol gamit ang quantum circuit.
qubit = QuantumRegister(1, "Q")
ebit0 = QuantumRegister(1, "A")
ebit1 = QuantumRegister(1, "B")
a = ClassicalRegister(1, "a")
b = ClassicalRegister(1, "b")
protocol = QuantumCircuit(qubit, ebit0, ebit1, a, b)
# Prepare ebit used for teleportation
protocol.h(ebit0)
protocol.cx(ebit0, ebit1)
protocol.barrier()
# Alice's operations
protocol.cx(qubit, ebit0)
protocol.h(qubit)
protocol.barrier()
# Alice measures and sends classical bits to Bob
protocol.measure(ebit0, a)
protocol.measure(qubit, b)
protocol.barrier()
# Bob uses the classical bits to conditionally apply gates
with protocol.if_test((a, 1)):
protocol.x(ebit1)
with protocol.if_test((b, 1)):
protocol.z(ebit1)
display(protocol.draw(output="mpl"))
Gumagamit ang circuit ng ilang tampok ng Qiskit na hindi pa natin nakita sa mga nakaraang aralin, kabilang ang mga function na barrier at if_test.
Ang function na barrier ay lumilikha ng visual na paghihiwalay upang mas madaling basahin ang diagram ng circuit, at pinipigilan din nito ang Qiskit na magsagawa ng iba't ibang simplipikasyon at optimisasyon sa kahabaan ng barrier sa panahon ng compilation kapag pinatakbo ang mga circuit sa totoong hardware.
Ang function na if_test ay naglalapat ng operasyon nang may kondisyon batay sa isang classical bit o register.
Una, sinimulan ng circuit ang sa estado na (na hindi bahagi ng protocol mismo), kasunod ang mga operasyon ni Alice, pagkatapos ang kanyang mga sukat, at sa wakas ang mga operasyon ni Bob. Para masuri kung tama ang paggana ng protocol, mag-aaplay tayo ng isang random na single-qubit gate sa initialized na estado na ng upang makakuha ng random na quantum state vector na ite-teleport. Sa pamamagitan ng pag-aplay ng inverse (ibig sabihin, ang conjugate transpose) ng gate na iyon sa pagkatapos mapatakbo ang protocol, mapatutunayan natin na na-teleport ang estado sa pamamagitan ng pagsukat upang makitang bumalik ito sa estado na .
Una, random na pipiliin natin ang isang unitary qubit gate.
random_gate = UGate(
theta=random.random() * 2 * pi,
phi=random.random() * 2 * pi,
lam=random.random() * 2 * pi,
)
display(array_to_latex(random_gate.to_matrix()))
Ngayon, gagawa tayo ng bagong testing circuit na una ay mag-aaplay ng ating random gate sa , pagkatapos ay patatakbuhin ang teleportation circuit, at sa wakas ay mag-aaplay ng inverse ng ating random gate sa qubit at susukat. Ang resulta ay dapat na nang may katiyakan.
# Create a new circuit including the same bits and qubits used in the
# teleportation protocol.
test = QuantumCircuit(qubit, ebit0, ebit1, a, b)
# Start with the randomly selected gate on Q
test.append(random_gate, qubit)
test.barrier()
# Append the entire teleportation protocol from above.
test = test.compose(protocol)
test.barrier()
# Finally, apply the inverse of the random unitary to B and measure.
test.append(random_gate.inverse(), ebit1)
result = ClassicalRegister(1, "Result")
test.add_register(result)
test.measure(ebit1, result)
display(test.draw(output="mpl"))
Sa wakas, patakbuhin natin ang Aer simulator sa circuit na ito at mag-plot ng histogram ng mga output. Makikita natin ang mga estadistika para sa lahat ng tatlong classical bits: ang pinakamababa/pinakakaliwang bit ay dapat laging , na nagpapahiwatig na matagumpay na na-teleport ang qubit sa , habang ang dalawang ibang bits ay dapat na halos pantay-pantay.
result = AerSimulator().run(test).result()
statistics = result.get_counts()
display(plot_histogram(statistics))
Maaari rin nating i-filter ang mga estadistika upang tumuon lamang sa test result qubit kung gusto natin, ganito:
filtered_statistics = marginal_distribution(statistics, [2])
display(plot_histogram(filtered_statistics))
Superdense Coding
Ang superdense coding ay isang protocol na, sa ilang paraan, nagtatamasa ng layuning kabaliktaran ng teleportation. Sa halip na payagan ang pagpapadala ng isang qubit gamit ang dalawang classical bits ng komunikasyon (sa gastos ng isang e-bit ng entanglement), pinapayagan nito ang pagpapadala ng dalawang classical bits gamit ang isang qubit ng quantum na komunikasyon (muli, sa gastos ng isang e-bit ng entanglement).
Sa mas detalyadong paraan, mayroon tayong isang nagpapadala (Alice) at isang tumatanggap (Bob) na nagbabahagi ng isang e-bit ng entanglement. Ayon sa mga kombensyon sa aralin, nangangahulugang hawak ni Alice ang isang qubit , hawak ni Bob ang isang qubit , at magkasama ang pares na ay nasa estado na . Nais ni Alice na magpadala ng dalawang classical bits kay Bob, na tatawaging at , at magagawa niya ito sa pamamagitan ng pagpapadala sa kanya ng isang qubit.
Makatwirang tingnan ang tagumpay na ito bilang mas hindi kawili-wili kaysa sa nagagawa ng teleportation. Ang pagpapadala ng mga qubit ay malamang na magiging mas mahirap kaysa sa pagpapadala ng mga classical bit sa mahabang panahon, kaya ang pag-trade ng isang qubit ng quantum na komunikasyon para sa dalawang bits ng classical na komunikasyon, at may kasamang gastos na e-bit pa, ay tila hindi sulit. Gayunpaman, hindi ito nangangahulugang ang superdense coding ay hindi kawili-wili, dahil tiyak na kawili-wili ito.
Alinsunod sa tema ng aralin, isang dahilan kung bakit kawili-wili ang superdense coding ay ipinakita nito ang isang kongkreto at (sa konteksto ng information theory) medyo kapansin-pansing paggamit ng entanglement. Isang kilalang teorema sa quantum information theory, na kilala bilang Holevo's theorem, ay nagpapahiwatig na nang walang paggamit ng shared entangled state, imposibleng makipag-communicate ng higit sa isang bit ng classical na impormasyon sa pamamagitan ng pagpapadala ng isang qubit. (Mas pangkalahatan ang Holevo's theorem kaysa dito. Ang eksaktong pahayag nito ay teknikal at nangangailangan ng paliwanag, ngunit ito ay isa sa mga konsekwensya nito.) Kaya, sa pamamagitan ng superdense coding, ang shared entanglement ay epektibong nagpapahintulot ng pagdoble ng classical information-carrying capacity ng pagpapadala ng mga qubit.
Protocol
Ang sumusunod na quantum circuit diagram ay naglalarawan ng superdense coding protocol:

Sa madaling salita, narito ang ginagawa ni Alice:
-
Kung , nagsasagawa si Alice ng gate sa kanyang qubit (at kung ay hindi siya gumagawa).
-
Kung , nagsasagawa si Alice ng gate sa kanyang qubit (at kung ay hindi siya gumagawa).
Pagkatapos ay ipinapadala ni Alice ang kanyang qubit kay Bob.
Ang ginagawa ni Bob kapag natanggap niya ang qubit ay una ay nagsasagawa ng controlled-NOT gate, kung saan ang ang control at ang ang target, at pagkatapos ay nag-aaplay siya ng Hadamard gate sa . Pagkatapos ay sinusukat niya ang para makuha ang at ang para makuha ang , gamit ang standard basis measurements sa parehong kaso.
Pagsusuri
Ang ideya sa likod ng protocol na ito ay simple: epektibong pinipili ni Alice kung aling Bell state ang gusto niyang ibahagi kay Bob, ipinapadala ni Alice kay Bob ang kanyang qubit, at sinusukat ni Bob upang malaman kung alin ang Bell state na pinili ni Alice.
Iyon ay, una silang nagbabahagi ng at depende sa mga bits na at iniiwanan ni Alice ang estado o inililipat ito sa isa sa ibang mga Bell state sa pamamagitan ng pag-aplay ng o sa kanyang qubit
Ang mga aksyon ni Bob ay may sumusunod na epekto sa apat na Bell state:
Maaari itong suriin nang direkta, sa pamamagitan ng pagkalkula ng mga resulta ng mga operasyon ni Bob sa mga estadong ito nang isa-isa.
Kaya, kapag nagsagawa si Bob ng kanyang mga sukat, nagagawa niyang malaman kung alin ang Bell state na pinili ni Alice. Ang pag-verify na tama ang paggana ng protocol ay isang bagay ng pagsuri sa bawat kaso:
-
Kung , ang estado ng kapag natanggap ni Bob ang ay . Binabago niya ang estadong ito sa at nakukuha ang .
-
Kung , ang estado ng kapag natanggap ni Bob ang ay . Binabago niya ang estadong ito sa at nakukuha ang .
-
Kung , ang estado ng kapag natanggap ni Bob ang ay . Binabago niya ang estadong ito sa at nakukuha ang .
-
Kung , ang estado ng kapag natanggap ni Bob ang ay . Binabago niya ang estadong ito sa at nakukuha ang . (Walang epekto ang negative-one phase factor dito.)
Implementasyon ng superdense coding
Narito ang isang simpleng implementasyon ng superdense coding kung saan tinutukoy natin ang circuit mismo depende sa mga bits na ipapadala. Una, pipiliin natin ang dalawang bits na ipapadala. (Mamaya ay random na pipiliin natin ang mga ito, ngunit sa ngayon ay gagawa lang tayo ng arbitrary na pagpili.)
c = "1"
d = "0"
Ngayon ay itatayo natin ang circuit nang naaayon. Dito ay papayagan natin ang Qiskit na gamitin ang mga default na pangalan para sa mga qubit: para sa itaas na qubit at para sa ibabang isa.
protocol = QuantumCircuit(2)
# Prepare ebit used for superdense coding
protocol.h(0)
protocol.cx(0, 1)
protocol.barrier()
# Alice's operations
if d == "1":
protocol.z(0)
if c == "1":
protocol.x(0)
protocol.barrier()
# Bob's actions
protocol.cx(0, 1)
protocol.h(0)
protocol.measure_all()
display(protocol.draw(output="mpl"))
Hindi masyadong maraming bago dito, maliban sa function na measure_all, na sumusukat sa lahat ng mga qubit at inilalagay ang mga resulta sa isang classical register (at kaya ay may dalawang bits sa kasong ito).
Ang pagpapatakbo ng Aer simulator ay nagbubunga ng inaasahang output.
result = AerSimulator().run(protocol).result()
statistics = result.get_counts()
for outcome, frequency in statistics.items():
print(f"Measured {outcome} with frequency {frequency}")
display(plot_histogram(statistics))
Measured 10 with frequency 1024
Ngayon, gamitin natin ang isang karagdagang qubit bilang random bit generator — sa esensya ay para magtapon ng mga patas na barya. Gagamitin natin ito para random na pumili ng at , at pagkatapos ay patakbuhin ang superdense coding protocol.
rbg = QuantumRegister(1, "coin")
ebit0 = QuantumRegister(1, "A")
ebit1 = QuantumRegister(1, "B")
Alice_c = ClassicalRegister(1, "Alice c")
Alice_d = ClassicalRegister(1, "Alice d")
test = QuantumCircuit(rbg, ebit0, ebit1, Alice_d, Alice_c)
# Initialize the ebit
test.h(ebit0)
test.cx(ebit0, ebit1)
test.barrier()
# Use the 'coin' qubit twice to generate Alice's bits c and d.
test.h(rbg)
test.measure(rbg, Alice_c)
test.h(rbg)
test.measure(rbg, Alice_d)
test.barrier()
# Now the protocol runs, starting with Alice's actions, which depend
# on her bits.
with test.if_test((Alice_d, 1), label="Z"):
test.z(ebit0)
with test.if_test((Alice_c, 1), label="X"):
test.x(ebit0)
test.barrier()
# Bob's actions
test.cx(ebit0, ebit1)
test.h(ebit0)
test.barrier()
Bob_c = ClassicalRegister(1, "Bob c")
Bob_d = ClassicalRegister(1, "Bob d")
test.add_register(Bob_d)
test.add_register(Bob_c)
test.measure(ebit0, Bob_d)
test.measure(ebit1, Bob_c)
display(test.draw(output="mpl"))
Ang pagpapatakbo ng Aer simulator ay nagpapakita ng mga resulta: ang mga classical bits nina Alice at Bob ay palaging magkatugma.
result = AerSimulator().run(test).result()
statistics = result.get_counts()
display(plot_histogram(statistics))
Implementasyon sa Qiskit
Maaari nating ipatupad ang CHSH game, kasama ang quantum na estratehiyang tinukoy sa itaas, sa Qiskit tulad ng sumusunod.
Una, narito ang kahulugan ng laro mismo, na nagpapahintulot na ang isang arbitrary na estratehiya ay mailagay bilang argumento.
def chsh_game(strategy):
# This function runs the CHSH game, using the strategy (a function
# from two bits to two bits), returning 1 for a win and 0 for a loss.
# Choose x and y randomly
x, y = random.randint(0, 1), random.randint(0, 1)
# Use the strategy to determine a and b
a, b = strategy(x, y)
# Decide if the strategy wins or loses
if (a != b) == (x & y):
return 1 # Win
return 0 # Lose
Ngayon ay lilikha tayo ng isang function na naglalabas ng circuit depende sa mga tanong para kay Alice at Bob. Hahayaan nating magkaroon ng mga default na pangalan ang mga qubit para sa kaginhawaan, at gagamitin natin ang built-in na gate para sa mga aksyon ni Alice at Bob.
def chsh_circuit(x, y):
# This function creates a `QuantumCircuit` implementing the quantum
# strategy described above (including the e-bit preparation).
qc = QuantumCircuit(2, 2)
# Prepare an e-bit
qc.h(0)
qc.cx(0, 1)
qc.barrier()
# Alice's actions
if x == 0:
qc.ry(0, 0)
else:
qc.ry(-pi / 2, 0)
qc.measure(0, 0)
# Bob's actions
if y == 0:
qc.ry(-pi / 4, 1)
else:
qc.ry(pi / 4, 1)
qc.measure(1, 1)
return qc
Narito ang apat na posibleng circuit, depende sa kung anong mga tanong ang itatanong.
# Draw the four possible circuits
print("(x,y) = (0,0)")
display(chsh_circuit(0, 0).draw(output="mpl"))
print("(x,y) = (0,1)")
display(chsh_circuit(0, 1).draw(output="mpl"))
print("(x,y) = (1,0)")
display(chsh_circuit(1, 0).draw(output="mpl"))
print("(x,y) = (1,1)")
display(chsh_circuit(1, 1).draw(output="mpl"))
(x,y) = (0,0)
(x,y) = (0,1)
(x,y) = (1,0)
(x,y) = (1,1)
Ngayon ay lilikha tayo ng isang job gamit ang Aer simulator na nagpapatakbo ng circuit nang isang beses para sa isang ibinigay na pares ng input .
def quantum_strategy(x, y):
# This function runs the appropriate quantum circuit defined above
# one time and returns the measurement results
# Setting `shots=1` to run the circuit once
result = AerSimulator().run(chsh_circuit(x, y), shots=1).result()
statistics = result.get_counts()
# Determine the output bits and return them
bits = list(statistics.keys())[0]
a, b = bits[0], bits[1]
return a, b
Sa wakas, maglalaro tayo ng 1000 beses at kukuwentahin ang bahagi ng mga laong nanalo ang estratehiya.
NUM_GAMES = 1000
TOTAL_SCORE = 0
for _ in range(NUM_GAMES):
TOTAL_SCORE += chsh_game(quantum_strategy)
print("Fraction of games won:", TOTAL_SCORE / NUM_GAMES)
Fraction of games won: 0.867
Maaari rin tayong mag-define ng klasikal na estratehiya at tingnan kung gaano ito kagaling. Isa lamang itong estratehiya — ang iba ay maaaring subukan sa pamamagitan ng pagbabago ng code — ngunit isa ito sa mga pinakamainam na klasikal na estratehiya.
def classical_strategy(x, y):
# This function implements just one example of an optimal classical
# strategy for the CHSH game. Other classical strategies can be
# implemented by changing the bit values assigned to a and b.
# Alice's answer
if x == 0:
a = 0
elif x == 1:
a = 1
# Bob's answer
if y == 0:
b = 1
elif y == 1:
b = 0
return a, b
Muli, maglalaro tayo ng 1000 beses upang makita kung gaano ito kagaling.
NUM_GAMES = 1000
TOTAL_SCORE = 0
for _ in range(NUM_GAMES):
TOTAL_SCORE += chsh_game(classical_strategy)
print("Fraction of games won:", TOTAL_SCORE / NUM_GAMES)
Fraction of games won: 0.747
Bagaman may kinalaman ang randomness, malamang na hindi magbago nang husto ang mga estadistika pagkatapos ng 1000 runs. Nananalo ang quantum strategy nang mga 85% ng oras habang hindi kayang manalo ang classical strategy nang higit sa mga 75% ng oras.