Skip to content

Commit

Permalink
Docs preview for PR #1728.
Browse files Browse the repository at this point in the history
  • Loading branch information
cuda-quantum-bot committed Jul 10, 2024
1 parent 3f00157 commit c389511
Show file tree
Hide file tree
Showing 94 changed files with 3,287 additions and 1,091 deletions.
Binary file added pr-1728/_images/orca_tbi.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# Deutschs' Algorithm "
"# Deutsch's Algorithm "
]
},
{
Expand All @@ -17,7 +17,7 @@
"\n",
"The function $f$ has a property; either it is constant or balanced. \n",
"\n",
"If constant, the outputs are the same regardless of the inputs i.e. $f(0) = f(1) = 0$ or $f(0) = f(1) = 1$.\n",
"If constant, the outputs are the same regardless of the inputs, i.e., $f(0) = f(1) = 0$ or $f(0) = f(1) = 1$.\n",
"\n",
"If balanced, the ouputs are balanced across their possibilities, i.e, if $f(0) = 0$ then $f(1) = 1$ or if $f(0) = 1$ then $f(1) = 0$.\n",
"\n",
Expand All @@ -32,14 +32,14 @@
"metadata": {},
"outputs": [],
"source": [
"# Treat the code snippet below like a black box, i.e you don't have access to the value of the property argument and can just query f with different inputs.\n",
"# Treat the code snippet below like a black box, i.e., you don't have access to the value of the property argument and can just query f with different inputs.\n",
"\n",
"\n",
"def f(x, property='constant'):\n",
"\n",
" if property == 'constant':\n",
"\n",
" # The output is a 1 regardless of the input, we can also make the output to be 0.\n",
" # The output is a 1 regardless of the input; we can also make the output to be 0.\n",
"\n",
" if x == 0:\n",
" return 1\n",
Expand Down Expand Up @@ -96,9 +96,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"If you step through the if statements above, one can see that we require 2 calls to the function to determine its property. That is we have to query $f$ twice.\n",
"If you step through the `if` statements above, one can see that we require 2 calls to the function to determine its property. That is, we have to query $f$ twice.\n",
"\n",
"The claim is that Deutschs' algorithm can solve for this property with 1 function evalulation demonstrating quantum advantage. \n",
"The claim is that Deutsch's algorithm can solve for this property with 1 function evalulation, demonstrating quantum advantage. \n",
"\n",
"Below we first go through the math and then the implementation in CUDA Quantum. \n",
"\n"
Expand Down Expand Up @@ -142,7 +142,7 @@
"\n",
"If $y = 0$, then $U_f\\ket{x}\\ket{y} = U_f\\ket{x}\\ket{0} = \\ket{x}\\ket{0 \\oplus f(x)} = \\ket{x}\\ket{f(x)}$ since $f(x)$ can either be $0/1$ and $0 \\oplus 0 = 0$ and $0 \\oplus 1 = 1$.\n",
"\n",
"This is remarkable as by setting $\\ket{y} = \\ket{0}$, we can extract the value of $f(x)$ by measuring the value of the second qubit. \n",
"This is remarkable because by setting $\\ket{y} = \\ket{0}$, we can extract the value of $f(x)$ by measuring the value of the second qubit. \n",
" \n",
"\n"
]
Expand All @@ -155,9 +155,9 @@
"## Phase oracle\n",
"\n",
"\n",
"Since $f(x)$ can be either $0/1$, $0 \\oplus f(x) = 0 \\oplus 0/1 = 0/1 = f(x)$. \n",
"Since $f(x)$ can be either $0$ or $1$, we have that $0 \\oplus f(x) = 0 \\oplus 0 = 0 = f(x)$ or $0 \\oplus f(x) = 0 \\oplus 1 = 1 = f(x)$. \n",
"\n",
"Similarly, $1 \\oplus f(x) = 1 \\oplus 0/1 = 1/0 = \\overline{f(x)}$ where the bar on top of $f(x)$ denotes 'not $f(x)$'. \n",
"Similarly, $1 \\oplus f(x) = 1 \\oplus 0 = 1 = \\overline{f(x)}$ or $1 \\oplus f(x) = 1 \\oplus 1 = 0 = \\overline{f(x)}$ where the bar on top of $f(x)$ denotes 'not $f(x)$'. \n",
"\n",
"\n",
"Let us now prove a result which we shall use later: \n",
Expand All @@ -178,7 +178,7 @@
"$$\n",
"\n",
"\n",
"In summary, $U_f\\ket{x}\\ket{-} = (-1)^{f(x)}\\ket{x}\\ket{-}$ where the $\\ket{-}$ qubit was left unchanged and a phase was applied to $\\ket{x}$ \n",
"In summary, $U_f\\ket{x}\\ket{-} = (-1)^{f(x)}\\ket{x}\\ket{-}$ where the $\\ket{-}$ qubit was left unchanged and a phase was applied to $\\ket{x}$. \n",
"\n",
"\n",
"\n"
Expand Down Expand Up @@ -287,9 +287,9 @@
"\\end{aligned}\n",
"$$\n",
"\n",
"We can now measure the first qubit to yield either a $0/1$ to determine if $f(x)$ is constant or balanced. \n",
"We can now measure the first qubit to yield either a $0$ or a $1$ to determine if $f(x)$ is constant or balanced. \n",
"\n",
"Deutschs' algorithm may not be practically useful but does demonstrate quantum advantage since it uses one function call to determine the property of $f$ in comparison to two for classical methods. \n",
"Deutsch's algorithm may not be practically useful but does demonstrate quantum advantage since it uses one function call to determine the property of $f$ in comparison to two for classical methods. \n",
"\n",
"\n"
]
Expand Down
32 changes: 23 additions & 9 deletions pr-1728/_sources/examples/python/tutorials/hybrid_qnns.ipynb.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,26 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Import the relevant packages.\n",
"# Install the relevant packages.\n",
"\n",
"!pip install matplotlib==3.8.4\n",
"!pip install torch==2.2.2\n",
"!pip install torchvision==0.17.0\n",
"!pip install scikit-learn==1.4.2\n",
"!pip install scikit-learn==1.4.2"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"\n",
"# Import the relevant libraries \n",
"\n",
"import cudaq\n",
"from cudaq import spin\n",
Expand Down Expand Up @@ -70,8 +80,8 @@
"device = torch.device('cpu')\n",
"cudaq.set_target(\"qpp-cpu\")\n",
"\n",
"# cudaq.set_target(\"nvidia\")\n",
"# device = torch.device(\"cuda:0\")"
"#cudaq.set_target(\"nvidia\")\n",
"#device = torch.device(\"cuda:0\")"
]
},
{
Expand Down Expand Up @@ -177,8 +187,12 @@
],
"source": [
"# Plot some images from the training set to visualise.\n",
"\n",
"grid_img = torchvision.utils.make_grid(x_train[:10],\n",
"if device != 'cpu':\n",
" sample_to_plot = x_train[:10].to(torch.device('cpu'))\n",
"else:\n",
" sample_to_plot = x_train[:10]\n",
" \n",
"grid_img = torchvision.utils.make_grid(sample_to_plot,\n",
" nrow=5,\n",
" padding=3,\n",
" normalize=True)\n",
Expand Down Expand Up @@ -344,7 +358,7 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -459,7 +473,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0]"
"version": "3.10.12"
},
"orig_nbformat": 4,
"vscode": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Classical fourier transforms aid many areas such as signal processing and data compression. Below, we quantize it to enable Quantum Fourier Transforms (QFT) in CUDA-Q.\n",
"Classical Fourier transforms aid many areas such as signal processing and data compression. Below, we quantize it to enable Quantum Fourier Transforms (QFT) in CUDA-Q.\n",
"\n",
"QFT is a key ingredient in Shor's algorithm which is exponentially faster at factoring prime numbers and also plays a vital role in many other interesting quantum algorithms. \n",
"\n",
Expand Down Expand Up @@ -90,7 +90,7 @@
"\n",
"Let us now extend this and see how we can apply this to $n=3$ qubits. \n",
"\n",
"For $n=3, N = 2^3 = 8$ and we would like to perform $\\text{QFT}|101\\rangle$ which in binary is $2^2 \\times 1 + 2^1 \\times 0 + 2^0 \\times 1 = 5 $: \n",
"For $n=3, N = 2^3 = 8$ and we would like to perform $\\text{QFT}|101\\rangle$ which in binary is $2^2 \\times 1 + 2^1 \\times 0 + 2^0 \\times 1 = 5$: \n",
"\n",
"$$\n",
"\\begin{equation} \n",
Expand All @@ -104,7 +104,7 @@
"\\end{equation}\n",
"$$\n",
"\n",
"where we have used the fact that $e^{i\\theta} = cos(\\theta) + isin(\\theta).$\n",
"where we have used the fact that $e^{i\\theta} = \\cos(\\theta) + i\\sin(\\theta).$\n",
"\n",
"Here, we see how in addition to the Hadamard gates, we need some phase gates to apply the appropriate phases to the basis states. It turns out that the gate we need is the controlled $R_k$ rotation where the $R_k$ gate is denoted by:\n",
"\n",
Expand All @@ -122,7 +122,7 @@
"\n",
"\n",
"\n",
"Here is a generalized ciruit for a $n$ qubit quantum fourier transform:"
"Here is a generalized ciruit for a $n$-qubit quantum Fourier transform:"
]
},
{
Expand Down Expand Up @@ -156,7 +156,7 @@
"@cudaq.kernel\n",
"def quantum_fourier_transform(input_state: List[int]):\n",
" '''Args: \n",
" input_state (list[int]): specifies the input state to be fourier transformed. '''\n",
" input_state (list[int]): specifies the input state to be Fourier transformed. '''\n",
"\n",
" qubit_count = len(input_state)\n",
"\n",
Expand Down Expand Up @@ -239,18 +239,132 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Barring the gates used in the state preparation step, the circuit starts off by implementing a Hadamard gate and then $n-1$ rotations on the zeroth qubit - a total of $n$ gates. This is followed by a Hadamard and $n-2$ conditional rotations on the first qubit which totals to $n -1$ gates. If we continue the series, we get $n + (n-1) + (n-2)... = n(n+1)/2$. Hence, this circuit provides an algorithm with $O(n^2)$ gates for computing the QFT. \n",
"Barring the gates used in the state preparation step, the circuit starts off by implementing a Hadamard gate and then $n-1$ rotations on the zeroth qubit - a total of $n$ gates. This is followed by a Hadamard and $n-2$ conditional rotations on the first qubit which totals to $n -1$ gates. If we continue the series, we get $n + (n-1) + (n-2)... = n(n+1)/2$ gates. Hence, this circuit provides an algorithm with $O(n^2)$ gates for computing the QFT. \n",
"\n",
"The best classical algorithms for computing fast fourier transforms on $2^{n}$ elements require $O(n2^{n})$ gates. This means that it requires exponentially more operations to compute the fast fourier transform on a classical computer than it does to implement the QFT on a quantum computer.\n",
"The best classical algorithms for computing fast Fourier transforms on $2^{n}$ elements require $O(n2^{n})$ gates. This means that it requires exponentially more operations to compute the fast Fourier transform on a classical computer than it does to implement the QFT on a quantum computer.\n",
"\n",
"Why are we not using QFT for real life applications then? The problem lies in quantum measurement. The quantum fourier transformed amplitudes cannot be accessed by quantum measurement. However there are other quantum algorithms that do make use of QFT such as Shors' algorithm. \n",
"Why are we not using QFT for real life applications then? The problem lies in quantum measurement. The quantum-Fourier-transformed amplitudes cannot be accessed by quantum measurement. However there are other quantum algorithms that do make use of QFT such as Shor's algorithm. \n",
"\n",
"One can also invert the QFT where the circuit is executed in reverse with the inverse of each gate. The figure below shows the general $n$ qubit inverse QFT. Why don't you try implementing this in CUDA-Q?\n",
"One can also invert the QFT where the circuit is executed in reverse with the inverse of each gate. The figure below shows the general $n$-qubit inverse QFT. Why don't you try implementing this in CUDA-Q?\n",
"\n",
"<img src=\"images/inverse_qft.png\" alt=\"qft\" width=\"600\">\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Quantum Fourier Transform revisited\n",
"We provided one implementation of the Quantum Fourier Transform above. To demonstrate some of the other features of CUDA-Q, let's define a new kernel for the Quantum Fourier Transform, which we'll call `quantum_fourier_transform2`. Pay attention to how the kernel definition differs from the example above.\n",
"\n",
" Since the Quantum Fourier Transform is a unitary operator, its inverse is its adjoint. Therefore, once we have implemented the Quantum Fourier Transform as a kernel in CUDA-Q, we can use the built-in `adjoint` operation to create the Inverse Quantum Fourier Transform."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"# Define kernels for the Quantum Fourier Transform and the Inverse Quantum Fourier Transform\n",
"@cudaq.kernel\n",
"def quantum_fourier_transform2(qubits: cudaq.qview):\n",
" '''Args: \n",
" qubits (cudaq.qview): specifies the quantum register to which apply the QFT.'''\n",
" qubit_count = len(qubits)\n",
" # Apply Hadamard gates and controlled rotation gates.\n",
" for i in range(qubit_count):\n",
" h(qubits[i])\n",
" for j in range(i + 1, qubit_count):\n",
" angle = (2 * np.pi) / (2**(j - i + 1))\n",
" cr1(angle, [qubits[j]], qubits[i])\n",
" \n",
"@cudaq.kernel\n",
"def inverse_qft(qubits: cudaq.qview):\n",
" '''Args: \n",
" qubits (cudaq.qview): specifies the quantum register to which apply the inverse QFT.'''\n",
" cudaq.adjoint(quantum_fourier_transform2, qubits)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's see that this approach gives us the same results as the section above. "
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" ╭───╮╭───╮╭─────────╮╭──────────╮ »\n",
"q0 : ┤ x ├┤ h ├┤ r1(1.5) ├┤ r1(0.75) ├──────────────────────────────────────»\n",
" ╰───╯╰───╯╰────┬────╯╰────┬─────╯╭───╮╭─────────╮ ╭──────────╮»\n",
"q1 : ───────────────●──────────┼──────┤ h ├┤ r1(1.5) ├──────────┤ r1(-1.5) ├»\n",
" ╭───╮ │ ╰───╯╰────┬────╯╭───╮╭───╮╰────┬─────╯»\n",
"q2 : ┤ x ├─────────────────────●────────────────●─────┤ h ├┤ h ├─────●──────»\n",
" ╰───╯ ╰───╯╰───╯ »\n",
"\n",
"################################################################################\n",
"\n",
" ╭───────────╮╭──────────╮╭───╮\n",
"─────┤ r1(-0.75) ├┤ r1(-1.5) ├┤ h ├\n",
"╭───╮╰─────┬─────╯╰────┬─────╯╰───╯\n",
"┤ h ├──────┼───────────●───────────\n",
"╰───╯ │ \n",
"───────────●───────────────────────\n",
" \n",
"\n",
"[0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.-0.j 0.-0.j 0.+0.j]\n"
]
}
],
"source": [
"@cudaq.kernel\n",
"def verification_example(input_state : List[int]):\n",
" '''Args: \n",
" input_state (list[int]): specifies the input state to be transformed with QFT and the inverse QFT. '''\n",
" qubit_count = len(input_state)\n",
" # Initialize qubits.\n",
" qubits = cudaq.qvector(qubit_count)\n",
"\n",
" # Initialize the quantum circuit to the initial state.\n",
" for i in range(qubit_count):\n",
" if input_state[i] == 1:\n",
" x(qubits[i])\n",
" \n",
" # Apply the quantum Fourier Transform\n",
" quantum_fourier_transform2(qubits)\n",
"\n",
" # Apply the inverse quantum Fourier Transform\n",
" inverse_qft(qubits)\n",
"\n",
"# The state to which the QFT operation is applied to. The zeroth element in the list is the zeroth qubit.\n",
"input_state = [1, 0, 1]\n",
"\n",
"\n",
"# Number of decimal points to round up the statevector to.\n",
"precision = 2\n",
"\n",
"\n",
"print(cudaq.draw(verification_example, input_state))\n",
"\n",
"# Print the statevector to the specified precision\n",
"statevector = np.array(cudaq.get_state(verification_example, input_state))\n",
"print(np.round(statevector, precision)) # The result should be the input state"
]
},
{
"cell_type": "code",
"execution_count": 3,
Expand Down Expand Up @@ -285,7 +399,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0]"
"version": "3.10.12"
},
"orig_nbformat": 4,
"vscode": {
Expand Down
1 change: 1 addition & 0 deletions pr-1728/_sources/using/backends/backends.rst.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ CUDA-Q Backends
* :ref:`nvidia-mqpu-fp64 <nvidia-mgpu-backend>`
* :doc:`nvqc <nvqc>`
* :ref:`oqc <oqc-backend>`
* :ref:`orca <orca-backend>`
* :ref:`qpp-cpu <qpp-cpu-backend>`
* :ref:`quantinuum <quantinuum-backend>`
* :ref:`remote-mqpu <mqpu-platform>`
Expand Down
Loading

0 comments on commit c389511

Please sign in to comment.