code: def eigvals(
      op: qml.operation.Operator, k=1, which="SA"
  ) -> TensorLike:
      r"""The eigenvalues of one or more operations.
  
      .. note::
  
          For a :class:`~.SparseHamiltonian` object, the eigenvalues are computed with the efficient
          ``scipy.sparse.linalg.eigsh`` method which returns :math:`k` eigenvalues. The default value
          of :math:`k` is :math:`1`. For an :math:`N \times N` sparse matrix, :math:`k` must be
          smaller than :math:`N - 1`, otherwise ``scipy.sparse.linalg.eigsh`` fails. If the requested
          :math:`k` is equal or larger than :math:`N - 1`, the regular ``qml.math.linalg.eigvalsh``
          is applied on the dense matrix. For more details see the ``scipy.sparse.linalg.eigsh``
          `documentation <https://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.linalg.eigsh.html#scipy.sparse.linalg.eigsh>`_.
  
      Args:
          op (Operator or QNode or QuantumTape or Callable): A quantum operator or quantum circuit.
          k (int): The number of eigenvalues to be returned for a :class:`~.SparseHamiltonian`.
          which (str): Method for computing the eigenvalues of a :class:`~.SparseHamiltonian`. The
              possible methods are ``'LM'`` (largest in magnitude), ``'SM'`` (smallest in magnitude),
              ``'LA'`` (largest algebraic), ``'SA'`` (smallest algebraic) and ``'BE'`` (:math:`k/2`
              from each end of the spectrum).
  
      Returns:
          TensorLike or qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]:
  
          If an operator is provided as input, the eigenvalues are returned directly in the form of a tensor.
          Otherwise, the transformed circuit is returned as described in :func:`qml.transform <pennylane.transform>`.
          Executing this circuit will provide the eigenvalues as a tensor.
  
      **Example**
  
      Given an operation, ``qml.eigvals`` returns the eigenvalues:
  
      >>> op = qml.PauliZ(0) @ qml.PauliX(1) - 0.5 * qml.PauliY(1)
      >>> qml.eigvals(op)
      array([-1.11803399, -1.11803399,  1.11803399,  1.11803399])
  
      It can also be used in a functional form:
  
      >>> x = torch.tensor(0.6, requires_grad=True)
      >>> eigval_fn = qml.eigvals(qml.RX)
      >>> eigval_fn(x, wires=0)
      tensor([0.9553+0.2955j, 0.9553-0.2955j], grad_fn=<LinalgEigBackward>)
  
      In its functional form, it is fully differentiable with respect to gate arguments:
  
      >>> loss = torch.real(torch.sum(eigval_fn(x, wires=0)))
      >>> loss.backward()
      >>> x.grad
      tensor(-0.2955)
  
      This operator transform can also be applied to QNodes, tapes, and quantum functions
      that contain multiple operations; see Usage Details below for more details.
  
      .. details::
          :title: Usage Details
  
          ``qml.eigvals`` can also be used with QNodes, tapes, or quantum functions that
          contain multiple operations. However, in this situation, **eigenvalues may
          be computed numerically**. This can lead to a large computational overhead
          for a large number of wires.
  
          Consider the following quantum function:
  
          .. code-block:: python3
  
              def circuit(theta):
                  qml.RX(theta, wires=1)
                  qml.PauliZ(wires=0)
  
          We can use ``qml.eigvals`` to generate a new function that returns the eigenvalues
          corresponding to the function ``circuit``:
  
          >>> eigvals_fn = qml.eigvals(circuit)
          >>> theta = np.pi / 4
          >>> eigvals_fn(theta)
          array([ 0.92387953+0.38268343j,  0.92387953-0.38268343j,
                 -0.92387953+0.38268343j, -0.92387953-0.38268343j])
      """
      if not isinstance(op, qml.operation.Operator):
          if not isinstance(
              op, (qml.tape.QuantumScript, qml.QNode)
          ) and not callable(op):
              raise OperationTransformError(
                  "Input is not an Operator, tape, QNode, or quantum function"
              )
          return _eigvals_tranform(op, k=k, which=which)
  
      if isinstance(op, qml.Hamiltonian):
          warnings.warn(
              "For Hamiltonians, the eigenvalues will be computed numerically. "
              "This may be computationally intensive for a large number of wires. "
              "Consider using a sparse representation of the Hamiltonian with qml.SparseHamiltonian.",
              UserWarning,
          )
          return qml.math.linalg.eigvalsh(qml.matrix(op))
  
      if isinstance(op, qml.SparseHamiltonian):
          sparse_matrix = op.sparse_matrix()
          if k < sparse_matrix.shape[0] - 1:
              return scipy.sparse.linalg.eigsh(
                  sparse_matrix, k=k, which=which
              )[0]
          return qml.math.linalg.eigvalsh(sparse_matrix.toarray())
  
      # TODO: make `eigvals` take a `wire_order` argument to mimic `matrix`
      try:
          return op.eigvals()
      except qml.operation.EigvalsUndefinedError:
          return eigvals(op.expand(), k=k, which=which)
  
file_path: pennylane/pennylane/ops/functions/eigvals.py
imports: from typing import Sequence, Callable
  import warnings
  from functools import reduce, partial
  import scipy
  import pennylane
  from pennylane.transforms.op_transforms import OperationTransformError
  from pennylane import transform
  from pennylane.typing import TensorLike
label_desc: Use image node_id 1 for calling a global function with example usage: eigvals(op, k, which) and returns: _eigvals_tranform, qml, qml, op, scipy, eigvals