Repository: Qiskit/qiskit

Issue:
SabreSwap changes coupling map parameter in place
<!-- ⚠️ 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
- **Python version**: 3.8
- **Operating system**: MacOS

### What is the current behavior?

SabreSwap makes the coupling map symmetric "in place". This affects also SabreLayout indirectly.

### Steps to reproduce the problem

```python
from qiskit import QuantumCircuit
from qiskit.transpiler import PassManager, CouplingMap
from qiskit.transpiler.passes import SabreSwap

from qiskit.test.mock.backends import FakeTenerife

coupling_map = CouplingMap(FakeTenerife().configuration().coupling_map)
print(coupling_map)

passmanager = PassManager(SabreSwap(coupling_map))
result = passmanager.run(QuantumCircuit(1))

print(coupling_map)
```
```
[[1, 0], [2, 0], [2, 1], [3, 2], [3, 4], [4, 2]]
[[1, 0], [2, 0], [2, 1], [3, 2], [3, 4], [4, 2], [0, 1], [0, 2], [1, 2], [2, 3], [4, 3], [2, 4]]
```


### What is the expected behavior?

Do not touch my coupling map! :)

### Suggested solutions

Use a copy.





Discussion:

Resolving patch:
diff --git a/qiskit/transpiler/passes/routing/sabre_swap.py b/qiskit/transpiler/passes/routing/sabre_swap.py
--- a/qiskit/transpiler/passes/routing/sabre_swap.py
+++ b/qiskit/transpiler/passes/routing/sabre_swap.py
@@ -13,7 +13,7 @@
 """Routing via SWAP insertion using the SABRE method from Li et al."""
 
 import logging
-from copy import copy
+from copy import copy, deepcopy
 from itertools import cycle
 import numpy as np
 
@@ -118,7 +118,14 @@ def __init__(self, coupling_map, heuristic='basic', seed=None):
         """
 
         super().__init__()
-        self.coupling_map = coupling_map
+
+        # Assume bidirectional couplings, fixing gate direction is easy later.
+        if coupling_map.is_symmetric:
+            self.coupling_map = coupling_map
+        else:
+            self.coupling_map = deepcopy(coupling_map)
+            self.coupling_map.make_symmetric()
+
         self.heuristic = heuristic
         self.seed = seed
         self.applied_gates = None
@@ -146,9 +153,6 @@ def run(self, dag):
         # Preserve input DAG's name, regs, wire_map, etc. but replace the graph.
         mapped_dag = dag._copy_circuit_metadata()
 
-        # Assume bidirectional couplings, fixing gate direction is easy later.
-        self.coupling_map.make_symmetric()
-
         canonical_register = dag.qregs['q']
         current_layout = Layout.generate_trivial_layout(canonical_register)
 


Test patch:
diff --git a/test/python/transpiler/test_sabre_swap.py b/test/python/transpiler/test_sabre_swap.py
--- a/test/python/transpiler/test_sabre_swap.py
+++ b/test/python/transpiler/test_sabre_swap.py
@@ -84,6 +84,17 @@ def test_lookahead_mode(self):
 
         self.assertEqual(new_qc.num_nonlocal_gates(), 7)
 
+    def test_do_not_change_cm(self):
+        """Coupling map should not change.
+        See https://github.com/Qiskit/qiskit-terra/issues/5675"""
+        cm_edges = [(1, 0), (2, 0), (2, 1), (3, 2), (3, 4), (4, 2)]
+        coupling = CouplingMap(cm_edges)
+
+        passmanager = PassManager(SabreSwap(coupling))
+        _ = passmanager.run(QuantumCircuit(1))
+
+        self.assertEqual(set(cm_edges), set(coupling.get_edges()))
+
 
 if __name__ == '__main__':
     unittest.main()