{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Symbolic compilation\n",
"\n",
"**Download this notebook - {nb-download}`symbolics_example.ipynb`**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Motivation: in compilation, particularly of hybrid classical-quantum variational algorithms in which the structure of a circuit remains constant but the parameters of some gates change, it can be useful to compile using symbolic parameters and optimise the circuit without knowledge of what these parameters will be instantiated to afterwards.
\n",
"
\n",
"In this tutorial, we will show how to compile a circuit containing mathematical symbols, and then instantiate the symbols afterwards. To do this, you need to have `pytket` installed. Run:
\n",
"
\n",
"`pip install pytket`
\n",
"
\n",
"To begin, we will import the `Circuit` and `Transform` classes from `pytket`, and the `fresh_symbol` method from `pytket.circuit`."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from pytket.circuit import Circuit, fresh_symbol\n",
"from pytket.transform import Transform"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, we can construct a circuit containing symbols. You can ask for symbols by calling the `fresh_symbol` method with a string as an argument. This string represents the preferred symbol name; if this has already been used elsewhere, an appropriate suffix of the form `_x`, with `x` a natural number, will be added to generate a new symbol, as shown below:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"a\n",
"a_1\n"
]
}
],
"source": [
"a = fresh_symbol(\"a\")\n",
"a1 = fresh_symbol(\"a\")\n",
"print(a)\n",
"print(a1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We are going to make a circuit using just three 'phase gadgets': `Rz` gates surrounded by ladders of `CX` gates."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[CX q[0], q[1]; CX q[1], q[2]; CX q[2], q[3]; Rz(a) q[3]; CX q[2], q[3]; CX q[1], q[2]; CX q[0], q[1]; CX q[3], q[2]; CX q[2], q[1]; CX q[1], q[0]; Rz(b) q[0]; CX q[1], q[0]; CX q[2], q[1]; CX q[0], q[1]; CX q[3], q[2]; CX q[1], q[2]; CX q[2], q[3]; Rz(0.5) q[3]; CX q[2], q[3]; CX q[1], q[2]; CX q[0], q[1]; ]"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"b = fresh_symbol(\"b\")\n",
"circ = Circuit(4)\n",
"circ.CX(0, 1)\n",
"circ.CX(1, 2)\n",
"circ.CX(2, 3)\n",
"circ.Rz(a, 3)\n",
"circ.CX(2, 3)\n",
"circ.CX(1, 2)\n",
"circ.CX(0, 1)\n",
"circ.CX(3, 2)\n",
"circ.CX(2, 1)\n",
"circ.CX(1, 0)\n",
"circ.Rz(b, 0)\n",
"circ.CX(1, 0)\n",
"circ.CX(2, 1)\n",
"circ.CX(3, 2)\n",
"circ.CX(0, 1)\n",
"circ.CX(1, 2)\n",
"circ.CX(2, 3)\n",
"circ.Rz(0.5, 3)\n",
"circ.CX(2, 3)\n",
"circ.CX(1, 2)\n",
"circ.CX(0, 1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can use the `render_circuit_jupyter` method to display the circuit."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"from pytket.circuit.display import render_circuit_jupyter"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"