Repository: Qiskit/qiskit

Issue:
DAGCircuit.compose does not remap condition bits
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues -->

### Information

- **Qiskit Terra version**: master@ 487b07fb

### What is the current behavior?

During #4454 , it came up that `DAGCircuit.compose` will remap clbits used in classical instructions, but does not always remap clbits used in conditional gates.

### Steps to reproduce the problem

```
>>> qc = qk.QuantumCircuit(3,3)
>>> qc.x(0)
>>> qc.measure([0,1], [0, 1])
>>> qc.x(2).c_if(qc.cregs[0], 1)
>>> qc.measure(2,2)
>>> print(qc)
     ┌───┐┌─┐
q_0: ┤ X ├┤M├──────────
     └┬─┬┘└╥┘
q_1: ─┤M├──╫───────────
      └╥┘  ║  ┌───┐ ┌─┐
q_2: ──╫───╫──┤ X ├─┤M├
       ║   ║  └─┬─┘ └╥┘
       ║   ║ ┌──┴──┐ ║
c_0: ══╬═══╩═╡     ╞═╬═
       ║     │     │ ║
c_1: ══╩═════╡ = 1 ╞═╬═
             │     │ ║
c_2: ════════╡     ╞═╩═
             └─────┘
>>> qk.execute(qc, qk.Aer.get_backend('qasm_simulator')).result().get_counts()
{'101': 1024}
>>> base = qk.QuantumCircuit(3,3)
>>> print(base.compose(qc, clbits=[1,0,2]))
     ┌───┐┌─┐
q_0: ┤ X ├┤M├──────────
     └┬─┬┘└╥┘
q_1: ─┤M├──╫───────────
      └╥┘  ║  ┌───┐ ┌─┐
q_2: ──╫───╫──┤ X ├─┤M├
       ║   ║  └─┬─┘ └╥┘
       ║   ║ ┌──┴──┐ ║
c_0: ══╩═══╬═╡     ╞═╬═
           ║ │     │ ║
c_1: ══════╩═╡ = 1 ╞═╬═
             │     │ ║
c_2: ════════╡     ╞═╩═
             └─────┘
>>> qk.execute(base.compose(qc, clbits=[1,0,2]), qk.Aer.get_backend('qasm_simulator')).result().get_counts()
{'010': 1024}
```


### What is the expected behavior?

Conditional gates in the in the composed circuit should have their conditions updated to match the provided `clbits`. In the example above, the condition should be `= 2` and the output counts should all be `110`.

### Suggested solutions

`DAGCircuit._map_condition` is already called by `DAGCircuit.compose`, but needs to be updated for the possibility that the `wire_map` reorders bits in the classical register used by `condition`.


Discussion:

Resolving patch:
diff --git a/qiskit/dagcircuit/dagcircuit.py b/qiskit/dagcircuit/dagcircuit.py
--- a/qiskit/dagcircuit/dagcircuit.py
+++ b/qiskit/dagcircuit/dagcircuit.py
@@ -31,7 +31,7 @@
 import networkx as nx
 
 from qiskit.circuit.quantumregister import QuantumRegister, Qubit
-from qiskit.circuit.classicalregister import ClassicalRegister
+from qiskit.circuit.classicalregister import ClassicalRegister, Clbit
 from qiskit.circuit.gate import Gate
 from qiskit.dagcircuit.exceptions import DAGCircuitError
 from qiskit.dagcircuit.dagnode import DAGNode
@@ -452,15 +452,25 @@ def _map_condition(self, wire_map, condition):
             condition (tuple or None): (ClassicalRegister,int)
         Returns:
             tuple(ClassicalRegister,int): new condition
+        Raises:
+            DAGCircuitError: if condition register not in wire_map
         """
         if condition is None:
             new_condition = None
         else:
-            # Map the register name, using fact that registers must not be
-            # fragmented by the wire_map (this must have been checked
-            # elsewhere)
-            bit0 = condition[0][0]
-            new_condition = (wire_map.get(bit0, bit0).register, condition[1])
+            # if there is a condition, map the condition bits to the
+            # composed cregs based on the wire_map
+            cond_val = condition[1]
+            new_cond_val = 0
+            new_creg = None
+            for bit in wire_map:
+                if isinstance(bit, Clbit):
+                    new_creg = wire_map[bit].register
+                    if 2**(bit.index) & cond_val:
+                        new_cond_val += 2**(wire_map[bit].index)
+            if new_creg is None:
+                raise DAGCircuitError("Condition registers not found in wire_map.")
+            new_condition = (new_creg, new_cond_val)
         return new_condition
 
     def extend_back(self, dag, edge_map=None):
@@ -525,19 +535,30 @@ def compose(self, other, edge_map=None, qubits=None, clbits=None, front=False, i
                           "Use qubits and clbits args to specify a list of "
                           "self edges to compose onto.", DeprecationWarning,
                           stacklevel=2)
+
+        # number of qubits and clbits must match number in circuit or None
+        identity_qubit_map = dict(zip(other.qubits, self.qubits))
+        identity_clbit_map = dict(zip(other.clbits, self.clbits))
         if qubits is None:
-            qubits = []
+            qubit_map = identity_qubit_map
+        elif len(qubits) != len(other.qubits):
+            raise DAGCircuitError("Number of items in qubits parameter does not"
+                                  " match number of qubits in the circuit.")
+        else:
+            qubit_map = {other.qubits[i]: (self.qubits[q] if isinstance(q, int) else q)
+                         for i, q in enumerate(qubits)}
         if clbits is None:
-            clbits = []
-        qubit_map = {other.qubits[i]: (self.qubits[q] if isinstance(q, int) else q)
-                     for i, q in enumerate(qubits)}
-        clbit_map = {other.clbits[i]: (self.clbits[c] if isinstance(c, int) else c)
-                     for i, c in enumerate(clbits)}
+            clbit_map = identity_clbit_map
+        elif len(clbits) != len(other.clbits):
+            raise DAGCircuitError("Number of items in clbits parameter does not"
+                                  " match number of clbits in the circuit.")
+        else:
+            clbit_map = {other.clbits[i]: (self.clbits[c] if isinstance(c, int) else c)
+                         for i, c in enumerate(clbits)}
         edge_map = edge_map or {**qubit_map, **clbit_map} or None
+
         # if no edge_map, try to do a 1-1 mapping in order
         if edge_map is None:
-            identity_qubit_map = dict(zip(other.qubits, self.qubits))
-            identity_clbit_map = dict(zip(other.clbits, self.clbits))
             edge_map = {**identity_qubit_map, **identity_clbit_map}
 
         # Check the edge_map for duplicate values


Test patch:
diff --git a/test/python/dagcircuit/test_compose.py b/test/python/dagcircuit/test_compose.py
--- a/test/python/dagcircuit/test_compose.py
+++ b/test/python/dagcircuit/test_compose.py
@@ -42,7 +42,8 @@ def setUp(self):
         self.left_qubit4 = qreg2[1]
         self.left_clbit0 = creg[0]
         self.left_clbit1 = creg[1]
-        self.condition = (creg, 3)
+        self.condition1 = (creg, 1)
+        self.condition2 = (creg, 2)
 
     def test_compose_inorder(self):
         """Composing two dags of the same width, default order.
@@ -274,7 +275,7 @@ def test_compose_conditional(self):
                     ┌──┴───┴──┐             └─┬─┘    │    ║ └╥┘
         lqr_1_2: |0>┤ U1(0.1) ├  +         ┌──┴──┐┌──┴──┐ ║  ║
                     └─────────┘     rcr_0: ╡     ╞╡     ╞═╩══╬═
-        lqr_2_0: |0>─────■─────            │ = 3 ││ = 3 │    ║
+        lqr_2_0: |0>─────■─────            │ = 2 ││ = 1 │    ║
                        ┌─┴─┐        rcr_1: ╡     ╞╡     ╞════╩═
         lqr_2_1: |0>───┤ X ├───            └─────┘└─────┘
                        └───┘
@@ -295,7 +296,7 @@ def test_compose_conditional(self):
                     └───┘    └─┬─┘    │   └╥┘ ║
                             ┌──┴──┐┌──┴──┐ ║  ║
         lcr_0: ═════════════╡     ╞╡     ╞═╩══╬═
-                            │ = 3 ││ = 3 │    ║
+                            │ = 1 ││ = 2 │    ║
         lcr_1: ═════════════╡     ╞╡     ╞════╩═
                             └─────┘└─────┘
         """
@@ -303,8 +304,8 @@ def test_compose_conditional(self):
         creg = ClassicalRegister(2, 'rcr')
 
         circuit_right = QuantumCircuit(qreg, creg)
-        circuit_right.x(qreg[1]).c_if(creg, 3)
-        circuit_right.h(qreg[0]).c_if(creg, 3)
+        circuit_right.x(qreg[1]).c_if(creg, 2)
+        circuit_right.h(qreg[0]).c_if(creg, 1)
         circuit_right.measure(qreg, creg)
 
         # permuted subset of qubits and clbits
@@ -317,8 +318,8 @@ def test_compose_conditional(self):
         circuit_composed = dag_to_circuit(dag_left)
 
         circuit_expected = self.circuit_left.copy()
-        circuit_expected.x(self.left_qubit4).c_if(*self.condition)
-        circuit_expected.h(self.left_qubit1).c_if(*self.condition)
+        circuit_expected.x(self.left_qubit4).c_if(*self.condition1)
+        circuit_expected.h(self.left_qubit1).c_if(*self.condition2)
         circuit_expected.measure(self.left_qubit4, self.left_clbit0)
         circuit_expected.measure(self.left_qubit1, self.left_clbit1)