Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

44 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

graphix-mqtbench

This plugin provides an interface between Graphix and the MQT Bench suite for benchmarking purposes.

Installation

This package supports uv:

git clone https://github.com/TeamGraphix/graphix-mqtbench.git
cd graphix-mqtbench
uv sync

This creates a virtual environment and installs the necessary dependencies from the pyproject.toml and uv lockfile.

Note: This package depends on the graphix-qasm-parser plugin to transpile qiskit circuits into Graphix circuits.

Basic usage

The package provides a wrapper around MQT Bench quantum circuits. Given a benchmark name and a qubit count, the class MQTBenchmark exposes a raw Qiskit circuit, and the corresponding Graphix circuit and pattern.

from graphix_mqtbench import MQTBenchmark, BenchmarkName

bench = MQTBenchmark(name=BenchmarkName.QFT, nqubits=2)
pattern = bench.pattern
pattern.to_bloch().draw()

Supported benchmarks

The definitions in _benchmark_names.py depend on the version of the mqtbench package. In particular, mqtbench 2.2.3 introduced the new benchmarks dynamic_qft and iqpe which contain feed-forward primitives that are still unrepresentable on Graphix circuits, so test_benchmark_names fails if mqtbench 2.2.3 is used with the current code. We currently pin mqtbench to version 2.2.2 and provide the script _generate_benchmark_names.py, which developers can run to regenerate _benchmark_names.py. Running

uv run python _generate_benchmark_names.py

regenerates _benchmark_names.py.

Benchmarking Graphix

To run this notebook, install the package with extra dependencies:

uv sync --extra examples

Benchmark characterization

As of version 0.3.5, Graphix supports two optimizations at the pattern level: space minimization and Pauli removal.

  • Space minimization rearranges the pattern commands in order to minimize the maximum number of qubits alive at any given time during the execution. This optimization is crucial to reduce the memory allocation in dense-state simulations. For patterns with causal flow (e.g., those directly transpiled from a quantum circuit), Pattern.minimize_space returns an optimal vale: max_space = n_qubits + 1.

  • Pauli removal removes Pauli measurements on non-input qubits at the expense of adding local Clifford commands. This optimization can significantly reduce the number of commands (and, specially, measurement commands which are the bottleneck in dense-state simulations). However, it comes with a trade-off: patterns with causal flow are only guaranteed to have gflow after this optimization step. Performing space minimization on patterns without causal flow is known to be an NP-hard problem, and heuristics can fail to find a "good" measurement order.

As show in the table below, "Pauli removal + Space minimization" will often reduce the number of commands but max_space can become significantly larger than if only "Space minimization" is applied.

from graphix_mqtbench import generate_benchmarks
import pandas as pd

nqubit = 4
benchmarks = generate_benchmarks(nqubit)

rows = []
for bench in benchmarks:
    p = bench.pattern
    p_space = p.minimize_space(copy=True)
    p_pauli = p.infer_pauli_measurements().remove_pauli_measurements(copy=True)
    p_pauli_space = p_pauli.minimize_space(copy=True)

    rows.append({
        ("Circuit", "Benchmark"): bench.name.value,
        ("Circuit", "Qubits"): bench.nqubits,
        ("Circuit", "Gates"): len(bench.circuit.instruction),
        ("Transpilation", "Max Space"): p.max_space(),
        ("Transpilation", "Cmds"): len(p),
        ("Space min.", "Max Space"): p_space.max_space(),
        ("Space min.", "Cmds"): len(p_space),
        ("Pauli removal", "Max Space"): p_pauli.max_space(),
        ("Pauli removal", "Cmds"): len(p_pauli),
        ("Pauli removal + Space min.", "Max Space"): p_pauli_space.max_space(),
        ("Pauli removal + Space min.", "Cmds"): len(p_pauli_space),
    })

df = pd.DataFrame(rows)
df.columns = pd.MultiIndex.from_tuples(df.columns)
df
Circuit Transpilation Space min. Pauli removal Pauli removal + Space min.
Benchmark Qubits Gates Max Space Cmds Max Space Cmds Max Space Cmds Max Space Cmds
0 ae 4 119 5 716 5 716 23 183 10 183
1 bmw_quark_cardinality 4 123 5 656 5 656 12 167 10 167
2 bmw_quark_copula 4 72 5 396 5 396 12 145 12 145
3 bv 4 4 5 17 5 17 6 11 5 11
4 cdkm_ripple_carry_adder 4 7 5 235 5 235 20 99 20 99
5 dj 4 16 5 89 5 89 5 23 5 23
6 draper_qft_adder 4 29 5 180 5 180 13 54 9 54
7 full_adder 4 6 5 228 5 228 14 74 12 74
8 ghz 4 4 5 32 5 32 5 28 5 28
9 graphstate 4 8 5 24 5 24 5 24 5 24
10 grover 4 132 5 939 5 939 19 309 19 309
11 hhl 4 49 5 306 5 306 16 94 16 94
12 modular_adder 4 31 5 180 5 180 12 57 9 57
13 multiplier 4 43 5 397 5 397 22 123 8 123
14 qaoa 4 24 5 151 5 151 8 66 8 66
15 qft 4 34 5 212 5 212 17 79 11 79
16 qftentangled 4 38 5 236 5 236 13 98 9 98
17 qnn 4 27 5 197 5 197 6 66 5 66
18 qpeexact 4 25 5 154 5 154 9 51 9 51
19 qpeinexact 4 37 5 224 5 224 17 90 8 90
20 qwalk 4 250 5 2135 5 2135 117 695 109 695
21 randomcircuit 4 108 5 968 5 968 45 299 24 299
22 rg_qft_multiplier 4 40 5 252 5 252 15 96 13 96
23 vbe_ripple_carry_adder 4 6 5 228 5 228 14 74 12 74
24 vqe_real_amp 4 25 5 263 5 263 8 112 8 112
25 vqe_su2 4 89 5 551 5 551 11 167 8 167
26 vqe_two_local 4 34 5 326 5 326 10 110 8 110
27 wstate 4 13 5 110 5 110 10 58 7 58

Minimal backend benchmark

import timeit
from graphix_mqtbench import MQTBenchmark, BenchmarkName
import numpy as np

rng = np.random.default_rng(42)

def simulate(pattern, backend):
    def run():
        return pattern.simulate_pattern(backend=backend, rng=rng)
    return run

benchmark = MQTBenchmark(name=BenchmarkName.QFT, nqubits=14)
pattern = benchmark.pattern.minimize_space()

run = simulate(pattern, backend="statevector")
timer = timeit.Timer(run)
t = min(timer.repeat(number=1, repeat=5))

print(
f"Benchmark = {benchmark.name.value}\n\
nqubits = {benchmark.nqubits}\n\
max_space = {pattern.max_space()}\n\
n_commands = {len(pattern)}\n\
simulation time = {t:.5f} s")
Benchmark = qft
nqubits = 14
max_space = 15
n_commands = 2982
simulation time = 0.65946 s

Acknowledgements

The function graphix_mqtbench.converter.qiskit_to_graphix_circuit was developped by @ACE07-Sev for the unitaryDESIGN 2025 edition.

About

This plugin provides an interface between Graphix and the MQT Bench suite for benchmarking purposes.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages