diff --git a/qiskit/circuit/classicalfunction/__init__.py b/qiskit/circuit/classicalfunction/__init__.py index 0f2a7b9ead52..6e65d39d2e77 100644 --- a/qiskit/circuit/classicalfunction/__init__.py +++ b/qiskit/circuit/classicalfunction/__init__.py @@ -91,12 +91,6 @@ def grover_oracle(a: Int1, b: Int1, c: Int1, d: Int1) -> Int1: """ -from qiskit.utils.optionals import HAS_TWEEDLEDUM - -HAS_TWEEDLEDUM.require_now("classical function oracles") - -# pylint: disable=wrong-import-position - from .classicalfunction import ClassicalFunction from .exceptions import ( ClassicalFunctionParseError, diff --git a/qiskit/circuit/classicalfunction/boolean_expression.py b/qiskit/circuit/classicalfunction/boolean_expression.py index 79e7ede087fd..1ed820058b18 100644 --- a/qiskit/circuit/classicalfunction/boolean_expression.py +++ b/qiskit/circuit/classicalfunction/boolean_expression.py @@ -15,13 +15,12 @@ from os.path import basename, isfile from typing import Callable, Optional -from tweedledum import BitVec, BoolFunction # pylint: disable=import-error -from tweedledum.synthesis import pkrm_synth # pylint: disable=import-error - from qiskit.circuit import QuantumCircuit +from qiskit.utils.optionals import HAS_TWEEDLEDUM from .classical_element import ClassicalElement +@HAS_TWEEDLEDUM.require_in_instance class BooleanExpression(ClassicalElement): """The Boolean Expression gate.""" @@ -35,6 +34,8 @@ def __init__(self, expression: str, name: str = None, var_order: list = None) -> (default: by appearance) """ + from tweedledum import BoolFunction # pylint: disable=import-error + self._tweedledum_bool_expression = BoolFunction.from_expression( expression, var_order=var_order ) @@ -57,6 +58,8 @@ def simulate(self, bitstring: str) -> bool: Returns: bool: result of the evaluation. """ + from tweedledum import BitVec # pylint: disable=import-error + bits = [] for bit in bitstring: bits.append(BitVec(1, bit)) @@ -85,6 +88,7 @@ def synth( if synthesizer is None: from .utils import tweedledum2qiskit # Avoid an import cycle + from tweedledum.synthesis import pkrm_synth # pylint: disable=import-error truth_table = self._tweedledum_bool_expression.truth_table(output_bit=0) return tweedledum2qiskit(pkrm_synth(truth_table), name=self.name, qregs=qregs) @@ -107,6 +111,8 @@ def from_dimacs_file(cls, filename: str): FileNotFoundError: If filename is not found. """ + from tweedledum import BoolFunction # pylint: disable=import-error + expr_obj = cls.__new__(cls) if not isfile(filename): raise FileNotFoundError("The file %s does not exists." % filename) diff --git a/qiskit/circuit/classicalfunction/classical_function_visitor.py b/qiskit/circuit/classicalfunction/classical_function_visitor.py index 1b882ec628cb..dfe8b956b092 100644 --- a/qiskit/circuit/classicalfunction/classical_function_visitor.py +++ b/qiskit/circuit/classicalfunction/classical_function_visitor.py @@ -17,11 +17,11 @@ import ast import _ast -from tweedledum.classical import LogicNetwork # pylint: disable=import-error - +from qiskit.utils.optionals import HAS_TWEEDLEDUM from .exceptions import ClassicalFunctionParseError, ClassicalFunctionCompilerTypeError +@HAS_TWEEDLEDUM.require_in_instance class ClassicalFunctionVisitor(ast.NodeVisitor): """Node visitor as defined in https://docs.python.org/3/library/ast.html#ast.NodeVisitor""" @@ -58,6 +58,8 @@ def visit_FunctionDef(self, node): # Extend scope with the decorator's names scope.update({decorator.id: ("decorator", None) for decorator in node.decorator_list}) + from tweedledum.classical import LogicNetwork # pylint: disable=import-error + self.scopes.append(scope) self._network = LogicNetwork() self.extend_scope(node.args) diff --git a/qiskit/circuit/classicalfunction/classicalfunction.py b/qiskit/circuit/classicalfunction/classicalfunction.py index dae3449db225..eaa37e4c4111 100644 --- a/qiskit/circuit/classicalfunction/classicalfunction.py +++ b/qiskit/circuit/classicalfunction/classicalfunction.py @@ -15,18 +15,17 @@ import ast from typing import Callable, Optional -from tweedledum.classical import simulate # pylint: disable=import-error -from tweedledum.synthesis import pkrm_synth # pylint: disable=import-error - from qiskit.circuit import QuantumCircuit, QuantumRegister from qiskit.exceptions import QiskitError +from qiskit.utils.optionals import HAS_TWEEDLEDUM from .classical_element import ClassicalElement from .classical_function_visitor import ClassicalFunctionVisitor from .utils import tweedledum2qiskit +@HAS_TWEEDLEDUM.require_in_instance class ClassicalFunction(ClassicalElement): - """Represent a classical function function and its logic network.""" + """Represent a classical function and its logic network.""" def __init__(self, source, name=None): """Creates a ``ClassicalFunction`` from Python source code in ``source``. @@ -107,6 +106,8 @@ def simulate(self, bitstring: str) -> bool: Returns: bool: result of the evaluation. """ + from tweedledum.classical import simulate # pylint: disable=import-error + return simulate(self._network, bitstring) def simulate_all(self): @@ -126,6 +127,8 @@ def simulate_all(self): @property def truth_table(self): """Returns (and computes) the truth table""" + from tweedledum.classical import simulate # pylint: disable=import-error + if self._truth_table is None: self._truth_table = simulate(self._network) return self._truth_table @@ -153,6 +156,8 @@ def synth( if synthesizer: return synthesizer(self) + from tweedledum.synthesis import pkrm_synth # pylint: disable=import-error + return tweedledum2qiskit(pkrm_synth(self.truth_table[0]), name=self.name, qregs=qregs) def _define(self): diff --git a/qiskit/circuit/classicalfunction/utils.py b/qiskit/circuit/classicalfunction/utils.py index c949aae5984f..1ef523cae493 100644 --- a/qiskit/circuit/classicalfunction/utils.py +++ b/qiskit/circuit/classicalfunction/utils.py @@ -12,9 +12,7 @@ """Internal utils for Classical Function Compiler""" -from tweedledum.ir import Qubit # pylint: disable=import-error -from tweedledum.passes import parity_decomp # pylint: disable=import-error - +from qiskit.utils.optionals import HAS_TWEEDLEDUM from qiskit.circuit import QuantumCircuit from qiskit.circuit.library.standard_gates import ( @@ -42,6 +40,7 @@ } +@HAS_TWEEDLEDUM.require_in_call def _convert_tweedledum_operator(op): base_gate = _QISKIT_OPS.get(op.kind()) if base_gate is None: @@ -52,6 +51,8 @@ def _convert_tweedledum_operator(op): # TODO: need to deal with cbits too! if op.num_controls() > 0: + from tweedledum.ir import Qubit # pylint: disable=import-error + qubits = op.qubits() ctrl_state = "" for qubit in qubits[: op.num_controls()]: @@ -60,6 +61,7 @@ def _convert_tweedledum_operator(op): return base_gate() +@HAS_TWEEDLEDUM.require_in_call def tweedledum2qiskit(tweedledum_circuit, name=None, qregs=None): """Converts a `Tweedledum `_ circuit into a Qiskit circuit. @@ -81,6 +83,8 @@ def tweedledum2qiskit(tweedledum_circuit, name=None, qregs=None): else: qiskit_qc = QuantumCircuit(tweedledum_circuit.num_qubits(), name=name) + from tweedledum.passes import parity_decomp # pylint: disable=import-error + for instruction in parity_decomp(tweedledum_circuit): gate = _convert_tweedledum_operator(instruction) qubits = [qubit.uid() for qubit in instruction.qubits()]