Hi everyone,
I have defined a custom Hilbert space to describe particles with arbitrary spin S and introduced general expressions for the spin operators S_x, S_y and S_z.
I am now struggling to implement as a custom ITensor operator the projector P_m=|m\rangle \langle m| on the state |m\rangle of the computational basis (i.e. S_z |m\rangle = m |m\rangle). P_m is simply a matrix whose m-th diagonal element is 1, while the rest is 0.
Ideally, I would like to define a general operator with a parameter m, so that I can easily vary it for each element of the computational basis. This would greatly simplify the calculation of the corresponding expectation value at each site of the chain.
I have also another question regarding the site type âQuditâ and the definition of arbitrary operators. For example, a^\dagger is defined as
function op(::OpName"Adag", ::SiteType"Qudit", d::Int)
mat = zeros(d, d)
for k in 1:(d - 1)
mat[k + 1, k] = âk
end
return mat
end
but what is the meaning of d? Once the qudit site type has been defined, then it is possible to call the operator without specifying the dimension, e.g.
To answer the first part of your question, you can define an op overload which takes custom keyword arguments then pass these keywords through a call to the top level op function. Here is some example code:
using ITensors
function ITensors.op(::OpName"Proj",::SiteType"S=1/2";m=1)
M = zeros(2,2)
M[m,m] = 1.0
return M
end
let
s = siteind("S=1/2")
P1 = op("Proj",s;m=1)
P2 = op("Proj",s;m=2)
@show P1
@show P2
return
end
Notice above how my custom overload ITensors.op(::OpName"Proj",::SiteType"S=1/2";m=1) takes the m keyword argument then I pass m through the call to op in the main code below.
Regarding your other question about the "Qudit " site type, the purpose of the d::Int argument is so that our system internally can pass the dimension of the site to the op functions. Without it, they would not have the information needed to make the correct size matrix to return. This information gets automatically read off from the size of the Index passed to the op function at the user level, so you donât have to pass it yourself (answering your questions about how itâs possible to call op without manually specifying the dimension yourself - that information is already contained in sites[5] in your example). You can just think of it as a required extra argument that all op overloads for the âQuditâ site type are required to have for internal, developer-level reasons.
Hi Miles,
Thanks for the help and your detailed answer.
Now I want to compute the expectation value of each projection operator P_m with respect to a random state. For the qudit case I was thinking of something of this kind
using ITensors
function ITensors.op(::OpName"Proj", ::SiteType"Qudit", d::Int; m=1)
M = zeros(d,d)
M[m,m] = 1.0
return M
end
let
N=4
d=5
s = siteinds("Qudit", N, dim=d)
psi_init=randomMPS(s, 10)
P2=op("Proj", s[3]; m=2)
for idxm in 1:d
@show expect(psi_init, "Proj"; m=idxm)
end
return
end
but for each idxm I get the same results. I was wondering if there is a way to pass the parameter m directly in the expect function, without having to overload every time the definition of the projector.
Thanks!
Currently the expect function doesnât forward its keyword arguments to the op function inside, which I think we have good reasons for doing (mainly that not all of the op overloads accept keywords).
So a different solution that could work well for you is to use the version of expect that takes a Julia Matrix as input rather than the name (string) of an operator.
So for example:
for idxm in 1:d
Pi = zeros(d,d)
Pi[idxm,idxm] = 1.0
@show expect(psi_init,Pi)
end