Repository navigation
Fix Multiline (MultilineMPS/MultilineMPO) correctness and API inconsistencies - #508
Merged
Merged
Conversation
Member
Author
|
After having discussed with @leburgel, I realised I didn't fully appreciate/understand what multiline actually represents, so recent changes rectify some mistakes I made, and tried to explain these niche things more cleanly in the docs/docstrings.
|
1 of 4 tasks
lkdvos
reviewed
Sep 9, 2026
leburgel
reviewed
Sep 22, 2026
leburgel
reviewed
Sep 22, 2026
`length`, `eltype`, iteration and `m[i]` now refer to the stored lines, while `size`/`axes`/`eachindex` keep describing the `(nrows, ncols)` lattice shape. Internal code uses `parent` instead of reaching into `.data`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lines are now `Union{InfiniteMPS, FiniteMPS}` and `Union{InfiniteMPO, FiniteMPO}`,
which excludes Hamiltonian lines. `InfiniteMultilineMPS`/`FiniteMultilineMPS` and
`InfiniteMultilineMPO`/`FiniteMultilineMPO` dispatch on the kind of line. Finite
lines can be built and inspected, but `leading_boundary` only accepts infinite
lines. The meaningless `*` methods between multiline objects are replaced by
`*(::InfiniteMultilineMPO, ::InfiniteMPS)`, and `checkbounds` on the multiline
orthoviews now dispatches on the line type.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
For a `MultilineMPS`/`MultilineMPO` pair the contracted quantity is the eigenvalue of the transfer operator rather than an overlap, since bra and ket are different lines. `expectation_value` on multiline objects is removed, `expectation_value(::InfiniteMPS, ::InfiniteMPO)` forwards to the new function, and the statmech algorithms log `dominant_eigenvalue` instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each row is rendered through its own line's display, and for `MultilineMPO` the row-to-row mapping is shown explicitly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`size`, `axes` and `eachindex` now follow `length`, so `size(m) == (length(m),)` instead of the `(nrows, ncols)` lattice shape. The orthogonality views keep indexing the lattice as `[row, col]`, and code that needs the number of columns uses the internal `linelength`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- rename `dominant_eigenvalue` to `leading_eigenvalue` and stop exporting it - allow any `AbstractMPS`/`AbstractMPO` lines in `MultilineMPS`/`MultilineMPO` - rename the internal column count to `width` - one `checkbounds` for the multiline views, delegating the column to the line's tensors - drop instance-level `spacetype`/`sectortype`/`storagetype`, TensorKit already forwards them - pick the VUMPS objective by dispatch instead of an `isa` switch - free energy as `-log` of the eigenvalue in the hard-hexagon example, and docs wording Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lkdvos
approved these changes
Oct 4, 2026
Member
Author
|
Looks good from my end! Maybe @leburgel wants to take a look before merging? |
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.
Multiline{T}was inconsistent about what it is: sometimes a 2D array indexed by(row, col), sometimes a 1D sequence ofT-typed lines, with different parts of the code picking different conventions. The real bugs this caused:expectation_value(::MultilineMPS, ::MultilineMPO, ...)had a fallback that silently returned something meaningless (prodinstead ofsum, no row shift,envsdiscarded) for any line type not explicitly guarded, including Hamiltonian lines.MultilineMPO * MultilineMPSnever worked, and naive fixes left both a shape bug (lengthcountingrows*cols) and a silently wrong row shift.isfinite(::MultilineMPO),changebonds(::MultilineMPO, ::SvdCut)andaxes(m, i)fori > 2all threw.Changes
Semantics
Multilineis a plain vector of its lines:length/size/axes/eachindex/eltype/iterate/m[i]all refer to the lines, sosize(m) == (length(m),). The lattice of lines and sites is only indexed through the orthogonality views (ψ.AL[row, col]etc.) and lattice-valued queries such asphysicalspace(ψ); internal code that needs the number of columns useslinelength(m).dominant_eigenvalue(ψ, O, [envs]): for a multiline pair, the contracted quantity is the eigenvalue of the transfer operator, not an overlap, since bra and ket are different lines.expectation_value(::InfiniteMPS, ::InfiniteMPO)forwards to it, and the statmech algorithms log it.expectation_value(::MultilineMPS, ::MultilineMPO)is removed, together with its unguarded fallback, in favor ofdominant_eigenvalue. Note for PEPSKit:test/boundarymps/vumps.jlcallsexpectation_value(mps, T)on aMultilineTransferPEPSand needs to switch todominant_eigenvalue; its VUMPS keeps working through itscontract_mpo_expvaloverload.*(::MultilineMPO, ::MultilineMPS)and*(::MultilineMPO, ::MultilineMPO)are removed;*(::InfiniteMultilineMPO, ::InfiniteMPS)pushes the boundary through every row, advancing it one full period.isfinite,changebonds(::MultilineMPO/::MultilineMPS, ::SvdCut),axes(m, i), and added instance-levelspacetype/sectortype/storagetype.Line types
MultilineMPSlines areUnion{InfiniteMPS, FiniteMPS},MultilineMPOlinesUnion{InfiniteMPO, FiniteMPO}; Hamiltonian lines are excluded.InfiniteMultilineMPS/FiniteMultilineMPSandInfiniteMultilineMPO/FiniteMultilineMPOdispatch on the kind of line.leading_boundaryandchangebonds(_, _, ::OptimalExpand)only acceptInfiniteMultilineMPS(andInfiniteMultilineMPOwhere the operator is typed), so they fail at dispatch.AbstractMatrixconstructor that silently built finite-lineMultilineMPOs.checkboundson the multiline orthoviews dispatches on infinite vs finite lines.Display
summaryreports the 2D shape, andshowrenders each row through that line's ownshow, with the row mapping shown forMultilineMPO.Here the multiline MPS:
Details
And here a multiline MPO:
Details
Tests
test/mpo/multiline.jl: exact row-shift tests forMultilineMPO * InfiniteMPSwith permutation MPOs, row- and column-accumulateddominant_eigenvalue, a 2-rowleading_boundarycheck (λ₂ ≈ λ₁²), the line aliases, and that the removedexpectation_value, Hamiltonian lines and finite lines are rejected.test/states/multilinemps.jl: instance-levelisfinite(ψ), and the vector semantics (size,axes,eachindex,eltype) next to the 2D shape of the views.Documentation
states.md: row-shift convention, why a multiline has one fixed point, and subtleties (sizevs iteration,norm(ψ) == sqrt(nrows), finite lines).operators.md: newMultilineMPOsection.algorithms.md:dominant_eigenvalueunderleading_boundary.Multiline,MultilineMPO,MultilineMPS,expectation_value,dominant_eigenvalue; changelog entries.Breaking
length/size/axes/eachindex/eltypeofMultiline(lengthwasnrows * ncolsandsizethe lattice shape, now both follow the lines;eltype(::MultilineMPS)was the site tensor type, now the line type), removal ofexpectation_valueon multiline objects, of theMultilineMPO(::AbstractMatrix)constructor and of*between multiline objects, and the narrower line types.Not addressed
MultilineMPS, sinceInfiniteMPSitself doesn't implementzerovector/scale.effective_excitation_hamiltonian(::MultilineMPO, ::MultilineQP, envs)usesparent(envs).leftenvson aVector, and the renormalization energy uses the same line as bra and ket. Both predate this PR.Checklist
julia --project=test test/runtests.jl, or the relevant subset)docs/src/)[Unreleased]indocs/src/changelog.md, if this PR is user-facing (new feature, behavior change, bug fix, deprecation, or removal)