Skip to content
arnab82Public

About

CAMPS + Pauli Propagation: short-time dynamical correlators via Clifford-augmented MPS

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

4 Commits

Folders and files

Repository files navigation

CAMPS-PP — CAMPS + Pauli Propagation

CI Docs

Documentation is built with Documenter.jl (sources in docs/) and deployed by the Documentation workflow. (Serving the site via GitHub Pages requires enabling Pages for the repository — available for public repos, or private repos on a plan that includes Pages.)

Short-time Heisenberg Pauli propagation followed by correlator measurements against a Clifford-augmented matrix-product state (CAMPS). Operator evolution uses PauliOperators.jl; ITensors handles MPS optimization and MPO contractions.

Dependency note. Project.toml pins PauliOperators via a [sources] git URL (https://github.com/arnab82/PauliOperators.jl.git), which provides SparsePauliVector, trotterize, evolve!, and the truncation strategies. Pkg.instantiate() fetches it automatically; Manifest.toml is git-ignored.

The unpublished manuscript used to derive this implementation remains local; it is not required at runtime and is not stored in this repository. See notes/THEORY.md for the equations and implementation conventions.

Layout

camps/
├── src/          # source modules
│   ├── CAMPSFlow.jl         # Pauli→MPO, Clifford circuits, Clifford-frame
│   │                        #   observable algebra, outer-loop CAMPS/DMRG
│   ├── clifford_group.jl    # full 720-element two-qubit Clifford group
│   ├── camps_fused_dmrg.jl  # production-style fused-into-DMRG disentangler
│   ├── clifford_nonlocal.jl # long-range (vertical-bond) Clifford disentangling
│   └── CAMPSCorrelators.jl  # lattice Hamiltonians, PauliTrajectory, short-time
│                            #   propagation, MPS/CAMPS correlator evaluation
├── examples/     # experiment drivers (all run end-to-end)
│   ├── run_camps_4x4_afm_periodic.jl   # 4x4 AFM torus; reps + disentangler opts
│   ├── run_camps_2d_heisenberg_probe.jl
│   ├── run_camps_heisenberg_spin_benchmark.jl
│   ├── run_camps_validation_1d.jl
│   ├── run_camps_correlators.jl
│   ├── run_camps_xx_memory_study.jl
│   └── run_camps_l128_cutoff_sweep.jl
├── notebooks/    # exploratory Jupyter notebooks (IJulia)
│   ├── 01_correlators.ipynb            # dynamical correlators (Dict + SPV)
│   ├── 02_ground_state_methods.ipynb   # outer/fused, light/full, local/nonlocal
│   └── 03_convergence.ipynb            # δ→0 + χ convergence post-processing
├── postprocessing/  # convergence analysis on computed correlators
│   ├── convergence.jl                 # δ→0 + χ extrapolation (CAMPSConvergence)
│   └── run_8x8_afm_periodic_fused.jl  # 8x8 fused CAMPS + full convergence run
├── notes/        # theory and design notes
│   ├── THEORY.md
│   ├── CAMPS_GROUND_STATE.md  # how |Ψ₀⟩=D|χ⟩ is optimized
│   ├── DISENTANGLING.md       # outer vs fused disentangling + full Clifford group
│   └── REPRESENTATIONS.md   # PauliSum (Dict) vs SparsePauliVector (SPV)
├── test/runtests.jl
├── results/      # generated artifacts (git-ignored)
└── Project.toml  # isolated env pinned to the local PauliOperators 3.1 source

The [sources] entry in Project.toml resolves PauliOperators to the sibling checkout, so the propagation code uses trotterize, evolve!, and the truncation strategies from PauliOperators 3.1 rather than the older registry version in the parent SPD environment.

Setup and tests

From this directory:

julia --project=. -e 'import Pkg; Pkg.instantiate()'
julia --project=. test/runtests.jl

Operator representations: Dict and SPV

Every operator-consuming routine accepts either PauliOperators representation, and each is exercised interchangeably:

  • :dict — the Dict-backed PauliSum{N,T} (PauliBasis ⇒ coefficient).
  • :spv — the flat, sorted, zero-allocation SparsePauliVector{N,W,T}.

build_pauli_trajectory takes a representation keyword (:dict default, :spv) that selects the storage of the propagated operator, independent of the Hamiltonian's own representation. The Clifford-frame conjugation (apply_circuit_heisenberg) preserves whichever representation it is handed, so SparsePauliVector inputs stay SparsePauliVector through readout. Both paths produce numerically identical correlators for a fixed Trotter generator order; see notes/REPRESENTATIONS.md.

Run the 4x4 antiferromagnetic Heisenberg torus with both representations and an automatic agreement check:

julia --project=. examples/run_camps_4x4_afm_periodic.jl both 24 0.20 0.05
#                                                       ^rep ^maxdim ^t_max ^dt

CAMPS disentangling and the full Clifford group

The ground state |Ψ₀⟩ = D|χ⟩ offloads MPS entanglement into a Clifford dressing D. Two disentangling strategies and the full two-qubit Clifford candidate set are available (see notes/DISENTANGLING.md):

  • Clifford bank — clifford_bank = :full uses all 720 two-qubit Cliffords (the group modulo Paulis; the full 11,520 is 16× redundant for entanglement), or :light for the compact validation bank.
  • :outer — alternate complete DMRG runs with Clifford disentangling sweeps.
  • :fused — production style: Clifford selection fused into each two-site DMRG update before the SVD, so |χ⟩ is truncated only after entanglement is offloaded (smaller bond dimension for a given accuracy).
  • Locality (:fused only) — clifford_locality = :local (MPS-adjacent bonds) or :local_nonlocal, which also disentangles the long-range vertical 2D bonds via an exact Clifford SWAP network. All-Clifford and representability- preserving, with a do-no-harm safeguard so it is never worse than :local (see notes/DISENTANGLING.md for the measured verdict on the 4×4 torus).
# production-style: fused disentangling + full 720-element Clifford group
ground = run_camps_ground(H, sites; disentangler=:fused, clifford_bank=:full,
                          maxdims=[400], n_outer=6)

# also disentangle the long-range vertical bonds (all-Clifford, SWAP network)
ground = run_camps_ground(H, sites; disentangler=:fused, clifford_bank=:full,
                          clifford_locality=:local_nonlocal, lattice=(nx, ny),
                          periodic=true, maxdims=[400], n_outer=6)

Both strategies produce the same CAMPSResult and feed the correlator pipeline identically. Correctness is covered in test/runtests.jl (group closure = 720, identity-only fused = plain DMRG, and two-route frame-consistent energies).

Convergence post-processing

postprocessing/convergence.jl (module CAMPSConvergence) reproduces the two-axis convergence protocol on already-computed correlators — the propagation and CAMPS optimization run once; this is cheap readout-side analysis:

  • δ→0 coefficient extrapolation — epsilon_clip_sweep clips the readout at a ladder of coefficient thresholds ε_clip, recording the discarded weight δ; extrapolate_delta_to_zero linearly extrapolates the correlator to δ→0, removing the coefficient-truncation bias.
  • χ bond-dimension convergence — bond_dimension_sweep SVD-truncates the frame MPS |χ⟩ to a ladder of bond dimensions (no re-optimization), repeats the δ→0 extrapolation at each, and print_bond_convergence tabulates the residual |corr(χ) − corr(χ_max)|.

Feed the δ→0-extrapolated, χ-converged correlators to a PSD/Prony time extension separately. Full driver:

julia --project=. postprocessing/run_8x8_afm_periodic_fused.jl
# 8x8 periodic AFM, fused CAMPS + full Clifford group, χ_list={120,400}, t≤0.5,
# writing extrapolated correlators to results/camps_8x8_afm_fused_<ts>.jld2
# (expensive; append e.g. `3 3 12 2 0.10 0.05 4,8 5e-3,1e-3 full` to scale down)

Minimal correlation workflow

using ITensors, ITensorMPS, PauliOperators

include("src/CAMPSCorrelators.jl")
using .CAMPSCorrelators

nx, ny = 4, 4
N = nx * ny
sites = siteinds("S=1/2", N)
H = heisenberg_square_paulisum(nx, ny; periodic=true)   # AFM torus (J = +1)

trajectory = build_pauli_trajectory(
    H;
    source_site=1,
    axis=:X,
    times=0.0:0.05:0.30,
    dt=0.05,
    order=2,
    coefficient_cutoff=1e-8,
    max_weight=6,
    representation=:spv,           # or :dict
)

ground = run_camps_ground(H, sites; maxdims=[32, 64, 128], n_outer=2)

rows = camps_axis_correlators(
    trajectory,
    ground.result,
    sites;
    target_sites=1:N,
    axis=:X,
    normalization=:spinhalf,
    readout_cutoff=1e-3,
)

Each result row records the complex correlator, propagation term count, accumulated propagation truncation diagnostic, readout term count, and the coefficient 2-norm removed by the optional readout cutoff.

Model conventions

heisenberg_square_paulisum constructs

$$H = J\sum_{\langle i,j\rangle}\mathbf S_i\cdot\mathbf S_j = \frac{J}{4}\sum_{\langle i,j\rangle} (X_iX_j+Y_iY_j+Z_iZ_j)$$

in a one-dimensional snake ordering; J = +1 (the default) is antiferromagnetic. family=:spinhalf in the MPO converter uses X=2Sx, Y=2Sy, and Z=2Sz; the factors are folded into each MPO term. The correlation normalization :spinhalf therefore multiplies a Pauli-Pauli correlator by 1/4.

Current scope

The Clifford search intentionally uses a compact validation bank rather than all 11,520 two-qubit Clifford elements, and the Clifford step is performed as an outer sweep between ordinary DMRG optimizations. Those are controlled approximations to a production CAMPS optimizer and are stated explicitly in notes/THEORY.md; the Clifford-frame observable algebra itself is exact and covered by dense tests.

About

CAMPS + Pauli Propagation: short-time dynamical correlators via Clifford-augmented MPS

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages