diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml deleted file mode 100644 index c7439503e..000000000 --- a/.JuliaFormatter.toml +++ /dev/null @@ -1 +0,0 @@ -style = "blue" \ No newline at end of file diff --git a/.github/workflows/FormatCheck.yml b/.github/workflows/FormatCheck.yml index 17bac37d5..a7b4fbad8 100644 --- a/.github/workflows/FormatCheck.yml +++ b/.github/workflows/FormatCheck.yml @@ -1,4 +1,4 @@ -name: "Format Check" +name: FormatCheck on: push: @@ -7,10 +7,12 @@ on: - 'master' tags: '*' pull_request: + branches: + - 'main' + - 'master' jobs: - format-check: + formatcheck: name: "Format Check" - uses: "QuantumKitHub/.github/.github/workflows/formatcheck.yml@main" - with: - juliaformatter-version: "2" + uses: "QuantumKitHub/QuantumKitHubActions/.github/workflows/FormatCheck.yml@main" + \ No newline at end of file diff --git a/docs/make.jl b/docs/make.jl index c432c28b8..4691f118f 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -2,7 +2,7 @@ if Base.active_project() != joinpath(@__DIR__, "Project.toml") using Pkg Pkg.activate(@__DIR__) - Pkg.develop(PackageSpec(; path=joinpath(@__DIR__, ".."))) + Pkg.develop(PackageSpec(; path = joinpath(@__DIR__, ".."))) Pkg.resolve() Pkg.instantiate() end @@ -15,7 +15,7 @@ using MPSKitModels: MPSKitModels # used for docstrings # bibliography bibpath = joinpath(@__DIR__, "src", "assets", "pepskit.bib") -bib = CitationBibliography(bibpath; style=:authoryear) +bib = CitationBibliography(bibpath; style = :authoryear) # interlinks # Zygote didn't update to documenter v1 yet... @@ -53,12 +53,12 @@ examples_partition_functions = joinpath.( examples_boundary_mps = joinpath.(["boundary_mps"], Ref("index.md")) makedocs(; - modules=[PEPSKit, MPSKitModels], - sitename="PEPSKit.jl", - format=Documenter.HTML(; - prettyurls=true, mathengine, assets=["assets/custom.css"], size_threshold=1024000 + modules = [PEPSKit, MPSKitModels], + sitename = "PEPSKit.jl", + format = Documenter.HTML(; + prettyurls = true, mathengine, assets = ["assets/custom.css"], size_threshold = 1024000 ), - pages=[ + pages = [ "Home" => "index.md", "Manual" => ["man/models.md", "man/multithreading.md", "man/precompilation.md"], "Examples" => [ @@ -72,9 +72,9 @@ makedocs(; "Library" => "lib/lib.md", "References" => "references.md", ], - checkdocs=:none, + checkdocs = :none, # checkdocs_ignored_modules=[MPSKitModels], # doesn't seem to work... - plugins=[bib, links], + plugins = [bib, links], ) -deploydocs(; repo="github.com/QuantumKitHub/PEPSKit.jl.git", push_preview=true) +deploydocs(; repo = "github.com/QuantumKitHub/PEPSKit.jl.git", push_preview = true) diff --git a/examples/2d_ising_partition_function/main.jl b/examples/2d_ising_partition_function/main.jl index 2c3726fd0..e10ab4bb0 100644 --- a/examples/2d_ising_partition_function/main.jl +++ b/examples/2d_ising_partition_function/main.jl @@ -39,7 +39,7 @@ Since we later want to compute the magnetization and energy to check our results the appropriate rank-4 tensors here as well while we're at it. """ -function classical_ising(; beta=log(1 + sqrt(2)) / 2, J=1.0) +function classical_ising(; beta = log(1 + sqrt(2)) / 2, J = 1.0) K = beta * J ## Boltzmann weights @@ -92,7 +92,7 @@ settings: Venv = ℂ^20 env₀ = CTMRGEnv(Z, Venv) -env, = leading_boundary(env₀, Z; tol=1e-8, maxiter=500); +env, = leading_boundary(env₀, Z; tol = 1.0e-8, maxiter = 500); md""" Note that CTMRG environments for partition functions differ from the PEPS environments only @@ -125,7 +125,7 @@ magnetization and energy per site (where we use `quadgk` to perform integrals of auxiliary variable from $0$ to $\pi/2$): """ -function classical_ising_exact(; beta=log(1 + sqrt(2)) / 2, J=1.0) +function classical_ising_exact(; beta = log(1 + sqrt(2)) / 2, J = 1.0) K = beta * J k = 1 / sinh(2 * K)^2 diff --git a/examples/3d_ising_partition_function/main.jl b/examples/3d_ising_partition_function/main.jl index 45693172c..222989330 100644 --- a/examples/3d_ising_partition_function/main.jl +++ b/examples/3d_ising_partition_function/main.jl @@ -45,7 +45,7 @@ lattice. To verify our example we will check the magnetization and energy, so we the corresponding rank-6 tensors `M` and `E` while we're at it. """ -function three_dimensional_classical_ising(; beta, J=1.0) +function three_dimensional_classical_ising(; beta, J = 1.0) K = beta * J ## Boltzmann weights @@ -150,9 +150,9 @@ we'll specify the specific reverse rule algorithm that will be used to compute t of this cost function. """ -boundary_alg = SimultaneousCTMRG(; maxiter=150, tol=1e-8, verbosity=1) +boundary_alg = SimultaneousCTMRG(; maxiter = 150, tol = 1.0e-8, verbosity = 1) rrule_alg = EigSolver(; - solver_alg=KrylovKit.Arnoldi(; maxiter=30, tol=1e-6, eager=true), iterscheme=:diffgauge + solver_alg = KrylovKit.Arnoldi(; maxiter = 30, tol = 1.0e-6, eager = true), iterscheme = :diffgauge ) T = InfinitePEPO(O) @@ -167,7 +167,7 @@ function pepo_costfun((peps, env_double_layer, env_triple_layer)) env_double_layer, n_double_layer, boundary_alg; - alg_rrule=rrule_alg, + alg_rrule = rrule_alg, ) ## construct the PEPS-PEPO-PEPS overlap network n_triple_layer = InfiniteSquareNetwork(ψ, T) @@ -177,7 +177,7 @@ function pepo_costfun((peps, env_double_layer, env_triple_layer)) env_triple_layer, n_triple_layer, boundary_alg; - alg_rrule=rrule_alg, + alg_rrule = rrule_alg, ) ## update the environments for reuse PEPSKit.ignore_derivatives() do @@ -242,12 +242,12 @@ function pepo_retract((peps, env_double_layer, env_triple_layer), η, α) return (peps´, env_double_layer´, env_triple_layer´), ξ end function pepo_transport!( - ξ, - (peps, env_double_layer, env_triple_layer), - η, - α, - (peps´, env_double_layer´, env_triple_layer´), -) + ξ, + (peps, env_double_layer, env_triple_layer), + η, + α, + (peps´, env_double_layer´, env_triple_layer´), + ) return PEPSKit.peps_transport!( ξ, (peps, env_double_layer), η, α, (peps´, env_double_layer´) ) @@ -268,15 +268,15 @@ psi0 = initializePEPS(T, Vpeps) env2_0 = CTMRGEnv(InfiniteSquareNetwork(psi0), Venv) env3_0 = CTMRGEnv(InfiniteSquareNetwork(psi0, T), Venv) -optimizer_alg = LBFGS(32; maxiter=100, gradtol=1e-5, verbosity=3) +optimizer_alg = LBFGS(32; maxiter = 100, gradtol = 1.0e-5, verbosity = 3) (psi_final, env2_final, env3_final), f, = optimize( pepo_costfun, (psi0, env2_0, env3_0), optimizer_alg; - inner=PEPSKit.real_inner, - retract=pepo_retract, - (transport!)=(pepo_transport!), + inner = PEPSKit.real_inner, + retract = pepo_retract, + (transport!) = (pepo_transport!), ); md""" diff --git a/examples/bose_hubbard/main.jl b/examples/bose_hubbard/main.jl index 9e93cf362..1bc17cb03 100644 --- a/examples/bose_hubbard/main.jl +++ b/examples/bose_hubbard/main.jl @@ -87,9 +87,9 @@ optimization framework in the usual way to find the ground state. So, we first s algorithms and their tolerances: """ -boundary_alg = (; tol=1e-8, alg=:simultaneous, trscheme=(; alg=:fixedspace)) -gradient_alg = (; tol=1e-6, maxiter=10, alg=:eigsolver, iterscheme=:diffgauge) -optimizer_alg = (; tol=1e-4, alg=:lbfgs, maxiter=150, ls_maxiter=2, ls_maxfg=2); +boundary_alg = (; tol = 1.0e-8, alg = :simultaneous, trscheme = (; alg = :fixedspace)) +gradient_alg = (; tol = 1.0e-6, maxiter = 10, alg = :eigsolver, iterscheme = :diffgauge) +optimizer_alg = (; tol = 1.0e-4, alg = :lbfgs, maxiter = 150, ls_maxiter = 2, ls_maxfg = 2); md""" !!! note @@ -118,7 +118,7 @@ And at last, we optimize (which might take a bit): """ peps, env, E, info = fixedpoint( - H, peps₀, env₀; boundary_alg, gradient_alg, optimizer_alg, verbosity=3 + H, peps₀, env₀; boundary_alg, gradient_alg, optimizer_alg, verbosity = 3 ) @show E; diff --git a/examples/boundary_mps/main.jl b/examples/boundary_mps/main.jl index 2fc80221a..7e025a43c 100644 --- a/examples/boundary_mps/main.jl +++ b/examples/boundary_mps/main.jl @@ -128,7 +128,7 @@ boundary MPS fixed point, we call [`leading_boundary`](@ref) using the [`MPSKit.VUMPS`](@extref) algorithm: """ -mps, env, ϵ = leading_boundary(mps₀, T, VUMPS(; tol=1e-6, verbosity=2)); +mps, env, ϵ = leading_boundary(mps₀, T, VUMPS(; tol = 1.0e-6, verbosity = 2)); md""" The norm of the state per unit cell is then given by the expectation value @@ -142,7 +142,7 @@ This can be compared to the result obtained using CTMRG, where we see that the r match: """ -env_ctmrg, = leading_boundary(CTMRGEnv(ψ, ComplexSpace(20)), ψ; tol=1e-6, verbosity=2) +env_ctmrg, = leading_boundary(CTMRGEnv(ψ, ComplexSpace(20)), ψ; tol = 1.0e-6, verbosity = 2) norm_ctmrg = abs(norm(ψ, env_ctmrg)) @show abs(norm_vumps - norm_ctmrg) / norm_vumps; @@ -162,7 +162,7 @@ argument and then define the corresponding transfer operator, where we again spe direction which will be facing north: """ -ψ_2x2 = InfinitePEPS(rand, ComplexF64, ComplexSpace(2), ComplexSpace(2); unitcell=(2, 2)) +ψ_2x2 = InfinitePEPS(rand, ComplexF64, ComplexSpace(2), ComplexSpace(2); unitcell = (2, 2)) T_2x2 = PEPSKit.MultilineTransferPEPS(ψ_2x2, dir); md""" @@ -170,11 +170,11 @@ Now, the procedure is the same as before: We compute the norm once using VUMPS, """ mps₀_2x2 = initialize_mps(T_2x2, fill(ComplexSpace(20), 2, 2)) -mps_2x2, = leading_boundary(mps₀_2x2, T_2x2, VUMPS(; tol=1e-6, verbosity=2)) +mps_2x2, = leading_boundary(mps₀_2x2, T_2x2, VUMPS(; tol = 1.0e-6, verbosity = 2)) norm_2x2_vumps = abs(prod(expectation_value(mps_2x2, T_2x2))) env_ctmrg_2x2, = leading_boundary( - CTMRGEnv(ψ_2x2, ComplexSpace(20)), ψ_2x2; tol=1e-6, verbosity=2 + CTMRGEnv(ψ_2x2, ComplexSpace(20)), ψ_2x2; tol = 1.0e-6, verbosity = 2 ) norm_2x2_ctmrg = abs(norm(ψ_2x2, env_ctmrg_2x2)) @@ -196,7 +196,7 @@ T | \psi \rangle$. The classical Ising PEPO is defined as follows: """ -function ising_pepo(β; unitcell=(1, 1, 1)) +function ising_pepo(β; unitcell = (1, 1, 1)) t = ComplexF64[exp(β) exp(-β); exp(-β) exp(β)] q = sqrt(t) @@ -223,7 +223,7 @@ As before, we converge the boundary MPS using VUMPS and then compute the expecta """ mps₀_pepo = initialize_mps(transfer_pepo, [ComplexSpace(20)]) -mps_pepo, = leading_boundary(mps₀_pepo, transfer_pepo, VUMPS(; tol=1e-6, verbosity=2)) +mps_pepo, = leading_boundary(mps₀_pepo, transfer_pepo, VUMPS(; tol = 1.0e-6, verbosity = 2)) norm_pepo = abs(prod(expectation_value(mps_pepo, transfer_pepo))); @show norm_pepo; diff --git a/examples/fermi_hubbard/main.jl b/examples/fermi_hubbard/main.jl index 2d5ae117f..c94ba7748 100644 --- a/examples/fermi_hubbard/main.jl +++ b/examples/fermi_hubbard/main.jl @@ -70,9 +70,9 @@ Again, the procedure of ground state optimization is very similar to before. Fir define all algorithmic parameters: """ -boundary_alg = (; tol=1e-8, alg=:simultaneous, trscheme=(; alg=:fixedspace)) -gradient_alg = (; tol=1e-6, alg=:eigsolver, maxiter=10, iterscheme=:diffgauge) -optimizer_alg = (; tol=1e-4, alg=:lbfgs, maxiter=80, ls_maxiter=3, ls_maxfg=3) +boundary_alg = (; tol = 1.0e-8, alg = :simultaneous, trscheme = (; alg = :fixedspace)) +gradient_alg = (; tol = 1.0e-6, alg = :eigsolver, maxiter = 10, iterscheme = :diffgauge) +optimizer_alg = (; tol = 1.0e-4, alg = :lbfgs, maxiter = 80, ls_maxiter = 3, ls_maxfg = 3) md""" Second, we initialize a PEPS state and environment (which we converge) constructed from @@ -89,7 +89,7 @@ And third, we start the ground state search (this does take quite long): """ peps, env, E, info = fixedpoint( - H, peps₀, env₀; boundary_alg, gradient_alg, optimizer_alg, verbosity=3 + H, peps₀, env₀; boundary_alg, gradient_alg, optimizer_alg, verbosity = 3 ) @show E; diff --git a/examples/heisenberg/main.jl b/examples/heisenberg/main.jl index 4acfa18da..41e0255b6 100644 --- a/examples/heisenberg/main.jl +++ b/examples/heisenberg/main.jl @@ -37,7 +37,7 @@ the `heisenberg_XYZ` method from [MPSKitModels](https://quantumkithub.github.io/ which is redefined for the `InfiniteSquare` and reexported in PEPSKit: """ -H = heisenberg_XYZ(InfiniteSquare(); Jx=-1, Jy=1, Jz=-1) +H = heisenberg_XYZ(InfiniteSquare(); Jx = -1, Jy = 1, Jz = -1) md""" ## Setting up the algorithms and initial guesses @@ -63,7 +63,7 @@ arguments. To see a description of all arguments, see the docstring of specific tolerance and during the CTMRG run keep all index dimensions fixed: """ -boundary_alg = (; tol=1e-10, trscheme=(; alg=:fixedspace)); +boundary_alg = (; tol = 1.0e-10, trscheme = (; alg = :fixedspace)); md""" Let us also configure the optimizer algorithm. We are going to optimize the PEPS using the @@ -72,7 +72,7 @@ the convergence tolerance (for the gradient norm) as well as the maximal number and the BFGS memory size (which is used to approximate the Hessian): """ -optimizer_alg = (; alg=:lbfgs, tol=1e-4, maxiter=100, lbfgs_memory=16); +optimizer_alg = (; alg = :lbfgs, tol = 1.0e-4, maxiter = 100, lbfgs_memory = 16); md""" Additionally, during optimization, we want to reuse the previous CTMRG environment to diff --git a/examples/heisenberg_su/main.jl b/examples/heisenberg_su/main.jl index 06718cd51..29b2c02e1 100644 --- a/examples/heisenberg_su/main.jl +++ b/examples/heisenberg_su/main.jl @@ -34,7 +34,7 @@ no internal symmetries (`symm = Trivial`) or use the global $U(1)$ symmetry symm = Trivial ## ∈ {Trivial, U1Irrep} Nr, Nc = 2, 2 -H = real(heisenberg_XYZ(ComplexF64, symm, InfiniteSquare(Nr, Nc); Jx=1, Jy=1, Jz=1)); +H = real(heisenberg_XYZ(ComplexF64, symm, InfiniteSquare(Nr, Nc); Jx = 1, Jy = 1, Jz = 1)); md""" ## Simple updating @@ -50,14 +50,14 @@ if symm == Trivial bond_space = ℂ^Dbond env_space = ℂ^χenv elseif symm == U1Irrep - physical_space = ℂ[U1Irrep](1//2 => 1, -1//2 => 1) - bond_space = ℂ[U1Irrep](0 => Dbond ÷ 2, 1//2 => Dbond ÷ 4, -1//2 => Dbond ÷ 4) - env_space = ℂ[U1Irrep](0 => χenv ÷ 2, 1//2 => χenv ÷ 4, -1//2 => χenv ÷ 4) + physical_space = ℂ[U1Irrep](1 // 2 => 1, -1 // 2 => 1) + bond_space = ℂ[U1Irrep](0 => Dbond ÷ 2, 1 // 2 => Dbond ÷ 4, -1 // 2 => Dbond ÷ 4) + env_space = ℂ[U1Irrep](0 => χenv ÷ 2, 1 // 2 => χenv ÷ 4, -1 // 2 => χenv ÷ 4) else error("not implemented") end -wpeps = InfiniteWeightPEPS(rand, Float64, physical_space, bond_space; unitcell=(Nr, Nc)); +wpeps = InfiniteWeightPEPS(rand, Float64, physical_space, bond_space; unitcell = (Nr, Nc)); md""" Next, we can start the `SimpleUpdate` routine, successively decreasing the time intervals @@ -66,14 +66,14 @@ truncation schemes, which we use here to set a maximal bond dimension and at the fix a truncation error (if that can be reached by remaining below `Dbond`): """ -dts = [1e-2, 1e-3, 4e-4] -tols = [1e-6, 1e-8, 1e-8] +dts = [1.0e-2, 1.0e-3, 4.0e-4] +tols = [1.0e-6, 1.0e-8, 1.0e-8] maxiter = 10000 -trscheme_peps = truncerr(1e-10) & truncdim(Dbond) +trscheme_peps = truncerr(1.0e-10) & truncdim(Dbond) for (dt, tol) in zip(dts, tols) alg = SimpleUpdate(dt, tol, maxiter, trscheme_peps) - result = simpleupdate(wpeps, H, alg; bipartite=true) + result = simpleupdate(wpeps, H, alg; bipartite = true) global wpeps = result[1] end @@ -86,14 +86,14 @@ on the evolved PEPS. Let's do so: peps = InfinitePEPS(wpeps) ## absorb the weights env₀ = CTMRGEnv(rand, Float64, peps, env_space) -trscheme_env = truncerr(1e-10) & truncdim(χenv) +trscheme_env = truncerr(1.0e-10) & truncdim(χenv) env, = leading_boundary( env₀, peps; - alg=:sequential, - projector_alg=:fullinfinite, - tol=1e-10, - trscheme=trscheme_env, + alg = :sequential, + projector_alg = :fullinfinite, + tol = 1.0e-10, + trscheme = trscheme_env, ); md""" diff --git a/examples/hubbard_su/main.jl b/examples/hubbard_su/main.jl index 27a82eb3a..3308b6505 100644 --- a/examples/hubbard_su/main.jl +++ b/examples/hubbard_su/main.jl @@ -31,7 +31,7 @@ constructed on a $2 \times 2$ unit cell, so we have: t = 1 U = 6 Nr, Nc = 2, 2 -H = hubbard_model(Float64, Trivial, Trivial, InfiniteSquare(Nr, Nc); t, U, mu=U / 2); +H = hubbard_model(Float64, Trivial, Trivial, InfiniteSquare(Nr, Nc); t, U, mu = U / 2); md""" ## Running the simple update algorithm @@ -46,7 +46,7 @@ real `Float64` entries: Dbond = 8 physical_space = Vect[fℤ₂](0 => 2, 1 => 2) virtual_space = Vect[fℤ₂](0 => Dbond / 2, 1 => Dbond / 2) -wpeps = InfiniteWeightPEPS(rand, Float64, physical_space, virtual_space; unitcell=(Nr, Nc)); +wpeps = InfiniteWeightPEPS(rand, Float64, physical_space, virtual_space; unitcell = (Nr, Nc)); md""" Let's set the algorithm parameters: The plan is to successively decrease the time interval of @@ -56,14 +56,14 @@ use the keyword `bipartite=false` - meaning that we use the full $2 \times 2$ un without assuming a bipartite structure. Thus, we can start evolving: """ -dts = [1e-2, 1e-3, 4e-4, 1e-4] -tols = [1e-6, 1e-8, 1e-8, 1e-8] +dts = [1.0e-2, 1.0e-3, 4.0e-4, 1.0e-4] +tols = [1.0e-6, 1.0e-8, 1.0e-8, 1.0e-8] maxiter = 20000 for (n, (dt, tol)) in enumerate(zip(dts, tols)) - trscheme = truncerr(1e-10) & truncdim(Dbond) + trscheme = truncerr(1.0e-10) & truncdim(Dbond) alg = SimpleUpdate(dt, tol, maxiter, trscheme) - global wpeps, = simpleupdate(wpeps, H, alg; bipartite=false) + global wpeps, = simpleupdate(wpeps, H, alg; bipartite = false) end md""" @@ -89,7 +89,7 @@ env_space = Vect[fℤ₂](0 => χenv₀ / 2, 1 => χenv₀ / 2) env = CTMRGEnv(rand, Float64, peps, env_space) for χ in [χenv₀, χenv] global env, = leading_boundary( - env, peps; alg=:sequential, tol=1e-5, trscheme=truncdim(χ) + env, peps; alg = :sequential, tol = 1.0e-5, trscheme = truncdim(χ) ) end diff --git a/examples/j1j2_su/main.jl b/examples/j1j2_su/main.jl index e30f76707..4bb7b8d5f 100644 --- a/examples/j1j2_su/main.jl +++ b/examples/j1j2_su/main.jl @@ -32,14 +32,14 @@ next-nearest-neighbour interactions: """ Dbond, χenv, symm = 4, 32, U1Irrep -trscheme_env = truncerr(1e-10) & truncdim(χenv) +trscheme_env = truncerr(1.0e-10) & truncdim(χenv) Nr, Nc, J1 = 2, 2, 1.0 ## random initialization of 2x2 iPEPS with weights and CTMRGEnv (using real numbers) -Pspace = Vect[U1Irrep](1//2 => 1, -1//2 => 1) -Vspace = Vect[U1Irrep](0 => 2, 1//2 => 1, -1//2 => 1) -Espace = Vect[U1Irrep](0 => χenv ÷ 2, 1//2 => χenv ÷ 4, -1//2 => χenv ÷ 4) -wpeps = InfiniteWeightPEPS(rand, Float64, Pspace, Vspace; unitcell=(Nr, Nc)); +Pspace = Vect[U1Irrep](1 // 2 => 1, -1 // 2 => 1) +Vspace = Vect[U1Irrep](0 => 2, 1 // 2 => 1, -1 // 2 => 1) +Espace = Vect[U1Irrep](0 => χenv ÷ 2, 1 // 2 => χenv ÷ 4, -1 // 2 => χenv ÷ 4) +wpeps = InfiniteWeightPEPS(rand, Float64, Pspace, Vspace; unitcell = (Nr, Nc)); md""" The value $J_2 / J_1 = 0.5$ corresponds to a [possible spin liquid phase](@cite liu_gapless_2022), @@ -48,13 +48,13 @@ Therefore, we shall gradually increase $J_2 / J_1$ from 0.1 to 0.5, each time in on the previously evolved PEPS: """ -dt, tol, maxiter = 1e-2, 1e-8, 30000 +dt, tol, maxiter = 1.0e-2, 1.0e-8, 30000 check_interval = 4000 -trscheme_peps = truncerr(1e-10) & truncdim(Dbond) +trscheme_peps = truncerr(1.0e-10) & truncdim(Dbond) alg = SimpleUpdate(dt, tol, maxiter, trscheme_peps) for J2 in 0.1:0.1:0.5 H = real( ## convert Hamiltonian `LocalOperator` to real floats - j1_j2_model(ComplexF64, symm, InfiniteSquare(Nr, Nc); J1, J2, sublattice=false), + j1_j2_model(ComplexF64, symm, InfiniteSquare(Nr, Nc); J1, J2, sublattice = false), ) result = simpleupdate(wpeps, H, alg; check_interval) global wpeps = result[1] @@ -65,10 +65,10 @@ After we reach $J_2 / J_1 = 0.5$, we gradually decrease the evolution time step a more accurately evolved PEPS: """ -dts = [1e-3, 1e-4] -tols = [1e-9, 1e-9] +dts = [1.0e-3, 1.0e-4] +tols = [1.0e-9, 1.0e-9] J2 = 0.5 -H = real(j1_j2_model(ComplexF64, symm, InfiniteSquare(Nr, Nc); J1, J2, sublattice=false)) +H = real(j1_j2_model(ComplexF64, symm, InfiniteSquare(Nr, Nc); J1, J2, sublattice = false)) for (dt, tol) in zip(dts, tols) alg′ = SimpleUpdate(dt, tol, maxiter, trscheme_peps) result = simpleupdate(wpeps, H, alg′; check_interval) @@ -85,7 +85,7 @@ the expectation value, where we make sure to normalize by the unit cell size: peps = InfinitePEPS(wpeps) normalize!.(peps.A, Inf) ## normalize PEPS with absorbed weights by largest element env₀ = CTMRGEnv(rand, Float64, peps, Espace) -env, = leading_boundary(env₀, peps; tol=1e-10, alg=:sequential, trscheme=trscheme_env); +env, = leading_boundary(env₀, peps; tol = 1.0e-10, alg = :sequential, trscheme = trscheme_env); E = expectation_value(peps, H, env) / (Nr * Nc) md""" @@ -113,9 +113,9 @@ symmetry can be advantageous for obtaining lower energies.) using MPSKit: randomize! noise_peps = InfinitePEPS(randomize!.(deepcopy(peps.A))) -peps₀ = peps + 1e-1noise_peps +peps₀ = peps + 1.0e-1noise_peps peps_opt, env_opt, E_opt, = fixedpoint( - H, peps₀, env; optimizer_alg=(; tol=1e-4, maxiter=80) + H, peps₀, env; optimizer_alg = (; tol = 1.0e-4, maxiter = 80) ); md""" diff --git a/examples/make.jl b/examples/make.jl index 1d8900164..220e449b3 100644 --- a/examples/make.jl +++ b/examples/make.jl @@ -2,7 +2,7 @@ if Base.active_project() != joinpath(@__DIR__, "Project.toml") using Pkg Pkg.activate(@__DIR__) - Pkg.develop(PackageSpec(; path=(@__DIR__) * "/../")) + Pkg.develop(PackageSpec(; path = (@__DIR__) * "/../")) Pkg.resolve() Pkg.instantiate() end @@ -17,7 +17,7 @@ using TOML, SHA const CACHEFILE = joinpath(@__DIR__, "Cache.toml") -getcache() = isfile(CACHEFILE) ? TOML.parsefile(CACHEFILE) : Dict{String,Any}() +getcache() = isfile(CACHEFILE) ? TOML.parsefile(CACHEFILE) : Dict{String, Any}() function iscached(name) cache = getcache() @@ -62,31 +62,31 @@ function build_example(name) source_file = joinpath(source_dir, "main.jl") target_dir = joinpath(@__DIR__, "..", "docs", "src", "examples", name) - if !iscached(name) + return if !iscached(name) Literate.markdown( source_file, target_dir; - execute=true, - name="index", - preprocess=attach_notebook_badge(name), - mdstrings=true, - nbviewer_root_url="https://nbviewer.jupyter.org/github/QuantumKitHub/PEPSKit.jl/blob/gh-pages/dev", - binder_root_url="https://mybinder.org/v2/gh/QuantumKitHub/PEPSKit.jl/gh-pages?filepath=dev", - credits=false, - repo_root_url="https://github.com/QuantumKitHub/PEPSKit.jl", + execute = true, + name = "index", + preprocess = attach_notebook_badge(name), + mdstrings = true, + nbviewer_root_url = "https://nbviewer.jupyter.org/github/QuantumKitHub/PEPSKit.jl/blob/gh-pages/dev", + binder_root_url = "https://mybinder.org/v2/gh/QuantumKitHub/PEPSKit.jl/gh-pages?filepath=dev", + credits = false, + repo_root_url = "https://github.com/QuantumKitHub/PEPSKit.jl", ) Literate.notebook( source_file, target_dir; - execute=false, - name="main", - preprocess=str -> replace(str, r"(? "\$"), - mdstrings=true, - credits=false, + execute = false, + name = "main", + preprocess = str -> replace(str, r"(? "\$"), + mdstrings = true, + credits = false, ) foreach(filter(!=("main.jl"), readdir(source_dir))) do f - return cp(joinpath(source_dir, f), joinpath(target_dir, f); force=true) + return cp(joinpath(source_dir, f), joinpath(target_dir, f); force = true) end setcached(name) end diff --git a/examples/xxz/main.jl b/examples/xxz/main.jl index 81b2fad37..1cffdb898 100644 --- a/examples/xxz/main.jl +++ b/examples/xxz/main.jl @@ -31,7 +31,7 @@ parameters: J = 1.0 Delta = 1.0 -spin = 1//2 +spin = 1 // 2 symmetry = U1Irrep lattice = InfiniteSquare(2, 2) H₀ = heisenberg_XXZ(ComplexF64, symmetry, lattice; J, Delta, spin); @@ -43,8 +43,8 @@ charges: """ S_aux = [ - U1Irrep(-1//2) U1Irrep(1//2) - U1Irrep(1//2) U1Irrep(-1//2) + U1Irrep(-1 // 2) U1Irrep(1 // 2) + U1Irrep(1 // 2) U1Irrep(-1 // 2) ] H = add_physical_charge(H₀, S_aux); @@ -71,9 +71,9 @@ From this point onwards it's business as usual: Create an initial PEPS and envir (using the symmetric spaces), specify the algorithmic parameters and optimize: """ -boundary_alg = (; tol=1e-8, alg=:simultaneous, trscheme=(; alg=:fixedspace)) -gradient_alg = (; tol=1e-6, alg=:eigsolver, maxiter=10, iterscheme=:diffgauge) -optimizer_alg = (; tol=1e-4, alg=:lbfgs, maxiter=85, ls_maxiter=3, ls_maxfg=3) +boundary_alg = (; tol = 1.0e-8, alg = :simultaneous, trscheme = (; alg = :fixedspace)) +gradient_alg = (; tol = 1.0e-6, alg = :eigsolver, maxiter = 10, iterscheme = :diffgauge) +optimizer_alg = (; tol = 1.0e-4, alg = :lbfgs, maxiter = 85, ls_maxiter = 3, ls_maxfg = 3) peps₀ = InfinitePEPS(randn, ComplexF64, physical_spaces, virtual_spaces) env₀, = leading_boundary(CTMRGEnv(peps₀, V_env), peps₀; boundary_alg...); @@ -86,7 +86,7 @@ and environment dimensions): """ peps, env, E, info = fixedpoint( - H, peps₀, env₀; boundary_alg, gradient_alg, optimizer_alg, verbosity=3 + H, peps₀, env₀; boundary_alg, gradient_alg, optimizer_alg, verbosity = 3 ) @show E; diff --git a/src/Defaults.jl b/src/Defaults.jl index 9e80248cd..972717cb5 100644 --- a/src/Defaults.jl +++ b/src/Defaults.jl @@ -84,7 +84,7 @@ export set_scheduler! using OhMyThreads # CTMRG -const ctmrg_tol = 1e-8 +const ctmrg_tol = 1.0e-8 const ctmrg_maxiter = 100 const ctmrg_miniter = 4 const ctmrg_alg = :simultaneous # ∈ {:simultaneous, :sequential} @@ -98,7 +98,7 @@ const svd_rrule_tol = ctmrg_tol const svd_rrule_min_krylovdim = 48 const svd_rrule_verbosity = -1 const svd_rrule_alg = :full # ∈ {:full, :gmres, :bicgstab, :arnoldi} -const svd_rrule_broadening = 1e-13 +const svd_rrule_broadening = 1.0e-13 const krylovdim_factor = 1.4 # Projectors @@ -106,7 +106,7 @@ const projector_alg = :halfinfinite # ∈ {:halfinfinite, :fullinfinite} const projector_verbosity = 0 # Fixed-point gradient -const gradient_tol = 1e-6 +const gradient_tol = 1.0e-6 const gradient_maxiter = 30 const gradient_verbosity = -1 const gradient_linsolver = :bicgstab # ∈ {:gmres, :bicgstab} @@ -117,7 +117,7 @@ const gradient_alg = :linsolver # ∈ {:geomsum, :manualiter, :linsolver, :eigso # Optimization const reuse_env = true -const optimizer_tol = 1e-4 +const optimizer_tol = 1.0e-4 const optimizer_maxiter = 100 const optimizer_verbosity = 3 const optimizer_alg = :lbfgs # ∈ {:gradientdescent, :conjugategradient, :lbfgs} @@ -154,7 +154,7 @@ To reset the scheduler to its default value, one calls `set_scheduler!` without arguments which then uses the default `DynamicScheduler()`. If the number of used threads is just one it falls back to `SerialScheduler()`. """ -function set_scheduler!(sc=OhMyThreads.Implementation.NotGiven(); kwargs...) +function set_scheduler!(sc = OhMyThreads.Implementation.NotGiven(); kwargs...) if isempty(kwargs) && sc isa OhMyThreads.Implementation.NotGiven scheduler[] = Threads.nthreads() == 1 ? SerialScheduler() : DynamicScheduler() else diff --git a/src/algorithms/contractions/bondenv/als_solve.jl b/src/algorithms/contractions/bondenv/als_solve.jl index 1bc06b9d9..c244c7370 100644 --- a/src/algorithms/contractions/bondenv/als_solve.jl +++ b/src/algorithms/contractions/bondenv/als_solve.jl @@ -20,8 +20,8 @@ Construct the tensor ``` """ function _tensor_Ra( - benv::BondEnv{T,S}, b::AbstractTensorMap{T,S,2,1} -) where {T<:Number,S<:ElementarySpace} + benv::BondEnv{T, S}, b::AbstractTensorMap{T, S, 2, 1} + ) where {T <: Number, S <: ElementarySpace} return @autoopt @tensor Ra[DX1 Db1; DX0 Db0] := ( benv[DX1 DY1; DX0 DY0] * b[Db0 DY0; db] * conj(b[Db1 DY1; db]) ) @@ -44,8 +44,8 @@ Construct the tensor ``` """ function _tensor_Sa( - benv::BondEnv{T,S}, b::AbstractTensorMap{T,S,2,1}, a2b2::AbstractTensorMap{T,S,2,2} -) where {T<:Number,S<:ElementarySpace} + benv::BondEnv{T, S}, b::AbstractTensorMap{T, S, 2, 1}, a2b2::AbstractTensorMap{T, S, 2, 2} + ) where {T <: Number, S <: ElementarySpace} return @autoopt @tensor Sa[DX1 Db1; da] := ( benv[DX1 DY1; DX0 DY0] * conj(b[Db1 DY1; db]) * a2b2[DX0 DY0; da db] ) @@ -68,8 +68,8 @@ Construct the tensor ``` """ function _tensor_Rb( - benv::BondEnv{T,S}, a::AbstractTensorMap{T,S,2,1} -) where {T<:Number,S<:ElementarySpace} + benv::BondEnv{T, S}, a::AbstractTensorMap{T, S, 2, 1} + ) where {T <: Number, S <: ElementarySpace} return @autoopt @tensor Rb[Da1 DY1; Da0 DY0] := ( benv[DX1 DY1; DX0 DY0] * a[DX0 Da0; da] * conj(a[DX1 Da1; da]) ) @@ -92,8 +92,8 @@ Construct the tensor ``` """ function _tensor_Sb( - benv::BondEnv{T,S}, a::AbstractTensorMap{T,S,2,1}, a2b2::AbstractTensorMap{T,S,2,2} -) where {T<:Number,S<:ElementarySpace} + benv::BondEnv{T, S}, a::AbstractTensorMap{T, S, 2, 1}, a2b2::AbstractTensorMap{T, S, 2, 2} + ) where {T <: Number, S <: ElementarySpace} return @autoopt @tensor Sb[Da1 DY1; db] := ( benv[DX1 DY1; DX0 DY0] * conj(a[DX1 Da1; da]) * a2b2[DX0 DY0; da db] ) @@ -116,8 +116,8 @@ Calculate the inner product ``` """ function inner_prod( - benv::BondEnv{T,S}, a1b1::AbstractTensorMap{T,S,2,2}, a2b2::AbstractTensorMap{T,S,2,2} -) where {T<:Number,S<:ElementarySpace} + benv::BondEnv{T, S}, a1b1::AbstractTensorMap{T, S, 2, 2}, a2b2::AbstractTensorMap{T, S, 2, 2} + ) where {T <: Number, S <: ElementarySpace} return @autoopt @tensor benv[DX1 DY1; DX0 DY0] * conj(a1b1[DX1 DY1; da db]) * a2b2[DX0 DY0; da db] @@ -134,8 +134,8 @@ Calculate the fidelity between two evolution steps ``` """ function fidelity( - benv::BondEnv{T,S}, a1b1::AbstractTensorMap{T,S,2,2}, a2b2::AbstractTensorMap{T,S,2,2} -) where {T<:Number,S<:ElementarySpace} + benv::BondEnv{T, S}, a1b1::AbstractTensorMap{T, S, 2, 2}, a2b2::AbstractTensorMap{T, S, 2, 2} + ) where {T <: Number, S <: ElementarySpace} b12 = inner_prod(benv, a1b1, a2b2) b11 = inner_prod(benv, a1b1, a1b1) b22 = inner_prod(benv, a2b2, a2b2) @@ -153,13 +153,13 @@ Contract the axis between `a` and `b` tensors ``` """ function _combine_ab( - a::AbstractTensorMap{T,S,2,1}, b::AbstractTensorMap{T,S,1,2} -) where {T<:Number,S<:ElementarySpace} + a::AbstractTensorMap{T, S, 2, 1}, b::AbstractTensorMap{T, S, 1, 2} + ) where {T <: Number, S <: ElementarySpace} return @tensor ab[DX DY; da db] := a[DX da; D] * b[D; db DY] end function _combine_ab( - a::AbstractTensorMap{T,S,2,1}, b::AbstractTensorMap{T,S,2,1} -) where {T<:Number,S<:ElementarySpace} + a::AbstractTensorMap{T, S, 2, 1}, b::AbstractTensorMap{T, S, 2, 1} + ) where {T <: Number, S <: ElementarySpace} return @tensor ab[DX DY; da db] := a[DX D; da] * b[D DY; db] end @@ -173,8 +173,8 @@ Calculate the cost function ``` """ function cost_function_als( - benv::BondEnv{T,S}, a1b1::AbstractTensorMap{T,S,2,2}, a2b2::AbstractTensorMap{T,S,2,2} -) where {T<:Number,S<:ElementarySpace} + benv::BondEnv{T, S}, a1b1::AbstractTensorMap{T, S, 2, 2}, a2b2::AbstractTensorMap{T, S, 2, 2} + ) where {T <: Number, S <: ElementarySpace} t1 = inner_prod(benv, a1b1, a1b1) t2 = inner_prod(benv, a2b2, a2b2) t3 = inner_prod(benv, a1b1, a2b2) @@ -198,10 +198,10 @@ Solve the equations `Rx x = Sx` (x = a, b) with initial guess `x0` ``` """ function _solve_ab( - Rx::AbstractTensorMap{T,S,2,2}, - Sx::AbstractTensorMap{T,S,2,1}, - x0::AbstractTensorMap{T,S,2,1}, -) where {T<:Number,S<:ElementarySpace} + Rx::AbstractTensorMap{T, S, 2, 2}, + Sx::AbstractTensorMap{T, S, 2, 1}, + x0::AbstractTensorMap{T, S, 2, 1}, + ) where {T <: Number, S <: ElementarySpace} f(x) = (@tensor Sx2[-1 -2; -3] := Rx[-1 -2; 1 2] * x[1 2; -3]) x1, info = linsolve(f, Sx, x0, 0, 1) return x1, info diff --git a/src/algorithms/contractions/bondenv/benv_ctm.jl b/src/algorithms/contractions/bondenv/benv_ctm.jl index 549440d74..a936a74f5 100644 --- a/src/algorithms/contractions/bondenv/benv_ctm.jl +++ b/src/algorithms/contractions/bondenv/benv_ctm.jl @@ -49,22 +49,12 @@ function bondenv_fu(row::Int, col::Int, X::PEPSOrth, Y::PEPSOrth, env::CTMRGEnv) C4--χ3--T3X---------χ5---------T3Y--χ7---C3 r+1 c-1 c c+1 c+2 =# - @autoopt @tensor benv[DX1 DY1; DX0 DY0] := ( - c4[χ3 χ1] * - t4[χ1 DWX0 DWX1 χ2] * - c1[χ2 χ4] * - t3X[χ5 DSX0 DSX1 χ3] * - X[DNX0 DX0 DSX0 DWX0] * - conj(X[DNX1 DX1 DSX1 DWX1]) * - t1X[χ4 DNX0 DNX1 χ6] * - c3[χ9 χ7] * - t2[χ10 DEY0 DEY1 χ9] * - c2[χ8 χ10] * - t3Y[χ7 DSY0 DSY1 χ5] * - Y[DNY0 DEY0 DSY0 DY0] * - conj(Y[DNY1 DEY1 DSY1 DY1]) * - t1Y[χ6 DNY0 DNY1 χ8] - ) + @autoopt @tensor benv[DX1 DY1; DX0 DY0] := + c4[χ3 χ1] * t4[χ1 DWX0 DWX1 χ2] * c1[χ2 χ4] * t3X[χ5 DSX0 DSX1 χ3] * + X[DNX0 DX0 DSX0 DWX0] * conj(X[DNX1 DX1 DSX1 DWX1]) * t1X[χ4 DNX0 DNX1 χ6] * + c3[χ9 χ7] * t2[χ10 DEY0 DEY1 χ9] * c2[χ8 χ10] * t3Y[χ7 DSY0 DSY1 χ5] * + Y[DNY0 DEY0 DSY0 DY0] * conj(Y[DNY1 DEY1 DSY1 DY1]) * t1Y[χ6 DNY0 DNY1 χ8] + normalize!(benv, Inf) return benv end diff --git a/src/algorithms/contractions/bondenv/benv_tools.jl b/src/algorithms/contractions/bondenv/benv_tools.jl index 5d8d9d7d9..3d5fc9676 100644 --- a/src/algorithms/contractions/bondenv/benv_tools.jl +++ b/src/algorithms/contractions/bondenv/benv_tools.jl @@ -1,2 +1,2 @@ -const BondEnv{T,S} = AbstractTensorMap{T,S,2,2} where {T<:Number,S<:ElementarySpace} -const PEPSOrth{T,S} = AbstractTensor{T,S,4} where {T<:Number,S<:ElementarySpace} +const BondEnv{T, S} = AbstractTensorMap{T, S, 2, 2} where {T <: Number, S <: ElementarySpace} +const PEPSOrth{T, S} = AbstractTensor{T, S, 4} where {T <: Number, S <: ElementarySpace} diff --git a/src/algorithms/contractions/bondenv/gaugefix.jl b/src/algorithms/contractions/bondenv/gaugefix.jl index 3a2a17d65..c6b7af059 100644 --- a/src/algorithms/contractions/bondenv/gaugefix.jl +++ b/src/algorithms/contractions/bondenv/gaugefix.jl @@ -16,9 +16,9 @@ function positive_approx(benv::BondEnv) D, U = eigh((benv + benv') / 2) # determine if `env` is (mostly) positive or negative sgn = sign(sum(D.data)) - # When optimizing the truncation of a bond, + # When optimizing the truncation of a bond, # its environment can always be multiplied by a number. - # If `benv` is negative (e.g. obtained approximately from CTMRG), + # If `benv` is negative (e.g. obtained approximately from CTMRG), # we can multiply it by (-1). data = D.data @inbounds for i in eachindex(data) @@ -44,10 +44,10 @@ Reference: - Physical Review B 92, 035142 (2015) """ function fixgauge_benv( - Z::AbstractTensorMap{T,S,1,2}, - a::AbstractTensorMap{T,S,1,2}, - b::AbstractTensorMap{T,S,2,1}, -) where {T<:Number,S<:ElementarySpace} + Z::AbstractTensorMap{T, S, 1, 2}, + a::AbstractTensorMap{T, S, 1, 2}, + b::AbstractTensorMap{T, S, 2, 1}, + ) where {T <: Number, S <: ElementarySpace} @assert !isdual(space(Z, 1)) @assert !isdual(space(a, 2)) @assert !isdual(space(b, 2)) @@ -109,11 +109,11 @@ apply the gauge transformation `Linv`, `Rinv` for `Z` to `X`, `Y`: ``` """ function _fixgauge_benvXY( - X::PEPSOrth{T,S}, - Y::PEPSOrth{T,S}, - Linv::AbstractTensorMap{T,S,1,1}, - Rinv::AbstractTensorMap{T,S,1,1}, -) where {T<:Number,S<:ElementarySpace} + X::PEPSOrth{T, S}, + Y::PEPSOrth{T, S}, + Linv::AbstractTensorMap{T, S, 1, 1}, + Rinv::AbstractTensorMap{T, S, 1, 1}, + ) where {T <: Number, S <: ElementarySpace} @plansor X[-1 -2 -3 -4] := X[-1 1 -3 -4] * Rinv[1; -2] @plansor Y[-1 -2 -3 -4] := Y[-1 -2 -3 1] * Linv[1; -4] return X, Y diff --git a/src/algorithms/contractions/ctmrg_contractions.jl b/src/algorithms/contractions/ctmrg_contractions.jl index 53196fc87..1d794e5cc 100644 --- a/src/algorithms/contractions/ctmrg_contractions.jl +++ b/src/algorithms/contractions/ctmrg_contractions.jl @@ -1,7 +1,7 @@ -const CTMRGEdgeTensor{T,S,N} = AbstractTensorMap{T,S,N,1} -const CTMRG_PEPS_EdgeTensor{T,S} = CTMRGEdgeTensor{T,S,3} -const CTMRG_PF_EdgeTensor{T,S} = CTMRGEdgeTensor{T,S,2} -const CTMRGCornerTensor{T,S} = AbstractTensorMap{T,S,1,1} +const CTMRGEdgeTensor{T, S, N} = AbstractTensorMap{T, S, N, 1} +const CTMRG_PEPS_EdgeTensor{T, S} = CTMRGEdgeTensor{T, S, 3} +const CTMRG_PF_EdgeTensor{T, S} = CTMRGEdgeTensor{T, S, 2} +const CTMRGCornerTensor{T, S} = AbstractTensorMap{T, S, 1, 1} # Enlarged corner contractions # ---------------------------- @@ -34,11 +34,9 @@ coordinates, environments and network, or by directly providing the tensors. ``` """ function enlarge_northwest_corner( - E_west::CTMRG_PEPS_EdgeTensor, - C_northwest::CTMRGCornerTensor, - E_north::CTMRG_PEPS_EdgeTensor, - A::PEPSSandwich, -) + E_west::CTMRG_PEPS_EdgeTensor, C_northwest::CTMRGCornerTensor, + E_north::CTMRG_PEPS_EdgeTensor, A::PEPSSandwich, + ) return @tensor begin EC[χS DWt DWb; χ2] := E_west[χS DWt DWb; χ1] * C_northwest[χ1; χ2] @@ -53,11 +51,9 @@ function enlarge_northwest_corner( end end function enlarge_northwest_corner( - E_west::CTMRG_PF_EdgeTensor, - C_northwest::CTMRGCornerTensor, - E_north::CTMRG_PF_EdgeTensor, - A::PFTensor, -) + E_west::CTMRG_PF_EdgeTensor, C_northwest::CTMRGCornerTensor, + E_north::CTMRG_PF_EdgeTensor, A::PFTensor, + ) return @autoopt @tensor corner[χ_S D_S; χ_E D_E] := E_west[χ_S D1; χ1] * C_northwest[χ1; χ2] * E_north[χ2 D2; χ_E] * A[D1 D_S; D2 D_E] end @@ -76,11 +72,9 @@ coordinates, environments and network, or by directly providing the tensors. ``` """ function enlarge_northeast_corner( - E_north::CTMRG_PEPS_EdgeTensor, - C_northeast::CTMRGCornerTensor, - E_east::CTMRG_PEPS_EdgeTensor, - A::PEPSSandwich, -) + E_north::CTMRG_PEPS_EdgeTensor, C_northeast::CTMRGCornerTensor, + E_east::CTMRG_PEPS_EdgeTensor, A::PEPSSandwich, + ) return @tensor begin EC[χW DNt DNb; χ2] := E_north[χW DNt DNb; χ1] * C_northeast[χ1; χ2] @@ -95,11 +89,9 @@ function enlarge_northeast_corner( end end function enlarge_northeast_corner( - E_north::CTMRG_PF_EdgeTensor, - C_northeast::CTMRGCornerTensor, - E_east::CTMRG_PF_EdgeTensor, - A::PFTensor, -) + E_north::CTMRG_PF_EdgeTensor, C_northeast::CTMRGCornerTensor, + E_east::CTMRG_PF_EdgeTensor, A::PFTensor, + ) return @autoopt @tensor corner[χ_W D_W; χ_S D_S] := E_north[χ_W D1; χ1] * C_northeast[χ1; χ2] * E_east[χ2 D2; χ_S] * A[D_W D_S; D1 D2] end @@ -118,11 +110,9 @@ coordinates, environments and network, or by directly providing the tensors. ``` """ function enlarge_southeast_corner( - E_east::CTMRG_PEPS_EdgeTensor, - C_southeast::CTMRGCornerTensor, - E_south::CTMRG_PEPS_EdgeTensor, - A::PEPSSandwich, -) + E_east::CTMRG_PEPS_EdgeTensor, C_southeast::CTMRGCornerTensor, + E_south::CTMRG_PEPS_EdgeTensor, A::PEPSSandwich, + ) return @tensor begin EC[χN DEt DEb; χ2] := E_east[χN DEt DEb; χ1] * C_southeast[χ1; χ2] @@ -137,11 +127,9 @@ function enlarge_southeast_corner( end end function enlarge_southeast_corner( - E_east::CTMRG_PF_EdgeTensor, - C_southeast::CTMRGCornerTensor, - E_south::CTMRG_PF_EdgeTensor, - A::PFTensor, -) + E_east::CTMRG_PF_EdgeTensor, C_southeast::CTMRGCornerTensor, + E_south::CTMRG_PF_EdgeTensor, A::PFTensor, + ) return @autoopt @tensor corner[χ_N D_N; χ_W D_W] := E_east[χ_N D1; χ1] * C_southeast[χ1; χ2] * E_south[χ2 D2; χ_W] * A[D_W D2; D_N D1] end @@ -160,11 +148,9 @@ coordinates, environments and network, or by directly providing the tensors. ``` """ function enlarge_southwest_corner( - E_south::CTMRG_PEPS_EdgeTensor, - C_southwest::CTMRGCornerTensor, - E_west::CTMRG_PEPS_EdgeTensor, - A::PEPSSandwich, -) + E_south::CTMRG_PEPS_EdgeTensor, C_southwest::CTMRGCornerTensor, + E_west::CTMRG_PEPS_EdgeTensor, A::PEPSSandwich, + ) return @tensor begin EC[χE DSt DSb; χ2] := E_south[χE DSt DSb; χ1] * C_southwest[χ1; χ2] @@ -179,11 +165,9 @@ function enlarge_southwest_corner( end end function enlarge_southwest_corner( - E_south::CTMRG_PF_EdgeTensor, - C_southwest::CTMRGCornerTensor, - E_west::CTMRG_PF_EdgeTensor, - A::PFTensor, -) + E_south::CTMRG_PF_EdgeTensor, C_southwest::CTMRGCornerTensor, + E_west::CTMRG_PF_EdgeTensor, A::PFTensor, + ) return @autoopt @tensor corner[χ_E D_E; χ_N D_N] := E_south[χ_E D1; χ1] * C_southwest[χ1; χ2] * E_west[χ2 D2; χ_N] * A[D2 D1; D_N D_E] end @@ -205,22 +189,14 @@ Contract the CTMRG left projector with the higher-dimensional subspace facing to """ function left_projector(E_1, C, E_2, V, isqS, A::PEPSSandwich) return @autoopt @tensor P_left[χ_in D_inabove D_inbelow; χ_out] := - E_1[χ_in D1 D2; χ1] * - C[χ1; χ2] * - E_2[χ2 D3 D4; χ3] * - ket(A)[d; D3 D5 D_inabove D1] * - conj(bra(A)[d; D4 D6 D_inbelow D2]) * - conj(V[χ4; χ3 D5 D6]) * - isqS[χ4; χ_out] + E_1[χ_in D1 D2; χ1] * C[χ1; χ2] * E_2[χ2 D3 D4; χ3] * + ket(A)[d; D3 D5 D_inabove D1] * conj(bra(A)[d; D4 D6 D_inbelow D2]) * + conj(V[χ4; χ3 D5 D6]) * isqS[χ4; χ_out] end function left_projector(E_1, C, E_2, V, isqS, A::PFTensor) return @autoopt @tensor P_left[χ_in D_in; χ_out] := - E_1[χ_in D1; χ1] * - C[χ1; χ2] * - E_2[χ2 D2; χ3] * - A[D1 D_in; D2 D3] * - conj(V[χ4; χ3 D3]) * - isqS[χ4; χ_out] + E_1[χ_in D1; χ1] * C[χ1; χ2] * E_2[χ2 D2; χ3] * + A[D1 D_in; D2 D3] * conj(V[χ4; χ3 D3]) * isqS[χ4; χ_out] end """ @@ -237,22 +213,15 @@ Contract the CTMRG right projector with the higher-dimensional subspace facing t """ function right_projector(E_1, C, E_2, U, isqS, A::PEPSSandwich) return @autoopt @tensor P_right[χ_in; χ_out D_outabove D_outbelow] := - isqS[χ_in; χ1] * - conj(U[χ1; χ2 D1 D2]) * - ket(A)[d; D3 D5 D_outabove D1] * - conj(bra(A)[d; D4 D6 D_outbelow D2]) * - E_2[χ2 D3 D4; χ3] * - C[χ3; χ4] * - E_1[χ4 D5 D6; χ_out] + isqS[χ_in; χ1] * conj(U[χ1; χ2 D1 D2]) * + ket(A)[d; D3 D5 D_outabove D1] * conj(bra(A)[d; D4 D6 D_outbelow D2]) * + E_2[χ2 D3 D4; χ3] * C[χ3; χ4] * E_1[χ4 D5 D6; χ_out] end function right_projector(E_1, C, E_2, U, isqS, A::PFTensor) return @autoopt @tensor P_right[χ_in; χ_out D_out] := - isqS[χ_in; χ1] * - conj(U[χ1; χ2 D1]) * + isqS[χ_in; χ1] * conj(U[χ1; χ2 D1]) * A[D1 D_out; D2 D3] * - E_2[χ2 D2; χ3] * - C[χ3; χ4] * - E_1[χ4 D3; χ_out] + E_2[χ2 D2; χ3] * C[χ3; χ4] * E_1[χ4 D3; χ_out] end """ @@ -319,98 +288,68 @@ Alternatively, contract the environment with a vector `x` acting on it or contract the adjoint environment with `x`, e.g. as needed for iterative solvers. """ function half_infinite_environment( - quadrant1::AbstractTensorMap{T,S,N,N}, quadrant2::AbstractTensorMap{T,S,N,N} -) where {T,S,N} + quadrant1::AbstractTensorMap{T, S, N, N}, quadrant2::AbstractTensorMap{T, S, N, N} + ) where {T, S, N} p = (codomainind(quadrant1), domainind(quadrant1)) return tensorcontract(quadrant1, p, false, quadrant2, p, false, p) end function half_infinite_environment( - C_1, C_2, E_1, E_2, E_3, E_4, A_1::P, A_2::P -) where {P<:PEPSSandwich} + C_1, C_2, E_1, E_2, E_3, E_4, A_1::P, A_2::P + ) where {P <: PEPSSandwich} return @autoopt @tensor env[χ_in D_inabove D_inbelow; χ_out D_outabove D_outbelow] := - E_1[χ_in D1 D2; χ1] * - C_1[χ1; χ2] * - E_2[χ2 D3 D4; χ3] * - ket(A_1)[d1; D3 D9 D_inabove D1] * - conj(bra(A_1)[d1; D4 D10 D_inbelow D2]) * - ket(A_2)[d2; D5 D7 D_outabove D9] * - conj(bra(A_2)[d2; D6 D8 D_outbelow D10]) * - E_3[χ3 D5 D6; χ4] * - C_2[χ4; χ5] * - E_4[χ5 D7 D8; χ_out] + E_1[χ_in D1 D2; χ1] * C_1[χ1; χ2] * E_2[χ2 D3 D4; χ3] * + ket(A_1)[d1; D3 D9 D_inabove D1] * conj(bra(A_1)[d1; D4 D10 D_inbelow D2]) * + ket(A_2)[d2; D5 D7 D_outabove D9] * conj(bra(A_2)[d2; D6 D8 D_outbelow D10]) * + E_3[χ3 D5 D6; χ4] * C_2[χ4; χ5] * E_4[χ5 D7 D8; χ_out] end function half_infinite_environment( - C_1, C_2, E_1, E_2, E_3, E_4, x::AbstractTensor{T,S,3}, A_1::P, A_2::P -) where {T,S,P<:PEPSSandwich} + C_1, C_2, E_1, E_2, E_3, E_4, x::AbstractTensor{T, S, 3}, A_1::P, A_2::P + ) where {T, S, P <: PEPSSandwich} return @autoopt @tensor env_x[χ_in D_inabove D_inbelow] := - E_1[χ_in D1 D2; χ1] * - C_1[χ1; χ2] * - E_2[χ2 D3 D4; χ3] * - ket(A_1)[d1; D3 D9 D_inabove D1] * - conj(bra(A_1)[d1; D4 D10 D_inbelow D2]) * - ket(A_2)[d2; D5 D7 D11 D9] * - conj(bra(A_2)[d2; D6 D8 D12 D10]) * - E_3[χ3 D5 D6; χ4] * - C_2[χ4; χ5] * - E_4[χ5 D7 D8; χ6] * + E_1[χ_in D1 D2; χ1] * C_1[χ1; χ2] * E_2[χ2 D3 D4; χ3] * + ket(A_1)[d1; D3 D9 D_inabove D1] * conj(bra(A_1)[d1; D4 D10 D_inbelow D2]) * + ket(A_2)[d2; D5 D7 D11 D9] * conj(bra(A_2)[d2; D6 D8 D12 D10]) * + E_3[χ3 D5 D6; χ4] * C_2[χ4; χ5] * E_4[χ5 D7 D8; χ6] * x[χ6 D11 D12] end function half_infinite_environment( - x::AbstractTensor{T,S,3}, C_1, C_2, E_1, E_2, E_3, E_4, A_1::P, A_2::P -) where {T,S,P<:PEPSSandwich} + x::AbstractTensor{T, S, 3}, C_1, C_2, E_1, E_2, E_3, E_4, A_1::P, A_2::P + ) where {T, S, P <: PEPSSandwich} return @autoopt @tensor x_env[χ_in D_inabove D_inbelow] := x[χ1 D1 D2] * - conj(E_1[χ1 D3 D4; χ2]) * - conj(C_1[χ2; χ3]) * - conj(E_2[χ3 D5 D6; χ4]) * - conj(ket(A_1)[d1; D5 D11 D1 D3]) * - bra(A_1)[d1; D6 D12 D2 D4] * - conj(ket(A_2)[d2; D7 D9 D_inabove D11]) * - bra(A_2)[d2; D8 D10 D_inbelow D12] * - conj(E_3[χ4 D7 D8; χ5]) * - conj(C_2[χ5; χ6]) * - conj(E_4[χ6 D9 D10; χ_in]) + conj(E_1[χ1 D3 D4; χ2]) * conj(C_1[χ2; χ3]) * conj(E_2[χ3 D5 D6; χ4]) * + conj(ket(A_1)[d1; D5 D11 D1 D3]) * bra(A_1)[d1; D6 D12 D2 D4] * + conj(ket(A_2)[d2; D7 D9 D_inabove D11]) * bra(A_2)[d2; D8 D10 D_inbelow D12] * + conj(E_3[χ4 D7 D8; χ5]) * conj(C_2[χ5; χ6]) * conj(E_4[χ6 D9 D10; χ_in]) end function half_infinite_environment( - C_1, C_2, E_1, E_2, E_3, E_4, A_1::P, A_2::P -) where {P<:PFTensor} + C_1, C_2, E_1, E_2, E_3, E_4, A_1::P, A_2::P + ) where {P <: PFTensor} return @autoopt @tensor env[χ_in D_in; χ_out D_out] := - E_1[χ_in D1; χ1] * - C_1[χ1; χ2] * - E_2[χ2 D3; χ3] * + E_1[χ_in D1; χ1] * C_1[χ1; χ2] * E_2[χ2 D3; χ3] * A_1[D1 D_in; D3 D9] * A_2[D9 D_out; D5 D7] * - E_3[χ3 D5; χ4] * - C_2[χ4; χ5] * - E_4[χ5 D7; χ_out] + E_3[χ3 D5; χ4] * C_2[χ4; χ5] * E_4[χ5 D7; χ_out] end function half_infinite_environment( - C_1, C_2, E_1, E_2, E_3, E_4, x::AbstractTensor{T,S,2}, A_1::P, A::P -) where {T,S,P<:PFTensor} + C_1, C_2, E_1, E_2, E_3, E_4, x::AbstractTensor{T, S, 2}, A_1::P, A::P + ) where {T, S, P <: PFTensor} return @autoopt @tensor env_x[χ_in D_in] := - E_1[χ_in D1; χ1] * - C_1[χ1; χ2] * - E_2[χ2 D3; χ3] * + E_1[χ_in D1; χ1] * C_1[χ1; χ2] * E_2[χ2 D3; χ3] * A_1[D1 D_in; D3 D9] * A_2[D9 D11; D5 D7] * - E_3[χ3 D5; χ4] * - C_2[χ4; χ5] * - E_4[χ5 D7; χ6] * + E_3[χ3 D5; χ4] * C_2[χ4; χ5] * E_4[χ5 D7; χ6] * x[χ6 D11] end function half_infinite_environment( - x::AbstractTensor{T,S,2}, C_1, C_2, E_1, E_2, E_3, E_4, A_1::P, A_2::P -) where {T,S,P<:PFTensor} + x::AbstractTensor{T, S, 2}, C_1, C_2, E_1, E_2, E_3, E_4, A_1::P, A_2::P + ) where {T, S, P <: PFTensor} return @autoopt @tensor env_x[χ_in D_in] := x[χ1 D1 D2] * - conj(E_1[χ1 D3; χ2]) * - conj(C_1[χ2; χ3]) * - conj(E_2[χ3 D5; χ4]) * + conj(E_1[χ1 D3; χ2]) * conj(C_1[χ2; χ3]) * conj(E_2[χ3 D5; χ4]) * conj(A_1[D3 D1; D5 D11]) * conj(A_2[D11 D_in; D7 D9]) * - conj(E_3[χ4 D7; χ5]) * - conj(C_2[χ5; χ6]) * - conj(E_4[χ6 D9; χ_in]) + conj(E_3[χ4 D7; χ5]) * conj(C_2[χ5; χ6]) * conj(E_4[χ6 D9; χ_in]) end """ @@ -481,11 +420,9 @@ Alternatively, contract the environment with a vector `x` acting on it or contract the adjoint environment with `x`, e.g. as needed for iterative solvers. """ @generated function full_infinite_environment( - quadrant1::AbstractTensorMap{T,S,N,N}, - quadrant2::AbstractTensorMap{T,S,N,N}, - quadrant3::AbstractTensorMap{T,S,N,N}, - quadrant4::AbstractTensorMap{T,S,N,N}, -) where {T,S,N} + quadrant1::AbstractTensorMap{T, S, N, N}, quadrant2::AbstractTensorMap{T, S, N, N}, + quadrant3::AbstractTensorMap{T, S, N, N}, quadrant4::AbstractTensorMap{T, S, N, N}, + ) where {T, S, N} env_e = tensorexpr( :env, (envlabel(:out), ntuple(i -> virtuallabel(:out, i), N - 1)...), @@ -520,245 +457,107 @@ or contract the adjoint environment with `x`, e.g. as needed for iterative solve ) end function full_infinite_environment( - half1::AbstractTensorMap{T,S,N}, half2::AbstractTensorMap{T,S,N} -) where {T,S,N} + half1::AbstractTensorMap{T, S, N}, half2::AbstractTensorMap{T, S, N} + ) where {T, S, N} return half_infinite_environment(half1, half2) end function full_infinite_environment( - C_1, - C_2, - C_3, - C_4, - E_1, - E_2, - E_3, - E_4, - E_5, - E_6, - E_7, - E_8, - A_1::P, - A_2::P, - A_3::P, - A_4::P, -) where {P<:PEPSSandwich} + C_1, C_2, C_3, C_4, + E_1, E_2, E_3, E_4, E_5, E_6, E_7, E_8, + A_1::P, A_2::P, A_3::P, A_4::P, + ) where {P <: PEPSSandwich} return @autoopt @tensor env[χ_in D_inabove D_inbelow; χ_out D_outabove D_outbelow] := - E_1[χ_in D1 D2; χ1] * - C_1[χ1; χ2] * - E_2[χ2 D3 D4; χ3] * - ket(A_1)[d1; D3 D11 D_inabove D1] * - conj(bra(A_1)[d1; D4 D12 D_inbelow D2]) * - ket(A_2)[d2; D5 D7 D9 D11] * - conj(bra(A_2)[d2; D6 D8 D10 D12]) * - E_3[χ3 D5 D6; χ4] * - C_2[χ4; χ5] * - E_4[χ5 D7 D8; χ6] * - E_5[χ6 D13 D14; χ7] * - C_3[χ7; χ8] * - E_6[χ8 D15 D16; χ9] * - ket(A_3)[d3; D9 D13 D15 D17] * - conj(bra(A_3)[d3; D10 D14 D16 D18]) * - ket(A_4)[d4; D_outabove D17 D19 D21] * - conj(bra(A_4)[d4; D_outbelow D18 D20 D22]) * - E_7[χ9 D19 D20; χ10] * - C_4[χ10; χ11] * - E_8[χ11 D21 D22; χ_out] + E_1[χ_in D1 D2; χ1] * C_1[χ1; χ2] * E_2[χ2 D3 D4; χ3] * + ket(A_1)[d1; D3 D11 D_inabove D1] * conj(bra(A_1)[d1; D4 D12 D_inbelow D2]) * + ket(A_2)[d2; D5 D7 D9 D11] * conj(bra(A_2)[d2; D6 D8 D10 D12]) * + E_3[χ3 D5 D6; χ4] * C_2[χ4; χ5] * E_4[χ5 D7 D8; χ6] * + E_5[χ6 D13 D14; χ7] * C_3[χ7; χ8] * E_6[χ8 D15 D16; χ9] * + ket(A_3)[d3; D9 D13 D15 D17] * conj(bra(A_3)[d3; D10 D14 D16 D18]) * + ket(A_4)[d4; D_outabove D17 D19 D21] * conj(bra(A_4)[d4; D_outbelow D18 D20 D22]) * + E_7[χ9 D19 D20; χ10] * C_4[χ10; χ11] * E_8[χ11 D21 D22; χ_out] end function full_infinite_environment( - C_1, - C_2, - C_3, - C_4, - E_1, - E_2, - E_3, - E_4, - E_5, - E_6, - E_7, - E_8, - x::AbstractTensor{T,S,3}, - A_1::P, - A_2::P, - A_3::P, - A_4::P, -) where {T,S,P<:PEPSSandwich} + C_1, C_2, C_3, C_4, + E_1, E_2, E_3, E_4, E_5, E_6, E_7, E_8, + x::AbstractTensor{T, S, 3}, + A_1::P, A_2::P, A_3::P, A_4::P, + ) where {T, S, P <: PEPSSandwich} return @autoopt @tensor env_x[χ_in D_inabove D_inbelow] := - E_1[χ_in D1 D2; χ1] * - C_1[χ1; χ2] * - E_2[χ2 D3 D4; χ3] * - ket(A_1)[d1; D3 D11 D_inabove D1] * - conj(bra(A_1)[d1; D4 D12 D_inbelow D2]) * - ket(A_2)[d2; D5 D7 D9 D11] * - conj(bra(A_2)[d2; D6 D8 D10 D12]) * - E_3[χ3 D5 D6; χ4] * - C_2[χ4; χ5] * - E_4[χ5 D7 D8; χ6] * - E_5[χ6 D13 D14; χ7] * - C_3[χ7; χ8] * - E_6[χ8 D15 D16; χ9] * - ket(A_3)[d3; D9 D13 D15 D17] * - conj(bra_3[d3; D10 D14 D16 D18]) * - ket(A_4)[d4; D_xabove D17 D19 D21] * - conj(bra(A_4)[d4; D_xbelow D18 D20 D22]) * - E_7[χ9 D19 D20; χ10] * - C_4[χ10; χ11] * - E_8[χ11 D21 D22; χ_x] * + E_1[χ_in D1 D2; χ1] * C_1[χ1; χ2] * E_2[χ2 D3 D4; χ3] * + ket(A_1)[d1; D3 D11 D_inabove D1] * conj(bra(A_1)[d1; D4 D12 D_inbelow D2]) * + ket(A_2)[d2; D5 D7 D9 D11] * conj(bra(A_2)[d2; D6 D8 D10 D12]) * + E_3[χ3 D5 D6; χ4] * C_2[χ4; χ5] * E_4[χ5 D7 D8; χ6] * + E_5[χ6 D13 D14; χ7] * C_3[χ7; χ8] * E_6[χ8 D15 D16; χ9] * + ket(A_3)[d3; D9 D13 D15 D17] * conj(bra_3[d3; D10 D14 D16 D18]) * + ket(A_4)[d4; D_xabove D17 D19 D21] * conj(bra(A_4)[d4; D_xbelow D18 D20 D22]) * + E_7[χ9 D19 D20; χ10] * C_4[χ10; χ11] * E_8[χ11 D21 D22; χ_x] * x[χ_x D_xabove D_xbelow] end function full_infinite_environment( - x::AbstractTensor{T,S,3}, - C_1, - C_2, - C_3, - C_4, - E_1, - E_2, - E_3, - E_4, - E_5, - E_6, - E_7, - E_8, - A_1::P, - A_2::P, - A_3::P, - A_4::P, -) where {T,S,P<:PEPSSandwich} + x::AbstractTensor{T, S, 3}, + C_1, C_2, C_3, C_4, + E_1, E_2, E_3, E_4, E_5, E_6, E_7, E_8, + A_1::P, A_2::P, A_3::P, A_4::P, + ) where {T, S, P <: PEPSSandwich} return @autoopt @tensor x_env[χ_in D_inabove D_inbelow] := x[χ_x D_xabove D_xbelow] * - E_1[χ_x D1 D2; χ1] * - C_1[χ1; χ2] * - E_2[χ2 D3 D4; χ3] * - ket(A_1)[d1; D3 D11 D_xabove D1] * - conj(bra(A_1)[d1; D4 D12 D_xbelow D2]) * - ket(A_2)[d2; D5 D7 D9 D11] * - conj(bra(A_2)[d2; D6 D8 D10 D12]) * - E_3[χ3 D5 D6; χ4] * - C_2[χ4; χ5] * - E_4[χ5 D7 D8; χ6] * - E_5[χ6 D13 D14; χ7] * - C_3[χ7; χ8] * - E_6[χ8 D15 D16; χ9] * - ket(A_3)[d3; D9 D13 D15 D17] * - conj(bra(A_3)[d3; D10 D14 D16 D18]) * - ket(A_4)[d4; D_inabove D17 D19 D21] * - conj(bra(A_4)[d4; D_inbelow D18 D20 D22]) * - E_7[χ9 D19 D20; χ10] * - C_4[χ10; χ11] * - E_8[χ11 D21 D22; χ_in] + E_1[χ_x D1 D2; χ1] * C_1[χ1; χ2] * E_2[χ2 D3 D4; χ3] * + ket(A_1)[d1; D3 D11 D_xabove D1] * conj(bra(A_1)[d1; D4 D12 D_xbelow D2]) * + ket(A_2)[d2; D5 D7 D9 D11] * conj(bra(A_2)[d2; D6 D8 D10 D12]) * + E_3[χ3 D5 D6; χ4] * C_2[χ4; χ5] * E_4[χ5 D7 D8; χ6] * + E_5[χ6 D13 D14; χ7] * C_3[χ7; χ8] * E_6[χ8 D15 D16; χ9] * + ket(A_3)[d3; D9 D13 D15 D17] * conj(bra(A_3)[d3; D10 D14 D16 D18]) * + ket(A_4)[d4; D_inabove D17 D19 D21] * conj(bra(A_4)[d4; D_inbelow D18 D20 D22]) * + E_7[χ9 D19 D20; χ10] * C_4[χ10; χ11] * E_8[χ11 D21 D22; χ_in] end function full_infinite_environment( - C_1, - C_2, - C_3, - C_4, - E_1, - E_2, - E_3, - E_4, - E_5, - E_6, - E_7, - E_8, - A_1::P, - A_2::P, - A_3::P, - A_4::P, -) where {P<:PFTensor} + C_1, C_2, C_3, C_4, + E_1, E_2, E_3, E_4, E_5, E_6, E_7, E_8, + A_1::P, A_2::P, A_3::P, A_4::P, + ) where {P <: PFTensor} return @autoopt @tensor env[χ_in D_in; χ_out D_out] := - E_1[χ_in D1; χ1] * - C_1[χ1; χ2] * - E_2[χ2 D3; χ3] * + E_1[χ_in D1; χ1] * C_1[χ1; χ2] * E_2[χ2 D3; χ3] * A_1[D1 D_in; D3 D11] * A_2[D11 D9; D5 D7] * - E_3[χ3 D5; χ4] * - C_2[χ4; χ5] * - E_4[χ5 D7; χ6] * - E_5[χ6 D13; χ7] * - C_3[χ7; χ8] * - E_6[χ8 D15; χ9] * + E_3[χ3 D5; χ4] * C_2[χ4; χ5] * E_4[χ5 D7; χ6] * + E_5[χ6 D13; χ7] * C_3[χ7; χ8] * E_6[χ8 D15; χ9] * A_3[D17 D15; D9 D13] * A_4[D21 D19; D_out D17] * - E_7[χ9 D19; χ10] * - C_4[χ10; χ11] * - E_8[χ11 D21; χ_out] + E_7[χ9 D19; χ10] * C_4[χ10; χ11] * E_8[χ11 D21; χ_out] end function full_infinite_environment( - C_1, - C_2, - C_3, - C_4, - E_1, - E_2, - E_3, - E_4, - E_5, - E_6, - E_7, - E_8, - x::AbstractTensor{T,S,2}, - A_1::P, - A_2::P, - A_3::P, - A_4::P, -) where {T,S,P<:PFTensor} + C_1, C_2, C_3, C_4, + E_1, E_2, E_3, E_4, E_5, E_6, E_7, E_8, + x::AbstractTensor{T, S, 2}, + A_1::P, A_2::P, A_3::P, A_4::P, + ) where {T, S, P <: PFTensor} return @autoopt @tensor env_x[χ_in D_in] := - E_1[χ_in D1; χ1] * - C_1[χ1; χ2] * - E_2[χ2 D3; χ3] * + E_1[χ_in D1; χ1] * C_1[χ1; χ2] * E_2[χ2 D3; χ3] * A_1[D1 D_in; D3 D11] * A_2[D11 D9; D5 D7] * - E_3[χ3 D5; χ4] * - C_2[χ4; χ5] * - E_4[χ5 D7; χ6] * - E_5[χ6 D13; χ7] * - C_3[χ7; χ8] * - E_6[χ8 D15; χ9] * + E_3[χ3 D5; χ4] * C_2[χ4; χ5] * E_4[χ5 D7; χ6] * + E_5[χ6 D13; χ7] * C_3[χ7; χ8] * E_6[χ8 D15; χ9] * A_3[D17 D15; D9 D13] * A_4[D21 D19; D_x D17] * - E_7[χ9 D19; χ10] * - C_4[χ10; χ11] * - E_8[χ11 D21; χ_x] * + E_7[χ9 D19; χ10] * C_4[χ10; χ11] * E_8[χ11 D21; χ_x] * x[χ_x D_x] end function full_infinite_environment( - x::AbstractTensor{T,S,2}, - C_1, - C_2, - C_3, - C_4, - E_1, - E_2, - E_3, - E_4, - E_5, - E_6, - E_7, - E_8, - A_1::P, - A_2::P, - A_3::P, - A_4::P, -) where {T,S,P<:PFTensor} + x::AbstractTensor{T, S, 2}, + C_1, C_2, C_3, C_4, + E_1, E_2, E_3, E_4, E_5, E_6, E_7, E_8, + A_1::P, A_2::P, A_3::P, A_4::P, + ) where {T, S, P <: PFTensor} return @autoopt @tensor x_env[χ_in D_in] := x[χ_x D_x] * - E_1[χ_x D1; χ1] * - C_1[χ1; χ2] * - E_2[χ2 D3; χ3] * + E_1[χ_x D1; χ1] * C_1[χ1; χ2] * E_2[χ2 D3; χ3] * A_1[D1 D_x; D3 D11] * A_2[D11 D9; D5 D7] * - E_3[χ3 D5; χ4] * - C_2[χ4; χ5] * - E_4[χ5 D7; χ6] * - E_5[χ6 D13; χ7] * - C_3[χ7; χ8] * - E_6[χ8 D15; χ9] * + E_3[χ3 D5; χ4] * C_2[χ4; χ5] * E_4[χ5 D7; χ6] * + E_5[χ6 D13; χ7] * C_3[χ7; χ8] * E_6[χ8 D15; χ9] * A_3[D17 D15; D9 D13] * A_4[D21 D19; D_in D17] * - E_7[χ9 D19; χ10] * - C_4[χ10; χ11] * - E_8[χ11 D21; χ_in] + E_7[χ9 D19; χ10] * C_4[χ10; χ11] * E_8[χ11 D21; χ_in] end # Renormalization contractions @@ -781,10 +580,10 @@ Apply projectors to each side of a quadrant. ``` """ @generated function renormalize_corner( - quadrant::AbstractTensorMap{<:Any,S,N,N}, - P_left::AbstractTensorMap{<:Any,S,N,1}, - P_right::AbstractTensorMap{<:Any,S,1,N}, -) where {S,N} + quadrant::AbstractTensorMap{<:Any, S, N, N}, + P_left::AbstractTensorMap{<:Any, S, N, 1}, + P_right::AbstractTensorMap{<:Any, S, 1, N}, + ) where {S, N} corner_e = tensorexpr(:corner, (envlabel(:out),), (envlabel(:in),)) P_right_e = tensorexpr( :P_right, @@ -842,30 +641,25 @@ function renormalize_northwest_corner((row, col), enlarged_env, P_left, P_right) ) end function renormalize_northwest_corner( - quadrant::AbstractTensorMap{T,S,N,N}, P_left, P_right -) where {T,S,N} + quadrant::AbstractTensorMap{T, S, N, N}, P_left, P_right + ) where {T, S, N} return renormalize_corner(quadrant, P_left, P_right) end function renormalize_northwest_corner( - E_west, C_northwest, E_north, P_left, P_right, A::PEPSSandwich -) + E_west, C_northwest, E_north, P_left, P_right, A::PEPSSandwich + ) return @autoopt @tensor corner[χ_in; χ_out] := P_right[χ_in; χ1 D1 D2] * - E_west[χ1 D3 D4; χ2] * - C_northwest[χ2; χ3] * - E_north[χ3 D5 D6; χ4] * - ket(A)[d; D5 D7 D1 D3] * - conj(bra(A)[d; D6 D8 D2 D4]) * + E_west[χ1 D3 D4; χ2] * C_northwest[χ2; χ3] * E_north[χ3 D5 D6; χ4] * + ket(A)[d; D5 D7 D1 D3] * conj(bra(A)[d; D6 D8 D2 D4]) * P_left[χ4 D7 D8; χ_out] end function renormalize_northwest_corner( - E_west, C_northwest, E_north, P_left, P_right, A::PFTensor -) + E_west, C_northwest, E_north, P_left, P_right, A::PFTensor + ) return @autoopt @tensor corner[χ_in; χ_out] := P_right[χ_in; χ1 D1] * - E_west[χ1 D3; χ2] * - C_northwest[χ2; χ3] * - E_north[χ3 D5; χ4] * + E_west[χ1 D3; χ2] * C_northwest[χ2; χ3] * E_north[χ3 D5; χ4] * A[D3 D1; D5 D7] * P_left[χ4 D7; χ_out] end @@ -906,31 +700,26 @@ function renormalize_northeast_corner((row, col), enlarged_env, P_left, P_right) end function renormalize_northeast_corner( - quadrant::AbstractTensorMap{T,S,N,N}, P_left, P_right -) where {T,S,N} + quadrant::AbstractTensorMap{T, S, N, N}, P_left, P_right + ) where {T, S, N} return renormalize_corner(quadrant, P_left, P_right) end function renormalize_northeast_corner( - E_north, C_northeast, E_east, P_left, P_right, A::PEPSSandwich -) + E_north, C_northeast, E_east, P_left, P_right, A::PEPSSandwich + ) return @autoopt @tensor corner[χ_in; χ_out] := P_right[χ_in; χ1 D1 D2] * - E_north[χ1 D3 D4; χ2] * - C_northeast[χ2; χ3] * - E_east[χ3 D5 D6; χ4] * - ket(A)[d; D3 D5 D7 D1] * - conj(bra(A)[d; D4 D6 D8 D2]) * + E_north[χ1 D3 D4; χ2] * C_northeast[χ2; χ3] * E_east[χ3 D5 D6; χ4] * + ket(A)[d; D3 D5 D7 D1] * conj(bra(A)[d; D4 D6 D8 D2]) * P_left[χ4 D7 D8; χ_out] end function renormalize_northeast_corner( - E_north, C_northeast, E_east, P_left, P_right, A::PFTensor -) + E_north, C_northeast, E_east, P_left, P_right, A::PFTensor + ) return @autoopt @tensor corner[χ_in; χ_out] := P_right[χ_in; χ1 D1] * - E_north[χ1 D3; χ2] * - C_northeast[χ2; χ3] * - E_east[χ3 D5; χ4] * + E_north[χ1 D3; χ2] * C_northeast[χ2; χ3] * E_east[χ3 D5; χ4] * A[D1 D7; D3 D5] * P_left[χ4 D7; χ_out] end @@ -970,30 +759,25 @@ function renormalize_southeast_corner((row, col), enlarged_env, P_left, P_right) ) end function renormalize_southeast_corner( - quadrant::AbstractTensorMap{T,S,N,N}, P_left, P_right -) where {T,S,N} + quadrant::AbstractTensorMap{T, S, N, N}, P_left, P_right + ) where {T, S, N} return renormalize_corner(quadrant, P_left, P_right) end function renormalize_southeast_corner( - E_east, C_southeast, E_south, P_left, P_right, A::PEPSSandwich -) + E_east, C_southeast, E_south, P_left, P_right, A::PEPSSandwich + ) return @autoopt @tensor corner[χ_in; χ_out] := P_right[χ_in; χ1 D1 D2] * - E_east[χ1 D3 D4; χ2] * - C_southeast[χ2; χ3] * - E_south[χ3 D5 D6; χ4] * - ket(A)[d; D1 D3 D5 D7] * - conj(bra(A)[d; D2 D4 D6 D8]) * + E_east[χ1 D3 D4; χ2] * C_southeast[χ2; χ3] * E_south[χ3 D5 D6; χ4] * + ket(A)[d; D1 D3 D5 D7] * conj(bra(A)[d; D2 D4 D6 D8]) * P_left[χ4 D7 D8; χ_out] end function renormalize_southeast_corner( - E_east, C_southeast, E_south, P_left, P_right, A::PFTensor -) + E_east, C_southeast, E_south, P_left, P_right, A::PFTensor + ) return @autoopt @tensor corner[χ_in; χ_out] := P_right[χ_in; χ1 D1] * - E_east[χ1 D3; χ2] * - C_southeast[χ2; χ3] * - E_south[χ3 D5; χ4] * + E_east[χ1 D3; χ2] * C_southeast[χ2; χ3] * E_south[χ3 D5; χ4] * A[D7 D5; D1 D3] * P_left[χ4 D7; χ_out] end @@ -1033,30 +817,25 @@ function renormalize_southwest_corner((row, col), enlarged_env, P_left, P_right) ) end function renormalize_southwest_corner( - quadrant::AbstractTensorMap{T,S,N,N}, P_left, P_right -) where {T,S,N} + quadrant::AbstractTensorMap{T, S, N, N}, P_left, P_right + ) where {T, S, N} return renormalize_southwest_corner(quadrant, P_left, P_right) end function renormalize_southwest_corner( - E_south, C_southwest, E_west, P_left, P_right, A::PEPSSandwich -) + E_south, C_southwest, E_west, P_left, P_right, A::PEPSSandwich + ) return @autoopt @tensor corner[χ_in; χ_out] := P_right[χ_in; χ1 D1 D2] * - E_south[χ1 D3 D4; χ2] * - C_southwest[χ2; χ3] * - E_west[χ3 D5 D6; χ4] * - ket(A)[d; D7 D1 D3 D5] * - conj(bra(A)[d; D8 D2 D4 D6]) * + E_south[χ1 D3 D4; χ2] * C_southwest[χ2; χ3] * E_west[χ3 D5 D6; χ4] * + ket(A)[d; D7 D1 D3 D5] * conj(bra(A)[d; D8 D2 D4 D6]) * P_left[χ4 D7 D8; χ_out] end function renormalize_southwest_corner( - E_south, C_southwest, E_west, P_left, P_right, A::PFTensor -) + E_south, C_southwest, E_west, P_left, P_right, A::PFTensor + ) return @autoopt @tensor corner[χ_in; χ_out] := P_right[χ_in; χ1 D1] * - E_south[χ1 D3; χ2] * - C_southwest[χ2; χ3] * - E_west[χ3 D5; χ4] * + E_south[χ1 D3; χ2] * C_southwest[χ2; χ3] * E_west[χ3 D5; χ4] * A[D5 D3; D7 D1] * P_left[χ4 D7; χ_out] end @@ -1080,10 +859,10 @@ function renormalize_bottom_corner((row, col), env::CTMRGEnv, projectors) return renormalize_bottom_corner(C_southwest, E_south, P_bottom) end @generated function renormalize_bottom_corner( - C_southwest::CTMRGCornerTensor{<:Any,S}, - E_south::CTMRGEdgeTensor{<:Any,S,N}, - P_bottom::AbstractTensorMap{<:Any,S,N,1}, -) where {S,N} + C_southwest::CTMRGCornerTensor{<:Any, S}, + E_south::CTMRGEdgeTensor{<:Any, S, N}, + P_bottom::AbstractTensorMap{<:Any, S, N, 1}, + ) where {S, N} C_out_e = tensorexpr(:corner, (envlabel(:out),), (envlabel(:in),)) C_southwest_e = tensorexpr(:C_southwest, (envlabel(:SSW),), (envlabel(:WSW),)) E_south_e = tensorexpr( @@ -1121,10 +900,10 @@ function renormalize_top_corner((row, col), env::CTMRGEnv, projectors) return renormalize_top_corner(C_northwest, E_north, P_top) end @generated function renormalize_top_corner( - C_northwest::CTMRGCornerTensor{<:Any,S}, - E_north::CTMRGEdgeTensor{<:Any,S,N}, - P_top::AbstractTensorMap{<:Any,S,1,N}, -) where {S,N} + C_northwest::CTMRGCornerTensor{<:Any, S}, + E_north::CTMRGEdgeTensor{<:Any, S, N}, + P_top::AbstractTensorMap{<:Any, S, 1, N}, + ) where {S, N} C_out_e = tensorexpr(:corner, (envlabel(:out),), (envlabel(:in),)) C_northwest_e = tensorexpr(:C_northwest, (envlabel(:WNW),), (envlabel(:NNW),)) E_north_e = tensorexpr( @@ -1156,8 +935,8 @@ environment tensors. ``` """ function renormalize_north_edge( - (row, col), env::CTMRGEnv, P_left, P_right, network::InfiniteSquareNetwork -) + (row, col), env::CTMRGEnv, P_left, P_right, network::InfiniteSquareNetwork + ) return renormalize_north_edge( env.edges[NORTH, _prev(row, end), col], P_left[NORTH, row, col], @@ -1188,8 +967,8 @@ environment tensors. ``` """ function renormalize_east_edge( - (row, col), env::CTMRGEnv, P_bottom, P_top, network::InfiniteSquareNetwork -) + (row, col), env::CTMRGEnv, P_bottom, P_top, network::InfiniteSquareNetwork + ) return renormalize_east_edge( env.edges[EAST, row, _next(col, end)], P_bottom[EAST, row, col, end], @@ -1218,8 +997,8 @@ environment tensors. ``` """ function renormalize_south_edge( - (row, col), env::CTMRGEnv, P_left, P_right, network::InfiniteSquareNetwork -) + (row, col), env::CTMRGEnv, P_left, P_right, network::InfiniteSquareNetwork + ) return renormalize_south_edge( env.edges[SOUTH, _next(row, end), col], P_left[SOUTH, row, col], @@ -1251,12 +1030,8 @@ environment tensors. ``` """ function renormalize_west_edge( # For simultaneous CTMRG scheme - (row, col), - env::CTMRGEnv, - P_bottom::Array{Pb,3}, - P_top::Array{Pt,3}, - network::InfiniteSquareNetwork, -) where {Pt,Pb} + (row, col), env::CTMRGEnv, P_bottom::Array{Pb, 3}, P_top::Array{Pt, 3}, network::InfiniteSquareNetwork, + ) where {Pt, Pb} return renormalize_west_edge( env.edges[WEST, row, _prev(col, end)], P_bottom[WEST, row, col], @@ -1265,11 +1040,8 @@ function renormalize_west_edge( # For simultaneous CTMRG scheme ) end function renormalize_west_edge( # For sequential CTMRG scheme - (row, col), - env::CTMRGEnv, - projectors, - network::InfiniteSquareNetwork, -) + (row, col), env::CTMRGEnv, projectors, network::InfiniteSquareNetwork, + ) return renormalize_west_edge( env.edges[WEST, row, _prev(col, end)], projectors[1][row], @@ -1278,8 +1050,8 @@ function renormalize_west_edge( # For sequential CTMRG scheme ) end function renormalize_west_edge( - E_west::CTMRG_PEPS_EdgeTensor, P_bottom, P_top, A::PEPSSandwich -) + E_west::CTMRG_PEPS_EdgeTensor, P_bottom, P_top, A::PEPSSandwich + ) # starting with P_top to save one permute in the end return @tensor begin # already putting χE in front here to make next permute cheaper @@ -1317,9 +1089,9 @@ Multiply corner tensor with incoming and outgoing gauge signs. ``` """ function fix_gauge_corner( - corner::CTMRGCornerTensor, σ_in::CTMRGCornerTensor, σ_out::CTMRGCornerTensor -) - @autoopt @tensor corner_fix[χ_in; χ_out] := + corner::CTMRGCornerTensor, σ_in::CTMRGCornerTensor, σ_out::CTMRGCornerTensor + ) + return @autoopt @tensor corner_fix[χ_in; χ_out] := σ_in[χ_in; χ1] * corner[χ1; χ2] * conj(σ_out[χ_out; χ2]) end @@ -1387,8 +1159,8 @@ Multiply edge tensor with incoming and outgoing gauge signs. ``` """ @generated function fix_gauge_edge( - edge::CTMRGEdgeTensor{T,S,N}, σ_in::CTMRGCornerTensor, σ_out::CTMRGCornerTensor -) where {T,S,N} + edge::CTMRGEdgeTensor{T, S, N}, σ_in::CTMRGCornerTensor, σ_out::CTMRGCornerTensor + ) where {T, S, N} edge_fix_e = tensorexpr( :edge_fix, (envlabel(:in), ntuple(i -> virtuallabel(i), N - 1)...), @@ -1412,9 +1184,7 @@ Apply `fix_gauge_edge` to the north edge with appropriate row and column indices """ function fix_gauge_north_edge((row, col), env::CTMRGEnv, signs) return fix_gauge_edge( - env.edges[NORTH, row, col], - signs[NORTH, row, col], - signs[NORTH, row, _next(col, end)], + env.edges[NORTH, row, col], signs[NORTH, row, col], signs[NORTH, row, _next(col, end)], ) end @@ -1436,9 +1206,7 @@ Apply `fix_gauge_edge` to the south edge with appropriate row and column indices """ function fix_gauge_south_edge((row, col), env::CTMRGEnv, signs) return fix_gauge_edge( - env.edges[SOUTH, row, col], - signs[SOUTH, row, col], - signs[SOUTH, row, _prev(col, end)], + env.edges[SOUTH, row, col], signs[SOUTH, row, col], signs[SOUTH, row, _prev(col, end)], ) end @@ -1535,7 +1303,7 @@ end ## PEPS tensor expressions -function _virtual_labels(dir, layer, args...; contract=nothing) +function _virtual_labels(dir, layer, args...; contract = nothing) return isnothing(contract) ? (dir, layer, args...) : (contract, layer) end _north_labels(args...; kwargs...) = _virtual_labels(:N, args...; kwargs...) @@ -1545,46 +1313,37 @@ _west_labels(args...; kwargs...) = _virtual_labels(:W, args...; kwargs...) # layer=:top for ket PEPS, layer=:bot for bra PEPS, connects to PEPO slice h function _pepo_pepstensor_expr( - tensorname, - layer::Symbol, - h::Int, - args...; - contract_north=nothing, - contract_east=nothing, - contract_south=nothing, - contract_west=nothing, -) + tensorname, layer::Symbol, h::Int, args...; + contract_north = nothing, contract_east = nothing, + contract_south = nothing, contract_west = nothing, + ) return tensorexpr( tensorname, (physicallabel(h, args...),), ( - virtuallabel(_north_labels(layer, args...; contract=contract_north)...), - virtuallabel(_east_labels(layer, args...; contract=contract_east)...), - virtuallabel(_south_labels(layer, args...; contract=contract_south)...), - virtuallabel(_west_labels(layer, args...; contract=contract_west)...), + virtuallabel(_north_labels(layer, args...; contract = contract_north)...), + virtuallabel(_east_labels(layer, args...; contract = contract_east)...), + virtuallabel(_south_labels(layer, args...; contract = contract_south)...), + virtuallabel(_west_labels(layer, args...; contract = contract_west)...), ), ) end # PEPO slice h function _pepo_pepotensor_expr( - tensorname, - h::Int, - args...; - contract_north=nothing, - contract_east=nothing, - contract_south=nothing, - contract_west=nothing, -) + tensorname, h::Int, args...; + contract_north = nothing, contract_east = nothing, + contract_south = nothing, contract_west = nothing, + ) layer = Symbol(:mid, :_, h) return tensorexpr( tensorname, (physicallabel(h + 1, args...), physicallabel(h, args...)), ( - virtuallabel(_north_labels(layer, args...; contract=contract_north)...), - virtuallabel(_east_labels(layer, args...; contract=contract_east)...), - virtuallabel(_south_labels(layer, args...; contract=contract_south)...), - virtuallabel(_west_labels(layer, args...; contract=contract_west)...), + virtuallabel(_north_labels(layer, args...; contract = contract_north)...), + virtuallabel(_east_labels(layer, args...; contract = contract_east)...), + virtuallabel(_south_labels(layer, args...; contract = contract_south)...), + virtuallabel(_west_labels(layer, args...; contract = contract_west)...), ), ) end @@ -1626,8 +1385,8 @@ end ## Enlarged corner (quadrant) expressions function _pepo_enlarged_corner_expr( - cornername, codom_label, dom_label, codom_dir, dom_dir, H::Int, args... -) + cornername, codom_label, dom_label, codom_dir, dom_dir, H::Int, args... + ) return tensorexpr( cornername, ( @@ -1648,16 +1407,9 @@ end ## Environment expressions function _pepo_env_expr( - envname, - codom_label, - dom_label, - codom_dir, - dom_dir, - codom_site, - dom_site, - H::Int, - args..., -) + envname, codom_label, dom_label, codom_dir, dom_dir, codom_site, dom_site, H::Int, + args..., + ) return tensorexpr( envname, ( @@ -1690,8 +1442,8 @@ end ## Projector expressions function _pepo_codomain_projector_expr( - projname, codom_label, dom_label, dom_dir, H::Int, args... -) + projname, codom_label, dom_label, dom_dir, H::Int, args... + ) return tensorexpr( projname, (envlabel(codom_label, args...),), @@ -1705,8 +1457,8 @@ function _pepo_codomain_projector_expr( end function _pepo_domain_projector_expr( - projname, codom_label, codom_dir, dom_label, H::Int, args... -) + projname, codom_label, codom_dir, dom_label, H::Int, args... + ) return tensorexpr( projname, ( @@ -1725,17 +1477,11 @@ end ## Site contraction @generated function _contract_site( - C_northwest, - C_northeast, - C_southeast, - C_southwest, - E_north::CTMRGEdgeTensor{T,S,N}, - E_east::CTMRGEdgeTensor{T,S,N}, - E_south::CTMRGEdgeTensor{T,S,N}, - E_west::CTMRGEdgeTensor{T,S,N}, - O::PEPOSandwich{H}, -) where {T,S,N,H} - @assert N == H + 3 + C_northwest, C_northeast, C_southeast, C_southwest, + E_north::TE, E_east::TE, E_south::TE, E_west::TE, + O::PEPOSandwich{H}, + ) where {TE <: CTMRGEdgeTensor, H} + @assert numout(TE) == H + 3 C_northwest_e = _corner_expr(:C_northwest, :WNW, :NNW) C_northeast_e = _corner_expr(:C_northeast, :NNE, :ENE) @@ -1750,18 +1496,10 @@ end ket_e, bra_e, pepo_es = _pepo_sandwich_expr(:O, H) rhs = Expr( - :call, - :*, - C_northwest_e, - C_northeast_e, - C_southeast_e, - C_southwest_e, - E_north_e, - E_east_e, - E_south_e, - E_west_e, - ket_e, - Expr(:call, :conj, bra_e), + :call, :*, + C_northwest_e, C_northeast_e, C_southeast_e, C_southwest_e, + E_north_e, E_east_e, E_south_e, E_west_e, + ket_e, Expr(:call, :conj, bra_e), pepo_es..., ) @@ -1771,11 +1509,11 @@ end ## Enlarged corner contractions @generated function enlarge_northwest_corner( - E_west::CTMRGEdgeTensor{T,S,N}, - C_northwest::CTMRGCornerTensor, - E_north::CTMRGEdgeTensor{T,S,N}, - O::PEPOSandwich{H}, -) where {T,S,N,H} + E_west::CTMRGEdgeTensor{T, S, N}, + C_northwest::CTMRGCornerTensor, + E_north::CTMRGEdgeTensor{T, S, N}, + O::PEPOSandwich{H}, + ) where {T, S, N, H} @assert N == H + 3 E_west_e = _pepo_edge_expr(:E_west, :SW, :WNW, :W, H) @@ -1786,13 +1524,9 @@ end C_out_e = _pepo_enlarged_corner_expr(:C_northwest´, :SW, :NE, :S, :E, H) rhs = Expr( - :call, - :*, - E_west_e, - C_northwest_e, - E_north_e, - ket_e, - Expr(:call, :conj, bra_e), + :call, :*, + E_west_e, C_northwest_e, E_north_e, + ket_e, Expr(:call, :conj, bra_e), pepo_es..., ) @@ -1800,11 +1534,11 @@ end end @generated function enlarge_northeast_corner( - E_north::CTMRGEdgeTensor{T,S,N}, - C_northeast::CTMRGCornerTensor, - E_east::CTMRGEdgeTensor{T,S,N}, - O::PEPOSandwich{H}, -) where {T,S,N,H} + E_north::CTMRGEdgeTensor{T, S, N}, + C_northeast::CTMRGCornerTensor, + E_east::CTMRGEdgeTensor{T, S, N}, + O::PEPOSandwich{H}, + ) where {T, S, N, H} @assert N == H + 3 E_north_e = _pepo_edge_expr(:E_north, :NW, :NNE, :N, H) @@ -1815,13 +1549,9 @@ end C_out_e = _pepo_enlarged_corner_expr(:C_northeast´, :NW, :SE, :W, :S, H) rhs = Expr( - :call, - :*, - E_north_e, - C_northeast, - E_east_e, - ket_e, - Expr(:call, :conj, bra_e), + :call, :*, + E_north_e, C_northeast, E_east_e, + ket_e, Expr(:call, :conj, bra_e), pepo_es..., ) @@ -1829,11 +1559,11 @@ end end @generated function enlarge_southeast_corner( - E_east::CTMRGEdgeTensor{T,S,N}, - C_southeast::CTMRGCornerTensor, - E_south::CTMRGEdgeTensor{T,S,N}, - O::PEPOSandwich{H}, -) where {T,S,N,H} + E_east::CTMRGEdgeTensor{T, S, N}, + C_southeast::CTMRGCornerTensor, + E_south::CTMRGEdgeTensor{T, S, N}, + O::PEPOSandwich{H}, + ) where {T, S, N, H} @assert N == H + 3 E_east_e = _pepo_edge_expr(:E_east, :NE, :ESE, :E, H) @@ -1844,13 +1574,9 @@ end C_out_e = _pepo_enlarged_corner_expr(:C_southeast´, :NE, :SW, :N, :W, H) rhs = Expr( - :call, - :*, - E_east_e, - C_southeast_e, - E_south_e, - ket_e, - Expr(:call, :conj, bra_e), + :call, :*, + E_east_e, C_southeast_e, E_south_e, + ket_e, Expr(:call, :conj, bra_e), pepo_es..., ) @@ -1858,11 +1584,11 @@ end end @generated function enlarge_southwest_corner( - E_south::CTMRGEdgeTensor{T,S,N}, - C_southwest::CTMRGCornerTensor, - E_west::CTMRGEdgeTensor{T,S,N}, - O::PEPOSandwich{H}, -) where {T,S,N,H} + E_south::CTMRGEdgeTensor{T, S, N}, + C_southwest::CTMRGCornerTensor, + E_west::CTMRGEdgeTensor{T, S, N}, + O::PEPOSandwich{H}, + ) where {T, S, N, H} @assert N == H + 3 E_south_e = _pepo_edge_expr(:E_south, :SE, :SSW, :S, H) @@ -1873,13 +1599,9 @@ end C_out_e = _pepo_enlarged_corner_expr(:C_southwest´, :SE, :NW, :E, :N, H) rhs = Expr( - :call, - :*, - E_south_e, - C_southwest_e, - E_west_e, - ket_e, - Expr(:call, :conj, bra_e), + :call, :*, + E_south_e, C_southwest_e, E_west_e, + ket_e, Expr(:call, :conj, bra_e), pepo_es..., ) @@ -1896,28 +1618,21 @@ function _half_infinite_environnment_expr(H) C1_e = _corner_expr(:C_1, :WNW, :NNW) E1_e = _pepo_edge_expr(:E_1, :SW, :WNW, :W, H, 1) E2_e = _pepo_edge_expr(:E_2, :NNW, :NC, :N, H, 1) - ket1_e, bra1_e, pepo1_es = _pepo_sandwich_expr(:A_1, H, 1; contract_east=:NC) + ket1_e, bra1_e, pepo1_es = _pepo_sandwich_expr(:A_1, H, 1; contract_east = :NC) # site 2 (domain) C2_e = _corner_expr(:C_2, :NNE, :ENE) E3_e = _pepo_edge_expr(:E_3, :NC, :NNE, :N, H, 2) E4_e = _pepo_edge_expr(:E_4, :ENE, :SE, :E, H, 2) - ket2_e, bra2_e, pepo2_es = _pepo_sandwich_expr(:A_2, H, 2; contract_west=:NC) + ket2_e, bra2_e, pepo2_es = _pepo_sandwich_expr(:A_2, H, 2; contract_west = :NC) partial_expr = Expr( - :call, - :*, - E1_e, - C1_e, - E2_e, - ket1_e, - Expr(:call, :conj, bra1_e), + :call, :*, + E1_e, C1_e, E2_e, + ket1_e, Expr(:call, :conj, bra1_e), pepo1_es..., - E3_e, - C2_e, - E4_e, - ket2_e, - Expr(:call, :conj, bra2_e), + E3_e, C2_e, E4_e, + ket2_e, Expr(:call, :conj, bra2_e), pepo2_es..., ) @@ -1925,8 +1640,8 @@ function _half_infinite_environnment_expr(H) end @generated function half_infinite_environment( - C_1, C_2, E_1, E_2, E_3, E_4, A_1::PEPOSandwich{H}, A_2::PEPOSandwich{H} -) where {H} + C_1, C_2, E_1, E_2, E_3, E_4, A_1::PEPOSandwich{H}, A_2::PEPOSandwich{H} + ) where {H} # return projector expression env_e = _pepo_env_expr(:env, :SW, :SE, :S, :S, 1, 2, H) @@ -1936,16 +1651,11 @@ end return macroexpand(@__MODULE__, :(return @autoopt @tensor $env_e := $rhs)) end @generated function half_infinite_environment( - C_1, - C_2, - E_1, - E_2, - E_3, - E_4, - x::AbstractTensor{T,S,N}, - A_1::PEPOSandwich{H}, - A_2::PEPOSandwich{H}, -) where {T,S,N,H} + C_1, C_2, + E_1, E_2, E_3, E_4, + x::AbstractTensor{T, S, N}, + A_1::PEPOSandwich{H}, A_2::PEPOSandwich{H}, + ) where {T, S, N, H} @assert N == H + 3 # codomain vector (output) @@ -1962,16 +1672,11 @@ end ) end @generated function half_infinite_environment( - x::AbstractTensor{T,S,N}, - C_1, - C_2, - E_1, - E_2, - E_3, - E_4, - A_1::PEPOSandwich{H}, - A_2::PEPOSandwich{H}, -) where {T,S,N,H} + x::AbstractTensor{T, S, N}, + C_1, C_2, + E_1, E_2, E_3, E_4, + A_1::PEPOSandwich{H}, A_2::PEPOSandwich{H}, + ) where {T, S, N, H} @assert N == H + 3 # codomain vector (input) x_e = _pepo_env_arg_expr(:x, :SW, :S, 1, H) @@ -1995,14 +1700,14 @@ function _full_infinite_environment_expr(H) C1_e = _corner_expr(:C_1, :WNW, :NNW) E1_e = _pepo_edge_expr(:E_1, :SW, :WNW, :W, H, 1) E2_e = _pepo_edge_expr(:E_2, :NNW, :NC, :N, H, 1) - ket1_e, bra1_e, pepo1_es = _pepo_sandwich_expr(:A_1, H, 1; contract_east=:NC) + ket1_e, bra1_e, pepo1_es = _pepo_sandwich_expr(:A_1, H, 1; contract_east = :NC) # site 2 C2_e = _corner_expr(:C_2, :NNE, :ENE) E3_e = _pepo_edge_expr(:E_3, :NC, :NNE, :N, H, 2) E4_e = _pepo_edge_expr(:E_4, :ENE, :EC, :E, H, 2) ket2_e, bra2_e, pepo2_es = _pepo_sandwich_expr( - :A_2, H, 2; contract_west=:NC, contract_south=:EC + :A_2, H, 2; contract_west = :NC, contract_south = :EC ) # site 3 @@ -2010,41 +1715,28 @@ function _full_infinite_environment_expr(H) E5_e = _pepo_edge_expr(:E_5, :EC, :WSW, :E, H, 3) E6_e = _pepo_edge_expr(:E_6, :SSW, :SC, :S, H, 3) ket3_e, bra3_e, pepo3_es = _pepo_sandwich_expr( - :A_3, H, 3; contract_north=:EC, contract_west=:SC + :A_3, H, 3; contract_north = :EC, contract_west = :SC ) # site 4 (domain) C4_e = _corner_expr(:C_4, :SSW, :WSW) E7_e = _pepo_edge_expr(:E_7, :SC, :SSW, :S, H, 4) E8_e = _pepo_edge_expr(:E_8, :WSW, :NW, :W, H, 4) - ket4_e, bra4_e, pepo4_es = _pepo_sandwich_expr(:A_4, H, 4; contract_east=:SC) + ket4_e, bra4_e, pepo4_es = _pepo_sandwich_expr(:A_4, H, 4; contract_east = :SC) partial_expr = Expr( - :call, - :*, - E1_e, - C1_e, - E2_e, - ket1_e, - Expr(:call, :conj, bra1_e), + :call, :*, + E1_e, C1_e, E2_e, + ket1_e, Expr(:call, :conj, bra1_e), pepo1_es..., - E3_e, - C2_e, - E4_e, - ket2_e, - Expr(:call, :conj, bra2_e), + E3_e, C2_e, E4_e, + ket2_e, Expr(:call, :conj, bra2_e), pepo2_es..., - E5_e, - C3_e, - E6_e, - ket3_e, - Expr(:call, :conj, bra3_e), + E5_e, C3_e, E6_e, + ket3_e, Expr(:call, :conj, bra3_e), pepo3_es..., - E7_e, - C4_e, - E8_e, - ket4_e, - Expr(:call, :conj, bra4_e), + E7_e, C4_e, E8_e, + ket4_e, Expr(:call, :conj, bra4_e), pepo4_es..., ) @@ -2052,23 +1744,10 @@ function _full_infinite_environment_expr(H) end @generated function full_infinite_environment( - C_1, - C_2, - C_3, - C_4, - E_1, - E_2, - E_3, - E_4, - E_5, - E_6, - E_7, - E_8, - A_1::PEPOSandwich{H}, - A_2::PEPOSandwich{H}, - A_3::PEPOSandwich{H}, - A_4::PEPOSandwich{H}, -) where {H} + C_1, C_2, C_3, C_4, + E_1, E_2, E_3, E_4, E_5, E_6, E_7, E_8, + A_1::PEPOSandwich{H}, A_2::PEPOSandwich{H}, A_3::PEPOSandwich{H}, A_4::PEPOSandwich{H}, + ) where {H} # return projector expression env_e = _pepo_env_expr(:env, :SW, :NW, :S, :N, 1, 4, N - 1) @@ -2078,24 +1757,11 @@ end return macroexpand(@__MODULE__, :(return @autoopt @tensor $env_e := $proj_expr)) end @generated function full_infinite_environment( - C_1, - C_2, - C_3, - C_4, - E_1, - E_2, - E_3, - E_4, - E_5, - E_6, - E_7, - E_8, - x::AbstractTensor{T,S,N}, - A_1::PEPOSandwich{H}, - A_2::PEPOSandwich{H}, - A_3::PEPOSandwich{H}, - A_4::PEPOSandwich{H}, -) where {T,S,N,H} + C_1, C_2, C_3, C_4, + E_1, E_2, E_3, E_4, E_5, E_6, E_7, E_8, + x::AbstractTensor{T, S, N}, + A_1::PEPOSandwich{H}, A_2::PEPOSandwich{H}, A_3::PEPOSandwich{H}, A_4::PEPOSandwich{H}, + ) where {T, S, N, H} @assert N == H + 3 # codomain vecor (output) @@ -2110,24 +1776,11 @@ end return macroexpand(@__MODULE__, :(return @autoopt @tensor $env_x_e := $proj_expr * x_e)) end @generated function full_infinite_environment( - x::AbstractTensor{T,S,N}, - C_1, - C_2, - C_3, - C_4, - E_1, - E_2, - E_3, - E_4, - E_5, - E_6, - E_7, - E_8, - A_1::PEPOSandwich{H}, - A_2::PEPOSandwich{H}, - A_3::PEPOSandwich{H}, - A_4::PEPOSandwich{H}, -) where {T,S,N,H} + x::AbstractTensor{T, S, N}, + C_1, C_2, C_3, C_4, + E_1, E_2, E_3, E_4, E_5, E_6, E_7, E_8, + A_1::PEPOSandwich{H}, A_2::PEPOSandwich{H}, A_3::PEPOSandwich{H}, A_4::PEPOSandwich{H}, + ) where {T, S, N, H} @assert N == H + 3 # codomain vecor (input) @@ -2147,8 +1800,8 @@ end ## Corner renormalization contractions @generated function renormalize_northwest_corner( - E_west, C_northwest, E_north, P_left, P_right, A::PEPOSandwich{H} -) where {H} + E_west, C_northwest, E_north, P_left, P_right, A::PEPOSandwich{H} + ) where {H} C_out_e = _corner_expr(:corner, :out, :in) P_right_e = _pepo_codomain_projector_expr(:P_right, :out, :S, :S, H) @@ -2159,14 +1812,10 @@ end P_left_e = _pepo_domain_projector_expr(:P_left, :E, :E, :in, H) rhs = Expr( - :call, - :*, + :call, :*, P_right_e, - E_west_e, - C_northwest_e, - E_north_e, - ket_e, - Expr(:call, :conj, bra_e), + E_west_e, C_northwest_e, E_north_e, + ket_e, Expr(:call, :conj, bra_e), pepo_es..., P_left_e, ) @@ -2175,8 +1824,8 @@ end end @generated function renormalize_northeast_corner( - E_north, C_northeast, E_east, P_left, P_right, A::PEPOSandwich{H} -) where {H} + E_north, C_northeast, E_east, P_left, P_right, A::PEPOSandwich{H} + ) where {H} C_out_e = _corner_expr(:corner, :out, :in) P_right_e = _pepo_codomain_projector_expr(:P_right, :out, :W, :W, H) @@ -2187,14 +1836,10 @@ end P_left_e = _pepo_domain_projector_expr(:P_left, :S, :S, :in, H) rhs = Expr( - :call, - :*, + :call, :*, P_right_e, - E_north_e, - C_northeast_e, - E_east_e, - ket_e, - Expr(:call, :conj, bra_e), + E_north_e, C_northeast_e, E_east_e, + ket_e, Expr(:call, :conj, bra_e), pepo_es..., P_left_e, ) @@ -2203,8 +1848,8 @@ end end @generated function renormalize_southeast_corner( - E_east, C_southeast, E_south, P_left, P_right, A::PEPOSandwich{H} -) where {H} + E_east, C_southeast, E_south, P_left, P_right, A::PEPOSandwich{H} + ) where {H} C_out_e = _corner_expr(:corner, :out, :in) P_right_e = _pepo_codomain_projector_expr(:P_right, :out, :N, :N, H) @@ -2215,14 +1860,10 @@ end P_left_e = _pepo_domain_projector_expr(:P_left, :W, :W, :in, H) rhs = Expr( - :call, - :*, + :call, :*, P_right_e, - E_east_e, - C_southeast_e, - E_south_e, - ket_e, - Expr(:call, :conj, bra_e), + E_east_e, C_southeast_e, E_south_e, + ket_e, Expr(:call, :conj, bra_e), pepo_es..., P_left_e, ) @@ -2231,8 +1872,8 @@ end end @generated function renormalize_southwest_corner( - E_south, C_southwest, E_west, P_left, P_right, A::PEPOSandwich{H} -) where {H} + E_south, C_southwest, E_west, P_left, P_right, A::PEPOSandwich{H} + ) where {H} C_out_e = _corner_expr(:corner, :out, :in) P_right_e = _pepo_codomain_projector_expr(:P_right, :out, :E, :E, H) @@ -2243,14 +1884,10 @@ end P_left_e = _pepo_domain_projector_expr(:P_left, :N, :N, :in, H) rhs = Expr( - :call, - :*, + :call, :*, P_right_e, - E_south_e, - C_southwest_e, - E_west_e, - ket_e, - Expr(:call, :conj, bra_e), + E_south_e, C_southwest_e, E_west_e, + ket_e, Expr(:call, :conj, bra_e), pepo_es..., P_left_e, ) @@ -2261,8 +1898,8 @@ end ## Edge renormalization contractions @generated function renormalize_north_edge( - E_north::CTMRGEdgeTensor{T,S,N}, P_left, P_right, A::PEPOSandwich{H} -) where {T,S,N,H} + E_north::CTMRGEdgeTensor{T, S, N}, P_left, P_right, A::PEPOSandwich{H} + ) where {T, S, N, H} @assert N == H + 3 E_out_e = _pepo_edge_expr(:edge, :out, :in, :S, H) @@ -2273,12 +1910,10 @@ end P_left_e = _pepo_domain_projector_expr(:P_left, :E, :E, :in, H) rhs = Expr( - :call, - :*, + :call, :*, P_right_e, E_north_e, - ket_e, - Expr(:call, :conj, bra_e), + ket_e, Expr(:call, :conj, bra_e), pepo_es..., P_left_e, ) @@ -2287,8 +1922,8 @@ end end @generated function renormalize_east_edge( - E_east::CTMRGEdgeTensor{T,S,N}, P_bottom, P_top, A::PEPOSandwich{H} -) where {T,S,N,H} + E_east::CTMRGEdgeTensor{T, S, N}, P_bottom, P_top, A::PEPOSandwich{H} + ) where {T, S, N, H} @assert N == H + 3 E_out_e = _pepo_edge_expr(:edge, :out, :in, :W, H) @@ -2299,12 +1934,10 @@ end P_bottom_e = _pepo_domain_projector_expr(:P_bottom, :S, :S, :in, H) rhs = Expr( - :call, - :*, + :call, :*, P_top_e, E_east_e, - ket_e, - Expr(:call, :conj, bra_e), + ket_e, Expr(:call, :conj, bra_e), pepo_es..., P_bottom_e, ) @@ -2313,8 +1946,8 @@ end end @generated function renormalize_south_edge( - E_south::CTMRGEdgeTensor{T,S,N}, P_left, P_right, A::PEPOSandwich{H} -) where {T,S,N,H} + E_south::CTMRGEdgeTensor{T, S, N}, P_left, P_right, A::PEPOSandwich{H} + ) where {T, S, N, H} @assert N == H + 3 E_out_e = _pepo_edge_expr(:edge, :out, :in, :N, H) @@ -2325,12 +1958,10 @@ end P_left_e = _pepo_domain_projector_expr(:P_left, :W, :W, :in, H) rhs = Expr( - :call, - :*, + :call, :*, P_right_e, E_south_e, - ket_e, - Expr(:call, :conj, bra_e), + ket_e, Expr(:call, :conj, bra_e), pepo_es..., P_left_e, ) @@ -2339,8 +1970,8 @@ end end @generated function renormalize_west_edge( - E_west::CTMRGEdgeTensor{T,S,N}, P_bottom, P_top, A::PEPOSandwich{H} -) where {T,S,N,H} + E_west::CTMRGEdgeTensor{T, S, N}, P_bottom, P_top, A::PEPOSandwich{H} + ) where {T, S, N, H} @assert N == H + 3 E_out_e = _pepo_edge_expr(:edge, :out, :in, :E, H) @@ -2351,12 +1982,10 @@ end P_bottom_e = _pepo_domain_projector_expr(:P_bottom, :N, :N, :in, H) rhs = Expr( - :call, - :*, + :call, :*, P_top_e, E_west_e, - ket_e, - Expr(:call, :conj, bra_e), + ket_e, Expr(:call, :conj, bra_e), pepo_es..., P_bottom_e, ) diff --git a/src/algorithms/contractions/localoperator.jl b/src/algorithms/contractions/localoperator.jl index 79a32642d..c47e0ff14 100644 --- a/src/algorithms/contractions/localoperator.jl +++ b/src/algorithms/contractions/localoperator.jl @@ -28,26 +28,24 @@ specified by `inds`. The `peps` is contracted with `O` from above and below, and sandwich is surrounded with the appropriate environment tensors. """ function contract_local_operator( - inds::NTuple{N,CartesianIndex{2}}, - O::AbstractTensorMap{T,S,N,N}, - ket::InfinitePEPS, - bra::InfinitePEPS, - env::CTMRGEnv, -) where {T,S,N} + inds::NTuple{N, CartesianIndex{2}}, + O::AbstractTensorMap{T, S, N, N}, + ket::InfinitePEPS, bra::InfinitePEPS, + env::CTMRGEnv, + ) where {T, S, N} static_inds = Val.(inds) return _contract_local_operator(static_inds, O, ket, bra, env) end function contract_local_operator( - inds::NTuple{N,Tuple{Int,Int}}, - O::AbstractTensorMap{T,S,N,N}, - ket::InfinitePEPS, - bra::InfinitePEPS, - env::CTMRGEnv, -) where {T,S,N} + inds::NTuple{N, Tuple{Int, Int}}, + O::AbstractTensorMap{T, S, N, N}, + ket::InfinitePEPS, bra::InfinitePEPS, + env::CTMRGEnv, + ) where {T, S, N} return contract_local_operator(CartesianIndex.(inds), O, ket, bra, env) end -# This implements the contraction of an operator acting on sites `inds`. +# This implements the contraction of an operator acting on sites `inds`. # The generated function ensures that we can use @tensor to write dynamic contractions (and maximize performance). function _contract_corner_expr(rowrange, colrange) @@ -126,7 +124,7 @@ function _contract_edge_expr(rowrange, colrange) return edges_N, edges_E, edges_S, edges_W end -function _contract_state_expr(rowrange, colrange, cartesian_inds=nothing) +function _contract_state_expr(rowrange, colrange, cartesian_inds = nothing) rmin, rmax = extrema(rowrange) cmin, cmax = extrema(colrange) gridsize = (rmax - rmin + 1, cmax - cmin + 1) @@ -174,12 +172,11 @@ function _contract_state_expr(rowrange, colrange, cartesian_inds=nothing) end @generated function _contract_local_operator( - inds::NTuple{N,Val}, - O::AbstractTensorMap{T,S,N,N}, - ket::InfinitePEPS, - bra::InfinitePEPS, - env::CTMRGEnv, -) where {T,S,N} + inds::NTuple{N, Val}, + O::AbstractTensorMap{T, S, N, N}, + ket::InfinitePEPS, bra::InfinitePEPS, + env::CTMRGEnv, + ) where {T, S, N} cartesian_inds = collect(CartesianIndex{2}, map(x -> x.parameters[1], inds.parameters)) # weird hack to extract information from Val allunique(cartesian_inds) || throw(ArgumentError("Indices should not overlap: $cartesian_inds.")) @@ -196,18 +193,10 @@ end bra, ket = _contract_state_expr(rowrange, colrange, cartesian_inds) multiplication_ex = Expr( - :call, - :*, - corner_NW, - corner_NE, - corner_SE, - corner_SW, - edges_N..., - edges_E..., - edges_S..., - edges_W..., - ket..., - map(x -> Expr(:call, :conj, x), bra)..., + :call, :*, + corner_NW, corner_NE, corner_SE, corner_SW, + edges_N..., edges_E..., edges_S..., edges_W..., + ket..., map(x -> Expr(:call, :conj, x), bra)..., operator, ) @@ -227,22 +216,21 @@ on a rectangular patch based on `inds` but replacing the operator with an identi that the PEPS norm is computed. (Note that this is not the physical norm of the state.) """ function contract_local_norm( - inds::NTuple{N,CartesianIndex{2}}, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv -) where {N} + inds::NTuple{N, CartesianIndex{2}}, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv + ) where {N} static_inds = Val.(inds) return _contract_local_norm(static_inds, ket, bra, env) end function contract_local_norm( - inds::NTuple{N,Tuple{Int,Int}}, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv -) where {N} + inds::NTuple{N, Tuple{Int, Int}}, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv + ) where {N} return contract_local_norm(CartesianIndex.(inds), ket, bra, env) end @generated function _contract_local_norm( - inds::NTuple{N,Val}, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv -) where {N} + inds::NTuple{N, Val}, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv + ) where {N} cartesian_inds = collect(CartesianIndex{2}, map(x -> x.parameters[1], inds.parameters)) # weird hack to extract information from Val - allunique(cartesian_inds) || - throw(ArgumentError("Indices should not overlap: $cartesian_inds.")) + allunique(cartesian_inds) || throw(ArgumentError("Indices should not overlap: $cartesian_inds.")) rowrange = getindex.(cartesian_inds, 1) colrange = getindex.(cartesian_inds, 2) @@ -251,18 +239,10 @@ end bra, ket = _contract_state_expr(rowrange, colrange) multiplication_ex = Expr( - :call, - :*, - corner_NW, - corner_NE, - corner_SE, - corner_SW, - edges_N..., - edges_E..., - edges_S..., - edges_W..., - ket..., - map(x -> Expr(:call, :conj, x), bra)..., + :call, :*, + corner_NW, corner_NE, corner_SE, corner_SW, + edges_N..., edges_E..., edges_S..., edges_W..., + ket..., map(x -> Expr(:call, :conj, x), bra)..., ) returnex = quote @@ -280,14 +260,14 @@ This works by generating the appropriate contraction on a rectangular patch with specified by `inds`. The result is normalized such that `tr(ρ) = 1`. """ function reduced_densitymatrix( - inds::NTuple{N,CartesianIndex{2}}, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv -) where {N} + inds::NTuple{N, CartesianIndex{2}}, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv + ) where {N} static_inds = Val.(inds) return _contract_densitymatrix(static_inds, ket, bra, env) end function reduced_densitymatrix( - inds::NTuple{N,Tuple{Int,Int}}, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv -) where {N} + inds::NTuple{N, Tuple{Int, Int}}, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv + ) where {N} return reduced_densitymatrix(CartesianIndex.(inds), ket, bra, env) end function reduced_densitymatrix(inds, ket::InfinitePEPS, env::CTMRGEnv) @@ -298,8 +278,8 @@ end # Keep contraction order but try to optimize intermediate permutations: # EE_SWA is largest object so keep largest legs to the front there function reduced_densitymatrix( - inds::Tuple{CartesianIndex{2}}, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv -) + inds::Tuple{CartesianIndex{2}}, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv + ) row, col = Tuple(inds[1]) # Unpack variables and absorb corners @@ -337,8 +317,8 @@ function reduced_densitymatrix( end function reduced_densitymatrix( - inds::NTuple{2,CartesianIndex{2}}, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv -) + inds::NTuple{2, CartesianIndex{2}}, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv + ) if inds[2] - inds[1] == CartesianIndex(1, 0) return reduced_densitymatrix2x1(inds[1], ket, bra, env) elseif inds[2] - inds[1] == CartesianIndex(0, 1) @@ -352,8 +332,8 @@ end # Special case 2x1 density matrix: # Keep contraction order but try to optimize intermediate permutations: function reduced_densitymatrix2x1( - ind::CartesianIndex, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv -) + ind::CartesianIndex, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv + ) row, col = Tuple(ind) # Unpack variables and absorb corners @@ -402,8 +382,8 @@ function reduced_densitymatrix2x1( end function reduced_densitymatrix1x2( - ind::CartesianIndex, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv -) + ind::CartesianIndex, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv + ) row, col = Tuple(ind) # Unpack variables and absorb corners @@ -452,8 +432,8 @@ function reduced_densitymatrix1x2( end @generated function _contract_densitymatrix( - inds::NTuple{N,Val}, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv -) where {N} + inds::NTuple{N, Val}, ket::InfinitePEPS, bra::InfinitePEPS, env::CTMRGEnv + ) where {N} cartesian_inds = collect(CartesianIndex{2}, map(x -> x.parameters[1], inds.parameters)) # weird hack to extract information from Val allunique(cartesian_inds) || throw(ArgumentError("Indices should not overlap: $cartesian_inds.")) @@ -470,18 +450,10 @@ end bra, ket = _contract_state_expr(rowrange, colrange, cartesian_inds) multiplication_ex = Expr( - :call, - :*, - corner_NW, - corner_NE, - corner_SE, - corner_SW, - edges_N..., - edges_E..., - edges_S..., - edges_W..., - ket..., - map(x -> Expr(:call, :conj, x), bra)..., + :call, :*, + corner_NW, corner_NE, corner_SE, corner_SW, + edges_N..., edges_E..., edges_S..., edges_W..., + ket..., map(x -> Expr(:call, :conj, x), bra)..., ) multex = :(@autoopt @tensor $result := $multiplication_ex) return quote diff --git a/src/algorithms/contractions/vumps_contractions.jl b/src/algorithms/contractions/vumps_contractions.jl index c886da6ef..97f231905 100644 --- a/src/algorithms/contractions/vumps_contractions.jl +++ b/src/algorithms/contractions/vumps_contractions.jl @@ -3,21 +3,17 @@ # function MPSKit.transfer_left( - GL::GenericMPSTensor{S,N}, - O::Union{PEPSSandwich,PEPOSandwich}, - A::GenericMPSTensor{S,N}, - Ā::GenericMPSTensor{S,N}, -) where {S,N} + GL::GenericMPSTensor{S, N}, O::Union{PEPSSandwich, PEPOSandwich}, + A::GenericMPSTensor{S, N}, Ā::GenericMPSTensor{S, N}, + ) where {S, N} Ā = twistdual(Ā, 2:N) return _transfer_left(GL, O, A, Ā) end function MPSKit.transfer_right( - GR::GenericMPSTensor{S,N}, - O::Union{PEPSSandwich,PEPOSandwich}, - A::GenericMPSTensor{S,N}, - Ā::GenericMPSTensor{S,N}, -) where {S,N} + GR::GenericMPSTensor{S, N}, O::Union{PEPSSandwich, PEPOSandwich}, + A::GenericMPSTensor{S, N}, Ā::GenericMPSTensor{S, N}, + ) where {S, N} Ā = twistdual(Ā, 2:N) return _transfer_right(GR, O, A, Ā) end @@ -25,11 +21,9 @@ end ## PEPS function _transfer_left( - GL::GenericMPSTensor{S,3}, - O::PEPSSandwich, - A::GenericMPSTensor{S,3}, - Ā::GenericMPSTensor{S,3}, -) where {S} + GL::GenericMPSTensor{S, 3}, O::PEPSSandwich, + A::GenericMPSTensor{S, 3}, Ā::GenericMPSTensor{S, 3}, + ) where {S} return @autoopt @tensor GL′[χ_SE D_E_above D_E_below; χ_NE] := GL[χ_SW D_W_above D_W_below; χ_NW] * conj(Ā[χ_SW D_S_above D_S_below; χ_SE]) * @@ -40,12 +34,10 @@ end # transfer with excited GL function MPSKit.transfer_left( - GL::GenericMPSTensor{S,4}, - O::PEPSSandwich, - A::GenericMPSTensor{S,3}, - Ā::GenericMPSTensor{S,3}, -) where {S} - @autoopt @tensor GL′[χ_SE D_E_above d_string D_E_below; χ_NE] := + GL::GenericMPSTensor{S, 4}, O::PEPSSandwich, + A::GenericMPSTensor{S, 3}, Ā::GenericMPSTensor{S, 3}, + ) where {S} + return @autoopt @tensor GL′[χ_SE D_E_above d_string D_E_below; χ_NE] := GL[χ_SW D_W_above d_string D_W_below; χ_NW] * conj(Ā[χ_SW D_S_above D_S_below; χ_SE]) * ket(O)[d; D_N_above D_E_above D_S_above D_W_above] * @@ -54,11 +46,9 @@ function MPSKit.transfer_left( end function _transfer_right( - GR::GenericMPSTensor{S,3}, - O::PEPSSandwich, - A::GenericMPSTensor{S,3}, - Ā::GenericMPSTensor{S,3}, -) where {S} + GR::GenericMPSTensor{S, 3}, O::PEPSSandwich, + A::GenericMPSTensor{S, 3}, Ā::GenericMPSTensor{S, 3}, + ) where {S} return @autoopt @tensor GR′[χ_NW D_W_above D_W_below; χ_SW] := GR[χ_NE D_E_above D_E_below; χ_SE] * conj(Ā[χ_SW D_S_above D_S_below; χ_SE]) * @@ -70,11 +60,9 @@ end ## PEPO @generated function _transfer_left( - GL::GenericMPSTensor{S,N}, - O::PEPOSandwich{H}, - A::GenericMPSTensor{S,N}, - Ā::GenericMPSTensor{S,N}, -) where {S,N,H} + GL::GenericMPSTensor{S, N}, O::PEPOSandwich{H}, + A::GenericMPSTensor{S, N}, Ā::GenericMPSTensor{S, N}, + ) where {S, N, H} # sanity check @assert H == N - 3 @@ -85,13 +73,10 @@ end ket_e, bra_e, pepo_es = _pepo_sandwich_expr(:O, H) rhs = Expr( - :call, - :*, + :call, :*, GL_e, - A_e, - Expr(:call, :conj, Ā_e), - ket_e, - Expr(:call, :conj, bra_e), + A_e, Expr(:call, :conj, Ā_e), + ket_e, Expr(:call, :conj, bra_e), pepo_es..., ) @@ -99,11 +84,9 @@ end end @generated function _transfer_right( - GR::GenericMPSTensor{S,N}, - O::PEPOSandwich{H}, - A::GenericMPSTensor{S,N}, - Ā::GenericMPSTensor{S,N}, -) where {S,N,H} + GR::GenericMPSTensor{S, N}, O::PEPOSandwich{H}, + A::GenericMPSTensor{S, N}, Ā::GenericMPSTensor{S, N}, + ) where {S, N, H} # sanity check @assert H == N - 3 @@ -114,13 +97,10 @@ end ket_e, bra_e, pepo_es = _pepo_sandwich_expr(:O, H) rhs = Expr( - :call, - :*, + :call, :*, GR_e, - A_e, - Expr(:call, :conj, Ā_e), - ket_e, - Expr(:call, :conj, bra_e), + A_e, Expr(:call, :conj, Ā_e), + ket_e, Expr(:call, :conj, bra_e), pepo_es..., ) @@ -128,8 +108,8 @@ end end @generated function environment_overlap( - GL::GenericMPSTensor{S,N}, GR::GenericMPSTensor{S,N} -) where {S,N} + GL::GenericMPSTensor{S, N}, GR::GenericMPSTensor{S, N} + ) where {S, N} GL_e = tensorexpr(:GL, (N + 1, (2:N)...), 1) GR_e = tensorexpr(:GR, 1:N, N + 1) return macroexpand(@__MODULE__, :(return o = @tensor $GL_e * $GR_e)) @@ -137,12 +117,10 @@ end # TODO: properly implement in the most efficient way function MPSKit.contract_mpo_expval( - AC::GenericMPSTensor{S,N}, - GL::GenericMPSTensor{S,N}, - O::Union{PEPSSandwich,PEPOSandwich}, - GR::GenericMPSTensor{S,N}, - ACbar::GenericMPSTensor{S,N}=AC, -) where {S,N} + AC::GenericMPSTensor{S, N}, GL::GenericMPSTensor{S, N}, + O::Union{PEPSSandwich, PEPOSandwich}, GR::GenericMPSTensor{S, N}, + ACbar::GenericMPSTensor{S, N} = AC, + ) where {S, N} GL´ = MPSKit.transfer_left(GL, O, AC, ACbar) return environment_overlap(GL´, GR) end @@ -152,18 +130,18 @@ end # This is appropriating the MPSKit MPO derivative structures, which might not be the best # idea in the long run. -const PEPS_C_Hamiltonian{S,N} = MPSKit.MPO_C_Hamiltonian{ - <:GenericMPSTensor{S,N},<:GenericMPSTensor{S,N} +const PEPS_C_Hamiltonian{S, N} = MPSKit.MPO_C_Hamiltonian{ + <:GenericMPSTensor{S, N}, <:GenericMPSTensor{S, N}, } # this one is technically type-piracy PEPS_C_Hamiltonian(GL, GR) = MPSKit.MPODerivativeOperator(GL, (), GR) -const PEPS_AC_Hamiltonian{S,N} = MPSKit.MPO_AC_Hamiltonian{ - <:GenericMPSTensor{S,N},<:PEPSSandwich,<:GenericMPSTensor{S,N} +const PEPS_AC_Hamiltonian{S, N} = MPSKit.MPO_AC_Hamiltonian{ + <:GenericMPSTensor{S, N}, <:PEPSSandwich, <:GenericMPSTensor{S, N}, } PEPS_AC_Hamiltonian(GL, O, GR) = MPSKit.MPODerivativeOperator(GL, (O,), GR) -const PEPS_AC2_Hamiltonian{S,N} = MPSKit.MPO_AC2_Hamiltonian{ - <:GenericMPSTensor{S,N},<:PEPSSandwich,<:PEPSSandwich,<:GenericMPSTensor{S,N} +const PEPS_AC2_Hamiltonian{S, N} = MPSKit.MPO_AC2_Hamiltonian{ + <:GenericMPSTensor{S, N}, <:PEPSSandwich, <:PEPSSandwich, <:GenericMPSTensor{S, N}, } PEPS_AC2_Hamiltonian(GL, O1, O2, GR) = MPSKit.MPODerivativeOperator(GL, (O1, O2), GR) @@ -178,8 +156,8 @@ function MPSKit.C_hamiltonian(site::Int, below, ::InfiniteTransferMatrix, above, end function MPSKit.AC_hamiltonian( - site::Int, below, operator::InfiniteTransferPEPS, above, envs -) + site::Int, below, operator::InfiniteTransferPEPS, above, envs + ) GL = leftenv(envs, site, below) GL = twistdual(GL, 1) GR = rightenv(envs, site, below) @@ -188,8 +166,8 @@ function MPSKit.AC_hamiltonian( end function MPSKit.AC2_hamiltonian( - site::Int, below, operator::InfiniteTransferPEPS, above, envs -) + site::Int, below, operator::InfiniteTransferPEPS, above, envs + ) GL = leftenv(envs, site, below) GL = twistdual(GL, 1) GR = rightenv(envs, site + 1, below) @@ -199,7 +177,7 @@ end # Actions # -@generated function (h::PEPS_C_Hamiltonian{S,N})(C::MPSBondTensor{S}) where {S,N} +@generated function (h::PEPS_C_Hamiltonian{S, N})(C::MPSBondTensor{S}) where {S, N} C´_e = tensorexpr(:C´, -1, -2) C_e = tensorexpr(:C, 1, 2) GL_e = tensorexpr(:(h.leftenv), (-1, (3:(N + 1))...), 1) @@ -207,7 +185,7 @@ end return macroexpand(@__MODULE__, :(return @tensor $C´_e := $GL_e * $C_e * $GR_e)) end -function (h::PEPS_AC_Hamiltonian{S,N})(AC::GenericMPSTensor{S,N}) where {S,N} +function (h::PEPS_AC_Hamiltonian{S, N})(AC::GenericMPSTensor{S, N}) where {S, N} return @autoopt @tensor AC′[χ_SW D_S_above D_S_below; χ_SE] := h.leftenv[χ_SW D_W_above D_W_below; χ_NW] * AC[χ_NW D_N_above D_N_below; χ_NE] * @@ -216,7 +194,7 @@ function (h::PEPS_AC_Hamiltonian{S,N})(AC::GenericMPSTensor{S,N}) where {S,N} conj(bra(h.operators[1])[d; D_N_below D_E_below D_S_below D_W_below]) end -function (h::PEPS_AC2_Hamiltonian{S,3})(AC2::AbstractTensorMap{<:Any,S,3,3}) where {S} +function (h::PEPS_AC2_Hamiltonian{S, 3})(AC2::AbstractTensorMap{<:Any, S, 3, 3}) where {S} return @autoopt @tensor AC2′[χ_SW D_S_above1 D_S_below1; χ_SE D_S_below2 D_S_above2] := h.leftenv[χ_SW D_W_above1 D_W_below1; χ_NW] * AC2[χ_NW D_N_above1 D_N_below1; χ_NE D_N_below2 D_N_above2] * @@ -229,12 +207,12 @@ end # PEPS derivative function ∂peps( - AC::GenericMPSTensor{S,3}, - ĀC::GenericMPSTensor{S,3}, - O::PEPSTensor{S}, - GL::GenericMPSTensor{S,3}, - GR::GenericMPSTensor{S,3}, -) where {S} + AC::GenericMPSTensor{S, 3}, + ĀC::GenericMPSTensor{S, 3}, + O::PEPSTensor{S}, + GL::GenericMPSTensor{S, 3}, + GR::GenericMPSTensor{S, 3}, + ) where {S} return @tensor ∂p[d; D_N_below D_E_below D_S_below D_W_below] := GL[χ_SW D_W_above D_W_below; χ_NW] * AC[χ_NW D_N_above D_N_below; χ_NE] * @@ -245,14 +223,14 @@ end # PEPO Derivative contractions # ---------------------------- -const PEPO_AC_Hamiltonian{S,N,H} = MPSKit.MPO_AC_Hamiltonian{ - <:GenericMPSTensor{S,N},<:PEPOSandwich{H},<:GenericMPSTensor{S,N} +const PEPO_AC_Hamiltonian{S, N, H} = MPSKit.MPO_AC_Hamiltonian{ + <:GenericMPSTensor{S, N}, <:PEPOSandwich{H}, <:GenericMPSTensor{S, N}, } PEPO_AC_Hamiltonian(GL, O, GR) = MPSKit.MPODerivativeOperator(GL, (O,), GR) function MPSKit.AC_hamiltonian( - site::Int, below, operator::InfiniteTransferPEPO, above, envs -) + site::Int, below, operator::InfiniteTransferPEPO, above, envs + ) GL = leftenv(envs, site, below) GL = twistdual(GL, 1) GR = rightenv(envs, site, below) @@ -260,7 +238,7 @@ function MPSKit.AC_hamiltonian( return PEPO_AC_Hamiltonian(GL, operator[site], GR) end -@generated function (h::PEPO_AC_Hamiltonian{S,N,H})(AC::GenericMPSTensor{S,N}) where {S,N,H} +@generated function (h::PEPO_AC_Hamiltonian{S, N, H})(AC::GenericMPSTensor{S, N}) where {S, N, H} # sanity check @assert H == N - 3 "Incompatible number of legs and layers" @@ -278,18 +256,16 @@ end # PEPS derivative # sandwich with the bottom dropped out... -const ∂PEPOSandwich{N,T<:PEPSTensor,P<:PEPOTensor} = Tuple{T,Vararg{P,N}} +const ∂PEPOSandwich{N, T <: PEPSTensor, P <: PEPOTensor} = Tuple{T, Vararg{P, N}} ket(p::∂PEPOSandwich) = p[1] pepo(p::∂PEPOSandwich) = p[2:end] pepo(p::∂PEPOSandwich, i::Int) = p[1 + i] @generated function ∂peps( - AC::GenericMPSTensor{S,N}, - ĀC::GenericMPSTensor{S,N}, - O::∂PEPOSandwich{H}, - GL::GenericMPSTensor{S,N}, - GR::GenericMPSTensor{S,N}, -) where {S,N,H} + AC::GenericMPSTensor{S, N}, ĀC::GenericMPSTensor{S, N}, + O::∂PEPOSandwich{H}, + GL::GenericMPSTensor{S, N}, GR::GenericMPSTensor{S, N}, + ) where {S, N, H} # sanity check @assert H == N - 3 diff --git a/src/algorithms/correlators.jl b/src/algorithms/correlators.jl index 0e6a07aae..237a756f9 100644 --- a/src/algorithms/correlators.jl +++ b/src/algorithms/correlators.jl @@ -1,16 +1,15 @@ function correlator_horizontal( - bra::InfinitePEPS, - operator, - i::CartesianIndex{2}, - js::AbstractVector{CartesianIndex{2}}, - ket::InfinitePEPS, - env::CTMRGEnv, -) + bra::InfinitePEPS, + operator, + i::CartesianIndex{2}, js::AbstractVector{CartesianIndex{2}}, + ket::InfinitePEPS, + env::CTMRGEnv, + ) size(ket) == size(bra) || throw(DimensionMismatch("The ket and bra must have the same unit cell.")) all(==(i[1]) ∘ first ∘ Tuple, js) || throw(ArgumentError("Not a horizontal correlation function")) - issorted(vcat(i, js); by=last ∘ Tuple) || + issorted(vcat(i, js); by = last ∘ Tuple) || throw(ArgumentError("Not an increasing sequence of coordinates")) O = FiniteMPO(operator) @@ -34,7 +33,7 @@ function correlator_horizontal( Atop = env.edges[NORTH, _prev(i[1], end), mod1(i[2], end)] Abot = env.edges[SOUTH, _next(i[1], end), mod1(i[2], end)] sandwich = ( - ket[mod1(i[1], end), mod1(i[2], end)], bra[mod1(i[1], end), mod1(i[2], end)] + ket[mod1(i[1], end), mod1(i[2], end)], bra[mod1(i[1], end), mod1(i[2], end)], ) T = TransferMatrix(Atop, sandwich, _dag(Abot)) Vo = Vo * T @@ -50,7 +49,7 @@ function correlator_horizontal( Atop = env.edges[NORTH, _prev(i[1], end), mod1(i[2], end)] Abot = env.edges[SOUTH, _next(i[1], end), mod1(i[2], end)] sandwich = ( - ket[mod1(i[1], end), mod1(i[2], end)], bra[mod1(i[1], end), mod1(i[2], end)] + ket[mod1(i[1], end), mod1(i[2], end)], bra[mod1(i[1], end), mod1(i[2], end)], ) T = TransferMatrix(Atop, sandwich, _dag(Abot)) Vo = Vo * T @@ -68,12 +67,12 @@ function correlator_horizontal( end function start_correlator( - i::CartesianIndex{2}, - below::InfinitePEPS, - O::MPOTensor, - above::InfinitePEPS, - env::CTMRGEnv, -) + i::CartesianIndex{2}, + below::InfinitePEPS, + O::MPOTensor, + above::InfinitePEPS, + env::CTMRGEnv, + ) r, c = Tuple(i) E_north = env.edges[NORTH, _prev(r, end), mod1(c, end)] E_south = env.edges[SOUTH, _next(r, end), mod1(c, end)] @@ -107,13 +106,13 @@ function start_correlator( end function end_correlator_numerator( - j::CartesianIndex{2}, - V, - above::InfinitePEPS, - O::MPOTensor, - below::InfinitePEPS, - env::CTMRGEnv, -) + j::CartesianIndex{2}, + V, + above::InfinitePEPS, + O::MPOTensor, + below::InfinitePEPS, + env::CTMRGEnv, + ) r, c = Tuple(j) E_north = env.edges[NORTH, _prev(r, end), mod1(c, end)] E_east = env.edges[EAST, mod1(r, end), _next(c, end)] @@ -146,13 +145,12 @@ function end_correlator_denominator(j::CartesianIndex{2}, V, env::CTMRGEnv) end function correlator_vertical( - bra::InfinitePEPS, - O, - i::CartesianIndex{2}, - js::AbstractVector{CartesianIndex{2}}, - ket::InfinitePEPS, - env::CTMRGEnv, -) + bra::InfinitePEPS, + O, + i::CartesianIndex{2}, js::AbstractVector{CartesianIndex{2}}, + ket::InfinitePEPS, + env::CTMRGEnv, + ) rotated_bra = rotl90(bra) rotated_ket = bra === ket ? rotated_bra : rotl90(ket) @@ -164,16 +162,15 @@ function correlator_vertical( ) end -const CoordCollection{N} = Union{AbstractVector{CartesianIndex{N}},CartesianIndices{N}} +const CoordCollection{N} = Union{AbstractVector{CartesianIndex{N}}, CartesianIndices{N}} function MPSKit.correlator( - bra::InfinitePEPS, - O, - i::CartesianIndex{2}, - js::CoordCollection{2}, - ket::InfinitePEPS, - env::CTMRGEnv, -) + bra::InfinitePEPS, + O, + i::CartesianIndex{2}, js::CoordCollection{2}, + ket::InfinitePEPS, + env::CTMRGEnv, + ) js = vec(js) # map CartesianIndices to actual Vector instead of Matrix if all(==(i[1]) ∘ first ∘ Tuple, js) @@ -186,13 +183,12 @@ function MPSKit.correlator( end function MPSKit.correlator( - bra::InfinitePEPS, - O, - i::CartesianIndex{2}, - j::CartesianIndex{2}, - ket::InfinitePEPS, - env::CTMRGEnv, -) + bra::InfinitePEPS, + O, + i::CartesianIndex{2}, j::CartesianIndex{2}, + ket::InfinitePEPS, + env::CTMRGEnv, + ) return only(correlator(bra, O, i, j:j, ket, env)) end diff --git a/src/algorithms/ctmrg/ctmrg.jl b/src/algorithms/ctmrg/ctmrg.jl index f781f5807..a1cba4fc9 100644 --- a/src/algorithms/ctmrg/ctmrg.jl +++ b/src/algorithms/ctmrg/ctmrg.jl @@ -6,7 +6,7 @@ for contracting infinite PEPS. """ abstract type CTMRGAlgorithm end -const CTMRG_SYMBOLS = IdDict{Symbol,Type{<:CTMRGAlgorithm}}() +const CTMRG_SYMBOLS = IdDict{Symbol, Type{<:CTMRGAlgorithm}}() """ CTMRGAlgorithm(; kwargs...) @@ -14,15 +14,14 @@ const CTMRG_SYMBOLS = IdDict{Symbol,Type{<:CTMRGAlgorithm}}() Keyword argument parser returning the appropriate `CTMRGAlgorithm` algorithm struct. """ function CTMRGAlgorithm(; - alg=Defaults.ctmrg_alg, - tol=Defaults.ctmrg_tol, - maxiter=Defaults.ctmrg_maxiter, - miniter=Defaults.ctmrg_miniter, - verbosity=Defaults.ctmrg_verbosity, - trscheme=(; alg=Defaults.trscheme), - svd_alg=(;), - projector_alg=Defaults.projector_alg, # only allows for Symbol/NamedTuple to expose projector kwargs -) + alg = Defaults.ctmrg_alg, + tol = Defaults.ctmrg_tol, + maxiter = Defaults.ctmrg_maxiter, miniter = Defaults.ctmrg_miniter, + verbosity = Defaults.ctmrg_verbosity, + trscheme = (; alg = Defaults.trscheme), + svd_alg = (;), + projector_alg = Defaults.projector_alg, # only allows for Symbol/NamedTuple to expose projector kwargs + ) # replace symbol with projector alg type haskey(CTMRG_SYMBOLS, alg) || throw(ArgumentError("unknown CTMRG algorithm: $alg")) alg_type = CTMRG_SYMBOLS[alg] @@ -30,7 +29,7 @@ function CTMRGAlgorithm(; # parse CTMRG projector algorithm projector_algorithm = ProjectorAlgorithm(; - alg=projector_alg, svd_alg, trscheme, verbosity + alg = projector_alg, svd_alg, trscheme, verbosity ) return alg_type(tol, maxiter, miniter, verbosity, projector_algorithm) @@ -108,8 +107,8 @@ function leading_boundary(env₀::CTMRGEnv, network::InfiniteSquareNetwork; kwar return leading_boundary(env₀, network, alg) end function leading_boundary( - env₀::CTMRGEnv, network::InfiniteSquareNetwork, alg::CTMRGAlgorithm -) + env₀::CTMRGEnv, network::InfiniteSquareNetwork, alg::CTMRGAlgorithm + ) log = ignore_derivatives(() -> MPSKit.IterLog("CTMRG")) return LoggingExtras.withlevel(; alg.verbosity) do env = deepcopy(env₀) @@ -141,16 +140,16 @@ end # custom CTMRG logging function ctmrg_loginit!(log, η, network, env) - @infov 2 loginit!(log, η, network_value(network, env)) + return @infov 2 loginit!(log, η, network_value(network, env)) end function ctmrg_logiter!(log, iter, η, network, env) - @infov 3 logiter!(log, iter, η, network_value(network, env)) + return @infov 3 logiter!(log, iter, η, network_value(network, env)) end function ctmrg_logfinish!(log, iter, η, network, env) - @infov 2 logfinish!(log, iter, η, network_value(network, env)) + return @infov 2 logfinish!(log, iter, η, network_value(network, env)) end function ctmrg_logcancel!(log, iter, η, network, env) - @warnv 1 logcancel!(log, iter, η, network_value(network, env)) + return @warnv 1 logcancel!(log, iter, η, network_value(network, env)) end @non_differentiable ctmrg_loginit!(args...) diff --git a/src/algorithms/ctmrg/gaugefix.jl b/src/algorithms/ctmrg/gaugefix.jl index af9eec742..c5aa9e504 100644 --- a/src/algorithms/ctmrg/gaugefix.jl +++ b/src/algorithms/ctmrg/gaugefix.jl @@ -6,7 +6,7 @@ This assumes that the `envfinal` is the result of one CTMRG iteration on `envpre Given that the CTMRG run is converged, the returned environment will be element-wise converged to `envprev`. """ -function gauge_fix(envprev::CTMRGEnv{C,T}, envfinal::CTMRGEnv{C,T}) where {C,T} +function gauge_fix(envprev::CTMRGEnv{C, T}, envfinal::CTMRGEnv{C, T}) where {C, T} # Check if spaces in envprev and envfinal are the same same_spaces = map(eachcoordinate(envfinal, 1:4)) do (dir, r, c) space(envfinal.edges[dir, r, c]) == space(envprev.edges[dir, r, c]) && @@ -57,10 +57,9 @@ end # this is a bit of a hack to get the fixed point of the mixed transfer matrix # because MPSKit is not compatible with AD @generated function _transfer_right( - v::AbstractTensorMap{<:Any,S,1,N₁}, - A::GenericMPSTensor{S,N₂}, - Abar::GenericMPSTensor{S,N₂}, -) where {S,N₁,N₂} + v::AbstractTensorMap{<:Any, S, 1, N₁}, + A::GenericMPSTensor{S, N₂}, Abar::GenericMPSTensor{S, N₂}, + ) where {S, N₁, N₂} t_out = tensorexpr(:v, -1, -(2:(N₁ + 1))) t_top = tensorexpr(:A, (-1, reverse(3:(N₂ + 1))...), 1) t_bot = tensorexpr(:Abar, (-(N₁ + 1), reverse(3:(N₂ + 1))...), 2) @@ -71,7 +70,7 @@ end end function transfermatrix_fixedpoint(tops, bottoms, ρinit) _, vecs, info = eigsolve(ρinit, 1, :LM, Arnoldi()) do ρ - return foldr(zip(tops, bottoms); init=ρ) do (top, bottom), ρ + return foldr(zip(tops, bottoms); init = ρ) do (top, bottom), ρ return _transfer_right(ρ, top, bottom) end end @@ -108,8 +107,8 @@ function fix_relative_phases(envfinal::CTMRGEnv, signs) return corners_fixed, edges_fixed end function fix_relative_phases( - U::Array{Ut,3}, V::Array{Vt,3}, signs -) where {Ut<:AbstractTensorMap,Vt<:AbstractTensorMap} + U::Array{Ut, 3}, V::Array{Vt, 3}, signs + ) where {Ut <: AbstractTensorMap, Vt <: AbstractTensorMap} U_fixed = map(CartesianIndices(U)) do I dir, r, c = I.I if dir == NORTHWEST @@ -164,7 +163,7 @@ end Check if the element-wise difference of the corner and edge tensors of the final and fixed CTMRG environments are below `atol` and return the maximal difference. """ -function calc_elementwise_convergence(envfinal::CTMRGEnv, envfix::CTMRGEnv; atol::Real=1e-6) +function calc_elementwise_convergence(envfinal::CTMRGEnv, envfix::CTMRGEnv; atol::Real = 1.0e-6) ΔC = envfinal.corners .- envfix.corners ΔCmax = norm(ΔC, Inf) ΔCmean = norm(ΔC) diff --git a/src/algorithms/ctmrg/projectors.jl b/src/algorithms/ctmrg/projectors.jl index fe364b484..f2dc247b3 100644 --- a/src/algorithms/ctmrg/projectors.jl +++ b/src/algorithms/ctmrg/projectors.jl @@ -5,7 +5,7 @@ Abstract super type for all CTMRG projector algorithms. """ abstract type ProjectorAlgorithm end -const PROJECTOR_SYMBOLS = IdDict{Symbol,Type{<:ProjectorAlgorithm}}() +const PROJECTOR_SYMBOLS = IdDict{Symbol, Type{<:ProjectorAlgorithm}}() """ ProjectorAlgorithm(; kwargs...) @@ -13,11 +13,11 @@ const PROJECTOR_SYMBOLS = IdDict{Symbol,Type{<:ProjectorAlgorithm}}() Keyword argument parser returning the appropriate `ProjectorAlgorithm` algorithm struct. """ function ProjectorAlgorithm(; - alg=Defaults.projector_alg, - svd_alg=(;), - trscheme=(;), - verbosity=Defaults.projector_verbosity, -) + alg = Defaults.projector_alg, + svd_alg = (;), + trscheme = (;), + verbosity = Defaults.projector_verbosity, + ) # replace symbol with projector alg type haskey(PROJECTOR_SYMBOLS, alg) || throw(ArgumentError("unknown projector algorithm: $alg")) @@ -43,24 +43,16 @@ function svd_algorithm(alg::ProjectorAlgorithm, (dir, r, c)) fwd_alg = alg.svd_alg.fwd_alg fix_svd = if isfullsvd(alg.svd_alg.fwd_alg) FixedSVD( - fwd_alg.U[dir, r, c], - fwd_alg.S[dir, r, c], - fwd_alg.V[dir, r, c], - fwd_alg.U_full[dir, r, c], - fwd_alg.S_full[dir, r, c], - fwd_alg.V_full[dir, r, c], + fwd_alg.U[dir, r, c], fwd_alg.S[dir, r, c], fwd_alg.V[dir, r, c], + fwd_alg.U_full[dir, r, c], fwd_alg.S_full[dir, r, c], fwd_alg.V_full[dir, r, c], ) else FixedSVD( - fwd_alg.U[dir, r, c], - fwd_alg.S[dir, r, c], - fwd_alg.V[dir, r, c], - nothing, - nothing, - nothing, + fwd_alg.U[dir, r, c], fwd_alg.S[dir, r, c], fwd_alg.V[dir, r, c], + nothing, nothing, nothing, ) end - return SVDAdjoint(; fwd_alg=fix_svd, rrule_alg=alg.svd_alg.rrule_alg) + return SVDAdjoint(; fwd_alg = fix_svd, rrule_alg = alg.svd_alg.rrule_alg) else return alg.svd_alg end @@ -101,13 +93,13 @@ Construct the half-infinite projector algorithm based on the following keyword a 0. Suppress output information 1. Print singular value degeneracy warnings """ -struct HalfInfiniteProjector{S<:SVDAdjoint,T} <: ProjectorAlgorithm +struct HalfInfiniteProjector{S <: SVDAdjoint, T} <: ProjectorAlgorithm svd_alg::S trscheme::T verbosity::Int end function HalfInfiniteProjector(; kwargs...) - return ProjectorAlgorithm(; alg=:halfinfinite, kwargs...) + return ProjectorAlgorithm(; alg = :halfinfinite, kwargs...) end PROJECTOR_SYMBOLS[:halfinfinite] = HalfInfiniteProjector @@ -139,13 +131,13 @@ Construct the full-infinite projector algorithm based on the following keyword a 0. Suppress output information 1. Print singular value degeneracy warnings """ -struct FullInfiniteProjector{S<:SVDAdjoint,T} <: ProjectorAlgorithm +struct FullInfiniteProjector{S <: SVDAdjoint, T} <: ProjectorAlgorithm svd_alg::S trscheme::T verbosity::Int end function FullInfiniteProjector(; kwargs...) - return ProjectorAlgorithm(; alg=:fullinfinite, kwargs...) + return ProjectorAlgorithm(; alg = :fullinfinite, kwargs...) end PROJECTOR_SYMBOLS[:fullinfinite] = FullInfiniteProjector @@ -160,7 +152,7 @@ function compute_projector(enlarged_corners, coordinate, alg::HalfInfiniteProjec # SVD half-infinite environment halfinf = half_infinite_environment(enlarged_corners...) svd_alg = svd_algorithm(alg, coordinate) - U, S, V, info = PEPSKit.tsvd!(halfinf, svd_alg; trunc=alg.trscheme) + U, S, V, info = PEPSKit.tsvd!(halfinf, svd_alg; trunc = alg.trscheme) # Check for degenerate singular values Zygote.isderiving() && ignore_derivatives() do @@ -181,7 +173,7 @@ function compute_projector(enlarged_corners, coordinate, alg::FullInfiniteProjec # SVD full-infinite environment fullinf = full_infinite_environment(halfinf_left, halfinf_right) svd_alg = svd_algorithm(alg, coordinate) - U, S, V, info = PEPSKit.tsvd!(fullinf, svd_alg; trunc=alg.trscheme) + U, S, V, info = PEPSKit.tsvd!(fullinf, svd_alg; trunc = alg.trscheme) # Check for degenerate singular values Zygote.isderiving() && ignore_derivatives() do diff --git a/src/algorithms/ctmrg/sequential.jl b/src/algorithms/ctmrg/sequential.jl index adeb94d51..04be3285b 100644 --- a/src/algorithms/ctmrg/sequential.jl +++ b/src/algorithms/ctmrg/sequential.jl @@ -24,7 +24,7 @@ For a full description, see [`leading_boundary`](@ref). The supported keywords a * `svd_alg::Union{<:SVDAdjoint,NamedTuple}` * `projector_alg::Symbol=:$(Defaults.projector_alg)` """ -struct SequentialCTMRG{P<:ProjectorAlgorithm} <: CTMRGAlgorithm +struct SequentialCTMRG{P <: ProjectorAlgorithm} <: CTMRGAlgorithm tol::Float64 maxiter::Int miniter::Int @@ -32,7 +32,7 @@ struct SequentialCTMRG{P<:ProjectorAlgorithm} <: CTMRGAlgorithm projector_alg::P end function SequentialCTMRG(; kwargs...) - return CTMRGAlgorithm(; alg=:sequential, kwargs...) + return CTMRGAlgorithm(; alg = :sequential, kwargs...) end CTMRG_SYMBOLS[:sequential] = SequentialCTMRG @@ -82,7 +82,7 @@ for a specific `coordinate` (where `dir=WEST` is already implied in the `:sequen function sequential_projectors(col::Int, network, env::CTMRGEnv, alg::ProjectorAlgorithm) coordinates = eachcoordinate(env)[:, col] T_dst = Base.promote_op( - sequential_projectors, NTuple{3,Int}, typeof(network), typeof(env), typeof(alg) + sequential_projectors, NTuple{3, Int}, typeof(network), typeof(env), typeof(alg) ) proj_and_info = similar(coordinates, T_dst) proj_and_info′::typeof(proj_and_info) = dtmap!!(proj_and_info, coordinates) do (r, c) @@ -95,8 +95,8 @@ function sequential_projectors(col::Int, network, env::CTMRGEnv, alg::ProjectorA return _split_proj_and_info(proj_and_info′) end function sequential_projectors( - coordinate::NTuple{3,Int}, network, env::CTMRGEnv, alg::HalfInfiniteProjector -) + coordinate::NTuple{3, Int}, network, env::CTMRGEnv, alg::HalfInfiniteProjector + ) _, r, c = coordinate r′ = _prev(r, size(env, 2)) Q1 = TensorMap(EnlargedCorner(network, env, (SOUTHWEST, r, c))) @@ -104,8 +104,8 @@ function sequential_projectors( return compute_projector((Q1, Q2), coordinate, alg) end function sequential_projectors( - coordinate::NTuple{3,Int}, network, env::CTMRGEnv, alg::FullInfiniteProjector -) + coordinate::NTuple{3, Int}, network, env::CTMRGEnv, alg::FullInfiniteProjector + ) rowsize, colsize = size(env)[2:3] coordinate_nw = _next_coordinate(coordinate, rowsize, colsize) coordinate_ne = _next_coordinate(coordinate_nw, rowsize, colsize) diff --git a/src/algorithms/ctmrg/simultaneous.jl b/src/algorithms/ctmrg/simultaneous.jl index 01d6139ee..ffe68bec2 100644 --- a/src/algorithms/ctmrg/simultaneous.jl +++ b/src/algorithms/ctmrg/simultaneous.jl @@ -23,7 +23,7 @@ For a full description, see [`leading_boundary`](@ref). The supported keywords a * `svd_alg::Union{<:SVDAdjoint,NamedTuple}` * `projector_alg::Symbol=:$(Defaults.projector_alg)` """ -struct SimultaneousCTMRG{P<:ProjectorAlgorithm} <: CTMRGAlgorithm +struct SimultaneousCTMRG{P <: ProjectorAlgorithm} <: CTMRGAlgorithm tol::Float64 maxiter::Int miniter::Int @@ -31,7 +31,7 @@ struct SimultaneousCTMRG{P<:ProjectorAlgorithm} <: CTMRGAlgorithm projector_alg::P end function SimultaneousCTMRG(; kwargs...) - return CTMRGAlgorithm(; alg=:simultaneous, kwargs...) + return CTMRGAlgorithm(; alg = :simultaneous, kwargs...) end CTMRG_SYMBOLS[:simultaneous] = SimultaneousCTMRG @@ -44,8 +44,8 @@ function ctmrg_iteration(network, env::CTMRGEnv, alg::SimultaneousCTMRG) enlarged_corners′ = similar(coordinates, T_corners) enlarged_corners::typeof(enlarged_corners′) = dtmap!!(enlarged_corners′, eachcoordinate(network, 1:4)) do idx - return TensorMap(EnlargedCorner(network, env, idx)) - end # expand environment + return TensorMap(EnlargedCorner(network, env, idx)) + end # expand environment projectors, info = simultaneous_projectors(enlarged_corners, env, alg.projector_alg) # compute projectors on all coordinates env′ = renormalize_simultaneously(enlarged_corners, projectors, network, env) # renormalize enlarged corners return env′, info @@ -76,26 +76,23 @@ Compute CTMRG projectors in the `:simultaneous` scheme either for all provided enlarged corners or on a specific `coordinate`. """ function simultaneous_projectors( - enlarged_corners::Array{E,3}, env::CTMRGEnv, alg::ProjectorAlgorithm -) where {E} + enlarged_corners::Array{E, 3}, env::CTMRGEnv, alg::ProjectorAlgorithm + ) where {E} coordinates = eachcoordinate(env, 1:4) T_dst = Base.promote_op( simultaneous_projectors, - NTuple{3,Int}, - typeof(enlarged_corners), - typeof(env), - typeof(alg), + NTuple{3, Int}, typeof(enlarged_corners), typeof(env), typeof(alg), ) proj_and_info′ = similar(coordinates, T_dst) proj_and_info::typeof(proj_and_info′) = dtmap!!(proj_and_info′, coordinates) do coordinate - return simultaneous_projectors(coordinate, enlarged_corners, env, alg) - end + return simultaneous_projectors(coordinate, enlarged_corners, env, alg) + end return _split_proj_and_info(proj_and_info) end function simultaneous_projectors( - coordinate, enlarged_corners::Array{E,3}, env, alg::HalfInfiniteProjector -) where {E} + coordinate, enlarged_corners::Array{E, 3}, env, alg::HalfInfiniteProjector + ) where {E} coordinate′ = _next_coordinate(coordinate, size(env)[2:3]...) trscheme = truncation_scheme(alg, env.edges[coordinate[1], coordinate′[2:3]...]) alg′ = @set alg.trscheme = trscheme @@ -103,8 +100,8 @@ function simultaneous_projectors( return compute_projector(ec, coordinate, alg′) end function simultaneous_projectors( - coordinate, enlarged_corners::Array{E,3}, env, alg::FullInfiniteProjector -) where {E} + coordinate, enlarged_corners::Array{E, 3}, env, alg::FullInfiniteProjector + ) where {E} coordinate′ = _next_coordinate(coordinate, size(env)[2:3]...) trscheme = truncation_scheme(alg, env.edges[coordinate[1], coordinate′[2:3]...]) alg′ = @set alg.trscheme = trscheme @@ -129,33 +126,33 @@ Renormalize all enlarged corners and edges simultaneously. function renormalize_simultaneously(enlarged_corners, projectors, network, env) P_left, P_right = projectors coordinates = eachcoordinate(env, 1:4) - T_CE = Tuple{cornertype(env),edgetype(env)} + T_CE = Tuple{cornertype(env), edgetype(env)} corners_edges′ = similar(coordinates, T_CE) corners_edges::typeof(corners_edges′) = dtmap!!(corners_edges′, coordinates) do (dir, r, c) - if dir == NORTH - corner = renormalize_northwest_corner( - (r, c), enlarged_corners, P_left, P_right - ) - edge = renormalize_north_edge((r, c), env, P_left, P_right, network) - elseif dir == EAST - corner = renormalize_northeast_corner( - (r, c), enlarged_corners, P_left, P_right - ) - edge = renormalize_east_edge((r, c), env, P_left, P_right, network) - elseif dir == SOUTH - corner = renormalize_southeast_corner( - (r, c), enlarged_corners, P_left, P_right - ) - edge = renormalize_south_edge((r, c), env, P_left, P_right, network) - elseif dir == WEST - corner = renormalize_southwest_corner( - (r, c), enlarged_corners, P_left, P_right - ) - edge = renormalize_west_edge((r, c), env, P_left, P_right, network) - end - return corner / norm(corner), edge / norm(edge) + if dir == NORTH + corner = renormalize_northwest_corner( + (r, c), enlarged_corners, P_left, P_right + ) + edge = renormalize_north_edge((r, c), env, P_left, P_right, network) + elseif dir == EAST + corner = renormalize_northeast_corner( + (r, c), enlarged_corners, P_left, P_right + ) + edge = renormalize_east_edge((r, c), env, P_left, P_right, network) + elseif dir == SOUTH + corner = renormalize_southeast_corner( + (r, c), enlarged_corners, P_left, P_right + ) + edge = renormalize_south_edge((r, c), env, P_left, P_right, network) + elseif dir == WEST + corner = renormalize_southwest_corner( + (r, c), enlarged_corners, P_left, P_right + ) + edge = renormalize_west_edge((r, c), env, P_left, P_right, network) end + return corner / norm(corner), edge / norm(edge) + end return CTMRGEnv(map(first, corners_edges), map(last, corners_edges)) end diff --git a/src/algorithms/ctmrg/sparse_environments.jl b/src/algorithms/ctmrg/sparse_environments.jl index 1085be036..be84ec28a 100644 --- a/src/algorithms/ctmrg/sparse_environments.jl +++ b/src/algorithms/ctmrg/sparse_environments.jl @@ -15,7 +15,7 @@ Construct an enlarged corner with the correct row and column indices based on th `coordinates` which are of the form `(dir, row, col)`. """ -struct EnlargedCorner{TC,TE,TA} +struct EnlargedCorner{TC, TE, TA} C::TC E_1::TE E_2::TE @@ -98,7 +98,7 @@ function half_infinite_environment(ec_1::EnlargedCorner, ec_2::EnlargedCorner) return HalfInfiniteEnv(ec_1, ec_2) end -# Compute left and right projectors sparsely without constructing enlarged corners explicitly +# Compute left and right projectors sparsely without constructing enlarged corners explicitly function left_and_right_projector(U, S, V, Q::EnlargedCorner, Q_next::EnlargedCorner) isqS = sdiag_pow(S, -0.5) P_left = left_projector(Q.E_1, Q.C, Q.E_2, V, isqS, Q.A) @@ -125,7 +125,7 @@ $(FIELDS) Construct sparse half-infinite environment based on two sparse enlarged corners (quadrants). """ -struct HalfInfiniteEnv{TC,TE,TA} # TODO: subtype as AbstractTensorMap once TensorKit is updated +struct HalfInfiniteEnv{TC, TE, TA} # TODO: subtype as AbstractTensorMap once TensorKit is updated C_1::TC C_2::TC E_1::TE @@ -137,14 +137,9 @@ struct HalfInfiniteEnv{TC,TE,TA} # TODO: subtype as AbstractTensorMap once Tens end function HalfInfiniteEnv(quadrant1::EnlargedCorner, quadrant2::EnlargedCorner) return HalfInfiniteEnv( - quadrant1.C, - quadrant2.C, - quadrant1.E_1, - quadrant1.E_2, - quadrant2.E_1, - quadrant2.E_2, - quadrant1.A_1, - quadrant2.A_2, + quadrant1.C, quadrant2.C, + quadrant1.E_1, quadrant1.E_2, quadrant2.E_1, quadrant2.E_2, + quadrant1.A_1, quadrant2.A_2, ) end @@ -213,7 +208,7 @@ $(FIELDS) Construct sparse full-infinite environment based on four sparse enlarged corners (quadrants). """ -struct FullInfiniteEnv{TC,TE,TA} # TODO: subtype as AbstractTensorMap once TensorKit is updated +struct FullInfiniteEnv{TC, TE, TA} # TODO: subtype as AbstractTensorMap once TensorKit is updated C_1::TC C_2::TC C_3::TC @@ -232,25 +227,13 @@ struct FullInfiniteEnv{TC,TE,TA} # TODO: subtype as AbstractTensorMap once Tens A_4::TA end function FullInfiniteEnv( - quadrant1::E, quadrant2::E, quadrant3::E, quadrant4::E -) where {E<:EnlargedCorner} + quadrant1::E, quadrant2::E, quadrant3::E, quadrant4::E + ) where {E <: EnlargedCorner} return FullInfiniteEnv( - quadrant1.C, - quadrant2.C, - quadrant3.C, - quadrant4.C, - quadrant1.E_1, - quadrant1.E_2, - quadrant2.E_1, - quadrant2.E_2, - quadrant3.E_1, - quadrant3.E_2, - quadrant4.E_1, - quadrant4.E_2, - quadrant1.A, - quadrant2.A, - quadrant3.A, - quadrant4.A, + quadrant1.C, quadrant2.C, quadrant3.C, quadrant4.C, + quadrant1.E_1, quadrant1.E_2, quadrant2.E_1, quadrant2.E_2, + quadrant3.E_1, quadrant3.E_2, quadrant4.E_1, quadrant4.E_2, + quadrant1.A, quadrant2.A, quadrant3.A, quadrant4.A, ) end @@ -261,22 +244,9 @@ Instantiate full-infinite environment as `TensorMap` explicitly. """ function TensorKit.TensorMap(env::FullInfiniteEnv) # Dense operator return full_infinite_environment( - env.C_1, - env.C_2, - env.C_3, - env.C_4, - env.E_1, - env.E_2, - env.E_3, - env.E_4, - env.E_2, - env.E_3, - env.E_4, - env.E_5, - env.A_1, - env.A_2, - env.A_3, - env.A_4, + env.C_1, env.C_2, env.C_3, env.C_4, + env.E_1, env.E_2, env.E_3, env.E_4, env.E_2, env.E_3, env.E_4, env.E_5, + env.A_1, env.A_2, env.A_3, env.A_4, ) end @@ -289,51 +259,25 @@ linear map or adjoint linear map on `x` if `Val(true)` or `Val(false)` is passed """ function (env::FullInfiniteEnv)(x, ::Val{false}) # Linear map: env() * x return full_infinite_environment( - env.C_1, - env.C_2, - env.C_3, - env.C_4, - env.E_1, - env.E_2, - env.E_3, - env.E_4, - env.E_5, - env.E_6, - env.E_7, - env.E_8, + env.C_1, env.C_2, env.C_3, env.C_4, + env.E_1, env.E_2, env.E_3, env.E_4, env.E_5, env.E_6, env.E_7, env.E_8, x, - env.A_1, - env.A_2, - env.A_3, - env.A_4, + env.A_1, env.A_2, env.A_3, env.A_4, ) end function (env::FullInfiniteEnv)(x, ::Val{true}) # Adjoint linear map: env()' * x return full_infinite_environment( x, - env.C_1, - env.C_2, - env.C_3, - env.C_4, - env.E_1, - env.E_2, - env.E_3, - env.E_4, - env.E_5, - env.E_6, - env.E_7, - env.E_8, - env.A_1, - env.A_2, - env.A_3, - env.A_4, + env.C_1, env.C_2, env.C_3, env.C_4, + env.E_1, env.E_2, env.E_3, env.E_4, env.E_5, env.E_6, env.E_7, env.E_8, + env.A_1, env.A_2, env.A_3, env.A_4, ) end # Wrapper around full_infinite_environment contraction using EnlargedCorners (used in ctmrg_projectors) function full_infinite_environment( - ec_1::E, ec_2::E, ec_3::E, ec_4::E -) where {E<:EnlargedCorner} + ec_1::E, ec_2::E, ec_3::E, ec_4::E + ) where {E <: EnlargedCorner} return FullInfiniteEnv(ec_1, ec_2, ec_3, ec_4) end diff --git a/src/algorithms/optimization/fixed_point_differentiation.jl b/src/algorithms/optimization/fixed_point_differentiation.jl index d83fdbf13..f625ba41c 100644 --- a/src/algorithms/optimization/fixed_point_differentiation.jl +++ b/src/algorithms/optimization/fixed_point_differentiation.jl @@ -1,10 +1,10 @@ abstract type GradMode{F} end -const GRADIENT_MODE_SYMBOLS = IdDict{Symbol,Type{<:GradMode}}() -const LINSOLVER_SOLVER_SYMBOLS = IdDict{Symbol,Type{<:KrylovKit.LinearSolver}}( +const GRADIENT_MODE_SYMBOLS = IdDict{Symbol, Type{<:GradMode}}() +const LINSOLVER_SOLVER_SYMBOLS = IdDict{Symbol, Type{<:KrylovKit.LinearSolver}}( :gmres => GMRES, :bicgstab => BiCGStab ) -const EIGSOLVER_SOLVER_SYMBOLS = IdDict{Symbol,Type{<:KrylovKit.KrylovAlgorithm}}( +const EIGSOLVER_SOLVER_SYMBOLS = IdDict{Symbol, Type{<:KrylovKit.KrylovAlgorithm}}( :arnoldi => Arnoldi ) @@ -14,35 +14,35 @@ const EIGSOLVER_SOLVER_SYMBOLS = IdDict{Symbol,Type{<:KrylovKit.KrylovAlgorithm} Keyword argument parser returning the appropriate `GradMode` algorithm struct. """ function GradMode(; - alg=Defaults.gradient_alg, - tol=Defaults.gradient_tol, - maxiter=Defaults.gradient_maxiter, - verbosity=Defaults.gradient_verbosity, - iterscheme=Defaults.gradient_iterscheme, - solver_alg=(;), -) + alg = Defaults.gradient_alg, + tol = Defaults.gradient_tol, + maxiter = Defaults.gradient_maxiter, + verbosity = Defaults.gradient_verbosity, + iterscheme = Defaults.gradient_iterscheme, + solver_alg = (;), + ) # replace symbol with GradMode alg type haskey(GRADIENT_MODE_SYMBOLS, alg) || throw(ArgumentError("unknown GradMode algorithm: $alg")) alg_type = GRADIENT_MODE_SYMBOLS[alg] # parse GradMode algorithm - gradient_algorithm = if alg_type <: Union{GeomSum,ManualIter} + gradient_algorithm = if alg_type <: Union{GeomSum, ManualIter} alg_type{iterscheme}(tol, maxiter, verbosity) - elseif alg_type <: Union{<:LinSolver,<:EigSolver} + elseif alg_type <: Union{<:LinSolver, <:EigSolver} solver = if solver_alg isa NamedTuple # determine linear/eigen solver algorithm solver_kwargs = (; tol, maxiter, verbosity, solver_alg...) solver_type = if alg_type <: LinSolver # replace symbol with solver alg type - solver_kwargs = (; alg=Defaults.gradient_linsolver, solver_kwargs...) + solver_kwargs = (; alg = Defaults.gradient_linsolver, solver_kwargs...) haskey(LINSOLVER_SOLVER_SYMBOLS, solver_kwargs.alg) || throw( ArgumentError("unknown LinSolver solver: $(solver_kwargs.alg)"), ) LINSOLVER_SOLVER_SYMBOLS[solver_kwargs.alg] elseif alg_type <: EigSolver solver_kwargs = (; - alg=Defaults.gradient_eigsolver, - eager=Defaults.gradient_eigsolver_eager, + alg = Defaults.gradient_eigsolver, + eager = Defaults.gradient_eigsolver_eager, solver_kwargs..., ) haskey(EIGSOLVER_SOLVER_SYMBOLS, solver_kwargs.alg) || throw( @@ -51,7 +51,7 @@ function GradMode(; EIGSOLVER_SOLVER_SYMBOLS[solver_kwargs.alg] end - solver_kwargs = Base.structdiff(solver_kwargs, (; alg=nothing)) # remove `alg` keyword argument + solver_kwargs = Base.structdiff(solver_kwargs, (; alg = nothing)) # remove `alg` keyword argument solver_type(; solver_kwargs...) else solver_alg @@ -97,7 +97,7 @@ struct GeomSum{F} <: GradMode{F} maxiter::Int verbosity::Int end -GeomSum(; kwargs...) = GradMode(; alg=:geomsum, kwargs...) +GeomSum(; kwargs...) = GradMode(; alg = :geomsum, kwargs...) GRADIENT_MODE_SYMBOLS[:geomsum] = GeomSum @@ -131,7 +131,7 @@ struct ManualIter{F} <: GradMode{F} maxiter::Int verbosity::Int end -ManualIter(; kwargs...) = GradMode(; alg=:manualiter, kwargs...) +ManualIter(; kwargs...) = GradMode(; alg = :manualiter, kwargs...) GRADIENT_MODE_SYMBOLS[:manualiter] = ManualIter @@ -164,7 +164,7 @@ Construct the `LinSolver` algorithm struct based on the following keyword argume struct LinSolver{F} <: GradMode{F} solver_alg::KrylovKit.LinearSolver end -LinSolver(; kwargs...) = GradMode(; alg=:linsolver, kwargs...) +LinSolver(; kwargs...) = GradMode(; alg = :linsolver, kwargs...) GRADIENT_MODE_SYMBOLS[:linsolver] = LinSolver @@ -196,7 +196,7 @@ Construct the `EigSolver` algorithm struct based on the following keyword argume struct EigSolver{F} <: GradMode{F} solver_alg::KrylovKit.KrylovAlgorithm end -EigSolver(; kwargs...) = GradMode(; alg=:eigsolver, kwargs...) +EigSolver(; kwargs...) = GradMode(; alg = :eigsolver, kwargs...) GRADIENT_MODE_SYMBOLS[:eigsolver] = EigSolver @@ -208,13 +208,13 @@ Evaluating the gradient of the cost function for CTMRG: =# function _rrule( - gradmode::GradMode{:diffgauge}, - config::RuleConfig, - ::typeof(leading_boundary), - envinit, - state, - alg::CTMRGAlgorithm, -) + gradmode::GradMode{:diffgauge}, + config::RuleConfig, + ::typeof(leading_boundary), + envinit, + state, + alg::CTMRGAlgorithm, + ) env, info = leading_boundary(envinit, state, alg) alg_fixed = @set alg.projector_alg.trscheme = FixedSpaceTruncation() # fix spaces during differentiation @@ -240,13 +240,13 @@ end # Here f is differentiated from an pre-computed SVD with fixed U, S and V function _rrule( - gradmode::GradMode{:fixed}, - config::RuleConfig, - ::typeof(MPSKit.leading_boundary), - envinit, - state, - alg::SimultaneousCTMRG, -) + gradmode::GradMode{:fixed}, + config::RuleConfig, + ::typeof(MPSKit.leading_boundary), + envinit, + state, + alg::SimultaneousCTMRG, + ) env, = leading_boundary(envinit, state, alg) env_conv, info = ctmrg_iteration(InfiniteSquareNetwork(state), env, alg) env_fixed, signs = gauge_fix(env, env_conv) @@ -294,16 +294,16 @@ function _fix_svd_algorithm(alg::SVDAdjoint, signs, info) U_fixed, V_fixed = fix_relative_phases(info.U, info.V, signs) U_full_fixed, V_full_fixed = fix_relative_phases(info.U_full, info.V_full, signs_full) return SVDAdjoint(; - fwd_alg=FixedSVD(U_fixed, info.S, V_fixed, U_full_fixed, info.S_full, V_full_fixed), - rrule_alg=alg.rrule_alg, + fwd_alg = FixedSVD(U_fixed, info.S, V_fixed, U_full_fixed, info.S_full, V_full_fixed), + rrule_alg = alg.rrule_alg, ) end -function _fix_svd_algorithm(alg::SVDAdjoint{F}, signs, info) where {F<:IterSVD} +function _fix_svd_algorithm(alg::SVDAdjoint{F}, signs, info) where {F <: IterSVD} # fix kept U and V only since iterative SVD doesn't have access to full spectrum U_fixed, V_fixed = fix_relative_phases(info.U, info.V, signs) return SVDAdjoint(; - fwd_alg=FixedSVD(U_fixed, info.S, V_fixed, nothing, nothing, nothing), - rrule_alg=alg.rrule_alg, + fwd_alg = FixedSVD(U_fixed, info.S, V_fixed, nothing, nothing, nothing), + rrule_alg = alg.rrule_alg, ) end @@ -390,7 +390,7 @@ function fpgrad(∂F∂x, ∂f∂x, ∂f∂A, x₀, alg::EigSolver) if alg.solver_alg.verbosity > 0 && info.converged < 1 @warn("gradient fixed-point iteration reached maximal number of iterations:", info) end - if norm(vecs[1][2]) < 1e-2 * alg.solver_alg.tol + if norm(vecs[1][2]) < 1.0e-2 * alg.solver_alg.tol @warn "Fixed-point gradient computation using Arnoldi failed: auxiliary component should be finite but was $(vecs[1][2]). Possibly the Jacobian does not have a unique eigenvalue 1." end y = scale(vecs[1][1], 1 / vecs[1][2]) diff --git a/src/algorithms/optimization/peps_optimization.jl b/src/algorithms/optimization/peps_optimization.jl index bf50dc01f..1ab23544b 100644 --- a/src/algorithms/optimization/peps_optimization.jl +++ b/src/algorithms/optimization/peps_optimization.jl @@ -25,15 +25,12 @@ struct PEPSOptimize{G} gradient_alg::G optimizer_alg::OptimKit.OptimizationAlgorithm reuse_env::Bool - symmetrization::Union{Nothing,SymmetrizationStyle} + symmetrization::Union{Nothing, SymmetrizationStyle} function PEPSOptimize( # Inner constructor to prohibit illegal setting combinations - boundary_alg::CTMRGAlgorithm, - gradient_alg::G, - optimizer_alg, - reuse_env, - symmetrization, - ) where {G} + boundary_alg::CTMRGAlgorithm, gradient_alg::G, optimizer_alg, + reuse_env, symmetrization, + ) where {G} if gradient_alg isa GradMode if boundary_alg isa SequentialCTMRG && iterscheme(gradient_alg) === :fixed msg = ":fixed was converted to :diffgauge since SequentialCTMRG does not \ @@ -47,26 +44,20 @@ struct PEPSOptimize{G} end function PEPSOptimize(; - boundary_alg=(;), - gradient_alg=(;), - optimizer_alg=(;), - reuse_env=Defaults.reuse_env, - symmetrization=nothing, -) + boundary_alg = (;), gradient_alg = (;), optimizer_alg = (;), + reuse_env = Defaults.reuse_env, symmetrization = nothing, + ) boundary_algorithm = _alg_or_nt(CTMRGAlgorithm, boundary_alg) gradient_algorithm = _alg_or_nt(GradMode, gradient_alg) optimizer_algorithm = _alg_or_nt(OptimKit.OptimizationAlgorithm, optimizer_alg) return PEPSOptimize( - boundary_algorithm, - gradient_algorithm, - optimizer_algorithm, - reuse_env, - symmetrization, + boundary_algorithm, gradient_algorithm, optimizer_algorithm, + reuse_env, symmetrization, ) end -const OPTIMIZATION_SYMBOLS = IdDict{Symbol,Type{<:OptimKit.OptimizationAlgorithm}}( +const OPTIMIZATION_SYMBOLS = IdDict{Symbol, Type{<:OptimKit.OptimizationAlgorithm}}( :gradientdescent => GradientDescent, :conjugategradient => ConjugateGradient, :lbfgs => LBFGS, @@ -78,15 +69,15 @@ function _alg_or_nt(::Type{<:OptimKit.OptimizationAlgorithm}, alg::NamedTuple) end function _OptimizationAlgorithm(; - alg=Defaults.optimizer_alg, - tol=Defaults.optimizer_tol, - maxiter=Defaults.optimizer_maxiter, - verbosity=Defaults.optimizer_verbosity, - ls_maxiter=Defaults.ls_maxiter, - ls_maxfg=Defaults.ls_maxfg, - lbfgs_memory=Defaults.lbfgs_memory, - # TODO: add linesearch, ... to kwargs and defaults? -) + alg = Defaults.optimizer_alg, + tol = Defaults.optimizer_tol, + maxiter = Defaults.optimizer_maxiter, + verbosity = Defaults.optimizer_verbosity, + ls_maxiter = Defaults.ls_maxiter, + ls_maxfg = Defaults.ls_maxfg, + lbfgs_memory = Defaults.lbfgs_memory, + # TODO: add linesearch, ... to kwargs and defaults? + ) # replace symbol with optimizer alg type haskey(OPTIMIZATION_SYMBOLS, alg) || throw(ArgumentError("unknown optimizer algorithm: $alg")) @@ -94,9 +85,9 @@ function _OptimizationAlgorithm(; # instantiate algorithm return if alg_type <: LBFGS - alg_type(lbfgs_memory; gradtol=tol, maxiter, verbosity, ls_maxiter, ls_maxfg) + alg_type(lbfgs_memory; gradtol = tol, maxiter, verbosity, ls_maxiter, ls_maxfg) else - alg_type(; gradtol=tol, maxiter, verbosity, ls_maxiter, ls_maxfg) + alg_type(; gradtol = tol, maxiter, verbosity, ls_maxiter, ls_maxfg) end end @@ -187,22 +178,16 @@ information `NamedTuple` which contains the following entries: * `times` : History of optimization step execution times. """ function fixedpoint( - operator, - peps₀::InfinitePEPS, - env₀::CTMRGEnv; - (finalize!)=OptimKit._finalize!, - kwargs..., -) + operator, peps₀::InfinitePEPS, env₀::CTMRGEnv; + (finalize!) = OptimKit._finalize!, kwargs..., + ) alg = select_algorithm(fixedpoint, env₀; kwargs...) return fixedpoint(operator, peps₀, env₀, alg; finalize!) end function fixedpoint( - operator, - peps₀::InfinitePEPS, - env₀::CTMRGEnv, - alg::PEPSOptimize; - (finalize!)=OptimKit._finalize!, -) + operator, peps₀::InfinitePEPS, env₀::CTMRGEnv, alg::PEPSOptimize; + (finalize!) = OptimKit._finalize!, + ) # setup retract and finalize! for symmetrization if isnothing(alg.symmetrization) retract = peps_retract @@ -235,21 +220,14 @@ function fixedpoint( # optimize operator cost function (peps_final, env_final), cost_final, ∂cost, numfg, convergence_history = optimize( - (peps₀, env₀), - alg.optimizer_alg; - retract, - inner=real_inner, - finalize!, - (transport!)=(peps_transport!), + (peps₀, env₀), alg.optimizer_alg; + retract, inner = real_inner, finalize!, (transport!) = (peps_transport!), ) do (peps, env) start_time = time_ns() E, gs = withgradient(peps) do ψ env′, info = hook_pullback( - leading_boundary, - env, - ψ, - alg.boundary_alg; - alg_rrule=alg.gradient_alg, + leading_boundary, env, ψ, alg.boundary_alg; + alg_rrule = alg.gradient_alg, ) ignore_derivatives() do alg.reuse_env && update!(env, env′) @@ -260,15 +238,15 @@ function fixedpoint( end g = only(gs) # `withgradient` returns tuple of gradients `gs` push!(gradnorms_unitcell, norm.(g.A)) - push!(times, (time_ns() - start_time) * 1e-9) + push!(times, (time_ns() - start_time) * 1.0e-9) return E, g end info = (; - last_gradient=∂cost, - fg_evaluations=numfg, - costs=convergence_history[:, 1], - gradnorms=convergence_history[:, 2], + last_gradient = ∂cost, + fg_evaluations = numfg, + costs = convergence_history[:, 1], + gradnorms = convergence_history[:, 2], truncation_errors, condition_numbers, gradnorms_unitcell, @@ -348,8 +326,8 @@ real_inner(_, η₁, η₂) = real(dot(η₁, η₂)) Return the `retract` and `finalize!` function for symmetrizing the `peps` and `grad` tensors. """ function symmetrize_retract_and_finalize!( - symm::SymmetrizationStyle, retract=peps_retract, (finalize!)=OptimKit._finalize! -) + symm::SymmetrizationStyle, retract = peps_retract, (finalize!) = OptimKit._finalize! + ) function symmetrize_then_finalize!((peps, env), E, grad, numiter) # symmetrize the gradient grad_symm = symmetrize!(grad, symm) diff --git a/src/algorithms/select_algorithm.jl b/src/algorithms/select_algorithm.jl index cdf731bd9..a2a177a61 100644 --- a/src/algorithms/select_algorithm.jl +++ b/src/algorithms/select_algorithm.jl @@ -1,5 +1,5 @@ _alg_or_nt(::Type{T}, alg::NamedTuple) where {T} = T(; alg...) -_alg_or_nt(::Type{T}, alg::A) where {T,A<:T} = alg +_alg_or_nt(::Type{T}, alg::A) where {T, A <: T} = alg _alg_or_nt(T, alg) = throw(ArgumentError("unkown $T: $alg")) """ @@ -18,18 +18,16 @@ algorithm struct docstrings. function select_algorithm end function select_algorithm( - ::typeof(fixedpoint), - env₀::CTMRGEnv; - tol=Defaults.optimizer_tol, # top-level tolerance - verbosity=3, # top-level verbosity - boundary_alg=(;), - gradient_alg=(;), - optimizer_alg=(;), - kwargs..., -) + ::typeof(fixedpoint), + env₀::CTMRGEnv; + tol = Defaults.optimizer_tol, # top-level tolerance + verbosity = 3, # top-level verbosity + boundary_alg = (;), gradient_alg = (;), optimizer_alg = (;), + kwargs..., + ) # adjust CTMRG tols and verbosity if boundary_alg isa NamedTuple - defaults = (; verbosity=verbosity ≤ 3 ? -1 : 3, tol=1e-4tol) + defaults = (; verbosity = verbosity ≤ 3 ? -1 : 3, tol = 1.0e-4tol) boundary_kwargs = merge(defaults, boundary_alg) boundary_alg = select_algorithm(leading_boundary, env₀; boundary_kwargs...) end @@ -37,7 +35,7 @@ function select_algorithm( # adjust gradient verbosity if gradient_alg isa NamedTuple # TODO: check this: - defaults = (; verbosity=verbosity ≤ 3 ? -1 : 3, tol=1e-2tol) + defaults = (; verbosity = verbosity ≤ 3 ? -1 : 3, tol = 1.0e-2tol) gradient_alg = merge(defaults, gradient_alg) end @@ -51,18 +49,18 @@ function select_algorithm( end function select_algorithm( - ::typeof(leading_boundary), - env₀::CTMRGEnv; - alg=Defaults.ctmrg_alg, - tol=Defaults.ctmrg_tol, - verbosity=Defaults.ctmrg_verbosity, - svd_alg=(;), - kwargs..., -) + ::typeof(leading_boundary), + env₀::CTMRGEnv; + alg = Defaults.ctmrg_alg, + tol = Defaults.ctmrg_tol, + verbosity = Defaults.ctmrg_verbosity, + svd_alg = (;), + kwargs..., + ) # adjust SVD rrule settings to CTMRG tolerance, verbosity and environment dimension if svd_alg isa NamedTuple && - haskey(svd_alg, :rrule_alg) && - svd_alg.rrule_alg isa NamedTuple + haskey(svd_alg, :rrule_alg) && + svd_alg.rrule_alg isa NamedTuple χenv = maximum(env₀.corners) do corner return dim(space(corner, 1)) end @@ -70,10 +68,10 @@ function select_algorithm( krylovdim = max( Defaults.svd_rrule_min_krylovdim, round(Int, Defaults.krylovdim_factor * χenv) ) - rrule_alg = (; tol=1e1tol, verbosity=verbosity - 2, krylovdim, svd_alg.rrule_alg...) + rrule_alg = (; tol = 1.0e1tol, verbosity = verbosity - 2, krylovdim, svd_alg.rrule_alg...) svd_alg = (; rrule_alg, svd_alg...) end svd_algorithm = SVDAdjoint(; svd_alg...) - return CTMRGAlgorithm(; alg, tol, verbosity, svd_alg=svd_algorithm, kwargs...) + return CTMRGAlgorithm(; alg, tol, verbosity, svd_alg = svd_algorithm, kwargs...) end diff --git a/src/algorithms/time_evolution/evoltools.jl b/src/algorithms/time_evolution/evoltools.jl index 4dfab91da..2f5e53ff7 100644 --- a/src/algorithms/time_evolution/evoltools.jl +++ b/src/algorithms/time_evolution/evoltools.jl @@ -28,10 +28,9 @@ end Check if two 2-site bonds are related by a (periodic) lattice translation. """ function is_equivalent_bond( - bond1::NTuple{2,CartesianIndex{2}}, - bond2::NTuple{2,CartesianIndex{2}}, - (Nrow, Ncol)::NTuple{2,Int}, -) + bond1::NTuple{2, CartesianIndex{2}}, bond2::NTuple{2, CartesianIndex{2}}, + (Nrow, Ncol)::NTuple{2, Int}, + ) r1 = bond1[1] - bond1[2] r2 = bond2[1] - bond2[2] shift_row = bond1[1][1] - bond2[1][1] @@ -45,7 +44,7 @@ end Get the term of a 2-site gate acting on a certain bond. Input `gate` should only include one term for each nearest neighbor bond. """ -function get_gateterm(gate::LocalOperator, bond::NTuple{2,CartesianIndex{2}}) +function get_gateterm(gate::LocalOperator, bond::NTuple{2, CartesianIndex{2}}) bonds = findall(p -> is_equivalent_bond(p.first, bond, size(gate.lattice)), gate.terms) if length(bonds) == 0 # try reversed site order @@ -135,11 +134,10 @@ Apply 2-site `gate` on the reduced matrices `a`, `b` ``` """ function _apply_gate( - a::AbstractTensorMap{T,S}, - b::AbstractTensorMap{T,S}, - gate::AbstractTensorMap{T,S,2,2}, - trscheme::TruncationScheme, -) where {T<:Number,S<:ElementarySpace} + a::AbstractTensorMap{T, S}, b::AbstractTensorMap{T, S}, + gate::AbstractTensorMap{T, S, 2, 2}, + trscheme::TruncationScheme, + ) where {T <: Number, S <: ElementarySpace} @tensor a2b2[-1 -2; -3 -4] := gate[-2 -3; 1 2] * a[-1 1 3] * b[3 2 -4] trunc = if trscheme isa FixedSpaceTruncation V = space(b, 1) @@ -147,7 +145,7 @@ function _apply_gate( else trscheme end - return tsvd!(a2b2; trunc, alg=TensorKit.SVD()) + return tsvd!(a2b2; trunc, alg = TensorKit.SVD()) end """ @@ -162,8 +160,8 @@ in which the axes are ordered as ``` """ function gate_to_mpo3( - gate::AbstractTensorMap{T,S,3,3}, trunc=truncbelow(MPSKit.Defaults.tol) -) where {T<:Number,S<:ElementarySpace} + gate::AbstractTensorMap{T, S, 3, 3}, trunc = truncbelow(MPSKit.Defaults.tol) + ) where {T <: Number, S <: ElementarySpace} Os = MPSKit.decompose_localmpo(MPSKit.add_util_leg(gate), trunc) g1 = removeunit(Os[1], 1) g2 = Os[2] @@ -201,9 +199,9 @@ function _get_gatempo_se(ham::LocalOperator, dt::Number, row::Int, col::Int) # NN / NNN bonds are counted 4 / 2 times, respectively. @tensor Odt[i' j' k'; i j k] := -dt * ( - (nb1x[i' j'; i j] * units[3][k' k] + units[1][i'; i] * nb1y[j' k'; j k]) / 4 + + (nb1x[i' j'; i j] * units[3][k' k] + units[1][i'; i] * nb1y[j' k'; j k]) / 4 + (nb2[i' k'; i k] * units[2][j'; j]) / 2 - ) + ) op = exp(Odt) return gate_to_mpo3(op) end diff --git a/src/algorithms/time_evolution/simpleupdate.jl b/src/algorithms/time_evolution/simpleupdate.jl index db6e0aa49..3a095ea1c 100644 --- a/src/algorithms/time_evolution/simpleupdate.jl +++ b/src/algorithms/time_evolution/simpleupdate.jl @@ -30,12 +30,10 @@ Simple update of the x-bond `peps.weights[1,r,c]`. ``` """ function _su_xbond!( - row::Int, - col::Int, - gate::AbstractTensorMap{T,S,2,2}, - peps::InfiniteWeightPEPS, - trscheme::TruncationScheme, -) where {T<:Number,S<:ElementarySpace} + row::Int, col::Int, + gate::AbstractTensorMap{T, S, 2, 2}, peps::InfiniteWeightPEPS, + trscheme::TruncationScheme, + ) where {T <: Number, S <: ElementarySpace} Nr, Nc = size(peps) @assert 1 <= row <= Nr && 1 <= col <= Nc cp1 = _next(col, Nc) @@ -53,7 +51,7 @@ function _su_xbond!( _allfalse = ntuple(Returns(false), 3) A = _absorb_weights(A, peps.weights, row, col, (NORTH, SOUTH, WEST), _allfalse, true) B = _absorb_weights(B, peps.weights, row, cp1, (NORTH, SOUTH, EAST), _allfalse, true) - # update tensor dict and weight on current bond + # update tensor dict and weight on current bond # (max element of weight is normalized to 1) peps.vertices[row, col], peps.vertices[row, cp1] = A, B peps.weights[1, row, col] = s / norm(s, Inf) @@ -67,22 +65,20 @@ One round of simple update on `peps` applying the nearest neighbor `gate`. When the input `peps` has a unit cell size of (2, 2), one can set `bipartite = true` to enforce the bipartite structure. """ function su_iter( - gate::LocalOperator, peps::InfiniteWeightPEPS, alg::SimpleUpdate; bipartite::Bool=false -) + gate::LocalOperator, peps::InfiniteWeightPEPS, alg::SimpleUpdate; bipartite::Bool = false + ) @assert size(gate.lattice) == size(peps) Nr, Nc = size(peps) if bipartite @assert Nr == Nc == 2 end (Nr >= 2 && Nc >= 2) || throw( - ArgumentError( - "iPEPS unit cell size for simple update should be no smaller than (2, 2)." - ), + ArgumentError("iPEPS unit cell size for simple update should be no smaller than (2, 2)."), ) peps2 = deepcopy(peps) gate_mirrored = mirror_antidiag(gate) for direction in 1:2 - # mirror the y-weights to x-direction + # mirror the y-weights to x-direction # to update them using code for x-weights if direction == 2 peps2 = mirror_antidiag(peps2) @@ -123,12 +119,9 @@ end Perform simple update with Hamiltonian `ham` containing up to nearest neighbor interaction terms. """ function _simpleupdate2site( - peps::InfiniteWeightPEPS, - ham::LocalOperator, - alg::SimpleUpdate; - bipartite::Bool=false, - check_interval::Int=500, -) + peps::InfiniteWeightPEPS, ham::LocalOperator, alg::SimpleUpdate; + bipartite::Bool = false, check_interval::Int = 500, + ) time_start = time() # exponentiating the 2-site Hamiltonian gate gate = get_expham(ham, alg.dt) @@ -147,11 +140,7 @@ function _simpleupdate2site( label = (converge ? "conv" : (cancel ? "cancel" : "iter")) message = @sprintf( "SU %s %-7d: dt = %.0e, weight diff = %.3e, time = %.3f sec\n", - label, - count, - alg.dt, - wtdiff, - time1 - ((converge || cancel) ? time_start : time0) + label, count, alg.dt, wtdiff, time1 - ((converge || cancel) ? time_start : time0) ) cancel ? (@warn message) : (@info message) end @@ -177,13 +166,9 @@ Perform a simple update on the infinite PEPS (`peps`) using the Hamiltonian `ham - The 3-site simple update algorithm is incompatible with a bipartite PEPS. Using `bipartite = true` with either `force_3site = true` or a `ham` with next-nearest neighbor terms is not allowed. """ function simpleupdate( - peps::InfiniteWeightPEPS, - ham::LocalOperator, - alg::SimpleUpdate; - bipartite::Bool=false, - force_3site::Bool=false, - check_interval::Int=500, -) + peps::InfiniteWeightPEPS, ham::LocalOperator, alg::SimpleUpdate; + bipartite::Bool = false, force_3site::Bool = false, check_interval::Int = 500, + ) # determine if Hamiltonian contains nearest neighbor terms only nnonly = is_nearest_neighbour(ham) use_3site = force_3site || !nnonly diff --git a/src/algorithms/time_evolution/simpleupdate3site.jl b/src/algorithms/time_evolution/simpleupdate3site.jl index 1672e2c5e..3c2d2b17f 100644 --- a/src/algorithms/time_evolution/simpleupdate3site.jl +++ b/src/algorithms/time_evolution/simpleupdate3site.jl @@ -134,18 +134,18 @@ Perform QR decomposition through a PEPS tensor ``` """ function qr_through( - R0::AbstractTensorMap{T,S,1,1}, M::AbstractTensorMap{T,S,1,4}; normalize::Bool=true -) where {T<:Number,S<:ElementarySpace} + R0::AbstractTensorMap{T, S, 1, 1}, M::AbstractTensorMap{T, S, 1, 4}; normalize::Bool = true + ) where {T <: Number, S <: ElementarySpace} @tensor A[-1 -2 -3 -4; -5] := R0[-1; 1] * M[1; -2 -3 -4 -5] - q, r = leftorth!(A; alg=QRpos()) + q, r = leftorth!(A; alg = QRpos()) @assert isdual(domain(r, 1)) == isdual(codomain(r, 1)) normalize && normalize!(r, Inf) return q, r end function qr_through( - ::Nothing, M::AbstractTensorMap{T,S,1,4}; normalize::Bool=true -) where {T<:Number,S<:ElementarySpace} - q, r = leftorth(M, ((1, 2, 3, 4), (5,)); alg=QRpos()) + ::Nothing, M::AbstractTensorMap{T, S, 1, 4}; normalize::Bool = true + ) where {T <: Number, S <: ElementarySpace} + q, r = leftorth(M, ((1, 2, 3, 4), (5,)); alg = QRpos()) @assert isdual(domain(r, 1)) == isdual(codomain(r, 1)) normalize && normalize!(r, Inf) return q, r @@ -160,18 +160,18 @@ Perform LQ decomposition through a tensor ``` """ function lq_through( - M::AbstractTensorMap{T,S,1,4}, L1::AbstractTensorMap{T,S,1,1}; normalize::Bool=true -) where {T<:Number,S<:ElementarySpace} + M::AbstractTensorMap{T, S, 1, 4}, L1::AbstractTensorMap{T, S, 1, 1}; normalize::Bool = true + ) where {T <: Number, S <: ElementarySpace} @plansor A[-1; -2 -3 -4 -5] := M[-1; -2 -3 -4 1] * L1[1; -5] - l, q = rightorth!(A; alg=LQpos()) + l, q = rightorth!(A; alg = LQpos()) @assert isdual(domain(l, 1)) == isdual(codomain(l, 1)) normalize && normalize!(l, Inf) return l, q end function lq_through( - M::AbstractTensorMap{T,S,1,4}, ::Nothing; normalize::Bool=true -) where {T<:Number,S<:ElementarySpace} - l, q = rightorth(M; alg=LQpos()) + M::AbstractTensorMap{T, S, 1, 4}, ::Nothing; normalize::Bool = true + ) where {T <: Number, S <: ElementarySpace} + l, q = rightorth(M; alg = LQpos()) @assert isdual(domain(l, 1)) == isdual(codomain(l, 1)) normalize && normalize!(l, Inf) return l, q @@ -180,20 +180,20 @@ end """ Given a cluster `Ms`, find all `R`, `L` matrices on each internal bond """ -function _get_allRLs(Ms::Vector{T}) where {T<:PEPSTensor} +function _get_allRLs(Ms::Vector{T}) where {T <: PEPSTensor} # M1 -- (R1,L1) -- M2 -- (R2,L2) -- M3 N = length(Ms) # get the first R and the last L - R_first = qr_through(nothing, Ms[1]; normalize=true)[2] - L_last = lq_through(Ms[N], nothing; normalize=true)[1] + R_first = qr_through(nothing, Ms[1]; normalize = true)[2] + L_last = lq_through(Ms[N], nothing; normalize = true)[1] Rs = Vector{typeof(R_first)}(undef, N - 1) Ls = Vector{typeof(L_last)}(undef, N - 1) Rs[1], Ls[end] = R_first, L_last # get remaining R, L matrices for n in 2:(N - 1) m = N - n + 1 - _, Rs[n] = qr_through(Rs[n - 1], Ms[n]; normalize=true) - Ls[m - 1], _ = lq_through(Ms[m], Ls[m]; normalize=true) + _, Rs[n] = qr_through(Rs[n - 1], Ms[n]; normalize = true) + Ls[m - 1], _ = lq_through(Ms[m], Ls[m]; normalize = true) end return Rs, Ls end @@ -213,11 +213,11 @@ The arrows between `Pa`, `s`, `Pb` are ``` """ function _proj_from_RL( - r::AbstractTensorMap{T,S,1,1}, - l::AbstractTensorMap{T,S,1,1}; - trunc::TruncationScheme=notrunc(), - rev::Bool=false, -) where {T<:Number,S<:ElementarySpace} + r::AbstractTensorMap{T, S, 1, 1}, + l::AbstractTensorMap{T, S, 1, 1}; + trunc::TruncationScheme = notrunc(), + rev::Bool = false, + ) where {T <: Number, S <: ElementarySpace} rl = r * l @assert isdual(domain(rl, 1)) == isdual(codomain(rl, 1)) u, s, vh, ϵ = tsvd!(rl; trunc) @@ -236,8 +236,8 @@ Given a cluster `Ms` and the pre-calculated `R`, `L` bond matrices, find all projectors `Pa`, `Pb` and Schmidt weights `wts` on internal bonds. """ function _get_allprojs( - Ms, Rs, Ls, trschemes::Vector{E}, revs::Vector{Bool} -) where {E<:TruncationScheme} + Ms, Rs, Ls, trschemes::Vector{E}, revs::Vector{Bool} + ) where {E <: TruncationScheme} N = length(Ms) @assert length(trschemes) == N - 1 projs_errs = map(1:(N - 1)) do i @@ -247,7 +247,7 @@ function _get_allprojs( else trschemes[i] end - return _proj_from_RL(Rs[i], Ls[i]; trunc, rev=revs[i]) + return _proj_from_RL(Rs[i], Ls[i]; trunc, rev = revs[i]) end Pas = map(Base.Fix2(getindex, 1), projs_errs) wts = map(Base.Fix2(getindex, 2), projs_errs) @@ -261,8 +261,8 @@ end Find projectors to truncate internal bonds of the cluster `Ms` """ function _cluster_truncate!( - Ms::Vector{T}, trschemes::Vector{E}, revs::Vector{Bool} -) where {T<:PEPSTensor,E<:TruncationScheme} + Ms::Vector{T}, trschemes::Vector{E}, revs::Vector{Bool} + ) where {T <: PEPSTensor, E <: TruncationScheme} Rs, Ls = _get_allRLs(Ms) Pas, Pbs, wts, ϵs = _get_allprojs(Ms, Rs, Ls, trschemes, revs) # apply projectors @@ -275,8 +275,8 @@ function _cluster_truncate!( end function _apply_gatempo!( - Ms::Vector{T1}, gs::Vector{T2} -) where {T1<:PEPSTensor,T2<:AbstractTensorMap} + Ms::Vector{T1}, gs::Vector{T2} + ) where {T1 <: PEPSTensor, T2 <: AbstractTensorMap} @assert length(Ms) == length(gs) @assert all(!isdual(space(g, 1)) for g in gs[2:end]) # fusers to merge axes on bonds in the gate-cluster product @@ -325,8 +325,8 @@ In the cluster, the axes of each PEPSTensor are reordered as ``` """ function apply_gatempo!( - Ms::Vector{T1}, gs::Vector{T2}; trschemes::Vector{E} -) where {T1<:PEPSTensor,T2<:AbstractTensorMap,E<:TruncationScheme} + Ms::Vector{T1}, gs::Vector{T2}; trschemes::Vector{E} + ) where {T1 <: PEPSTensor, T2 <: AbstractTensorMap, E <: TruncationScheme} @assert length(Ms) == length(gs) revs = [isdual(space(M, 1)) for M in Ms[2:end]] @assert !all(revs) @@ -340,9 +340,9 @@ const sqrtwts_se = [ntuple(dir -> !(dir in idxs), 4) for idxs in openaxs_se] const invperms_se = [((2,), (3, 5, 4, 1)), ((2,), (5, 3, 4, 1)), ((2,), (5, 3, 1, 4))] const perms_se = [ begin - p = invperm((p1..., p2...)) - ((p[1],), p[2:end]) - end for (p1, p2) in invperms_se + p = invperm((p1..., p2...)) + ((p[1],), p[2:end]) + end for (p1, p2) in invperms_se ] """ Obtain the following 3-site cluster @@ -360,24 +360,19 @@ function get_3site_se(peps::InfiniteWeightPEPS, row::Int, col::Int) coords_se = [(row, col), (row, cp1), (rm1, cp1)] cluster = collect( permute( - _absorb_weights( - peps.vertices[CartesianIndex(coord)], - peps.weights, - coord[1], - coord[2], - Tuple(1:4), - sqrtwts, - false, - ), - perm, - ) for (coord, sqrtwts, perm) in zip(coords_se, sqrtwts_se, perms_se) + _absorb_weights( + peps.vertices[CartesianIndex(coord)], peps.weights, + coord[1], coord[2], Tuple(1:4), sqrtwts, false, + ), + perm, + ) for (coord, sqrtwts, perm) in zip(coords_se, sqrtwts_se, perms_se) ) return cluster end function _su3site_se!( - row::Int, col::Int, gs::Vector{T}, peps::InfiniteWeightPEPS, trschemes::Vector{E} -) where {T<:AbstractTensorMap,E<:TruncationScheme} + row::Int, col::Int, gs::Vector{T}, peps::InfiniteWeightPEPS, trschemes::Vector{E} + ) where {T <: AbstractTensorMap, E <: TruncationScheme} Nr, Nc = size(peps) @assert 1 <= row <= Nr && 1 <= col <= Nc rm1, cp1 = _prev(row, Nr), _next(col, Nc) @@ -408,8 +403,8 @@ end One round of 3-site simple update. """ function su3site_iter( - gatempos::Vector{G}, peps::InfiniteWeightPEPS, alg::SimpleUpdate -) where {G<:AbstractMatrix} + gatempos::Vector{G}, peps::InfiniteWeightPEPS, alg::SimpleUpdate + ) where {G <: AbstractMatrix} Nr, Nc = size(peps) (Nr >= 2 && Nc >= 2) || throw( ArgumentError( @@ -438,8 +433,8 @@ end Perform 3-site simple update for Hamiltonian `ham`. """ function _simpleupdate3site( - peps::InfiniteWeightPEPS, ham::LocalOperator, alg::SimpleUpdate; check_interval::Int=500 -) + peps::InfiniteWeightPEPS, ham::LocalOperator, alg::SimpleUpdate; check_interval::Int = 500 + ) time_start = time() # convert Hamiltonian to 3-site exponentiated gate MPOs gatempos = [ @@ -463,11 +458,7 @@ function _simpleupdate3site( label = (converge ? "conv" : (cancel ? "cancel" : "iter")) message = @sprintf( "SU %s %-7d: dt = %.0e, weight diff = %.3e, time = %.3f sec\n", - label, - count, - alg.dt, - wtdiff, - time1 - ((converge || cancel) ? time_start : time0) + label, count, alg.dt, wtdiff, time1 - ((converge || cancel) ? time_start : time0) ) cancel ? (@warn message) : (@info message) end diff --git a/src/algorithms/toolbox.jl b/src/algorithms/toolbox.jl index b7c241356..f6524e5fd 100644 --- a/src/algorithms/toolbox.jl +++ b/src/algorithms/toolbox.jl @@ -24,16 +24,16 @@ should be a rank-4 tensor conforming to the [`PartitionFunctionTensor`](@ref) in convention. """ function MPSKit.expectation_value( - pf::InfinitePartitionFunction, - op::Pair{CartesianIndex{2},<:AbstractTensorMap{T,S,2,2}}, - env::CTMRGEnv, -) where {T,S} + pf::InfinitePartitionFunction, + op::Pair{CartesianIndex{2}, <:AbstractTensorMap{T, S, 2, 2}}, + env::CTMRGEnv, + ) where {T, S} return contract_local_tensor(op[1], op[2], env) / - contract_local_tensor(op[1], pf[op[1]], env) + contract_local_tensor(op[1], pf[op[1]], env) end function MPSKit.expectation_value( - pf::InfinitePartitionFunction, op::Pair{Tuple{Int,Int}}, env::CTMRGEnv -) + pf::InfinitePartitionFunction, op::Pair{Tuple{Int, Int}}, env::CTMRGEnv + ) return expectation_value(pf, CartesianIndex(op[1]) => op[2], env) end @@ -46,7 +46,7 @@ yields a finite imaginary part (up to a tolerance). function cost_function(peps::InfinitePEPS, env::CTMRGEnv, O::LocalOperator) E = MPSKit.expectation_value(peps, O, env) ignore_derivatives() do - isapprox(imag(E), 0; atol=sqrt(eps(real(E)))) || + isapprox(imag(E), 0; atol = sqrt(eps(real(E)))) || @warn "Expectation value is not real: $E." end return real(E) @@ -65,8 +65,7 @@ CTMRG environment. function network_value(network::InfiniteSquareNetwork, env::CTMRGEnv) return prod(Iterators.product(axes(network)...)) do (r, c) return _contract_site((r, c), network, env) * _contract_corners((r, c), env) / - _contract_vertical_edges((r, c), env) / - _contract_horizontal_edges((r, c), env) + _contract_vertical_edges((r, c), env) / _contract_horizontal_edges((r, c), env) end end network_value(state, env::CTMRGEnv) = network_value(InfiniteSquareNetwork(state), env) @@ -76,31 +75,24 @@ network_value(state, env::CTMRGEnv) = network_value(InfiniteSquareNetwork(state) Contract around a single site `ind` of a square network using a given CTMRG environment. """ -function _contract_site(ind::Tuple{Int,Int}, network, env::CTMRGEnv) +function _contract_site(ind::Tuple{Int, Int}, network, env::CTMRGEnv) r, c = ind return _contract_site( env.corners[NORTHWEST, _prev(r, end), _prev(c, end)], env.corners[NORTHEAST, _prev(r, end), _next(c, end)], env.corners[SOUTHEAST, _next(r, end), _next(c, end)], env.corners[SOUTHWEST, _next(r, end), _prev(c, end)], - env.edges[NORTH, _prev(r, end), c], - env.edges[EAST, r, _next(c, end)], - env.edges[SOUTH, _next(r, end), c], - env.edges[WEST, r, _prev(c, end)], + env.edges[NORTH, _prev(r, end), c], env.edges[EAST, r, _next(c, end)], + env.edges[SOUTH, _next(r, end), c], env.edges[WEST, r, _prev(c, end)], network[r, c], ) end function _contract_site( - C_northwest, - C_northeast, - C_southeast, - C_southwest, - E_north::CTMRG_PEPS_EdgeTensor, - E_east::CTMRG_PEPS_EdgeTensor, - E_south::CTMRG_PEPS_EdgeTensor, - E_west::CTMRG_PEPS_EdgeTensor, - O::PEPSSandwich, -) + C_northwest, C_northeast, C_southeast, C_southwest, + E_north::CTMRG_PEPS_EdgeTensor, E_east::CTMRG_PEPS_EdgeTensor, + E_south::CTMRG_PEPS_EdgeTensor, E_west::CTMRG_PEPS_EdgeTensor, + O::PEPSSandwich, + ) return @autoopt @tensor E_west[χ_WSW D_W_above D_W_below; χ_WNW] * C_northwest[χ_WNW; χ_NNW] * E_north[χ_NNW D_N_above D_N_below; χ_NNE] * @@ -113,16 +105,11 @@ function _contract_site( conj(bra(O)[d; D_N_below D_E_below D_S_below D_W_below]) end function _contract_site( - C_northwest, - C_northeast, - C_southeast, - C_southwest, - E_north::CTMRG_PF_EdgeTensor, - E_east::CTMRG_PF_EdgeTensor, - E_south::CTMRG_PF_EdgeTensor, - E_west::CTMRG_PF_EdgeTensor, - O::PFTensor, -) + C_northwest, C_northeast, C_southeast, C_southwest, + E_north::CTMRG_PF_EdgeTensor, E_east::CTMRG_PF_EdgeTensor, + E_south::CTMRG_PF_EdgeTensor, E_west::CTMRG_PF_EdgeTensor, + O::PFTensor, + ) return @autoopt @tensor E_west[χ_WSW D_W; χ_WNW] * C_northwest[χ_WNW; χ_NNW] * E_north[χ_NNW D_N; χ_NNE] * @@ -140,7 +127,7 @@ end Contract all corners around the south-east at position `ind` of the CTMRG environment `env`. """ -function _contract_corners(ind::Tuple{Int,Int}, env::CTMRGEnv) +function _contract_corners(ind::Tuple{Int, Int}, env::CTMRGEnv) r, c = ind C_NW = env.corners[NORTHWEST, _prev(r, end), _prev(c, end)] C_NE = env.corners[NORTHEAST, _prev(r, end), c] @@ -155,7 +142,7 @@ end Contract the vertical edges and corners around the east edge at position `ind` of the CTMRG environment `env`. """ -function _contract_vertical_edges(ind::Tuple{Int,Int}, env::CTMRGEnv) +function _contract_vertical_edges(ind::Tuple{Int, Int}, env::CTMRGEnv) r, c = ind return _contract_vertical_edges( env.corners[NORTHWEST, _prev(r, end), _prev(c, end)], @@ -167,13 +154,11 @@ function _contract_vertical_edges(ind::Tuple{Int,Int}, env::CTMRGEnv) ) end @generated function _contract_vertical_edges( - C_northwest::CTMRGCornerTensor, - C_northeast::CTMRGCornerTensor, - C_southeast::CTMRGCornerTensor, - C_southwest::CTMRGCornerTensor, - E_east::CTMRGEdgeTensor{T,S,N}, - E_west::CTMRGEdgeTensor{T,S,N}, -) where {T,S,N} + C_northwest::CTMRGCornerTensor, C_northeast::CTMRGCornerTensor, + C_southeast::CTMRGCornerTensor, C_southwest::CTMRGCornerTensor, + E_east::CTMRGEdgeTensor{T, S, N}, + E_west::CTMRGEdgeTensor{T, S, N}, + ) where {T, S, N} C_northwest_e = tensorexpr(:C_northwest, (envlabel(:NW),), (envlabel(:N),)) C_northeast_e = tensorexpr(:C_northeast, (envlabel(:N),), (envlabel(:NE),)) C_southeast_e = tensorexpr(:C_southeast, (envlabel(:SE),), (envlabel(:S),)) @@ -187,14 +172,8 @@ end ) rhs = Expr( - :call, - :*, - E_west_e, - C_northwest_e, - C_northeast_e, - E_east_e, - C_southeast_e, - C_southwest_e, + :call, :*, + E_west_e, C_northwest_e, C_northeast_e, E_east_e, C_southeast_e, C_southwest_e, ) return macroexpand(@__MODULE__, :(return @autoopt @tensor $rhs)) @@ -206,7 +185,7 @@ end Contract the horizontal edges and corners around the south edge at position `ind` of the CTMRG environment `env`. """ -function _contract_horizontal_edges(ind::Tuple{Int,Int}, env::CTMRGEnv) +function _contract_horizontal_edges(ind::Tuple{Int, Int}, env::CTMRGEnv) r, c = ind return _contract_horizontal_edges( env.corners[NORTHWEST, _prev(r, end), _prev(c, end)], @@ -218,13 +197,10 @@ function _contract_horizontal_edges(ind::Tuple{Int,Int}, env::CTMRGEnv) ) end @generated function _contract_horizontal_edges( - C_northwest::CTMRGCornerTensor, - C_northeast::CTMRGCornerTensor, - C_southeast::CTMRGCornerTensor, - C_southwest::CTMRGCornerTensor, - E_north::CTMRGEdgeTensor{T,S,N}, - E_south::CTMRGEdgeTensor{T,S,N}, -) where {T,S,N} + C_northwest::CTMRGCornerTensor, C_northeast::CTMRGCornerTensor, + C_southeast::CTMRGCornerTensor, C_southwest::CTMRGCornerTensor, + E_north::CTMRGEdgeTensor{T, S, N}, E_south::CTMRGEdgeTensor{T, S, N}, + ) where {T, S, N} C_northwest_e = tensorexpr(:C_northwest, (envlabel(:W),), (envlabel(:NW),)) C_northeast_e = tensorexpr(:C_northeast, (envlabel(:NE),), (envlabel(:E),)) C_southeast_e = tensorexpr(:C_southeast, (envlabel(:E),), (envlabel(:SE),)) @@ -238,14 +214,8 @@ end ) rhs = Expr( - :call, - :*, - C_northwest_e, - E_north_e, - C_northeast_e, - C_southeast_e, - E_south_e, - C_southwest_e, + :call, :*, + C_northwest_e, E_north_e, C_northeast_e, C_southeast_e, E_south_e, C_southwest_e, ) return macroexpand(@__MODULE__, :(return @autoopt @tensor $rhs)) @@ -256,7 +226,7 @@ Adjoint of an MPS tensor, but permutes the physical spaces back into the codomai Intuitively, this conjugates a tensor and then reinterprets its 'direction' as an MPS tensor. """ -function _dag(A::MPSKit.GenericMPSTensor{S,N}) where {S,N} +function _dag(A::MPSKit.GenericMPSTensor{S, N}) where {S, N} return permute(A', ((1, (3:(N + 1))...), (2,))) end @@ -272,13 +242,13 @@ passed through to `MPSKit.transfer_spectrum` (e.g. allowing to target the correl in a specific symmetry sector). """ -function MPSKit.correlation_length(state, env::CTMRGEnv; num_vals=2, kwargs...) - _correlation_length(env; num_vals, kwargs...) +function MPSKit.correlation_length(state, env::CTMRGEnv; num_vals = 2, kwargs...) + return _correlation_length(env; num_vals, kwargs...) end function _correlation_length( - env::CTMRGEnv; num_vals=2, sector=one(sectortype(env)), kwargs... -) + env::CTMRGEnv; num_vals = 2, sector = one(sectortype(env)), kwargs... + ) _, n_rows, n_cols = size(env) # Horizontal @@ -291,7 +261,7 @@ function _correlation_length( if isone(sector) N = first(vals) else - vals_triv = MPSKit.transfer_spectrum(above; below, num_vals=1, kwargs...) + vals_triv = MPSKit.transfer_spectrum(above; below, num_vals = 1, kwargs...) N = first(vals_triv) end return vals ./ N # normalize largest eigenvalue @@ -307,7 +277,7 @@ function _correlation_length( if isone(sector) N = first(vals) else - vals_triv = MPSKit.transfer_spectrum(above; below, num_vals=1, kwargs...) + vals_triv = MPSKit.transfer_spectrum(above; below, num_vals = 1, kwargs...) N = first(vals_triv) end return vals ./ N # normalize largest eigenvalue @@ -335,7 +305,7 @@ specified using the `state_vector` kwarg in the form of a matrix of size `unitce containing vectors that match the PEPS physical dimensions. If `nothing` is provided, random Gaussian coefficients are used. """ -function product_peps(peps_args...; unitcell=(1, 1), noise_amp=1e-2, state_vector=nothing) +function product_peps(peps_args...; unitcell = (1, 1), noise_amp = 1.0e-2, state_vector = nothing) noise_peps = InfinitePEPS(peps_args...; unitcell) typeof(spacetype(noise_peps[1])) <: GradedSpace && error("symmetric tensors not generically supported") @@ -366,18 +336,16 @@ Contract a local tensor `O` inserted into a partition function `pf` at position using the environment `env`. """ function contract_local_tensor( - inds::Tuple{Int,Int}, O::PFTensor, env::CTMRGEnv{C,<:CTMRG_PF_EdgeTensor} -) where {C} + inds::Tuple{Int, Int}, O::PFTensor, env::CTMRGEnv{C, <:CTMRG_PF_EdgeTensor} + ) where {C} r, c = inds return _contract_site( env.corners[NORTHWEST, _prev(r, end), _prev(c, end)], env.corners[NORTHEAST, _prev(r, end), _next(c, end)], env.corners[SOUTHEAST, _next(r, end), _next(c, end)], env.corners[SOUTHWEST, _next(r, end), _prev(c, end)], - env.edges[NORTH, _prev(r, end), c], - env.edges[EAST, r, _next(c, end)], - env.edges[SOUTH, _next(r, end), c], - env.edges[WEST, r, _prev(c, end)], + env.edges[NORTH, _prev(r, end), c], env.edges[EAST, r, _next(c, end)], + env.edges[SOUTH, _next(r, end), c], env.edges[WEST, r, _prev(c, end)], O, ) end @@ -389,11 +357,11 @@ Contract a local tensor `O` inserted into the PEPO of a given `network` at posit using the environment `env`. """ function contract_local_tensor( - ind::Tuple{Int,Int,Int}, - O::PEPOTensor, - network::InfiniteSquareNetwork{<:PEPOSandwich}, - env::CTMRGEnv, -) + ind::Tuple{Int, Int, Int}, + O::PEPOTensor, + network::InfiniteSquareNetwork{<:PEPOSandwich}, + env::CTMRGEnv, + ) r, c, h = ind sandwich´ = Base.setindex(network[r, c], O, h + 2) return _contract_site( @@ -401,10 +369,8 @@ function contract_local_tensor( env.corners[NORTHEAST, _prev(r, end), _next(c, end)], env.corners[SOUTHEAST, _next(r, end), _next(c, end)], env.corners[SOUTHWEST, _next(r, end), _prev(c, end)], - env.edges[NORTH, _prev(r, end), c], - env.edges[EAST, r, _next(c, end)], - env.edges[SOUTH, _next(r, end), c], - env.edges[WEST, r, _prev(c, end)], + env.edges[NORTH, _prev(r, end), c], env.edges[EAST, r, _next(c, end)], + env.edges[SOUTH, _next(r, end), c], env.edges[WEST, r, _prev(c, end)], sandwich´, ) end diff --git a/src/algorithms/truncation/bond_truncation.jl b/src/algorithms/truncation/bond_truncation.jl index c50e1ac38..8dbbec08f 100644 --- a/src/algorithms/truncation/bond_truncation.jl +++ b/src/algorithms/truncation/bond_truncation.jl @@ -21,18 +21,13 @@ The truncation algorithm can be constructed from the following keyword arguments @kwdef struct ALSTruncation trscheme::TruncationScheme maxiter::Int = 50 - tol::Float64 = 1e-15 + tol::Float64 = 1.0e-15 check_interval::Int = 0 end function _als_message( - iter::Int, - cost::Float64, - fid::Float64, - Δcost::Float64, - Δfid::Float64, - time_elapsed::Float64, -) + iter::Int, cost::Float64, fid::Float64, Δcost::Float64, Δfid::Float64, time_elapsed::Float64, + ) return @sprintf( "%5d, fid = %.8e, Δfid = %.8e, time = %.4f s\n", iter, fid, Δfid, time_elapsed ) * @sprintf(" cost = %.3e, Δcost/cost0 = %.3e", cost, Δcost) @@ -61,11 +56,11 @@ The index order of `a` or `b` is ``` """ function bond_truncate( - a::AbstractTensorMap{T,S,2,1}, - b::AbstractTensorMap{T,S,1,2}, - benv::BondEnv{T,S}, - alg::ALSTruncation, -) where {T<:Number,S<:ElementarySpace} + a::AbstractTensorMap{T, S, 2, 1}, + b::AbstractTensorMap{T, S, 1, 2}, + benv::BondEnv{T, S}, + alg::ALSTruncation, + ) where {T <: Number, S <: ElementarySpace} # dual check of physical index @assert !isdual(space(a, 2)) @assert !isdual(space(b, 2)) @@ -75,7 +70,7 @@ function bond_truncate( a2b2 = _combine_ab(a, b) # initialize truncated a, b perm_ab = ((1, 3), (4, 2)) - a, s, b = tsvd(a2b2, perm_ab; trunc=alg.trscheme) + a, s, b = tsvd(a2b2, perm_ab; trunc = alg.trscheme) s /= norm(s, Inf) a, b = absorb_s(a, s, b) #= temporarily reorder axes of a and b to @@ -121,12 +116,7 @@ function bond_truncate( cancel || (verbose && (converge || iter == 1 || iter % alg.check_interval == 0)) if showinfo message = _als_message( - iter, - cost, - fid, - Δcost, - Δfid, - time1 - ((cancel || converge) ? time00 : time0), + iter, cost, fid, Δcost, Δfid, time1 - ((cancel || converge) ? time00 : time0), ) if converge @info "ALS conv" * message @@ -138,18 +128,18 @@ function bond_truncate( end converge && break end - a, s, b = tsvd!(permute(_combine_ab(a, b), perm_ab); trunc=alg.trscheme) + a, s, b = tsvd!(permute(_combine_ab(a, b), perm_ab); trunc = alg.trscheme) # normalize singular value spectrum s /= norm(s, Inf) return a, s, b, (; fid, Δfid) end function bond_truncate( - a::AbstractTensorMap{T,S,2,1}, - b::AbstractTensorMap{T,S,1,2}, - benv::BondEnv{T,S}, - alg::FullEnvTruncation, -) where {T<:Number,S<:ElementarySpace} + a::AbstractTensorMap{T, S, 2, 1}, + b::AbstractTensorMap{T, S, 1, 2}, + benv::BondEnv{T, S}, + alg::FullEnvTruncation, + ) where {T <: Number, S <: ElementarySpace} # dual check of physical index @assert !isdual(space(a, 2)) @assert !isdual(space(b, 2)) @@ -161,7 +151,7 @@ function bond_truncate( =# Qa, Ra = leftorth(a) Rb, Qb = rightorth(b) - # if Qa → Ra, a twist is needed to express a as + # if Qa → Ra, a twist is needed to express a as # contraction of Rb, Qb instead of Qa * Ra isdual(space(Ra, 1)) && twist!(Ra, 1) # similarly if Rb → Qb diff --git a/src/algorithms/truncation/fullenv_truncation.jl b/src/algorithms/truncation/fullenv_truncation.jl index f3fa336b3..18926da82 100644 --- a/src/algorithms/truncation/fullenv_truncation.jl +++ b/src/algorithms/truncation/fullenv_truncation.jl @@ -26,7 +26,7 @@ The truncation algorithm can be constructed from the following keyword arguments @kwdef struct FullEnvTruncation trscheme::TruncationScheme maxiter::Int = 50 - tol::Float64 = 1e-15 + tol::Float64 = 1.0e-15 trunc_init::Bool = true check_interval::Int = 0 end @@ -47,8 +47,8 @@ between two states specified by the bond matrices `b1`, `b2` ``` """ function inner_prod( - benv::BondEnv{T,S}, b1::AbstractTensorMap{T,S,1,1}, b2::AbstractTensorMap{T,S,1,1} -) where {T<:Number,S<:ElementarySpace} + benv::BondEnv{T, S}, b1::AbstractTensorMap{T, S, 1, 1}, b2::AbstractTensorMap{T, S, 1, 1} + ) where {T <: Number, S <: ElementarySpace} val = @tensor conj(b1[1; 2]) * benv[1 2; 3 4] * b2[3; 4] return val end @@ -63,10 +63,10 @@ between two states specified by the bond matrices `b1`, `b2` ``` """ function fidelity( - benv::BondEnv{T,S}, b1::AbstractTensorMap{T,S,1,1}, b2::AbstractTensorMap{T,S,1,1} -) where {T<:Number,S<:ElementarySpace} + benv::BondEnv{T, S}, b1::AbstractTensorMap{T, S, 1, 1}, b2::AbstractTensorMap{T, S, 1, 1} + ) where {T <: Number, S <: ElementarySpace} return abs2(inner_prod(benv, b1, b2)) / - real(inner_prod(benv, b1, b1) * inner_prod(benv, b2, b2)) + real(inner_prod(benv, b1, b1) * inner_prod(benv, b2, b2)) end """ @@ -85,10 +85,10 @@ function _linearmap_twist!(t::AbstractTensorMap) end function _fet_message( - iter::Int, fid::Float64, Δfid::Float64, Δwt::Float64, time_elapsed::Float64 -) + iter::Int, fid::Float64, Δfid::Float64, Δwt::Float64, time_elapsed::Float64 + ) return @sprintf("%5d: fid = %.8e, Δfid = %.8e, ", iter, fid, Δfid) * - @sprintf("|Δs| = %.6e, time = %.4f s", Δwt, time_elapsed) + @sprintf("|Δs| = %.6e, time = %.4f s", Δwt, time_elapsed) end """ @@ -221,14 +221,14 @@ Returns the SVD result of the new bond matrix `U`, `S`, `V`, as well as an infor * `Δs` : Last singular value difference. """ function fullenv_truncate( - b0::AbstractTensorMap{T,S,1,1}, benv::BondEnv{T,S}, alg::FullEnvTruncation -) where {T<:Number,S<:ElementarySpace} + b0::AbstractTensorMap{T, S, 1, 1}, benv::BondEnv{T, S}, alg::FullEnvTruncation + ) where {T <: Number, S <: ElementarySpace} verbose = (alg.check_interval > 0) # `benv` is assumed to be positive; here we only check codomain(benv) == domain(benv). @assert codomain(benv) == domain(benv) time00 = time() # initialize u, s, vh with truncated or untruncated SVD - u, s, vh = tsvd(b0; trunc=(alg.trunc_init ? alg.trscheme : notrunc())) + u, s, vh = tsvd(b0; trunc = (alg.trunc_init ? alg.trscheme : notrunc())) b1 = similar(b0) # normalize `s` (bond matrices can always be normalized) s /= norm(s, Inf) @@ -244,7 +244,7 @@ function fullenv_truncate( _linearmap_twist!(B) r, info_r = linsolve(Base.Fix1(*, B), p, r, 0, 1) @tensor b1[-1; -2] = u[-1; 1] * r[1 -2] - u, s, vh = tsvd(b1; trunc=alg.trscheme) + u, s, vh = tsvd(b1; trunc = alg.trscheme) s /= norm(s, Inf) # update `- l ← = - u ← s ←` @tensor l[-1 -2] := u[-1; 1] * s[1; -2] @@ -255,7 +255,7 @@ function fullenv_truncate( l, info_l = linsolve(Base.Fix1(*, B), p, l, 0, 1) @tensor b1[-1; -2] = l[-1 1] * vh[1; -2] fid = fidelity(benv, b0, b1) - u, s, vh = tsvd!(b1; trunc=alg.trscheme) + u, s, vh = tsvd!(b1; trunc = alg.trscheme) s /= norm(s, Inf) # determine convergence Δs = (space(s) == space(s0)) ? _singular_value_distance((s, s0)) : NaN diff --git a/src/algorithms/truncation/truncationschemes.jl b/src/algorithms/truncation/truncationschemes.jl index 3420c90b3..a7e70265c 100644 --- a/src/algorithms/truncation/truncationschemes.jl +++ b/src/algorithms/truncation/truncationschemes.jl @@ -7,11 +7,11 @@ have different spaces, this truncation style is different from `TruncationSpace` """ struct FixedSpaceTruncation <: TruncationScheme end -struct SiteDependentTruncation{T<:TruncationScheme} <: TruncationScheme - trschemes::Array{T,3} +struct SiteDependentTruncation{T <: TruncationScheme} <: TruncationScheme + trschemes::Array{T, 3} end -const TRUNCATION_SCHEME_SYMBOLS = IdDict{Symbol,Type{<:TruncationScheme}}( +const TRUNCATION_SCHEME_SYMBOLS = IdDict{Symbol, Type{<:TruncationScheme}}( :fixedspace => FixedSpaceTruncation, :notrunc => TensorKit.NoTruncation, :truncerr => TensorKit.TruncationError, @@ -22,7 +22,7 @@ const TRUNCATION_SCHEME_SYMBOLS = IdDict{Symbol,Type{<:TruncationScheme}}( ) # Should be TruncationScheme but rename to avoid type piracy -function _TruncationScheme(; alg=Defaults.trscheme, η=nothing) +function _TruncationScheme(; alg = Defaults.trscheme, η = nothing) # replace Symbol with TruncationScheme type haskey(TRUNCATION_SCHEME_SYMBOLS, alg) || throw(ArgumentError("unknown truncation scheme: $alg")) @@ -32,14 +32,14 @@ function _TruncationScheme(; alg=Defaults.trscheme, η=nothing) end function truncation_scheme( - trscheme::TruncationScheme, direction::Int, row::Int, col::Int; kwargs... -) + trscheme::TruncationScheme, direction::Int, row::Int, col::Int; kwargs... + ) return trscheme end function truncation_scheme( - trscheme::SiteDependentTruncation, direction::Int, row::Int, col::Int; -) + trscheme::SiteDependentTruncation, direction::Int, row::Int, col::Int + ) return trscheme.trschemes[direction, row, col] end @@ -55,15 +55,17 @@ function mirror_antidiag(trscheme::SiteDependentTruncation) mirror_antidiag(trscheme.trschemes[EAST, :, :]), mirror_antidiag(trscheme.trschemes[NORTH, :, :]), ); - dims=1, + dims = 1, ) elseif directions == 4 - trschemes_mirrored = stack(( - mirror_antidiag(trscheme.trschemes[EAST, :, :]), - mirror_antidiag(trscheme.trschemes[NORTH, :, :]), - mirror_antidiag(trscheme.trschemes[WEST, :, :]), - mirror_antidiag(trscheme.trschemes[SOUTH, :, :]), - )) + trschemes_mirrored = stack( + ( + mirror_antidiag(trscheme.trschemes[EAST, :, :]), + mirror_antidiag(trscheme.trschemes[NORTH, :, :]), + mirror_antidiag(trscheme.trschemes[WEST, :, :]), + mirror_antidiag(trscheme.trschemes[SOUTH, :, :]), + ) + ) else error("Unsupported number of directions for mirror_antidiag: $directions") end diff --git a/src/environments/ctmrg_environments.jl b/src/environments/ctmrg_environments.jl index de85fe06e..ef269d270 100644 --- a/src/environments/ctmrg_environments.jl +++ b/src/environments/ctmrg_environments.jl @@ -24,22 +24,22 @@ network being contracted. $(TYPEDFIELDS) """ -struct CTMRGEnv{C,T} +struct CTMRGEnv{C, T} "4 x rows x cols array of corner tensors, where the first dimension specifies the spatial direction" - corners::Array{C,3} + corners::Array{C, 3} "4 x rows x cols array of edge tensors, where the first dimension specifies the spatial direction" - edges::Array{T,3} + edges::Array{T, 3} end const ProductSpaceLike{N} = Union{ - NTuple{N,Int},NTuple{N,<:ElementarySpace},ProductSpace{<:ElementarySpace,N} + NTuple{N, Int}, NTuple{N, <:ElementarySpace}, ProductSpace{<:ElementarySpace, N}, } -const SpaceLike = Union{ElementarySpaceLike,ProductSpaceLike} +const SpaceLike = Union{ElementarySpaceLike, ProductSpaceLike} -_elementwise_dual(s::NTuple{N,<:ElementarySpace}) where {N} = dual.(s) +_elementwise_dual(s::NTuple{N, <:ElementarySpace}) where {N} = dual.(s) _spacetype(::Int) = ComplexSpace -_spacetype(::S) where {S<:ElementarySpace} = S +_spacetype(::S) where {S <: ElementarySpace} = S _spacetype(s::ProductSpaceLike) = _spacetype(first(s)) _to_space(χ::Int) = ℂ^χ @@ -47,14 +47,14 @@ _to_space(χ::ElementarySpace) = χ _to_space(χ::ProductSpaceLike) = prod(_to_space, χ) function _corner_tensor( - f, ::Type{T}, left_vspace::S, right_vspace::S=left_vspace -) where {T,S<:ElementarySpaceLike} + f, ::Type{T}, left_vspace::S, right_vspace::S = left_vspace + ) where {T, S <: ElementarySpaceLike} return f(T, _to_space(left_vspace) ← _to_space(right_vspace)) end function _edge_tensor( - f, ::Type{T}, left_vspace::S, pspaces::P, right_vspace::S=left_vspace -) where {T,S<:ElementarySpaceLike,P<:ProductSpaceLike} + f, ::Type{T}, left_vspace::S, pspaces::P, right_vspace::S = left_vspace + ) where {T, S <: ElementarySpaceLike, P <: ProductSpaceLike} return f(T, _to_space(left_vspace) ⊗ _to_space(pspaces), _to_space(right_vspace)) end @@ -83,35 +83,18 @@ representing a product space for the case of a partition function representing o PEPSs and PEPOs. """ function CTMRGEnv( - Ds_north::A, - Ds_east::A, - chis_north::B, - chis_east::B=chis_north, - chis_south::B=chis_north, - chis_west::B=chis_north, -) where {A<:AbstractMatrix{<:ProductSpaceLike},B<:AbstractMatrix{<:ElementarySpaceLike}} + Ds_north::A, Ds_east::A, + chis_north::B, chis_east::B = chis_north, chis_south::B = chis_north, chis_west::B = chis_north, + ) where {A <: AbstractMatrix{<:ProductSpaceLike}, B <: AbstractMatrix{<:ElementarySpaceLike}} return CTMRGEnv( - randn, - ComplexF64, - N, - Ds_north, - Ds_east, - chis_north, - chis_east, - chis_south, - chis_west, + randn, ComplexF64, N, Ds_north, Ds_east, chis_north, chis_east, chis_south, chis_west, ) end function CTMRGEnv( - f, - T, - Ds_north::A, - Ds_east::A, - chis_north::B, - chis_east::B=chis_north, - chis_south::B=chis_north, - chis_west::B=chis_north, -) where {A<:AbstractMatrix{<:ProductSpaceLike},B<:AbstractMatrix{<:ElementarySpaceLike}} + f, T, + Ds_north::A, Ds_east::A, + chis_north::B, chis_east::B = chis_north, chis_south::B = chis_north, chis_west::B = chis_north, + ) where {A <: AbstractMatrix{<:ProductSpaceLike}, B <: AbstractMatrix{<:ElementarySpaceLike}} # no recursive broadcasting? Ds_south = _elementwise_dual.(circshift(Ds_north, (-1, 0))) Ds_west = _elementwise_dual.(circshift(Ds_east, (0, 1))) @@ -174,46 +157,29 @@ The environment virtual spaces for each site correspond to virtual space of the corresponding edge tensor for each direction. """ function CTMRGEnv( - D_north::P, - D_east::P, - chi_north::S, - chi_east::S=chi_north, - chi_south::S=chi_north, - chi_west::S=chi_north; - unitcell::Tuple{Int,Int}=(1, 1), -) where {P<:ProductSpaceLike,S<:ElementarySpaceLike} + D_north::P, D_east::P, + chi_north::S, chi_east::S = chi_north, chi_south::S = chi_north, chi_west::S = chi_north; + unitcell::Tuple{Int, Int} = (1, 1), + ) where {P <: ProductSpaceLike, S <: ElementarySpaceLike} return CTMRGEnv( - randn, - ComplexF64, - fill(D_north, unitcell), - fill(D_east, unitcell), - fill(chi_north, unitcell), - fill(chi_east, unitcell), - fill(chi_south, unitcell), - fill(chi_west, unitcell), + randn, ComplexF64, + fill(D_north, unitcell), fill(D_east, unitcell), + fill(chi_north, unitcell), fill(chi_east, unitcell), + fill(chi_south, unitcell), fill(chi_west, unitcell), ) end function CTMRGEnv( - f, - T, - D_north::P, - D_east::P, - chi_north::S, - chi_east::S=chi_north, - chi_south::S=chi_north, - chi_west::S=chi_north; - unitcell::Tuple{Int,Int}=(1, 1), -) where {P<:ProductSpaceLike,S<:ElementarySpaceLike} + f, T, + D_north::P, D_east::P, + chi_north::S, chi_east::S = chi_north, + chi_south::S = chi_north, chi_west::S = chi_north; + unitcell::Tuple{Int, Int} = (1, 1), + ) where {P <: ProductSpaceLike, S <: ElementarySpaceLike} return CTMRGEnv( - f, - T, - N, - fill(D_north, unitcell), - fill(D_east, unitcell), - fill(chi_north, unitcell), - fill(chi_east, unitcell), - fill(chi_south, unitcell), - fill(chi_west, unitcell), + f, T, N, + fill(D_north, unitcell), fill(D_east, unitcell), + fill(chi_north, unitcell), fill(chi_east, unitcell), + fill(chi_south, unitcell), fill(chi_west, unitcell), ) end @@ -235,45 +201,28 @@ of the corresponding edge tensor for each direction. Specifically, for a given s `chis_west[r, c]` corresponds to the north space of the west edge tensor. """ function CTMRGEnv( - network::InfiniteSquareNetwork, - chis_north::A, - chis_east::A=chis_north, - chis_south::A=chis_north, - chis_west::A=chis_north, -) where {A<:AbstractMatrix{<:ElementarySpaceLike}} + network::InfiniteSquareNetwork, + chis_north::A, chis_east::A = chis_north, chis_south::A = chis_north, chis_west::A = chis_north, + ) where {A <: AbstractMatrix{<:ElementarySpaceLike}} Ds_north = _north_env_spaces(network) Ds_east = _east_env_spaces(network) return CTMRGEnv( - randn, - scalartype(network), - Ds_north, - Ds_east, - _to_space.(chis_north), - _to_space.(chis_east), - _to_space.(chis_south), - _to_space.(chis_west), + randn, scalartype(network), + Ds_north, Ds_east, + _to_space.(chis_north), _to_space.(chis_east), _to_space.(chis_south), _to_space.(chis_west), ) end function CTMRGEnv( - f, - T, - network::InfiniteSquareNetwork, - chis_north::A, - chis_east::A=chis_north, - chis_south::A=chis_north, - chis_west::A=chis_north, -) where {A<:AbstractMatrix{<:ElementarySpaceLike}} + f, T, + network::InfiniteSquareNetwork, + chis_north::A, chis_east::A = chis_north, chis_south::A = chis_north, chis_west::A = chis_north, + ) where {A <: AbstractMatrix{<:ElementarySpaceLike}} Ds_north = _north_env_spaces(network) Ds_east = _east_env_spaces(network) return CTMRGEnv( - f, - T, - Ds_north, - Ds_east, - _to_space.(chis_north), - _to_space.(chis_east), - _to_space.(chis_south), - _to_space.(chis_west), + f, T, + Ds_north, Ds_east, + _to_space.(chis_north), _to_space.(chis_east), _to_space.(chis_south), _to_space.(chis_west), ) end @@ -297,49 +246,37 @@ The environment virtual spaces for each site correspond to virtual space of the corresponding edge tensor for each direction. """ function CTMRGEnv( - network::InfiniteSquareNetwork, - chi_north::S, - chi_east::S=chi_north, - chi_south::S=chi_north, - chi_west::S=chi_north, -) where {S<:ElementarySpaceLike} + network::InfiniteSquareNetwork, + chi_north::S, chi_east::S = chi_north, chi_south::S = chi_north, chi_west::S = chi_north, + ) where {S <: ElementarySpaceLike} return CTMRGEnv( network, - fill(chi_north, size(network)), - fill(chi_east, size(network)), - fill(chi_south, size(network)), - fill(chi_west, size(network)), + fill(chi_north, size(network)), fill(chi_east, size(network)), + fill(chi_south, size(network)), fill(chi_west, size(network)), ) end function CTMRGEnv( - f, - T, - network::InfiniteSquareNetwork, - chi_north::S, - chi_east::S=chi_north, - chi_south::S=chi_north, - chi_west::S=chi_north, -) where {S<:ElementarySpaceLike} + f, T, + network::InfiniteSquareNetwork, + chi_north::S, chi_east::S = chi_north, chi_south::S = chi_north, chi_west::S = chi_north, + ) where {S <: ElementarySpaceLike} return CTMRGEnv( - f, - T, + f, T, network, - fill(chi_north, size(network)), - fill(chi_east, size(network)), - fill(chi_south, size(network)), - fill(chi_west, size(network)), + fill(chi_north, size(network)), fill(chi_east, size(network)), + fill(chi_south, size(network)), fill(chi_west, size(network)), ) end # allow constructing environments for implicitly defined contractible networks -function CTMRGEnv(state::Union{InfinitePartitionFunction,InfinitePEPS}, args...) +function CTMRGEnv(state::Union{InfinitePartitionFunction, InfinitePEPS}, args...) return CTMRGEnv(InfiniteSquareNetwork(state), args...) end -function CTMRGEnv(f, T, state::Union{InfinitePartitionFunction,InfinitePEPS}, args...) +function CTMRGEnv(f, T, state::Union{InfinitePartitionFunction, InfinitePEPS}, args...) return CTMRGEnv(f, T, InfiniteSquareNetwork(state), args...) end -@non_differentiable CTMRGEnv(state::Union{InfinitePartitionFunction,InfinitePEPS}, args...) +@non_differentiable CTMRGEnv(state::Union{InfinitePartitionFunction, InfinitePEPS}, args...) # Custom adjoint for CTMRGEnv constructor, needed for fixed-point differentiation function ChainRulesCore.rrule(::Type{CTMRGEnv}, corners, edges) @@ -380,26 +317,26 @@ Base.real(env::CTMRGEnv) = CTMRGEnv(real.(env.corners), real.(env.edges)) Base.complex(env::CTMRGEnv) = CTMRGEnv(complex.(env.corners), complex.(env.edges)) cornertype(env::CTMRGEnv) = cornertype(typeof(env)) -cornertype(::Type{CTMRGEnv{C,E}}) where {C,E} = C +cornertype(::Type{CTMRGEnv{C, E}}) where {C, E} = C edgetype(env::CTMRGEnv) = edgetype(typeof(env)) -edgetype(::Type{CTMRGEnv{C,E}}) where {C,E} = E +edgetype(::Type{CTMRGEnv{C, E}}) where {C, E} = E -TensorKit.spacetype(::Type{E}) where {E<:CTMRGEnv} = spacetype(cornertype(E)) +TensorKit.spacetype(::Type{E}) where {E <: CTMRGEnv} = spacetype(cornertype(E)) # In-place update of environment -function update!(env::CTMRGEnv{C,T}, env´::CTMRGEnv{C,T}) where {C,T} +function update!(env::CTMRGEnv{C, T}, env´::CTMRGEnv{C, T}) where {C, T} env.corners .= env´.corners env.edges .= env´.edges return env end # Rotate corners & edges counter-clockwise -function Base.rotl90(env::CTMRGEnv{C,T}) where {C,T} +function Base.rotl90(env::CTMRGEnv{C, T}) where {C, T} # Initialize rotated corners & edges with rotated sizes corners′ = Zygote.Buffer( - Array{C,3}(undef, 4, size(env.corners, 3), size(env.corners, 2)) + Array{C, 3}(undef, 4, size(env.corners, 3), size(env.corners, 2)) ) - edges′ = Zygote.Buffer(Array{T,3}(undef, 4, size(env.edges, 3), size(env.edges, 2))) + edges′ = Zygote.Buffer(Array{T, 3}(undef, 4, size(env.edges, 3), size(env.edges, 2))) for dir in 1:4 dir2 = _prev(dir, 4) corners′[dir2, :, :] = rotl90(env.corners[dir, :, :]) @@ -409,12 +346,12 @@ function Base.rotl90(env::CTMRGEnv{C,T}) where {C,T} end # Rotate corners & edges clockwise -function Base.rotr90(env::CTMRGEnv{C,T}) where {C,T} +function Base.rotr90(env::CTMRGEnv{C, T}) where {C, T} # Initialize rotated corners & edges with rotated sizes corners′ = Zygote.Buffer( - Array{C,3}(undef, 4, size(env.corners, 3), size(env.corners, 2)) + Array{C, 3}(undef, 4, size(env.corners, 3), size(env.corners, 2)) ) - edges′ = Zygote.Buffer(Array{T,3}(undef, 4, size(env.edges, 3), size(env.edges, 2))) + edges′ = Zygote.Buffer(Array{T, 3}(undef, 4, size(env.edges, 3), size(env.edges, 2))) for dir in 1:4 dir2 = _next(dir, 4) corners′[dir2, :, :] = rotr90(env.corners[dir, :, :]) @@ -424,12 +361,12 @@ function Base.rotr90(env::CTMRGEnv{C,T}) where {C,T} end # Rotate corners & edges by 180 degrees -function Base.rot180(env::CTMRGEnv{C,T}) where {C,T} +function Base.rot180(env::CTMRGEnv{C, T}) where {C, T} # Initialize rotated corners & edges with rotated sizes corners′ = Zygote.Buffer( - Array{C,3}(undef, 4, size(env.corners, 2), size(env.corners, 3)) + Array{C, 3}(undef, 4, size(env.corners, 2), size(env.corners, 3)) ) - edges′ = Zygote.Buffer(Array{T,3}(undef, 4, size(env.edges, 2), size(env.edges, 3))) + edges′ = Zygote.Buffer(Array{T, 3}(undef, 4, size(env.edges, 2), size(env.edges, 3))) for dir in 1:4 dir2 = _next(_next(dir, 4), 4) corners′[dir2, :, :] = rot180(env.corners[dir, :, :]) @@ -485,13 +422,13 @@ end # big vector. In other words, the associated vector space is not the natural one associated # to the original (physical) system, and addition, scaling, etc. are performed element-wise. -function VI.scalartype(::Type{CTMRGEnv{C,T}}) where {C,T} +function VI.scalartype(::Type{CTMRGEnv{C, T}}) where {C, T} S₁ = scalartype(C) S₂ = scalartype(T) return promote_type(S₁, S₂) end -function VI.zerovector(env::CTMRGEnv, ::Type{S}) where {S<:Number} +function VI.zerovector(env::CTMRGEnv, ::Type{S}) where {S <: Number} _zerovector = Base.Fix2(zerovector, S) return CTMRGEnv(map(_zerovector, env.corners), map(_zerovector, env.edges)) end diff --git a/src/environments/vumps_environments.jl b/src/environments/vumps_environments.jl index 6ed058506..28f509d71 100644 --- a/src/environments/vumps_environments.jl +++ b/src/environments/vumps_environments.jl @@ -4,28 +4,28 @@ using MPSKit: InfiniteEnvironments # ProductSpace instances function MPSKit.issamespace( - env::InfiniteEnvironments, - below::InfiniteMPS, - operator::InfiniteTransferMatrix, - above::InfiniteMPS, -) + env::InfiniteEnvironments, + below::InfiniteMPS, + operator::InfiniteTransferMatrix, + above::InfiniteMPS, + ) L = MPSKit.check_length(above, operator, below) for i in 1:L space(env.GLs[i]) == ( left_virtualspace(below, i) ⊗ - _elementwise_dual(left_virtualspace(operator, i)) ← left_virtualspace(above, i) + _elementwise_dual(left_virtualspace(operator, i)) ← left_virtualspace(above, i) ) || return false space(env.GRs[i]) == ( right_virtualspace(above, i) ⊗ right_virtualspace(operator, i) ← - right_virtualspace(below, i) + right_virtualspace(below, i) ) || return false end return true end function MPSKit.allocate_GL( - bra::InfiniteMPS, mpo::InfiniteTransferMatrix, ket::InfiniteMPS, i::Int -) + bra::InfiniteMPS, mpo::InfiniteTransferMatrix, ket::InfiniteMPS, i::Int + ) T = Base.promote_type(scalartype(bra), scalartype(mpo), scalartype(ket)) V = left_virtualspace(bra, i) ⊗ _elementwise_dual(left_virtualspace(mpo, i)) ← @@ -35,8 +35,8 @@ function MPSKit.allocate_GL( end function MPSKit.allocate_GR( - bra::InfiniteMPS, mpo::InfiniteTransferMatrix, ket::InfiniteMPS, i::Int -) + bra::InfiniteMPS, mpo::InfiniteTransferMatrix, ket::InfiniteMPS, i::Int + ) T = Base.promote_type(scalartype(bra), scalartype(mpo), scalartype(ket)) V = right_virtualspace(ket, i) ⊗ right_virtualspace(mpo, i) ← right_virtualspace(bra, i) TT = TensorMap{T} diff --git a/src/networks/infinitesquarenetwork.jl b/src/networks/infinitesquarenetwork.jl index ac7f14312..f003bd095 100644 --- a/src/networks/infinitesquarenetwork.jl +++ b/src/networks/infinitesquarenetwork.jl @@ -14,11 +14,11 @@ struct InfiniteSquareNetwork{O} for I in eachindex(IndexCartesian(), A) d, w = Tuple(I) north_virtualspace(A[d, w]) == - _elementwise_dual(south_virtualspace(A[_prev(d, end), w])) || throw( + _elementwise_dual(south_virtualspace(A[_prev(d, end), w])) || throw( SpaceMismatch("North virtual space at site $((d, w)) does not match.") ) east_virtualspace(A[d, w]) == - _elementwise_dual(west_virtualspace(A[d, _next(w, end)])) || + _elementwise_dual(west_virtualspace(A[d, _next(w, end)])) || throw(SpaceMismatch("East virtual space at site $((d, w)) does not match.")) end return InfiniteSquareNetwork{eltype(A)}(A) @@ -35,7 +35,7 @@ Base.eltype(n::InfiniteSquareNetwork) = eltype(typeof(n)) Base.eltype(::Type{InfiniteSquareNetwork{O}}) where {O} = O Base.copy(n::InfiniteSquareNetwork) = InfiniteSquareNetwork(copy(unitcell(n))) -function Base.similar(n::InfiniteSquareNetwork, T::Type{TorA}=scalartype(n)) where {TorA} +function Base.similar(n::InfiniteSquareNetwork, T::Type{TorA} = scalartype(n)) where {TorA} return InfiniteSquareNetwork(map(t -> similar(t, T), unitcell(n))) end function Base.repeat(n::InfiniteSquareNetwork, counts...) @@ -59,7 +59,7 @@ virtualspace(n::InfiniteSquareNetwork, r::Int, c::Int, dir) = virtualspace(n[r, ## Vector interface -function VectorInterface.scalartype(::Type{T}) where {T<:InfiniteSquareNetwork} +function VectorInterface.scalartype(::Type{T}) where {T <: InfiniteSquareNetwork} return scalartype(eltype(T)) end function VectorInterface.zerovector(A::InfiniteSquareNetwork) @@ -115,8 +115,8 @@ end # generic implementation function ChainRulesCore.rrule( - ::typeof(Base.getindex), network::InfiniteSquareNetwork, r::Int, c::Int -) + ::typeof(Base.getindex), network::InfiniteSquareNetwork, r::Int, c::Int + ) O = network[r, c] function getindex_pullback(ΔO_) @@ -133,8 +133,8 @@ end # specialized PFTensor implementation function ChainRulesCore.rrule( - ::typeof(Base.getindex), network::InfiniteSquareNetwork{<:PFTensor}, r::Int, c::Int -) + ::typeof(Base.getindex), network::InfiniteSquareNetwork{<:PFTensor}, r::Int, c::Int + ) O = network[r, c] function getindex_pullback(ΔO_) diff --git a/src/networks/local_sandwich.jl b/src/networks/local_sandwich.jl index 431f67f48..a49dbc259 100644 --- a/src/networks/local_sandwich.jl +++ b/src/networks/local_sandwich.jl @@ -46,7 +46,7 @@ _mul_localsandwich(α::Number, O::PFTensor) = α * O ## PEPS -const PEPSSandwich{T<:PEPSTensor} = Tuple{T,T} +const PEPSSandwich{T <: PEPSTensor} = Tuple{T, T} ket(O::PEPSSandwich) = O[1] bra(O::PEPSSandwich) = O[2] @@ -90,7 +90,7 @@ end ## PEPO -const PEPOSandwich{N,T<:PEPSTensor,P<:PEPOTensor} = Tuple{T,T,Vararg{P,N}} +const PEPOSandwich{N, T <: PEPSTensor, P <: PEPOTensor} = Tuple{T, T, Vararg{P, N}} ket(O::PEPOSandwich) = O[1] bra(O::PEPOSandwich) = O[2] @@ -98,9 +98,11 @@ pepo(O::PEPOSandwich) = O[3:end] pepo(O::PEPOSandwich, i::Int) = O[2 + i] function virtualspace(O::PEPOSandwich, dir) - return prod([ - virtualspace(ket(O), dir), - virtualspace.(pepo(O), Ref(dir))..., - virtualspace(bra(O), dir)', - ]) + return prod( + [ + virtualspace(ket(O), dir), + virtualspace.(pepo(O), Ref(dir))..., + virtualspace(bra(O), dir)', + ] + ) end diff --git a/src/networks/tensors.jl b/src/networks/tensors.jl index 1f245e95c..055dc374a 100644 --- a/src/networks/tensors.jl +++ b/src/networks/tensors.jl @@ -19,7 +19,7 @@ and west spaces, respectively. S ``` """ -const PartitionFunctionTensor{S<:ElementarySpace} = AbstractTensorMap{<:Any,S,2,2} +const PartitionFunctionTensor{S <: ElementarySpace} = AbstractTensorMap{<:Any, S, 2, 2} const PFTensor = PartitionFunctionTensor Base.rotl90(t::PFTensor) = permute(t, ((3, 1), (4, 2))) @@ -53,7 +53,7 @@ respectively. S P ``` """ -const PEPSTensor{S<:ElementarySpace} = AbstractTensorMap{<:Any,S,1,4} +const PEPSTensor{S <: ElementarySpace} = AbstractTensorMap{<:Any, S, 1, 4} """ PEPSTensor(f, ::Type{T}, Pspace::S, Nspace::S, @@ -64,25 +64,17 @@ Alternatively, only the space dimensions can be provided and ℂ is assumed as t The tensor elements are generated based on `f` and the element type is specified in `T`. """ function PEPSTensor( - f, - ::Type{T}, - Pspace::S, - Nspace::S, - Espace::S=Nspace, - Sspace::S=Nspace', - Wspace::S=Espace', -) where {T,S<:ElementarySpace} + f, ::Type{T}, + Pspace::S, + Nspace::S, Espace::S = Nspace, Sspace::S = Nspace', Wspace::S = Espace', + ) where {T, S <: ElementarySpace} return f(T, Pspace ← Nspace ⊗ Espace ⊗ Sspace ⊗ Wspace) end function PEPSTensor( - f, - ::Type{T}, - Pspace::Int, - Nspace::Int, - Espace::Int=Nspace, - Sspace::Int=Nspace, - Wspace::Int=Espace, -) where {T} + f, ::Type{T}, + Pspace::Int, + Nspace::Int, Espace::Int = Nspace, Sspace::Int = Nspace, Wspace::Int = Espace, + ) where {T} return f(T, ℂ^Pspace ← ℂ^Nspace ⊗ ℂ^Espace ⊗ (ℂ^Sspace)' ⊗ (ℂ^Wspace)') end @@ -118,7 +110,7 @@ mapping from ``P´'`` to ``P`` where ``P´'`` corresponds to a physical PEPS ind S P ``` """ -const PEPOTensor{S<:ElementarySpace} = AbstractTensorMap{<:Any,S,2,4} +const PEPOTensor{S <: ElementarySpace} = AbstractTensorMap{<:Any, S, 2, 4} Base.rotl90(t::PEPOTensor) = permute(t, ((1, 2), (4, 5, 6, 3))) Base.rotr90(t::PEPOTensor) = permute(t, ((1, 2), (6, 3, 4, 5))) diff --git a/src/operators/infinitepepo.jl b/src/operators/infinitepepo.jl index cc3e7be88..1f6acb6c4 100644 --- a/src/operators/infinitepepo.jl +++ b/src/operators/infinitepepo.jl @@ -7,25 +7,25 @@ Represents an infinite projected entangled-pair operator (PEPO) on a 3D cubic la $(TYPEDFIELDS) """ -struct InfinitePEPO{T<:PEPOTensor} - A::Array{T,3} - InfinitePEPO{T}(A::Array{T,3}) where {T} = new{T}(A) - function InfinitePEPO(A::Array{T,3}) where {T<:PEPOTensor} +struct InfinitePEPO{T <: PEPOTensor} + A::Array{T, 3} + InfinitePEPO{T}(A::Array{T, 3}) where {T} = new{T}(A) + function InfinitePEPO(A::Array{T, 3}) where {T <: PEPOTensor} # space checks for (d, w, h) in Tuple.(CartesianIndices(A)) codomain_physicalspace(A[d, w, h]) == - domain_physicalspace(A[d, w, _next(h, end)]) || + domain_physicalspace(A[d, w, _next(h, end)]) || throw(SpaceMismatch("Physical space at site $((d, w, h)) does not match.")) north_virtualspace(A[d, w, h]) == south_virtualspace(A[_prev(d, end), w, h])' || throw( - SpaceMismatch( - "North virtual space at site $((d, w, h)) does not match." - ), - ) + SpaceMismatch( + "North virtual space at site $((d, w, h)) does not match." + ), + ) east_virtualspace(A[d, w, h]) == west_virtualspace(A[d, _next(w, end), h])' || throw( - SpaceMismatch("East virtual space at site $((d, w, h)) does not match.") - ) + SpaceMismatch("East virtual space at site $((d, w, h)) does not match.") + ) end return new{T}(A) end @@ -38,7 +38,7 @@ end Allow users to pass in an array of tensors. """ -function InfinitePEPO(A::AbstractArray{T,3}) where {T<:PEPOTensor} +function InfinitePEPO(A::AbstractArray{T, 3}) where {T <: PEPOTensor} return InfinitePEPO(Array(deepcopy(A))) end @@ -48,13 +48,13 @@ end Allow users to pass in arrays of spaces. """ function InfinitePEPO( - Pspaces::A, Nspaces::A, Espaces::A=Nspaces -) where {A<:AbstractArray{<:ElementarySpace,3}} + Pspaces::A, Nspaces::A, Espaces::A = Nspaces + ) where {A <: AbstractArray{<:ElementarySpace, 3}} return InfinitePEPO(randn, ComplexF64, Pspaces, Nspaces, Espaces) end function InfinitePEPO( - f, T, Pspaces::A, Nspaces::A, Espaces::A=Nspaces -) where {A<:AbstractArray{<:ElementarySpace,3}} + f, T, Pspaces::A, Nspaces::A, Espaces::A = Nspaces + ) where {A <: AbstractArray{<:ElementarySpace, 3}} size(Pspaces) == size(Nspaces) == size(Espaces) || throw(ArgumentError("Input spaces should have equal sizes.")) @@ -70,8 +70,8 @@ function InfinitePEPO( end function InfinitePEPO( - Pspaces::A, Nspaces::A, Espaces::A=Nspaces -) where {A<:AbstractArray{<:ElementarySpace,2}} + Pspaces::A, Nspaces::A, Espaces::A = Nspaces + ) where {A <: AbstractArray{<:ElementarySpace, 2}} size(Pspaces) == size(Nspaces) == size(Espaces) || throw(ArgumentError("Input spaces should have equal sizes.")) @@ -87,7 +87,7 @@ end Create an InfinitePEPO by specifying a tensor which is repeated across the unit cell. """ -function InfinitePEPO(A::T; unitcell::Tuple{Int,Int,Int}=(1, 1, 1)) where {T<:PEPOTensor} +function InfinitePEPO(A::T; unitcell::Tuple{Int, Int, Int} = (1, 1, 1)) where {T <: PEPOTensor} return InfinitePEPO(fill(A, unitcell)) end @@ -97,27 +97,24 @@ end Create an InfinitePEPO by specifying its spaces and unit cell. """ function InfinitePEPO( - Pspace::S, Nspace::S, Espace::S=Nspace; unitcell::Tuple{Int,Int,Int}=(1, 1, 1) -) where {S<:ElementarySpace} + Pspace::S, Nspace::S, Espace::S = Nspace; unitcell::Tuple{Int, Int, Int} = (1, 1, 1) + ) where {S <: ElementarySpace} return InfinitePEPO( - randn, - ComplexF64, - fill(Pspace, unitcell), - fill(Nspace, unitcell), - fill(Espace, unitcell), + randn, ComplexF64, + fill(Pspace, unitcell), fill(Nspace, unitcell), fill(Espace, unitcell), ) end function InfinitePEPO( - f, T, Pspace::S, Nspace::S, Espace::S=Nspace; unitcell::Tuple{Int,Int,Int}=(1, 1, 1) -) where {S<:ElementarySpace} + f, T, Pspace::S, Nspace::S, Espace::S = Nspace; unitcell::Tuple{Int, Int, Int} = (1, 1, 1) + ) where {S <: ElementarySpace} return InfinitePEPO( f, T, fill(Pspace, unitcell), fill(Nspace, unitcell), fill(Espace, unitcell) ) end function initializePEPS( - T::InfinitePEPO{<:PEPOTensor{S}}, vspace::S -) where {S<:ElementarySpace} + T::InfinitePEPO{<:PEPOTensor{S}}, vspace::S + ) where {S <: ElementarySpace} Pspaces = map(Iterators.product(axes(T, 1), axes(T, 2))) do (r, c) return domain_physicalspace(T, r, c) end @@ -135,7 +132,7 @@ Base.eltype(::Type{InfinitePEPO{T}}) where {T} = T Base.eltype(A::InfinitePEPO) = eltype(typeof(A)) Base.copy(A::InfinitePEPO) = InfinitePEPO(copy(unitcell(A))) -function Base.similar(A::InfinitePEPO, T::Type{TorA}=scalartype(A)) where {TorA} +function Base.similar(A::InfinitePEPO, T::Type{TorA} = scalartype(A)) where {TorA} return InfinitePEPO(map(t -> similar(t, T), unitcell(A))) end Base.repeat(A::InfinitePEPO, counts...) = InfinitePEPO(repeat(unitcell(A), counts...)) @@ -150,7 +147,7 @@ end ## Spaces -TensorKit.spacetype(::Type{P}) where {P<:InfinitePEPO} = spacetype(eltype(P)) +TensorKit.spacetype(::Type{P}) where {P <: InfinitePEPO} = spacetype(eltype(P)) virtualspace(T::InfinitePEPO, r::Int, c::Int, h::Int, dir) = virtualspace(T[r, c, h], dir) domain_physicalspace(T::InfinitePEPO, r::Int, c::Int) = domain_physicalspace(T[r, c, 1]) function codomain_physicalspace(T::InfinitePEPO, r::Int, c::Int) @@ -167,18 +164,18 @@ end ## InfiniteSquareNetwork interface -function InfiniteSquareNetwork(top::InfinitePEPS, mid::InfinitePEPO, bot::InfinitePEPS=top) +function InfiniteSquareNetwork(top::InfinitePEPS, mid::InfinitePEPO, bot::InfinitePEPS = top) size(top) == size(bot) == size(mid)[1:2] || throw( ArgumentError("Top PEPS, bottom PEPS and PEPO layers should have equal sizes") ) return InfiniteSquareNetwork( - map(tuple, unitcell(top), unitcell(bot), eachslice(unitcell(mid); dims=3)...) + map(tuple, unitcell(top), unitcell(bot), eachslice(unitcell(mid); dims = 3)...) ) end ## Vector interface -VI.scalartype(::Type{NT}) where {NT<:InfinitePEPO} = scalartype(eltype(NT)) +VI.scalartype(::Type{NT}) where {NT <: InfinitePEPO} = scalartype(eltype(NT)) VI.zerovector(A::InfinitePEPO) = InfinitePEPO(zerovector(unitcell(A))) ## (Approximate) equality @@ -195,18 +192,16 @@ end ## Rotations -Base.rotl90(A::InfinitePEPO) = InfinitePEPO(stack(rotl90, eachslice(unitcell(A); dims=3))) -Base.rotr90(A::InfinitePEPO) = InfinitePEPO(stack(rotr90, eachslice(unitcell(A); dims=3))) -Base.rot180(A::InfinitePEPO) = InfinitePEPO(stack(rot180, eachslice(unitcell(A); dims=3))) +Base.rotl90(A::InfinitePEPO) = InfinitePEPO(stack(rotl90, eachslice(unitcell(A); dims = 3))) +Base.rotr90(A::InfinitePEPO) = InfinitePEPO(stack(rotr90, eachslice(unitcell(A); dims = 3))) +Base.rot180(A::InfinitePEPO) = InfinitePEPO(stack(rot180, eachslice(unitcell(A); dims = 3))) ## Chainrules function ChainRulesCore.rrule( - ::Type{InfiniteSquareNetwork}, - top::InfinitePEPS, - mid::InfinitePEPO{P}, - bot::InfinitePEPS, -) where {P<:PEPOTensor} + ::Type{InfiniteSquareNetwork}, + top::InfinitePEPS, mid::InfinitePEPO{P}, bot::InfinitePEPS, + ) where {P <: PEPOTensor} network = InfiniteSquareNetwork(top, mid, bot) function InfiniteSquareNetwork_pullback(Δnetwork_) @@ -219,7 +214,7 @@ function ChainRulesCore.rrule( return network, InfiniteSquareNetwork_pullback end -function _stack_tuples(A::Matrix{NTuple{N,T}}) where {N,T} +function _stack_tuples(A::Matrix{NTuple{N, T}}) where {N, T} out = Array{T}(undef, size(A)..., N) for (r, c) in Iterators.product(axes(A)...) out[r, c, :] .= A[r, c] diff --git a/src/operators/lattices/squarelattice.jl b/src/operators/lattices/squarelattice.jl index e72b63b49..005c0bdad 100644 --- a/src/operators/lattices/squarelattice.jl +++ b/src/operators/lattices/squarelattice.jl @@ -16,7 +16,7 @@ By default, an infinite square with a (1, 1)-unitcell is constructed. struct InfiniteSquare <: AbstractLattice{2} Nrows::Int Ncols::Int - function InfiniteSquare(Nrows::Integer=1, Ncols::Integer=1) + function InfiniteSquare(Nrows::Integer = 1, Ncols::Integer = 1) Nrows > 0 && Ncols > 0 || error("unit cell size needs to be positive") return new(Nrows, Ncols) end @@ -29,7 +29,7 @@ function vertices(lattice::InfiniteSquare) end function nearest_neighbours(lattice::InfiniteSquare) - neighbors = Tuple{CartesianIndex,CartesianIndex}[] + neighbors = Tuple{CartesianIndex, CartesianIndex}[] for idx in vertices(lattice) push!(neighbors, (idx, idx + CartesianIndex(0, 1))) push!(neighbors, (idx, idx + CartesianIndex(1, 0))) @@ -38,7 +38,7 @@ function nearest_neighbours(lattice::InfiniteSquare) end function next_nearest_neighbours(lattice::InfiniteSquare) - neighbors = Tuple{CartesianIndex,CartesianIndex}[] + neighbors = Tuple{CartesianIndex, CartesianIndex}[] for idx in vertices(lattice) push!(neighbors, (idx, idx + CartesianIndex(1, 1))) push!(neighbors, (idx + CartesianIndex(0, 1), idx + CartesianIndex(1, 0))) diff --git a/src/operators/localoperator.jl b/src/operators/localoperator.jl index 7855b488c..ede181afd 100644 --- a/src/operators/localoperator.jl +++ b/src/operators/localoperator.jl @@ -23,10 +23,10 @@ lattice = fill(ℂ^2, 1, 1) # single-site unitcell O1 = LocalOperator(lattice, ((1, 1),) => σx, ((1, 1), (1, 2)) => σx ⊗ σx, ((1, 1), (2, 1)) => σx ⊗ σx) ``` """ -struct LocalOperator{T<:Tuple,S} +struct LocalOperator{T <: Tuple, S} lattice::Matrix{S} terms::T - function LocalOperator{T,S}(lattice::Matrix{S}, terms::T) where {T,S} + function LocalOperator{T, S}(lattice::Matrix{S}, terms::T) where {T, S} plattice = PeriodicArray(lattice) # Check if the indices of the operator are valid with themselves and the lattice for (inds, operator) in terms @@ -39,14 +39,13 @@ struct LocalOperator{T<:Tuple,S} @assert space(operator, i) == plattice[inds[i]] end end - return new{T,S}(lattice, terms) + return new{T, S}(lattice, terms) end end function LocalOperator( - lattice::Matrix, - terms::Pair...; - atol=maximum(x -> eps(real(scalartype(x[2])))^(3 / 4), terms), -) + lattice::Matrix, terms::Pair...; + atol = maximum(x -> eps(real(scalartype(x[2])))^(3 / 4), terms), + ) allinds = getindex.(terms, 1) alloperators = getindex.(terms, 2) @@ -62,7 +61,7 @@ function LocalOperator( end terms_tuple = Tuple(relevant_terms) - return LocalOperator{typeof(terms_tuple),eltype(lattice)}(lattice, terms_tuple) + return LocalOperator{typeof(terms_tuple), eltype(lattice)}(lattice, terms_tuple) end """ @@ -120,7 +119,7 @@ end # -------------- function Base.:*(α::Number, O::LocalOperator) scaled_terms = map(((inds, operator),) -> (inds => α * operator), O.terms) - return LocalOperator{typeof(scaled_terms),eltype(O.lattice)}(O.lattice, scaled_terms) + return LocalOperator{typeof(scaled_terms), eltype(O.lattice)}(O.lattice, scaled_terms) end Base.:*(O::LocalOperator, α::Number) = α * O @@ -144,7 +143,7 @@ Base.:-(O1::LocalOperator, O2::LocalOperator) = O1 + (-O2) Get the position of `site` after reflection about the anti-diagonal line of a unit cell of size `(Nrow, Ncol)`. """ -function mirror_antidiag(site::CartesianIndex{2}, (Nrow, Ncol)::NTuple{2,Int}) +function mirror_antidiag(site::CartesianIndex{2}, (Nrow, Ncol)::NTuple{2, Int}) r, c = site[1], site[2] return CartesianIndex(Ncol - c + 1, Nrow - r + 1) end @@ -163,7 +162,7 @@ function mirror_antidiag(H::LocalOperator) lattice2 = mirror_antidiag(physicalspace(H)) terms2 = ( (Tuple(mirror_antidiag(site, size(H.lattice)) for site in sites) => op) for - (sites, op) in H.terms + (sites, op) in H.terms ) return LocalOperator(lattice2, terms2...) end @@ -188,11 +187,11 @@ end # Charge shifting # --------------- -TensorKit.spacetype(::Type{T}) where {S,T<:LocalOperator{<:Any,S}} = S +TensorKit.spacetype(::Type{T}) where {S, T <: LocalOperator{<:Any, S}} = S @generated function _fuse_isomorphisms( - op::AbstractTensorMap{<:Any,S,N,N}, fs::Vector{<:AbstractTensorMap{<:Any,S,1,2}} -) where {S,N} + op::AbstractTensorMap{<:Any, S, N, N}, fs::Vector{<:AbstractTensorMap{<:Any, S, 1, 2}} + ) where {S, N} op_out_e = tensorexpr(:op_out, -(1:N), -((1:N) .+ N)) op_e = tensorexpr(:op, 1:3:(3 * N), 2:3:(3 * N)) f_es = map(1:N) do i @@ -214,7 +213,7 @@ $(SIGNATURES) Fuse identities on auxiliary physical spaces into a given operator. """ -function _fuse_ids(op::AbstractTensorMap{T,S,N,N}, Ps::NTuple{N,S}) where {T,S,N} +function _fuse_ids(op::AbstractTensorMap{T, S, N, N}, Ps::NTuple{N, S}) where {T, S, N} # make isomorphisms fs = map(1:N) do i return isomorphism(fuse(space(op, i), Ps[i]), space(op, i) ⊗ Ps[i]) diff --git a/src/operators/models.jl b/src/operators/models.jl index ac28b7a2e..2dbcc6bbe 100644 --- a/src/operators/models.jl +++ b/src/operators/models.jl @@ -1,4 +1,3 @@ - # ## Tools for defining Hamiltonians # @@ -10,8 +9,8 @@ Create a nearest neighbor `LocalOperator` by specifying the 2-site interaction t which acts both in horizontal and vertical direction. """ function nearest_neighbour_hamiltonian( - lattice::Matrix{S}, h::AbstractTensorMap{T,S,2,2} -) where {S,T} + lattice::Matrix{S}, h::AbstractTensorMap{T, S, 2, 2} + ) where {S, T} terms = [] for I in eachindex(IndexCartesian(), lattice) J1 = I + CartesianIndex(1, 0) @@ -27,12 +26,9 @@ end # function MPSKitModels.transverse_field_ising( - T::Type{<:Number}, - S::Union{Type{Trivial},Type{Z2Irrep}}, - lattice::InfiniteSquare; - J=1.0, - g=1.0, -) + T::Type{<:Number}, S::Union{Type{Trivial}, Type{Z2Irrep}}, lattice::InfiniteSquare; + J = 1.0, g = 1.0, + ) ZZ = rmul!(σᶻᶻ(T, S), -J) X = rmul!(σˣ(T, S), g * -J) spaces = fill(domain(X)[1], (lattice.Nrows, lattice.Ncols)) @@ -47,18 +43,13 @@ function MPSKitModels.heisenberg_XYZ(lattice::InfiniteSquare; kwargs...) return heisenberg_XYZ(ComplexF64, Trivial, lattice; kwargs...) end function MPSKitModels.heisenberg_XYZ( - T::Type{<:Number}, - S::Type{<:Sector}, - lattice::InfiniteSquare; - Jx=-1.0, - Jy=1.0, - Jz=-1.0, - spin=1//2, -) + T::Type{<:Number}, S::Type{<:Sector}, lattice::InfiniteSquare; + Jx = -1.0, Jy = 1.0, Jz = -1.0, spin = 1 // 2, + ) term = - rmul!(S_xx(T, S; spin=spin), Jx) + - rmul!(S_yy(T, S; spin=spin), Jy) + - rmul!(S_zz(T, S; spin=spin), Jz) + rmul!(S_xx(T, S; spin = spin), Jx) + + rmul!(S_yy(T, S; spin = spin), Jy) + + rmul!(S_zz(T, S; spin = spin), Jz) spaces = fill(domain(term)[1], (lattice.Nrows, lattice.Ncols)) return LocalOperator( spaces, (neighbor => term for neighbor in nearest_neighbours(lattice))... @@ -66,13 +57,14 @@ function MPSKitModels.heisenberg_XYZ( end function MPSKitModels.heisenberg_XXZ( - T::Type{<:Number}, S::Type{<:Sector}, lattice::InfiniteSquare; J=1.0, Delta=1.0, spin=1 -) + T::Type{<:Number}, S::Type{<:Sector}, lattice::InfiniteSquare; + J = 1.0, Delta = 1.0, spin = 1 + ) h = J * ( - (S_plusmin(T, S; spin=spin) + S_minplus(T, S; spin=spin)) / 2 + - Delta * S_zz(T, S; spin=spin) - ) + (S_plusmin(T, S; spin = spin) + S_minplus(T, S; spin = spin)) / 2 + + Delta * S_zz(T, S; spin = spin) + ) rmul!(h, 1 / 4) spaces = fill(domain(h)[1], (lattice.Nrows, lattice.Ncols)) return LocalOperator( @@ -81,15 +73,10 @@ function MPSKitModels.heisenberg_XXZ( end function MPSKitModels.hubbard_model( - T::Type{<:Number}, - particle_symmetry::Type{<:Sector}, - spin_symmetry::Type{<:Sector}, - lattice::InfiniteSquare; - t=1.0, - U=1.0, - mu=0.0, - n::Integer=0, -) + T::Type{<:Number}, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}, + lattice::InfiniteSquare; + t = 1.0, U = 1.0, mu = 0.0, n::Integer = 0, + ) # TODO: just add this @assert n == 0 "Currently no support for imposing a fixed particle number" N = MPSKitModels.e_number(T, particle_symmetry, spin_symmetry) @@ -105,18 +92,12 @@ function MPSKitModels.hubbard_model( end function MPSKitModels.bose_hubbard_model( - elt::Type{<:Number}, - symmetry::Type{<:Sector}, - lattice::InfiniteSquare; - cutoff::Integer=5, - t=1.0, - U=1.0, - mu=0.0, - n::Integer=0, -) + elt::Type{<:Number}, symmetry::Type{<:Sector}, lattice::InfiniteSquare; + cutoff::Integer = 5, t = 1.0, U = 1.0, mu = 0.0, n::Integer = 0, + ) hopping_term = - a_plusmin(elt, symmetry; cutoff=cutoff) + a_minplus(elt, symmetry; cutoff=cutoff) - N = a_number(elt, symmetry; cutoff=cutoff) + a_plusmin(elt, symmetry; cutoff = cutoff) + a_minplus(elt, symmetry; cutoff = cutoff) + N = a_number(elt, symmetry; cutoff = cutoff) interaction_term = MPSKitModels.contract_onesite(N, N - id(domain(N))) spaces = fill(space(N, 1), (lattice.Nrows, lattice.Ncols)) @@ -141,15 +122,10 @@ function MPSKitModels.bose_hubbard_model( end function MPSKitModels.tj_model( - T::Type{<:Number}, - particle_symmetry::Type{<:Sector}, - spin_symmetry::Type{<:Sector}, - lattice::InfiniteSquare; - t=2.5, - J=1.0, - mu=0.0, - slave_fermion::Bool=false, -) + T::Type{<:Number}, particle_symmetry::Type{<:Sector}, spin_symmetry::Type{<:Sector}, + lattice::InfiniteSquare; + t = 2.5, J = 1.0, mu = 0.0, slave_fermion::Bool = false, + ) hopping = TJOperators.e_plusmin(particle_symmetry, spin_symmetry; slave_fermion) + TJOperators.e_minplus(particle_symmetry, spin_symmetry; slave_fermion) @@ -190,14 +166,9 @@ function j1_j2_model(lattice::InfiniteSquare; kwargs...) return j1_j2_model(ComplexF64, Trivial, lattice; kwargs...) end function j1_j2_model( - T::Type{<:Number}, - S::Type{<:Sector}, - lattice::InfiniteSquare; - J1=1.0, - J2=1.0, - spin=1//2, - sublattice=true, -) + T::Type{<:Number}, S::Type{<:Sector}, lattice::InfiniteSquare; + J1 = 1.0, J2 = 1.0, spin = 1 // 2, sublattice = true, + ) term_AA = S_xx(T, S; spin) + S_yy(T, S; spin) + S_zz(T, S; spin) term_AB = if sublattice -S_xx(T, S; spin) + S_yy(T, S; spin) - S_zz(T, S; spin) # Apply sublattice rotation @@ -229,8 +200,9 @@ function pwave_superconductor(lattice::InfiniteSquare; kwargs...) return pwave_superconductor(ComplexF64, lattice; kwargs...) end function pwave_superconductor( - T::Type{<:Number}, lattice::InfiniteSquare; t::Number=1, μ::Number=2, Δ::Number=1 -) + T::Type{<:Number}, lattice::InfiniteSquare; + t::Number = 1, μ::Number = 2, Δ::Number = 1 + ) physical_space = Vect[FermionParity](0 => 1, 1 => 1) spaces = fill(physical_space, (lattice.Nrows, lattice.Ncols)) @@ -245,7 +217,7 @@ function pwave_superconductor( # two-site (y-direction) hy = zeros(T, physical_space^2 ← physical_space^2) - block(hy, FermionParity(0)) .= [0 Δ*im; -Δ*im 0] + block(hy, FermionParity(0)) .= [0 Δ * im; -Δ * im 0] block(hy, FermionParity(1)) .= [0 -t; -t 0] x_neighbors = filter(n -> n[2].I[2] > n[1].I[2], nearest_neighbours(lattice)) diff --git a/src/operators/transfermatrix.jl b/src/operators/transfermatrix.jl index c8d006b5b..3aa9c8ed3 100644 --- a/src/operators/transfermatrix.jl +++ b/src/operators/transfermatrix.jl @@ -12,11 +12,11 @@ import MPSKit: Multiline, MultilineEnvironments Represents an infinite transfer operator corresponding to a single row of a partition function which corresponds to the overlap between 'ket' and 'bra' `InfinitePEPS` states. """ -const InfiniteTransferPEPS{T<:PEPSTensor} = InfiniteMPO{PEPSSandwich{T}} +const InfiniteTransferPEPS{T <: PEPSTensor} = InfiniteMPO{PEPSSandwich{T}} function InfiniteTransferPEPS( - top::PeriodicArray{T,1}, bot::PeriodicArray{T,1} -) where {T<:PEPSTensor} + top::PeriodicArray{T, 1}, bot::PeriodicArray{T, 1} + ) where {T <: PEPSTensor} return InfiniteMPO(map(tuple, top, bot)) end @@ -67,14 +67,14 @@ Represents an infinite transfer operator corresponding to a single row of a part function which corresponds to the expectation value of an `InfinitePEPO` between 'ket' and 'bra' `InfinitePEPS` states. """ -const InfiniteTransferPEPO{H,T<:PEPSTensor,O<:PEPOTensor} = InfiniteMPO{PEPOSandwich{H,T,O}} +const InfiniteTransferPEPO{H, T <: PEPSTensor, O <: PEPOTensor} = InfiniteMPO{PEPOSandwich{H, T, O}} function InfiniteTransferPEPO( - top::PeriodicArray{T,1}, mid::PeriodicArray{O,2}, bot::PeriodicArray{T,1} -) where {T,O} + top::PeriodicArray{T, 1}, mid::PeriodicArray{O, 2}, bot::PeriodicArray{T, 1} + ) where {T, O} size(top, 1) == size(bot, 1) == size(mid, 1) || throw(ArgumentError("Top PEPS, bottom PEPS and PEPO rows should have length")) - return InfiniteMPO(map(tuple, top, bot, eachslice(mid; dims=2)...)) + return InfiniteMPO(map(tuple, top, bot, eachslice(mid; dims = 2)...)) end InfiniteTransferPEPO(top, mid) = InfiniteTransferPEPO(top, mid, top) @@ -119,8 +119,8 @@ end # Common interface # -const InfiniteTransferMatrix = Union{InfiniteTransferPEPS,InfiniteTransferPEPO} -const MultilineTransferMatrix = Union{MultilineTransferPEPS,MultilineTransferPEPO} +const InfiniteTransferMatrix = Union{InfiniteTransferPEPS, InfiniteTransferPEPO} +const MultilineTransferMatrix = Union{MultilineTransferPEPS, MultilineTransferPEPO} virtualspace(O::InfiniteTransferMatrix, i, dir) = virtualspace(O[i], dir) @@ -141,36 +141,40 @@ virtualspace(O::InfiniteTransferMatrix, i, dir) = virtualspace(O[i], dir) Inialize a boundary MPS for the transfer operator `O` by specifying an array of virtual spaces consistent with the unit cell. """ -function initialize_mps(O::Union{InfiniteTransferMatrix,MultilineTransferMatrix}, arg) # initialize(f=randn, T=scalartype(O), O, ...) +function initialize_mps(O::Union{InfiniteTransferMatrix, MultilineTransferMatrix}, arg) # initialize(f=randn, T=scalartype(O), O, ...) return initialize_mps(randn, scalartype(O), O, arg) end function initialize_mps( - f, T, O::InfiniteTransferMatrix, virtualspaces::AbstractArray{S,1} -) where {S} - return InfiniteMPS([ - f( - T, - virtualspaces[_prev(i, end)] * _elementwise_dual(north_virtualspace(O, i)), - virtualspaces[mod1(i, end)], - ) for i in 1:length(O) - ]) + f, T, O::InfiniteTransferMatrix, virtualspaces::AbstractArray{S, 1} + ) where {S} + return InfiniteMPS( + [ + f( + T, + virtualspaces[_prev(i, end)] * _elementwise_dual(north_virtualspace(O, i)), + virtualspaces[mod1(i, end)], + ) for i in 1:length(O) + ] + ) end function initialize_mps(f, T, O::InfiniteTransferMatrix, χ::Int) - return InfiniteMPS([ - f(T, ℂ^χ * _elementwise_dual(north_virtualspace(O, i)), ℂ^χ) for i in 1:length(O) - ]) + return InfiniteMPS( + [ + f(T, ℂ^χ * _elementwise_dual(north_virtualspace(O, i)), ℂ^χ) for i in 1:length(O) + ] + ) end function initialize_mps( - f, T, O::MultilineTransferMatrix, virtualspaces::AbstractArray{S,2} -) where {S} + f, T, O::MultilineTransferMatrix, virtualspaces::AbstractArray{S, 2} + ) where {S} mpss = map(1:size(O, 1)) do r return initialize_mps(f, T, O[r], virtualspaces[r, :]) end return MPSKit.Multiline(mpss) end function initialize_mps( - f, T, O::MultilineTransferMatrix, virtualspaces::AbstractArray{S,1} -) where {S} + f, T, O::MultilineTransferMatrix, virtualspaces::AbstractArray{S, 1} + ) where {S} return initialize_mps(f, T, O, repeat(virtualspaces, length(O), 1)) end function initialize_mps(f, T, O::MultilineTransferMatrix, V::ElementarySpace) diff --git a/src/states/infinitepartitionfunction.jl b/src/states/infinitepartitionfunction.jl index a558227ab..cec961c62 100644 --- a/src/states/infinitepartitionfunction.jl +++ b/src/states/infinitepartitionfunction.jl @@ -7,17 +7,17 @@ Represents an infinite partition function on a 2D square lattice. $(TYPEDFIELDS) """ -struct InfinitePartitionFunction{T<:PartitionFunctionTensor} +struct InfinitePartitionFunction{T <: PartitionFunctionTensor} A::Matrix{T} - function InfinitePartitionFunction{T}(A::Matrix{T}) where {T<:PartitionFunctionTensor} + function InfinitePartitionFunction{T}(A::Matrix{T}) where {T <: PartitionFunctionTensor} return new{T}(A) end - function InfinitePartitionFunction(A::Matrix{T}) where {T<:PartitionFunctionTensor} + function InfinitePartitionFunction(A::Matrix{T}) where {T <: PartitionFunctionTensor} for (d, w) in Tuple.(CartesianIndices(A)) north_virtualspace(A[d, w]) == south_virtualspace(A[_prev(d, end), w])' || throw( - SpaceMismatch("North virtual space at site $((d, w)) does not match.") - ) + SpaceMismatch("North virtual space at site $((d, w)) does not match.") + ) east_virtualspace(A[d, w]) == west_virtualspace(A[d, _next(w, end)])' || throw(SpaceMismatch("East virtual space at site $((d, w)) does not match.")) dim(space(A[d, w])) > 0 || @warn "no fusion channels at site ($d, $w)" @@ -36,7 +36,7 @@ const InfinitePF{T} = InfinitePartitionFunction{T} Create an `InfinitePartitionFunction` by specifying a matrix containing the PEPS tensors at each site in the unit cell. """ -function InfinitePartitionFunction(A::AbstractMatrix{T}) where {T<:PartitionFunctionTensor} +function InfinitePartitionFunction(A::AbstractMatrix{T}) where {T <: PartitionFunctionTensor} return InfinitePartitionFunction(Array(deepcopy(A))) # TODO: find better way to copy end @@ -50,13 +50,13 @@ of the PEPS tensor at each site in the unit cell as a matrix. Each individual sp specified as either an `Int` or an `ElementarySpace`. """ function InfinitePartitionFunction( - Nspaces::A, Espaces::A -) where {A<:AbstractMatrix{<:ElementarySpaceLike}} + Nspaces::A, Espaces::A + ) where {A <: AbstractMatrix{<:ElementarySpaceLike}} return InfinitePartitionFunction(randn, ComplexF64, Nspaces, Espaces) end function InfinitePartitionFunction( - f, T, Nspaces::M, Espaces::M=Nspaces -) where {M<:AbstractMatrix{<:ElementarySpaceLike}} + f, T, Nspaces::M, Espaces::M = Nspaces + ) where {M <: AbstractMatrix{<:ElementarySpaceLike}} size(Nspaces) == size(Espaces) || throw(ArgumentError("Input spaces should have equal sizes.")) @@ -91,8 +91,8 @@ The unit cell has periodic boundary conditions, so `[r, c]` is indexed modulo th size of the unit cell. """ function InfinitePartitionFunction( - A::T; unitcell::Tuple{Int,Int}=(1, 1) -) where {T<:PartitionFunctionTensor} + A::T; unitcell::Tuple{Int, Int} = (1, 1) + ) where {T <: PartitionFunctionTensor} return InfinitePartitionFunction(fill(A, unitcell)) end @@ -105,15 +105,15 @@ Create an InfinitePartitionFunction by specifying its physical, north and east s Spaces can be specified either via `Int` or via `ElementarySpace`. """ function InfinitePartitionFunction( - Nspace::S, Espace::S=Nspace; unitcell::Tuple{Int,Int}=(1, 1) -) where {S<:ElementarySpaceLike} + Nspace::S, Espace::S = Nspace; unitcell::Tuple{Int, Int} = (1, 1) + ) where {S <: ElementarySpaceLike} return InfinitePartitionFunction( randn, ComplexF64, fill(Nspace, unitcell), fill(Espace, unitcell) ) end function InfinitePartitionFunction( - f, T, Nspace::S, Espace::S=Nspace; unitcell::Tuple{Int,Int}=(1, 1) -) where {S<:ElementarySpaceLike} + f, T, Nspace::S, Espace::S = Nspace; unitcell::Tuple{Int, Int} = (1, 1) + ) where {S <: ElementarySpaceLike} return InfinitePartitionFunction(f, T, fill(Nspace, unitcell), fill(Espace, unitcell)) end @@ -127,8 +127,8 @@ Base.eltype(A::InfinitePartitionFunction) = eltype(typeof(A)) Base.copy(A::InfinitePartitionFunction) = InfinitePartitionFunction(copy(unitcell(A))) function Base.similar( - A::InfinitePartitionFunction, T::Type{TorA}=scalartype(A) -) where {TorA} + A::InfinitePartitionFunction, T::Type{TorA} = scalartype(A) + ) where {TorA} return InfinitePartitionFunction(map(t -> similar(t, T), unitcell(A))) end function Base.repeat(A::InfinitePartitionFunction, counts...) @@ -147,7 +147,7 @@ end ## Spaces -TensorKit.spacetype(::Type{T}) where {T<:InfinitePartitionFunction} = spacetype(eltype(T)) +TensorKit.spacetype(::Type{T}) where {T <: InfinitePartitionFunction} = spacetype(eltype(T)) virtualspace(n::InfinitePartitionFunction, r::Int, c::Int, dir) = virtualspace(n[r, c], dir) ## InfiniteSquareNetwork interface @@ -158,9 +158,9 @@ end ## Vector interface -VI.scalartype(::Type{NT}) where {NT<:InfinitePartitionFunction} = scalartype(eltype(NT)) +VI.scalartype(::Type{NT}) where {NT <: InfinitePartitionFunction} = scalartype(eltype(NT)) function VI.zerovector(A::InfinitePartitionFunction) - InfinitePartitionFunction(zerovector(unitcell(A))) + return InfinitePartitionFunction(zerovector(unitcell(A))) end ## (Approximate) equality @@ -170,8 +170,8 @@ function Base.:(==)(A₁::InfinitePartitionFunction, A₂::InfinitePartitionFunc end end function Base.isapprox( - A₁::InfinitePartitionFunction, A₂::InfinitePartitionFunction; kwargs... -) + A₁::InfinitePartitionFunction, A₂::InfinitePartitionFunction; kwargs... + ) return all(zip(unitcell(A₁), unitcell(A₂))) do (p₁, p₂) return isapprox(p₁, p₂; kwargs...) end diff --git a/src/states/infinitepeps.jl b/src/states/infinitepeps.jl index 06e67cea7..ae7c30aad 100644 --- a/src/states/infinitepeps.jl +++ b/src/states/infinitepeps.jl @@ -7,15 +7,15 @@ Represents an infinite projected entangled-pair state on a 2D square lattice. $(TYPEDFIELDS) """ -struct InfinitePEPS{T<:PEPSTensor} +struct InfinitePEPS{T <: PEPSTensor} A::Matrix{T} - InfinitePEPS{T}(A::Matrix{T}) where {T<:PEPSTensor} = new{T}(A) - function InfinitePEPS(A::Array{T,2}) where {T<:PEPSTensor} + InfinitePEPS{T}(A::Matrix{T}) where {T <: PEPSTensor} = new{T}(A) + function InfinitePEPS(A::Array{T, 2}) where {T <: PEPSTensor} for (d, w) in Tuple.(CartesianIndices(A)) north_virtualspace(A[d, w]) == south_virtualspace(A[_prev(d, end), w])' || throw( - SpaceMismatch("North virtual space at site $((d, w)) does not match.") - ) + SpaceMismatch("North virtual space at site $((d, w)) does not match.") + ) east_virtualspace(A[d, w]) == west_virtualspace(A[d, _next(w, end)])' || throw(SpaceMismatch("East virtual space at site $((d, w)) does not match.")) dim(space(A[d, w])) > 0 || @warn "no fusion channels at site ($d, $w)" @@ -26,7 +26,7 @@ end ## Constructors -const ElementarySpaceLike = Union{Int,ElementarySpace} +const ElementarySpaceLike = Union{Int, ElementarySpace} """ InfinitePEPS(A::AbstractMatrix{T}) @@ -46,13 +46,13 @@ of the PEPS tensor at each site in the unit cell as a matrix. Each individual sp specified as either an `Int` or an `ElementarySpace`. """ function InfinitePEPS( - Pspaces::A, Nspaces::A, Espaces::A -) where {A<:AbstractMatrix{<:ElementarySpaceLike}} + Pspaces::A, Nspaces::A, Espaces::A + ) where {A <: AbstractMatrix{<:ElementarySpaceLike}} return InfinitePEPS(randn, ComplexF64, Pspaces, Nspaces, Espaces) end function InfinitePEPS( - f, T, Pspaces::M, Nspaces::M, Espaces::M=Nspaces -) where {M<:AbstractMatrix{<:ElementarySpaceLike}} + f, T, Pspaces::M, Nspaces::M, Espaces::M = Nspaces + ) where {M <: AbstractMatrix{<:ElementarySpaceLike}} size(Pspaces) == size(Nspaces) == size(Espaces) || throw(ArgumentError("Input spaces should have equal sizes.")) @@ -86,7 +86,7 @@ and column index `[r, c]` by one, respectively: The unit cell has periodic boundary conditions, so `[r, c]` is indexed modulo the size of the unit cell. """ -function InfinitePEPS(A::T; unitcell::Tuple{Int,Int}=(1, 1)) where {T<:PEPSTensor} +function InfinitePEPS(A::T; unitcell::Tuple{Int, Int} = (1, 1)) where {T <: PEPSTensor} return InfinitePEPS(fill(A, unitcell)) end @@ -97,19 +97,16 @@ Create an InfinitePEPS by specifying its physical, north and east spaces and uni Spaces can be specified either via `Int` or via `ElementarySpace`. """ function InfinitePEPS( - Pspace::S, Nspace::S, Espace::S=Nspace; unitcell::Tuple{Int,Int}=(1, 1) -) where {S<:ElementarySpaceLike} + Pspace::S, Nspace::S, Espace::S = Nspace; unitcell::Tuple{Int, Int} = (1, 1) + ) where {S <: ElementarySpaceLike} return InfinitePEPS( - randn, - ComplexF64, - fill(Pspace, unitcell), - fill(Nspace, unitcell), - fill(Espace, unitcell), + randn, ComplexF64, + fill(Pspace, unitcell), fill(Nspace, unitcell), fill(Espace, unitcell), ) end function InfinitePEPS( - f, T, Pspace::S, Nspace::S, Espace::S=Nspace; unitcell::Tuple{Int,Int}=(1, 1) -) where {S<:ElementarySpaceLike} + f, T, Pspace::S, Nspace::S, Espace::S = Nspace; unitcell::Tuple{Int, Int} = (1, 1) + ) where {S <: ElementarySpaceLike} return InfinitePEPS( f, T, fill(Pspace, unitcell), fill(Nspace, unitcell), fill(Espace, unitcell) ) @@ -124,7 +121,7 @@ Base.eltype(::Type{InfinitePEPS{T}}) where {T} = T Base.eltype(A::InfinitePEPS) = eltype(typeof(A)) Base.copy(A::InfinitePEPS) = InfinitePEPS(copy(unitcell(A))) -function Base.similar(A::InfinitePEPS, T::Type{TorA}=scalartype(A)) where {TorA} +function Base.similar(A::InfinitePEPS, T::Type{TorA} = scalartype(A)) where {TorA} return InfinitePEPS(map(t -> similar(t, T), unitcell(A))) end Base.repeat(A::InfinitePEPS, counts...) = InfinitePEPS(repeat(unitcell(A), counts...)) @@ -139,13 +136,13 @@ end ## Spaces -TensorKit.spacetype(::Type{T}) where {T<:InfinitePEPS} = spacetype(eltype(T)) +TensorKit.spacetype(::Type{T}) where {T <: InfinitePEPS} = spacetype(eltype(T)) virtualspace(n::InfinitePEPS, r::Int, c::Int, dir) = virtualspace(n[r, c], dir) physicalspace(n::InfinitePEPS, r::Int, c::Int) = physicalspace(n[r, c]) ## InfiniteSquareNetwork interface -function InfiniteSquareNetwork(top::InfinitePEPS, bot::InfinitePEPS=top) +function InfiniteSquareNetwork(top::InfinitePEPS, bot::InfinitePEPS = top) size(top) == size(bot) || throw( ArgumentError("Top PEPS, bottom PEPS and PEPO rows should have the same length") ) @@ -154,7 +151,7 @@ end ## Vector interface -VI.scalartype(::Type{NT}) where {NT<:InfinitePEPS} = scalartype(eltype(NT)) +VI.scalartype(::Type{NT}) where {NT <: InfinitePEPS} = scalartype(eltype(NT)) VI.zerovector(A::InfinitePEPS) = InfinitePEPS(zerovector(unitcell(A))) function VI.scale(ψ::InfinitePEPS, α::Number) @@ -259,8 +256,8 @@ function ChainRulesCore.rrule(::typeof(Base.getindex), network::InfinitePEPS, ar end function ChainRulesCore.rrule( - ::Type{InfiniteSquareNetwork}, top::InfinitePEPS, bot::InfinitePEPS -) + ::Type{InfiniteSquareNetwork}, top::InfinitePEPS, bot::InfinitePEPS + ) network = InfiniteSquareNetwork(top, bot) function InfiniteSquareNetwork_pullback(Δnetwork_) diff --git a/src/states/infiniteweightpeps.jl b/src/states/infiniteweightpeps.jl index e0f45a589..93f86b4b5 100644 --- a/src/states/infiniteweightpeps.jl +++ b/src/states/infiniteweightpeps.jl @@ -1,11 +1,10 @@ - """ const PEPSWeight Default type for PEPS bond weights with 2 virtual indices, conventionally ordered as: ``wt : WS ← EN``. `WS`, `EN` denote the west/south, east/north spaces for x/y-weights on the square lattice, respectively. """ -const PEPSWeight{T,S} = AbstractTensorMap{T,S,1,1} +const PEPSWeight{T, S} = AbstractTensorMap{T, S, 1, 1} """ struct SUWeight{E<:PEPSWeight} @@ -23,12 +22,12 @@ $(TYPEDFIELDS) SUWeight(wts_mats::AbstractMatrix{E}...) where {E<:PEPSWeight} """ -struct SUWeight{E<:PEPSWeight} - data::Array{E,3} - SUWeight{E}(data::Array{E,3}) where {E} = new{E}(data) +struct SUWeight{E <: PEPSWeight} + data::Array{E, 3} + SUWeight{E}(data::Array{E, 3}) where {E} = new{E}(data) end -function SUWeight(data::Array{E,3}) where {E<:PEPSWeight} +function SUWeight(data::Array{E, 3}) where {E <: PEPSWeight} scalartype(data) <: Real || error("Weight elements must be real numbers.") for wt in data isa(wt, DiagonalTensorMap) || @@ -42,7 +41,7 @@ function SUWeight(data::Array{E,3}) where {E<:PEPSWeight} return SUWeight{E}(data) end -function SUWeight(wts_mats::AbstractMatrix{E}...) where {E<:PEPSWeight} +function SUWeight(wts_mats::AbstractMatrix{E}...) where {E <: PEPSWeight} n_mat = length(wts_mats) Nr, Nc = size(wts_mats[1]) @assert all((Nr, Nc) == size(wts_mat) for wts_mat in wts_mats) @@ -58,7 +57,7 @@ Base.size(W::SUWeight, i) = size(W.data, i) Base.length(W::SUWeight) = length(W.data) Base.eltype(W::SUWeight) = eltype(typeof(W)) Base.eltype(::Type{SUWeight{E}}) where {E} = E -VI.scalartype(::Type{T}) where {T<:SUWeight} = scalartype(eltype(T)) +VI.scalartype(::Type{T}) where {T <: SUWeight} = scalartype(eltype(T)) Base.getindex(W::SUWeight, args...) = Base.getindex(W.data, args...) Base.setindex!(W::SUWeight, args...) = (Base.setindex!(W.data, args...); W) @@ -66,7 +65,7 @@ Base.axes(W::SUWeight, args...) = axes(W.data, args...) Base.iterate(W::SUWeight, args...) = iterate(W.data, args...) ## spaces -TensorKit.spacetype(::Type{T}) where {E,T<:SUWeight{E}} = spacetype(E) +TensorKit.spacetype(::Type{T}) where {E, T <: SUWeight{E}} = spacetype(E) ## (Approximate) equality function Base.:(==)(wts1::SUWeight, wts2::SUWeight) @@ -125,13 +124,13 @@ $(TYPEDFIELDS) InfiniteWeightPEPS([f=randn, T=ComplexF64,] Pspaces::M, Nspaces::M, [Espaces::M]) where {M<:AbstractMatrix{<:Union{Int,ElementarySpace}}} InfiniteWeightPEPS([f=randn, T=ComplexF64,] Pspace::S, Nspace::S, Espace::S=Nspace; unitcell::Tuple{Int,Int}=(1, 1)) where {S<:ElementarySpace} """ -struct InfiniteWeightPEPS{T<:PEPSTensor,E<:PEPSWeight} +struct InfiniteWeightPEPS{T <: PEPSTensor, E <: PEPSWeight} vertices::Matrix{T} weights::SUWeight{E} function InfiniteWeightPEPS( - vertices::Matrix{T}, weights::SUWeight{E} - ) where {T<:PEPSTensor,E<:PEPSWeight} + vertices::Matrix{T}, weights::SUWeight{E} + ) where {T <: PEPSTensor, E <: PEPSWeight} @assert size(vertices) == size(weights)[2:end] Nr, Nc = size(vertices) # check space matching between vertex tensors and weight matrices @@ -147,7 +146,7 @@ struct InfiniteWeightPEPS{T<:PEPSTensor,E<:PEPSWeight} space(weights[1, r, c], 2)' == space(vertices[r, _next(c, Nc)], 5) || throw(SpaceMismatch("East space of bond weight x$((r, c)) does not match.")) end - return new{T,E}(vertices, weights) + return new{T, E}(vertices, weights) end end @@ -158,8 +157,8 @@ Create an InfiniteWeightPEPS from matrices of vertex tensors, and separate matrices of weights on each type of bond at all locations in the unit cell. """ function InfiniteWeightPEPS( - vertices::Matrix{T}, weight_mats::Matrix{E}... -) where {T<:PEPSTensor,E<:PEPSWeight} + vertices::Matrix{T}, weight_mats::Matrix{E}... + ) where {T <: PEPSTensor, E <: PEPSWeight} return InfiniteWeightPEPS(vertices, SUWeight(weight_mats...)) end @@ -172,13 +171,13 @@ Each individual space can be specified as either an `Int` or an `ElementarySpace Bond weights are initialized as identity matrices of element type `Float64`. """ function InfiniteWeightPEPS( - Pspaces::M, Nspaces::M, Espaces::M -) where {M<:AbstractMatrix{<:Union{Int,ElementarySpace}}} + Pspaces::M, Nspaces::M, Espaces::M + ) where {M <: AbstractMatrix{<:Union{Int, ElementarySpace}}} return InfiniteWeightPEPS(randn, ComplexF64, Pspaces, Nspaces, Espaces) end function InfiniteWeightPEPS( - f, T, Pspaces::M, Nspaces::M, Espaces::M=Nspaces -) where {M<:AbstractMatrix{<:Union{Int,ElementarySpace}}} + f, T, Pspaces::M, Nspaces::M, Espaces::M = Nspaces + ) where {M <: AbstractMatrix{<:Union{Int, ElementarySpace}}} @assert all(!isdual, Pspaces) @assert all(!isdual, Nspaces) @assert all(!isdual, Espaces) @@ -198,12 +197,12 @@ Create an InfiniteWeightPEPS by specifying its physical, north and east spaces ( Use `T` to specify the element type of the vertex tensors. Bond weights are initialized as identity matrices of element type `Float64`. """ -function InfiniteWeightPEPS(Pspaces::S, Nspaces::S, Espaces::S) where {S<:ElementarySpace} +function InfiniteWeightPEPS(Pspaces::S, Nspaces::S, Espaces::S) where {S <: ElementarySpace} return InfiniteWeightPEPS(randn, ComplexF64, Pspaces, Nspaces, Espaces) end function InfiniteWeightPEPS( - f, T, Pspace::S, Nspace::S, Espace::S=Nspace; unitcell::Tuple{Int,Int}=(1, 1) -) where {S<:ElementarySpace} + f, T, Pspace::S, Nspace::S, Espace::S = Nspace; unitcell::Tuple{Int, Int} = (1, 1) + ) where {S <: ElementarySpace} return InfiniteWeightPEPS( f, T, fill(Pspace, unitcell), fill(Nspace, unitcell), fill(Espace, unitcell) ) @@ -213,17 +212,12 @@ function Base.size(peps::InfiniteWeightPEPS) return size(peps.vertices) end -TensorKit.spacetype(::Type{T}) where {E,T<:InfiniteWeightPEPS{E}} = spacetype(E) +TensorKit.spacetype(::Type{T}) where {E, T <: InfiniteWeightPEPS{E}} = spacetype(E) function _absorb_weights( - t::PEPSTensor, - weights::SUWeight, - row::Int, - col::Int, - axs::NTuple{N,Int}, - sqrtwts::NTuple{N,Bool}, - invwt::Bool, -) where {N} + t::PEPSTensor, weights::SUWeight, + row::Int, col::Int, axs::NTuple{N, Int}, sqrtwts::NTuple{N, Bool}, invwt::Bool, + ) where {N} Nr, Nc = size(weights)[2:end] @assert 1 <= row <= Nr && 1 <= col <= Nc @assert 1 <= N <= 4 @@ -301,14 +295,14 @@ absorb_weight(t, 2, 3, 2, weights; invwt=true) ``` """ function absorb_weight( - t::PEPSTensor, - row::Int, - col::Int, - ax::Int, - weights::SUWeight; - sqrtwt::Bool=false, - invwt::Bool=false, -) + t::PEPSTensor, + row::Int, + col::Int, + ax::Int, + weights::SUWeight; + sqrtwt::Bool = false, + invwt::Bool = false, + ) return _absorb_weights(t, weights, row, col, (ax,), (sqrtwt,), invwt) end @@ -324,7 +318,7 @@ function InfinitePEPS(peps::InfiniteWeightPEPS) return InfinitePEPS( collect( _absorb_weights(peps.vertices[r, c], peps.weights, r, c, axs, _alltrue, false) - for r in 1:Nr, c in 1:Nc + for r in 1:Nr, c in 1:Nc ), ) end diff --git a/src/utility/diffable_threads.jl b/src/utility/diffable_threads.jl index ff9c96af6..7f2567487 100644 --- a/src/utility/diffable_threads.jl +++ b/src/utility/diffable_threads.jl @@ -6,15 +6,15 @@ Differentiable wrapper around [OhMyThreads.tmap]. All calls of `dtmap` inside of PEPSKit use the threading scheduler stored inside `Defaults.scheduler` which can be modified using `set_scheduler!`. """ -dtmap(args...; scheduler=Defaults.scheduler[]) = tmap(args...; scheduler) +dtmap(args...; scheduler = Defaults.scheduler[]) = tmap(args...; scheduler) -dtmap!!(args...; scheduler=Defaults.scheduler[]) = tmap!(args...; scheduler) +dtmap!!(args...; scheduler = Defaults.scheduler[]) = tmap!(args...; scheduler) # Follows the `map` rrule from ChainRules.jl but specified for the case of one AbstractArray that is being mapped # https://github.com/JuliaDiff/ChainRules.jl/blob/e245d50a1ae56ce46fc8c1f0fe9b925964f1146e/src/rulesets/Base/base.jl#L243 function ChainRulesCore.rrule( - config::RuleConfig{>:HasReverseMode}, ::typeof(dtmap), f, A::AbstractArray; kwargs... -) + config::RuleConfig{>:HasReverseMode}, ::typeof(dtmap), f, A::AbstractArray; kwargs... + ) el_rrules = tmap(A; kwargs...) do a rrule_via_ad(config, f, a) end @@ -36,13 +36,10 @@ function ChainRulesCore.rrule( end function ChainRulesCore.rrule( - config::RuleConfig{>:HasReverseMode}, - ::typeof(dtmap!!), - f, - C′::AbstractArray, - A::AbstractArray; - kwargs..., -) + config::RuleConfig{>:HasReverseMode}, ::typeof(dtmap!!), + f, C′::AbstractArray, A::AbstractArray; + kwargs..., + ) C, dtmap_pullback = rrule(config, dtmap, f, A; kwargs...) function dtmap!!_pullback(dy) dtmap, df, dA = dtmap_pullback(dy) diff --git a/src/utility/hook_pullback.jl b/src/utility/hook_pullback.jl index acfdb0173..e6d281478 100644 --- a/src/utility/hook_pullback.jl +++ b/src/utility/hook_pullback.jl @@ -22,13 +22,13 @@ pullback. See also [`_rrule`](@ref). """ -function hook_pullback(@nospecialize(f), args...; alg_rrule=nothing, kwargs...) +function hook_pullback(@nospecialize(f), args...; alg_rrule = nothing, kwargs...) return f(args...; kwargs...) end function ChainRulesCore.rrule( - config::RuleConfig, ::typeof(hook_pullback), f, args...; alg_rrule=nothing, kwargs... -) + config::RuleConfig, ::typeof(hook_pullback), f, args...; alg_rrule = nothing, kwargs... + ) # Need to add ∂hook_pullback y, f_pullback = _rrule(alg_rrule, config, f, args...; kwargs...) return y, Δ -> (NoTangent(), f_pullback(Δ)...) @@ -45,5 +45,5 @@ the default `alg_rrule=nothing` results in the default AD pullback. No tangent is expected for the `alg_rrule` argument """ function _rrule(::Nothing, config::RuleConfig, f, args...; kwargs...) - rrule_via_ad(config, f, args...; kwargs...) + return rrule_via_ad(config, f, args...; kwargs...) end diff --git a/src/utility/svd.jl b/src/utility/svd.jl index 569dd3c5f..341d58f4b 100644 --- a/src/utility/svd.jl +++ b/src/utility/svd.jl @@ -1,13 +1,6 @@ using TensorKit: - AdjointTensorMap, - SectorDict, - RealOrComplexFloat, - NoTruncation, - TruncationSpace, - _empty_svdtensors, - _compute_svddata!, - _create_svdtensors, - _compute_truncdim, + AdjointTensorMap, SectorDict, RealOrComplexFloat, NoTruncation, TruncationSpace, + _empty_svdtensors, _compute_svddata!, _create_svdtensors, _compute_truncdim, _compute_truncerr const KrylovKitCRCExt = Base.get_extension(KrylovKit, :KrylovKitChainRulesCoreExt) @@ -61,30 +54,30 @@ Construct a `SVDAdjoint` algorithm struct based on the following keyword argumen - `:bicgstab`: BiCGStab iterative linear solver, see the [KrylovKit docs](https://jutho.github.io/KrylovKit.jl/stable/man/algorithms/#KrylovKit.BiCGStab) for details - `:arnoldi`: Arnoldi Krylov algorithm, see the [KrylovKit docs](https://jutho.github.io/KrylovKit.jl/stable/man/algorithms/#KrylovKit.Arnoldi) for details """ -struct SVDAdjoint{F,R} +struct SVDAdjoint{F, R} fwd_alg::F rrule_alg::R end # Keep truncation algorithm separate to be able to specify CTMRG dependent information -const SVD_FWD_SYMBOLS = IdDict{Symbol,Any}( +const SVD_FWD_SYMBOLS = IdDict{Symbol, Any}( :sdd => TensorKit.SDD, :svd => TensorKit.SVD, :iterative => - (; tol=1e-14, krylovdim=25, kwargs...) -> - IterSVD(; alg=GKL(; tol, krylovdim), kwargs...), + (; tol = 1.0e-14, krylovdim = 25, kwargs...) -> + IterSVD(; alg = GKL(; tol, krylovdim), kwargs...), ) -const SVD_RRULE_SYMBOLS = IdDict{Symbol,Type{<:Any}}( +const SVD_RRULE_SYMBOLS = IdDict{Symbol, Type{<:Any}}( :full => FullSVDReverseRule, :gmres => GMRES, :bicgstab => BiCGStab, :arnoldi => Arnoldi ) -function SVDAdjoint(; fwd_alg=(;), rrule_alg=(;)) +function SVDAdjoint(; fwd_alg = (;), rrule_alg = (;)) # parse forward SVD algorithm fwd_algorithm = if fwd_alg isa NamedTuple - fwd_kwargs = (; alg=Defaults.svd_fwd_alg, fwd_alg...) # overwrite with specified kwargs + fwd_kwargs = (; alg = Defaults.svd_fwd_alg, fwd_alg...) # overwrite with specified kwargs haskey(SVD_FWD_SYMBOLS, fwd_kwargs.alg) || throw(ArgumentError("unknown forward algorithm: $(fwd_kwargs.alg)")) fwd_type = SVD_FWD_SYMBOLS[fwd_kwargs.alg] - fwd_kwargs = Base.structdiff(fwd_kwargs, (; alg=nothing)) # remove `alg` keyword argument + fwd_kwargs = Base.structdiff(fwd_kwargs, (; alg = nothing)) # remove `alg` keyword argument fwd_type(; fwd_kwargs...) else fwd_alg @@ -93,11 +86,11 @@ function SVDAdjoint(; fwd_alg=(;), rrule_alg=(;)) # parse reverse-rule SVD algorithm rrule_algorithm = if rrule_alg isa NamedTuple rrule_kwargs = (; - alg=Defaults.svd_rrule_alg, - tol=Defaults.svd_rrule_tol, - krylovdim=Defaults.svd_rrule_min_krylovdim, - broadening=Defaults.svd_rrule_broadening, - verbosity=Defaults.svd_rrule_verbosity, + alg = Defaults.svd_rrule_alg, + tol = Defaults.svd_rrule_tol, + krylovdim = Defaults.svd_rrule_min_krylovdim, + broadening = Defaults.svd_rrule_broadening, + verbosity = Defaults.svd_rrule_verbosity, rrule_alg..., ) # overwrite with specified kwargs @@ -111,11 +104,11 @@ function SVDAdjoint(; fwd_alg=(;), rrule_alg=(;)) end if rrule_type <: FullSVDReverseRule - rrule_kwargs = Base.structdiff(rrule_kwargs, (; alg=nothing, tol=0.0, krylovdim=0)) # remove `alg`, `tol` and `krylovdim` keyword arguments + rrule_kwargs = Base.structdiff(rrule_kwargs, (; alg = nothing, tol = 0.0, krylovdim = 0)) # remove `alg`, `tol` and `krylovdim` keyword arguments else - rrule_kwargs = Base.structdiff(rrule_kwargs, (; alg=nothing, broadening=0.0)) # remove `alg` and `broadening` keyword arguments + rrule_kwargs = Base.structdiff(rrule_kwargs, (; alg = nothing, broadening = 0.0)) # remove `alg` and `broadening` keyword arguments rrule_type <: BiCGStab && - (rrule_kwargs = Base.structdiff(rrule_kwargs, (; krylovdim=nothing))) # BiCGStab doens't take `krylovdim` + (rrule_kwargs = Base.structdiff(rrule_kwargs, (; krylovdim = nothing))) # BiCGStab doens't take `krylovdim` end rrule_type(; rrule_kwargs...) else @@ -134,12 +127,12 @@ depending on the algorithm. E.g., for `IterSVD` the adjoint for a truncated SVD from `KrylovKit.svdsolve` is used. """ PEPSKit.tsvd(t, alg; kwargs...) = PEPSKit.tsvd!(copy(t), alg; kwargs...) -function PEPSKit.tsvd!(t, alg::SVDAdjoint; trunc=NoTruncation(), p::Real=2) +function PEPSKit.tsvd!(t, alg::SVDAdjoint; trunc = NoTruncation(), p::Real = 2) return _tsvd!(t, alg.fwd_alg, trunc, p) end function PEPSKit.tsvd!( - t::AdjointTensorMap, alg::SVDAdjoint; trunc=NoTruncation(), p::Real=2 -) + t::AdjointTensorMap, alg::SVDAdjoint; trunc = NoTruncation(), p::Real = 2 + ) u, s, vt, info = PEPSKit.tsvd!(adjoint(t), alg; trunc, p) return adjoint(vt), adjoint(s), adjoint(u), info end @@ -148,12 +141,12 @@ end # Copy code from TensorKit but additionally return full U, S and V to make compatible with :fixed mode function _tsvd!( - t::TensorMap{<:RealOrComplexFloat}, - alg::Union{TensorKit.SDD,TensorKit.SVD}, - trunc::TruncationScheme, - p::Real, -) - U, S, V⁺, truncerr = TensorKit.tsvd!(t; trunc=NoTruncation(), p, alg) + t::TensorMap{<:RealOrComplexFloat}, + alg::Union{TensorKit.SDD, TensorKit.SVD}, + trunc::TruncationScheme, + p::Real, + ) + U, S, V⁺, truncerr = TensorKit.tsvd!(t; trunc = NoTruncation(), p, alg) if !(trunc isa NoTruncation) && !isempty(blocksectors(t)) Sdata = SectorDict(c => diag(b) for (c, b) in blocks(S)) @@ -171,7 +164,7 @@ function _tsvd!( # construct info NamedTuple condnum = cond(S) info = (; - truncation_error=truncerr, condition_number=condnum, U_full=U, S_full=S, V_full=V⁺ + truncation_error = truncerr, condition_number = condnum, U_full = U, S_full = S, V_full = V⁺, ) return Ũ, S̃, Ṽ⁺, info end @@ -188,7 +181,7 @@ U, S, and V and, potentially, the full decompositions if the adjoints needs acce $(TYPEDFIELDS) """ -struct FixedSVD{Ut,St,Vt,Utf,Stf,Vtf} +struct FixedSVD{Ut, St, Vt, Utf, Stf, Vtf} U::Ut S::St V::Vt @@ -209,11 +202,11 @@ end # Return pre-computed SVD function _tsvd!(_, alg::FixedSVD, ::TruncationScheme, ::Real) info = (; - truncation_error=0, - condition_number=cond(alg.S), - U_full=alg.U_full, - S_full=alg.S_full, - V_full=alg.V_full, + truncation_error = 0, + condition_number = cond(alg.S), + U_full = alg.U_full, + S_full = alg.S_full, + V_full = alg.V_full, ) return alg.U, alg.S, alg.V, info end @@ -242,7 +235,7 @@ Construct an `IterSVD` algorithm struct based on the following keyword arguments * `start_vector=random_start_vector` : Function providing the initial vector for the iterative SVD algorithm. """ @kwdef struct IterSVD - alg::KrylovKit.GKL = KrylovKit.GKL(; tol=1e-14, krylovdim=25) + alg::KrylovKit.GKL = KrylovKit.GKL(; tol = 1.0e-14, krylovdim = 25) fallback_threshold::Float64 = Inf start_vector = random_start_vector end @@ -267,17 +260,17 @@ function _tsvd!(f, alg::IterSVD, trunc::TruncationScheme, p::Real) # construct info NamedTuple condition_number = cond(S) info = (; - truncation_error, condition_number, U_full=nothing, S_full=nothing, V_full=nothing + truncation_error, condition_number, U_full = nothing, S_full = nothing, V_full = nothing, ) return U, S, V, info end function TensorKit._compute_svddata!( - f, alg::IterSVD, trunc::Union{NoTruncation,TruncationSpace} -) + f, alg::IterSVD, trunc::Union{NoTruncation, TruncationSpace} + ) InnerProductStyle(f) === EuclideanInnerProduct() || throw_invalid_innerproduct(:full!) I = sectortype(f) - dims = SectorDict{I,Int}() + dims = SectorDict{I, Int}() sectors = trunc isa NoTruncation ? blocksectors(f) : blocksectors(trunc.space) generator = Base.Iterators.map(sectors) do c @@ -302,7 +295,7 @@ function TensorKit._compute_svddata!( V = V[1:howmany, :] else # Slice in case more values were converged than requested U = stack(view(lvecs, 1:howmany)) - V = stack(conj, view(rvecs, 1:howmany); dims=1) + V = stack(conj, view(rvecs, 1:howmany); dims = 1) end end @@ -319,12 +312,12 @@ end # TensorKit.tsvd! rrule with info NamedTuple return value function ChainRulesCore.rrule( - ::typeof(PEPSKit.tsvd!), - t::AbstractTensorMap, - alg::SVDAdjoint{F,R}; - trunc::TruncationScheme=TensorKit.NoTruncation(), - p::Real=2, -) where {F,R<:FullSVDReverseRule} + ::typeof(PEPSKit.tsvd!), + t::AbstractTensorMap, + alg::SVDAdjoint{F, R}; + trunc::TruncationScheme = TensorKit.NoTruncation(), + p::Real = 2, + ) where {F, R <: FullSVDReverseRule} @assert !(alg.fwd_alg isa IterSVD) "IterSVD is not compatible with tsvd reverse-rule" Ũ, S̃, Ṽ⁺, info = tsvd(t, alg; trunc, p) U, S, V⁺ = info.U_full, info.S_full, info.V_full # untruncated SVD decomposition @@ -350,14 +343,14 @@ function ChainRulesCore.rrule( ΔUc, ΔSdc, ΔV⁺c; - tol=pullback_tol, - broadening=alg.rrule_alg.broadening, - verbosity=alg.rrule_alg.verbosity, + tol = pullback_tol, + broadening = alg.rrule_alg.broadening, + verbosity = alg.rrule_alg.verbosity, ) end return NoTangent(), Δt, NoTangent() end - function tsvd!_nothing_pullback(::Tuple{ZeroTangent,ZeroTangent,ZeroTangent}) + function tsvd!_nothing_pullback(::Tuple{ZeroTangent, ZeroTangent, ZeroTangent}) return NoTangent(), ZeroTangent(), NoTangent() end @@ -366,18 +359,18 @@ end # KrylovKit rrule compatible with TensorMaps & function handles function ChainRulesCore.rrule( - ::typeof(PEPSKit.tsvd!), - f, - alg::SVDAdjoint{F,R}; - trunc::TruncationScheme=notrunc(), - p::Real=2, -) where {F,R<:Union{GMRES,BiCGStab,Arnoldi}} + ::typeof(PEPSKit.tsvd!), + f, + alg::SVDAdjoint{F, R}; + trunc::TruncationScheme = notrunc(), + p::Real = 2, + ) where {F, R <: Union{GMRES, BiCGStab, Arnoldi}} U, S, V, info = tsvd(f, alg; trunc, p) # update rrule_alg tolerance to be compatible with smallest singular value rrule_alg = alg.rrule_alg smallest_sval = minimum(((_, b),) -> minimum(diag(b)), blocks(S)) - proper_tol = clamp(rrule_alg.tol, eps(scalartype(S))^(3 / 4), 1e-2 * smallest_sval) + proper_tol = clamp(rrule_alg.tol, eps(scalartype(S))^(3 / 4), 1.0e-2 * smallest_sval) rrule_alg = @set rrule_alg.tol = proper_tol function tsvd!_itersvd_pullback(ΔUSVi) @@ -396,7 +389,7 @@ function ChainRulesCore.rrule( # Dummy objects only used for warnings minimal_info = KrylovKit.ConvergenceInfo(n_vals, nothing, nothing, -1, -1) # Only num. converged is used - minimal_alg = GKL(; tol=rrule_alg.tol, verbosity=1) # Tolerance is used for gauge sensitivity, verbosity is used for warnings + minimal_alg = GKL(; tol = rrule_alg.tol, verbosity = 1) # Tolerance is used for gauge sensitivity, verbosity is used for warnings if ΔUc isa AbstractZero && ΔVc isa AbstractZero # Handle ZeroTangent singular vectors Δlvecs = fill(ZeroTangent(), n_vals) @@ -428,7 +421,7 @@ function ChainRulesCore.rrule( end return NoTangent(), Δf, NoTangent() end - function tsvd!_itersvd_pullback(::Tuple{ZeroTangent,ZeroTangent,ZeroTangent}) + function tsvd!_itersvd_pullback(::Tuple{ZeroTangent, ZeroTangent, ZeroTangent}) return NoTangent(), ZeroTangent(), NoTangent() end @@ -439,7 +432,7 @@ end _safe_inv(x, tol) = abs(x) < tol ? zero(x) : inv(x) # compute inverse singular value difference contribution to SVD gradient with broadening ε -function _broadened_inv_S(S::AbstractVector{T}, tol, ε=0) where {T} +function _broadened_inv_S(S::AbstractVector{T}, tol, ε = 0) where {T} F = similar(S, (axes(S, 1), axes(S, 1))) @inbounds for j in axes(F, 2), i in axes(F, 1) F[i, j] = if i == j @@ -454,7 +447,7 @@ end # Lorentzian broadening for divergent term in SVD rrule, see # https://journals.aps.org/prresearch/abstract/10.1103/PhysRevResearch.7.013237 -function _lorentz_broaden(x, ε=eps(real(scalartype(x)))^(3 / 4)) +function _lorentz_broaden(x, ε = eps(real(scalartype(x)))^(3 / 4)) return x / (x^2 + ε) end @@ -471,7 +464,7 @@ end # # Arguments are U, S and Vd of full (non-truncated, but still thin) SVD, as well as # cotangent ΔU, ΔS, ΔVd variables of truncated SVD -# +# # Checks whether the cotangent variables are such that they would couple to gauge-dependent # degrees of freedom (phases of singular vectors), and prints a warning if this is the case # @@ -482,17 +475,17 @@ end # no scalar indexing, lots of broadcasting and views # function svd_pullback!( - ΔA::AbstractMatrix, - U::AbstractMatrix, - S::AbstractVector, - Vd::AbstractMatrix, - ΔU, - ΔS, - ΔVd; - tol::Real=_default_pullback_gaugetol(S), - broadening::Real=0, - verbosity=1, -) + ΔA::AbstractMatrix, + U::AbstractMatrix, + S::AbstractVector, + Vd::AbstractMatrix, + ΔU, + ΔS, + ΔVd; + tol::Real = _default_pullback_gaugetol(S), + broadening::Real = 0, + verbosity = 1, + ) # Basic size checks and determination m, n = size(U, 1), size(Vd, 2) @@ -522,7 +515,7 @@ function svd_pullback!( Sp = view(S, 1:p) # rank - r = searchsortedlast(S, tol; rev=true) + r = searchsortedlast(S, tol; rev = true) # compute antihermitian part of projection of ΔU and ΔV onto U and V # also already subtract this projection from ΔU and ΔV @@ -589,13 +582,13 @@ function svd_pullback!( VrΔV = fill!(similar(Vd, (r - p, p)), 0) end - X = @. (1//2) * ( + X = @. (1 // 2) * ( (UrΔU + VrΔV) * _safe_inv(Sp' - Sr, tol) + - (UrΔU - VrΔV) * _safe_inv(Sp' + Sr, tol) + (UrΔU - VrΔV) * _safe_inv(Sp' + Sr, tol) ) - Y = @. (1//2) * ( + Y = @. (1 // 2) * ( (UrΔU + VrΔV) * _safe_inv(Sp' - Sr, tol) - - (UrΔU - VrΔV) * _safe_inv(Sp' + Sr, tol) + (UrΔU - VrΔV) * _safe_inv(Sp' + Sr, tol) ) # ΔA += Ur * X * Vp' + Up * Y' * Vr' diff --git a/src/utility/symmetrization.jl b/src/utility/symmetrization.jl index 5bde3ea92..7a1a92193 100644 --- a/src/utility/symmetrization.jl +++ b/src/utility/symmetrization.jl @@ -55,8 +55,8 @@ end # this is definitely not what you would want to do, but it circumvents having to think # about what hermiticity means at the level of transfer operators, which is something function _fit_spaces( - y::AbstractTensorMap{T,S,N₁,N₂}, x::AbstractTensorMap{T,S,N₁,N₂} -) where {T,S<:IndexSpace,N₁,N₂} + y::AbstractTensorMap{T, S, N₁, N₂}, x::AbstractTensorMap{T, S, N₁, N₂} + ) where {T, S <: IndexSpace, N₁, N₂} for i in 1:(N₁ + N₂) if space(x, i) ≠ space(y, i) f = unitary(space(x, i) ← space(y, i)) @@ -70,11 +70,11 @@ function _fit_spaces( end _fit_spaces(y::InfinitePEPS, x::InfinitePEPS) = InfinitePEPS(map(_fit_spaces, y.A, x.A)) -function herm_depth_inv(x::Union{PEPSTensor,PEPOTensor}) +function herm_depth_inv(x::Union{PEPSTensor, PEPOTensor}) return 0.5 * (x + _fit_spaces(herm_depth(x), x)) end -function herm_width_inv(x::Union{PEPSTensor,PEPOTensor}) +function herm_width_inv(x::Union{PEPSTensor, PEPOTensor}) return 0.5 * (x + _fit_spaces(herm_width(x), x)) end @@ -87,9 +87,9 @@ end function rot_inv(x) return 0.25 * ( x + - _fit_spaces(rotl90(x), x) + - _fit_spaces(rot180(x), x) + - _fit_spaces(rotr90(x), x) + _fit_spaces(rotl90(x), x) + + _fit_spaces(rot180(x), x) + + _fit_spaces(rotr90(x), x) ) end diff --git a/src/utility/util.jl b/src/utility/util.jl index acb96246f..4cfdb2541 100644 --- a/src/utility/util.jl +++ b/src/utility/util.jl @@ -52,15 +52,15 @@ _safe_pow(a::Number, pow::Real, tol::Real) = (pow < 0 && abs(a) < tol) ? zero(a) Compute `s^pow` for a diagonal matrix `s`. """ -function sdiag_pow(s::DiagonalTensorMap, pow::Real; tol::Real=eps(scalartype(s))^(3 / 4)) +function sdiag_pow(s::DiagonalTensorMap, pow::Real; tol::Real = eps(scalartype(s))^(3 / 4)) # Relative tol w.r.t. largest singular value (use norm(∘, Inf) to make differentiable) tol *= norm(s, Inf) spow = DiagonalTensorMap(_safe_pow.(s.data, pow, tol), space(s, 1)) return spow end function sdiag_pow( - s::AbstractTensorMap{T,S,1,1}, pow::Real; tol::Real=eps(scalartype(s))^(3 / 4) -) where {T,S} + s::AbstractTensorMap{T, S, 1, 1}, pow::Real; tol::Real = eps(scalartype(s))^(3 / 4) + ) where {T, S} # Relative tol w.r.t. largest singular value (use norm(∘, Inf) to make differentiable) tol *= norm(s, Inf) spow = similar(s) @@ -73,11 +73,9 @@ function sdiag_pow( end function ChainRulesCore.rrule( - ::typeof(sdiag_pow), - s::AbstractTensorMap, - pow::Real; - tol::Real=eps(scalartype(s))^(3 / 4), -) + ::typeof(sdiag_pow), s::AbstractTensorMap, pow::Real; + tol::Real = eps(scalartype(s))^(3 / 4), + ) tol *= norm(s, Inf) spow = sdiag_pow(s, pow; tol) spow_minus1_conj = scale!(sdiag_pow(s', pow - 1; tol), pow) @@ -138,7 +136,7 @@ Fermionic supertrace by using `@tensor`. """ str(t::AbstractTensorMap) = _str(BraidingStyle(sectortype(t)), t) _str(::Bosonic, t::AbstractTensorMap) = tr(t) -@generated function _str(::Fermionic, t::AbstractTensorMap{<:Any,<:Any,N,N}) where {N} +@generated function _str(::Fermionic, t::AbstractTensorMap{<:Any, <:Any, N, N}) where {N} tex = tensorexpr(:t, ntuple(identity, N), ntuple(identity, N)) return macroexpand(@__MODULE__, :(@tensor $tex)) end @@ -149,8 +147,8 @@ end Compute `tr(H * ρ)` without forming `H * ρ`. """ @generated function trmul( - H::AbstractTensorMap{<:Any,S,N,N}, ρ::AbstractTensorMap{<:Any,S,N,N} -) where {S,N} + H::AbstractTensorMap{<:Any, S, N, N}, ρ::AbstractTensorMap{<:Any, S, N, N} + ) where {S, N} Hex = tensorexpr(:H, ntuple(identity, N), ntuple(i -> i + N, N)) ρex = tensorexpr(:ρ, ntuple(i -> i + N, N), ntuple(identity, N)) return macroexpand(@__MODULE__, :(@tensor $Hex * $ρex)) @@ -158,8 +156,8 @@ end # Check whether diagonals contain degenerate values up to absolute or relative tolerance function is_degenerate_spectrum( - S; atol::Real=0, rtol::Real=atol > 0 ? 0 : sqrt(eps(scalartype(S))) -) + S; atol::Real = 0, rtol::Real = atol > 0 ? 0 : sqrt(eps(scalartype(S))) + ) for (_, b) in blocks(S) s = real(diag(b)) for i in 1:(length(s) - 1) @@ -234,7 +232,7 @@ function ChainRulesCore.rrule(::typeof(_setindex), a::AbstractArray, tv, args... end end return ( - NoTangent(), backwards_a, backwards_tv, fill(ZeroTangent(), length(args))... + NoTangent(), backwards_a, backwards_tv, fill(ZeroTangent(), length(args))..., ) end return t, _setindex_pullback diff --git a/test/bondenv/benv_fu.jl b/test/bondenv/benv_fu.jl index 52431a855..7e444bb7e 100644 --- a/test/bondenv/benv_fu.jl +++ b/test/bondenv/benv_fu.jl @@ -8,12 +8,12 @@ using Random Random.seed!(100) Nr, Nc = 2, 2 # create Hubbard iPEPS using simple update -function get_hubbard_state(t::Float64=1.0, U::Float64=8.0) - H = hubbard_model(ComplexF64, Trivial, U1Irrep, InfiniteSquare(Nr, Nc); t, U, mu=U / 2) - Vphy = Vect[FermionParity ⊠ U1Irrep]((0, 0) => 2, (1, 1//2) => 1, (1, -1//2) => 1) - wpeps = InfiniteWeightPEPS(rand, ComplexF64, Vphy, Vphy; unitcell=(Nr, Nc)) - alg = SimpleUpdate(1e-2, 1e-8, 10000, truncerr(1e-10) & truncdim(4)) - wpeps, = simpleupdate(wpeps, H, alg; bipartite=false, check_interval=2000) +function get_hubbard_state(t::Float64 = 1.0, U::Float64 = 8.0) + H = hubbard_model(ComplexF64, Trivial, U1Irrep, InfiniteSquare(Nr, Nc); t, U, mu = U / 2) + Vphy = Vect[FermionParity ⊠ U1Irrep]((0, 0) => 2, (1, 1 // 2) => 1, (1, -1 // 2) => 1) + wpeps = InfiniteWeightPEPS(rand, ComplexF64, Vphy, Vphy; unitcell = (Nr, Nc)) + alg = SimpleUpdate(1.0e-2, 1.0e-8, 10000, truncerr(1.0e-10) & truncdim(4)) + wpeps, = simpleupdate(wpeps, H, alg; bipartite = false, check_interval = 2000) peps = InfinitePEPS(wpeps) normalize!.(peps.A, Inf) return peps @@ -22,9 +22,9 @@ end peps = get_hubbard_state() # calculate CTMRG environment Envspace = Vect[FermionParity ⊠ U1Irrep]( - (0, 0) => 4, (1, 1//2) => 1, (1, -1//2) => 1, (0, 1) => 1, (0, -1) => 1 + (0, 0) => 4, (1, 1 // 2) => 1, (1, -1 // 2) => 1, (0, 1) => 1, (0, -1) => 1 ) -ctm_alg = SequentialCTMRG(; tol=1e-10, verbosity=2, trscheme=truncerr(1e-10) & truncdim(8)) +ctm_alg = SequentialCTMRG(; tol = 1.0e-10, verbosity = 2, trscheme = truncerr(1.0e-10) & truncdim(8)) env, = leading_boundary(CTMRGEnv(rand, ComplexF64, peps, Envspace), peps, ctm_alg) for row in 1:Nr, col in 1:Nc cp1 = PEPSKit._next(col, Nc) @@ -33,7 +33,7 @@ for row in 1:Nr, col in 1:Nc benv = PEPSKit.bondenv_fu(row, col, X, Y, env) @assert [isdual(space(benv, ax)) for ax in 1:numind(benv)] == [0, 0, 1, 1] Z = PEPSKit.positive_approx(benv) - # verify that gauge fixing can greatly reduce + # verify that gauge fixing can greatly reduce # condition number for physical state bond envs cond1 = cond(Z' * Z) Z2, a2, b2, (Linv, Rinv) = PEPSKit.fixgauge_benv(Z, a, b) diff --git a/test/bondenv/bond_truncate.jl b/test/bondenv/bond_truncate.jl index 33225a635..f7c31e1a3 100644 --- a/test/bondenv/bond_truncate.jl +++ b/test/bondenv/bond_truncate.jl @@ -9,7 +9,7 @@ using KrylovKit Random.seed!(0) maxiter = 500 check_interval = 20 -trscheme = truncerr(1e-10) & truncdim(8) +trscheme = truncerr(1.0e-10) & truncdim(8) Vext = Vect[FermionParity](0 => 100, 1 => 100) Vint = Vect[FermionParity](0 => 6, 1 => 6) Vphy = Vect[FermionParity](0 => 1, 1 => 2) @@ -24,15 +24,15 @@ for Vbondl in (Vint, Vint'), Vbondr in (Vint, Vint') a2, s, b2 = tsvd(a2b2, perm_ab) a2, b2 = PEPSKit.absorb_s(a2, s, b2) # bond tensor (truncated SVD initialization) - a0, s, b0 = tsvd(a2b2, perm_ab; trunc=trscheme) + a0, s, b0 = tsvd(a2b2, perm_ab; trunc = trscheme) a0, b0 = PEPSKit.absorb_s(a0, s, b0) fid0 = PEPSKit.fidelity(benv, PEPSKit._combine_ab(a0, b0), a2b2) @info "Fidelity of simple SVD truncation = $fid0.\n" - ss = Dict{String,DiagonalTensorMap}() + ss = Dict{String, DiagonalTensorMap}() for (label, alg) in ( - ("ALS", ALSTruncation(; trscheme, maxiter, check_interval)), - ("FET", FullEnvTruncation(; trscheme, maxiter, check_interval, trunc_init=false)), - ) + ("ALS", ALSTruncation(; trscheme, maxiter, check_interval)), + ("FET", FullEnvTruncation(; trscheme, maxiter, check_interval, trunc_init = false)), + ) a1, ss[label], b1, info = PEPSKit.bond_truncate(a2, b2, benv, alg) @info "$label improved fidelity = $(info.fid)." display(ss[label]) @@ -40,5 +40,5 @@ for Vbondl in (Vint, Vint'), Vbondr in (Vint, Vint') @test info.fid ≈ PEPSKit.fidelity(benv, PEPSKit._combine_ab(a1, b1), a2b2) @test info.fid > fid0 end - @test isapprox(ss["ALS"], ss["FET"], atol=1e-3) + @test isapprox(ss["ALS"], ss["FET"], atol = 1.0e-3) end diff --git a/test/boundarymps/vumps.jl b/test/boundarymps/vumps.jl index 235660c90..48d577bc1 100644 --- a/test/boundarymps/vumps.jl +++ b/test/boundarymps/vumps.jl @@ -8,7 +8,7 @@ using LinearAlgebra Random.seed!(29384293742893) const vumps_alg = VUMPS(; - tol=1e-6, alg_eigsolve=MPSKit.Defaults.alg_eigsolve(; ishermitian=false), verbosity=2 + tol = 1.0e-6, alg_eigsolve = MPSKit.Defaults.alg_eigsolve(; ishermitian = false), verbosity = 2 ) @testset "(1, 1) PEPS" begin @@ -20,19 +20,19 @@ const vumps_alg = VUMPS(; mps, env, ϵ = leading_boundary(mps, T, vumps_alg) N = abs(sum(expectation_value(mps, T))) - mps2, = changebonds(mps, T, OptimalExpand(; trscheme=truncdim(30))) + mps2, = changebonds(mps, T, OptimalExpand(; trscheme = truncdim(30))) mps2, env2, ϵ = leading_boundary(mps2, T, vumps_alg) N2 = abs(sum(expectation_value(mps2, T))) - @test N ≈ N2 rtol = 1e-2 + @test N ≈ N2 rtol = 1.0e-2 ctm, = leading_boundary(CTMRGEnv(psi, ComplexSpace(20)), psi) N´ = abs(norm(psi, ctm)) - @test N ≈ N´ atol = 1e-3 + @test N ≈ N´ atol = 1.0e-3 end @testset "(2, 2) PEPS" begin - psi = InfinitePEPS(ComplexSpace(2), ComplexSpace(2); unitcell=(2, 2)) + psi = InfinitePEPS(ComplexSpace(2), ComplexSpace(2); unitcell = (2, 2)) T = PEPSKit.MultilineTransferPEPS(psi, 1) mps = initialize_mps(rand, scalartype(T), T, fill(ComplexSpace(20), 2, 2)) @@ -42,7 +42,7 @@ end ctm, = leading_boundary(CTMRGEnv(psi, ComplexSpace(20)), psi) N´ = abs(norm(psi, ctm)) - @test N ≈ N´ rtol = 1e-2 + @test N ≈ N´ rtol = 1.0e-2 end @testset "Fermionic PEPS" begin @@ -50,7 +50,7 @@ end d = Vect[fℤ₂](0 => 1, 1 => 1) χ = Vect[fℤ₂](0 => 10, 1 => 10) - psi = InfinitePEPS(D, d; unitcell=(1, 1)) + psi = InfinitePEPS(D, d; unitcell = (1, 1)) n = InfiniteSquareNetwork(psi) T = InfiniteTransferPEPS(psi, 1, 1) @@ -62,7 +62,7 @@ end ctm, = leading_boundary(CTMRGEnv(psi, χ), psi) N_ctm = abs(norm(psi, ctm)) - @test N_vumps ≈ N_ctm rtol = 1e-2 + @test N_vumps ≈ N_ctm rtol = 1.0e-2 # and again after blocking the local sandwiches n´ = InfiniteSquareNetwork(map(PEPSKit.mpotensor, PEPSKit.unitcell(n))) @@ -76,12 +76,12 @@ end N_ctm´ = abs(network_value(n´, ctm´)) @show N_vumps´ - @test N_vumps´ ≈ N_vumps rtol = 1e-2 - @test N_vumps´ ≈ N_ctm´ rtol = 1e-2 + @test N_vumps´ ≈ N_vumps rtol = 1.0e-2 + @test N_vumps´ ≈ N_ctm´ rtol = 1.0e-2 end @testset "PEPO runthrough" begin - function ising_pepo(beta; unitcell=(1, 1, 1)) + function ising_pepo(beta; unitcell = (1, 1, 1)) t = ComplexF64[exp(beta) exp(-beta); exp(-beta) exp(beta)] q = sqrt(t) @@ -89,13 +89,7 @@ end O[1, 1, 1, 1, 1, 1] = 1 O[2, 2, 2, 2, 2, 2] = 1 @tensor o[-1 -2; -3 -4 -5 -6] := - O[1 2; 3 4 5 6] * - q[-1; 1] * - q[-2; 2] * - q[-3; 3] * - q[-4; 4] * - q[-5; 5] * - q[-6; 6] + O[1 2; 3 4 5 6] * q[-1; 1] * q[-2; 2] * q[-3; 3] * q[-4; 4] * q[-5; 5] * q[-6; 6] O = TensorMap(o, ℂ^2 ⊗ (ℂ^2)' ← ℂ^2 ⊗ ℂ^2 ⊗ (ℂ^2)' ⊗ (ℂ^2)') diff --git a/test/ctmrg/correlation_length.jl b/test/ctmrg/correlation_length.jl index 84d5a2d12..f3dcf73e7 100644 --- a/test/ctmrg/correlation_length.jl +++ b/test/ctmrg/correlation_length.jl @@ -6,18 +6,18 @@ using PEPSKit: CTMRGEnv, InfinitePEPS @testset "Correlation length" begin # regression test for https://github.com/QuantumKitHub/PEPSKit.jl/issues/197 - vD = Vect[SU2Irrep](1//2 => 1) + vD = Vect[SU2Irrep](1 // 2 => 1) vd = Vect[SU2Irrep](2 => 1) tAKLT_A = ones(vd ← vD ⊗ vD ⊗ vD ⊗ vD) tAKLT_B = permute(adjoint(tAKLT_A), ((5,), (1, 2, 3, 4))) ψ = InfinitePEPS([tAKLT_A tAKLT_B; tAKLT_B tAKLT_A]) - trscheme = truncbelow(1e-12) & truncdim(48) - boundary_alg = (; tol=1e-10, trscheme=trscheme, maxiter=400, verbosity=3) + trscheme = truncbelow(1.0e-12) & truncdim(48) + boundary_alg = (; tol = 1.0e-10, trscheme = trscheme, maxiter = 400, verbosity = 3) env0 = CTMRGEnv(randn, Float64, ψ, oneunit(vD)) env, info_ctmrg = leading_boundary(env0, ψ; boundary_alg...) - ξ_h, ξ_v, λ_h, λ_v = correlation_length(ψ, env; sector=SU2Irrep(1)) + ξ_h, ξ_v, λ_h, λ_v = correlation_length(ψ, env; sector = SU2Irrep(1)) @test ξ_h isa Vector{Float64} @test size(ξ_h) == (2,) @test all(isfinite.(ξ_h)) @@ -30,6 +30,6 @@ using PEPSKit: CTMRGEnv, InfinitePEPS # AKLT state should have correlation length ~ 2sites # https://journals.aps.org/prb/abstract/10.1103/PhysRevB.96.121115 - @test all(x -> isapprox(x * size(ψ, 2), 2; atol=0.1), ξ_h) - @test all(x -> isapprox(x * size(ψ, 1), 2; atol=0.1), ξ_v) + @test all(x -> isapprox(x * size(ψ, 2), 2; atol = 0.1), ξ_h) + @test all(x -> isapprox(x * size(ψ, 1), 2; atol = 0.1), ξ_v) end diff --git a/test/ctmrg/fixed_iterscheme.jl b/test/ctmrg/fixed_iterscheme.jl index afa3c67ea..dbf4b5ba5 100644 --- a/test/ctmrg/fixed_iterscheme.jl +++ b/test/ctmrg/fixed_iterscheme.jl @@ -17,17 +17,17 @@ using PEPSKit: # initialize parameters χbond = 2 χenv = 16 -svd_algs = [SVDAdjoint(; fwd_alg=TensorKit.SDD()), SVDAdjoint(; fwd_alg=IterSVD())] +svd_algs = [SVDAdjoint(; fwd_alg = TensorKit.SDD()), SVDAdjoint(; fwd_alg = IterSVD())] projector_algs = [:halfinfinite] #, :fullinfinite] unitcells = [(1, 1), (3, 4)] -atol = 1e-5 +atol = 1.0e-5 # test for element-wise convergence after application of fixed step @testset "$unitcell unit cell with $(typeof(svd_alg.fwd_alg)) and $projector_alg" for ( - unitcell, svd_alg, projector_alg -) in Iterators.product( - unitcells, svd_algs, projector_algs -) + unitcell, svd_alg, projector_alg, + ) in Iterators.product( + unitcells, svd_algs, projector_algs + ) ctm_alg = SimultaneousCTMRG(; svd_alg, projector_alg) # initialize states @@ -55,10 +55,10 @@ end @testset "Element-wise consistency of TensorKit.SDD and IterSVD" begin ctm_alg_iter = SimultaneousCTMRG(; - maxiter=200, - svd_alg=SVDAdjoint(; fwd_alg=IterSVD(; alg=GKL(; tol=1e-14, krylovdim=χenv + 10))), + maxiter = 200, + svd_alg = SVDAdjoint(; fwd_alg = IterSVD(; alg = GKL(; tol = 1.0e-14, krylovdim = χenv + 10))), ) - ctm_alg_full = SimultaneousCTMRG(; svd_alg=SVDAdjoint(; fwd_alg=TensorKit.SDD())) + ctm_alg_full = SimultaneousCTMRG(; svd_alg = SVDAdjoint(; fwd_alg = TensorKit.SDD())) # initialize states Random.seed!(91283219347) diff --git a/test/ctmrg/flavors.jl b/test/ctmrg/flavors.jl index 590f43033..b7605b769 100644 --- a/test/ctmrg/flavors.jl +++ b/test/ctmrg/flavors.jl @@ -11,21 +11,19 @@ unitcells = [(1, 1), (3, 4)] projector_algs = [:halfinfinite, :fullinfinite] @testset "$(unitcell) unit cell with $projector_alg" for (unitcell, projector_alg) in - Iterators.product( - unitcells, projector_algs -) + Iterators.product(unitcells, projector_algs) # compute environments Random.seed!(32350283290358) psi = InfinitePEPS(2, χbond; unitcell) env_sequential, = leading_boundary( - CTMRGEnv(psi, ComplexSpace(χenv)), psi; alg=:sequential, projector_alg + CTMRGEnv(psi, ComplexSpace(χenv)), psi; alg = :sequential, projector_alg ) env_simultaneous, = leading_boundary( - CTMRGEnv(psi, ComplexSpace(χenv)), psi; alg=:simultaneous, projector_alg + CTMRGEnv(psi, ComplexSpace(χenv)), psi; alg = :simultaneous, projector_alg ) # compare norms - @test abs(norm(psi, env_sequential)) ≈ abs(norm(psi, env_simultaneous)) rtol = 1e-6 + @test abs(norm(psi, env_sequential)) ≈ abs(norm(psi, env_simultaneous)) rtol = 1.0e-6 # compare singular values CS_sequential = map(c -> tsvd(c)[2], env_sequential.corners) @@ -36,7 +34,7 @@ projector_algs = [:halfinfinite, :fullinfinite] e_new = isometry(MPSKit._firstspace(c_as), smallest) return norm(e_new' * c_as * e_new - e_old' * c_lm * e_old) end - @test ΔCS < 1e-2 + @test ΔCS < 1.0e-2 TS_sequential = map(t -> tsvd(t)[2], env_sequential.edges) TS_simultaneous = map(t -> tsvd(t)[2], env_simultaneous.edges) @@ -44,26 +42,24 @@ projector_algs = [:halfinfinite, :fullinfinite] MPSKit._firstspace(t_lm) == MPSKit._firstspace(t_as) || return scalartype(t_lm)(Inf) return norm(t_as - t_lm) end - @test ΔTS < 1e-2 + @test ΔTS < 1.0e-2 # compare Heisenberg energies H = heisenberg_XYZ(InfiniteSquare(unitcell...)) E_sequential = cost_function(psi, env_sequential, H) E_simultaneous = cost_function(psi, env_simultaneous, H) - @test E_sequential ≈ E_simultaneous rtol = 1e-3 + @test E_sequential ≈ E_simultaneous rtol = 1.0e-3 end # test fixedspace actually fixes space @testset "Fixedspace truncation using $alg and $projector_alg" for (alg, projector_alg) in - Iterators.product( - [:sequential, :simultaneous], projector_algs -) + Iterators.product([:sequential, :simultaneous], projector_algs) Ds = fill(2, 3, 3) χs = [16 17 18; 15 20 21; 14 19 22] psi = InfinitePEPS(Ds, Ds, Ds) env = CTMRGEnv(psi, rand(10:20, 3, 3), rand(10:20, 3, 3)) env2, = leading_boundary( - env, psi; alg, maxiter=1, trscheme=FixedSpaceTruncation(), projector_alg + env, psi; alg, maxiter = 1, trscheme = FixedSpaceTruncation(), projector_alg ) # check that the space is fixed diff --git a/test/ctmrg/gaugefix.jl b/test/ctmrg/gaugefix.jl index 775428c4e..e7b28f64e 100644 --- a/test/ctmrg/gaugefix.jl +++ b/test/ctmrg/gaugefix.jl @@ -10,17 +10,17 @@ scalartypes = [Float64, ComplexF64] unitcells = [(1, 1), (2, 2), (3, 2)] ctmrg_algs = [SequentialCTMRG, SimultaneousCTMRG] projector_algs = [:halfinfinite, :fullinfinite] -tol = 1e-6 # large tol due to χ=6 +tol = 1.0e-6 # large tol due to χ=6 χ = 6 -atol = 1e-4 +atol = 1.0e-4 function _pre_converge_env( - ::Type{T}, physical_space, peps_space, ctm_space, unitcell; seed=12345 -) where {T} + ::Type{T}, physical_space, peps_space, ctm_space, unitcell; seed = 12345 + ) where {T} Random.seed!(seed) # Seed RNG to make random environment consistent psi = InfinitePEPS(rand, T, physical_space, peps_space; unitcell) env₀ = CTMRGEnv(psi, ctm_space) - env_conv, = leading_boundary(env₀, psi; alg=:sequential, tol) + env_conv, = leading_boundary(env₀, psi; alg = :sequential, tol) return env_conv, psi end @@ -38,10 +38,10 @@ for (S, T, unitcell) in Iterators.product(spacetypes, scalartypes, unitcells) end @testset "($S) - ($T) - ($unitcell) - ($ctmrg_alg) - ($projector_alg)" for ( - S, T, unitcell, ctmrg_alg, projector_alg -) in Iterators.product( - spacetypes, scalartypes, unitcells, ctmrg_algs, projector_algs -) + S, T, unitcell, ctmrg_alg, projector_alg, + ) in Iterators.product( + spacetypes, scalartypes, unitcells, ctmrg_algs, projector_algs + ) alg = ctmrg_alg(; tol, projector_alg) env_pre, psi = preconv[(S, T, unitcell)] n = InfiniteSquareNetwork(psi) diff --git a/test/ctmrg/jacobian_real_linear.jl b/test/ctmrg/jacobian_real_linear.jl index 0a66f0469..0e3509621 100644 --- a/test/ctmrg/jacobian_real_linear.jl +++ b/test/ctmrg/jacobian_real_linear.jl @@ -7,9 +7,9 @@ using PEPSKit: ctmrg_iteration, gauge_fix, fix_relative_phases, fix_global_phases, _fix_svd_algorithm algs = [ - (:fixed, SimultaneousCTMRG(; projector_alg=:halfinfinite)), - (:diffgauge, SequentialCTMRG(; projector_alg=:halfinfinite)), - (:diffgauge, SimultaneousCTMRG(; projector_alg=:halfinfinite)), + (:fixed, SimultaneousCTMRG(; projector_alg = :halfinfinite)), + (:diffgauge, SequentialCTMRG(; projector_alg = :halfinfinite)), + (:diffgauge, SimultaneousCTMRG(; projector_alg = :halfinfinite)), # TODO: FullInfiniteProjector errors since even real_err_∂A, real_err_∂x are finite? # (:fixed, SimultaneousCTMRG(; projector_alg=FullInfiniteProjector)), # (:diffgauge, SequentialCTMRG(; projector_alg=FullInfiniteProjector)), @@ -54,8 +54,8 @@ Dbond, χenv = 2, 16 complex_err_∂A = norm(scale(∂f∂A(env_in), α_complex) - ∂f∂A(scale(env_in, α_complex))) complex_err_∂x = norm(scale(∂f∂x(env_in), α_complex) - ∂f∂x(scale(env_in, α_complex))) - @test real_err_∂A < 1e-9 - @test real_err_∂x < 1e-9 - @test complex_err_∂A > 1e-3 - @test complex_err_∂x > 1e-3 + @test real_err_∂A < 1.0e-9 + @test real_err_∂x < 1.0e-9 + @test complex_err_∂A > 1.0e-3 + @test complex_err_∂x > 1.0e-3 end diff --git a/test/ctmrg/partition_function.jl b/test/ctmrg/partition_function.jl index cba765c0d..a649da8a7 100644 --- a/test/ctmrg/partition_function.jl +++ b/test/ctmrg/partition_function.jl @@ -17,7 +17,7 @@ for the 2D classical Ising Model with partition function \\mathcal{Z}(\\beta) = \\sum_{\\{s\\}} \\exp(-\\beta H(s)) \\text{ with } H(s) = -J \\sum_{\\langle i, j \\rangle} s_i s_j ``` """ -function classical_ising_exact(; beta=log(1 + sqrt(2)) / 2, J=1.0) +function classical_ising_exact(; beta = log(1 + sqrt(2)) / 2, J = 1.0) K = beta * J k = 1 / sinh(2 * K)^2 @@ -43,7 +43,7 @@ Implements the 2D classical Ising model with partition function \\mathcal{Z}(\\beta) = \\sum_{\\{s\\}} \\exp(-\\beta H(s)) \\text{ with } H(s) = -J \\sum_{\\langle i, j \\rangle} s_i s_j ``` """ -function classical_ising(; beta=log(1 + sqrt(2)) / 2, J=1.0) +function classical_ising(; beta = log(1 + sqrt(2)) / 2, J = 1.0) K = beta * J # Boltzmann weights @@ -98,11 +98,11 @@ projector_algs = [:halfinfinite, :fullinfinite] @test sectortype(Z) === Trivial @testset "Classical Ising partition function using $alg with $projector_alg" for ( - alg, projector_alg -) in Iterators.product( - ctm_styles, projector_algs -) - env, = leading_boundary(env0, Z; alg, maxiter=150, projector_alg) + alg, projector_alg, + ) in Iterators.product( + ctm_styles, projector_algs + ) + env, = leading_boundary(env0, Z; alg, maxiter = 150, projector_alg) # check observables λ = network_value(Z, env) @@ -111,12 +111,12 @@ projector_algs = [:halfinfinite, :fullinfinite] f_exact, m_exact, e_exact = classical_ising_exact(; beta) # should be real-ish - @test abs(imag(λ)) < 1e-4 - @test abs(imag(m)) < 1e-4 - @test abs(imag(e)) < 1e-4 + @test abs(imag(λ)) < 1.0e-4 + @test abs(imag(m)) < 1.0e-4 + @test abs(imag(e)) < 1.0e-4 # should match exact solution - @test -log(λ) / beta ≈ f_exact rtol = 1e-4 - @test abs(m) ≈ abs(m_exact) rtol = 1e-4 - @test e ≈ e_exact rtol = 1e-1 # accuracy limited by bond dimension and maxiter + @test -log(λ) / beta ≈ f_exact rtol = 1.0e-4 + @test abs(m) ≈ abs(m_exact) rtol = 1.0e-4 + @test e ≈ e_exact rtol = 1.0e-1 # accuracy limited by bond dimension and maxiter end diff --git a/test/ctmrg/pepo.jl b/test/ctmrg/pepo.jl index 7acd262ad..5b52bd367 100644 --- a/test/ctmrg/pepo.jl +++ b/test/ctmrg/pepo.jl @@ -1,4 +1,3 @@ - using Test using Random using LinearAlgebra @@ -10,7 +9,7 @@ using Zygote ## Setup -function three_dimensional_classical_ising(; beta, J=1.0) +function three_dimensional_classical_ising(; beta, J = 1.0) K = beta * J # Boltzmann weights @@ -60,11 +59,11 @@ ctm_styles = [:sequential, :simultaneous] projector_algs = [:halfinfinite, :fullinfinite] @testset "PEPO CTMRG runthroughs for unitcell=$(unitcell)" for unitcell in - [(1, 1, 1), (1, 1, 2)] + [(1, 1, 1), (1, 1, 2)] Random.seed!(81812781144) # contract - T = InfinitePEPO(O; unitcell=unitcell) + T = InfinitePEPO(O; unitcell = unitcell) psi0 = initializePEPS(T, χpeps) n = InfiniteSquareNetwork(psi0, T) env0 = CTMRGEnv(n, χenv) @@ -75,11 +74,9 @@ projector_algs = [:halfinfinite, :fullinfinite] @test sectortype(T) === Trivial @testset "PEPO CTMRG contraction using $alg with $projector_alg" for ( - alg, projector_alg - ) in Iterators.product( - ctm_styles, projector_algs - ) - env, = leading_boundary(env0, n; alg, maxiter=150, projector_alg) + alg, projector_alg, + ) in Iterators.product(ctm_styles, projector_algs) + env, = leading_boundary(env0, n; alg, maxiter = 150, projector_alg) end end @@ -87,12 +84,12 @@ end Random.seed!(81812781144) # prep - ctm_alg = SimultaneousCTMRG(; maxiter=150, tol=1e-8, verbosity=2) + ctm_alg = SimultaneousCTMRG(; maxiter = 150, tol = 1.0e-8, verbosity = 2) alg_rrule = EigSolver(; - solver_alg=KrylovKit.Arnoldi(; maxiter=30, tol=1e-6, eager=true), - iterscheme=:diffgauge, + solver_alg = KrylovKit.Arnoldi(; maxiter = 30, tol = 1.0e-6, eager = true), + iterscheme = :diffgauge, ) - opt_alg = LBFGS(32; maxiter=50, gradtol=1e-5, verbosity=3) + opt_alg = LBFGS(32; maxiter = 50, gradtol = 1.0e-5, verbosity = 3) function pepo_retract(x, η, α) x´_partial, ξ = PEPSKit.peps_retract(x[1:2], η, α) x´ = (x´_partial..., deepcopy(x[3])) @@ -103,7 +100,7 @@ end end # contract - T = InfinitePEPO(O; unitcell=(1, 1, 1)) + T = InfinitePEPO(O; unitcell = (1, 1, 1)) psi0 = initializePEPS(T, χpeps) env2_0 = CTMRGEnv(InfiniteSquareNetwork(psi0), χenv) env3_0 = CTMRGEnv(InfiniteSquareNetwork(psi0, T), χenv) @@ -112,9 +109,9 @@ end (psi_final, env2_final, env3_final), f, = optimize( (psi0, env2_0, env3_0), opt_alg; - inner=PEPSKit.real_inner, - retract=pepo_retract, - (transport!)=(pepo_transport!), + inner = PEPSKit.real_inner, + retract = pepo_retract, + (transport!) = (pepo_transport!), ) do (psi, env2, env3) E, gs = withgradient(psi) do ψ n2 = InfiniteSquareNetwork(ψ) @@ -143,5 +140,5 @@ end nrm3 = PEPSKit._contract_site((1, 1), n3_final, env3_final) # compare to Monte-Carlo result from https://www.worldscientific.com/doi/abs/10.1142/S0129183101002383 - @test abs(m / nrm3) ≈ 0.667162 rtol = 1e-2 + @test abs(m / nrm3) ≈ 0.667162 rtol = 1.0e-2 end diff --git a/test/ctmrg/unitcell.jl b/test/ctmrg/unitcell.jl index f47f293ef..9f858e422 100644 --- a/test/ctmrg/unitcell.jl +++ b/test/ctmrg/unitcell.jl @@ -8,23 +8,16 @@ using TensorKit Random.seed!(91283219347) stype = ComplexF64 ctm_algs = [ - SequentialCTMRG(; projector_alg=:halfinfinite), - SequentialCTMRG(; projector_alg=:fullinfinite), - SimultaneousCTMRG(; projector_alg=:halfinfinite), - SimultaneousCTMRG(; projector_alg=:fullinfinite), + SequentialCTMRG(; projector_alg = :halfinfinite), + SequentialCTMRG(; projector_alg = :fullinfinite), + SimultaneousCTMRG(; projector_alg = :halfinfinite), + SimultaneousCTMRG(; projector_alg = :fullinfinite), ] function test_unitcell( - ctm_alg, - unitcell, - Pspaces, - Nspaces, - Espaces, - chis_north, - chis_east, - chis_south, - chis_west, -) + ctm_alg, unitcell, + Pspaces, Nspaces, Espaces, chis_north, chis_east, chis_south, chis_west, + ) peps = InfinitePEPS(randn, stype, Pspaces, Nspaces, Espaces) env = CTMRGEnv(randn, stype, peps, chis_north, chis_east, chis_south, chis_west) @@ -36,14 +29,13 @@ function test_unitcell( PEPSKit._to_space.(Pspaces), [ (c,) => randn( - scalartype(peps), - PEPSKit._to_space(Pspaces[c]), - PEPSKit._to_space(Pspaces[c]), - ) for c in CartesianIndices(unitcell) + scalartype(peps), + PEPSKit._to_space(Pspaces[c]), PEPSKit._to_space(Pspaces[c]), + ) for c in CartesianIndices(unitcell) ]..., ) @test expectation_value(peps, random_op, env) isa Number - @test expectation_value(peps, random_op, env′) isa Number + return @test expectation_value(peps, random_op, env′) isa Number end function random_dualize!(M::AbstractMatrix{<:ElementarySpace}) @@ -64,15 +56,8 @@ end chis_west = rand(5:10, unitcell...) test_unitcell( - ctm_alg, - unitcell, - Pspaces, - Nspaces, - Espaces, - chis_north, - chis_east, - chis_south, - chis_west, + ctm_alg, unitcell, + Pspaces, Nspaces, Espaces, chis_north, chis_east, chis_south, chis_west, ) end @@ -88,15 +73,8 @@ end chis_west = random_dualize!(ComplexSpace.(rand(5:10, unitcell...))) test_unitcell( - ctm_alg, - unitcell, - Pspaces, - Nspaces, - Espaces, - chis_north, - chis_east, - chis_south, - chis_west, + ctm_alg, unitcell, + Pspaces, Nspaces, Espaces, chis_north, chis_east, chis_south, chis_west, ) end diff --git a/test/examples/bose_hubbard.jl b/test/examples/bose_hubbard.jl index be363fef9..5dd237127 100644 --- a/test/examples/bose_hubbard.jl +++ b/test/examples/bose_hubbard.jl @@ -26,9 +26,9 @@ Vpeps = U1Space(0 => 2, 1 => 1, -1 => 1) Venv = U1Space(0 => 6, 1 => 4, -1 => 4, 2 => 2, -2 => 2) # algorithms -boundary_alg = (; tol=1e-8, alg=:simultaneous, verbosity=2, trscheme=(; alg=:fixedspace)) -gradient_alg = (; tol=1e-6, maxiter=10, alg=:eigsolver, iterscheme=:diffgauge) -optimizer_alg = (; tol=1e-4, alg=:lbfgs, verbosity=3, maxiter=25, ls_maxiter=2, ls_maxfg=2) +boundary_alg = (; tol = 1.0e-8, alg = :simultaneous, verbosity = 2, trscheme = (; alg = :fixedspace)) +gradient_alg = (; tol = 1.0e-6, maxiter = 10, alg = :eigsolver, iterscheme = :diffgauge) +optimizer_alg = (; tol = 1.0e-4, alg = :lbfgs, verbosity = 3, maxiter = 25, ls_maxiter = 2, ls_maxfg = 2) reuse_env = true # Hamiltonian diff --git a/test/examples/heisenberg.jl b/test/examples/heisenberg.jl index 262ba8b28..b92f12a0f 100644 --- a/test/examples/heisenberg.jl +++ b/test/examples/heisenberg.jl @@ -9,7 +9,7 @@ using OptimKit # initialize parameters Dbond = 2 χenv = 16 -gradtol = 1e-3 +gradtol = 1.0e-3 # compare against Juraj Hasik's data: # https://github.com/jurajHasik/j1j2_ipeps_states/blob/main/single-site_pg-C4v-A1/j20.0/state_1s_A1_j20.0_D2_chi_opt48.dat E_ref = -0.6602310934799577 @@ -22,10 +22,10 @@ E_ref = -0.6602310934799577 env₀, = leading_boundary(CTMRGEnv(peps₀, ComplexSpace(χenv)), peps₀) # optimize energy and compute correlation lengths - peps, env, E, = fixedpoint(H, peps₀, env₀; optimizer_alg=(; tol=gradtol, maxiter=25)) + peps, env, E, = fixedpoint(H, peps₀, env₀; optimizer_alg = (; tol = gradtol, maxiter = 25)) ξ_h, ξ_v, = correlation_length(peps, env) - @test E ≈ E_ref atol = 1e-2 + @test E ≈ E_ref atol = 1.0e-2 @test all(@. ξ_h > 0 && ξ_v > 0) end @@ -38,10 +38,10 @@ end env₀, = leading_boundary(CTMRGEnv(peps₀, ComplexSpace(χenv)), peps₀) # optimize energy and compute correlation lengths - peps, env, E, = fixedpoint(H, peps₀, env₀; optimizer_alg=(; tol=gradtol, maxiter=25)) + peps, env, E, = fixedpoint(H, peps₀, env₀; optimizer_alg = (; tol = gradtol, maxiter = 25)) ξ_h, ξ_v, = correlation_length(peps, env) - @test E ≈ 2 * E_ref atol = 1e-2 + @test E ≈ 2 * E_ref atol = 1.0e-2 @test all(@. ξ_h > 0 && ξ_v > 0) end @@ -52,52 +52,52 @@ end Pspace = ℂ^2 Vspace = ℂ^Dbond Espace = ℂ^χenv - wpeps = InfiniteWeightPEPS(rand, Float64, Pspace, Vspace; unitcell=(N1, N2)) - ctmrg_tol = 1e-6 + wpeps = InfiniteWeightPEPS(rand, Float64, Pspace, Vspace; unitcell = (N1, N2)) + ctmrg_tol = 1.0e-6 # normalize vertex tensors for ind in CartesianIndices(wpeps.vertices) wpeps.vertices[ind] /= norm(wpeps.vertices[ind], Inf) end # Heisenberg model Hamiltonian - ham = heisenberg_XYZ(InfiniteSquare(N1, N2); Jx=1.0, Jy=1.0, Jz=1.0) + ham = heisenberg_XYZ(InfiniteSquare(N1, N2); Jx = 1.0, Jy = 1.0, Jz = 1.0) # assert imaginary part is zero @assert length(imag(ham).terms) == 0 ham = real(ham) # simple update - dts = [1e-2, 1e-3, 1e-3, 1e-4] - tols = [1e-7, 1e-8, 1e-8, 1e-8] + dts = [1.0e-2, 1.0e-3, 1.0e-3, 1.0e-4] + tols = [1.0e-7, 1.0e-8, 1.0e-8, 1.0e-8] maxiter = 5000 for (n, (dt, tol)) in enumerate(zip(dts, tols)) Dbond2 = (n == 2) ? Dbond + 2 : Dbond - trscheme = truncerr(1e-10) & truncdim(Dbond2) + trscheme = truncerr(1.0e-10) & truncdim(Dbond2) alg = SimpleUpdate(dt, tol, maxiter, trscheme) - result = simpleupdate(wpeps, ham, alg; bipartite=false) + result = simpleupdate(wpeps, ham, alg; bipartite = false) wpeps = result[1] end # absorb weight into site tensors and CTMRG peps = InfinitePEPS(wpeps) - env, = leading_boundary(CTMRGEnv(rand, Float64, peps, Espace), peps; tol=ctmrg_tol) + env, = leading_boundary(CTMRGEnv(rand, Float64, peps, Espace), peps; tol = ctmrg_tol) # measure physical quantities e_site = cost_function(peps, env, ham) / (N1 * N2) @info "Simple update energy = $e_site" # benchmark data from Phys. Rev. B 94, 035133 (2016) - @test isapprox(e_site, -0.6594; atol=1e-3) + @test isapprox(e_site, -0.6594; atol = 1.0e-3) # continue with auto differentiation peps_final, env_final, E_final, = fixedpoint( ham, peps, env; - optimizer_alg=(; tol=gradtol, maxiter=25), - boundary_alg=(; maxiter=150, svd_alg=(; rrule_alg=(; alg=:full, tol=1e-5))), + optimizer_alg = (; tol = gradtol, maxiter = 25), + boundary_alg = (; maxiter = 150, svd_alg = (; rrule_alg = (; alg = :full, tol = 1.0e-5))), ) # sensitivity warnings and degeneracies due to SU(2)? ξ_h, ξ_v, = correlation_length(peps_final, env_final) e_site2 = E_final / (N1 * N2) @info "Auto diff energy = $e_site2" - @test e_site2 ≈ E_ref atol = 1e-2 + @test e_site2 ≈ E_ref atol = 1.0e-2 @test all(@. ξ_h > 0 && ξ_v > 0) end diff --git a/test/examples/j1j2_model.jl b/test/examples/j1j2_model.jl index 9f6511680..743d90406 100644 --- a/test/examples/j1j2_model.jl +++ b/test/examples/j1j2_model.jl @@ -11,25 +11,21 @@ using OptimKit # initialize states Random.seed!(91283219347) -H = j1_j2_model(InfiniteSquare(); J2=0.25) -peps₀ = product_peps(2, χbond; noise_amp=1e-1) +H = j1_j2_model(InfiniteSquare(); J2 = 0.25) +peps₀ = product_peps(2, χbond; noise_amp = 1.0e-1) peps₀ = symmetrize!(peps₀, RotateReflect()) env₀, = leading_boundary(CTMRGEnv(peps₀, ComplexSpace(χenv)), peps₀) # find fixedpoint peps, env, E, = fixedpoint( - H, - peps₀, - env₀; - tol=1e-3, - gradient_alg=(; iterscheme=:diffgauge), - symmetrization=RotateReflect(), + H, peps₀, env₀; + tol = 1.0e-3, gradient_alg = (; iterscheme = :diffgauge), symmetrization = RotateReflect(), ) ξ_h, ξ_v, = correlation_length(peps, env) # compare against Juraj Hasik's data: # https://github.com/jurajHasik/j1j2_ipeps_states/blob/main/single-site_pg-C4v-A1/j20.25/state_1s_A1_j20.25_D2_chi_opt48.dat ξ_ref = -1 / log(0.2723596743547324) -@test E ≈ -0.5618837021945925 atol = 1e-3 -@test all(@. isapprox(ξ_h, ξ_ref; atol=1e-1) && isapprox(ξ_v, ξ_ref; atol=1e-1)) -@test ξ_h ≈ ξ_v atol = 1e-6 # Test symmetrization of optimized PEPS and environment +@test E ≈ -0.5618837021945925 atol = 1.0e-3 +@test all(@. isapprox(ξ_h, ξ_ref; atol = 1.0e-1) && isapprox(ξ_v, ξ_ref; atol = 1.0e-1)) +@test ξ_h ≈ ξ_v atol = 1.0e-6 # Test symmetrization of optimized PEPS and environment diff --git a/test/examples/pwave.jl b/test/examples/pwave.jl index e07456053..fe0883bf0 100644 --- a/test/examples/pwave.jl +++ b/test/examples/pwave.jl @@ -20,7 +20,7 @@ peps₀ = InfinitePEPS(Pspace, Vspace, Vspace; unitcell) env₀, = leading_boundary(CTMRGEnv(peps₀, Envspace), peps₀) # find fixedpoint -_, _, E, = fixedpoint(H, peps₀, env₀; tol=1e-3, optimizer_alg=(; maxiter=10)) +_, _, E, = fixedpoint(H, peps₀, env₀; tol = 1.0e-3, optimizer_alg = (; maxiter = 10)) # comparison with Gaussian PEPS minimum at D=2 on 1000x1000 square lattice with aPBC -@test E / prod(size(peps₀)) ≈ -2.6241 atol = 5e-2 +@test E / prod(size(peps₀)) ≈ -2.6241 atol = 5.0e-2 diff --git a/test/examples/tf_ising.jl b/test/examples/tf_ising.jl index 9ef71b62c..5646ef40b 100644 --- a/test/examples/tf_ising.jl +++ b/test/examples/tf_ising.jl @@ -19,7 +19,7 @@ mˣ = 0.91 # initialize parameters χbond = 2 χenv = 16 -gradtol = 1e-3 +gradtol = 1.0e-3 # initialize states H = transverse_field_ising(InfiniteSquare(); g) @@ -28,7 +28,7 @@ peps₀ = InfinitePEPS(2, χbond) env₀, = leading_boundary(CTMRGEnv(peps₀, ComplexSpace(χenv)), peps₀) # find fixedpoint -peps, env, E, = fixedpoint(H, peps₀, env₀; tol=gradtol) +peps, env, E, = fixedpoint(H, peps₀, env₀; tol = gradtol) ξ_h, ξ_v, = correlation_length(peps, env) # compute magnetization @@ -39,44 +39,40 @@ Mz = LocalOperator(physicalspace(H), (CartesianIndex(1, 1),) => σz) magnx = expectation_value(peps, Mx, env) magnz = expectation_value(peps, Mz, env) -@test E ≈ e atol = 1e-2 -@test imag(magnx) ≈ 0 atol = 1e-6 -@test abs(magnx) ≈ mˣ atol = 5e-2 +@test E ≈ e atol = 1.0e-2 +@test imag(magnx) ≈ 0 atol = 1.0e-6 +@test abs(magnx) ≈ mˣ atol = 5.0e-2 # compute connected correlation functions corrh = correlator( - peps, σz ⊗ σz, CartesianIndex(1, 1), CartesianIndex(1, 2):CartesianIndex(1, 21), env - ) .- magnz^2 + peps, σz ⊗ σz, CartesianIndex(1, 1), CartesianIndex(1, 2):CartesianIndex(1, 21), env +) .- magnz^2 corrv = correlator( - peps, σz ⊗ σz, CartesianIndex(1, 1), CartesianIndex(2, 1):CartesianIndex(21, 1), env - ) .- magnz^2 + peps, σz ⊗ σz, CartesianIndex(1, 1), CartesianIndex(2, 1):CartesianIndex(21, 1), env +) .- magnz^2 -@test corrh[end] ≈ 0.0 atol = 1e-5 -@test 1 / log(corrh[18] / corrh[19]) ≈ ξ_h[1] atol = 2e-2 # test correlation length far away from short-range effects -@test corrv[end] ≈ 0.0 atol = 1e-5 -@test 1 / log(corrv[18] / corrv[19]) ≈ ξ_v[1] atol = 3e-2 # test correlation length far away from short-range effects -@test corrv ≈ corrh rtol = 1e-2 +@test corrh[end] ≈ 0.0 atol = 1.0e-5 +@test 1 / log(corrh[18] / corrh[19]) ≈ ξ_h[1] atol = 2.0e-2 # test correlation length far away from short-range effects +@test corrv[end] ≈ 0.0 atol = 1.0e-5 +@test 1 / log(corrv[18] / corrv[19]) ≈ ξ_v[1] atol = 3.0e-2 # test correlation length far away from short-range effects +@test corrv ≈ corrh rtol = 1.0e-2 # compute weird geometries corrh_2 = correlator( - peps, - σz ⊗ σz, - CartesianIndex(3, 2), - CartesianIndex(3, 3):CartesianIndex(1, 2):CartesianIndex(3, 7), - env, - ) .- magnz^2 + peps, σz ⊗ σz, + CartesianIndex(3, 2), CartesianIndex(3, 3):CartesianIndex(1, 2):CartesianIndex(3, 7), + env, +) .- magnz^2 @test corrh_2 ≈ corrh[1:2:5] corrv_2 = correlator( - peps, - σz ⊗ σz, - CartesianIndex(2, 3), - CartesianIndex(3, 3):CartesianIndex(2, 1):CartesianIndex(7, 3), - env, - ) .- magnz^2 + peps, σz ⊗ σz, + CartesianIndex(2, 3), CartesianIndex(3, 3):CartesianIndex(2, 1):CartesianIndex(7, 3), + env, +) .- magnz^2 @test corrv_2 ≈ corrv[1:2:5] # Change from specific values and distances to a range @@ -91,8 +87,8 @@ corrv_int = @test_broken correlator(peps, σz ⊗ σz, CartesianIndex(1, 1), CartesianIndex(2, 2), env) # find fixedpoint in polarized phase and compute correlations lengths -H_polar = transverse_field_ising(InfiniteSquare(); g=4.5) -peps_polar, env_polar, = fixedpoint(H_polar, peps₀, env₀; tol=gradtol) +H_polar = transverse_field_ising(InfiniteSquare(); g = 4.5) +peps_polar, env_polar, = fixedpoint(H_polar, peps₀, env₀; tol = gradtol) ξ_h_polar, ξ_v_polar, = correlation_length(peps_polar, env_polar) @test ξ_h_polar < ξ_h @test ξ_v_polar < ξ_v diff --git a/test/gradients/ctmrg_gradients.jl b/test/gradients/ctmrg_gradients.jl index 0638b2a69..e973c0a03 100644 --- a/test/gradients/ctmrg_gradients.jl +++ b/test/gradients/ctmrg_gradients.jl @@ -16,7 +16,7 @@ Espaces = [ComplexSpace(χenv), Vect[FermionParity](0 => χenv / 2, 1 => χenv / models = [heisenberg_XYZ(InfiniteSquare()), pwave_superconductor(InfiniteSquare())] names = ["Heisenberg", "p-wave superconductor"] -gradtol = 1e-4 +gradtol = 1.0e-4 ctmrg_verbosity = 0 ctmrg_algs = [[:sequential, :simultaneous], [:sequential, :simultaneous]] projector_algs = [[:halfinfinite, :fullinfinite], [:halfinfinite, :fullinfinite]] @@ -38,9 +38,9 @@ naive_gradient_done = Set() ## Tests # ------ @testset "AD CTMRG energy gradients for $(names[i]) model" verbose = true for i in - eachindex( - models -) + eachindex( + models + ) Pspace = Pspaces[i] Vspace = Vspaces[i] Espace = Espaces[i] @@ -50,10 +50,10 @@ naive_gradient_done = Set() galgs = gradient_algs[i] gischemes = gradient_iterschemes[i] @testset "ctmrg_alg=:$ctmrg_alg, projector_alg=:$projector_alg, svd_rrule_alg=:$svd_rrule_alg, gradient_alg=:$gradient_alg, gradient_iterscheme=:$gradient_iterscheme" for ( - ctmrg_alg, projector_alg, svd_rrule_alg, gradient_alg, gradient_iterscheme - ) in Iterators.product( - calgs, palgs, salgs, galgs, gischemes - ) + ctmrg_alg, projector_alg, svd_rrule_alg, gradient_alg, gradient_iterscheme, + ) in Iterators.product( + calgs, palgs, salgs, galgs, gischemes + ) # filter all disallowed combinations (ctmrg_alg == :sequential && gradient_iterscheme == :fixed) && continue @@ -71,24 +71,24 @@ naive_gradient_done = Set() psi = InfinitePEPS(Pspace, Vspace) # instantiate to avoid having to type this twice... contrete_ctmrg_alg = PEPSKit.CTMRGAlgorithm(; - alg=ctmrg_alg, - verbosity=ctmrg_verbosity, - projector_alg=projector_alg, - svd_alg=(; rrule_alg=(; alg=svd_rrule_alg)), + alg = ctmrg_alg, + verbosity = ctmrg_verbosity, + projector_alg = projector_alg, + svd_alg = (; rrule_alg = (; alg = svd_rrule_alg)), ) # instantiate because hook_pullback doesn't go through the keyword selector... concrete_gradient_alg = if isnothing(gradient_alg) nothing # TODO: add this to the PEPSKit.GradMode selector? else - PEPSKit.GradMode(; alg=gradient_alg, tol=gradtol, iterscheme=gradient_iterscheme) + PEPSKit.GradMode(; alg = gradient_alg, tol = gradtol, iterscheme = gradient_iterscheme) end env, = leading_boundary(CTMRGEnv(psi, Espace), psi, contrete_ctmrg_alg) alphas, fs, dfs1, dfs2 = OptimKit.optimtest( (psi, env), dir; - alpha=steps, - retract=PEPSKit.peps_retract, - inner=PEPSKit.real_inner, + alpha = steps, + retract = PEPSKit.peps_retract, + inner = PEPSKit.real_inner, ) do (peps, env) E, g = Zygote.withgradient(peps) do psi env2, = PEPSKit.hook_pullback( @@ -96,13 +96,13 @@ naive_gradient_done = Set() env, psi, contrete_ctmrg_alg; - alg_rrule=concrete_gradient_alg, + alg_rrule = concrete_gradient_alg, ) return cost_function(psi, env2, models[i]) end return E, only(g) end - @test dfs1 ≈ dfs2 atol = 1e-2 + @test dfs1 ≈ dfs2 atol = 1.0e-2 end end diff --git a/test/timeevol/cluster_projectors.jl b/test/timeevol/cluster_projectors.jl index 91b2994e8..69826dee6 100644 --- a/test/timeevol/cluster_projectors.jl +++ b/test/timeevol/cluster_projectors.jl @@ -30,7 +30,7 @@ Vspaces = [ revs = [isdual(space(M, 1)) for M in Ms1[2:end]] # no truncation Ms2 = deepcopy(Ms1) - wts2, ϵs, = _cluster_truncate!(Ms2, fill(FixedSpaceTruncation(), N-1), revs) + wts2, ϵs, = _cluster_truncate!(Ms2, fill(FixedSpaceTruncation(), N - 1), revs) @test all((ϵ == 0) for ϵ in ϵs) absorb_wts_cluster!(Ms2, wts2) for (i, M) in enumerate(Ms2) @@ -41,7 +41,7 @@ Vspaces = [ @test all(lorths) && all(rorths) # truncation on one bond Ms3 = deepcopy(Ms1) - wts3, ϵs, = _cluster_truncate!(Ms3, fill(truncspace(Vns), N-1), revs) + wts3, ϵs, = _cluster_truncate!(Ms3, fill(truncspace(Vns), N - 1), revs) @test all((i == n) || (ϵ == 0) for (i, ϵ) in enumerate(ϵs)) absorb_wts_cluster!(Ms3, wts3) for (i, M) in enumerate(Ms3) @@ -79,46 +79,46 @@ end @testset "Hubbard model with usual SU and 3-site SU" begin Nr, Nc = 2, 2 - ctmrg_tol = 1e-9 + ctmrg_tol = 1.0e-9 Random.seed!(100) # with U(1) spin rotation symmetry Pspace = hubbard_space(Trivial, U1Irrep) - Vspace = Vect[FermionParity ⊠ U1Irrep]((0, 0) => 2, (1, 1//2) => 1, (1, -1//2) => 1) - Espace = Vect[FermionParity ⊠ U1Irrep]((0, 0) => 8, (1, 1//2) => 4, (1, -1//2) => 4) - trscheme_env = truncerr(1e-12) & truncdim(16) - wpeps = InfiniteWeightPEPS(rand, Float64, Pspace, Vspace; unitcell=(Nr, Nc)) + Vspace = Vect[FermionParity ⊠ U1Irrep]((0, 0) => 2, (1, 1 // 2) => 1, (1, -1 // 2) => 1) + Espace = Vect[FermionParity ⊠ U1Irrep]((0, 0) => 8, (1, 1 // 2) => 4, (1, -1 // 2) => 4) + trscheme_env = truncerr(1.0e-12) & truncdim(16) + wpeps = InfiniteWeightPEPS(rand, Float64, Pspace, Vspace; unitcell = (Nr, Nc)) ham = real( - hubbard_model(ComplexF64, Trivial, U1Irrep, InfiniteSquare(Nr, Nc); t=1.0, U=8.0) + hubbard_model(ComplexF64, Trivial, U1Irrep, InfiniteSquare(Nr, Nc); t = 1.0, U = 8.0) ) # usual 2-site simple update, and measure energy - dts = [1e-2, 1e-2, 5e-3] - tols = [1e-8, 1e-8, 1e-8] + dts = [1.0e-2, 1.0e-2, 5.0e-3] + tols = [1.0e-8, 1.0e-8, 1.0e-8] maxiter = 10000 for (n, (dt, tol)) in enumerate(zip(dts, tols)) - trscheme = truncerr(1e-10) & truncdim(n == 1 ? 4 : 2) + trscheme = truncerr(1.0e-10) & truncdim(n == 1 ? 4 : 2) alg = SimpleUpdate(dt, tol, maxiter, trscheme) - result = simpleupdate(wpeps, ham, alg; bipartite=true, check_interval=1000) + result = simpleupdate(wpeps, ham, alg; bipartite = true, check_interval = 1000) wpeps = result[1] end peps = InfinitePEPS(wpeps) normalize!.(peps.A, Inf) env = CTMRGEnv(rand, Float64, peps, Espace) - env, = leading_boundary(env, peps; tol=ctmrg_tol, trscheme=trscheme_env) + env, = leading_boundary(env, peps; tol = ctmrg_tol, trscheme = trscheme_env) e_site = cost_function(peps, env, ham) / (Nr * Nc) @info "2-site simple update energy = $e_site" # continue with 3-site simple update; energy should not change much - dts = [1e-2, 5e-3] - tols = [1e-8, 1e-8] - trscheme = truncerr(1e-10) & truncdim(2) + dts = [1.0e-2, 5.0e-3] + tols = [1.0e-8, 1.0e-8] + trscheme = truncerr(1.0e-10) & truncdim(2) for (n, (dt, tol)) in enumerate(zip(dts, tols)) alg = SimpleUpdate(dt, tol, maxiter, trscheme) - result = simpleupdate(wpeps, ham, alg; check_interval=1000, force_3site=true) + result = simpleupdate(wpeps, ham, alg; check_interval = 1000, force_3site = true) wpeps = result[1] end peps = InfinitePEPS(wpeps) normalize!.(peps.A, Inf) - env, = leading_boundary(env, peps; tol=ctmrg_tol, trscheme=trscheme_env) + env, = leading_boundary(env, peps; tol = ctmrg_tol, trscheme = trscheme_env) e_site2 = cost_function(peps, env, ham) / (Nr * Nc) @info "3-site simple update energy = $e_site2" - @test e_site ≈ e_site2 atol = 5e-4 + @test e_site ≈ e_site2 atol = 5.0e-4 end diff --git a/test/timeevol/cluster_tools.jl b/test/timeevol/cluster_tools.jl index cf9166d79..7e99380ae 100644 --- a/test/timeevol/cluster_tools.jl +++ b/test/timeevol/cluster_tools.jl @@ -1,6 +1,6 @@ function _contract_left( - M::AbstractTensorMap{T,S,1,4}, sl::DiagonalTensorMap{T,S} -) where {T<:Number,S<:ElementarySpace} + M::AbstractTensorMap{T, S, 1, 4}, sl::DiagonalTensorMap{T, S} + ) where {T <: Number, S <: ElementarySpace} M0 = twist(M, filter(ax -> isdual(space(M, ax)), 1:4)) if isdual(codomain(M, 1)) @tensor sl1[e1; e0] := conj(M[w1; p n s e1]) * sl[w0; w1] * M0[w0; p n s e0] @@ -13,8 +13,8 @@ function _contract_left( return sl1 end function _contract_left( - M::AbstractTensorMap{T,S,1,4}, ::Nothing -) where {T<:Number,S<:ElementarySpace} + M::AbstractTensorMap{T, S, 1, 4}, ::Nothing + ) where {T <: Number, S <: ElementarySpace} M0 = twist(M, filter(ax -> isdual(space(M, ax)), 1:4)) @tensor sl1[e1; e0] := conj(M[w; p n s e1]) * M0[w; p n s e0] if isdual(space(sl1, 1)) @@ -24,8 +24,8 @@ function _contract_left( end function _contract_right( - M::AbstractTensorMap{T,S,1,4}, sr::DiagonalTensorMap{T,S} -) where {T<:Number,S<:ElementarySpace} + M::AbstractTensorMap{T, S, 1, 4}, sr::DiagonalTensorMap{T, S} + ) where {T <: Number, S <: ElementarySpace} M0 = twist(M, filter(ax -> !isdual(space(M, ax)), 2:5)) if isdual(domain(M, 4)) @tensor sr1[w0; w1] := M0[w0; p n s e0] * sr[e1; e0] * conj(M[w1; p n s e1]) @@ -38,8 +38,8 @@ function _contract_right( return sr1 end function _contract_right( - M::AbstractTensorMap{T,S,1,4}, ::Nothing -) where {T<:Number,S<:ElementarySpace} + M::AbstractTensorMap{T, S, 1, 4}, ::Nothing + ) where {T <: Number, S <: ElementarySpace} M0 = twist(M, filter(ax -> !isdual(space(M, ax)), 2:5)) @tensor sr1[w0; w1] := M0[w0; p n s e] * conj(M[w1; p n s e]) if isdual(space(sr1, 1)) @@ -52,8 +52,8 @@ end Verify the generalized left/right orthogonal condition """ function verify_cluster_orth( - Ms::Vector{T1}, wts::Vector{T2} -) where {T1<:AbstractTensorMap,T2<:AbstractTensorMap} + Ms::Vector{T1}, wts::Vector{T2} + ) where {T1 <: AbstractTensorMap, T2 <: AbstractTensorMap} N = length(Ms) @assert length(wts) == N - 1 lorths = fill(false, N - 1) @@ -74,8 +74,8 @@ function verify_cluster_orth( end function inner_prod_cluster( - Ms1::Vector{T1}, Ms2::Vector{T2} -) where {T1<:AbstractTensorMap,T2<:AbstractTensorMap} + Ms1::Vector{T1}, Ms2::Vector{T2} + ) where {T1 <: AbstractTensorMap, T2 <: AbstractTensorMap} N = length(Ms1) @assert length(Ms2) == N @assert all((numout(t) == 1 && numin(t) == 4) for t in Ms1) @@ -105,8 +105,8 @@ function inner_prod_cluster( end function absorb_wts_cluster!( - Ms::Vector{T1}, wts::Vector{T2} -) where {T1<:AbstractTensorMap,T2<:AbstractTensorMap} + Ms::Vector{T1}, wts::Vector{T2} + ) where {T1 <: AbstractTensorMap, T2 <: AbstractTensorMap} revs = [isdual(space(M, 1)) for M in Ms[2:end]] for (i, (wt, rev)) in enumerate(zip(wts, revs)) wtsqrt = sdiag_pow(wt, 0.5) @@ -118,16 +118,17 @@ function absorb_wts_cluster!( Ms[i + 1][-1; -2 -3 -4 -5] = wtsqrt[-1; 1] * Ms[i + 1][1; -2 -3 -4 -5] end end + return end function fidelity_cluster( - Ms1::Vector{T1}, Ms2::Vector{T2} -) where {T1<:AbstractTensorMap,T2<:AbstractTensorMap} + Ms1::Vector{T1}, Ms2::Vector{T2} + ) where {T1 <: AbstractTensorMap, T2 <: AbstractTensorMap} return abs2(inner_prod_cluster(Ms1, Ms2)) / - (inner_prod_cluster(Ms1, Ms1) * inner_prod_cluster(Ms2, Ms2)) + (inner_prod_cluster(Ms1, Ms1) * inner_prod_cluster(Ms2, Ms2)) end -function mpo_to_gate3(gs::Vector{T}) where {T<:AbstractTensorMap} +function mpo_to_gate3(gs::Vector{T}) where {T <: AbstractTensorMap} #= -1 -2 -3 ↑ ↑ ↑ diff --git a/test/timeevol/sitedep_truncation.jl b/test/timeevol/sitedep_truncation.jl index ca62daca9..dcef94e5f 100644 --- a/test/timeevol/sitedep_truncation.jl +++ b/test/timeevol/sitedep_truncation.jl @@ -8,47 +8,47 @@ using PEPSKit: NORTH, EAST function get_bonddims(wpeps::InfiniteWeightPEPS) xdims = collect(dim(domain(t, EAST)) for t in wpeps.vertices) ydims = collect(dim(domain(t, NORTH)) for t in wpeps.vertices) - return stack([xdims, ydims]; dims=1) + return stack([xdims, ydims]; dims = 1) end @testset "Simple update: bipartite 2-site" begin Nr, Nc = 2, 2 - ham = real(heisenberg_XYZ(InfiniteSquare(Nr, Nc); Jx=1.0, Jy=1.0, Jz=1.0)) + ham = real(heisenberg_XYZ(InfiniteSquare(Nr, Nc); Jx = 1.0, Jy = 1.0, Jz = 1.0)) Random.seed!(100) - wpeps0 = InfiniteWeightPEPS(rand, Float64, ℂ^2, ℂ^10; unitcell=(Nr, Nc)) + wpeps0 = InfiniteWeightPEPS(rand, Float64, ℂ^2, ℂ^10; unitcell = (Nr, Nc)) normalize!.(wpeps0.vertices, Inf) # set trscheme to be compatible with bipartite structure - bonddims = stack([[6 4; 4 6], [5 7; 7 5]]; dims=1) + bonddims = stack([[6 4; 4 6], [5 7; 7 5]]; dims = 1) trscheme = SiteDependentTruncation(collect(truncdim(d) for d in bonddims)) - alg = SimpleUpdate(1e-2, 1e-14, 4, trscheme) - wpeps, = simpleupdate(wpeps0, ham, alg; bipartite=true) + alg = SimpleUpdate(1.0e-2, 1.0e-14, 4, trscheme) + wpeps, = simpleupdate(wpeps0, ham, alg; bipartite = true) @test get_bonddims(wpeps) == bonddims # check bipartite structure is preserved for col in 1:2 cp1 = PEPSKit._next(col, 2) @test ( wpeps.vertices[1, col] == wpeps.vertices[2, cp1] && - wpeps.weights[1, 1, col] == wpeps.weights[1, 2, cp1] && - wpeps.weights[2, 1, col] == wpeps.weights[2, 2, cp1] + wpeps.weights[1, 1, col] == wpeps.weights[1, 2, cp1] && + wpeps.weights[2, 1, col] == wpeps.weights[2, 2, cp1] ) end end @testset "Simple update: generic 2-site and 3-site" begin Nr, Nc = 3, 4 - ham = real(heisenberg_XYZ(InfiniteSquare(Nr, Nc); Jx=1.0, Jy=1.0, Jz=1.0)) + ham = real(heisenberg_XYZ(InfiniteSquare(Nr, Nc); Jx = 1.0, Jy = 1.0, Jz = 1.0)) Random.seed!(100) - wpeps0 = InfiniteWeightPEPS(rand, Float64, ℂ^2, ℂ^10; unitcell=(Nr, Nc)) + wpeps0 = InfiniteWeightPEPS(rand, Float64, ℂ^2, ℂ^10; unitcell = (Nr, Nc)) normalize!.(wpeps0.vertices, Inf) # Site dependent truncation bonddims = rand(2:8, 2, Nr, Nc) @show bonddims trscheme = SiteDependentTruncation(collect(truncdim(d) for d in bonddims)) - alg = SimpleUpdate(1e-2, 1e-14, 2, trscheme) + alg = SimpleUpdate(1.0e-2, 1.0e-14, 2, trscheme) # 2-site SU - wpeps, = simpleupdate(wpeps0, ham, alg; bipartite=false) + wpeps, = simpleupdate(wpeps0, ham, alg; bipartite = false) @test get_bonddims(wpeps) == bonddims # 3-site SU - wpeps, = simpleupdate(wpeps0, ham, alg; bipartite=false, force_3site=true) + wpeps, = simpleupdate(wpeps0, ham, alg; bipartite = false, force_3site = true) @test get_bonddims(wpeps) == bonddims end diff --git a/test/utility/correlator.jl b/test/utility/correlator.jl index 18943dfee..3ba9786ee 100644 --- a/test/utility/correlator.jl +++ b/test/utility/correlator.jl @@ -8,7 +8,7 @@ Pspace = tJ.tj_space(Trivial, Trivial) Vspace = Vect[FermionParity](0 => 2, 1 => 2) Espace = Vect[FermionParity](0 => 3, 1 => 3) Random.seed!(100) -peps = InfinitePEPS(rand, ComplexF64, Pspace, Vspace; unitcell=(2, 2)); +peps = InfinitePEPS(rand, ComplexF64, Pspace, Vspace; unitcell = (2, 2)); env = CTMRGEnv(rand, ComplexF64, peps, Espace); lattice = collect(space(t, 1) for t in peps.A) @@ -19,8 +19,10 @@ site1s = collect(site0 + CartesianIndex(0, i) for i in 2:2:maxsep) op = tJ.S_exchange(ComplexF64, Trivial, Trivial); vals1 = correlator(peps, op, site0, site1s, env) -vals2 = collect(begin - O = LocalOperator(lattice, (site0, site1) => op) - val = expectation_value(peps, O, env) -end for site1 in site1s) +vals2 = collect( + begin + O = LocalOperator(lattice, (site0, site1) => op) + val = expectation_value(peps, O, env) + end for site1 in site1s +) @test vals1 ≈ vals2 diff --git a/test/utility/diff_maps.jl b/test/utility/diff_maps.jl index 5606f731c..52a25d1ff 100644 --- a/test/utility/diff_maps.jl +++ b/test/utility/diff_maps.jl @@ -3,5 +3,5 @@ using PEPSKit: dtmap # Can the rrule of dtmap be made inferable? (if check_inferred=true, tests error at the moment) @testset "Differentiable tmap" begin - test_rrule(dtmap, x -> x^3, randn(5, 5); check_inferred=false) + test_rrule(dtmap, x -> x^3, randn(5, 5); check_inferred = false) end diff --git a/test/utility/iwpeps_rotation.jl b/test/utility/iwpeps_rotation.jl index 876fdf432..0ff43a70a 100644 --- a/test/utility/iwpeps_rotation.jl +++ b/test/utility/iwpeps_rotation.jl @@ -18,7 +18,7 @@ function test_rotation(wts::SUWeight) return nothing end -function flip_twice(a::AbstractTensorMap, idx; inv::Bool=false) +function flip_twice(a::AbstractTensorMap, idx; inv::Bool = false) _flip(a) = flip(a, idx; inv) return (_flip ∘ _flip)(a) end @@ -31,40 +31,40 @@ function test_rotation(psi::InfiniteWeightPEPS) psi_rl = (rotr90 ∘ rotl90)(psi) @test psi_lr.weights ≈ psi_rl.weights ≈ psi.weights @test all( - flip_twice(v1, (3, 5); inv=true) ≈ v2 for - (v1, v2) in zip(psi_lr.vertices, psi.vertices) + flip_twice(v1, (3, 5); inv = true) ≈ v2 for + (v1, v2) in zip(psi_lr.vertices, psi.vertices) ) @test all( - flip_twice(v1, (2, 4); inv=true) ≈ v2 for - (v1, v2) in zip(psi_rl.vertices, psi.vertices) + flip_twice(v1, (2, 4); inv = true) ≈ v2 for + (v1, v2) in zip(psi_rl.vertices, psi.vertices) ) psi_l4 = compose_n(rotl90, 4)(psi) psi_r4 = compose_n(rotr90, 4)(psi) psi_2 = compose_n(rot180, 2)(psi) @test psi_l4 ≈ psi_r4 ≈ psi_2 @test all( - flip_twice(v1, Tuple(2:5); inv=true) ≈ v2 for - (v1, v2) in zip(psi_2.vertices, psi.vertices) + flip_twice(v1, Tuple(2:5); inv = true) ≈ v2 for + (v1, v2) in zip(psi_2.vertices, psi.vertices) ) # conversion to InfinitePEPS psi_l = rotl90(psi) peps_l = InfinitePEPS(psi_l) for (i, t) in enumerate(peps_l.A) - peps_l.A[i] = flip(t, (3, 5); inv=true) + peps_l.A[i] = flip(t, (3, 5); inv = true) end @test peps_l ≈ rotl90(peps) psi_r = rotr90(psi) peps_r = InfinitePEPS(psi_r) for (i, t) in enumerate(peps_r.A) - peps_r.A[i] = flip(t, (2, 4); inv=true) + peps_r.A[i] = flip(t, (2, 4); inv = true) end @test peps_r ≈ rotr90(peps) psi_2 = rot180(psi) peps_2 = InfinitePEPS(psi_2) for (i, t) in enumerate(peps_2.A) - peps_2.A[i] = flip(t, Tuple(2:5); inv=true) + peps_2.A[i] = flip(t, Tuple(2:5); inv = true) end - @test peps_2 ≈ rot180(peps) + return @test peps_2 ≈ rot180(peps) end Vphy = Vect[FermionParity](0 => 1, 1 => 1) diff --git a/test/utility/retractions.jl b/test/utility/retractions.jl index e04963e0c..1d61d24c0 100644 --- a/test/utility/retractions.jl +++ b/test/utility/retractions.jl @@ -10,14 +10,14 @@ Vphyss = [ℂ^2, U1Space(0 => 1, -1 => 1, 1 => 1)] Vpepss = [ℂ^4, U1Space(0 => 2, -1 => 1, 1 => 1)] @testset "Norm-preserving tensor retractions for sectortype $(sectortype(Vphyss[i]))" for i in - eachindex( - Vphyss -) + eachindex( + Vphyss + ) Vphys = Vphyss[i] Vpeps = Vpepss[i] peps_space = Vphys ← Vpeps ⊗ Vpeps ⊗ Vpeps' ⊗ Vpeps' - α = 1e-1 * randn(Float64) + α = 1.0e-1 * randn(Float64) A = randn(dtype, peps_space) normalized_A = scale(A, inv(norm(A))) η = randn(dtype, peps_space) @@ -26,8 +26,8 @@ Vpepss = [ℂ^4, U1Space(0 => 2, -1 => 1, 1 => 1)] add!(ζ, normalized_A, -inner(normalized_A, ζ)) A´, ξ = PEPSKit.norm_preserving_retract(A, η, α) - @test norm(A´) ≈ norm(A) rtol = 1e-12 + @test norm(A´) ≈ norm(A) rtol = 1.0e-12 PEPSKit.norm_preserving_transport!(ζ, A, η, α, A´) - @test inner(ζ, A´) ≈ 0 atol = 1e-12 + @test inner(ζ, A´) ≈ 0 atol = 1.0e-12 end diff --git a/test/utility/svd_wrapper.jl b/test/utility/svd_wrapper.jl index 40836bb8c..7f382836e 100644 --- a/test/utility/svd_wrapper.jl +++ b/test/utility/svd_wrapper.jl @@ -8,7 +8,7 @@ using PEPSKit # using PEPSKit: HalfInfiniteEnv # Gauge-invariant loss function -function lossfun(A, alg, R=randn(space(A)), trunc=notrunc()) +function lossfun(A, alg, R = randn(space(A)), trunc = notrunc()) U, S, V, = PEPSKit.tsvd(A, alg; trunc) return real(dot(R, U * V)) + dot(S, S) # Overlap with random tensor R is gauge-invariant and differentiable, also for m≠n end @@ -17,13 +17,13 @@ m, n = 20, 30 dtype = ComplexF64 χ = 12 trunc = truncspace(ℂ^χ) -rtol = 1e-9 +rtol = 1.0e-9 Random.seed!(123456789) r = randn(dtype, ℂ^m, ℂ^n) R = randn(space(r)) -full_alg = SVDAdjoint(; rrule_alg=(; alg=:full, broadening=0)) -iter_alg = SVDAdjoint(; fwd_alg=(; alg=:iterative)) +full_alg = SVDAdjoint(; rrule_alg = (; alg = :full, broadening = 0)) +iter_alg = SVDAdjoint(; fwd_alg = (; alg = :iterative)) @testset "Non-truncacted SVD" begin l_fullsvd, g_fullsvd = withgradient(A -> lossfun(A, full_alg, R), r) @@ -46,8 +46,8 @@ end s.data[1:2:m] .= s.data[2:2:m] # make every singular value two-fold degenerate r_degen = u * s * v - no_broadening_no_cutoff_alg = @set full_alg.rrule_alg.broadening = 1e-30 - small_broadening_alg = @set full_alg.rrule_alg.broadening = 1e-13 + no_broadening_no_cutoff_alg = @set full_alg.rrule_alg.broadening = 1.0e-30 + small_broadening_alg = @set full_alg.rrule_alg.broadening = 1.0e-13 l_only_cutoff, g_only_cutoff = withgradient( A -> lossfun(A, full_alg, R, trunc), r_degen @@ -62,7 +62,7 @@ end ) @test l_only_cutoff ≈ l_no_broadening_no_cutoff ≈ l_small_broadening - @test norm(g_no_broadening_no_cutoff[1] - g_small_broadening[1]) > 1e-1 # divergences mess up the gradient + @test norm(g_no_broadening_no_cutoff[1] - g_small_broadening[1]) > 1.0e-1 # divergences mess up the gradient @test g_only_cutoff[1] ≈ g_small_broadening[1] rtol = rtol # cutoff and Lorentzian broadening have similar effect end @@ -100,8 +100,8 @@ end s.data[1:2:m] .= s.data[2:2:m] # make every singular value two-fold degenerate symm_r_degen = u * s * v - no_broadening_no_cutoff_alg = @set full_alg.rrule_alg.broadening = 1e-30 - small_broadening_alg = @set full_alg.rrule_alg.broadening = 1e-13 + no_broadening_no_cutoff_alg = @set full_alg.rrule_alg.broadening = 1.0e-30 + small_broadening_alg = @set full_alg.rrule_alg.broadening = 1.0e-13 l_only_cutoff, g_only_cutoff = withgradient( A -> lossfun(A, full_alg, symm_R, symm_trspace), symm_r_degen @@ -116,7 +116,7 @@ end ) @test l_only_cutoff ≈ l_no_broadening_no_cutoff ≈ l_small_broadening - @test norm(g_no_broadening_no_cutoff[1] - g_small_broadening[1]) > 1e-2 # divergences mess up the gradient + @test norm(g_no_broadening_no_cutoff[1] - g_small_broadening[1]) > 1.0e-2 # divergences mess up the gradient @test g_only_cutoff[1] ≈ g_small_broadening[1] rtol = rtol # cutoff and Lorentzian broadening have similar effect end diff --git a/test/utility/symmetrization.jl b/test/utility/symmetrization.jl index f221d39a5..1e3749c70 100644 --- a/test/utility/symmetrization.jl +++ b/test/utility/symmetrization.jl @@ -8,7 +8,7 @@ using TensorKit peps_depth = symmetrize!(deepcopy(peps), ReflectDepth()) peps_reflect = _fit_spaces( - InfinitePEPS(reverse(map(herm_depth, peps_depth.A); dims=1)), peps_depth + InfinitePEPS(reverse(map(herm_depth, peps_depth.A); dims = 1)), peps_depth ) @test peps_depth ≈ peps_reflect end @@ -18,7 +18,7 @@ end peps_width = symmetrize!(deepcopy(peps), ReflectWidth()) peps_reflect = _fit_spaces( - InfinitePEPS(reverse(map(herm_width, peps_width.A); dims=2)), peps_width + InfinitePEPS(reverse(map(herm_width, peps_width.A); dims = 2)), peps_width ) @test peps_width ≈ peps_reflect end @@ -41,12 +41,12 @@ end @test peps_full ≈ _fit_spaces(rotr90(peps_full), peps_full) peps_reflect_depth = _fit_spaces( - InfinitePEPS(reverse(map(herm_depth, peps_full.A); dims=1)), peps_full + InfinitePEPS(reverse(map(herm_depth, peps_full.A); dims = 1)), peps_full ) @test peps_full ≈ peps_reflect_depth peps_reflect_width = _fit_spaces( - InfinitePEPS(reverse(map(herm_width, peps_full.A); dims=2)), peps_full + InfinitePEPS(reverse(map(herm_width, peps_full.A); dims = 2)), peps_full ) @test peps_full ≈ peps_reflect_width end