Implement symmetric operators by basis transformation + projection#52
Conversation
Symmetric operators are now generated from their Trivial counterparts by applying a documented basis transformation (exposed as basis_transform) and projecting onto the symmetric tensor structure via TensorKit's TensorMap(::AbstractArray, ...) constructor. Incompatible symmetries are detected automatically and throw an informative ArgumentError. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Z2Irrep uses the Hadamard transformation onto the spin-flip eigenbasis, U1Irrep a permutation to TensorKit's charge order, and SU2Irrep the identity (descending-m convention). All hand-written symmetric blocks are replaced by projection of the Trivial operators. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The U1Irrep grading is a refinement of the fermion-parity grading with identical basis order, so the transformation is the identity and all U1 operators are generated by projection of the fZ2 versions. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All 9 (particle, spin) symmetry combinations are generated from the (Trivial, Trivial) operators. The basis transformation is a permutation derived from the sector order; for SU2Irrep particle symmetry the eta-pairing doublet (|ud>, |0>) is combined with the documented staggered gauge G = i^n per site. This newly enables half_ud_num for all SU2 combinations, the spin operators and S_plus_S_min/S_min_S_plus/S_exchange with SU2 particle symmetry, and S_exchange for (SU2, SU2). It also fixes a bug where the hand-written e_plus_e_min/e_min_e_plus with SU2 spin symmetry were transposed relative to their (Trivial, Trivial) counterparts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- test/hubbardoperators.jl: per-operator availability predicates over all 9 symmetry combinations, spectral comparisons for the newly enabled operators, regression pins for the staggered-gauge e_hopping values and the e_plus_e_min matrix-element direction, and a particle-hole symmetric Hamiltonian spectrum test covering the SU2-particle combos. - new test/utils.jl covering the public symmetrize API. - basis_transform unitarity testsets in all modules. - docs: design section in index.md, symmetrize docstring with doctest. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Exact transformations (permutations, identities, the staggered gauge)
are returned as (Gaussian) integer matrices, which promote to any
scalar type without loss of precision.
- basis_transform accepts an optional element type; this only affects
the Z2 spin Hadamard, the single transformation with inexact entries,
which is now computed at the requested precision.
- The symmetric operators are constructed directly at the requested
scalar type, so real operators stay real end-to-end instead of
round-tripping through complex.
- The default projection tolerance is floored at sqrt(eps(Float64)):
the fusion-tensor data is Float64 for non-abelian sectors, so e.g.
S_exchange(Complex{BigFloat}, SU2Irrep) now constructs (at Float64
accuracy, documented) instead of spuriously failing the symmetry
check. Abelian symmetries preserve full precision.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The public interface now stays within the tensor language: each module's basis_transform returns a TensorMap between the (desymmetrized) trivial reference space and the desymmetrized symmetric space, and the new exported desymmetrize maps graded spaces and tensors onto their dense counterparts over ComplexSpace — the inverse of symmetrize up to the basis transformation. Since a TensorMap cannot mix sector types, both sides of a transformation live over ComplexSpace. Exact transformations keep their integer scalar type (matching the existing tj_projector convention), so promotion remains lossless. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Error messages from symmetrize and _restrict_scalartype are now generic (the method name already appears in the stacktrace). The default projection tolerance is floored at eps of TensorKit.sectorscalartype, the element type of the fusion-tensor data: sectors with exact integer topological data get no floor (full-precision projection), while e.g. SU2Irrep is floored at its Float64 Clebsch-Gordan precision. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
sectorscalartype is only available since the TensorKitSectors split in TensorKit v0.14. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The symmetrization pipeline is now scalar-type faithful by construction: - Trivial constructors respect the requested scalar type: S_y_S_y takes the (exactly zero-imaginary) real part for real types, and the Hubbard S_y requires a complex type, matching SpinOperators. - The staggered gauge for SU2Irrep particle symmetry is only inserted for operators that do not commute with it. For commuting operators, skipping the gauge is an exact identity, so they never touch complex intermediates. Non-commuting operators are genuinely complex and throw an informative error for real scalar types (after the symmetry check, so incompatible operators still report as such). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
🚀 New features to boost your workflow:
|
|
Up to minor suggestions, I think this looks good. |
Co-authored-by: Yue Zhengyuan <yuezy1997@icloud.com> Co-authored-by: Jutho <Jutho@users.noreply.github.com>
|
I think I've addressed the comments that were there, and tried to also include changes to the test suite and keep everything somewhat clear. Let me know if there are other comments, but I think this is ready for another round of review and/or merging. I propose to update the minor version here, since this does seem like quite a substantial change. |
Yue-Zhengyuan
left a comment
There was a problem hiding this comment.
In SpinOperators, do we split spinmatrices into dedicated functions for only one of Sx, Sy, Sz and identity? Then for Sy we can explicitly reject real element type.
Yue-Zhengyuan
left a comment
There was a problem hiding this comment.
I notice that the eigenvalue test test_operator is now only used by test/tjoperators.jl. Can we update the t-J tests to more closely follow the Hubbard ones, and then remove test_operator and its dependence entirely?
The main reason I am not following these is that these operators are defined in function of the Hubbard ones, and not in function of the non-symmetric ones.
I don't think this is fair though: now you really only check that the eigenvalues are the same, while the whole idea of the L-site chain is to also catch errors in eigenvectors as these would interact non-trivially for non-commuting operators. I agree that there are definitely issues with that approach, but I would prefer to update the TJ operators in a separate PR, as this was kind of supposed to be just about the general approach of using basis transformations, not also rewriting the TJ module definitions?
Fine by me, although that really is a separate change, so can we keep this for a follow-up PR as well? |
I overlooked this. Then I'm OK not to change the symmetric-vs-trivial checks for t-J now.
I have restored the old behavior of |
Yue-Zhengyuan
left a comment
There was a problem hiding this comment.
OK to merge if all tests pass!
This is a somewhat larger refactor of this package, as brought up and discussed a couple of times with @Yue-Zhengyuan. The idea is to have a lot less of the manual code set up for the symmetric operators by simply defining the basis transformation once, and then reusing that for all of the defined operators.
This has a number of benefits: it is more maintainable, less error-prone, and a lot easier to add new operators, both in the package as well as for custom operators in user scripts since it is usually easier to just express the non-symmetric matrix. Maybe less of a huge benefit is that this also gives a more direct error for non symmetric operators - it now really shows how an operator was tried to project onto a symmetric subspace and failed.
I would however say that it also comes with a number of drawbacks: Things might be slightly more expensive, as we now have to do some multiplications and projections, and it is no longer an exact analytical mapping (especially for non-abelian), which in particular is bounded by the precision of the symmetric projection, which in turn depends on the CGC precision.
My feeling is that the drawbacks are probably warranted, since I don't think the goal here should be to have a system that generates operators in tight loops as fast as possible, as that case should probably use some form of caching the operators anyways.
Additionally, as the precision of TensorKit calculations is anyways bounded by the precision of the Fsymbol and Rsymbols, it probably does not actually make that much of a difference that the operator entries have small errors of the same magnitude.
An important follow-up is probably to actually make sure to make documentation pages for these conventions, as for now this is mostly restricted to the docstrings.
I can have a look at that, but I first would like some feedback and opinions.