Repository: Qiskit/qiskit

Issue:
StochasticSwap bug
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues -->

### Informations

- **Qiskit Terra version**:
- **Python version**: 0.7.0
- **Operating system**:

### What is the current behavior?
The stochastic swap mapper seems to create a non-equivalent circuit for the following case:

```python
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit import BasicAer, execute
from qiskit.transpiler import PassManager, transpile
from qiskit.transpiler.passes import StochasticSwap
from qiskit.mapper import CouplingMap

coupling = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]
qr = QuantumRegister(7, 'q')
cr = ClassicalRegister(7, 'c')
circuit = QuantumCircuit(qr, cr)
circuit.h(qr[3])
circuit.cx(qr[0], qr[6])
circuit.cx(qr[6], qr[0])
circuit.cx(qr[0], qr[1])
circuit.cx(qr[3], qr[1])
circuit.cx(qr[3], qr[0])
circuit.measure(qr, cr)

simulator = BasicAer.get_backend('qasm_simulator')
coupling_map = CouplingMap(couplinglist=coupling)

pass_manager = PassManager(StochasticSwap(coupling_map=coupling_map))
stochastic_circ = transpile(circuit, simulator, pass_manager=pass_manager)

print(execute(circuit, simulator).result().get_counts())
print(execute(stochastic_circ, simulator).result().get_counts())
```
```
{'0000000': 488, '0001011': 536}
{'0000000': 499, '0001001': 525}
```


Discussion:
Fixing the seed does indeed give differing results.
I run into the same issue while writing #1571. If [this line](https://github.com/Qiskit/qiskit-terra/pull/1571/files#diff-f90b12ed72fd4f413470e60e65140155R160) is changed to 42, the `StochasticSwap` also returns a fully different result (in the key, not in the count)
@nonhermitian how did you fixed the seed?
Via the `seed_mapper` kwarg in execute.
The circuits are non-equivalent (different `counts` dict keys). But also it just does not swap correctly (leaves CNOTs between non-adjacent qubits).

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
@@ -225,12 +225,13 @@ def _layer_permutation(self, layer_partition, layout, qubit_subset,
                                 cost_reduced = True
                                 min_cost = new_cost
                                 optimal_layout = new_layout
-                                optimal_edge = qubits
+                                optimal_edge = [self.initial_layout[q] for q in edge]
+                                optimal_qubits = qubits
 
                     # Were there any good swap choices?
                     if cost_reduced:
-                        qubit_set.remove(optimal_edge[0])
-                        qubit_set.remove(optimal_edge[1])
+                        qubit_set.remove(optimal_qubits[0])
+                        qubit_set.remove(optimal_qubits[1])
                         trial_layout = optimal_layout
                         slice_circuit.apply_operation_back(
                             SwapGate(optimal_edge[0],


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
@@ -533,7 +533,7 @@ def test_congestion(self):
         expected.measure(qr[0], cr[0])
         expected.h(qr[0])
         expected.measure(ar[0], cr[2])
-        expected.swap(ar[1], qr[1])
+        expected.swap(qr[1], ar[1])
         expected.cx(qr[0], qr[1])
         expected.measure(ar[1], cr[3])
         expected.measure(qr[1], cr[1])
@@ -578,6 +578,34 @@ def test_all_single_qubit(self):
         after = pass_.run(dag)
         self.assertEqual(dag, after)
 
+    def test_only_output_cx_and_swaps_in_coupling_map(self):
+        """Test that output DAG contains only 2q gates from the the coupling map."""
+
+        coupling = CouplingMap([[0, 1], [1, 2], [2, 3]])
+        qr = QuantumRegister(4, 'q')
+        cr = ClassicalRegister(4, 'c')
+        circuit = QuantumCircuit(qr, cr)
+        circuit.h(qr[0])
+        circuit.cx(qr[0], qr[1])
+        circuit.cx(qr[0], qr[2])
+        circuit.cx(qr[0], qr[3])
+        circuit.measure(qr, cr)
+        dag = circuit_to_dag(circuit)
+
+        layout = Layout([(QuantumRegister(4, 'q'), 0),
+                         (QuantumRegister(4, 'q'), 1),
+                         (QuantumRegister(4, 'q'), 2),
+                         (QuantumRegister(4, 'q'), 3)])
+
+        pass_ = StochasticSwap(coupling, layout, 20, 5)
+        after = pass_.run(dag)
+
+        valid_couplings = [set([layout[a], layout[b]])
+                           for (a, b) in coupling.get_edges()]
+
+        for _2q_node in after.get_2q_nodes():
+            self.assertIn(set(_2q_node['qargs']), valid_couplings)
+
 
 if __name__ == '__main__':
     unittest.main()