Skip to content
This repository was archived by the owner on Dec 7, 2021. It is now read-only.

Use the circuit library's QFT #909

Merged
merged 17 commits into from
Apr 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
18 changes: 12 additions & 6 deletions qiskit/aqua/algorithms/amplitude_estimators/ae.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,24 @@
# 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.

"""The Quantum Phase Estimation-based Amplitude Estimation algorithm."""

from typing import Optional, Union, List, Tuple
import warnings
import logging
from collections import OrderedDict
import numpy as np
from scipy.stats import chi2, norm
from scipy.optimize import bisect

from qiskit import QuantumCircuit
from qiskit.circuit.library import QFT
from qiskit.providers import BaseBackend
from qiskit.aqua import QuantumInstance, AquaError
from qiskit.aqua.utils import CircuitFactory
from qiskit.aqua.circuits import PhaseEstimationCircuit
from qiskit.aqua.components.iqfts import IQFT, Standard
from qiskit.aqua.components.iqfts import IQFT
from qiskit.aqua.utils.validation import validate_min
from .ae_algorithm import AmplitudeEstimationAlgorithm
from .ae_utils import pdf_a, derivative_log_pdf_a, bisect_max
Expand Down Expand Up @@ -54,7 +57,7 @@ def __init__(self, num_eval_qubits: int,
a_factory: Optional[CircuitFactory] = None,
q_factory: Optional[CircuitFactory] = None,
i_objective: Optional[int] = None,
iqft: Optional[IQFT] = None,
iqft: Optional[Union[QuantumCircuit, IQFT]] = None,
quantum_instance: Optional[Union[QuantumInstance, BaseBackend]] = None) -> None:
r"""
Args:
Expand All @@ -75,10 +78,13 @@ def __init__(self, num_eval_qubits: int,
self._m = num_eval_qubits
self._M = 2 ** num_eval_qubits

if iqft is None:
iqft = Standard(self._m)

self._iqft = iqft
if isinstance(iqft, IQFT):
warnings.warn('The qiskit.aqua.components.iqfts.IQFT module is deprecated as of 0.7.0 '
'and will be removed no earlier than 3 months after the release. '
'You should pass a QuantumCircuit instead, see '
'qiskit.circuit.library.QFT and the .inverse() method.',
DeprecationWarning, stacklevel=2)
self._iqft = iqft or QFT(self._m).inverse()
self._circuit = None
self._ret = {}

Expand Down
9 changes: 3 additions & 6 deletions qiskit/aqua/algorithms/linear_solvers/hhl.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
# 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.
"""
The HHL algorithm.
"""

"""The HHL algorithm."""

from typing import Optional, Union
import logging
Expand All @@ -37,9 +36,7 @@


class HHL(QuantumAlgorithm):

r"""
The HHL algorithm.
r"""The HHL algorithm.

The HHL algorithm (after the author's surnames Harrow-Hassidim-Lloyd) is a quantum algorithm
to solve systems of linear equations :math:`A\overrightarrow{x}=\overrightarrow{b}`.
Expand Down
15 changes: 11 additions & 4 deletions qiskit/aqua/algorithms/minimum_eigen_solvers/qpe.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
# 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.
"""
The Quantum Phase Estimation Algorithm.
"""

"""The Quantum Phase Estimation Algorithm."""

import logging
from typing import Optional, List, Dict, Union
Expand Down Expand Up @@ -60,7 +59,7 @@ class QPEMinimumEigensolver(QuantumAlgorithm, MinimumEigensolver):
def __init__(self,
operator: Optional[BaseOperator] = None,
state_in: Optional[InitialState] = None,
iqft: Optional[IQFT] = None,
iqft: Optional[Union[QuantumCircuit, IQFT]] = None,
num_time_slices: int = 1,
num_ancillae: int = 1,
expansion_mode: str = 'trotter',
Expand Down Expand Up @@ -90,7 +89,15 @@ def __init__(self,
validate_min('expansion_order', expansion_order, 1)
super().__init__(quantum_instance)
self._state_in = state_in

if isinstance(iqft, IQFT):
warnings.warn('The qiskit.aqua.components.iqfts.IQFT module is deprecated as of 0.7.0 '
'and will be removed no earlier than 3 months after the release. '
'You should pass a QuantumCircuit instead, see '
'qiskit.circuit.library.QFT and the .inverse() method.',
DeprecationWarning, stacklevel=2)
self._iqft = iqft

self._num_time_slices = num_time_slices
self._num_ancillae = num_ancillae
self._expansion_mode = expansion_mode
Expand Down
69 changes: 14 additions & 55 deletions qiskit/aqua/circuits/fourier_transform_circuits.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# This code is part of Qiskit.
#
# (C) Copyright IBM 2019.
# (C) Copyright IBM 2019, 2020.
#
# 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 @@ -11,28 +11,17 @@
# 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.
"""
Quantum Fourier Transform Circuit.
"""

import numpy as np
"""DEPRECATED. Quantum Fourier Transform Circuit."""

from qiskit.circuit import QuantumRegister, QuantumCircuit, Qubit # pylint: disable=unused-import
import warnings

from qiskit.circuit.library import QFT
from qiskit.aqua import AquaError


class FourierTransformCircuits:
"""
Quantum Fourier Transform Circuit.
"""
@staticmethod
def _do_swaps(circuit, qubits):
num_qubits = len(qubits)
for i in range(num_qubits // 2):
circuit.cx(qubits[i], qubits[num_qubits - i - 1])
circuit.cx(qubits[num_qubits - i - 1], qubits[i])
circuit.cx(qubits[i], qubits[num_qubits - i - 1])
"""DEPRECATED. Quantum Fourier Transform Circuit."""

@staticmethod
def construct_circuit(
Expand All @@ -42,8 +31,7 @@ def construct_circuit(
approximation_degree=0,
do_swaps=True
):
"""
Construct the circuit representing the desired state vector.
"""Construct the circuit representing the desired state vector.

Args:
circuit (QuantumCircuit): The optional circuit to extend from.
Expand All @@ -60,50 +48,21 @@ def construct_circuit(
Raises:
AquaError: invalid input
"""
warnings.warn('The class FourierTransformCircuits is deprecated and will be removed '
'no earlier than 3 months after the release 0.7.0. You should use the '
'qiskit.circuit.library.QFT class instead.',
DeprecationWarning, stacklevel=2)

if circuit is None:
raise AquaError('Missing input QuantumCircuit.')

if qubits is None:
raise AquaError('Missing input qubits.')

if isinstance(qubits, QuantumRegister):
if not circuit.has_register(qubits):
circuit.add_register(qubits)
elif isinstance(qubits, list):
for qubit in qubits:
if isinstance(qubit, Qubit):
if not circuit.has_register(qubit.register):
circuit.add_register(qubit.register)
else:
raise AquaError('A QuantumRegister or a list of qubits '
'is expected for the input qubits.')
else:
raise AquaError('A QuantumRegister or a list of qubits '
'is expected for the input qubits.')

if do_swaps and not inverse:
FourierTransformCircuits._do_swaps(circuit, qubits)

qubit_range = reversed(range(len(qubits))) if inverse else range(len(qubits))
for j in qubit_range:
neighbor_range = range(np.max([0, j - len(qubits) + approximation_degree + 1]), j)
if inverse:
neighbor_range = reversed(neighbor_range)
circuit.u2(0, np.pi, qubits[j])
for k in neighbor_range:
lam = 1.0 * np.pi / float(2 ** (j - k))
if inverse:
lam *= -1
circuit.u1(lam / 2, qubits[j])
circuit.cx(qubits[j], qubits[k])
circuit.u1(-lam / 2, qubits[k])
circuit.cx(qubits[j], qubits[k])
circuit.u1(lam / 2, qubits[k])
if not inverse:
circuit.u2(0, np.pi, qubits[j])
qft = QFT(len(qubits), approximation_degree=approximation_degree, do_swaps=do_swaps)
if inverse:
qft = qft.inverse()

if do_swaps and inverse:
FourierTransformCircuits._do_swaps(circuit, qubits)
circuit.append(qft.to_instruction(), qubits)

return circuit
44 changes: 32 additions & 12 deletions qiskit/aqua/circuits/phase_estimation_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
# 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.
"""
Quantum Phase Estimation Circuit.
"""

"""Quantum Phase Estimation Circuit."""

import warnings
import numpy as np

from qiskit import QuantumRegister, QuantumCircuit, ClassicalRegister
Expand All @@ -26,9 +26,7 @@


class PhaseEstimationCircuit:
"""
Quantum Phase Estimation Circuit.
"""
"""Quantum Phase Estimation Circuit."""

def __init__(
self,
Expand All @@ -46,13 +44,12 @@ def __init__(
pauli_list=None
):
"""
Constructor.

Args:
operator (WeightedPauliOperator): the hamiltonian Operator object
state_in (InitialState): the InitialState component
representing the initial quantum state
iqft (IQFT): the Inverse Quantum Fourier Transform component
iqft (Union[QuantumCircuit, IQFT]): the Inverse Quantum Fourier Transform as circuit or
Aqua component
num_time_slices (int): the number of time slices
num_ancillae (int): the number of ancillary qubits to use for the measurement
expansion_mode (str): the expansion mode (trotter|suzuki)
Expand All @@ -65,6 +62,7 @@ def __init__(
shallow_circuit_concat (bool): indicate whether to use shallow (cheap) mode
for circuit concatenation
pauli_list (list[Pauli]): the flat list of paulis for the operator

Raises:
AquaError: Missing input
"""
Expand All @@ -80,7 +78,16 @@ def __init__(
self._unitary_circuit_factory = unitary_circuit_factory
self._state_in = state_in
self._state_in_circuit_factory = state_in_circuit_factory

# cannot check for IQFT type due to circular import
if not isinstance(iqft, QuantumCircuit):
warnings.warn('The qiskit.aqua.components.iqfts.IQFT module is deprecated as of 0.7.0 '
'and will be removed no earlier than 3 months after the release. '
'You should pass a QuantumCircuit instead, see '
'qiskit.circuit.library.QFT and the .inverse() method.',
DeprecationWarning, stacklevel=2)
self._iqft = iqft

self._num_time_slices = num_time_slices
self._num_ancillae = num_ancillae
self._expansion_mode = expansion_mode
Expand All @@ -100,8 +107,7 @@ def construct_circuit(
auxiliary_register=None,
measurement=False,
):
"""
Construct the Phase Estimation circuit
"""Construct the Phase Estimation circuit

Args:
state_register (QuantumRegister): the optional register to use for the quantum state
Expand All @@ -113,6 +119,7 @@ def construct_circuit(

Returns:
QuantumCircuit: the QuantumCircuit object for the constructed circuit

Raises:
RuntimeError: Multiple identity pauli terms are present
ValueError: invalid mode
Expand Down Expand Up @@ -209,7 +216,20 @@ def construct_circuit(
self._unitary_circuit_factory.build_controlled_power(qc, q, a[i], 2 ** i, aux)

# inverse qft on ancillae
self._iqft.construct_circuit(mode='circuit', qubits=a, circuit=qc, do_swaps=False)
if isinstance(self._iqft, QuantumCircuit):
# check if QFT has the right size
if self._iqft.num_qubits != len(a):
try: # try resizing
self._iqft.num_qubits = len(a)
except AttributeError:
raise ValueError('The IQFT cannot be resized and does not have the '
'required size of {}'.format(len(a)))

if hasattr(self._iqft, 'do_swaps'):
self._iqft.do_swaps = False
qc.append(self._iqft.to_instruction(), a)
else:
self._iqft.construct_circuit(mode='circuit', qubits=a, circuit=qc, do_swaps=False)

if measurement:
c_ancilla = ClassicalRegister(self._num_ancillae, name='ca')
Expand Down
Loading