Add two-site BUG time integrator#1
Open
madhavmen wants to merge 15 commits into
Open
Conversation
Feature release delivering the first stable version of Alice, an open-source project for 1D tensor network algorithms built on Nicole. The release covers the full MPS/MPO infrastructure, a TOML-driven AutoMPO Hamiltonian builder, three-scheme DMRG with environment caching, and comprehensive physics model support for spin, fermionic, and Hubbard systems. No breaking changes; this is the initial public API. Version: 0.1.0 Release Date: May 4, 2026 New Features: Tensor Network Infrastructure (network.py, observe.py): - MPS, MPO, and Network classes providing block-sparse matrix product states and operators with full support for Abelian and non-Abelian (SU(2)) symmetry groups inherited from Nicole - Left- and right-canonicalization routines with norm computation and bond-consistency validation - observe function for MPS-MPO-MPS expectation-value computation, accepting both pure MPS and mixed MPS/MPO states AutoMPO Construction (autompo.py, interaction.py): - build_interaction: TOML-configured interaction map builder with built-in model presets and support for user-defined model functions - build_hamiltonian: term-by-term MPO assembler accumulating interactions via Nicole's oplus, then compressing with two canonical sweeps; handles arbitrary symmetry groups including non-Abelian SU(2) - compact_every parameter for incremental compaction during large Hamiltonian builds to limit intermediate bond dimension growth - Interaction, Interaction1Site, Interaction2Site data types for unambiguous representation of on-site and two-site coupling terms Lattice Geometries (geometry.py): - 1D chain: straight nearest-neighbor traversal for standard spin and fermion chains - 2D snake traversal: boustrophedon MPS ordering for rectangular lattices, supporting quasi-1D cylinders and ladders - 2D square lattice: full nearest-neighbor interaction map with both horizontal and vertical bonds - Custom geometry support via the build_geometry dispatch mechanism Physical Spaces (system.py): - build_bosonic: spin-s site with spherical spin operator templates and Jordan-Wigner-free intermediate tensors; supports U(1) and SU(2) - build_fermionic: spinless-fermion site with Jordan-Wigner-dressed hopping templates and number operator; supports U(1) and Z(2) - build_conductor: spinful-fermion site with JW-dressed hopping templates, spin operators, and double-occupancy operator; supports U(1)xU(1), Z(2)xU(1), U(1)xSU(2), and Z(2)xSU(2) Physics Models (models.py): - Heisenberg: spin-s Heisenberg chain with NN coupling J and optional NNN coupling J'; built on build_bosonic; supports U(1) and SU(2) - Free fermion: spinless tight-binding chain with NN hopping t, optional NNN hopping t', and optional chemical potential mu; built on build_fermionic; supports U(1) and Z(2) - Hubbard: spinful Hubbard chain with NN hopping t, on-site interaction U, optional NNN hopping t', and chemical potential mu referenced to half-filling; built on build_conductor; supports all four Band symmetry sectors DMRG Algorithm (dmrg.py, sweep.py, scheme_1s.py, scheme_2s.py, complement.py, davidson.py): - Three update schemes: 1-site (bond-dimension preserving, for convergence refinement), 2-site (SVD truncation for diagnostic checks), and 1-site-plus (primary scheme for bond dimension growth via a complement isometry projected from the 2-site residual) - Davidson eigensolver operating directly in the symmetry-block-sparse space with thick restart; uses the plain residual as the correction vector (no preconditioning) - Energy-based convergence criterion with configurable threshold per sweep - dmrg.Options.from_toml for TOML-driven configuration; dmrg.run entry point returning a dmrg.Summary with sweep history and discarded weights Environment Caching (environ.py): - Environment class with optional disk-spilling of environment blocks via torch.save for long chains that exceed available RAM - Sliding in-memory window with configurable size limiting peak memory usage - Asynchronous I/O on a background thread to overlap disk transfers with sweep computation Systematic Logging (logging.py): - configure_logging: one-call setup of Alice's logging hierarchy with configurable level and format, backed by Python's standard logging module - Sweep-by-sweep diagnostics logging site index, energy, bond dimensions, and discarded weight per half-sweep - Geometry and interaction-map summaries logged as ASCII diagrams at construction time Test Suite (538 tests): - 538 tests pass, 0 skipped. - New test modules: tests/algorithm/dmrg/test_davidson.py (10 tests), test_dmrg.py (36), test_environ.py (39), test_scheme_1s.py (5), test_scheme_1sp.py (31), test_scheme_2s.py (11), test_sweep.py (14); tests/algorithm/test_interface.py (11); tests/diagonaliztn/test_autompo.py (38), test_conductor.py (8), test_freefermion.py (4), test_heisenberg.py (8); tests/network/test_network.py (113), test_observe.py (12); tests/physics/test_chain.py (19), test_geometry.py (11), test_models.py (43), test_square.py (39), test_system.py (86) Statistics and Scope: - 196 commits in the initial release. - 63 files changed: 15908 insertions, 26 deletions. - Source modules: src/alice/network/network.py, autompo.py, interaction.py, observe.py; src/alice/physics/geometry.py, models.py, system.py; src/alice/algorithm/dmrg/dmrg.py, environ.py, sweep.py, scheme_1s.py, scheme_2s.py, complement.py, davidson.py; src/alice/algorithm/interface.py; src/alice/logging.py - Test modules: tests/algorithm/dmrg/, tests/algorithm/, tests/diagonaliztn/, tests/network/, tests/physics/ - Docs pages touched: README.md Rationale: Alice is structured around a shared core — the MPS, MPO, and network infrastructure — on top of which algorithms and models are developed as independent units. The two-level physics layer (space builders in system.py, Hamiltonian models in models.py) separates operator construction from coupling assignment, allowing either layer to be replaced without modifying the other. The AutoMPO pipeline delegates all sector arithmetic to Nicole's oplus, which makes the Hamiltonian builder agnostic to the symmetry group and correct for SU(2) without any special-casing. The three DMRG schemes are designed to be used in sequence: 1-site-plus sweeps drive bond dimension growth via controlled expansion, and 1-site sweeps refine convergence once the target bond dimension is reached. The 2-site scheme is provided primarily for diagnostic purposes and would rarely be the scheme of choice in a production calculation. Environment caching with asynchronous I/O ensures that chain lengths are limited by disk space rather than RAM, enabling production runs on modest hardware. The TOML-driven configuration keeps the user-facing API concise and reproducible across workstations and HPC clusters without code changes. Breaking Changes: None. This is the initial public release; there is no prior API to break. Requirements: Python >= 3.11, PyTorch >= 2.5, Nicole >= 0.3.6, Yuzuha >= 0.1.5. All 538 tests pass.
Documentation update release introducing the complete Alice documentation site. A Material-themed MkDocs site with 45 pages across getting-started guides, a full API reference, and worked DMRG examples is added. The PyPI distribution is concurrently renamed from alice to alice-net; the import namespace and all public APIs are unchanged. No breaking changes. Version: 0.1.1 Release Date: May 6, 2026 Documentation: Infrastructure (mkdocs.yml, docs/overrides/, docs/stylesheets/, docs/hooks.py): - mkdocs.yml: full site configuration with Material theme, custom alice color scheme, three-tab navigation, dark/light/system theme switching, content and search features - docs/overrides/home.html: custom landing page with hero image and feature cards - docs/stylesheets/extra.css: alice color palette, hero-section layout, light/dark overrides - docs/hooks.py: post-processing hook converting inline bullet text in table cells to proper HTML list elements - Plugins: mkdocstrings (NumPy-style docstrings), markdown-exec (configured for future live execution), git-revision-date-localized, git-committers - Extensions: arithmatex (MathJax), superfences (Mermaid), tabbed, emoji (Material + FontAwesome) Getting Started (docs/getting-started/, 7 pages): - what-is-alice.md: philosophy, relationship with Nicole, supported symmetry groups and algorithms - installation.md: pip/uv install, development setup, optional dependency groups - core-concepts.md: MPS/MPO block-sparse structure, symmetry sectors, DMRG sweep logic - quick-start.md: end-to-end Heisenberg DMRG example from site definition through energy output - contributing.md: branch model, coding conventions, test requirements - git-control.md: tagging, branching, and release workflow for the Alice project - changelog.md: version history beginning with v0.1.0 API Reference (docs/api/, 30 pages): - Network: Network, MPS, MPO (construction, canonicalization, norm, serialization, SVD compression, norm redistribution); observe (expectation-value sweep with SU(2) Bridge weight support) - Interaction: Interaction, Interaction1Site, Interaction2Site dataclass references; build_interaction with plugin section documentation - Geometry: generate_snake_order, intrcmap_1dchain, intrcmap_square, build_geometry with parameter tables and usage notes - Local Space: build_bosonic, build_fermionic, build_conductor with symmetry-mode tables - Hamiltonian: build_hamiltonian; build_heisenberg, build_free_fermion, build_hubbard - DMRG: dmrg.Options (full parameter reference with TOML key mapping), dmrg.Summary (output fields and serialization), dmrg.run (update schemes 1s/2s/1sp, convergence criteria) - Logging: configure_logging (handler configuration, log levels, output file naming) Examples (docs/examples/, 8 pages): - dmrg/heisenberg.md: ground-state energy of a spin-1/2 chain, U(1) and SU(2) symmetry comparison - dmrg/free-fermion.md: tight-binding chain benchmark against exact diagonalization - dmrg/hubbard.md: charge and spin sector targeting in a single-band Hubbard model; disk-caching walkthrough for large chains - autompo-toml.md: [[interaction]] tables, [plugin] sections for user-defined models, built-in presets - extensions/custom-geometry.md, custom-space.md, custom-model.md: guides for extending Alice outside the built-in presets Packaging: Distribution Renamed to alice-net (pyproject.toml, src/alice/): - Distribution name changed from alice to alice-net; wheel target added pointing to src/alice; project URLs (homepage, documentation, repository, issues) expanded - Copyright notices updated from "Alice library" to "Alice project" across all source, test, and example files - README badge links and logging startup banner updated to reflect alice-net - Install: pip install alice-net or uv add alice-net; import namespace alice is unchanged Test Suite (538 tests): - 538 tests pass, 0 skipped. - No new test files added; this release is documentation and packaging only. The existing test suite is unchanged. Statistics and Scope: - 42 commits since v0.1.0. - 112 files changed: 3228 insertions, 64 deletions. - Source modules touched: src/alice/__init__.py, src/alice/logging.py, src/alice/network/__init__.py, src/alice/physics/__init__.py, src/alice/algorithm/__init__.py (copyright notices); pyproject.toml (version, distribution name) - Test modules touched: all test files (copyright notice update) - Docs pages touched: 45 new pages across docs/api/, docs/examples/, docs/getting-started/; docs/index.md, docs/hooks.py, docs/overrides/home.html, docs/stylesheets/extra.css; mkdocs.yml Rationale: Building the documentation alongside the v0.1.1 release makes the site immediately accurate and prevents the documentation debt that accumulates when docs are written separately from implementation. The Material theme and mkdocstrings stack mirrors the Nicole documentation site, which keeps the user experience consistent across both projects and reduces the maintenance overhead of running two divergent documentation systems. Renaming the PyPI distribution to alice-net removes a potential package conflict without touching any import paths or API surfaces, making the change invisible to users who already have Alice code written. Breaking Changes: None. All previously valid calls continue to work unchanged. The only user-visible change outside the documentation is the PyPI distribution name. Requirements: Python >= 3.11, PyTorch >= 2.5, Nicole >= 0.3.6, Yuzuha >= 0.1.5. All 538 tests pass.
Feature release introducing the Geometry dataclass, Kagome lattice support, a full traversal order naming overhaul, and MPS/MPO text diagram rendering. The geometry module is restructured into independent per-lattice modules (chain.py, square.py, kagome.py), and the build_interaction pipeline is extended with an intrcmap_fn hook. Several breaking changes to the geometry and build_interaction APIs are introduced. Version: 0.1.2 Release Date: May 11, 2026 New Features: Geometry Dataclass (geometry.py, chain.py, square.py, kagome.py): - Geometry dataclass introduced to carry the fully-resolved lattice as a single object: cfg (configuration dict), ord_map (tuple-keyed coordinate-to-index map), and latt (list of all lattice coordinates). - build_geometry returns a Geometry instance; build_intrcmap generates the bare interaction map from a Geometry, enabling independent reuse without rebuilding the lattice. - Geometry exposes convenience properties: L (chain length), lx, ly, lattice, traverse, to_1d, to_2d. Lattice Modules Refactored (chain.py, square.py): - 1D chain geometry separated into chain.py with build_traversal and intrcmap_1dchain. - 2D square lattice separated into square.py with build_traversal, build_traversal_sequential, build_traversal_serpentine, and intrcmap_square. - All lattice modules expose build_traversal as a public entry point. Kagome Lattice (kagome.py): - intrcmap_kagome generates nearest-neighbor bonds for the 3-sublattice Kagome geometry: N2U (upward-triangle) and N2D (downward-triangle) bond families. - build_traversal supports sequential and serpentine traversal orders. - ord_map keys are (row, col, u) tuples, where u indexes the sublattice within each unit cell. Traversal Order Naming (square.py, kagome.py, geometry.py): - 'snake' renamed to 'serpentine'; 'snake' is no longer recognized. - 'zigzag' renamed to 'sequential'; sequential is now the default traversal for all 2D lattices. - generate_snake_order removed; its logic is now internal to build_geometry's serpentine traversal path. MPS/MPO Text Display (network/display.py, network/network.py): - network_summary renders a text diagram of an MPS or MPO chain, showing node symbols, bond dimensions, and an information block. - MPS.__repr__ and MPO.__repr__ delegate to network_summary for interactive session display. Operator Templates (system.py): - Sp4, Sp4dag, Sm4, Sm4dag operator templates added to build_bosonic and build_conductor for U(1) symmetry mode, enabling separate raising and lowering channels for anisotropic single-channel couplings. build_interaction Pipeline (interaction.py): - intrcmap_fn parameter added as an optional second-stage plugin hook; if provided, it replaces the built-in intrcmap_* dispatch and receives a Geometry instance as its argument. - geometry_fn signature updated: callers must now return a Geometry instance instead of a dict. Documentation: API Reference (docs/api/): - geometry.md: new page documenting the Geometry dataclass. - build-intrcmap.md: new page documenting the build_intrcmap function. - intrcmap-kagome.md: new page with traversal tables and bond diagrams for the Kagome lattice. - generate-snake-order.md removed; replaced by updated build-geometry.md. - build-interaction.md: updated with four-stage pipeline description, intrcmap_fn hook section, and updated return-value types. - mps.md, mpo.md: new string-representation sections with text diagram examples. - mkdocs.yml: geometry section updated; custom-intrcmap.md added to extensions. Getting Started and Examples (docs/): - core-concepts.md: two-stage geometry construction documented in the AutoMPO pipeline section. - custom-geometry.md: updated with Geometry dataclass and separation of geometry and interaction map stages. - custom-intrcmap.md: new extension guide showing how to replace the intrcmap stage with a custom bond filter. - free-fermion.md: NNN hopping section removed; NNN bonds are not supported for 1D chains. - All documentation headings standardized to title case. - changelog.md: version history updated through v0.1.2. Test Suite (659 tests): - 659 tests pass, 0 skipped. - New test files: tests/network/test_display.py (network_summary and _select_sites), tests/physics/test_kagome.py (intrcmap_kagome and build_traversal for Kagome). Statistics and Scope: - 120 commits since v0.1.1. - 66 files changed: 3478 insertions, 826 deletions. - Source modules touched: src/alice/__init__.py, src/alice/network/display.py, src/alice/network/interaction.py, src/alice/network/network.py, src/alice/network/autompo.py, src/alice/network/observe.py, src/alice/physics/__init__.py, src/alice/physics/chain.py, src/alice/physics/geometry.py, src/alice/physics/kagome.py, src/alice/physics/square.py, src/alice/physics/system.py, src/alice/algorithm/dmrg/dmrg.py, src/alice/algorithm/dmrg/scheme_2s.py. - Test modules touched: tests/algorithm/dmrg/conftest.py, tests/algorithm/dmrg/test_scheme_1sp.py, tests/diagonaliztn/test_autompo.py, tests/network/test_display.py, tests/network/test_network.py, tests/physics/test_chain.py, tests/physics/test_geometry.py, tests/physics/test_kagome.py, tests/physics/test_models.py, tests/physics/test_square.py, tests/physics/test_system.py. - Docs pages touched: docs/api/geometry/ (7 files), docs/api/interaction/ (2), docs/api/network/ (4), docs/api/hamiltonian/ (4), docs/api/ (2), docs/examples/extensions/ (4), docs/getting-started/ (5); mkdocs.yml. Rationale: The geometry module was originally a single file mixing traversal-order generation, interaction-map construction, and dispatch logic. Separating these responsibilities into per-lattice modules makes each module small enough to read in isolation and allows new lattice types to be added without touching existing code. The Geometry dataclass formalizes the previously implicit contract between build_geometry and the intrcmap_* functions: instead of passing raw dicts between stages, callers receive a typed object with stable properties. Splitting construction into two explicit stages — build_geometry, which resolves the traversal and coordinate map, and build_intrcmap, which generates bonds — lets users build multiple interaction maps for the same lattice without repeating the traversal computation. This is particularly useful for Kagome, where the 3-sublattice unit cell requires a three-element tuple key (row, col, u); the old 2D-list ord_map did not generalize to this structure. The traversal naming overhaul (snake → serpentine, zigzag → sequential) aligns the public API with the language used in the documentation, and making sequential the default reflects that column-major ordering is the more natural starting point for 2D lattices. The intrcmap_fn plugin hook extends the same compositional philosophy to the bond-generation stage: users can replace only the part of the pipeline they need to customize without touching the geometry construction. Breaking Changes: - build_geometry return type: now returns a Geometry instance instead of a dict. Callers must update references to use Geometry properties (geo.cfg, geo.ord_map, geo.latt, geo.L). - intrcmap_* functions now accept a Geometry instance as their first argument instead of a dict. Direct calls to intrcmap_1dchain, intrcmap_square, or intrcmap_kagome must pass a Geometry object. - build_interaction return type: the third element of the returned tuple is now a Geometry instance (was int). Callers that used the integer chain length must replace it with geo.L. - geometry_fn signature: custom geometry functions passed to build_interaction must now return a Geometry instance, not a dict. - generate_snake_order has been removed. Use build_geometry with traverse='serpentine' to obtain serpentine ordering. - traverse='snake' is no longer recognized. Replace with traverse='serpentine'. Requirements: Python >= 3.11, PyTorch >= 2.5, Nicole >= 0.3.6, Yuzuha >= 0.1.5. All 659 tests pass.
Feature release introducing init_mps, a universal particle-type–agnostic MPS
initializer for DMRG, and atomic per-sweep checkpointing via a new
checkpoint_dir option in dmrg.Options. Network.bond_states is added to expose
physical state counts per bond for non-Abelian simulations. No breaking changes.
Version: 0.1.3
Release Date: May 13, 2026
New Features:
Universal MPS Initializer (automps.py):
- init_mps constructs an initial MPS for DMRG from any (Spc, Op) pair returned
by load_space. Works for bosonic, fermionic, and conductor sites without a
particle_type= argument; the (Spc, Op) pair encodes all symmetry information.
- bond_dim=1: deterministic product state with exact charge targeting. Every
bond carries a single sector; best used with CBE (scheme='1sp') or 2-site
(scheme='2s') DMRG, which expand bond dimension during the first sweep.
- bond_dim>1: random MPS with group-derived bond sectors. Reachable charges are
found by breadth-first search from the center-bond charge to depth 2, keeping
the sector count independent of chain length.
- Auto-balanced config=None heuristic covers all standard even-L half-filled
cases: alternating high/low sectors for 2-sector spaces, single neutral-charge
sector for 3-sector spaces, alternating neutral-pair for 4-sector spaces, and
the SU(2) dimer path for pure-SU(2) spaces. Explicit config lists override the
auto-selection for unusual fillings or odd L.
- Exported from alice and alice.network public namespaces.
DMRG Checkpointing (dmrg.py):
- New checkpoint_dir option in dmrg.Options: after every completed sweep, the
current state is serialized atomically to dmrg.ckpt in the specified directory.
The write first goes to dmrg_lock.ckpt, then is renamed to dmrg.ckpt; on POSIX
systems the rename is atomic, so a crash during serialization cannot corrupt
the previous checkpoint.
- Checkpoint file is in PyTorch format and loadable via dmrg.Summary.load.
- checkpoint_dir defaults to None, resolving to the current working directory at
run() call time (matching the behavior of Options.logging). Stored as str for
TOML round-trip compatibility.
Network.bond_states (network.py):
- New bond_states property on Network (and hence MPS and MPO): returns the
number of physical states at each internal bond (list of length L - 1).
Entry i is index.num_states for the right bond of site i.
- Equal to bond_dims for Abelian groups (U(1), Z(2)). For SU(2) it is larger:
each multiplet of spin j contributes 2j+1 states, making bond_states the
physically meaningful truncation measure in non-Abelian simulations.
DMRG Examples (examples_dmrg/):
- dmrg_heisenberg.py, dmrg_freefermion.py, dmrg_conductor.py updated to accept
an init parameter ('iter_diag' or 'random'), using init_mps for the random
path. Per-example _random_mps helpers removed.
Documentation:
API Reference (docs/api/network/):
- init-mps.md: new page with parameter table, charge-convention notes, mode
descriptions, and runnable examples for Heisenberg and free-fermion cases.
- network.md: bond_states property added to Network class reference.
- index.md: init_mps entry added to the Network module index.
Getting Started (docs/getting-started/):
- quick-start.md: updated to use init_mps for MPS construction and the
Summary.save / dmrg.Summary.load checkpoint interface.
- changelog.md: version history updated through v0.1.3.
Navigation (mkdocs.yml):
- init-mps.md added under the Network section.
Packaging (pyproject.toml):
- Version bumped to 0.1.3.
Test Suite (742 tests):
- 742 tests pass, 0 skipped.
- New test file: tests/network/test_automps.py (77 tests covering TestAutoConfig,
TestBondCharges, TestReachableCharges, TestProductStateMPS, TestRandomMPS).
- New tests in tests/algorithm/dmrg/test_dmrg.py: TestCheckpoint (6 tests
covering file creation, lock-file cleanup, load round-trip, default-cwd
behavior, per-sweep frequency, and TOML round-trip).
Statistics and Scope:
- 18 commits since v0.1.2.
- 18 files changed: 1384 insertions, 188 deletions.
- Source modules touched: src/alice/__init__.py, src/alice/network/__init__.py,
src/alice/network/automps.py, src/alice/network/network.py,
src/alice/algorithm/dmrg/dmrg.py.
- Test modules touched: tests/algorithm/dmrg/conftest.py,
tests/algorithm/dmrg/test_dmrg.py, tests/network/test_automps.py.
- Docs pages touched: docs/api/network/index.md, docs/api/network/init-mps.md,
docs/api/network/network.md, docs/getting-started/quick-start.md,
docs/getting-started/changelog.md; mkdocs.yml.
Rationale:
init_mps was introduced because every DMRG example script was reimplementing its
own _random_mps helper with hardcoded charge heuristics that only worked for one
particle type. These helpers were redundant and accumulated subtle differences over
time. init_mps centralizes that logic once: the (Spc, Op) pair from load_space
already carries the group structure, so no particle_type= argument is required, and
the auto-balanced _auto_config heuristic covers all standard even-L half-filled
cases without user input. The BFS-based sector selection for random MPS replaces
the previous per-type hardcoded sector lists with a uniform algorithm that works for
any symmetry group supported by Nicole.
Checkpointing was the last missing piece of the DMRG restart workflow. Summary.load
and Summary.save already existed for post-run storage; checkpoint_dir extends them to
in-run checkpointing so that a simulation interrupted by a wall-time limit or
hardware fault can be resumed from the last completed sweep without losing work. The
atomic write strategy — serialize to a lock file, then rename — ensures the on-disk
checkpoint is always either absent or a complete, valid state; there is no window
during which a partial write can leave a corrupt file.
Breaking Changes: None. All previously valid calls continue to work unchanged.
Requirements: Python >= 3.11, PyTorch >= 2.5, Nicole >= 0.3.6, Yuzuha >= 0.1.5.
All 742 tests pass.
Feature release introducing NormalMPO, an MPO subclass that separates the
physical scale factor from unit-normed internal tensors, and thermal_mpo, which
approximates ρ(β) = exp(−βH) via a truncated Taylor series in MPO arithmetic.
The observe function is extended to compute normalized thermal expectation values
Tr[ρO] / Tr[ρ] when passed a NormalMPO state. No breaking changes.
Version: 0.1.4
Release Date: May 31, 2026
New Features:
NormalMPO (thermal.py):
- New MPO subclass representing scale × mpo, where mpo.norm() ≈ 1 after
compact() or from_mpo(). Keeps the physical magnitude in _scale, decoupled
from the internal tensors, so SVD truncation thresholds are always applied on
a consistent unit scale.
- from_mpo(mpo): clones the input MPO, canonicalizes to site 0, extracts the
Frobenius norm into _scale, and returns a unit-normed NormalMPO.
- scale property: read-only access to _scale.
- compact(trunc): two-sweep canonicalization that folds the extracted norm into
_scale instead of redistributing it; restores the standard IN/OUT bond arrow
convention via capcup after each sweep, required by subsequent oplus and trace
operations.
- __matmul__ (@ operator): per-site einsum('abrs,cdsu->acbdru') followed by two
merge_axes calls (right bonds first, then left) maintaining the
(L, R, phys_in, phys_out) axis order; _scale is the product of the two input
scales.
- __add__ (+ operator): per-site oplus with relative weight |alpha|^(1/L) per
site, where alpha = other._scale / self._scale; the sign of alpha is absorbed
into site 0 to avoid complex fractional powers when Taylor coefficients are
negative.
- __mul__ / __rmul__ (* operator): updates _scale only; site tensors are
unchanged.
- Exported from alice.network and the alice top-level namespace.
thermal_mpo (thermal.py):
- Approximates ρ(β) = exp(−βH) via the truncated Taylor series
ρ(β) ≈ Σ_{n=0}^{N} (−β)^n/n! H^n, where H^0 = I is an L-site identity MPO
built from the physical space index spc following the same itag convention as
build_hamiltonian.
- compact() is called after every addition and every power step to control bond
growth.
- trunc parameter: truncation options forwarded to each compact() call; defaults
to {'thresh': 1e-14}.
- coeff_thresh parameter: early-stopping threshold on |β^n / n!|; loop exits
when the coefficient falls below this value. Defaults to 1e-15 (safe for
double precision).
- The returned NormalMPO carries _scale ≈ Tr[ρ] (the partition function up to
the MPO norm), so a single trace call suffices to recover Z.
- Exported from alice.network and the alice top-level namespace.
observe Extended for Thermal States (observe.py):
- observe() now dispatches on isinstance(state, NormalMPO) before the generic
MPO check; passing a plain MPO still raises NotImplementedError with a
migration note.
- New _observe_thermal helper: forms rho @ NormalMPO.from_mpo(observable),
calls compact(), and returns Tr[ρO] / Tr[ρ]; raises ZeroDivisionError if
Tr[ρ] is numerically zero.
Documentation:
API Reference (docs/api/network/):
- normal-mpo.md: new page with mkdocstrings block and Notes covering the
representation invariant (scale × unit-norm MPO), arithmetic contract, and
dtype-preservation design of __add__.
- thermal-mpo.md: new page with algorithm, convergence, partition function, and
thermal expectation value notes.
- index.md: NormalMPO added to the Classes table; thermal_mpo and updated
observe description added to the Functions table.
Navigation and Changelog (mkdocs.yml, docs/getting-started/changelog.md):
- mkdocs.yml: NormalMPO and thermal_mpo added under the Network nav section.
- changelog.md: version history updated through v0.1.4.
Packaging (pyproject.toml):
- Version bumped to 0.1.4.
- nicole dependency floor raised from >=0.3.6 to >=0.3.7.
Test Suite (740 tests):
- 740 tests pass, 0 skipped.
- New test file: tests/network/test_thermal.py (48 tests across
TestNormalMPOConstruction, TestNormalMPOTrace, TestNormalMPOMatmul,
TestNormalMPOAdd, TestThermalMPO, TestFreeFermionThermal).
- tests/network/test_observe.py: error-message assertions updated to match
revised NotImplementedError and TypeError text in observe().
Statistics and Scope:
- 15 commits since v0.1.3.
- 11 files changed: 1254 insertions, 12 deletions.
- Source modules touched: src/alice/network/thermal.py,
src/alice/network/observe.py, src/alice/network/__init__.py.
- Test modules touched: tests/network/test_thermal.py,
tests/network/test_observe.py.
- Docs pages touched: docs/api/network/normal-mpo.md,
docs/api/network/thermal-mpo.md, docs/api/network/index.md,
docs/getting-started/changelog.md; mkdocs.yml, pyproject.toml.
Rationale:
Accumulating the Taylor series on unnormalized MPO tensors causes rapid overflow
or underflow as H^n grows or decays with n. NormalMPO decouples the physical
magnitude from the truncation logic: keeping site tensors at unit norm means the
SVD threshold in compact() is always relative to the largest singular value of
the normalized operator, independent of the overall scale. The dtype-preservation
decision in __add__ — computing |alpha|^(1/L) and absorbing the sign of alpha
into site 0 — is necessary because a negative base with a fractional exponent
would silently promote float64 tensors to complex128, causing dtype mismatches in
subsequent __matmul__ calls. The capcup loop at the end of compact() is also
non-obvious: Nicole's QR/SVD sweeps may reorient bond arrows, and both oplus
(used in __add__) and the transfer-matrix einsum (used in trace) assume the
standard IN/OUT convention.
The thermal_mpo implementation calls compact() after every addition and every
power step rather than only at the end. This keeps bond dimensions bounded
throughout the accumulation loop rather than allowing them to grow unboundedly
until a final compression pass. The early-stopping condition on the Taylor
coefficient magnitude provides an automatic, quantitative convergence check that
is independent of both chain length and the value of the order argument.
Breaking Changes: None. All previously valid calls continue to work unchanged.
Requirements: Python >= 3.11, PyTorch >= 2.5, Nicole >= 0.3.7, Yuzuha >= 0.1.5.
All 740 tests pass.
Patch release with two targeted improvements: DMRG environment-block caching is made safe for concurrent runs by isolating each invocation in a unique subdirectory, and the early-stopping criterion in thermal_mpo is corrected to test the actual contribution magnitude rather than the bare Taylor coefficient. No breaking changes. Version: 0.1.5 Release Date: June 8, 2026 Bug Fixes: DMRG Environment Cache Isolation (dmrg.py): - run() previously wrote all cached environment blocks to a fixed left/ and right/ path directly inside env_cache_dir. Two concurrent DMRG jobs sharing the same Options (and hence the same env_cache_dir) would read and overwrite each other's blocks, silently corrupting both runs. - run() now generates a unique subdirectory (first 8 hex characters of a UUID4, e.g. env_cache_dir/a1b2c3d4/) on entry and removes it in a finally block on return or exception. The left/ and right/ subdirectories are created inside this unique path. shutil.rmtree with ignore_errors=True is used for cleanup so that a partially-written or already-deleted directory does not mask the exception from the sweep loop. - Options.env_cache_dir docstring updated to document the subdirectory scheme and the automatic cleanup guarantee. thermal_mpo Early-Stopping Correction (thermal.py): - The early-stopping guard previously tested abs(coeff) < coeff_thresh, where coeff = (-beta)^n / n!. For Hamiltonians with large operator norm, H_pow.scale (the Frobenius norm of H^n tracked by NormalMPO) can be many orders of magnitude larger than 1, so the actual n-th term contribution abs(coeff) * H_pow.scale remained significant long after the bare coefficient fell below coeff_thresh. The loop exited too early, silently underestimating exp(-beta * H) for any Hamiltonian whose operator norm exceeds 1. - The guard is now abs(coeff) * H_pow.scale < coeff_thresh, using the scale already maintained by the NormalMPO representation at zero extra cost. - A conditional that skipped the H_pow update step when the next coefficient was small has been removed. H_pow is now always advanced when n < order; the decision to exit is made at the top of the following iteration with the corrected criterion. - order and coeff_thresh parameter docstrings updated to describe the corrected stopping condition. Test Suite (795 tests): - 795 tests pass, 0 skipped. - New test class TestEnvCache in tests/algorithm/dmrg/test_dmrg.py (4 tests: test_unique_subdir_removed_on_success, test_unique_subdir_created_inside_cache_dir, test_two_runs_use_distinct_subdirs, test_no_leftover_files_after_two_runs). - New test test_env_cache_dir_toml_round_trip added to TestOptions in tests/algorithm/dmrg/test_dmrg.py. Statistics and Scope: - 5 commits since v0.1.4. - 5 files changed: 185 insertions, 18 deletions. - Source modules touched: src/alice/algorithm/dmrg/dmrg.py, src/alice/network/thermal.py. - Test modules touched: tests/algorithm/dmrg/test_dmrg.py. - Docs pages touched: docs/getting-started/changelog.md. - Packaging: pyproject.toml (version bumped to 0.1.5). Rationale: The cache-isolation bug was latent because most DMRG workflows run a single job at a time. The collision surface only appears when multiple jobs share a config file or a shared scratch directory — a common pattern in batch-job environments. Using a UUID subdirectory is the minimal fix: it requires no coordination between processes, works across NFS and local filesystems, and is invisible to callers because the subdirectory is created and removed entirely inside run(). The thermal_mpo stopping condition was wrong by construction. The early-stopping literature for Taylor-series MPO expansions checks the actual term magnitude, not the scalar coefficient, precisely because MPO norms grow with chain length and expansion order. The NormalMPO representation already carries the running Frobenius norm in H_pow.scale, making the corrected check a one-character change. The redundant conditional on the power-update step was defensive code that became incorrect once the stopping condition was changed: it could skip updating H_pow on an iteration where the corrected criterion would not exit, leading to a stale power on the next iteration. Breaking Changes: None. All previously valid calls continue to work unchanged. Requirements: Python >= 3.11, PyTorch >= 2.5, Nicole >= 0.3.7, Yuzuha >= 0.1.5. All 795 tests pass.
Enhancement release extending init_mps with a target_qn parameter for explicit quantum-number targeting, fixing a silent zero-MPS bug in random MPS initialization for odd-L chains, and upgrading the warning pathway in automps from warnings.warn to structured logging. No breaking changes. Version: 0.1.6 Release Date: June 10, 2026 Enhancements: init_mps target_qn Parameter (automps.py): - New keyword argument target_qn on init_mps: specifies the desired right-boundary charge Q[L] (total quantum number of the chain). Defaults to None, which resolves to Q_vac (half-filling), preserving existing behavior for even-L half-filled cases. - Both modes honor target_qn. Product-state mode (bond_dim=1): _auto_config targets target_qn; the right boundary is always Q[L] from the resulting charge path (rigid). Random-MPS mode (bond_dim>1): _auto_config targets target_qn to obtain a physically appropriate center-bond charge, and the right boundary index is explicitly pinned to target_qn, decoupling the boundary from the path. - When an explicit target_qn is given and the auto-config cannot reach it (e.g. target_qn=0 for odd-L spin-1/2), init_mps raises ValueError in both modes rather than silently constructing an MPS in the wrong sector. Odd-L Random MPS Fix (automps.py): - Bug fixed: _random_mps previously pinned both boundary indices to Op['vac'] (charge Q_vac). For odd L, no config can return the bond charge to Q_vac in an odd number of fusion steps, so every charge block of the last tensor was forbidden. The MPS canonicalized to zero without raising any error. - The right boundary index is now constructed with effective_right = Q[L] (the actual end charge of the auto-config path) when target_qn was not given explicitly. For even L this is still Q_vac; for odd L it is the correct non-vacuum charge, producing a non-zero MPS in the expected sector. - The Op parameter of _random_mps has been removed (no longer needed); the left boundary is built from Q[0] and the right boundary from target_qn or effective_right. _auto_config Generalization (automps.py): - _auto_config now accepts target_qn; all three internal strategies (single-sector fill, period-2 alternation, greedy fallback) target target_qn instead of Q_vac. The period-2 strategy no longer applies a per-period shortcut — the full length-L path is checked against target_qn, making it correct for any target. - The function is now a pure helper with no side effects; the sole warning site is init_mps. Warning System Upgrade (automps.py): - init_mps no longer calls warnings.warn(UserWarning) when the auto-config cannot close to Q_vac (e.g. odd L). The message is now emitted via logging.getLogger(__name__), consistent with Alice's structured logging infrastructure. Module-level import warnings replaced by import logging and a logger = logging.getLogger(__name__) instance. Documentation: API Reference (docs/api/network/init-mps.md): - New Logic Overview section: ASCII decision diagram showing how target_qn, config, Q[L], and bond_dim interact inside init_mps, including the effective_right asymmetry between product-state and random-MPS modes. - New Odd-chain lengths section: explains the default WARNING behavior, the target_qn fix path, and the ValueError guard; includes a runnable spin-1/2 U(1) example for L=7. - Bond Sectors in Random Mode section updated: clarifies that the BFS is seeded from Q_c = Q[L//2] of the targeted auto-config, not from Q_vac. - Charge Conventions note updated: center-bond charge is zero only for even L with a balanced auto-config. Changelog (docs/getting-started/changelog.md): - Version history updated through v0.1.6. Test Suite (814 tests): - 814 tests pass, 0 skipped. - New TestAutoConfigTargetQn (4 tests): verifies that _auto_config reaches an explicit target_qn exactly, covering odd and even L across Spin U1 and Ferm U1 spaces. - New TestInitMpsOddL (3 tests): regression tests for the zero-MPS bug — checks non-zero norm, correct right-boundary charge, and WARNING emission across all standard physical spaces for odd L. - New TestTargetQn (7 tests): end-to-end tests for the target_qn keyword on init_mps, covering both modes, even/odd L, negative targets, and ValueError on unreachable sectors. Statistics and Scope: - 7 commits since v0.1.5. - 5 files changed: 484 insertions, 89 deletions. - Source modules touched: src/alice/network/automps.py. - Test modules touched: tests/network/test_automps.py. - Docs pages touched: docs/api/network/init-mps.md, docs/getting-started/changelog.md. - Packaging: pyproject.toml (version bumped to 0.1.6). Rationale: The zero-MPS bug for odd-L random initialization was silent by construction: no exception was raised during init_mps itself. The MPS canonicalized to zero, and the error only surfaced inside the Davidson eigensolver when the initial trial vector had zero norm, producing a zero-division rather than an informative initialization error. The root cause was that _random_mps always used Op['vac'] for the right boundary index, which carries Q_vac. For even L the auto-config closes exactly at Q_vac, so every charge block of the last tensor has a valid assignment. For odd L the charge path ends at Q[L] != Q_vac, so the right boundary and the accumulated path are in different sectors and Nicole's block-sparse engine produces an all-zero tensor. Using Q[L] as the effective right boundary is the minimal correct fix: it requires no additional user input and is provably correct for all L, because Q[L] is always the charge the path actually reaches. The target_qn parameter addresses a separate limitation: before this release, init_mps had no way to request a specific quantum number sector for doped or odd-L systems — the only alternative was passing an explicit config list, which requires the caller to know the charge arithmetic. target_qn delegates that arithmetic to _auto_config, which already understands group fusion rules. The ValueError path for unreachable targets gives immediate, actionable feedback instead of raising an opaque Nicole index-mismatch error inside the canonicalization sweep. Breaking Changes: None. All previously valid calls continue to work unchanged. Existing calls to init_mps without target_qn behave identically to v0.1.5 for even-L chains. Odd-L chains no longer silently produce a zero random MPS. Requirements: Python >= 3.11, PyTorch >= 2.5, Nicole >= 0.3.7, Yuzuha >= 0.1.5. All 814 tests pass.
Add `alice.algorithm.two_site_bug`, a gate-based two-site BUG (Basis-Update & Galerkin) integrator for real- and imaginary-time evolution of an MPS under a nearest-neighbour Hamiltonian. It is built entirely on the existing Alice/Nicole stack (MPS, the AutoMPO interaction list, decomp, the PyTorch backend) and adds no new tensor infrastructure. - run(mps, interactions, opts): even/odd Trotter sweeps of two-site bond gates with a truncated-SVD split that adapts the bond dimension; Lie (first-order) and Strang (second-order) steps, plus imaginary-time cooling. - Bond gates reuse the AutoMPO interaction list: each nearest-neighbour Interaction2Site's leading/terminal tensors are contracted over their operator channel and exponentiated block-wise on the PyTorch backend, preserving the symmetry block structure exactly. - Options (TOML-loadable) and Summary mirror the DMRG interface; Summary records per-step kept and proposed (augmented) bond dimensions. - Tests validate against exact diagonalization: state fidelity, exact norm conservation, U(1) charge conservation, and second-order Trotter scaling. - Docs: API reference pages, nav entry, and changelog. ruff check passes; full suite: 835 passed.
Replace the gate-based two-site update with the faithful rank-adaptive Basis-Update & Galerkin (Ceruti–Kusch–Lubich) K/L/S local bond update. - Vendor the Nicole-native, symmetry-aware faithful-KLS kernel under `_kernel/` (K-augment, L-augment, Galerkin S-step with Krylov expv). - Alice bridge: bond Hamiltonians from the AutoMPO interaction list (bond.py), canonical MPS snapshot + odd/even Strang sweep (scheme.py) driving the kernel. - Remove the gate-based propagator path (gate.py and its tests). - `trunc_thresh` (S-step SVD threshold) controls how far each bond grows; the per-step discarded weight is tracked in `Summary.disc_weights`. - Tests: full-phys domain wall vs exact diagonalization (1 - F ~ 1.9e-8 at dt = 0.05, clean 2nd-order Strang), U(1) Sz and norm conservation, and imaginary-time cooling.
madhavmen
force-pushed
the
feature/two-site-bug
branch
from
June 19, 2026 22:52
0d5c1a5 to
686cd0e
Compare
A rank-adaptive BUG variant derived from the faithful Ceruti-Kusch-Lubich scheme, differing only in the local bond update: the discarded (orthogonal-complement) projector is applied to the K/L generator before the exponential (project-before), and the basis is grown by a plain direct sum [U0 | Qk] / [V0 ; Ql] with no augmented overlap matrices. The project-before generator is non-Hermitian, so the K/L substep uses a symmetry-preserving tensor Arnoldi exponential; the Hermitian S-step reuses the faithful kernel's tensor Lanczos. The odd/even Trotter sweep, AutoMPO bond Hamiltonians, and Options/Summary are reused unchanged from two_site_bug, so only the per-bond candidate is new. Validated on the symmetric Heisenberg chain against exact diagonalization (state fidelity, O(dt^2) Strang convergence, norm and total-Sz conservation, rank growth, imaginary-time cooling) — 22 tests. Adds the discarded_bug package and tests, docs/api/discarded-bug pages with mkdocs nav and api/index entries (and the previously missing two-site-bug overview section), a changelog entry, and the module exports.
Reimplement the discarded-projector BUG as the MPS specialisation of the Lubich tree-tensor-network BUG. Like two-site TDVP and DMRG it takes a Hamiltonian MPO and exponentiates the two-site effective Hamiltonian with the left/right MPO environments (no Trotter splitting), reusing the DMRG environment machinery; it is inverse-free. A step recursively bisects the chain — the MPS realisation of the reference's balanced-binary-tree Step (the tree is built by recursive bisection of the 1D modes). At each bisection bond the two-site block is evolved once, the K-step and L-step grow the left/right frames with the discarded projector (qr([Theta1_left|U0]) / qr([Theta1_right;V0]), no augmented overlap matrices), and the Galerkin core is the projection of the evolved block, SVD-truncated. Frames are read off the evolved block so a product-state interface grows its genuine rank-2 entanglement. Because every bond is a tree node, the bond dimension grows along the whole chain (the full ballistic light cone) as a domain wall melts. The step is first order in dt with no backward substep; the validated property is the rank growth / light-cone spread. Everything stays in the U(1) block-sparse Nicole representation so the kept rank respects the charge sectors. - Replace the per-bond Trotter/KLS scheme.py with the recursive-bisection sweep.py and the symmetry-aware block_local_update in candidate.py; vendor the Krylov expv. - run(mps, mpo, opts) on a Hamiltonian MPO; Options/Summary mirror the DMRG interface. - Tests cover the full light-cone growth (peaked profile to 2**(L/2)), first-order single-step convergence, that the forward-only error does not shrink with dt, and norm / U(1) / imaginary-time conservation, all vs exact diagonalization. - Update the API docs and changelog to the MPO recursive-bisection scheme.
Replace the recursive-bisection / block-evolution scheme with a single global Basis-Update & Galerkin sweep (mirror of the Julia port): form phi = H*psi via mpo_times_mps, build augmented left/right isometries that keep psi exact and admit only the discarded part (I - U0 U0^dagger) phi per basis matrix (symmetry-blocked), then integrate one Galerkin centre tensor under the two-site effective Hamiltonian. No M/N overlap matrices, no backward substep. Exact at full bond dimension, 2nd order and convergent under truncation. - sweep.py: mpo_times_mps + k_sweep + l_sweep + global_step; the two-site effective apply and centre truncation/assembly helpers folded in. - candidate.py: deleted (block_local_update / bond_snapshot / augmenters removed). - discarded_bug.py, __init__.py: docstrings updated to the global sweep. - tests: validate vs exact diagonalisation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
alice.algorithm.two_site_bug, a gate-based two-site BUG (Basis-Update &Galerkin) integrator for real- and imaginary-time evolution of an
MPSunder anearest-neighbour Hamiltonian. It is an independent algorithm unit built entirely
on the existing Alice/Nicole stack — symmetry-aware
MPS, the AutoMPO interactionlist, Nicole
decomp/contract/merge_axes, and the PyTorch backend — and addsno new tensor infrastructure.
How it works
commuting bond groups (even and odd left-site index). Each step applies two-site
bond gates group by group; within a group the gates act on disjoint site pairs,
so the group is exact.
'strang'(symmetric, second-order) and'lie'(first-order) compositions are provided, plus imaginary-time cooling.
.
directly from each nearest-neighbour
Interaction2Site: the leading and terminalMPO tensors are contracted over their operator channel (exactly as
build_hamiltoniandoes) and exponentiated block-wise on the PyTorch backend,preserving the symmetry block structure. No bespoke operator algebra.
Summaryrecords, per step, both the kept bond dimension andthe proposed (pre-truncation) augmented dimension, so the basis augmentation
and the discarded rank growth are both visible.
Reused Alice/Nicole features
Symmetry-aware
MPS(any group Nicole supports) · AutoMPO interaction list andgeometries (any nearest-neighbour model
build_interactionproduces) · Nicoledecompfor the SVD rank adaptation · PyTorch backend for the block matrixexponential (GPU/dtype/autograd inherited) ·
loggingfor sweep-by-sweepdiagnostics · the
AlgorithmOptions/AlgorithmSummaryinterface (TOML I/O,serialize/deserialize) shared with DMRG.
Validation
New tests under
tests/algorithm/two_site_bug/check the integrator against exactdiagonalization on a Heisenberg domain wall:
exp(-iHt)(1 - F < 1e-6),S_zconservation,~dt^4), and Strang beating Lie,Scope
Nearest-neighbour Hamiltonians (the BUG target);Full suite: 835 passed;
ruff check src/ tests/clean; docs build verified.Related issues: none.