CQCL / pytket-docs

User manual and example notebooks for the pytket quantum computing toolkit
https://docs.quantinuum.com/tket/user-guide/
Apache License 2.0
331 stars 90 forks source link

`optimisation_level=2` bug #249

Closed lewis-wright closed 1 year ago

lewis-wright commented 1 year ago

Hi all,

I'm getting a bug when using backend.get_compiled_circuit() for different levels of optimisation_level. Essentially I'm strictly getting more single and two qubit gates when optimisation_level=2 as opposed to when optimisation_level=0. I'm using pytket.__version__ = '1.17.1' , I have tried with the most up-to-date pytket version in a fresh environment as well, with the same results. Here is a code snippet that reproduces the results:

from pytket import Circuit
from pytket.circuit import OpType
from pytket.extensions.qiskit import (
    AerBackend,
)
from pytket.passes import (
    auto_rebase_pass,
    RemoveRedundancies,
)
from pytket.utils.stats import gate_counts

def create_qft_circuit(n):
    circ = Circuit(n, name="QFT")
    for i in range(n):
        circ.H(i)
        for j in range(i + 1, n):
            circ.CU1(1 / 2 ** (j - i), i, j)
    return circ

n = 7  # Total number of qubits.

"""Pytket bug:
"""

approx_circuit = create_qft_circuit(n)
backend = AerBackend()
non_opt_circ = backend.get_compiled_circuit(approx_circuit, optimisation_level=0)
opt_circ = backend.get_compiled_circuit(approx_circuit, optimisation_level=2)

print("non-opt: ", non_opt_circ.n_2qb_gates())
print("opt: ", opt_circ.n_2qb_gates())

# Change to tket gateset.
gateset = {OpType.TK1, OpType.TK2}
custom = auto_rebase_pass(gateset)
custom.apply(non_opt_circ)  # Apply to opt circ
custom.apply(opt_circ)  # Apply to opt circ

RemoveRedundancies().apply(non_opt_circ)
RemoveRedundancies().apply(opt_circ)

print("non-opt tket: ", gate_counts(non_opt_circ))
print("opt tket: ", gate_counts(opt_circ))

Output:

non-opt:  21
opt:  42
non-opt tket:  Counter({<OpType.TK1: 40>: 91, <OpType.TK2: 41>: 21})
opt tket:  Counter({<OpType.TK1: 40>: 211, <OpType.TK2: 41>: 42})
CalMacCQ commented 1 year ago

In this particular example I think the difference in 2 qubit gate count (pre rebase) is due to the fact that Aer can run CU1 gates natively. The heavier optimisations that go via CX have more 2q gates.

These CU1 gates require 2 CX gates each to implement in general so the heavier optimisation which goes via {TK1, CX} has more two qubit gates in the resulting circuit.

This maybe isn't so surprising in this case. The gateset for AerBackend is very broad and not very representative of a real device.