Repository: Qiskit/qiskit

Issue:
intermittent bug in stochastic swap pass
```python
qasm = """OPENQASM 2.0;
include "qelib1.inc";
qreg q[5];
creg c[5];
cx q[4],q[1];
u3(0.771421551875327*pi,1.93195729272833*pi,1.95526496079462*pi) q[2];
cx q[1],q[4];
cx q[3],q[2];
cx q[4],q[1];
u1(0.0680407993035097*pi) q[2];
u3(0.474906730130952*pi,0.679527728632899*pi,1.16361128456302*pi) q[1];
cx q[2],q[3];
cx q[1],q[0];
u3(0.479236620087447*pi,0,0) q[3];
u3(1.65884252662582*pi,0,0) q[1];
cx q[3],q[2];
cx q[0],q[1];
cx q[2],q[0];
cx q[1],q[0];
cx q[3],q[2];
cx q[0],q[1];
cx q[2],q[3];
cx q[1],q[0];
cx q[3],q[2];
cx q[0],q[4];
cx q[1],q[2];
measure q[4] -> c[4];
measure q[0] -> c[0];
measure q[1] -> c[1];
measure q[2] -> c[2];
measure q[3] -> c[3];
"""

from qiskit import QuantumCircuit, execute, transpile, assemble, Aer
from qiskit.transpiler import CouplingMap
from qiskit.visualization import plot_histogram
from qiskit.transpiler import passes
from qiskit.transpiler import PassManager

circ = QuantumCircuit().from_qasm_str(qasm)
backend = Aer.get_backend('qasm_simulator')
coupling_map = [[0, 1], [1, 0], [1, 2], [1, 3], [2, 1], [3, 1], [3, 4], [4, 3]]

stochastic = passes.StochasticSwap(CouplingMap(coupling_map), seed=0)
lookahead = passes.LookaheadSwap(CouplingMap(coupling_map))
basic = passes.BasicSwap(CouplingMap(coupling_map))

pm = PassManager(stochastic)
new_circ = pm.run(circ)

counts_cm = backend.run(assemble(new_circ,shots=10000)).result().get_counts()
counts_no_cm = backend.run(assemble(circ,shots=10000)).result().get_counts()

plot_histogram([counts_cm,counts_no_cm],legend=['coupling_map','no_coupling_map'])
```

![image](https://user-images.githubusercontent.com/8622381/66239363-abfee580-e6c7-11e9-804e-11f3f37b7447.png)


The circuit mapped to coupling map returns different counts vs. original circuit.

This only occurs for some random seeds.


Discussion:
Oddly, running it through `transpile` with `seed_transpiler=0` (or any seed I tried) gives the correct result.
In the instance above, stochastic swap removes the measurement on qubit q3. This is also visible in the shown histogram: after running stochastic swap with the coupling map, every count is 0 where q3 is supposed to be 1. After adding a measurement on qubit q3, the counts are nearly identical.

Running the circuit through transpile does not show this error because the pass BarrierBeforeFinalMeasurements() is always added before any swap pass which seems to stop stochastic swap from removing measurement gates.

I see three possible fixes:
1. The method _mapper in https://github.com/Qiskit/qiskit-terra/blob/00ba08f742fec038d962d96d446186d9aadda83a/qiskit/transpiler/passes/mapping/stochastic_swap.py#L303 could be extended to make sure any removed measurement is added again to the circuit as given by last_edgemap.
2. Debugging and fixing when and why stochastic swap removes measurements.
3. Change nothing and expect developers to always use BarrierBeforeFinalMeasurements() before using any swap pass.

I tend to option 1 or 3 since the method seems to rely on removing measurements as per comment in line 303 and changing this could cause bugs down the road.

What should be done?

We should not always rely on the `BarrierBeforeFinalMeasurement` pass. That is just there to ensure measurements don't creep into the middle of the circuit, because then the circuit cannot run on current hardware. Future hardware can support middle measurements. So the transpiler should produce an equivalent circuit with or without the `BarrierBeforeFinalMeasuremet` pass.

Also, this seems to not be the whole story. The example below fails even with `execute()` -- i.e. when the default level 1 pass manager is invoked, which has inside it the implicit barrier insertion.

```python
qasm="""OPENQASM 2.0;
include "qelib1.inc";
qreg q[5];
creg c[5];
cx q[4],q[1];
u3(0.771421551875327*pi,1.93195729272833*pi,1.95526496079462*pi) q[2];
cx q[1],q[4];
cx q[3],q[2];
cx q[4],q[1];
u1(0.0680407993035097*pi) q[2];
u3(1.7210274485623*pi,0,0) q[3];
u3(0.474906730130952*pi,0.679527728632899*pi,1.16361128456302*pi) q[1];
cx q[2],q[3];
cx q[1],q[0];
u3(0.479236620087447*pi,0,0) q[3];
u3(1.65884252662582*pi,0,0) q[1];
cx q[3],q[2];
cx q[0],q[1];
cx q[1],q[0];
cx q[2],q[0];
cx q[0],q[2];
cx q[2],q[0];
cx q[1],q[0];
cx q[3],q[2];
cx q[0],q[1];
cx q[2],q[3];
cx q[1],q[0];
cx q[3],q[2];
cx q[0],q[4];
cx q[1],q[2];
u3(0.777850970026001*pi,0.585592073798391*pi,1.12646645031497*pi) q[3];
measure q[4] -> c[4];
measure q[0] -> c[0];
measure q[1] -> c[1];
measure q[2] -> c[2];
measure q[3] -> c[3];
"""
from qiskit import QuantumCircuit, execute, IBMQ, Aer
from qiskit.transpiler import CouplingMap
from qiskit.visualization import plot_histogram

backend = Aer.get_backend('qasm_simulator')

circ = QuantumCircuit().from_qasm_str(qasm)

coupling_map = [[0, 1], [1, 0], [1, 2], [1, 3], [2, 1], [3, 1], [3, 4], [4, 3]]

seed_transpiler = 0

couple_job = execute(circ, backend, shots=1000, basis_gates=['u1', 'u2', 'u3', 'cx'], coupling_map=coupling_map, seed_transpiler=seed_transpiler)
no_couple_job = execute(circ, backend, shots=1000, basis_gates=['u1', 'u2', 'u3', 'cx'], seed_transpiler=seed_transpiler)

couple_counts = couple_job.result().get_counts()
no_couple_counts = no_couple_job.result().get_counts()

plot_histogram([couple_counts,no_couple_counts],legend=['coupling_map','no_coupling_map'])
```

![image](https://user-images.githubusercontent.com/8622381/66953865-426ac980-f02d-11e9-9808-1e962e54b2a1.png)

The original fix was to have the swap mapper remove the measurements and then add them back at the end (https://github.com/Qiskit/qiskit-terra/pull/691), i.e. option 1 above.
Fixing the measurements does not seem to be sufficient: in the second instance provided by @ajavadia , an U3 gate on q3 is missing in the transpiled circuit after stochastic swap. The cx gates seem to be okay in both instances, i.e. if the measurement/u3 gate is reintroduced to the erroneously transpiled circuit, the counts are almost identical.

I can have a closer look when I have more time. :-)

Resolving patch:
diff --git a/qiskit/transpiler/passes/mapping/stochastic_swap.py b/qiskit/transpiler/passes/mapping/stochastic_swap.py
--- a/qiskit/transpiler/passes/mapping/stochastic_swap.py
+++ b/qiskit/transpiler/passes/mapping/stochastic_swap.py
@@ -129,13 +129,12 @@ def _layer_permutation(self, layer_partition, layout, qubit_subset,
         trials (int): Number of attempts the randomized algorithm makes.
 
         Returns:
-            Tuple: success_flag, best_circuit, best_depth, best_layout, trivial_flag
+            Tuple: success_flag, best_circuit, best_depth, best_layout
 
         If success_flag is True, then best_circuit contains a DAGCircuit with
         the swap circuit, best_depth contains the depth of the swap circuit,
         and best_layout contains the new positions of the data qubits after the
-        swap circuit has been applied. The trivial_flag is set if the layer
-        has no multi-qubit gates.
+        swap circuit has been applied.
 
         Raises:
             TranspilerError: if anything went wrong.
@@ -235,13 +234,13 @@ def _mapper(self, circuit_graph, coupling_graph, trials=20):
         for i, layer in enumerate(layerlist):
 
             # Attempt to find a permutation for this layer
-            success_flag, best_circuit, best_depth, best_layout, trivial_flag \
+            success_flag, best_circuit, best_depth, best_layout \
                 = self._layer_permutation(layer["partition"], layout,
                                           qubit_subset, coupling_graph,
                                           trials)
             logger.debug("mapper: layer %d", i)
-            logger.debug("mapper: success_flag=%s,best_depth=%s,trivial_flag=%s",
-                         success_flag, str(best_depth), trivial_flag)
+            logger.debug("mapper: success_flag=%s,best_depth=%s",
+                         success_flag, str(best_depth))
 
             # If this fails, try one gate at a time in this layer
             if not success_flag:
@@ -252,29 +251,21 @@ def _mapper(self, circuit_graph, coupling_graph, trials=20):
                 # Go through each gate in the layer
                 for j, serial_layer in enumerate(serial_layerlist):
 
-                    success_flag, best_circuit, best_depth, best_layout, trivial_flag = \
+                    success_flag, best_circuit, best_depth, best_layout = \
                         self._layer_permutation(
                             serial_layer["partition"],
                             layout, qubit_subset,
                             coupling_graph,
                             trials)
                     logger.debug("mapper: layer %d, sublayer %d", i, j)
-                    logger.debug("mapper: success_flag=%s,best_depth=%s,"
-                                 "trivial_flag=%s",
-                                 success_flag, str(best_depth), trivial_flag)
+                    logger.debug("mapper: success_flag=%s,best_depth=%s,",
+                                 success_flag, str(best_depth))
 
                     # Give up if we fail again
                     if not success_flag:
                         raise TranspilerError("swap mapper failed: " +
                                               "layer %d, sublayer %d" % (i, j))
 
-                    # If this layer is only single-qubit gates,
-                    # and we have yet to see multi-qubit gates,
-                    # continue to the next inner iteration
-                    if trivial_flag:
-                        logger.debug("mapper: skip to next sublayer")
-                        continue
-
                     # Update the record of qubit positions
                     # for each inner iteration
                     layout = best_layout
@@ -330,7 +321,7 @@ def _layer_permutation(layer_partition, layout, qubit_subset,
         rng (RandomState): Random number generator.
 
     Returns:
-        Tuple: success_flag, best_circuit, best_depth, best_layout, trivial_flag
+        Tuple: success_flag, best_circuit, best_depth, best_layout
 
     Raises:
         TranspilerError: if anything went wrong.
@@ -364,7 +355,7 @@ def _layer_permutation(layer_partition, layout, qubit_subset,
         logger.debug("layer_permutation: nothing to do")
         circ = DAGCircuit()
         circ.add_qreg(canonical_register)
-        return True, circ, 0, layout, (not bool(gates))
+        return True, circ, 0, layout
 
     # Begin loop over trials of randomized algorithm
     num_qubits = len(layout)
@@ -418,7 +409,7 @@ def _layer_permutation(layer_partition, layout, qubit_subset,
     # trials have failed
     if best_layout is None:
         logger.debug("layer_permutation: failed!")
-        return False, None, None, None, False
+        return False, None, None, None
 
     edgs = best_edges.edges()
     trivial_layout = Layout.generate_trivial_layout(canonical_register)
@@ -431,7 +422,7 @@ def _layer_permutation(layer_partition, layout, qubit_subset,
     # Otherwise, we return our result for this layer
     logger.debug("layer_permutation: success!")
     best_lay = best_layout.to_layout(qregs)
-    return True, best_circuit, best_depth, best_lay, False
+    return True, best_circuit, best_depth, best_lay
 
 
 def regtuple_to_numeric(items, qregs):


Test patch:
diff --git a/test/python/transpiler/test_stochastic_swap.py b/test/python/transpiler/test_stochastic_swap.py
--- a/test/python/transpiler/test_stochastic_swap.py
+++ b/test/python/transpiler/test_stochastic_swap.py
@@ -16,7 +16,7 @@
 
 import unittest
 from qiskit.transpiler.passes import StochasticSwap
-from qiskit.transpiler import CouplingMap
+from qiskit.transpiler import CouplingMap, PassManager
 from qiskit.transpiler.exceptions import TranspilerError
 from qiskit.converters import circuit_to_dag
 from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
@@ -511,6 +511,31 @@ def test_len_cm_vs_dag(self):
         with self.assertRaises(TranspilerError):
             _ = pass_.run(dag)
 
+    def test_single_gates_omitted(self):
+        """Test if single qubit gates are omitted."""
+
+        coupling_map = [[0, 1], [1, 0], [1, 2], [1, 3], [2, 1], [3, 1], [3, 4], [4, 3]]
+        qr = QuantumRegister(5, 'q')
+        cr = ClassicalRegister(5, 'c')
+        circuit = QuantumCircuit(qr, cr)
+        circuit.cx(qr[0], qr[4])
+        circuit.cx(qr[1], qr[2])
+        circuit.u3(1, 1.5, 0.7, qr[3])
+
+        expected = QuantumCircuit(qr, cr)
+        expected.cx(qr[1], qr[2])
+        expected.u3(1, 1.5, 0.7, qr[3])
+        expected.swap(qr[0], qr[1])
+        expected.swap(qr[3], qr[4])
+        expected.cx(qr[1], qr[3])
+
+        expected_dag = circuit_to_dag(expected)
+
+        stochastic = StochasticSwap(CouplingMap(coupling_map), seed=0)
+        after = PassManager(stochastic).run(circuit)
+        after = circuit_to_dag(after)
+        self.assertEqual(expected_dag, after)
+
 
 if __name__ == '__main__':
     unittest.main()