Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/src/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ When releasing a new version, move the "Unreleased" changes to a new version sec
and the right virtual leg of `mpo[end]` and contracted the two — which at length 1 is the *same*
tensor, so it returned `O * O` on twice the physical space instead of `O`.
([#484](https://github.com/QuantumKitHub/MPSKit.jl/pull/484))
- `make_time_mpo` with `TaylorCluster` on a Hamiltonian whose virtual bond dimension varies along
the chain. The loopback step labels rows by the left virtual bond and columns by the right one, but deleted the absorbed "three-level" rows and columns using the *right*-bond linear index for both. When the two bonds differ in size this deletes the wrong rows, leaving spurious rows behind and removing valid ones, so the resulting time-evolution MPO was wrong. Rows and columns are now derived from their own bond, and the removal happens in a single pass after all loopback contributions have been accumulated instead of inside the loop that still reads those entries.
([#511](https://github.com/QuantumKitHub/MPSKit.jl/pull/511))

### Performance

Expand Down
52 changes: 44 additions & 8 deletions src/algorithms/timestep/taylorcluster.jl
Original file line number Diff line number Diff line change
Expand Up @@ -130,21 +130,57 @@ function _taylor_loopback!(mpo, virtual_sz, linds, ::Val{N}, τ::Number) where {
V_right = virtual_sz[i + 1]
linds_right = linds[i + 1]
cinds_right = CartesianIndices(linds_right)
for b in cinds_right[2:end]
all(in((1, V_right)), b.I) || continue

b_lin = linds_right[b]
a = count(==(V_right), b.I)
threelevel_linds_right = _get_threelevel_linds(V_right, linds_right)
for c in threelevel_linds_right
c_cart = cinds_right[c]
a = count(==(V_right), c_cart.I)
factor = τ^a * factorial(N - a) / factorial(N)
slice[:, 1, 1, 1] = slice[:, 1, 1, 1] + factor * slice[:, 1, 1, b_lin]
for I in nonzero_keys(slice)
(I[1] == b_lin || I[4] == b_lin) && delete!(slice, I)
end
slice[:, 1, 1, 1] = slice[:, 1, 1, 1] + factor * slice[:, 1, 1, c]
end
end
_remove_threelevels!(mpo, virtual_sz, linds)
return mpo
end

function _get_threelevel_linds(virtual_sz, linds)
row_threelevels_linds = Int[]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have to allocate this before running over it? Is it not easier to just inline this function into the loop?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[edit] I see you need this below

for c in CartesianIndices(linds)
c_lin = linds[c]
cI = c.I
all(in((1, virtual_sz)), cI) && !all(==(1), cI) && push!(row_threelevels_linds, c_lin)
end
return row_threelevels_linds
end

# removes the rows and columns that are labled by level-labels made up of 1 and "3" only, but not all 1's.
function _remove_threelevels!(mpo, virtual_sz, linds)
for (i, slice) in enumerate(parent(mpo))
# three-level rows
row_threelevel_linds = _get_threelevel_linds(virtual_sz[i], linds[i])

# three-level columns
col_threelevel_linds = _get_threelevel_linds(virtual_sz[i + 1], linds[i + 1])

# build the set of all CartesianIndices in a three-level row or column
d1, _, _, d4 = size(slice)
threelevel_cinds = Set{CartesianIndex{4}}()
for r in row_threelevel_linds
union!(threelevel_cinds, CartesianIndices((r:r, 1:1, 1:1, 1:d4)))
end
for c in col_threelevel_linds
union!(threelevel_cinds, CartesianIndices((1:d1, 1:1, 1:1, c:c)))
end

# remove the nonzero entries that fall in a three-level row or column
# this avoids a lot of misses wrt looping over all nonzero_keys
for I in intersect(nonzero_keys(slice), threelevel_cinds)
delete!(slice, I)
end
end
return
end

# Algorithm 2: collapse rows and columns that are equivalent under the
# permutation symmetry of the Taylor expansion.
function _taylor_remove_equivalents!(mpo, virtual_sz, linds)
Expand Down
Loading