code: def pattern_matching(circuit_dag, pattern_dag):
      r"""Function that applies the pattern matching algorithm and returns the list of maximal matches.
  
      Args:
          circuit_dag (.CommutationDAG): A commutation DAG representing the circuit to be optimized.
          pattern_dag(.CommutationDAG): A commutation DAG representing the pattern.
  
      Returns:
          list(Match): the list of maximal matches.
  
      **Example**
  
      First let's consider the following circuit
  
      .. code-block:: python
  
          def circuit():
              qml.S(wires=0)
              qml.PauliZ(wires=0)
              qml.S(wires=1)
              qml.CZ(wires=[0, 1])
              qml.S(wires=1)
              qml.S(wires=2)
              qml.CZ(wires=[1, 2])
              qml.S(wires=2)
              return qml.expval(qml.PauliX(wires=0))
  
      Assume that we want to find all maximal matches of a pattern containing a sequence of two :class:`~.S` gates and
      a :class:`~.PauliZ` gate:
  
      .. code-block:: python
  
          def pattern():
              qml.S(wires=0)
              qml.S(wires=0)
              qml.PauliZ(wires=0)
  
  
      >>> circuit_dag = qml.commutation_dag(circuit)()
      >>> pattern_dag = qml.commutation_dag(pattern)()
      >>> all_max_matches = qml.pattern_matching(circuit_dag, pattern_dag)
  
      The matches are accessible by looping through the list outputted by ``qml.pattern_matching``. This output is a list
      of lists containing indices. Each list represents a match between a gate in the pattern with a gate in the circuit.
      The first indices represent the gates in the pattern and the second indices provide indices for the gates in the
      circuit (by order of appearance).
  
      >>> for match_conf in all_max_matches:
      ...     print(match_conf.match)
      [[0, 0], [2, 1]]
      [[0, 2], [1, 4]]
      [[0, 4], [1, 2]]
      [[0, 5], [1, 7]]
      [[0, 7], [1, 5]]
  
      The first match of this list corresponds to match the first gate (:class:`~.S`) in the pattern with the first gate
      in the circuit and also the third gate in the pattern (:class:`~.PauliZ`) with the second circuit gate.
  
      .. seealso:: :func:`~.pattern_matching_optimization`
  
      **Reference:**
  
      [1] Iten, R., Moyard, R., Metger, T., Sutter, D. and Woerner, S., 2022.
      Exact and practical pattern matching for quantum circuit optimization.
      `doi.org/10.1145/3498325 <https://dl.acm.org/doi/abs/10.1145/3498325>`_
  
      """
      # Match list
      match_list = []
  
      # Loop through all possible initial matches
      for node_c, node_p in itertools.product(
          circuit_dag.get_nodes(), pattern_dag.get_nodes()
      ):
          # Initial matches between two identical gates (No qubits comparison)
          if _compare_operation_without_qubits(node_c[1], node_p[1]):
              # Fix qubits from the first (target fixed and control restrained)
              not_fixed_qubits_confs = _not_fixed_qubits(
                  circuit_dag.num_wires,
                  node_c[1].wires,
                  pattern_dag.num_wires - len(node_p[1].wires),
              )
  
              # Loop over all possible qubits configurations given the first match constrains
              for not_fixed_qubits_conf in not_fixed_qubits_confs:
                  for (
                      not_fixed_qubits_conf_permuted
                  ) in itertools.permutations(not_fixed_qubits_conf):
                      for (
                          first_match_qubits_conf
                      ) in _first_match_qubits(
                          node_c[1], node_p[1], pattern_dag.num_wires
                      ):
                          # Qubits mapping between circuit and pattern
                          qubits_conf = (
                              _merge_first_match_and_permutation(
                                  first_match_qubits_conf,
                                  not_fixed_qubits_conf_permuted,
                              )
                          )
                          # Update wires, target_wires, control_wires
                          (
                              wires,
                              target_wires,
                              control_wires,
                          ) = _update_qubits(circuit_dag, qubits_conf)
  
                          # Forward match part of the algorithm
                          forward = ForwardMatch(
                              circuit_dag,
                              pattern_dag,
                              node_c[0],
                              node_p[0],
                              wires,
                              target_wires,
                              control_wires,
                          )
                          forward.run_forward_match()
  
                          # Backward match part of the algorithm
                          backward = BackwardMatch(
                              circuit_dag,
                              pattern_dag,
                              qubits_conf,
                              forward.match,
                              forward.circuit_matched_with,
                              forward.circuit_blocked,
                              forward.pattern_matched_with,
                              node_c[0],
                              node_p[0],
                              wires,
                              control_wires,
                              target_wires,
                          )
                          backward.run_backward_match()
  
                          _add_match(match_list, backward.match_final)
  
      match_list.sort(key=lambda x: len(x.match), reverse=True)
  
      # Extract maximal matches and optimizes the circuit for compatible maximal matches
      if match_list:
          maximal = MaximalMatches(match_list)
          maximal.run_maximal_matches()
          max_matches = maximal.max_match_list
          return max_matches
  
      return match_list
  
imports: import copy
  import itertools
  from collections import OrderedDict
  from typing import Sequence, Callable
  import numpy
  import pennylane
  from pennylane.transforms import transform
  from pennylane import adjoint
  from pennylane.ops.qubit.attributes import symmetric_over_all_wires
  from pennylane.tape import QuantumTape, QuantumScript
  from pennylane.transforms.commutation_dag import commutation_dag
  from pennylane.wires import Wires
label_desc: Use image node_id 2 for calling a global function with example usage: pattern_matching(circuit_dag, pattern_dag) and returns: match_list, max_matches