TensorKit.jl icon indicating copy to clipboard operation
TensorKit.jl copied to clipboard

Autodiff doesn't work for * for AdjointTensorMap

Open Confusio opened this issue 1 year ago • 2 comments

Here is the example:

using TensorKit, Zygote
g(x)=real(scalar(x'*x))
V=Z3Space(0=>2,1=>2,2=>2);
A=randn(ComplexF64,V*V*V',one(V));
gradient(g,A)

Output:

ERROR: MethodError: no method matching *(::ChainRulesCore.Tangent{…}, ::TensorKit.AdjointTensorMap{…})
The function `*` exists, but no method is defined for this combination of argument types.

Confusio avatar Oct 16 '24 05:10 Confusio

Firstly, are you running the latest version of TensorKit ? I tried to run your code on the latest release and it already fails on ''A=randn(ComplexF64,VVV',one(V));'' which makes me doubt this.

So, assuming the latest release. And assuming you're trying to make a vector i.e. Tensor rather than a TensorMap we get :

A=Tensor(randnormal, ComplexF64,V*V*V');

To then answer your question. As far as I know AD methods are implemented for the @tensor macro. So let's rewrite your g(x) function using that :

using TensorKit, Zygote
g(x)=real(scalar(x'*x))
function g_patched(x) 
    return real(@tensor conj(x[1,2,3])*x[1,2,3])
end

which yields the same output.

But works nicely with AD :

V=Z3Space(0=>2,1=>2,2=>2);
A=Tensor(randnormal, ComplexF64,V*V*V');
gradient(g_patched, A)

Admittedly it might be useful to implement Chainrules that make your usecase work as well. Especially since this would be more flexible concerning inputs (I guess this also makes it harder, I haven't looked into it.). This should get you going for now ?

Gertian avatar Oct 16 '24 07:10 Gertian

I use the TensorKit version of [07d1fe3e] TensorKit v1.0.0-DEV ~/.julia/dev/TensorKit. AD works for the @tensor macro; however, it fails with *. Sometimes, we just composite the linear maps. So I think AD for * is also essential.

Confusio avatar Oct 16 '24 08:10 Confusio

Will close this since it is now fixed in the latest releases.

lkdvos avatar Jan 02 '25 09:01 lkdvos