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.CLinalg for jobs of at least 20 qubits

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:

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.

compile(batch, _specs)

Compiles a batch of jobs

Parameters
  • batch (Batch) – the batch of jobs to compile

  • specs (N/A) – here for compatibility, the specs are ignored

Returns

Batch

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 CLinalg
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 = CLinalg(fusion=False)
stack_improved = plugin | CLinalg(fusion=False)

job = random_circuit(20, 80).to_job()
start = time.perf_counter()
stack_default.submit(job)
print("Time CLinalg only:  ", time.perf_counter() - start)
start = time.perf_counter()
stack_improved.submit(job)
print("Time Fusion+CLinalg:", time.perf_counter() - start)
Time CLinalg only:   2.9579462348483503
Time Fusion+CLinalg: 1.7561186710372567