191 lines
6.4 KiB
Plaintext
191 lines
6.4 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "61279ea7-f7f7-4cc3-8b9b-55497645e990",
|
||
"metadata": {
|
||
"tags": [
|
||
"version-info"
|
||
]
|
||
},
|
||
"source": [
|
||
"# Synthesize unitary operations"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "4c61cda7-58c7-44ea-a875-f008da47f439",
|
||
"metadata": {},
|
||
"source": [
|
||
"A unitary operation describes a norm-preserving change to a quantum system.\n",
|
||
"For $n$ qubits this change is described by a $2^n \\times 2^n$ dimensional, complex matrix $U$ whose adjoint equals the inverse, that is $U^\\dagger U = \\mathbb{1}$.\n",
|
||
"\n",
|
||
"Synthesizing specific unitary operations into a set of quantum gates is a fundamental task used, for example, in the design and application of quantum algorithms or in compiling quantum circuits.\n",
|
||
"\n",
|
||
"While efficient synthesis is possible for certain classes of unitaries – like those composed of Clifford gates or having a tensor product structure – most unitaries do not fall into these categories.\n",
|
||
"For general unitary matrices, synthesis is a complex task with computational costs that increase exponentially with the number of qubits.\n",
|
||
"Therefore, if you know an efficient decomposition for the unitary you would like to implement, it will likely be better than a general synthesis.\n",
|
||
"\n",
|
||
"<Admonition type=\"note\">\n",
|
||
" If no decomposition is available, the Qiskit SDK provides you with the tools to find one.\n",
|
||
" However, note that this generally generates deep circuits that may be unsuitable to run on noisy quantum computers.\n",
|
||
"</Admonition>"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 5,
|
||
"id": "306c494e-cb0b-4f4b-b698-5ed7e8492b4a",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"<qiskit.circuit.instructionset.InstructionSet at 0x7f5815995ab0>"
|
||
]
|
||
},
|
||
"execution_count": 5,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"import numpy as np\n",
|
||
"from qiskit import QuantumCircuit\n",
|
||
"\n",
|
||
"U = 0.5 * np.array(\n",
|
||
" [[1, 1, 1, 1], [-1, 1, -1, 1], [-1, -1, 1, 1], [-1, 1, 1, -1]]\n",
|
||
")\n",
|
||
"\n",
|
||
"circuit = QuantumCircuit(2)\n",
|
||
"circuit.unitary(U, circuit.qubits)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "306d503f-d0ba-4607-9cff-dc5e2e22a3c0",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Re-synthesis for circuit optimization\n",
|
||
"\n",
|
||
"Sometimes it is beneficial to re-synthesize a long series of single- and two-qubit gates, if the length can be reduced. For example, the following circuit uses three two-qubit gates."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 9,
|
||
"id": "85b63631-b958-48ac-9951-4fa65222a6e1",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"<Image src=\"/docs/images/guides/synthesize-unitary-operators/extracted-outputs/85b63631-b958-48ac-9951-4fa65222a6e1-0.avif\" alt=\"Output of the previous code cell\" />"
|
||
]
|
||
},
|
||
"execution_count": 9,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit\n",
|
||
"\n",
|
||
"qreg_q = QuantumRegister(2, \"q\")\n",
|
||
"creg_c = ClassicalRegister(4, \"c\")\n",
|
||
"circuit = QuantumCircuit(qreg_q, creg_c)\n",
|
||
"\n",
|
||
"circuit.h(qreg_q[0])\n",
|
||
"circuit.cx(qreg_q[0], qreg_q[1])\n",
|
||
"circuit.sx(qreg_q[1])\n",
|
||
"circuit.cz(qreg_q[0], qreg_q[1])\n",
|
||
"circuit.x(qreg_q[1])\n",
|
||
"circuit.x(qreg_q[0])\n",
|
||
"circuit.cx(qreg_q[0], qreg_q[1])\n",
|
||
"circuit.h(qreg_q[0])\n",
|
||
"circuit.draw(\"mpl\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "fce8c4f4-09b9-4d4f-8a92-41804d84e702",
|
||
"metadata": {},
|
||
"source": [
|
||
"However, after re-synthesizing with the following code, it only needs a single CX gate. (Here we use the `QuantumCircuit.decompose()` method to better visualize the gates used to re-synthesize the unitary.)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 7,
|
||
"id": "b9dedbfc-8378-4603-96dc-1c373a0a846d",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"global phase: 4.9931\n",
|
||
" ┌───────────────┐ ┌───────────────┐ \n",
|
||
"q_0: ─┤ U(π/2,-π/2,0) ├───■────┤ U(π/2,0,-π/2) ├──\n",
|
||
" ┌┴───────────────┴┐┌─┴─┐┌─┴───────────────┴─┐\n",
|
||
"q_1: ┤ U(2.1322,π/2,0) ├┤ X ├┤ U(π/2,-0.56139,0) ├\n",
|
||
" └─────────────────┘└───┘└───────────────────┘"
|
||
]
|
||
},
|
||
"execution_count": 7,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"from qiskit.quantum_info import Operator\n",
|
||
"\n",
|
||
"# compute unitary matrix of circuit\n",
|
||
"U = Operator(circuit)\n",
|
||
"\n",
|
||
"# re-synthesize\n",
|
||
"better_circuit = QuantumCircuit(2)\n",
|
||
"better_circuit.unitary(U, range(2))\n",
|
||
"better_circuit.decompose().draw()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "a1ebebda-423f-4f0e-acfe-3c83d3c3148b",
|
||
"metadata": {},
|
||
"source": [
|
||
"Qiskit's [transpile](../api/qiskit/compiler#qiskit.compiler.transpile) function automatically performs this re-synthesis for a sufficiently high optimization level.\n",
|
||
"\n",
|
||
"## Next steps\n",
|
||
"\n",
|
||
"<Admonition type=\"tip\" title=\"Recommendations\">\n",
|
||
" - See an example of circuit decomposition in the [Grover's Algorithm](https://learning.quantum.ibm.com/tutorial/grovers-algorithm) tutorial.\n",
|
||
" - For more information about the Qiskit transpiler, visit the [Transpile section](./transpile).\n",
|
||
"</Admonition>"
|
||
]
|
||
}
|
||
],
|
||
"metadata": {
|
||
"description": "On the implementation of arbitrary unitary matrices on qubits",
|
||
"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": "Synthesize unitary operations"
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 4
|
||
}
|