qat.plugins.FusionPlugin
The FusionPlugin
is designed to be used as is, in front of a linear algebra simulator.
It should improve the simulation time of supremacy-like quantum circuits, that is, dense random circuits. Notice that it can
degrade simulation performances for some other types of circuits, such as QAOA circuits!
Note
As of version 1.10, FusionPlugin is used by default by qat.qpus.LinAlg
for jobs of at least 20 qubits (CPU),
23 qubits (GPU).
- class qat.plugins.FusionPlugin(strategy: str = None, qbits_compilation_threshold: int = None, strategies: list = None, **strat_args)
A plugin that can group adjacent gates into bigger gates. Its purpose is to form an equivalent circuit with less, but larger, gates. It is designed to improve performances of subsequent simulation via a linear algebra based simulator. This plugin is intended for circuits comprising only quantum gates (classical operations and intermediate measurements are not compatible, and circuits containing those will be ignored).
- Parameters
strategy (optional, str) – the grouping strategy to apply (possible strategies are “eager”, “naive”, “adjacent”). Default is “eager”.
qbits_compilation_threshold (optional, int) – the minimum number of qubits in a circuit for it to be compiled Default is 1.
strategies (optional, list) – list of user-initialized strategies; if this parameter is provided, the strategy parameter as well as strat_args shall be ignored. Default is None.
strat_args (optional, kwargs) – arguments passed to the strategy’s constructor. See below for more details.
Strategies:
“naive”: This strategy naively accumulate gates in the order they come in the input circuit. It groups gate with its predecessor if the size of the grouped gate stays below some threshold.
“adjacent”: This strategy picks a gate of a given size (2-qbits by default), and groups all gates to its left and right whose set of qbits are included in its set of qbits.
“eager”: This strategy maintains a collection of groups and attempts to merge any incoming gate into one of these groups. It is usually more performant than the other two and is the default behavior of the plugin.
Strategy arguments:
“adjacent”: refer to the documentation of the constructor of
qat.fusion.strategies.AdjacentStrategy
“eager”: refer to the documentation of the constructor of
qat.fusion.strategies.EagerStrategy
“naive”: refer to the documentation of the constructor of
qat.fusion.strategies.NaiveStrategy
The default behavior is to use the “eager” strategy and to group gates until groups each a size of 3-qbits.
Warning
This Plugin expects all of the gates in the circuit to have matrices. It will fail to compile the circuit if matrices are missing. This entails that it cannot compile circuits with open parameters (such as variational circuits). You will need to first instantiate the parameters before compiling the circuit.
This plugin can be configured with different strategies, described in the qat.fusion
module.
Example
Let us try and run this Plugin on some simple random circuit.
Note
As of version 1.10, we pass fusion=False for this example, as the QPU uses FusionPlugin by default.
import time
import numpy as np
from qat.plugins import FusionPlugin
from qat.qpus import LinAlg
from qat.lang.AQASM import Program, RZ, RX, CNOT
def random_circuit(nbqbits, depth):
"""Generates a random circuit"""
prog = Program()
qbits = prog.qalloc(nbqbits)
for _ in range(depth):
for qbit in qbits:
RZ(np.random.random() * 2 * np.pi)(qbit)
RX(np.random.random() * 2 * np.pi)(qbit)
RZ(np.random.random() * 2 * np.pi)(qbit)
for i in range(nbqbits // 2):
CNOT(qbits[2 * i], qbits[2 * i + 1])
for i in range(1, nbqbits // 2):
CNOT(qbits[2 * i], qbits[2 * i - 1])
return prog.to_circ()
plugin = FusionPlugin()
stack_default = LinAlg(fusion=False)
stack_improved = plugin | LinAlg(fusion=False)
job = random_circuit(20, 80).to_job()
start = time.perf_counter()
stack_default.submit(job)
print("Time LinAlg only: ", time.perf_counter() - start)
start = time.perf_counter()
stack_improved.submit(job)
print("Time Fusion+LinAlg:", time.perf_counter() - start)
Time LinAlg only: 2.1037170700146817
Time Fusion+LinAlg: 0.8293755110353231