Drop Length 1 Index in ITensors

What’s the canonical way to drop length 1 Indices in ITensors? Specifically, I for tensor train algorithms, it is convenient to have order-3 tensors on both ends, but with the first and last index being of length 1. Is there convenient in-place way to drop these dimensions?

Example

i1 = Index(1, "i1")
i2 = Index(10, "i1")
A = ITensor(rand(1, 10), (i1, i2))

# how to drop `i1` in-place?

Good question. Mostly what we are recommending to users is that they just contract with a (dimension 1) vector to remove unwanted indices. Even though this does more work than is necessary, it’s usually not a bottleneck in most applications. So like

D = A * onehot(i1=>1)

Alternatively, you could use the following function drop_ones to do it:

using ITensors

function drop_ones(A::ITensor)
  one_inds = findall(isone,dim.(inds(A))) # dim==1 index locations
  d_inds = setdiff(1:order(A),i1s) # locations of > 1 indices
  a = dropdims(array(A);dims=tuple(one_inds...)) # remove dim==1 axes
  return ITensor(a,inds(A)[d_inds])
end

let
  i1 = Index(1, "i1")
  i2 = Index(10, "i2")
  A = ITensor(rand(1, 10), (i1, i2))

  D = drop_ones(A)
  @show D

  return
end
2 Likes

Thanks! Love ITensors btw. Carrying around named indices really makes working with tensors a breeze. Compared to macro solutions, it’s much easier to build on top of it.

2 Likes

Glad you’re finding it so useful! We do think the index system really pays off over time.

1 Like