Repository: Qiskit/qiskit

Issue:
transpile fails to count circuit qubits, resulting in LayoutError
### Environment

- **Qiskit Terra version**: 1d844eccae743032c4416fa67069dbc3478144a9
- **Python version**: 3.10.11
- **Operating system**: Arch Linux


### What is happening?

See title.

### How can we reproduce the issue?

```python
from qiskit import QuantumCircuit, QuantumRegister, transpile
from qiskit.circuit import CircuitInstruction
from qiskit.circuit.library import IGate

register = QuantumRegister(2, name="q")
a, b = register
circuit = QuantumCircuit.from_instructions(
    [
        CircuitInstruction(IGate(), (a,)),
        CircuitInstruction(IGate(), (b,)),
    ],
    qubits=register,
)
transpile(circuit, initial_layout=[0, 1])
```
```
---------------------------------------------------------------------------
LayoutError                               Traceback (most recent call last)
<ipython-input-9-6188e3e84229> in <module>
     12     qubits=register,
     13 )
---> 14 transpile(circuit, initial_layout=[0, 1])

~/projects/qiskit-terra/qiskit/compiler/transpiler.py in transpile(circuits, backend, basis_gates, inst_map, coupling_map, backend_properties, initial_layout, layout_method, routing_method, translation_method, scheduling_method, instruction_durations, dt, approximation_degree, timing_constraints, seed_transpiler, optimization_level, callback, output_name, unitary_synthesis_method, unitary_synthesis_plugin_config, target, hls_config, init_method, optimization_method, ignore_backend_supplied_default_methods)
    319         )
    320 
--> 321     unique_transpile_args, shared_args = _parse_transpile_args(
    322         circuits,
    323         backend,

~/projects/qiskit-terra/qiskit/compiler/transpiler.py in _parse_transpile_args(circuits, backend, basis_gates, inst_map, coupling_map, backend_properties, initial_layout, layout_method, routing_method, translation_method, scheduling_method, instruction_durations, dt, approximation_degree, seed_transpiler, optimization_level, callback, output_name, timing_constraints, unitary_synthesis_method, unitary_synthesis_plugin_config, target, hls_config, init_method, optimization_method, ignore_backend_supplied_default_methods)
    565 
    566     basis_gates = _parse_basis_gates(basis_gates, backend)
--> 567     initial_layout = _parse_initial_layout(initial_layout, circuits)
    568     inst_map = _parse_inst_map(inst_map, backend)
    569     coupling_map = _parse_coupling_map(coupling_map, backend)

~/projects/qiskit-terra/qiskit/compiler/transpiler.py in _parse_initial_layout(initial_layout, circuits)
    779     else:
    780         # even if one layout, but multiple circuits, the layout needs to be adapted for each
--> 781         initial_layout = [_layout_from_raw(initial_layout, circ) for circ in circuits]
    782 
    783     return initial_layout

~/projects/qiskit-terra/qiskit/compiler/transpiler.py in <listcomp>(.0)
    779     else:
    780         # even if one layout, but multiple circuits, the layout needs to be adapted for each
--> 781         initial_layout = [_layout_from_raw(initial_layout, circ) for circ in circuits]
    782 
    783     return initial_layout

~/projects/qiskit-terra/qiskit/compiler/transpiler.py in _layout_from_raw(initial_layout, circuit)
    760         elif isinstancelist(initial_layout):
    761             if all(isinstanceint(elem) for elem in initial_layout):
--> 762                 initial_layout = Layout.from_intlist(initial_layout, *circuit.qregs)
    763             elif all(elem is None or isinstance(elem, Qubit) for elem in initial_layout):
    764                 initial_layout = Layout.from_qubit_list(initial_layout, *circuit.qregs)

~/projects/qiskit-terra/qiskit/transpiler/layout.py in from_intlist(int_list, *qregs)
    322         # Check if list is too short to cover all qubits
    323         if len(int_list) != num_qubits:
--> 324             raise LayoutError(
    325                 f"Integer list length ({len(int_list)}) must equal number of qubits "
    326                 f"in circuit ({num_qubits}): {int_list}."

LayoutError: 'Integer list length (2) must equal number of qubits in circuit (0): [0, 1].'
```

### What should happen?

Should work.

### Any suggestions?

This circuit works:
```python
register = QuantumRegister(2, name="q")
circuit = QuantumCircuit(register)
a, b = register
circuit.id(a)
circuit.id(b)
```


Discussion:

Resolving patch:
diff --git a/qiskit/compiler/transpiler.py b/qiskit/compiler/transpiler.py
--- a/qiskit/compiler/transpiler.py
+++ b/qiskit/compiler/transpiler.py
@@ -28,7 +28,6 @@
 from qiskit import user_config
 from qiskit.circuit.quantumcircuit import QuantumCircuit
 from qiskit.circuit.quantumregister import Qubit
-from qiskit.converters import isinstanceint, isinstancelist
 from qiskit.dagcircuit import DAGCircuit
 from qiskit.providers.backend import Backend
 from qiskit.providers.models import BackendProperties
@@ -757,16 +756,27 @@ def _parse_initial_layout(initial_layout, circuits):
     def _layout_from_raw(initial_layout, circuit):
         if initial_layout is None or isinstance(initial_layout, Layout):
             return initial_layout
-        elif isinstancelist(initial_layout):
-            if all(isinstanceint(elem) for elem in initial_layout):
-                initial_layout = Layout.from_intlist(initial_layout, *circuit.qregs)
-            elif all(elem is None or isinstance(elem, Qubit) for elem in initial_layout):
-                initial_layout = Layout.from_qubit_list(initial_layout, *circuit.qregs)
-        elif isinstance(initial_layout, dict):
-            initial_layout = Layout(initial_layout)
+        if isinstance(initial_layout, dict):
+            return Layout(initial_layout)
+        # Should be an iterable either of ints or bits/None.
+        specifier = tuple(initial_layout)
+        if all(phys is None or isinstance(phys, Qubit) for phys in specifier):
+            mapping = {phys: virt for phys, virt in enumerate(specifier) if virt is not None}
+            if len(mapping) != circuit.num_qubits:
+                raise TranspilerError(
+                    f"'initial_layout' ({len(mapping)}) and circuit ({circuit.num_qubits}) had"
+                    " different numbers of qubits"
+                )
         else:
-            raise TranspilerError("The initial_layout parameter could not be parsed")
-        return initial_layout
+            if len(specifier) != circuit.num_qubits:
+                raise TranspilerError(
+                    f"'initial_layout' ({len(specifier)}) and circuit ({circuit.num_qubits}) had"
+                    " different numbers of qubits"
+                )
+            if len(specifier) != len(set(specifier)):
+                raise TranspilerError(f"'initial_layout' contained duplicate entries: {specifier}")
+            mapping = {int(phys): virt for phys, virt in zip(specifier, circuit.qubits)}
+        return Layout(mapping)
 
     # multiple layouts?
     if isinstance(initial_layout, list) and any(


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
@@ -627,14 +627,9 @@ def test_wrong_initial_layout(self):
             QuantumRegister(3, "q")[2],
         ]
 
-        with self.assertRaises(TranspilerError) as cm:
+        with self.assertRaisesRegex(TranspilerError, "different numbers of qubits"):
             transpile(qc, backend, initial_layout=bad_initial_layout)
 
-        self.assertEqual(
-            "FullAncillaAllocation: The layout refers to a qubit that does not exist in circuit.",
-            cm.exception.message,
-        )
-
     def test_parameterized_circuit_for_simulator(self):
         """Verify that a parameterized circuit can be transpiled for a simulator backend."""
         qr = QuantumRegister(2, name="qr")
@@ -1616,6 +1611,30 @@ def test_transpile_identity_circuit_no_target(self, opt_level):
         result = transpile(qc, optimization_level=opt_level)
         self.assertEqual(empty_qc, result)
 
+    @data(0, 1, 2, 3)
+    def test_initial_layout_with_loose_qubits(self, opt_level):
+        """Regression test of gh-10125."""
+        qc = QuantumCircuit([Qubit(), Qubit()])
+        qc.cx(0, 1)
+        transpiled = transpile(qc, initial_layout=[1, 0], optimization_level=opt_level)
+        self.assertIsNotNone(transpiled.layout)
+        self.assertEqual(
+            transpiled.layout.initial_layout, Layout({0: qc.qubits[1], 1: qc.qubits[0]})
+        )
+
+    @data(0, 1, 2, 3)
+    def test_initial_layout_with_overlapping_qubits(self, opt_level):
+        """Regression test of gh-10125."""
+        qr1 = QuantumRegister(2, "qr1")
+        qr2 = QuantumRegister(bits=qr1[:])
+        qc = QuantumCircuit(qr1, qr2)
+        qc.cx(0, 1)
+        transpiled = transpile(qc, initial_layout=[1, 0], optimization_level=opt_level)
+        self.assertIsNotNone(transpiled.layout)
+        self.assertEqual(
+            transpiled.layout.initial_layout, Layout({0: qc.qubits[1], 1: qc.qubits[0]})
+        )
+
 
 @ddt
 class TestPostTranspileIntegration(QiskitTestCase):