Usage of the dag function

Hi, dear developers

When I read the tutorials, I was confused about the usage of the dag function. For example, dag(T::ITensor; allow_alias = true). By default, an alias of the ITensor is returned (i.e. the output ITensor may share data with the input ITensor). If allow_alias = false , an alias is never returned. However, I can not understand the meaning of alias.

I tested the following code:

using ITensors

i = Index(2,"index_i");
j = Index(2,"index_j");
A = randomITensor(ComplexF64,i,j)
B = dag(A; allow_alias = true)
C = dag(A; allow_alias = false)


A[1,1]=1
@show A==B	
@show A==C

The results are two false. Like the tutorial says, B should be an alias for A. Why did I change A, but B stayed the same?

Thank you for your patience, I would be very grateful for any suggestions. I am looking to to hearing from you.
Regards,
Y.D.Shen.

dag applies a complex conjugate, so B/C would always change from A as it is complex data

Consider the real version with A = randomITensor(Float64,i,j)

A == B = true
A == C = false
false

which may be the behavior you are thinking of?

1 Like

Thank you for the quick reply!
Of course, the result you’ve achieved is more in keeping with the concept of alias in the tutorial. So, when we use the dag function, the alias of an ITensor can only be generated if its elements are all real numbers? If an ITensor contains complex numbers, its alias does not exist. Right?

If the tensor is real and allow_alias=true, dag returns an alias (view) of the original tensor, while if allow_alias=false, it returns a copy.

If the tensor is complex, no matter what it returns a copy (with the elements complex conjugated).

The goal is to allow users to avoid unnecessary copies of the data, if they know that is safe to do in their code.

1 Like

Thanks a lot!!

For some more background, note that the default behavior allow_alias=true is the same as Julia’s conj function when called on Array:

julia> x = randn(2, 2)
2×2 Matrix{Float64}:
  1.19278   -0.0609294
 -0.116113   1.63441

julia> y = conj(x)
2×2 Matrix{Float64}:
  1.19278   -0.0609294
 -0.116113   1.63441

julia> x[1, 1] = 2
2

julia> y
2×2 Matrix{Float64}:
  2.0       -0.0609294
 -0.116113   1.63441

So I added the option allow_alias=false for ITensor objects to provide more memory safety, when that is desired. The issue it is solving is that if a user knows they want to write a code like:

x = randn(2, 2) # or `randn(ComplexF64, 2, 2)`
y = conj(x)
y[1, 1] = 2

but they never want x to be modified, the only way to do that in Julia is either:

x = randn(2, 2) # or `randn(ComplexF64, 2, 2)`
y = conj(copy(x)) # Unnecessary copy in the complex case
y = isreal(x) ? copy(x) : conj(x) # Annoying to write
y[1, 1] = 2

allow_alias=false basically automatically handles the logic isreal(x) ? copy(x) : conj(x) for you.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.