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

Qiskit / qiskit / 13415421333

19 Feb 2025 02:50PM UTC coverage: 88.855% (-0.03%) from 88.882%
13415421333

push

github

web-flow
Deprecate `qiskit.circuit.classicalfunction` (#13786)

* Deprecate `ClassicalFunction`

* Changes according to PR review

* Update releasenotes/notes/deprecate-classical-function-3bf44ef26d984366.yaml

Co-authored-by: Julien Gacon <gaconju@gmail.com>

* Update qiskit/circuit/classicalfunction/__init__.py

Co-authored-by: Julien Gacon <gaconju@gmail.com>

* Update releasenotes/notes/deprecate-classical-function-3bf44ef26d984366.yaml

Co-authored-by: Julien Gacon <gaconju@gmail.com>

* Test fix

* Deprecate `BooleanExpression` as well

* Linting

* Test fix due to deprecation

* Update the release note

* Test message fix

* Update deprecation message and ignore deprecation warning in the non-deprecated PhaseOracle

* Added an explanation on how to create a bit flip oracle from a phase flip oracle

* Fixes according to PR review

* Typo

---------

Co-authored-by: Julien Gacon <gaconju@gmail.com>

0 of 26 new or added lines in 4 files covered. (0.0%)

25 existing lines in 6 files now uncovered.

79122 of 89046 relevant lines covered (88.86%)

352060.74 hits per line

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

0.0
/qiskit/circuit/classicalfunction/classicalfunction.py
1
# This code is part of Qiskit.
2
#
3
# (C) Copyright IBM 2020.
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
"""ClassicalFunction class"""
14

15
import ast
×
16
from typing import Callable, Optional
×
17

NEW
18
from qiskit.utils.deprecation import deprecate_func
×
19
from qiskit.circuit import QuantumCircuit, QuantumRegister
×
20
from qiskit.exceptions import QiskitError
×
21
from qiskit.utils.optionals import HAS_TWEEDLEDUM
×
22
from .classical_element import ClassicalElement
×
23
from .classical_function_visitor import ClassicalFunctionVisitor
×
24
from .utils import tweedledum2qiskit
×
25

26

27
class ClassicalFunction(ClassicalElement):
×
28
    """Represent a classical function and its logic network."""
29

NEW
30
    @HAS_TWEEDLEDUM.require_in_instance
×
NEW
31
    @deprecate_func(
×
32
        since="1.4",
33
        removal_timeline="in Qiskit 2.0",
34
        additional_msg="Use `PhaseOracle` instead, which can be turned into a "
35
        "bit-flip oracle by applying Hadamard gates on the target "
36
        "qubit before and after the instruction, and conditioning."
37
        "the instruction on the target qubit.",
38
    )
UNCOV
39
    def __init__(self, source, name=None):
×
40
        """Creates a ``ClassicalFunction`` from Python source code in ``source``.
41

42
        The code should be a single function with types.
43

44
        Args:
45
            source (str): Python code with type hints.
46
            name (str): Optional. Default: "*classicalfunction*". ClassicalFunction name.
47

48
        Raises:
49
            QiskitError: If source is not a string.
50
        """
51
        if not isinstance(source, str):
×
52
            raise QiskitError("ClassicalFunction needs a source code as a string.")
×
53
        self._ast = ast.parse(source)
×
54
        self._network = None
×
55
        self._scopes = None
×
56
        self._args = None
×
57
        self._truth_table = None
×
58
        super().__init__(
×
59
            name or "*classicalfunction*",
60
            num_qubits=sum(qreg.size for qreg in self.qregs),
61
            params=[],
62
        )
63

64
    def compile(self):
×
65
        """Parses and creates the logical circuit"""
66
        _classical_function_visitor = ClassicalFunctionVisitor()
×
67
        _classical_function_visitor.visit(self._ast)
×
68
        self._network = _classical_function_visitor._network
×
69
        self._scopes = _classical_function_visitor.scopes
×
70
        self._args = _classical_function_visitor.args
×
71
        self.name = _classical_function_visitor.name
×
72

73
    @property
×
74
    def network(self):
×
75
        """Returns the logical network"""
76
        if self._network is None:
×
77
            self.compile()
×
78
        return self._network
×
79

80
    @property
×
81
    def scopes(self):
×
82
        """Returns the scope dict"""
83
        if self._scopes is None:
×
84
            self.compile()
×
85
        return self._scopes
×
86

87
    @property
×
88
    def args(self):
×
89
        """Returns the classicalfunction arguments"""
90
        if self._args is None:
×
91
            self.compile()
×
92
        return self._args
×
93

94
    @property
×
95
    def types(self):
×
96
        """Dumps a list of scopes with their variables and types.
97

98
        Returns:
99
            list(dict): A list of scopes as dicts, where key is the variable name and
100
            value is its type.
101
        """
102
        ret = []
×
103
        for scope in self.scopes:
×
104
            ret.append({k: v[0] for k, v in scope.items()})
×
105
        return ret
×
106

107
    def simulate(self, bitstring: str) -> bool:
×
108
        """Evaluate the expression on a bitstring.
109

110
        This evaluation is done classically.
111

112
        Args:
113
            bitstring: The bitstring for which to evaluate.
114

115
        Returns:
116
            bool: result of the evaluation.
117
        """
118
        from tweedledum.classical import simulate  # pylint: disable=import-error
×
119

120
        return simulate(self._network, bitstring)
×
121

122
    def simulate_all(self):
×
123
        """
124
        Returns a truth table.
125

126
        Returns:
127
            str: a bitstring with a truth table
128
        """
129
        result = []
×
130
        for position in range(2 ** self._network.num_pis()):
×
131
            sim_result = "".join([str(int(tt[position])) for tt in self.truth_table])
×
132
            result.append(sim_result)
×
133

134
        return "".join(reversed(result))
×
135

136
    @property
×
137
    def truth_table(self):
×
138
        """Returns (and computes) the truth table"""
139
        from tweedledum.classical import simulate  # pylint: disable=import-error
×
140

141
        if self._truth_table is None:
×
142
            self._truth_table = simulate(self._network)
×
143
        return self._truth_table
×
144

145
    def synth(
×
146
        self,
147
        registerless: bool = True,
148
        synthesizer: Optional[Callable[[ClassicalElement], QuantumCircuit]] = None,
149
    ) -> QuantumCircuit:
150
        """Synthesis the logic network into a :class:`~qiskit.circuit.QuantumCircuit`.
151

152
        Args:
153
            registerless: Default ``True``. If ``False`` uses the parameter names to create
154
            registers with those names. Otherwise, creates a circuit with a flat quantum register.
155
            synthesizer: Optional. If None tweedledum's pkrm_synth is used.
156

157
        Returns:
158
            QuantumCircuit: A circuit implementing the logic network.
159
        """
160
        if registerless:
×
161
            qregs = None
×
162
        else:
163
            qregs = self.qregs
×
164

165
        if synthesizer:
×
166
            return synthesizer(self)
×
167

168
        from tweedledum.synthesis import pkrm_synth  # pylint: disable=import-error
×
169

170
        return tweedledum2qiskit(pkrm_synth(self.truth_table[0]), name=self.name, qregs=qregs)
×
171

172
    def _define(self):
×
173
        """The definition of the classical function is its synthesis"""
174
        self.definition = self.synth()
×
175

176
    @property
×
177
    def qregs(self):
×
178
        """The list of qregs used by the classicalfunction"""
179
        qregs = [QuantumRegister(1, name=arg) for arg in self.args if self.types[0][arg] == "Int1"]
×
180
        if self.types[0]["return"] == "Int1":
×
181
            qregs.append(QuantumRegister(1, name="return"))
×
182
        return qregs
×
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

© 2026 Coveralls, Inc