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

Implement an MPS method initializing the tensors to identity (copy-tensors) #218

Merged
merged 17 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
24 changes: 24 additions & 0 deletions src/Ansatz/MPS.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,30 @@ function MPS(arrays::Vector{<:AbstractArray}; order=defaultorder(MPS))
return MPS(ansatz, NonCanonical())
end

MPS(arraysdims::NTuple{N,<:Vector{Int}}; order=defaultorder(MPS)) where {N} = MPS(collect(arraysdims); order=order)
MPS(arraysdims::Vector{<:Tuple{Vararg{Int}}}; order=defaultorder(MPS)) = MPS(collect.(arraysdims); order=order)
function MPS(arraysdims::NTuple{N,Tuple{Vararg{Int}}}; order=defaultorder(MPS)) where {N}
return MPS(collect(collect.(arraysdims)); order=order)
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 would currently just delete these methods for now...

Suggested change
MPS(arraysdims::NTuple{N,<:Vector{Int}}; order=defaultorder(MPS)) where {N} = MPS(collect(arraysdims); order=order)
MPS(arraysdims::Vector{<:Tuple{Vararg{Int}}}; order=defaultorder(MPS)) = MPS(collect.(arraysdims); order=order)
function MPS(arraysdims::NTuple{N,Tuple{Vararg{Int}}}; order=defaultorder(MPS)) where {N}
return MPS(collect(collect.(arraysdims)); order=order)
end

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I removed them

function MPS(arraysdims::Vector{<:Vector{Int}}; order=defaultorder(MPS))
Copy link
Member

Choose a reason for hiding this comment

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

I would use Base.identity, not a constructor since you're not passing arrays.

Suggested change
function MPS(arraysdims::Vector{<:Vector{Int}}; order=defaultorder(MPS))
function Base.identity(::Type{MPS}, arraysdims; order=defaultorder(MPS))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was one possibility along with the one @jofrevalles suggested below of using ones. I replaced the constructor by identity as I think it fits better than ones.

@assert length(arraysdims[1]) == 2 "First array must have 2 dimensions"
@assert all(==(3) ∘ length, arraysdims[2:(end - 1)]) "All arrays must have 3 dimensions"
@assert length(arraysdims[end]) == 2 "Last array must have 2 dimensions"
issetequal(order, defaultorder(MPS)) ||
throw(ArgumentError("order must be a permutation of $(String.(defaultorder(MPS)))"))

return MPS(
map(arraysdims) do arrdims
mindim = minimum(arrdims)
arr = zeros(ComplexF64, arrdims...)
deltas = ntuple(x -> ntuple(_ -> x, length(arrdims)), mindim)
broadcast(delta -> arr[delta...] = 1.0, deltas)
arr
end;
order=order,
Todorbsc marked this conversation as resolved.
Show resolved Hide resolved
)
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 would not create another constructor for MPS, since that may be misleading to the user who wants to directly create an MPS with some specific arrays. Instead, you could extend the function ones or one similiar, to make that when we call ones(MPS, arraydims ... ) we get this kind of MPS. Something similar to the things we do with rand.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As I said above, I agree it is better to not implement another constructor. The option that fits the best for me is Base.identity, check it out :)

Copy link
Member

@mofeing mofeing Oct 9, 2024

Choose a reason for hiding this comment

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

Yeah, in general I agree with @jofrevalles but I think ones might be misleading since it could mean you're initializing the MPS to a $\ket{11\dots 1}$ state.

I think identity is better because contracting against another "identity" MPS gives you 1, all the tensors are just COPY-tensors and "identity initialization" is how is known in some packages (it's also known as eye-initialization but eye is how the identity is known on those languages).

function Base.convert(::Type{MPS}, tn::Product)
@assert socket(tn) == State()

Expand Down
3 changes: 1 addition & 2 deletions test/Ansatz_test.jl
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
@testset "Ansatz" begin
end
@testset "Ansatz" begin end
22 changes: 22 additions & 0 deletions test/MPS_test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,28 @@
@test inds(ψ; at=site"3", dir=:left) == inds(ψ; at=site"2", dir=:right) !== nothing
@test all(i -> size(ψ, inds(ψ; at=Site(i))) == 2, 1:nsites(ψ))

dispatch_arraysdims = [
([2, 4], [5, 4, 3], [2, 3]),
[(2, 4), (5, 4, 3), (2, 3)],
((2, 4), (5, 4, 3), (2, 3)),
[[2, 4], [5, 4, 3], [2, 3]],
]
for arraysdims in dispatch_arraysdims
ψ = MPS(arraysdims) # Default order (:o, :l, :r)
@test size(tensors(ψ; at=site"1")) == (2, 4)
@test size(tensors(ψ; at=site"2")) == (5, 4, 3)
@test size(tensors(ψ; at=site"3")) == (2, 3)
t1 = tensors(ψ; at=site"1")
@test t1[1, 1] == t1[2, 2] == 1
@test sum(t1) == 2
t2 = tensors(ψ; at=site"2")
@test t2[1, 1, 1] == t2[2, 2, 2] == t2[3, 3, 3] == 1
@test sum(t2) == 3
t3 = tensors(ψ; at=site"3")
@test t3[1, 1] == t3[2, 2] == 1
@test sum(t3) == 2
end

Copy link
Member

Choose a reason for hiding this comment

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

Wrap this into a @testset

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@testset "Site" begin
ψ = MPS([rand(2, 2), rand(2, 2, 2), rand(2, 2)])

Expand Down
Loading