Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add evolve! for evolution of an MPS with an MPO #264

Merged
merged 18 commits into from
Nov 29, 2024

Conversation

jofrevalles
Copy link
Member

@jofrevalles jofrevalles commented Nov 27, 2024

Summary

This PR enhances the evolve! to handle the evolution of an MPS with an MPO in different canonical forms. Additionally, it includes new test cases to verify the correctness of the evolution functions.

  • Maybe fix code so the output indices are always like the input mps. This way things are easier to check if works properly.
  • Refactor and regroup some code so new canonical Forms do not need to change the evolve! funciton, but just extend it as they need.
  • Add more tests for variable maxdim, threshold? I don't know.

@starsfordummies Please take a look and tell me what do you think!

Also we should take a look at issue #238 (which asks to extend mixed_canonize! so it dispatches on Form). So if we already have an mps that is in MixedCanonical, there is no need to do the full sweep if we just want to change the ortogonality center.

Example

julia> using Tenet; using Test

julia> ψ = MPS([rand(2, 2), rand(2, 2, 2), rand(2, 2, 2), rand(2, 2, 2), rand(2, 2)]); normalize!(ψ)
MPS (inputs=0, outputs=5)

julia> mpo = rand(MPO; n=5, maxdim=4)
MPO (inputs=5, outputs=5)

julia> ϕ_1 = evolve!(canonize(ψ), mpo)
MPS (inputs=0, outputs=5)

julia> ϕ_2 = evolve!(mixed_canonize!(ψ, Site(3)), mpo)
MPS (inputs=0, outputs=5)

julia> size.(ϕ_1)
9-element Vector{Tuple{Int64, Vararg{Int64}}}:
 (2,)
 (2, 2, 4)
 (2, 2)
 (2,)
 (4, 2, 2)
 (2, 2)
 (4,)
 (4, 2, 4)
 (4,)

julia> function create_replacements(ϕ_1_sites::Dict, ϕ_2_sites::Dict) # Function to reindex the output tensor
           # Ensure the keys match in both dictionaries
           if keys(ϕ_1_sites) != keys(ϕ_2_sites)
               throw(ArgumentError("Keys of the dictionaries do not match."))
           end

           # Create a list of replacements
           replacements = [(ϕ_2_sites[key] => ϕ_1_sites[key]) for key in keys(ϕ_1_sites)]

           return replacements
       end
create_replacements (generic function with 1 method)

julia> t1 = contract(ϕ_1)
2×2×2×2×2 Tensor{Float64, 5, Array{Float64, 5}}: ...

julia> t2 = replace(contract(ϕ_2), create_replacements(Quantum(ϕ_1).sites, Quantum(ϕ_2).sites)...)
2×2×2×2×2 Tensor{Float64, 5, Array{Float64, 5}}: ...

julia> @test t1  t2
Test Passed

Copy link

codecov bot commented Nov 28, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 80.47%. Comparing base (0ba1707) to head (4b7bdaf).
Report is 10 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #264      +/-   ##
==========================================
+ Coverage   79.59%   80.47%   +0.88%     
==========================================
  Files          32       34       +2     
  Lines        2068     2182     +114     
==========================================
+ Hits         1646     1756     +110     
- Misses        422      426       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

If `threshold` or `maxdim` are not `nothing`, the tensors are truncated after each sweep at the proper value.
"""
function evolve!(ψ::AbstractAnsatz, mpo::AbstractMPO; threshold=nothing, maxdim=nothing, normalize=true)
evolve!(form(ψ), ψ, mpo; threshold, maxdim, normalize)
Copy link
Member Author

Choose a reason for hiding this comment

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

@starsfordummies Tomorrow I will add here the replace! so this evolve! function does not change the output indices, after that, we can merge!

@jofrevalles
Copy link
Member Author

@starsfordummies Okay, I added the reset_inded kwarg on evolve! (which defaults to true). If this one is true, the indices after the evolution are reset to the original ones.

For me, this PR is ready to merge.

Copy link
Contributor

@starsfordummies starsfordummies left a comment

Choose a reason for hiding this comment

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

Awesome! If you haven't yet, you could add an evolve() function so that you're not forced to do it inplace, other than that looks great to me!

Copy link
Member

@mofeing mofeing left a comment

Choose a reason for hiding this comment

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

great! thanks! this was very needed

src/Ansatz.jl Outdated Show resolved Hide resolved
Comment on lines +689 to +697
old_norm = norm(ψ)
if isnothing(bond) # Normalize all λ tensors
for i in 1:(nsites(ψ) - 1)
λ = tensors(ψ; between=(Site(i), Site(i + 1)))
replace!(ψ, λ => λ ./ norm(λ)^(1 / (nsites(ψ) - 1)))
replace!(ψ, λ => λ ./ old_norm^(1 / (nsites(ψ) - 1)))
end
else
λ = tensors(ψ; between=bond)
replace!(ψ, λ => λ ./ norm(λ))
replace!(ψ, λ => λ ./ old_norm)
Copy link
Member

Choose a reason for hiding this comment

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

so in reality, there's no need for this because norm(λ) will only be computed once as it already is

Copy link
Member Author

Choose a reason for hiding this comment

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

Nop, you need the norm of the full mps.

Copy link
Member Author

Choose a reason for hiding this comment

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

I already tried that but fails on some truncate tests.

Copy link
Member

Choose a reason for hiding this comment

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

ahh i see the difference now, I thought it was the same norm call

src/MPS.jl Outdated Show resolved Hide resolved
src/MPS.jl Outdated Show resolved Hide resolved
src/MPS.jl Outdated Show resolved Hide resolved
src/MPS.jl Show resolved Hide resolved
src/MPS.jl Outdated
Comment on lines 648 to 657
for i in nsites(ψ):-1:2
canonize_site!(ψ, Site(i); direction=:left, method=:svd)
end

# left-to-right SVD sweep, get left-canonical tensors and singular values and truncate
for i in 1:(nsites(ψ) - 1)
canonize_site!(ψ, Site(i); direction=:right, method=:svd)
(!isnothing(threshold) || !isnothing(maxdim)) &&
truncate!(ψ, [Site(i), Site(i + 1)]; threshold, maxdim, normalize, compute_local_svd=false)
end
Copy link
Member

Choose a reason for hiding this comment

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

I guess you can replace this with mixed_canonize! to the left-most site and reuse the method for MixedCanonical

Suggested change
for i in nsites(ψ):-1:2
canonize_site!(ψ, Site(i); direction=:left, method=:svd)
end
# left-to-right SVD sweep, get left-canonical tensors and singular values and truncate
for i in 1:(nsites(ψ) - 1)
canonize_site!(ψ, Site(i); direction=:right, method=:svd)
(!isnothing(threshold) || !isnothing(maxdim)) &&
truncate!(ψ, [Site(i), Site(i + 1)]; threshold, maxdim, normalize, compute_local_svd=false)
end
mixed_canonize!(ψ, site"1")
truncate_sweep(ψ; threshold, maxdim, normalize)

Copy link
Member Author

Choose a reason for hiding this comment

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

No you can't do this. I specifically created this function because in the Canonical form you do not contract the lambdas but still truncate them. This is different from the other methods.

Copy link
Member

Choose a reason for hiding this comment

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

okay, i want to better understand this but let's merge it and refactor it later (if we need)

Comment on lines +614 to +618
if !isnothing(threshold) || !isnothing(maxdim)
truncate_sweep!(Canonical(), ψ; threshold, maxdim, normalize)
else
normalize && canonize!(ψ; normalize)
end
Copy link
Member

Choose a reason for hiding this comment

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

do you need to normalize if you don't truncate?
also, for this case (i.e. Canonical form) you will canonize 2 times if you truncate and normalize (1 in truncate_sweep for recanonization and another here for normalization)

Suggested change
if !isnothing(threshold) || !isnothing(maxdim)
truncate_sweep!(Canonical(), ψ; threshold, maxdim, normalize)
else
normalize && canonize!(ψ; normalize)
end
if !isnothing(threshold) || !isnothing(maxdim)
truncate_sweep!(Canonical(), ψ; threshold, maxdim, normalize)
normalize && canonize!(ψ; normalize)
end

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't understand this. This is not the case, you don't need to normalize if you already normalize the bond that you truncate.

And yes, you might want to normalize if you don't truncate if the mpo is not unitary and evolves the ψ out of norm.

Copy link
Member

Choose a reason for hiding this comment

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

why would you want to normalize here a TN that it's not already normalized? but ok, I see that both things could be understandable from a semantics point of view

let's merge, discuss on Monday and refactor it if we need

@jofrevalles
Copy link
Member Author

Okay, @mofeing I removed some unnecessary Quantum calls. This is ready to merge.

@mofeing mofeing merged commit 8ac83f4 into master Nov 29, 2024
5 checks passed
@mofeing mofeing deleted the feature/evolve-mps-with-mpo branch November 29, 2024 13:41
jofrevalles added a commit that referenced this pull request Dec 2, 2024
* Add evolve! function for an MPS with an MPO

* Add tests for MPS-MPO evolution

* Remove unnecessary @show

* Add comment

* Fix kwarg handling on truncate! function

* Fix normalize! for Canonical form and small fixes on evolve! with MPO

* Extend evolve!(mps, mpo) tests

* Format code

* Remove unnecessary kwarg

* Refactor code so it is easier to extend for other canonical forms

* Fix comment

* Enhance tests

* Add reset_index kwarg

* Update tests

* Format code

* Remove unnecessary Quantum functions, add docstring for truncate_sweep!

* Format code

* Remove stale function
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants