bsc-quantic / Tenet.jl

Composable Tensor Network library in Julia
https://bsc-quantic.github.io/Tenet.jl/
Apache License 2.0
17 stars 1 forks source link

Adjoint `Tensor` contraction produces incoherent results #40

Closed jofrevalles closed 1 year ago

jofrevalles commented 1 year ago

Summary

The contraction of an adjoint Tensor produces incoherent results with the normal Tensor ones. Specifically, it returns an Array type of data instead of Tensor type. I believe that is also why the PR #39 is failing on some tests.

Example

julia> using Tenet
julia> b = Tensor(rand(2, 2), (:i, :j))
2×2 Tensor{Float64, 2, Matrix{Float64}}:
 0.604068  0.472015
 0.732286  0.0951967
julia> contract(5,b)
2×2 Tensor{Float64, 2, Matrix{Float64}}:
 3.02034  2.36008
 3.66143  0.475984
julia> contract(5,b')
2×2 Matrix{Float64}:
 3.02034  3.66143
 2.36008  0.475984

I believe that this is a problem with the adjoint Tensor not being a Tensor type:

julia> using Tenet
julia> b = Tensor(rand(2, 2), (:i, :j))
julia> b' isa Tensor
false
jofrevalles commented 1 year ago

@mofeing Do you agree that adjoint(a::Tensor) should also be a Tensor?

mofeing commented 1 year ago

Nice catch. Add a test for this pls.

@mofeing Do you agree that adjoint(a::Tensor) should also be a Tensor?

I agree. But it is a little tricky in the sense that not every N-dim array has adjoint defined to it.

The methods should be sth like:

adjoint(t::Tensor{T,2,A}) where {T,A<:AbstractMatrix{T}} = Tensor(adjoint(parent(t)), reverse(labels(t))
adjoint(t::Tensor{T,1,A}) where {T,A<:AbstractVector{T}} = Tensor(conj(parent(t)), labels(t))

The adjoint of a column-vector should not be a row-vector because that info is already encoded on the indices and we would need to create an index with dim=1 (row-vectors have size (1,n)) which would complicate things needlessly.

mofeing commented 1 year ago

@jofrevalles can you check it this continues to be a problem in the new repo Tensors.jl? If not, I will close this issue.

jofrevalles commented 1 year ago

With the last PR this is not a problem anymore:

julia> using Tensors
julia> a = Tensor(rand(Complex{Float64}, 2, 2), (:i, :j));
julia> b = adjoint(a)
2×2 Tensor{ComplexF64, 2, Matrix{ComplexF64}}:
 0.798311-0.698864im  0.314514-0.77349im
 0.562423-0.160019im  0.986719-0.297658im
julia> b isa Tensor
true
julia> b.labels
(:i, :j)
julia> contract(a, b)
0-dimensional Tensor{ComplexF64, 0, Array{ComplexF64, 0}}:
3.2270577277410437 + 0.0im