Step 05 of 12 · 40 min
Bell state in Python and Qiskit
The same Bell circuit, in current Qiskit, on a local sampler. The notebook pins qiskit>=2.3.0,<2.4.0. No API key belongs in it.
Install
This lab pins qiskit>=2.3.0,<2.4.0. The notebook is notebooks/bell_state_lab.ipynb. Install requirements.txt in a virtual environment.
StatevectorSampler runs on your computer. It does not spend Open Plan time. Copy the circuit before measure_all() so the unmeasured circuit is still available.
The Python words in the table are the words this code uses. There is no separate vocabulary lecture on this page.
ModuleNotFoundError: qiskit
The notebook kernel is not the environment where you installed Qiskit. Activate the virtual environment, then start Jupyter from that shell.
The counts use a different name than meas
measure_all() names the classical register meas in this version. Read result[0].data["meas"].
An API key is about to go into the notebook
Please pause. This cell does not need an API key, and a key in a notebook can be copied by accident. A hardware run is a later, optional step. If a key was shown, revoke it in the IBM dashboard and create a replacement. You can keep learning on the simulator. Ask a facilitator without pasting the key.
Same circuit, line by line
| Code | Python | Qiskit | What to observe |
|---|---|---|---|
| from qiskit import QuantumCircuit | import loads a name. | QuantumCircuit will store the gates. | Nothing has run yet. |
| from qiskit.primitives import StatevectorSampler | A second import. | The local ideal sampler. | Still no qubits changed. |
| bell_circuit = QuantumCircuit(2) | A name bound to a new object. 2 is an argument. | Two qubits, indexed from 0. | Both start in |0⟩. |
| bell_circuit.h(0) | h is a method. 0 selects qubit 0. | Hadamard on qubit 0. | Qubit 0 is in equal superposition. Qubit 1 is still |0⟩. |
| bell_circuit.cx(0, 1) | Two arguments: control, then target. | CX from qubit 0 onto qubit 1. | The state is (|00⟩ + |11⟩) / √2. |
| measured_circuit = bell_circuit.copy() | copy makes a second object. | The original stays unmeasured. | Two Python objects, one circuit. |
| measured_circuit.measure_all() | A method call. | One classical bit per qubit. | The next run can return bitstrings. |
| sampler = StatevectorSampler() | A new object from a class. | Local ideal sampler. | No QPU time. |
| job = sampler.run([measured_circuit], shots=1024) | A list argument and a named argument. | 1024 ideal shots. | job is the handle for that run. |
| result = job.result() | The call returns an object. | The finished sampler output. | You have not read the tallies yet. |
| counts = result[0].data["meas"].get_counts() | A dictionary comes back. | Bitstrings and tallies. | Ideal mass on 00 and 11. Qubit 0 is the rightmost bit. |
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler
bell_circuit = QuantumCircuit(2)
bell_circuit.h(0)
bell_circuit.cx(0, 1)
measured_circuit = bell_circuit.copy()
measured_circuit.measure_all()
sampler = StatevectorSampler()
job = sampler.run([measured_circuit], shots=1024)
result = job.result()
counts = result[0].data["meas"].get_counts()
print(counts)Software structure
The technical definition is in the first column. One Home Depot line sits beside it. This analogy stops at these programming words.
| Word | Technical definition | Home Depot |
|---|---|---|
| Package or library | A folder of Python modules you install and import. | A department or toolbox |
| Module | One Python file of related names inside a package. | A specific aisle |
| Class | The definition of a kind of object. | The design or type of tool |
| Object or instance | One value created from a class. | The actual tool selected |
| Method | A function that belongs to an object. | An action the tool can perform |
| Argument | A value you pass into a call. | A setting, measurement, or instruction |
| Variable | A name bound to a value. | A labeled container holding something |
