579 lines
16 KiB
Plaintext
579 lines
16 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "434beca8-b15d-4f42-a887-4636fb692789",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Overview of operator classes"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "434beca86fbddfbe-75b2-44d7-8783-b756382fd6d5",
|
|
"metadata": {
|
|
"tags": [
|
|
"version-info"
|
|
]
|
|
},
|
|
"source": [
|
|
"<details>\n",
|
|
"<summary><b>Package versions</b></summary>\n",
|
|
"\n",
|
|
"The code on this page was developed using the following requirements.\n",
|
|
"We recommend using these versions or newer.\n",
|
|
"\n",
|
|
"```\n",
|
|
"qiskit[all]~=1.2.4\n",
|
|
"qiskit-aer~=0.15.1\n",
|
|
"qiskit-ibm-runtime~=0.31.0\n",
|
|
"qiskit-serverless~=0.17.1\n",
|
|
"qiskit-ibm-catalog~=0.1\n",
|
|
"```\n",
|
|
"</details>"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "1c4cfc09-242c-4389-b03e-8c241c573306",
|
|
"metadata": {},
|
|
"source": [
|
|
"In Qiskit, quantum operators are represented using classes from the [`quantum_info`](/api/qiskit/quantum_info) module. The most important operator class is [`SparsePauliOp`](/api/qiskit/qiskit.quantum_info.SparsePauliOp), which represents a general quantum operator as a linear combination of Pauli strings. `SparsePauliOp` is the class most commonly used to represent quantum observables. The rest of this page explains how to use `SparsePauliOp` and other operator classes."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "6fc6f151-f2ca-44f6-811b-d15c71ee1fa6",
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2019-08-21T09:02:56.554914Z",
|
|
"start_time": "2019-08-21T09:02:54.249612Z"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"import numpy as np\n",
|
|
"from qiskit.quantum_info.operators import Operator, Pauli, SparsePauliOp"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "23a940b3-fce0-4f84-8461-5a72c0ce9aa7",
|
|
"metadata": {},
|
|
"source": [
|
|
"## SparsePauliOp\n",
|
|
"\n",
|
|
"The [`SparsePauliOp`](/api/qiskit/qiskit.quantum_info.SparsePauliOp) class represents a linear combination of Pauli strings. There are several ways to initialize a `SparsePauliOp`, but the most flexible way is to use the [`from_sparse_list`](/api/qiskit/qiskit.quantum_info.SparsePauliOp#from_sparse_list) method, as demonstrated in the following code cell. The `from_sparse_list` accepts a list of `(pauli_string, qubit_indices, coefficient)` triplets."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "90053827-6a1f-4fb4-8188-808afe3ddd4f",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"SparsePauliOp(['XIIZI', 'IYIIY'],\n",
|
|
" coeffs=[ 1.+0.j, -1.+1.j])"
|
|
]
|
|
},
|
|
"execution_count": 2,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"op1 = SparsePauliOp.from_sparse_list(\n",
|
|
" [(\"ZX\", [1, 4], 1.0), (\"YY\", [0, 3], -1 + 1j)], num_qubits=5\n",
|
|
")\n",
|
|
"op1"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "fc7ffabb-5245-4687-b84b-25176a64dc07",
|
|
"metadata": {},
|
|
"source": [
|
|
"`SparsePauliOp` supports arithmetic operations, as demonstrated in the following code cell."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "2e21467f-b6fe-4ac5-9654-66dec83a97fb",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"op1 + op2:\n",
|
|
"SparsePauliOp(['XIIZI', 'IYIIY', 'ZIIXX', 'IIZZI'],\n",
|
|
" coeffs=[ 1.+0.j, -1.+1.j, 1.+2.j, -1.+1.j])\n",
|
|
"\n",
|
|
"2 * op1:\n",
|
|
"SparsePauliOp(['XIIZI', 'IYIIY'],\n",
|
|
" coeffs=[ 2.+0.j, -2.+2.j])\n",
|
|
"\n",
|
|
"op1 @ op2:\n",
|
|
"SparsePauliOp(['YIIYX', 'XIZII', 'ZYIXZ', 'IYZZY'],\n",
|
|
" coeffs=[ 1.+2.j, -1.+1.j, -1.+3.j, 0.-2.j])\n",
|
|
"\n",
|
|
"op1.tensor(op2):\n",
|
|
"SparsePauliOp(['XIIZIZIIXX', 'XIIZIIIZZI', 'IYIIYZIIXX', 'IYIIYIIZZI'],\n",
|
|
" coeffs=[ 1.+2.j, -1.+1.j, -3.-1.j, 0.-2.j])\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"op2 = SparsePauliOp.from_sparse_list(\n",
|
|
" [(\"XXZ\", [0, 1, 4], 1 + 2j), (\"ZZ\", [1, 2], -1 + 1j)], num_qubits=5\n",
|
|
")\n",
|
|
"\n",
|
|
"# Addition\n",
|
|
"print(\"op1 + op2:\")\n",
|
|
"print(op1 + op2)\n",
|
|
"print()\n",
|
|
"# Multiplication by a scalar\n",
|
|
"print(\"2 * op1:\")\n",
|
|
"print(2 * op1)\n",
|
|
"print()\n",
|
|
"# Operator multiplication (composition)\n",
|
|
"print(\"op1 @ op2:\")\n",
|
|
"print(op1 @ op2)\n",
|
|
"print()\n",
|
|
"# Tensor product\n",
|
|
"print(\"op1.tensor(op2):\")\n",
|
|
"print(op1.tensor(op2))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "85fb16f2-5296-4c4d-9836-249358fd7e12",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Pauli\n",
|
|
"\n",
|
|
"The [`Pauli`](/api/qiskit/qiskit.quantum_info.Pauli) class represents a single Pauli string with an optional phase coefficient from the set $\\set{+1, i, -1, -i}$. A `Pauli` can be initialized by passing a string of characters from the set `{\"I\", \"X\", \"Y\", \"Z\"}`, optionally prefixed by one of `{\"\", \"i\", \"-\", \"-i\"}` to represent the phase coefficient."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "edc33fe7-989e-489b-92f6-81975b20bd05",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"Pauli('iXX')"
|
|
]
|
|
},
|
|
"execution_count": 4,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"op1 = Pauli(\"iXX\")\n",
|
|
"op1"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "82c19270-98d0-4543-bad5-5bfaacee406f",
|
|
"metadata": {},
|
|
"source": [
|
|
"The following code cell demonstrates the use of some attributes and methods."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"id": "69b105cd-e978-45be-a3e9-bab344d9111f",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Dimension of iXX: (4, 4)\n",
|
|
"Phase of iXX: 3\n",
|
|
"Matrix representation of iXX: \n",
|
|
" [[0.+0.j 0.+0.j 0.+0.j 0.+1.j]\n",
|
|
" [0.+0.j 0.+0.j 0.+1.j 0.+0.j]\n",
|
|
" [0.+0.j 0.+1.j 0.+0.j 0.+0.j]\n",
|
|
" [0.+1.j 0.+0.j 0.+0.j 0.+0.j]]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(f\"Dimension of {op1}: {op1.dim}\")\n",
|
|
"print(f\"Phase of {op1}: {op1.phase}\")\n",
|
|
"print(f\"Matrix representation of {op1}: \\n {op1.to_matrix()}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "4c4b1efe-4025-4b88-bbce-d0b3060e0ab1",
|
|
"metadata": {},
|
|
"source": [
|
|
"`Pauli` objects possess a number of other methods to manipulate the operators such as determining its adjoint, whether it (anti)commutes with another `Pauli`, and computing the dot product with another `Pauli`. Refer to the [API documentation](/api/qiskit/qiskit.quantum_info.Pauli) for more info."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "0f02f8da-fab6-4ba6-b4ec-80d577cf8914",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Operator\n",
|
|
"\n",
|
|
"The [`Operator`](/api/qiskit/qiskit.quantum_info.Operator) class represents a general linear operator. Unlike `SparsePauliOp`, `Operator` stores the linear operator as a dense matrix. Because the memory required to store a dense matrix scales exponentially with the number of qubits, the `Operator` class is only suitable for use with a small number of qubits.\n",
|
|
"\n",
|
|
"You can initialize an `Operator` by directly passing a Numpy array storing the matrix of the operator. For example, the following code cell creates a two-qubit Pauli XX operator:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"id": "f8d9d183-586c-44ac-aa93-317a2adb40ad",
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2019-08-21T09:02:56.572857Z",
|
|
"start_time": "2019-08-21T09:02:56.566140Z"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Operator([[0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],\n",
|
|
" [0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],\n",
|
|
" [0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j],\n",
|
|
" [1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]],\n",
|
|
" input_dims=(2, 2), output_dims=(2, 2))\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"XX = Operator(\n",
|
|
" np.array(\n",
|
|
" [\n",
|
|
" [0, 0, 0, 1],\n",
|
|
" [0, 0, 1, 0],\n",
|
|
" [0, 1, 0, 0],\n",
|
|
" [1, 0, 0, 0],\n",
|
|
" ]\n",
|
|
" )\n",
|
|
")\n",
|
|
"XX"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "4ded9878-c239-4e79-a60e-fff048c15784",
|
|
"metadata": {},
|
|
"source": [
|
|
"The operator object stores the underlying matrix, and the input and output dimension of subsystems.\n",
|
|
"\n",
|
|
"* `data`: To access the underlying Numpy array, you can use the `Operator.data` property.\n",
|
|
"* `dims`: To return the total input and output dimension of the operator, you can use the `Operator.dim` property. *Note: the output is returned as a tuple* `(input_dim, output_dim)`, *which is the reverse of the shape of the underlying matrix.*"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"id": "d9a6fe93-00a1-498f-9110-67b022db0a4f",
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2019-08-21T09:02:56.589962Z",
|
|
"start_time": "2019-08-21T09:02:56.585681Z"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"array([[0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],\n",
|
|
" [0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],\n",
|
|
" [0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j],\n",
|
|
" [1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]])"
|
|
]
|
|
},
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"XX.data"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"id": "784a657a-1731-4ecd-9bc0-aa0b96bc27e8",
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2019-08-21T09:02:56.615497Z",
|
|
"start_time": "2019-08-21T09:02:56.611146Z"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"(4, 4)"
|
|
]
|
|
},
|
|
"execution_count": 8,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"input_dim, output_dim = XX.dim\n",
|
|
"input_dim, output_dim"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "0f84bf31-ce41-454a-9e2c-11c0ec4a04dc",
|
|
"metadata": {},
|
|
"source": [
|
|
"The operator class also keeps track of subsystem dimensions, which can be used for composing operators together. These can be accessed using the `input_dims` and `output_dims` functions.\n",
|
|
"\n",
|
|
"For $2^N$ by $2^M$ operators, the input and output dimensions are automatically assumed to be M-qubit and N-qubit:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"id": "b4576985-9ae2-46f0-a29d-9ca3bea53bf0",
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2019-08-21T09:02:56.804167Z",
|
|
"start_time": "2019-08-21T09:02:56.798857Z"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Input dimensions: (2, 2)\n",
|
|
"Output dimensions: (2,)\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"op = Operator(np.random.rand(2**1, 2**2))\n",
|
|
"print(\"Input dimensions:\", op.input_dims())\n",
|
|
"print(\"Output dimensions:\", op.output_dims())"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "9bae9b8c-b7f5-4e1e-ad8b-4482f19af531",
|
|
"metadata": {},
|
|
"source": [
|
|
"If the input matrix is not divisible into qubit subsystems, then it will be stored as a single-qubit operator. For example, for a $6\\times6$ matrix:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"id": "186c1ac5-0bf2-4a86-84d8-bffa3f1763a1",
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2019-08-21T09:02:57.764881Z",
|
|
"start_time": "2019-08-21T09:02:57.760401Z"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Input dimensions: (6,)\n",
|
|
"Output dimensions: (6,)\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"op = Operator(np.random.rand(6, 6))\n",
|
|
"print(\"Input dimensions:\", op.input_dims())\n",
|
|
"print(\"Output dimensions:\", op.output_dims())"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "e813709d-4ac3-4abc-863f-9d5d262ba753",
|
|
"metadata": {},
|
|
"source": [
|
|
"The input and output dimension can also be manually specified when initializing a new operator:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 11,
|
|
"id": "e14faef6-3b05-4447-9960-3b140ddff1a1",
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2019-08-21T09:02:58.292849Z",
|
|
"start_time": "2019-08-21T09:02:58.287354Z"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Input dimensions: (4,)\n",
|
|
"Output dimensions: (2,)\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Force input dimension to be (4,) rather than (2, 2)\n",
|
|
"op = Operator(np.random.rand(2**1, 2**2), input_dims=[4])\n",
|
|
"print(\"Input dimensions:\", op.input_dims())\n",
|
|
"print(\"Output dimensions:\", op.output_dims())"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 12,
|
|
"id": "41845475-f6e9-4057-b21e-89cf1a62f672",
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2019-08-21T09:02:58.779572Z",
|
|
"start_time": "2019-08-21T09:02:58.774878Z"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Input dimensions: (2, 3)\n",
|
|
"Output dimensions: (2, 3)\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Specify system is a qubit and qutrit\n",
|
|
"op = Operator(np.random.rand(6, 6), input_dims=[2, 3], output_dims=[2, 3])\n",
|
|
"print(\"Input dimensions:\", op.input_dims())\n",
|
|
"print(\"Output dimensions:\", op.output_dims())"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "1ed55128-5b97-4733-ac0f-6b762e48691b",
|
|
"metadata": {},
|
|
"source": [
|
|
"You can also extract just the input or output dimensions of a subset of subsystems using the `input_dims` and `output_dims` functions:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 13,
|
|
"id": "c9fe7460-8e93-47aa-acc1-425bfe797c17",
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2019-08-21T09:03:02.187313Z",
|
|
"start_time": "2019-08-21T09:03:02.183719Z"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Dimension of input system 0: (2,)\n",
|
|
"Dimension of input system 1: (3,)\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(\"Dimension of input system 0:\", op.input_dims([0]))\n",
|
|
"print(\"Dimension of input system 1:\", op.input_dims([1]))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "3e8538f5-77d4-4683-838f-abff122cd3f7",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Next steps\n",
|
|
"\n",
|
|
"<Admonition type=\"tip\" title=\"Recommendations\">\n",
|
|
" - Learn how to [specify observables in the Pauli basis](./specify-observables-pauli).\n",
|
|
" - See an example of using operators in the [Combine error mitigation options with the estimator primitive](https://learning.quantum.ibm.com/tutorial/combine-error-mitigation-options-with-the-estimator-primitive) tutorial.\n",
|
|
" - Read more [in-depth coverage of the Operator class](./operator-class).\n",
|
|
" - Explore the [Operator API](/api/qiskit/qiskit.quantum_info.Operator#operator) reference.\n",
|
|
"</Admonition>"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"anaconda-cloud": {},
|
|
"celltoolbar": "Tags",
|
|
"description": "Use the Qiskit quantum information module to construct and manipulate operators",
|
|
"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": "Operators module overview",
|
|
"varInspector": {
|
|
"cols": {
|
|
"lenName": 16,
|
|
"lenType": 16,
|
|
"lenVar": 40
|
|
},
|
|
"kernels_config": {
|
|
"python": {
|
|
"delete_cmd_postfix": "",
|
|
"delete_cmd_prefix": "del ",
|
|
"library": "var_list.py",
|
|
"varRefreshCmd": "print(var_dic_list())"
|
|
},
|
|
"r": {
|
|
"delete_cmd_postfix": ") ",
|
|
"delete_cmd_prefix": "rm(",
|
|
"library": "var_list.r",
|
|
"varRefreshCmd": "cat(var_dic_list()) "
|
|
}
|
|
},
|
|
"types_to_exclude": [
|
|
"module",
|
|
"function",
|
|
"builtin_function_or_method",
|
|
"instance",
|
|
"_Feature"
|
|
],
|
|
"window_display": false
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
}
|