code: def test_solve_discrete_are_grad():
      a, b, q, r = (
          np.array([[4, 3], [-4.5, -3.5]]),
          np.array([[1], [-1]]),
          np.array([[9, 6], [6, 4]]),
          np.array([[1]]),
      )
      a, b, q, r = (x.astype(config.floatX) for x in [a, b, q, r])
  
      rng = np.random.default_rng(utt.fetch_seed())
  
      # TODO: Is there a "theoretically motivated" value to use here? I pulled 1e-4 out of a hat
      atol = 1e-4 if config.floatX == "float32" else 1e-12
  
      utt.verify_grad(
          functools.partial(
              solve_discrete_are, enforce_Q_symmetric=True
          ),
          pt=[a, b, q, r],
          rng=rng,
          abs_tol=atol,
      )
  
imports: import functools
  import itertools
  import numpy
  import pytest
  import scipy
  import pytensor
  from pytensor import function, grad
  from pytensor import tensor
  from pytensor.configdefaults import config
  from pytensor.tensor.slinalg import Cholesky, CholeskySolve, Solve, SolveBase, SolveTriangular, block_diag, cho_solve, cholesky, eigvalsh, expm, kron, solve, solve_continuous_lyapunov, solve_discrete_are, solve_discrete_lyapunov, solve_triangular
  from pytensor.tensor.type import dmatrix, matrix, tensor, vector
  from tests import unittest_tools
label_desc: Use image node_id 20 for calling a global function with example usage: test_solve_discrete_are_grad() without return types