code: def _undetermined_coefficients_match(
      expr, x, func=None, eq_homogeneous=S.Zero
  ):
      r"""
      Returns a trial function match if undetermined coefficients can be applied
      to ``expr``, and ``None`` otherwise.
  
      A trial expression can be found for an expression for use with the method
      of undetermined coefficients if the expression is an
      additive/multiplicative combination of constants, polynomials in `x` (the
      independent variable of expr), `\sin(a x + b)`, `\cos(a x + b)`, and
      `e^{a x}` terms (in other words, it has a finite number of linearly
      independent derivatives).
  
      Note that you may still need to multiply each term returned here by
      sufficient `x` to make it linearly independent with the solutions to the
      homogeneous equation.
  
      This is intended for internal use by ``undetermined_coefficients`` hints.
  
      SymPy currently has no way to convert `\sin^n(x) \cos^m(y)` into a sum of
      only `\sin(a x)` and `\cos(b x)` terms, so these are not implemented.  So,
      for example, you will need to manually convert `\sin^2(x)` into `[1 +
      \cos(2 x)]/2` to properly apply the method of undetermined coefficients on
      it.
  
      Examples
      ========
  
      >>> from sympy import log, exp
      >>> from sympy.solvers.ode.nonhomogeneous import _undetermined_coefficients_match
      >>> from sympy.abc import x
      >>> _undetermined_coefficients_match(9*x*exp(x) + exp(-x), x)
      {'test': True, 'trialset': {x*exp(x), exp(-x), exp(x)}}
      >>> _undetermined_coefficients_match(log(x), x)
      {'test': False}
  
      """
      a = Wild("a", exclude=[x])
      b = Wild("b", exclude=[x])
      expr = powsimp(
          expr, combine="exp"
      )  # exp(x)*exp(2*x + 1) => exp(3*x + 1)
      retdict = {}
  
      def _test_term(expr, x):
          r"""
          Test if ``expr`` fits the proper form for undetermined coefficients.
          """
          if not expr.has(x):
              return True
          elif expr.is_Add:
              return all(_test_term(i, x) for i in expr.args)
          elif expr.is_Mul:
              if expr.has(sin, cos):
                  foundtrig = False
                  # Make sure that there is only one trig function in the args.
                  # See the docstring.
                  for i in expr.args:
                      if i.has(sin, cos):
                          if foundtrig:
                              return False
                          else:
                              foundtrig = True
              return all(_test_term(i, x) for i in expr.args)
          elif expr.is_Function:
              if expr.func in (sin, cos, exp, sinh, cosh):
                  if expr.args[0].match(a * x + b):
                      return True
                  else:
                      return False
              else:
                  return False
          elif (
              expr.is_Pow
              and expr.base.is_Symbol
              and expr.exp.is_Integer
              and expr.exp >= 0
          ):
              return True
          elif expr.is_Pow and expr.base.is_number:
              if expr.exp.match(a * x + b):
                  return True
              else:
                  return False
          elif expr.is_Symbol or expr.is_number:
              return True
          else:
              return False
  
      def _get_trial_set(expr, x, exprs=set()):
          r"""
          Returns a set of trial terms for undetermined coefficients.
  
          The idea behind undetermined coefficients is that the terms expression
          repeat themselves after a finite number of derivatives, except for the
          coefficients (they are linearly dependent).  So if we collect these,
          we should have the terms of our trial function.
          """
  
          def _remove_coefficient(expr, x):
              r"""
              Returns the expression without a coefficient.
  
              Similar to expr.as_independent(x)[1], except it only works
              multiplicatively.
              """
              term = S.One
              if expr.is_Mul:
                  for i in expr.args:
                      if i.has(x):
                          term *= i
              elif expr.has(x):
                  term = expr
              return term
  
          expr = expand_mul(expr)
          if expr.is_Add:
              for term in expr.args:
                  if _remove_coefficient(term, x) in exprs:
                      pass
                  else:
                      exprs.add(_remove_coefficient(term, x))
                      exprs = exprs.union(
                          _get_trial_set(term, x, exprs)
                      )
          else:
              term = _remove_coefficient(expr, x)
              tmpset = exprs.union({term})
              oldset = set()
              while tmpset != oldset:
                  # If you get stuck in this loop, then _test_term is probably
                  # broken
                  oldset = tmpset.copy()
                  expr = expr.diff(x)
                  term = _remove_coefficient(expr, x)
                  if term.is_Add:
                      tmpset = tmpset.union(
                          _get_trial_set(term, x, tmpset)
                      )
                  else:
                      tmpset.add(term)
              exprs = tmpset
          return exprs
  
      def is_homogeneous_solution(term):
          r"""This function checks whether the given trialset contains any root
          of homogeneous equation"""
          return expand(
              sub_func_doit(eq_homogeneous, func, term)
          ).is_zero
  
      retdict["test"] = _test_term(expr, x)
      if retdict["test"]:
          # Try to generate a list of trial solutions that will have the
          # undetermined coefficients. Note that if any of these are not linearly
          # independent with any of the solutions to the homogeneous equation,
          # then they will need to be multiplied by sufficient x to make them so.
          # This function DOES NOT do that (it doesn't even look at the
          # homogeneous equation).
          temp_set = set()
          for i in Add.make_args(expr):
              act = _get_trial_set(i, x)
              if eq_homogeneous is not S.Zero:
                  while any(is_homogeneous_solution(ts) for ts in act):
                      act = {x * ts for ts in act}
              temp_set = temp_set.union(act)
  
          retdict["trialset"] = temp_set
      return retdict
  
imports: from collections import defaultdict
  from sympy.core import Add, S
  from sympy.core.function import diff, expand, _mexpand, expand_mul
  from sympy.core.relational import Eq
  from sympy.core.sorting import default_sort_key
  from sympy.core.symbol import Dummy, Wild
  from sympy.functions import exp, cos, cosh, im, log, re, sin, sinh, atan2, conjugate
  from sympy.integrals import Integral
  from sympy.polys import Poly, RootOf, rootof, roots
  from sympy.simplify import collect, simplify, separatevars, powsimp, trigsimp
  from sympy.utilities import numbered_symbols
  from sympy.solvers.solvers import solve
  from sympy.matrices import wronskian
  from .subscheck import sub_func_doit
  from sympy.solvers.ode.ode import get_numbered_constants
label_desc: Use image node_id 6 for calling a global function with example usage: _undetermined_coefficients_match(expr, x, func, eq_homogeneous) and returns: retdict, exprs, expand, True, term, all, all, False, True, True, False, False, True, False, True, False