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

    expr = expr_ij*a_i*a_j or expr_0 or expr_i*a_i

    where all the a_i are noncommuting symbols in basis and the expr's

    are commuting expressions then

    bilinear_product(expr) = expr_ij*fct(a_i, a_j)

    bilinear_product(expr_0) = expr_0

    bilinear_product(expr_i*a_i) = expr_i*a_i
If a sympy 'Expr' is of the form:
If a sympy Expr is of the form :
def bilinear_product(expr, fct):
    """
    If a sympy 'Expr' is of the form:

    expr = expr_ij*a_i*a_j or expr_0 or expr_i*a_i

    where all the a_i are noncommuting symbols in basis and the expr's

    are commuting expressions then

    bilinear_product(expr) = expr_ij*fct(a_i, a_j)

    bilinear_product(expr_0) = expr_0

    bilinear_product(expr_i*a_i) = expr_i*a_i
    """

    def bilinear_term(expr, fct):
        if expr.is_zero:
            return expr
        if isinstance(expr, Mul):  # bases in expr
            (coefs, bases) = expr.args_cnc()
            coef = Mul(*tuple(coefs))
            if isinstance(bases[0], Pow):  # base is a_i**2
                args = bases[0].args
                return coef * fct(args[0], args[0])
            elif len(bases) == 1:  # base is a_i
                return expr
            else:  # base is a_i*a_j
                return coef * fct(bases[0], bases[1])
        elif isinstance(expr, Pow):  # expr is a_i*a_i
            args = expr.args
            return fct(args[0], args[0])
        elif isinstance(expr, Symbol):
            return expr
        else:
            raise TypeError('!!!!Cannot compute bilinear_product for ' + str(expr) + '!!!!\n')

    expr = expand(expand(expr))

    if not isinstance(expr, Add):
        return bilinear_term(expr, fct)
    else:
        result = S.Zero
        for term in expr.args:
            tmp = bilinear_term(term, fct)
            result += tmp
        return result
def bilinear_product ( expr , fct ) : def bilinear_term ( expr , fct ) : if expr . is_zero : return expr if isinstance ( expr , Mul ) : # bases in expr ( coefs , bases ) = expr . args_cnc ( ) coef = Mul ( * tuple ( coefs ) ) if isinstance ( bases [ 0 ] , Pow ) : # base is a_i**2 args = bases [ 0 ] . args return coef * fct ( args [ 0 ] , args [ 0 ] ) elif len ( bases ) == 1 : # base is a_i return expr else : # base is a_i*a_j return coef * fct ( bases [ 0 ] , bases [ 1 ] ) elif isinstance ( expr , Pow ) : # expr is a_i*a_i args = expr . args return fct ( args [ 0 ] , args [ 0 ] ) elif isinstance ( expr , Symbol ) : return expr else : raise TypeError ( '!!!!Cannot compute bilinear_product for ' + str ( expr ) + '!!!!\n' ) expr = expand ( expand ( expr ) ) if not isinstance ( expr , Add ) : return bilinear_term ( expr , fct ) else : result = S . Zero for term in expr . args : tmp = bilinear_term ( term , fct ) result += tmp return result