Combining arrray of ITensors with a new index

Hi,

I have an array of ITensors with the same indices: ts = [t1, t2, t3, ...]. I would like to combine them into a new ITensor with one added index, which indexes into the ITensors in the array, e.g. ts * onehot(i => 1) is equal to t1. Is there a good way to do this without converting all of the ITensors into arrays and then using the usual ITensor(arr, finds, newind)?

Thank you!

Interesting question. Here’s a code pattern that will do this for you, using the onehot function:

N = length(ts)
i = Index(N,"i")
its = [ts[n] * onehot(i=>n) for n=1:N]

Does that do what you want?

(Fyi, In the future we plan to add better “slicing” capabilities to ITensor that will also do something like the reverse of this (set i to different values and obtain the resulting tensors without needing to do contractions).)

Hi Miles,

Thank you for the response. This works for me, though I have to sum over the final array of tensors to get the final combined tensor:

N = length(ts)
i = Index(N,"i")
its = [ts[n] * onehot(i=>n) for n=1:N]
combined = sum(its)

Better slicing capabilities would be great!

Thank you!

Oh I see, you wanted them summed together. That makes sense. For that I would just recommend using a for loop, like this:

N = length(ts)
i = Index(N,"i")
combined = ITensor()
for n=1:N
   combined += ts[n] * onehot(i=>n)
end

Another way to write that loop code would be:

combined = sum(n->ts[n]*onehot(i=>n),1:N)

Neither of the above makes an array of ITensors first, so might be a little bit cleaner and faster. Definitely slicing (in the future) would be the best of all. In a slicing system, one could make the combined tensor first then add all of the ts’s into it, without having to do separate allocations and contractions of the intermediates. So it would be faster and shorter code.

Great, I’m going to go with:

combined = sum(n -> ts[n] * onehot(i => n), eachindex(ts))

Thank you for the help!

1 Like

Nice solution!