(expr, x)
return retdict
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 import _undetermined_coefficients_match
    >>> from sympy.abc import x
    >>> _undetermined_coefficients_match(9*x*exp(x) + exp(-x), x)
    {'test': True, 'trialset': set([x*exp(x), exp(-x), exp(x)])}
    >>> _undetermined_coefficients_match(log(x), x)
    {'test': False}
r"""
    Returns a trial function match if undetermined coefficients can be applied
    to ``expr``, and ``None`` otherwise.
r Returns a trial function match if undetermined coefficients can be applied to expr and None otherwise .
def _undetermined_coefficients_match(expr, x):
    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 import _undetermined_coefficients_match
    >>> from sympy.abc import x
    >>> _undetermined_coefficients_match(9*x*exp(x) + exp(-x), x)
    {'test': True, 'trialset': set([x*exp(x), exp(-x), exp(x)])}
    >>> _undetermined_coefficients_match(log(x), x)
    {'test': False}

    """
    from sympy import S
    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 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):
                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.
            """
            # I was using the below match, but it doesn't always put all of the
            # coefficient in c.  c.f. 2**x*6*exp(x)*log(2)
            # The below code is probably cleaner anyway.
#            c = Wild('c', exclude=[x])
#            t = Wild('t')
#            r = expr.match(c*t)
            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(set([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

    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).
        retdict['trialset'] = _get_trial_set(expr, x)

    return retdict
def _undetermined_coefficients_match ( expr , x ) : from sympy import S 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 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 ) : 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.
            """ # I was using the below match, but it doesn't always put all of the # coefficient in c.  c.f. 2**x*6*exp(x)*log(2) # The below code is probably cleaner anyway. #            c = Wild('c', exclude=[x]) #            t = Wild('t') #            r = expr.match(c*t) 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 ( set ( [ 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 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). retdict [ 'trialset' ] = _get_trial_set ( expr , x ) return retdict