{
"cells": [
{
"cell_type": "markdown",
"id": "dd3d8d19",
"metadata": {},
"source": [
"# LOv rewriting rules\n",
"\n",
"The aim of this notebook is to rewrite a circuit using rewriting rules based on the article: *LOv-Calculus: A Graphical Language for Linear Optical Quantum Circuits*.\n",
"\n",
"We show how to use these rewriting rules to generate unique triangular normal forms."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "96bdb88a",
"metadata": {},
"outputs": [],
"source": [
"import perceval as pcvl\n",
"from perceval.utils.algorithms.optimize import optimize\n",
"from perceval.utils.algorithms.norm import frobenius\n",
"import random\n",
"\n",
"from perceval.rendering.circuit import DisplayConfig, SymbSkin\n",
"DisplayConfig.select_skin(SymbSkin)"
]
},
{
"cell_type": "markdown",
"id": "ba837e96",
"metadata": {},
"source": [
"This is the first rewrite rule used in this noteobok. It is the rule 37 in the article."
]
},
{
"cell_type": "markdown",
"id": "09923a89",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "ede320ce",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
""
],
"text/plain": [
""
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pattern1=pcvl.Circuit(3, name=\"pattern1\")//(0,pcvl.PS(pcvl.P(\"phi0\")))//(0,pcvl.BS(theta=pcvl.P(\"theta1\")))//(0,pcvl.PS(pcvl.P(\"phi2\")))//(1,pcvl.PS(pcvl.P(\"phi1\")))//(1,pcvl.BS(theta=pcvl.P(\"theta2\")))//(0,pcvl.BS(theta=pcvl.P(\"theta3\")))\n",
"pattern1._color = \"lightgreen\"\n",
"pcvl.pdisplay(pcvl.Circuit(3).add(0,pattern1,False), recursive=True)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "1e1ee73a",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
""
],
"text/plain": [
""
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rewrite1=pcvl.Circuit(3, name=\"rewrite\")//(0,pcvl.PS(pcvl.P(\"beta2\")))//(1,pcvl.PS(pcvl.P(\"beta1\")))//(1,pcvl.BS(theta=pcvl.P(\"alpha1\")))//(0,pcvl.BS(theta=pcvl.P(\"alpha2\")))//(1,pcvl.PS(pcvl.P(\"beta3\")))//(1,pcvl.BS(theta=pcvl.P(\"alpha3\")))//(0,pcvl.PS(pcvl.P(\"beta4\")))//(1,pcvl.PS(pcvl.P(\"beta5\")))//(2,pcvl.PS(pcvl.P(\"beta6\")))\n",
"rewrite1._color = \"lightgreen\"\n",
"pcvl.pdisplay(pcvl.Circuit(3).add(0,rewrite1,False), recursive=True)"
]
},
{
"cell_type": "markdown",
"id": "d4197839",
"metadata": {},
"source": [
"Let us implement now the rule number 1."
]
},
{
"cell_type": "markdown",
"id": "171cff3a",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "5468fdb9",
"metadata": {},
"outputs": [],
"source": [
"pattern2=pcvl.Circuit(1, name=\"pattern2\")//pcvl.PS(pcvl.P(\"phi1\"))//pcvl.PS(pcvl.P(\"phi2\"))\n",
"rewrite2=pcvl.Circuit(1, name=\"rewrite2\")//pcvl.PS(pcvl.P(\"phi\"))"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "e428775f",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
""
],
"text/plain": [
""
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pcvl.pdisplay(pcvl.Circuit(1).add(0,pattern2,False), recursive=True)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "e2bdd9f4",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
""
],
"text/plain": [
""
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pcvl.pdisplay(pcvl.Circuit(1).add(0,rewrite2,False), recursive=True)"
]
},
{
"cell_type": "markdown",
"id": "7d547376",
"metadata": {},
"source": [
"In fact, this rule has been directly implemented in Perceval, with the call of `simplify`."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "49074c57",
"metadata": {},
"outputs": [],
"source": [
"from perceval.utils.algorithms.simplification import simplify"
]
},
{
"cell_type": "markdown",
"id": "6ceae57c",
"metadata": {},
"source": [
"The third rule used in this notebook is the following one:"
]
},
{
"cell_type": "markdown",
"id": "246fc6ce",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "d056ab6c",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
""
],
"text/plain": [
""
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pattern3=pcvl.Circuit(2, name=\"pattern3\")//(1,pcvl.PS(pcvl.P(\"phip\")))//(0,pcvl.BS(theta=pcvl.P(\"theta\")))\n",
"pattern3._color = \"pink\"\n",
"pcvl.pdisplay(pcvl.Circuit(2).add(0,pattern3,False), recursive=True)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "6ef8057d",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
""
],
"text/plain": [
""
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rewrite3=pcvl.Circuit(2, name=\"rewrite3\")//(0,pcvl.PS(pcvl.P(\"phi1\")))//(0,pcvl.BS(theta=pcvl.P(\"theta\")))//(0,pcvl.PS(pcvl.P(\"phi2\")))//(1,pcvl.PS(pcvl.P(\"phi3\")))\n",
"rewrite3._color = \"pink\"\n",
"pcvl.pdisplay(pcvl.Circuit(2).add(0,rewrite3,False), recursive=True)"
]
},
{
"cell_type": "markdown",
"id": "6c7efe31",
"metadata": {},
"source": [
"And the fourth rule is the rule 38 in the article."
]
},
{
"cell_type": "markdown",
"id": "4cae9637",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "597bc933",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
""
],
"text/plain": [
""
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pattern4=pcvl.Circuit(2, name=\"pattern4\")//(0,pcvl.BS(theta=pcvl.P(\"theta1\")))//(0,pcvl.PS(pcvl.P(\"phi1\")))//(0,pcvl.BS(theta=pcvl.P(\"theta2\")))\n",
"pattern4._color = \"orange\"\n",
"pcvl.pdisplay(pcvl.Circuit(2).add(0,pattern4,False), recursive=True)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "1866e2c5",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
""
],
"text/plain": [
""
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rewrite4=pcvl.Circuit(2, name=\"rewrite4\")//(0,pcvl.PS(pcvl.P(\"beta1\")))//(0,pcvl.BS(theta=pcvl.P(\"alpha1\")))//(0,pcvl.PS(pcvl.P(\"beta2\")))//(1,pcvl.PS(pcvl.P(\"beta3\")))\n",
"rewrite4._color = \"orange\"\n",
"pcvl.pdisplay(pcvl.Circuit(2).add(0,rewrite4,False), recursive=True)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "deafebff",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
""
],
"text/plain": [
""
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"a=pcvl.Circuit.generic_interferometer(4, lambda idx:pcvl.Circuit(2)//pcvl.PS(phi=random.random())//pcvl.BS(theta=random.random()), depth=8, shape=\"rectangle\")\n",
"pcvl.pdisplay(a, recursive=True, render_size=0.7)"
]
},
{
"cell_type": "markdown",
"id": "f13dd7d7",
"metadata": {},
"source": [
"## Normalizing Circuit"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "0f5ee748",
"metadata": {},
"outputs": [],
"source": [
"import drawsvg as draw"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "df109c0f",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"matching pattern pattern3\n",
"matching pattern pattern4\n",
"matching pattern pattern1\n",
"matching pattern pattern3\n",
"matching pattern pattern4\n"
]
}
],
"source": [
"reverse = []\n",
"direct=[]\n",
"def draw_frame(a):\n",
" if isinstance(a, pcvl.Circuit):\n",
" d = pcvl.pdisplay(a, recursive=True, render_size=0.6)\n",
" reverse.insert(0, d)\n",
" direct.append(d)\n",
" return d\n",
" return a\n",
"\n",
"rules = [(pattern1, rewrite1, \"lightgreen\"), # (pattern2, rewrite2, \"lightblue\"),\n",
" (pattern3, rewrite3, \"pink\"), (pattern4, rewrite4, \"orange\")]\n",
"\n",
"with draw.frame_animate_jupyter(draw_frame, delay=0.1) as anim:\n",
" anim.draw_frame(a)\n",
" while True:\n",
" found = False\n",
" for pattern, rewrite, color in rules:\n",
" start_pos = 0\n",
" while True:\n",
" print(\"matching pattern\", pattern.name)\n",
" matched = a.match(pattern, browse=True, pos=start_pos)\n",
" if matched is None:\n",
" break\n",
" print(\"matching ok\", matched.v_map)\n",
" idx = a.isolate(list(matched.pos_map.keys()), color=color)\n",
" anim.draw_frame(a)\n",
" for k, v in matched.v_map.items():\n",
" pattern.param(k).set_value(v)\n",
" v = pattern.compute_unitary(False)\n",
" print(\"optimizing rewrite\",rewrite.name)\n",
" res = optimize(rewrite, v, frobenius, sign=-1)\n",
" print(\"found params with distance\", res.fun)\n",
" subc = rewrite.copy()\n",
" found = True\n",
" a.replace(idx, subc, merge=False)\n",
" anim.draw_frame(a)\n",
" a.replace(idx, subc, merge=True)\n",
" pattern.reset_parameters()\n",
" rewrite.reset_parameters()\n",
" a = simplify(a)\n",
" anim.draw_frame(a)\n",
" start_pos = idx\n",
" if not found:\n",
" break"
]
},
{
"cell_type": "markdown",
"id": "954dfac2",
"metadata": {},
"source": [
"This representation is exactly the normal form that we wanted to obtain !"
]
},
{
"cell_type": "markdown",
"id": "c174aa4c",
"metadata": {},
"source": [
"## Reference\n",
"\n",
"> A. Clément, N. Heurtel, S. Mansfield, S. Perdrix, B. Valiron. LOv-Calculus: A Graphical Language for Linear Optical Quantum Circuits, 47th International Symposium on Mathematical Foundations of Computer Science [MFCS](https://doi.org/10.4230/LIPIcs.MFCS.2022.35), 35:1--35:16 (2022)."
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}