Skip to content

BP gauge for graph tensor network state#17

Merged
xuanzhaogao merged 4 commits into
mainfrom
dev
Jul 3, 2025
Merged

BP gauge for graph tensor network state#17
xuanzhaogao merged 4 commits into
mainfrom
dev

Conversation

@xuanzhaogao
Copy link
Copy Markdown
Collaborator

@xuanzhaogao xuanzhaogao commented Jul 1, 2025

What is done:

  1. implementation of a graph tensor network state
  2. bp on graph tn state
  3. gauge with bp messages

What is not done:

  1. simple update and practical simulations

@xuanzhaogao xuanzhaogao requested a review from GiggleLiu July 1, 2025 17:52
@xuanzhaogao xuanzhaogao assigned GiggleLiu and unassigned GiggleLiu Jul 1, 2025
@xuanzhaogao
Copy link
Copy Markdown
Collaborator Author

Another problem: numerical instablity is observed, see #15

Copy link
Copy Markdown

@GiggleLiu GiggleLiu left a comment

Choose a reason for hiding this comment

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

Very good. If you could add more comments or docstrings in the code, that would be perfect.

Comment thread test/bp.jl
Comment thread src/ansatz.jl
Comment thread src/ansatz.jl Outdated
@@ -0,0 +1,89 @@
# the tensor network ansatz, |ket>
struct TensorNetworkAnsatz{TA, TB}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Any constraints on TA and TB?

Comment thread src/bp.jl
end
end

struct BPStep
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Please add more descriptions to data structures to improved code readability.

Comment thread src/ansatz.jl
g::SimpleGraph{Int} # g is used to store the connections between the tensors
site_tensors::Vector{TA} # the tensors are stored as vector of arrays, corresponding to vertices of the graph. The virtual bounds are in order of its neighbors, the last dimension is the open dimension
gauge_tensors::Vector{TB} # corresponding to edges of the graph, listed in the order of edges(g), and enforce e.src < e.dst, real valued diagonal matrices
gauge_tensors_map::Dict{Tuple{Int, Int}, Int} # maps between the edge and the index of the gauge tensor
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

From tutorial perspective, I think maybe using SimpleEdge instead of Tuple{Int, Int} is easier for others to understand.

Comment thread src/utils.jl Outdated
return g
end

function chain(n::Int)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Check Graphs.path_graph.

Comment thread src/utils.jl

# codes about constructing the einsum expression

function all_eins(g::SimpleGraph{Int}, count::Int)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bad design. Better not use count, which is a contextual information, as an argument. When I have a similar need of generating new indices, I usually pass an index store object to this function, e.g. https://github.com/CodingThrust/SimpleTDVP.jl/blob/fb946b589dc094b02587154d96efc8bc1ea99ec6/src/utils.jl#L1

Comment thread src/utils.jl
# 2:d + 1 are indices of the virtual indices of T
# d + 2:2d + 1 are indices of the virtual indices of T*
d = length(nebis)
T_ids = [2:d+1..., 1]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Consider using index store, which is concepturely easier.

Comment thread src/utils.jl Outdated
Comment on lines +120 to +122
for i in eachindex(D)
(abs(D[i]) < 10 * eps(T)) && (D[i] = 10 * eps(T))
end
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
for i in eachindex(D)
(abs(D[i]) < 10 * eps(T)) && (D[i] = 10 * eps(T))
end
D .= max.(D, 10 * eps(T))

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

fixed

Comment thread src/utils.jl Outdated
# need to consider the pseudoinverse if D contains 0
sqrt_D = sqrt.(D)
sqrt_M = U * diagm(sqrt_D)
sqrt_M_inv = diagm([!iszero(d) ? inv(d) : zero(typeof(d)) for d in sqrt_D]) * adjoint(U)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

How can we have zero d? Also, zero(typeof(d)) is equivalent to zero(d).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It is possible, since in some cases the ansatz is low ranked. For example, the boundary site of a chain with d_virtual > d_physical.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

But you have line 120-122. It will remove zero entries.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Oh I forgot about that. 127 acutally is a pesudoinverse, but it does not work. I will remove that.

@GiggleLiu
Copy link
Copy Markdown

FYI: The checklist of open source software: openjournals/joss-reviews#5700 (comment)

@xuanzhaogao
Copy link
Copy Markdown
Collaborator Author

Revised according to most of the comments.
I will merge the PR first for demo.

@xuanzhaogao xuanzhaogao merged commit 0e637df into main Jul 3, 2025
3 checks passed
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.

2 participants