Skip to content
This repository has been archived by the owner on Sep 12, 2023. It is now read-only.

Change labels for the conj of a Tensor #13

Open
jofrevalles opened this issue Apr 3, 2023 · 4 comments
Open

Change labels for the conj of a Tensor #13

jofrevalles opened this issue Apr 3, 2023 · 4 comments

Comments

@jofrevalles
Copy link
Member

Summary

The conjugate of a Tensor returns the conjugated data but the labels are not changed.
This can be a problem if we want to partially contract a Tensor with its conjugate along a set of indices, since it will assume that the not-contracted indices are the same. Instead, I would suggest that a conjugate of a Tensor should have different labels for the indices, and we could specify how to do the contraction in contract (similar like OMEinsum does).

Example

I would expect here that the contraction using ein from OMEinsum and contract are equivalent and return a Matrix. Instead, contract returns a one-dimensional Tensor:

julia> using Tenet; using OMEinsum
julia> ψ = rand(MatrixProductState{Open}, 16, 2, 8)
TensorNetwork{MatrixProductState{Open}}(#tensors=16, #inds=31)
julia> ϕ = canonicalize(ψ, 8)
TensorNetwork{MatrixProductState{Open}}(#tensors=16, #inds=31)
julia> A = tensors(ϕ, 3)
4×8×2 Tensor{Float64, 3, Tensor{Float64, 3, Array{Float64, 3}}} ...

julia> ein"ijk,ilk->jl"(A, conj(A))
8×8 Matrix{Float64}:
  1.0           1.88736e-16  -5.18883e-17   7.96737e-17   4.55119e-17   8.11426e-17   9.05258e-17  -2.42104e-16
  1.88736e-16   1.0          -1.24729e-16   6.9704e-17   -9.5709e-17    1.38493e-16  -1.15753e-16   9.93998e-17
 -5.18883e-17  -1.24729e-16   1.0          -4.28209e-17  -1.86243e-16  -6.10515e-17   7.70803e-17   1.09875e-16
  7.96737e-17   6.9704e-17   -4.28209e-17   1.0           4.127e-17     7.7117e-17   -3.30114e-17  -2.96137e-16
  4.55119e-17  -9.5709e-17   -1.86243e-16   4.127e-17     1.0           9.96209e-17   1.93268e-17   8.23654e-17
  8.11426e-17   1.38493e-16  -6.10515e-17   7.7117e-17    9.96209e-17   1.0           2.74511e-16   1.37748e-16
  9.05258e-17  -1.15753e-16   7.70803e-17  -3.30114e-17   1.93268e-17   2.74511e-16   1.0           9.30275e-17
 -2.42104e-16   9.93998e-17   1.09875e-16  -2.96137e-16   8.23654e-17   1.37748e-16   9.30275e-17   1.0

julia> Tenet.contract(A, conj(A), (labels(A)[1], labels(A)[3]))
8-element Tensor{Float64, 1, Vector{Float64}}:
 0.999999999999999
 0.999999999999999
 0.9999999999999998
 1.0
 0.9999999999999994
 0.9999999999999998
 1.0
 1.0
@mofeing
Copy link
Member

mofeing commented Apr 3, 2023

I don't agree with this. conj(A) is the conjugate of A and should not replace the labels of it. This is the correct result because you're trying the following to contract A with its conjugate (which should be a scalar) but you're only contracting left and physical inds(i.e.lrp,lrp->rr). As you leave the right inds untouched but they have the same name, it is treated as if you extract the diagonal of the target matrix that you're looking for (i.e. rr->r).

You should call replace after conj to replace the name of the right index.

Tenet.contract(A, replace(conj(A), labels(A)[2] => :new_ind_name), (labels(A)[1], labels(A)[3]))

@jofrevalles
Copy link
Member Author

In all tensor contraction functions I used, if you don't specify that the index is being contracted, it is taken as two different indexes. That's the whole purpose of specifying the labels to contract.

You should call replace after conj to replace the name of the right index.

Okay, this can work. Nevertheless, I still think it is not a good idea since we will have to use this always that we specify a set of labels.

@mofeing
Copy link
Member

mofeing commented Apr 3, 2023

In all tensor contraction functions I used, if you don't specify that the index is being contracted, it is taken as two different indexes. That's the whole purpose of specifying the labels to contract.

That's because what you usually pass are arrays but in our case, we already have arrays asociated to a set of indices. Tensors have arrays and labels, that's why you don't specify the indices to contract. It's already implicit.

Okay, this can work. Nevertheless, I still think it is not a good idea since we will have to use this always that we specify a set of labels.

We can discuss this after holidays, but the way other libraries follow does not convince me.

@jofrevalles
Copy link
Member Author

Continuing with the discussion, I believe that the line:

julia> Tenet.contract(A, conj(A), (labels(A)[1], labels(A)[3]))

where A is a three-dimensional Tensor, should already do replace(conj(A), labels(A)[2] => :new_ind_name), since that is why we specify the labels. Another possibility is to change the labels for the conjugate of a Tensor (which I think makes sense for a Tensor in a TensorNetwork) and then link the indices to contract.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants