Skip to content
Open
Show file tree
Hide file tree
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ target/
# Ideas
.idea/
.vscode/

# Jupyter notebook checkpoints
examples/.ipynb_checkpoints/
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,9 @@ Clean:

```
make clean
```
```

## Usage
You can find a basic description of the rust package and how to use it [here](examples/Rust%20library%20overview.ipynb). This is mainly meant for contributors and integrators.

If you want to use the algorithms provided in the library to compile your circuits, you can find a simple user guide for the Python bindings [here](examples/Basic%20python%20usage.ipynb).
371 changes: 371 additions & 0 deletions examples/Basic python usage.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,371 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "79cab848",
"metadata": {},
"source": [
"# Introductory python tutorial for the synIR library\n",
"Welcome to the synIR (/ˈsɪnɚ/) library!\n",
"\n",
"This jupyter notebook showcases the basic python usage of our quantum compilation library.\n",
"\n",
"You can find a detailed detailed explanation of the rust-part of the library in [Rust library overview notebook](Rust%20library%20overview.ipynb)."
]
},
{
"cell_type": "markdown",
"id": "8cb6ca94",
"metadata": {},
"source": [
"## Installing synpy library\n",
"If you install from the top github folder\n",
"```\n",
"pip install requirements.txt\n",
"pip install synpy/ \n",
"```\n",
"\n",
"If you install from the pypi\n",
"```\n",
"pip install synpy\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "fa8b2c58",
"metadata": {},
"source": [
"## Using Qiskit Highlevel synthesis pass"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "9bb3f555",
"metadata": {},
"outputs": [],
"source": [
"from qiskit.quantum_info import Clifford\n",
"from qiskit import QuantumCircuit"
]
},
{
"cell_type": "markdown",
"id": "1eeb1e13",
"metadata": {},
"source": [
"Create a simple Qiskit Clifford circuit. Unfortuntately, a Qiskit QuantumCircuit does not know that it is Clifford so we need to make construct it first (`cliff`) and then add it to the a circuit (`qc`)."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "d4ee235d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<qiskit.circuit.instructionset.InstructionSet at 0x11507ce50>"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tmp = QuantumCircuit(2)\n",
"tmp.h(0)\n",
"tmp.cx(0, 1)\n",
"cliff = Clifford(tmp)\n",
Comment on lines +79 to +82
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer an example that is not trivial (i.e., that shows that the plugin does something at least).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lemme park this here to add later from qiskit docs

from qiskit import QuantumCircuit
from qiskit.quantum_info import Clifford, random_clifford
 
qc = QuantumCircuit(3)
cliff = random_clifford(2)
qc.append(cliff, [0, 1])
qc.ccx(0, 1, 2)
qc.draw('mpl')

"qc = QuantumCircuit(2)\n",
"qc.append(cliff, (0,1))"
]
},
{
"cell_type": "markdown",
"id": "41b04321",
"metadata": {},
"source": [
"Synthesize the circuit directly using the plugin. Here, the plugin takes the Qiskit Clifford object."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "eb6a5001",
"metadata": {},
"outputs": [],
"source": [
"from synpy.qiskit.plugin import SynPyCliffordPlugin"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "dfc5427a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" ┌───┐ \n",
"q_0: ┤ H ├──■──\n",
" └───┘┌─┴─┐\n",
"q_1: ─────┤ X ├\n",
" └───┘\n"
]
}
],
"source": [
"direct_circ = SynPyCliffordPlugin().run(cliff, None, None, [])\n",
"print(direct_circ)"
]
},
{
"cell_type": "markdown",
"id": "e09456ee",
"metadata": {},
"source": [
"Using the Qiskit transpiler by giving the plugin to the transpiler."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "a974bc82",
"metadata": {},
"outputs": [],
"source": [
"from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig\n",
"from qiskit import transpile"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "47657c94",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" ┌───┐ \n",
"q_0: ┤ H ├──■──\n",
" └───┘┌─┴─┐\n",
"q_1: ─────┤ X ├\n",
" └───┘\n"
]
}
],
"source": [
"hls_config = HLSConfig(clifford=[SynPyCliffordPlugin()])\n",
"transpiled_circuit = transpile(qc, hls_config=hls_config)\n",
"print(transpiled_circuit)"
]
},
{
"cell_type": "markdown",
"id": "5972832d",
"metadata": {},
"source": [
"Our plugin is also registered as a string in the known transpiler plugins as `\"synpy\"` so we can use that instead. "
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "f4ff80de",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['synpy', 'ag', 'bm', 'default', 'greedy', 'layers', 'lnn']"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from qiskit.transpiler.passes.synthesis import (\n",
" high_level_synthesis_plugin_names,\n",
")\n",
" \n",
"high_level_synthesis_plugin_names(\"clifford\")"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "78798b35",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" ┌───┐ \n",
"q_0: ┤ H ├──■──\n",
" └───┘┌─┴─┐\n",
"q_1: ─────┤ X ├\n",
" └───┘\n"
]
}
],
"source": [
"hls_config = HLSConfig(clifford=[\"synpy\"])\n",
"transpiled_circuit = transpile(qc, hls_config=hls_config)\n",
"print(transpiled_circuit)"
]
},
{
"cell_type": "markdown",
"id": "31011de6",
"metadata": {},
"source": [
"## Using Pauliopt library with synpy"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "14ef5e61",
"metadata": {},
"outputs": [],
"source": [
"from pauliopt.pauli.pauli_polynomial import PauliPolynomial\n",
"from pauliopt.pauli.pauli_gadget import PPhase\n",
"from pauliopt.pauli_strings import X, Y, Z, I\n",
"from pauliopt.utils import Angle, pi"
]
},
{
"cell_type": "markdown",
"id": "6a0b91d4",
"metadata": {},
"source": [
"Make a Toffoli gate using PauliOpt"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "12340f3d",
"metadata": {},
"outputs": [],
"source": [
"pp = PauliPolynomial(3)\n",
"angle = pi/4\n",
"pp >>= PPhase(angle) @ [I, I, X]\n",
"pp >>= PPhase(angle) @ [Z, I, I]\n",
"pp >>= PPhase(angle) @ [I, Z, I]\n",
"pp >>= PPhase(-angle) @ [I, Z, X]\n",
"pp >>= PPhase(-angle) @ [Z, Z, I]\n",
"pp >>= PPhase(-angle) @ [Z, I, X]\n",
"pp >>= PPhase(angle) @ [Z, Z, X]"
]
},
{
"cell_type": "markdown",
"id": "d42f7096",
"metadata": {},
"source": [
"Synthesize a new circuit using synpy"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "8d3c8807",
"metadata": {},
"outputs": [],
"source": [
"from synpy.pauliopt.synthesizer import PauliOptSynthesizer"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "78c8e3f4",
"metadata": {},
"outputs": [],
"source": [
"pauliopt_circuit = PauliOptSynthesizer().synthesize(pp)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "9ceaabaa",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" ┌─────────┐ »\n",
"q_0: ┤ Rz(π/4) ├─────────────────────■────────────────────────────■───────────»\n",
" ├─────────┤ ┌─┴─┐ ┌──────────┐ ┌─┴─┐ »\n",
"q_1: ┤ Rz(π/4) ├─────────────■─────┤ X ├────┤ Rz(7π/4) ├──■─────┤ X ├──────■──»\n",
" └──┬───┬──┘┌─────────┐┌─┴─┐┌──┴───┴───┐└──────────┘┌─┴─┐┌──┴───┴───┐┌─┴─┐»\n",
"q_2: ───┤ H ├───┤ Rz(π/4) ├┤ X ├┤ Rz(7π/4) ├────────────┤ X ├┤ Rz(7π/4) ├┤ X ├»\n",
" └───┘ └─────────┘└───┘└──────────┘ └───┘└──────────┘└───┘»\n",
"« \n",
"«q_0: ─────────────■────────────\n",
"« │ \n",
"«q_1: ─────────────┼────■───────\n",
"« ┌─────────┐┌─┴─┐┌─┴─┐┌───┐\n",
"«q_2: ┤ Rz(π/4) ├┤ X ├┤ X ├┤ H ├\n",
"« └─────────┘└───┘└───┘└───┘\n"
]
}
],
"source": [
"print(pauliopt_circuit.to_qiskit())"
]
},
{
"cell_type": "markdown",
"id": "5ee0dfac",
"metadata": {},
"source": [
"# Future plans\n",
"This library is still under construction. If you are looking for specific features that are not yet implemented, please make an issue on the Github page.\n",
"\n",
"Our next plans include, but are not limited to:\n",
"- Implement the PSGS algorithm for Pauli Polynomial synthesis (open PR)\n",
"- Improve Qiskit transpiler integration, e.g. add PauliExponentialSynthesis\n",
"- Circuit-to-PauliExponential parser for generic circuits\n",
"- Improve code structure, package structure, and code style."
Comment on lines +342 to +346
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be better to put this in the README, where it's easier to update.

]
}
],
"metadata": {
"kernelspec": {
"display_name": "synpy",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.11"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading
Loading