11struct NoExpand <: Algorithm end
22
3- function changebonds_left (AL, Cs, alg; kwargs... )
4- AL, Cs = changebonds (; expand_rightspace = AL, embed_leftspace = Cs, alg, kwargs... )[[2 ,end ]]
5- return AL, Cs
3+ function changebonds_left (AL, C:: AbstractTensorMap , alg; kwargs... )
4+ Anew, Cnew = changebonds_left (AL, (C,), alg; kwargs... )
5+ return Anew, only (Cnew)
6+ end
7+ function changebonds_left (AL, Cs:: Tuple , alg; kwargs... )
8+ ALnew, Csnew = changebonds (; expand_rightspace = AL, embed_leftspace = Cs, alg, kwargs... )[[2 ,end ]]
9+ Csnew = collect (Csnew)
10+ for i in eachindex (Csnew)[1 : 1 ]
11+ @assert ALnew * Csnew[i] ≈ AL * Cs[i] " Error in left embedding is large"
12+ end
13+ return ALnew, Csnew
14+ end
15+
16+ function changebonds_right (C:: AbstractTensorMap , AR, alg; kwargs... )
17+ Cnew, ARnew = changebonds_right ((C,), AR, alg; kwargs... )
18+ return only (Cnew), ARnew
619end
720function changebonds_right (Cs, AR, alg; kwargs... )
8- Cs, AR = changebonds (; expand_leftspace = AR, embed_rightspace = Cs, alg, kwargs... )[[1 ,4 ]]
9- return Cs, AR
21+ Csnew, ARnew = changebonds (; expand_leftspace = AR, embed_rightspace = Cs, alg, kwargs... )[[1 ,4 ]]
22+ Csnew = collect (Csnew)
23+ for i in eachindex (Csnew)[1 : 1 ]
24+ @assert Csnew[i] * ARnew ≈ Cs[i] * AR " Error in right embedding is $(norm (Csnew[i] * ARnew - Cs[i] * AR)) "
25+ end
26+ return Csnew, ARnew
1027end
1128function changebonds (al,c,ar, alg; kwargs... )
12- _, al, c, ar, _ = changebonds (; expand_rightspace = al, expand_leftspace = ar, embed_both = (c,), alg, kwargs... )
13- return al, only (c), ar
29+ _, alnew, cnew, arnew, _ = changebonds (; expand_rightspace = al, expand_leftspace = ar, embed_both = (c,), alg, kwargs... )
30+ @assert alnew * only (cnew) * arnew ≈ al * c * ar " Error in two-site embedding is $(norm (alnew * only (cnew) * arnew - al * c * ar)) "
31+ return alnew, only (cnew), arnew
1432end
1533
1634function changebonds (;
@@ -21,8 +39,8 @@ function changebonds(;
2139 embed_both = missing ,
2240 alg,
2341 ac2 = missing ,
24- expansion_leftspace = ismissing (ac2) ? missing : sup_inf_space (ac2),
25- expansion_rightspace = ismissing (expansion_leftspace) ? (ismissing (ac2) ? missing : sup_inf_space (ac2)) : expansion_leftspace,
42+ expansion_leftspace = missing , # = ismissing(ac2) ? missing : sup_inf_space(ac2),
43+ expansion_rightspace = missing # ismissing(expansion_leftspace) ? (ismissing(ac2) ? missing : sup_inf_space(ac2)) : expansion_leftspace,
2644 )
2745 return changebonds (
2846 embed_rightspace, expand_rightspace,embed_both, expand_leftspace, embed_leftspace, alg;
@@ -36,24 +54,28 @@ function changebonds(
3654 )
3755 if ! ismissing (expand_rightspace)
3856 expand_rightspace_new = _expand_leftisometry (expand_rightspace, alg, expansion_leftspace)
39- if space (expand_rightspace) != space (expand_rightspace_new) || true
57+ if space (expand_rightspace) != space (expand_rightspace_new)
58+ println (" happened1" )
4059 if ! ismissing (embed_leftspace)
41- embed_leftspace = (_embed_left_space (expand_rightspace_new, A, alg ) for A in embed_leftspace)
60+ embed_leftspace = collect (_embed_left_space (expand_rightspace_new, expand_rightspace,A ) for A in embed_leftspace)
4261 end
4362 if ! ismissing (embed_both)
44- embed_both = (_embed_left_space (expand_rightspace_new, A, alg ) for A in embed_both)
63+ embed_both = collect (_embed_left_space (expand_rightspace_new, expand_rightspace, A ) for A in embed_both)
4564 end
65+ else
66+ @assert expand_rightspace ≈ expand_rightspace_new " Error: expand_rightspace is not approximately equal to expand_rightspace_new, but their spaces are the same. This should not happen."
4667 end
4768 expand_rightspace = expand_rightspace_new
4869 end
4970 if ! ismissing (expand_leftspace)
5071 expand_leftspace_new = _expand_rightisometry (expand_leftspace, alg, expansion_rightspace)
51- if space (expand_leftspace) != space (expand_leftspace_new) || true
72+ if space (expand_leftspace) != space (expand_leftspace_new)
73+ println (" happened2" )
5274 if ! ismissing (embed_rightspace)
53- embed_rightspace = (_embed_right_space (A, expand_leftspace_new, alg ) for A in embed_rightspace)
75+ embed_rightspace = collect (_embed_right_space (A,expand_leftspace, expand_leftspace_new ) for A in embed_rightspace)
5476 end
5577 if ! ismissing (embed_both)
56- embed_both = (_embed_right_space (A, expand_leftspace_new, alg ) for A in embed_both)
78+ embed_both = collect (_embed_right_space (A, expand_leftspace, expand_leftspace_new ) for A in embed_both)
5779 end
5880 end
5981 expand_leftspace = expand_leftspace_new
6890function sup_inf_space (ac2)
6991 VL = fuse (space (ac2, 1 ) ⊗ space (ac2, 2 ))
7092 VR = fuse (space (ac2, 3 ) ⊗ space (ac2, 4 ))
93+ @show VL, VR
94+ @show supremum (VL, VR), infimum (VL, VR)
95+ @show supremum (VL, VR) ⊖ infimum (VL, VR)
7196 return supremum (VL, VR) ⊖ infimum (VL, VR)
7297end
7398function _sample_space (space, sup, trscheme)
77102function _expand_leftisometry (A:: MPSTensor , alg, expansion_leftspace)
78103 VL = left_null (A)
79104 V = _sample_space (right_virtualspace (VL), expansion_leftspace, alg. trscheme)
105+ # @show right_virtualspace(VL), expansion_leftspace, V
106+ dim (V) == 0 && return A
80107 XL = randisometry (scalartype (VL), right_virtualspace (VL) ← V)
81- return catdomain (A, VL * XL)
108+ x = catdomain (A, VL * XL)
109+ @tensor I1[right' ; right] := x[phys,left,right] * conj (x[phys,left,right' ])
110+ @assert I1 ≈ one (I1) " I1 is $I1 "
111+ return x
82112end
83113
84114function _expand_rightisometry (A:: MPSTensor , alg, expansion_rightspace)
85115 return _transpose_front (_expand_rightisometry (_transpose_tail (A; copy = true ), alg, expansion_rightspace))
86116end
87117function _expand_rightisometry (AR_tail:: AbstractTensorMap , alg, expansion_rightspace)
88118 VR = right_null (AR_tail)
119+ @tensor overlap[left' ; left] := AR_tail[left,phys,right] * conj (VR[left' ,phys,right])
120+ @assert abs (norm (overlap))< 1e-10 " Error in overlap is $(norm (overlap)) "
121+
89122 V = _sample_space (space (VR, 1 ), expansion_rightspace, alg. trscheme)
123+ dim (V) == 0 && return AR_tail
90124 XR = randisometry (scalartype (VR), space (VR, 1 ) ← V)
91- return catcodomain (AR_tail, XR' * VR)
125+ b = XR' * VR
126+ @tensor I1[left; left' ] := b[left,phys,right] * conj (b[left' ,phys,right])
127+ @assert I1 ≈ one (I1) " Error in b is $(norm (I1 - one (I1))) $(norm (I1)) , $(norm (one (I1))) "
128+
129+ x = catcodomain (AR_tail, b)
130+ x = _transpose_front (x)
131+ @tensor I1[left' ; left] := x[left,phys,right] * conj (x[left' ,phys,right])
132+ @assert I1 ≈ one (I1) " Error is $(norm (I1 - one (I1))) $(norm (I1)) , $(norm (one (I1))) "
133+ return _transpose_tail (x)
92134end
93135
94- function _embed_left_space (A:: MPSTensor , C:: MPSBondTensor , alg)
136+ function _embed_left_space (A:: MPSTensor , C:: MPSBondTensor , alg:: Algorithm )
95137 C′ = similar (C, right_virtualspace (A) ← right_virtualspace (C))
96138 scale! (randn! (C′), alg. noisefactor)
97139 C′ = TensorKit. absorb! (C′, C)
98140 return C′
99141end
100- function _embed_left_space (A:: MPSTensor , Anext:: MPSTensor , alg)
142+ function _embed_left_space (A:: MPSTensor , Anext:: MPSTensor , alg:: Algorithm )
101143 Anext′ = similar (Anext, right_virtualspace (A) ⊗ physicalspace (Anext) ← right_virtualspace (Anext))
102144 scale! (randn! (Anext′), alg. noisefactor)
103145 Anext′ = TensorKit. absorb! (Anext′, Anext)
104146 return Anext′
105147end
106148
107- function _embed_right_space (C:: MPSBondTensor , A:: AbstractTensorMap , alg)
149+ function _embed_right_space (C:: MPSBondTensor , A:: AbstractTensorMap , alg:: Algorithm )
108150 C′ = similar (C, left_virtualspace (C) ← space (A, 1 ))
109151 scale! (randn! (C′), alg. noisefactor)
110152 C′ = TensorKit. absorb! (C′, C)
111153 return C′
112154end
113- function _embed_right_space (Anext:: MPSTensor , A:: AbstractTensorMap , alg)
155+ function _embed_right_space (Anext:: MPSTensor , A:: AbstractTensorMap , alg:: Algorithm )
114156 Anext′ = similar (Anext, left_virtualspace (Anext) ⊗ physicalspace (Anext) ← space (A, 1 ))
115157 scale! (randn! (Anext′), alg. noisefactor)
116158 Anext′ = TensorKit. absorb! (Anext′, Anext)
117159 return Anext′
118160end
119161
162+ function _embed_left_space (A:: MPSTensor , Aold:: MPSTensor , C:: MPSBondTensor )
163+ @tensor C_new[- 1 ; - 2 ] := conj (A[1 ,2 ;- 1 ])* Aold[1 ,2 ;3 ] * C[3 ; - 2 ]
164+ return add_noise (C_new)
165+ end
166+ function _embed_left_space (A:: MPSTensor , Aold:: MPSTensor , C:: MPSTensor )
167+ @tensor C_new[- 1 ,- 2 ; - 3 ] := conj (A[1 ,2 ;- 1 ])* Aold[1 ,2 ;3 ]* C[3 ,- 2 ; - 3 ]
168+ return add_noise (C_new)
169+ end
170+ function _embed_right_space (C:: MPSBondTensor , Aold:: AbstractTensorMap , A:: AbstractTensorMap )
171+ @tensor C_new[- 1 ; - 2 ] := C[- 1 ; 1 ]* Aold[1 ,2 ;3 ]* conj (A[- 2 ,2 ; 3 ])
172+ return add_noise (C_new)
173+ end
174+ function _embed_right_space (C:: MPSTensor , Aold:: AbstractTensorMap , A:: AbstractTensorMap )
175+ @tensor C_new[- 1 ,- 2 ; - 3 ] := C[- 1 ,- 2 ; 1 ]* Aold[1 ,2 ;3 ]* conj (A[- 3 ,2 ; 3 ])
176+ return add_noise (C_new)
177+ end
178+
179+ function add_noise (A:: AbstractTensorMap , noisefactor= eps ()^ (3 / 4 ))
180+ A′ = similar (A)
181+ scale! (randn! (A′), noisefactor)
182+ return A + A′
183+ end
184+
185+
186+
187+
120188
121189extract_sector_types (:: Type{GradedSpace{S,D}} ) where {S<: Sector ,D} = (S,)
122190extract_sector_types (:: Type{GradedSpace{ProductSector{T},D}} ) where {T<: Tuple ,D} = Tuple (T. parameters)
123191extract_sector_types (sp:: GradedSpace ) = extract_sector_types (typeof (sp))
124- function generate_sampling_space (psi:: MPSKit.AbstractMPS ; cutoff:: Integer = 100 , minsize:: Integer = 1 )
192+ function generate_sampling_space (psi:: MPSKit.AbstractMPS ; cutoff:: Integer = 50 , minsize:: Integer = 1 )
125193 sp = physicalspace (psi. AL[1 ])
126194 I = sectortype (sp)
127195 types = extract_sector_types (sp)
@@ -138,29 +206,41 @@ end
138206
139207function constrained_product (iters, cutoff)
140208 N = length (iters)
141-
142- # 1. Materialize the necessary prefixes (0 to cutoff -> cutoff + 1 elements)
209+
210+ # Materialize prefixes up to cutoff (0.. cutoff -> cutoff + 1 elements)
143211 prefixes = [collect (Iterators. take (it, cutoff + 1 )) for it in iters]
212+ cutoff_sq = cutoff^ 2
144213
145- # 2. Lazy generation via Channel
214+ # Generate tuples whose index-vector lies inside an L2 ball (sphere)
215+ # i.e. sum(i.^2) <= cutoff^2. We prune by limiting each coordinate
216+ # to floor(sqrt(remaining_budget_sq)) and to the available prefix length.
146217 return Channel () do channel
147- function recurse (dim, current_sum, current_tuple)
218+ function recurse (dim, current_sqsum, current_tuple)
219+ # available maximum index for this dimension from collected prefix
220+ max_avail = length (prefixes[dim]) - 1
221+ if max_avail < 0
222+ return
223+ end
224+
148225 if dim == N
149- # Remaining budget for the last dimension
150- remaining = cutoff - current_sum
151- for i in 0 : remaining
152- # i+1 because Julia is 1-indexed for array access
153- put! (channel, (current_tuple... , prefixes[dim][i+ 1 ]))
226+ rem_sq = cutoff_sq - current_sqsum
227+ max_i = min (max_avail, floor (Int, sqrt (max (0 , rem_sq))))
228+ if max_i >= 0
229+ for i in 0 : max_i
230+ put! (channel, (current_tuple... , prefixes[dim][i+ 1 ]))
231+ end
154232 end
155233 else
156- # Each index can be anything from 0 up to the remaining budget
157- upper_bound = cutoff - current_sum
158- for i in 0 : upper_bound
159- recurse (dim + 1 , current_sum + i, (current_tuple... , prefixes[dim][i+ 1 ]))
234+ rem_sq = cutoff_sq - current_sqsum
235+ max_i = min (max_avail, cutoff, floor (Int, sqrt (max (0 , rem_sq))))
236+ if max_i >= 0
237+ for i in 0 : max_i
238+ recurse (dim + 1 , current_sqsum + i* i, (current_tuple... , prefixes[dim][i+ 1 ]))
239+ end
160240 end
161241 end
162242 end
163-
243+
164244 recurse (1 , 0 , ())
165245 end
166246end
0 commit comments