code: def transpile(
      tape: QuantumTape,
      coupling_map: Union[List, nx.Graph],
      device=None,
  ) -> (Sequence[QuantumTape], Callable):
      """Transpile a circuit according to a desired coupling map
  
      .. warning::
  
          This transform does not yet support measurements of Hamiltonians or tensor products of observables. If a circuit
          is passed which contains these types of measurements, a ``NotImplementedError`` will be raised.
  
      Args:
          tape (QNode or QuantumTape or Callable): A quantum tape.
          coupling_map (list[tuple(int, int)] or nx.Graph): Either a list of tuples(int, int) or an instance of
              `networkx.Graph` specifying the couplings between different qubits.
  
      Returns:
          qnode (QNode) or quantum function (Callable) or tuple[List[.QuantumTape], function]: The transformed circuit as described in :func:`qml.transform <pennylane.transform>`.
  
      **Example**
  
      Consider the following example circuit
  
      .. code-block:: python
  
          def circuit():
              qml.CNOT(wires=[0, 1])
              qml.CNOT(wires=[2, 3])
              qml.CNOT(wires=[1, 3])
              qml.CNOT(wires=[1, 2])
              qml.CNOT(wires=[2, 3])
              qml.CNOT(wires=[0, 3])
              return qml.probs(wires=[0, 1, 2, 3])
  
      which, before transpiling it looks like this:
  
      .. code-block:: text
  
          0: ──╭●──────────────╭●──╭┤ Probs
          1: ──╰X──╭●──╭●──────│───├┤ Probs
          2: ──╭●──│───╰X──╭●──│───├┤ Probs
          3: ──╰X──╰X──────╰X──╰X──╰┤ Probs
  
      Suppose we have a device which has connectivity constraints according to the graph:
  
      .. code-block:: text
  
          0 --- 1
          |     |
          2 --- 3
  
      We encode this in a coupling map as a list of the edges which are present in the graph, and then pass this, together
      with the circuit, to the transpile function to get a circuit which can be executed for the specified coupling map:
  
      >>> dev = qml.device('default.qubit', wires=[0, 1, 2, 3])
      >>> transpiled_circuit = qml.transforms.transpile(circuit, coupling_map=[(0, 1), (1, 3), (3, 2), (2, 0)])
      >>> transpiled_qnode = qml.QNode(transpiled_circuit, dev)
      >>> print(qml.draw(transpiled_qnode)())
      0: ─╭●────────────────╭●─┤ ╭Probs
      1: ─╰X─╭●───────╭●────│──┤ ├Probs
      2: ─╭●─│──╭SWAP─│──╭X─╰X─┤ ├Probs
      3: ─╰X─╰X─╰SWAP─╰X─╰●────┤ ╰Probs
  
      A swap gate has been applied to wires 2 and 3, and the remaining gates have been adapted accordingly
  
      """
      if device:
          device_wires = device.wires
          is_default_mixed = (
              getattr(device, "short_name", "") == "default.mixed"
          )
      else:
          device_wires = None
          is_default_mixed = False
      # init connectivity graph
      coupling_graph = (
          nx.Graph(coupling_map)
          if not isinstance(coupling_map, nx.Graph)
          else coupling_map
      )
  
      # make sure every wire is present in coupling map
      if any(wire not in coupling_graph.nodes for wire in tape.wires):
          wires = tape.wires.tolist()
          raise ValueError(
              f"Not all wires present in coupling map! wires: {wires}, coupling map: {coupling_graph.nodes}"
          )
  
      if any(
          isinstance(m.obs, (Hamiltonian, Tensor))
          for m in tape.measurements
      ):
          raise NotImplementedError(
              "Measuring expectation values of tensor products or Hamiltonians is not yet supported"
          )
  
      if any(len(op.wires) > 2 for op in tape.operations):
          raise NotImplementedError(
              "The transpile transform only supports gates acting on 1 or 2 qubits."
          )
  
      # we wrap all manipulations inside stop_recording() so that we don't queue anything due to unrolling of templates
      # or newly applied swap gates
      with QueuingManager.stop_recording():
          # this unrolls everything in the current tape (in particular templates)
          def stop_at(obj):
              return (obj.name in all_ops) and (
                  not getattr(obj, "only_visual", False)
              )
  
          expanded_tape = tape.expand(stop_at=stop_at)
  
          # make copy of ops
          list_op_copy = expanded_tape.operations.copy()
          wire_order = device_wires or tape.wires
          measurements = _process_measurements(
              expanded_tape, device_wires, is_default_mixed
          )
  
          gates = []
  
          while len(list_op_copy) > 0:
              op = list_op_copy[0]
  
              # gates which act only on one wire
              if len(op.wires) == 1:
                  gates.append(op)
                  list_op_copy.pop(0)
                  continue
  
              # two-qubit gates which can be handled by the coupling map
              if (
                  op.wires in coupling_graph.edges
                  or tuple(reversed(op.wires)) in coupling_graph.edges
              ):
                  gates.append(op)
                  list_op_copy.pop(0)
                  continue
  
              # since in each iteration, we adjust indices of each op, we reset logical -> phyiscal mapping
              wire_map = {w: w for w in wire_order}
  
              # to make sure two qubit gates which act on non-neighbouring qubits q1, q2 can be applied, we first look
              # for the shortest path between the two qubits in the connectivity graph. We then move the q2 into the
              # neighbourhood of q1 via swap operations.
              source_wire, dest_wire = op.wires
              # pylint:disable=too-many-function-args
              shortest_path = nx.algorithms.shortest_path(
                  coupling_graph, source_wire, dest_wire
              )
              path_length = len(shortest_path) - 1
              wires_to_swap = [
                  shortest_path[(i - 1) : (i + 1)]
                  for i in range(path_length, 1, -1)
              ]
  
              for w0, w1 in wires_to_swap:
                  # swap wires
                  gates.append(SWAP(wires=[w0, w1]))
                  # update logical -> phyiscal mapping
                  wire_map = {
                      k: (w0 if v == w1 else (w1 if v == w0 else v))
                      for k, v in wire_map.items()
                  }
  
              # append op to gates with adjusted indices and remove from list
              gates.append(op.map_wires(wire_map))
              list_op_copy.pop(0)
  
              list_op_copy = [
                  op.map_wires(wire_map) for op in list_op_copy
              ]
              wire_order = [wire_map[w] for w in wire_order]
              measurements = [
                  m.map_wires(wire_map) for m in measurements
              ]
      new_tape = type(tape)(gates, measurements, shots=tape.shots)
  
      # note: no need for transposition with density matrix, so type must be `StateMP` but not `DensityMatrixMP`
      # pylint: disable=unidiomatic-typecheck
      any_state_mp = any(
          type(m) is qml.measurements.StateMP for m in measurements
      )
      if not any_state_mp or device_wires is None:
  
          def null_postprocessing(results):
              """A postprocesing function returned by a transform that only converts the batch of results
              into a result for a single ``QuantumTape``.
              """
              return results[0]
  
          return (new_tape,), null_postprocessing
  
      return (new_tape,), partial(
          state_transposition,
          mps=measurements,
          new_wire_order=wire_order,
          original_wire_order=device_wires,
      )
  
file_path: pennylane/pennylane/transforms/transpile.py
imports: from functools import partial
  from typing import List, Union, Sequence, Callable
  import networkx
  import pennylane
  from pennylane.transforms import transform
  from pennylane import Hamiltonian
  from pennylane.operation import Tensor
  from pennylane.ops import __all__
  from pennylane.ops.qubit import SWAP
  from pennylane.queuing import QueuingManager
  from pennylane.tape import QuantumTape
label_desc: Use image node_id 3 for calling a global function with example usage: transpile(tape, coupling_map, device) and returns: new_tape,  partial, new_tape,  null_postprocessing, unknown, results