Skip to content

Commit

Permalink
New visualization and minor changes to PK notebook
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam Gitter authored and Adam Gitter committed Feb 19, 2025
1 parent 3ce2e67 commit 0ec7b1b
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 132 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,37 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Phase kickback [[1](#childs),[2](#LinLin),[3](#Wolf)] is an important and highly used primitive in quantum computing. It deals with kicking the result of a function to the phase of a quantum state so it can be smartly manipulated with constructive and destructive interferences to achieve the desired result. Every quantum algortihm can be decomposed into these steps: 1) Encoding the data; 2) Manipulating the data; and 3) Extracting the result. The phase kickback primitive is a key step in the manipulation of the data that enables extracting the result. See the [Deutsch-Jozsa](https://github.com/Classiq/classiq-library/blob/main/algorithms/deutsch_jozsa/deutsch_jozsa.ipynb) and [Simon's](https://github.com/Classiq/classiq-library/blob/main/algorithms/simon/simon.ipynb) algorithms for concrete examples.\n",
"Phase kickback [[1](#childs),[2](#LinLin),[3](#Wolf)] is an important and highly used primitive in quantum computing. The algorithm deals with \"kicking\" the result of a function to the phase of a quantum state so it can be wisely manipulated with interferences to achieve the desired result. Every quantum algorithm can be decomposed into these steps: 1) Encoding the data, 2) Manipulating the data, and 3) Extracting the result. The phase kickback primitive is a key step in manipulating the data, enabling the extraction of the result. See the [Deutsch-Jozsa](https://github.com/Classiq/classiq-library/blob/main/algorithms/deutsch_jozsa/deutsch_jozsa.ipynb) and [Simon's](https://github.com/Classiq/classiq-library/blob/main/algorithms/simon/simon.ipynb) algorithms for concrete examples.\n",
"\n",
"The standard way [[4](#NielsenChuang)] to apply a classical function $f:\\{0,1\\}^n \\rightarrow \\{0,1\\}$ on quantum states is with the oracle model: \n",
"$\\begin{equation}\n",
"The standard way [[4](#NielsenChuang)] of applying a classical function $f:\\{0,1\\}^n \\rightarrow \\{0,1\\}$ on quantum states is by utilizing the oracle model \n",
"$$\n",
"O_f (|x \\rangle_n|y \\rangle_1) = |x \\rangle_n|y \\oplus f(x) \\rangle_1\n",
"\\end{equation}$\n",
"with $|x \\rangle$ and $|y \\rangle$ as the argument and target quantum states, respectively, and $\\oplus$ as the addition modolu $2$ or the XOR operation. The phase kickback primitive takes the oracle $O_f$ as input, and performs this operation:\n",
"$$\n",
"where $|x \\rangle$ and $|y \\rangle$ are the argument and target quantum states, respectively, and $\\oplus$ is the addition modulo $2$ or the XOR operation. \n",
"\n",
"The phase kickback primitive takes the oracle $O_f$ as input, and performs the operation\n",
"$\\begin{equation}\n",
"|x \\rangle\\rightarrow (-1)^{f(x)}|x \\rangle\n",
"\\end{equation}$\n",
"This can be applied on a superposition of state:\n",
"\\end{equation}$. \n",
"This can be applied to a superposition of states \n",
"$\\begin{equation}\n",
"\\sum_{i=0}^{2^n-1}\\alpha_i|x_i \\rangle\\rightarrow (-1)^{f(x_i)}\\alpha_i|x_i \\rangle\n",
"\\end{equation}$\n",
"with $\\alpha_i$ as the amplitude of the $|x_i \\rangle$ state.\n",
"as well, where $\\alpha_i$ are the amplitudes of the $|x_i \\rangle$ state. \n",
"\n",
"How does this happen? Its beauty lies in its simplicity: applying the oracle $O_f$ to the state target quantum state $|- \\rangle=\\frac{1}{\\sqrt{2}}|0 \\rangle-\\frac{1}{\\sqrt{2}}|1 \\rangle$:\n",
"$\\begin{equation}\n",
"The operation is achieved by simply applying the oracle $O_f$ to the state target quantum state $|- \\rangle=\\frac{1}{\\sqrt{2}}|0 \\rangle-\\frac{1}{\\sqrt{2}}|1 \\rangle$:\n",
"$$\n",
"O_f|x \\rangle |- \\rangle = (-1)^{f(x)}|x \\rangle |- \\rangle\n",
"\\end{equation}$\n",
"then effectively achieving the desired transformation $|x \\rangle\\rightarrow (-1)^{f(x)}|x \\rangle$. "
"$$\n",
"and then arriving at the desired transformation $|x \\rangle\\rightarrow (-1)^{f(x)}|x \\rangle$. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div style=\"text-align:center;\">\n",
" <img src=\"https://docs.classiq.io/resources/phase_kickback_high_level.png\" alt=\"Phase Kickback High Level\" />\n",
" <img src=\"https://docs.classiq.io/resources/PK_high_level.png\" alt=\"Phase Kickback High Level\" />\n",
"</div>"
]
},
Expand Down Expand Up @@ -76,7 +78,7 @@
"\\end{equation}$\n",
"\n",
"This useful trick is not the same as the Phase Kickback described in the literature [[1](#childs),[2](#LinLin),[3](#Wolf)]\n",
"</details>."
"</details>"
]
},
{
Expand All @@ -90,7 +92,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"When using the Classiq system (as for any development platform), it is recommended to design your code at the functional level in terms of functions. The above figure indicates which functional building blocks you need, so you can now implement them, one function at a time, and then connect them."
"When using the Classiq platform (as for any development platform), it is recommended to design your code at the functional level in terms of functions. The above figure indicates which functional building blocks you need, so you can now implement them, one function at a time, and then connect them."
]
},
{
Expand All @@ -105,24 +107,17 @@
"metadata": {},
"source": [
"<div style=\"text-align:center;\">\n",
" <img src=\"https://docs.classiq.io/resources/phase_kickback_prepare_minus.gif\" alt=\"Phase Kickback High Level\" />\n",
" <img src=\"https://docs.classiq.io/resources/prepare_minus.gif\" alt=\"Prepare Minus Function\" />\n",
"</div>"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"execution": {
"iopub.execute_input": "2024-05-07T13:28:40.509980Z",
"iopub.status.busy": "2024-05-07T13:28:40.509504Z",
"iopub.status.idle": "2024-05-07T13:28:43.317981Z",
"shell.execute_reply": "2024-05-07T13:28:43.317192Z"
}
},
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"from classiq import H, Output, QBit, X, allocate, qfunc\n",
"from classiq import *\n",
"\n",
"\n",
"@qfunc\n",
Expand All @@ -147,7 +142,7 @@
"metadata": {},
"source": [
"<div style=\"text-align:center;\">\n",
" <img src=\"https://docs.classiq.io/resources/phase_kickback_oracle_function.gif\" alt=\"Phase Kickback High Level\" />\n",
" <img src=\"https://docs.classiq.io/resources/oracle_function_new.gif\" alt=\"Oracle Function\" />\n",
"</div>"
]
},
Expand All @@ -160,20 +155,10 @@
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"execution": {
"iopub.execute_input": "2024-05-07T13:28:43.324621Z",
"iopub.status.busy": "2024-05-07T13:28:43.323957Z",
"iopub.status.idle": "2024-05-07T13:28:43.327908Z",
"shell.execute_reply": "2024-05-07T13:28:43.327270Z"
}
},
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"from classiq import QNum\n",
"\n",
"\n",
"@qfunc\n",
"def oracle_function(target: QBit, x: QNum):\n",
" target ^= x == 0"
Expand All @@ -191,26 +176,16 @@
"metadata": {},
"source": [
"<div style=\"text-align:center;\">\n",
" <img src=\"https://docs.classiq.io/resources/phase_kickback_oracle_phase_kickback.gif\" alt=\"Phase Kickback High Level\" />\n",
" <img src=\"https://docs.classiq.io/resources/Compute_uncompute.gif\" alt=\"compute and uncompute\" />\n",
"</div>"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"execution": {
"iopub.execute_input": "2024-05-07T13:28:43.332422Z",
"iopub.status.busy": "2024-05-07T13:28:43.331903Z",
"iopub.status.idle": "2024-05-07T13:28:43.341870Z",
"shell.execute_reply": "2024-05-07T13:28:43.341160Z"
}
},
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"from classiq import within_apply\n",
"\n",
"\n",
"@qfunc\n",
"def oracle_phase_kickback(x: QNum):\n",
" target = QBit(\"target\")\n",
Expand Down Expand Up @@ -254,7 +229,7 @@
"metadata": {},
"source": [
"<div style=\"text-align:center;\">\n",
" <img src=\"https://docs.classiq.io/resources/phase_kickback_hadamrd_tansform.gif\" alt=\"Phase Kickback High Level\" />\n",
" <img src=\"https://docs.classiq.io/resources/Hadamard_PK_new.gif\" alt=\"Hadamard Transform\" />\n",
"</div>"
]
},
Expand All @@ -263,7 +238,7 @@
"metadata": {},
"source": [
"\n",
"Therefore, the phase kickback primitive is constructed of this:\n",
"Therefore, the phase kickback primitive is constructed by the following steps:\n",
"\n",
"1. Initializing the `qnum` type with $4$ qubits using the `allocate` function such that $| x \\rangle=|0\\rangle$.\n",
"2. Applying the Hadamard transform using the `hadamard_transform` function such that $| x \\rangle = \\frac{1}{\\sqrt{2^n}}\\sum_{i=0}^{2^n-1}| i \\rangle_n$.\n",
Expand All @@ -272,28 +247,18 @@
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"execution": {
"iopub.execute_input": "2024-05-07T13:28:43.345452Z",
"iopub.status.busy": "2024-05-07T13:28:43.344967Z",
"iopub.status.idle": "2024-05-07T13:28:45.966322Z",
"shell.execute_reply": "2024-05-07T13:28:45.965655Z"
}
},
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Opening: https://platform.classiq.io/circuit/51cc75df-75d3-4f91-ba4c-fc48e41784bc?version=0.41.0.dev39%2B79c8fd0855\n"
"Opening: https://platform.classiq.io/circuit/2tFx2LvEKS1hHC1H4zqM7swXcnb?version=0.66.1\n"
]
}
],
"source": [
"from classiq import create_model, hadamard_transform, show, synthesize\n",
"\n",
"\n",
"@qfunc\n",
"def main(x: Output[QNum]):\n",
" allocate(num_qubits=4, out=x)\n",
Expand All @@ -311,15 +276,15 @@
"metadata": {},
"source": [
"<div style=\"text-align:center;\">\n",
" <img src=\"https://docs.classiq.io/resources/phase_kickback_main.gif\" alt=\"Phase Kickback High Level\" />\n",
" <img src=\"https://docs.classiq.io/resources/PK_algorithm_overview.gif\" alt=\"Phase Kickback overview\" />\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Verify that the quantum program actually operates as expected; receiving a $(-)$ phase only for the state $|0\\rangle$, that is:\n",
"Verify that the quantum program actually operates as expected; receiving a minus $(-)$ phase only for the state $|0\\rangle$, that is:\n",
"$\\begin{equation}\n",
"| x \\rangle = \\frac{1}{\\sqrt{2^4}}(|1\\rangle+| 2 \\rangle+\\dots +| 15 \\rangle-|0\\rangle)\n",
"\\end{equation}$\n",
Expand All @@ -331,15 +296,15 @@
"metadata": {},
"source": [
"<div style=\"text-align:center;\">\n",
" <img src=\"https://docs.classiq.io/resources/phase_kickback_result.gif\" alt=\"Phase Kickback High Level\" />\n",
" <img src=\"https://docs.classiq.io/resources/PK_execution_new.gif\" alt=\"Execution with State Vector\" />\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Indeed, see that you receive the $(-)$ phase only for the zero state, as expected.\n",
"Indeed, we receive the minus $(-)$ phase only for the zero state, as expected.\n",
"The result shows bit strings of five bits rather than just four. This includes the `target` qubit measurement that always results in 0.\n",
"\n",
"To see how this phase kickback is actually implemented in practice see the [Deutsch-Josza example](https://github.com/Classiq/classiq-library/blob/main/algorithms/deutsch_jozsa/deutsch_jozsa.ipynb) and [Simon's example](https://github.com/Classiq/classiq-library/blob/main/algorithms/simon/simon.ipynb)."
Expand Down Expand Up @@ -405,40 +370,19 @@
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"execution": {
"iopub.execute_input": "2024-05-07T13:28:46.004172Z",
"iopub.status.busy": "2024-05-07T13:28:46.003615Z",
"iopub.status.idle": "2024-05-07T13:28:48.262514Z",
"shell.execute_reply": "2024-05-07T13:28:48.261873Z"
}
},
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Opening: https://platform.classiq.io/circuit/4915ffcd-0613-479c-b93e-14bdaa8c5d27?version=0.41.0.dev39%2B79c8fd0855\n"
"Opening: https://platform.classiq.io/circuit/2tFx8UpAVEPQkNGfpEWm73lVWkH?version=0.66.1\n"
]
}
],
"source": [
"from classiq import (\n",
" H,\n",
" Output,\n",
" QBit,\n",
" QNum,\n",
" X,\n",
" allocate,\n",
" create_model,\n",
" hadamard_transform,\n",
" qfunc,\n",
" show,\n",
" synthesize,\n",
" within_apply,\n",
" write_qmod,\n",
")\n",
"from classiq import *\n",
"\n",
"\n",
"@qfunc\n",
Expand Down Expand Up @@ -470,46 +414,16 @@
"\n",
"qmod = create_model(main)\n",
"qprog = synthesize(qmod)\n",
"show(qprog)\n",
"\n",
"write_qmod(qmod, \"phase_kickback\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Native QMOD version:"
"show(qprog)"
]
},
{
"cell_type": "markdown",
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"```\n",
"// Phase Kickback\n",
"\n",
"qfunc prepare_minus(output target:qbit){\n",
" allocate(1, target);\n",
" X(target);\n",
" H(target);\n",
"}\n",
"\n",
"qfunc oracle_function(x: qnum, target: qbit){\n",
" target ^= x==0;\n",
"}\n",
"\n",
"qfunc oracle_phase_kickback(x:qnum){\n",
" target:qbit;\n",
" within{prepare_minus(target);} apply{oracle_function(x,target);}\n",
"}\n",
"\n",
"qfunc main(output x:qnum){\n",
" allocate(4, x);\n",
" hadamard_transform(x);\n",
" oracle_phase_kickback(x);\n",
"}\n",
"```"
"write_qmod(qmod, \"phase_kickback\")"
]
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,46 @@
{}
{
"constraints": {
"max_gate_count": {},
"optimization_parameter": "no_opt"
},
"preferences": {
"machine_precision": 8,
"custom_hardware_settings": {
"basis_gates": [
"r",
"ry",
"rx",
"u1",
"u2",
"t",
"sdg",
"h",
"cx",
"sx",
"sxdg",
"x",
"tdg",
"u",
"cy",
"z",
"rz",
"cz",
"p",
"id",
"y",
"s"
],
"is_symmetric_connectivity": true
},
"debug_mode": true,
"synthesize_all_separately": false,
"optimization_level": 3,
"output_format": [
"qasm"
],
"pretty_qasm": true,
"transpilation_option": "auto optimize",
"timeout_seconds": 300,
"random_seed": 906707084
}
}

0 comments on commit 0ec7b1b

Please sign in to comment.