Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

two-qubit decomposition into sqrt(iSWAP) + approximation #9375

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9d475cb
add siswap gate to standard gates
ajavadia Jan 12, 2023
c9ac910
add sqrt(iswap) decomposition method
ajavadia Jan 13, 2023
d10f8c5
documentation
ajavadia Jan 13, 2023
c6eb038
release notes and tests
ajavadia Jan 13, 2023
84853cd
adding files
ajavadia Jan 13, 2023
6d00e34
lint
ajavadia Jan 24, 2023
071f070
Update qiskit/circuit/library/standard_gates/sqisw.py
ajavadia Feb 3, 2023
ccb293c
Update qiskit/circuit/library/standard_gates/sqisw.py
ajavadia Feb 3, 2023
d9dde5d
Update qiskit/synthesis/__init__.py
ajavadia Feb 3, 2023
9930079
rename sqisw to siswap
ajavadia Feb 3, 2023
c523180
adding approximation for siswap decomposition
ajavadia Feb 8, 2023
cc0b349
working corner case of CAN(pi/4, y, -z) which happens often in approx…
ajavadia Feb 17, 2023
e4f8b35
adding more tests
ajavadia Feb 17, 2023
88b0757
adding more tests
ajavadia Feb 17, 2023
0160592
adding siswap in standard equivalence library
ajavadia Feb 17, 2023
48ce32c
docstrings
ajavadia Feb 17, 2023
8797d81
simplify code
ajavadia Feb 19, 2023
e018148
lint
ajavadia Feb 19, 2023
512a86a
lint
ajavadia Feb 19, 2023
51b42f4
Merge branch 'main' into sqisw-gate
ajavadia Feb 23, 2023
83ea3b6
Update qiskit/synthesis/__init__.py
ajavadia Feb 23, 2023
ae38e99
Update qiskit/synthesis/__init__.py
ajavadia Feb 23, 2023
5ae2fb3
Update qiskit/synthesis/__init__.py
ajavadia Feb 24, 2023
52c7798
Update qiskit/circuit/library/standard_gates/siswap.py
ajavadia Feb 24, 2023
99b2c1f
Update qiskit/synthesis/su4/siswap_decompose.py
ajavadia Feb 24, 2023
eac72e4
Update qiskit/synthesis/su4/siswap_decompose.py
ajavadia Feb 24, 2023
ecbb3b1
Merge branch 'main' into sqisw-gate
ajavadia Mar 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions qiskit/circuit/library/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
SdgGate
SwapGate
iSwapGate
SiSwapGate
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SiSwap Gate should also be added to the documentation in this init file, and removed from the docs in circuit/library/standard_gates.
See the following PR: #9668

SXGate
SXdgGate
TGate
Expand Down
2 changes: 1 addition & 1 deletion qiskit/circuit/library/pauli_evolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

from qiskit.circuit.gate import Gate
from qiskit.circuit.parameterexpression import ParameterExpression
from qiskit.synthesis import EvolutionSynthesis, LieTrotter
from qiskit.synthesis.evolution import EvolutionSynthesis, LieTrotter
from qiskit.quantum_info import Pauli, SparsePauliOp


Expand Down
64 changes: 63 additions & 1 deletion qiskit/circuit/library/standard_gates/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,67 @@
# that they have been altered from the originals.

"""
Standard gates
=============================================================
Standard gates (:mod:`qiskit.circuit.library.standard_gates`)
=============================================================
Comment on lines -14 to +16
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's been a bad merge here - this file had its docstring reduced to a single by Shelly just recently to avoid mistakes in the documentation, and it should stay a single line. This file isn't built into the documentation at all (the only changes needed are to qiskit/circuit/library/__init__.py), but we've had a few cases where this file was erroneously updated instead only, leading to missing documentation.

It's better to put this back to just being one line, but the import should stay.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, see the details in PR #9668. Please add this gate to the docs in the init file of circuit/library.


.. autosummary::
:toctree: ../stubs/

C3XGate
C3SXGate
C4XGate
CCXGate
DCXGate
CHGate
CPhaseGate
CRXGate
CRYGate
CRZGate
CSwapGate
CSXGate
CUGate
CU1Gate
CU3Gate
CXGate
CYGate
CZGate
CCZGate
HGate
IGate
MCPhaseGate
PhaseGate
RCCXGate
RC3XGate
RXGate
RXXGate
RYGate
RYYGate
RZGate
RZZGate
RZXGate
XXMinusYYGate
XXPlusYYGate
ECRGate
SGate
SdgGate
CSGate
CSdgGate
SwapGate
iSwapGate
SiSwapGate
SXGate
SXdgGate
TGate
TdgGate
UGate
U1Gate
U2Gate
U3Gate
XGate
YGate
ZGate

"""

from .h import HGate, CHGate
Expand All @@ -31,6 +91,7 @@
from .s import SGate, SdgGate, CSGate, CSdgGate
from .swap import SwapGate, CSwapGate
from .iswap import iSwapGate
from .siswap import SiSwapGate
from .sx import SXGate, SXdgGate, CSXGate
from .dcx import DCXGate
from .t import TGate, TdgGate
Expand Down Expand Up @@ -99,6 +160,7 @@ def get_standard_gate_name_mapping():
CSdgGate(),
SwapGate(),
iSwapGate(),
SiSwapGate(),
SXdgGate(),
TGate(),
TdgGate(),
Expand Down
18 changes: 18 additions & 0 deletions qiskit/circuit/library/standard_gates/equivalence_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
SwapGate,
CSwapGate,
iSwapGate,
SiSwapGate,
SXGate,
SXdgGate,
CSXGate,
Expand Down Expand Up @@ -762,6 +763,23 @@
def_iswap.append(inst, qargs, cargs)
_sel.add_equivalence(iSwapGate(), def_iswap)

# SiSwapGate
#
# ┌──────────┐ ┌────────────┐┌────────────┐
# q_0: ┤0 ├ q_0: ┤0 ├┤0 ├
# │ Siswap │ ≡ │ Rxx(-π/4) ││ Ryy(-π/4) │
# q_1: ┤1 ├ q_1: ┤1 ├┤1 ├
# └──────────┘ └────────────┘└────────────┘

q = QuantumRegister(2, "q")
def_siswap = QuantumCircuit(q)
for inst, qargs, cargs in [
(RXXGate(-pi / 4), [q[0], q[1]], []),
(RYYGate(-pi / 4), [q[0], q[1]], []),
]:
def_siswap.append(inst, qargs, cargs)
_sel.add_equivalence(SiSwapGate(), def_siswap)

# SXGate
# global phase: π/4
# ┌────┐ ┌─────┐┌───┐┌─────┐
Expand Down
77 changes: 77 additions & 0 deletions qiskit/circuit/library/standard_gates/siswap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2017, 2023.
#
# 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
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""sqrt(iSWAP) gate."""

import numpy as np
from qiskit.circuit.gate import Gate


class SiSwapGate(Gate):
r"""sqrt(iSWAP) gate.

A 2-qubit symmetric gate from the iSWAP (or XY) family.
It has Weyl chamber coordinates (π/8, π/8, 0).

Can be applied to a :class:`~qiskit.circuit.QuantumCircuit`
with the :meth:`~qiskit.circuit.QuantumCircuit.SiSwap` method.

.. parsed-literal::

┌────────────┐┌────────────┐
q_0: ┤0 ├┤0 ├
│ Rxx(-π/4) ││ Ryy(-π/4) │
q_1: ┤1 ├┤1 ├
└────────────┘└────────────┘

.. math::
\sqrt{\mathrm{iSwap}}\ q_0, q_1 =
\begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & \frac{1}{\sqrt{2}} & \frac{i}{\sqrt{2}} & 0 \\
0 & \frac{i}{\sqrt{2}} & \frac{1}{\sqrt{2}} & 0 \\
0 & 0 & 0 & 1
\end{pmatrix}
"""

def __init__(self):
"""Create new SiSwap gate."""
super().__init__("siswap", 2, [])

def _define(self):
"""
gate siswap a, b { rxx(-pi/4) a, b; ryy(-pi/4) a, b; }
"""
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumRegister, QuantumCircuit
from .rxx import RXXGate
from .ryy import RYYGate

q = QuantumRegister(2, "q")
qc = QuantumCircuit(q, name=self.name)
rules = [(RXXGate(-np.pi / 4), [q[0], q[1]], []), (RYYGate(-np.pi / 4), [q[0], q[1]], [])]
for instr, qargs, cargs in rules:
qc._append(instr, qargs, cargs)
Comment on lines +59 to +63
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're going to use the _append form, we ought to construct a validated CircuitInstruction to add - the form of allowing qargs and cargs to _append will be deprecated, as part of drawing a clearer distinction between the responsibilities of the caller of append and the caller of _append.

If you don't want to worry about it, it shouldn't really matter for performance to just use append.


self.definition = qc

def __array__(self, dtype=None):
"""Return a numpy.array for the DCX gate."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""Return a numpy.array for the DCX gate."""
"""Return a numpy.array for the :math:`\\sqrt{iSWAP}` gate."""

perhaps?

return np.array(
[
[1, 0, 0, 0],
[0, 1 / np.sqrt(2), 1j / np.sqrt(2), 0],
[0, 1j / np.sqrt(2), 1 / np.sqrt(2), 0],
[0, 0, 0, 1],
],
dtype=dtype,
)
10 changes: 5 additions & 5 deletions qiskit/quantum_info/synthesis/two_qubit_decompose.py
Original file line number Diff line number Diff line change
Expand Up @@ -1092,17 +1092,17 @@ def __call__(
basis_fidelity: Optional[float] = None,
approximate: bool = True,
*,
_num_basis_uses: int = None,
_num_basis_uses: Optional[int] = None,
) -> QuantumCircuit:
"""Decompose a two-qubit `unitary` over fixed basis + SU(2) using the best approximation given
that each basis application has a finite `basis_fidelity`.

Args:
unitary (Operator or ndarray): 4x4 unitary to synthesize.
basis_fidelity (float or None): Fidelity to be assumed for applications of KAK Gate.
unitary: 4x4 unitary to synthesize.
basis_fidelity: Fidelity to be assumed for applications of KAK Gate.
If given, overrides basis_fidelity given at init.
approximate (bool): Approximates if basis fidelities are less than 1.0.
_num_basis_uses (int): force a particular approximation by passing a number in [0, 3].
approximate: Approximates if basis fidelities are less than 1.0.
_num_basis_uses: force a particular approximation by passing a number in [0, 3].
Returns:
QuantumCircuit: Synthesized circuit.
Raises:
Expand Down
23 changes: 2 additions & 21 deletions qiskit/quantum_info/synthesis/xx_decompose/decomposer.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"""
from __future__ import annotations
import heapq
import math
from operator import itemgetter
from typing import Callable

Expand All @@ -27,31 +26,13 @@
from qiskit.quantum_info.operators import Operator
from qiskit.quantum_info.synthesis.one_qubit_decompose import ONE_QUBIT_EULER_BASIS_GATES
from qiskit.quantum_info.synthesis.two_qubit_decompose import TwoQubitWeylDecomposition
from qiskit.synthesis.su4.utils import average_infidelity

from .circuits import apply_reflection, apply_shift, canonical_xx_circuit
from .utilities import EPSILON
from .polytopes import XXPolytope


def _average_infidelity(p, q):
"""
Computes the infidelity distance between two points p, q expressed in positive canonical
coordinates.
"""

a0, b0, c0 = p
a1, b1, c1 = q

return 1 - 1 / 20 * (
4
+ 16
* (
math.cos(a0 - a1) ** 2 * math.cos(b0 - b1) ** 2 * math.cos(c0 - c1) ** 2
+ math.sin(a0 - a1) ** 2 * math.sin(b0 - b1) ** 2 * math.sin(c0 - c1) ** 2
)
)


Comment on lines +29 to -54
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

qiskit.quantum_info shouldn't be able to access qiskit.synthesis, because the latter is way higher up in the hierarchy. Of course, the actual solution is that all the code currently in qiskit.quantum_info.synthesis, and at least the bits that are concerned with circuit objects not just matrices, ought to move into qiskit.synthesis, but that's a problem for a different PR.

For right now, it might be a shade better just to eat this code duplication right now to avoid creating even larger circular import cycles - I saw you already hit one caused by this in a file above, because you had to make an import more specific.

class XXDecomposer:
"""
A class for optimal decomposition of 2-qubit unitaries into 2-qubit basis gates of XX type
Expand Down Expand Up @@ -155,7 +136,7 @@ def _best_decomposition(canonical_coordinate, available_strengths):

strength_polytope = XXPolytope.from_strengths(*[x / 2 for x in sequence])
candidate_point = strength_polytope.nearest(canonical_coordinate)
candidate_cost = sequence_cost + _average_infidelity(
candidate_cost = sequence_cost + average_infidelity(
canonical_coordinate, candidate_point
)

Expand Down
8 changes: 8 additions & 0 deletions qiskit/synthesis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@
SolovayKitaevDecomposition
generate_basic_approximations

SU(4) (2-qubit unitary) Synthesis
=================================

.. autosummary::
:toctree: ../stubs/

SiSwapDecomposer
"""

from .evolution import (
Expand Down Expand Up @@ -122,3 +129,4 @@
synth_cnotdihedral_general,
)
from .discrete_basis import SolovayKitaevDecomposition, generate_basic_approximations
from .su4 import SiSwapDecomposer
15 changes: 15 additions & 0 deletions qiskit/synthesis/su4/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2023.
#
# 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
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""Two-qubit unitary synthesis methods."""

from .siswap_decompose import SiSwapDecomposer
Loading