code: def exacteig(
      A: LinearOperator,
      neig: int,
      mode: str,
      M: Optional[LinearOperator],
  ) -> Tuple[torch.Tensor, torch.Tensor]:
      """
      Eigendecomposition using explicit matrix construction.
      No additional option for this method.
  
      Examples
      --------
      >>> import torch
      >>> import numpy as np
      >>> from deepchem.utils.differentiation_utils import LinearOperator
      >>> A = LinearOperator.m(torch.rand(2, 2))
      >>> neig = 2
      >>> mode = "lowest"
      >>> M = None
      >>> evals, evecs = exacteig(A, neig, mode, M)
      >>> evals.shape
      torch.Size([2])
      >>> evecs.shape
      torch.Size([2, 2])
  
      Parameters
      ----------
      A: LinearOperator
          Linear operator to be diagonalized. Shape: ``(*BA, q, q)``.
      neig: int
          Number of eigenvalues and eigenvectors to be calculated.
      mode: str
          Mode of the eigenvalues to be calculated (``"lowest"``, ``"uppest"``)
      M: Optional[LinearOperator] (default None)
          The overlap matrix. If None, identity matrix is used. Shape: ``(*BM, q, q)``.
  
      Returns
      -------
      evals: torch.Tensor
          Eigenvalues of the linear operator.
      evecs: torch.Tensor
          Eigenvectors of the linear operator.
  
      Warnings
      --------
      * As this method construct the linear operators explicitly, it might requires
        a large memory.
  
      """
      Amatrix = A.fullmatrix()  # (*BA, q, q)
      if M is None:
          # evals, evecs = torch.linalg.eigh(Amatrix, eigenvectors=True)  # (*BA, q), (*BA, q, q)
          evals, evecs = degen_symeig.apply(Amatrix)  # (*BA, q, q)
          return _take_eigpairs(evals, evecs, neig, mode)
      else:
          Mmatrix = M.fullmatrix()  # (*BM, q, q)
  
          # M decomposition to make A symmetric
          # it is done this way to make it numerically stable in avoiding
          # complex eigenvalues for (near-)degenerate case
          L = torch.linalg.cholesky(Mmatrix)  # (*BM, q, q)
          Linv = torch.inverse(L)  # (*BM, q, q)
          LinvT = Linv.transpose(-2, -1).conj()  # (*BM, q, q)
          A2 = torch.matmul(
              Linv, torch.matmul(Amatrix, LinvT)
          )  # (*BAM, q, q)
  
          # calculate the eigenvalues and eigenvectors
          # (the eigvecs are normalized in M-space)
          # evals, evecs = torch.linalg.eigh(A2, eigenvectors=True)  # (*BAM, q, q)
          evals, evecs = degen_symeig.apply(A2)  # (*BAM, q, q)
          evals, evecs = _take_eigpairs(
              evals, evecs, neig, mode
          )  # (*BAM, neig) and (*BAM, q, neig)
          evecs = torch.matmul(LinvT, evecs)
          return evals, evecs
  
file_path: deepchem/deepchem/utils/differentiation_utils/symeig.py
imports: import torch
  from typing import Optional, Sequence, Tuple, Union
  from deepchem.utils.differentiation_utils import LinearOperator
  import functools
  from deepchem.utils.pytorch_utils import tallqr, to_fortran_order
  from deepchem.utils.differentiation_utils import get_bcasted_dims
label_desc: Use image node_id 1 for calling a global function with example usage: exacteig(A, neig, mode, M) and returns: _take_eigpairs, evals,  evecs