Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Womanium Final Assignment - Abdullah Kazi #237

Merged
merged 3 commits into from
Aug 4, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
376 changes: 376 additions & 0 deletions Abdullah_Kazi_hw4.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,376 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "markdown",
"source": [
"## Quantum Walk Operators: Circle with 4 Nodes and Line with 16 Nodes"
],
"metadata": {
"id": "o2AZRlMtArsY"
}
},
{
"cell_type": "markdown",
"source": [
"Introduction\n",
"Quantum walks are the quantum analog of classical random walks, providing a useful framework for developing quantum algorithms. They have applications in quantum search, graph algorithms, and simulations. In this notebook, we will design quantum walk operators for two specific cases: a circle with 4 nodes and a line with 16 nodes.\n",
"\n",
"Quantum Walk on a Circle with 4 Nodes\n",
"A circle (or cyclic graph) with 4 nodes is a simple structure where each node is connected to two others, forming a closed loop. The transition probabilities are equal for each step."
],
"metadata": {
"id": "TqNM2IvVAwcd"
}
},
{
"cell_type": "markdown",
"source": [
" 0 - 1\n",
" | |\n",
" 3 - 2\n"
],
"metadata": {
"id": "eC6k2SVDA0sB"
}
},
{
"cell_type": "markdown",
"source": [
"Transition Probabilities:\n",
"Each node has a 50% probability of transitioning to either of its adjacent nodes.\n",
"\n",
"Quantum Walk Operator:\n",
"\n",
"Initialization:\n",
"\n",
"We initialize a quantum register to represent the position of the walker on the graph.\n",
"Apply the Hadamard transform to create a superposition of all possible starting positions.\n",
"W Operator (Walk Operator):\n",
"\n",
"For each possible state (vertex), we calculate the transition probabilities to the adjacent nodes.\n",
"Use controlled operations to update the state based on these probabilities.\n",
"S Operator (Shift Operator):\n",
"\n",
"We use a conditional swap operation to simulate the movement between nodes based on the calculated transition probabilities.\n",
"Mathematical Representation:\n",
"\n",
"The state space is spanned by the basis states |0⟩, |1⟩, |2⟩, |3⟩.\n",
"The walk operator W updates the amplitudes based on the adjacency matrix of the graph.\n",
"The shift operator S swaps the states according to the adjacency relationships.\n",
"Quantum Walk on a Line with 16 Nodes\n",
"A line (or path graph) with 16 nodes is a linear structure where each node (except the endpoints) is connected to two others."
],
"metadata": {
"id": "z8zA-ihvA32H"
}
},
{
"cell_type": "markdown",
"source": [
" 0 - 1 - 2 - ... - 14 - 15\n"
],
"metadata": {
"id": "t3MDMKUgA91A"
}
},
{
"cell_type": "markdown",
"source": [
"Transition Probabilities:\n",
"\n",
"For nodes 0 and 15 (endpoints), the transition probability is 100% to their single adjacent node.\n",
"For all other nodes, the transition probability is 50% to each adjacent node.\n",
"Quantum Walk Operator:\n",
"\n",
"Initialization:\n",
"\n",
"Initialize a quantum register to represent the position of the walker on the graph.\n",
"Apply the Hadamard transform to create a superposition of all possible starting positions.\n",
"W Operator (Walk Operator):\n",
"\n",
"For each possible state (vertex), we calculate the transition probabilities to the adjacent nodes.\n",
"Use controlled operations to update the state based on these probabilities.\n",
"S Operator (Shift Operator):\n",
"\n",
"We use a conditional swap operation to simulate the movement between nodes based on the calculated transition probabilities.\n",
"Mathematical Representation:\n",
"\n",
"The state space is spanned by the basis states |0⟩, |1⟩, |2⟩, ..., |15⟩.\n",
"The walk operator W updates the amplitudes based on the adjacency matrix of the graph.\n",
"The shift operator S swaps the states according to the adjacency relationships."
],
"metadata": {
"id": "kEaFHlEoBBeg"
}
},
{
"cell_type": "markdown",
"source": [
"Theoretical and Mathematical Reasoning\n",
"Quantum Walk Operators:\n",
"The quantum walk operator can be broken down into two primary components:\n",
"\n",
"Walk Operator (W):\n",
"\n",
"Responsible for determining the probabilities of transitioning from one node to another.\n",
"Uses controlled operations to apply these transitions based on the current state of the walker.\n",
"Shift Operator (S):\n",
"\n",
"Responsible for executing the transitions determined by the walk operator.\n",
"Uses conditional swaps to simulate the movement of the walker on the graph.\n",
"Hadamard Transform:\n",
"The Hadamard transform is applied to create an equal superposition of all possible starting positions. This ensures that the quantum walk explores all nodes simultaneously, leveraging quantum parallelism.\n",
"\n",
"Controlled Operations:\n",
"Controlled operations are used to apply the transitions and swaps conditionally, based on the current state of the walker. This allows for the precise control needed to simulate the quantum walk.\n",
"\n",
"Adjacency Matrix:\n",
"The adjacency matrix of the graph defines the connections between nodes. It is used to determine the transition probabilities and control the operations accordingly."
],
"metadata": {
"id": "6_Vd1p1sBGeH"
}
},
{
"cell_type": "code",
"source": [
"from classiq import *\n",
"\n",
"size = 2 #(2^size number of vertices)\n",
"\n",
"@qfunc\n",
"def prepare_minus(x: QBit):\n",
" X(x)\n",
" H(x)\n",
"\n",
"\n",
"@qfunc\n",
"def diffuzer_oracle(aux: Output[QNum],x:QNum):\n",
" aux^=(x!=0)\n",
"\n",
"\n",
"@qfunc\n",
"def zero_diffuzer(x: QNum):\n",
" aux = QNum('aux')\n",
" allocate(1,aux)\n",
" within_apply(compute=lambda: prepare_minus(aux),\n",
" action=lambda: diffuzer_oracle)\n",
"\n",
"\n",
"def W_iteration(i:int,vertices: QNum, adjacent_vertices:QNum):\n",
" prob = [0,0,0,0]\n",
" prob[(i+1)% 4]=0.5\n",
" prob[(i-1)% 4]=0.5\n",
" print(f'State={i}, prob vec ={prob}')\n",
"\n",
" control(ctrl=vertices==i,\n",
" operand=lambda: within_apply(\n",
" compute= lambda: inplace_prepare_state(probabilities=prob, bound=0.01, target=adjacent_vertices),\n",
" action= lambda: zero_diffuzer(adjacent_vertices)))\n",
"\n",
"\n",
"@qfunc\n",
"def W_operator(vertices:QNum, adjacent_vertices: QNum):\n",
" for i in range(2**size):\n",
" W_iteration(i,vertices,adjacent_vertices)\n",
"\n",
"\n",
"@qfunc\n",
"def edge_oracle(res:Output[QBit], vertices: QNum, adjacent_vertices: QNum):\n",
" res |= (((vertices+adjacent_vertices)%2) ==1)\n",
"\n",
"\n",
"@qfunc\n",
"def bitwise_swap(x: QArray[QBit], y:QArray[QBit]):\n",
" repeat(count= x.len,\n",
" iteration= lambda i: SWAP(x[i],y[i]))\n",
"\n",
"\n",
"@qfunc\n",
"def S_operator(vertices:QNum, adjacent_vertices: QNum):\n",
" res = QNum('res')\n",
" edge_oracle(res,vertices,adjacent_vertices)\n",
" control(ctrl= res==1,\n",
" operand= lambda: bitwise_swap(vertices,adjacent_vertices))\n",
"\n",
"@qfunc\n",
"def main(vertices:Output[QNum], adjacent_vertices:Output[QNum]):\n",
"\n",
" allocate(size,vertices)\n",
" hadamard_transform(vertices)\n",
" allocate(size,adjacent_vertices)\n",
"\n",
" W_operator(vertices,adjacent_vertices)\n",
" S_operator(vertices,adjacent_vertices)\n",
"\n",
"qmod = create_model(main)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "aMYyI1B69Twu",
"outputId": "9e4e064f-b8d9-4a12-97ab-854a4f01c8ce"
},
"execution_count": 11,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"State=0, prob vec =[0, 0.5, 0, 0.5]\n",
"State=1, prob vec =[0.5, 0, 0.5, 0]\n",
"State=2, prob vec =[0, 0.5, 0, 0.5]\n",
"State=3, prob vec =[0.5, 0, 0.5, 0]\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"import classiq\n",
"from classiq import *\n",
"from classiq.execution import ExecutionDetails, ExecutionPreferences, ClassiqBackendPreferences\n",
"import matplotlib.pyplot as plt\n",
"from classiq.execution import ExecutionPreferences\n",
"from classiq.qmod.symbolic import floor, log, pi, ceiling\n",
"\n",
"size = 4 # qubits"
],
"metadata": {
"id": "0pLQWDll74lc"
},
"execution_count": 6,
"outputs": []
},
{
"cell_type": "code",
"source": [
"from classiq import *\n",
"\n",
"size = 4\n",
"\n",
"@qfunc\n",
"def prepare_minus(x: QBit):\n",
" X(x)\n",
" H(x)\n",
"\n",
"\n",
"@qfunc\n",
"def diffuzer_oracle(aux: Output[QNum],x:QNum):\n",
" aux^=(x!=0)\n",
"\n",
"\n",
"@qfunc\n",
"def zero_diffuzer(x: QNum):\n",
" aux = QNum('aux')\n",
" allocate(1,aux)\n",
" within_apply(compute=lambda: prepare_minus(aux),\n",
" action=lambda: diffuzer_oracle)\n",
"\n",
"def W_iteration(i:int,vertices: QNum, adjacent_vertices:QNum):\n",
"\n",
" prob = [0]* 2**size\n",
" if i==0:\n",
" prob[i+1] = 1.0 #Probability\n",
" elif i==((2**size)-1):\n",
" prob[i-1] = 1.0 #Probability\n",
" else:\n",
" prob[i-1] = 0.5 #Probability\n",
" prob[i+1] = 0.5 #Probability\n",
" print(f'State={i}, prob vec ={prob}')\n",
"\n",
"\n",
" control(ctrl=vertices==i,\n",
" operand=lambda: within_apply(\n",
" compute= lambda: inplace_prepare_state(probabilities=prob, bound=0.01, target=adjacent_vertices),\n",
" action= lambda: zero_diffuzer(adjacent_vertices)))\n",
"\n",
"\n",
"@qfunc\n",
"def W_operator(vertices:QNum, adjacent_vertices: QNum):\n",
" for i in range(2**size):\n",
" W_iteration(i,vertices,adjacent_vertices)\n",
"\n",
"\n",
"@qfunc\n",
"def edge_oracle(res:Output[QBit], vertices: QNum, adjacent_vertices: QNum):\n",
" res |= (((vertices-adjacent_vertices) == 1) | ((vertices-adjacent_vertices) == -1))\n",
"\n",
"\n",
"@qfunc\n",
"def bitwise_swap(x: QArray[QBit], y:QArray[QBit]):\n",
" repeat(count= x.len,\n",
" iteration= lambda i: SWAP(x[i],y[i]))\n",
"\n",
"\n",
"@qfunc\n",
"def S_operator(vertices:QNum, adjacent_vertices: QNum):\n",
" res = QNum('res')\n",
" edge_oracle(res,vertices,adjacent_vertices)\n",
" control(ctrl= res==1,\n",
" operand= lambda: bitwise_swap(vertices,adjacent_vertices))\n",
"\n",
"@qfunc\n",
"def main(vertices:Output[QNum], adjacent_vertices:Output[QNum]):\n",
" '''function'''\n",
"\n",
" allocate(size,vertices)\n",
" hadamard_transform(vertices)\n",
" allocate(size,adjacent_vertices)\n",
"\n",
" W_operator(vertices,adjacent_vertices)\n",
" S_operator(vertices,adjacent_vertices)\n",
"\n",
"qmod = create_model(main)\n"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "u1A5ROiA79xZ",
"outputId": "6b9e143b-cba7-41b6-cdf0-e8b956d41a5d"
},
"execution_count": 10,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"State=0, prob vec =[0, 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n",
"State=1, prob vec =[0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n",
"State=2, prob vec =[0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n",
"State=3, prob vec =[0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n",
"State=4, prob vec =[0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n",
"State=5, prob vec =[0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n",
"State=6, prob vec =[0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0]\n",
"State=7, prob vec =[0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0]\n",
"State=8, prob vec =[0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0]\n",
"State=9, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0]\n",
"State=10, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0]\n",
"State=11, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0]\n",
"State=12, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0]\n",
"State=13, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0]\n",
"State=14, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5]\n",
"State=15, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 0]\n"
]
}
]
}
]
}
Loading