From 2c7190eb9bf245068b520e1096482bd73c86fc79 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Thu, 17 Oct 2024 09:43:28 +0400
Subject: [PATCH 01/34] fix: update connectivity in default transpiler

---
 src/qibo/backends/__init__.py       | 8 ++------
 src/qibo/models/error_mitigation.py | 5 ++---
 tests/test_backends_global.py       | 9 +++++++--
 3 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/src/qibo/backends/__init__.py b/src/qibo/backends/__init__.py
index f666bdcd6c..1f898a890e 100644
--- a/src/qibo/backends/__init__.py
+++ b/src/qibo/backends/__init__.py
@@ -144,12 +144,8 @@ def _default_transpiler(cls):
             and natives is not None
             and connectivity_edges is not None
         ):
-            # only for q{i} naming
-            node_mapping = {q: i for i, q in enumerate(qubits)}
-            edges = [
-                (node_mapping[e[0]], node_mapping[e[1]]) for e in connectivity_edges
-            ]
-            connectivity = nx.Graph(edges)
+            connectivity = nx.Graph(connectivity_edges)
+            connectivity.add_nodes_from(qubits)
 
             return Passes(
                 connectivity=connectivity,
diff --git a/src/qibo/models/error_mitigation.py b/src/qibo/models/error_mitigation.py
index 289cf2b7c7..c6d72e2c09 100644
--- a/src/qibo/models/error_mitigation.py
+++ b/src/qibo/models/error_mitigation.py
@@ -1172,9 +1172,8 @@ def _execute_circuit(circuit, qubit_map, noise_model=None, nshots=10000, backend
     elif backend.name == "qibolab":  # pragma: no cover
         qubits = backend.qubits
         connectivity_edges = backend.connectivity
-        node_mapping = {q: i for i, q in enumerate(qubits)}
-        edges = [(node_mapping[e[0]], node_mapping[e[1]]) for e in connectivity_edges]
-        connectivity = nx.Graph(edges)
+        connectivity = nx.Graph(connectivity_edges)
+        connectivity.add_nodes_from(qubits)
         transpiler = Passes(
             connectivity=connectivity,
             passes=[Custom(initial_map=qubit_map, connectivity=connectivity)],
diff --git a/tests/test_backends_global.py b/tests/test_backends_global.py
index 45f990eb76..8b73583029 100644
--- a/tests/test_backends_global.py
+++ b/tests/test_backends_global.py
@@ -171,8 +171,13 @@ def natives(self):
     _Global._backend = backend
     transpiler = _Global.transpiler()
 
-    assert list(transpiler.connectivity.nodes) == [0, 1, 2, 3, 4]
-    assert list(transpiler.connectivity.edges) == [(0, 1), (1, 2), (2, 3), (3, 4)]
+    assert list(transpiler.connectivity.nodes) == ["A1", "A2", "A3", "A4", "A5"]
+    assert list(transpiler.connectivity.edges) == [
+        ("A1", "A2"),
+        ("A2", "A3"),
+        ("A3", "A4"),
+        ("A4", "A5"),
+    ]
     assert (
         NativeGates.CZ in transpiler.native_gates
         and NativeGates.GPI2 in transpiler.native_gates

From e1e769ab03319e8ea1e8afe4c4ec9115af82c8c7 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Tue, 22 Oct 2024 17:45:49 +0400
Subject: [PATCH 02/34] fix: remove initial_layout & use wire_names & update
 test files

---
 src/qibo/models/circuit.py                   |  31 +-
 src/qibo/transpiler/abstract.py              |  17 +-
 src/qibo/transpiler/optimizer.py             |   7 +-
 src/qibo/transpiler/pipeline.py              |  92 ++---
 src/qibo/transpiler/placer.py                | 195 ++++------
 src/qibo/transpiler/router.py                | 176 ++++-----
 tests/test_models_circuit.py                 |   6 +-
 tests/test_tomography_gate_set_tomography.py |   5 +-
 tests/test_transpiler_optimizer.py           |  10 +-
 tests/test_transpiler_pipeline.py            | 157 ++++----
 tests/test_transpiler_placer.py              | 276 ++++++--------
 tests/test_transpiler_router.py              | 367 +++++++++++--------
 12 files changed, 598 insertions(+), 741 deletions(-)

diff --git a/src/qibo/models/circuit.py b/src/qibo/models/circuit.py
index 9b3916b3ae..b3edcb3006 100644
--- a/src/qibo/models/circuit.py
+++ b/src/qibo/models/circuit.py
@@ -142,9 +142,9 @@ class Circuit:
         accelerators (dict, optional): Dictionary that maps device names to the number of times each
             device will be used. Defaults to ``None``.
         wire_names (list or dict, optional): Names for qubit wires.
-            If ``None``, defaults to (``q0``, ``q1``... ``qn``).
+            If ``None``, defaults to [``q0``, ``q1``... ``q(n-1)``].
             If ``list`` is passed, length of ``list`` must match ``nqubits``.
-            If ``dict`` is passed, the keys should match the default pattern.
+            If ``dict`` is passed, keys should be wire names and values should be qubit indices. Values should be unique and range from 0 to ``nqubits - 1``.
             Defaults to ``None``.
         ndevices (int): Total number of devices. Defaults to ``None``.
         nglobal (int): Base two logarithm of the number of devices. Defaults to ``None``.
@@ -171,13 +171,13 @@ def __init__(
                 f"Number of qubits must be positive but is {nqubits}.",
             )
         self.nqubits = nqubits
-        self.wire_names = wire_names
         self.init_kwargs = {
             "nqubits": nqubits,
             "accelerators": accelerators,
             "density_matrix": density_matrix,
             "wire_names": wire_names,
         }
+        self.wire_names = wire_names
         self.queue = _Queue(nqubits)
         # Keep track of parametrized gates for the ``set_parameters`` method
         self.parametrized_gates = _ParametrizedGates()
@@ -300,10 +300,8 @@ def wire_names(self, wire_names: Union[list, dict]):
                     f"but is {len(wire_names)}.",
                 )
 
-            if any([not isinstance(name, str) for name in wire_names]):
-                raise_error(ValueError, "all wire names must be type ``str``.")
-
-            self._wire_names = wire_names
+            self._wire_names = wire_names.copy()
+            # self._wire_names = wire_names
         elif isinstance(wire_names, dict):
             if len(wire_names.keys()) > self.nqubits:
                 raise_error(
@@ -311,21 +309,25 @@ def wire_names(self, wire_names: Union[list, dict]):
                     "number of elements in the ``wire_names`` dictionary "
                     + "cannot be bigger than ``nqubits``.",
                 )
-
-            if any([not isinstance(name, str) for name in wire_names.keys()]) or any(
-                [not isinstance(name, str) for name in wire_names.values()]
-            ):
+            if not all(isinstance(k, int) for k in wire_names.values()):
                 raise_error(
                     ValueError,
-                    "all keys and values in the ``wire_names`` dictionary must be type ``str``.",
+                    "all values of the ``wire_names`` dictionary must be integers.",
+                )
+            if sorted(wire_names.values()) != list(range(self.nqubits)):
+                raise_error(
+                    ValueError,
+                    "all values of the ``wire_names`` dictionary must be unique integers from 0 to ``nqubits``.",
                 )
 
             self._wire_names = [
-                wire_names.get(f"q{i}", f"q{i}") for i in range(self.nqubits)
+                k for k, _ in sorted(wire_names.items(), key=lambda x: x[1])
             ]
         else:
             self._wire_names = [f"q{i}" for i in range(self.nqubits)]
 
+        self.init_kwargs["wire_names"] = self._wire_names
+
     @property
     def repeated_execution(self):
         return self.has_collapse or (
@@ -406,8 +408,9 @@ def light_cone(self, *qubits):
         qubit_map = {q: i for i, q in enumerate(sorted(qubits))}
         kwargs = dict(self.init_kwargs)
         kwargs["nqubits"] = len(qubits)
+        new_wire_names = [self.wire_names[q] for q in list(sorted(qubits))]
+        kwargs["wire_names"] = new_wire_names
         circuit = self.__class__(**kwargs)
-        circuit.wire_names = [self.wire_names[q] for q in list(sorted(qubits))]
         circuit.add(gate.on_qubits(qubit_map) for gate in reversed(list_of_gates))
         return circuit, qubit_map
 
diff --git a/src/qibo/transpiler/abstract.py b/src/qibo/transpiler/abstract.py
index 439045e72a..e24f7acead 100644
--- a/src/qibo/transpiler/abstract.py
+++ b/src/qibo/transpiler/abstract.py
@@ -1,5 +1,4 @@
 from abc import ABC, abstractmethod
-from typing import Tuple
 
 import networkx as nx
 
@@ -12,14 +11,11 @@ def __init__(self, connectivity: nx.Graph, *args):
         """A placer implements the initial logical-physical qubit mapping"""
 
     @abstractmethod
-    def __call__(self, circuit: Circuit, *args) -> dict:
-        """Find initial qubit mapping
+    def __call__(self, circuit: Circuit, *args):
+        """Find initial qubit mapping. Mapping is saved in the circuit.
 
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be mapped.
-
-        Returns:
-            (dict): dictionary containing the initial logical to physical qubit mapping.
         """
 
 
@@ -29,17 +25,14 @@ def __init__(self, connectivity: nx.Graph, *args):
         """A router implements the mapping of a circuit on a specific hardware."""
 
     @abstractmethod
-    def __call__(
-        self, circuit: Circuit, initial_layout: dict, *args
-    ) -> Tuple[Circuit, dict]:
+    def __call__(self, circuit: Circuit, *args) -> Circuit:
         """Match circuit to hardware connectivity.
 
         Args:
-            circuit (qibo.models.Circuit): circuit to be routed.
-            initial_layout (dict): dictionary containing the initial logical to physical qubit mapping.
+            circuit (:class:`qibo.models.circuit.Circuit`): circuit to be routed.
 
         Returns:
-            (:class:`qibo.models.circuit.Circuit`, dict): routed circuit and dictionary containing the final logical to physical qubit mapping.
+            (:class:`qibo.models.circuit.Circuit`): routed circuit.
         """
 
 
diff --git a/src/qibo/transpiler/optimizer.py b/src/qibo/transpiler/optimizer.py
index 7008957627..2ba05895e3 100644
--- a/src/qibo/transpiler/optimizer.py
+++ b/src/qibo/transpiler/optimizer.py
@@ -27,7 +27,10 @@ def __call__(self, circuit: Circuit) -> Circuit:
             )
         if logical_qubits == physical_qubits:
             return circuit
-        new_circuit = Circuit(physical_qubits)
+        new_wire_names = circuit.wire_names.copy() + [
+            name for name in self.connectivity.nodes if name not in circuit.wire_names
+        ]
+        new_circuit = Circuit(nqubits=physical_qubits, wire_names=new_wire_names)
         for gate in circuit.queue:
             new_circuit.add(gate)
         return new_circuit
@@ -48,7 +51,7 @@ def __init__(self, max_qubits: int = 1):
 
     def __call__(self, circuit: Circuit):
         fused_circuit = circuit.fuse(max_qubits=self.max_qubits)
-        new = circuit.__class__(circuit.nqubits)
+        new = circuit.__class__(nqubits=circuit.nqubits, wire_names=circuit.wire_names)
         for fgate in fused_circuit.queue:
             if isinstance(fgate, gates.FusedGate):
                 new.add(gates.Unitary(fgate.matrix(), *fgate.qubits))
diff --git a/src/qibo/transpiler/pipeline.py b/src/qibo/transpiler/pipeline.py
index a6bf3a7b9d..cdbe2a8567 100644
--- a/src/qibo/transpiler/pipeline.py
+++ b/src/qibo/transpiler/pipeline.py
@@ -10,7 +10,7 @@
 from qibo.transpiler._exceptions import TranspilerPipelineError
 from qibo.transpiler.abstract import Optimizer, Placer, Router
 from qibo.transpiler.optimizer import Preprocessing
-from qibo.transpiler.placer import StarConnectivityPlacer, Trivial, assert_placement
+from qibo.transpiler.placer import StarConnectivityPlacer, assert_placement
 from qibo.transpiler.router import (
     ConnectivityError,
     StarConnectivityRouter,
@@ -28,7 +28,6 @@ def assert_circuit_equivalence(
     original_circuit: Circuit,
     transpiled_circuit: Circuit,
     final_map: dict,
-    initial_map: Optional[dict] = None,
     test_states: Optional[list] = None,
     ntests: int = 3,
 ):
@@ -38,14 +37,11 @@ def assert_circuit_equivalence(
         original_circuit (:class:`qibo.models.circuit.Circuit`): Original circuit.
         transpiled_circuit (:class:`qibo.models.circuit.Circuit`): Transpiled circuit.
         final_map (dict): logical-physical qubit mapping after routing.
-        initial_map (dict, optional): logical_physical qubit mapping before routing.
-            If ``None``, trivial initial map is used. Defauts to ``None``.
         test_states (list, optional): states on which the test is performed.
             If ``None``, ``ntests`` random states will be tested. Defauts to ``None``.
         ntests (int, optional): number of random states tested. Defauts to :math:`3`.
     """
     backend = NumpyBackend()
-    ordering = np.argsort(np.array(list(final_map.values())))
     if transpiled_circuit.nqubits != original_circuit.nqubits:
         raise_error(
             ValueError,
@@ -57,22 +53,26 @@ def assert_circuit_equivalence(
             random_statevector(dims=2**original_circuit.nqubits, backend=backend)
             for _ in range(ntests)
         ]
-    if initial_map is not None:
-        reordered_test_states = []
-        initial_map = np.array(list(initial_map.values()))
-        reordered_test_states = [
-            _transpose_qubits(initial_state, initial_map)
-            for initial_state in test_states
-        ]
-    else:
-        reordered_test_states = test_states
 
-    for i in range(len(test_states)):
+    # original: list = original_circuit.wire_names
+    # transpiled: list = transpiled_circuit.wire_names
+    # initial_map = [0, 1, 2, 3, 4]
+    # initial_map = [original.index(qubit) for qubit in transpiled]
+    # reordered_test_states = []
+    # reordered_test_states = [
+    #     _transpose_qubits(initial_state, initial_map) for initial_state in test_states
+    # ]
+
+    ordering = list(final_map.values())
+
+    for i, state in enumerate(test_states):
         target_state = backend.execute_circuit(
-            original_circuit, initial_state=test_states[i]
+            original_circuit, initial_state=state
         ).state()
         final_state = backend.execute_circuit(
-            transpiled_circuit, initial_state=reordered_test_states[i]
+            # transpiled_circuit, initial_state=reordered_test_states[i]
+            transpiled_circuit,
+            initial_state=state,
         ).state()
         final_state = _transpose_qubits(final_state, ordering)
         fidelity = np.abs(np.dot(np.conj(target_state), final_state))
@@ -99,7 +99,6 @@ def assert_transpiling(
     original_circuit: Circuit,
     transpiled_circuit: Circuit,
     connectivity: nx.Graph,
-    initial_layout: dict,
     final_layout: dict,
     native_gates: NativeGates = NativeGates.default(),
     check_circuit_equivalence=True,
@@ -110,7 +109,6 @@ def assert_transpiling(
         original_circuit (qibo.models.Circuit): circuit before transpiling.
         transpiled_circuit (qibo.models.Circuit): circuit after transpiling.
         connectivity (networkx.Graph): chip qubits connectivity.
-        initial_layout (dict): initial physical-logical qubit mapping.
         final_layout (dict): final physical-logical qubit mapping.
         native_gates (NativeGates): native gates supported by the hardware.
         check_circuit_equivalence (Bool): use simulations to check if the transpiled circuit is the same as the original.
@@ -123,22 +121,17 @@ def assert_transpiling(
     if original_circuit.nqubits != transpiled_circuit.nqubits:
         qubit_matcher = Preprocessing(connectivity=connectivity)
         original_circuit = qubit_matcher(circuit=original_circuit)
-    assert_placement(
-        circuit=original_circuit, layout=initial_layout, connectivity=connectivity
-    )
-    assert_placement(
-        circuit=transpiled_circuit, layout=final_layout, connectivity=connectivity
-    )
+    assert_placement(circuit=original_circuit, connectivity=connectivity)
+    assert_placement(circuit=transpiled_circuit, connectivity=connectivity)
     if check_circuit_equivalence:
         assert_circuit_equivalence(
             original_circuit=original_circuit,
             transpiled_circuit=transpiled_circuit,
-            initial_map=initial_layout,
             final_map=final_layout,
         )
 
 
-def restrict_connectivity_qubits(connectivity: nx.Graph, qubits: list):
+def restrict_connectivity_qubits(connectivity: nx.Graph, qubits: list[str]):
     """Restrict the connectivity to selected qubits.
 
     Args:
@@ -174,14 +167,12 @@ class Passes:
             If ``None``, default transpiler will be used.
             Defaults to ``None``.
         connectivity (:class:`networkx.Graph`, optional): physical qubits connectivity.
-            If ``None``, :class:`` is used.
+            If ``None``, full connectivity is assumed.
             Defaults to ``None``.
         native_gates (:class:`qibo.transpiler.unroller.NativeGates`, optional): native gates.
             Defaults to :math:`qibo.transpiler.unroller.NativeGates.default`.
         on_qubits (list, optional): list of physical qubits to be used.
             If "None" all qubits are used. Defaults to ``None``.
-        int_qubit_name (bool, optional): if `True` the `final_layout` keys are
-            cast to integers.
     """
 
     def __init__(
@@ -190,18 +181,15 @@ def __init__(
         connectivity: nx.Graph = None,
         native_gates: NativeGates = NativeGates.default(),
         on_qubits: list = None,
-        int_qubit_names: bool = False,
     ):
         if on_qubits is not None:
             connectivity = restrict_connectivity_qubits(connectivity, on_qubits)
         self.connectivity = connectivity
         self.native_gates = native_gates
         self.passes = self.default() if passes is None else passes
-        self.initial_layout = None
-        self.int_qubit_names = int_qubit_names
 
     def default(self):
-        """Return the default transpiler pipeline for the required hardware connectivity."""
+        """Return the default star connectivity transpiler pipeline."""
         if not isinstance(self.connectivity, nx.Graph):
             raise_error(
                 TranspilerPipelineError,
@@ -211,9 +199,9 @@ def default(self):
         # preprocessing
         default_passes.append(Preprocessing(connectivity=self.connectivity))
         # default placer pass
-        default_passes.append(StarConnectivityPlacer())
+        default_passes.append(StarConnectivityPlacer(connectivity=self.connectivity))
         # default router pass
-        default_passes.append(StarConnectivityRouter())
+        default_passes.append(StarConnectivityRouter(connectivity=self.connectivity))
         # default unroller pass
         default_passes.append(Unroller(native_gates=self.native_gates))
 
@@ -222,36 +210,20 @@ def default(self):
     def __call__(self, circuit):
         """
         This function returns the compiled circuits and the dictionary mapping
-        physical (keys) to logical (values) qubit. If `int_qubit_name` is `True`
-        each key `i` correspond to the `i-th` qubit in the graph.
+        physical (keys) to logical (values) qubit.
         """
-        final_layout = self.initial_layout = None
+
+        final_layout = None
         for transpiler_pass in self.passes:
             if isinstance(transpiler_pass, Optimizer):
                 transpiler_pass.connectivity = self.connectivity
                 circuit = transpiler_pass(circuit)
             elif isinstance(transpiler_pass, Placer):
                 transpiler_pass.connectivity = self.connectivity
-                if self.initial_layout is None:
-                    self.initial_layout = transpiler_pass(circuit)
-                    final_layout = (
-                        self.initial_layout
-                    )  # This way the final layout will be the same as the initial layout if no router is used
-                else:
-                    raise_error(
-                        TranspilerPipelineError,
-                        "You are defining more than one placer pass.",
-                    )
+                final_layout = transpiler_pass(circuit)
             elif isinstance(transpiler_pass, Router):
                 transpiler_pass.connectivity = self.connectivity
-                if self.initial_layout is not None:
-                    circuit, final_layout = transpiler_pass(
-                        circuit, self.initial_layout
-                    )
-                else:
-                    raise_error(
-                        TranspilerPipelineError, "Use a placement pass before routing."
-                    )
+                circuit, final_layout = transpiler_pass(circuit)
             elif isinstance(transpiler_pass, Unroller):
                 circuit = transpiler_pass(circuit)
             else:
@@ -259,8 +231,6 @@ def __call__(self, circuit):
                     TranspilerPipelineError,
                     f"Unrecognised transpiler pass: {transpiler_pass}",
                 )
-        if self.int_qubit_names and final_layout is not None:
-            final_layout = {int(key[1:]): value for key, value in final_layout.items()}
         return circuit, final_layout
 
     def is_satisfied(self, circuit: Circuit):
@@ -280,7 +250,3 @@ def is_satisfied(self, circuit: Circuit):
             return False
         except DecompositionError:
             return False
-
-    def get_initial_layout(self):
-        """Return initial qubit layout"""
-        return self.initial_layout
diff --git a/src/qibo/transpiler/placer.py b/src/qibo/transpiler/placer.py
index 7944ea81f2..405a21dadf 100644
--- a/src/qibo/transpiler/placer.py
+++ b/src/qibo/transpiler/placer.py
@@ -4,25 +4,24 @@
 
 from qibo import gates
 from qibo.backends import _check_backend_and_local_state
-from qibo.config import log, raise_error
+from qibo.config import raise_error
 from qibo.models import Circuit
 from qibo.transpiler._exceptions import PlacementError
 from qibo.transpiler.abstract import Placer, Router
 from qibo.transpiler.router import _find_connected_qubit
 
 
-def assert_placement(
-    circuit: Circuit, layout: dict, connectivity: nx.Graph = None
-) -> bool:
+def assert_placement(circuit: Circuit, connectivity: nx.Graph):
     """Check if layout is in the correct form and matches the number of qubits of the circuit.
 
     Args:
         circuit (:class:`qibo.models.circuit.Circuit`): Circuit model to check.
-        layout (dict): physical to logical qubit mapping.
+        layout (dict): qubit names.
         connectivity (:class:`networkx.Graph`, optional): Chip connectivity.
             This argument is necessary if the layout is applied to a subset of
             qubits of the original connectivity graph. Defaults to ``None``.
     """
+    layout = circuit.wire_names
     assert_mapping_consistency(layout=layout, connectivity=connectivity)
     if circuit.nqubits > len(layout):
         raise_error(
@@ -37,33 +36,21 @@ def assert_placement(
         )
 
 
-def assert_mapping_consistency(layout: dict, connectivity: nx.Graph = None):
+def assert_mapping_consistency(layout: list, connectivity: nx.Graph):
     """Check if layout is in the correct form.
 
     Args:
-        layout (dict): physical to logical qubit mapping.
+        layout (dict): qubit names.
         connectivity (:class:`networkx.Graph`, optional):  Chip connectivity.
             This argument is necessary if the layout is applied to a subset of
-            qubits of the original connectivity graph. Defaults to ``None``.
+            qubits of the original connectivity graph.
     """
-    values = sorted(layout.values())
-    physical_qubits = list(layout)
-    nodes = (
-        list(range(len(values))) if connectivity is None else list(connectivity.nodes)
-    )
-    ref_keys = (
-        ["q" + str(i) for i in nodes] if isinstance(physical_qubits[0], str) else nodes
-    )
-    if sorted(physical_qubits) != sorted(ref_keys):
+    nodes = list(connectivity.nodes)
+    if sorted(nodes) != sorted(layout):
         raise_error(
             PlacementError,
             "Some physical qubits in the layout may be missing or duplicated.",
         )
-    if values != list(range(len(values))):
-        raise_error(
-            PlacementError,
-            "Some logical qubits in the layout may be missing or duplicated.",
-        )
 
 
 def _find_gates_qubits_pairs(circuit: Circuit):
@@ -99,17 +86,19 @@ class StarConnectivityPlacer(Placer):
              q
 
     Args:
-        connectivity (:class:`networkx.Graph`): chip connectivity, not used for this transpiler.
-        middle_qubit (int, optional): qubit id of the qubit that is in the middle of the star.
+        connectivity (:class:`networkx.Graph`): star connectivity graph.
     """
 
-    def __init__(self, connectivity=None, middle_qubit: int = 2):
-        self.middle_qubit = middle_qubit
-        if connectivity is not None:  # pragma: no cover
-            log.warning(
-                "StarConnectivityRouter does not use the connectivity graph."
-                "The connectivity graph will be ignored."
-            )
+    def __init__(self, connectivity: nx.Graph):
+        self.connectivity = connectivity
+        for node in self.connectivity.nodes:
+            if self.connectivity.degree(node) == 4:
+                self.middle_qubit = node
+            elif self.connectivity.degree(node) != 1:
+                raise_error(
+                    ValueError,
+                    "This connectivity graph is not a star graph.",
+                )
 
     def __call__(self, circuit: Circuit):
         """Apply the transpiler transformation on a given circuit.
@@ -117,14 +106,9 @@ def __call__(self, circuit: Circuit):
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): The original Qibo circuit to transform.
                 Only single qubit gates and two qubits gates are supported by the router.
-
-        Returns:
-            dict: physical to logical qubit mapping.
         """
 
-        # find the number of qubits for hardware circuit
-        nqubits = max(circuit.nqubits, self.middle_qubit + 1)
-        hardware_qubits = list(range(nqubits))
+        middle_qubit_idx = circuit.wire_names.index(self.middle_qubit)
 
         for i, gate in enumerate(circuit.queue):
             if len(gate.qubits) > 2:
@@ -133,118 +117,72 @@ def __call__(self, circuit: Circuit):
                     "Gates targeting more than 2 qubits are not supported",
                 )
             if len(gate.qubits) == 2:
-                if self.middle_qubit not in gate.qubits:
+                if middle_qubit_idx not in gate.qubits:
                     new_middle = _find_connected_qubit(
                         gate.qubits,
                         circuit.queue[i + 1 :],
-                        hardware_qubits,
                         error=PlacementError,
+                        mapping=list(range(circuit.nqubits)),
                     )
-                    hardware_qubits[self.middle_qubit], hardware_qubits[new_middle] = (
-                        new_middle,
-                        self.middle_qubit,
+
+                    (
+                        circuit.wire_names[middle_qubit_idx],
+                        circuit.wire_names[new_middle],
+                    ) = (
+                        circuit.wire_names[new_middle],
+                        circuit.wire_names[middle_qubit_idx],
                     )
                     break
 
-        return dict(zip(["q" + str(i) for i in range(nqubits)], hardware_qubits))
-
 
 class Trivial(Placer):
-    """Place qubits according to the following notation:
-
-    .. math::
-        \\{\\textup{"q0"} : 0, \\textup{"q1"} : 1, ..., \\textup{"qn"} : n}.
-
-    Args:
-        connectivity (networkx.Graph, optional): chip connectivity.
-    """
+    """Place qubits according to the order of the qubit names that the user provides."""
 
     def __init__(self, connectivity: nx.Graph = None):
         self.connectivity = connectivity
 
-    def __call__(self, circuit: Circuit):
+    def __call__(self, circuit: Circuit = None):
         """Find the trivial placement for the circuit.
 
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
-
-        Returns:
-            (dict): physical to logical qubit mapping.
         """
-        if self.connectivity is not None:
-            if self.connectivity.number_of_nodes() != circuit.nqubits:
-                raise_error(
-                    PlacementError,
-                    "The number of nodes of the connectivity graph must match "
-                    + "the number of qubits in the circuit",
-                )
-            trivial_layout = dict(
-                zip(
-                    ["q" + str(i) for i in list(self.connectivity.nodes())],
-                    range(circuit.nqubits),
-                )
-            )
-        else:
-            trivial_layout = dict(
-                zip(
-                    ["q" + str(i) for i in range(circuit.nqubits)],
-                    range(circuit.nqubits),
-                )
-            )
-        return trivial_layout
+        if circuit is None:
+            raise_error(ValueError, "Circuit must be provided.")
+        return
 
 
 class Custom(Placer):
     """Define a custom initial qubit mapping.
 
     Args:
-        map (list or dict): physical to logical qubit mapping.
-            Examples: :math:`[1,2,0]` or
-            :math:`{\\textup{"q0"}: 1, \\textup{"q1"}: 2, \\textup{"q2"}:0}`
-            to assign the physical qubits :math:`\\{0, 1, 2\\}`
-            to the logical qubits :math:`[1, 2, 0]`.
-        connectivity (:class:`networkx.Graph`, optional): chip connectivity.
-            This argument is necessary if the layout applied to a subset of
-            qubits of the original connectivity graph. Defaults to ``None``.
+        map (list or dict): A mapping between physical and logical qubits.
+            - If **dict**, the keys should be physical qubit names, and the values should be the corresponding logical qubit numbers.
+            - If **list**, it should contain logical qubit numbers, arranged in the order of the physical qubits.
     """
 
-    def __init__(self, initial_map: Union[list, dict], connectivity: nx.Graph = None):
-        self.connectivity = connectivity
+    def __init__(self, initial_map: Union[list, dict], connectivity: nx.Graph):
         self.initial_map = initial_map
+        self.connectivity = connectivity
+        if self.initial_map is None:
+            raise_error(ValueError, "Initial mapping must be provided.")
+        if self.connectivity is None:
+            raise_error(ValueError, "Connectivity graph must be provided.")
 
-    def __call__(self, circuit=None):
-        """Return the custom placement if it can be applied to the given circuit (if given).
+    def __call__(self, circuit: Circuit):
+        """Apply the custom placement to the given circuit.
 
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
-
-        Returns:
-            (dict): physical to logical qubit mapping.
         """
         if isinstance(self.initial_map, dict):
-            pass
+            circuit.wire_names = sorted(self.initial_map, key=self.initial_map.get)
         elif isinstance(self.initial_map, list):
-            if self.connectivity is not None:
-                self.initial_map = dict(
-                    zip(
-                        ["q" + str(i) for i in self.connectivity.nodes()],
-                        self.initial_map,
-                    )
-                )
-            else:
-                self.initial_map = dict(
-                    zip(
-                        ["q" + str(i) for i in range(len(self.initial_map))],
-                        self.initial_map,
-                    )
-                )
+            circuit.wire_names = self.initial_map
         else:
             raise_error(TypeError, "Use dict or list to define mapping.")
-        if circuit is not None:
-            assert_placement(circuit, self.initial_map, connectivity=self.connectivity)
-        else:
-            assert_mapping_consistency(self.initial_map, connectivity=self.connectivity)
-        return self.initial_map
+
+        assert_placement(circuit, connectivity=self.connectivity)
 
 
 class Subgraph(Placer):
@@ -260,6 +198,8 @@ class Subgraph(Placer):
 
     def __init__(self, connectivity: nx.Graph):
         self.connectivity = connectivity
+        if self.connectivity is None:
+            raise_error(ValueError, "Connectivity graph must be provided.")
 
     def __call__(self, circuit: Circuit):
         """Find the initial layout of the given circuit using subgraph isomorphism.
@@ -301,9 +241,9 @@ def __call__(self, circuit: Circuit):
             ):
                 break
 
-        sorted_result = dict(sorted(result.mapping.items()))
-
-        return {"q" + str(k): v for k, v in sorted_result.items()}
+        circuit.wire_names = sorted(result.mapping, key=lambda k: result.mapping[k])
+        # sorted_result = dict(sorted(result.mapping.items()))
+        # circuit.wire_names = sorted(sorted_result, key=sorted_result.get)
 
 
 class Random(Placer):
@@ -320,7 +260,7 @@ class Random(Placer):
             initializes a generator with a random seed. Defaults to ``None``.
     """
 
-    def __init__(self, connectivity, samples: int = 100, seed=None):
+    def __init__(self, connectivity: nx.Graph, samples: int = 100, seed=None):
         self.connectivity = connectivity
         self.samples = samples
         self.seed = seed
@@ -338,7 +278,6 @@ def __call__(self, circuit):
         gates_qubits_pairs = _find_gates_qubits_pairs(circuit)
         nodes = self.connectivity.number_of_nodes()
         keys = list(self.connectivity.nodes())
-        dict_keys = ["q" + str(i) for i in keys]
 
         final_mapping = dict(zip(keys, range(nodes)))
         final_graph = nx.relabel_nodes(self.connectivity, final_mapping)
@@ -351,16 +290,17 @@ def __call__(self, circuit):
             cost = self._cost(graph, gates_qubits_pairs)
 
             if cost == 0:
-                final_layout = dict(zip(dict_keys, list(mapping.values())))
-                return dict(sorted(final_layout.items()))
+                final_layout = dict(zip(keys, list(mapping.values())))
+                circuit.wire_names = sorted(final_layout, key=final_layout.get)
+                return
 
             if cost < final_cost:
                 final_graph = graph
                 final_mapping = mapping
                 final_cost = cost
 
-        final_layout = dict(zip(dict_keys, list(final_mapping.values())))
-        return dict(sorted(final_layout.items()))
+        final_layout = dict(zip(keys, list(final_mapping.values())))
+        circuit.wire_names = sorted(final_layout, key=final_layout.get)
 
     def _cost(self, graph: nx.Graph, gates_qubits_pairs: list):
         """
@@ -422,13 +362,11 @@ def __call__(self, circuit: Circuit):
         Returns:
             (dict): physical to logical qubit mapping.
         """
-        initial_placer = Trivial(self.connectivity)
-        initial_placement = initial_placer(circuit=circuit)
         self.routing_algorithm.connectivity = self.connectivity
         new_circuit = self._assemble_circuit(circuit)
-        final_placement = self._routing_step(initial_placement, new_circuit)
+        final_placement = self._routing_step(new_circuit)
 
-        return final_placement
+        # return final_placement
 
     def _assemble_circuit(self, circuit: Circuit):
         """Assemble a single circuit to apply Reverse Traversal placement based on depth.
@@ -461,20 +399,19 @@ def _assemble_circuit(self, circuit: Circuit):
             gates_qubits_pairs.reverse()
         assembled_gates_qubits_pairs += gates_qubits_pairs[0:remainder]
 
-        new_circuit = Circuit(circuit.nqubits)
+        new_circuit = Circuit(circuit.nqubits, wire_names=circuit.wire_names)
         for qubits in assembled_gates_qubits_pairs:
             # As only the connectivity is important here we can replace everything with CZ gates
             new_circuit.add(gates.CZ(qubits[0], qubits[1]))
 
         return new_circuit.invert()
 
-    def _routing_step(self, layout: dict, circuit: Circuit):
+    def _routing_step(self, circuit: Circuit):
         """Perform routing of the circuit.
 
         Args:
-            layout (dict): intial qubit layout.
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be routed.
         """
-        _, final_mapping = self.routing_algorithm(circuit, layout)
+        _, final_mapping = self.routing_algorithm(circuit)
 
         return final_mapping
diff --git a/src/qibo/transpiler/router.py b/src/qibo/transpiler/router.py
index b1aad8fc69..4b8276522d 100644
--- a/src/qibo/transpiler/router.py
+++ b/src/qibo/transpiler/router.py
@@ -6,7 +6,7 @@
 import numpy as np
 
 from qibo import gates
-from qibo.config import log, raise_error
+from qibo.config import raise_error
 from qibo.models import Circuit
 from qibo.transpiler._exceptions import ConnectivityError
 from qibo.transpiler.abstract import Router
@@ -23,19 +23,12 @@ def assert_connectivity(connectivity: nx.Graph, circuit: Circuit):
         circuit (:class:`qibo.models.circuit.Circuit`): circuit model to check.
         connectivity (:class:`networkx.Graph`): chip connectivity.
     """
-    if list(connectivity.nodes) != list(range(connectivity.number_of_nodes())):
-        node_mapping = {node: i for i, node in enumerate(connectivity.nodes)}
-        new_connectivity = nx.Graph()
-        new_connectivity.add_edges_from(
-            [(node_mapping[u], node_mapping[v]) for u, v in connectivity.edges]
-        )
-        connectivity = new_connectivity
+    layout = circuit.wire_names
     for gate in circuit.queue:
         if len(gate.qubits) > 2 and not isinstance(gate, gates.M):
             raise_error(ConnectivityError, f"{gate.name} acts on more than two qubits.")
         if len(gate.qubits) == 2:
-            # physical_qubits = tuple(sorted((circuit.wire_names[gate.qubits[0]], circuit.wire_names[gate.qubits[1]])))
-            physical_qubits = tuple(sorted(gate.qubits))  # for q_i naming
+            physical_qubits = (layout[gate.qubits[0]], layout[gate.qubits[1]])
             if physical_qubits not in connectivity.edges:
                 raise_error(
                     ConnectivityError,
@@ -43,25 +36,6 @@ def assert_connectivity(connectivity: nx.Graph, circuit: Circuit):
                 )
 
 
-def _relabel_connectivity(connectivity, layout):
-    """Relabels the connectivity graph using the passed layout.
-
-    Args:
-        connectivity (nx.Graph): input connectivity.
-        layout (dict): input qubit layout.
-    Returns:
-        (dict) the updated connectivity.
-    """
-    node_mapping = {}
-    layout = dict(
-        sorted(layout.items(), key=lambda item: int(item[0][1:]))
-    )  # for q_i naming
-    for i, node in enumerate(list(layout.keys())):
-        node_mapping[int(node[1:])] = i  # for q_i naming
-    new_connectivity = nx.relabel_nodes(connectivity, node_mapping)
-    return new_connectivity
-
-
 class StarConnectivityRouter(Router):
     """Transforms an arbitrary circuit to one that can be executed on hardware.
 
@@ -76,91 +50,81 @@ class StarConnectivityRouter(Router):
     by adding SWAP gates when needed.
 
     Args:
-        connectivity (:class:`networkx.Graph`): chip connectivity, not used for this transpiler.
-        middle_qubit (int, optional): qubit id of the qubit that is in the middle of the star.
+        connectivity (:class:`networkx.Graph`): star connectivity graph.
     """
 
-    def __init__(self, connectivity=None, middle_qubit: int = 2):
-        self.middle_qubit = middle_qubit
-        if connectivity is not None:  # pragma: no cover
-            log.warning(
-                "StarConnectivityRouter does not use the connectivity graph."
-                "The connectivity graph will be ignored."
-            )
+    def __init__(self, connectivity: nx.Graph):
+        self.connectivity = connectivity
+        for node in self.connectivity.nodes:
+            if self.connectivity.degree(node) == 4:
+                self.middle_qubit = node
+            elif self.connectivity.degree(node) != 1:
+                raise_error(
+                    ValueError,
+                    "This connectivity graph is not a star graph.",
+                )
 
-    def __call__(self, circuit: Circuit, initial_layout: dict):
+    def __call__(self, circuit: Circuit):
         """Apply the transpiler transformation on a given circuit.
 
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): The original Qibo circuit to transform.
                 Only single qubit gates and two qubits gates are supported by the router.
-            initial_layout (dict): initial physical-to-logical qubit mapping,
-                use `qibo.transpiler.placer.StarConnectivityPlacer` for better performance.
-
-        Returns:
-            (:class:`qibo.models.circuit.Circuit`, list): circuit that performs the same operation
-                as the original but respects the hardware connectivity,
-                and list that maps logical to hardware qubits.
         """
 
-        middle_qubit = self.middle_qubit
-        nqubits = max(circuit.nqubits, middle_qubit + 1)
-        # new circuit object that will be compatible with hardware connectivity
-        new = Circuit(nqubits)
-        # list to maps logical to hardware qubits
-        hardware_qubits = list(initial_layout.values())
+        middle_qubit_idx = circuit.wire_names.index(self.middle_qubit)
+        nqubits = circuit.nqubits
+        new = Circuit(nqubits=nqubits, wire_names=circuit.wire_names)
+        l2p = list(range(nqubits))
 
         for i, gate in enumerate(circuit.queue):
-            # map gate qubits to hardware
-            qubits = tuple(hardware_qubits.index(q) for q in gate.qubits)
+            routed_qubits = [l2p[q] for q in gate.qubits]
+
             if isinstance(gate, gates.M):
-                new_gate = gates.M(*qubits, **gate.init_kwargs)
+                new_gate = gates.M(*routed_qubits, **gate.init_kwargs)
                 new_gate.result = gate.result
                 new.add(new_gate)
                 continue
 
-            if len(qubits) > 2:
+            if len(routed_qubits) > 2:
                 raise_error(
                     ConnectivityError,
                     "Gates targeting more than two qubits are not supported.",
                 )
 
-            if len(qubits) == 2 and middle_qubit not in qubits:
+            if len(routed_qubits) == 2 and middle_qubit_idx not in routed_qubits:
                 # find which qubit should be moved
                 new_middle = _find_connected_qubit(
-                    qubits,
+                    routed_qubits,
                     circuit.queue[i + 1 :],
-                    hardware_qubits,
                     error=ConnectivityError,
+                    mapping=l2p,
                 )
-                # update hardware qubits according to the swap
-                hardware_qubits[middle_qubit], hardware_qubits[new_middle] = (
-                    hardware_qubits[new_middle],
-                    hardware_qubits[middle_qubit],
-                )
-                new.add(gates.SWAP(middle_qubit, new_middle))
-                # update gate qubits according to the new swap
-                qubits = tuple(hardware_qubits.index(q) for q in gate.qubits)
+
+                new.add(gates.SWAP(new_middle, middle_qubit_idx))
+                idx1, idx2 = l2p.index(middle_qubit_idx), l2p.index(new_middle)
+                l2p[idx1], l2p[idx2] = l2p[idx2], l2p[idx1]
+
+            routed_qubits = [l2p[q] for q in gate.qubits]
 
             # add gate to the hardware circuit
             if isinstance(gate, gates.Unitary):
                 # gates.Unitary requires matrix as first argument
                 matrix = gate.init_args[0]
-                new.add(gate.__class__(matrix, *qubits, **gate.init_kwargs))
+                new.add(gate.__class__(matrix, *routed_qubits, **gate.init_kwargs))
             else:
-                new.add(gate.__class__(*qubits, **gate.init_kwargs))
-        hardware_qubits_keys = ["q" + str(i) for i in range(5)]
-        return new, dict(zip(hardware_qubits_keys, hardware_qubits))
+                new.add(gate.__class__(*routed_qubits, **gate.init_kwargs))
+        return new, {circuit.wire_names[i]: l2p[i] for i in range(nqubits)}
 
 
-def _find_connected_qubit(qubits, queue, hardware_qubits, error):
+def _find_connected_qubit(qubits, queue, error, mapping):
     """Helper method for :meth:`qibo.transpiler.router.StarConnectivityRouter`
     and :meth:`qibo.transpiler.router.StarConnectivityPlacer`.
 
     Finds which qubit should be mapped to hardware middle qubit
     by looking at the two-qubit gates that follow.
     """
-    possible_qubits = set(qubits)
+    possible_qubits = {qubits[0], qubits[1]}
     for next_gate in queue:
         if len(next_gate.qubits) > 2:
             raise_error(
@@ -168,11 +132,13 @@ def _find_connected_qubit(qubits, queue, hardware_qubits, error):
                 "Gates targeting more than 2 qubits are not supported",
             )
         if len(next_gate.qubits) == 2:
-            possible_qubits &= {hardware_qubits.index(q) for q in next_gate.qubits}
+            possible_qubits &= {
+                mapping[next_gate.qubits[0]],
+                mapping[next_gate.qubits[1]],
+            }
 
-            if not possible_qubits:
+            if len(possible_qubits) == 0:
                 return qubits[0]
-
             if len(possible_qubits) == 1:
                 return possible_qubits.pop()
 
@@ -185,7 +151,6 @@ class CircuitMap:
     Also implements the initial two-qubit block decompositions.
 
     Args:
-        initial_layout (dict): initial physical to logical qubit mapping.
         circuit (:class:`qibo.models.circuit.Circuit`): circuit to be routed.
         blocks (:class:`qibo.transpiler.blocks.CircuitBlocks`, optional): circuit
             block representation. If ``None``, the blocks will be computed from the circuit.
@@ -194,7 +159,6 @@ class CircuitMap:
 
     def __init__(
         self,
-        initial_layout: Optional[dict] = None,
         circuit: Optional[Circuit] = None,
         blocks: Optional[CircuitBlocks] = None,
         temp: Optional[bool] = False,
@@ -204,23 +168,21 @@ def __init__(
         self._temporary = temp
         if self._temporary:
             return
-        elif circuit is None:
+        if circuit is None:
             raise_error(ValueError, "Circuit must be provided.")
-
         if blocks is not None:
             self.circuit_blocks = blocks
         else:
             self.circuit_blocks = CircuitBlocks(circuit, index_names=True)
 
-        self._nqubits = circuit.nqubits
-        self._routed_blocks = CircuitBlocks(Circuit(circuit.nqubits))
+        self.nqubits = circuit.nqubits
+        self._routed_blocks = CircuitBlocks(
+            Circuit(circuit.nqubits, wire_names=circuit.wire_names)
+        )
         self._swaps = 0
 
-        if initial_layout is None:
-            return
-
-        self.wire_names = list(initial_layout.keys())
-        self.physical_to_logical = list(initial_layout.values())
+        self.wire_names = circuit.wire_names.copy()
+        self.physical_to_logical = list(range(self.nqubits))
 
     @property
     def physical_to_logical(self):
@@ -302,7 +264,7 @@ def routed_circuit(self, circuit_kwargs: Optional[dict] = None):
     def final_layout(self):
         """Returns the final physical-logical qubits mapping."""
 
-        return {self.wire_names[i]: self._p2l[i] for i in range(self._nqubits)}
+        return {self.wire_names[i]: self._l2p[i] for i in range(self.nqubits)}
 
     def update(self, logical_swap: tuple):
         """Updates the qubit mapping after applying a ``SWAP``
@@ -384,19 +346,18 @@ def added_swaps(self):
         """Returns the number of SWAP gates added to the circuit during routing."""
         return self.circuit_map._swaps
 
-    def __call__(self, circuit: Circuit, initial_layout: dict):
+    def __call__(self, circuit: Circuit):
         """Circuit connectivity matching.
 
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be matched
                 to hardware connectivity.
-            initial_layout (dict): initial physical-to-logical qubit mapping
 
         Returns:
             (:class:`qibo.models.circuit.Circuit`, dict): circut mapped to hardware topology,
                 and final physical-to-logical qubit mapping.
         """
-        self._preprocessing(circuit=circuit, initial_layout=initial_layout)
+        self._preprocessing(circuit=circuit)
         while self._dag.number_of_nodes() != 0:
             execute_block_list = self._check_execution()
             if execute_block_list is not None:
@@ -405,7 +366,6 @@ def __call__(self, circuit: Circuit, initial_layout: dict):
                 self._find_new_mapping()
 
         circuit_kwargs = circuit.init_kwargs
-        circuit_kwargs["wire_names"] = list(initial_layout.keys())
         routed_circuit = self.circuit_map.routed_circuit(circuit_kwargs=circuit_kwargs)
         if self._final_measurements is not None:
             routed_circuit = self._append_final_measurements(
@@ -490,7 +450,7 @@ def _compute_cost(self, candidate: tuple):
             (list, int): best path to move qubits and qubit meeting point in the path.
         """
         temporary_circuit = CircuitMap(
-            circuit=Circuit(self.circuit_map._nqubits),
+            circuit=Circuit(self.circuit_map.nqubits),
             blocks=deepcopy(self.circuit_map.circuit_blocks),
         )
 
@@ -573,7 +533,7 @@ def _update_front_layer(self):
             node[0] for node in self._dag.nodes(data="layer") if node[1] == 0
         ]
 
-    def _preprocessing(self, circuit: Circuit, initial_layout: dict):
+    def _preprocessing(self, circuit: Circuit):
         """The following objects will be initialised:
             - circuit: class to represent circuit and to perform logical-physical qubit mapping.
             - _final_measurements: measurement gates at the end of the circuit.
@@ -581,14 +541,13 @@ def _preprocessing(self, circuit: Circuit, initial_layout: dict):
 
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be preprocessed.
-            initial_layout (dict): initial physical-to-logical qubit mapping.
         """
-
-        self.connectivity = _relabel_connectivity(self.connectivity, initial_layout)
-
+        self.connectivity = nx.relabel_nodes(
+            self.connectivity, {v: i for i, v in enumerate(circuit.wire_names)}
+        )
         copied_circuit = circuit.copy(deep=True)
         self._final_measurements = self._detach_final_measurements(copied_circuit)
-        self.circuit_map = CircuitMap(initial_layout, copied_circuit)
+        self.circuit_map = CircuitMap(copied_circuit)
         self._dag = _create_dag(self.circuit_map.blocks_logical_qubits_pairs())
         self._update_front_layer()
 
@@ -679,17 +638,16 @@ def __init__(
         self._temp_added_swaps = []
         random.seed(seed)
 
-    def __call__(self, circuit: Circuit, initial_layout: dict):
+    def __call__(self, circuit: Circuit):
         """Route the circuit.
 
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be routed.
-            initial_layout (dict): initial physical to logical qubit mapping.
 
         Returns:
             (:class:`qibo.models.circuit.Circuit`, dict): routed circuit and final layout.
         """
-        self._preprocessing(circuit=circuit, initial_layout=initial_layout)
+        self._preprocessing(circuit=circuit)
         longest_path = np.max(self._dist_matrix)
 
         while self._dag.number_of_nodes() != 0:
@@ -711,7 +669,6 @@ def __call__(self, circuit: Circuit, initial_layout: dict):
                 self._shortest_path_routing()
 
         circuit_kwargs = circuit.init_kwargs
-        circuit_kwargs["wire_names"] = list(initial_layout.keys())
         routed_circuit = self.circuit_map.routed_circuit(circuit_kwargs=circuit_kwargs)
         if self._final_measurements is not None:
             routed_circuit = self._append_final_measurements(
@@ -725,7 +682,7 @@ def added_swaps(self):
         """Returns the number of SWAP gates added to the circuit during routing."""
         return self.circuit_map._swaps
 
-    def _preprocessing(self, circuit: Circuit, initial_layout: dict):
+    def _preprocessing(self, circuit: Circuit):
         """The following objects will be initialised:
             - circuit: class to represent circuit and to perform logical-physical qubit mapping.
             - _final_measurements: measurement gates at the end of the circuit.
@@ -738,14 +695,15 @@ def _preprocessing(self, circuit: Circuit, initial_layout: dict):
 
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be preprocessed.
-            initial_layout (dict): initial physical-to-logical qubit mapping.
         """
 
-        self.connectivity = _relabel_connectivity(self.connectivity, initial_layout)
+        self.connectivity = nx.relabel_nodes(
+            self.connectivity, {v: i for i, v in enumerate(circuit.wire_names)}
+        )
 
         copied_circuit = circuit.copy(deep=True)
         self._final_measurements = self._detach_final_measurements(copied_circuit)
-        self.circuit_map = CircuitMap(initial_layout, copied_circuit)
+        self.circuit_map = CircuitMap(copied_circuit)
         self._dist_matrix = nx.floyd_warshall_numpy(self.connectivity)
         self._dag = _create_dag(self.circuit_map.blocks_logical_qubits_pairs())
         self._memory_map = []
@@ -977,7 +935,7 @@ def _create_dag(gates_qubits_pairs: list):
     dag = nx.DiGraph()
     dag.add_nodes_from(range(len(gates_qubits_pairs)))
 
-    for i in range(len(gates_qubits_pairs)):
+    for i, _ in enumerate(gates_qubits_pairs):
         dag.nodes[i]["qubits"] = gates_qubits_pairs[i]
 
     # Find all successors
@@ -986,7 +944,7 @@ def _create_dag(gates_qubits_pairs: list):
         saturated_qubits = []
         for next_idx, next_gate in enumerate(gates_qubits_pairs[idx + 1 :]):
             for qubit in gate:
-                if (qubit in next_gate) and (not qubit in saturated_qubits):
+                if (qubit in next_gate) and (qubit not in saturated_qubits):
                     saturated_qubits.append(qubit)
                     connectivity_list.append((idx, next_idx + idx + 1))
             if len(saturated_qubits) >= 2:
diff --git a/tests/test_models_circuit.py b/tests/test_models_circuit.py
index c6a72a39ff..2485be51a3 100644
--- a/tests/test_models_circuit.py
+++ b/tests/test_models_circuit.py
@@ -639,14 +639,12 @@ def test_circuit_draw():
 def test_circuit_wire_names_errors():
     with pytest.raises(TypeError):
         circuit = Circuit(5, wire_names=1)
-    with pytest.raises(ValueError):
-        circuit = Circuit(5, wire_names=["a", "b", "c"])
     with pytest.raises(ValueError):
         circuit = Circuit(2, wire_names={"q0": "1", "q1": "2", "q2": "3"})
     with pytest.raises(ValueError):
         circuit = Circuit(2, wire_names={"q0": "1", "q1": 2})
     with pytest.raises(ValueError):
-        circuit = Circuit(2, wire_names=["1", 2])
+        circuit = Circuit(2, wire_names={"q0": 4, "q1": 5, "q2": 6})
 
 
 def test_circuit_draw_wire_names():
@@ -766,7 +764,7 @@ def test_circuit_draw_line_wrap_names(capsys):
         + "q4: ... ───"
     )
 
-    circuit = Circuit(5, wire_names={"q1": "a"})
+    circuit = Circuit(5, wire_names=["q0", "a", "q2", "q3", "q4"])
     for i1 in range(5):
         circuit.add(gates.H(i1))
         for i2 in range(i1 + 1, 5):
diff --git a/tests/test_tomography_gate_set_tomography.py b/tests/test_tomography_gate_set_tomography.py
index d6d2ffd2df..de79d67922 100644
--- a/tests/test_tomography_gate_set_tomography.py
+++ b/tests/test_tomography_gate_set_tomography.py
@@ -278,7 +278,9 @@ def test_GST_with_transpiler(backend):
     # define transpiler
     connectivity = nx.Graph()
     # star connectivity
-    connectivity.add_edges_from([(0, 2), (1, 2), (2, 3), (2, 4)])
+    connectivity.add_edges_from(
+        [("q0", "q2"), ("q1", "q2"), ("q2", "q3"), ("q2", "q4")]
+    )
     transpiler = Passes(
         connectivity=connectivity,
         passes=[
@@ -287,7 +289,6 @@ def test_GST_with_transpiler(backend):
             Sabre(connectivity),
             Unroller(NativeGates.default(), backend=backend),
         ],
-        int_qubit_names=True,
     )
     # transpiled GST
     T_empty_1q, T_empty_2q, *T_approx_gates = GST(
diff --git a/tests/test_transpiler_optimizer.py b/tests/test_transpiler_optimizer.py
index 171c7516d4..457e25ecf7 100644
--- a/tests/test_transpiler_optimizer.py
+++ b/tests/test_transpiler_optimizer.py
@@ -6,10 +6,14 @@
 from qibo.transpiler.optimizer import Preprocessing, Rearrange
 
 
-def star_connectivity():
+def star_connectivity(names=["q0", "q1", "q2", "q3", "q4"], middle_qubit_idx=2):
     chip = nx.Graph()
-    chip.add_nodes_from(list(range(5)))
-    graph_list = [(i, 2) for i in range(5) if i != 2]
+    chip.add_nodes_from(names)
+    graph_list = [
+        (names[i], names[middle_qubit_idx])
+        for i in range(len(names))
+        if i != middle_qubit_idx
+    ]
     chip.add_edges_from(graph_list)
     return chip
 
diff --git a/tests/test_transpiler_pipeline.py b/tests/test_transpiler_pipeline.py
index bfa13f9e4d..82fe4c9419 100644
--- a/tests/test_transpiler_pipeline.py
+++ b/tests/test_transpiler_pipeline.py
@@ -17,11 +17,9 @@
 from qibo.transpiler.unroller import NativeGates, Unroller
 
 
-def generate_random_circuit(nqubits, ngates, seed=None):
-    """Generate random circuits one-qubit rotations and CZ gates."""
-    if seed is not None:  # pragma: no cover
-        np.random.seed(seed)
-
+def generate_random_circuit(nqubits, ngates, names=None, seed=42):
+    """Generate a random circuit with RX and CZ gates."""
+    np.random.seed(seed)
     one_qubit_gates = [gates.RX, gates.RY, gates.RZ, gates.X, gates.Y, gates.Z, gates.H]
     two_qubit_gates = [
         gates.CNOT,
@@ -34,7 +32,7 @@ def generate_random_circuit(nqubits, ngates, seed=None):
     ]
     n1, n2 = len(one_qubit_gates), len(two_qubit_gates)
     n = n1 + n2 if nqubits > 1 else n1
-    circuit = Circuit(nqubits)
+    circuit = Circuit(nqubits, wire_names=names)
     for _ in range(ngates):
         igate = int(np.random.randint(0, n))
         if igate >= n1:
@@ -47,49 +45,56 @@ def generate_random_circuit(nqubits, ngates, seed=None):
             gate = one_qubit_gates[igate]
         if issubclass(gate, gates.ParametrizedGate):
             theta = 2 * np.pi * np.random.random()
-            circuit.add(gate(*q, theta=theta))
+            circuit.add(gate(*q, theta=theta, trainable=False))
         else:
             circuit.add(gate(*q))
     return circuit
 
 
-def star_connectivity():
+def star_connectivity(names=["q0", "q1", "q2", "q3", "q4"], middle_qubit_idx=2):
     chip = nx.Graph()
-    chip.add_nodes_from(list(range(5)))
-    graph_list = [(i, 2) for i in range(5) if i != 2]
+    chip.add_nodes_from(names)
+    graph_list = [
+        (names[i], names[middle_qubit_idx])
+        for i in range(len(names))
+        if i != middle_qubit_idx
+    ]
     chip.add_edges_from(graph_list)
     return chip
 
 
 def test_restrict_qubits_error_no_subset():
     with pytest.raises(ConnectivityError) as excinfo:
-        restrict_connectivity_qubits(star_connectivity(), [1, 2, 6])
+        restrict_connectivity_qubits(star_connectivity(), ["q0", "q1", "q5"])
     assert "Some qubits are not in the original connectivity." in str(excinfo.value)
 
 
 def test_restrict_qubits_error_not_connected():
     with pytest.raises(ConnectivityError) as excinfo:
-        restrict_connectivity_qubits(star_connectivity(), [1, 3])
+        restrict_connectivity_qubits(star_connectivity(), ["q0", "q1"])
     assert "New connectivity graph is not connected." in str(excinfo.value)
 
 
 def test_restrict_qubits():
-    new_connectivity = restrict_connectivity_qubits(star_connectivity(), [1, 2, 3])
-    assert list(new_connectivity.nodes) == [1, 2, 3]
-    assert list(new_connectivity.edges) == [(1, 2), (2, 3)]
+    new_connectivity = restrict_connectivity_qubits(
+        star_connectivity(["A", "B", "C", "D", "E"]), ["A", "B", "C"]
+    )
+    assert list(new_connectivity.nodes) == ["A", "B", "C"]
+    assert list(new_connectivity.edges) == [("A", "C"), ("B", "C")]
 
 
 @pytest.mark.parametrize("ngates", [5, 10, 50])
-def test_pipeline_default(ngates):
-    circ = generate_random_circuit(nqubits=5, ngates=ngates)
-    default_transpiler = Passes(passes=None, connectivity=star_connectivity())
+@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
+def test_pipeline_default(ngates, names):
+    circ = generate_random_circuit(nqubits=5, ngates=ngates, names=names)
+    connectivity = star_connectivity(names)
+
+    default_transpiler = Passes(passes=None, connectivity=connectivity)
     transpiled_circ, final_layout = default_transpiler(circ)
-    initial_layout = default_transpiler.get_initial_layout()
     assert_transpiling(
         original_circuit=circ,
         transpiled_circuit=transpiled_circ,
-        connectivity=star_connectivity(),
-        initial_layout=initial_layout,
+        connectivity=connectivity,
         final_layout=final_layout,
         native_gates=NativeGates.default(),
         check_circuit_equivalence=False,
@@ -128,14 +133,13 @@ def test_assert_circuit_equivalence_false():
         assert_circuit_equivalence(circ1, circ2, final_map=final_map)
 
 
-def test_int_qubit_names():
-    circ = Circuit(2)
-    final_map = {i: i for i in range(5)}
-    default_transpiler = Passes(
-        passes=None, connectivity=star_connectivity(), int_qubit_names=True
-    )
+def test_int_qubit_names_default():
+    names = [1244, 1532, 2315, 6563, 8901]
+    circ = Circuit(5, wire_names=names)
+    connectivity = star_connectivity(names)
+    default_transpiler = Passes(passes=None, connectivity=connectivity)
     _, final_layout = default_transpiler(circ)
-    assert final_map == final_layout
+    assert final_layout == {names[i]: i for i in range(5)}
 
 
 def test_assert_circuit_equivalence_wrong_nqubits():
@@ -148,13 +152,14 @@ def test_assert_circuit_equivalence_wrong_nqubits():
 
 def test_error_connectivity():
     with pytest.raises(TranspilerPipelineError):
-        default_transpiler = Passes(passes=None, connectivity=None)
+        Passes(passes=None, connectivity=None)
 
 
 @pytest.mark.parametrize("qubits", [3, 5])
 def test_is_satisfied(qubits):
     default_transpiler = Passes(passes=None, connectivity=star_connectivity())
     circuit = Circuit(qubits)
+    circuit.wire_names = ["q0", "q1", "q2", "q3", "q4"][:qubits]
     circuit.add(gates.CZ(0, 2))
     circuit.add(gates.Z(0))
     assert default_transpiler.is_satisfied(circuit)
@@ -176,104 +181,78 @@ def test_is_satisfied_false_connectivity():
     assert not default_transpiler.is_satisfied(circuit)
 
 
-@pytest.mark.parametrize("qubits", [2, 5])
-@pytest.mark.parametrize("gates", [5, 20])
+@pytest.mark.parametrize("nqubits", [2, 3, 5])
+@pytest.mark.parametrize("ngates", [5, 20])
 @pytest.mark.parametrize("placer", [Random, Trivial, ReverseTraversal])
-@pytest.mark.parametrize("routing", [ShortestPaths, Sabre])
-def test_custom_passes(placer, routing, gates, qubits):
-    circ = generate_random_circuit(nqubits=qubits, ngates=gates)
+@pytest.mark.parametrize("router", [ShortestPaths, Sabre])
+def test_custom_passes(placer, router, ngates, nqubits):
+    connectivity = star_connectivity()
+    circ = generate_random_circuit(nqubits=nqubits, ngates=ngates)
     custom_passes = []
-    custom_passes.append(Preprocessing(connectivity=star_connectivity()))
+    custom_passes.append(Preprocessing(connectivity=connectivity))
     if placer == ReverseTraversal:
         custom_passes.append(
             placer(
-                connectivity=star_connectivity(),
-                routing_algorithm=routing(connectivity=star_connectivity()),
+                connectivity=connectivity,
+                routing_algorithm=router(connectivity=connectivity),
             )
         )
     else:
-        custom_passes.append(placer(connectivity=star_connectivity()))
-    custom_passes.append(routing(connectivity=star_connectivity()))
+        custom_passes.append(placer(connectivity=connectivity))
+    custom_passes.append(router(connectivity=connectivity))
     custom_passes.append(Unroller(native_gates=NativeGates.default()))
     custom_pipeline = Passes(
         custom_passes,
-        connectivity=star_connectivity(),
+        connectivity=connectivity,
         native_gates=NativeGates.default(),
     )
     transpiled_circ, final_layout = custom_pipeline(circ)
-    initial_layout = custom_pipeline.get_initial_layout()
     assert_transpiling(
         original_circuit=circ,
         transpiled_circuit=transpiled_circ,
-        connectivity=star_connectivity(),
-        initial_layout=initial_layout,
+        connectivity=connectivity,
         final_layout=final_layout,
         native_gates=NativeGates.default(),
     )
 
 
-@pytest.mark.parametrize("gates", [5, 20])
+@pytest.mark.parametrize("ngates", [5, 20])
 @pytest.mark.parametrize("placer", [Random, Trivial, ReverseTraversal])
 @pytest.mark.parametrize("routing", [ShortestPaths, Sabre])
-def test_custom_passes_restrict(gates, placer, routing):
-    circ = generate_random_circuit(nqubits=3, ngates=gates)
+@pytest.mark.parametrize(
+    "restrict_names", [["q1", "q2", "q3"], ["q0", "q2", "q4"], ["q4", "q2", "q3"]]
+)
+def test_custom_passes_restrict(ngates, placer, routing, restrict_names):
+    connectivity = star_connectivity()
+    circ = generate_random_circuit(nqubits=3, ngates=ngates, names=restrict_names)
     custom_passes = []
-    custom_passes.append(Preprocessing(connectivity=star_connectivity()))
+    custom_passes.append(Preprocessing(connectivity=connectivity))
     if placer == ReverseTraversal:
         custom_passes.append(
             placer(
-                connectivity=star_connectivity(),
-                routing_algorithm=routing(connectivity=star_connectivity()),
+                connectivity=connectivity,
+                routing_algorithm=routing(connectivity=connectivity),
             )
         )
     else:
-        custom_passes.append(placer(connectivity=star_connectivity()))
-    custom_passes.append(routing(connectivity=star_connectivity()))
+        custom_passes.append(placer(connectivity=connectivity))
+    custom_passes.append(routing(connectivity=connectivity))
     custom_passes.append(Unroller(native_gates=NativeGates.default()))
     custom_pipeline = Passes(
         custom_passes,
-        connectivity=star_connectivity(),
+        connectivity=connectivity,
         native_gates=NativeGates.default(),
-        on_qubits=[1, 2, 3],
+        on_qubits=restrict_names,
     )
     transpiled_circ, final_layout = custom_pipeline(circ)
-    initial_layout = custom_pipeline.get_initial_layout()
     assert_transpiling(
         original_circuit=circ,
         transpiled_circuit=transpiled_circ,
-        connectivity=restrict_connectivity_qubits(star_connectivity(), [1, 2, 3]),
-        initial_layout=initial_layout,
+        connectivity=restrict_connectivity_qubits(star_connectivity(), restrict_names),
         final_layout=final_layout,
         native_gates=NativeGates.default(),
     )
-    assert transpiled_circ.wire_names == ["q1", "q2", "q3"]
-
-
-def test_custom_passes_multiple_placer():
-    custom_passes = []
-    custom_passes.append(Random(connectivity=star_connectivity()))
-    custom_passes.append(Trivial(connectivity=star_connectivity()))
-    custom_pipeline = Passes(
-        custom_passes,
-        connectivity=star_connectivity(),
-        native_gates=NativeGates.default(),
-    )
-    circ = generate_random_circuit(nqubits=5, ngates=20)
-    with pytest.raises(TranspilerPipelineError):
-        transpiled_circ, final_layout = custom_pipeline(circ)
-
-
-def test_custom_passes_no_placer():
-    custom_passes = []
-    custom_passes.append(ShortestPaths(connectivity=star_connectivity()))
-    custom_pipeline = Passes(
-        custom_passes,
-        connectivity=star_connectivity(),
-        native_gates=NativeGates.default(),
-    )
-    circ = generate_random_circuit(nqubits=5, ngates=20)
-    with pytest.raises(TranspilerPipelineError):
-        transpiled_circ, final_layout = custom_pipeline(circ)
+    assert set(transpiled_circ.wire_names) == set(restrict_names)
 
 
 def test_custom_passes_wrong_pass():
@@ -281,11 +260,12 @@ def test_custom_passes_wrong_pass():
     custom_pipeline = Passes(passes=custom_passes, connectivity=None)
     circ = generate_random_circuit(nqubits=5, ngates=5)
     with pytest.raises(TranspilerPipelineError):
-        transpiled_circ, final_layout = custom_pipeline(circ)
+        custom_pipeline(circ)
 
 
 def test_int_qubit_names():
-    connectivity = star_connectivity()
+    names = [980, 123, 45, 9, 210464]
+    connectivity = star_connectivity(names)
     transpiler = Passes(
         connectivity=connectivity,
         passes=[
@@ -294,19 +274,16 @@ def test_int_qubit_names():
             Sabre(connectivity),
             Unroller(NativeGates.default()),
         ],
-        int_qubit_names=True,
     )
-    circuit = Circuit(1)
+    circuit = Circuit(1, wire_names=[123])
     circuit.add(gates.I(0))
     circuit.add(gates.H(0))
     circuit.add(gates.M(0))
     transpiled_circuit, final_map = transpiler(circuit)
-    initial_layout = transpiler.get_initial_layout()
     assert_transpiling(
         original_circuit=circuit,
         transpiled_circuit=transpiled_circuit,
         connectivity=connectivity,
-        initial_layout=initial_layout,
         final_layout=final_map,
         native_gates=NativeGates.default(),
     )
diff --git a/tests/test_transpiler_placer.py b/tests/test_transpiler_placer.py
index 6855a7eeac..ac153b8b03 100644
--- a/tests/test_transpiler_placer.py
+++ b/tests/test_transpiler_placer.py
@@ -19,80 +19,65 @@
 from qibo.transpiler.router import ShortestPaths
 
 
-def star_connectivity():
+def star_connectivity(names=["q0", "q1", "q2", "q3", "q4"], middle_qubit_idx=2):
     chip = nx.Graph()
-    chip.add_nodes_from(list(range(5)))
-    graph_list = [(i, 2) for i in range(5) if i != 2]
+    chip.add_nodes_from(names)
+    graph_list = [
+        (names[i], names[middle_qubit_idx])
+        for i in range(len(names))
+        if i != middle_qubit_idx
+    ]
     chip.add_edges_from(graph_list)
     return chip
 
 
-def star_circuit():
-    circuit = Circuit(5)
+def star_circuit(names=["q0", "q1", "q2", "q3", "q4"]):
+    circuit = Circuit(5, wire_names=names)
     for i in range(1, 5):
         circuit.add(gates.CNOT(i, 0))
     return circuit
 
 
-@pytest.mark.parametrize("connectivity", [star_connectivity(), None])
-@pytest.mark.parametrize(
-    "layout",
-    [{"q0": 0, "q1": 1, "q2": 2, "q3": 3, "q4": 4}, {0: 0, 1: 1, 2: 2, 3: 3, 4: 4}],
-)
-def test_assert_placement_true(layout, connectivity):
+def test_assert_placement_true():
     circuit = Circuit(5)
-    assert_placement(circuit, layout, connectivity=connectivity)
+    assert_placement(circuit, connectivity=star_connectivity())
 
 
-@pytest.mark.parametrize("qubits", [5, 3])
 @pytest.mark.parametrize(
-    "layout", [{"q0": 0, "q1": 1, "q2": 2, "q3": 3}, {"q0": 0, "q0": 1, "q2": 2}]
+    "qubits, names", [(5, ["A", "B", "C", "D", "F"]), (3, ["A", "B", "C"])]
 )
-def test_assert_placement_false(qubits, layout):
-    circuit = Circuit(qubits)
+def test_assert_placement_false(qubits, names):
+    connectivity = star_connectivity()
+    circuit = Circuit(qubits, wire_names=names)
     with pytest.raises(PlacementError):
-        assert_placement(circuit, layout)
+        assert_placement(circuit, connectivity)
 
 
-@pytest.mark.parametrize(
-    "layout",
-    [{"q0": 0, "q1": 1, "q2": 2, "q3": 3, "q4": 4}, {0: 0, 1: 1, 2: 2, 3: 3, 4: 4}],
-)
-def test_mapping_consistency(layout):
-    assert_mapping_consistency(layout)
+@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
+def test_mapping_consistency(names):
+    assert_mapping_consistency(names, star_connectivity(names))
 
 
-@pytest.mark.parametrize(
-    "layout",
-    [
-        {"q0": 0, "q1": 0, "q2": 1, "q3": 4, "q4": 3},
-        {"q0": 0, "q1": 2, "q0": 1, "q3": 4, "q4": 3},
-    ],
-)
-def test_mapping_consistency_error(layout):
+def test_mapping_consistency_error():
     with pytest.raises(PlacementError):
-        assert_mapping_consistency(layout)
+        assert_mapping_consistency(["A", "B", "C", "D", "F"], star_connectivity())
 
 
-def test_mapping_consistency_restricted():
-    layout = {"q0": 0, "q2": 1}
-    connectivity = star_connectivity()
-    restricted_connectivity = restrict_connectivity_qubits(connectivity, [0, 2])
-    assert_mapping_consistency(layout, restricted_connectivity)
+@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
+def test_mapping_consistency_restricted(names):
+    connectivity = star_connectivity(names)
+    on_qubit = [names[0], names[2]]
+    restricted_connectivity = restrict_connectivity_qubits(connectivity, on_qubit)
+    assert_mapping_consistency(on_qubit, restricted_connectivity)
 
 
-@pytest.mark.parametrize(
-    "layout",
-    [
-        {"q0": 0, "q2": 2},
-        {"q0": 0, "q1": 1},
-    ],
-)
-def test_mapping_consistency_restricted_error(layout):
-    connectivity = star_connectivity()
-    restricted_connectivity = restrict_connectivity_qubits(connectivity, [0, 2])
+@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
+def test_mapping_consistency_restricted_error(names):
+    connectivity = star_connectivity(names)
+    on_qubit = [names[0], names[2]]
+    restricted_connectivity = restrict_connectivity_qubits(connectivity, on_qubit)
     with pytest.raises(PlacementError):
-        assert_mapping_consistency(layout, restricted_connectivity)
+        assert_mapping_consistency([names[3], names[4]], restricted_connectivity)
 
 
 def test_gates_qubits_pairs():
@@ -112,98 +97,85 @@ def test_gates_qubits_pairs_error():
 
 
 def test_trivial():
-    circuit = Circuit(5)
-    connectivity = star_connectivity()
+    names = ["q4", "q3", "q2", "q1", "q0"]
+    circuit = Circuit(5, wire_names=names)
+    connectivity = star_connectivity(names)
     placer = Trivial(connectivity=connectivity)
-    layout = placer(circuit)
-    assert layout == {"q0": 0, "q1": 1, "q2": 2, "q3": 3, "q4": 4}
-    assert_placement(circuit, layout)
+    placer(circuit)
+    assert circuit.wire_names == names
+    assert_placement(circuit, connectivity)
 
 
 def test_trivial_restricted():
-    circuit = Circuit(2)
+    names = ["q0", "q2"]
+    circuit = Circuit(2, wire_names=names)
     connectivity = star_connectivity()
-    restricted_connectivity = restrict_connectivity_qubits(connectivity, [0, 2])
+    restricted_connectivity = restrict_connectivity_qubits(connectivity, names)
     placer = Trivial(connectivity=restricted_connectivity)
-    layout = placer(circuit)
-    assert layout == {"q0": 0, "q2": 1}
-    assert_placement(
-        circuit=circuit, layout=layout, connectivity=restricted_connectivity
-    )
+    placer(circuit)
+    assert circuit.wire_names == names
+    assert_placement(circuit, restricted_connectivity)
 
 
-def test_trivial_error():
-    circuit = Circuit(4)
-    connectivity = star_connectivity()
-    placer = Trivial(connectivity=connectivity)
-    with pytest.raises(PlacementError):
-        layout = placer(circuit)
+@pytest.mark.parametrize(
+    "custom_layout",
+    [["E", "D", "C", "B", "A"], {"E": 0, "D": 1, "C": 2, "B": 3, "A": 4}],
+)
+def test_custom(custom_layout):
+    circuit = Circuit(5)
+    connectivity = star_connectivity(["A", "B", "C", "D", "E"])
+    placer = Custom(connectivity=connectivity, initial_map=custom_layout)
+    placer(circuit)
+    assert circuit.wire_names == ["E", "D", "C", "B", "A"]
 
 
 @pytest.mark.parametrize(
-    "custom_layout", [[4, 3, 2, 1, 0], {"q0": 4, "q1": 3, "q2": 2, "q3": 1, "q4": 0}]
+    "custom_layout", [[4, 3, 2, 1, 0], {4: 0, 3: 1, 2: 2, 1: 3, 0: 4}]
 )
-@pytest.mark.parametrize("give_circuit", [True, False])
-@pytest.mark.parametrize("give_connectivity", [True, False])
-def test_custom(custom_layout, give_circuit, give_connectivity):
-    if give_circuit:
-        circuit = Circuit(5)
-    else:
-        circuit = None
-    if give_connectivity:
-        connectivity = star_connectivity()
-    else:
-        connectivity = None
+def test_custom_int(custom_layout):
+    names = [0, 1, 2, 3, 4]
+    circuit = Circuit(5, wire_names=names)
+    connectivity = star_connectivity(names)
     placer = Custom(connectivity=connectivity, initial_map=custom_layout)
-    layout = placer(circuit)
-    assert layout == {"q0": 4, "q1": 3, "q2": 2, "q3": 1, "q4": 0}
+    placer(circuit)
+    assert circuit.wire_names == [4, 3, 2, 1, 0]
 
 
-@pytest.mark.parametrize("custom_layout", [[1, 0], {"q0": 1, "q2": 0}])
+@pytest.mark.parametrize("custom_layout", [["D", "C"], {"C": 1, "D": 0}])
 def test_custom_restricted(custom_layout):
-    circuit = Circuit(2)
-    connectivity = star_connectivity()
-    restricted_connectivity = restrict_connectivity_qubits(connectivity, [0, 2])
+    circuit = Circuit(2, wire_names=["C", "D"])
+    connectivity = star_connectivity(["A", "B", "C", "D", "E"])
+    restricted_connectivity = restrict_connectivity_qubits(connectivity, ["C", "D"])
     placer = Custom(connectivity=restricted_connectivity, initial_map=custom_layout)
-    layout = placer(circuit)
-    assert layout == {"q0": 1, "q2": 0}
-    assert_placement(
-        circuit=circuit, layout=layout, connectivity=restricted_connectivity
-    )
+    placer(circuit)
+    assert circuit.wire_names == ["D", "C"]
+    assert_placement(circuit, restricted_connectivity)
 
 
 def test_custom_error_circuit():
     circuit = Circuit(3)
     custom_layout = [4, 3, 2, 1, 0]
-    connectivity = star_connectivity()
-    placer = Custom(connectivity=connectivity, initial_map=custom_layout)
-    with pytest.raises(PlacementError):
-        layout = placer(circuit)
-
-
-def test_custom_error_no_circuit():
-    connectivity = star_connectivity()
-    custom_layout = {"q0": 4, "q1": 3, "q2": 2, "q3": 0, "q4": 0}
+    connectivity = star_connectivity(names=custom_layout)
     placer = Custom(connectivity=connectivity, initial_map=custom_layout)
-    with pytest.raises(PlacementError):
-        layout = placer()
+    with pytest.raises(ValueError):
+        placer(circuit)
 
 
 def test_custom_error_type():
     circuit = Circuit(5)
     connectivity = star_connectivity()
-    layout = 1
-    placer = Custom(connectivity=connectivity, initial_map=layout)
+    placer = Custom(connectivity=connectivity, initial_map=1)
     with pytest.raises(TypeError):
-        layout = placer(circuit)
+        placer(circuit)
 
 
 def test_subgraph_perfect():
     connectivity = star_connectivity()
     placer = Subgraph(connectivity=connectivity)
-    layout = placer(star_circuit())
-    assert layout["q2"] == 0
-    assert_placement(star_circuit(), layout)
+    circuit = star_circuit()
+    placer(circuit)
+    assert circuit.wire_names[0] == "q2"
+    assert_placement(circuit, connectivity)
 
 
 def imperfect_circuit():
@@ -223,8 +195,9 @@ def imperfect_circuit():
 def test_subgraph_non_perfect():
     connectivity = star_connectivity()
     placer = Subgraph(connectivity=connectivity)
-    layout = placer(imperfect_circuit())
-    assert_placement(imperfect_circuit(), layout)
+    circuit = imperfect_circuit()
+    placer(circuit)
+    assert_placement(circuit, connectivity)
 
 
 def test_subgraph_error():
@@ -232,7 +205,7 @@ def test_subgraph_error():
     placer = Subgraph(connectivity=connectivity)
     circuit = Circuit(5)
     with pytest.raises(ValueError):
-        layout = placer(circuit)
+        placer(circuit)
 
 
 def test_subgraph_restricted():
@@ -244,56 +217,49 @@ def test_subgraph_restricted():
     circuit.add(gates.CNOT(1, 2))
     circuit.add(gates.CNOT(3, 1))
     connectivity = star_connectivity()
-    restricted_connectivity = restrict_connectivity_qubits(connectivity, [0, 2, 3, 4])
-    placer = Subgraph(connectivity=restricted_connectivity)
-    layout = placer(circuit)
-    assert_placement(
-        circuit=circuit, layout=layout, connectivity=restricted_connectivity
+    restricted_connectivity = restrict_connectivity_qubits(
+        connectivity, ["q0", "q2", "q3", "q4"]
     )
+    placer = Subgraph(connectivity=restricted_connectivity)
+    placer(circuit)
+    assert_placement(circuit, restricted_connectivity)
 
 
 @pytest.mark.parametrize("reps", [1, 10, 100])
-def test_random(reps):
-    connectivity = star_connectivity()
+@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
+def test_random(reps, names):
+    connectivity = star_connectivity(names)
     placer = Random(connectivity=connectivity, samples=reps)
-    layout = placer(star_circuit())
-    assert_placement(star_circuit(), layout)
-
-
-def test_random_perfect():
-    circ = Circuit(5)
-    circ.add(gates.CZ(0, 1))
-    connectivity = star_connectivity()
-    placer = Random(connectivity=connectivity, samples=1000)
-    layout = placer(circ)
-    assert_placement(star_circuit(), layout)
+    circuit = star_circuit(names=names)
+    placer(circuit)
+    assert_placement(circuit, connectivity)
 
 
 def test_random_restricted():
-    circuit = Circuit(4)
+    names = [0, 1, 2, 3, 4]
+    circuit = Circuit(4, wire_names=names[:4])
     circuit.add(gates.CNOT(1, 3))
     circuit.add(gates.CNOT(2, 1))
     circuit.add(gates.CNOT(3, 2))
     circuit.add(gates.CNOT(2, 1))
     circuit.add(gates.CNOT(1, 2))
     circuit.add(gates.CNOT(3, 1))
-    connectivity = star_connectivity()
+    connectivity = star_connectivity(names)
     restricted_connectivity = restrict_connectivity_qubits(connectivity, [0, 2, 3, 4])
     placer = Random(connectivity=restricted_connectivity, samples=100)
-    layout = placer(circuit)
-    assert_placement(
-        circuit=circuit, layout=layout, connectivity=restricted_connectivity
-    )
+    placer(circuit)
+    assert_placement(circuit, restricted_connectivity)
 
 
-@pytest.mark.parametrize("gates", [None, 5, 13])
-def test_reverse_traversal(gates):
-    circuit = star_circuit()
-    connectivity = star_connectivity()
+@pytest.mark.parametrize("ngates", [None, 5, 13])
+@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
+def test_reverse_traversal(ngates, names):
+    circuit = star_circuit(names=names)
+    connectivity = star_connectivity(names=names)
     routing = ShortestPaths(connectivity=connectivity)
-    placer = ReverseTraversal(connectivity, routing, depth=gates)
-    layout = placer(circuit)
-    assert_placement(circuit, layout)
+    placer = ReverseTraversal(connectivity, routing, depth=ngates)
+    placer(circuit)
+    assert_placement(circuit, connectivity)
 
 
 def test_reverse_traversal_no_gates():
@@ -302,7 +268,7 @@ def test_reverse_traversal_no_gates():
     placer = ReverseTraversal(connectivity, routing, depth=10)
     circuit = Circuit(5)
     with pytest.raises(ValueError):
-        layout = placer(circuit)
+        placer(circuit)
 
 
 def test_reverse_traversal_restricted():
@@ -314,34 +280,36 @@ def test_reverse_traversal_restricted():
     circuit.add(gates.CNOT(1, 2))
     circuit.add(gates.CNOT(3, 1))
     connectivity = star_connectivity()
-    restricted_connectivity = restrict_connectivity_qubits(connectivity, [0, 2, 3, 4])
+    restrict_names = ["q0", "q2", "q3", "q4"]
+    restricted_connectivity = restrict_connectivity_qubits(connectivity, restrict_names)
+    circuit.wire_names = restrict_names
     routing = ShortestPaths(connectivity=restricted_connectivity)
     placer = ReverseTraversal(
         connectivity=restricted_connectivity, routing_algorithm=routing, depth=5
     )
-    layout = placer(circuit)
-    assert_placement(
-        circuit=circuit, layout=layout, connectivity=restricted_connectivity
-    )
+    placer(circuit)
+    assert_placement(circuit, restricted_connectivity)
 
 
 def test_star_connectivity_placer():
-    circ = Circuit(3)
+    circ = Circuit(5)
     circ.add(gates.CZ(0, 1))
     circ.add(gates.CZ(1, 2))
     circ.add(gates.CZ(0, 2))
-    placer = StarConnectivityPlacer(middle_qubit=2)
-    layout = placer(circ)
-    assert_placement(circ, layout)
-    assert layout == {"q0": 0, "q1": 2, "q2": 1}
+    connectivity = star_connectivity()
+    placer = StarConnectivityPlacer(connectivity)
+    placer(circ)
+    assert_placement(circ, connectivity)
+    assert circ.wire_names == ["q0", "q2", "q1", "q3", "q4"]
 
 
 @pytest.mark.parametrize("first", [True, False])
 def test_star_connectivity_placer_error(first):
-    circ = Circuit(3)
+    circ = Circuit(5)
     if first:
         circ.add(gates.CZ(0, 1))
     circ.add(gates.TOFFOLI(0, 1, 2))
-    placer = StarConnectivityPlacer(middle_qubit=2)
+    connectivity = star_connectivity()
+    placer = StarConnectivityPlacer(connectivity)
     with pytest.raises(PlacementError):
-        layout = placer(circ)
+        placer(circ)
diff --git a/tests/test_transpiler_router.py b/tests/test_transpiler_router.py
index 80b0e72aa3..4bcfe949af 100644
--- a/tests/test_transpiler_router.py
+++ b/tests/test_transpiler_router.py
@@ -32,38 +32,58 @@
 )
 
 
-def star_connectivity(middle_qubit=2):
+def star_connectivity(names=["q0", "q1", "q2", "q3", "q4"], middle_qubit_idx=2):
     chip = nx.Graph()
-    chip.add_nodes_from(list(range(5)))
-    graph_list = [(i, middle_qubit) for i in range(5) if i != middle_qubit]
+    chip.add_nodes_from(names)
+    graph_list = [
+        (names[i], names[middle_qubit_idx])
+        for i in range(len(names))
+        if i != middle_qubit_idx
+    ]
     chip.add_edges_from(graph_list)
     return chip
 
 
-def grid_connectivity():
+def grid_connectivity(names=["q0", "q1", "q2", "q3", "q4"]):
     chip = nx.Graph()
-    chip.add_nodes_from(list(range(5)))
-    graph_list = [(0, 1), (1, 2), (2, 3), (3, 0), (0, 4)]
+    chip.add_nodes_from(names)
+    graph_list = [
+        (names[0], names[1]),
+        (names[1], names[2]),
+        (names[2], names[3]),
+        (names[3], names[0]),
+        (names[0], names[4]),
+    ]
     chip.add_edges_from(graph_list)
     return chip
 
 
-def line_connectivity(n):
+def line_connectivity(n, names):
+    if names is None:
+        names = [f"q{i}" for i in range(n)]
     chip = nx.Graph()
-    chip.add_nodes_from(list(range(n)))
-    graph_list = [(i, i + 1) for i in range(n - 1)]
+    chip.add_nodes_from(names)
+    graph_list = [(names[i], names[i + 1]) for i in range(n - 1)]
     chip.add_edges_from(graph_list)
     return chip
 
 
-def generate_random_circuit(nqubits, ngates, seed=42):
+def generate_random_circuit(nqubits, ngates, names=None, seed=42):
     """Generate a random circuit with RX and CZ gates."""
     np.random.seed(seed)
-    one_qubit_gates = [gates.RX, gates.RY, gates.RZ]
-    two_qubit_gates = [gates.CZ, gates.CNOT, gates.SWAP]
+    one_qubit_gates = [gates.RX, gates.RY, gates.RZ, gates.X, gates.Y, gates.Z, gates.H]
+    two_qubit_gates = [
+        gates.CNOT,
+        gates.CZ,
+        gates.SWAP,
+        gates.iSWAP,
+        gates.CRX,
+        gates.CRY,
+        gates.CRZ,
+    ]
     n1, n2 = len(one_qubit_gates), len(two_qubit_gates)
     n = n1 + n2 if nqubits > 1 else n1
-    circuit = Circuit(nqubits)
+    circuit = Circuit(nqubits, wire_names=names)
     for _ in range(ngates):
         igate = int(np.random.randint(0, n))
         if igate >= n1:
@@ -89,9 +109,9 @@ def star_circuit():
     return circuit
 
 
-def matched_circuit():
+def matched_circuit(names):
     """Return a simple circuit that can be executed on star connectivity"""
-    circuit = Circuit(5)
+    circuit = Circuit(5, wire_names=names)
     circuit.add(gates.CZ(0, 2))
     circuit.add(gates.CZ(1, 2))
     circuit.add(gates.Z(1))
@@ -101,7 +121,8 @@ def matched_circuit():
 
 
 def test_assert_connectivity():
-    assert_connectivity(star_connectivity(), matched_circuit())
+    names = ["A", "B", "C", "D", "E"]
+    assert_connectivity(star_connectivity(names), matched_circuit(names))
 
 
 def test_assert_connectivity_false():
@@ -118,93 +139,128 @@ def test_assert_connectivity_3q():
         assert_connectivity(star_connectivity(), circuit)
 
 
-@pytest.mark.parametrize("gates", [5, 25])
+def test_bell_state_3q():
+    from qibo.transpiler.pipeline import _transpose_qubits
+
+    circuit = Circuit(3)
+    circuit.add(gates.H(0))
+    circuit.add(gates.CNOT(0, 2))
+    circuit.add(gates.X(0))
+    circuit.add(gates.M(0, 1, 2))
+
+    c = circuit.copy()
+    connectivity = line_connectivity(3, None)
+    router = Sabre(connectivity=connectivity)
+    routed_circuit, final_map = router(c)
+
+    backend = NumpyBackend()
+    state = np.array([1, 0, 0, 0, 0, 0, 0, 0])
+    target_state = backend.execute_circuit(routed_circuit, state).state()
+    target_state = _transpose_qubits(target_state, list(final_map.values()))
+    assert np.all(
+        np.isclose(
+            np.real(target_state).round(1), np.array([0, 0.7, 0, 0, 0.7, 0, 0, 0])
+        )
+    )
+
+
+@pytest.mark.parametrize("ngates", [5, 25])
 @pytest.mark.parametrize("placer", [Trivial, Random])
 @pytest.mark.parametrize("connectivity", [star_connectivity(), grid_connectivity()])
-def test_random_circuits_5q(gates, placer, connectivity):
+def test_random_circuits_5q(ngates, placer, connectivity):
     placer = placer(connectivity=connectivity)
-    layout_circ = Circuit(5)
-    initial_layout = placer(layout_circ)
     transpiler = ShortestPaths(connectivity=connectivity)
-    circuit = generate_random_circuit(nqubits=5, ngates=gates)
-    transpiled_circuit, final_qubit_map = transpiler(circuit, initial_layout)
+
+    circuit = generate_random_circuit(nqubits=5, ngates=ngates)
+    original_circuit = circuit.copy()
+    placer(circuit)
+    transpiled_circuit, final_qubit_map = transpiler(circuit)
+
     assert transpiler.added_swaps >= 0
     assert_connectivity(connectivity, transpiled_circuit)
-    assert_placement(transpiled_circuit, final_qubit_map)
-    assert gates + transpiler.added_swaps == transpiled_circuit.ngates
-    qubit_matcher = Preprocessing(connectivity=connectivity)
-    new_circuit = qubit_matcher(circuit=circuit)
+    assert_placement(transpiled_circuit, connectivity)
+    assert ngates + transpiler.added_swaps == transpiled_circuit.ngates
     assert_circuit_equivalence(
-        original_circuit=new_circuit,
+        original_circuit=original_circuit,
         transpiled_circuit=transpiled_circuit,
         final_map=final_qubit_map,
-        initial_map=initial_layout,
     )
 
 
-def test_random_circuits_15q_50g():
-    nqubits, ngates = 15, 50
-    connectivity = line_connectivity(nqubits)
+@pytest.mark.parametrize("nqubits", [11, 12, 13, 14, 15])
+@pytest.mark.parametrize("ngates", [30, 50])
+def test_random_circuits_15q_50g(nqubits, ngates):
+    connectivity = line_connectivity(nqubits, None)
     placer = Random(connectivity=connectivity)
-    layout_circ = Circuit(nqubits)
-    initial_layout = placer(layout_circ)
     transpiler = Sabre(connectivity=connectivity)
     circuit = generate_random_circuit(nqubits=nqubits, ngates=ngates)
-    transpiled_circuit, final_qubit_map = transpiler(circuit, initial_layout)
+    original_circuit = circuit.copy()
+
+    placer(circuit)
+    transpiled_circuit, final_qubit_map = transpiler(circuit)
+
     assert transpiler.added_swaps >= 0
     assert_connectivity(connectivity, transpiled_circuit)
-    assert_placement(transpiled_circuit, final_qubit_map)
+    assert_placement(transpiled_circuit, connectivity)
     assert ngates + transpiler.added_swaps == transpiled_circuit.ngates
-    qubit_matcher = Preprocessing(connectivity=connectivity)
-    new_circuit = qubit_matcher(circuit=circuit)
     assert_circuit_equivalence(
-        original_circuit=new_circuit,
+        original_circuit=original_circuit,
         transpiled_circuit=transpiled_circuit,
         final_map=final_qubit_map,
-        initial_map=initial_layout,
     )
 
 
 def test_star_circuit():
-    placer = Subgraph(star_connectivity())
-    initial_layout = placer(star_circuit())
-    transpiler = ShortestPaths(connectivity=star_connectivity())
-    transpiled_circuit, final_qubit_map = transpiler(star_circuit(), initial_layout)
+    connectivity = star_connectivity()
+    circuit = star_circuit()
+    placer = Subgraph(connectivity=connectivity)
+    transpiler = ShortestPaths(connectivity=connectivity)
+
+    placer(circuit)
+    transpiled_circuit, final_qubit_map = transpiler(circuit)
+
     assert transpiler.added_swaps == 0
     assert_connectivity(star_connectivity(), transpiled_circuit)
-    assert_placement(transpiled_circuit, final_qubit_map)
+    assert_placement(transpiled_circuit, connectivity)
     assert_circuit_equivalence(
         original_circuit=star_circuit(),
         transpiled_circuit=transpiled_circuit,
         final_map=final_qubit_map,
-        initial_map=initial_layout,
     )
 
 
 def test_star_circuit_custom_map():
-    placer = Custom(initial_map=[1, 0, 2, 3, 4], connectivity=star_connectivity())
-    initial_layout = placer()
-    transpiler = ShortestPaths(connectivity=star_connectivity())
-    transpiled_circuit, final_qubit_map = transpiler(star_circuit(), initial_layout)
+    connectivity = star_connectivity()
+    circuit = star_circuit()
+    placer = Custom(
+        initial_map=["q1", "q0", "q2", "q3", "q4"], connectivity=connectivity
+    )
+    transpiler = ShortestPaths(connectivity=connectivity)
+
+    placer(circuit)
+    transpiled_circuit, final_qubit_map = transpiler(circuit)
+
     assert transpiler.added_swaps == 1
     assert_connectivity(star_connectivity(), transpiled_circuit)
-    assert_placement(transpiled_circuit, final_qubit_map)
+    assert_placement(transpiled_circuit, connectivity)
     assert_circuit_equivalence(
         original_circuit=star_circuit(),
         transpiled_circuit=transpiled_circuit,
         final_map=final_qubit_map,
-        initial_map=initial_layout,
     )
 
 
 def test_routing_with_measurements():
-    placer = Trivial(connectivity=star_connectivity())
+    connectivity = star_connectivity()
     circuit = Circuit(5)
     circuit.add(gates.CNOT(0, 1))
     circuit.add(gates.M(0, 2, 3))
-    initial_layout = placer(circuit=circuit)
-    transpiler = ShortestPaths(connectivity=star_connectivity())
-    transpiled_circuit, final_qubit_map = transpiler(circuit, initial_layout)
+    placer = Trivial(connectivity)
+    transpiler = ShortestPaths(connectivity)
+
+    placer(circuit=circuit)
+    transpiled_circuit, final_qubit_map = transpiler(circuit)
+
     assert transpiled_circuit.ngates == 3
     measured_qubits = transpiled_circuit.queue[2].qubits
     assert measured_qubits == (0, 1, 3)
@@ -212,37 +268,28 @@ def test_routing_with_measurements():
         original_circuit=circuit,
         transpiled_circuit=transpiled_circuit,
         final_map=final_qubit_map,
-        initial_map=initial_layout,
     )
 
 
 def test_sabre_looping():
     # Setup where the looping occurs
     # Line connectivity, gates with gate_array, Trivial placer
+
+    connectivity = line_connectivity(10, None)
     gate_array = [(7, 2), (6, 0), (5, 6), (4, 8), (3, 5), (9, 1)]
     loop_circ = Circuit(10)
     for qubits in gate_array:
         loop_circ.add(gates.CZ(*qubits))
 
-    chip = nx.Graph()
-    chip.add_nodes_from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
-    chip.add_edges_from(
-        [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)]
-    )
-
-    placer = Trivial(connectivity=chip)
-    initial_layout = placer(loop_circ)
+    placer = Trivial(connectivity)
     router_no_threshold = Sabre(
-        connectivity=chip, swap_threshold=np.inf
+        connectivity=connectivity, swap_threshold=np.inf
     )  # Without reset
-    router_threshold = Sabre(connectivity=chip)  # With reset
+    router_threshold = Sabre(connectivity=connectivity)  # With reset
 
-    routed_no_threshold, final_mapping_no_threshold = router_no_threshold(
-        loop_circ, initial_layout=initial_layout
-    )
-    routed_threshold, final_mapping_threshold = router_threshold(
-        loop_circ, initial_layout=initial_layout
-    )
+    placer(loop_circ)
+    routed_no_threshold, final_mapping_no_threshold = router_no_threshold(loop_circ)
+    routed_threshold, final_mapping_threshold = router_threshold(loop_circ)
 
     count_no_threshold = router_no_threshold.added_swaps
     count_threshold = router_threshold.added_swaps
@@ -252,13 +299,11 @@ def test_sabre_looping():
         original_circuit=loop_circ,
         transpiled_circuit=routed_no_threshold,
         final_map=final_mapping_no_threshold,
-        initial_map=initial_layout,
     )
     assert_circuit_equivalence(
         original_circuit=loop_circ,
         transpiled_circuit=routed_threshold,
         final_map=final_mapping_threshold,
-        initial_map=initial_layout,
     )
 
 
@@ -269,18 +314,13 @@ def test_sabre_shortest_path_routing():
     for qubits in gate_array:
         loop_circ.add(gates.CZ(*qubits))
 
-    # line connectivity
-    chip = nx.Graph()
-    chip.add_nodes_from(range(10))
-    chip.add_edges_from(
-        [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)]
-    )
+    connectivity = line_connectivity(10, None)
 
-    placer = Trivial(connectivity=chip)
-    initial_layout = placer(loop_circ)
-    router = Sabre(connectivity=chip)
+    placer = Trivial(connectivity)
+    router = Sabre(connectivity)
 
-    router._preprocessing(circuit=loop_circ, initial_layout=initial_layout)
+    placer(loop_circ)
+    router._preprocessing(circuit=loop_circ)
     router._shortest_path_routing()  # q2 should be moved adjacent to q8
 
     gate_28 = router.circuit_map.circuit_blocks.block_list[2]
@@ -300,14 +340,15 @@ def test_circuit_map():
     circ.add(gates.CZ(1, 2))
     circ.add(gates.CZ(0, 1))
     circ.add(gates.CZ(2, 3))
-    initial_layout = {"q0": 2, "q1": 0, "q2": 1, "q3": 3}
-    circuit_map = CircuitMap(initial_layout=initial_layout, circuit=circ)
+    circ.wire_names = ["q1", "q2", "q0", "q3"]
+
+    circuit_map = CircuitMap(circuit=circ)
     block_list = circuit_map.circuit_blocks
     # test blocks_qubits_pairs
     assert circuit_map.blocks_logical_qubits_pairs() == [(0, 1), (1, 2), (0, 1), (2, 3)]
     # test execute_block and routed_circuit
     circuit_map.execute_block(block_list.search_by_index(0))
-    routed_circuit = circuit_map.routed_circuit()
+    routed_circuit = circuit_map.routed_circuit(circuit_kwargs=circ.init_kwargs)
     assert isinstance(routed_circuit.queue[0], gates.H)
     assert len(routed_circuit.queue) == 4
     qubits = routed_circuit.queue[2].qubits
@@ -318,7 +359,7 @@ def test_circuit_map():
 
     # test update 1
     circuit_map.update((0, 2))
-    routed_circuit = circuit_map.routed_circuit()
+    routed_circuit = circuit_map.routed_circuit(circuit_kwargs=circ.init_kwargs)
     assert isinstance(routed_circuit.queue[4], gates.SWAP)
     qubits = routed_circuit.queue[4].qubits
     assert (
@@ -326,12 +367,12 @@ def test_circuit_map():
         and routed_circuit.wire_names[qubits[1]] == "q0"
     )
     assert circuit_map._swaps == 1
-    assert circuit_map.physical_to_logical == [0, 2, 1, 3]
-    assert circuit_map.logical_to_physical == [0, 2, 1, 3]
+    assert circuit_map.physical_to_logical == [2, 1, 0, 3]
+    assert circuit_map.logical_to_physical == [2, 1, 0, 3]
 
     # test update 2
     circuit_map.update((1, 2))
-    routed_circuit = circuit_map.routed_circuit()
+    routed_circuit = circuit_map.routed_circuit(circuit_kwargs=circ.init_kwargs)
     assert isinstance(routed_circuit.queue[5], gates.SWAP)
     qubits = routed_circuit.queue[5].qubits
     assert (
@@ -339,14 +380,14 @@ def test_circuit_map():
         and routed_circuit.wire_names[qubits[1]] == "q1"
     )
     assert circuit_map._swaps == 2
-    assert circuit_map.physical_to_logical == [0, 1, 2, 3]
-    assert circuit_map.logical_to_physical == [0, 1, 2, 3]
+    assert circuit_map.physical_to_logical == [1, 2, 0, 3]
+    assert circuit_map.logical_to_physical == [2, 0, 1, 3]
 
-    # # test execute_block after multiple swaps
+    # test execute_block after multiple swaps
     circuit_map.execute_block(block_list.search_by_index(1))
     circuit_map.execute_block(block_list.search_by_index(2))
     circuit_map.execute_block(block_list.search_by_index(3))
-    routed_circuit = circuit_map.routed_circuit()
+    routed_circuit = circuit_map.routed_circuit(circuit_kwargs=circ.init_kwargs)
     assert isinstance(routed_circuit.queue[6], gates.CZ)
 
     qubits = routed_circuit.queue[6].qubits
@@ -366,73 +407,81 @@ def test_circuit_map():
     )
     assert len(circuit_map.circuit_blocks()) == 0
     # test final layout
-    assert circuit_map.final_layout() == {"q0": 0, "q1": 1, "q2": 2, "q3": 3}
+    assert circuit_map.final_layout() == {"q0": 1, "q1": 2, "q2": 0, "q3": 3}
 
 
-def test_sabre_matched():
+@pytest.mark.parametrize(
+    "names",
+    [["q0", "q1", "q2", "q3", "q4"], [0, 1, 2, 3, 4], ["A", "B", "C", "D", "E"]],
+)
+def test_sabre_matched(names):
+    connectivity = star_connectivity(names=names)
+    circuit = matched_circuit(names)
+    original_circuit = circuit.copy()
     placer = Trivial()
-    layout_circ = Circuit(5)
-    initial_layout = placer(layout_circ)
-    router = Sabre(connectivity=star_connectivity())
-    routed_circuit, final_map = router(
-        circuit=matched_circuit(), initial_layout=initial_layout
-    )
+    router = Sabre(connectivity=connectivity)
+
+    placer(circuit)
+    routed_circuit, final_map = router(circuit)
+
     assert router.added_swaps == 0
-    assert final_map == {"q0": 0, "q1": 1, "q2": 2, "q3": 3, "q4": 4}
-    assert_connectivity(circuit=routed_circuit, connectivity=star_connectivity())
+    assert_connectivity(circuit=routed_circuit, connectivity=connectivity)
     assert_circuit_equivalence(
-        original_circuit=matched_circuit(),
+        original_circuit=original_circuit,
         transpiled_circuit=routed_circuit,
         final_map=final_map,
-        initial_map=initial_layout,
     )
 
 
 @pytest.mark.parametrize("seed", [42])
 def test_sabre_simple(seed):
-    placer = Trivial()
+    connectivity = star_connectivity()
     circ = Circuit(5)
     circ.add(gates.CZ(0, 1))
-    initial_layout = placer(circ)
-    router = Sabre(connectivity=star_connectivity(), seed=seed)
-    routed_circuit, final_map = router(circuit=circ, initial_layout=initial_layout)
+    original_circuit = circ.copy()
+    placer = Trivial()
+    router = Sabre(connectivity=connectivity, seed=seed)
+
+    placer(circ)
+    routed_circuit, final_map = router(circ)
+
     assert router.added_swaps == 1
     assert final_map == {"q0": 2, "q1": 1, "q2": 0, "q3": 3, "q4": 4}
     assert routed_circuit.queue[0].qubits == (0, 2)
     assert isinstance(routed_circuit.queue[0], gates.SWAP)
     assert isinstance(routed_circuit.queue[1], gates.CZ)
-    assert_connectivity(circuit=routed_circuit, connectivity=star_connectivity())
+    assert_connectivity(circuit=routed_circuit, connectivity=connectivity)
     assert_circuit_equivalence(
-        original_circuit=circ,
+        original_circuit=original_circuit,
         transpiled_circuit=routed_circuit,
         final_map=final_map,
-        initial_map=initial_layout,
     )
 
 
 @pytest.mark.parametrize("n_gates", [10, 40])
 @pytest.mark.parametrize("look", [0, 5])
 @pytest.mark.parametrize("decay", [0.5, 1.0])
-@pytest.mark.parametrize("placer", [Trivial, Random])
+@pytest.mark.parametrize("placer_param", [Trivial, Random])
 @pytest.mark.parametrize("connectivity", [star_connectivity(), grid_connectivity()])
-def test_sabre_random_circuits(n_gates, look, decay, placer, connectivity):
-    placer = placer(connectivity=connectivity)
-    layout_circ = Circuit(5)
-    initial_layout = placer(layout_circ)
-    router = Sabre(connectivity=connectivity, lookahead=look, decay_lookahead=decay)
+def test_sabre_random_circuits(n_gates, look, decay, placer_param, connectivity):
     circuit = generate_random_circuit(nqubits=5, ngates=n_gates)
     measurement = gates.M(*range(5))
     circuit.add(measurement)
-    transpiled_circuit, final_qubit_map = router(circuit, initial_layout)
+    original_circuit = circuit.copy()
+    placer = placer_param(connectivity=connectivity)
+    router = Sabre(connectivity=connectivity, lookahead=look, decay_lookahead=decay)
+
+    placer(circuit)
+    transpiled_circuit, final_qubit_map = router(circuit)
+
     assert router.added_swaps >= 0
     assert_connectivity(connectivity, transpiled_circuit)
-    assert_placement(transpiled_circuit, final_qubit_map)
+    assert_placement(transpiled_circuit, connectivity)
     assert n_gates + router.added_swaps + 1 == transpiled_circuit.ngates
     assert_circuit_equivalence(
-        original_circuit=circuit,
+        original_circuit=original_circuit,
         transpiled_circuit=transpiled_circuit,
         final_map=final_qubit_map,
-        initial_map=initial_layout,
     )
     assert transpiled_circuit.queue[-1].register_name == measurement.register_name
 
@@ -440,9 +489,9 @@ def test_sabre_random_circuits(n_gates, look, decay, placer, connectivity):
 def test_sabre_memory_map():
     placer = Trivial()
     layout_circ = Circuit(5)
-    initial_layout = placer(layout_circ)
+    placer(layout_circ)
     router = Sabre(connectivity=star_connectivity())
-    router._preprocessing(circuit=star_circuit(), initial_layout=initial_layout)
+    router._preprocessing(circuit=star_circuit())
     router._memory_map = [[1, 0, 2, 3, 4]]
     value = router._compute_cost((0, 1))
     assert value == float("inf")
@@ -458,8 +507,7 @@ def test_sabre_intermediate_measurements():
     connectivity.add_nodes_from([0, 1, 2])
     connectivity.add_edges_from([(0, 1), (1, 2)])
     router = Sabre(connectivity=connectivity)
-    initial_layout = {"q0": 0, "q1": 1, "q2": 2}
-    routed_circ, _ = router(circuit=circ, initial_layout=initial_layout)
+    routed_circ, _ = router(circuit=circ)
     assert routed_circ.queue[3].register_name == measurement.register_name
 
 
@@ -469,42 +517,47 @@ def test_restrict_qubits(router_algorithm):
     circ.add(gates.CZ(0, 1))
     circ.add(gates.CZ(0, 2))
     circ.add(gates.CZ(2, 1))
-    initial_layout = {"q0": 0, "q2": 2, "q3": 1}
+    circ.wire_names = ["q0", "q3", "q2"]
     connectivity = star_connectivity()
-    restricted_connectivity = restrict_connectivity_qubits(connectivity, [0, 2, 3])
+    restricted_connectivity = restrict_connectivity_qubits(
+        connectivity, ["q0", "q2", "q3"]
+    )
     router = router_algorithm(connectivity=restricted_connectivity)
-    routed_circ, final_layout = router(circuit=circ, initial_layout=initial_layout)
+    routed_circ, final_layout = router(circuit=circ)
     assert_circuit_equivalence(
         original_circuit=circ,
         transpiled_circuit=routed_circ,
         final_map=final_layout,
-        initial_map=initial_layout,
     )
     assert_connectivity(restricted_connectivity, routed_circ)
-    assert_placement(routed_circ, final_layout, connectivity=restricted_connectivity)
-    assert routed_circ.wire_names == ["q0", "q2", "q3"]
+    assert_placement(routed_circ, connectivity=restricted_connectivity)
+    assert routed_circ.wire_names == ["q0", "q3", "q2"]
 
 
 def test_star_error_multi_qubit():
     circuit = Circuit(3)
     circuit.add(gates.TOFFOLI(0, 1, 2))
-    transpiler = StarConnectivityRouter(middle_qubit=2)
+    connectivity = star_connectivity(middle_qubit_idx=2)
+    transpiler = StarConnectivityRouter(connectivity)
     with pytest.raises(ConnectivityError):
-        transpiled, hardware_qubits = transpiler(
-            initial_layout={"q0": 0, "q1": 1, "q2": 2}, circuit=circuit
-        )
+        transpiled, hardware_qubits = transpiler(circuit=circuit)
 
 
-@pytest.mark.parametrize("nqubits", [1, 3, 5])
+# @pytest.mark.parametrize("nqubits", [1, 3, 5])
+@pytest.mark.parametrize("nqubits", [5])
 @pytest.mark.parametrize("middle_qubit", [0, 2, 4])
 @pytest.mark.parametrize("depth", [2, 10])
 @pytest.mark.parametrize("measurements", [True, False])
 @pytest.mark.parametrize("unitaries", [True, False])
-def test_star_router(nqubits, depth, middle_qubit, measurements, unitaries):
+@pytest.mark.parametrize(
+    "names",
+    [["q0", "q1", "q2", "q3", "q4"], [0, 1, 2, 3, 4], ["A", "B", "C", "D", "E"]],
+)
+def test_star_router(nqubits, depth, middle_qubit, measurements, unitaries, names):
     unitary_dim = min(2, nqubits)
-    connectivity = star_connectivity(middle_qubit)
+    connectivity = star_connectivity(names=names, middle_qubit_idx=middle_qubit)
     if unitaries:
-        circuit = Circuit(nqubits)
+        circuit = Circuit(nqubits, wire_names=names)
         pairs = list(itertools.combinations(range(nqubits), unitary_dim))
         for _ in range(depth):
             qubits = pairs[int(np.random.randint(len(pairs)))]
@@ -514,32 +567,28 @@ def test_star_router(nqubits, depth, middle_qubit, measurements, unitaries):
                 )
             )
     else:
-        circuit = generate_random_circuit(nqubits, depth)
+        circuit = generate_random_circuit(nqubits, depth, names)
     if measurements:
         circuit.add(gates.M(0))
-    transpiler = StarConnectivityRouter(middle_qubit=middle_qubit)
-    placer = StarConnectivityPlacer(middle_qubit=middle_qubit)
-    initial_layout = placer(circuit=circuit)
-    transpiled_circuit, final_qubit_map = transpiler(
-        circuit=circuit, initial_layout=initial_layout
-    )
+    original_circuit = circuit.copy()
+    transpiler = StarConnectivityRouter(connectivity)
+    placer = StarConnectivityPlacer(connectivity)
+
+    placer(circuit)
+    transpiled_circuit, final_qubit_map = transpiler(circuit)
     assert_connectivity(connectivity, transpiled_circuit)
-    assert_placement(transpiled_circuit, final_qubit_map)
-    matched_original = Circuit(max(circuit.nqubits, middle_qubit + 1))
-    for gate in circuit.queue:
-        matched_original.add(gate)
+    assert_placement(transpiled_circuit, connectivity)
     assert_circuit_equivalence(
-        original_circuit=matched_original,
+        original_circuit=original_circuit,
         transpiled_circuit=transpiled_circuit,
         final_map=final_qubit_map,
-        initial_map=initial_layout,
     )
 
 
 def test_undo():
     circ = Circuit(4)
-    initial_layout = {"q0": 0, "q1": 1, "q2": 2, "q3": 3}
-    circuit_map = CircuitMap(initial_layout=initial_layout, circuit=circ)
+    circ.wire_names = ["q0", "q1", "q2", "q3"]
+    circuit_map = CircuitMap(circuit=circ)
 
     # Two SWAP gates are added
     circuit_map.update((1, 2))
@@ -572,8 +621,8 @@ def test_circuitmap_no_circuit():
 
 def test_logical_to_physical_setter():
     circ = Circuit(4)
-    initial_layout = {"q0": 0, "q1": 3, "q2": 2, "q3": 1}
-    circuit_map = CircuitMap(initial_layout=initial_layout, circuit=circ)
+    circ.wire_names = ["q0", "q3", "q2", "q1"]
+    circuit_map = CircuitMap(circuit=circ)
     circuit_map.logical_to_physical = [2, 0, 1, 3]
     assert circuit_map.logical_to_physical == [2, 0, 1, 3]
     assert circuit_map.physical_to_logical == [1, 2, 0, 3]

From 2a888adad71f62970bbe3393c250332e730f8db6 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Wed, 23 Oct 2024 09:16:34 +0400
Subject: [PATCH 03/34] fix: update code-examples

---
 doc/source/code-examples/advancedexamples.rst | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/doc/source/code-examples/advancedexamples.rst b/doc/source/code-examples/advancedexamples.rst
index 8a3736b99c..e506bca6c3 100644
--- a/doc/source/code-examples/advancedexamples.rst
+++ b/doc/source/code-examples/advancedexamples.rst
@@ -2103,13 +2103,14 @@ Multiple transpilation steps can be implemented using the :class:`qibo.transpile
     # Define connectivity as nx.Graph
     def star_connectivity():
         chip = nx.Graph()
-        chip.add_nodes_from(list(range(5)))
-        graph_list = [(i, 2) for i in range(5) if i != 2]
-        chip.add_edges_from(graph_list)
+        chip.add_nodes_from(["q0", "q1", "q2", "q3", "q4"])
+        chip.add_edges_from([("q0", "q2"), ("q1", "q2"), ("q2", "q3"), ("q2", "q4")])
         return chip
 
     # Define the circuit
-    circuit = Circuit(2)
+    # wire_names must match nodes in the connectivity graph.
+    # The index in wire_names represents the logical qubit number in the circuit.
+    circuit = Circuit(2, wire_names=["q0", "q1"])
     circuit.add(gates.H(0))
     circuit.add(gates.CZ(0, 1))
 
@@ -2131,13 +2132,10 @@ Multiple transpilation steps can be implemented using the :class:`qibo.transpile
     transpiled_circ, final_layout = custom_pipeline(circuit)
 
     # Optinally call assert_transpiling to check that the final circuit can be executed on hardware
-    # For this test it is necessary to get the initial layout
-    initial_layout = custom_pipeline.get_initial_layout()
     assert_transpiling(
         original_circuit=circuit,
         transpiled_circuit=transpiled_circ,
         connectivity=star_connectivity(),
-        initial_layout=initial_layout,
         final_layout=final_layout,
         native_gates=NativeGates.default()
     )

From 05b6f68bc684584607e6c21fdeb9f7adca800e4b Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Wed, 23 Oct 2024 09:26:12 +0400
Subject: [PATCH 04/34] fix: update comparison in test_bell_state_3q

---
 tests/test_transpiler_router.py | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/tests/test_transpiler_router.py b/tests/test_transpiler_router.py
index 4bcfe949af..c598f1344c 100644
--- a/tests/test_transpiler_router.py
+++ b/tests/test_transpiler_router.py
@@ -155,13 +155,10 @@ def test_bell_state_3q():
 
     backend = NumpyBackend()
     state = np.array([1, 0, 0, 0, 0, 0, 0, 0])
+    original_state = backend.execute_circuit(circuit, state).state()
     target_state = backend.execute_circuit(routed_circuit, state).state()
     target_state = _transpose_qubits(target_state, list(final_map.values()))
-    assert np.all(
-        np.isclose(
-            np.real(target_state).round(1), np.array([0, 0.7, 0, 0, 0.7, 0, 0, 0])
-        )
-    )
+    assert np.all(np.isclose(np.real(original_state), np.real(target_state)))
 
 
 @pytest.mark.parametrize("ngates", [5, 25])

From 876b79c2789a7c66c722442829fd8048ed7d2551 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Wed, 23 Oct 2024 12:00:57 +0400
Subject: [PATCH 05/34] feat: circuit draw with int qubit names

---
 src/qibo/models/circuit.py   |  7 ++++---
 tests/test_models_circuit.py | 18 ++++++++++++++++++
 2 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/src/qibo/models/circuit.py b/src/qibo/models/circuit.py
index b3edcb3006..e4ea88ee9c 100644
--- a/src/qibo/models/circuit.py
+++ b/src/qibo/models/circuit.py
@@ -1280,6 +1280,7 @@ def diagram(self, line_wrap: int = 70, legend: bool = False) -> str:
         """Build the string representation of the circuit diagram."""
         # build string representation of gates
         matrix = [[] for _ in range(self.nqubits)]
+        wire_names = [str(name) for name in self.wire_names]
         idx = [0] * self.nqubits
 
         for gate in self.queue:
@@ -1301,12 +1302,12 @@ def diagram(self, line_wrap: int = 70, legend: bool = False) -> str:
                 matrix[row][col] += "─" * (1 + maxlen - len(matrix[row][col]))
 
         # Print to terminal
-        max_name_len = max(len(name) for name in self.wire_names)
+        max_name_len = max(len(name) for name in wire_names)
         output = ""
         for q in range(self.nqubits):
             output += (
-                self.wire_names[q]
-                + " " * (max_name_len - len(self.wire_names[q]))
+                wire_names[q]
+                + " " * (max_name_len - len(wire_names[q]))
                 + ": ─"
                 + "".join(matrix[q])
                 + "\n"
diff --git a/tests/test_models_circuit.py b/tests/test_models_circuit.py
index 2485be51a3..c423af8428 100644
--- a/tests/test_models_circuit.py
+++ b/tests/test_models_circuit.py
@@ -667,6 +667,24 @@ def test_circuit_draw_wire_names():
     assert str(circuit) == ref
 
 
+def test_circuit_draw_wire_names_int():
+    ref = (
+        "2133: ─H─U1─U1─U1─U1───────────────────────────x───\n"
+        + "8   : ───o──|──|──|──H─U1─U1─U1────────────────|─x─\n"
+        + "2319: ──────o──|──|────o──|──|──H─U1─U1────────|─|─\n"
+        + "0   : ─────────o──|───────o──|────o──|──H─U1───|─x─\n"
+        + "1908: ────────────o──────────o───────o────o──H─x───"
+    )
+    circuit = Circuit(5, wire_names=[2133, 8, 2319, 0, 1908])
+    for i1 in range(5):
+        circuit.add(gates.H(i1))
+        for i2 in range(i1 + 1, 5):
+            circuit.add(gates.CU1(i2, i1, theta=0))
+    circuit.add(gates.SWAP(0, 4))
+    circuit.add(gates.SWAP(1, 3))
+    assert str(circuit) == ref
+
+
 def test_circuit_draw_line_wrap(capsys):
     """Test circuit text draw with line wrap."""
     ref_line_wrap_50 = (

From 02e99457a90a37cbb23f391be981f42812159ae0 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Wed, 23 Oct 2024 12:32:18 +0400
Subject: [PATCH 06/34] fix: placer.py coverage

---
 src/qibo/transpiler/placer.py   |  6 ------
 tests/test_transpiler_placer.py | 20 ++++++++++++++++++++
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/src/qibo/transpiler/placer.py b/src/qibo/transpiler/placer.py
index 405a21dadf..963d47749d 100644
--- a/src/qibo/transpiler/placer.py
+++ b/src/qibo/transpiler/placer.py
@@ -164,10 +164,6 @@ class Custom(Placer):
     def __init__(self, initial_map: Union[list, dict], connectivity: nx.Graph):
         self.initial_map = initial_map
         self.connectivity = connectivity
-        if self.initial_map is None:
-            raise_error(ValueError, "Initial mapping must be provided.")
-        if self.connectivity is None:
-            raise_error(ValueError, "Connectivity graph must be provided.")
 
     def __call__(self, circuit: Circuit):
         """Apply the custom placement to the given circuit.
@@ -198,8 +194,6 @@ class Subgraph(Placer):
 
     def __init__(self, connectivity: nx.Graph):
         self.connectivity = connectivity
-        if self.connectivity is None:
-            raise_error(ValueError, "Connectivity graph must be provided.")
 
     def __call__(self, circuit: Circuit):
         """Find the initial layout of the given circuit using subgraph isomorphism.
diff --git a/tests/test_transpiler_placer.py b/tests/test_transpiler_placer.py
index ac153b8b03..8a2532583c 100644
--- a/tests/test_transpiler_placer.py
+++ b/tests/test_transpiler_placer.py
@@ -53,6 +53,14 @@ def test_assert_placement_false(qubits, names):
         assert_placement(circuit, connectivity)
 
 
+@pytest.mark.parametrize("qubits", [10, 1])
+def test_assert_placement_error(qubits):
+    connectivity = star_connectivity()
+    circuit = Circuit(qubits)
+    with pytest.raises(PlacementError):
+        assert_placement(circuit, connectivity)
+
+
 @pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
 def test_mapping_consistency(names):
     assert_mapping_consistency(names, star_connectivity(names))
@@ -106,6 +114,13 @@ def test_trivial():
     assert_placement(circuit, connectivity)
 
 
+def test_trivial_error():
+    connectivity = star_connectivity()
+    placer = Trivial(connectivity=connectivity)
+    with pytest.raises(ValueError):
+        placer()
+
+
 def test_trivial_restricted():
     names = ["q0", "q2"]
     circuit = Circuit(2, wire_names=names)
@@ -313,3 +328,8 @@ def test_star_connectivity_placer_error(first):
     placer = StarConnectivityPlacer(connectivity)
     with pytest.raises(PlacementError):
         placer(circ)
+
+    chip = nx.Graph()
+    chip.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 4)])
+    with pytest.raises(ValueError):
+        StarConnectivityPlacer(chip)

From 05f36e70a322af283c38cb034f44c5f19d33f549 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Wed, 23 Oct 2024 12:41:32 +0400
Subject: [PATCH 07/34] fix: circuit.py coverage

---
 tests/test_models_circuit.py | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/tests/test_models_circuit.py b/tests/test_models_circuit.py
index c423af8428..6c5864981a 100644
--- a/tests/test_models_circuit.py
+++ b/tests/test_models_circuit.py
@@ -636,7 +636,12 @@ def test_circuit_draw():
     assert str(circuit) == ref
 
 
-def test_circuit_wire_names_errors():
+def test_circuit_wire_names():
+    circuit = Circuit(5)
+    assert circuit.wire_names == ["q0", "q1", "q2", "q3", "q4"]
+    circuit = Circuit(5, wire_names={"q1": 3, "q3": 1, "q2": 4, "q4": 0, "q0": 2})
+    assert circuit.wire_names == ["q4", "q3", "q0", "q1", "q2"]
+
     with pytest.raises(TypeError):
         circuit = Circuit(5, wire_names=1)
     with pytest.raises(ValueError):
@@ -644,7 +649,7 @@ def test_circuit_wire_names_errors():
     with pytest.raises(ValueError):
         circuit = Circuit(2, wire_names={"q0": "1", "q1": 2})
     with pytest.raises(ValueError):
-        circuit = Circuit(2, wire_names={"q0": 4, "q1": 5, "q2": 6})
+        circuit = Circuit(3, wire_names={"q0": 4, "q1": 5, "q2": 6})
 
 
 def test_circuit_draw_wire_names():

From 01b667d65a1d1323bfc7da26f573bbbd67c8b9f9 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Wed, 23 Oct 2024 12:44:39 +0400
Subject: [PATCH 08/34] fix: router.py coverage

---
 tests/test_transpiler_router.py | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/tests/test_transpiler_router.py b/tests/test_transpiler_router.py
index c598f1344c..8583d9577b 100644
--- a/tests/test_transpiler_router.py
+++ b/tests/test_transpiler_router.py
@@ -539,6 +539,11 @@ def test_star_error_multi_qubit():
     with pytest.raises(ConnectivityError):
         transpiled, hardware_qubits = transpiler(circuit=circuit)
 
+    chip = nx.Graph()
+    chip.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 4)])
+    with pytest.raises(ValueError):
+        StarConnectivityRouter(chip)
+
 
 # @pytest.mark.parametrize("nqubits", [1, 3, 5])
 @pytest.mark.parametrize("nqubits", [5])

From 4e21132656e3d1c9a5dc0999ba9929428a91740e Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Thu, 24 Oct 2024 12:50:15 +0400
Subject: [PATCH 09/34] fix: remove dead codes

---
 src/qibo/models/circuit.py      |  1 -
 src/qibo/transpiler/pipeline.py | 10 ----------
 src/qibo/transpiler/placer.py   | 15 +--------------
 3 files changed, 1 insertion(+), 25 deletions(-)

diff --git a/src/qibo/models/circuit.py b/src/qibo/models/circuit.py
index e4ea88ee9c..48523eb6cf 100644
--- a/src/qibo/models/circuit.py
+++ b/src/qibo/models/circuit.py
@@ -301,7 +301,6 @@ def wire_names(self, wire_names: Union[list, dict]):
                 )
 
             self._wire_names = wire_names.copy()
-            # self._wire_names = wire_names
         elif isinstance(wire_names, dict):
             if len(wire_names.keys()) > self.nqubits:
                 raise_error(
diff --git a/src/qibo/transpiler/pipeline.py b/src/qibo/transpiler/pipeline.py
index cdbe2a8567..c2f9e2c26a 100644
--- a/src/qibo/transpiler/pipeline.py
+++ b/src/qibo/transpiler/pipeline.py
@@ -54,15 +54,6 @@ def assert_circuit_equivalence(
             for _ in range(ntests)
         ]
 
-    # original: list = original_circuit.wire_names
-    # transpiled: list = transpiled_circuit.wire_names
-    # initial_map = [0, 1, 2, 3, 4]
-    # initial_map = [original.index(qubit) for qubit in transpiled]
-    # reordered_test_states = []
-    # reordered_test_states = [
-    #     _transpose_qubits(initial_state, initial_map) for initial_state in test_states
-    # ]
-
     ordering = list(final_map.values())
 
     for i, state in enumerate(test_states):
@@ -70,7 +61,6 @@ def assert_circuit_equivalence(
             original_circuit, initial_state=state
         ).state()
         final_state = backend.execute_circuit(
-            # transpiled_circuit, initial_state=reordered_test_states[i]
             transpiled_circuit,
             initial_state=state,
         ).state()
diff --git a/src/qibo/transpiler/placer.py b/src/qibo/transpiler/placer.py
index 963d47749d..f1ad7c6005 100644
--- a/src/qibo/transpiler/placer.py
+++ b/src/qibo/transpiler/placer.py
@@ -201,9 +201,6 @@ def __call__(self, circuit: Circuit):
 
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
-
-        Returns:
-            (dict): physical to logical qubit mapping.
         """
         gates_qubits_pairs = _find_gates_qubits_pairs(circuit)
         if len(gates_qubits_pairs) < 3:
@@ -236,8 +233,6 @@ def __call__(self, circuit: Circuit):
                 break
 
         circuit.wire_names = sorted(result.mapping, key=lambda k: result.mapping[k])
-        # sorted_result = dict(sorted(result.mapping.items()))
-        # circuit.wire_names = sorted(sorted_result, key=sorted_result.get)
 
 
 class Random(Placer):
@@ -264,9 +259,6 @@ def __call__(self, circuit):
 
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): Circuit to be transpiled.
-
-        Returns:
-            (dict): physical-to-logical qubit mapping.
         """
         _, local_state = _check_backend_and_local_state(self.seed, backend=None)
         gates_qubits_pairs = _find_gates_qubits_pairs(circuit)
@@ -352,15 +344,10 @@ def __call__(self, circuit: Circuit):
 
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
-
-        Returns:
-            (dict): physical to logical qubit mapping.
         """
         self.routing_algorithm.connectivity = self.connectivity
         new_circuit = self._assemble_circuit(circuit)
-        final_placement = self._routing_step(new_circuit)
-
-        # return final_placement
+        self._routing_step(new_circuit)
 
     def _assemble_circuit(self, circuit: Circuit):
         """Assemble a single circuit to apply Reverse Traversal placement based on depth.

From 12bf8b0e870bc73ed78848b5f33fa42f0ce3225e Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Thu, 24 Oct 2024 13:35:13 +0400
Subject: [PATCH 10/34] fix: refactor connectivity graphs in test files

---
 tests/conftest.py                  |  49 ++++++++++
 tests/test_transpiler_optimizer.py |  18 +---
 tests/test_transpiler_pipeline.py  |  36 +++-----
 tests/test_transpiler_placer.py    |  64 ++++++-------
 tests/test_transpiler_router.py    | 139 ++++++++++++++++-------------
 5 files changed, 170 insertions(+), 136 deletions(-)

diff --git a/tests/conftest.py b/tests/conftest.py
index db51f97456..5aaaf1a129 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -5,6 +5,7 @@
 
 import sys
 
+import networkx as nx
 import pytest
 
 from qibo.backends import _Global, construct_backend
@@ -81,6 +82,54 @@ def clear():
     _Global._transpiler = None
 
 
+@pytest.fixture
+def star_connectivity():
+    def _star_connectivity(names=["q0", "q1", "q2", "q3", "q4"], middle_qubit_idx=2):
+        chip = nx.Graph()
+        chip.add_nodes_from(names)
+        graph_list = [
+            (names[i], names[middle_qubit_idx])
+            for i in range(len(names))
+            if i != middle_qubit_idx
+        ]
+        chip.add_edges_from(graph_list)
+        return chip
+
+    return _star_connectivity
+
+
+@pytest.fixture
+def grid_connectivity():
+    def _grid_connectivity(names=["q0", "q1", "q2", "q3", "q4"]):
+        chip = nx.Graph()
+        chip.add_nodes_from(names)
+        graph_list = [
+            (names[0], names[1]),
+            (names[1], names[2]),
+            (names[2], names[3]),
+            (names[3], names[0]),
+            (names[0], names[4]),
+        ]
+        chip.add_edges_from(graph_list)
+        return chip
+
+    return _grid_connectivity
+
+
+@pytest.fixture
+def line_connectivity():
+    def _line_connectivity(n, names=None):
+        if names is None:
+            names = [f"q{i}" for i in range(n)]
+        chip = nx.Graph()
+        chip.add_nodes_from(names)
+        graph_list = [(names[i], names[i + 1]) for i in range(n - 1)]
+        chip.add_edges_from(graph_list)
+        return chip
+
+    return _line_connectivity
+
+
 def pytest_generate_tests(metafunc):
     module_name = metafunc.module.__name__
 
diff --git a/tests/test_transpiler_optimizer.py b/tests/test_transpiler_optimizer.py
index 457e25ecf7..cd55115a9b 100644
--- a/tests/test_transpiler_optimizer.py
+++ b/tests/test_transpiler_optimizer.py
@@ -6,26 +6,14 @@
 from qibo.transpiler.optimizer import Preprocessing, Rearrange
 
 
-def star_connectivity(names=["q0", "q1", "q2", "q3", "q4"], middle_qubit_idx=2):
-    chip = nx.Graph()
-    chip.add_nodes_from(names)
-    graph_list = [
-        (names[i], names[middle_qubit_idx])
-        for i in range(len(names))
-        if i != middle_qubit_idx
-    ]
-    chip.add_edges_from(graph_list)
-    return chip
-
-
-def test_preprocessing_error():
+def test_preprocessing_error(star_connectivity):
     circ = Circuit(7)
     preprocesser = Preprocessing(connectivity=star_connectivity())
     with pytest.raises(ValueError):
         new_circuit = preprocesser(circuit=circ)
 
 
-def test_preprocessing_same():
+def test_preprocessing_same(star_connectivity):
     circ = Circuit(5)
     circ.add(gates.CNOT(0, 1))
     preprocesser = Preprocessing(connectivity=star_connectivity())
@@ -33,7 +21,7 @@ def test_preprocessing_same():
     assert new_circuit.ngates == 1
 
 
-def test_preprocessing_add():
+def test_preprocessing_add(star_connectivity):
     circ = Circuit(3)
     circ.add(gates.CNOT(0, 1))
     preprocesser = Preprocessing(connectivity=star_connectivity())
diff --git a/tests/test_transpiler_pipeline.py b/tests/test_transpiler_pipeline.py
index 82fe4c9419..4affd8026a 100644
--- a/tests/test_transpiler_pipeline.py
+++ b/tests/test_transpiler_pipeline.py
@@ -51,31 +51,19 @@ def generate_random_circuit(nqubits, ngates, names=None, seed=42):
     return circuit
 
 
-def star_connectivity(names=["q0", "q1", "q2", "q3", "q4"], middle_qubit_idx=2):
-    chip = nx.Graph()
-    chip.add_nodes_from(names)
-    graph_list = [
-        (names[i], names[middle_qubit_idx])
-        for i in range(len(names))
-        if i != middle_qubit_idx
-    ]
-    chip.add_edges_from(graph_list)
-    return chip
-
-
-def test_restrict_qubits_error_no_subset():
+def test_restrict_qubits_error_no_subset(star_connectivity):
     with pytest.raises(ConnectivityError) as excinfo:
         restrict_connectivity_qubits(star_connectivity(), ["q0", "q1", "q5"])
     assert "Some qubits are not in the original connectivity." in str(excinfo.value)
 
 
-def test_restrict_qubits_error_not_connected():
+def test_restrict_qubits_error_not_connected(star_connectivity):
     with pytest.raises(ConnectivityError) as excinfo:
         restrict_connectivity_qubits(star_connectivity(), ["q0", "q1"])
     assert "New connectivity graph is not connected." in str(excinfo.value)
 
 
-def test_restrict_qubits():
+def test_restrict_qubits(star_connectivity):
     new_connectivity = restrict_connectivity_qubits(
         star_connectivity(["A", "B", "C", "D", "E"]), ["A", "B", "C"]
     )
@@ -85,7 +73,7 @@ def test_restrict_qubits():
 
 @pytest.mark.parametrize("ngates", [5, 10, 50])
 @pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
-def test_pipeline_default(ngates, names):
+def test_pipeline_default(ngates, names, star_connectivity):
     circ = generate_random_circuit(nqubits=5, ngates=ngates, names=names)
     connectivity = star_connectivity(names)
 
@@ -133,7 +121,7 @@ def test_assert_circuit_equivalence_false():
         assert_circuit_equivalence(circ1, circ2, final_map=final_map)
 
 
-def test_int_qubit_names_default():
+def test_int_qubit_names_default(star_connectivity):
     names = [1244, 1532, 2315, 6563, 8901]
     circ = Circuit(5, wire_names=names)
     connectivity = star_connectivity(names)
@@ -156,7 +144,7 @@ def test_error_connectivity():
 
 
 @pytest.mark.parametrize("qubits", [3, 5])
-def test_is_satisfied(qubits):
+def test_is_satisfied(qubits, star_connectivity):
     default_transpiler = Passes(passes=None, connectivity=star_connectivity())
     circuit = Circuit(qubits)
     circuit.wire_names = ["q0", "q1", "q2", "q3", "q4"][:qubits]
@@ -165,7 +153,7 @@ def test_is_satisfied(qubits):
     assert default_transpiler.is_satisfied(circuit)
 
 
-def test_is_satisfied_false_decomposition():
+def test_is_satisfied_false_decomposition(star_connectivity):
     default_transpiler = Passes(passes=None, connectivity=star_connectivity())
     circuit = Circuit(5)
     circuit.add(gates.CZ(0, 2))
@@ -173,7 +161,7 @@ def test_is_satisfied_false_decomposition():
     assert not default_transpiler.is_satisfied(circuit)
 
 
-def test_is_satisfied_false_connectivity():
+def test_is_satisfied_false_connectivity(star_connectivity):
     default_transpiler = Passes(passes=None, connectivity=star_connectivity())
     circuit = Circuit(5)
     circuit.add(gates.CZ(0, 1))
@@ -185,7 +173,7 @@ def test_is_satisfied_false_connectivity():
 @pytest.mark.parametrize("ngates", [5, 20])
 @pytest.mark.parametrize("placer", [Random, Trivial, ReverseTraversal])
 @pytest.mark.parametrize("router", [ShortestPaths, Sabre])
-def test_custom_passes(placer, router, ngates, nqubits):
+def test_custom_passes(placer, router, ngates, nqubits, star_connectivity):
     connectivity = star_connectivity()
     circ = generate_random_circuit(nqubits=nqubits, ngates=ngates)
     custom_passes = []
@@ -222,7 +210,9 @@ def test_custom_passes(placer, router, ngates, nqubits):
 @pytest.mark.parametrize(
     "restrict_names", [["q1", "q2", "q3"], ["q0", "q2", "q4"], ["q4", "q2", "q3"]]
 )
-def test_custom_passes_restrict(ngates, placer, routing, restrict_names):
+def test_custom_passes_restrict(
+    ngates, placer, routing, restrict_names, star_connectivity
+):
     connectivity = star_connectivity()
     circ = generate_random_circuit(nqubits=3, ngates=ngates, names=restrict_names)
     custom_passes = []
@@ -263,7 +253,7 @@ def test_custom_passes_wrong_pass():
         custom_pipeline(circ)
 
 
-def test_int_qubit_names():
+def test_int_qubit_names(star_connectivity):
     names = [980, 123, 45, 9, 210464]
     connectivity = star_connectivity(names)
     transpiler = Passes(
diff --git a/tests/test_transpiler_placer.py b/tests/test_transpiler_placer.py
index 8a2532583c..86295022cb 100644
--- a/tests/test_transpiler_placer.py
+++ b/tests/test_transpiler_placer.py
@@ -19,18 +19,6 @@
 from qibo.transpiler.router import ShortestPaths
 
 
-def star_connectivity(names=["q0", "q1", "q2", "q3", "q4"], middle_qubit_idx=2):
-    chip = nx.Graph()
-    chip.add_nodes_from(names)
-    graph_list = [
-        (names[i], names[middle_qubit_idx])
-        for i in range(len(names))
-        if i != middle_qubit_idx
-    ]
-    chip.add_edges_from(graph_list)
-    return chip
-
-
 def star_circuit(names=["q0", "q1", "q2", "q3", "q4"]):
     circuit = Circuit(5, wire_names=names)
     for i in range(1, 5):
@@ -38,7 +26,7 @@ def star_circuit(names=["q0", "q1", "q2", "q3", "q4"]):
     return circuit
 
 
-def test_assert_placement_true():
+def test_assert_placement_true(star_connectivity):
     circuit = Circuit(5)
     assert_placement(circuit, connectivity=star_connectivity())
 
@@ -46,7 +34,7 @@ def test_assert_placement_true():
 @pytest.mark.parametrize(
     "qubits, names", [(5, ["A", "B", "C", "D", "F"]), (3, ["A", "B", "C"])]
 )
-def test_assert_placement_false(qubits, names):
+def test_assert_placement_false(qubits, names, star_connectivity):
     connectivity = star_connectivity()
     circuit = Circuit(qubits, wire_names=names)
     with pytest.raises(PlacementError):
@@ -54,7 +42,7 @@ def test_assert_placement_false(qubits, names):
 
 
 @pytest.mark.parametrize("qubits", [10, 1])
-def test_assert_placement_error(qubits):
+def test_assert_placement_error(qubits, star_connectivity):
     connectivity = star_connectivity()
     circuit = Circuit(qubits)
     with pytest.raises(PlacementError):
@@ -62,17 +50,17 @@ def test_assert_placement_error(qubits):
 
 
 @pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
-def test_mapping_consistency(names):
+def test_mapping_consistency(names, star_connectivity):
     assert_mapping_consistency(names, star_connectivity(names))
 
 
-def test_mapping_consistency_error():
+def test_mapping_consistency_error(star_connectivity):
     with pytest.raises(PlacementError):
         assert_mapping_consistency(["A", "B", "C", "D", "F"], star_connectivity())
 
 
 @pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
-def test_mapping_consistency_restricted(names):
+def test_mapping_consistency_restricted(names, star_connectivity):
     connectivity = star_connectivity(names)
     on_qubit = [names[0], names[2]]
     restricted_connectivity = restrict_connectivity_qubits(connectivity, on_qubit)
@@ -80,7 +68,7 @@ def test_mapping_consistency_restricted(names):
 
 
 @pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
-def test_mapping_consistency_restricted_error(names):
+def test_mapping_consistency_restricted_error(names, star_connectivity):
     connectivity = star_connectivity(names)
     on_qubit = [names[0], names[2]]
     restricted_connectivity = restrict_connectivity_qubits(connectivity, on_qubit)
@@ -104,7 +92,7 @@ def test_gates_qubits_pairs_error():
         gates_qubits_pairs = _find_gates_qubits_pairs(circuit)
 
 
-def test_trivial():
+def test_trivial(star_connectivity):
     names = ["q4", "q3", "q2", "q1", "q0"]
     circuit = Circuit(5, wire_names=names)
     connectivity = star_connectivity(names)
@@ -114,14 +102,14 @@ def test_trivial():
     assert_placement(circuit, connectivity)
 
 
-def test_trivial_error():
+def test_trivial_error(star_connectivity):
     connectivity = star_connectivity()
     placer = Trivial(connectivity=connectivity)
     with pytest.raises(ValueError):
         placer()
 
 
-def test_trivial_restricted():
+def test_trivial_restricted(star_connectivity):
     names = ["q0", "q2"]
     circuit = Circuit(2, wire_names=names)
     connectivity = star_connectivity()
@@ -136,7 +124,7 @@ def test_trivial_restricted():
     "custom_layout",
     [["E", "D", "C", "B", "A"], {"E": 0, "D": 1, "C": 2, "B": 3, "A": 4}],
 )
-def test_custom(custom_layout):
+def test_custom(custom_layout, star_connectivity):
     circuit = Circuit(5)
     connectivity = star_connectivity(["A", "B", "C", "D", "E"])
     placer = Custom(connectivity=connectivity, initial_map=custom_layout)
@@ -147,7 +135,7 @@ def test_custom(custom_layout):
 @pytest.mark.parametrize(
     "custom_layout", [[4, 3, 2, 1, 0], {4: 0, 3: 1, 2: 2, 1: 3, 0: 4}]
 )
-def test_custom_int(custom_layout):
+def test_custom_int(custom_layout, star_connectivity):
     names = [0, 1, 2, 3, 4]
     circuit = Circuit(5, wire_names=names)
     connectivity = star_connectivity(names)
@@ -157,7 +145,7 @@ def test_custom_int(custom_layout):
 
 
 @pytest.mark.parametrize("custom_layout", [["D", "C"], {"C": 1, "D": 0}])
-def test_custom_restricted(custom_layout):
+def test_custom_restricted(custom_layout, star_connectivity):
     circuit = Circuit(2, wire_names=["C", "D"])
     connectivity = star_connectivity(["A", "B", "C", "D", "E"])
     restricted_connectivity = restrict_connectivity_qubits(connectivity, ["C", "D"])
@@ -167,7 +155,7 @@ def test_custom_restricted(custom_layout):
     assert_placement(circuit, restricted_connectivity)
 
 
-def test_custom_error_circuit():
+def test_custom_error_circuit(star_connectivity):
     circuit = Circuit(3)
     custom_layout = [4, 3, 2, 1, 0]
     connectivity = star_connectivity(names=custom_layout)
@@ -176,7 +164,7 @@ def test_custom_error_circuit():
         placer(circuit)
 
 
-def test_custom_error_type():
+def test_custom_error_type(star_connectivity):
     circuit = Circuit(5)
     connectivity = star_connectivity()
     placer = Custom(connectivity=connectivity, initial_map=1)
@@ -184,7 +172,7 @@ def test_custom_error_type():
         placer(circuit)
 
 
-def test_subgraph_perfect():
+def test_subgraph_perfect(star_connectivity):
     connectivity = star_connectivity()
     placer = Subgraph(connectivity=connectivity)
     circuit = star_circuit()
@@ -207,7 +195,7 @@ def imperfect_circuit():
     return circuit
 
 
-def test_subgraph_non_perfect():
+def test_subgraph_non_perfect(star_connectivity):
     connectivity = star_connectivity()
     placer = Subgraph(connectivity=connectivity)
     circuit = imperfect_circuit()
@@ -215,7 +203,7 @@ def test_subgraph_non_perfect():
     assert_placement(circuit, connectivity)
 
 
-def test_subgraph_error():
+def test_subgraph_error(star_connectivity):
     connectivity = star_connectivity()
     placer = Subgraph(connectivity=connectivity)
     circuit = Circuit(5)
@@ -223,7 +211,7 @@ def test_subgraph_error():
         placer(circuit)
 
 
-def test_subgraph_restricted():
+def test_subgraph_restricted(star_connectivity):
     circuit = Circuit(4)
     circuit.add(gates.CNOT(0, 3))
     circuit.add(gates.CNOT(0, 1))
@@ -242,7 +230,7 @@ def test_subgraph_restricted():
 
 @pytest.mark.parametrize("reps", [1, 10, 100])
 @pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
-def test_random(reps, names):
+def test_random(reps, names, star_connectivity):
     connectivity = star_connectivity(names)
     placer = Random(connectivity=connectivity, samples=reps)
     circuit = star_circuit(names=names)
@@ -250,7 +238,7 @@ def test_random(reps, names):
     assert_placement(circuit, connectivity)
 
 
-def test_random_restricted():
+def test_random_restricted(star_connectivity):
     names = [0, 1, 2, 3, 4]
     circuit = Circuit(4, wire_names=names[:4])
     circuit.add(gates.CNOT(1, 3))
@@ -268,7 +256,7 @@ def test_random_restricted():
 
 @pytest.mark.parametrize("ngates", [None, 5, 13])
 @pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
-def test_reverse_traversal(ngates, names):
+def test_reverse_traversal(ngates, names, star_connectivity):
     circuit = star_circuit(names=names)
     connectivity = star_connectivity(names=names)
     routing = ShortestPaths(connectivity=connectivity)
@@ -277,7 +265,7 @@ def test_reverse_traversal(ngates, names):
     assert_placement(circuit, connectivity)
 
 
-def test_reverse_traversal_no_gates():
+def test_reverse_traversal_no_gates(star_connectivity):
     connectivity = star_connectivity()
     routing = ShortestPaths(connectivity=connectivity)
     placer = ReverseTraversal(connectivity, routing, depth=10)
@@ -286,7 +274,7 @@ def test_reverse_traversal_no_gates():
         placer(circuit)
 
 
-def test_reverse_traversal_restricted():
+def test_reverse_traversal_restricted(star_connectivity):
     circuit = Circuit(4)
     circuit.add(gates.CNOT(1, 3))
     circuit.add(gates.CNOT(2, 1))
@@ -306,7 +294,7 @@ def test_reverse_traversal_restricted():
     assert_placement(circuit, restricted_connectivity)
 
 
-def test_star_connectivity_placer():
+def test_star_connectivity_placer(star_connectivity):
     circ = Circuit(5)
     circ.add(gates.CZ(0, 1))
     circ.add(gates.CZ(1, 2))
@@ -319,7 +307,7 @@ def test_star_connectivity_placer():
 
 
 @pytest.mark.parametrize("first", [True, False])
-def test_star_connectivity_placer_error(first):
+def test_star_connectivity_placer_error(first, star_connectivity):
     circ = Circuit(5)
     if first:
         circ.add(gates.CZ(0, 1))
diff --git a/tests/test_transpiler_router.py b/tests/test_transpiler_router.py
index 8583d9577b..6d10dfd5b1 100644
--- a/tests/test_transpiler_router.py
+++ b/tests/test_transpiler_router.py
@@ -32,42 +32,6 @@
 )
 
 
-def star_connectivity(names=["q0", "q1", "q2", "q3", "q4"], middle_qubit_idx=2):
-    chip = nx.Graph()
-    chip.add_nodes_from(names)
-    graph_list = [
-        (names[i], names[middle_qubit_idx])
-        for i in range(len(names))
-        if i != middle_qubit_idx
-    ]
-    chip.add_edges_from(graph_list)
-    return chip
-
-
-def grid_connectivity(names=["q0", "q1", "q2", "q3", "q4"]):
-    chip = nx.Graph()
-    chip.add_nodes_from(names)
-    graph_list = [
-        (names[0], names[1]),
-        (names[1], names[2]),
-        (names[2], names[3]),
-        (names[3], names[0]),
-        (names[0], names[4]),
-    ]
-    chip.add_edges_from(graph_list)
-    return chip
-
-
-def line_connectivity(n, names):
-    if names is None:
-        names = [f"q{i}" for i in range(n)]
-    chip = nx.Graph()
-    chip.add_nodes_from(names)
-    graph_list = [(names[i], names[i + 1]) for i in range(n - 1)]
-    chip.add_edges_from(graph_list)
-    return chip
-
-
 def generate_random_circuit(nqubits, ngates, names=None, seed=42):
     """Generate a random circuit with RX and CZ gates."""
     np.random.seed(seed)
@@ -120,26 +84,26 @@ def matched_circuit(names):
     return circuit
 
 
-def test_assert_connectivity():
+def test_assert_connectivity(star_connectivity):
     names = ["A", "B", "C", "D", "E"]
     assert_connectivity(star_connectivity(names), matched_circuit(names))
 
 
-def test_assert_connectivity_false():
+def test_assert_connectivity_false(star_connectivity):
     circuit = Circuit(5)
     circuit.add(gates.CZ(0, 1))
     with pytest.raises(ConnectivityError):
         assert_connectivity(star_connectivity(), circuit)
 
 
-def test_assert_connectivity_3q():
+def test_assert_connectivity_3q(star_connectivity):
     circuit = Circuit(5)
     circuit.add(gates.TOFFOLI(0, 1, 2))
     with pytest.raises(ConnectivityError):
         assert_connectivity(star_connectivity(), circuit)
 
 
-def test_bell_state_3q():
+def test_bell_state_3q(line_connectivity):
     from qibo.transpiler.pipeline import _transpose_qubits
 
     circuit = Circuit(3)
@@ -163,10 +127,33 @@ def test_bell_state_3q():
 
 @pytest.mark.parametrize("ngates", [5, 25])
 @pytest.mark.parametrize("placer", [Trivial, Random])
-@pytest.mark.parametrize("connectivity", [star_connectivity(), grid_connectivity()])
-def test_random_circuits_5q(ngates, placer, connectivity):
-    placer = placer(connectivity=connectivity)
-    transpiler = ShortestPaths(connectivity=connectivity)
+def test_random_circuits_5q(ngates, placer, star_connectivity):
+    connectivity = star_connectivity()
+    placer = placer(connectivity)
+    transpiler = ShortestPaths(connectivity)
+
+    circuit = generate_random_circuit(nqubits=5, ngates=ngates)
+    original_circuit = circuit.copy()
+    placer(circuit)
+    transpiled_circuit, final_qubit_map = transpiler(circuit)
+
+    assert transpiler.added_swaps >= 0
+    assert_connectivity(connectivity, transpiled_circuit)
+    assert_placement(transpiled_circuit, connectivity)
+    assert ngates + transpiler.added_swaps == transpiled_circuit.ngates
+    assert_circuit_equivalence(
+        original_circuit=original_circuit,
+        transpiled_circuit=transpiled_circuit,
+        final_map=final_qubit_map,
+    )
+
+
+@pytest.mark.parametrize("ngates", [5, 25])
+@pytest.mark.parametrize("placer", [Trivial, Random])
+def test_random_circuits_5q_grid(ngates, placer, grid_connectivity):
+    connectivity = grid_connectivity()
+    placer = placer(connectivity)
+    transpiler = ShortestPaths(connectivity)
 
     circuit = generate_random_circuit(nqubits=5, ngates=ngates)
     original_circuit = circuit.copy()
@@ -186,7 +173,7 @@ def test_random_circuits_5q(ngates, placer, connectivity):
 
 @pytest.mark.parametrize("nqubits", [11, 12, 13, 14, 15])
 @pytest.mark.parametrize("ngates", [30, 50])
-def test_random_circuits_15q_50g(nqubits, ngates):
+def test_random_circuits_15q_50g(nqubits, ngates, line_connectivity):
     connectivity = line_connectivity(nqubits, None)
     placer = Random(connectivity=connectivity)
     transpiler = Sabre(connectivity=connectivity)
@@ -207,7 +194,7 @@ def test_random_circuits_15q_50g(nqubits, ngates):
     )
 
 
-def test_star_circuit():
+def test_star_circuit(star_connectivity):
     connectivity = star_connectivity()
     circuit = star_circuit()
     placer = Subgraph(connectivity=connectivity)
@@ -226,7 +213,7 @@ def test_star_circuit():
     )
 
 
-def test_star_circuit_custom_map():
+def test_star_circuit_custom_map(star_connectivity):
     connectivity = star_connectivity()
     circuit = star_circuit()
     placer = Custom(
@@ -247,7 +234,7 @@ def test_star_circuit_custom_map():
     )
 
 
-def test_routing_with_measurements():
+def test_routing_with_measurements(star_connectivity):
     connectivity = star_connectivity()
     circuit = Circuit(5)
     circuit.add(gates.CNOT(0, 1))
@@ -268,7 +255,7 @@ def test_routing_with_measurements():
     )
 
 
-def test_sabre_looping():
+def test_sabre_looping(line_connectivity):
     # Setup where the looping occurs
     # Line connectivity, gates with gate_array, Trivial placer
 
@@ -304,7 +291,7 @@ def test_sabre_looping():
     )
 
 
-def test_sabre_shortest_path_routing():
+def test_sabre_shortest_path_routing(line_connectivity):
     gate_array = [(0, 9), (5, 9), (2, 8)]  # The gate (2, 8) should be routed next
 
     loop_circ = Circuit(10)
@@ -411,7 +398,7 @@ def test_circuit_map():
     "names",
     [["q0", "q1", "q2", "q3", "q4"], [0, 1, 2, 3, 4], ["A", "B", "C", "D", "E"]],
 )
-def test_sabre_matched(names):
+def test_sabre_matched(names, star_connectivity):
     connectivity = star_connectivity(names=names)
     circuit = matched_circuit(names)
     original_circuit = circuit.copy()
@@ -431,7 +418,7 @@ def test_sabre_matched(names):
 
 
 @pytest.mark.parametrize("seed", [42])
-def test_sabre_simple(seed):
+def test_sabre_simple(seed, star_connectivity):
     connectivity = star_connectivity()
     circ = Circuit(5)
     circ.add(gates.CZ(0, 1))
@@ -459,14 +446,44 @@ def test_sabre_simple(seed):
 @pytest.mark.parametrize("look", [0, 5])
 @pytest.mark.parametrize("decay", [0.5, 1.0])
 @pytest.mark.parametrize("placer_param", [Trivial, Random])
-@pytest.mark.parametrize("connectivity", [star_connectivity(), grid_connectivity()])
-def test_sabre_random_circuits(n_gates, look, decay, placer_param, connectivity):
+def test_sabre_random_circuits(n_gates, look, decay, placer_param, star_connectivity):
+    connectivity = star_connectivity()
+    circuit = generate_random_circuit(nqubits=5, ngates=n_gates)
+    measurement = gates.M(*range(5))
+    circuit.add(measurement)
+    original_circuit = circuit.copy()
+    placer = placer_param(connectivity)
+    router = Sabre(connectivity, lookahead=look, decay_lookahead=decay)
+
+    placer(circuit)
+    transpiled_circuit, final_qubit_map = router(circuit)
+
+    assert router.added_swaps >= 0
+    assert_connectivity(connectivity, transpiled_circuit)
+    assert_placement(transpiled_circuit, connectivity)
+    assert n_gates + router.added_swaps + 1 == transpiled_circuit.ngates
+    assert_circuit_equivalence(
+        original_circuit=original_circuit,
+        transpiled_circuit=transpiled_circuit,
+        final_map=final_qubit_map,
+    )
+    assert transpiled_circuit.queue[-1].register_name == measurement.register_name
+
+
+@pytest.mark.parametrize("n_gates", [10, 40])
+@pytest.mark.parametrize("look", [0, 5])
+@pytest.mark.parametrize("decay", [0.5, 1.0])
+@pytest.mark.parametrize("placer_param", [Trivial, Random])
+def test_sabre_random_circuits_grid(
+    n_gates, look, decay, placer_param, grid_connectivity
+):
+    connectivity = grid_connectivity()
     circuit = generate_random_circuit(nqubits=5, ngates=n_gates)
     measurement = gates.M(*range(5))
     circuit.add(measurement)
     original_circuit = circuit.copy()
-    placer = placer_param(connectivity=connectivity)
-    router = Sabre(connectivity=connectivity, lookahead=look, decay_lookahead=decay)
+    placer = placer_param(connectivity)
+    router = Sabre(connectivity, lookahead=look, decay_lookahead=decay)
 
     placer(circuit)
     transpiled_circuit, final_qubit_map = router(circuit)
@@ -483,7 +500,7 @@ def test_sabre_random_circuits(n_gates, look, decay, placer_param, connectivity)
     assert transpiled_circuit.queue[-1].register_name == measurement.register_name
 
 
-def test_sabre_memory_map():
+def test_sabre_memory_map(star_connectivity):
     placer = Trivial()
     layout_circ = Circuit(5)
     placer(layout_circ)
@@ -509,7 +526,7 @@ def test_sabre_intermediate_measurements():
 
 
 @pytest.mark.parametrize("router_algorithm", [Sabre, ShortestPaths])
-def test_restrict_qubits(router_algorithm):
+def test_restrict_qubits(router_algorithm, star_connectivity):
     circ = Circuit(3)
     circ.add(gates.CZ(0, 1))
     circ.add(gates.CZ(0, 2))
@@ -531,7 +548,7 @@ def test_restrict_qubits(router_algorithm):
     assert routed_circ.wire_names == ["q0", "q3", "q2"]
 
 
-def test_star_error_multi_qubit():
+def test_star_error_multi_qubit(star_connectivity):
     circuit = Circuit(3)
     circuit.add(gates.TOFFOLI(0, 1, 2))
     connectivity = star_connectivity(middle_qubit_idx=2)
@@ -555,7 +572,9 @@ def test_star_error_multi_qubit():
     "names",
     [["q0", "q1", "q2", "q3", "q4"], [0, 1, 2, 3, 4], ["A", "B", "C", "D", "E"]],
 )
-def test_star_router(nqubits, depth, middle_qubit, measurements, unitaries, names):
+def test_star_router(
+    nqubits, depth, middle_qubit, measurements, unitaries, names, star_connectivity
+):
     unitary_dim = min(2, nqubits)
     connectivity = star_connectivity(names=names, middle_qubit_idx=middle_qubit)
     if unitaries:

From 36c1348f588bfb2aa46789523cb97eb7b37c4a9f Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Thu, 24 Oct 2024 13:55:45 +0400
Subject: [PATCH 11/34] fix: return type of a router

---
 src/qibo/transpiler/abstract.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/qibo/transpiler/abstract.py b/src/qibo/transpiler/abstract.py
index e24f7acead..11e1641759 100644
--- a/src/qibo/transpiler/abstract.py
+++ b/src/qibo/transpiler/abstract.py
@@ -1,4 +1,5 @@
 from abc import ABC, abstractmethod
+from typing import Tuple
 
 import networkx as nx
 
@@ -25,7 +26,7 @@ def __init__(self, connectivity: nx.Graph, *args):
         """A router implements the mapping of a circuit on a specific hardware."""
 
     @abstractmethod
-    def __call__(self, circuit: Circuit, *args) -> Circuit:
+    def __call__(self, circuit: Circuit, *args) -> Tuple[Circuit, dict]:
         """Match circuit to hardware connectivity.
 
         Args:

From f19dc6ed1ecb1e624ba6c4bbc63f72c3d3f56f20 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Fri, 25 Oct 2024 11:31:04 +0400
Subject: [PATCH 12/34] fix: minor changes

---
 src/qibo/models/circuit.py       | 3 +--
 src/qibo/transpiler/optimizer.py | 6 +++---
 src/qibo/transpiler/placer.py    | 2 --
 tests/test_transpiler_placer.py  | 7 -------
 4 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/src/qibo/models/circuit.py b/src/qibo/models/circuit.py
index 48523eb6cf..08aa4e639d 100644
--- a/src/qibo/models/circuit.py
+++ b/src/qibo/models/circuit.py
@@ -407,8 +407,7 @@ def light_cone(self, *qubits):
         qubit_map = {q: i for i, q in enumerate(sorted(qubits))}
         kwargs = dict(self.init_kwargs)
         kwargs["nqubits"] = len(qubits)
-        new_wire_names = [self.wire_names[q] for q in list(sorted(qubits))]
-        kwargs["wire_names"] = new_wire_names
+        kwargs["wire_names"] = [self.wire_names[q] for q in list(sorted(qubits))]
         circuit = self.__class__(**kwargs)
         circuit.add(gate.on_qubits(qubit_map) for gate in reversed(list_of_gates))
         return circuit, qubit_map
diff --git a/src/qibo/transpiler/optimizer.py b/src/qibo/transpiler/optimizer.py
index 2ba05895e3..a30f117757 100644
--- a/src/qibo/transpiler/optimizer.py
+++ b/src/qibo/transpiler/optimizer.py
@@ -27,9 +27,9 @@ def __call__(self, circuit: Circuit) -> Circuit:
             )
         if logical_qubits == physical_qubits:
             return circuit
-        new_wire_names = circuit.wire_names.copy() + [
-            name for name in self.connectivity.nodes if name not in circuit.wire_names
-        ]
+        new_wire_names = circuit.wire_names + list(
+            self.connectivity.nodes - circuit.wire_names
+        )
         new_circuit = Circuit(nqubits=physical_qubits, wire_names=new_wire_names)
         for gate in circuit.queue:
             new_circuit.add(gate)
diff --git a/src/qibo/transpiler/placer.py b/src/qibo/transpiler/placer.py
index f1ad7c6005..0e7d1ec136 100644
--- a/src/qibo/transpiler/placer.py
+++ b/src/qibo/transpiler/placer.py
@@ -147,8 +147,6 @@ def __call__(self, circuit: Circuit = None):
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
         """
-        if circuit is None:
-            raise_error(ValueError, "Circuit must be provided.")
         return
 
 
diff --git a/tests/test_transpiler_placer.py b/tests/test_transpiler_placer.py
index 86295022cb..90d4d301f7 100644
--- a/tests/test_transpiler_placer.py
+++ b/tests/test_transpiler_placer.py
@@ -102,13 +102,6 @@ def test_trivial(star_connectivity):
     assert_placement(circuit, connectivity)
 
 
-def test_trivial_error(star_connectivity):
-    connectivity = star_connectivity()
-    placer = Trivial(connectivity=connectivity)
-    with pytest.raises(ValueError):
-        placer()
-
-
 def test_trivial_restricted(star_connectivity):
     names = ["q0", "q2"]
     circuit = Circuit(2, wire_names=names)

From 7534ef24bcb140dc34e1dcf436c0615b6c7adb1b Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Fri, 25 Oct 2024 17:50:46 +0400
Subject: [PATCH 13/34] fix: remove add_nodes_from when setting backend

---
 src/qibo/backends/__init__.py       | 2 --
 src/qibo/models/error_mitigation.py | 2 --
 2 files changed, 4 deletions(-)

diff --git a/src/qibo/backends/__init__.py b/src/qibo/backends/__init__.py
index 1f898a890e..2f64654e8b 100644
--- a/src/qibo/backends/__init__.py
+++ b/src/qibo/backends/__init__.py
@@ -145,8 +145,6 @@ def _default_transpiler(cls):
             and connectivity_edges is not None
         ):
             connectivity = nx.Graph(connectivity_edges)
-            connectivity.add_nodes_from(qubits)
-
             return Passes(
                 connectivity=connectivity,
                 passes=[
diff --git a/src/qibo/models/error_mitigation.py b/src/qibo/models/error_mitigation.py
index c6d72e2c09..b2f5a1c31a 100644
--- a/src/qibo/models/error_mitigation.py
+++ b/src/qibo/models/error_mitigation.py
@@ -1170,10 +1170,8 @@ def _execute_circuit(circuit, qubit_map, noise_model=None, nshots=10000, backend
     if backend is None:  # pragma: no cover
         backend = get_backend()
     elif backend.name == "qibolab":  # pragma: no cover
-        qubits = backend.qubits
         connectivity_edges = backend.connectivity
         connectivity = nx.Graph(connectivity_edges)
-        connectivity.add_nodes_from(qubits)
         transpiler = Passes(
             connectivity=connectivity,
             passes=[Custom(initial_map=qubit_map, connectivity=connectivity)],

From 67fae1f83f12bf6a86c7b2b5bb2b17f259b2c6c9 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Mon, 28 Oct 2024 10:19:35 +0400
Subject: [PATCH 14/34] fix: Circuit remove default wire_names / dict
 wire_names

---
 src/qibo/models/circuit.py                   | 41 +++++---------------
 src/qibo/transpiler/placer.py                | 11 ++++--
 tests/conftest.py                            |  6 +--
 tests/test_models_circuit.py                 | 27 +++++++------
 tests/test_tomography_gate_set_tomography.py |  8 +---
 tests/test_transpiler_pipeline.py            | 17 ++++----
 tests/test_transpiler_placer.py              | 12 +++---
 tests/test_transpiler_router.py              |  8 ++--
 8 files changed, 50 insertions(+), 80 deletions(-)

diff --git a/src/qibo/models/circuit.py b/src/qibo/models/circuit.py
index 08aa4e639d..58c214aae5 100644
--- a/src/qibo/models/circuit.py
+++ b/src/qibo/models/circuit.py
@@ -158,7 +158,7 @@ def __init__(
         nqubits: int,
         accelerators=None,
         density_matrix: bool = False,
-        wire_names: Optional[Union[list, dict]] = None,
+        wire_names: Optional[list] = None,
     ):
         if not isinstance(nqubits, int):
             raise_error(
@@ -282,49 +282,28 @@ def __add__(self, circuit):
 
     @property
     def wire_names(self):
+        if self._wire_names is None:
+            return list(range(self.nqubits))
         return self._wire_names
 
     @wire_names.setter
-    def wire_names(self, wire_names: Union[list, dict]):
-        if not isinstance(wire_names, (list, dict, type(None))):
+    def wire_names(self, wire_names: Optional[list]):
+        if not isinstance(wire_names, (list, type(None))):
             raise_error(
                 TypeError,
-                f"``wire_names`` must be type ``list`` or ``dict``, but is {type(wire_names)}.",
+                f"``wire_names`` must be type ``list``, but is {type(wire_names)}.",
             )
 
-        if isinstance(wire_names, list):
+        if wire_names is not None:
             if len(wire_names) != self.nqubits:
                 raise_error(
                     ValueError,
                     "Number of wire names must be equal to the number of qubits, "
                     f"but is {len(wire_names)}.",
                 )
-
             self._wire_names = wire_names.copy()
-        elif isinstance(wire_names, dict):
-            if len(wire_names.keys()) > self.nqubits:
-                raise_error(
-                    ValueError,
-                    "number of elements in the ``wire_names`` dictionary "
-                    + "cannot be bigger than ``nqubits``.",
-                )
-            if not all(isinstance(k, int) for k in wire_names.values()):
-                raise_error(
-                    ValueError,
-                    "all values of the ``wire_names`` dictionary must be integers.",
-                )
-            if sorted(wire_names.values()) != list(range(self.nqubits)):
-                raise_error(
-                    ValueError,
-                    "all values of the ``wire_names`` dictionary must be unique integers from 0 to ``nqubits``.",
-                )
-
-            self._wire_names = [
-                k for k, _ in sorted(wire_names.items(), key=lambda x: x[1])
-            ]
         else:
-            self._wire_names = [f"q{i}" for i in range(self.nqubits)]
-
+            self._wire_names = None
         self.init_kwargs["wire_names"] = self._wire_names
 
     @property
@@ -1347,8 +1326,8 @@ def chunkstring(string, length):
                     loutput += ["" for _ in range(self.nqubits)]
                     suffix = " ...\n"
                     prefix = (
-                        self.wire_names[row]
-                        + " " * (max_name_len - len(self.wire_names[row]))
+                        wire_names[row]
+                        + " " * (max_name_len - len(wire_names[row]))
                         + ": "
                     )
                     if i == 0:
diff --git a/src/qibo/transpiler/placer.py b/src/qibo/transpiler/placer.py
index 0e7d1ec136..ca12406c33 100644
--- a/src/qibo/transpiler/placer.py
+++ b/src/qibo/transpiler/placer.py
@@ -109,6 +109,7 @@ def __call__(self, circuit: Circuit):
         """
 
         middle_qubit_idx = circuit.wire_names.index(self.middle_qubit)
+        wire_names = circuit.wire_names.copy()
 
         for i, gate in enumerate(circuit.queue):
             if len(gate.qubits) > 2:
@@ -126,14 +127,16 @@ def __call__(self, circuit: Circuit):
                     )
 
                     (
-                        circuit.wire_names[middle_qubit_idx],
-                        circuit.wire_names[new_middle],
+                        wire_names[middle_qubit_idx],
+                        wire_names[new_middle],
                     ) = (
-                        circuit.wire_names[new_middle],
-                        circuit.wire_names[middle_qubit_idx],
+                        wire_names[new_middle],
+                        wire_names[middle_qubit_idx],
                     )
                     break
 
+        circuit.wire_names = wire_names
+
 
 class Trivial(Placer):
     """Place qubits according to the order of the qubit names that the user provides."""
diff --git a/tests/conftest.py b/tests/conftest.py
index 5aaaf1a129..572864b29c 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -84,7 +84,7 @@ def clear():
 
 @pytest.fixture
 def star_connectivity():
-    def _star_connectivity(names=["q0", "q1", "q2", "q3", "q4"], middle_qubit_idx=2):
+    def _star_connectivity(names=list(range(5)), middle_qubit_idx=2):
         chip = nx.Graph()
         chip.add_nodes_from(names)
         graph_list = [
@@ -100,7 +100,7 @@ def _star_connectivity(names=["q0", "q1", "q2", "q3", "q4"], middle_qubit_idx=2)
 
 @pytest.fixture
 def grid_connectivity():
-    def _grid_connectivity(names=["q0", "q1", "q2", "q3", "q4"]):
+    def _grid_connectivity(names=list(range(5))):
         chip = nx.Graph()
         chip.add_nodes_from(names)
         graph_list = [
@@ -120,7 +120,7 @@ def _grid_connectivity(names=["q0", "q1", "q2", "q3", "q4"]):
 def line_connectivity():
     def _line_connectivity(n, names=None):
         if names is None:
-            names = [f"q{i}" for i in range(n)]
+            names = list(range(n))
         chip = nx.Graph()
         chip.add_nodes_from(names)
         graph_list = [(names[i], names[i + 1]) for i in range(n - 1)]
diff --git a/tests/test_models_circuit.py b/tests/test_models_circuit.py
index 6c5864981a..f521446c26 100644
--- a/tests/test_models_circuit.py
+++ b/tests/test_models_circuit.py
@@ -625,7 +625,7 @@ def test_circuit_draw():
         "q3: ─────────o──|───────o──|────o──|──H─U1───|─x─\n"
         "q4: ────────────o──────────o───────o────o──H─x───"
     )
-    circuit = Circuit(5)
+    circuit = Circuit(5, wire_names=["q0", "q1", "q2", "q3", "q4"])
     for i1 in range(5):
         circuit.add(gates.H(i1))
         for i2 in range(i1 + 1, 5):
@@ -638,18 +638,17 @@ def test_circuit_draw():
 
 def test_circuit_wire_names():
     circuit = Circuit(5)
-    assert circuit.wire_names == ["q0", "q1", "q2", "q3", "q4"]
-    circuit = Circuit(5, wire_names={"q1": 3, "q3": 1, "q2": 4, "q4": 0, "q0": 2})
-    assert circuit.wire_names == ["q4", "q3", "q0", "q1", "q2"]
+    assert circuit.wire_names == [0, 1, 2, 3, 4]
+    assert circuit._wire_names == None
+
+    circuit.wire_names = ["a", "b", "c", "d", "e"]
+    assert circuit.wire_names == ["a", "b", "c", "d", "e"]
+    assert circuit._wire_names == ["a", "b", "c", "d", "e"]
 
     with pytest.raises(TypeError):
         circuit = Circuit(5, wire_names=1)
     with pytest.raises(ValueError):
-        circuit = Circuit(2, wire_names={"q0": "1", "q1": "2", "q2": "3"})
-    with pytest.raises(ValueError):
-        circuit = Circuit(2, wire_names={"q0": "1", "q1": 2})
-    with pytest.raises(ValueError):
-        circuit = Circuit(3, wire_names={"q0": 4, "q1": 5, "q2": 6})
+        circuit = Circuit(5, wire_names=["a", "b", "c"])
 
 
 def test_circuit_draw_wire_names():
@@ -726,7 +725,7 @@ def test_circuit_draw_line_wrap(capsys):
         + "q4: ... ───"
     )
 
-    circuit = Circuit(5)
+    circuit = Circuit(5, wire_names=["q0", "q1", "q2", "q3", "q4"])
     for i1 in range(5):
         circuit.add(gates.H(i1))
         for i2 in range(i1 + 1, 5):
@@ -816,7 +815,7 @@ def test_circuit_draw_line_wrap_names(capsys):
 def test_circuit_draw_channels(capsys, legend):
     """Check that channels are drawn correctly."""
 
-    circuit = Circuit(2, density_matrix=True)
+    circuit = Circuit(2, density_matrix=True, wire_names=["q0", "q1"])
     circuit.add(gates.H(0))
     circuit.add(gates.PauliNoiseChannel(0, list(zip(["X", "Z"], [0.1, 0.2]))))
     circuit.add(gates.H(1))
@@ -853,7 +852,7 @@ def test_circuit_draw_callbacks(capsys, legend):
     from qibo.callbacks import EntanglementEntropy
 
     entropy = EntanglementEntropy([0])
-    c = Circuit(2)
+    c = Circuit(2, wire_names=["q0", "q1"])
     c.add(gates.CallbackGate(entropy))
     c.add(gates.H(0))
     c.add(gates.CallbackGate(entropy))
@@ -884,7 +883,7 @@ def test_circuit_draw_labels():
         + "q3: ─────────o──|───────o──|────o──|──H─G4───|─x─\n"
         + "q4: ────────────o──────────o───────o────o──H─x───"
     )
-    circuit = Circuit(5)
+    circuit = Circuit(5, wire_names=["q0", "q1", "q2", "q3", "q4"])
     for i1 in range(5):
         circuit.add(gates.H(i1))
         for i2 in range(i1 + 1, 5):
@@ -905,7 +904,7 @@ def test_circuit_draw_names(capsys):
         + "q3: ─────────o──|───────o──|────o──|──H─cx───|─x─\n"
         + "q4: ────────────o──────────o───────o────o──H─x───"
     )
-    circuit = Circuit(5)
+    circuit = Circuit(5, wire_names=["q0", "q1", "q2", "q3", "q4"])
     for i1 in range(5):
         circuit.add(gates.H(i1))
         for i2 in range(i1 + 1, 5):
diff --git a/tests/test_tomography_gate_set_tomography.py b/tests/test_tomography_gate_set_tomography.py
index de79d67922..c2a40d944f 100644
--- a/tests/test_tomography_gate_set_tomography.py
+++ b/tests/test_tomography_gate_set_tomography.py
@@ -261,7 +261,7 @@ def test_GST_non_invertible_matrix():
         matrices = GST(gate_set=[], pauli_liouville=True, gauge_matrix=T)
 
 
-def test_GST_with_transpiler(backend):
+def test_GST_with_transpiler(backend, star_connectivity):
     import networkx as nx
 
     target_gates = [gates.SX(0), gates.Z(0), gates.CNOT(0, 1)]
@@ -276,11 +276,7 @@ def test_GST_with_transpiler(backend):
         transpiler=None,
     )
     # define transpiler
-    connectivity = nx.Graph()
-    # star connectivity
-    connectivity.add_edges_from(
-        [("q0", "q2"), ("q1", "q2"), ("q2", "q3"), ("q2", "q4")]
-    )
+    connectivity = star_connectivity()
     transpiler = Passes(
         connectivity=connectivity,
         passes=[
diff --git a/tests/test_transpiler_pipeline.py b/tests/test_transpiler_pipeline.py
index 4affd8026a..84b5befaed 100644
--- a/tests/test_transpiler_pipeline.py
+++ b/tests/test_transpiler_pipeline.py
@@ -53,13 +53,13 @@ def generate_random_circuit(nqubits, ngates, names=None, seed=42):
 
 def test_restrict_qubits_error_no_subset(star_connectivity):
     with pytest.raises(ConnectivityError) as excinfo:
-        restrict_connectivity_qubits(star_connectivity(), ["q0", "q1", "q5"])
+        restrict_connectivity_qubits(star_connectivity(), [0, 1, 5])
     assert "Some qubits are not in the original connectivity." in str(excinfo.value)
 
 
 def test_restrict_qubits_error_not_connected(star_connectivity):
     with pytest.raises(ConnectivityError) as excinfo:
-        restrict_connectivity_qubits(star_connectivity(), ["q0", "q1"])
+        restrict_connectivity_qubits(star_connectivity(), [0, 1])
     assert "New connectivity graph is not connected." in str(excinfo.value)
 
 
@@ -96,7 +96,7 @@ def test_assert_circuit_equivalence_equal():
     circ1.add(gates.CZ(0, 1))
     circ2.add(gates.X(0))
     circ2.add(gates.CZ(0, 1))
-    final_map = {"q0": 0, "q1": 1}
+    final_map = {0: 0, 1: 1}
     assert_circuit_equivalence(circ1, circ2, final_map=final_map)
 
 
@@ -106,7 +106,7 @@ def test_assert_circuit_equivalence_swap():
     circ1.add(gates.X(0))
     circ2.add(gates.SWAP(0, 1))
     circ2.add(gates.X(1))
-    final_map = {"q0": 1, "q1": 0}
+    final_map = {0: 1, 1: 0}
     assert_circuit_equivalence(circ1, circ2, final_map=final_map)
 
 
@@ -116,7 +116,7 @@ def test_assert_circuit_equivalence_false():
     circ1.add(gates.X(0))
     circ2.add(gates.SWAP(0, 1))
     circ2.add(gates.X(1))
-    final_map = {"q0": 0, "q1": 1}
+    final_map = {0: 0, 1: 1}
     with pytest.raises(TranspilerPipelineError):
         assert_circuit_equivalence(circ1, circ2, final_map=final_map)
 
@@ -133,7 +133,7 @@ def test_int_qubit_names_default(star_connectivity):
 def test_assert_circuit_equivalence_wrong_nqubits():
     circ1 = Circuit(1)
     circ2 = Circuit(2)
-    final_map = {"q0": 0, "q1": 1}
+    final_map = {0: 0, 1: 1}
     with pytest.raises(ValueError):
         assert_circuit_equivalence(circ1, circ2, final_map=final_map)
 
@@ -147,7 +147,6 @@ def test_error_connectivity():
 def test_is_satisfied(qubits, star_connectivity):
     default_transpiler = Passes(passes=None, connectivity=star_connectivity())
     circuit = Circuit(qubits)
-    circuit.wire_names = ["q0", "q1", "q2", "q3", "q4"][:qubits]
     circuit.add(gates.CZ(0, 2))
     circuit.add(gates.Z(0))
     assert default_transpiler.is_satisfied(circuit)
@@ -207,9 +206,7 @@ def test_custom_passes(placer, router, ngates, nqubits, star_connectivity):
 @pytest.mark.parametrize("ngates", [5, 20])
 @pytest.mark.parametrize("placer", [Random, Trivial, ReverseTraversal])
 @pytest.mark.parametrize("routing", [ShortestPaths, Sabre])
-@pytest.mark.parametrize(
-    "restrict_names", [["q1", "q2", "q3"], ["q0", "q2", "q4"], ["q4", "q2", "q3"]]
-)
+@pytest.mark.parametrize("restrict_names", [[1, 2, 3], [0, 2, 4], [4, 2, 3]])
 def test_custom_passes_restrict(
     ngates, placer, routing, restrict_names, star_connectivity
 ):
diff --git a/tests/test_transpiler_placer.py b/tests/test_transpiler_placer.py
index 90d4d301f7..e170c3eb7d 100644
--- a/tests/test_transpiler_placer.py
+++ b/tests/test_transpiler_placer.py
@@ -105,7 +105,7 @@ def test_trivial(star_connectivity):
 def test_trivial_restricted(star_connectivity):
     names = ["q0", "q2"]
     circuit = Circuit(2, wire_names=names)
-    connectivity = star_connectivity()
+    connectivity = star_connectivity(["q0", "q1", "q2", "q3", "q4"])
     restricted_connectivity = restrict_connectivity_qubits(connectivity, names)
     placer = Trivial(connectivity=restricted_connectivity)
     placer(circuit)
@@ -170,7 +170,7 @@ def test_subgraph_perfect(star_connectivity):
     placer = Subgraph(connectivity=connectivity)
     circuit = star_circuit()
     placer(circuit)
-    assert circuit.wire_names[0] == "q2"
+    assert circuit.wire_names[0] == 2
     assert_placement(circuit, connectivity)
 
 
@@ -213,9 +213,7 @@ def test_subgraph_restricted(star_connectivity):
     circuit.add(gates.CNOT(1, 2))
     circuit.add(gates.CNOT(3, 1))
     connectivity = star_connectivity()
-    restricted_connectivity = restrict_connectivity_qubits(
-        connectivity, ["q0", "q2", "q3", "q4"]
-    )
+    restricted_connectivity = restrict_connectivity_qubits(connectivity, [0, 2, 3, 4])
     placer = Subgraph(connectivity=restricted_connectivity)
     placer(circuit)
     assert_placement(circuit, restricted_connectivity)
@@ -276,7 +274,7 @@ def test_reverse_traversal_restricted(star_connectivity):
     circuit.add(gates.CNOT(1, 2))
     circuit.add(gates.CNOT(3, 1))
     connectivity = star_connectivity()
-    restrict_names = ["q0", "q2", "q3", "q4"]
+    restrict_names = [0, 2, 3, 4]
     restricted_connectivity = restrict_connectivity_qubits(connectivity, restrict_names)
     circuit.wire_names = restrict_names
     routing = ShortestPaths(connectivity=restricted_connectivity)
@@ -296,7 +294,7 @@ def test_star_connectivity_placer(star_connectivity):
     placer = StarConnectivityPlacer(connectivity)
     placer(circ)
     assert_placement(circ, connectivity)
-    assert circ.wire_names == ["q0", "q2", "q1", "q3", "q4"]
+    assert circ.wire_names == [0, 2, 1, 3, 4]
 
 
 @pytest.mark.parametrize("first", [True, False])
diff --git a/tests/test_transpiler_router.py b/tests/test_transpiler_router.py
index 6d10dfd5b1..afd661a4b1 100644
--- a/tests/test_transpiler_router.py
+++ b/tests/test_transpiler_router.py
@@ -216,9 +216,7 @@ def test_star_circuit(star_connectivity):
 def test_star_circuit_custom_map(star_connectivity):
     connectivity = star_connectivity()
     circuit = star_circuit()
-    placer = Custom(
-        initial_map=["q1", "q0", "q2", "q3", "q4"], connectivity=connectivity
-    )
+    placer = Custom(initial_map=[1, 0, 2, 3, 4], connectivity=connectivity)
     transpiler = ShortestPaths(connectivity=connectivity)
 
     placer(circuit)
@@ -430,7 +428,7 @@ def test_sabre_simple(seed, star_connectivity):
     routed_circuit, final_map = router(circ)
 
     assert router.added_swaps == 1
-    assert final_map == {"q0": 2, "q1": 1, "q2": 0, "q3": 3, "q4": 4}
+    assert final_map == {0: 2, 1: 1, 2: 0, 3: 3, 4: 4}
     assert routed_circuit.queue[0].qubits == (0, 2)
     assert isinstance(routed_circuit.queue[0], gates.SWAP)
     assert isinstance(routed_circuit.queue[1], gates.CZ)
@@ -532,7 +530,7 @@ def test_restrict_qubits(router_algorithm, star_connectivity):
     circ.add(gates.CZ(0, 2))
     circ.add(gates.CZ(2, 1))
     circ.wire_names = ["q0", "q3", "q2"]
-    connectivity = star_connectivity()
+    connectivity = star_connectivity(["q0", "q1", "q2", "q3", "q4"])
     restricted_connectivity = restrict_connectivity_qubits(
         connectivity, ["q0", "q2", "q3"]
     )

From 2ac1a856ac0ffb9434af37d8ec32b462cda67026 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Mon, 28 Oct 2024 12:04:24 +0400
Subject: [PATCH 15/34] fix: wire_names update docstrings

---
 src/qibo/models/circuit.py | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/qibo/models/circuit.py b/src/qibo/models/circuit.py
index 58c214aae5..c4d3714820 100644
--- a/src/qibo/models/circuit.py
+++ b/src/qibo/models/circuit.py
@@ -141,11 +141,9 @@ class Circuit:
             Defaults to ``False``.
         accelerators (dict, optional): Dictionary that maps device names to the number of times each
             device will be used. Defaults to ``None``.
-        wire_names (list or dict, optional): Names for qubit wires.
-            If ``None``, defaults to [``q0``, ``q1``... ``q(n-1)``].
+        wire_names (list, optional): Names for qubit wires.
+            If ``None``, defaults to [``0``, ``1``, ..., ``nqubits - 1``].
             If ``list`` is passed, length of ``list`` must match ``nqubits``.
-            If ``dict`` is passed, keys should be wire names and values should be qubit indices. Values should be unique and range from 0 to ``nqubits - 1``.
-            Defaults to ``None``.
         ndevices (int): Total number of devices. Defaults to ``None``.
         nglobal (int): Base two logarithm of the number of devices. Defaults to ``None``.
         nlocal (int): Total number of available qubits in each device. Defaults to ``None``.

From 788fd06253073894de0ff457b4faad059ac32087 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Mon, 28 Oct 2024 12:06:57 +0400
Subject: [PATCH 16/34] fix: line connectivity remove fixture

---
 tests/conftest.py               | 14 --------------
 tests/test_transpiler_router.py | 18 ++++++++++++++----
 2 files changed, 14 insertions(+), 18 deletions(-)

diff --git a/tests/conftest.py b/tests/conftest.py
index 572864b29c..16b00578aa 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -116,20 +116,6 @@ def _grid_connectivity(names=list(range(5))):
     return _grid_connectivity
 
 
-@pytest.fixture
-def line_connectivity():
-    def _line_connectivity(n, names=None):
-        if names is None:
-            names = list(range(n))
-        chip = nx.Graph()
-        chip.add_nodes_from(names)
-        graph_list = [(names[i], names[i + 1]) for i in range(n - 1)]
-        chip.add_edges_from(graph_list)
-        return chip
-
-    return _line_connectivity
-
-
 def pytest_generate_tests(metafunc):
     module_name = metafunc.module.__name__
 
diff --git a/tests/test_transpiler_router.py b/tests/test_transpiler_router.py
index afd661a4b1..f132628df4 100644
--- a/tests/test_transpiler_router.py
+++ b/tests/test_transpiler_router.py
@@ -32,6 +32,16 @@
 )
 
 
+def line_connectivity(n, names=None):
+    if names is None:
+        names = list(range(n))
+    chip = nx.Graph()
+    chip.add_nodes_from(names)
+    graph_list = [(names[i], names[i + 1]) for i in range(n - 1)]
+    chip.add_edges_from(graph_list)
+    return chip
+
+
 def generate_random_circuit(nqubits, ngates, names=None, seed=42):
     """Generate a random circuit with RX and CZ gates."""
     np.random.seed(seed)
@@ -103,7 +113,7 @@ def test_assert_connectivity_3q(star_connectivity):
         assert_connectivity(star_connectivity(), circuit)
 
 
-def test_bell_state_3q(line_connectivity):
+def test_bell_state_3q():
     from qibo.transpiler.pipeline import _transpose_qubits
 
     circuit = Circuit(3)
@@ -173,7 +183,7 @@ def test_random_circuits_5q_grid(ngates, placer, grid_connectivity):
 
 @pytest.mark.parametrize("nqubits", [11, 12, 13, 14, 15])
 @pytest.mark.parametrize("ngates", [30, 50])
-def test_random_circuits_15q_50g(nqubits, ngates, line_connectivity):
+def test_random_circuits_15q_50g(nqubits, ngates):
     connectivity = line_connectivity(nqubits, None)
     placer = Random(connectivity=connectivity)
     transpiler = Sabre(connectivity=connectivity)
@@ -253,7 +263,7 @@ def test_routing_with_measurements(star_connectivity):
     )
 
 
-def test_sabre_looping(line_connectivity):
+def test_sabre_looping():
     # Setup where the looping occurs
     # Line connectivity, gates with gate_array, Trivial placer
 
@@ -289,7 +299,7 @@ def test_sabre_looping(line_connectivity):
     )
 
 
-def test_sabre_shortest_path_routing(line_connectivity):
+def test_sabre_shortest_path_routing():
     gate_array = [(0, 9), (5, 9), (2, 8)]  # The gate (2, 8) should be routed next
 
     loop_circ = Circuit(10)

From 4e3dbce27c457c0796fbd1acd7c2ef4a7051ae14 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Mon, 28 Oct 2024 12:40:01 +0400
Subject: [PATCH 17/34] fix: test files default qubit

---
 tests/test_measurements.py        | 2 +-
 tests/test_models_circuit_fuse.py | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/test_measurements.py b/tests/test_measurements.py
index 48151b23ab..af5344fb4f 100644
--- a/tests/test_measurements.py
+++ b/tests/test_measurements.py
@@ -434,7 +434,7 @@ def test_measurement_basis(backend, nqubits, outcome):
 
 
 def test_measurement_basis_list(backend):
-    c = Circuit(4)
+    c = Circuit(4, wire_names=["q0", "q1", "q2", "q3"])
     c.add(gates.H(0))
     c.add(gates.X(2))
     c.add(gates.H(2))
diff --git a/tests/test_models_circuit_fuse.py b/tests/test_models_circuit_fuse.py
index 22e9c74f0e..ae90d42b02 100644
--- a/tests/test_models_circuit_fuse.py
+++ b/tests/test_models_circuit_fuse.py
@@ -228,7 +228,7 @@ def test_fused_gate_draw():
         "q3: ───────────────o──|───────────o──|──[─o──H─]─|──[─U1───]─|─x─\n"
         "q4: ──────────────────o──────────────o───────────o──[─o──H─]─x───"
     )
-    circuit = Circuit(5)
+    circuit = Circuit(5, wire_names=["q0", "q1", "q2", "q3", "q4"])
     for i1 in range(5):
         circuit.add(gates.H(i1))
         for i2 in range(i1 + 1, 5):

From d4e507cbed5a2a3525ec0ecda39485dc60d7cd5b Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Mon, 28 Oct 2024 13:30:18 +0400
Subject: [PATCH 18/34] fix: refactor assert functions

---
 src/qibo/transpiler/pipeline.py         | 118 +------------
 src/qibo/transpiler/placer.py           |  45 +----
 src/qibo/transpiler/router.py           |  23 ---
 src/qibo/transpiler/unroller.py         |  33 ----
 src/qibo/transpiler/utils.py            | 213 ++++++++++++++++++++++++
 tests/test_transpiler_decompositions.py |   3 +-
 tests/test_transpiler_pipeline.py       |   8 +-
 tests/test_transpiler_placer.py         |   3 +-
 tests/test_transpiler_router.py         |  15 +-
 tests/test_transpiler_unroller.py       |   8 +-
 10 files changed, 232 insertions(+), 237 deletions(-)
 create mode 100644 src/qibo/transpiler/utils.py

diff --git a/src/qibo/transpiler/pipeline.py b/src/qibo/transpiler/pipeline.py
index c2f9e2c26a..3e75f1a368 100644
--- a/src/qibo/transpiler/pipeline.py
+++ b/src/qibo/transpiler/pipeline.py
@@ -1,124 +1,14 @@
-from typing import Optional
-
 import networkx as nx
-import numpy as np
 
-from qibo.backends import NumpyBackend
 from qibo.config import raise_error
 from qibo.models import Circuit
-from qibo.quantum_info.random_ensembles import random_statevector
 from qibo.transpiler._exceptions import TranspilerPipelineError
 from qibo.transpiler.abstract import Optimizer, Placer, Router
 from qibo.transpiler.optimizer import Preprocessing
-from qibo.transpiler.placer import StarConnectivityPlacer, assert_placement
-from qibo.transpiler.router import (
-    ConnectivityError,
-    StarConnectivityRouter,
-    assert_connectivity,
-)
-from qibo.transpiler.unroller import (
-    DecompositionError,
-    NativeGates,
-    Unroller,
-    assert_decomposition,
-)
-
-
-def assert_circuit_equivalence(
-    original_circuit: Circuit,
-    transpiled_circuit: Circuit,
-    final_map: dict,
-    test_states: Optional[list] = None,
-    ntests: int = 3,
-):
-    """Checks that the transpiled circuit agrees with the original using simulation.
-
-    Args:
-        original_circuit (:class:`qibo.models.circuit.Circuit`): Original circuit.
-        transpiled_circuit (:class:`qibo.models.circuit.Circuit`): Transpiled circuit.
-        final_map (dict): logical-physical qubit mapping after routing.
-        test_states (list, optional): states on which the test is performed.
-            If ``None``, ``ntests`` random states will be tested. Defauts to ``None``.
-        ntests (int, optional): number of random states tested. Defauts to :math:`3`.
-    """
-    backend = NumpyBackend()
-    if transpiled_circuit.nqubits != original_circuit.nqubits:
-        raise_error(
-            ValueError,
-            "Transpiled and original circuit do not have the same number of qubits.",
-        )
-
-    if test_states is None:
-        test_states = [
-            random_statevector(dims=2**original_circuit.nqubits, backend=backend)
-            for _ in range(ntests)
-        ]
-
-    ordering = list(final_map.values())
-
-    for i, state in enumerate(test_states):
-        target_state = backend.execute_circuit(
-            original_circuit, initial_state=state
-        ).state()
-        final_state = backend.execute_circuit(
-            transpiled_circuit,
-            initial_state=state,
-        ).state()
-        final_state = _transpose_qubits(final_state, ordering)
-        fidelity = np.abs(np.dot(np.conj(target_state), final_state))
-        try:
-            np.testing.assert_allclose(fidelity, 1.0)
-        except AssertionError:
-            raise_error(TranspilerPipelineError, "Circuit equivalence not satisfied.")
-
-
-def _transpose_qubits(state: np.ndarray, qubits_ordering: np.ndarray):
-    """Reorders qubits of a given state vector.
-
-    Args:
-        state (np.ndarray): final state of the circuit.
-        qubits_ordering (np.ndarray): final qubit ordering.
-    """
-    original_shape = state.shape
-    state = np.reshape(state, len(qubits_ordering) * (2,))
-    state = np.transpose(state, qubits_ordering)
-    return np.reshape(state, original_shape)
-
-
-def assert_transpiling(
-    original_circuit: Circuit,
-    transpiled_circuit: Circuit,
-    connectivity: nx.Graph,
-    final_layout: dict,
-    native_gates: NativeGates = NativeGates.default(),
-    check_circuit_equivalence=True,
-):
-    """Check that all transpiler passes have been executed correctly.
-
-    Args:
-        original_circuit (qibo.models.Circuit): circuit before transpiling.
-        transpiled_circuit (qibo.models.Circuit): circuit after transpiling.
-        connectivity (networkx.Graph): chip qubits connectivity.
-        final_layout (dict): final physical-logical qubit mapping.
-        native_gates (NativeGates): native gates supported by the hardware.
-        check_circuit_equivalence (Bool): use simulations to check if the transpiled circuit is the same as the original.
-    """
-    assert_connectivity(circuit=transpiled_circuit, connectivity=connectivity)
-    assert_decomposition(
-        circuit=transpiled_circuit,
-        native_gates=native_gates,
-    )
-    if original_circuit.nqubits != transpiled_circuit.nqubits:
-        qubit_matcher = Preprocessing(connectivity=connectivity)
-        original_circuit = qubit_matcher(circuit=original_circuit)
-    assert_placement(circuit=original_circuit, connectivity=connectivity)
-    assert_placement(circuit=transpiled_circuit, connectivity=connectivity)
-    if check_circuit_equivalence:
-        assert_circuit_equivalence(
-            original_circuit=original_circuit,
-            transpiled_circuit=transpiled_circuit,
-            final_map=final_layout,
-        )
+from qibo.transpiler.placer import StarConnectivityPlacer
+from qibo.transpiler.router import ConnectivityError, StarConnectivityRouter
+from qibo.transpiler.unroller import DecompositionError, NativeGates, Unroller
+from qibo.transpiler.utils import assert_connectivity, assert_decomposition
 
 
 def restrict_connectivity_qubits(connectivity: nx.Graph, qubits: list[str]):
diff --git a/src/qibo/transpiler/placer.py b/src/qibo/transpiler/placer.py
index ca12406c33..2e796670f8 100644
--- a/src/qibo/transpiler/placer.py
+++ b/src/qibo/transpiler/placer.py
@@ -9,48 +9,7 @@
 from qibo.transpiler._exceptions import PlacementError
 from qibo.transpiler.abstract import Placer, Router
 from qibo.transpiler.router import _find_connected_qubit
-
-
-def assert_placement(circuit: Circuit, connectivity: nx.Graph):
-    """Check if layout is in the correct form and matches the number of qubits of the circuit.
-
-    Args:
-        circuit (:class:`qibo.models.circuit.Circuit`): Circuit model to check.
-        layout (dict): qubit names.
-        connectivity (:class:`networkx.Graph`, optional): Chip connectivity.
-            This argument is necessary if the layout is applied to a subset of
-            qubits of the original connectivity graph. Defaults to ``None``.
-    """
-    layout = circuit.wire_names
-    assert_mapping_consistency(layout=layout, connectivity=connectivity)
-    if circuit.nqubits > len(layout):
-        raise_error(
-            PlacementError,
-            "Layout can't be used on circuit. The circuit requires more qubits.",
-        )
-    if circuit.nqubits < len(layout):
-        raise_error(
-            PlacementError,
-            "Layout can't be used on circuit. "
-            + "Ancillary extra qubits need to be added to the circuit.",
-        )
-
-
-def assert_mapping_consistency(layout: list, connectivity: nx.Graph):
-    """Check if layout is in the correct form.
-
-    Args:
-        layout (dict): qubit names.
-        connectivity (:class:`networkx.Graph`, optional):  Chip connectivity.
-            This argument is necessary if the layout is applied to a subset of
-            qubits of the original connectivity graph.
-    """
-    nodes = list(connectivity.nodes)
-    if sorted(nodes) != sorted(layout):
-        raise_error(
-            PlacementError,
-            "Some physical qubits in the layout may be missing or duplicated.",
-        )
+from qibo.transpiler.utils import assert_placement
 
 
 def _find_gates_qubits_pairs(circuit: Circuit):
@@ -159,7 +118,7 @@ class Custom(Placer):
     Args:
         map (list or dict): A mapping between physical and logical qubits.
             - If **dict**, the keys should be physical qubit names, and the values should be the corresponding logical qubit numbers.
-            - If **list**, it should contain logical qubit numbers, arranged in the order of the physical qubits.
+            - If **list**, it should contain physical qubit names, arranged in the order of the logical qubits.
     """
 
     def __init__(self, initial_map: Union[list, dict], connectivity: nx.Graph):
diff --git a/src/qibo/transpiler/router.py b/src/qibo/transpiler/router.py
index 4b8276522d..289128e02e 100644
--- a/src/qibo/transpiler/router.py
+++ b/src/qibo/transpiler/router.py
@@ -13,29 +13,6 @@
 from qibo.transpiler.blocks import Block, CircuitBlocks
 
 
-def assert_connectivity(connectivity: nx.Graph, circuit: Circuit):
-    """Assert if a circuit can be executed on Hardware.
-
-    No gates acting on more than two qubits.
-    All two-qubit operations can be performed on hardware.
-
-    Args:
-        circuit (:class:`qibo.models.circuit.Circuit`): circuit model to check.
-        connectivity (:class:`networkx.Graph`): chip connectivity.
-    """
-    layout = circuit.wire_names
-    for gate in circuit.queue:
-        if len(gate.qubits) > 2 and not isinstance(gate, gates.M):
-            raise_error(ConnectivityError, f"{gate.name} acts on more than two qubits.")
-        if len(gate.qubits) == 2:
-            physical_qubits = (layout[gate.qubits[0]], layout[gate.qubits[1]])
-            if physical_qubits not in connectivity.edges:
-                raise_error(
-                    ConnectivityError,
-                    f"The circuit does not respect the connectivity. {gate.name} acts on {physical_qubits} but only the following qubits are directly connected: {connectivity.edges}.",
-                )
-
-
 class StarConnectivityRouter(Router):
     """Transforms an arbitrary circuit to one that can be executed on hardware.
 
diff --git a/src/qibo/transpiler/unroller.py b/src/qibo/transpiler/unroller.py
index ee6e15d0a1..5bae287e7c 100644
--- a/src/qibo/transpiler/unroller.py
+++ b/src/qibo/transpiler/unroller.py
@@ -121,39 +121,6 @@ def __call__(self, circuit: Circuit):
         return translated_circuit
 
 
-def assert_decomposition(
-    circuit: Circuit,
-    native_gates: NativeGates,
-):
-    """Checks if a circuit has been correctly decomposed into native gates.
-
-    Args:
-        circuit (:class:`qibo.models.circuit.Circuit`): circuit model to check.
-        native_gates (:class:`qibo.transpiler.unroller.NativeGates`):
-            native gates in the transpiled circuit.
-    """
-    for gate in circuit.queue:
-        if isinstance(gate, gates.M):
-            continue
-        if len(gate.qubits) <= 2:
-            try:
-                native_type_gate = NativeGates.from_gate(gate)
-                if not native_type_gate & native_gates:
-                    raise_error(
-                        DecompositionError,
-                        f"{gate.name} is not a native gate.",
-                    )
-            except ValueError:
-                raise_error(
-                    DecompositionError,
-                    f"{gate.name} is not a native gate.",
-                )
-        else:
-            raise_error(
-                DecompositionError, f"{gate.name} acts on more than two qubits."
-            )
-
-
 def translate_gate(
     gate,
     native_gates: NativeGates,
diff --git a/src/qibo/transpiler/utils.py b/src/qibo/transpiler/utils.py
new file mode 100644
index 0000000000..10d76a3f3d
--- /dev/null
+++ b/src/qibo/transpiler/utils.py
@@ -0,0 +1,213 @@
+from typing import Optional
+
+import networkx as nx
+import numpy as np
+
+from qibo import gates
+from qibo.backends.numpy import NumpyBackend
+from qibo.config import raise_error
+from qibo.models.circuit import Circuit
+from qibo.quantum_info.random_ensembles import random_statevector
+from qibo.transpiler._exceptions import (
+    ConnectivityError,
+    DecompositionError,
+    PlacementError,
+    TranspilerPipelineError,
+)
+from qibo.transpiler.optimizer import Preprocessing
+from qibo.transpiler.unroller import NativeGates
+
+
+def assert_transpiling(
+    original_circuit: Circuit,
+    transpiled_circuit: Circuit,
+    connectivity: nx.Graph,
+    final_layout: dict,
+    native_gates: NativeGates = NativeGates.default(),
+    check_circuit_equivalence=True,
+):
+    """Check that all transpiler passes have been executed correctly.
+
+    Args:
+        original_circuit (qibo.models.Circuit): circuit before transpiling.
+        transpiled_circuit (qibo.models.Circuit): circuit after transpiling.
+        connectivity (networkx.Graph): chip qubits connectivity.
+        final_layout (dict): final physical-logical qubit mapping.
+        native_gates (NativeGates): native gates supported by the hardware.
+        check_circuit_equivalence (Bool): use simulations to check if the transpiled circuit is the same as the original.
+    """
+    assert_connectivity(circuit=transpiled_circuit, connectivity=connectivity)
+    assert_decomposition(
+        circuit=transpiled_circuit,
+        native_gates=native_gates,
+    )
+    if original_circuit.nqubits != transpiled_circuit.nqubits:
+        qubit_matcher = Preprocessing(connectivity=connectivity)
+        original_circuit = qubit_matcher(circuit=original_circuit)
+    assert_placement(circuit=original_circuit, connectivity=connectivity)
+    assert_placement(circuit=transpiled_circuit, connectivity=connectivity)
+    if check_circuit_equivalence:
+        assert_circuit_equivalence(
+            original_circuit=original_circuit,
+            transpiled_circuit=transpiled_circuit,
+            final_map=final_layout,
+        )
+
+
+def assert_circuit_equivalence(
+    original_circuit: Circuit,
+    transpiled_circuit: Circuit,
+    final_map: dict,
+    test_states: Optional[list] = None,
+    ntests: int = 3,
+):
+    """Checks that the transpiled circuit agrees with the original using simulation.
+
+    Args:
+        original_circuit (:class:`qibo.models.circuit.Circuit`): Original circuit.
+        transpiled_circuit (:class:`qibo.models.circuit.Circuit`): Transpiled circuit.
+        final_map (dict): logical-physical qubit mapping after routing.
+        test_states (list, optional): states on which the test is performed.
+            If ``None``, ``ntests`` random states will be tested. Defauts to ``None``.
+        ntests (int, optional): number of random states tested. Defauts to :math:`3`.
+    """
+    backend = NumpyBackend()
+    if transpiled_circuit.nqubits != original_circuit.nqubits:
+        raise_error(
+            ValueError,
+            "Transpiled and original circuit do not have the same number of qubits.",
+        )
+
+    if test_states is None:
+        test_states = [
+            random_statevector(dims=2**original_circuit.nqubits, backend=backend)
+            for _ in range(ntests)
+        ]
+
+    ordering = list(final_map.values())
+
+    for i, state in enumerate(test_states):
+        target_state = backend.execute_circuit(
+            original_circuit, initial_state=state
+        ).state()
+        final_state = backend.execute_circuit(
+            transpiled_circuit,
+            initial_state=state,
+        ).state()
+        final_state = _transpose_qubits(final_state, ordering)
+        fidelity = np.abs(np.dot(np.conj(target_state), final_state))
+        try:
+            np.testing.assert_allclose(fidelity, 1.0)
+        except AssertionError:
+            raise_error(TranspilerPipelineError, "Circuit equivalence not satisfied.")
+
+
+def _transpose_qubits(state: np.ndarray, qubits_ordering: np.ndarray):
+    """Reorders qubits of a given state vector.
+
+    Args:
+        state (np.ndarray): final state of the circuit.
+        qubits_ordering (np.ndarray): final qubit ordering.
+    """
+    original_shape = state.shape
+    state = np.reshape(state, len(qubits_ordering) * (2,))
+    state = np.transpose(state, qubits_ordering)
+    return np.reshape(state, original_shape)
+
+
+def assert_placement(circuit: Circuit, connectivity: nx.Graph):
+    """Check if layout is in the correct form and matches the number of qubits of the circuit.
+
+    Args:
+        circuit (:class:`qibo.models.circuit.Circuit`): Circuit model to check.
+        layout (dict): qubit names.
+        connectivity (:class:`networkx.Graph`, optional): Chip connectivity.
+            This argument is necessary if the layout is applied to a subset of
+            qubits of the original connectivity graph. Defaults to ``None``.
+    """
+    layout = circuit.wire_names
+    assert_mapping_consistency(layout=layout, connectivity=connectivity)
+    if circuit.nqubits > len(layout):
+        raise_error(
+            PlacementError,
+            "Layout can't be used on circuit. The circuit requires more qubits.",
+        )
+    if circuit.nqubits < len(layout):
+        raise_error(
+            PlacementError,
+            "Layout can't be used on circuit. "
+            + "Ancillary extra qubits need to be added to the circuit.",
+        )
+
+
+def assert_mapping_consistency(layout: list, connectivity: nx.Graph):
+    """Check if layout is in the correct form.
+
+    Args:
+        layout (dict): qubit names.
+        connectivity (:class:`networkx.Graph`, optional):  Chip connectivity.
+            This argument is necessary if the layout is applied to a subset of
+            qubits of the original connectivity graph.
+    """
+    nodes = list(connectivity.nodes)
+    if sorted(nodes) != sorted(layout):
+        raise_error(
+            PlacementError,
+            "Some physical qubits in the layout may be missing or duplicated.",
+        )
+
+
+def assert_connectivity(connectivity: nx.Graph, circuit: Circuit):
+    """Assert if a circuit can be executed on Hardware.
+
+    No gates acting on more than two qubits.
+    All two-qubit operations can be performed on hardware.
+
+    Args:
+        circuit (:class:`qibo.models.circuit.Circuit`): circuit model to check.
+        connectivity (:class:`networkx.Graph`): chip connectivity.
+    """
+    layout = circuit.wire_names
+    for gate in circuit.queue:
+        if len(gate.qubits) > 2 and not isinstance(gate, gates.M):
+            raise_error(ConnectivityError, f"{gate.name} acts on more than two qubits.")
+        if len(gate.qubits) == 2:
+            physical_qubits = (layout[gate.qubits[0]], layout[gate.qubits[1]])
+            if physical_qubits not in connectivity.edges:
+                raise_error(
+                    ConnectivityError,
+                    f"The circuit does not respect the connectivity. {gate.name} acts on {physical_qubits} but only the following qubits are directly connected: {connectivity.edges}.",
+                )
+
+
+def assert_decomposition(
+    circuit: Circuit,
+    native_gates: NativeGates,
+):
+    """Checks if a circuit has been correctly decomposed into native gates.
+
+    Args:
+        circuit (:class:`qibo.models.circuit.Circuit`): circuit model to check.
+        native_gates (:class:`qibo.transpiler.unroller.NativeGates`):
+            native gates in the transpiled circuit.
+    """
+    for gate in circuit.queue:
+        if isinstance(gate, gates.M):
+            continue
+        if len(gate.qubits) <= 2:
+            try:
+                native_type_gate = NativeGates.from_gate(gate)
+                if not native_type_gate & native_gates:
+                    raise_error(
+                        DecompositionError,
+                        f"{gate.name} is not a native gate.",
+                    )
+            except ValueError:
+                raise_error(
+                    DecompositionError,
+                    f"{gate.name} is not a native gate.",
+                )
+        else:
+            raise_error(
+                DecompositionError, f"{gate.name} acts on more than two qubits."
+            )
diff --git a/tests/test_transpiler_decompositions.py b/tests/test_transpiler_decompositions.py
index 44c299cc3b..108a4cc416 100644
--- a/tests/test_transpiler_decompositions.py
+++ b/tests/test_transpiler_decompositions.py
@@ -5,7 +5,8 @@
 from qibo.backends import NumpyBackend
 from qibo.models import Circuit
 from qibo.quantum_info.random_ensembles import random_unitary
-from qibo.transpiler.unroller import NativeGates, assert_decomposition, translate_gate
+from qibo.transpiler.unroller import NativeGates, translate_gate
+from qibo.transpiler.utils import assert_decomposition
 
 default_natives = NativeGates.Z | NativeGates.RZ | NativeGates.M | NativeGates.I
 
diff --git a/tests/test_transpiler_pipeline.py b/tests/test_transpiler_pipeline.py
index 84b5befaed..d8d1379fb6 100644
--- a/tests/test_transpiler_pipeline.py
+++ b/tests/test_transpiler_pipeline.py
@@ -6,15 +6,11 @@
 from qibo.models import Circuit
 from qibo.transpiler._exceptions import ConnectivityError, TranspilerPipelineError
 from qibo.transpiler.optimizer import Preprocessing
-from qibo.transpiler.pipeline import (
-    Passes,
-    assert_circuit_equivalence,
-    assert_transpiling,
-    restrict_connectivity_qubits,
-)
+from qibo.transpiler.pipeline import Passes, restrict_connectivity_qubits
 from qibo.transpiler.placer import Random, ReverseTraversal, Trivial
 from qibo.transpiler.router import Sabre, ShortestPaths
 from qibo.transpiler.unroller import NativeGates, Unroller
+from qibo.transpiler.utils import assert_circuit_equivalence, assert_transpiling
 
 
 def generate_random_circuit(nqubits, ngates, names=None, seed=42):
diff --git a/tests/test_transpiler_placer.py b/tests/test_transpiler_placer.py
index e170c3eb7d..306d686f0f 100644
--- a/tests/test_transpiler_placer.py
+++ b/tests/test_transpiler_placer.py
@@ -13,10 +13,9 @@
     Subgraph,
     Trivial,
     _find_gates_qubits_pairs,
-    assert_mapping_consistency,
-    assert_placement,
 )
 from qibo.transpiler.router import ShortestPaths
+from qibo.transpiler.utils import assert_mapping_consistency, assert_placement
 
 
 def star_circuit(names=["q0", "q1", "q2", "q3", "q4"]):
diff --git a/tests/test_transpiler_router.py b/tests/test_transpiler_router.py
index f132628df4..0b5e21bc40 100644
--- a/tests/test_transpiler_router.py
+++ b/tests/test_transpiler_router.py
@@ -9,26 +9,25 @@
 from qibo.models import Circuit
 from qibo.quantum_info.random_ensembles import random_unitary
 from qibo.transpiler._exceptions import ConnectivityError
-from qibo.transpiler.blocks import Block
-from qibo.transpiler.optimizer import Preprocessing
-from qibo.transpiler.pipeline import (
-    assert_circuit_equivalence,
-    restrict_connectivity_qubits,
-)
+from qibo.transpiler.pipeline import restrict_connectivity_qubits
 from qibo.transpiler.placer import (
     Custom,
     Random,
     StarConnectivityPlacer,
     Subgraph,
     Trivial,
-    assert_placement,
 )
 from qibo.transpiler.router import (
     CircuitMap,
     Sabre,
     ShortestPaths,
     StarConnectivityRouter,
+)
+from qibo.transpiler.utils import (
+    _transpose_qubits,
+    assert_circuit_equivalence,
     assert_connectivity,
+    assert_placement,
 )
 
 
@@ -114,8 +113,6 @@ def test_assert_connectivity_3q(star_connectivity):
 
 
 def test_bell_state_3q():
-    from qibo.transpiler.pipeline import _transpose_qubits
-
     circuit = Circuit(3)
     circuit.add(gates.H(0))
     circuit.add(gates.CNOT(0, 2))
diff --git a/tests/test_transpiler_unroller.py b/tests/test_transpiler_unroller.py
index d3aa3e9ba9..c72b735c3f 100644
--- a/tests/test_transpiler_unroller.py
+++ b/tests/test_transpiler_unroller.py
@@ -3,12 +3,8 @@
 from qibo import gates
 from qibo.models import Circuit
 from qibo.transpiler._exceptions import DecompositionError
-from qibo.transpiler.unroller import (
-    NativeGates,
-    Unroller,
-    assert_decomposition,
-    translate_gate,
-)
+from qibo.transpiler.unroller import NativeGates, Unroller, translate_gate
+from qibo.transpiler.utils import assert_decomposition
 
 
 def test_native_gates_from_gatelist():

From 5cf75b59fbfd05a277a14f3e8e3ca38d6048f576 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Mon, 28 Oct 2024 14:14:52 +0400
Subject: [PATCH 19/34] fix: refactor assert funcs

---
 src/qibo/transpiler/placer.py                 |   9 +-
 src/qibo/transpiler/router.py                 |   5 +-
 src/qibo/transpiler/utils.py                  |  14 ++
 tests/test_transpiler_pipeline.py             |  32 ----
 tests/test_transpiler_placer.py               |  56 +-----
 tests/test_transpiler_router.py               |  30 +---
 .../test_transpiler_unitary_decompositions.py |   1 -
 tests/test_transpiler_unroller.py             |  30 ----
 tests/test_transpiler_utils.py                | 164 ++++++++++++++++++
 9 files changed, 198 insertions(+), 143 deletions(-)
 create mode 100644 tests/test_transpiler_utils.py

diff --git a/src/qibo/transpiler/placer.py b/src/qibo/transpiler/placer.py
index 2e796670f8..64826946c1 100644
--- a/src/qibo/transpiler/placer.py
+++ b/src/qibo/transpiler/placer.py
@@ -9,7 +9,7 @@
 from qibo.transpiler._exceptions import PlacementError
 from qibo.transpiler.abstract import Placer, Router
 from qibo.transpiler.router import _find_connected_qubit
-from qibo.transpiler.utils import assert_placement
+from qibo.transpiler.utils import assert_placement, assert_qubit_match
 
 
 def _find_gates_qubits_pairs(circuit: Circuit):
@@ -66,7 +66,7 @@ def __call__(self, circuit: Circuit):
             circuit (:class:`qibo.models.circuit.Circuit`): The original Qibo circuit to transform.
                 Only single qubit gates and two qubits gates are supported by the router.
         """
-
+        assert_qubit_match(circuit, self.connectivity)
         middle_qubit_idx = circuit.wire_names.index(self.middle_qubit)
         wire_names = circuit.wire_names.copy()
 
@@ -109,6 +109,7 @@ def __call__(self, circuit: Circuit = None):
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
         """
+        assert_qubit_match(circuit, self.connectivity)
         return
 
 
@@ -131,6 +132,7 @@ def __call__(self, circuit: Circuit):
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
         """
+        assert_qubit_match(circuit, self.connectivity)
         if isinstance(self.initial_map, dict):
             circuit.wire_names = sorted(self.initial_map, key=self.initial_map.get)
         elif isinstance(self.initial_map, list):
@@ -162,6 +164,7 @@ def __call__(self, circuit: Circuit):
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
         """
+        assert_qubit_match(circuit, self.connectivity)
         gates_qubits_pairs = _find_gates_qubits_pairs(circuit)
         if len(gates_qubits_pairs) < 3:
             raise_error(
@@ -220,6 +223,7 @@ def __call__(self, circuit):
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): Circuit to be transpiled.
         """
+        assert_qubit_match(circuit, self.connectivity)
         _, local_state = _check_backend_and_local_state(self.seed, backend=None)
         gates_qubits_pairs = _find_gates_qubits_pairs(circuit)
         nodes = self.connectivity.number_of_nodes()
@@ -305,6 +309,7 @@ def __call__(self, circuit: Circuit):
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
         """
+        assert_qubit_match(circuit, self.connectivity)
         self.routing_algorithm.connectivity = self.connectivity
         new_circuit = self._assemble_circuit(circuit)
         self._routing_step(new_circuit)
diff --git a/src/qibo/transpiler/router.py b/src/qibo/transpiler/router.py
index 289128e02e..3a5505a51f 100644
--- a/src/qibo/transpiler/router.py
+++ b/src/qibo/transpiler/router.py
@@ -11,6 +11,7 @@
 from qibo.transpiler._exceptions import ConnectivityError
 from qibo.transpiler.abstract import Router
 from qibo.transpiler.blocks import Block, CircuitBlocks
+from qibo.transpiler.utils import assert_qubit_match
 
 
 class StarConnectivityRouter(Router):
@@ -48,7 +49,7 @@ def __call__(self, circuit: Circuit):
             circuit (:class:`qibo.models.circuit.Circuit`): The original Qibo circuit to transform.
                 Only single qubit gates and two qubits gates are supported by the router.
         """
-
+        assert_qubit_match(circuit, self.connectivity)
         middle_qubit_idx = circuit.wire_names.index(self.middle_qubit)
         nqubits = circuit.nqubits
         new = Circuit(nqubits=nqubits, wire_names=circuit.wire_names)
@@ -334,6 +335,7 @@ def __call__(self, circuit: Circuit):
             (:class:`qibo.models.circuit.Circuit`, dict): circut mapped to hardware topology,
                 and final physical-to-logical qubit mapping.
         """
+        assert_qubit_match(circuit, self.connectivity)
         self._preprocessing(circuit=circuit)
         while self._dag.number_of_nodes() != 0:
             execute_block_list = self._check_execution()
@@ -624,6 +626,7 @@ def __call__(self, circuit: Circuit):
         Returns:
             (:class:`qibo.models.circuit.Circuit`, dict): routed circuit and final layout.
         """
+        assert_qubit_match(circuit, self.connectivity)
         self._preprocessing(circuit=circuit)
         longest_path = np.max(self._dist_matrix)
 
diff --git a/src/qibo/transpiler/utils.py b/src/qibo/transpiler/utils.py
index 10d76a3f3d..7325db8f81 100644
--- a/src/qibo/transpiler/utils.py
+++ b/src/qibo/transpiler/utils.py
@@ -18,6 +18,20 @@
 from qibo.transpiler.unroller import NativeGates
 
 
+def assert_qubit_match(circuit: Circuit, connectivity: nx.Graph):
+    """Check if the number of qubits in the circuit matches the connectivity graph.
+
+    Args:
+        circuit (:class:`qibo.models.circuit.Circuit`): Circuit model to check.
+        connectivity (:class:`networkx.Graph`): Chip connectivity.
+    """
+    if circuit.nqubits != len(connectivity.nodes):
+        raise_error(
+            TranspilerPipelineError,
+            "Number of qubits in the circuit does not match the connectivity graph.",
+        )
+
+
 def assert_transpiling(
     original_circuit: Circuit,
     transpiled_circuit: Circuit,
diff --git a/tests/test_transpiler_pipeline.py b/tests/test_transpiler_pipeline.py
index d8d1379fb6..30f0cddfbe 100644
--- a/tests/test_transpiler_pipeline.py
+++ b/tests/test_transpiler_pipeline.py
@@ -85,38 +85,6 @@ def test_pipeline_default(ngates, names, star_connectivity):
     )
 
 
-def test_assert_circuit_equivalence_equal():
-    circ1 = Circuit(2)
-    circ2 = Circuit(2)
-    circ1.add(gates.X(0))
-    circ1.add(gates.CZ(0, 1))
-    circ2.add(gates.X(0))
-    circ2.add(gates.CZ(0, 1))
-    final_map = {0: 0, 1: 1}
-    assert_circuit_equivalence(circ1, circ2, final_map=final_map)
-
-
-def test_assert_circuit_equivalence_swap():
-    circ1 = Circuit(2)
-    circ2 = Circuit(2)
-    circ1.add(gates.X(0))
-    circ2.add(gates.SWAP(0, 1))
-    circ2.add(gates.X(1))
-    final_map = {0: 1, 1: 0}
-    assert_circuit_equivalence(circ1, circ2, final_map=final_map)
-
-
-def test_assert_circuit_equivalence_false():
-    circ1 = Circuit(2)
-    circ2 = Circuit(2)
-    circ1.add(gates.X(0))
-    circ2.add(gates.SWAP(0, 1))
-    circ2.add(gates.X(1))
-    final_map = {0: 0, 1: 1}
-    with pytest.raises(TranspilerPipelineError):
-        assert_circuit_equivalence(circ1, circ2, final_map=final_map)
-
-
 def test_int_qubit_names_default(star_connectivity):
     names = [1244, 1532, 2315, 6563, 8901]
     circ = Circuit(5, wire_names=names)
diff --git a/tests/test_transpiler_placer.py b/tests/test_transpiler_placer.py
index 306d686f0f..1b05743621 100644
--- a/tests/test_transpiler_placer.py
+++ b/tests/test_transpiler_placer.py
@@ -3,7 +3,7 @@
 
 from qibo import gates
 from qibo.models import Circuit
-from qibo.transpiler._exceptions import PlacementError
+from qibo.transpiler._exceptions import PlacementError, TranspilerPipelineError
 from qibo.transpiler.pipeline import restrict_connectivity_qubits
 from qibo.transpiler.placer import (
     Custom,
@@ -15,7 +15,7 @@
     _find_gates_qubits_pairs,
 )
 from qibo.transpiler.router import ShortestPaths
-from qibo.transpiler.utils import assert_mapping_consistency, assert_placement
+from qibo.transpiler.utils import assert_placement
 
 
 def star_circuit(names=["q0", "q1", "q2", "q3", "q4"]):
@@ -25,56 +25,6 @@ def star_circuit(names=["q0", "q1", "q2", "q3", "q4"]):
     return circuit
 
 
-def test_assert_placement_true(star_connectivity):
-    circuit = Circuit(5)
-    assert_placement(circuit, connectivity=star_connectivity())
-
-
-@pytest.mark.parametrize(
-    "qubits, names", [(5, ["A", "B", "C", "D", "F"]), (3, ["A", "B", "C"])]
-)
-def test_assert_placement_false(qubits, names, star_connectivity):
-    connectivity = star_connectivity()
-    circuit = Circuit(qubits, wire_names=names)
-    with pytest.raises(PlacementError):
-        assert_placement(circuit, connectivity)
-
-
-@pytest.mark.parametrize("qubits", [10, 1])
-def test_assert_placement_error(qubits, star_connectivity):
-    connectivity = star_connectivity()
-    circuit = Circuit(qubits)
-    with pytest.raises(PlacementError):
-        assert_placement(circuit, connectivity)
-
-
-@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
-def test_mapping_consistency(names, star_connectivity):
-    assert_mapping_consistency(names, star_connectivity(names))
-
-
-def test_mapping_consistency_error(star_connectivity):
-    with pytest.raises(PlacementError):
-        assert_mapping_consistency(["A", "B", "C", "D", "F"], star_connectivity())
-
-
-@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
-def test_mapping_consistency_restricted(names, star_connectivity):
-    connectivity = star_connectivity(names)
-    on_qubit = [names[0], names[2]]
-    restricted_connectivity = restrict_connectivity_qubits(connectivity, on_qubit)
-    assert_mapping_consistency(on_qubit, restricted_connectivity)
-
-
-@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
-def test_mapping_consistency_restricted_error(names, star_connectivity):
-    connectivity = star_connectivity(names)
-    on_qubit = [names[0], names[2]]
-    restricted_connectivity = restrict_connectivity_qubits(connectivity, on_qubit)
-    with pytest.raises(PlacementError):
-        assert_mapping_consistency([names[3], names[4]], restricted_connectivity)
-
-
 def test_gates_qubits_pairs():
     circuit = Circuit(5)
     circuit.add(gates.CNOT(0, 1))
@@ -152,7 +102,7 @@ def test_custom_error_circuit(star_connectivity):
     custom_layout = [4, 3, 2, 1, 0]
     connectivity = star_connectivity(names=custom_layout)
     placer = Custom(connectivity=connectivity, initial_map=custom_layout)
-    with pytest.raises(ValueError):
+    with pytest.raises(TranspilerPipelineError):
         placer(circuit)
 
 
diff --git a/tests/test_transpiler_router.py b/tests/test_transpiler_router.py
index 0b5e21bc40..2a09e23725 100644
--- a/tests/test_transpiler_router.py
+++ b/tests/test_transpiler_router.py
@@ -93,25 +93,6 @@ def matched_circuit(names):
     return circuit
 
 
-def test_assert_connectivity(star_connectivity):
-    names = ["A", "B", "C", "D", "E"]
-    assert_connectivity(star_connectivity(names), matched_circuit(names))
-
-
-def test_assert_connectivity_false(star_connectivity):
-    circuit = Circuit(5)
-    circuit.add(gates.CZ(0, 1))
-    with pytest.raises(ConnectivityError):
-        assert_connectivity(star_connectivity(), circuit)
-
-
-def test_assert_connectivity_3q(star_connectivity):
-    circuit = Circuit(5)
-    circuit.add(gates.TOFFOLI(0, 1, 2))
-    with pytest.raises(ConnectivityError):
-        assert_connectivity(star_connectivity(), circuit)
-
-
 def test_bell_state_3q():
     circuit = Circuit(3)
     circuit.add(gates.H(0))
@@ -407,7 +388,7 @@ def test_sabre_matched(names, star_connectivity):
     connectivity = star_connectivity(names=names)
     circuit = matched_circuit(names)
     original_circuit = circuit.copy()
-    placer = Trivial()
+    placer = Trivial(connectivity=connectivity)
     router = Sabre(connectivity=connectivity)
 
     placer(circuit)
@@ -428,7 +409,7 @@ def test_sabre_simple(seed, star_connectivity):
     circ = Circuit(5)
     circ.add(gates.CZ(0, 1))
     original_circuit = circ.copy()
-    placer = Trivial()
+    placer = Trivial(connectivity=connectivity)
     router = Sabre(connectivity=connectivity, seed=seed)
 
     placer(circ)
@@ -506,10 +487,11 @@ def test_sabre_random_circuits_grid(
 
 
 def test_sabre_memory_map(star_connectivity):
-    placer = Trivial()
+    connectivity = star_connectivity()
+    placer = Trivial(connectivity=connectivity)
     layout_circ = Circuit(5)
     placer(layout_circ)
-    router = Sabre(connectivity=star_connectivity())
+    router = Sabre(connectivity=connectivity)
     router._preprocessing(circuit=star_circuit())
     router._memory_map = [[1, 0, 2, 3, 4]]
     value = router._compute_cost((0, 1))
@@ -554,7 +536,7 @@ def test_restrict_qubits(router_algorithm, star_connectivity):
 
 
 def test_star_error_multi_qubit(star_connectivity):
-    circuit = Circuit(3)
+    circuit = Circuit(5)
     circuit.add(gates.TOFFOLI(0, 1, 2))
     connectivity = star_connectivity(middle_qubit_idx=2)
     transpiler = StarConnectivityRouter(connectivity)
diff --git a/tests/test_transpiler_unitary_decompositions.py b/tests/test_transpiler_unitary_decompositions.py
index 49f8cf2fe9..25a0ec25f3 100644
--- a/tests/test_transpiler_unitary_decompositions.py
+++ b/tests/test_transpiler_unitary_decompositions.py
@@ -3,7 +3,6 @@
 from scipy.linalg import expm
 
 from qibo import Circuit, gates, matrices
-from qibo.config import PRECISION_TOL
 from qibo.quantum_info.linalg_operations import partial_trace
 from qibo.quantum_info.metrics import purity
 from qibo.quantum_info.random_ensembles import random_unitary
diff --git a/tests/test_transpiler_unroller.py b/tests/test_transpiler_unroller.py
index c72b735c3f..f232dab702 100644
--- a/tests/test_transpiler_unroller.py
+++ b/tests/test_transpiler_unroller.py
@@ -39,36 +39,6 @@ def test_translate_gate_error_2q():
         translate_gate(gates.CZ(0, 1), natives)
 
 
-def test_assert_decomposition():
-    circuit = Circuit(2)
-    circuit.add(gates.CZ(0, 1))
-    circuit.add(gates.Z(0))
-    circuit.add(gates.M(1))
-    assert_decomposition(circuit, native_gates=NativeGates.default())
-
-
-def test_assert_decomposition_fail_1q():
-    circuit = Circuit(1)
-    circuit.add(gates.X(0))
-    with pytest.raises(DecompositionError):
-        assert_decomposition(circuit, native_gates=NativeGates.default())
-
-
-@pytest.mark.parametrize("gate", [gates.CNOT(0, 1), gates.iSWAP(0, 1)])
-def test_assert_decomposition_fail_2q(gate):
-    circuit = Circuit(2)
-    circuit.add(gate)
-    with pytest.raises(DecompositionError):
-        assert_decomposition(circuit, native_gates=NativeGates.default())
-
-
-def test_assert_decomposition_fail_3q():
-    circuit = Circuit(3)
-    circuit.add(gates.TOFFOLI(0, 1, 2))
-    with pytest.raises(DecompositionError):
-        assert_decomposition(circuit, native_gates=NativeGates.default())
-
-
 @pytest.mark.parametrize(
     "natives_2q",
     [NativeGates.CZ, NativeGates.iSWAP, NativeGates.CZ | NativeGates.iSWAP],
diff --git a/tests/test_transpiler_utils.py b/tests/test_transpiler_utils.py
new file mode 100644
index 0000000000..f804c4a8fd
--- /dev/null
+++ b/tests/test_transpiler_utils.py
@@ -0,0 +1,164 @@
+import pytest
+
+from qibo import gates
+from qibo.models.circuit import Circuit
+from qibo.transpiler._exceptions import (
+    ConnectivityError,
+    DecompositionError,
+    PlacementError,
+    TranspilerPipelineError,
+)
+from qibo.transpiler.pipeline import restrict_connectivity_qubits
+from qibo.transpiler.unroller import NativeGates
+from qibo.transpiler.utils import (
+    assert_circuit_equivalence,
+    assert_connectivity,
+    assert_decomposition,
+    assert_mapping_consistency,
+    assert_placement,
+    assert_qubit_match,
+)
+
+
+def test_assert_qubit_match(star_connectivity):
+    circuit = Circuit(3)
+    with pytest.raises(TranspilerPipelineError):
+        assert_qubit_match(circuit, star_connectivity())
+
+    circuit = Circuit(5)
+    assert_qubit_match(circuit, star_connectivity())
+
+
+def test_assert_circuit_equivalence_equal():
+    circ1 = Circuit(2)
+    circ2 = Circuit(2)
+    circ1.add(gates.X(0))
+    circ1.add(gates.CZ(0, 1))
+    circ2.add(gates.X(0))
+    circ2.add(gates.CZ(0, 1))
+    final_map = {0: 0, 1: 1}
+    assert_circuit_equivalence(circ1, circ2, final_map=final_map)
+
+
+def test_assert_circuit_equivalence_swap():
+    circ1 = Circuit(2)
+    circ2 = Circuit(2)
+    circ1.add(gates.X(0))
+    circ2.add(gates.SWAP(0, 1))
+    circ2.add(gates.X(1))
+    final_map = {0: 1, 1: 0}
+    assert_circuit_equivalence(circ1, circ2, final_map=final_map)
+
+
+def test_assert_circuit_equivalence_false():
+    circ1 = Circuit(2)
+    circ2 = Circuit(2)
+    circ1.add(gates.X(0))
+    circ2.add(gates.SWAP(0, 1))
+    circ2.add(gates.X(1))
+    final_map = {0: 0, 1: 1}
+    with pytest.raises(TranspilerPipelineError):
+        assert_circuit_equivalence(circ1, circ2, final_map=final_map)
+
+
+@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
+def test_mapping_consistency(names, star_connectivity):
+    assert_mapping_consistency(names, star_connectivity(names))
+
+
+def test_mapping_consistency_error(star_connectivity):
+    with pytest.raises(PlacementError):
+        assert_mapping_consistency(["A", "B", "C", "D", "F"], star_connectivity())
+
+
+@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
+def test_mapping_consistency_restricted(names, star_connectivity):
+    connectivity = star_connectivity(names)
+    on_qubit = [names[0], names[2]]
+    restricted_connectivity = restrict_connectivity_qubits(connectivity, on_qubit)
+    assert_mapping_consistency(on_qubit, restricted_connectivity)
+
+
+@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
+def test_mapping_consistency_restricted_error(names, star_connectivity):
+    connectivity = star_connectivity(names)
+    on_qubit = [names[0], names[2]]
+    restricted_connectivity = restrict_connectivity_qubits(connectivity, on_qubit)
+    with pytest.raises(PlacementError):
+        assert_mapping_consistency([names[3], names[4]], restricted_connectivity)
+
+
+def test_assert_placement_true(star_connectivity):
+    circuit = Circuit(5)
+    assert_placement(circuit, connectivity=star_connectivity())
+
+
+@pytest.mark.parametrize(
+    "qubits, names", [(5, ["A", "B", "C", "D", "F"]), (3, ["A", "B", "C"])]
+)
+def test_assert_placement_false(qubits, names, star_connectivity):
+    connectivity = star_connectivity()
+    circuit = Circuit(qubits, wire_names=names)
+    with pytest.raises(PlacementError):
+        assert_placement(circuit, connectivity)
+
+
+@pytest.mark.parametrize("qubits", [10, 1])
+def test_assert_placement_error(qubits, star_connectivity):
+    connectivity = star_connectivity()
+    circuit = Circuit(qubits)
+    with pytest.raises(PlacementError):
+        assert_placement(circuit, connectivity)
+
+
+def test_assert_decomposition():
+    circuit = Circuit(2)
+    circuit.add(gates.CZ(0, 1))
+    circuit.add(gates.Z(0))
+    circuit.add(gates.M(1))
+    assert_decomposition(circuit, native_gates=NativeGates.default())
+
+
+def test_assert_decomposition_fail_1q():
+    circuit = Circuit(1)
+    circuit.add(gates.X(0))
+    with pytest.raises(DecompositionError):
+        assert_decomposition(circuit, native_gates=NativeGates.default())
+
+
+@pytest.mark.parametrize("gate", [gates.CNOT(0, 1), gates.iSWAP(0, 1)])
+def test_assert_decomposition_fail_2q(gate):
+    circuit = Circuit(2)
+    circuit.add(gate)
+    with pytest.raises(DecompositionError):
+        assert_decomposition(circuit, native_gates=NativeGates.default())
+
+
+def test_assert_decomposition_fail_3q():
+    circuit = Circuit(3)
+    circuit.add(gates.TOFFOLI(0, 1, 2))
+    with pytest.raises(DecompositionError):
+        assert_decomposition(circuit, native_gates=NativeGates.default())
+
+
+def test_assert_connectivity(star_connectivity):
+    names = ["A", "B", "C", "D", "E"]
+    circuit = Circuit(5, wire_names=names)
+    circuit.add(gates.CZ(0, 2))
+    circuit.add(gates.CZ(1, 2))
+    circuit.add(gates.CZ(2, 1))
+    assert_connectivity(star_connectivity(names), circuit)
+
+
+def test_assert_connectivity_false(star_connectivity):
+    circuit = Circuit(5)
+    circuit.add(gates.CZ(0, 1))
+    with pytest.raises(ConnectivityError):
+        assert_connectivity(star_connectivity(), circuit)
+
+
+def test_assert_connectivity_3q(star_connectivity):
+    circuit = Circuit(5)
+    circuit.add(gates.TOFFOLI(0, 1, 2))
+    with pytest.raises(ConnectivityError):
+        assert_connectivity(star_connectivity(), circuit)

From 942991a746df7eb3ef3872a4d209a7bb596caccd Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Mon, 28 Oct 2024 14:21:46 +0400
Subject: [PATCH 20/34] fix: pandoc update result draw()

---
 doc/source/code-examples/advancedexamples.rst |  6 +++---
 doc/source/code-examples/examples.rst         | 20 +++++++++----------
 src/qibo/gates/abstract.py                    |  8 ++++----
 src/qibo/gates/measurements.py                |  6 +++---
 4 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/doc/source/code-examples/advancedexamples.rst b/doc/source/code-examples/advancedexamples.rst
index e506bca6c3..cea5acf77c 100644
--- a/doc/source/code-examples/advancedexamples.rst
+++ b/doc/source/code-examples/advancedexamples.rst
@@ -1280,9 +1280,9 @@ Let's see how to use them. For starters, let's define a dummy circuit with some
    # visualize the circuit
    circ.draw()
 
-   #  q0: ─RZ─RX─RZ─RX─RZ─o────o────────M─
-   #  q1: ─RZ─RX─RZ─RX─RZ─X─RZ─X─o────o─M─
-   #  q2: ─RZ─RX─RZ─RX─RZ────────X─RZ─X─M─
+   #  0: ─RZ─RX─RZ─RX─RZ─o────o────────M─
+   #  1: ─RZ─RX─RZ─RX─RZ─X─RZ─X─o────o─M─
+   #  2: ─RZ─RX─RZ─RX─RZ────────X─RZ─X─M─
 
 .. testoutput::
    :hide:
diff --git a/doc/source/code-examples/examples.rst b/doc/source/code-examples/examples.rst
index ca5bdc190c..83621a6383 100644
--- a/doc/source/code-examples/examples.rst
+++ b/doc/source/code-examples/examples.rst
@@ -313,20 +313,20 @@ For example
     c.draw()
     # Prints
     '''
-    q0: ─H─U1─U1─U1─U1───────────────────────────x───
-    q1: ───o──|──|──|──H─U1─U1─U1────────────────|─x─
-    q2: ──────o──|──|────o──|──|──H─U1─U1────────|─|─
-    q3: ─────────o──|───────o──|────o──|──H─U1───|─x─
-    q4: ────────────o──────────o───────o────o──H─x───
+    0: ─H─U1─U1─U1─U1───────────────────────────x───
+    1: ───o──|──|──|──H─U1─U1─U1────────────────|─x─
+    2: ──────o──|──|────o──|──|──H─U1─U1────────|─|─
+    3: ─────────o──|───────o──|────o──|──H─U1───|─x─
+    4: ────────────o──────────o───────o────o──H─x───
     '''
 .. testoutput::
     :hide:
 
-    q0: ─H─U1─U1─U1─U1───────────────────────────x───
-    q1: ───o──|──|──|──H─U1─U1─U1────────────────|─x─
-    q2: ──────o──|──|────o──|──|──H─U1─U1────────|─|─
-    q3: ─────────o──|───────o──|────o──|──H─U1───|─x─
-    q4: ────────────o──────────o───────o────o──H─x───
+    0: ─H─U1─U1─U1─U1───────────────────────────x───
+    1: ───o──|──|──|──H─U1─U1─U1────────────────|─x─
+    2: ──────o──|──|────o──|──|──H─U1─U1────────|─|─
+    3: ─────────o──|───────o──|────o──|──H─U1───|─x─
+    4: ────────────o──────────o───────o────o──H─x───
 
 How to visualize a circuit with style?
 --------------------------------------
diff --git a/src/qibo/gates/abstract.py b/src/qibo/gates/abstract.py
index a2919c9f95..3b038f2e96 100644
--- a/src/qibo/gates/abstract.py
+++ b/src/qibo/gates/abstract.py
@@ -273,10 +273,10 @@ def on_qubits(self, qubit_map) -> "Gate":
                 c.draw()
             .. testoutput::
 
-                q0: ───X─────
-                q1: ───|─o─X─
-                q2: ─o─|─|─o─
-                q3: ─X─o─X───
+                0: ───X─────
+                1: ───|─o─X─
+                2: ─o─|─|─o─
+                3: ─X─o─X───
         """
         if self.is_controlled_by:
             targets = (qubit_map.get(q) for q in self.target_qubits)
diff --git a/src/qibo/gates/measurements.py b/src/qibo/gates/measurements.py
index bc2c375dc3..b35b3f0f47 100644
--- a/src/qibo/gates/measurements.py
+++ b/src/qibo/gates/measurements.py
@@ -250,9 +250,9 @@ def on_qubits(self, qubit_map) -> "Gate":
                 c.draw()
             .. testoutput::
 
-                q0: ─M─
-                q1: ─|─
-                q2: ─M─
+                0: ─M─
+                1: ─|─
+                2: ─M─
         """
 
         qubits = (qubit_map.get(q) for q in self.qubits)

From 25d87886c6a9bf6e66c45bedd82bd566c86e56c4 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Mon, 28 Oct 2024 15:40:53 +0400
Subject: [PATCH 21/34] fix: pandoc update

---
 doc/source/code-examples/advancedexamples.rst | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/doc/source/code-examples/advancedexamples.rst b/doc/source/code-examples/advancedexamples.rst
index cea5acf77c..684d3f92dd 100644
--- a/doc/source/code-examples/advancedexamples.rst
+++ b/doc/source/code-examples/advancedexamples.rst
@@ -1398,12 +1398,12 @@ number of CNOT or RX pairs (depending on the value of ``insertion_gate``) insert
 circuit in correspondence to the original ones. Since we decided to simulate noisy CNOTs::
 
    Level 1
-   q0: ─X─  -->  q0: ─X───X──X─
-   q1: ─o─  -->  q1: ─o───o──o─
+   0: ─X─  -->  0: ─X───X──X─
+   1: ─o─  -->  1: ─o───o──o─
 
    Level 2
-   q0: ─X─  -->  q0: ─X───X──X───X──X─
-   q1: ─o─  -->  q1: ─o───o──o───o──o─
+   0: ─X─  -->  0: ─X───X──X───X──X─
+   1: ─o─  -->  1: ─o───o──o───o──o─
 
    .
    .
@@ -2094,11 +2094,12 @@ Multiple transpilation steps can be implemented using the :class:`qibo.transpile
 
     from qibo import gates
     from qibo.models import Circuit
-    from qibo.transpiler.pipeline import Passes, assert_transpiling
+    from qibo.transpiler.pipeline import Passes
     from qibo.transpiler.optimizer import Preprocessing
     from qibo.transpiler.router import ShortestPaths
     from qibo.transpiler.unroller import Unroller, NativeGates
     from qibo.transpiler.placer import Random
+    from qibo.transpiler.utils import assert_transpiling
 
     # Define connectivity as nx.Graph
     def star_connectivity():

From 93ac772c579f932e9d70fe7c79f4862b81da829f Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Mon, 28 Oct 2024 16:20:48 +0400
Subject: [PATCH 22/34] feat: Circuit __init__ int/list first arg init

---
 src/qibo/models/circuit.py   | 31 ++++++++++++++++++++++++++++---
 tests/test_models_circuit.py | 20 ++++++++++++++++++++
 2 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/src/qibo/models/circuit.py b/src/qibo/models/circuit.py
index c4d3714820..457b4f8ac3 100644
--- a/src/qibo/models/circuit.py
+++ b/src/qibo/models/circuit.py
@@ -120,7 +120,7 @@ class Circuit:
     A specific backend has to be used for performing calculations.
 
     Args:
-        nqubits (int): Total number of qubits in the circuit.
+        nqubits (int, list): Number of qubits in the circuit or a list of wire names.
         init_kwargs (dict): a dictionary with the following keys
 
             - *nqubits*
@@ -141,7 +141,7 @@ class Circuit:
             Defaults to ``False``.
         accelerators (dict, optional): Dictionary that maps device names to the number of times each
             device will be used. Defaults to ``None``.
-        wire_names (list, optional): Names for qubit wires.
+        wire_names (list, optional): Names for qubit wire names.
             If ``None``, defaults to [``0``, ``1``, ..., ``nqubits - 1``].
             If ``list`` is passed, length of ``list`` must match ``nqubits``.
         ndevices (int): Total number of devices. Defaults to ``None``.
@@ -153,11 +153,12 @@ class Circuit:
 
     def __init__(
         self,
-        nqubits: int,
+        nqubits: Optional[Union[str, list]] = None,
         accelerators=None,
         density_matrix: bool = False,
         wire_names: Optional[list] = None,
     ):
+        nqubits, wire_names = self._parse(nqubits, wire_names)
         if not isinstance(nqubits, int):
             raise_error(
                 TypeError,
@@ -203,6 +204,30 @@ def __init__(
                 )
             self._distributed_init(nqubits, accelerators)
 
+    def _parse(self, qubit_spec, wire_names):
+        """Parse the input arguments for defining a circuit. Allows the user to initialize the circuit as follows:
+
+        .. code-block:: python
+            c = Circuit(3)
+            c = Circuit(3, wire_names=["q0", "q1", "q2"])
+            c = Circuit(["q0", "q1", "q2"])
+        """
+        if qubit_spec is None and wire_names is not None:
+            return len(wire_names), wire_names
+        if qubit_spec is not None and wire_names is None:
+            if isinstance(qubit_spec, int):
+                return qubit_spec, None
+            if isinstance(qubit_spec, list):
+                return len(qubit_spec), qubit_spec
+        if qubit_spec is not None and wire_names is not None:
+            if qubit_spec == len(wire_names):
+                return qubit_spec, wire_names
+
+        raise_error(
+            ValueError,
+            "Number of qubits and wire names are not consistent.",
+        )
+
     def _distributed_init(self, nqubits, accelerators):  # pragma: no cover
         """Distributed implementation of :class:`qibo.models.circuit.Circuit`.
 
diff --git a/tests/test_models_circuit.py b/tests/test_models_circuit.py
index f521446c26..1b4ee2ec2b 100644
--- a/tests/test_models_circuit.py
+++ b/tests/test_models_circuit.py
@@ -48,6 +48,26 @@ def test_circuit_init():
     assert c.nqubits == 2
 
 
+def test_circuit_init_parse():
+    a = Circuit(3)
+    assert a.nqubits == 3 and a.wire_names == [0, 1, 2]
+    b = Circuit(3, wire_names=["a", "b", "c"])
+    assert b.nqubits == 3 and b.wire_names == ["a", "b", "c"]
+    c = Circuit(["a", "b", "c"])
+    assert c.nqubits == 3 and c.wire_names == ["a", "b", "c"]
+    d = Circuit(wire_names=["x", "y", "z"])
+    assert d.nqubits == 3 and d.wire_names == ["x", "y", "z"]
+
+
+def test_circuit_init_errors():
+    with pytest.raises(ValueError):
+        a = Circuit()
+    with pytest.raises(ValueError):
+        b = Circuit(3, wire_names=["a", "b"])
+    with pytest.raises(ValueError):
+        c = Circuit(["a", "b", "c"], wire_names=["x", "y"])
+
+
 def test_eigenstate(backend):
     nqubits = 3
     c = Circuit(nqubits)

From 41f5eff1cc44ad8df1c6c9485eda96d638b4f557 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Mon, 28 Oct 2024 16:46:59 +0400
Subject: [PATCH 23/34] fix: Circuit._parse -> _resolve_qubits

---
 src/qibo/models/circuit.py   | 51 ++++++++++++++++++------------------
 tests/test_models_circuit.py | 21 +++++++++++++--
 2 files changed, 45 insertions(+), 27 deletions(-)

diff --git a/src/qibo/models/circuit.py b/src/qibo/models/circuit.py
index 457b4f8ac3..08fc5822b4 100644
--- a/src/qibo/models/circuit.py
+++ b/src/qibo/models/circuit.py
@@ -158,7 +158,7 @@ def __init__(
         density_matrix: bool = False,
         wire_names: Optional[list] = None,
     ):
-        nqubits, wire_names = self._parse(nqubits, wire_names)
+        nqubits, wire_names = _resolve_qubits(nqubits, wire_names)
         if not isinstance(nqubits, int):
             raise_error(
                 TypeError,
@@ -204,30 +204,6 @@ def __init__(
                 )
             self._distributed_init(nqubits, accelerators)
 
-    def _parse(self, qubit_spec, wire_names):
-        """Parse the input arguments for defining a circuit. Allows the user to initialize the circuit as follows:
-
-        .. code-block:: python
-            c = Circuit(3)
-            c = Circuit(3, wire_names=["q0", "q1", "q2"])
-            c = Circuit(["q0", "q1", "q2"])
-        """
-        if qubit_spec is None and wire_names is not None:
-            return len(wire_names), wire_names
-        if qubit_spec is not None and wire_names is None:
-            if isinstance(qubit_spec, int):
-                return qubit_spec, None
-            if isinstance(qubit_spec, list):
-                return len(qubit_spec), qubit_spec
-        if qubit_spec is not None and wire_names is not None:
-            if qubit_spec == len(wire_names):
-                return qubit_spec, wire_names
-
-        raise_error(
-            ValueError,
-            "Number of qubits and wire names are not consistent.",
-        )
-
     def _distributed_init(self, nqubits, accelerators):  # pragma: no cover
         """Distributed implementation of :class:`qibo.models.circuit.Circuit`.
 
@@ -1387,3 +1363,28 @@ def draw(self, line_wrap: int = 70, legend: bool = False):
             String containing text circuit diagram.
         """
         sys.stdout.write(self.diagram(line_wrap, legend) + "\n")
+
+
+def _resolve_qubits(qubits, wire_names):
+    """Parse the input arguments for defining a circuit. Allows the user to initialize the circuit as follows:
+
+    .. code-block:: python
+        c = Circuit(3)
+        c = Circuit(3, wire_names=["q0", "q1", "q2"])
+        c = Circuit(["q0", "q1", "q2"])
+    """
+    if qubits is None and wire_names is not None:
+        return len(wire_names), wire_names
+    if qubits is not None and wire_names is None:
+        if isinstance(qubits, int):
+            return qubits, None
+        if isinstance(qubits, list):
+            return len(qubits), qubits
+    if qubits is not None and wire_names is not None:
+        if qubits == len(wire_names):
+            return qubits, wire_names
+
+    raise_error(
+        ValueError,
+        "Number of qubits and wire names are not consistent.",
+    )
diff --git a/tests/test_models_circuit.py b/tests/test_models_circuit.py
index 1b4ee2ec2b..b10fa71c5d 100644
--- a/tests/test_models_circuit.py
+++ b/tests/test_models_circuit.py
@@ -6,6 +6,7 @@
 import pytest
 
 from qibo import Circuit, gates
+from qibo.models.circuit import _resolve_qubits
 from qibo.models.utils import initialize
 
 
@@ -48,7 +49,23 @@ def test_circuit_init():
     assert c.nqubits == 2
 
 
-def test_circuit_init_parse():
+def test_resolve_qubits():
+    nqubits, wire_names = _resolve_qubits(3, None)
+    assert nqubits == 3 and wire_names is None
+    nqubits, wire_names = _resolve_qubits(3, ["a", "b", "c"])
+    assert nqubits == 3 and wire_names == ["a", "b", "c"]
+    nqubits, wire_names = _resolve_qubits(["a", "b", "c"], None)
+    assert nqubits == 3 and wire_names == ["a", "b", "c"]
+
+    with pytest.raises(ValueError):
+        _resolve_qubits(None, None)
+    with pytest.raises(ValueError):
+        _resolve_qubits(3, ["a", "b"])
+    with pytest.raises(ValueError):
+        _resolve_qubits(["a", "b", "c"], ["x", "y"])
+
+
+def test_circuit_init_resolve_qubits():
     a = Circuit(3)
     assert a.nqubits == 3 and a.wire_names == [0, 1, 2]
     b = Circuit(3, wire_names=["a", "b", "c"])
@@ -59,7 +76,7 @@ def test_circuit_init_parse():
     assert d.nqubits == 3 and d.wire_names == ["x", "y", "z"]
 
 
-def test_circuit_init_errors():
+def test_circuit_init_resolve_qubits_err():
     with pytest.raises(ValueError):
         a = Circuit()
     with pytest.raises(ValueError):

From a4f2092708a9f15e066e28fdeb6da18eaaaa302f Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Wed, 30 Oct 2024 10:26:08 +0400
Subject: [PATCH 24/34] fix: minor updates / update docstring of qibo.Circuit

---
 doc/source/code-examples/advancedexamples.rst |  4 +--
 src/qibo/models/circuit.py                    | 33 ++++++++++++++-----
 2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/doc/source/code-examples/advancedexamples.rst b/doc/source/code-examples/advancedexamples.rst
index 684d3f92dd..e94faf9f58 100644
--- a/doc/source/code-examples/advancedexamples.rst
+++ b/doc/source/code-examples/advancedexamples.rst
@@ -2103,9 +2103,7 @@ Multiple transpilation steps can be implemented using the :class:`qibo.transpile
 
     # Define connectivity as nx.Graph
     def star_connectivity():
-        chip = nx.Graph()
-        chip.add_nodes_from(["q0", "q1", "q2", "q3", "q4"])
-        chip.add_edges_from([("q0", "q2"), ("q1", "q2"), ("q2", "q3"), ("q2", "q4")])
+        chip = nx.Graph([("q0", "q2"), ("q1", "q2"), ("q2", "q3"), ("q2", "q4")])
         return chip
 
     # Define the circuit
diff --git a/src/qibo/models/circuit.py b/src/qibo/models/circuit.py
index 08fc5822b4..29d44e6d0f 100644
--- a/src/qibo/models/circuit.py
+++ b/src/qibo/models/circuit.py
@@ -119,8 +119,23 @@ class Circuit:
     This circuit is symbolic and cannot perform calculations.
     A specific backend has to be used for performing calculations.
 
+    Circuits can be created with a specific number of qubits and wire names.
+    Example:
+        .. testcode::
+            from qibo import Circuit
+            c = Circuit(5)  # Default wire names are [0, 1, 2, 3, 4]
+            c = Circuit(["A", "B", "C", "D", "E"])
+            c = Circuit(5, wire_names=["A", "B", "C", "D", "E"])
+            c = Circuit(wire_names=["A", "B", "C", "D", "E"])
+
     Args:
-        nqubits (int, list): Number of qubits in the circuit or a list of wire names.
+        nqubits (int | list, optional): Number of qubits in the circuit or a list of wire names.
+        wire_names (list, optional): List of wire names.
+            - Either ``nqubits`` or ``wire_names`` must be provided.
+            - If only ``nqubits`` is provided, wire names will default to [``0``, ``1``, ..., ``nqubits - 1``].
+            - If only ``wire_names`` is provided, ``nqubits`` will be set to the length of ``wire_names``.
+            - ``nqubits`` and ``wire_names`` must be consistent with each other.
+
         init_kwargs (dict): a dictionary with the following keys
 
             - *nqubits*
@@ -141,9 +156,6 @@ class Circuit:
             Defaults to ``False``.
         accelerators (dict, optional): Dictionary that maps device names to the number of times each
             device will be used. Defaults to ``None``.
-        wire_names (list, optional): Names for qubit wire names.
-            If ``None``, defaults to [``0``, ``1``, ..., ``nqubits - 1``].
-            If ``list`` is passed, length of ``list`` must match ``nqubits``.
         ndevices (int): Total number of devices. Defaults to ``None``.
         nglobal (int): Base two logarithm of the number of devices. Defaults to ``None``.
         nlocal (int): Total number of available qubits in each device. Defaults to ``None``.
@@ -385,7 +397,7 @@ def light_cone(self, *qubits):
         qubit_map = {q: i for i, q in enumerate(sorted(qubits))}
         kwargs = dict(self.init_kwargs)
         kwargs["nqubits"] = len(qubits)
-        kwargs["wire_names"] = [self.wire_names[q] for q in list(sorted(qubits))]
+        kwargs["wire_names"] = [self.wire_names[q] for q in sorted(qubits)]
         circuit = self.__class__(**kwargs)
         circuit.add(gate.on_qubits(qubit_map) for gate in reversed(list_of_gates))
         return circuit, qubit_map
@@ -1368,10 +1380,13 @@ def draw(self, line_wrap: int = 70, legend: bool = False):
 def _resolve_qubits(qubits, wire_names):
     """Parse the input arguments for defining a circuit. Allows the user to initialize the circuit as follows:
 
-    .. code-block:: python
-        c = Circuit(3)
-        c = Circuit(3, wire_names=["q0", "q1", "q2"])
-        c = Circuit(["q0", "q1", "q2"])
+    Example:
+        .. code-block:: python
+            from qibo import Circuit
+            c = Circuit(3)
+            c = Circuit(3, wire_names=["q0", "q1", "q2"])
+            c = Circuit(["q0", "q1", "q2"])
+            c = Circuit(wire_names=["q0", "q1", "q2"])
     """
     if qubits is None and wire_names is not None:
         return len(wire_names), wire_names

From 10be459c7ee5bd681a2403ef25d735a2987e04d6 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Wed, 30 Oct 2024 10:47:44 +0400
Subject: [PATCH 25/34] fix: update test files _resolve_qubits / wire_names
 setter

---
 src/qibo/models/circuit.py   | 19 +++++--------------
 tests/test_models_circuit.py |  6 ++++--
 2 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/src/qibo/models/circuit.py b/src/qibo/models/circuit.py
index 29d44e6d0f..042b31632e 100644
--- a/src/qibo/models/circuit.py
+++ b/src/qibo/models/circuit.py
@@ -171,16 +171,6 @@ def __init__(
         wire_names: Optional[list] = None,
     ):
         nqubits, wire_names = _resolve_qubits(nqubits, wire_names)
-        if not isinstance(nqubits, int):
-            raise_error(
-                TypeError,
-                f"Number of qubits must be an integer but is {nqubits}.",
-            )
-        if nqubits < 1:
-            raise_error(
-                ValueError,
-                f"Number of qubits must be positive but is {nqubits}.",
-            )
         self.nqubits = nqubits
         self.init_kwargs = {
             "nqubits": nqubits,
@@ -1391,15 +1381,16 @@ def _resolve_qubits(qubits, wire_names):
     if qubits is None and wire_names is not None:
         return len(wire_names), wire_names
     if qubits is not None and wire_names is None:
-        if isinstance(qubits, int):
+        if isinstance(qubits, int) and qubits > 0:
             return qubits, None
         if isinstance(qubits, list):
             return len(qubits), qubits
     if qubits is not None and wire_names is not None:
-        if qubits == len(wire_names):
-            return qubits, wire_names
+        if isinstance(qubits, int) and isinstance(wire_names, list):
+            if qubits == len(wire_names):
+                return qubits, wire_names
 
     raise_error(
         ValueError,
-        "Number of qubits and wire names are not consistent.",
+        "Invalid input arguments for defining a circuit.",
     )
diff --git a/tests/test_models_circuit.py b/tests/test_models_circuit.py
index b10fa71c5d..b2b2ca904d 100644
--- a/tests/test_models_circuit.py
+++ b/tests/test_models_circuit.py
@@ -56,6 +56,8 @@ def test_resolve_qubits():
     assert nqubits == 3 and wire_names == ["a", "b", "c"]
     nqubits, wire_names = _resolve_qubits(["a", "b", "c"], None)
     assert nqubits == 3 and wire_names == ["a", "b", "c"]
+    nqubits, wire_names = _resolve_qubits(None, ["x", "y", "z"])
+    assert nqubits == 3 and wire_names == ["x", "y", "z"]
 
     with pytest.raises(ValueError):
         _resolve_qubits(None, None)
@@ -683,9 +685,9 @@ def test_circuit_wire_names():
     assert circuit._wire_names == ["a", "b", "c", "d", "e"]
 
     with pytest.raises(TypeError):
-        circuit = Circuit(5, wire_names=1)
+        circuit.wire_names = 5
     with pytest.raises(ValueError):
-        circuit = Circuit(5, wire_names=["a", "b", "c"])
+        circuit.wire_names = ["a", "b", "c", "d"]
 
 
 def test_circuit_draw_wire_names():

From a1d3302ffd583c913bff6ac5460d85fee0769faa Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Wed, 30 Oct 2024 11:23:03 +0400
Subject: [PATCH 26/34] fix: combine similar assert func to assert_placement

---
 src/qibo/transpiler/placer.py  | 15 ++++----
 src/qibo/transpiler/router.py  |  8 ++---
 src/qibo/transpiler/utils.py   | 49 +++++---------------------
 tests/test_transpiler_utils.py | 63 +++++++++++++---------------------
 4 files changed, 43 insertions(+), 92 deletions(-)

diff --git a/src/qibo/transpiler/placer.py b/src/qibo/transpiler/placer.py
index 64826946c1..4601fadf7d 100644
--- a/src/qibo/transpiler/placer.py
+++ b/src/qibo/transpiler/placer.py
@@ -9,7 +9,7 @@
 from qibo.transpiler._exceptions import PlacementError
 from qibo.transpiler.abstract import Placer, Router
 from qibo.transpiler.router import _find_connected_qubit
-from qibo.transpiler.utils import assert_placement, assert_qubit_match
+from qibo.transpiler.utils import assert_placement
 
 
 def _find_gates_qubits_pairs(circuit: Circuit):
@@ -66,7 +66,7 @@ def __call__(self, circuit: Circuit):
             circuit (:class:`qibo.models.circuit.Circuit`): The original Qibo circuit to transform.
                 Only single qubit gates and two qubits gates are supported by the router.
         """
-        assert_qubit_match(circuit, self.connectivity)
+        assert_placement(circuit, self.connectivity)
         middle_qubit_idx = circuit.wire_names.index(self.middle_qubit)
         wire_names = circuit.wire_names.copy()
 
@@ -109,7 +109,7 @@ def __call__(self, circuit: Circuit = None):
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
         """
-        assert_qubit_match(circuit, self.connectivity)
+        assert_placement(circuit, self.connectivity)
         return
 
 
@@ -132,7 +132,8 @@ def __call__(self, circuit: Circuit):
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
         """
-        assert_qubit_match(circuit, self.connectivity)
+        assert_placement(circuit, self.connectivity)
+
         if isinstance(self.initial_map, dict):
             circuit.wire_names = sorted(self.initial_map, key=self.initial_map.get)
         elif isinstance(self.initial_map, list):
@@ -164,7 +165,7 @@ def __call__(self, circuit: Circuit):
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
         """
-        assert_qubit_match(circuit, self.connectivity)
+        assert_placement(circuit, self.connectivity)
         gates_qubits_pairs = _find_gates_qubits_pairs(circuit)
         if len(gates_qubits_pairs) < 3:
             raise_error(
@@ -223,7 +224,7 @@ def __call__(self, circuit):
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): Circuit to be transpiled.
         """
-        assert_qubit_match(circuit, self.connectivity)
+        assert_placement(circuit, self.connectivity)
         _, local_state = _check_backend_and_local_state(self.seed, backend=None)
         gates_qubits_pairs = _find_gates_qubits_pairs(circuit)
         nodes = self.connectivity.number_of_nodes()
@@ -309,7 +310,7 @@ def __call__(self, circuit: Circuit):
         Args:
             circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
         """
-        assert_qubit_match(circuit, self.connectivity)
+        assert_placement(circuit, self.connectivity)
         self.routing_algorithm.connectivity = self.connectivity
         new_circuit = self._assemble_circuit(circuit)
         self._routing_step(new_circuit)
diff --git a/src/qibo/transpiler/router.py b/src/qibo/transpiler/router.py
index 3a5505a51f..d4a782740b 100644
--- a/src/qibo/transpiler/router.py
+++ b/src/qibo/transpiler/router.py
@@ -11,7 +11,7 @@
 from qibo.transpiler._exceptions import ConnectivityError
 from qibo.transpiler.abstract import Router
 from qibo.transpiler.blocks import Block, CircuitBlocks
-from qibo.transpiler.utils import assert_qubit_match
+from qibo.transpiler.utils import assert_placement
 
 
 class StarConnectivityRouter(Router):
@@ -49,7 +49,7 @@ def __call__(self, circuit: Circuit):
             circuit (:class:`qibo.models.circuit.Circuit`): The original Qibo circuit to transform.
                 Only single qubit gates and two qubits gates are supported by the router.
         """
-        assert_qubit_match(circuit, self.connectivity)
+        assert_placement(circuit, self.connectivity)
         middle_qubit_idx = circuit.wire_names.index(self.middle_qubit)
         nqubits = circuit.nqubits
         new = Circuit(nqubits=nqubits, wire_names=circuit.wire_names)
@@ -335,7 +335,7 @@ def __call__(self, circuit: Circuit):
             (:class:`qibo.models.circuit.Circuit`, dict): circut mapped to hardware topology,
                 and final physical-to-logical qubit mapping.
         """
-        assert_qubit_match(circuit, self.connectivity)
+        assert_placement(circuit, self.connectivity)
         self._preprocessing(circuit=circuit)
         while self._dag.number_of_nodes() != 0:
             execute_block_list = self._check_execution()
@@ -626,7 +626,7 @@ def __call__(self, circuit: Circuit):
         Returns:
             (:class:`qibo.models.circuit.Circuit`, dict): routed circuit and final layout.
         """
-        assert_qubit_match(circuit, self.connectivity)
+        assert_placement(circuit, self.connectivity)
         self._preprocessing(circuit=circuit)
         longest_path = np.max(self._dist_matrix)
 
diff --git a/src/qibo/transpiler/utils.py b/src/qibo/transpiler/utils.py
index 7325db8f81..89bd367d79 100644
--- a/src/qibo/transpiler/utils.py
+++ b/src/qibo/transpiler/utils.py
@@ -18,20 +18,6 @@
 from qibo.transpiler.unroller import NativeGates
 
 
-def assert_qubit_match(circuit: Circuit, connectivity: nx.Graph):
-    """Check if the number of qubits in the circuit matches the connectivity graph.
-
-    Args:
-        circuit (:class:`qibo.models.circuit.Circuit`): Circuit model to check.
-        connectivity (:class:`networkx.Graph`): Chip connectivity.
-    """
-    if circuit.nqubits != len(connectivity.nodes):
-        raise_error(
-            TranspilerPipelineError,
-            "Number of qubits in the circuit does not match the connectivity graph.",
-        )
-
-
 def assert_transpiling(
     original_circuit: Circuit,
     transpiled_circuit: Circuit,
@@ -130,41 +116,22 @@ def _transpose_qubits(state: np.ndarray, qubits_ordering: np.ndarray):
 
 
 def assert_placement(circuit: Circuit, connectivity: nx.Graph):
-    """Check if layout is in the correct form and matches the number of qubits of the circuit.
+    """Check if the layout of the circuit is consistent with the circuit and connectivity graph.
 
     Args:
         circuit (:class:`qibo.models.circuit.Circuit`): Circuit model to check.
-        layout (dict): qubit names.
         connectivity (:class:`networkx.Graph`, optional): Chip connectivity.
-            This argument is necessary if the layout is applied to a subset of
-            qubits of the original connectivity graph. Defaults to ``None``.
     """
-    layout = circuit.wire_names
-    assert_mapping_consistency(layout=layout, connectivity=connectivity)
-    if circuit.nqubits > len(layout):
+    if circuit.nqubits != len(circuit.wire_names) or circuit.nqubits != len(
+        connectivity.nodes
+    ):
         raise_error(
             PlacementError,
-            "Layout can't be used on circuit. The circuit requires more qubits.",
+            f"Number of qubits in the circuit ({circuit.nqubits}) "
+            + f"does not match the number of qubits in the layout ({len(circuit.wire_names)}) "
+            + f"or the connectivity graph ({len(connectivity.nodes)}).",
         )
-    if circuit.nqubits < len(layout):
-        raise_error(
-            PlacementError,
-            "Layout can't be used on circuit. "
-            + "Ancillary extra qubits need to be added to the circuit.",
-        )
-
-
-def assert_mapping_consistency(layout: list, connectivity: nx.Graph):
-    """Check if layout is in the correct form.
-
-    Args:
-        layout (dict): qubit names.
-        connectivity (:class:`networkx.Graph`, optional):  Chip connectivity.
-            This argument is necessary if the layout is applied to a subset of
-            qubits of the original connectivity graph.
-    """
-    nodes = list(connectivity.nodes)
-    if sorted(nodes) != sorted(layout):
+    if set(circuit.wire_names) != set(connectivity.nodes):
         raise_error(
             PlacementError,
             "Some physical qubits in the layout may be missing or duplicated.",
diff --git a/tests/test_transpiler_utils.py b/tests/test_transpiler_utils.py
index f804c4a8fd..02a1e08670 100644
--- a/tests/test_transpiler_utils.py
+++ b/tests/test_transpiler_utils.py
@@ -14,21 +14,10 @@
     assert_circuit_equivalence,
     assert_connectivity,
     assert_decomposition,
-    assert_mapping_consistency,
     assert_placement,
-    assert_qubit_match,
 )
 
 
-def test_assert_qubit_match(star_connectivity):
-    circuit = Circuit(3)
-    with pytest.raises(TranspilerPipelineError):
-        assert_qubit_match(circuit, star_connectivity())
-
-    circuit = Circuit(5)
-    assert_qubit_match(circuit, star_connectivity())
-
-
 def test_assert_circuit_equivalence_equal():
     circ1 = Circuit(2)
     circ2 = Circuit(2)
@@ -61,44 +50,19 @@ def test_assert_circuit_equivalence_false():
         assert_circuit_equivalence(circ1, circ2, final_map=final_map)
 
 
-@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
-def test_mapping_consistency(names, star_connectivity):
-    assert_mapping_consistency(names, star_connectivity(names))
-
-
-def test_mapping_consistency_error(star_connectivity):
-    with pytest.raises(PlacementError):
-        assert_mapping_consistency(["A", "B", "C", "D", "F"], star_connectivity())
-
-
-@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
-def test_mapping_consistency_restricted(names, star_connectivity):
-    connectivity = star_connectivity(names)
-    on_qubit = [names[0], names[2]]
-    restricted_connectivity = restrict_connectivity_qubits(connectivity, on_qubit)
-    assert_mapping_consistency(on_qubit, restricted_connectivity)
-
-
-@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
-def test_mapping_consistency_restricted_error(names, star_connectivity):
-    connectivity = star_connectivity(names)
-    on_qubit = [names[0], names[2]]
-    restricted_connectivity = restrict_connectivity_qubits(connectivity, on_qubit)
-    with pytest.raises(PlacementError):
-        assert_mapping_consistency([names[3], names[4]], restricted_connectivity)
-
-
 def test_assert_placement_true(star_connectivity):
     circuit = Circuit(5)
     assert_placement(circuit, connectivity=star_connectivity())
 
 
 @pytest.mark.parametrize(
-    "qubits, names", [(5, ["A", "B", "C", "D", "F"]), (3, ["A", "B", "C"])]
+    "qubits, names", [(1, ["A", "B", "C", "D", "E"]), (10, ["A", "B", "C", "D", "E"])]
 )
 def test_assert_placement_false(qubits, names, star_connectivity):
     connectivity = star_connectivity()
-    circuit = Circuit(qubits, wire_names=names)
+    circuit = Circuit(5)
+    circuit.nqubits = qubits
+    circuit._wire_names = names
     with pytest.raises(PlacementError):
         assert_placement(circuit, connectivity)
 
@@ -111,6 +75,25 @@ def test_assert_placement_error(qubits, star_connectivity):
         assert_placement(circuit, connectivity)
 
 
+@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
+def test_assert_placement_restricted(names, star_connectivity):
+    connectivity = star_connectivity(names)
+    on_qubit = [names[0], names[2]]
+    circuit = Circuit(2, wire_names=on_qubit)
+    restricted_connectivity = restrict_connectivity_qubits(connectivity, on_qubit)
+    assert_placement(circuit, restricted_connectivity)
+
+
+@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
+def test_assert_placement_restricted_error(names, star_connectivity):
+    connectivity = star_connectivity(names)
+    on_qubit = [names[0], names[2]]
+    circuit = Circuit(2, wire_names=[names[3], names[4]])
+    restricted_connectivity = restrict_connectivity_qubits(connectivity, on_qubit)
+    with pytest.raises(PlacementError):
+        assert_placement(circuit, restricted_connectivity)
+
+
 def test_assert_decomposition():
     circuit = Circuit(2)
     circuit.add(gates.CZ(0, 1))

From 0851eeb2fa846848cff4507c37930c3f24489c76 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Wed, 30 Oct 2024 11:32:48 +0400
Subject: [PATCH 27/34] fix: minor test files update

---
 tests/test_transpiler_placer.py | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/tests/test_transpiler_placer.py b/tests/test_transpiler_placer.py
index 1b05743621..4117c6bc49 100644
--- a/tests/test_transpiler_placer.py
+++ b/tests/test_transpiler_placer.py
@@ -18,7 +18,7 @@
 from qibo.transpiler.utils import assert_placement
 
 
-def star_circuit(names=["q0", "q1", "q2", "q3", "q4"]):
+def star_circuit(names=[0, 1, 2, 3, 4]):
     circuit = Circuit(5, wire_names=names)
     for i in range(1, 5):
         circuit.add(gates.CNOT(i, 0))
@@ -67,8 +67,9 @@ def test_trivial_restricted(star_connectivity):
     [["E", "D", "C", "B", "A"], {"E": 0, "D": 1, "C": 2, "B": 3, "A": 4}],
 )
 def test_custom(custom_layout, star_connectivity):
-    circuit = Circuit(5)
-    connectivity = star_connectivity(["A", "B", "C", "D", "E"])
+    names = ["A", "B", "C", "D", "E"]
+    circuit = Circuit(5, wire_names=names)
+    connectivity = star_connectivity(names)
     placer = Custom(connectivity=connectivity, initial_map=custom_layout)
     placer(circuit)
     assert circuit.wire_names == ["E", "D", "C", "B", "A"]
@@ -102,7 +103,7 @@ def test_custom_error_circuit(star_connectivity):
     custom_layout = [4, 3, 2, 1, 0]
     connectivity = star_connectivity(names=custom_layout)
     placer = Custom(connectivity=connectivity, initial_map=custom_layout)
-    with pytest.raises(TranspilerPipelineError):
+    with pytest.raises(PlacementError):
         placer(circuit)
 
 
@@ -154,7 +155,7 @@ def test_subgraph_error(star_connectivity):
 
 
 def test_subgraph_restricted(star_connectivity):
-    circuit = Circuit(4)
+    circuit = Circuit(4, wire_names=[0, 2, 3, 4])
     circuit.add(gates.CNOT(0, 3))
     circuit.add(gates.CNOT(0, 1))
     circuit.add(gates.CNOT(3, 2))
@@ -180,7 +181,7 @@ def test_random(reps, names, star_connectivity):
 
 def test_random_restricted(star_connectivity):
     names = [0, 1, 2, 3, 4]
-    circuit = Circuit(4, wire_names=names[:4])
+    circuit = Circuit(4, wire_names=[0, 2, 3, 4])
     circuit.add(gates.CNOT(1, 3))
     circuit.add(gates.CNOT(2, 1))
     circuit.add(gates.CNOT(3, 2))

From 824bb76ee3fd4c612cc0e9f078d38ebcb9cb56ee Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Thu, 21 Nov 2024 17:47:11 +0400
Subject: [PATCH 28/34] passes move connectivity check to __call__

---
 src/qibo/backends/__init__.py                |  6 ++--
 src/qibo/models/error_mitigation.py          |  2 +-
 src/qibo/tomography/gate_set_tomography.py   | 13 ++-----
 src/qibo/transpiler/optimizer.py             | 10 +++++-
 src/qibo/transpiler/placer.py                | 36 ++++++++++++--------
 src/qibo/transpiler/router.py                | 26 ++++++++------
 src/qibo/transpiler/utils.py                 |  6 ++++
 tests/test_backends_global.py                |  6 ++--
 tests/test_tomography_gate_set_tomography.py |  6 ++--
 tests/test_transpiler_optimizer.py           |  9 +++++
 tests/test_transpiler_pipeline.py            | 24 ++++++-------
 tests/test_transpiler_placer.py              |  7 ++--
 tests/test_transpiler_router.py              |  3 +-
 tests/test_transpiler_utils.py               |  4 +++
 14 files changed, 94 insertions(+), 64 deletions(-)

diff --git a/src/qibo/backends/__init__.py b/src/qibo/backends/__init__.py
index f0777b24e1..c4c52c58af 100644
--- a/src/qibo/backends/__init__.py
+++ b/src/qibo/backends/__init__.py
@@ -151,9 +151,9 @@ def _default_transpiler(cls):
             return Passes(
                 connectivity=connectivity,
                 passes=[
-                    Preprocessing(connectivity),
-                    Trivial(connectivity),
-                    Sabre(connectivity),
+                    Preprocessing(),
+                    Trivial(),
+                    Sabre(),
                     Unroller(NativeGates[natives]),
                 ],
             )
diff --git a/src/qibo/models/error_mitigation.py b/src/qibo/models/error_mitigation.py
index 9dce0017ff..2a31ca2571 100644
--- a/src/qibo/models/error_mitigation.py
+++ b/src/qibo/models/error_mitigation.py
@@ -1183,7 +1183,7 @@ def _execute_circuit(circuit, qubit_map, noise_model=None, nshots=10000, backend
         connectivity = nx.Graph(connectivity_edges)
         transpiler = Passes(
             connectivity=connectivity,
-            passes=[Custom(initial_map=qubit_map, connectivity=connectivity)],
+            passes=[Custom(initial_map=qubit_map)],
         )
         circuit, _ = transpiler(circuit)
     elif noise_model is not None:
diff --git a/src/qibo/tomography/gate_set_tomography.py b/src/qibo/tomography/gate_set_tomography.py
index d3b4286f32..5a8331f527 100644
--- a/src/qibo/tomography/gate_set_tomography.py
+++ b/src/qibo/tomography/gate_set_tomography.py
@@ -1,14 +1,13 @@
 from functools import cache
 from inspect import signature
 from itertools import product
-from random import Random
 from typing import List, Union
 
 import numpy as np
 from sympy import S
 
 from qibo import Circuit, gates, symbols
-from qibo.backends import _check_backend
+from qibo.backends import _check_backend, get_transpiler
 from qibo.config import raise_error
 from qibo.hamiltonians import SymbolicHamiltonian
 from qibo.transpiler.optimizer import Preprocessing
@@ -261,15 +260,7 @@ def GST(
     backend = _check_backend(backend)
 
     if backend.name == "qibolab" and transpiler is None:  # pragma: no cover
-        transpiler = Passes(
-            connectivity=backend.platform.topology,
-            passes=[
-                Preprocessing(backend.platform.topology),
-                Random(backend.platform.topology),
-                Sabre(backend.platform.topology),
-                Unroller(NativeGates.default()),
-            ],
-        )
+        transpiler = get_transpiler()
 
     matrices = []
     empty_matrices = []
diff --git a/src/qibo/transpiler/optimizer.py b/src/qibo/transpiler/optimizer.py
index a30f117757..3b93e5843a 100644
--- a/src/qibo/transpiler/optimizer.py
+++ b/src/qibo/transpiler/optimizer.py
@@ -13,10 +13,18 @@ class Preprocessing(Optimizer):
         connectivity (:class:`networkx.Graph`): hardware chip connectivity.
     """
 
-    def __init__(self, connectivity: nx.Graph):
+    def __init__(self, connectivity: nx.Graph = None):
         self.connectivity = connectivity
 
     def __call__(self, circuit: Circuit) -> Circuit:
+        if self.connectivity is None or not all(
+            qubit in self.connectivity.nodes for qubit in circuit.wire_names
+        ):
+            raise_error(
+                ValueError,
+                "The circuit qubits are not in the connectivity graph.",
+            )
+
         physical_qubits = self.connectivity.number_of_nodes()
         logical_qubits = circuit.nqubits
         if logical_qubits > physical_qubits:
diff --git a/src/qibo/transpiler/placer.py b/src/qibo/transpiler/placer.py
index 4601fadf7d..e162cf80aa 100644
--- a/src/qibo/transpiler/placer.py
+++ b/src/qibo/transpiler/placer.py
@@ -48,16 +48,9 @@ class StarConnectivityPlacer(Placer):
         connectivity (:class:`networkx.Graph`): star connectivity graph.
     """
 
-    def __init__(self, connectivity: nx.Graph):
+    def __init__(self, connectivity: nx.Graph = None):
         self.connectivity = connectivity
-        for node in self.connectivity.nodes:
-            if self.connectivity.degree(node) == 4:
-                self.middle_qubit = node
-            elif self.connectivity.degree(node) != 1:
-                raise_error(
-                    ValueError,
-                    "This connectivity graph is not a star graph.",
-                )
+        self.middle_qubit = None
 
     def __call__(self, circuit: Circuit):
         """Apply the transpiler transformation on a given circuit.
@@ -67,6 +60,8 @@ def __call__(self, circuit: Circuit):
                 Only single qubit gates and two qubits gates are supported by the router.
         """
         assert_placement(circuit, self.connectivity)
+        self._check_star_connectivity()
+
         middle_qubit_idx = circuit.wire_names.index(self.middle_qubit)
         wire_names = circuit.wire_names.copy()
 
@@ -96,6 +91,17 @@ def __call__(self, circuit: Circuit):
 
         circuit.wire_names = wire_names
 
+    def _check_star_connectivity(self):
+        """Check if the connectivity graph is a star graph."""
+        for node in self.connectivity.nodes:
+            if self.connectivity.degree(node) == 4:
+                self.middle_qubit = node
+            elif self.connectivity.degree(node) != 1:
+                raise_error(
+                    ValueError,
+                    "This connectivity graph is not a star graph.",
+                )
+
 
 class Trivial(Placer):
     """Place qubits according to the order of the qubit names that the user provides."""
@@ -103,7 +109,7 @@ class Trivial(Placer):
     def __init__(self, connectivity: nx.Graph = None):
         self.connectivity = connectivity
 
-    def __call__(self, circuit: Circuit = None):
+    def __call__(self, circuit: Circuit):
         """Find the trivial placement for the circuit.
 
         Args:
@@ -122,7 +128,7 @@ class Custom(Placer):
             - If **list**, it should contain physical qubit names, arranged in the order of the logical qubits.
     """
 
-    def __init__(self, initial_map: Union[list, dict], connectivity: nx.Graph):
+    def __init__(self, initial_map: Union[list, dict], connectivity: nx.Graph = None):
         self.initial_map = initial_map
         self.connectivity = connectivity
 
@@ -141,7 +147,7 @@ def __call__(self, circuit: Circuit):
         else:
             raise_error(TypeError, "Use dict or list to define mapping.")
 
-        assert_placement(circuit, connectivity=self.connectivity)
+        assert_placement(circuit, self.connectivity)
 
 
 class Subgraph(Placer):
@@ -155,7 +161,7 @@ class Subgraph(Placer):
         connectivity (:class:`networkx.Graph`): chip connectivity.
     """
 
-    def __init__(self, connectivity: nx.Graph):
+    def __init__(self, connectivity: nx.Graph = None):
         self.connectivity = connectivity
 
     def __call__(self, circuit: Circuit):
@@ -213,7 +219,7 @@ class Random(Placer):
             initializes a generator with a random seed. Defaults to ``None``.
     """
 
-    def __init__(self, connectivity: nx.Graph, samples: int = 100, seed=None):
+    def __init__(self, connectivity: nx.Graph = None, samples: int = 100, seed=None):
         self.connectivity = connectivity
         self.samples = samples
         self.seed = seed
@@ -296,8 +302,8 @@ class ReverseTraversal(Placer):
 
     def __init__(
         self,
-        connectivity: nx.Graph,
         routing_algorithm: Router,
+        connectivity: nx.Graph = None,
         depth: Optional[int] = None,
     ):
         self.connectivity = connectivity
diff --git a/src/qibo/transpiler/router.py b/src/qibo/transpiler/router.py
index d4a782740b..027b17119b 100644
--- a/src/qibo/transpiler/router.py
+++ b/src/qibo/transpiler/router.py
@@ -33,14 +33,7 @@ class StarConnectivityRouter(Router):
 
     def __init__(self, connectivity: nx.Graph):
         self.connectivity = connectivity
-        for node in self.connectivity.nodes:
-            if self.connectivity.degree(node) == 4:
-                self.middle_qubit = node
-            elif self.connectivity.degree(node) != 1:
-                raise_error(
-                    ValueError,
-                    "This connectivity graph is not a star graph.",
-                )
+        self.middle_qubit = None
 
     def __call__(self, circuit: Circuit):
         """Apply the transpiler transformation on a given circuit.
@@ -49,7 +42,9 @@ def __call__(self, circuit: Circuit):
             circuit (:class:`qibo.models.circuit.Circuit`): The original Qibo circuit to transform.
                 Only single qubit gates and two qubits gates are supported by the router.
         """
+        self._check_star_connectivity()
         assert_placement(circuit, self.connectivity)
+
         middle_qubit_idx = circuit.wire_names.index(self.middle_qubit)
         nqubits = circuit.nqubits
         new = Circuit(nqubits=nqubits, wire_names=circuit.wire_names)
@@ -94,6 +89,17 @@ def __call__(self, circuit: Circuit):
                 new.add(gate.__class__(*routed_qubits, **gate.init_kwargs))
         return new, {circuit.wire_names[i]: l2p[i] for i in range(nqubits)}
 
+    def _check_star_connectivity(self):
+        """Check if the connectivity graph is a star graph."""
+        for node in self.connectivity.nodes:
+            if self.connectivity.degree(node) == 4:
+                self.middle_qubit = node
+            elif self.connectivity.degree(node) != 1:
+                raise_error(
+                    ValueError,
+                    "This connectivity graph is not a star graph.",
+                )
+
 
 def _find_connected_qubit(qubits, queue, error, mapping):
     """Helper method for :meth:`qibo.transpiler.router.StarConnectivityRouter`
@@ -308,7 +314,7 @@ class ShortestPaths(Router):
             If ``None``, defaults to :math:`42`. Defaults to ``None``.
     """
 
-    def __init__(self, connectivity: nx.Graph, seed: Optional[int] = None):
+    def __init__(self, connectivity: nx.Graph = None, seed: Optional[int] = None):
         self.connectivity = connectivity
         self._front_layer = None
         self.circuit_map = None
@@ -595,7 +601,7 @@ class Sabre(Router):
 
     def __init__(
         self,
-        connectivity: nx.Graph,
+        connectivity: nx.Graph = None,
         lookahead: int = 2,
         decay_lookahead: float = 0.6,
         delta: float = 0.001,
diff --git a/src/qibo/transpiler/utils.py b/src/qibo/transpiler/utils.py
index 89bd367d79..d988ce6add 100644
--- a/src/qibo/transpiler/utils.py
+++ b/src/qibo/transpiler/utils.py
@@ -122,6 +122,12 @@ def assert_placement(circuit: Circuit, connectivity: nx.Graph):
         circuit (:class:`qibo.models.circuit.Circuit`): Circuit model to check.
         connectivity (:class:`networkx.Graph`, optional): Chip connectivity.
     """
+    if connectivity is None:
+        raise_error(
+            ValueError,
+            "Connectivity graph is missing.",
+        )
+
     if circuit.nqubits != len(circuit.wire_names) or circuit.nqubits != len(
         connectivity.nodes
     ):
diff --git a/tests/test_backends_global.py b/tests/test_backends_global.py
index 8e4e07610d..dc0b6dfeaa 100644
--- a/tests/test_backends_global.py
+++ b/tests/test_backends_global.py
@@ -128,9 +128,9 @@ def test_set_get_transpiler():
     transpiler = Passes(
         connectivity=connectivity,
         passes=[
-            Preprocessing(connectivity),
-            Random(connectivity, seed=0),
-            Sabre(connectivity),
+            Preprocessing(),
+            Random(seed=0),
+            Sabre(),
             Unroller(NativeGates.default()),
         ],
     )
diff --git a/tests/test_tomography_gate_set_tomography.py b/tests/test_tomography_gate_set_tomography.py
index c2a40d944f..be0c4d4fc6 100644
--- a/tests/test_tomography_gate_set_tomography.py
+++ b/tests/test_tomography_gate_set_tomography.py
@@ -280,9 +280,9 @@ def test_GST_with_transpiler(backend, star_connectivity):
     transpiler = Passes(
         connectivity=connectivity,
         passes=[
-            Preprocessing(connectivity),
-            Random(connectivity),
-            Sabre(connectivity),
+            Preprocessing(),
+            Random(),
+            Sabre(),
             Unroller(NativeGates.default(), backend=backend),
         ],
     )
diff --git a/tests/test_transpiler_optimizer.py b/tests/test_transpiler_optimizer.py
index cd55115a9b..eefcd2c1fb 100644
--- a/tests/test_transpiler_optimizer.py
+++ b/tests/test_transpiler_optimizer.py
@@ -8,10 +8,19 @@
 
 def test_preprocessing_error(star_connectivity):
     circ = Circuit(7)
+
+    preprocesser = Preprocessing()
+    with pytest.raises(ValueError):
+        new_circuit = preprocesser(circuit=circ)
+
     preprocesser = Preprocessing(connectivity=star_connectivity())
     with pytest.raises(ValueError):
         new_circuit = preprocesser(circuit=circ)
 
+    circ = Circuit(5, wire_names=[0, 1, 2, "q3", "q4"])
+    with pytest.raises(ValueError):
+        new_circuit = preprocesser(circuit=circ)
+
 
 def test_preprocessing_same(star_connectivity):
     circ = Circuit(5)
diff --git a/tests/test_transpiler_pipeline.py b/tests/test_transpiler_pipeline.py
index 30f0cddfbe..61f843f7e9 100644
--- a/tests/test_transpiler_pipeline.py
+++ b/tests/test_transpiler_pipeline.py
@@ -140,17 +140,16 @@ def test_custom_passes(placer, router, ngates, nqubits, star_connectivity):
     connectivity = star_connectivity()
     circ = generate_random_circuit(nqubits=nqubits, ngates=ngates)
     custom_passes = []
-    custom_passes.append(Preprocessing(connectivity=connectivity))
+    custom_passes.append(Preprocessing())
     if placer == ReverseTraversal:
         custom_passes.append(
             placer(
-                connectivity=connectivity,
-                routing_algorithm=router(connectivity=connectivity),
+                routing_algorithm=router(),
             )
         )
     else:
-        custom_passes.append(placer(connectivity=connectivity))
-    custom_passes.append(router(connectivity=connectivity))
+        custom_passes.append(placer())
+    custom_passes.append(router())
     custom_passes.append(Unroller(native_gates=NativeGates.default()))
     custom_pipeline = Passes(
         custom_passes,
@@ -177,17 +176,16 @@ def test_custom_passes_restrict(
     connectivity = star_connectivity()
     circ = generate_random_circuit(nqubits=3, ngates=ngates, names=restrict_names)
     custom_passes = []
-    custom_passes.append(Preprocessing(connectivity=connectivity))
+    custom_passes.append(Preprocessing())
     if placer == ReverseTraversal:
         custom_passes.append(
             placer(
-                connectivity=connectivity,
-                routing_algorithm=routing(connectivity=connectivity),
+                routing_algorithm=routing(),
             )
         )
     else:
-        custom_passes.append(placer(connectivity=connectivity))
-    custom_passes.append(routing(connectivity=connectivity))
+        custom_passes.append(placer())
+    custom_passes.append(routing())
     custom_passes.append(Unroller(native_gates=NativeGates.default()))
     custom_pipeline = Passes(
         custom_passes,
@@ -220,9 +218,9 @@ def test_int_qubit_names(star_connectivity):
     transpiler = Passes(
         connectivity=connectivity,
         passes=[
-            Preprocessing(connectivity),
-            Random(connectivity, seed=0),
-            Sabre(connectivity),
+            Preprocessing(),
+            Random(seed=0),
+            Sabre(),
             Unroller(NativeGates.default()),
         ],
     )
diff --git a/tests/test_transpiler_placer.py b/tests/test_transpiler_placer.py
index 4117c6bc49..1e8193ec2a 100644
--- a/tests/test_transpiler_placer.py
+++ b/tests/test_transpiler_placer.py
@@ -201,7 +201,7 @@ def test_reverse_traversal(ngates, names, star_connectivity):
     circuit = star_circuit(names=names)
     connectivity = star_connectivity(names=names)
     routing = ShortestPaths(connectivity=connectivity)
-    placer = ReverseTraversal(connectivity, routing, depth=ngates)
+    placer = ReverseTraversal(routing, connectivity, depth=ngates)
     placer(circuit)
     assert_placement(circuit, connectivity)
 
@@ -209,7 +209,7 @@ def test_reverse_traversal(ngates, names, star_connectivity):
 def test_reverse_traversal_no_gates(star_connectivity):
     connectivity = star_connectivity()
     routing = ShortestPaths(connectivity=connectivity)
-    placer = ReverseTraversal(connectivity, routing, depth=10)
+    placer = ReverseTraversal(routing, connectivity, depth=10)
     circuit = Circuit(5)
     with pytest.raises(ValueError):
         placer(circuit)
@@ -261,4 +261,5 @@ def test_star_connectivity_placer_error(first, star_connectivity):
     chip = nx.Graph()
     chip.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 4)])
     with pytest.raises(ValueError):
-        StarConnectivityPlacer(chip)
+        placer = StarConnectivityPlacer(chip)
+        placer(circ)
diff --git a/tests/test_transpiler_router.py b/tests/test_transpiler_router.py
index 2a09e23725..5883d22abe 100644
--- a/tests/test_transpiler_router.py
+++ b/tests/test_transpiler_router.py
@@ -546,7 +546,8 @@ def test_star_error_multi_qubit(star_connectivity):
     chip = nx.Graph()
     chip.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 4)])
     with pytest.raises(ValueError):
-        StarConnectivityRouter(chip)
+        router = StarConnectivityRouter(chip)
+        _, _ = router(circuit=circuit)
 
 
 # @pytest.mark.parametrize("nqubits", [1, 3, 5])
diff --git a/tests/test_transpiler_utils.py b/tests/test_transpiler_utils.py
index 02a1e08670..7476e1d80f 100644
--- a/tests/test_transpiler_utils.py
+++ b/tests/test_transpiler_utils.py
@@ -66,6 +66,10 @@ def test_assert_placement_false(qubits, names, star_connectivity):
     with pytest.raises(PlacementError):
         assert_placement(circuit, connectivity)
 
+    connectivity = None
+    with pytest.raises(ValueError):
+        assert_placement(circuit, connectivity)
+
 
 @pytest.mark.parametrize("qubits", [10, 1])
 def test_assert_placement_error(qubits, star_connectivity):

From 214a4ea910dce6ba99132744c4122378b903ed87 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Fri, 22 Nov 2024 14:02:23 +0400
Subject: [PATCH 29/34] fix: remove Trivial and Custom

---
 doc/source/code-examples/advancedexamples.rst |  2 -
 src/qibo/backends/__init__.py                 |  2 -
 src/qibo/models/error_mitigation.py           |  9 +--
 src/qibo/transpiler/__init__.py               |  2 -
 src/qibo/transpiler/placer.py                 | 49 +-----------
 tests/test_transpiler_pipeline.py             |  6 +-
 tests/test_transpiler_placer.py               | 76 -------------------
 tests/test_transpiler_router.py               | 54 ++++---------
 8 files changed, 19 insertions(+), 181 deletions(-)

diff --git a/doc/source/code-examples/advancedexamples.rst b/doc/source/code-examples/advancedexamples.rst
index 39737ec13c..9904a4ab1e 100644
--- a/doc/source/code-examples/advancedexamples.rst
+++ b/doc/source/code-examples/advancedexamples.rst
@@ -2139,8 +2139,6 @@ Qibo implements a built-in transpiler with customizable options for each step. T
 be used at each transpiler step are reported below with a short description.
 
 The initial placement can be found with one of the following procedures:
-- Trivial: logical-physical qubit mapping is an identity.
-- Custom: custom logical-physical qubit mapping.
 - Random greedy: the best mapping is found within a set of random layouts based on a greedy policy.
 - Subgraph isomorphism: the initial mapping is the one that guarantees the execution of most gates at
 the beginning of the circuit without introducing any SWAP.
diff --git a/src/qibo/backends/__init__.py b/src/qibo/backends/__init__.py
index c4c52c58af..5d2d5deb08 100644
--- a/src/qibo/backends/__init__.py
+++ b/src/qibo/backends/__init__.py
@@ -135,7 +135,6 @@ def set_transpiler(cls, transpiler):
     def _default_transpiler(cls):
         from qibo.transpiler.optimizer import Preprocessing
         from qibo.transpiler.pipeline import Passes
-        from qibo.transpiler.placer import Trivial
         from qibo.transpiler.router import Sabre
         from qibo.transpiler.unroller import NativeGates, Unroller
 
@@ -152,7 +151,6 @@ def _default_transpiler(cls):
                 connectivity=connectivity,
                 passes=[
                     Preprocessing(),
-                    Trivial(),
                     Sabre(),
                     Unroller(NativeGates[natives]),
                 ],
diff --git a/src/qibo/models/error_mitigation.py b/src/qibo/models/error_mitigation.py
index 2a31ca2571..ac876e84ea 100644
--- a/src/qibo/models/error_mitigation.py
+++ b/src/qibo/models/error_mitigation.py
@@ -1174,18 +1174,11 @@ def _execute_circuit(circuit, qubit_map, noise_model=None, nshots=10000, backend
         qibo.states.CircuitResult: The result of the circuit execution.
     """
     from qibo.transpiler.pipeline import Passes
-    from qibo.transpiler.placer import Custom
 
     if backend is None:  # pragma: no cover
         backend = get_backend()
     elif backend.name == "qibolab":  # pragma: no cover
-        connectivity_edges = backend.connectivity
-        connectivity = nx.Graph(connectivity_edges)
-        transpiler = Passes(
-            connectivity=connectivity,
-            passes=[Custom(initial_map=qubit_map)],
-        )
-        circuit, _ = transpiler(circuit)
+        circuit.wire_names = qubit_map
     elif noise_model is not None:
         circuit = noise_model.apply(circuit)
 
diff --git a/src/qibo/transpiler/__init__.py b/src/qibo/transpiler/__init__.py
index bfe576776c..40675f0be1 100644
--- a/src/qibo/transpiler/__init__.py
+++ b/src/qibo/transpiler/__init__.py
@@ -1,12 +1,10 @@
 from qibo.transpiler.optimizer import Preprocessing, Rearrange
 from qibo.transpiler.pipeline import Passes
 from qibo.transpiler.placer import (
-    Custom,
     Random,
     ReverseTraversal,
     StarConnectivityPlacer,
     Subgraph,
-    Trivial,
 )
 from qibo.transpiler.router import Sabre, ShortestPaths, StarConnectivityRouter
 from qibo.transpiler.unroller import NativeGates
diff --git a/src/qibo/transpiler/placer.py b/src/qibo/transpiler/placer.py
index e162cf80aa..4539272574 100644
--- a/src/qibo/transpiler/placer.py
+++ b/src/qibo/transpiler/placer.py
@@ -1,4 +1,4 @@
-from typing import Optional, Union
+from typing import Optional
 
 import networkx as nx
 
@@ -103,53 +103,6 @@ def _check_star_connectivity(self):
                 )
 
 
-class Trivial(Placer):
-    """Place qubits according to the order of the qubit names that the user provides."""
-
-    def __init__(self, connectivity: nx.Graph = None):
-        self.connectivity = connectivity
-
-    def __call__(self, circuit: Circuit):
-        """Find the trivial placement for the circuit.
-
-        Args:
-            circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
-        """
-        assert_placement(circuit, self.connectivity)
-        return
-
-
-class Custom(Placer):
-    """Define a custom initial qubit mapping.
-
-    Args:
-        map (list or dict): A mapping between physical and logical qubits.
-            - If **dict**, the keys should be physical qubit names, and the values should be the corresponding logical qubit numbers.
-            - If **list**, it should contain physical qubit names, arranged in the order of the logical qubits.
-    """
-
-    def __init__(self, initial_map: Union[list, dict], connectivity: nx.Graph = None):
-        self.initial_map = initial_map
-        self.connectivity = connectivity
-
-    def __call__(self, circuit: Circuit):
-        """Apply the custom placement to the given circuit.
-
-        Args:
-            circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
-        """
-        assert_placement(circuit, self.connectivity)
-
-        if isinstance(self.initial_map, dict):
-            circuit.wire_names = sorted(self.initial_map, key=self.initial_map.get)
-        elif isinstance(self.initial_map, list):
-            circuit.wire_names = self.initial_map
-        else:
-            raise_error(TypeError, "Use dict or list to define mapping.")
-
-        assert_placement(circuit, self.connectivity)
-
-
 class Subgraph(Placer):
     """
     Subgraph isomorphism qubit placer.
diff --git a/tests/test_transpiler_pipeline.py b/tests/test_transpiler_pipeline.py
index 61f843f7e9..b43129a0eb 100644
--- a/tests/test_transpiler_pipeline.py
+++ b/tests/test_transpiler_pipeline.py
@@ -7,7 +7,7 @@
 from qibo.transpiler._exceptions import ConnectivityError, TranspilerPipelineError
 from qibo.transpiler.optimizer import Preprocessing
 from qibo.transpiler.pipeline import Passes, restrict_connectivity_qubits
-from qibo.transpiler.placer import Random, ReverseTraversal, Trivial
+from qibo.transpiler.placer import Random, ReverseTraversal
 from qibo.transpiler.router import Sabre, ShortestPaths
 from qibo.transpiler.unroller import NativeGates, Unroller
 from qibo.transpiler.utils import assert_circuit_equivalence, assert_transpiling
@@ -134,7 +134,7 @@ def test_is_satisfied_false_connectivity(star_connectivity):
 
 @pytest.mark.parametrize("nqubits", [2, 3, 5])
 @pytest.mark.parametrize("ngates", [5, 20])
-@pytest.mark.parametrize("placer", [Random, Trivial, ReverseTraversal])
+@pytest.mark.parametrize("placer", [Random, ReverseTraversal])
 @pytest.mark.parametrize("router", [ShortestPaths, Sabre])
 def test_custom_passes(placer, router, ngates, nqubits, star_connectivity):
     connectivity = star_connectivity()
@@ -167,7 +167,7 @@ def test_custom_passes(placer, router, ngates, nqubits, star_connectivity):
 
 
 @pytest.mark.parametrize("ngates", [5, 20])
-@pytest.mark.parametrize("placer", [Random, Trivial, ReverseTraversal])
+@pytest.mark.parametrize("placer", [Random, ReverseTraversal])
 @pytest.mark.parametrize("routing", [ShortestPaths, Sabre])
 @pytest.mark.parametrize("restrict_names", [[1, 2, 3], [0, 2, 4], [4, 2, 3]])
 def test_custom_passes_restrict(
diff --git a/tests/test_transpiler_placer.py b/tests/test_transpiler_placer.py
index 1e8193ec2a..f9d41ecc55 100644
--- a/tests/test_transpiler_placer.py
+++ b/tests/test_transpiler_placer.py
@@ -6,12 +6,10 @@
 from qibo.transpiler._exceptions import PlacementError, TranspilerPipelineError
 from qibo.transpiler.pipeline import restrict_connectivity_qubits
 from qibo.transpiler.placer import (
-    Custom,
     Random,
     ReverseTraversal,
     StarConnectivityPlacer,
     Subgraph,
-    Trivial,
     _find_gates_qubits_pairs,
 )
 from qibo.transpiler.router import ShortestPaths
@@ -41,80 +39,6 @@ def test_gates_qubits_pairs_error():
         gates_qubits_pairs = _find_gates_qubits_pairs(circuit)
 
 
-def test_trivial(star_connectivity):
-    names = ["q4", "q3", "q2", "q1", "q0"]
-    circuit = Circuit(5, wire_names=names)
-    connectivity = star_connectivity(names)
-    placer = Trivial(connectivity=connectivity)
-    placer(circuit)
-    assert circuit.wire_names == names
-    assert_placement(circuit, connectivity)
-
-
-def test_trivial_restricted(star_connectivity):
-    names = ["q0", "q2"]
-    circuit = Circuit(2, wire_names=names)
-    connectivity = star_connectivity(["q0", "q1", "q2", "q3", "q4"])
-    restricted_connectivity = restrict_connectivity_qubits(connectivity, names)
-    placer = Trivial(connectivity=restricted_connectivity)
-    placer(circuit)
-    assert circuit.wire_names == names
-    assert_placement(circuit, restricted_connectivity)
-
-
-@pytest.mark.parametrize(
-    "custom_layout",
-    [["E", "D", "C", "B", "A"], {"E": 0, "D": 1, "C": 2, "B": 3, "A": 4}],
-)
-def test_custom(custom_layout, star_connectivity):
-    names = ["A", "B", "C", "D", "E"]
-    circuit = Circuit(5, wire_names=names)
-    connectivity = star_connectivity(names)
-    placer = Custom(connectivity=connectivity, initial_map=custom_layout)
-    placer(circuit)
-    assert circuit.wire_names == ["E", "D", "C", "B", "A"]
-
-
-@pytest.mark.parametrize(
-    "custom_layout", [[4, 3, 2, 1, 0], {4: 0, 3: 1, 2: 2, 1: 3, 0: 4}]
-)
-def test_custom_int(custom_layout, star_connectivity):
-    names = [0, 1, 2, 3, 4]
-    circuit = Circuit(5, wire_names=names)
-    connectivity = star_connectivity(names)
-    placer = Custom(connectivity=connectivity, initial_map=custom_layout)
-    placer(circuit)
-    assert circuit.wire_names == [4, 3, 2, 1, 0]
-
-
-@pytest.mark.parametrize("custom_layout", [["D", "C"], {"C": 1, "D": 0}])
-def test_custom_restricted(custom_layout, star_connectivity):
-    circuit = Circuit(2, wire_names=["C", "D"])
-    connectivity = star_connectivity(["A", "B", "C", "D", "E"])
-    restricted_connectivity = restrict_connectivity_qubits(connectivity, ["C", "D"])
-    placer = Custom(connectivity=restricted_connectivity, initial_map=custom_layout)
-    placer(circuit)
-    assert circuit.wire_names == ["D", "C"]
-    assert_placement(circuit, restricted_connectivity)
-
-
-def test_custom_error_circuit(star_connectivity):
-    circuit = Circuit(3)
-    custom_layout = [4, 3, 2, 1, 0]
-    connectivity = star_connectivity(names=custom_layout)
-    placer = Custom(connectivity=connectivity, initial_map=custom_layout)
-    with pytest.raises(PlacementError):
-        placer(circuit)
-
-
-def test_custom_error_type(star_connectivity):
-    circuit = Circuit(5)
-    connectivity = star_connectivity()
-    placer = Custom(connectivity=connectivity, initial_map=1)
-    with pytest.raises(TypeError):
-        placer(circuit)
-
-
 def test_subgraph_perfect(star_connectivity):
     connectivity = star_connectivity()
     placer = Subgraph(connectivity=connectivity)
diff --git a/tests/test_transpiler_router.py b/tests/test_transpiler_router.py
index 5883d22abe..79ec82bbc9 100644
--- a/tests/test_transpiler_router.py
+++ b/tests/test_transpiler_router.py
@@ -10,13 +10,7 @@
 from qibo.quantum_info.random_ensembles import random_unitary
 from qibo.transpiler._exceptions import ConnectivityError
 from qibo.transpiler.pipeline import restrict_connectivity_qubits
-from qibo.transpiler.placer import (
-    Custom,
-    Random,
-    StarConnectivityPlacer,
-    Subgraph,
-    Trivial,
-)
+from qibo.transpiler.placer import Random, StarConnectivityPlacer, Subgraph
 from qibo.transpiler.router import (
     CircuitMap,
     Sabre,
@@ -114,10 +108,9 @@ def test_bell_state_3q():
 
 
 @pytest.mark.parametrize("ngates", [5, 25])
-@pytest.mark.parametrize("placer", [Trivial, Random])
-def test_random_circuits_5q(ngates, placer, star_connectivity):
+def test_random_circuits_5q(ngates, star_connectivity):
     connectivity = star_connectivity()
-    placer = placer(connectivity)
+    placer = Random(connectivity)
     transpiler = ShortestPaths(connectivity)
 
     circuit = generate_random_circuit(nqubits=5, ngates=ngates)
@@ -137,10 +130,9 @@ def test_random_circuits_5q(ngates, placer, star_connectivity):
 
 
 @pytest.mark.parametrize("ngates", [5, 25])
-@pytest.mark.parametrize("placer", [Trivial, Random])
-def test_random_circuits_5q_grid(ngates, placer, grid_connectivity):
+def test_random_circuits_5q_grid(ngates, grid_connectivity):
     connectivity = grid_connectivity()
-    placer = placer(connectivity)
+    placer = Random(connectivity)
     transpiler = ShortestPaths(connectivity)
 
     circuit = generate_random_circuit(nqubits=5, ngates=ngates)
@@ -204,10 +196,8 @@ def test_star_circuit(star_connectivity):
 def test_star_circuit_custom_map(star_connectivity):
     connectivity = star_connectivity()
     circuit = star_circuit()
-    placer = Custom(initial_map=[1, 0, 2, 3, 4], connectivity=connectivity)
+    circuit.wire_names = [1, 0, 2, 3, 4]
     transpiler = ShortestPaths(connectivity=connectivity)
-
-    placer(circuit)
     transpiled_circuit, final_qubit_map = transpiler(circuit)
 
     assert transpiler.added_swaps == 1
@@ -225,10 +215,8 @@ def test_routing_with_measurements(star_connectivity):
     circuit = Circuit(5)
     circuit.add(gates.CNOT(0, 1))
     circuit.add(gates.M(0, 2, 3))
-    placer = Trivial(connectivity)
-    transpiler = ShortestPaths(connectivity)
 
-    placer(circuit=circuit)
+    transpiler = ShortestPaths(connectivity)
     transpiled_circuit, final_qubit_map = transpiler(circuit)
 
     assert transpiled_circuit.ngates == 3
@@ -243,7 +231,7 @@ def test_routing_with_measurements(star_connectivity):
 
 def test_sabre_looping():
     # Setup where the looping occurs
-    # Line connectivity, gates with gate_array, Trivial placer
+    # Line connectivity, gates with gate_array
 
     connectivity = line_connectivity(10, None)
     gate_array = [(7, 2), (6, 0), (5, 6), (4, 8), (3, 5), (9, 1)]
@@ -251,13 +239,11 @@ def test_sabre_looping():
     for qubits in gate_array:
         loop_circ.add(gates.CZ(*qubits))
 
-    placer = Trivial(connectivity)
     router_no_threshold = Sabre(
         connectivity=connectivity, swap_threshold=np.inf
     )  # Without reset
     router_threshold = Sabre(connectivity=connectivity)  # With reset
 
-    placer(loop_circ)
     routed_no_threshold, final_mapping_no_threshold = router_no_threshold(loop_circ)
     routed_threshold, final_mapping_threshold = router_threshold(loop_circ)
 
@@ -286,10 +272,8 @@ def test_sabre_shortest_path_routing():
 
     connectivity = line_connectivity(10, None)
 
-    placer = Trivial(connectivity)
     router = Sabre(connectivity)
 
-    placer(loop_circ)
     router._preprocessing(circuit=loop_circ)
     router._shortest_path_routing()  # q2 should be moved adjacent to q8
 
@@ -388,10 +372,8 @@ def test_sabre_matched(names, star_connectivity):
     connectivity = star_connectivity(names=names)
     circuit = matched_circuit(names)
     original_circuit = circuit.copy()
-    placer = Trivial(connectivity=connectivity)
-    router = Sabre(connectivity=connectivity)
 
-    placer(circuit)
+    router = Sabre(connectivity=connectivity)
     routed_circuit, final_map = router(circuit)
 
     assert router.added_swaps == 0
@@ -409,10 +391,8 @@ def test_sabre_simple(seed, star_connectivity):
     circ = Circuit(5)
     circ.add(gates.CZ(0, 1))
     original_circuit = circ.copy()
-    placer = Trivial(connectivity=connectivity)
-    router = Sabre(connectivity=connectivity, seed=seed)
 
-    placer(circ)
+    router = Sabre(connectivity=connectivity, seed=seed)
     routed_circuit, final_map = router(circ)
 
     assert router.added_swaps == 1
@@ -431,14 +411,13 @@ def test_sabre_simple(seed, star_connectivity):
 @pytest.mark.parametrize("n_gates", [10, 40])
 @pytest.mark.parametrize("look", [0, 5])
 @pytest.mark.parametrize("decay", [0.5, 1.0])
-@pytest.mark.parametrize("placer_param", [Trivial, Random])
-def test_sabre_random_circuits(n_gates, look, decay, placer_param, star_connectivity):
+def test_sabre_random_circuits(n_gates, look, decay, star_connectivity):
     connectivity = star_connectivity()
     circuit = generate_random_circuit(nqubits=5, ngates=n_gates)
     measurement = gates.M(*range(5))
     circuit.add(measurement)
     original_circuit = circuit.copy()
-    placer = placer_param(connectivity)
+    placer = Random(connectivity)
     router = Sabre(connectivity, lookahead=look, decay_lookahead=decay)
 
     placer(circuit)
@@ -459,16 +438,13 @@ def test_sabre_random_circuits(n_gates, look, decay, placer_param, star_connecti
 @pytest.mark.parametrize("n_gates", [10, 40])
 @pytest.mark.parametrize("look", [0, 5])
 @pytest.mark.parametrize("decay", [0.5, 1.0])
-@pytest.mark.parametrize("placer_param", [Trivial, Random])
-def test_sabre_random_circuits_grid(
-    n_gates, look, decay, placer_param, grid_connectivity
-):
+def test_sabre_random_circuits_grid(n_gates, look, decay, grid_connectivity):
     connectivity = grid_connectivity()
     circuit = generate_random_circuit(nqubits=5, ngates=n_gates)
     measurement = gates.M(*range(5))
     circuit.add(measurement)
     original_circuit = circuit.copy()
-    placer = placer_param(connectivity)
+    placer = Random(connectivity)
     router = Sabre(connectivity, lookahead=look, decay_lookahead=decay)
 
     placer(circuit)
@@ -488,9 +464,7 @@ def test_sabre_random_circuits_grid(
 
 def test_sabre_memory_map(star_connectivity):
     connectivity = star_connectivity()
-    placer = Trivial(connectivity=connectivity)
     layout_circ = Circuit(5)
-    placer(layout_circ)
     router = Sabre(connectivity=connectivity)
     router._preprocessing(circuit=star_circuit())
     router._memory_map = [[1, 0, 2, 3, 4]]

From abed4b9ff40db47a919970df6234d5230e05e6ff Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Fri, 22 Nov 2024 14:30:19 +0400
Subject: [PATCH 30/34] fix: remove default star transpiler / enforce
 connectivity

---
 src/qibo/transpiler/pipeline.py   | 36 +++++++-------------------
 tests/test_transpiler_pipeline.py | 42 +++++--------------------------
 tests/test_transpiler_unroller.py |  4 +--
 3 files changed, 17 insertions(+), 65 deletions(-)

diff --git a/src/qibo/transpiler/pipeline.py b/src/qibo/transpiler/pipeline.py
index 3e75f1a368..b2f5ccf735 100644
--- a/src/qibo/transpiler/pipeline.py
+++ b/src/qibo/transpiler/pipeline.py
@@ -4,11 +4,13 @@
 from qibo.models import Circuit
 from qibo.transpiler._exceptions import TranspilerPipelineError
 from qibo.transpiler.abstract import Optimizer, Placer, Router
-from qibo.transpiler.optimizer import Preprocessing
-from qibo.transpiler.placer import StarConnectivityPlacer
-from qibo.transpiler.router import ConnectivityError, StarConnectivityRouter
+from qibo.transpiler.router import ConnectivityError
 from qibo.transpiler.unroller import DecompositionError, NativeGates, Unroller
-from qibo.transpiler.utils import assert_connectivity, assert_decomposition
+from qibo.transpiler.utils import (
+    assert_connectivity,
+    assert_decomposition,
+    assert_placement,
+)
 
 
 def restrict_connectivity_qubits(connectivity: nx.Graph, qubits: list[str]):
@@ -47,8 +49,6 @@ class Passes:
             If ``None``, default transpiler will be used.
             Defaults to ``None``.
         connectivity (:class:`networkx.Graph`, optional): physical qubits connectivity.
-            If ``None``, full connectivity is assumed.
-            Defaults to ``None``.
         native_gates (:class:`qibo.transpiler.unroller.NativeGates`, optional): native gates.
             Defaults to :math:`qibo.transpiler.unroller.NativeGates.default`.
         on_qubits (list, optional): list of physical qubits to be used.
@@ -57,8 +57,8 @@ class Passes:
 
     def __init__(
         self,
+        connectivity: nx.Graph,
         passes: list = None,
-        connectivity: nx.Graph = None,
         native_gates: NativeGates = NativeGates.default(),
         on_qubits: list = None,
     ):
@@ -66,26 +66,7 @@ def __init__(
             connectivity = restrict_connectivity_qubits(connectivity, on_qubits)
         self.connectivity = connectivity
         self.native_gates = native_gates
-        self.passes = self.default() if passes is None else passes
-
-    def default(self):
-        """Return the default star connectivity transpiler pipeline."""
-        if not isinstance(self.connectivity, nx.Graph):
-            raise_error(
-                TranspilerPipelineError,
-                "Define the hardware chip connectivity to use default transpiler",
-            )
-        default_passes = []
-        # preprocessing
-        default_passes.append(Preprocessing(connectivity=self.connectivity))
-        # default placer pass
-        default_passes.append(StarConnectivityPlacer(connectivity=self.connectivity))
-        # default router pass
-        default_passes.append(StarConnectivityRouter(connectivity=self.connectivity))
-        # default unroller pass
-        default_passes.append(Unroller(native_gates=self.native_gates))
-
-        return default_passes
+        self.passes = [] if passes is None else passes
 
     def __call__(self, circuit):
         """
@@ -123,6 +104,7 @@ def is_satisfied(self, circuit: Circuit):
             (bool): satisfiability condition.
         """
         try:
+            assert_placement(circuit=circuit, connectivity=self.connectivity)
             assert_connectivity(circuit=circuit, connectivity=self.connectivity)
             assert_decomposition(circuit=circuit, native_gates=self.native_gates)
             return True
diff --git a/tests/test_transpiler_pipeline.py b/tests/test_transpiler_pipeline.py
index b43129a0eb..27cdb882fd 100644
--- a/tests/test_transpiler_pipeline.py
+++ b/tests/test_transpiler_pipeline.py
@@ -67,33 +67,6 @@ def test_restrict_qubits(star_connectivity):
     assert list(new_connectivity.edges) == [("A", "C"), ("B", "C")]
 
 
-@pytest.mark.parametrize("ngates", [5, 10, 50])
-@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
-def test_pipeline_default(ngates, names, star_connectivity):
-    circ = generate_random_circuit(nqubits=5, ngates=ngates, names=names)
-    connectivity = star_connectivity(names)
-
-    default_transpiler = Passes(passes=None, connectivity=connectivity)
-    transpiled_circ, final_layout = default_transpiler(circ)
-    assert_transpiling(
-        original_circuit=circ,
-        transpiled_circuit=transpiled_circ,
-        connectivity=connectivity,
-        final_layout=final_layout,
-        native_gates=NativeGates.default(),
-        check_circuit_equivalence=False,
-    )
-
-
-def test_int_qubit_names_default(star_connectivity):
-    names = [1244, 1532, 2315, 6563, 8901]
-    circ = Circuit(5, wire_names=names)
-    connectivity = star_connectivity(names)
-    default_transpiler = Passes(passes=None, connectivity=connectivity)
-    _, final_layout = default_transpiler(circ)
-    assert final_layout == {names[i]: i for i in range(5)}
-
-
 def test_assert_circuit_equivalence_wrong_nqubits():
     circ1 = Circuit(1)
     circ2 = Circuit(2)
@@ -102,15 +75,12 @@ def test_assert_circuit_equivalence_wrong_nqubits():
         assert_circuit_equivalence(circ1, circ2, final_map=final_map)
 
 
-def test_error_connectivity():
-    with pytest.raises(TranspilerPipelineError):
-        Passes(passes=None, connectivity=None)
-
-
 @pytest.mark.parametrize("qubits", [3, 5])
 def test_is_satisfied(qubits, star_connectivity):
-    default_transpiler = Passes(passes=None, connectivity=star_connectivity())
-    circuit = Circuit(qubits)
+    default_transpiler = Passes(
+        passes=None, connectivity=star_connectivity(), on_qubits=list(range(qubits))
+    )
+    circuit = Circuit(qubits, wire_names=list(range(qubits)))
     circuit.add(gates.CZ(0, 2))
     circuit.add(gates.Z(0))
     assert default_transpiler.is_satisfied(circuit)
@@ -152,7 +122,7 @@ def test_custom_passes(placer, router, ngates, nqubits, star_connectivity):
     custom_passes.append(router())
     custom_passes.append(Unroller(native_gates=NativeGates.default()))
     custom_pipeline = Passes(
-        custom_passes,
+        passes=custom_passes,
         connectivity=connectivity,
         native_gates=NativeGates.default(),
     )
@@ -188,7 +158,7 @@ def test_custom_passes_restrict(
     custom_passes.append(routing())
     custom_passes.append(Unroller(native_gates=NativeGates.default()))
     custom_pipeline = Passes(
-        custom_passes,
+        passes=custom_passes,
         connectivity=connectivity,
         native_gates=NativeGates.default(),
         on_qubits=restrict_names,
diff --git a/tests/test_transpiler_unroller.py b/tests/test_transpiler_unroller.py
index 3dea6df27e..4d33aa8d10 100644
--- a/tests/test_transpiler_unroller.py
+++ b/tests/test_transpiler_unroller.py
@@ -112,8 +112,8 @@ def test_temp_cnot_decomposition():
     glist = [gates.GPI2, gates.RZ, gates.Z, gates.M, gates.CNOT]
     native_gates = NativeGates(0).from_gatelist(glist)
 
-    custom_pipeline = Passes([Unroller(native_gates=native_gates)])
-    transpiled_circuit, _ = custom_pipeline(circ)
+    unroller = Unroller(native_gates=native_gates)
+    transpiled_circuit = unroller(circ)
 
     # H
     assert transpiled_circuit.queue[0].name == "z"

From ad079dec3df4b618fda5ac6fe9f5614a5db04fc6 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Fri, 22 Nov 2024 14:35:42 +0400
Subject: [PATCH 31/34] fix: modify is_satisfied

---
 src/qibo/transpiler/pipeline.py   | 11 ++++++-----
 tests/test_transpiler_pipeline.py |  6 ++++++
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/src/qibo/transpiler/pipeline.py b/src/qibo/transpiler/pipeline.py
index b2f5ccf735..9a0f2cd04d 100644
--- a/src/qibo/transpiler/pipeline.py
+++ b/src/qibo/transpiler/pipeline.py
@@ -2,9 +2,12 @@
 
 from qibo.config import raise_error
 from qibo.models import Circuit
-from qibo.transpiler._exceptions import TranspilerPipelineError
+from qibo.transpiler._exceptions import (
+    ConnectivityError,
+    PlacementError,
+    TranspilerPipelineError,
+)
 from qibo.transpiler.abstract import Optimizer, Placer, Router
-from qibo.transpiler.router import ConnectivityError
 from qibo.transpiler.unroller import DecompositionError, NativeGates, Unroller
 from qibo.transpiler.utils import (
     assert_connectivity,
@@ -108,7 +111,5 @@ def is_satisfied(self, circuit: Circuit):
             assert_connectivity(circuit=circuit, connectivity=self.connectivity)
             assert_decomposition(circuit=circuit, native_gates=self.native_gates)
             return True
-        except ConnectivityError:
-            return False
-        except DecompositionError:
+        except (ConnectivityError, DecompositionError, PlacementError, ValueError):
             return False
diff --git a/tests/test_transpiler_pipeline.py b/tests/test_transpiler_pipeline.py
index 27cdb882fd..6092957022 100644
--- a/tests/test_transpiler_pipeline.py
+++ b/tests/test_transpiler_pipeline.py
@@ -86,6 +86,12 @@ def test_is_satisfied(qubits, star_connectivity):
     assert default_transpiler.is_satisfied(circuit)
 
 
+def test_is_satisfied_false_placement(star_connectivity):
+    default_transpiler = Passes(passes=None, connectivity=star_connectivity())
+    circuit = Circuit(5, wire_names=["A", "B", "C", "D", "E"])
+    assert not default_transpiler.is_satisfied(circuit)
+
+
 def test_is_satisfied_false_decomposition(star_connectivity):
     default_transpiler = Passes(passes=None, connectivity=star_connectivity())
     circuit = Circuit(5)

From 1f55f3c149d155fc545d5dbb3670593e23b79a7f Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Fri, 22 Nov 2024 14:45:33 +0400
Subject: [PATCH 32/34] fix: revert, make connectivity optiona

---
 src/qibo/transpiler/pipeline.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/qibo/transpiler/pipeline.py b/src/qibo/transpiler/pipeline.py
index 9a0f2cd04d..616cbbc87d 100644
--- a/src/qibo/transpiler/pipeline.py
+++ b/src/qibo/transpiler/pipeline.py
@@ -60,8 +60,8 @@ class Passes:
 
     def __init__(
         self,
-        connectivity: nx.Graph,
         passes: list = None,
+        connectivity: nx.Graph = None,
         native_gates: NativeGates = NativeGates.default(),
         on_qubits: list = None,
     ):

From 797331ed774f374481bac37984522a94d9e66cf7 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Mon, 25 Nov 2024 13:56:01 +0400
Subject: [PATCH 33/34] fix: type errors, Preprocessor connectivity check,
 utils.py -> asserts.py

---
 src/qibo/models/circuit.py                           |  2 +-
 src/qibo/transpiler/{utils.py => asserts.py}         |  0
 src/qibo/transpiler/optimizer.py                     |  8 ++++----
 src/qibo/transpiler/pipeline.py                      |  4 ++--
 src/qibo/transpiler/placer.py                        | 12 +++++++-----
 src/qibo/transpiler/router.py                        | 10 ++++++----
 ...ranspiler_utils.py => test_transpiler_asserts.py} |  6 +++---
 tests/test_transpiler_decompositions.py              |  2 +-
 tests/test_transpiler_optimizer.py                   |  5 -----
 tests/test_transpiler_pipeline.py                    |  2 +-
 tests/test_transpiler_placer.py                      |  2 +-
 tests/test_transpiler_router.py                      | 12 ++++++------
 tests/test_transpiler_unroller.py                    |  2 +-
 13 files changed, 33 insertions(+), 34 deletions(-)
 rename src/qibo/transpiler/{utils.py => asserts.py} (100%)
 rename tests/{test_transpiler_utils.py => test_transpiler_asserts.py} (99%)

diff --git a/src/qibo/models/circuit.py b/src/qibo/models/circuit.py
index c0d6bd2b86..31f8570d88 100644
--- a/src/qibo/models/circuit.py
+++ b/src/qibo/models/circuit.py
@@ -165,7 +165,7 @@ class Circuit:
 
     def __init__(
         self,
-        nqubits: Optional[Union[str, list]] = None,
+        nqubits: Optional[Union[int, list]] = None,
         accelerators=None,
         density_matrix: bool = False,
         wire_names: Optional[list] = None,
diff --git a/src/qibo/transpiler/utils.py b/src/qibo/transpiler/asserts.py
similarity index 100%
rename from src/qibo/transpiler/utils.py
rename to src/qibo/transpiler/asserts.py
diff --git a/src/qibo/transpiler/optimizer.py b/src/qibo/transpiler/optimizer.py
index 3b93e5843a..741078e5e9 100644
--- a/src/qibo/transpiler/optimizer.py
+++ b/src/qibo/transpiler/optimizer.py
@@ -1,3 +1,5 @@
+from typing import Optional
+
 import networkx as nx
 
 from qibo import gates
@@ -13,13 +15,11 @@ class Preprocessing(Optimizer):
         connectivity (:class:`networkx.Graph`): hardware chip connectivity.
     """
 
-    def __init__(self, connectivity: nx.Graph = None):
+    def __init__(self, connectivity: Optional[nx.Graph] = None):
         self.connectivity = connectivity
 
     def __call__(self, circuit: Circuit) -> Circuit:
-        if self.connectivity is None or not all(
-            qubit in self.connectivity.nodes for qubit in circuit.wire_names
-        ):
+        if not all(qubit in self.connectivity.nodes for qubit in circuit.wire_names):
             raise_error(
                 ValueError,
                 "The circuit qubits are not in the connectivity graph.",
diff --git a/src/qibo/transpiler/pipeline.py b/src/qibo/transpiler/pipeline.py
index 616cbbc87d..c1aae06775 100644
--- a/src/qibo/transpiler/pipeline.py
+++ b/src/qibo/transpiler/pipeline.py
@@ -8,12 +8,12 @@
     TranspilerPipelineError,
 )
 from qibo.transpiler.abstract import Optimizer, Placer, Router
-from qibo.transpiler.unroller import DecompositionError, NativeGates, Unroller
-from qibo.transpiler.utils import (
+from qibo.transpiler.asserts import (
     assert_connectivity,
     assert_decomposition,
     assert_placement,
 )
+from qibo.transpiler.unroller import DecompositionError, NativeGates, Unroller
 
 
 def restrict_connectivity_qubits(connectivity: nx.Graph, qubits: list[str]):
diff --git a/src/qibo/transpiler/placer.py b/src/qibo/transpiler/placer.py
index 4539272574..48e2cbd8ec 100644
--- a/src/qibo/transpiler/placer.py
+++ b/src/qibo/transpiler/placer.py
@@ -8,8 +8,8 @@
 from qibo.models import Circuit
 from qibo.transpiler._exceptions import PlacementError
 from qibo.transpiler.abstract import Placer, Router
+from qibo.transpiler.asserts import assert_placement
 from qibo.transpiler.router import _find_connected_qubit
-from qibo.transpiler.utils import assert_placement
 
 
 def _find_gates_qubits_pairs(circuit: Circuit):
@@ -48,7 +48,7 @@ class StarConnectivityPlacer(Placer):
         connectivity (:class:`networkx.Graph`): star connectivity graph.
     """
 
-    def __init__(self, connectivity: nx.Graph = None):
+    def __init__(self, connectivity: Optional[nx.Graph] = None):
         self.connectivity = connectivity
         self.middle_qubit = None
 
@@ -114,7 +114,7 @@ class Subgraph(Placer):
         connectivity (:class:`networkx.Graph`): chip connectivity.
     """
 
-    def __init__(self, connectivity: nx.Graph = None):
+    def __init__(self, connectivity: Optional[nx.Graph] = None):
         self.connectivity = connectivity
 
     def __call__(self, circuit: Circuit):
@@ -172,7 +172,9 @@ class Random(Placer):
             initializes a generator with a random seed. Defaults to ``None``.
     """
 
-    def __init__(self, connectivity: nx.Graph = None, samples: int = 100, seed=None):
+    def __init__(
+        self, connectivity: Optional[nx.Graph] = None, samples: int = 100, seed=None
+    ):
         self.connectivity = connectivity
         self.samples = samples
         self.seed = seed
@@ -256,7 +258,7 @@ class ReverseTraversal(Placer):
     def __init__(
         self,
         routing_algorithm: Router,
-        connectivity: nx.Graph = None,
+        connectivity: Optional[nx.Graph] = None,
         depth: Optional[int] = None,
     ):
         self.connectivity = connectivity
diff --git a/src/qibo/transpiler/router.py b/src/qibo/transpiler/router.py
index 027b17119b..704e4435b8 100644
--- a/src/qibo/transpiler/router.py
+++ b/src/qibo/transpiler/router.py
@@ -10,8 +10,8 @@
 from qibo.models import Circuit
 from qibo.transpiler._exceptions import ConnectivityError
 from qibo.transpiler.abstract import Router
+from qibo.transpiler.asserts import assert_placement
 from qibo.transpiler.blocks import Block, CircuitBlocks
-from qibo.transpiler.utils import assert_placement
 
 
 class StarConnectivityRouter(Router):
@@ -31,7 +31,7 @@ class StarConnectivityRouter(Router):
         connectivity (:class:`networkx.Graph`): star connectivity graph.
     """
 
-    def __init__(self, connectivity: nx.Graph):
+    def __init__(self, connectivity: Optional[nx.Graph] = None):
         self.connectivity = connectivity
         self.middle_qubit = None
 
@@ -314,7 +314,9 @@ class ShortestPaths(Router):
             If ``None``, defaults to :math:`42`. Defaults to ``None``.
     """
 
-    def __init__(self, connectivity: nx.Graph = None, seed: Optional[int] = None):
+    def __init__(
+        self, connectivity: Optional[nx.Graph] = None, seed: Optional[int] = None
+    ):
         self.connectivity = connectivity
         self._front_layer = None
         self.circuit_map = None
@@ -601,7 +603,7 @@ class Sabre(Router):
 
     def __init__(
         self,
-        connectivity: nx.Graph = None,
+        connectivity: Optional[nx.Graph] = None,
         lookahead: int = 2,
         decay_lookahead: float = 0.6,
         delta: float = 0.001,
diff --git a/tests/test_transpiler_utils.py b/tests/test_transpiler_asserts.py
similarity index 99%
rename from tests/test_transpiler_utils.py
rename to tests/test_transpiler_asserts.py
index 7476e1d80f..8b0b268003 100644
--- a/tests/test_transpiler_utils.py
+++ b/tests/test_transpiler_asserts.py
@@ -8,14 +8,14 @@
     PlacementError,
     TranspilerPipelineError,
 )
-from qibo.transpiler.pipeline import restrict_connectivity_qubits
-from qibo.transpiler.unroller import NativeGates
-from qibo.transpiler.utils import (
+from qibo.transpiler.asserts import (
     assert_circuit_equivalence,
     assert_connectivity,
     assert_decomposition,
     assert_placement,
 )
+from qibo.transpiler.pipeline import restrict_connectivity_qubits
+from qibo.transpiler.unroller import NativeGates
 
 
 def test_assert_circuit_equivalence_equal():
diff --git a/tests/test_transpiler_decompositions.py b/tests/test_transpiler_decompositions.py
index 108a4cc416..e26af68841 100644
--- a/tests/test_transpiler_decompositions.py
+++ b/tests/test_transpiler_decompositions.py
@@ -5,8 +5,8 @@
 from qibo.backends import NumpyBackend
 from qibo.models import Circuit
 from qibo.quantum_info.random_ensembles import random_unitary
+from qibo.transpiler.asserts import assert_decomposition
 from qibo.transpiler.unroller import NativeGates, translate_gate
-from qibo.transpiler.utils import assert_decomposition
 
 default_natives = NativeGates.Z | NativeGates.RZ | NativeGates.M | NativeGates.I
 
diff --git a/tests/test_transpiler_optimizer.py b/tests/test_transpiler_optimizer.py
index eefcd2c1fb..500f507178 100644
--- a/tests/test_transpiler_optimizer.py
+++ b/tests/test_transpiler_optimizer.py
@@ -8,11 +8,6 @@
 
 def test_preprocessing_error(star_connectivity):
     circ = Circuit(7)
-
-    preprocesser = Preprocessing()
-    with pytest.raises(ValueError):
-        new_circuit = preprocesser(circuit=circ)
-
     preprocesser = Preprocessing(connectivity=star_connectivity())
     with pytest.raises(ValueError):
         new_circuit = preprocesser(circuit=circ)
diff --git a/tests/test_transpiler_pipeline.py b/tests/test_transpiler_pipeline.py
index 6092957022..a8e43bc6aa 100644
--- a/tests/test_transpiler_pipeline.py
+++ b/tests/test_transpiler_pipeline.py
@@ -5,12 +5,12 @@
 from qibo import gates
 from qibo.models import Circuit
 from qibo.transpiler._exceptions import ConnectivityError, TranspilerPipelineError
+from qibo.transpiler.asserts import assert_circuit_equivalence, assert_transpiling
 from qibo.transpiler.optimizer import Preprocessing
 from qibo.transpiler.pipeline import Passes, restrict_connectivity_qubits
 from qibo.transpiler.placer import Random, ReverseTraversal
 from qibo.transpiler.router import Sabre, ShortestPaths
 from qibo.transpiler.unroller import NativeGates, Unroller
-from qibo.transpiler.utils import assert_circuit_equivalence, assert_transpiling
 
 
 def generate_random_circuit(nqubits, ngates, names=None, seed=42):
diff --git a/tests/test_transpiler_placer.py b/tests/test_transpiler_placer.py
index f9d41ecc55..13fef50904 100644
--- a/tests/test_transpiler_placer.py
+++ b/tests/test_transpiler_placer.py
@@ -4,6 +4,7 @@
 from qibo import gates
 from qibo.models import Circuit
 from qibo.transpiler._exceptions import PlacementError, TranspilerPipelineError
+from qibo.transpiler.asserts import assert_placement
 from qibo.transpiler.pipeline import restrict_connectivity_qubits
 from qibo.transpiler.placer import (
     Random,
@@ -13,7 +14,6 @@
     _find_gates_qubits_pairs,
 )
 from qibo.transpiler.router import ShortestPaths
-from qibo.transpiler.utils import assert_placement
 
 
 def star_circuit(names=[0, 1, 2, 3, 4]):
diff --git a/tests/test_transpiler_router.py b/tests/test_transpiler_router.py
index 79ec82bbc9..06899e78d3 100644
--- a/tests/test_transpiler_router.py
+++ b/tests/test_transpiler_router.py
@@ -9,6 +9,12 @@
 from qibo.models import Circuit
 from qibo.quantum_info.random_ensembles import random_unitary
 from qibo.transpiler._exceptions import ConnectivityError
+from qibo.transpiler.asserts import (
+    _transpose_qubits,
+    assert_circuit_equivalence,
+    assert_connectivity,
+    assert_placement,
+)
 from qibo.transpiler.pipeline import restrict_connectivity_qubits
 from qibo.transpiler.placer import Random, StarConnectivityPlacer, Subgraph
 from qibo.transpiler.router import (
@@ -17,12 +23,6 @@
     ShortestPaths,
     StarConnectivityRouter,
 )
-from qibo.transpiler.utils import (
-    _transpose_qubits,
-    assert_circuit_equivalence,
-    assert_connectivity,
-    assert_placement,
-)
 
 
 def line_connectivity(n, names=None):
diff --git a/tests/test_transpiler_unroller.py b/tests/test_transpiler_unroller.py
index 4d33aa8d10..181a348e82 100644
--- a/tests/test_transpiler_unroller.py
+++ b/tests/test_transpiler_unroller.py
@@ -3,8 +3,8 @@
 from qibo import gates
 from qibo.models import Circuit
 from qibo.transpiler._exceptions import DecompositionError
+from qibo.transpiler.asserts import assert_decomposition
 from qibo.transpiler.unroller import NativeGates, Unroller, translate_gate
-from qibo.transpiler.utils import assert_decomposition
 
 
 def test_native_gates_from_gatelist():

From 049ff015187bdafe8b941f9afbe209fd877f95b5 Mon Sep 17 00:00:00 2001
From: changsookim <>
Date: Mon, 25 Nov 2024 14:57:11 +0400
Subject: [PATCH 34/34] fix: utils -> asserts

---
 doc/source/code-examples/advancedexamples.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/source/code-examples/advancedexamples.rst b/doc/source/code-examples/advancedexamples.rst
index 9904a4ab1e..32da8b0129 100644
--- a/doc/source/code-examples/advancedexamples.rst
+++ b/doc/source/code-examples/advancedexamples.rst
@@ -2171,7 +2171,7 @@ Multiple transpilation steps can be implemented using the :class:`qibo.transpile
     from qibo.transpiler.router import ShortestPaths
     from qibo.transpiler.unroller import Unroller, NativeGates
     from qibo.transpiler.placer import Random
-    from qibo.transpiler.utils import assert_transpiling
+    from qibo.transpiler.asserts import assert_transpiling
 
     # Define connectivity as nx.Graph
     def star_connectivity():