States
FiniteMPS
A FiniteMPS is - at its core - a chain of mps tensors.
Usage
A FiniteMPS can be created by passing in a vector of tensormaps:
L = 10
data = [rand(ComplexF64, ℂ^1 ⊗ ℂ^2 ← ℂ^1) for _ in 1:L];
state = FiniteMPS(data)10-site FiniteMPS(ComplexF64, TensorKit.ComplexSpace) with maximal dimension 1 and center 21/2:
┌─[10]─ ℂ^2
│ ℂ^1
├─[9]─ ℂ^2
│ ℂ^1
├─[8]─ ℂ^2
│ ℂ^1
├─[7]─ ℂ^2
│ ℂ^1
├─[6]─ ℂ^2
│ ℂ^1
├─[5]─ ℂ^2
│ ℂ^1
├─[4]─ ℂ^2
│ ℂ^1
├─[3]─ ℂ^2
│ ℂ^1
├─[2]─ ℂ^2
│ ℂ^1
└─[1]─ ℂ^2Or alternatively by specifying its structure
max_bond_dimension = ℂ^4
physical_space = ℂ^2
state = FiniteMPS(rand, ComplexF64, L, physical_space, max_bond_dimension)10-site FiniteMPS(ComplexF64, TensorKit.ComplexSpace) with maximal dimension 4 and center 21/2:
┌─[10]─ ℂ^2
│ ℂ^2
├─[9]─ ℂ^2
│ ℂ^4
├─[8]─ ℂ^2
│ ℂ^4
├─[7]─ ℂ^2
│ ℂ^4
├─[6]─ ℂ^2
│ ℂ^4
├─[5]─ ℂ^2
│ ℂ^4
├─[4]─ ℂ^2
│ ℂ^4
├─[3]─ ℂ^2
│ ℂ^4
├─[2]─ ℂ^2
│ ℂ^2
└─[1]─ ℂ^2You can take dot products, renormalize!, expectation values,....
Gauging and canonical forms
An MPS representation is not unique: for every virtual bond we can insert 
There are two particularly convenient choices for the gauge at a site, the so-called left and right canonical form. For the left canonical form, all tensors to the left of a site are gauged such that they become left-isometries. By convention, we call these tensors AL.
al = state.AL[3]
al' * al ≈ id(right_virtualspace(al))trueSimilarly, the right canonical form turns the tensors into right-isometries. By convention, these are called AR.
ar = state.AR[3]
repartition(ar, 1, 2) * repartition(ar, 1, 2)' ≈ id(left_virtualspace(ar))trueIt is also possible to mix and match these two forms, where all tensors to the left of a given site are in the left gauge, while all tensors to the right are in the right gauge. In this case, the final gauge transformation tensor can no longer be absorbed, since that would spoil the gauge either to the left or the right. This center-gauged tensor is called C, which is also the gauge transformation to relate left- and right-gauged tensors. Finally, for convenience it is also possible to leave a single MPS tensor in the center gauge, which we call AC = AL * C
c = state.C[3] # to the right of site 3
c′ = state.C[2] # to the left of site 3
al * c ≈ state.AC[3] ≈ repartition(c′ * repartition(ar, 1, 2), 2, 1)trueThese forms are often used throughout MPS algorithms, and the FiniteMPS object acts as an automatic manager for this. It will automatically compute and cache the different forms, and detect when to recompute whenever needed. For example, in order to compute the overlap of an MPS with itself, we can choose any site and bring that into the center gauge. Since then both the left and right side simplify to the identity, this simply becomes the overlap of the gauge tensors:
d = dot(state, state)
all(c -> dot(c, c) ≈ d, state.C)trueImplementation details
Behind the scenes, a FiniteMPS has 4 fields
ALs::Vector{Union{Missing,A}}
ARs::Vector{Union{Missing,A}}
ACs::Vector{Union{Missing,A}}
Cs::Vector{Union{Missing,B}}and calling AL, AR, C or AC returns lazy views over these vectors that instantiate the tensors whenever they are requested. Similarly, changing a tensor will poison the ARs to the left of that tensor, and the ALs to the right. The idea behind this construction is that one never has to worry about how the state is gauged, as this gets handled automagically.
Warning
While a FiniteMPS can automatically detect when to recompute the different gauges, this requires that one of the tensors is set using an indexing operation. In particular, in-place changes to the different tensors will not trigger the recomputation.
InfiniteMPS
An InfiniteMPS can be thought of as being very similar to a finite mps, where the set of tensors is repeated periodically.
It can also be created by passing in a vector of TensorMaps:
data = [rand(ComplexF64, ℂ^4 ⊗ ℂ^2 ← ℂ^4) for _ in 1:2]
state = InfiniteMPS(data)2-site InfiniteMPS(ComplexF64, TensorKit.ComplexSpace) with maximal dimension 4:
| ⋮
| ℂ^4
├─[2]─ ℂ^2
│ ℂ^4
├─[1]─ ℂ^2
│ ℂ^4
| ⋮or by initializing it from given spaces
phys_spaces = fill(ℂ^2, 2)
virt_spaces = [ℂ^4, ℂ^5] # by convention to the right of a site
state = InfiniteMPS(phys_spaces, virt_spaces)2-site InfiniteMPS(ComplexF64, TensorKit.ComplexSpace) with maximal dimension 5:
| ⋮
| ℂ^5
├─[2]─ ℂ^2
│ ℂ^4
├─[1]─ ℂ^2
│ ℂ^5
| ⋮Note that the code above creates an InfiniteMPS with a two-site unit cell, where the given virtual spaces are located to the right of their respective sites.
Gauging and canonical forms
Much like for FiniteMPS, we can again query the gauged tensors AL, AR, C and AC. Here however, the implementation is much easier, since they all have to be recomputed whenever a single tensor changes. This is a result of periodically repeating the tensors, every AL is to the right of the changed site, and every AR is to the left. As a result, the fields are simply
AL::PeriodicArray{A,1}
AR::PeriodicArray{A,1}
C::PeriodicArray{B,1}
AC::PeriodicArray{A,1}WindowMPS
A WindowMPS or segment MPS can be seen as a mix between an InfiniteMPS and a FiniteMPS. It represents a window of mutable tensors (a finite MPS), embedded in an infinite environment (two infinite MPSs). It can therefore be created accordingly, ensuring that the edges match:
infinite_state = InfiniteMPS(ℂ^2, ℂ^4)
finite_state = FiniteMPS(5, ℂ^2, ℂ^4; left=ℂ^4, right=ℂ^4)
window = WindowMPS(infinite_state, finite_state, infinite_state)WindowMPS{TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}, TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 1, 1, Vector{ComplexF64}}}(InfiniteMPS{TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}, TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 1, 1, Vector{ComplexF64}}}(TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}[TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}(ComplexF64[0.49111764092646637 + 0.4502257908612838im, 0.03813140732194427 - 0.021143286906826143im, 0.018488411652815725 - 0.006419320860172586im, 0.011455442285145697 + 0.0006329506080456414im, 0.4835031730929473 + 0.5495037380863483im, 0.02379206019216925 - 0.09998055393014525im, 0.08218336931438958 + 0.0067906538528803295im, 0.011955046403285778 + 0.021201608856457242im, -0.530301300035086 - 0.43640405955548345im, 0.1719232348177675 - 0.004984862857304763im … 0.07301534124904852 - 0.20784888555057976im, 0.003706011721090788 - 0.010324317692303395im, 0.13306259442777726 + 0.118569479357338im, -0.4731338135251027 - 0.1583662490504851im, -0.004273629125594607 + 0.3468538158520734im, -0.06317956347580744 - 0.003513276647268765im, -0.06586039061413798 + 0.03358261892476462im, -0.41902341315912495 + 0.5450599850028998im, -0.2479247663736981 - 0.11244800580962386im, 0.1243335561532938 - 0.16511767927389193im], (ℂ^4 ⊗ ℂ^2) ← ℂ^4)], TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}[TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}(ComplexF64[0.45761635553761026 + 0.5100691038517801im, 0.704172959647916 + 0.09509227616479467im, -0.10385506942921839 + 0.0077677970980542035im, -0.057804891537718416 - 0.09627140995577456im, 0.5254964609761589 + 0.5020122219582603im, -0.6723076974734432 - 0.041559161149903386im, 0.11199692597157163 - 0.029113879023307032im, 0.038513292977887095 + 0.03275816581526525im, -0.02693621637443021 - 0.02195602691060266im, -0.1438948885191209 - 0.009721013145534092im … 0.03617110885030765 - 0.13286796606672774im, -0.1250596615895784 - 0.005410261047757464im, 0.00012435466187628853 + 0.00011081001071516262im, -0.010426259714431865 - 0.003135463552527614im, -0.043239490673448025 + 0.08561683091192149im, 0.020999533716164587 + 0.10587734794864531im, -6.155033006144148e-5 + 3.138489249565966e-5im, -0.009043473175561005 + 0.011539954013403674im, -0.040007031244905684 + 0.0384126287135785im, 0.08619363051617622 - 0.061297348701577166im], (ℂ^4 ⊗ ℂ^2) ← ℂ^4)], TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 1, 1, Vector{ComplexF64}}[TensorMap{ComplexF64, TensorKit.ComplexSpace, 1, 1, Vector{ComplexF64}}(ComplexF64[0.9912829309646871 + 0.0im, 0.009458360424378597 - 0.09888993244966424im, 0.054151421932813644 - 0.04240150404409009im, 0.020726633990351125 - 0.0003438616010349522im, 0.0 + 0.0im, 0.04320346666669952 + 0.0im, -0.014712803513583068 + 0.014165205412598676im, -0.0024963999751740837 - 0.0033325263191892602im, 0.0 - 0.0im, 0.0 - 0.0im, 0.004930807984091769 + 0.0im, -0.0009082372935994094 + 0.0015820582974993753im, 0.0 - 0.0im, 0.0 - 0.0im, 0.0 - 0.0im, 0.0009264110190681823 + 0.0im], ℂ^4 ← ℂ^4)], TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}[TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}(ComplexF64[0.4536272821747002 + 0.5056227962607245im, 0.08519171264106859 - 0.036320917077859234im, 0.03418882409637629 + 0.016831327668088317im, 0.008247724892858938 + 0.007570048983156507im, 0.5209156720480171 + 0.49763614676287876im, 0.02556826645044675 - 0.049013596829181424im, 0.06077491428690042 - 0.004152644478675276im, 0.012584266665146539 + 0.012802532416582735im, -0.026701411516744447 - 0.021764634708282334im, -0.008642760480634035 + 0.002036071134308263im … 0.0007630984470478803 - 0.0013149649056872948im, 0.00016657505419833573 + 0.0002957617402115484im, 0.00012327065370369337 + 0.0001098440722018153im, -0.0004383163783434057 - 0.00014671223816886545im, -3.959137113361565e-6 + 0.00032132919701120696im, -5.8530243783905684e-5 - 3.2547381990647037e-6im, -6.1013791585072115e-5 + 3.111130822106962e-5im, -0.00038818790719817294 + 0.0005049495761598245im, -0.00022968023546849866 - 0.00010417307165427852im, 0.00011518397646034398 - 0.0001529668375222995im], (ℂ^4 ⊗ ℂ^2) ← ℂ^4)]), FiniteMPS{TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}, TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 1, 1, Vector{ComplexF64}}}(Union{Missing, TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}}[TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}(ComplexF64[0.16422359304800715 + 0.46033140118827337im, 0.011508103563057051 + 0.21129314856743533im, 0.15233658247122253 + 0.0013678526588549247im, 0.34490194084061254 + 0.20873645760641013im, 0.49910303141871065 + 0.006806894409101427im, 0.11599051265069418 + 0.3881680449009062im, 0.16754334468049015 + 0.1972436830816966im, 0.19994438097475212 + 0.1018814033174955im, -0.04657949497440146 - 0.3095284784013158im, 0.19123188831901916 + 0.3696687159540691im … 0.23181729432305542 + 0.3114043317574665im, -0.2580483102329783 + 0.44320325131691457im, 0.40968948866887966 + 0.020288212014014533im, 0.014708054635428004 - 0.47338073748485665im, -0.37921548012097034 + 0.33301728424309845im, 0.09234281525664356 + 0.35777541973813776im, 0.030355378252550635 + 0.342924177381266im, 0.08321033284899679 - 0.15575066258344997im, 0.18526452335641105 - 0.1531079866733373im, 0.06614296083528945 - 0.06604062456619697im], (ℂ^4 ⊗ ℂ^2) ← ℂ^4), TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}(ComplexF64[0.3883874083166037 + 0.18596795591160856im, 0.20586326787026593 + 0.2079413278543148im, 0.12014777543767978 - 0.004959574307497883im, 0.05537894790216697 + 0.022530620206142167im, 0.4913955568095942 + 0.4011408231940292im, 0.3321187409051777 + 0.28766434164940496im, 0.26604200666840605 + 0.192460738923807im, 0.03369812117689586 + 0.08077799203648683im, 0.2427235819591223 + 0.3543926307966194im, 0.2643251260286523 + 0.058040844212717im … -0.05558043812247566 - 0.12606677530772414im, -0.2525865894650496 - 0.18927470796232101im, -0.21837251886535253 + 0.05928544811602755im, 0.3178885573840542 + 0.0535205788275889im, 0.1562735468946435 - 0.12930958699854836im, -0.02859994986808534 - 0.06698019090950799im, 0.2873538217882595 - 0.06301073860449105im, -0.3902359200527723 - 0.08714146709615683im, -0.09741308624884275 + 0.01764349932710873im, -0.32859387446644533 + 0.6589685729046737im], (ℂ^4 ⊗ ℂ^2) ← ℂ^4), TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}(ComplexF64[0.42157399623965675 + 0.5967815715069242im, 0.11988235607668131 + 0.14760441547114628im, 0.041222876581504406 + 0.057199854292402395im, 0.021282441676995487 + 0.018670778313379217im, 0.3925082205983779 + 0.48650303958681107im, 0.1059883858361628 + 0.13186564617183438im, 0.03660585228377146 + 0.056293689313406045im, 0.010256890402566145 + 0.014540311284175888im, 0.3449628064342074 + 0.15102530813574022im, -0.005400344768606402 - 0.23211038805449144im … -0.26571983870321 - 0.15709636274307917im, -0.026022491969393383 + 0.05209008425343903im, 0.24053899032337095 + 0.048452863176158614im, -0.35955311251813077 - 0.351706375012666im, -0.42050883275825757 - 0.4480411509067353im, -0.2160064352663158 - 0.1407166736813836im, -0.15560255601816764 + 0.18550670211742618im, 0.22547501450447904 - 0.17831383782680368im, -0.20441373311741148 - 0.17875793887568597im, 0.05870241631436119 + 0.1560254402360341im], (ℂ^4 ⊗ ℂ^2) ← ℂ^4), TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}(ComplexF64[0.39223144252555064 + 0.6602550151696147im, -0.013749971357609983 + 0.04475875565462853im, 0.018725218651843286 + 0.039048734253627954im, 0.0005415712695344406 + 0.009961810578283041im, 0.560065637917137 + 0.2999175168899774im, 0.00885093307044812 + 0.03359842110705737im, 0.024594084459789754 + 0.023525792888227218im, 0.0076564121412268545 + 0.0015009628271788178im, 0.045603490780319 - 0.5772375289164782im, 0.15045869884447582 - 0.10408220113367307im … -0.3456797734928413 - 0.31413429458106973im, -0.003915358123863394 - 0.08053359998005807im, -0.012376282454412774 + 0.0023672710771514976im, 0.11710547423686488 + 0.06900332257992009im, 0.03940782148406399 + 0.32493908199046395im, -0.01864756155212266 - 0.4114750439415024im, -0.0021954631691262355 + 0.03647768795134988im, 0.3080905107386367 - 0.32352244399529567im, 0.1718341549946398 - 0.5764123444527897im, -0.03915052695921151 + 0.37461358561238206im], (ℂ^4 ⊗ ℂ^2) ← ℂ^4), TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}(ComplexF64[0.18971564133435614 + 0.5498358541733437im, 0.006430150568349197 + 0.06435836545756524im, 0.011716475489463758 + 0.014763342580462325im, 0.002448862279096028 + 0.003409945559797928im, 0.6104549071028347 + 0.5167545706305747im, 0.02375980169975718 + 0.12334537919290904im, 0.027369364369117938 + 0.029143074802562757im, 0.00763552973708664 + 0.0025521114353255587im, 0.6704410150751233 + 0.3661503417575336im, -0.02216381301598247 + 0.25169728709231176im … 0.14261681418300176 - 0.0223748875383922im, -0.06419049777404005 - 0.032726266365683286im, -0.05418220406185318 - 0.07238995345461581im, 0.26371066468525983 + 0.5290771112305382im, 0.029218322060511778 + 0.17412345030494109im, -0.02116337726927431 + 0.10320443828076081im, -0.10860404585524416 - 0.012609707294146288im, 0.5053194546613778 + 0.5031899149326762im, 0.22935821178680113 + 0.12138873933267762im, -0.02924992872995371 + 0.10671780203745673im], (ℂ^4 ⊗ ℂ^2) ← ℂ^4)], Union{Missing, TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}}[missing, missing, missing, missing, missing], Union{Missing, TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}}[missing, missing, missing, missing, missing], Union{Missing, TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 1, 1, Vector{ComplexF64}}}[missing, missing, missing, missing, missing, TensorMap{ComplexF64, TensorKit.ComplexSpace, 1, 1, Vector{ComplexF64}}(ComplexF64[0.4099108589134228 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.5448725641826901 - 0.09827882719258953im, 0.1294723991573868 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.37512618741696563 - 0.08974121917668304im, 0.1648593278970946 - 0.18507825995900784im, 0.061156443434171676 + 0.0im, 0.0 + 0.0im, 0.4842520268476007 + 0.03673158210221258im, 0.19769954123196 - 0.12674885809387756im, 0.05581885720365112 + 0.023748037917486337im, 0.0063247418396542 + 0.0im], ℂ^4 ← ℂ^4)]), InfiniteMPS{TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}, TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 1, 1, Vector{ComplexF64}}}(TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}[TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}(ComplexF64[0.49111764092646637 + 0.4502257908612838im, 0.03813140732194427 - 0.021143286906826143im, 0.018488411652815725 - 0.006419320860172586im, 0.011455442285145697 + 0.0006329506080456414im, 0.4835031730929473 + 0.5495037380863483im, 0.02379206019216925 - 0.09998055393014525im, 0.08218336931438958 + 0.0067906538528803295im, 0.011955046403285778 + 0.021201608856457242im, -0.530301300035086 - 0.43640405955548345im, 0.1719232348177675 - 0.004984862857304763im … 0.07301534124904852 - 0.20784888555057976im, 0.003706011721090788 - 0.010324317692303395im, 0.13306259442777726 + 0.118569479357338im, -0.4731338135251027 - 0.1583662490504851im, -0.004273629125594607 + 0.3468538158520734im, -0.06317956347580744 - 0.003513276647268765im, -0.06586039061413798 + 0.03358261892476462im, -0.41902341315912495 + 0.5450599850028998im, -0.2479247663736981 - 0.11244800580962386im, 0.1243335561532938 - 0.16511767927389193im], (ℂ^4 ⊗ ℂ^2) ← ℂ^4)], TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}[TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}(ComplexF64[0.45761635553761026 + 0.5100691038517801im, 0.704172959647916 + 0.09509227616479467im, -0.10385506942921839 + 0.0077677970980542035im, -0.057804891537718416 - 0.09627140995577456im, 0.5254964609761589 + 0.5020122219582603im, -0.6723076974734432 - 0.041559161149903386im, 0.11199692597157163 - 0.029113879023307032im, 0.038513292977887095 + 0.03275816581526525im, -0.02693621637443021 - 0.02195602691060266im, -0.1438948885191209 - 0.009721013145534092im … 0.03617110885030765 - 0.13286796606672774im, -0.1250596615895784 - 0.005410261047757464im, 0.00012435466187628853 + 0.00011081001071516262im, -0.010426259714431865 - 0.003135463552527614im, -0.043239490673448025 + 0.08561683091192149im, 0.020999533716164587 + 0.10587734794864531im, -6.155033006144148e-5 + 3.138489249565966e-5im, -0.009043473175561005 + 0.011539954013403674im, -0.040007031244905684 + 0.0384126287135785im, 0.08619363051617622 - 0.061297348701577166im], (ℂ^4 ⊗ ℂ^2) ← ℂ^4)], TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 1, 1, Vector{ComplexF64}}[TensorMap{ComplexF64, TensorKit.ComplexSpace, 1, 1, Vector{ComplexF64}}(ComplexF64[0.9912829309646871 + 0.0im, 0.009458360424378597 - 0.09888993244966424im, 0.054151421932813644 - 0.04240150404409009im, 0.020726633990351125 - 0.0003438616010349522im, 0.0 + 0.0im, 0.04320346666669952 + 0.0im, -0.014712803513583068 + 0.014165205412598676im, -0.0024963999751740837 - 0.0033325263191892602im, 0.0 - 0.0im, 0.0 - 0.0im, 0.004930807984091769 + 0.0im, -0.0009082372935994094 + 0.0015820582974993753im, 0.0 - 0.0im, 0.0 - 0.0im, 0.0 - 0.0im, 0.0009264110190681823 + 0.0im], ℂ^4 ← ℂ^4)], TensorKit.TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}[TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}(ComplexF64[0.4536272821747002 + 0.5056227962607245im, 0.08519171264106859 - 0.036320917077859234im, 0.03418882409637629 + 0.016831327668088317im, 0.008247724892858938 + 0.007570048983156507im, 0.5209156720480171 + 0.49763614676287876im, 0.02556826645044675 - 0.049013596829181424im, 0.06077491428690042 - 0.004152644478675276im, 0.012584266665146539 + 0.012802532416582735im, -0.026701411516744447 - 0.021764634708282334im, -0.008642760480634035 + 0.002036071134308263im … 0.0007630984470478803 - 0.0013149649056872948im, 0.00016657505419833573 + 0.0002957617402115484im, 0.00012327065370369337 + 0.0001098440722018153im, -0.0004383163783434057 - 0.00014671223816886545im, -3.959137113361565e-6 + 0.00032132919701120696im, -5.8530243783905684e-5 - 3.2547381990647037e-6im, -6.1013791585072115e-5 + 3.111130822106962e-5im, -0.00038818790719817294 + 0.0005049495761598245im, -0.00022968023546849866 - 0.00010417307165427852im, 0.00011518397646034398 - 0.0001529668375222995im], (ℂ^4 ⊗ ℂ^2) ← ℂ^4)]))Algorithms will then act on this window of tensors, while leaving the left and right infinite states invariant.
MultilineMPS
A two-dimensional classical partition function can often be represented by an infinite tensor network. There are many ways to evaluate such a network, but here we focus on the so-called boundary MPS methods. These first reduce the problem from contracting a two-dimensional network to the contraction of a one-dimensional MPS, by finding the fixed point of the row-to-row (or column-to-column) transfer matrix. In these cases however, there might be a non-trivial periodicity in both the horizontal as well as vertical direction. Therefore, in MPSKit they are represented by MultilineMPS, which are simply a repeating set of MPS lines, one per row of the network.
state = MultilineMPS(fill(infinite_state, 2))2×1 MultilineMPS(ComplexF64, TensorKit.ComplexSpace) with maximal dimension 4:
row 1:
1-site InfiniteMPS(ComplexF64, TensorKit.ComplexSpace) with maximal dimension 4:
| ⋮
| ℂ^4
├─[1]─ ℂ^2
│ ℂ^4
| ⋮
⋮
row 2:
1-site InfiniteMPS(ComplexF64, TensorKit.ComplexSpace) with maximal dimension 4:
| ⋮
| ℂ^4
├─[1]─ ℂ^2
│ ℂ^4
| ⋮Properties are accessed with cartesian (row, column) indexing:
al = state.AL[2, 1];4×2←4 TensorMap{ComplexF64, TensorKit.ComplexSpace, 2, 1, Vector{ComplexF64}}:
codomain: (ℂ^4 ⊗ ℂ^2)
domain: ⊗(ℂ^4)
blocks:
* Trivial() => 8×4 reshape(view(::Vector{ComplexF64}, 1:32), 8, 4) with eltype ComplexF64:
0.491118+0.450226im … 0.133063+0.118569im
0.0381314-0.0211433im -0.473134-0.158366im
0.0184884-0.00641932im -0.00427363+0.346854im
0.0114554+0.000632951im -0.0631796-0.00351328im
0.483503+0.549504im -0.0658604+0.0335826im
0.0237921-0.0999806im … -0.419023+0.54506im
0.0821834+0.00679065im -0.247925-0.112448im
0.011955+0.0212016im 0.124334-0.165118imIndexing convention
Row i of a MultilineMPO O acts on line i of a MultilineMPS and maps it onto line i + 1, i.e. O[i] * state[i] ∝ state[i + 1]. environments, the derivative operators and leading_eigenvalue all follow it, pairing state[i + 1] as the bra against O[i] acting on the ket state[i]. Within a row, state.AL[i, j] and friends behave exactly as they would for state[i]::InfiniteMPS.
Bra and ket are therefore different lines, so a MultilineMPS is not a state whose expectation value makes sense to take.
One fixed point, many lines
It is worth mentioning explicitly what the point of the extra rows is, since it is easy to read a MultilineMPS as a stack of independent states. It is not. However many rows the operator has, the network has exactly one boundary fixed point, namely the MPS that returns to itself after being pushed through all of the rows. The lines of a MultilineMPS are bookkeeping for that single problem. Line i + 1 is the boundary after row i has been applied, so this lets leading_boundary cut it into nrows coupled subproblems instead of contracting every row into one operator. Each subproblem contributes a partial factor, and only their product is the eigenvalue of the fixed point. Independently of that, the ncols sites of the unit cell contribute factors of their own on top. leading_eigenvalue accumulates both.
Applying an operator therefore acts on an ordinary InfiniteMPS, advancing it by one full period:
O * ψ == O[end] * (… * (O[2] * (O[1] * ψ)))Notes
A
MultilineMPSbehaves as a vector of its lines:length,size, iteration andstate[i]all refer to the lines, sosize(state) == (length(state),). The viewsstate.AL[row, col]and friends index thelength(state)rows oflength(state[1])sites. SeeMultiline.dot/normsum over rows, as for a direct sum of the lines, sonorm(state) == sqrt(length(state))for normalized rows.Lines may be any
AbstractMPS, so that for example finite networks can be built and inspected, but no algorithm supports anything but infinite lines yet.InfiniteMultilineMPSandFiniteMultilineMPSdispatch on the kind of line.
These objects are also used extensively in the context of PEPSKit.jl.