code: def _decomposition_3_cnots(U, wires):
      r"""The most general form of this decomposition is U = (A \otimes B) V (C \otimes D),
      where V is as depicted in the circuit below:
       -╭U- = -C--╭X--RZ(d)--╭C---------╭X--A-
       -╰U- = -D--╰C--RY(b)--╰X--RY(a)--╰C--B-
      """
  
      # First we add a SWAP as per v1 of arXiv:0308033, which helps with some
      # rearranging of gates in the decomposition (it will cancel out the fact
      # that we need to add a SWAP to fix the determinant in another part later).
      swap_U = np.exp(1j * np.pi / 4) * math.dot(
          math.cast_like(SWAP, U), U
      )
  
      # Choose the rotation angles of RZ, RY in the two-qubit decomposition.
      # They are chosen as per Proposition V.1 in quant-ph/0308033 and are based
      # on the phases of the eigenvalues of :math:`E^\dagger \gamma(U) E`, where
      #    \gamma(U) = (E^\dag U E) (E^\dag U E)^T.
      # The rotation angles can be computed as follows (any three eigenvalues can be used)
      u = math.dot(Edag, math.dot(swap_U, E))
      gammaU = math.dot(u, math.T(u))
      evs, _ = math.linalg.eig(gammaU)
  
      angles = [math.angle(ev) for ev in evs]
  
      # We will sort the angles so that results are consistent across interfaces.
      # This step is skipped when using JAX-JIT, because it cannot sort without making the
      # magnitude of the angles concrete. This does not impact the validity of the resulting
      # decomposition, but may result in a different decompositions for jitting vs not.
      if not qml.math.is_abstract(U):
          angles = math.sort(angles)
  
      x, y, z = angles[0], angles[1], angles[2]
  
      # Compute functions of the eigenvalues; there are different options in v1
      # vs. v3 of the paper, I'm not entirely sure why. This is the version from v3.
      alpha = (x + y) / 2
      beta = (x + z) / 2
      delta = (z + y) / 2
  
      # This is the interior portion of the decomposition circuit
      interior_decomp = [
          qml.CNOT(wires=[wires[1], wires[0]]),
          qml.RZ(delta, wires=wires[0]),
          qml.RY(beta, wires=wires[1]),
          qml.CNOT(wires=wires),
          qml.RY(alpha, wires=wires[1]),
          qml.CNOT(wires=[wires[1], wires[0]]),
      ]
  
      # We need the matrix representation of this interior part, V, in order to
      # decompose U = (A \otimes B) V (C \otimes D)
      #
      # Looking at the decomposition above, V has determinant -1 (because there
      # are 3 CNOTs, each with determinant -1). The relationship between U and V
      # requires that both are in SU(4), so we add a SWAP after to V. We will see
      # how this gets fixed later.
      #
      # -╭V- = -╭X--RZ(d)--╭C---------╭X--╭SWAP-
      # -╰V- = -╰C--RY(b)--╰X--RY(a)--╰C--╰SWAP-
  
      RZd = qml.RZ(math.cast_like(delta, 1j), wires=wires[0]).matrix()
      RYb = qml.RY(beta, wires=wires[0]).matrix()
      RYa = qml.RY(alpha, wires=wires[0]).matrix()
  
      V_mats = [
          CNOT10,
          math.kron(RZd, RYb),
          CNOT01,
          math.kron(math.eye(2), RYa),
          CNOT10,
          SWAP,
      ]
  
      V = math.convert_like(math.eye(4), U)
  
      for mat in V_mats:
          V = math.dot(math.cast_like(mat, U), V)
  
      # Now we need to find the four SU(2) operations A, B, C, D
      A, B, C, D = _extract_su2su2_prefactors(swap_U, V)
  
      # At this point, we have the following:
      # -╭U-╭SWAP- = --C--╭X-RZ(d)-╭C-------╭X-╭SWAP--A
      # -╰U-╰SWAP- = --D--╰C-RZ(b)-╰X-RY(a)-╰C-╰SWAP--B
      #
      # Using the relationship that SWAP(A \otimes B) SWAP = B \otimes A,
      # -╭U-╭SWAP- = --C--╭X-RZ(d)-╭C-------╭X--B--╭SWAP-
      # -╰U-╰SWAP- = --D--╰C-RZ(b)-╰X-RY(a)-╰C--A--╰SWAP-
      #
      # Now the SWAPs cancel, giving us the desired decomposition
      # (up to a global phase).
      # -╭U- = --C--╭X-RZ(d)-╭C-------╭X--B--
      # -╰U- = --D--╰C-RZ(b)-╰X-RY(a)-╰C--A--
  
      A_ops = one_qubit_decomposition(A, wires[1])
      B_ops = one_qubit_decomposition(B, wires[0])
      C_ops = one_qubit_decomposition(C, wires[0])
      D_ops = one_qubit_decomposition(D, wires[1])
  
      # Return the full decomposition
      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 8 for calling a global function with example usage: _decomposition_3_cnots(U, wires) and returns: unknown