Repository: Qiskit/qiskit

Issue:
Transpiler pushes gates behind measurements
<!-- ⚠️ 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**: 0.13.0
- **Python version**: 3.7.5
- **Operating system**: MacOS Catalina

### What is the current behavior?

If circuits with measurements are run on real hardware they must be the last operation on the wire/qubit. If the measurement is specified as last operation, but no prior global barrier is added the transpiler might move gates behind these measurements and causes the circuit to fail.

### Steps to reproduce the problem

Transpile the QASM below [1] with the specifications of the singapore backend [2].
Then the transpiled circuit contains the following part:

![Screen Shot 2020-03-05 at 18 16 47](https://user-images.githubusercontent.com/5978796/76095964-80a95b00-5fc5-11ea-8c9c-08b093c90893.png)

### What is the expected behavior?

If measurement are added as final operations, they should remain the final operations.

### Suggested solutions

Possibly check if the measurements are the final operations and apply the transpiler only to the part prior to the measurements.

### Resources for reproducing the problem

[1] QASM:
```qasm
OPENQASM 2.0;
include "qelib1.inc";
qreg q[4];
qreg aux[3];
creg c0[1];
u3(1.51080452689302,0.0,0.0) q[2];
u1(0.0) q[2];
cx q[2],q[1];
u3(1.0354507674742846,0.0,0.0) q[1];
cx q[2],q[1];
u3(1.682873047977714,0.0,0.0) q[1];
cx q[2],q[1];
u1(-0.0) q[1];
cx q[2],q[1];
u1(-0.0) q[1];
cx q[2],q[0];
u3(0.6814046158063359,0.0,0.0) q[0];
cx q[1],q[0];
u3(0.15368907928867048,0.0,0.0) q[0];
cx q[1],q[0];
cx q[2],q[0];
cx q[1],q[0];
u3(0.31774997878994404,0.0,0.0) q[0];
cx q[1],q[0];
u3(1.7092511325680475,0.0,0.0) q[0];
cx q[2],q[0];
u1(-0.0) q[0];
cx q[1],q[0];
u1(-0.0) q[0];
cx q[1],q[0];
cx q[2],q[0];
cx q[1],q[0];
u1(-0.0) q[0];
cx q[1],q[0];
u1(-0.0) q[0];
ry(1.1780972450961724) q[3];
cx q[0],aux[1];
ccx q[1],aux[1],aux[2];
u3(3.141592653589793,0,3.141592653589793) aux[0];
u3(3.141592653589793,0,3.141592653589793) q[2];
u3(3.141592653589793,0,3.141592653589793) aux[2];
ccx q[2],aux[2],aux[0];
u3(3.141592653589793,0,3.141592653589793) q[2];
u3(3.141592653589793,0,3.141592653589793) aux[2];
ccx q[1],aux[1],aux[2];
cx q[0],aux[1];
cu3(-0.5885047295390851,0.0,0.0) aux[0],q[3];
cu3(0.0981359209240381,0,0) aux[0],q[3];
ccx aux[0],q[0],q[3];
cu3(-0.0981359209240381,0,0) aux[0],q[3];
ccx aux[0],q[0],q[3];
cu3(0.1962718418480762,0,0) aux[0],q[3];
ccx aux[0],q[1],q[3];
cu3(-0.1962718418480762,0,0) aux[0],q[3];
ccx aux[0],q[1],q[3];
cu3(0.3925436836961524,0,0) aux[0],q[3];
ccx aux[0],q[2],q[3];
cu3(-0.3925436836961524,0,0) aux[0],q[3];
ccx aux[0],q[2],q[3];
cx q[0],aux[1];
ccx q[1],aux[1],aux[2];
u3(-3.141592653589793,-3.141592653589793,0) aux[2];
u3(-3.141592653589793,-3.141592653589793,0) q[2];
ccx q[2],aux[2],aux[0];
u3(-3.141592653589793,-3.141592653589793,0) aux[2];
u3(-3.141592653589793,-3.141592653589793,0) q[2];
u3(-3.141592653589793,-3.141592653589793,0) aux[0];
ccx q[1],aux[1],aux[2];
cx q[0],aux[1];
measure q[3] -> c0[0]
```

[2] Specs of the singapore backend:
```
cmap = [[0, 1], [1, 0], [1, 2], [1, 6], [2, 1], [2, 3], [3, 2],
        [3, 4], [3, 8], [4, 3], [5, 6], [5, 10], [6, 1], [6, 5],
        [6, 7], [7, 6], [7, 8], [7, 12], [8, 3], [8, 7], [8, 9],
        [9, 8], [9, 14], [10, 5], [10, 11], [11, 10], [11, 12],
        [11, 16], [12, 7], [12, 11], [12, 13], [13, 12], [13, 14],
        [13, 18], [14, 9], [14, 13], [15, 16], [16, 11], [16, 15],
        [16, 17], [17, 16], [17, 18], [18, 13], [18, 17], [18, 19],
        [19, 18]]
basis_gates = ['u1', 'u2', 'u3', 'cx', 'id']
```



Discussion:
I think the root of the problem is that `BarrierBeforeFinalMeasurements` should be over all the qubits, not just those with measure. @kdk has more experience here, what do think?

Adding manually `barrier q, aux;` before the `measure` seems to do the trick.
Think this was caused I think by a change in stochastic swap, but making `BarrierBeforeFinalMeasurements` across all qubits should fix it, and will correspond more closely to the actual device constraint.

Resolving patch:
diff --git a/qiskit/transpiler/passes/utils/barrier_before_final_measurements.py b/qiskit/transpiler/passes/utils/barrier_before_final_measurements.py
--- a/qiskit/transpiler/passes/utils/barrier_before_final_measurements.py
+++ b/qiskit/transpiler/passes/utils/barrier_before_final_measurements.py
@@ -57,7 +57,9 @@ def run(self, dag):
         for creg in dag.cregs.values():
             barrier_layer.add_creg(creg)
 
-        final_qubits = {final_op.qargs[0] for final_op in final_ops}
+        # Add a barrier across all qubits so swap mapper doesn't add a swap
+        # from an unmeasured qubit after a measure.
+        final_qubits = dag.qubits()
 
         barrier_layer.apply_operation_back(
             Barrier(len(final_qubits)), list(final_qubits), [])


Test patch:
diff --git a/test/python/transpiler/test_barrier_before_final_measurements.py b/test/python/transpiler/test_barrier_before_final_measurements.py
--- a/test/python/transpiler/test_barrier_before_final_measurements.py
+++ b/test/python/transpiler/test_barrier_before_final_measurements.py
@@ -159,8 +159,8 @@ def test_two_qregs_to_a_single_creg(self):
     def test_preserve_measure_for_conditional(self):
         """Test barrier is inserted after any measurements used for conditionals
 
-         q0:--[H]--[m]------------     q0:--[H]--[m]---------------
-                    |                             |
+         q0:--[H]--[m]------------     q0:--[H]--[m]-------|-------
+                    |                             |        |
          q1:--------|--[ z]--[m]--  -> q1:--------|--[ z]--|--[m]--
                     |    |    |                   |    |       |
          c0:--------.--[=1]---|---     c0:--------.--[=1]------|---
@@ -182,7 +182,7 @@ def test_preserve_measure_for_conditional(self):
         expected.h(qr0)
         expected.measure(qr0, cr0)
         expected.z(qr1).c_if(cr0, 1)
-        expected.barrier(qr1)
+        expected.barrier(qr0, qr1)
         expected.measure(qr1, cr1)
 
         pass_ = BarrierBeforeFinalMeasurements()