45
45
# Iteration
46
46
#
47
47
48
+ # TODO : iteration
49
+
50
+ # TODO : different `map` functionalities as defined for ITensors.AbstractMPS
51
+
52
+ # TODO : broadcasting
53
+
48
54
function union (tn1:: AbstractITensorNetwork , tn2:: AbstractITensorNetwork ; kwargs... )
49
55
tn = ITensorNetwork (union (data_graph (tn1), data_graph (tn2)); kwargs... )
50
56
# Add any new edges that are introduced during the union
104
110
# Convenience wrapper
105
111
itensors (tn:: AbstractITensorNetwork ) = Vector {ITensor} (tn)
106
112
113
+ #
114
+ # Promotion and conversion
115
+ #
116
+
117
+ function LinearAlgebra. promote_leaf_eltypes (tn:: AbstractITensorNetwork )
118
+ return LinearAlgebra. promote_leaf_eltypes (itensors (tn))
119
+ end
120
+
121
+ function ITensors. promote_itensor_eltype (tn:: AbstractITensorNetwork )
122
+ return LinearAlgebra. promote_leaf_eltypes (tn)
123
+ end
124
+
125
+ ITensors. scalartype (tn:: AbstractITensorNetwork ) = LinearAlgebra. promote_leaf_eltypes (tn)
126
+
127
+ # TODO : eltype(::AbstractITensorNetwork) (cannot behave the same as eltype(::ITensors.AbstractMPS))
128
+
129
+ # TODO : mimic ITensors.AbstractMPS implementation using map
130
+ function ITensors. convert_leaf_eltype (eltype:: Type , tn:: AbstractITensorNetwork )
131
+ tn = copy (tn)
132
+ vertex_data (tn) .= convert_eltype .(Ref (eltype), vertex_data (tn))
133
+ return tn
134
+ end
135
+
136
+ # TODO : mimic ITensors.AbstractMPS implementation using map
137
+ function NDTensors. convert_scalartype (eltype:: Type{<:Number} , tn:: AbstractITensorNetwork )
138
+ tn = copy (tn)
139
+ vertex_data (tn) .= ITensors. adapt .(Ref (eltype), vertex_data (tn))
140
+ return tn
141
+ end
142
+
107
143
#
108
144
# Conversion to Graphs
109
145
#
@@ -185,11 +221,13 @@ end
185
221
function replaceinds (tn:: AbstractITensorNetwork , is_is′:: Pair{<:IndsNetwork,<:IndsNetwork} )
186
222
tn = copy (tn)
187
223
is, is′ = is_is′
188
- # TODO : Check that `is` and ` is′` have the same vertices and edges.
224
+ @assert underlying_graph (is) == underlying_graph ( is′)
189
225
for v in vertices (is)
226
+ isassigned (is, v) || continue
190
227
setindex_preserve_graph! (tn, replaceinds (tn[v], is[v] => is′[v]), v)
191
228
end
192
229
for e in edges (is)
230
+ isassigned (is, e) || continue
193
231
for v in (src (e), dst (e))
194
232
setindex_preserve_graph! (tn, replaceinds (tn[v], is[e] => is′[e]), v)
195
233
end
@@ -208,7 +246,7 @@ const map_inds_label_functions = [
208
246
:setprime ,
209
247
:noprime ,
210
248
:replaceprime ,
211
- :swapprime ,
249
+ # :swapprime, # TODO : add @test_broken as a reminder
212
250
:addtags ,
213
251
:removetags ,
214
252
:replacetags ,
@@ -227,6 +265,24 @@ for f in map_inds_label_functions
227
265
function $f (n:: Union{IndsNetwork,AbstractITensorNetwork} , args... ; kwargs... )
228
266
return map_inds ($ f, n, args... ; kwargs... )
229
267
end
268
+
269
+ function $f (
270
+ ffilter:: typeof (linkinds),
271
+ n:: Union{IndsNetwork,AbstractITensorNetwork} ,
272
+ args... ;
273
+ kwargs... ,
274
+ )
275
+ return map_inds ($ f, n, args... ; sites= [], kwargs... )
276
+ end
277
+
278
+ function $f (
279
+ ffilter:: typeof (siteinds),
280
+ n:: Union{IndsNetwork,AbstractITensorNetwork} ,
281
+ args... ;
282
+ kwargs... ,
283
+ )
284
+ return map_inds ($ f, n, args... ; links= [], kwargs... )
285
+ end
230
286
end
231
287
end
232
288
@@ -402,12 +458,19 @@ function factorize(
402
458
return factorize (tn, edgetype (tn)(edge); kwargs... )
403
459
end
404
460
405
- # For ambiguity error
461
+ # For ambiguity error; TODO : decide whether to use graph mutating methods when resulting graph is unchanged?
406
462
function _orthogonalize_edge (tn:: AbstractITensorNetwork , edge:: AbstractEdge ; kwargs... )
407
- tn = factorize (tn, edge; kwargs... )
408
- # TODO : Implement as `only(common_neighbors(tn, src(edge), dst(edge)))`
409
- new_vertex = only (neighbors (tn, src (edge)) ∩ neighbors (tn, dst (edge)))
410
- return contract (tn, new_vertex => dst (edge))
463
+ # tn = factorize(tn, edge; kwargs...)
464
+ # # TODO : Implement as `only(common_neighbors(tn, src(edge), dst(edge)))`
465
+ # new_vertex = only(neighbors(tn, src(edge)) ∩ neighbors(tn, dst(edge)))
466
+ # return contract(tn, new_vertex => dst(edge))
467
+ tn = copy (tn)
468
+ left_inds = uniqueinds (tn, edge)
469
+ ltags = tags (tn, edge)
470
+ X, Y = factorize (tn[src (edge)], left_inds; tags= ltags, ortho= " left" , kwargs... )
471
+ tn[src (edge)] = X
472
+ tn[dst (edge)] *= Y
473
+ return tn
411
474
end
412
475
413
476
function orthogonalize (tn:: AbstractITensorNetwork , edge:: AbstractEdge ; kwargs... )
@@ -429,6 +492,25 @@ function orthogonalize(ψ::AbstractITensorNetwork, source_vertex)
429
492
return ψ
430
493
end
431
494
495
+ # TODO : decide whether to use graph mutating methods when resulting graph is unchanged?
496
+ function _truncate_edge (tn:: AbstractITensorNetwork , edge:: AbstractEdge ; kwargs... )
497
+ tn = copy (tn)
498
+ left_inds = uniqueinds (tn, edge)
499
+ ltags = tags (tn, edge)
500
+ U, S, V = svd (tn[src (edge)], left_inds; lefttags= ltags, ortho= " left" , kwargs... )
501
+ tn[src (edge)] = U
502
+ tn[dst (edge)] *= (S * V)
503
+ return tn
504
+ end
505
+
506
+ function truncate (tn:: AbstractITensorNetwork , edge:: AbstractEdge ; kwargs... )
507
+ return _truncate_edge (tn, edge; kwargs... )
508
+ end
509
+
510
+ function truncate (tn:: AbstractITensorNetwork , edge:: Pair ; kwargs... )
511
+ return truncate (tn, edgetype (tn)(edge); kwargs... )
512
+ end
513
+
432
514
function Base.:* (c:: Number , ψ:: AbstractITensorNetwork )
433
515
v₁ = first (vertices (ψ))
434
516
cψ = copy (ψ)
@@ -572,6 +654,91 @@ function visualize(
572
654
return visualize (Vector {ITensor} (tn), args... ; vertex_labels, kwargs... )
573
655
end
574
656
657
+ #
658
+ # Link dimensions
659
+ #
660
+
661
+ function maxlinkdim (tn:: AbstractITensorNetwork )
662
+ md = 1
663
+ for e in edges (tn)
664
+ md = max (md, linkdim (tn, e))
665
+ end
666
+ return md
667
+ end
668
+
669
+ function linkdim (tn:: AbstractITensorNetwork , edge:: Pair )
670
+ return linkdim (tn, edgetype (tn)(edge))
671
+ end
672
+
673
+ function linkdim (tn:: AbstractITensorNetwork{V} , edge:: AbstractEdge{V} ) where {V}
674
+ ls = linkinds (tn, edge)
675
+ return prod ([isnothing (l) ? 1 : dim (l) for l in ls])
676
+ end
677
+
678
+ function linkdims (tn:: AbstractITensorNetwork{V} ) where {V}
679
+ ld = DataGraph {V,Any,Int} (copy (underlying_graph (tn)))
680
+ for e in edges (ld)
681
+ ld[e] = linkdim (tn, e)
682
+ end
683
+ return ld
684
+ end
685
+
686
+ #
687
+ # Common index checking
688
+ #
689
+
690
+ function hascommoninds (
691
+ :: typeof (siteinds), A:: AbstractITensorNetwork{V} , B:: AbstractITensorNetwork{V}
692
+ ) where {V}
693
+ for v in vertices (A)
694
+ ! hascommoninds (siteinds (A, v), siteinds (B, v)) && return false
695
+ end
696
+ return true
697
+ end
698
+
699
+ function check_hascommoninds (
700
+ :: typeof (siteinds), A:: AbstractITensorNetwork{V} , B:: AbstractITensorNetwork{V}
701
+ ) where {V}
702
+ N = nv (A)
703
+ if nv (B) ≠ N
704
+ throw (
705
+ DimensionMismatch (
706
+ " $(typeof (A)) and $(typeof (B)) have mismatched number of vertices $N and $(nv (B)) ."
707
+ ),
708
+ )
709
+ end
710
+ for v in vertices (A)
711
+ ! hascommoninds (siteinds (A, v), siteinds (B, v)) && error (
712
+ " $(typeof (A)) A and $(typeof (B)) B must share site indices. On vertex $v , A has site indices $(siteinds (A, v)) while B has site indices $(siteinds (B, v)) ." ,
713
+ )
714
+ end
715
+ return nothing
716
+ end
717
+
718
+ function hassameinds (
719
+ :: typeof (siteinds), A:: AbstractITensorNetwork{V} , B:: AbstractITensorNetwork{V}
720
+ ) where {V}
721
+ nv (A) ≠ nv (B) && return false
722
+ for v in vertices (A)
723
+ ! ITensors. hassameinds (siteinds (A, v), siteinds (B, v)) && return false
724
+ end
725
+ return true
726
+ end
727
+
728
+ #
729
+ # Site combiners
730
+ #
731
+
732
+ # TODO : will be broken, fix this
733
+ function site_combiners (tn:: AbstractITensorNetwork{V} ) where {V}
734
+ Cs = DataGraph {V,ITensor} (copy (underlying_graph (tn)))
735
+ for v in vertices (tn)
736
+ s = siteinds (tn, v)
737
+ Cs[v] = combiner (s; tags= commontags (s))
738
+ end
739
+ return Cs
740
+ end
741
+
575
742
# # # TODO : should this make sure that internal indices
576
743
# # # don't clash?
577
744
# # function hvncat(
0 commit comments