|
Uni20
Asynchronous tensor and runtime library.
|
This document describes the currently implemented uni20 quantum-number API in src/uni20/symmetry/, together with the near-term extension points that will matter for tensor-network and DMRG work.
The implemented layer contains:
Symmetry is a canonicalized runtime handle for a direct-product symmetry specification such as N:U(1),Sz:U(1).QNum is a packed irrep label together with the Symmetry needed to interpret it.QNumList is a mutable ordered quantum-number container used while building or regularizing spaces.BlockSpace is an immutable coalesced (QNum, dim) tensor space.IrregularSpace is an immutable ordered sequence of (QNum, dim) blocks whose quantum numbers may repeat.LocalSpace is an immutable ordered local-state space whose charges may repeat.QNumSpace is an immutable one-irrep space.DenseSpace is an immutable symmetry-neutral dense extent.Space and SymmetrySpace describe their common contracts.Domain<...> and Codomain<...> are ordered morphism-boundary values.U1 is the first value-level quantum-number type and currently the only implemented symmetry factor.The relevant headers are:
src/uni20/symmetry/block_space.hppsrc/uni20/symmetry/block_sector.hppsrc/uni20/symmetry/dense_space.hppsrc/uni20/symmetry/irregular_space.hppsrc/uni20/symmetry/local_space.hppsrc/uni20/symmetry/morphism_boundary.hppsrc/uni20/symmetry/qnum_space.hppsrc/uni20/symmetry/space.hppsrc/uni20/symmetry/symmetry.hppsrc/uni20/symmetry/qnum.hppsrc/uni20/symmetry/u1.hppSymmetry is constructed primarily from a string specification:
Current properties:
N and Sz are semantic, not decorative.Symmetry also exposes:
valid()factor_count()factors()to_string()Symmetry::parse(...)U1 is the value-level irrep type for one U(1) factor:
Implemented operations:
dual(U1)qdim(U1) returning 1.0degree(U1) returning 1operator+ and operator-to_string(U1) using decimal half-integer form such as 2.5to_string_fraction(U1) using fractional form such as 5/2std::format, and std::hashU(1) values are stored as half_int, so both integer and half-integer charges are supported.
half_int is basic_half_int<std::int64_t>; from_twice(n) deduces its signed storage type from n. Conversions between basic_half_int storage types preserve the exact doubled value. Widening (including equal-range storage types) is implicit, constexpr, and non-throwing:
Narrowing is explicit and constexpr for representable values. It throws std::overflow_error when the doubled value is outside the destination's range, rather than truncating or rounding:
These constructors do not introduce mixed-storage binary arithmetic overloads; convert operands to a common storage type before using such operations.
QNum is the packed irrep label used by the tensor code:
Implemented operations:
QNum::identity(sym)valid()symmetry()raw_code()dual(q)is_identity(q)qdim(q)degree(q)to_string(q) producing comma-separated named components such as N=1,Sz=0.5u1_component(q, "N")coerce(q, target_symmetry) for named-component coercionoperator+ as the unique-fusion shortcut for currently implemented abelian factorsFor the current U(1) implementation, missing component assignments in make_qnum(...) default to the identity.
QNumList is a mutable ordered quantum-number container with one important invariant: every entry must have the same Symmetry.
Implemented operations:
SymmetrySymmetry plus an initializer listsymmetry()size()empty()push_back(...)clear()contains(...)sort()normalize() which sorts and removes duplicatesIts construction-time semantics are:
SymmetryThis makes it useful while building sparse physical legs, sparse MPO bond spaces, and regularization metadata. Persistent tensor boundaries should use the immutable LocalSpace or BlockSpace values.
Space is a concept satisfied directly by concrete space values. It requires copyable value semantics, exact equality, and a mutable std::string label:
SymmetrySpace additionally requires an explicit Symmetry:
The structural portion of a space is immutable. set_label(...) is the only mutation supplied by these values. Exact equality includes the label.
BlockSpace is the immutable coalesced tensor-space representation. It stores canonical unique blocks (QNum, dim).
Implemented operations:
SymmetrySymmetry plus an initializer list or input range of blockssymmetry()size()empty()total_dim()contains(...)sectors()label() and set_label(...)Construction requires a valid explicit Symmetry, including for an empty space. Each block dimension must be positive and every QNum must belong to that symmetry. Construction sorts blocks canonically and rejects repeated QNum sectors.
IrregularSpace is the valid non-regular block-space representation. It stores an ordered sequence of BlockSector values:
QNum sectors are preservedSymmetrylabel() and set_label(...) manage its semantic leg labelIt is useful when projecting out or forgetting part of a symmetry. Sectors which were distinct under the original symmetry may acquire the same projected QNum, while their existing block segmentation and order remain useful. Representing that result as an IrregularSpace avoids immediate data movement.
LocalSpace is the immutable ordered local-state representation:
Symmetry and an initializer list, input range, or QNumListQNum values are preservedSymmetryqnums() exposes a read-only spanlabel() and set_label(...) manage the semantic leg labelIt is suitable for physical legs where different basis states may carry the same charge.
QNumSpace contains one valid QNum, with the symmetry obtained from that irrep. It is useful for fixed-charge boundaries and one-irrep legs. Its only mutable field is the string label.
DenseSpace contains a dense extent and string label. It deliberately has no Symmetry: a dense leg may batch or bundle symmetric tensors without contributing a charge to their selection rules. Zero extent is permitted.
Three explicit regularization helpers are implemented:
regularize(QNumList) coalesces the sparse space into a BlockSpace and records, for each original entry, the destination block and offset inside that blockregularize(LocalSpace) performs the same coalescing for an immutable local space and preserves its labelregularize(IrregularSpace) coalesces repeated blocks and records the destination canonical block plus half-open degeneracy range for every original blockConvenience conversions are:
to_block_space(QNumList)to_block_space(LocalSpace)to_block_space(IrregularSpace)These helpers are intended to support explicit sparse-to-coalesced transitions without making coalescing automatic. BlockSpace itself is always regular, so there is no regularize(BlockSpace) operation.
Each symmetry factor is encoded to a factor-local uint64_t, and QNum combines those factor-local codes into one tagged uint64_t payload. Inline codes use the low 63 bits. Bit 63 is reserved for a future process-local, interned out-of-line representation; construction currently throws std::overflow_error when a combined code does not fit in the inline range.
For U(1), the local encoding is chosen so that numerical order matches the natural display order:
0+1/2-1/2+1-1+3/2-3/2...This ordering is useful both for debugging output and for canonical sorting in QNumList and canonical block ordering in BlockSpace.
Component names are used to align related symmetries.
Examples:
N:U(1) into N:U(1),Sz:U(1) fills the missing Sz component with the identityN:U(1),Sz:U(1) into N:U(1) is allowed only when Sz is the identityThis is intended to make block bookkeeping practical when related spaces carry slightly different direct-product labels.
The current code is deliberately U(1)-first. The intended growth path is:
New symmetry factors should be addable without editing Symmetry itself. The current internal adapter layer already points in that direction:
U1SymmetryFactor<T> adapteroperator+ is only the unique-fusion shortcut. A future non-abelian API will need an explicit fusion result type that can represent:
That design is intentionally deferred until there is a concrete non-abelian implementation to drive it.
The long-term target is broader than ordinary group irreps. Uni20 will need to support braided fusion tensor categories closely enough to model:
That means the eventual symmetry context must carry more than just fusion and duality data. It will also need a place for braid data such as R-matrices.
The current code does not yet implement F-moves or recoupling coefficients. Future APIs are expected to cover at least:
This layer will matter once Uni20 moves beyond abelian block bookkeeping and starts doing genuine non-abelian or braided tensor algebra.
Coupling caches will be partitioned by normalized symmetry context, rather than stored in one global cross-symmetry cache. Cache keys will therefore contain only ordered irrep codes meaningful within the owning context and will not repeat the Symmetry pointer. If an operation combines compatible symmetry descriptions, it must first normalize every QNum to one common target—for example by matching named components, inserting identities, and reordering components—then query that target context's cache. Normalization must reject non-identity component loss or incompatible factor types.
The implemented Domain<Spaces...> and Codomain<Spaces...> value templates and generic Dual<S> adaptor provide the two independent orientation axes:
Dual<S>;Domain<...> versus Codomain<...>.Both axes are represented explicitly. Each boundary retains concrete or dual space types and ordered values. Space structure is exposed read-only, while set_label<I>(...) changes one leg label without replacing its space. Domain<> and Codomain<> represent the tensor unit.
The earlier conjugate<T> / co<T> direction-wrapper proposal conflated these axes and is no longer the intended design. Moving a leg between domain and codomain is an explicit wire-bending operation that toggles object duality. See Spaces, Duals, and Tensor Morphisms.
The first U(1) three-leg tensor can therefore be modeled as a morphism such as:
This does not require direction variants of BlockSpace or QNumList.
The dual-space adaptor is implemented. The remaining helpers in this section are deferred symmetry-side tasks for the U(1) DMRG path.
Likely next convenience helpers on spaces:
find_block(q) / index_of(q) on BlockSpacedim(q) on BlockSpaceQNumList and BlockSpacedelta_shift spiritThese are expected to become useful as soon as the MPO and AMatrix compiler code is written.
The morphism layer defines generic Dual<S> using the symmetry's value-level dual(QNum) operation. It does not require parallel concrete families such as DualBlockSpace and DualLocalSpace. Dualization is a categorical adaptor of the space, not a mutation or canonicalization of its stored sector structure.
The current regularization helpers provide the forward block/index mapping needed to coalesce sparse spaces explicitly. Later work may also want:
The first U(1) DMRG path does not require those operators yet.
The symmetry headers reference this document directly so that API changes are more likely to prompt a doc update in the same patch. If you change the public surface of Symmetry, QNum, QNumList, BlockSpace, IrregularSpace, LocalSpace, QNumSpace, DenseSpace, Domain, Codomain, or U1, update both:
src/uni20/symmetry/