<jupyter_start><jupyter_text>Symbolic compilation: tket example 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.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:`pip install pytket`To begin, we will import the `Circuit` and `Transform` classes from `pytket`, and the `fresh_symbol` method from `pytket.circuit`.<jupyter_code>from pytket.circuit import Circuit, fresh_symbol
from pytket.transform import Transform<jupyter_output><empty_output><jupyter_text>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:<jupyter_code>a = fresh_symbol("a")
a1 = fresh_symbol("a")
print(a)
print(a1)<jupyter_output><empty_output><jupyter_text>We are going to make a circuit using just three 'phase gadgets': `Rz` gates surrounded by ladders of `CX` gates.<jupyter_code>b = fresh_symbol("b")
circ = Circuit(4)
circ.CX(0, 1)
circ.CX(1, 2)
circ.CX(2, 3)
circ.Rz(a, 3)
circ.CX(2, 3)
circ.CX(1, 2)
circ.CX(0, 1)
circ.CX(3, 2)
circ.CX(2, 1)
circ.CX(1, 0)
circ.Rz(b, 0)
circ.CX(1, 0)
circ.CX(2, 1)
circ.CX(3, 2)
circ.CX(0, 1)
circ.CX(1, 2)
circ.CX(2, 3)
circ.Rz(0.5, 3)
circ.CX(2, 3)
circ.CX(1, 2)
circ.CX(0, 1)<jupyter_output><empty_output><jupyter_text>Now we can use the `render_circuit_jupyter` method to display the circuit.<jupyter_code>from pytket.circuit.display import render_circuit_jupyter
render_circuit_jupyter(circ)<jupyter_output><empty_output><jupyter_text>Now let's use a transform to shrink the circuit. For more detail on transforms, see the `transform_example` notebook.<jupyter_code>Transform.OptimisePhaseGadgets().apply(circ)
render_circuit_jupyter(circ)<jupyter_output><empty_output><jupyter_text>Note that the type of gate has changed to `U1`, but the phase gadgets have been successfully combined. The `U1` gate is an IBM-specific gate that is equivalent to an `Rz`.We can now instantiate the symbols with some desired values. We make a dictionary, with each key a symbol name, and each value a double. Note that this value is in units of 'half-turns', in which a value of $1$ corresponds to a rotation of $\pi$.Before instantiating our parameters we make a copy of the circuit, so that we can repeat the exercise without the need for recompilation.<jupyter_code>symbol_circ = circ.copy()
symbol_dict = {a: 0.5, b: 0.75}
circ.symbol_substitution(symbol_dict)
render_circuit_jupyter(circ)<jupyter_output><empty_output><jupyter_text>Because this symbol substitution was called on the copy, we still have our original symbolic circuit.<jupyter_code>render_circuit_jupyter(symbol_circ)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08884106978173993, 'fraction_numerical': 0.015985244389794036, 'mean_word_length': 6.231111111111111, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '130009', 'license': 'Apache-2.0', 'n_tokens_mistral': 1101, 'n_tokens_neox': 1020, 'n_words': 390, 'path': 'examples/symbolics_example.ipynb', 'repo_name': 'CQCL/pytket', 'size': '3253'}