def route_circuit(
        self,
        circuit: cirq.AbstractCircuit,
        *,
        lookahead_radius: int = 8,
        tag_inserted_swaps: bool = False,
        initial_mapper: cirq.AbstractInitialMapper | None = None,
        context: cirq.TransformerContext | None = None,
    ) -> tuple[cirq.AbstractCircuit, dict[cirq.Qid, cirq.Qid], dict[cirq.Qid, cirq.Qid]]:
        """Transforms the given circuit to make it executable on the device.

        This transformer assumes that all multi-qubit operations have been decomposed into 2-qubit
        operations and will raise an error if `circuit` a n-qubit operation where n > 2. If
        `circuit` contains `cirq.CircuitOperation`s and `context.deep` is True then they are first
        unrolled before proceeding. If `context.deep` is False or `context` is None then any
        `cirq.CircuitOperation` that acts on more than 2-qubits will also raise an error.

        The algorithm tries to find the best swap at each timestep by ranking a set of candidate
        swaps against operations starting from the current timestep (say s) to the timestep at index
        s + `lookahead_radius` to prune the set of candidate swaps. If it fails  to converge to a to
        a single swap because of highly symmetrical device or circuit connectivity, then symmetry
        breaking strategies are used.

        Since routing doesn't necessarily modify any specific operation and only adds swaps
        before / after operations to ensure the circuit can be executed, tagging operations with
        tags from context.tags_to_ignore will have no impact on the routing procedure.

        Args:
            circuit: the input circuit to be transformed.
            lookahead_radius: the maximum number of succeeding timesteps the algorithm will
                consider for ranking candidate swaps with the cost cost function.
            tag_inserted_swaps: whether or not a RoutingSwapTag should be attched to inserted swap
                operations.
            initial_mapper: an initial mapping strategy (placement) of logical qubits in the
                circuit onto physical qubits on the device.
            context: transformer context storing common configurable options for transformers.

        Returns:
            The routed circuit, which is equivalent to original circuit up to a final qubit
                permutation and where each 2-qubit operation is between adjacent qubits in the
                `device_graph`.
            The initial mapping from logical to physical qubits used as part of the routing
                procedure.
            The mapping from physical qubits before inserting swaps to physical qubits after
                inserting swaps.

        Raises:
            ValueError: if circuit has operations that act on 3 or more qubits, except measurements.
        """

        # 0. Handle CircuitOperations by unrolling them.
        if context is not None and context.deep is True:
            circuit = transformer_primitives.unroll_circuit_op(circuit, deep=True)
        if any(
            protocols.num_qubits(op) > 2 and not protocols.is_measurement(op)
            for op in circuit.all_operations()
        ):
            raise ValueError("Input circuit must only have ops that act on 1 or 2 qubits.")

        # 1. Do the initial mapping of logical to physical qubits.
        if initial_mapper is None:
            initial_mapper = line_initial_mapper.LineInitialMapper(self.device_graph)
        initial_mapping = initial_mapper.initial_mapping(circuit)

        # 2. Construct a mapping manager that implicitly keeps track of this mapping and provides
        # convinience methods over the image of the map on the device graph.
        mm = mapping_manager.MappingManager(self.device_graph, initial_mapping)

        # 3. Get two_qubit_ops and single-qubit operations.
        two_qubit_ops, single_qubit_ops = self._get_one_and_two_qubit_ops_as_timesteps(circuit)

        # 4. Do the routing and save the routed circuit as a list of moments.
        routed_ops = self._route(
            mm,
            two_qubit_ops,
            single_qubit_ops,
            lookahead_radius,
            tag_inserted_swaps=tag_inserted_swaps,
        )

        # 5. Return the routed circuit by packing each inner list of ops as densely as possible and
        # preserving outer moment structure. Also return initial map and swap permutation map.
        return (
            circuits.Circuit(circuits.Circuit(m) for m in routed_ops),
            initial_mapping,
            {
                initial_mapping[mm.int_to_logical_qid[k]]: mm.int_to_physical_qid[v]
                for k, v in enumerate(mm.logical_to_physical)
            },
        )
Transforms the given circuit to make it executable on the device.

        This transformer assumes that all multi-qubit operations have been decomposed into 2-qubit
        operations and will raise an error if `circuit` a n-qubit operation where n > 2. If
        `circuit` contains `cirq.CircuitOperation`s and `context.deep` is True then they are first
        unrolled before proceeding. If `context.deep` is False or `context` is None then any
        `cirq.CircuitOperation` that acts on more than 2-qubits will also raise an error.

        The algorithm tries to find the best swap at each timestep by ranking a set of candidate
        swaps against operations starting from the current timestep (say s) to the timestep at index
        s + `lookahead_radius` to prune the set of candidate swaps. If it fails  to converge to a to
        a single swap because of highly symmetrical device or circuit connectivity, then symmetry
        breaking strategies are used.

        Since routing doesn't necessarily modify any specific operation and only adds swaps
        before / after operations to ensure the circuit can be executed, tagging operations with
        tags from context.tags_to_ignore will have no impact on the routing procedure.

        Args:
            circuit: the input circuit to be transformed.
            lookahead_radius: the maximum number of succeeding timesteps the algorithm will
                consider for ranking candidate swaps with the cost cost function.
            tag_inserted_swaps: whether or not a RoutingSwapTag should be attched to inserted swap
                operations.
            initial_mapper: an initial mapping strategy (placement) of logical qubits in the
                circuit onto physical qubits on the device.
            context: transformer context storing common configurable options for transformers.

        Returns:
            The routed circuit, which is equivalent to original circuit up to a final qubit
                permutation and where each 2-qubit operation is between adjacent qubits in the
                `device_graph`.
            The initial mapping from logical to physical qubits used as part of the routing
                procedure.
            The mapping from physical qubits before inserting swaps to physical qubits after
                inserting swaps.

        Raises:
            ValueError: if circuit has operations that act on 3 or more qubits, except measurements.
        
cirq-core/cirq/transformers/routing/route_circuit_cqc.py