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

Adding QFT gate to natively reason about Quantum Fourier Transforms #11463

Merged
merged 24 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
71efe1c
initial commit
alexanderivrii Dec 28, 2023
3705ba4
release notes
alexanderivrii Dec 28, 2023
68c2ccf
fixing synthesis plugin options
alexanderivrii Dec 28, 2023
c835e20
Merge branch 'main' into qft_gate
alexanderivrii Feb 4, 2024
425a6d9
finalize merge conflicts
alexanderivrii Feb 4, 2024
ef45120
fixing default option values for qft plugins'
alexanderivrii Feb 6, 2024
09086e6
additional tests for qft plugins
alexanderivrii Feb 6, 2024
f1d4215
Merge branch 'main' into qft_gate
alexanderivrii Feb 6, 2024
5d8be05
Merge branch 'main' into qft_gate
alexanderivrii May 2, 2024
eac4ed6
renaming QftGate to QFTGate
alexanderivrii May 2, 2024
cac843b
Merge branch 'main' into qft_gate
alexanderivrii Jul 4, 2024
5acfc3f
Also renaming Qft to QFT in synthesis method names
alexanderivrii Jul 4, 2024
0b605bc
Merge branch 'qft_gate' of github.com:alexanderivrii/qiskit-terra int…
alexanderivrii Jul 4, 2024
6106c4a
appplying Jake's suggestion from code review
alexanderivrii Jul 4, 2024
a76fbe7
inlining _basic_definition into _define
alexanderivrii Jul 5, 2024
0d06898
docstring improvements
alexanderivrii Jul 5, 2024
71860bf
more docstring improvements
alexanderivrii Jul 5, 2024
d496f08
renaming do_swaps to reverse_qubits in the new code
alexanderivrii Jul 5, 2024
2822d5c
typos
alexanderivrii Jul 5, 2024
6feb4fc
adding synth_qft_full to __init__
alexanderivrii Jul 7, 2024
a0ea5ba
round of suggestions from code review
alexanderivrii Jul 9, 2024
b230c58
another round of code review suggestions
alexanderivrii Jul 9, 2024
8806c27
fixes
alexanderivrii Jul 9, 2024
4ae4c9e
also adding QFTGate plugins to the docs
alexanderivrii Jul 9, 2024
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
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ sk = "qiskit.transpiler.passes.synthesis.solovay_kitaev_synthesis:SolovayKitaevS
"permutation.kms" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:KMSSynthesisPermutation"
"permutation.basic" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:BasicSynthesisPermutation"
"permutation.acg" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:ACGSynthesisPermutation"
"qft.full" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:QFTSynthesisFull"
"qft.line" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:QFTSynthesisLine"
"qft.default" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:QFTSynthesisFull"
"permutation.token_swapper" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:TokenSwapperSynthesisPermutation"

[project.entry-points."qiskit.transpiler.init"]
Expand Down
3 changes: 2 additions & 1 deletion qiskit/circuit/library/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@
:template: autosummary/class_no_inherited_members.rst

QFT
QFTGate

Arithmetic Circuits
===================
Expand Down Expand Up @@ -523,7 +524,7 @@
XOR,
InnerProduct,
)
from .basis_change import QFT
from .basis_change import QFT, QFTGate
from .arithmetic import (
FunctionalPauliRotations,
LinearPauliRotations,
Expand Down
2 changes: 1 addition & 1 deletion qiskit/circuit/library/basis_change/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@

"""The basis change circuits."""

from .qft import QFT
from .qft import QFT, QFTGate
46 changes: 40 additions & 6 deletions qiskit/circuit/library/basis_change/qft.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""Quantum Fourier Transform Circuit."""
"""Define a Quantum Fourier Transform circuit (QFT) and a native gate (QFTGate)."""

from typing import Optional
from __future__ import annotations
import warnings
import numpy as np

from qiskit.circuit import QuantumCircuit, QuantumRegister, CircuitInstruction

from qiskit.circuit.quantumcircuit import QuantumCircuit, QuantumRegister, CircuitInstruction, Gate
from ..blueprintcircuit import BlueprintCircuit


Expand Down Expand Up @@ -75,12 +74,12 @@ class QFT(BlueprintCircuit):

def __init__(
self,
num_qubits: Optional[int] = None,
num_qubits: int | None = None,
approximation_degree: int = 0,
do_swaps: bool = True,
inverse: bool = False,
insert_barriers: bool = False,
name: Optional[str] = None,
name: str | None = None,
) -> None:
"""Construct a new QFT circuit.

Expand Down Expand Up @@ -293,3 +292,38 @@ def _build(self) -> None:

wrapped = circuit.to_instruction() if self.insert_barriers else circuit.to_gate()
self.compose(wrapped, qubits=self.qubits, inplace=True)


class QFTGate(Gate):
r"""Quantum Fourier Transform Gate.

The Quantum Fourier Transform (QFT) on :math:`n` qubits is the operation

.. math::

|j\rangle \mapsto \frac{1}{2^{n/2}} \sum_{k=0}^{2^n - 1} e^{2\pi ijk / 2^n} |k\rangle

"""

def __init__(
self,
num_qubits: int,
):
"""
Args:
num_qubits: The number of qubits on which the QFT acts.
"""
super().__init__(name="qft", num_qubits=num_qubits, params=[])

def __array__(self, dtype=complex):
"""Return a numpy array for the QFTGate."""
n = self.num_qubits
nums = np.arange(2**n)
outer = np.outer(nums, nums)
return np.exp(2j * np.pi * outer * (0.5**n), dtype=dtype) * (0.5 ** (n / 2))

def _define(self):
"""Provide a specific decomposition of the QFTGate into a quantum circuit."""
from qiskit.synthesis.qft import synth_qft_full

self.definition = synth_qft_full(num_qubits=self.num_qubits)
2 changes: 2 additions & 0 deletions qiskit/qpy/binary_io/circuits.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,8 @@ def _read_instruction(
"DiagonalGate",
}:
gate = gate_class(params)
elif gate_name == "QFTGate":
gate = gate_class(len(qargs), *params)
else:
if gate_name == "Barrier":
params = [len(qargs)]
Expand Down
3 changes: 2 additions & 1 deletion qiskit/synthesis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
======================

.. autofunction:: synth_qft_line
.. autofunction:: synth_qft_full

Unitary Synthesis
=================
Expand Down Expand Up @@ -162,7 +163,7 @@
synth_circuit_from_stabilizers,
)
from .discrete_basis import SolovayKitaevDecomposition, generate_basic_approximations
from .qft import synth_qft_line
from .qft import synth_qft_line, synth_qft_full
from .unitary.qsd import qs_decomposition
from .unitary import aqc
from .one_qubit import OneQubitEulerDecomposer
Expand Down
1 change: 1 addition & 0 deletions qiskit/synthesis/qft/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
"""Module containing stabilizer QFT circuit synthesis."""

from .qft_decompose_lnn import synth_qft_line
from .qft_decompose_full import synth_qft_full
alexanderivrii marked this conversation as resolved.
Show resolved Hide resolved
79 changes: 79 additions & 0 deletions qiskit/synthesis/qft/qft_decompose_full.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 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
# 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.
"""
Circuit synthesis for a QFT circuit.
"""

from __future__ import annotations
import numpy as np
from qiskit.circuit.quantumcircuit import QuantumCircuit


def synth_qft_full(
num_qubits: int,
do_swaps: bool = True,
approximation_degree: int = 0,
insert_barriers: bool = False,
inverse: bool = False,
name: str | None = None,
) -> QuantumCircuit:
"""Construct a circuit for the Quantum Fourier Transform using all-to-all connectivity.

.. note::

With the default value of ``do_swaps = True``, this synthesis algorithm creates a
circuit that faithfully implements the QFT operation. This circuit contains a sequence
of swap gates at the end, corresponding to reversing the order of its output qubits.
In some applications this reversal permutation can be avoided. Setting ``do_swaps = False``
creates a circuit without this reversal permutation, at the expense that this circuit
implements the "QFT-with-reversal" instead of QFT. Alternatively, the
:class:`~.ElidePermutations` transpiler pass is able to remove these swap gates.

Args:
num_qubits: The number of qubits on which the Quantum Fourier Transform acts.
do_swaps: Whether to synthesize the "QFT" or the "QFT-with-reversal" operation.
approximation_degree: The degree of approximation (0 for no approximation).
It is possible to implement the QFT approximately by ignoring
controlled-phase rotations with the angle beneath a threshold. This is discussed
in more detail in https://arxiv.org/abs/quant-ph/9601018 or
https://arxiv.org/abs/quant-ph/0403071.
insert_barriers: If ``True``, barriers are inserted for improved visualization.
inverse: If ``True``, the inverse Quantum Fourier Transform is constructed.
name: The name of the circuit.

Returns:
A circuit implementing the QFT operation.

"""

circuit = QuantumCircuit(num_qubits, name=name)

for j in reversed(range(num_qubits)):
circuit.h(j)
num_entanglements = max(0, j - max(0, approximation_degree - (num_qubits - j - 1)))
for k in reversed(range(j - num_entanglements, j)):
# Use negative exponents so that the angle safely underflows to zero, rather than
# using a temporary variable that overflows to infinity in the worst case.
lam = np.pi * (2.0 ** (k - j))
circuit.cp(lam, j, k)

if insert_barriers:
circuit.barrier()

if do_swaps:
for i in range(num_qubits // 2):
circuit.swap(i, num_qubits - i - 1)

if inverse:
circuit = circuit.inverse()

return circuit
26 changes: 17 additions & 9 deletions qiskit/synthesis/qft/qft_decompose_lnn.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,29 @@
def synth_qft_line(
num_qubits: int, do_swaps: bool = True, approximation_degree: int = 0
) -> QuantumCircuit:
"""Synthesis of a QFT circuit for a linear nearest neighbor connectivity.
Based on Fig 2.b in Fowler et al. [1].
"""Construct a circuit for the Quantum Fourier Transform using linear
neighbor connectivity.

Note that this method *reverts* the order of qubits in the circuit,
compared to the original :class:`.QFT` code.
Hence, the default value of the ``do_swaps`` parameter is ``True``
since it produces a circuit with fewer CX gates.
The construction is based on Fig 2.b in Fowler et al. [1].

.. note::

With the default value of ``do_swaps = True``, this synthesis algorithm creates a
circuit that faithfully implements the QFT operation. When ``do_swaps = False``,
this synthesis algorithm creates a circuit that corresponds to "QFT-with-reversal":
applying the QFT and reversing the order of its output qubits.

Args:
num_qubits: The number of qubits on which the QFT acts.
num_qubits: The number of qubits on which the Quantum Fourier Transform acts.
approximation_degree: The degree of approximation (0 for no approximation).
do_swaps: Whether to include the final swaps in the QFT.
It is possible to implement the QFT approximately by ignoring
controlled-phase rotations with the angle beneath a threshold. This is discussed
in more detail in https://arxiv.org/abs/quant-ph/9601018 or
https://arxiv.org/abs/quant-ph/0403071.
do_swaps: Whether to synthesize the "QFT" or the "QFT-with-reversal" operation.

Returns:
A circuit implementation of the QFT circuit.
A circuit implementing the QFT operation.

References:
1. A. G. Fowler, S. J. Devitt, and L. C. L. Hollenberg,
Expand Down
Loading
Loading