759 lines
31 KiB
Plaintext
759 lines
31 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b88d9242-a6f2-47b6-8e0a-daf60d0c4374",
|
|
"metadata": {},
|
|
"source": [
|
|
"# The Operator class"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "9a7539be-eb3f-4a29-8a76-ea9c93559142",
|
|
"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": "eb4d8e3f-5efb-4223-a15b-d6ef541370dc",
|
|
"metadata": {},
|
|
"source": [
|
|
"This page shows how to use the [`Operator`](/api/qiskit/qiskit.quantum_info.Operator) class. For a high-level overview of operator representations in Qiskit, including the `Operator` class and others, see [Overview of operator classes](./operators-overview)."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "549bc166-9c0e-4e89-b7e2-8adafd7110c3",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import numpy as np\n",
|
|
"from qiskit.circuit import QuantumCircuit\n",
|
|
"from qiskit.circuit.library import CXGate, RXGate, XGate\n",
|
|
"from qiskit.quantum_info import Operator, Pauli, process_fidelity"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "8292bbef-0a61-44db-a096-cee8c9b23827",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Convert classes to Operators\n",
|
|
"\n",
|
|
"Several other classes in Qiskit can be directly converted to an `Operator` object using the operator initialization method. For example:\n",
|
|
"\n",
|
|
"* `Pauli` objects\n",
|
|
"* `Gate` and `Instruction` objects\n",
|
|
"* `QuantumCircuit` objects\n",
|
|
"\n",
|
|
"Note that the last point means you can use the `Operator` class as a unitary simulator to compute the final unitary matrix for a quantum circuit, without having to call a simulator backend. If the circuit contains any unsupported operations, an exception is raised. Unsupported operations are: measure, reset, conditional operations, or a gate that does not have a matrix definition or decomposition in terms of gate with matrix definitions."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "cb6e9d7a-8dc9-4b32-81f0-278d2e7e64b5",
|
|
"metadata": {},
|
|
"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": [
|
|
"# Create an Operator from a Pauli object\n",
|
|
"\n",
|
|
"pauliXX = Pauli(\"XX\")\n",
|
|
"Operator(pauliXX)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "ffdda3ff-75ca-486c-8e52-be80244b969f",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Operator([[1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],\n",
|
|
" [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",
|
|
" input_dims=(2, 2), output_dims=(2, 2))\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Create an Operator for a Gate object\n",
|
|
"Operator(CXGate())"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "b8cbc1d9-4957-4b2d-b59c-32c1efbfbeed",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Operator([[0.70710678+0.j , 0. -0.70710678j],\n",
|
|
" [0. -0.70710678j, 0.70710678+0.j ]],\n",
|
|
" input_dims=(2,), output_dims=(2,))\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Create an operator from a parameterized Gate object\n",
|
|
"Operator(RXGate(np.pi / 2))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"id": "e60c3079-84bf-40cd-ace7-bae419118c99",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Operator([[ 0.70710678+0.j, 0.70710678+0.j, 0. +0.j, ...,\n",
|
|
" 0. +0.j, 0. +0.j, 0. +0.j],\n",
|
|
" [ 0. +0.j, 0. +0.j, 0.70710678+0.j, ...,\n",
|
|
" 0. +0.j, 0. +0.j, 0. +0.j],\n",
|
|
" [ 0. +0.j, 0. +0.j, 0. +0.j, ...,\n",
|
|
" 0. +0.j, 0. +0.j, 0. +0.j],\n",
|
|
" ...,\n",
|
|
" [ 0. +0.j, 0. +0.j, 0. +0.j, ...,\n",
|
|
" 0. +0.j, 0. +0.j, 0. +0.j],\n",
|
|
" [ 0. +0.j, 0. +0.j, 0.70710678+0.j, ...,\n",
|
|
" 0. +0.j, 0. +0.j, 0. +0.j],\n",
|
|
" [ 0.70710678+0.j, -0.70710678+0.j, 0. +0.j, ...,\n",
|
|
" 0. +0.j, 0. +0.j, 0. +0.j]],\n",
|
|
" input_dims=(2, 2, 2, 2, 2, 2, 2, 2, 2, 2), output_dims=(2, 2, 2, 2, 2, 2, 2, 2, 2, 2))\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Create an operator from a QuantumCircuit object\n",
|
|
"circ = QuantumCircuit(10)\n",
|
|
"circ.h(0)\n",
|
|
"for j in range(1, 10):\n",
|
|
" circ.cx(j - 1, j)\n",
|
|
"\n",
|
|
"# Convert circuit to an operator by implicit unitary simulation\n",
|
|
"Operator(circ)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "693e4885-bd79-4a2f-8e2b-8e4d81892c05",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Use Operators in circuits\n",
|
|
"\n",
|
|
"Unitary `Operators` can be directly inserted into a `QuantumCircuit` using the `QuantumCircuit.append` method. This converts the `Operator` into a `UnitaryGate` object, which is added to the circuit.\n",
|
|
"\n",
|
|
"If the operator is not unitary, an exception is raised. This can be checked using the `Operator.is_unitary()` function, which returns `True` if the operator is unitary and `False` otherwise."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"id": "223c07c9-1b1d-4a33-a397-091cac2ec9e3",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"image/svg+xml": [
|
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg width=\"266.38pt\" height=\"172pt\" version=\"1.1\" viewBox=\"0 0 266.38 172\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><defs><style type=\"text/css\">*{stroke-linejoin: round; stroke-linecap: butt}</style></defs><path d=\"m0 172h266.38v-172h-266.38z\" fill=\"#ffffff\"/><path d=\"m64.497 44.283h190.05\" clip-path=\"url(#e2710788234)\" fill=\"none\" stroke=\"#000000\" stroke-linecap=\"square\" stroke-width=\"2\"/><path d=\"m64.497 90.637h190.05\" clip-path=\"url(#e2710788234)\" fill=\"none\" stroke=\"#000000\" stroke-linecap=\"square\" stroke-width=\"2\"/><path d=\"m73.768 141.63 4.6354-9.2708\" clip-path=\"url(#e2710788234)\" fill=\"none\" stroke=\"#778899\" stroke-linecap=\"square\"/><path d=\"m64.497 135.48h190.05\" clip-path=\"url(#e2710788234)\" fill=\"none\" stroke=\"#778899\" stroke-linecap=\"square\" stroke-width=\"2\"/><path d=\"m64.497 138.5h190.05\" clip-path=\"url(#e2710788234)\" fill=\"none\" stroke=\"#778899\" stroke-linecap=\"square\" stroke-width=\"2\"/><path d=\"m176.21 126.45h12.052l-6.026 8.6914z\" clip-path=\"url(#e2710788234)\" fill=\"#778899\"/><path d=\"m222.56 126.45h12.052l-6.026 8.6914z\" clip-path=\"url(#e2710788234)\" fill=\"#778899\"/><path d=\"m59.862 21.106h-1158.8v185.42h1158.8z\" clip-path=\"url(#e2710788234)\" fill=\"#ffffff\" stroke=\"#ffffff\" stroke-width=\"1.5\"/><path d=\"m183.74 44.283v82.162\" clip-path=\"url(#e2710788234)\" fill=\"none\" stroke=\"#778899\" stroke-linecap=\"square\" stroke-width=\"2\"/><path d=\"m180.73 44.283v82.162\" clip-path=\"url(#e2710788234)\" fill=\"none\" stroke=\"#778899\" stroke-linecap=\"square\" stroke-width=\"2\"/><path d=\"m230.1 90.637v35.808\" clip-path=\"url(#e2710788234)\" fill=\"none\" stroke=\"#778899\" stroke-linecap=\"square\" stroke-width=\"2\"/><path d=\"m227.08 90.637v35.808\" clip-path=\"url(#e2710788234)\" fill=\"none\" stroke=\"#778899\" stroke-linecap=\"square\" stroke-width=\"2\"/><path d=\"m82.344 105.7h60.724v-76.484h-60.724z\" clip-path=\"url(#e2710788234)\" fill=\"#9f1853\" stroke=\"#9f1853\" stroke-width=\"1.5\"/><path d=\"m167.17 59.348h30.13v-30.13h-30.13z\" clip-path=\"url(#e2710788234)\" fill=\"#a8a8a8\" stroke=\"#a8a8a8\" stroke-width=\"1.5\"/><path d=\"m192.78 48.803c0-2.7958-1.1118-5.4799-3.0887-7.4568s-4.661-3.0887-7.4568-3.0887-5.4799 1.1118-7.4568 3.0887-3.0887 4.661-3.0887 7.4568\" clip-path=\"url(#e2710788234)\" fill=\"none\" stroke=\"#000000\" stroke-width=\"2\"/><path d=\"m182.24 48.803 10.546-10.546\" clip-path=\"url(#e2710788234)\" fill=\"none\" stroke=\"#000000\" stroke-linecap=\"square\" stroke-width=\"2\"/><path d=\"m213.53 105.7h30.13v-30.13h-30.13z\" clip-path=\"url(#e2710788234)\" fill=\"#a8a8a8\" stroke=\"#a8a8a8\" stroke-width=\"1.5\"/><path d=\"m239.14 95.157c0-2.7958-1.1118-5.4799-3.0887-7.4568s-4.661-3.0887-7.4568-3.0887-5.4799 1.1118-7.4568 3.0887-3.0887 4.661-3.0887 7.4568\" clip-path=\"url(#e2710788234)\" fill=\"none\" stroke=\"#000000\" stroke-width=\"2\"/><path d=\"m228.59 95.157 10.546-10.546\" clip-path=\"url(#e2710788234)\" fill=\"none\" stroke=\"#000000\" stroke-linecap=\"square\" stroke-width=\"2\"/><g clip-path=\"url(#e2710788234)\"><g transform=\"translate(37.189 48.734) scale(.1625 -.1625)\"><defs><path id=\"DejaVuSans-Oblique-71\" transform=\"scale(.015625)\" d=\"m2669 525q-231-303-546-460-314-156-695-156-531 0-833 358-301 358-301 986 0 506 186 978t533 847q225 244 517 375t614 131q387 0 637-153t363-462l100 525h578l-934-4813h-579l360 1844zm-1778 813q0-463 193-705 194-242 560-242 544 0 928 520t384 1264q0 450-199 689-198 239-569 239-272 0-504-127-231-126-403-370-181-256-286-600-104-343-104-668z\"/><path id=\"DejaVuSans-30\" transform=\"scale(.015625)\" d=\"m2034 4250q-487 0-733-480-245-479-245-1442 0-959 245-1439 246-480 733-480 491 0 736 480 246 480 246 1439 0 963-246 1442-245 480-736 480zm0 500q785 0 1199-621 414-620 414-1801 0-1178-414-1799-414-620-1199-620-784 0-1198 620-414 621-414 1799 0 1181 414 1801 414 621 1198 621z\"/></defs><use xlink:href=\"#DejaVuSans-Oblique-71\"/><use transform=\"translate(63.477 -16.406) scale(.7)\" xlink:href=\"#DejaVuSans-30\"/></g></g><g clip-path=\"url(#e2710788234)\"><g transform=\"translate(37.189 95.088) scale(.1625 -.1625)\"><defs><path id=\"DejaVuSans-31\" transform=\"scale(.015625)\" d=\"m794 531h1031v3560l-1122-225v575l1116 225h631v-4135h1031v-531h-2687v531z\"/></defs><use xlink:href=\"#DejaVuSans-Oblique-71\"/><use transform=\"translate(63.477 -16.406) scale(.7)\" xlink:href=\"#DejaVuSans-31\"/></g></g><g clip-path=\"url(#e2710788234)\"><g transform=\"translate(69.133 130.19) scale(.104 -.104)\"><defs><path id=\"DejaVuSans-32\" transform=\"scale(.015625)\" d=\"m1228 531h2203v-531h-2962v531q359 372 979 998 621 627 780 809 303 340 423 576 121 236 121 464 0 372-261 606-261 235-680 235-297 0-627-103-329-103-704-313v638q381 153 712 231 332 78 607 78 725 0 1156-363 431-362 431-968 0-288-108-546-107-257-392-607-78-91-497-524-418-433-1181-1211z\"/></defs><use xlink:href=\"#DejaVuSans-32\"/></g></g><g clip-path=\"url(#e2710788234)\"><g transform=\"translate(46.291 141.48) scale(.1625 -.1625)\"><defs><path id=\"DejaVuSans-63\" transform=\"scale(.015625)\" d=\"m3122 3366v-538q-244 135-489 202t-495 67q-560 0-870-355-309-354-309-995t309-996q310-354 870-354 250 0 495 67t489 202v-532q-241-112-499-168-257-57-548-57-791 0-1257 497-465 497-465 1341 0 856 470 1346 471 491 1290 491 265 0 518-55 253-54 491-163z\"/></defs><use xlink:href=\"#DejaVuSans-63\"/></g></g><g clip-path=\"url(#e2710788234)\"><g transform=\"translate(85.588 47.87) scale(.13 -.13)\" fill=\"#ffffff\"><use xlink:href=\"#DejaVuSans-30\"/></g></g><g clip-path=\"url(#e2710788234)\"><g transform=\"translate(85.588 94.224) scale(.13 -.13)\" fill=\"#ffffff\"><use xlink:href=\"#DejaVuSans-31\"/></g></g><g clip-path=\"url(#e2710788234)\"><g transform=\"translate(94.071 71.047) scale(.13 -.13)\" fill=\"#ffffff\"><defs><path id=\"DejaVuSans-55\" transform=\"scale(.015625)\" d=\"m556 4666h635v-2835q0-750 271-1080 272-329 882-329 606 0 878 329 272 330 272 1080v2835h634v-2913q0-912-452-1378-451-466-1332-466-885 0-1337 466-451 466-451 1378v2913z\"/><path id=\"DejaVuSans-6e\" transform=\"scale(.015625)\" d=\"m3513 2113v-2113h-575v2094q0 497-194 743-194 247-581 247-466 0-735-297-269-296-269-809v-1978h-578v3500h578v-544q207 316 486 472 280 156 646 156 603 0 912-373 310-373 310-1098z\"/><path id=\"DejaVuSans-69\" transform=\"scale(.015625)\" d=\"m603 3500h575v-3500h-575v3500zm0 1363h575v-729h-575v729z\"/><path id=\"DejaVuSans-74\" transform=\"scale(.015625)\" d=\"m1172 4494v-994h1184v-447h-1184v-1900q0-428 117-550t477-122h590v-481h-590q-666 0-919 248-253 249-253 905v1900h-422v447h422v994h578z\"/><path id=\"DejaVuSans-61\" transform=\"scale(.015625)\" d=\"m2194 1759q-697 0-966-159t-269-544q0-306 202-486 202-179 548-179 479 0 768 339t289 901v128h-572zm1147 238v-1997h-575v531q-197-318-491-470t-719-152q-537 0-855 302-317 302-317 808 0 590 395 890 396 300 1180 300h807v57q0 397-261 614t-733 217q-300 0-585-72-284-72-546-216v532q315 122 612 182 297 61 578 61 760 0 1135-394 375-393 375-1193z\"/><path id=\"DejaVuSans-72\" transform=\"scale(.015625)\" d=\"m2631 2963q-97 56-211 82-114 27-251 27-488 0-749-317t-261-911v-1844h-578v3500h578v-544q182 319 472 473 291 155 707 155 59 0 131-8 72-7 159-23l3-590z\"/><path id=\"DejaVuSans-79\" transform=\"scale(.015625)\" d=\"m2059-325q-243-625-475-815-231-191-618-191h-460v481h338q237 0 368 113 132 112 291 531l103 262-1415 3444h609l1094-2737 1094 2737h609l-1538-3825z\"/></defs><use xlink:href=\"#DejaVuSans-55\"/><use x=\"73.193359\" xlink:href=\"#DejaVuSans-6e\"/><use x=\"136.572266\" xlink:href=\"#DejaVuSans-69\"/><use x=\"164.355469\" xlink:href=\"#DejaVuSans-74\"/><use x=\"203.564453\" xlink:href=\"#DejaVuSans-61\"/><use x=\"264.84375\" xlink:href=\"#DejaVuSans-72\"/><use x=\"305.957031\" xlink:href=\"#DejaVuSans-79\"/></g></g><g clip-path=\"url(#e2710788234)\"><g transform=\"translate(193.82 130.19) scale(.104 -.104)\"><use xlink:href=\"#DejaVuSans-30\"/></g></g><g clip-path=\"url(#e2710788234)\"><g transform=\"translate(240.18 130.19) scale(.104 -.104)\"><use xlink:href=\"#DejaVuSans-31\"/></g></g><defs><clipPath id=\"e2710788234\"><rect x=\"7.2\" y=\"7.2\" width=\"251.98\" height=\"157.6\"/></clipPath></defs></svg>"
|
|
],
|
|
"text/plain": [
|
|
"<Figure size 454.517x284.278 with 1 Axes>"
|
|
]
|
|
},
|
|
"execution_count": 6,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"# Create an operator\n",
|
|
"XX = Operator(Pauli(\"XX\"))\n",
|
|
"\n",
|
|
"# Add to a circuit\n",
|
|
"circ = QuantumCircuit(2, 2)\n",
|
|
"circ.append(XX, [0, 1])\n",
|
|
"circ.measure([0, 1], [0, 1])\n",
|
|
"circ.draw(\"mpl\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "04a90485-7b03-4ae3-a37d-0ae87feee6a4",
|
|
"metadata": {},
|
|
"source": [
|
|
"Note that in the above example the operator is initialized from a `Pauli` object. However, the `Pauli` object may also be directly inserted into the circuit itself and will be converted into a sequence of single-qubit Pauli gates:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"id": "85f37f4a-078e-401f-b222-ec230da6ae78",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/html": [
|
|
"<pre style=\"word-wrap: normal;white-space: pre;background: #fff0;line-height: 1.1;font-family: "Courier New",Courier,monospace\"> ┌────────────┐┌─┐ \n",
|
|
"q_0: ┤0 ├┤M├───\n",
|
|
" │ Pauli(XX) │└╥┘┌─┐\n",
|
|
"q_1: ┤1 ├─╫─┤M├\n",
|
|
" └────────────┘ ║ └╥┘\n",
|
|
"c: 2/═══════════════╩══╩═\n",
|
|
" 0 1 </pre>"
|
|
],
|
|
"text/plain": [
|
|
" ┌────────────┐┌─┐ \n",
|
|
"q_0: ┤0 ├┤M├───\n",
|
|
" │ Pauli(XX) │└╥┘┌─┐\n",
|
|
"q_1: ┤1 ├─╫─┤M├\n",
|
|
" └────────────┘ ║ └╥┘\n",
|
|
"c: 2/═══════════════╩══╩═\n",
|
|
" 0 1 "
|
|
]
|
|
},
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"# Add to a circuit\n",
|
|
"circ2 = QuantumCircuit(2, 2)\n",
|
|
"circ2.append(Pauli(\"XX\"), [0, 1])\n",
|
|
"circ2.measure([0, 1], [0, 1])\n",
|
|
"circ2.draw()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "59bf4972-731f-40c4-9d26-ca0110827cdc",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Combine Operators\n",
|
|
"\n",
|
|
"Operators may be combined using several methods.\n",
|
|
"\n",
|
|
"### Tensor product\n",
|
|
"\n",
|
|
"Two operators $A$ and $B$ can be combined into a tensor product operator $A\\otimes B$ using the `Operator.tensor` function. Note that if both $A$ and $B$ are single-qubit operators, then `A.tensor(B)` = $A\\otimes B$ will have the subsystems indexed as matrix $B$ on subsystem 0, and matrix $A$ on subsystem 1."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"id": "0fcf1f68-8af1-417f-b6c3-313846ec5b0d",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Operator([[ 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],\n",
|
|
" [ 0.+0.j, -0.+0.j, 0.+0.j, -1.+0.j],\n",
|
|
" [ 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],\n",
|
|
" [ 0.+0.j, -1.+0.j, 0.+0.j, -0.+0.j]],\n",
|
|
" input_dims=(2, 2), output_dims=(2, 2))\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"A = Operator(Pauli(\"X\"))\n",
|
|
"B = Operator(Pauli(\"Z\"))\n",
|
|
"A.tensor(B)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "bca7c8a7-5f19-405c-9f27-3e75db53cb5e",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Tensor expansion\n",
|
|
"\n",
|
|
"A closely related operation is `Operator.expand`, which acts like a tensor product but in the reverse order. Hence, for two operators $A$ and $B$ you have `A.expand(B)` = $B\\otimes A$ where the subsystems are indexed as matrix $A$ on subsystem 0, and matrix $B$ on subsystem 1."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"id": "a38a8588-f0a5-4533-95dc-23ff383501d6",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Operator([[ 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",
|
|
" [ 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",
|
|
" input_dims=(2, 2), output_dims=(2, 2))\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"A = Operator(Pauli(\"X\"))\n",
|
|
"B = Operator(Pauli(\"Z\"))\n",
|
|
"A.expand(B)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "6a33cf17-68f8-442d-b4e0-6b899d1d280a",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Composition\n",
|
|
"\n",
|
|
"You can also compose two operators $A$ and $B$ to implement matrix multiplication using the `Operator.compose` method. `A.compose(B)` returns the operator with matrix $B.A$:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"id": "a45e1ef6-09b4-4d70-a9e2-0eb5f1b59a83",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Operator([[ 0.+0.j, 1.+0.j],\n",
|
|
" [-1.+0.j, 0.+0.j]],\n",
|
|
" input_dims=(2,), output_dims=(2,))\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"A = Operator(Pauli(\"X\"))\n",
|
|
"B = Operator(Pauli(\"Z\"))\n",
|
|
"A.compose(B)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "f54c6b4e-e8ac-4ae7-ac02-60300a46c88c",
|
|
"metadata": {},
|
|
"source": [
|
|
"You can also compose in the reverse order by applying $B$ in front of $A$ using the `front` kwarg of `compose`: `A.compose(B, front=True)` = $A.B$:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 11,
|
|
"id": "30b6a60d-11fd-4b19-a673-790aab891554",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Operator([[ 0.+0.j, -1.+0.j],\n",
|
|
" [ 1.+0.j, 0.+0.j]],\n",
|
|
" input_dims=(2,), output_dims=(2,))\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"A = Operator(Pauli(\"X\"))\n",
|
|
"B = Operator(Pauli(\"Z\"))\n",
|
|
"A.compose(B, front=True)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "f08c91f5-88f0-408f-ae9e-03cec65de305",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Subsystem composition\n",
|
|
"\n",
|
|
"Note that the previous compose requires that the total output dimension of the first operator $A$ is equal to the total input dimension of the composed operator $B$ (and similarly, the output dimension of $B$ must be equal to the input dimension of $A$ when composing with `front=True`).\n",
|
|
"\n",
|
|
"You can also compose a smaller operator with a selection of subsystems on a larger operator using the `qargs` kwarg of `compose`, either with or without `front=True`. In this case, the relevant input and output dimensions of the subsystems being composed must match. *Note that the smaller operator must always be the argument of the* `compose` *method.*\n",
|
|
"\n",
|
|
"For example, to compose a two-qubit gate with a three-qubit operator:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 12,
|
|
"id": "e604f408-3ec3-49fa-830a-eaf960fdd40d",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Operator([[ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j,\n",
|
|
" 0.+0.j],\n",
|
|
" [ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, -1.+0.j, 0.+0.j,\n",
|
|
" 0.+0.j],\n",
|
|
" [ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j,\n",
|
|
" 0.+0.j],\n",
|
|
" [ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,\n",
|
|
" -1.+0.j],\n",
|
|
" [ 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,\n",
|
|
" 0.+0.j],\n",
|
|
" [ 0.+0.j, -1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,\n",
|
|
" 0.+0.j],\n",
|
|
" [ 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,\n",
|
|
" 0.+0.j],\n",
|
|
" [ 0.+0.j, 0.+0.j, 0.+0.j, -1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,\n",
|
|
" 0.+0.j]],\n",
|
|
" input_dims=(2, 2, 2), output_dims=(2, 2, 2))\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Compose XZ with a 3-qubit identity operator\n",
|
|
"op = Operator(np.eye(2**3))\n",
|
|
"XZ = Operator(Pauli(\"XZ\"))\n",
|
|
"op.compose(XZ, qargs=[0, 2])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 13,
|
|
"id": "d2024a14-891b-46e4-93e7-4dc73e33e928",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Operator([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.-1.j, 0.+0.j, 0.+0.j],\n",
|
|
" [0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.-1.j, 0.+0.j, 0.+0.j, 0.+0.j],\n",
|
|
" [0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.-1.j],\n",
|
|
" [0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 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, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],\n",
|
|
" [0.+1.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],\n",
|
|
" [0.+0.j, 0.+0.j, 0.+0.j, 0.+1.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],\n",
|
|
" [0.+0.j, 0.+0.j, 0.+1.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]],\n",
|
|
" input_dims=(2, 2, 2), output_dims=(2, 2, 2))\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Compose YX in front of the previous operator\n",
|
|
"op = Operator(np.eye(2**3))\n",
|
|
"YX = Operator(Pauli(\"YX\"))\n",
|
|
"op.compose(YX, qargs=[0, 2], front=True)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "5e362de3-866d-42b3-8d3c-a3905d9d4005",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Linear combinations\n",
|
|
"\n",
|
|
"Operators may also be combined using standard linear operators for addition, subtraction, and scalar multiplication by complex numbers."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 14,
|
|
"id": "79b9ccd5-a002-4499-9439-7c553177abb8",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Operator([[-1.5+0.j, 0. +0.j, 0. +0.j, 0. +0.j],\n",
|
|
" [ 0. +0.j, 1.5+0.j, 1. +0.j, 0. +0.j],\n",
|
|
" [ 0. +0.j, 1. +0.j, 1.5+0.j, 0. +0.j],\n",
|
|
" [ 0. +0.j, 0. +0.j, 0. +0.j, -1.5+0.j]],\n",
|
|
" input_dims=(2, 2), output_dims=(2, 2))\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"XX = Operator(Pauli(\"XX\"))\n",
|
|
"YY = Operator(Pauli(\"YY\"))\n",
|
|
"ZZ = Operator(Pauli(\"ZZ\"))\n",
|
|
"\n",
|
|
"op = 0.5 * (XX + YY - 3 * ZZ)\n",
|
|
"op"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "235d9549-a7f6-4c8c-8592-de57e5e45fc6",
|
|
"metadata": {},
|
|
"source": [
|
|
"An important point is that while `tensor`, `expand`, and `compose` preserves the unitarity of unitary operators, linear combinations do not; hence, adding two unitary operators will, in general, result in a non-unitary operator:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 15,
|
|
"id": "97615df2-f6dc-4367-8463-f5c0c1ef94eb",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"False"
|
|
]
|
|
},
|
|
"execution_count": 15,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"op.is_unitary()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "1a2bf1cd-6f0f-446f-a993-ae9c2d22984e",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Implicit conversion to Operators\n",
|
|
"\n",
|
|
"Note that for all the following methods, if the second object is not already an `Operator` object, it is implicitly converted into one by the method. This means that matrices can be passed in directly without being explicitly converted to an `Operator` first. If the conversion is not possible, an exception is raised."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 16,
|
|
"id": "9d72e40f-8d72-4cd7-8350-1896e88528c0",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Operator([[0.+0.j, 1.+0.j],\n",
|
|
" [1.+0.j, 0.+0.j]],\n",
|
|
" input_dims=(2,), output_dims=(2,))\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Compose with a matrix passed as a list\n",
|
|
"Operator(np.eye(2)).compose([[0, 1], [1, 0]])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "0ee93f02-c3ea-44b0-8b87-f79e3107749e",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Compare Operators\n",
|
|
"\n",
|
|
"Operators implement an equality method that can be used to check if two operators are approximately equal."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 17,
|
|
"id": "ce9983d1-e20a-432d-af22-d6a1011f412c",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"True"
|
|
]
|
|
},
|
|
"execution_count": 17,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"Operator(Pauli(\"X\")) == Operator(XGate())"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "36bbbbf9-3ed7-4aab-bc9e-f542325372f1",
|
|
"metadata": {},
|
|
"source": [
|
|
"Note that this checks that each matrix element of the operators is approximately equal; two unitaries that differ by a global phase are not considered equal:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 18,
|
|
"id": "a42ba8a1-5ab5-44d0-bd54-4147f4f28e53",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"False"
|
|
]
|
|
},
|
|
"execution_count": 18,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"Operator(XGate()) == np.exp(1j * 0.5) * Operator(XGate())"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "c06612c0-be6e-41b5-9ba5-92a9d7755c2f",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Process fidelity\n",
|
|
"\n",
|
|
"You can also compare operators using the `process_fidelity` function from the *Quantum Information* module. This is an information-theoretic quantity for how close two quantum channels are to each other, and in the case of unitary operators it does not depend on global phase."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 19,
|
|
"id": "813d97d1-94d3-4c65-aca0-324b09cebc6a",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Process fidelity ="
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
" 1.0\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Two operators which differ only by phase\n",
|
|
"op_a = Operator(XGate())\n",
|
|
"op_b = np.exp(1j * 0.5) * Operator(XGate())\n",
|
|
"\n",
|
|
"# Compute process fidelity\n",
|
|
"F = process_fidelity(op_a, op_b)\n",
|
|
"print(\"Process fidelity =\", F)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "993bab6d-7f37-4363-a17e-8b8e3b7de30a",
|
|
"metadata": {},
|
|
"source": [
|
|
"Note that process fidelity is generally only a valid measure of closeness if the input operators are unitary (or CP in the case of quantum channels), and an exception is raised if the inputs are not CP."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "52ef24af-888c-4c76-ab6f-4e1e8323cf2a",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Next steps\n",
|
|
"\n",
|
|
"<Admonition type=\"tip\" title=\"Recommendations\">\n",
|
|
" - Explore the [Operator API](/api/qiskit/qiskit.quantum_info.Operator#operator) reference.\n",
|
|
"</Admonition>"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"anaconda-cloud": {},
|
|
"celltoolbar": "Tags",
|
|
"description": "In-depth explanation of using the Operator class in Qiskit.",
|
|
"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": "The Operator class",
|
|
"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
|
|
}
|