code: def _check_density_matrix(density_matrix):
      """Check the shape, the trace and the positive semi-definitiveness of a matrix."""
      dim = density_matrix.shape[-1]
      if (
          len(density_matrix.shape) not in (2, 3)
          or density_matrix.shape[-2] != dim
          or not np.log2(dim).is_integer()
      ):
          raise ValueError(
              "Density matrix must be of shape (2**N, 2**N) or (batch_dim, 2**N, 2**N)."
          )
  
      if len(density_matrix.shape) == 2:
          density_matrix = qml.math.stack([density_matrix])
  
      if not is_abstract(density_matrix):
          for dm in density_matrix:
              # Check trace
              trace = np.trace(dm)
              if not allclose(trace, 1.0, atol=1e-10):
                  raise ValueError(
                      "The trace of the density matrix should be one."
                  )
  
              # Check if the matrix is Hermitian
              conj_trans = np.transpose(np.conj(dm))
              if not allclose(dm, conj_trans):
                  raise ValueError("The matrix is not Hermitian.")
  
              # Check if positive semi-definite
              evs, _ = qml.math.linalg.eigh(dm)
              evs = np.real(evs)
              evs_non_negative = [ev for ev in evs if ev >= -1e-7]
              if len(evs) != len(evs_non_negative):
                  raise ValueError(
                      "The matrix is not positive semi-definite."
                  )
  
imports: import itertools
  import functools
  from string import ascii_letters
  from autoray import numpy
  from numpy import float64
  import pennylane
  from .None import single_dispatch
  from .multi_dispatch import diag, dot, scatter_element_add, einsum, get_interface
  from .utils import is_abstract, allclose, cast, convert_like, cast_like
  from .matrix_manipulation import _permute_dense_matrix
label_desc: Use image node_id 17 for calling a global function with example usage: _check_density_matrix(density_matrix) without return types