(expr, assumptions)
return MatMul(*newargs)
>>> from sympy import MatrixSymbol, Q, assuming, refine
    >>> X = MatrixSymbol('X', 2, 2)
    >>> expr = X * X.T
    >>> print(expr)
    X*X'
    >>> with assuming(Q.orthogonal(X)):
    ...     print(refine(expr))
    I
>>> from sympy import MatrixSymbol, Q, assuming, refine
    >>> X = MatrixSymbol('X', 2, 2)
    >>> expr = X * X.T
    >>> print(expr)
    X*X'
    >>> with assuming(Q.orthogonal(X)):
    ...     print(refine(expr))
    I
>>> from sympy import MatrixSymbol Q assuming refine >>> X = MatrixSymbol ( X 2 2 ) >>> expr = X * X . T >>> print ( expr ) X * X >>> with assuming ( Q . orthogonal ( X )) : ... print ( refine ( expr )) I
def refine_MatMul(expr, assumptions):
    """
    >>> from sympy import MatrixSymbol, Q, assuming, refine
    >>> X = MatrixSymbol('X', 2, 2)
    >>> expr = X * X.T
    >>> print(expr)
    X*X'
    >>> with assuming(Q.orthogonal(X)):
    ...     print(refine(expr))
    I
    """
    newargs = []
    last = expr.args[0]
    for arg in expr.args[1:]:
        if arg == last.T and ask(Q.orthogonal(arg), assumptions):
            last = Identity(arg.shape[0])
        elif arg == last.conjugate() and ask(Q.unitary(arg), assumptions):
            last = Identity(arg.shape[0])
        else:
            newargs.append(last)
            last = arg
    newargs.append(last)

    return MatMul(*newargs)
def refine_MatMul ( expr , assumptions ) : newargs = [ ] last = expr . args [ 0 ] for arg in expr . args [ 1 : ] : if arg == last . T and ask ( Q . orthogonal ( arg ) , assumptions ) : last = Identity ( arg . shape [ 0 ] ) elif arg == last . conjugate ( ) and ask ( Q . unitary ( arg ) , assumptions ) : last = Identity ( arg . shape [ 0 ] ) else : newargs . append ( last ) last = arg newargs . append ( last ) return MatMul ( * newargs )