Skip to content

TreeTN has no documented/tested storage convention #576

Description

@lingrui96

TreeTN has no documented/tested storage convention — the ITensor-per-node workaround works but is unspecified, and this is an ecosystem-wide gap, not just tensor4all-rs

Summary

TreeTN has no dedicated serialization function (tensor4all-hdf5 only exposes
save_itensor/load_itensor for TensorDynLen and save_mps/load_mps for
TensorTrain). A workaround exists — save each node's tensor individually as
an ITensor (with append_itensor, which already supports multiple named
tensors per file) and reconstruct the tree on load via
TreeTN::from_tensors, which infers graph connectivity purely from which
loaded tensors share a full Index (id + prime level + tags) — but this
workaround is:

  • Not documented anywhere (no README mention, no guide page, no example).
  • Not tested end-to-endsave_itensor/load_itensor and
    TreeTN::from_tensors each have their own tests, but no test exercises the
    full round-trip (save N node tensors → reload → from_tensors
    reconstructed tree matches the original).
  • Missing a naming/schema convention. append_itensor(filepath, name, tensor) requires a name per tensor, but nothing specifies what that name
    should be, whether it should encode the node's V value (TreeTN<T, V>'s
    node-name type), or how a reader recovers the node_names: Vec<V> argument
    from_tensors requires. Compare to save_mps, which has a fully specified
    schema (@type="MPS", length/llim/rlim attributes, numbered
    MPS[i]/ subgroups) — TreeTN has nothing analogous.

Why this is an ecosystem-wide gap, not a tensor4all-rs-only one

Checked the reference ITensors.jl HDF5 documentation
(https://itensor.github.io/ITensors.jl/stable/HDF5FileFormats.html): it
defines schemas for TagSet, Index, IndexSet, ITensor, Dense,
BlockSparse, and (via ITensorMPS.jl) MPS/MPO — but nothing for a
collection of connected ITensors representing a general tensor network,
PEPS, or tree tensor network. The docs state group names for a saved object
are "either specified by the user or specified to some default value" —
i.e., multi-tensor-network storage is explicitly left unspecified, by design,
upstream. ITensorNetworks.jl itself has no HDF5 format at all (already
noted in #158's "Target Structures" table).

So there is currently no prior art anywhere in the ITensors.jl/ITensorNetworks.jl
ecosystem to mirror, unlike the MPS case where a well-established Julia-side
schema already existed to copy.

Why this matters in practice

  1. Correctness/compatibility risk: two independent implementations (e.g.
    two research groups, or two AI-agent-assisted sessions) that both "store a
    TreeTN as a collection of ITensors" will very likely invent incompatible
    naming/grouping conventions, even though both are nominally using the same
    underlying ITensors.jl-compatible ITensor HDF5 schema. Files would not
    be interchangeable, and there would be no way to detect this without
    inspecting both implementations' code.
  2. Discoverability ("AI-friendliness"): an agent (or a new contributor)
    asked "how do I save a TreeTN" currently has no doc, guide, or example to
    find. The only way to arrive at the append_itensor + from_tensors
    workaround is by reading from_tensors's implementation closely enough to
    notice it reconstructs topology from shared Index identity, and
    independently knowing append_itensor supports multiple tensors per file.
    That is source-archaeology, not something a typical doc search or agent
    session should have to do.
  3. This project relies heavily on AI-assisted sessions (issue drafting,
    debugging, and implementation PRs alike — see e.g. HDF5 serialization for tensor4all-rs native format #158/Julia-level conversion between tensor4all-rs and ITensors.jl/ITensorNetworks.jl #159's near-
    simultaneous creation, debug.md, and PR feat: add ITensors.jl-compatible HDF5 serialization #198's Claude Code attribution),
    which makes the missing convention actively worse, not just inconvenient
    :
    • Recurring cost, not a one-time cost. Every session that needs
      TreeTN persistence has to re-derive the same workaround from scratch by
      reading source (from_tensors's shared-Index inference,
      append_itensor's multi-tensor-per-file support, cross-checking that
      ITensors.jl itself has no upstream convention to copy) — a real,
      repeated token/compute cost paid by every future session instead of
      being paid once and written down.
    • "Diversity" here means incompatibility, not robustness. Because
      there is no canonical schema, each session that independently derives
      the workaround will invent its own ad hoc naming/grouping convention.
      Unlike a human team, which can build informal shared convention over
      time even without documentation, stateless AI sessions have no memory
      across sessions — so two attempts by the same project, weeks apart,
      are plausibly more likely to diverge than two human engineers would
      be, not less. Formalizing the schema converts N independent guesses
      into one shared answer everyone (human or agent) can just look up.
  4. Silent failure modes: from_tensors requires each bond index to
    appear in exactly 2 tensors (errors otherwise) and needs node_names to
    already be known and correctly ordered by the caller — neither is
    recoverable from an HDF5 file that only contains a pile of unlabeled
    per-node ITensor groups.
  5. One concrete instance of the same "looks done, isn't" pattern: Julia-level conversion between tensor4all-rs and ITensors.jl/ITensorNetworks.jl #159
    ("Julia-level conversion between tensor4all-rs and
    ITensors.jl/ITensorNetworks.jl") is closed as COMPLETED, and its listed
    TreeTN ↔ TreeTensorNetwork (ITensorNetworks.jl) conversion target was
    never actually implemented — Tensor4all.jl's own source has no
    ITensorNetworks reference anywhere (not in code, not in Project.toml).
    Not raising this as a claim about issue-tracking process in general (no
    idea if this is a one-off or a pattern) — just noting it here because it's
    the concrete reason relying on issue/PR status as a proxy for "does TreeTN
    persistence exist" gave a wrong answer in this investigation, on this
    topic specifically.

Suggested resolution

Define an explicit, documented HDF5 schema for TreeTN, analogous to the
existing MPS schema, e.g.:

/<name>/
  @type = "TreeTN"
  @version = 1
  node_count = Int
  node_names/            # serialized V values, order matching node_N below
    ...
  edges/                 # explicit (node_a, node_b) pairs -- don't rely
    ...                  # solely on implicit shared-Index reconstruction
  node_0/ ...             # Layer 1 (ITensor)
  node_1/ ...
  ...

Storing edges/node_names explicitly (rather than only relying on
from_tensors's shared-Index inference) also sidesteps the "not exactly 2
tensors share this index" failure mode and removes the need for the caller
to already know node_names out-of-band.

Whatever schema is chosen should be documented (README + guide page) and
covered by an end-to-end round-trip test (save → reload → structural +
numerical equality with the original TreeTN), the same rigor already
applied to save_mps/save_itensor.

Since ITensorNetworks.jl has no prior art here either, this would need to
be a new schema proposal, potentially worth raising jointly with the
ITensors.jl/ITensorNetworks.jl maintainers rather than only within
tensor4all-rs, if broader interoperability is desired.

Status

Raised 2026-07-30 after investigating (in a separate session) whether
tensor4all-rs/Tensor4all.jl could persist a TreeTN built by
tensor4all-treetci::crossinterpolate2 — related discussion in
~/tensor4all-rust/treetci-optimize-no-early-stop-bug.md.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions