Lumaktaw sa pangunahing nilalaman
Ang proyektong ito ay nasa beta. Nakakita ng bug? Mag-bukas ng GitHub issue. May tanong o ideya? Magtanong sa Discussions — gusto naming marinig ang iyong feedback!
Gaano kaganda ang kalidad ng pagsasalin sa pahinang ito?

Patakbuhin ang iyong unang Circuit sa hardware

Package versions

Ang code sa pahinang ito ay ginawa gamit ang mga sumusunod na requirements. Inirerekomenda naming gamitin ang mga bersyong ito o mas bago.

qiskit[all]~=2.5.2
qiskit-ibm-runtime~=0.47.0

Ang halimbawang ito ay may dalawang bahagi. Una, gagawa ka ng simpleng "Hello world" na quantum program at patatakbuhin ito sa isang quantum processing unit (QPU). Dahil ang tunay na quantum research ay nangangailangan ng mas matibay na mga programa, sa ikalawang bahagi (I-scale sa malaking bilang ng qubits), i-scale mo ang simpleng programa hanggang sa utility level.

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"matplotlib": "matplotlib", "qiskit": "qiskit", "qiskit_ibm_runtime": "qiskit-ibm-runtime"}
_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")

I-install at mag-authenticate​

  1. Kung hindi mo pa nai-install ang Qiskit, hanapin ang mga instruksyon sa gabay na Quickstart.

    • I-install ang IBM Quantum Compute client para makapagpatakbo ng mga job sa quantum hardware:

      pip install qiskit-ibm-runtime
    • Mag-set up ng environment para makapagpatakbo ng mga Jupyter notebook nang lokal:

      pip install jupyter
  2. I-set up ang iyong authentication para ma-access ang quantum hardware sa pamamagitan ng libreng Open Plan.

    (Kung nakatanggap ka ng email na imbitasyon para sumali sa isang account, sundin ang mga hakbang para sa mga inimbitahang user sa halip.)

    • Pumunta sa IBM Quantum Platform para mag-log in o lumikha ng account.

      Mahalaga

      Kung kumokonekta ka sa pamamagitan ng proxy server, kailangan mong gumamit ng qiskit-ibm-runtime v0.44.0 o mas bago.

    • I-generate ang iyong API key (tinatawag din itong API token) sa dashboard, tapos kopyahin ito sa isang ligtas na lugar.

    • Pumunta sa pahina ng Instances at hanapin ang instance na gusto mong gamitin. I-hover ang CRN nito at i-click para kopyahin.

    • I-save ang iyong mga kredensyal nang lokal gamit ang code na ito:

      from qiskit_ibm_runtime import QiskitRuntimeService

      QiskitRuntimeService.save_account(
      # For `token`, use the 44-character API_KEY you created
      # and saved from the IBM Quantum Platform Home dashboard
      token="<your-api-key>",
      instance="<CRN>", # Optional
      )
  3. Maaari mo na ngayong gamitin ang Python code na ito sa tuwing gusto mong mag-authenticate sa IBM Quantum Compute Service:

    from qiskit_ibm_runtime import QiskitRuntimeService

    # Run every time you need the service
    service = QiskitRuntimeService()
Hindi gumagamit ng pinagkakatiwalaang Python environment?

Kung gumagamit ka ng pampublikong computer o iba pang hindi ligtas na environment, sundin ang mga instruksyon para sa manual na authentication para mapanatiling ligtas ang iyong mga kredensyal.

Gumawa at magpatakbo ng simpleng quantum program​

Ang apat na hakbang sa pagsusulat ng quantum program gamit ang mga Qiskit pattern ay:

  1. I-map ang problema sa quantum-native na format.

  2. I-optimize ang mga circuit at operator.

  3. Mag-execute gamit ang quantum primitive function.

  4. Suriin ang mga resulta.

Hakbang 1. I-map ang problema sa quantum-native na format​

Sa isang quantum program, ang quantum circuits ang katutubong format para kumatawan sa mga quantum na instruksyon, at ang mga operator naman ang kumakatawan sa mga observable na susukatín. Kapag gumagawa ng circuit, karaniwang gagawa ka ng bagong QuantumCircuit na object, tapos magdadagdag ng mga instruksyon dito nang sunud-sunod. Ang sumusunod na code cell ay gumagawa ng circuit na nagpo-produce ng Bell state, na isang state kung saan dalawang qubit ang ganap na naka-entangle sa isa't isa.

Tandaan: pag-order ng bit

Ang Qiskit SDK ay gumagamit ng LSb 0 bit numbering kung saan ang nthn^{th} na digit ay may value na 1≪n1 \ll n o 2n2^n. Para sa karagdagang detalye, tingnan ang paksa na Bit-ordering sa Qiskit SDK.

# This cell is hidden from users. It hides several unnecessary warnings.

import warnings
import logging

warnings.filterwarnings("ignore", message=".*Instance was not set*")
warnings.filterwarnings("ignore", message=".*loading instance*")
warnings.filterwarnings("ignore", message=".*using instance*")

# This cell is hidden from users. It hides several unnecessary warnings.

class IgnoreSpecificMessages(logging.Filter):
def filter(self, record):
for text in [
"Instance was not set",
"Loading default saved account",
"Loading instance",
"Instance was not set",
"using instance",
]:
if text in record.getMessage():
return False
return True

logger = logging.getLogger("qiskit_ibm_runtime")
logger.addFilter(IgnoreSpecificMessages())

for handler in logger.handlers:
handler.addFilter(IgnoreSpecificMessages())
from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService
from matplotlib import pyplot as plt

# Legacy server-side primitive before qiskit-ibm-runtime 0.50.0
# from qiskit_ibm_runtime import EstimatorOptions
# from qiskit_ibm_runtime import Estimator

# Client-side primitive introduced in qiskit-ibm-runtime 0.50.0
from qiskit_ibm_runtime.options_models import EstimatorOptions
from qiskit_ibm_runtime.executor_estimator import Estimator

# Uncomment the next line if you want to use a simulator:
# from qiskit_ibm_runtime.fake_provider import FakeBelemV2

# Create a new circuit with two qubits
qc = QuantumCircuit(2)

# Add a Hadamard gate to qubit 0
qc.h(0)

# Perform a controlled-X gate on qubit 1, controlled by qubit 0
qc.cx(0, 1)

# Return a drawing of the circuit using MatPlotLib ("mpl").
# These guides are written by using Jupyter notebooks, which
# display the output of the last line of each cell.
# If you're running this in a script, use `print(qc.draw())` to
# print a text drawing.
qc.draw("mpl")

Output of the previous code cell

Tingnan ang QuantumCircuit sa dokumentasyon para sa lahat ng available na operasyon. Kapag gumagawa ng mga quantum circuit, kailangan mo ring isaalang-alang kung anong uri ng data ang gusto mong ibalik pagkatapos ng execution. Nagbibigay ang Qiskit ng dalawang paraan para ibalik ang data: maaari kang makakuha ng sampling output para sa isang set ng mga qubit na pipiliin mong sukatin, o maaari kang makakuha ng expectation value ng isang observable. Ihanda ang iyong workload para sukatin ang iyong circuit sa isa sa dalawang paraang ito gamit ang primitives (ipinapaliwanag nang detalye sa Hakbang 3).

Ang halimbawang ito ay sumusukat ng mga expectation value gamit ang qiskit.quantum_info submodule, na tinutukoy gamit ang mga operator (mga mathematical na object na ginagamit para kumatawan sa isang aksyon o proseso na nagbabago ng quantum state). Ang sumusunod na code cell ay gumagawa ng anim na two-qubit na Pauli operator: IZ, IX, ZI, XI, ZZ, at XX.

# Set up six different observables.

observables_labels = ["IZ", "IX", "ZI", "XI", "ZZ", "XX"]
observables = [SparsePauliOp(label) for label in observables_labels]
Notasyon ng Operator

Dito, ang isang bagay tulad ng ZZ operator ay isang shorthand para sa tensor product na Z⊗ZZ\otimes Z, na nangangahulugang sinusukat ang Z sa qubit 1 at Z sa qubit 0 nang sabay, at nakakakuha ng impormasyon tungkol sa ugnayan ng qubit 1 at qubit 0. Ang mga expectation value na tulad nito ay karaniwang isinusulat din bilang ⟨Z1Z0⟩\langle Z_1 Z_0 \rangle.

Kung ang state ay naka-entangle, ang pagsukat ng ⟨Z1Z0⟩\langle Z_1 Z_0 \rangle ay dapat na iba sa pagsukat ng ⟨I1⊗Z0⟩⟨Z1⊗I0⟩\langle I_1 \otimes Z_0 \rangle \langle Z_1 \otimes I_0 \rangle. Para sa partikular na entangled state na ginawa ng ating circuit na inilarawan sa itaas, ang pagsukat ng ⟨Z1Z0⟩\langle Z_1 Z_0 \rangle ay dapat na 1 at ang pagsukat ng ⟨I1⊗Z0⟩⟨Z1⊗I0⟩\langle I_1 \otimes Z_0 \rangle \langle Z_1 \otimes I_0 \rangle ay dapat na zero.

Hakbang 2. I-optimize ang mga Circuit at operator​

Kapag nag-e-execute ng mga circuit sa isang device, mahalaga na i-optimize ang set ng mga instruksyon na nilalaman ng circuit at bawasan ang kabuuang depth (humigit-kumulang na bilang ng mga instruksyon) ng circuit. Tinitiyak nito na makukuha mo ang pinakamahusay na mga resulta sa pamamagitan ng pagbabawas ng mga epekto ng error at noise. Bukod dito, ang mga instruksyon ng circuit ay dapat na sumunod sa Instruction Set Architecture (ISA) ng backend device at dapat isaalang-alang ang mga basis gate at qubit connectivity ng device.

Ang sumusunod na code ay pumipili ng tunay na device kung saan isa-submit ang job at nagbabago ng circuit at mga observable para tumugma sa ISA ng backend na iyon. Kinakailangan na na-save mo na ang iyong mga kredensyal bago ito.

service = QiskitRuntimeService()

backend = service.least_busy(simulator=False, operational=True)

# Convert to an ISA circuit and layout-mapped observables.
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(qc)

isa_circuit.draw("mpl", idle_wires=False)

Output of the previous code cell

Hakbang 3. Mag-execute gamit ang mga quantum primitive​

Ang mga quantum computer ay maaaring mag-produce ng mga random na resulta, kaya karaniwang nangongolekta ka ng sample ng mga output sa pamamagitan ng paulit-ulit na pagpapatakbo ng circuit. Maaari mong i-estimate ang value ng observable gamit ang Estimator class. Ang Estimator ay isa sa dalawang primitive; ang isa ay ang Sampler, na maaaring gamitin para makakuha ng data mula sa isang quantum computer. Ang mga object na ito ay may run() na method na nagpapatupad ng piniling mga circuit, observable, at parameter (kung applicable), gamit ang isang primitive unified bloc (PUB).

# Construct the Estimator instance.

estimator = Estimator(mode=backend)
estimator.options.resilience_level = 1
estimator.options.default_shots = 5000

mapped_observables = [
observable.apply_layout(isa_circuit.layout) for observable in observables
]

# One pub, with one circuit to run against five 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: dab7lm9l216s739p6q10

Pagkatapos ma-submit ang isang job, maaari kang maghintay hanggang matapos ang job sa loob ng iyong kasalukuyang Python instance, o gamitin ang job_id para makuha ang data sa ibang pagkakataon. (Tingnan ang seksyon tungkol sa pagkuha ng mga job 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]
# Check there are six observables.
# If not, edit the comments in the previous cell and update this test.
assert len(pub_result.data.evs) == 6
Alternatibo: patakbuhin ang halimbawa gamit ang simulator

Kapag pinatakbo mo ang iyong quantum program sa isang tunay na device, ang iyong workload ay dapat munang maghintay sa pila bago tumakbo. Para makatipid ng oras, maaari mong gamitin sa halip ang sumusunod na code para patakbuhin ang maliit na workload na ito sa fake_provider gamit ang qiskit-ibm-runtime local testing mode. Tandaan na posible lang ito para sa maliit na circuit. Kapag nag-scale up ka sa susunod na seksyon, kailangan mong gumamit ng tunay na device.


# Use the following code instead if you want to run on a simulator:

from qiskit_ibm_runtime.fake_provider import FakeBelemV2
backend = FakeBelemV2()
estimator = Estimator(backend)

# Convert to an ISA circuit and layout-mapped observables.

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(qc)
mapped_observables = [
observable.apply_layout(isa_circuit.layout) for observable in observables
]

job = estimator.run([(isa_circuit, mapped_observables)])
result = job.result()

# 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 five observables,
# so contains information on all five.

pub_result = job.result()[0]

Hakbang 4. Suriin ang mga resulta​

Sa hakbang ng pagsusuri, karaniwang pino-post-process mo ang iyong mga resulta gamit, halimbawa, ang measurement error mitigation o zero noise extrapolation (ZNE). Maaari mong ipasok ang mga resultang ito sa isa pang workflow para sa karagdagang pagsusuri o maghanda ng graph ng mga pangunahing value at data. Sa pangkalahatan, ang hakbang na ito ay natatangi sa iyong problema. Para sa halimbawang ito, i-plot ang bawat isa sa mga expectation value na nasukat para sa ating circuit.

Ang mga expectation value at standard deviation para sa mga observable na tinukoy mo sa Estimator ay ina-access sa pamamagitan ng mga attribute na PubResult.data.evs at PubResult.data.stds ng resulta ng job. Para makuha ang mga resulta mula sa Sampler, gamitin ang function na PubResult.data.meas.get_counts(), na magbabalik ng dict ng mga resulta ng pagsukat, na ang mga bitstring ang mga key at ang mga count ang kaukulang value. Para sa karagdagang impormasyon, tingnan ang gabay na Sampler quickstart.

# Plot the result

values = pub_result.data.evs

errors = pub_result.data.stds

# plotting graph
plt.plot(observables_labels, values, "-o")
plt.xlabel("Observables")
plt.ylabel("Values")
plt.show()

Output of the previous code cell

Mapapansin na para sa mga qubit 0 at 1, ang mga independyenteng expectation value ng parehong X at Z ay 0, habang ang mga correlation (XX at ZZ) ay 1. Ito ay isang palatandaan ng quantum entanglement.

# Make sure the results follow the claim from the previous markdown cell.
# This can happen when the device occasionally behaves strangely. If this cell
# fails, you may just need to run the notebook again.

_results = {obs: val for obs, val in zip(observables_labels, values)}
for _label in ["IZ", "IX", "ZI", "XI"]:
assert abs(_results[_label]) < 0.2
for _label in ["XX", "ZZ"]:
assert _results[_label] > 0.8

I-scale sa malaking bilang ng qubits​

Sa quantum computing, ang utility-scale na trabaho ay napakahalaga para sa pag-unlad ng larangan. Ang ganitong trabaho ay nangangailangan ng mga computasyon na gawin sa mas malaking scale; nagtatrabaho sa mga circuit na maaaring gumamit ng mahigit 100 qubit at mahigit 1000 gate. Ipinapakita ng halimbawang ito kung paano mo magagawa ang utility-scale na trabaho sa IBM® QPU sa pamamagitan ng paglikha at pagsusuri ng isang 100-qubit GHZ state. Gumagamit ito ng Qiskit patterns workflow at nagtatapos sa pagsukat ng expectation value na ⟨Z0Zi⟩\langle Z_0 Z_i \rangle para sa bawat qubit.

Hakbang 1. I-map ang problema​

Sumulat ng function na nagbabalik ng QuantumCircuit na naghahanda ng nn-qubit GHZ state (mahalagang isang extended Bell state), tapos gamitin ang function na iyon para maghanda ng 100-qubit GHZ state at mangolekta ng mga observable na susukatín.

def get_qc_for_n_qubit_GHZ_state(n: int) -> QuantumCircuit:
"""This function will create a qiskit.QuantumCircuit (qc)
for an n-qubit GHZ state.

Args:
n (int): Number of qubits in the n-qubit GHZ state

Returns:
QuantumCircuit: Quantum circuit that generate the n-qubit GHZ state,
assuming all qubits start in the 0 state
"""
if isinstance(n, int) and n >= 2:
qc = QuantumCircuit(n)
qc.h(0)
for i in range(n - 1):
qc.cx(i, i + 1)
else:
raise Exception("n is not a valid input")
return qc

# Create a new circuit with 100 qubits in the GHZ state
n = 100
qc = get_qc_for_n_qubit_GHZ_state(n)

Susunod, i-map sa mga operator na interesado tayo. Ang halimbawang ito ay gumagamit ng mga ZZ operator sa pagitan ng mga qubit para suriin ang gawi habang lalong lumalayo ang mga ito sa isa't isa. Ang mga lalong hindi tumpak (sira) na expectation value sa pagitan ng mga malalayong qubit ay magpapakita ng antas ng noise na naroroon.

# ZZII...II, ZIZI...II, ... , ZIII...IZ
operator_strings = [
"Z" + "I" * i + "Z" + "I" * (n - 2 - i) for i in range(n - 1)
]

operators = [SparsePauliOp(operator) for operator in operator_strings]

Hakbang 2. I-optimize ang problema para sa execution sa quantum hardware​

Binabago ng sumusunod na code ang circuit at mga observable para tumugma sa ISA ng backend. Kinakailangan na na-save mo na ang iyong mga kredensyal bago ito.

service = QiskitRuntimeService()

backend = service.least_busy(
simulator=False, operational=True, min_num_qubits=100
)
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)

isa_circuit = pm.run(qc)
isa_operators_list = [op.apply_layout(isa_circuit.layout) for op in operators]

Hakbang 3. Mag-execute sa hardware​

I-submit ang job at i-enable ang error suppression gamit ang teknik na tinatawag na dynamical decoupling, na nagbabawas ng mga error. Tinutukoy ng resilience level kung gaano karaming resilience ang buuin laban sa mga error. Ang mas mataas na antas ay nagbibigay ng mas tumpak na mga resulta, ngunit nangangailangan ng mas mahabang oras ng pagproseso. Para sa karagdagang paliwanag ng mga opsyon na nakatakda sa sumusunod na code, tingnan ang Error mitigation at suppression techniques.

options = EstimatorOptions()
options.resilience_level = 1
options.dynamical_decoupling.enable = True
options.dynamical_decoupling.sequence_type = "XY4"

# Create an Estimator object
estimator = Estimator(backend, options=options)
# Submit the circuit to Estimator
job = estimator.run([(isa_circuit, isa_operators_list)])
job_id = job.job_id()
print(job_id)
dab84omrrl7c7386h52g

Hakbang 4. Post-process ng mga resulta​

Pagkatapos makumpleto ang job, i-plot ang mga resulta at mapapansin na ang ⟨Z0Zi⟩\langle Z_0 Z_i \rangle ay bumababa habang tumataas ang ii, kahit na sa isang ideal na simulation ang lahat ng ⟨Z0Zi⟩\langle Z_0 Z_i \rangle ay dapat na 1.

# data
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.

# plotting graph
plt.plot(data, values, marker="o", label="100-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()

Output of the previous code cell

Ipinapakita ng nakaraang graph na habang lumalaki ang distansya sa pagitan ng mga qubit, humihina ang signal dahil sa presensya ng noise.

Mga susunod na hakbang​

Mga rekomendasyon