1
- """
2
- Rewrite of the function
3
- `DataStructures.root_union!(s::IntDisjointSet{T}, x::T, y::T) where {T<:Integer}`.
4
- """
5
- function _introot_union! (s:: DataStructures.IntDisjointSets , x, y; left_root= true )
6
- parents = s. parents
7
- rks = s. ranks
8
- @inbounds xrank = rks[x]
9
- @inbounds yrank = rks[y]
10
- if ! left_root
11
- x, y = y, x
12
- end
13
- @inbounds parents[y] = x
14
- s. ngroups -= 1
15
- return x
16
- end
17
-
18
- """
19
- Rewrite of the function `DataStructures.root_union!(s::DisjointSet{T}, x::T, y::T)`.
20
- The difference is that in the output of `_root_union!`, x is guaranteed to be the root of y when
21
- setting `left_root=true`, and y will be the root of x when setting `left_root=false`.
22
- In `DataStructures.root_union!`, the root value cannot be specified.
23
- A specified root is useful in functions such as `_remove_deltas`, where when we union two
24
- indices into one disjointset, we want the index that is the outinds if the given tensor network
25
- to always be the root in the DisjointSets.
26
- """
27
- function _root_union! (s:: DisjointSets , x, y; left_root= true )
28
- return s. revmap[_introot_union! (s. internal, s. intmap[x], s. intmap[y]; left_root= true )]
29
- end
30
-
31
- """
32
- Partition the input network containing both `tn` and `deltas` (a vector of delta tensors)
33
- into two partitions, one adjacent to source_inds and the other adjacent to other external
34
- inds of the network.
35
- """
36
- function _binary_partition (
37
- tn:: ITensorNetwork , deltas:: Vector{ITensor} , source_inds:: Vector{<:Index}
38
- )
39
- all_tensors = [Vector {ITensor} (tn)... , deltas... ]
40
- external_inds = noncommoninds (all_tensors... )
1
+ function _binary_partition (tn:: ITensorNetwork , source_inds:: Vector{<:Index} )
2
+ external_inds = noncommoninds (Vector {ITensor} (tn)... )
41
3
# add delta tensor to each external ind
42
4
external_sim_ind = [sim (ind) for ind in external_inds]
5
+ tn = map_data (t -> replaceinds (t, external_inds => external_sim_ind), tn; edges= [])
6
+ tn_wo_deltas = rename_vertices (v -> v[1 ], subgraph (v -> v[2 ] == 1 , tn))
7
+ deltas = Vector {ITensor} (subgraph (v -> v[2 ] == 2 , tn))
43
8
new_deltas = [
44
9
delta (external_inds[i], external_sim_ind[i]) for i in 1 : length (external_inds)
45
10
]
46
- deltas = map (t -> replaceinds (t, external_inds => external_sim_ind), deltas)
47
11
deltas = [deltas... , new_deltas... ]
48
- tn = map_data (t -> replaceinds (t, external_inds => external_sim_ind), tn; edges = [] )
12
+ tn = disjoint_union (tn_wo_deltas, ITensorNetwork (deltas) )
49
13
p1, p2 = _mincut_partition_maxweightoutinds (
50
- disjoint_union (tn, ITensorNetwork (deltas)),
51
- source_inds,
52
- setdiff (external_inds, source_inds),
14
+ tn, source_inds, setdiff (external_inds, source_inds)
53
15
)
54
- tn_vs = [v[1 ] for v in p1 if v[2 ] == 1 ]
55
- source_tn = subgraph (tn, tn_vs)
56
- delta_indices = [v[1 ] for v in p1 if v[2 ] == 2 ]
57
- source_deltas = Vector {ITensor} ([deltas[i] for i in delta_indices])
58
- source_tn, source_deltas = _remove_deltas (source_tn, source_deltas)
59
- tn_vs = [v[1 ] for v in p2 if v[2 ] == 1 ]
60
- remain_tn = subgraph (tn, tn_vs)
61
- delta_indices = [v[1 ] for v in p2 if v[2 ] == 2 ]
62
- remain_deltas = Vector {ITensor} ([deltas[i] for i in delta_indices])
63
- remain_tn, remain_deltas = _remove_deltas (remain_tn, remain_deltas)
16
+ source_tn = _contract_deltas (subgraph (tn, p1))
17
+ remain_tn = _contract_deltas (subgraph (tn, p2))
64
18
@assert (
65
- length (noncommoninds (all_tensors... )) == length (
66
- noncommoninds (
67
- Vector {ITensor} (source_tn)... ,
68
- source_deltas... ,
69
- Vector {ITensor} (remain_tn)... ,
70
- remain_deltas... ,
71
- ),
72
- )
73
- )
74
- return source_tn, source_deltas, remain_tn, remain_deltas
75
- end
76
-
77
- """
78
- Given an input tensor network containing tensors in the input `tn`` and
79
- tensors in `deltas``, remove redundent delta tensors in `deltas` and change
80
- inds accordingly to make the output `tn` and `out_deltas` represent the same
81
- tensor network but with less delta tensors.
82
- Note: inds of tensors in `tn` and `deltas` may be changed, and `out_deltas`
83
- may still contain necessary delta tensors.
84
-
85
- ========
86
- Example:
87
- julia> is = [Index(2, "i") for i in 1:6]
88
- julia> a = ITensor(is[1], is[2])
89
- julia> b = ITensor(is[2], is[3])
90
- julia> delta1 = delta(is[3], is[4])
91
- julia> delta2 = delta(is[5], is[6])
92
- julia> tn = ITensorNetwork([a,b])
93
- julia> tn, out_deltas = ITensorNetworks._remove_deltas(tn, [delta1, delta2])
94
- julia> noncommoninds(Vector{ITensor}(tn)...)
95
- 2-element Vector{Index{Int64}}:
96
- (dim=2|id=339|"1")
97
- (dim=2|id=489|"4")
98
- julia> length(out_deltas)
99
- 1
100
- """
101
- function _remove_deltas (tn:: ITensorNetwork , deltas:: Vector{ITensor} )
102
- out_delta_inds = Vector {Pair} ()
103
- network = [Vector {ITensor} (tn)... , deltas... ]
104
- outinds = noncommoninds (network... )
105
- inds_list = map (t -> collect (inds (t)), deltas)
106
- deltainds = collect (Set (vcat (inds_list... )))
107
- ds = DisjointSets (deltainds)
108
- for t in deltas
109
- i1, i2 = inds (t)
110
- if find_root! (ds, i1) in outinds && find_root! (ds, i2) in outinds
111
- push! (out_delta_inds, find_root! (ds, i1) => find_root! (ds, i2))
112
- end
113
- if find_root! (ds, i1) in outinds
114
- _root_union! (ds, find_root! (ds, i1), find_root! (ds, i2))
115
- else
116
- _root_union! (ds, find_root! (ds, i2), find_root! (ds, i1))
117
- end
118
- end
119
- tn = map_data (
120
- t -> replaceinds (t, deltainds => [find_root! (ds, i) for i in deltainds]), tn; edges= []
19
+ length (external_inds) ==
20
+ length (noncommoninds (Vector {ITensor} (source_tn)... , Vector {ITensor} (remain_tn)... ))
121
21
)
122
- out_deltas = Vector {ITensor} ([delta (i. first, i. second) for i in out_delta_inds])
123
- return tn, out_deltas
22
+ return source_tn, remain_tn
124
23
end
125
24
126
25
"""
@@ -143,36 +42,30 @@ function partition(
143
42
@assert _is_rooted_directed_binary_tree (inds_btree)
144
43
output_tns = Vector {ITensorNetwork} ()
145
44
output_deltas_vector = Vector {Vector{ITensor}} ()
146
- # Mapping each vertex of the binary tree to a tn and a vector of deltas
147
- # representing the partition of the subtree containing this vertex and
148
- # its descendant vertices.
45
+ # Mapping each vertex of the binary tree to a tn representing the partition
46
+ # of the subtree containing this vertex and its descendant vertices.
149
47
leaves = leaf_vertices (inds_btree)
150
48
root = _root (inds_btree)
151
- v_to_subtree_tn_deltas = Dict {vertextype(inds_btree),Tuple } ()
152
- v_to_subtree_tn_deltas [root] = (tn, Vector {ITensor} ())
49
+ v_to_subtree_tn = Dict {vertextype(inds_btree),ITensorNetwork } ()
50
+ v_to_subtree_tn [root] = disjoint_union (tn, ITensorNetwork ())
153
51
for v in pre_order_dfs_vertices (inds_btree, root)
154
- @assert haskey (v_to_subtree_tn_deltas, v)
155
- input_tn, input_deltas = v_to_subtree_tn_deltas[v]
156
- if is_leaf (inds_btree, v)
157
- push! (output_tns, input_tn)
158
- push! (output_deltas_vector, input_deltas)
159
- continue
52
+ @assert haskey (v_to_subtree_tn, v)
53
+ input_tn = v_to_subtree_tn[v]
54
+ if ! is_leaf (inds_btree, v)
55
+ c1, c2 = child_vertices (inds_btree, v)
56
+ descendant_c1 = pre_order_dfs_vertices (inds_btree, c1)
57
+ indices = [inds_btree[l] for l in intersect (descendant_c1, leaves)]
58
+ tn1, input_tn = _binary_partition (input_tn, indices)
59
+ v_to_subtree_tn[c1] = tn1
60
+ descendant_c2 = pre_order_dfs_vertices (inds_btree, c2)
61
+ indices = [inds_btree[l] for l in intersect (descendant_c2, leaves)]
62
+ tn1, input_tn = _binary_partition (input_tn, indices)
63
+ v_to_subtree_tn[c2] = tn1
160
64
end
161
- c1, c2 = child_vertices (inds_btree, v)
162
- descendant_c1 = pre_order_dfs_vertices (inds_btree, c1)
163
- indices = [inds_btree[l] for l in intersect (descendant_c1, leaves)]
164
- tn1, deltas1, input_tn, input_deltas = _binary_partition (
165
- input_tn, input_deltas, indices
166
- )
167
- v_to_subtree_tn_deltas[c1] = (tn1, deltas1)
168
- descendant_c2 = pre_order_dfs_vertices (inds_btree, c2)
169
- indices = [inds_btree[l] for l in intersect (descendant_c2, leaves)]
170
- tn1, deltas1, input_tn, input_deltas = _binary_partition (
171
- input_tn, input_deltas, indices
172
- )
173
- v_to_subtree_tn_deltas[c2] = (tn1, deltas1)
174
- push! (output_tns, input_tn)
175
- push! (output_deltas_vector, input_deltas)
65
+ tn = rename_vertices (u -> u[1 ], subgraph (u -> u[2 ] == 1 , input_tn))
66
+ deltas = Vector {ITensor} (subgraph (u -> u[2 ] == 2 , input_tn))
67
+ push! (output_tns, tn)
68
+ push! (output_deltas_vector, deltas)
176
69
end
177
70
# In subgraph_vertices, each element is a vector of vertices to be
178
71
# grouped in one partition.
0 commit comments