{ "cells": [ { "cell_type": "markdown", "id": "410abc7e", "metadata": {}, "source": [ "# FusionPlugin - example use case with a random circuit\n", "\n", "`FusionPlugin` is a tool for reducing the number of gates in a circuit through gates fusion.\n", "Though primarily conceived with the intent of being used in front of statevector-based simulator, ie. `LinAlg`, some strategies included in this plugin are compatible with any QPU topology (such as *adjacent* strategy, which does not increase the gates' sizes).\n", "\n", "Here we'll show an example where the *eager* strategy can heavily reduce the number of gates in a circuit." ] }, { "cell_type": "markdown", "id": "9af12161", "metadata": {}, "source": [ "## Circuit generation\n", "\n", "Let us start by creating a random circuit, composed of layers of 1 and 2 qbits gates." ] }, { "cell_type": "code", "execution_count": null, "id": "015ce27a", "metadata": {}, "outputs": [], "source": [ "from qat.lang.AQASM import Program, RX, RY, RZ, CNOT\n", "import random as rdm\n", "\n", "# here we'll consider a 10-qubits circuit with 20 layers\n", "nbqubits = 24\n", "circuit_depth = 20" ] }, { "cell_type": "code", "execution_count": null, "id": "eee6b309", "metadata": {}, "outputs": [], "source": [ "program = Program()\n", "qubits = program.qalloc(nbqubits)\n", "\n", "for i in range(circuit_depth):\n", " for qubit in qubits:\n", " # on each qubit, apply a randomly selected pauli gate\n", " rdm.choice([RX, RY, RZ])(rdm.random())(qubit)\n", "\n", " for j in range(0, nbqubits, 2):\n", " # some degree of intrication\n", " CNOT(qubits[j - i % 2], qubits[j - i % 2 + 1])\n", "\n", "job = program.to_circ().to_job()" ] }, { "cell_type": "markdown", "id": "de98d4e0", "metadata": {}, "source": [ "Executing the cell below allows us to see that this circuit contains 720 gates, including 240 CNOT, the remaining gates being rotations." ] }, { "cell_type": "code", "execution_count": null, "id": "25969be3", "metadata": {}, "outputs": [], "source": [ "print(job.circuit.statistics())" ] }, { "cell_type": "markdown", "id": "3b648853", "metadata": {}, "source": [ "## Circuit optimization\n", "We'll first only compile this job, in order to see what the processed circuit looks like." ] }, { "cell_type": "code", "execution_count": null, "id": "bebd49d3", "metadata": {}, "outputs": [], "source": [ "from qat.plugins import FusionPlugin\n", "\n", "# both statements are equivalent, \"eager\" is the default strategy\n", "plugin = FusionPlugin(strategy=\"eager\")\n", "plugin = FusionPlugin()" ] }, { "cell_type": "code", "execution_count": null, "id": "8821c35b", "metadata": {}, "outputs": [], "source": [ "from qat.core import Batch, HardwareSpecs\n", "\n", "batch = Batch(jobs=[job])\n", "new_job = plugin.compile(batch, HardwareSpecs()).jobs[0]" ] }, { "cell_type": "markdown", "id": "8a683d04", "metadata": {}, "source": [ "Executing the cell bellow, we should see that the number of gates in the circuit has been reduced to 130. Notice that all those gates are \"custom gates\", meaning general gates that here are defined by a matrix." ] }, { "cell_type": "code", "execution_count": null, "id": "37fde9cb", "metadata": {}, "outputs": [], "source": [ "print(new_job.circuit.statistics())" ] }, { "cell_type": "markdown", "id": "99a7ca48", "metadata": {}, "source": [ "## Simulation with Linear Algebra based simulator\n", "Finally, we can execute our job with a linear algebra based simulator. By default, the FusionPlugin is already applied by the simulator, so we need to deactivate it in order to compare the simulation time. Do consider that, at only 24 qubits, FusionPlugin takes a non-negligible amount of time of the total measured time." ] }, { "cell_type": "code", "execution_count": null, "id": "a6eb3df0", "metadata": {}, "outputs": [], "source": [ "from time import perf_counter\n", "from qat.qpus import get_default_qpu" ] }, { "cell_type": "code", "execution_count": null, "id": "2b2e78d9", "metadata": {}, "outputs": [], "source": [ "# here we instantiate the default QPU and deactivates the default FusionPlugin\n", "qpu = get_default_qpu(fusion=False)\n", "time = perf_counter()\n", "qpu.submit(job)\n", "print(f\"Time taken by LinAlg: {perf_counter() - time}s\")" ] }, { "cell_type": "code", "execution_count": null, "id": "fc587d46", "metadata": {}, "outputs": [], "source": [ "# here we instantiate the default QPU without any argument, which applies the FusionPlugin by default\n", "qpu = get_default_qpu()\n", "time = perf_counter()\n", "qpu.submit(job)\n", "print(f\"Time taken by FusionPlugin+LinAlg {perf_counter() - time}s\")" ] } ], "metadata": { "documentation-tags": { "icon": [ "repo-forked" ] }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "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 }