Welcome to Cadabra Q&A, where you can ask questions and receive answers from other members of the community.
+2 votes

I want to compute ${\rm trace}(\phi\psi- \psi\phi)^2$. The answer is $2\phi\psi\phi\psi-2\phi^2\psi^2$.

So how can I do this in Cadabra?

I have declared $\phi,\psi$ to be matrices. I am not giving them ImplicitIndices.

I tried using complete(), by defining a rule, to give the trace cyclic symmetries but that does not work. It is not using the condition. So probably I am using the wrong function.

I thought of using the young tableau symmetries to define the indices of $\phi\psi$ but that gives symmetries to a specific tensor rather than the indices themselves. So cant be used in a product.

Is there a quick way to implement the trace in Cadabra. I have a very long expression I want to take the trace of?

asked in General questions by (170 points)
edited by

2 Answers

0 votes

Not perfect... but helpful.

A time ago I was trying something related to your question. After a while of looking on the web (and asking... just like you!) I came out with the following: define a circular function.

Let $a$ and $b$ be noncommuting, but distributable

{a,b}::NonCommuting.
{a,b}::Distributable.
def post_process(ex):
    expand_power(ex)
    distribute(ex)  

I define the function

def isCircular(arr1, arr2):
    return arr1 in arr2+' '+arr2

and a expression to test

expr := (a + b)**2;

The trick is now to convert this to a string, split it, and compare term by term if they are circular. NOTE: blank spaces before and after the plus sign inside the split method.

list = str(expr)
list = str(expr).split(' + ')
list;

for i in range(len(list)):
    for j in range(i+1,len(list)):
        if isCircular( list[i], list[j]):
            list[j] = list[i]
list;

Then, convert it back to a cadabra expression to finally simplify. NOTE: the newexpr is initalised as an empty expression, it is not a single double quote, but double single quotes.

newexpr = '';
for word in list:
    newexpr = newexpr + ' + ' + word    
;
cab_expr = Ex(newexpr)
collect_terms(cab_expr);

I tried something like expr := (a b + b a)**2; and the result is almost there! It could be a starting point!!!

Cheers.

answered by (5.9k points)
+1 vote

The current version on github handles this:

{\phi,\psi}::ImplicitIndex;
tr{#}::Trace;
ex:= tr( (\phi\psi - \psi\phi)**2 );
expand_power(_)
distribute(_)
sort_product(_);

produces your answer. Thanks to Connor Behan for providing the patch that makes this work.

answered by (52.7k points)
...