qiskit-documentation/docs/guides/bit-ordering.ipynb

397 lines
10 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "1f7fe7f1-988f-461f-8222-f291404b912a",
"metadata": {},
"source": [
"{/* cspell:ignore leftrightarrow */}"
]
},
{
"cell_type": "markdown",
"id": "49fb8eee-d17a-4648-8b6f-52097acfb305",
"metadata": {
"tags": [
"version-info"
]
},
"source": [
"# Bit-ordering in the Qiskit SDK"
]
},
{
"cell_type": "markdown",
"id": "369b8b49-a2af-4999-85df-f7659022e11b",
"metadata": {},
"source": [
"If you have a set of $n$ bits (or qubits), you'll usually label each bit $0\n",
"\\rightarrow n-1$. Different softwares and resources must choose how they order\n",
"these bits both in computer memory and when displayed on-screen.\n",
"\n",
"## Qiskit conventions\n",
"\n",
"Here's how the Qiskit SDK orders bits in different scenarios.\n",
"\n",
"### Quantum circuits\n",
"\n",
"The `QuantumCircuit` class stores its qubits in a list\n",
"(`QuantumCircuit.qubits`). The index of a qubit in this list defines the\n",
"qubit's label."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "a1c61ed7-72df-447e-a103-ce0e273626c9",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<Qubit register=(2, \"q\"), index=0>"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from qiskit import QuantumCircuit, QuantumRegister\n",
"from qiskit.circuit import Qubit\n",
"\n",
"qc = QuantumCircuit(2)\n",
"qc.qubits[0] # qubit \"0\"\n",
"\n",
"Qubit(QuantumRegister(2, \"q\"), 0)"
]
},
{
"cell_type": "markdown",
"id": "22c49977-e960-4620-ae1d-a7a90a879b45",
"metadata": {},
"source": [
"### Circuit diagrams\n",
"\n",
"On a circuit diagram, qubit $0$ is the topmost qubit, and qubit $n-1$ the\n",
"bottommost qubit. You can change this with the `reverse_bits` argument of\n",
"`QuantumCircuit.draw` (see [Change ordering in\n",
"Qiskit](#change-ordering-in-qiskit))."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "a4e175af-8882-427a-a276-bd51a3d9be57",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
" \n",
"q_0: ─────\n",
" ┌───┐\n",
"q_1: ┤ X ├\n",
" └───┘"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"qc.x(1)\n",
"qc.draw()"
]
},
{
"cell_type": "markdown",
"id": "19aa0892-a578-49e3-98df-14c696d01896",
"metadata": {},
"source": [
"### Integers\n",
"\n",
"When interpreting bits as a number, bit $0$ is the least significant bit, and\n",
"bit $n-1$ the most significant. This is helpful when coding because each bit has\n",
"the value $2^\\text{label}$ (label being the qubit's index in\n",
"`QuantumCircuit.qubits`). For example, the following circuit execution ends\n",
"with bit $0$ being `0`, and bit $1$ being `1`. This is interpreted as the\n",
"decimal integer `2` (measured with probability `1.0`)."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "7ecb86d3-fe3a-43b0-9293-cba967e80fdc",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" > Counts: {'10': 1024}\n"
]
}
],
"source": [
"from qiskit.primitives import StatevectorSampler as Sampler\n",
"\n",
"qc.measure_all()\n",
"\n",
"job = Sampler().run([qc])\n",
"result = job.result()\n",
"print(f\" > Counts: {result[0].data.meas.get_counts()}\")"
]
},
{
"cell_type": "markdown",
"id": "e263f4f9-f383-4583-bdd4-f8792d6809db",
"metadata": {},
"source": [
"### Strings\n",
"\n",
"When displaying or interpreting a list of bits (or qubits) as a string, bit\n",
"$n-1$ is the leftmost bit, and bit $0$ is the rightmost bit. This is because we\n",
"usually write numbers with the most significant digit on the left, and in\n",
"Qiskit, bit $n-1$ is interpreted as the most significant bit.\n",
"\n",
"For example, the following cell defines a `Statevector` from a string of\n",
"single-qubit states. In this case, qubit $0$ is in state $|+\\rangle$, and\n",
"qubit $1$ in state $|0\\rangle$."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "2cffb8d4-66db-4c1c-b0c2-b796ed6e8ce0",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{np.str_('00'): np.float64(0.4999999999999999),\n",
" np.str_('01'): np.float64(0.4999999999999999)}"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from qiskit.quantum_info import Statevector\n",
"\n",
"sv = Statevector.from_label(\"0+\")\n",
"sv.probabilities_dict()"
]
},
{
"cell_type": "markdown",
"id": "86c48e21-9138-4dec-a312-0b5deefd0e35",
"metadata": {},
"source": [
"This occasionally causes confusion when interpreting a string of bits, as you\n",
"might expect the leftmost bit to be bit $0$, whereas it usually represents bit\n",
"$n-1$.\n",
"\n",
"### Statevector matrices\n",
"\n",
"When representing a statevector as a list of complex numbers (amplitudes),\n",
"Qiskit orders these amplitudes such that the amplitude at index $x$ represents\n",
"the computational basis state $|x\\rangle$."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "d6ff798a-6bdc-4727-8331-b575fbf1e083",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(0.7071067811865475+0j)\n",
"0j\n"
]
}
],
"source": [
"print(sv[1]) # amplitude of state |01>\n",
"print(sv[2]) # amplitude of state |10>"
]
},
{
"cell_type": "markdown",
"id": "cc92b428-80c7-4530-bebc-3486aecee5f2",
"metadata": {},
"source": [
"### Gates\n",
"\n",
"Each gate in Qiskit can interpret a list of qubits in its own way, but\n",
"controlled gates usually follow the convention `(control, target)`.\n",
"\n",
"For example, the following cell adds a controlled-X gate where qubit $0$ is\n",
"the control and qubit $1$ is the target."
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "f2e34794-2f04-4065-9a1d-9aff022204db",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
" \n",
"q_0: ──■──\n",
" ┌─┴─┐\n",
"q_1: ┤ X ├\n",
" └───┘"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from qiskit import QuantumCircuit\n",
"\n",
"qc = QuantumCircuit(2)\n",
"qc.cx(0, 1)\n",
"qc.draw()"
]
},
{
"cell_type": "markdown",
"id": "2b9ee336-e645-41ee-aeda-5f9dfe3a3f88",
"metadata": {},
"source": [
"Following all the previously mentioned conventions in Qiskit, this CX-gate\n",
"performs the transformation $|01\\rangle \\leftrightarrow |11\\rangle$, so has the\n",
"following matrix.\n",
"\n",
"$$\n",
"\\begin{pmatrix}\n",
" 1 & 0 & 0 & 0 \\\\\n",
" 0 & 0 & 0 & 1 \\\\\n",
" 0 & 0 & 1 & 0 \\\\\n",
" 0 & 1 & 0 & 0 \\\\\n",
"\\end{pmatrix}\n",
"$$\n",
"\n",
"## Change ordering in Qiskit\n",
"\n",
"To draw a circuit with qubits in reversed order (that is, qubit $0$ at the\n",
"bottom), use the `reverse_bits` argument. This only affects the generated\n",
"diagram and does not affect the circuit; the X-gate still acts on qubit $0$."
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "6d31e88d-2a4f-4404-8177-7bccd0c19d4b",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
" \n",
"q_1: ─────\n",
" ┌───┐\n",
"q_0: ┤ X ├\n",
" └───┘"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from qiskit import QuantumCircuit\n",
"\n",
"qc = QuantumCircuit(2)\n",
"qc.x(0)\n",
"qc.draw(reverse_bits=True)"
]
},
{
"cell_type": "markdown",
"id": "4e343e80-3f77-4fe7-8942-afbe71f756ab",
"metadata": {},
"source": [
"You can use the `reverse_bits` method to return a new circuit with the\n",
"qubits' labels reversed (this does not mutate the original circuit)."
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "4c6a38b7-f6a1-4753-94e6-2c488ec37b8d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
" \n",
"q_0: ─────\n",
" ┌───┐\n",
"q_1: ┤ X ├\n",
" └───┘"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"qc.reverse_bits().draw()"
]
},
{
"cell_type": "markdown",
"id": "da750e37-2624-4797-82c0-560ee7d5367d",
"metadata": {},
"source": [
"Note that in this new circuit, the X-gate acts on qubit $1$.\n",
"\n",
"## Next steps\n",
"\n",
"<Admonition type=\"tip\" title=\"Recommendations\">\n",
" - See an example of using circuits in the [Grover's Algorithm](https://learning.quantum.ibm.com/tutorial/grovers-algorithm) tutorial.\n",
" - Explore the [QuantumCircuit API](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#quantumcircuit-class) reference.\n",
"</Admonition>"
]
}
],
"metadata": {
"description": "Learn about Qiskit SDK's ordering conventions and why we chose them",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3"
},
"title": "Bit-ordering in the Qiskit SDK"
},
"nbformat": 4,
"nbformat_minor": 4
}