Towards a generic transpilation approach for quantum circuits through re-synthesis¶

A PauliOpt demo¶

Arianne Meijer - van de Griend

University of Helsinki

Quantum circuit compilation¶

Suppose we want to run the circuit image-2.png

on a quantum computer with qubit connectivity image.png

In [3]:
from pauliopt.topologies import Topology

n_qubits = 4
no_topology = Topology.complete(n_qubits)
topology = Topology.line(n_qubits)
In [4]:
from pauliopt.phase import PhaseCircuit, PhaseGadget
from pauliopt.utils import pi

g = [(0,1), (1,2), (2,3), (3,0), (0,), (1,), (2,), (3,)]
angle = pi/8
gadgets = [PhaseGadget("X", angle, qubits) for qubits in g] \
        + [PhaseGadget("Z", angle, qubits) for qubits in g] 
example = PhaseCircuit(n_qubits, gadgets)
draw_circuit(example, no_topology)
Number of CNOTs: 16
Out[4]:

Intermediate representation¶

We can write this circuit as phase gadgets in ZX image.png

Which we can describe using binary matrices (Mixed ZX-phase polynomial [1]) image-3.png

[1] https://www.qplconference.org/proceedings2022/QPL_2022_paper_133.pdf

PauliOpt synthesis¶

Originally only naive synthesis. Now with the addition of Steiner-GraySynth [2], ParitySynth [3], and PermRowCol [4].

image.png

[2] https://arxiv.org/pdf/2004.06052.pdf (QPL2020)

[3] Vandaele, V., Martiel, S., & de Brugière, T. G. (2022). Phase polynomials synthesis algorithms for NISQ architectures and beyond. Quantum Science and Technology, 7(4), 045027.

[4] https://www.qplconference.org/proceedings2022/QPL_2022_paper_99.pdf

In [5]:
draw_circuit(example, topology, method="naive")
Number of CNOTs: 32
Out[5]:
In [7]:
draw_circuit(example, topology, method="paritysynth", \
                  cx_synth="naive")
Number of CNOTs: 32
Out[7]:
In [6]:
draw_circuit(example, topology, method="steiner-graysynth", \
                  cx_synth="naive")
Number of CNOTs: 32
Out[6]:
In [10]:
draw_circuit(example, topology, method="steiner-graysynth", \
                  cx_synth="permrowcol", reallocate=True)
Number of CNOTs: 21
Out[10]:

Simulated annealing¶

Find CNOTs to add the the circuit before synthesis to simplify synthesis

image.png

In [11]:
from pauliopt.phase import OptimizedPhaseCircuit

n_iter, cx_block = 1000, 3
opt = OptimizedPhaseCircuit(example.copy(), topology, cx_block,\
    phase_method="paritysynth", cx_method="permrowcol",reallocate=True)
opt.anneal(n_iter)
draw_circuit(opt)
Number of CNOTs: 23
Out[11]:
In [12]:
opt = OptimizedPhaseCircuit(example, topology, cx_block,\
    phase_method="steiner-graysynth", cx_method="permrowcol",reallocate=True)
opt.anneal(n_iter)
draw_circuit(opt)
Number of CNOTs: 18
Out[12]:

Reverse traversal¶

Iteratively improve both intial and output qubit mapping

image.png

Picture from [5].

[5] Li, G., Ding, Y., & Xie, Y. (2019, April). Tackling the qubit mapping problem for NISQ-era quantum devices. In Proceedings of the Twenty-Fourth International Conference on Architectural Support for Programming Languages and Operating Systems (pp. 1001-1014).

In [13]:
from pauliopt.phase import reverse_traversal

rt_iter = 10
opt_kwargs = {
    "phase_method": "paritysynth",
    "cx_method": "permrowcol",
    "reallocate": True
}
opt = reverse_traversal(example, topology, cx_block,\
                        rt_iter, 0, opt_kwargs)
print("Qubit numbering:", opt._qubit_mapping)
draw_circuit(opt)
Qubit numbering: range(0, 4)
Number of CNOTs: 24
Out[13]:
In [16]:
opt_kwargs["phase_method"] = "steiner-graysynth"
opt = reverse_traversal(example, topology, cx_block,\
                        rt_iter, 0, opt_kwargs)
print("Qubit numbering:", opt._qubit_mapping)
draw_circuit(opt)
Qubit numbering: range(0, 4)
Number of CNOTs: 21
Out[16]:
In [17]:
opt = reverse_traversal(example, topology, cx_block,\
                        rt_iter, n_iter, opt_kwargs)
print("Qubit numbering:", opt._qubit_mapping)
draw_circuit(opt)
Qubit numbering: range(0, 4)
Number of CNOTs: 18
Out[17]:
In [18]:
opt = reverse_traversal_anneal(example, topology, cx_block,\
                                rt_iter, n_iter, opt_kwargs)
print("Qubit numbering:", opt._qubit_mapping)
draw_circuit(opt)
Qubit numbering: [3, 0, 1, 2]
Number of CNOTs: 16
Out[18]:

Current WiP¶

  • Fix permutation recovery problems
  • Extend phase gadgets to Pauli gadgets
  • Generalize synthesis to Pauli gadgets
    • Push Cliffords in stead of CNOTs
    • Similar to Wednessday's talk on Pauli rotations
  • Add architecture constrained Clifford synthesis

image.png

Call to action¶

Code is open source and available on

https://github.com/sg495/pauliopt¶

Please use, improve, and leave feedback.

Paper: https://arxiv.org/pdf/2304.08814.pdf Note that the results in v1 of the paper are incorrect due to a bug that has since been fixed.