code: def _decomposition_2_cnots(U, wires):
      r"""If 2 CNOTs are required, we can write the circuit as
       -╭U- = -A--╭X--RZ(d)--╭X--C-
       -╰U- = -B--╰C--RX(p)--╰C--D-
      We need to find the angles for the Z and X rotations such that the inner
      part has the same spectrum as U, and then we can recover A, B, C, D.
      """
      # Compute the rotation angles
      u = math.dot(Edag, math.dot(U, E))
      gammaU = math.dot(u, math.T(u))
      evs, _ = math.linalg.eig(gammaU)
  
      # These choices are based on Proposition III.3 of
      # https://arxiv.org/abs/quant-ph/0308045
      # There is, however, a special case where the circuit has the form
      # -╭U- = -A--╭C--╭X--C-
      # -╰U- = -B--╰X--╰C--D-
      #
      # or some variant of this, where the two CNOTs are adjacent.
      #
      # What happens here is that the set of evs is -1, -1, 1, 1 and we can write
      # -╭U- = -A--╭X--SZ--╭X--C-
      # -╰U- = -B--╰C--SX--╰C--D-
      # where SZ and SX are square roots of Z and X respectively. (This
      # decomposition comes from using Hadamards to flip the direction of the
      # first CNOT, and then decomposing them and merging single-qubit gates.) For
      # some reason this case is not handled properly with the full algorithm, so
      # we treat it separately.
  
      sorted_evs = math.sort(math.real(evs))
  
      if math.allclose(sorted_evs, [-1, -1, 1, 1]):
          interior_decomp = [
              qml.CNOT(wires=[wires[1], wires[0]]),
              qml.S(wires=wires[0]),
              qml.SX(wires=wires[1]),
              qml.CNOT(wires=[wires[1], wires[0]]),
          ]
  
          # S \otimes SX
          inner_matrix = S_SX
      else:
          # For the non-special case, the eigenvalues come in conjugate pairs.
          # We need to find two non-conjugate eigenvalues to extract the angles.
          x = math.angle(evs[0])
          y = math.angle(evs[1])
  
          # If it was the conjugate, grab a different eigenvalue.
          if math.allclose(x, -y):
              y = math.angle(evs[2])
  
          delta = (x + y) / 2
          phi = (x - y) / 2
  
          interior_decomp = [
              qml.CNOT(wires=[wires[1], wires[0]]),
              qml.RZ(delta, wires=wires[0]),
              qml.RX(phi, wires=wires[1]),
              qml.CNOT(wires=[wires[1], wires[0]]),
          ]
  
          RZd = qml.RZ(math.cast_like(delta, 1j), wires=0).matrix()
          RXp = qml.RX(phi, wires=0).matrix()
          inner_matrix = math.kron(RZd, RXp)
  
      # We need the matrix representation of this interior part, V, in order to
      # decompose U = (A \otimes B) V (C \otimes D)
      V = math.dot(
          math.cast_like(CNOT10, U),
          math.dot(inner_matrix, math.cast_like(CNOT10, U)),
      )
  
      # Now we find the A, B, C, D in SU(2), and return the decomposition
      A, B, C, D = _extract_su2su2_prefactors(U, V)
  
      A_ops = one_qubit_decomposition(A, wires[0])
      B_ops = one_qubit_decomposition(B, wires[1])
      C_ops = one_qubit_decomposition(C, wires[0])
      D_ops = one_qubit_decomposition(D, wires[1])
  
      return C_ops + D_ops + interior_decomp + A_ops + B_ops
  
file_path: pennylane/pennylane/ops/op_math/decompositions/two_qubit_unitary.py
imports: import numpy
  import pennylane
  from pennylane import math
  from .single_qubit_unitary import one_qubit_decomposition
label_desc: Use image node_id 7 for calling a global function with example usage: _decomposition_2_cnots(U, wires) and returns: unknown