(F, fct, x)
If a sympy 'Expr' is of the form:

    expr = expr_0*a_1*...*a_n

    where all the a_j are noncommuting symbols in basis then

    product_derivation(expr) = diff(expr_0, x)*a_1*...*a_n
                               + expr_0*(fct(a_1, x)*a_2*...*a_n + ...
                               + a_1*...*a_(i-1)*fct(a_i, x)*a_(i + 1)*...*a_n + ...
                               + a_1*...*a_(n-1)*fct(a_n, x))
If a sympy 'Expr' is of the form:
If a sympy Expr is of the form :
def product_derivation(F, fct, x):
    """
    If a sympy 'Expr' is of the form:

    expr = expr_0*a_1*...*a_n

    where all the a_j are noncommuting symbols in basis then

    product_derivation(expr) = diff(expr_0, x)*a_1*...*a_n
                               + expr_0*(fct(a_1, x)*a_2*...*a_n + ...
                               + a_1*...*a_(i-1)*fct(a_i, x)*a_(i + 1)*...*a_n + ...
                               + a_1*...*a_(n-1)*fct(a_n, x))
    """
    if F.is_commutative:
        return diff(F, x)
    elif isinstance(F, Mul):
        (coefs, bases) = F.args_cnc()
        coef = Mul(*coefs)
        dcoef = diff(coef, x)
        if len(bases) == 1:
            return dcoef * bases[0] + coef * fct(bases[0], x)
        else:
            result = dcoef * Mul(*bases)
            for ib in range(len(bases)):
                result += coef * Mul(*bases[:ib]) * fct(bases[ib], x) * Mul(*bases[ib + 1:])
            return result
    elif isinstance(F, Symbol):
        return fct(F, x)
def product_derivation ( F , fct , x ) : if F . is_commutative : return diff ( F , x ) elif isinstance ( F , Mul ) : ( coefs , bases ) = F . args_cnc ( ) coef = Mul ( * coefs ) dcoef = diff ( coef , x ) if len ( bases ) == 1 : return dcoef * bases [ 0 ] + coef * fct ( bases [ 0 ] , x ) else : result = dcoef * Mul ( * bases ) for ib in range ( len ( bases ) ) : result += coef * Mul ( * bases [ : ib ] ) * fct ( bases [ ib ] , x ) * Mul ( * bases [ ib + 1 : ] ) return result elif isinstance ( F , Symbol ) : return fct ( F , x )