• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

qiskit-community / qiskit-algorithms / 5928979286

21 Aug 2023 04:30PM CUT coverage: 89.947% (-0.03%) from 89.975%
5928979286

Pull #45

github

web-flow
Merge c22a039b0 into 37dafdd20
Pull Request #45: Revert "Add tutorials"

6451 of 7172 relevant lines covered (89.95%)

0.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.93
/qiskit_algorithms/amplitude_amplifiers/amplification_problem.py
1
# This code is part of a Qiskit project.
2
#
3
# (C) Copyright IBM 2021, 2023.
4
#
5
# This code is licensed under the Apache License, Version 2.0. You may
6
# obtain a copy of this license in the LICENSE.txt file in the root directory
7
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8
#
9
# Any modifications or derivative works of this code must retain this
10
# copyright notice, and modified files need to carry a notice indicating
11
# that they have been altered from the originals.
12

13
"""The Amplification problem class."""
1✔
14
from __future__ import annotations
1✔
15

16
from collections.abc import Callable
1✔
17
from typing import Any
1✔
18

19
from qiskit.circuit import QuantumCircuit
1✔
20
from qiskit.circuit.library import GroverOperator
1✔
21
from qiskit.quantum_info import Statevector
1✔
22

23

24
class AmplificationProblem:
1✔
25
    """The amplification problem is the input to amplitude amplification algorithms, like Grover.
26

27
    This class contains all problem-specific information required to run an amplitude amplification
28
    algorithm. It minimally contains the Grover operator. It can further hold some post processing
29
    on the optimal bitstring.
30
    """
31

32
    def __init__(
1✔
33
        self,
34
        oracle: QuantumCircuit | Statevector,
35
        state_preparation: QuantumCircuit | None = None,
36
        grover_operator: QuantumCircuit | None = None,
37
        post_processing: Callable[[str], Any] | None = None,
38
        objective_qubits: int | list[int] | None = None,
39
        is_good_state: Callable[[str], bool] | list[int] | list[str] | Statevector | None = None,
40
    ) -> None:
41
        r"""
42
        Args:
43
            oracle: The oracle reflecting about the bad states.
44
            state_preparation: A circuit preparing the input state, referred to as
45
                :math:`\mathcal{A}`. If None, a layer of Hadamard gates is used.
46
            grover_operator: The Grover operator :math:`\mathcal{Q}` used as unitary in the
47
                phase estimation circuit. If None, this operator is constructed from the ``oracle``
48
                and ``state_preparation``.
49
            post_processing: A mapping applied to the most likely bitstring.
50
            objective_qubits: If set, specifies the indices of the qubits that should be measured.
51
                If None, all qubits will be measured. The ``is_good_state`` function will be
52
                applied on the measurement outcome of these qubits.
53
            is_good_state: A function to check whether a string represents a good state. By default
54
                if the ``oracle`` argument has an ``evaluate_bitstring`` method (currently only
55
                provided by the :class:`~qiskit.circuit.library.PhaseOracle` class) this will be
56
                used, otherwise this kwarg is required and **must** be specified.
57
        """
58
        self._oracle = oracle
1✔
59
        self._state_preparation = state_preparation
1✔
60
        self._grover_operator = grover_operator
1✔
61
        self._post_processing = post_processing
1✔
62
        self._objective_qubits = objective_qubits
1✔
63
        if is_good_state is not None:
1✔
64
            self._is_good_state = is_good_state
1✔
65
        elif hasattr(oracle, "evaluate_bitstring"):
1✔
66
            self._is_good_state = oracle.evaluate_bitstring
×
67
        else:
68
            self._is_good_state = None
1✔
69

70
    @property
1✔
71
    def oracle(self) -> QuantumCircuit | Statevector:
1✔
72
        """Return the oracle.
73

74
        Returns:
75
            The oracle.
76
        """
77
        return self._oracle
1✔
78

79
    @oracle.setter
1✔
80
    def oracle(self, oracle: QuantumCircuit | Statevector) -> None:
1✔
81
        """Set the oracle.
82

83
        Args:
84
            oracle: The oracle.
85
        """
86
        self._oracle = oracle
×
87

88
    @property
1✔
89
    def state_preparation(self) -> QuantumCircuit:
1✔
90
        r"""Get the state preparation operator :math:`\mathcal{A}`.
91

92
        Returns:
93
            The :math:`\mathcal{A}` operator as `QuantumCircuit`.
94
        """
95
        if self._state_preparation is None:
1✔
96
            state_preparation = QuantumCircuit(self.oracle.num_qubits)
1✔
97
            state_preparation.h(state_preparation.qubits)
1✔
98
            return state_preparation
1✔
99

100
        return self._state_preparation
1✔
101

102
    @state_preparation.setter
1✔
103
    def state_preparation(self, state_preparation: QuantumCircuit | None) -> None:
1✔
104
        r"""Set the :math:`\mathcal{A}` operator. If None, a layer of Hadamard gates is used.
105

106
        Args:
107
            state_preparation: The new :math:`\mathcal{A}` operator or None.
108
        """
109
        self._state_preparation = state_preparation
×
110

111
    @property
1✔
112
    def post_processing(self) -> Callable[[str], Any]:
1✔
113
        """Apply post processing to the input value.
114

115
        Returns:
116
            A handle to the post processing function. Acts as identity by default.
117
        """
118
        if self._post_processing is None:
1✔
119
            return lambda x: x
1✔
120

121
        return self._post_processing
×
122

123
    @post_processing.setter
1✔
124
    def post_processing(self, post_processing: Callable[[str], Any]) -> None:
1✔
125
        """Set the post processing function.
126

127
        Args:
128
            post_processing: A handle to the post processing function.
129
        """
130
        self._post_processing = post_processing
×
131

132
    @property
1✔
133
    def objective_qubits(self) -> list[int]:
1✔
134
        """The indices of the objective qubits.
135

136
        Returns:
137
            The indices of the objective qubits as list of integers.
138
        """
139
        if self._objective_qubits is None:
1✔
140
            return list(range(self.oracle.num_qubits))
1✔
141

142
        if isinstance(self._objective_qubits, int):
×
143
            return [self._objective_qubits]
×
144

145
        return self._objective_qubits
×
146

147
    @objective_qubits.setter
1✔
148
    def objective_qubits(self, objective_qubits: int | list[int] | None) -> None:
1✔
149
        """Set the objective qubits.
150

151
        Args:
152
            objective_qubits: The indices of the qubits that should be measured.
153
                If None, all qubits will be measured. The ``is_good_state`` function will be
154
                applied on the measurement outcome of these qubits.
155
        """
156
        self._objective_qubits = objective_qubits
×
157

158
    @property
1✔
159
    def is_good_state(self) -> Callable[[str], bool]:
1✔
160
        """Check whether a provided bitstring is a good state or not.
161

162
        Returns:
163
            A callable that takes in a bitstring and returns True if the measurement is a good
164
            state, False otherwise.
165
        """
166
        if (self._is_good_state is None) or callable(self._is_good_state):
1✔
167
            return self._is_good_state  # returns None if no is_good_state arg has been set
1✔
168
        elif isinstance(self._is_good_state, list):
1✔
169
            if all(isinstance(good_bitstr, str) for good_bitstr in self._is_good_state):
1✔
170
                return lambda bitstr: bitstr in self._is_good_state
1✔
171
            else:
172
                return lambda bitstr: all(
1✔
173
                    bitstr[good_index] == "1" for good_index in self._is_good_state
174
                )
175

176
        return lambda bitstr: bitstr in self._is_good_state.probabilities_dict()
1✔
177

178
    @is_good_state.setter
1✔
179
    def is_good_state(
1✔
180
        self, is_good_state: Callable[[str], bool] | list[int] | list[str] | Statevector
181
    ) -> None:
182
        """Set the ``is_good_state`` function.
183

184
        Args:
185
            is_good_state: A function to determine whether a bitstring represents a good state.
186
        """
187
        self._is_good_state = is_good_state
×
188

189
    @property
1✔
190
    def grover_operator(self) -> QuantumCircuit | None:
1✔
191
        r"""Get the :math:`\mathcal{Q}` operator, or Grover operator.
192

193
        If the Grover operator is not set, we try to build it from the :math:`\mathcal{A}` operator
194
        and `objective_qubits`. This only works if `objective_qubits` is a list of integers.
195

196
        Returns:
197
            The Grover operator, or None if neither the Grover operator nor the
198
            :math:`\mathcal{A}` operator is  set.
199
        """
200
        if self._grover_operator is None:
1✔
201
            return GroverOperator(self.oracle, self.state_preparation)
1✔
202
        return self._grover_operator
1✔
203

204
    @grover_operator.setter
1✔
205
    def grover_operator(self, grover_operator: QuantumCircuit | None) -> None:
1✔
206
        r"""Set the :math:`\mathcal{Q}` operator.
207

208
        If None, this operator is constructed from the ``oracle`` and ``state_preparation``.
209

210
        Args:
211
            grover_operator: The new :math:`\mathcal{Q}` operator or None.
212
        """
213
        self._grover_operator = grover_operator
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc