Panimula sa Qiskit
Sa notebook na ito, tatalakayin natin kung paano natin maipo-program ang quantum gates at quantum circuits gamit ang Qiskit at kahit paano natin sila mai-execute sa simulators at tunay na quantum computers gamit ang Qiskit patterns. Mamaya, ipapakilala natin ang iba't ibang paraan ng pag-encode ng impormasyon at tatapusin natin sa isang bonus na halimbawa ng Quantum Teleportation.
Bago ka magsimula
Sundin ang Install and set up na mga tagubilin kung hindi mo pa nagagawa, kasama ang mga hakbang upang Set up to use IBM Quantum™ Platform.
Inirerekomenda na gamitin mo ang Jupyter development environment para makipag-ugnayan sa quantum computers. Tiyaking i-install ang inirekomendang extra na visualization support ('qiskit[visualization]'). Kakailanganin mo rin ang matplotlib package para sa pangalawang bahagi ng halimbawang ito.
Para matuto tungkol sa quantum computing sa pangkalahatan, bisitahin ang Basics of quantum information course sa IBM Quantum Learning
Imports
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-aer qiskit-ibm-runtime
# Import necessary modules for this notebook
import time
import qiskit
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_bloch_multivector, plot_state_qsphere
from qiskit_aer import AerSimulator
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import EstimatorV2 as Estimator
from qiskit_ibm_runtime import SamplerV2 as Sampler
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.visualization import plot_histogram
print(qiskit.__version__)
2.3.1
Para mai-execute ang iyong quantum circuits sa hardware, kailangan mo munang i-set up ang iyong account. Maaari mong gawin ito tulad ng sumusunod:
- Pumunta sa upgraded IBM Quantum® Platform.
- Pumunta sa kanang itaas na sulok (gaya ng ipinapakita sa larawan sa itaas), gumawa ng iyong API token, at kopyahin ito sa isang ligtas na lokasyon.
- Sa susunod na cell, palitan ang
deleteThisAndPasteYourAPIKeyHereng iyong API key. - Pumunta sa kaliwang ibabang sulok (gaya ng ipinapakita sa larawan sa itaas) at gumawa ng iyong instance. Tiyaking piliin ang open plan.
- Pagkatapos magawa ang instance, kopyahin ang nauugnay na CRN code nito. Maaaring kailanganin mong mag-refresh upang makita ang instance.
- Sa cell sa ibaba, palitan ang
deleteThisAndPasteYourCRNHereng iyong CRN code.
Tingnan ang guide na ito para sa higit pang detalye kung paano i-set up ang iyong IBM Cloud® account.
⚠️ Tala: Ituring ang iyong API key na gaya ng isang ligtas na password. Tingnan ang Cloud setup guide para sa karagdagang impormasyon tungkol sa paggamit ng iyong API key sa parehong ligtas at hindi pinagkakatiwalaang environments.
#your_api_key = "deleteThisAndPasteYourAPIKeyHere"
#your_crn = "deleteThisAndPasteYourCRNHere"
QiskitRuntimeService.save_account(
channel="ibm_quantum_platform",
token=your_api_key,
instance=your_crn,
overwrite=True
)
1. Quantum Gates at Quantum Circuits
Ang quantum circuits ay mga modelo para sa quantum computation kung saan ang isang computation ay isang sequence ng quantum gates. Tingnan natin ang ilan sa mga sikat na quantum gates.
X Gate
Ang X gate ay katumbas ng rotation sa palibot ng X-axis ng Bloch sphere ng radians. Mina-map nito ang sa at sa . Ito ang quantum equivalent ng NOT gate para sa classical computers at minsan tinatawag na bit-flip.
# Let's apply an X-gate on a |0> qubit
qc = QuantumCircuit(1)
qc.x(0)
qc.draw(output='mpl')
# Let's see Bloch sphere visualization
sv = Statevector(qc)
plot_bloch_multivector(sv)

H Gate
Ang Hadamard gate ay kumakatawan sa isang rotation ng tungkol sa axis na nasa gitna ng -axis at -axis.
Mina-map nito ang basis state sa , na nangangahulugang ang isang sukat ay magkakaroon ng pantay na probabilities ng pagiging 1 o 0, na lumilikha ng 'superposition' ng states. Ang state na ito ay isinusulat din bilang .
# Let's apply an H-gate on a |0> qubit
qc = QuantumCircuit(1)
qc.x(0)
qc.h(0)
qc.draw(output='mpl')
# Let's see Bloch sphere visualization
sv = Statevector(qc)
plot_bloch_multivector(sv)

CX Gate (CNOT Gate)
Ang controlled NOT (o CNOT o CX) gate ay umaaksyon sa dalawang qubits. Isinasagawa nito ang NOT operation (katumbas ng pag-aaplay ng X gate) sa pangalawang qubit lamang kapag ang unang qubit ay at kung hindi ay iniiwan itong hindi nababago. Tala: Inumberan ng Qiskit ang mga bit sa isang string mula kanan papuntang kaliwa.
# Let's apply a CX-gate on |11>
qc = QuantumCircuit(2)
qc.x(0)
qc.x(1)
qc.cx(0,1)
qc.draw(output='mpl')
sv=Statevector(qc)
plot_state_qsphere(sv)

Lumikha ng unang Bell state
# Create a Bell state circuit
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0,1)
# Draw the circuit
qc.draw("mpl")
# Plot the state using q-sphere visualization
sv = Statevector(qc)
plot_state_qsphere(sv)
# q-sphere is useful for visualizing states when Bloch sphere fails to

Lumikha ng pangalawang Bell state
# Create a circuit with the second Bell state
qc = QuantumCircuit(2)
qc.x(0)
qc.h(0)
qc.cx(0,1)
qc.draw("mpl")
Ang paliwanag ay:
# Get the statevector of the circuit
sv = Statevector(qc)
# Plot the state using qsphere visualization
plot_state_qsphere(sv)

Lumikha ng 3-qubit GHZ state
# Create a circuit with 3-qubit GHZ state
qc= QuantumCircuit(3)
qc.h(0)
qc.cx(0,1)
qc.cx(0,2)
qc.draw("mpl")
# Get the statevector of the circuit
sv = Statevector(qc)
# Plot the state using qsphere visualization
plot_state_qsphere(sv)

Lumikha ng Qiskit logo state
# Create a circuit with the Qiskit logo state
qc = QuantumCircuit(4)
qc.h(0)
qc.cx(0,1)
qc.cx(0,2)
qc.cx(0,3)
qc.x(1)
# Draw the circuit
qc.draw("mpl")
# Get the statevector of the circuit
sv = Statevector(qc)
# Plot the state using qsphere visualization
plot_state_qsphere(sv)

2. Lumikha at magpatakbo ng simpleng quantum program
Ang apat na hakbang sa pagsulat ng quantum program gamit ang Qiskit patterns ay:
-
I-map ang problema sa isang quantum-native format.
-
I-optimize ang circuits at operators.
-
I-execute gamit ang quantum primitive function.
-
Suriin ang mga resulta.
2.1 I-map ang problema sa isang quantum-native format
Sa isang quantum program, ang quantum circuits ay ang native format kung saan kakatawan ang quantum instructions, at ang operators ay kumakatawan sa observables na susukatin. Kapag lumilikha ng circuit, kadalasan ay gumagawa ka ng bagong QuantumCircuit object, pagkatapos ay magdagdag ng mga tagubilin dito sa pagkakasunud-sunod.
Ang sumusunod na code cell ay lumilikha ng circuit na gumagawa ng GHZ state na kung saan tatlong qubit ay ganap na entangled sa isa't isa.
Gumagamit ang Qiskit SDK ng LSb 0 bit numbering kung saan ang digit ay may halaga na o . Para sa karagdagang detalye, tingnan ang Bit-ordering in the Qiskit SDK topic.
# Create a GHZ state circuit
qc = QuantumCircuit(3)
qc.h(0)
qc.cx(0,1)
qc.cx(0,2)
# Draw the circuit
qc.draw("mpl")
Tingnan ang QuantumCircuit sa documentation para sa lahat ng available operations.
Kapag lumilikha ng quantum circuits, kailangan mo ring isaalang-alang kung anong uri ng data ang nais mong ibalik pagkatapos ng execution. Nagbibigay ang Qiskit ng dalawang paraan upang ibalik ang data: maaari kang makakuha ng probability distribution para sa isang set ng qubits na pipiliin mong sukatin, o maaari kang makakuha ng expectation value ng isang observable. Ihanda ang iyong workload upang sukatin ang iyong circuit sa isa sa dalawang paraang ito gamit ang Qiskit primitives (ipinaliwanag nang detalyado sa Step 3).
Sinusukat ng halimbawang ito ang expectation values gamit ang qiskit.quantum_info submodule, na tinukoy gamit ang operators (mga mathematical na objects na ginagamit upang kumatawan sa isang aksyon o proseso na nagbabago ng quantum state). Ang sumusunod na code cell ay lumilikha ng anim na three-qubit Pauli operators: ZZZ, ZZX, ZII, XXI, ZZI at III.
# Set up six different observables.
observables_labels = ["ZZZ", "ZZX", "ZII", "XXI", "ZZI", "III"]
observables = [SparsePauliOp(label) for label in observables_labels]
print(observables)
[SparsePauliOp(['ZZZ'],
coeffs=[1.+0.j]), SparsePauliOp(['ZZX'],
coeffs=[1.+0.j]), SparsePauliOp(['ZII'],
coeffs=[1.+0.j]), SparsePauliOp(['XXI'],
coeffs=[1.+0.j]), SparsePauliOp(['ZZI'],
coeffs=[1.+0.j]), SparsePauliOp(['III'],
coeffs=[1.+0.j])]
Dito, ang isang bagay tulad ng ZZI operator ay shorthand para sa tensor product na , na nangangahulugang ang pagsukat ng Z sa qubit 2 at Z sa qubit 1 nang sabay-sabay, at pagkuha ng impormasyon tungkol sa correlation sa pagitan ng qubit 2 at qubit 1. Ang expectation values na ganito ay karaniwang isinusulat din bilang .
Kung ang state na obserbahan natin ay ang three-qubit GHZ state, ang sukat ng ay dapat na 1.
2.2 I-optimize ang circuits at operators
Kapag nag-execute ng circuits sa isang device, mahalagang i-optimize ang set ng instructions na nilalaman ng circuit at i-minimize ang overall depth (humigit-kumulang ang bilang ng instructions) ng circuit. Tinitiyak nito na makukuha mo ang pinakamahusay na resulta na posible sa pamamagitan ng pagbabawas ng mga epekto ng error at noise. Bukod pa rito, ang instructions ng circuit ay dapat sumunod sa Instruction Set Architecture (ISA) ng backend device at dapat isaalang-alang ang basis gates at qubit connectivity ng device.
Ang sumusunod na code ay nag-i-instantiate ng tunay na device upang isumite ang job at binabago ang circuit at observables upang tumugma sa ISA ng backend na iyon. Kung hindi mo pa nai-save ang iyong credentials, sundin ang mga tagubilin dito upang i-authenticate gamit ang iyong API token.
# Choose a real backend
service = QiskitRuntimeService(channel='ibm_quantum_platform',)
backend = service.least_busy(min_num_qubits=156)
# print backend details
print(
f"Name: {backend.name}\n"
f"Version: {backend.backend_version}\n"
f"No. of qubits: {backend.num_qubits}\n"
f"Processor type: {backend.processor_type}\n"
)
Name: ibm_marrakesh
Version: 1.0.21
No. of qubits: 156
Processor type: {'family': 'Heron', 'revision': '2'}
# option to use the AerSimulator instead of a real quantum device
seed_sim=42
backend=AerSimulator.from_backend(backend,seed_simulator=seed_sim)
I-transpile ang circuit sa ISA circuit
# Convert to an ISA circuit and layout-mapped observables.
pm = generate_preset_pass_manager(backend=backend, optimization_level=2)
isa_circuit = pm.run(qc)
isa_circuit.draw("mpl", idle_wires=False)

mapped_observables = [
observable.apply_layout(isa_circuit.layout) for observable in observables
]
print(mapped_observables)
[SparsePauliOp(['IIIIIIIIIIIIIIIIZIIIIIZIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],
coeffs=[1.+0.j]), SparsePauliOp(['IIIIIIIIIIIIIIIIZIIIIIXIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],
coeffs=[1.+0.j]), SparsePauliOp(['IIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],
coeffs=[1.+0.j]), SparsePauliOp(['IIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],
coeffs=[1.+0.j]), SparsePauliOp(['IIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],
coeffs=[1.+0.j]), SparsePauliOp(['IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],
coeffs=[1.+0.j])]
2.3 I-execute gamit ang quantum primitives
Ang quantum computers ay maaaring gumawa ng mga random na resulta, kaya karaniwan kang nagko-collect ng sample ng outputs sa pamamagitan ng pagpapatakbo ng circuit nang maraming beses. Maaari mong tantyahin ang halaga ng observable gamit ang Estimator class. Ang Estimator ay isa sa dalawang primitives; ang isa pa ay ang Sampler, na maaaring gamitin upang makakuha ng data mula sa quantum computer. Ang mga objects na ito ay may run() method na nag-e-execute ng selection ng circuits, observables, at parameters (kung naaangkop), gamit ang primitive unified bloc (PUB).
Kapag nagpapatakbo ng code na ito sa tunay na quantum hardware, isaalang-alang ang pag-aaplay ng error mitigation and suppression techniques upang bawasan ang likas na noise ng quantum computer.
# Construct the Estimator instance.
estimator = Estimator(mode=backend)
estimator.options.resilience_level = 1
estimator.options.default_shots = 5000
Magsumite ng job gamit ang Estimator primitive.
# One pub, with one circuit to run against six different observables.
job = estimator.run([(isa_circuit, mapped_observables)])
# Use the job ID to retrieve your job data later
print(f">>> Job ID: {job.job_id()}")
>>> Job ID: 97ecd036-1767-49b0-a1dc-c71638c3c3c4
/Users/jma/miniconda3/envs/3122/lib/python3.12/site-packages/qiskit_ibm_runtime/fake_provider/local_service.py:187: UserWarning: The resilience_level option has no effect in local testing mode.
warnings.warn("The resilience_level option has no effect in local testing mode.")
Pagkatapos maisumite ang job, maaari kang maghintay hanggang sa makumpleto ang job sa loob ng iyong kasalukuyang python instance, o gamitin ang job_id upang kunin ang data sa ibang pagkakataon. (Tingnan ang section on retrieving jobs para sa mga detalye.)
Pagkatapos makumpleto ang job, suriin ang output nito sa pamamagitan ng result() attribute ng job.
# This is the result of the entire submission. You submitted one Pub,
# so this contains one inner result (and some metadata of its own).
job_result = job.result()
# This is the result from our single pub, which had six observables,
# so contains information on all six.
pub_result = job.result()[0]
Ngayon ay maaari rin nating i-execute ang circuit gamit ang Sampler primitive
# We include the measurements in the circuit
qc.measure_all()
sampler = Sampler(mode=backend)
qc.draw(output="mpl")

Magsumite ng job gamit ang Sampler primitive.
job_sampler = sampler.run(pm.run([qc]))
# Use the job ID to retrieve your job data later
print(f">>> Job ID: {job_sampler.job_id()}")
# Get the results
results_sampler = job_sampler.result()
>>> Job ID: a6ee4d2f-c80d-4a86-9a76-e4b1a74502e7
2.4 Suriin ang mga resulta
Ang analyze step ay karaniwang kung saan maaari mong i-postprocess ang iyong mga resulta gamit, halimbawa, measurement error mitigation o zero noise extrapolation (ZNE). Maaari mong i-feed ang mga resultang ito sa isa pang workflow para sa karagdagang analysis o maghanda ng plot ng mga key values at data. Sa pangkalahatan, ang hakbang na ito ay tiyak sa iyong problema. Para sa halimbawang ito, i-plot ang bawat isa sa expectation values na nasukat para sa ating circuit.
Ang expectation values at standard deviations para sa observables na tinukoy mo sa Estimator ay maaaring ma-access sa pamamagitan ng PubResult.data.evs at PubResult.data.stds attributes ng job result. Para makuha ang mga resulta mula sa Sampler, gamitin ang PubResult.data.meas.get_counts() function, na magbabalik ng dict ng measurements sa anyong bitstrings bilang keys at counts bilang kanilang kaukulang values. Para sa karagdagang impormasyon, tingnan ang Get started with Sampler.
# Plot the result
from matplotlib import pyplot as plt
values = pub_result.data.evs
errors = pub_result.data.stds
# plotting graph
# Plotting with error bars
plt.errorbar(observables_labels, values, yerr=errors, fmt='-o', capsize=5)
plt.xlabel("Observables")
plt.ylabel("Values")
plt.title("Plot of Observables vs Values with Error Bars")
plt.grid(True)
plt.tight_layout()
plt.show()

Nakita natin na ang observables na at ay may expectation value na 1, dahil ang ay nagpapakilala ng dalawang minus signs na nagkakansela, at ang ay umaaksyon bilang identity, na iniiwan ang GHZ state na hindi nababago. Ang natitirang observables ay may expectation value na 0, dahil ang kanilang operators ay nagpapakilala ng odd number ng minus signs, o ang operators ay nag-flip ng bilang ng qubits na ginagawang orthogonal ang mga overlapping states.
Ngayon i-plot natin ang mga resulta para sa Sampler
counts_list = results_sampler[0].data.meas.get_counts()
print(counts_list)
print(f"Outcomes : {counts_list}")
display(plot_histogram(counts_list, title="GHZ state"))
{'111': 480, '000': 503, '101': 8, '100': 9, '001': 3, '011': 6, '010': 10, '110': 5}
Outcomes : {'111': 480, '000': 503, '101': 8, '100': 9, '001': 3, '011': 6, '010': 10, '110': 5}

2.5 Mag-scale sa malalaking bilang ng qubits
Sa quantum computing, ang utility-scale na trabaho ay mahalaga sa paggawa ng pag-unlad sa larangan. Ang ganitong trabaho ay nangangailangan ng computations na isasagawa sa mas malaking sukat; nagtatrabaho sa circuits na maaaring gumamit ng mahigit 100 qubits at mahigit 1000 gates. Ang halimbawang ito ay nagsasagawa ng maliit na hakbang sa direksyon na iyon na nagsa-scale ng GHZ problema sa qubits. Ginagamit nito ang Qiskit patterns workflow at nagtatapos sa pamamagitan ng pagsukat ng expectation value .
Step 1. I-map ang problema
Magsulat ng function na nagbabalik ng QuantumCircuit na naghahanda ng -qubit GHZ state (essentially isang pinalawak na Bell state), pagkatapos ay gamitin ang function na iyon upang ihanda ang isang 10-qubit GHZ state at kolektahin ang observables na susukatin.
def get_qc_for_n_qubit_GHZ_state(n: int) -> QuantumCircuit:
qc = QuantumCircuit(n)
qc.h(0)
for i in range(n-1):
qc.cx(i, i+1)
return qc
n = 10
qc_n_GHZ = get_qc_for_n_qubit_GHZ_state(n)
qc_n_GHZ.draw("mpl")

Susunod, i-map sa operators na interesado. Ang halimbawang ito ay gumagamit ng ZZ operators sa pagitan ng qubits upang suriin ang pag-uugali habang lumalayo sila. Ang lalong hindi tumpak (corrupted) na expectation values sa pagitan ng malalayong qubits ay magpapakita ng antas ng noise na naroroon.
# ZZII...II, ZIZI...II, ... , ZIII...IZ
operator_strings = [
"Z" + i * "I" + "Z" + "I" * (n-i-2) for i in range(n-1)
]
print(operator_strings)
print(len(operator_strings))
operators = [SparsePauliOp(operator) for operator in operator_strings]
['ZZIIIIIIII', 'ZIZIIIIIII', 'ZIIZIIIIII', 'ZIIIZIIIII', 'ZIIIIZIIII', 'ZIIIIIZIII', 'ZIIIIIIZII', 'ZIIIIIIIZI', 'ZIIIIIIIIZ']
9
Step 2. I-optimize ang problema para sa execution sa quantum backend
Baguhin ang circuit at observables upang tumugma sa ISA ng backend.
# Convert to an ISA circuit and layout-mapped observables.
pm = generate_preset_pass_manager(backend=backend, optimization_level=2)
isa_circuit = pm.run(qc_n_GHZ)
isa_operators_list = [operator.apply_layout(isa_circuit.layout) for operator in operators]
Step 3. I-execute sa backend
Magsumite ng job at kung i-execute mo ito sa hardware ay paganahin ang error suppression sa pamamagitan ng paggamit ng technique para sa pagbabawas ng errors na tinatawag na dynamical decoupling. Tinutukoy ng resilience level kung gaano kalaki ang resilience na buuin laban sa errors. Ang mas mataas na levels ay gumagawa ng mas tumpak na resulta, sa kapalit ng mas mahabang processing times. Para sa karagdagang paliwanag ng options na nakatakda sa sumusunod na code, tingnan ang Configure error mitigation for Qiskit Runtime.
# Submit the circuit to Estimator
job = estimator.run([(isa_circuit, isa_operators_list)])
job_id = job.job_id()
/Users/jma/miniconda3/envs/3122/lib/python3.12/site-packages/qiskit_ibm_runtime/fake_provider/local_service.py:187: UserWarning: The resilience_level option has no effect in local testing mode.
warnings.warn("The resilience_level option has no effect in local testing mode.")
Step 4. I-post-process ang mga resulta
Para mas maintindihan ang pag-uugali ng entangled quantum states sa tunay na hardware, sinusuri namin ang pairwise correlations sa pagitan ng qubits sa Z basis. Sa partikular, tinitingnan namin ang expectation values ⟨Z₀Zᵢ⟩, na sumusukat kung gaano kalakas ang correlation ng qubit 0 sa bawat ibang qubit i. Sa partikular ay i-plot natin:
Aling values ng ang inaasahan mong makita sa plot?
Mga opsyon:
a) Bumababa habang tumataas ang
b) Constant na 1
c) Maliliit na deviations sa palibot ng 1
d) Halinhinan na 1 at 0 para sa odd at even values ng
data = list(range(1, len(operators) + 1)) # Distance between the Z operators
result = job.result()[0]
values = result.data.evs # Expectation value at each Z operator.
values = [
v / values[0] for v in values
] # Normalize the expectation values to evaluate how they decay with distance.
plt.plot(data, values, marker="o", label=f"{n}-qubit GHZ state")
plt.xlabel("Distance between qubits $i$")
plt.ylabel(r"$\langle Z_i Z_0 \rangle / \langle Z_1 Z_0 \rangle $")
plt.legend()
plt.show()

Sa plot na ito ay napansin natin na ang ay nagba-fluctuate sa palibot ng value na 1, kahit na sa isang ideal simulation lahat ng ay dapat 1.
Tulad ng nakikita mo, ang mga resulta ng 10 qubit experiments ay maganda ngunit may mga error pa rin. Isang paraan para mapabuti ang mga resulta ay ang pagpapatupad ng GHZ state nang mas mahusay.
Karaniwan ay ipinapatupad ng isa ang GHZ state sa pamamagitan ng staircase-like CNOT gates sequence. Gayunpaman, maaari mong ipatupad ang GHZ state nang mas mahusay, na binabawasan ang 2-qubit depth mula sa n patungo sa n/2 o mas mababa pa.
Isang mahalagang metric para i-benchmark kung gaano katumpak ang magiging resulta, o kung gaano kakaunti ang noise ay magkakaroon para sa isang circuit ay 2-qubit gate depth. Ito ay dahil ang error rates para sa 2-qubit gates (~10 beses na mas mataas kaysa sa single qubit gates) ay nangingibabaw sa errors ng buong circuit. Gamitin ang sumusunod na code para makuha ang 2-qubit gate depth ng isang circuit.
qc.depth(lambda x: x.operation.num_qubits == 2)
def better_ghz(n):
"fan out"
s = int(n / 2)
qc = QuantumCircuit(n)
qc.h(s)
for m in range(s, 0, -1):
qc.cx(m, m - 1)
if not (n % 2 == 0 and m == s):
qc.cx(n - m - 1, n - m)
return qc
better_ghz(n).draw("mpl")

# Check 2-qubit gate depth before transpilation
qc_better_ghz = better_ghz(n)
qc_better_ghz.depth(lambda x: x.operation.num_qubits == 2)
5
Isang kawili-wiling bagay na dapat tandaan dito ay nababawasan natin ang quantum depth ng circuit na nais nating i-execute sa pamamagitan lamang ng pagiging matalino at pag-iisip ng ibang paraan upang i-program ito. Gayunpaman, magkakaroon ng mga sitwasyon at algorithms kung saan hindi natin maaaring umasa sa mga matalinong tricks na ito. Dito magagamit ang transpiler, tinutulungan tayong i-optimize lahat ng aspeto na ito nang mahusay, kaya hindi natin kailangang mag-alala nang labis tungkol sa kanila.
3. Pag-encode ng Impormasyon
3.1 Amplitude encoding
Ngayong nakita na natin kung paano bumuo ng quantum circuits, kawili-wiling tuklasin kung paano natin maaaring i-encode ang classical information sa quantum states. Isang malakas na paraan ay, amplitude encoding, kung saan ang amplitudes ng quantum state ay kumakatawan sa components ng classical vector.
Tingnan natin ang isang simpleng halimbawa. Ipagpalagay na nais nating i-encode ang classical vector
sa isang quantum state ng dalawang qubits. Ang layunin ay ihanda ang quantum state:
kung saan ang (o ) at ang vector ay nai-normalize nang sa gayon:
Ngayon isaalang-alang natin ang partikular na halimbawa:
Pagkatapos ang kaukulang quantum state ay:
Ang state na ito ay maaaring ihanda gamit ang kombinasyon ng rotation gates ng angles at para sa qubits 0 at 1 ayon sa pagkakabanggit
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
import numpy as np
qc = QuantumCircuit(2)
qc.ry(np.pi / 6, 0)
qc.ry(np.pi / 4, 1)
simulator = AerSimulator()
qc.save_statevector()
result = simulator.run(qc).result()
statevector = result.get_statevector()
print("Statevector:", statevector)
qc.draw(output="mpl")
Statevector: Statevector([0.8923991 +0.j, 0.23911762+0.j, 0.36964381+0.j,
0.09904576+0.j],
dims=(2, 2))
from qiskit.quantum_info import Statevector
# Define our vector
v = np.array([0.8924, 0.3696, 0.2391, 0.0990])
v = v/np.linalg.norm(v)
# Create a statevector from the vector
state = Statevector(v)
# Initialize a quantum circuit with 2 qubits
qc = QuantumCircuit(2)
qc.initialize(state.data, [0, 1])
# Optional: simulate the state
print("Statevector:", state)
# Visualize the circuit
qc.decompose().decompose().decompose().decompose().decompose().draw("mpl")
Statevector: Statevector([0.89242154+0.j, 0.36960892+0.j, 0.23910577+0.j,
0.09900239+0.j],
dims=(2, 2))

Kaya nakita natin kung paano i-encode ang impormasyon gamit ang rotational gates.
3.2 Angle encoding at parametrized circuits
Isang lalong kawili-wiling paraan ng pag-encode ng impormasyon sa isang quantum computer ay ang pagdidisenyo ng quantum circuit na naglalaman ng ilang rotational angles o parameters na maaaring i-tune upang kumatawan sa pamilya ng functions . Halimbawa, isaalang-alang natin ang sumusunod na parametrized quantum circuit:
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
# Define a symbolic parameter
theta = Parameter("θ")
qc = QuantumCircuit(2)
# We applied a parametrized RX gate
qc.rx(theta, 0)
qc.cx(0, 1)
qc.draw("mpl")
Sa matematika, maaari nating suriin kung ano ang pamilya ng functions na maaari nating katawanin sa circuit na ito:
Medyo malinaw na ang bilang ng states na maaari nating katawanin sa quantum circuit na ito ay limitado, dahil hindi natin maaaring katawanin ang states o halimbawa. Gayunpaman, ang pamilya ng states na maaari nating katawanin ay nagsisimulang lumaki kapag nagpapakilala tayo ng higit pang rotations sa angkop na lugar:
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
# Define a symbolic parameter
theta1 = Parameter("θ1")
theta2 = Parameter("θ2")
qc = QuantumCircuit(2)
qc.rx(theta1, 0)
qc.rx(theta2, 1)
qc.cx(0, 1)
qc.draw("mpl")
Sa kasong ito, ang quantum states na ating ipapakita ay:
\begin{align*} \text{CNOT}_{01} \, R_x^{\{1}}(\theta_2) R_x^{\{0}}(\theta_1) \ket{00} &= \text{CNOT}_{01} \, R_x^{\{1}}(\theta_2)\left( \cos(\theta_1/2)\ket{00} - i\sin(\theta_1/2)\ket{10} \right) \\ &= \text{CNOT}_{01}\left( \cos(\theta_1/2)\cos(\theta_2/2)\ket{00} - i\cos(\theta_1/2)\sin(\theta_2/2)\ket{01} \right. \\ &\quad \left. - i\sin(\theta_1/2)\cos(\theta_2/2)\ket{10} + \sin(\theta_1/2)\sin(\theta_2/2)\ket{11} \right) \\ &= \cos(\theta_1/2)\cos(\theta_2/2)\ket{00} - i\cos(\theta_1/2)\sin(\theta_2/2)\ket{01} \\ &\quad + \sin(\theta_1/2)\sin(\theta_2/2)\ket{10} - i\sin(\theta_1/2)\cos(\theta_2/2)\ket{11} \end{align*}Nakikita natin na ang circuit na ito ay gumagawa ng mas malawak na pamilya ng quantum states kumpara sa nauna. Sa partikular, maaari na itong gumawa ng states na may non-zero amplitudes para sa o na hindi posible sa circuit sa itaas. Gayunpaman, ang circuit na ito ay hindi pa rin universal quantum state generator, kahit na maaaring sapat na ito sa expressiveness para magdesinyo ng circuits na may ilang flexibility para kumatawan sa ilang functions. Sa pangkalahatan, mas maraming independent parameters (angles) na ipinapakilala natin, mas maraming expressiveness ang circuit upang tantyahin ang mga arbitrary quantum states.
Ansatzes at Circuit library
Ang ganitong uri ng parameterized quantum circuit ay maaaring gamitin upang bumuo ng Ansatzes, trial quantum states na nagnanais na tantyahin ang solusyon ng isang problema. Ang Ansatzes na ito ay isang central component ng Variational Quantum Algorithms, isang klase ng hybrid quantum-classical algorithms na gumagamit ng quantum computer upang suriin ang cost function at classical optimizer upang i-minimize ito. Pupunta tayo sa detalye tungkol sa mga paksang ito sa susunod na Unit, ngunit sa ngayon, ipapakilala natin kung paano bumuo ng simpleng ansatz gamit ang Circuit library in Qiskit.
from qiskit.circuit.library import efficient_su2
SU2_ansatz = efficient_su2(4, su2_gates=["rx", "y"], entanglement="linear", reps=1)
SU2_ansatz.decompose().draw(output="mpl")

Nakita natin kung paano bumuo ng isang simpleng Ansatz gamit ang efficient_su2 function ng qiskit.circuit.library na magagawang gumawa ng malawak na hanay ng quantum states sa pamamagitan ng pag-tune sa parameters nito .
Konklusyon
Sa notebook na ito, natutunan mo kung paano bumuo ng quantum circuits, mula sa pagbuo ng quantum gates hanggang sa pagtukoy at pagsukat ng observables, at kung paano mai-execute ang circuits na ito nang mahusay sa parehong simulators at aktwal na quantum hardware. Nakita mo rin ang kahalagahan ng maingat na circuit design upang mai-minimize ang mga error kapag nagtatrabaho sa tunay na quantum devices gayundin ang mga estratehiya para sa pag-scale ng circuits sa mas malalaking bilang ng qubits, lalo na sa pamamagitan ng halimbawa ng GHZ state. Bukod pa rito, tinuklas mo ang iba't ibang pamamaraan para sa pag-encode ng classical information sa quantum states, kabilang ang amplitude encoding at angle encoding. Sa lahat ng ito, ganap kang nasusulit upang lumipat sa susunod na session at magsimulang magtrabaho sa quantum algorithms.
Pag-install ng Qiskit Code Assistant sa VSCode
I-click ang link at sundin ang mga tagubilin.
Bonus: Quantum Teleportation
Kapag narinig mo ang term na quantum teleportation, maaaring maisip mo ang futuristic na sci-fi technology na nagpaparami sa isang bagay sa isang lugar at muling lumalabas ito sa isang lugar na malayo. Ngunit ang quantum teleportation ay walang katulad noon. Sa katotohanan, ang naite-teleport ay hindi matter, ito ay impormasyon.
Pinapayagan ng quantum teleportation ang pagsasalin ng quantum state ng isang qubit mula sa isang lokasyon patungo sa isa pa. Habang ang transfer na ito ay tila instantaneous, hindi ito lumalabag sa mga batas ng physics. Paano iyon posible? Tingnan natin!
Ang quantum teleportation ay isang protocol na nagpapahintulot sa isang sender (Alice) na ipadala ang state ng isang qubit q sa isang receiver (Bob) gamit ang dalawang pangunahing resources: isang shared entangled pair ng qubits a at b at dalawang bits ng classical communication c0 at c1.
Sa esensya, ang kailangan ng protocol ay:
q: Ang qubit ni Alice, sa simula ay nasa state na nais nating i-teleport.a: Ang kalahati ni Alice ng shared entangled pair.b: Ang kalahati ni Bob ng shared entangled pair.c0,c1: Classical bits para mag-imbak ng measurement results ni Alice.
At paano ito gumagana? Ang workflow ay ang sumusunod
- Ihanda ang state ni Alice sa
q. Gagawa tayo ng partikular na state tulad ng para sa verification. - Lumikha ng entanglement: Bumuo ng Bell pair sa pagitan ng
aatb. - Mga operasyon ni Alice: Nagsasagawa si Alice ng "Bell measurement" sa kanyang dalawang qubits (
qata) at iniimbak ang classical results sac0atc1. - Classical communication: Ipinapadala ni Alice ang kanyang dalawang classical bits (
c0,c1) kay Bob. - Mga correction ni Bob: Iniaaplay ni Bob ang mga partikular na quantum gates (X at/o Z) sa kanyang qubit (
b), na nakakondisyon sa values ngc0atc1na natanggap niya.
Kung lahat ay tama ang ginawa, ang qubit ni Bob na b ay matatapos sa state , ang orihinal na state ng q ni Alice!
Para sa mas malalim na paliwanag at pagtuklas ng quantum teleportation, kabilang ang pagdaan sa mathematical na paliwanag kung bakit gumagana ang protocol na ito, maaari kang mag-refer sa IBM Quantum Learning resources: Quantum Teleportation. Ito ay bahagi ng Basics of Quantum Information course.
import matplotlib.pyplot as plt
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit_aer import AerSimulator
from qiskit.visualization import plot_histogram, plot_bloch_multivector
# Define individual quantum registers for each qubit
q = QuantumRegister(1, name='q') # message qubit
a = QuantumRegister(1, name='a') # Alice's entangled qubit
b = QuantumRegister(1, name='b') # Bob's entangled qubit
# Classical register for Alice's measurements
cr_alice = ClassicalRegister(2, name='c_alice')
# Create quantum circuit
teleport_qc = QuantumCircuit(q, a, b, cr_alice, name='Teleportation')
# Step 1: Prepare message state |+⟩ on q
teleport_qc.h(q[0])
teleport_qc.barrier()
# Step 2: Create entanglement between a and b
teleport_qc.h(a[0])
teleport_qc.cx(a[0], b[0])
teleport_qc.barrier()
# Step 3: Alice's Bell measurement
teleport_qc.cx(q[0], a[0])
teleport_qc.h(q[0])
teleport_qc.barrier()
# Step 4: Alice measures q and a
teleport_qc.measure(q[0], cr_alice[0])
teleport_qc.measure(a[0], cr_alice[1])
teleport_qc.barrier()
# Step 5: Bob's conditional measurements
with teleport_qc.if_test((cr_alice[1], 1)):
teleport_qc.x(b[0])
with teleport_qc.if_test((cr_alice[0], 1)):
teleport_qc.z(b[0])
# Draw the circuit
teleport_qc.draw(output='mpl')

Pagkatapos i-execute ang protocol, lumalabas ang isang mahalagang tanong, paano natin mave-verify na gumana ang teleportation? Hindi natin direktang 'makikita' ang state ng qubit ni Bob pagkatapos ng protocol. Gayunpaman, dahil inihanda natin ang inisyal na state ni Alice (pinili natin ang ), maaari nating gamitin ang isang espesyal na uri ng simulation para tingnan kung ang qubit ni Bob na b ay nagtapos sa parehong state na iyon.
Gagamitin natin ang AerSimulator na may save_statevector upang tingnan kung ang qubit ni Bob na b ay nagtapos sa orihinal na state ni Alice (). Kinakalkula ng simulator na ito ang final quantum state vector.
at pagkatapos ay kinakatawan ito gamit ang plot_bloch_multivector upang i-visualize ang qubit ni Bob (b) kumpara sa inisyal na state ni Alice (q).
# Simulate the teleportation circuit
sv_simulator = AerSimulator(method='statevector')
teleport_qc_sv = teleport_qc.copy()
teleport_qc_sv.save_statevector()
# Execute the circuit on the statevector simulator
job_sv = sv_simulator.run(teleport_qc_sv)
result_sv = job_sv.result()
# Get the final statevector
final_statevector = result_sv.get_statevector()
print("Visualizing final qubit states:")
display(plot_bloch_multivector(final_statevector))
print("Note that Alice's qubits have collapsed to |00⟩, |01⟩, |10⟩, or |11⟩, while Bob's qubit is in the original state |+⟩.")
Visualizing final qubit states:

Note that Alice's qubits have collapsed to |00⟩, |01⟩, |10⟩, or |11⟩, while Bob's qubit is in the original state |+⟩.
Tulad ng nakikita natin sa visualization, ang unang dalawang qubits (na pag-aari ni Alice) ay collapsed sa 0 o 1. Samantala, ang ikatlong qubit (na pag-aari ni Bob), na kinakatawan sa ikatlong Bloch sphere, ay nakaturo sa x-axis, na nagpapahiwatig na ito ay nasa state na , kaya matagumpay nating naipatupad ang quantum teleportation protocol!
Buod
Sa puntong ito ay maginhawa nang gumawa ng mabilis na buod ng kung ano ang nakamit natin:
- Si Alice ay nagsalin ng isang unknown quantum state kay Bob.
- Walang physical particle na inilipat.
- Ang orihinal na state sa qubit ni Alice ay sinira, alinsunod sa No-Cloning theorem.
Gayunpaman, ang quantum teleportation ay nangangailangan pa rin ng classical communication (ang mga resulta ng pagsukat ni Alice na ipinadala kay Bob), at iyon ang nagpapaliwanag kung bakit ang prosesong ito ay hindi nagpapahintulot ng mas mabilis kaysa liwanag na paglipat ng impormasyon at ganap na naaayon sa lahat ng kilalang batas ng pisika.