@@ -390,3 +390,35 @@ function Base.isapprox(
390390 # don't take square roots to avoid precision loss
391391 return norm₁₂² ≤ max (atol^ 2 , rtol^ 2 * max (norm₁², norm₂²))
392392end
393+
394+ """
395+ swap(mpo::FiniteMPO, i::Integer; inv::Bool=false, alg=SDD(), trscheme)
396+ swap!(mpo::FiniteMPO, i::Integer; inv::Bool=false, alg=SDD(), trscheme)
397+
398+ Compose the mpo with a swap gate applied to indices `i` and `i + 1`, effectively creating an
399+ operator that acts on the Hilbert spaces with those factors swapped.
400+ The keyword arguments `alg` and `trscheme` can be used to control how the resulting tensor
401+ is truncated again.
402+ """
403+ swap (mpo:: FiniteMPO{<:MPOTensor} , i:: Integer ; kwargs... ) = swap! (copy (mpo), i; kwargs... )
404+ function swap! (
405+ mpo:: FiniteMPO{<:MPOTensor} , i:: Integer ;
406+ inv:: Bool = false ,
407+ alg = SDD (), trscheme = truncbelow (eps (real (scalartype (mpo)))^ (4 / 5 ))
408+ )
409+ O₁, O₂ = mpo[i], mpo[i + 1 ]
410+
411+ if inv
412+ @plansor O₂₁[- 1 - 2 - 3 ; - 4 - 5 - 6 ] :=
413+ τ' [- 3 - 6 ; 4 5 ] * O₁[- 2 4 ; 2 1 ] * O₂[1 5 ; 3 - 5 ] * τ[2 3 ; - 1 - 4 ]
414+ else
415+ @plansor O₂₁[- 1 - 2 - 3 ; - 4 - 5 - 6 ] :=
416+ τ[- 3 - 6 ; 4 5 ] * O₁[- 2 4 ; 2 1 ] * O₂[1 5 ; 3 - 5 ] * τ' [2 3 ; - 1 - 4 ]
417+ end
418+
419+ U, S, Vᴴ, = tsvd! (O₂₁; alg, trunc = trscheme)
420+ sqrtS = sqrt (S)
421+ @plansor mpo[i][- 1 - 2 ; - 3 - 4 ] := U[- 3 - 1 - 2 ; 1 ] * sqrtS[1 ; - 4 ]
422+ @plansor mpo[i + 1 ][- 1 - 2 ; - 3 - 4 ] := sqrtS[- 1 ; 1 ] * Vᴴ[1 ; - 3 - 4 - 2 ]
423+ return mpo
424+ end
0 commit comments