Repository: Qiskit/qiskit

Issue:
Circuit widths should be checked before compiling for backend
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues to confirm this idea does not exist. -->

### What is the expected enhancement?
Since we allow fior different width circuits in compile / transpile the width of the circuits should be validated to fit on the backend that they are being compiled for BEFORE actually being compiled. This prevents compiling many circuits only to have an exception thrown because a later one is not compatible with the backend. 




Discussion:
Hi, I'm interested in taking on this issue. Just a few questions to clarify some things. It looks like with the 0.9 Qiskit release the new way to create your qobj will be with `qiskit.compiler.transpile()`, and then `qiskit.tools.compile()` will eventually be removed. Am I safe to assume that this would mainly just be an addition to `transpile()`? It also looks like the code in `transpile()` will be changed, as noted by the comment stating the current code "is a hack while we are still using the old transpiler", so should I hold off on any additions until the code is updated?
Hi @mstypulk, great!

I would say wait until #2166 is merged, as it extensively touches the same files you would be working with.

Yes, you should modify the `transpile()` function. In #2166 this function moves under `qiskit.compiler.transpile()`. 

Iniside this function, you have a list of `circuits` that are being transpiled, and a list of `coupling_map`s that are targeted (after some parsing is done -- this is a list of either `CouplingMap` objects, or `None`). The former determines the width (number of virtual qubits), the latter the number of physical qubits. You can do a simple compatibility check there. 

Basically the `circuits` list and the `coupling_map` list must be element-wise compatible.
Hi @ajavadia,

I've been working on this, and just had a quick question. After the parsing is done, if the elements of the list of `coupling_map`s are `None`, are we still carrying out a check of virtual vs physical qubits? If so, would we do so by checking the number of virtual qubits from `circuits` against the number of physical qubits which can be retrieved from `backend.configuration().n_qubits`? 

Would this be an acceptable way of doing this?  

Resolving patch:
diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py
--- a/qiskit/compiler/transpile.py
+++ b/qiskit/compiler/transpile.py
@@ -22,6 +22,7 @@
 from qiskit.pulse import Schedule
 from qiskit.circuit.quantumregister import Qubit
 from qiskit import user_config
+from qiskit.transpiler.exceptions import TranspilerError
 
 
 def transpile(circuits,
@@ -142,7 +143,18 @@ def transpile(circuits,
                                               backend_properties, initial_layout,
                                               seed_transpiler, optimization_level,
                                               pass_manager)
-
+    # Check circuit width against number of qubits in coupling_map(s)
+    coupling_maps_list = list(config.coupling_map for config in transpile_configs)
+    for circuit, parsed_coupling_map in zip(circuits, coupling_maps_list):
+        # If coupling_map is not None
+        if isinstance(parsed_coupling_map, CouplingMap):
+            n_qubits = len(circuit.qubits)
+            max_qubits = parsed_coupling_map.size()
+            if n_qubits > max_qubits:
+                raise TranspilerError('Number of qubits ({}) '.format(n_qubits) +
+                                      'in {} '. format(circuit.name) +
+                                      'is greater than maximum ({}) '.format(max_qubits) +
+                                      'in the coupling_map')
     # Transpile circuits in parallel
     circuits = parallel_map(_transpile_circuit, list(zip(circuits, transpile_configs)))
 


Test patch:
diff --git a/test/python/compiler/test_transpiler.py b/test/python/compiler/test_transpiler.py
--- a/test/python/compiler/test_transpiler.py
+++ b/test/python/compiler/test_transpiler.py
@@ -29,6 +29,7 @@
 from qiskit.transpiler.passes import BarrierBeforeFinalMeasurements, CXDirection
 from qiskit.transpiler import Layout, CouplingMap
 from qiskit.circuit import Parameter
+from qiskit.transpiler.exceptions import TranspilerError
 
 
 class TestTranspile(QiskitTestCase):
@@ -589,3 +590,15 @@ def test_basis_subset(self):
         dag_circuit = circuit_to_dag(circuit)
         resources_after = dag_circuit.count_ops()
         self.assertEqual({'u3': 1}, resources_after)
+
+    def test_check_circuit_width(self):
+        """Verify transpilation of circuit with virtual qubits greater than
+        physical qubits raises error"""
+        cmap = [[1, 0], [1, 2], [2, 3], [4, 3], [4, 10], [5, 4],
+                [5, 6], [5, 9], [6, 8], [7, 8], [9, 8], [9, 10],
+                [11, 3], [11, 10], [11, 12], [12, 2], [13, 1], [13, 12]]
+
+        qc = QuantumCircuit(15, 15)
+
+        with self.assertRaises(TranspilerError):
+            transpile(qc, coupling_map=cmap)