Repository: Qiskit/qiskit

Issue:
StochasticSwap mapper fails when given no initial_layout if qreg does not use all qubits in coupling_map
<!-- ⚠️ 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**: master
- **Python version**: 3.7
- **Operating system**: OSX

### What is the current behavior?
I created a pass manager as follows:
```
pm = qiskit.transpiler.PassManager()
pm.append(Unroller(basis))
pm.append(BarrierBeforeFinalMeasurements())
pm.append(StochasticSwap(coupling, seed=123456))
pm.append(Decompose(SwapGate))
pm.append(CXDirection(coupling))
pm.append(CXCancellation())
pm.append(Unroller(['u1', 'u2', 'u3', 'id', 'cx']))
pm.append(Optimize1qGates())
```
to mimic the default set of passes.  However, when running a circuit through it I get the following error (for a width 5 circuit) in the StochasticSwap:

```
~/Desktop/Github_repos/qiskit-terra/qiskit/transpiler/passes/mapping/stochastic_swap.py in <listcomp>(.0)
    210                     # Loop over edges of coupling graph
    211                     for edge in coupling.get_edges():
--> 212                         qubits = [trial_layout[e] for e in edge]
    213                         # Are the qubits available?
    214                         if qubits[0] in qubit_set and qubits[1] in qubit_set:

~/Desktop/Github_repos/qiskit-terra/qiskit/mapper/_layout.py in __getitem__(self, item)
     55         if isinstance(item, int) and item < len(self) and item not in self:
     56             return None
---> 57         return dict.__getitem__(self, item)
     58 
     59     def __setitem__(self, key, value):

KeyError: 5
```
It seems that this is because the coupling map (in this case a 20q machine) has edges that are outside of the default initial_layout that is generated if no layout is given to the mapper.  This is leading to a KeyError because the register is smaller than the full number of qubits. Indeed, if I run a width 20 circuit, it works without error.

### Steps to reproduce the problem



### What is the expected behavior?



### Suggested solutions





Discussion:

Resolving patch:
diff --git a/qiskit/transpiler/passes/mapping/basic_swap.py b/qiskit/transpiler/passes/mapping/basic_swap.py
--- a/qiskit/transpiler/passes/mapping/basic_swap.py
+++ b/qiskit/transpiler/passes/mapping/basic_swap.py
@@ -16,6 +16,7 @@
 from copy import copy
 
 from qiskit.transpiler._basepasses import TransformationPass
+from qiskit.transpiler.exceptions import TranspilerError
 from qiskit.dagcircuit import DAGCircuit
 from qiskit.mapper import Layout
 from qiskit.extensions.standard import SwapGate
@@ -50,6 +51,10 @@ def run(self, dag):
 
         Returns:
             DAGCircuit: A mapped DAG.
+
+        Raises:
+            TranspilerError: if the coupling map or the layout are not
+            compatible with the DAG
         """
         new_dag = DAGCircuit()
 
@@ -59,6 +64,13 @@ def run(self, dag):
             else:
                 self.initial_layout = Layout.generate_trivial_layout(*dag.qregs.values())
 
+        if len(dag.get_qubits()) != len(self.initial_layout):
+            raise TranspilerError('The layout does not match the amount of qubits in the DAG')
+
+        if len(self.coupling_map.physical_qubits) != len(self.initial_layout):
+            raise TranspilerError(
+                "Mappers require to have the layout to be the same size as the coupling map")
+
         current_layout = copy(self.initial_layout)
 
         for layer in dag.serial_layers():
diff --git a/qiskit/transpiler/passes/mapping/lookahead_swap.py b/qiskit/transpiler/passes/mapping/lookahead_swap.py
--- a/qiskit/transpiler/passes/mapping/lookahead_swap.py
+++ b/qiskit/transpiler/passes/mapping/lookahead_swap.py
@@ -80,23 +80,26 @@ def run(self, dag):
             DAGCircuit: A dag mapped to be compatible with the coupling_map in
                 the property_set.
         Raises:
-            TranspilerError: If the provided DAG has more qubits than are
-                available in the coupling map.
+            TranspilerError: if the coupling map or the layout are not
+            compatible with the DAG
         """
 
         coupling_map = self._coupling_map
         ordered_virtual_gates = list(dag.serial_layers())
 
-        if len(dag.get_qubits()) > len(coupling_map.physical_qubits):
-            raise TranspilerError('DAG contains more qubits than are '
-                                  'present in the coupling map.')
-
         if self.initial_layout is None:
             if self.property_set["layout"]:
                 self.initial_layout = self.property_set["layout"]
             else:
                 self.initial_layout = Layout.generate_trivial_layout(*dag.qregs.values())
 
+        if len(dag.get_qubits()) != len(self.initial_layout):
+            raise TranspilerError('The layout does not match the amount of qubits in the DAG')
+
+        if len(self._coupling_map.physical_qubits) != len(self.initial_layout):
+            raise TranspilerError(
+                "Mappers require to have the layout to be the same size as the coupling map")
+
         mapped_gates = []
         layout = self.initial_layout.copy()
         gates_remaining = ordered_virtual_gates.copy()
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
@@ -21,7 +21,6 @@
 from qiskit.mapper import Layout
 from .barrier_before_final_measurements import BarrierBeforeFinalMeasurements
 
-
 logger = getLogger(__name__)
 
 
@@ -84,6 +83,10 @@ def run(self, dag):
 
         Returns:
             DAGCircuit: A mapped DAG.
+
+        Raises:
+            TranspilerError: if the coupling map or the layout are not
+            compatible with the DAG
         """
 
         if self.initial_layout is None:
@@ -92,6 +95,13 @@ def run(self, dag):
             else:
                 self.initial_layout = Layout.generate_trivial_layout(*dag.qregs.values())
 
+        if len(dag.get_qubits()) != len(self.initial_layout):
+            raise TranspilerError('The layout does not match the amount of qubits in the DAG')
+
+        if len(self.coupling_map.physical_qubits) != len(self.initial_layout):
+            raise TranspilerError(
+                "Mappers require to have the layout to be the same size as the coupling map")
+
         self.input_layout = self.initial_layout.copy()
 
         new_dag = self._mapper(dag, self.coupling_map, trials=self.trials, seed=self.seed)


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
@@ -10,6 +10,7 @@
 import unittest
 from qiskit.transpiler.passes import StochasticSwap
 from qiskit.mapper import CouplingMap, Layout
+from qiskit.transpiler.exceptions import TranspilerError
 from qiskit.converters import circuit_to_dag
 from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
 from qiskit.test import QiskitTestCase
@@ -610,6 +611,46 @@ def test_only_output_cx_and_swaps_in_coupling_map(self):
         for _2q_node in after.get_2q_nodes():
             self.assertIn(set(_2q_node['qargs']), valid_couplings)
 
+    def test_len_coupling_vs_dag(self):
+        """Test error if coupling map and dag are not the same size."""
+
+        coupling = CouplingMap([[0, 1], [1, 2], [2, 3], [3, 4]])
+        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)
+
+        pass_ = StochasticSwap(coupling)
+        with self.assertRaises(TranspilerError):
+            _ = pass_.run(dag)
+
+    def test_len_layout_vs_dag(self):
+        """Test error if the layout and dag are not the same size."""
+
+        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)])
+
+        pass_ = StochasticSwap(coupling, layout)
+        with self.assertRaises(TranspilerError):
+            _ = pass_.run(dag)
+
 
 if __name__ == '__main__':
     unittest.main()