Skip to content

Commit

Permalink
Format synthesis docs (#11755)
Browse files Browse the repository at this point in the history
* Format synthesis docs.

* Apply suggestions from Jake's code review

Co-authored-by: Jake Lishman <jake@binhbar.com>

* Apply rest of review comments

* Fix lint, latexify ~

* Apply suggestions from code review

* Revert bug in TwoQubitWeylfSimabmbEquiv

* Apply inline suggestions from Julien's code review

Co-authored-by: Julien Gacon <gaconju@gmail.com>

* Finish applying Julien's suggestions

* Apply suggestions from Shelly's code review

* inline typehints for synth docs

* Update qiskit/synthesis/clifford/clifford_decompose_ag.py

Co-authored-by: Evgenii Zheltonozhskii <zheltonozhskiy@gmail.com>

* Apply review comments from Shelly

* Make lint happy?

* Fix black

* Remove unnecessary indentation

* Fix backslash in non-raw string

---------

Co-authored-by: Jake Lishman <jake@binhbar.com>
Co-authored-by: Julien Gacon <gaconju@gmail.com>
Co-authored-by: Julien Gacon <jules.gacon@googlemail.com>
Co-authored-by: Evgenii Zheltonozhskii <zheltonozhskiy@gmail.com>
  • Loading branch information
5 people committed Feb 15, 2024
1 parent 381a881 commit 694de7c
Show file tree
Hide file tree
Showing 31 changed files with 407 additions and 333 deletions.
1 change: 1 addition & 0 deletions qiskit/quantum_info/operators/dihedral/dihedral.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ def to_circuit(self):
*Scalable randomised benchmarking of non-Clifford gates*,
npj Quantum Inf 2, 16012 (2016).
"""
# pylint: disable=cyclic-import
from qiskit.synthesis.cnotdihedral import synth_cnotdihedral_full

return synth_cnotdihedral_full(self)
Expand Down
4 changes: 2 additions & 2 deletions qiskit/quantum_info/operators/symplectic/clifford.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
from qiskit.quantum_info.operators.operator import Operator
from qiskit.quantum_info.operators.scalar_op import ScalarOp
from qiskit.quantum_info.operators.symplectic.base_pauli import _count_y
from qiskit.synthesis.linear import calc_inverse_matrix

from .base_pauli import BasePauli
from .clifford_circuits import _append_circuit, _append_operation
Expand Down Expand Up @@ -556,6 +555,7 @@ def from_linear_function(cls, linear_function):
Returns:
Clifford: the Clifford object for this linear function.
"""
from qiskit.synthesis.linear import calc_inverse_matrix # pylint: disable=cyclic-import

mat = linear_function.linear
mat_t = np.transpose(mat)
Expand Down Expand Up @@ -632,7 +632,7 @@ def to_circuit(self):
Phys. Rev. A 70, 052328 (2004).
`arXiv:quant-ph/0406196 <https://arxiv.org/abs/quant-ph/0406196>`_
"""
from qiskit.synthesis.clifford import synth_clifford_full
from qiskit.synthesis.clifford import synth_clifford_full # pylint: disable=cyclic-import

return synth_clifford_full(self)

Expand Down
18 changes: 10 additions & 8 deletions qiskit/synthesis/clifford/clifford_decompose_ag.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import numpy as np

from qiskit.circuit import QuantumCircuit
from qiskit.quantum_info import Clifford
from qiskit.quantum_info.operators.symplectic.clifford_circuits import (
_append_cx,
_append_h,
Expand All @@ -32,16 +33,17 @@
from .clifford_decompose_bm import _decompose_clifford_1q


def synth_clifford_ag(clifford):
"""Decompose a Clifford operator into a QuantumCircuit based on Aaronson-Gottesman method.
def synth_clifford_ag(clifford: Clifford) -> QuantumCircuit:
"""Decompose a :class:`.Clifford` operator into a :class:`.QuantumCircuit`
based on Aaronson-Gottesman method [1].
Args:
clifford (Clifford): a clifford operator.
clifford: A Clifford operator.
Return:
QuantumCircuit: a circuit implementation of the Clifford.
Returns:
A circuit implementation of the Clifford.
Reference:
References:
1. S. Aaronson, D. Gottesman, *Improved Simulation of Stabilizer Circuits*,
Phys. Rev. A 70, 052328 (2004).
`arXiv:quant-ph/0406196 <https://arxiv.org/abs/quant-ph/0406196>`_
Expand Down Expand Up @@ -114,9 +116,9 @@ def _set_qubit_x_true(clifford, circuit, qubit):


def _set_row_x_zero(clifford, circuit, qubit):
"""Set destabilizer.X[qubit, i] to False for all i > qubit.
r"""Set destabilizer.X[qubit, i] to False for all i > qubit.
This is done by applying CNOTS assumes k<=N and A[k][k]=1
This is done by applying CNOTs assuming :math:`k \leq N` and A[k][k]=1
"""
x = clifford.destab_x[qubit]
z = clifford.destab_z[qubit]
Expand Down
17 changes: 9 additions & 8 deletions qiskit/synthesis/clifford/clifford_decompose_bm.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import numpy as np

from qiskit.circuit import QuantumCircuit
from qiskit.quantum_info import Clifford
from qiskit.exceptions import QiskitError
from qiskit.quantum_info.operators.symplectic.clifford_circuits import (
_append_cx,
Expand All @@ -31,20 +32,20 @@
)


def synth_clifford_bm(clifford):
"""Optimal CX-cost decomposition of a Clifford operator on 2-qubits or 3-qubits
into a QuantumCircuit based on Bravyi-Maslov method.
def synth_clifford_bm(clifford: Clifford) -> QuantumCircuit:
"""Optimal CX-cost decomposition of a :class:`.Clifford` operator on 2 qubits
or 3 qubits into a :class:`.QuantumCircuit` based on the Bravyi-Maslov method [1].
Args:
clifford (Clifford): a clifford operator.
clifford: A Clifford operator.
Return:
QuantumCircuit: a circuit implementation of the Clifford.
Returns:
A circuit implementation of the Clifford.
Raises:
QiskitError: if clifford is on more than 3 qubits.
QiskitError: if Clifford is on more than 3 qubits.
Reference:
References:
1. S. Bravyi, D. Maslov, *Hadamard-free circuits expose the
structure of the Clifford group*,
`arXiv:2003.09412 [quant-ph] <https://arxiv.org/abs/2003.09412>`_
Expand Down
21 changes: 12 additions & 9 deletions qiskit/synthesis/clifford/clifford_decompose_full.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,29 @@
Circuit synthesis for the Clifford class for all-to-all architecture.
"""

from __future__ import annotations
from qiskit.circuit import QuantumCircuit
from qiskit.quantum_info import Clifford
from qiskit.synthesis.clifford.clifford_decompose_ag import synth_clifford_ag
from qiskit.synthesis.clifford.clifford_decompose_bm import synth_clifford_bm
from qiskit.synthesis.clifford.clifford_decompose_greedy import synth_clifford_greedy


def synth_clifford_full(clifford, method=None):
"""Decompose a Clifford operator into a QuantumCircuit.
def synth_clifford_full(clifford: Clifford, method: str | None = None) -> QuantumCircuit:
r"""Decompose a :class:`.Clifford` operator into a :class:`.QuantumCircuit`.
For N <= 3 qubits this is based on optimal CX cost decomposition
from reference [1]. For N > 3 qubits this is done using the general
For :math:`N \leq 3` qubits this is based on optimal CX-cost decomposition
from reference [1]. For :math:`N > 3` qubits this is done using the general
non-optimal greedy compilation routine from reference [3],
which typically yields better CX cost compared to the AG method in [2].
Args:
clifford (Clifford): a clifford operator.
method (str): Optional, a synthesis method ('AG' or 'greedy').
If set this overrides optimal decomposition for N <=3 qubits.
clifford: A Clifford operator.
method: Optional, a synthesis method (``'AG'`` or ``'greedy'``).
If set this overrides optimal decomposition for :math:`N \leq 3` qubits.
Return:
QuantumCircuit: a circuit implementation of the Clifford.
Returns:
A circuit implementation of the Clifford.
References:
1. S. Bravyi, D. Maslov, *Hadamard-free circuits expose the
Expand Down
24 changes: 14 additions & 10 deletions qiskit/synthesis/clifford/clifford_decompose_greedy.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2021, 2022.
# (C) Copyright IBM 2021, 2024.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
Expand All @@ -22,32 +22,36 @@
import numpy as np
from qiskit.circuit import QuantumCircuit
from qiskit.exceptions import QiskitError
from qiskit.quantum_info import Clifford, Pauli
from qiskit.quantum_info.operators.symplectic.clifford_circuits import (
_append_cx,
_append_h,
_append_s,
_append_swap,
)
from qiskit.quantum_info.operators.symplectic.pauli import Pauli


def synth_clifford_greedy(clifford):
"""Decompose a Clifford operator into a QuantumCircuit based on the
greedy Clifford compiler that is described in Appendix A of
Bravyi, Hu, Maslov and Shaydulin.
def synth_clifford_greedy(clifford: Clifford) -> QuantumCircuit:
"""Decompose a :class:`.Clifford` operator into a :class:`.QuantumCircuit` based
on the greedy Clifford compiler that is described in Appendix A of
Bravyi, Hu, Maslov and Shaydulin [1].
This method typically yields better CX cost compared to the Aaronson-Gottesman method.
Note that this function only implements the greedy Clifford compiler from Appendix A
of [1], and not the templates and symbolic Pauli gates optimizations
that are mentioned in the same paper.
Args:
clifford (Clifford): a clifford operator.
clifford: A Clifford operator.
Return:
QuantumCircuit: a circuit implementation of the Clifford.
Returns:
A circuit implementation of the Clifford.
Raises:
QiskitError: if symplectic Gaussian elimination fails.
Reference:
References:
1. Sergey Bravyi, Shaohan Hu, Dmitri Maslov, Ruslan Shaydulin,
*Clifford Circuit Optimization with Templates and Symbolic Pauli Gates*,
`arXiv:2105.02291 [quant-ph] <https://arxiv.org/abs/2105.02291>`_
Expand Down
85 changes: 43 additions & 42 deletions qiskit/synthesis/clifford/clifford_decompose_layers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2023.
# (C) Copyright IBM 2023, 2024.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
Expand All @@ -14,27 +14,29 @@
"""
# pylint: disable=invalid-name

from __future__ import annotations
from collections.abc import Callable
import numpy as np

from qiskit.circuit import QuantumCircuit
from qiskit.exceptions import QiskitError
from qiskit.quantum_info import Clifford # pylint: disable=cyclic-import
from qiskit.quantum_info.operators.symplectic.clifford_circuits import (
_append_h,
_append_s,
_append_cz,
)
from qiskit.synthesis.linear import (
synth_cnot_count_full_pmh,
synth_cnot_depth_line_kms,
)
from qiskit.synthesis.linear_phase import synth_cz_depth_line_mr
from qiskit.synthesis.linear_phase.cx_cz_depth_lnn import synth_cx_cz_depth_line_my
from qiskit.synthesis.linear_phase import synth_cz_depth_line_mr, synth_cx_cz_depth_line_my
from qiskit.synthesis.linear.linear_matrix_utils import (
calc_inverse_matrix,
_compute_rank,
_gauss_elimination,
_gauss_elimination_with_perm,
)
from qiskit.quantum_info.operators.symplectic.clifford_circuits import (
_append_h,
_append_s,
_append_cz,
)


def _default_cx_synth_func(mat):
Expand Down Expand Up @@ -62,15 +64,15 @@ def _default_cz_synth_func(symmetric_mat):


def synth_clifford_layers(
cliff,
cx_synth_func=_default_cx_synth_func,
cz_synth_func=_default_cz_synth_func,
cx_cz_synth_func=None,
cz_func_reverse_qubits=False,
validate=False,
):
"""Synthesis of a Clifford into layers, it provides a similar decomposition to the synthesis
described in Lemma 8 of Bravyi and Maslov.
cliff: Clifford,
cx_synth_func: Callable[[np.ndarray], QuantumCircuit] = _default_cx_synth_func,
cz_synth_func: Callable[[np.ndarray], QuantumCircuit] = _default_cz_synth_func,
cx_cz_synth_func: Callable[[np.ndarray], QuantumCircuit] | None = None,
cz_func_reverse_qubits: bool = False,
validate: bool = False,
) -> QuantumCircuit:
"""Synthesis of a :class:`.Clifford` into layers, it provides a similar
decomposition to the synthesis described in Lemma 8 of Bravyi and Maslov [1].
For example, a 5-qubit Clifford circuit is decomposed into the following layers:
Expand All @@ -87,24 +89,25 @@ def synth_clifford_layers(
q_4: ┤4 ├┤4 ├┤4 ├┤4 ├┤4 ├┤4 ├┤4 ├┤4 ├
└─────┘└─────┘└────────┘└─────┘└─────┘└─────┘└─────┘└────────┘
This decomposition is for the default cz_synth_func and cx_synth_func functions,
This decomposition is for the default ``cz_synth_func`` and ``cx_synth_func`` functions,
with other functions one may see slightly different decomposition.
Args:
cliff (Clifford): a clifford operator.
cx_synth_func (Callable): a function to decompose the CX sub-circuit.
It gets as input a boolean invertible matrix, and outputs a QuantumCircuit.
cz_synth_func (Callable): a function to decompose the CZ sub-circuit.
It gets as input a boolean symmetric matrix, and outputs a QuantumCircuit.
cliff: A Clifford operator.
cx_synth_func: A function to decompose the CX sub-circuit.
It gets as input a boolean invertible matrix, and outputs a :class:`.QuantumCircuit`.
cz_synth_func: A function to decompose the CZ sub-circuit.
It gets as input a boolean symmetric matrix, and outputs a :class:`.QuantumCircuit`.
cx_cz_synth_func (Callable): optional, a function to decompose both sub-circuits CZ and CX.
validate (Boolean): if True, validates the synthesis process.
cz_func_reverse_qubits (Boolean): True only if cz_synth_func is synth_cz_depth_line_mr,
since this function returns a circuit that reverts the order of qubits.
cz_func_reverse_qubits (Boolean): True only if ``cz_synth_func`` is
:func:`.synth_cz_depth_line_mr`, since this function returns a circuit that reverts
the order of qubits.
Return:
QuantumCircuit: a circuit implementation of the Clifford.
Returns:
A circuit implementation of the Clifford.
Reference:
References:
1. S. Bravyi, D. Maslov, *Hadamard-free circuits expose the
structure of the Clifford group*,
`arXiv:2003.09412 [quant-ph] <https://arxiv.org/abs/2003.09412>`_
Expand Down Expand Up @@ -156,8 +159,6 @@ def synth_clifford_layers(
layeredCircuit.append(H1_circ, qubit_list)

# Add Pauli layer to fix the Clifford phase signs
# pylint: disable=cyclic-import
from qiskit.quantum_info.operators.symplectic import Clifford

clifford_target = Clifford(layeredCircuit)
pauli_circ = _calc_pauli_diff(cliff, clifford_target)
Expand Down Expand Up @@ -185,17 +186,17 @@ def _create_graph_state(cliff, validate=False):
The algorithm is based on Lemma 6 in [2].
Args:
cliff (Clifford): a clifford operator.
cliff (Clifford): a Clifford operator.
validate (Boolean): if True, validates the synthesis process.
Return:
Returns:
H1_circ: a circuit containing a layer of Hadamard gates.
cliffh: cliffh.stab_x has full rank.
Raises:
QiskitError: if there are errors in the Gauss elimination process.
Reference:
References:
2. S. Aaronson, D. Gottesman, *Improved Simulation of Stabilizer Circuits*,
Phys. Rev. A 70, 052328 (2004).
`arXiv:quant-ph/0406196 <https://arxiv.org/abs/quant-ph/0406196>`_
Expand Down Expand Up @@ -251,11 +252,11 @@ def _decompose_graph_state(cliff, validate, cz_synth_func):
H2_circ is a circuit that can contain H gates on all qubits.
Args:
cliff (Clifford): a clifford operator corresponding to a graph state, cliff.stab_x has full rank.
cliff (Clifford): a Clifford operator corresponding to a graph state, cliff.stab_x has full rank.
validate (Boolean): if True, validates the synthesis process.
cz_synth_func (Callable): a function to decompose the CZ sub-circuit.
Return:
Returns:
S1_circ: a circuit that can contain only S gates.
CZ1_circ: a circuit that can contain only CZ gates.
H2_circ: a circuit containing a layer of Hadamard gates.
Expand Down Expand Up @@ -322,7 +323,7 @@ def _decompose_hadamard_free(
cx_cz_synth_func (Callable): optional, a function to decompose both sub-circuits CZ and CX.
cz_func_reverse_qubits (Boolean): True only if cz_synth_func is synth_cz_depth_line_mr.
Return:
Returns:
S2_circ: a circuit that can contain only S gates.
CZ2_circ: a circuit that can contain only CZ gates.
CX_circ: a circuit that can contain only CX gates.
Expand Down Expand Up @@ -411,18 +412,18 @@ def _calc_pauli_diff(cliff, cliff_target):


def synth_clifford_depth_lnn(cliff):
"""Synthesis of a Clifford into layers for linear-nearest neighbour connectivity.
"""Synthesis of a :class:`.Clifford` into layers for linear-nearest neighbour connectivity.
The depth of the synthesized n-qubit circuit is bounded by 7*n+2, which is not optimal.
It should be replaced by a better algorithm that provides depth bounded by 7*n-4 [3].
The depth of the synthesized n-qubit circuit is bounded by :math:`7n+2`, which is not optimal.
It should be replaced by a better algorithm that provides depth bounded by :math:`7n-4` [3].
Args:
cliff (Clifford): a clifford operator.
cliff (Clifford): a Clifford operator.
Return:
Returns:
QuantumCircuit: a circuit implementation of the Clifford.
Reference:
References:
1. S. Bravyi, D. Maslov, *Hadamard-free circuits expose the
structure of the Clifford group*,
`arXiv:2003.09412 [quant-ph] <https://arxiv.org/abs/2003.09412>`_
Expand Down

0 comments on commit 694de7c

Please sign in to comment.