Repository: sympy/sympy
File: sympy/matrices/matrixbase.py (Python)

Code before:
            for j in range(self.cols):
                if self[i, j]:
                    yield (i, j), self[i, j]

    def _eval_atoms(self, *types):
        values = self.values()
        if len(values) < self.rows * self.cols and isinstance(S.Zero, types):
            s = {S.Zero}
        else:
            s = set()
        return s.union(*[v.atoms(*types) for v in values])

    def _eval_free_symbols(self):
        return set().union(*(i.free_symbols for i in set(self.values())))

    def _eval_has(self, *patterns):
        return any(a.has(*patterns) for a in self.iter_values())

    def _eval_is_symbolic(self):
        return self.has(Symbol)

    # _eval_is_hermitian is called by some general SymPy
    # routines and has a different *args signature.  Make
    # sure the names don't clash by adding `_matrix_` in name.
    def _eval_is_matrix_hermitian(self, simpfunc):
        herm = lambda i, j: simpfunc(self[i, j] - self[j, i].transpose().conjugate()).is_zero
        return fuzzy_and(herm(i, j) for (i, j), v in self.iter_items())

    def _eval_is_zero_matrix(self):
        return fuzzy_and(v.is_zero for v in self.iter_values())

    def _eval_is_Identity(self) -> FuzzyBool:
        one = self.one
        zero = self.zero
        ident = lambda i, j, v: v is one if i == j else v is zero
        return all(ident(i, j, v) for (i, j), v in self.iter_items())

    def _eval_is_diagonal(self):
        return fuzzy_and(v.is_zero for (i, j), v in self.iter_items() if i != j)

    def _eval_is_lower(self):
        return all(v.is_zero for (i, j), v in self.iter_items() if i < j)

    def _eval_is_upper(self):
        return all(v.is_zero for (i, j), v in self.iter_items() if i > j)

    def _eval_is_lower_hessenberg(self):
        return all(v.is_zero for (i, j), v in self.iter_items() if i + 1 < j)

    def _eval_is_upper_hessenberg(self):
        return all(v.is_zero for (i, j), v in self.iter_items() if i > j + 1)

Review comment (suggestion):
In https://github.com/sympy/sympy/pull/27422 we discussed that transpose shouldn't propagate to matrix entries. Therefore this might not work in general, I believe. Instead I propose using adjoint directly.
```suggestion
        herm = lambda i, j: simpfunc(self[i, j] - self[j, i].adjoint()).is_zero
```

Code after:
            for j in range(self.cols):
                if self[i, j]:
                    yield (i, j), self[i, j]

    def _eval_atoms(self, *types):
        values = self.values()
        if len(values) < self.rows * self.cols and isinstance(S.Zero, types):
            s = {S.Zero}
        else:
            s = set()
        return s.union(*[v.atoms(*types) for v in values])

    def _eval_free_symbols(self):
        return set().union(*(i.free_symbols for i in set(self.values())))

    def _eval_has(self, *patterns):
        return any(a.has(*patterns) for a in self.iter_values())

    def _eval_is_symbolic(self):
        return self.has(Symbol)

    # _eval_is_hermitian is called by some general SymPy
    # routines and has a different *args signature.  Make
    # sure the names don't clash by adding `_matrix_` in name.
    def _eval_is_matrix_hermitian(self, simpfunc):
        herm = lambda i, j: simpfunc(self[i, j] - self[j, i].adjoint()).is_zero
        return fuzzy_and(herm(i, j) for (i, j), v in self.iter_items())

    def _eval_is_zero_matrix(self):
        return fuzzy_and(v.is_zero for v in self.iter_values())

    def _eval_is_Identity(self) -> FuzzyBool:
        one = self.one
        zero = self.zero
        ident = lambda i, j, v: v is one if i == j else v is zero
        return all(ident(i, j, v) for (i, j), v in self.iter_items())

    def _eval_is_diagonal(self):
        return fuzzy_and(v.is_zero for (i, j), v in self.iter_items() if i != j)

    def _eval_is_lower(self):
        return all(v.is_zero for (i, j), v in self.iter_items() if i < j)

    def _eval_is_upper(self):
        return all(v.is_zero for (i, j), v in self.iter_items() if i > j)

    def _eval_is_lower_hessenberg(self):
        return all(v.is_zero for (i, j), v in self.iter_items() if i + 1 < j)

    def _eval_is_upper_hessenberg(self):
        return all(v.is_zero for (i, j), v in self.iter_items() if i > j + 1)