Repository: Qiskit/qiskit

Issue:
Remove ParameterTable import From QFT.inverse
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues to confirm this idea does not exist. -->

### What is the expected enhancement?

Following https://github.com/Qiskit/qiskit-terra/pull/4319#discussion_r417599735 : 

> @mtreinish 1 hour ago Member
>
> Is there a reason this is a run time import?
> @kdk
> kdk 1 hour ago Author Member
> 
> Only because it's a bit of hack (qft shouldn't have to manage it's own parameter table). Looking now though, this could be avoided if we set inverted.data = [] instead of inverted._data = []. I'll take care of that.
@kdk
kdk 1 hour ago Author Member
>
> Never mind, inverted.data = [] fails with AttributeError: can't set attribute. Maybe because BlueprintCircuit overrides the data property but not also the setter?
@Cryoris
Cryoris 44 minutes ago •
Member
> 
> super()._invalidate()
> self._data = []
>
> should work I think, the blueprint circuit resets the parameter table upon _invalidate. (Then also the _invalidate method of QFT can be removed).
>
>Actually, on a second look, the inverse method should probably be added to the BlueprintCircuit to do this inversion. Then inverse would return a BlueprintCircuit instead of a QuantumCircuit. But we can do this after the release, this is not crucial for the functionality.



Discussion:

Resolving patch:
diff --git a/qiskit/circuit/library/basis_change/qft.py b/qiskit/circuit/library/basis_change/qft.py
--- a/qiskit/circuit/library/basis_change/qft.py
+++ b/qiskit/circuit/library/basis_change/qft.py
@@ -82,7 +82,7 @@ def __init__(
         do_swaps: bool = True,
         inverse: bool = False,
         insert_barriers: bool = False,
-        name: str = "QFT",
+        name: Optional[str] = None,
     ) -> None:
         """Construct a new QFT circuit.
 
@@ -94,6 +94,9 @@ def __init__(
             insert_barriers: If True, barriers are inserted as visualization improvement.
             name: The name of the circuit.
         """
+        if name is None:
+            name = "IQFT" if inverse else "QFT"
+
         super().__init__(name=name)
         self._approximation_degree = approximation_degree
         self._do_swaps = do_swaps
@@ -223,14 +226,14 @@ def inverse(self) -> "QFT":
             name = self.name + "_dg"
 
         inverted = self.copy(name=name)
-        inverted._data = []
+        super(QFT, inverted)._invalidate()
 
-        from qiskit.circuit.parametertable import ParameterTable
+        # data consists of the QFT gate only
+        iqft = self._data[0][0].inverse()
+        iqft.name = name
 
-        inverted._parameter_table = ParameterTable()
-
-        for inst, qargs, cargs in reversed(self._data):
-            inverted._append(inst.inverse(), qargs, cargs)
+        inverted._data = []
+        inverted._append(iqft, inverted.qubits, [])
 
         inverted._inverse = not self._inverse
         return inverted


Test patch:
diff --git a/test/python/circuit/library/test_qft.py b/test/python/circuit/library/test_qft.py
--- a/test/python/circuit/library/test_qft.py
+++ b/test/python/circuit/library/test_qft.py
@@ -153,6 +153,20 @@ def test_qft_num_gates(self, num_qubits, approximation_degree, insert_barriers):
             expected = qft.num_qubits if insert_barriers else 0
             self.assertEqual(ops.get("barrier", 0), expected)
 
+    def test_name_after_inverting(self):
+        """Test the name after inverting the QFT is IQFT and not QFT_dg."""
+        iqft = QFT(1).inverse()
+        i2qft = iqft.inverse()
+
+        with self.subTest(msg="inverted once"):
+            self.assertEqual(iqft.name, "IQFT")
+
+        with self.subTest(msg="inverted twice"):
+            self.assertEqual(i2qft.name, "QFT")
+
+        with self.subTest(msg="inverse as kwarg"):
+            self.assertEqual(QFT(1, inverse=True).name, "IQFT")
+
 
 if __name__ == "__main__":
     unittest.main()