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

Commit 19fab23

Browse files
authored
Use the circuit library's QFT (#909)
* use QFT from circuit lib * make algos accept circuits + QFTs * deprecate QFT circ and components * allow QFT to be passed as circuit * add deprecation warnings if QFT component used * fix missing import * fix cyclic import * remove todos, fixed in Qiskit/qiskit#4209 * filter deprecations warnings from QFT * add checks on qft size * only filter warnings locally * re-enable tests in tearDown to be sure
1 parent 10e555a commit 19fab23

File tree

13 files changed

+238
-154
lines changed

13 files changed

+238
-154
lines changed

qiskit/aqua/algorithms/amplitude_estimators/ae.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,24 @@
1111
# Any modifications or derivative works of this code must retain this
1212
# copyright notice, and modified files need to carry a notice indicating
1313
# that they have been altered from the originals.
14+
1415
"""The Quantum Phase Estimation-based Amplitude Estimation algorithm."""
1516

1617
from typing import Optional, Union, List, Tuple
18+
import warnings
1719
import logging
1820
from collections import OrderedDict
1921
import numpy as np
2022
from scipy.stats import chi2, norm
2123
from scipy.optimize import bisect
2224

2325
from qiskit import QuantumCircuit
26+
from qiskit.circuit.library import QFT
2427
from qiskit.providers import BaseBackend
2528
from qiskit.aqua import QuantumInstance, AquaError
2629
from qiskit.aqua.utils import CircuitFactory
2730
from qiskit.aqua.circuits import PhaseEstimationCircuit
28-
from qiskit.aqua.components.iqfts import IQFT, Standard
31+
from qiskit.aqua.components.iqfts import IQFT
2932
from qiskit.aqua.utils.validation import validate_min
3033
from .ae_algorithm import AmplitudeEstimationAlgorithm
3134
from .ae_utils import pdf_a, derivative_log_pdf_a, bisect_max
@@ -54,7 +57,7 @@ def __init__(self, num_eval_qubits: int,
5457
a_factory: Optional[CircuitFactory] = None,
5558
q_factory: Optional[CircuitFactory] = None,
5659
i_objective: Optional[int] = None,
57-
iqft: Optional[IQFT] = None,
60+
iqft: Optional[Union[QuantumCircuit, IQFT]] = None,
5861
quantum_instance: Optional[Union[QuantumInstance, BaseBackend]] = None) -> None:
5962
r"""
6063
Args:
@@ -75,10 +78,13 @@ def __init__(self, num_eval_qubits: int,
7578
self._m = num_eval_qubits
7679
self._M = 2 ** num_eval_qubits
7780

78-
if iqft is None:
79-
iqft = Standard(self._m)
80-
81-
self._iqft = iqft
81+
if isinstance(iqft, IQFT):
82+
warnings.warn('The qiskit.aqua.components.iqfts.IQFT module is deprecated as of 0.7.0 '
83+
'and will be removed no earlier than 3 months after the release. '
84+
'You should pass a QuantumCircuit instead, see '
85+
'qiskit.circuit.library.QFT and the .inverse() method.',
86+
DeprecationWarning, stacklevel=2)
87+
self._iqft = iqft or QFT(self._m).inverse()
8288
self._circuit = None
8389
self._ret = {}
8490

qiskit/aqua/algorithms/linear_solvers/hhl.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@
1111
# Any modifications or derivative works of this code must retain this
1212
# copyright notice, and modified files need to carry a notice indicating
1313
# that they have been altered from the originals.
14-
"""
15-
The HHL algorithm.
16-
"""
14+
15+
"""The HHL algorithm."""
1716

1817
from typing import Optional, Union
1918
import logging
@@ -37,9 +36,7 @@
3736

3837

3938
class HHL(QuantumAlgorithm):
40-
41-
r"""
42-
The HHL algorithm.
39+
r"""The HHL algorithm.
4340
4441
The HHL algorithm (after the author's surnames Harrow-Hassidim-Lloyd) is a quantum algorithm
4542
to solve systems of linear equations :math:`A\overrightarrow{x}=\overrightarrow{b}`.

qiskit/aqua/algorithms/minimum_eigen_solvers/qpe.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@
1111
# Any modifications or derivative works of this code must retain this
1212
# copyright notice, and modified files need to carry a notice indicating
1313
# that they have been altered from the originals.
14-
"""
15-
The Quantum Phase Estimation Algorithm.
16-
"""
14+
15+
"""The Quantum Phase Estimation Algorithm."""
1716

1817
import logging
1918
from typing import Optional, List, Dict, Union
@@ -60,7 +59,7 @@ class QPEMinimumEigensolver(QuantumAlgorithm, MinimumEigensolver):
6059
def __init__(self,
6160
operator: Optional[BaseOperator] = None,
6261
state_in: Optional[InitialState] = None,
63-
iqft: Optional[IQFT] = None,
62+
iqft: Optional[Union[QuantumCircuit, IQFT]] = None,
6463
num_time_slices: int = 1,
6564
num_ancillae: int = 1,
6665
expansion_mode: str = 'trotter',
@@ -90,7 +89,15 @@ def __init__(self,
9089
validate_min('expansion_order', expansion_order, 1)
9190
super().__init__(quantum_instance)
9291
self._state_in = state_in
92+
93+
if isinstance(iqft, IQFT):
94+
warnings.warn('The qiskit.aqua.components.iqfts.IQFT module is deprecated as of 0.7.0 '
95+
'and will be removed no earlier than 3 months after the release. '
96+
'You should pass a QuantumCircuit instead, see '
97+
'qiskit.circuit.library.QFT and the .inverse() method.',
98+
DeprecationWarning, stacklevel=2)
9399
self._iqft = iqft
100+
94101
self._num_time_slices = num_time_slices
95102
self._num_ancillae = num_ancillae
96103
self._expansion_mode = expansion_mode

qiskit/aqua/circuits/fourier_transform_circuits.py

Lines changed: 14 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# This code is part of Qiskit.
44
#
5-
# (C) Copyright IBM 2019.
5+
# (C) Copyright IBM 2019, 2020.
66
#
77
# This code is licensed under the Apache License, Version 2.0. You may
88
# obtain a copy of this license in the LICENSE.txt file in the root directory
@@ -11,28 +11,17 @@
1111
# Any modifications or derivative works of this code must retain this
1212
# copyright notice, and modified files need to carry a notice indicating
1313
# that they have been altered from the originals.
14-
"""
15-
Quantum Fourier Transform Circuit.
16-
"""
1714

18-
import numpy as np
15+
"""DEPRECATED. Quantum Fourier Transform Circuit."""
1916

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

19+
from qiskit.circuit.library import QFT
2220
from qiskit.aqua import AquaError
2321

2422

2523
class FourierTransformCircuits:
26-
"""
27-
Quantum Fourier Transform Circuit.
28-
"""
29-
@staticmethod
30-
def _do_swaps(circuit, qubits):
31-
num_qubits = len(qubits)
32-
for i in range(num_qubits // 2):
33-
circuit.cx(qubits[i], qubits[num_qubits - i - 1])
34-
circuit.cx(qubits[num_qubits - i - 1], qubits[i])
35-
circuit.cx(qubits[i], qubits[num_qubits - i - 1])
24+
"""DEPRECATED. Quantum Fourier Transform Circuit."""
3625

3726
@staticmethod
3827
def construct_circuit(
@@ -42,8 +31,7 @@ def construct_circuit(
4231
approximation_degree=0,
4332
do_swaps=True
4433
):
45-
"""
46-
Construct the circuit representing the desired state vector.
34+
"""Construct the circuit representing the desired state vector.
4735
4836
Args:
4937
circuit (QuantumCircuit): The optional circuit to extend from.
@@ -60,50 +48,21 @@ def construct_circuit(
6048
Raises:
6149
AquaError: invalid input
6250
"""
51+
warnings.warn('The class FourierTransformCircuits is deprecated and will be removed '
52+
'no earlier than 3 months after the release 0.7.0. You should use the '
53+
'qiskit.circuit.library.QFT class instead.',
54+
DeprecationWarning, stacklevel=2)
6355

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

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

70-
if isinstance(qubits, QuantumRegister):
71-
if not circuit.has_register(qubits):
72-
circuit.add_register(qubits)
73-
elif isinstance(qubits, list):
74-
for qubit in qubits:
75-
if isinstance(qubit, Qubit):
76-
if not circuit.has_register(qubit.register):
77-
circuit.add_register(qubit.register)
78-
else:
79-
raise AquaError('A QuantumRegister or a list of qubits '
80-
'is expected for the input qubits.')
81-
else:
82-
raise AquaError('A QuantumRegister or a list of qubits '
83-
'is expected for the input qubits.')
84-
85-
if do_swaps and not inverse:
86-
FourierTransformCircuits._do_swaps(circuit, qubits)
87-
88-
qubit_range = reversed(range(len(qubits))) if inverse else range(len(qubits))
89-
for j in qubit_range:
90-
neighbor_range = range(np.max([0, j - len(qubits) + approximation_degree + 1]), j)
91-
if inverse:
92-
neighbor_range = reversed(neighbor_range)
93-
circuit.u2(0, np.pi, qubits[j])
94-
for k in neighbor_range:
95-
lam = 1.0 * np.pi / float(2 ** (j - k))
96-
if inverse:
97-
lam *= -1
98-
circuit.u1(lam / 2, qubits[j])
99-
circuit.cx(qubits[j], qubits[k])
100-
circuit.u1(-lam / 2, qubits[k])
101-
circuit.cx(qubits[j], qubits[k])
102-
circuit.u1(lam / 2, qubits[k])
103-
if not inverse:
104-
circuit.u2(0, np.pi, qubits[j])
62+
qft = QFT(len(qubits), approximation_degree=approximation_degree, do_swaps=do_swaps)
63+
if inverse:
64+
qft = qft.inverse()
10565

106-
if do_swaps and inverse:
107-
FourierTransformCircuits._do_swaps(circuit, qubits)
66+
circuit.append(qft.to_instruction(), qubits)
10867

10968
return circuit

qiskit/aqua/circuits/phase_estimation_circuit.py

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
# Any modifications or derivative works of this code must retain this
1212
# copyright notice, and modified files need to carry a notice indicating
1313
# that they have been altered from the originals.
14-
"""
15-
Quantum Phase Estimation Circuit.
16-
"""
1714

15+
"""Quantum Phase Estimation Circuit."""
16+
17+
import warnings
1818
import numpy as np
1919

2020
from qiskit import QuantumRegister, QuantumCircuit, ClassicalRegister
@@ -26,9 +26,7 @@
2626

2727

2828
class PhaseEstimationCircuit:
29-
"""
30-
Quantum Phase Estimation Circuit.
31-
"""
29+
"""Quantum Phase Estimation Circuit."""
3230

3331
def __init__(
3432
self,
@@ -46,13 +44,12 @@ def __init__(
4644
pauli_list=None
4745
):
4846
"""
49-
Constructor.
50-
5147
Args:
5248
operator (WeightedPauliOperator): the hamiltonian Operator object
5349
state_in (InitialState): the InitialState component
5450
representing the initial quantum state
55-
iqft (IQFT): the Inverse Quantum Fourier Transform component
51+
iqft (Union[QuantumCircuit, IQFT]): the Inverse Quantum Fourier Transform as circuit or
52+
Aqua component
5653
num_time_slices (int): the number of time slices
5754
num_ancillae (int): the number of ancillary qubits to use for the measurement
5855
expansion_mode (str): the expansion mode (trotter|suzuki)
@@ -65,6 +62,7 @@ def __init__(
6562
shallow_circuit_concat (bool): indicate whether to use shallow (cheap) mode
6663
for circuit concatenation
6764
pauli_list (list[Pauli]): the flat list of paulis for the operator
65+
6866
Raises:
6967
AquaError: Missing input
7068
"""
@@ -80,7 +78,16 @@ def __init__(
8078
self._unitary_circuit_factory = unitary_circuit_factory
8179
self._state_in = state_in
8280
self._state_in_circuit_factory = state_in_circuit_factory
81+
82+
# cannot check for IQFT type due to circular import
83+
if not isinstance(iqft, QuantumCircuit):
84+
warnings.warn('The qiskit.aqua.components.iqfts.IQFT module is deprecated as of 0.7.0 '
85+
'and will be removed no earlier than 3 months after the release. '
86+
'You should pass a QuantumCircuit instead, see '
87+
'qiskit.circuit.library.QFT and the .inverse() method.',
88+
DeprecationWarning, stacklevel=2)
8389
self._iqft = iqft
90+
8491
self._num_time_slices = num_time_slices
8592
self._num_ancillae = num_ancillae
8693
self._expansion_mode = expansion_mode
@@ -100,8 +107,7 @@ def construct_circuit(
100107
auxiliary_register=None,
101108
measurement=False,
102109
):
103-
"""
104-
Construct the Phase Estimation circuit
110+
"""Construct the Phase Estimation circuit
105111
106112
Args:
107113
state_register (QuantumRegister): the optional register to use for the quantum state
@@ -113,6 +119,7 @@ def construct_circuit(
113119
114120
Returns:
115121
QuantumCircuit: the QuantumCircuit object for the constructed circuit
122+
116123
Raises:
117124
RuntimeError: Multiple identity pauli terms are present
118125
ValueError: invalid mode
@@ -209,7 +216,20 @@ def construct_circuit(
209216
self._unitary_circuit_factory.build_controlled_power(qc, q, a[i], 2 ** i, aux)
210217

211218
# inverse qft on ancillae
212-
self._iqft.construct_circuit(mode='circuit', qubits=a, circuit=qc, do_swaps=False)
219+
if isinstance(self._iqft, QuantumCircuit):
220+
# check if QFT has the right size
221+
if self._iqft.num_qubits != len(a):
222+
try: # try resizing
223+
self._iqft.num_qubits = len(a)
224+
except AttributeError:
225+
raise ValueError('The IQFT cannot be resized and does not have the '
226+
'required size of {}'.format(len(a)))
227+
228+
if hasattr(self._iqft, 'do_swaps'):
229+
self._iqft.do_swaps = False
230+
qc.append(self._iqft.to_instruction(), a)
231+
else:
232+
self._iqft.construct_circuit(mode='circuit', qubits=a, circuit=qc, do_swaps=False)
213233

214234
if measurement:
215235
c_ancilla = ClassicalRegister(self._num_ancillae, name='ca')

0 commit comments

Comments
 (0)