Add Spin-domain optimization support - #107
Conversation
There was a problem hiding this comment.
The code works, but still has too many rough edges. We can smooth it out to make the transition easier for implementing more general domains later on.
Also, it is better to not keep two interfaces (domain vs domain_dim) doing roughly the same thing.
About the general weights SumConstraint, I would rather keep it for a future version. Building the partial sums can be quite expensive and produce huge MPOs. It is also not part of our v1 constraints assumptions.
| - `domain` - The variable domain. Supported values are `[0, 1]` (the default) | ||
| and `[-1, 1]` for Ising spins. `domain_dim` remains available for the legacy | ||
| nonnegative integer domain `0:(domain_dim - 1)`; do not pass both keywords. |
There was a problem hiding this comment.
Subsume it as only the domain keyword.
There was a problem hiding this comment.
Updated the backend documentation to expose only the domain keyword.
bernalde
left a comment
There was a problem hiding this comment.
Maintainer review — Spin-domain support (Closes #106)
Solid, well-tested PR that completes the Ising/Spin child of #67. It adds a domain = [-1, 1] keyword to minimize/maximize, keeps [0, 1] as the default and domain_dim as the legacy qudit spelling, and rejects combining the two. I authored it, so this posts as COMMENT (GitHub blocks author APPROVE); main is not branch-protected and no review gate is reported, so nothing formally blocks merge. No blocking findings — two nonblocking notes inline.
What I verified
- Physical domain values thread through correctly.
op("D"; domain)makes the local operatordiagm(domain), soD = diagm([-1, 1])givesD² = I; the (already-diagonal-inclusive)tensorizethen encodes the diagonalQ_ii x_i²as the constanttr(Q)shift that spins actually contribute, and the off-diagonals asx_i x_j. Hand-checked the Ising doctest (min −2x₁x₂ + 0.25x₁ − 0.5x₂ → −2.25at[1, 1]), which is CI-verified. - Sampling/queries map indices ↔ values.
sampleindexespsi.domain[sample!(...)](generalizing the old.- 1);coeff/probmap values back to 0-based positions and reject out-of-domain queries. TheSolution{T,D}change keeps backward-compatible constructors defaulting to0:(d-1). - Signed
SumConstraintDFA is correct and permutation-safe. Building the state set as the subset-sum closure over all constrained weights means every prefix-sum in a real single pass is a reachable state regardless of site order, and theif … in statesguard only drops transitions that can't occur in a valid pass — so no feasible assignment is rejected. Thepreprocess = truesigned-constraint test (assertingpsi.permutation != 1:3, feasibility, and abrute_forcematch) exercises exactly this and passes. - Infeasibility-as-status contract holds, now carrying the domain (
infeasible_result(T, domain)→psi.domain == [-1, 1], still+Inf/-Inf, still throws onsample).
Findings — nonblocking
src/projection_mpo.jl:390—A = eltype(alphabet_values)is computed but unused.src/backends/dmrg.jl:53—domainis matched by exact equality, so[1, -1](the spin domain written high-spin-first) is rejected; worth accepting orderings or spelling out the ascending-order requirement in the error.
The signed-domain bond dimension grows with the number of reachable partial sums (vs rhs + 2 for nonnegative) — inherent to signed sums and now documented in constraints.md, so just noting it, not a concern.
Tests / CI
Full Pkg.test() passes locally (0 failures) and CI is green across all 11 checks on 9ad2747, including the new test/spin_domains.jl (quadratic/single-site/maximize/polynomial/constrained-with-preprocess/infeasible/validation, each cross-checked against brute_force(…; domain = [-1, 1])) and the Ising doctest.
Merge-readiness
No blocking issues; the two notes are optional polish. Correctly says Closes #106 (the sibling arbitrary-finite-domain and independent-domain children of #67 remain separate). As flagged in the PR body, open PRs #31/#44/#45 touch src/solution.jl/src/solver.jl and should reconcile after this lands. This account can't post a formal APPROVE on its own PR; no gate is reported as required.
|
Addressed every unresolved review thread, including both non-blocking notes, in
Validation: targeted projection/domain/Spin/constrained/JuMP suites passed; full The formal review decision is still |
Summary
domain = [-1, 1]support for quadratic and polynomial DMRG solves while keeping0:1as the Boolean defaultdomainas the single public spelling, includingdomain = 0:(d - 1)for nonnegative integer domainsSolutionsampling and probability queries, infeasible results, and constraint projection MPOsSumConstraint; other constraint types continue to operate on physical Spin valuesValidation
julia +release --project=. -e 'using Pkg; Pkg.test()'Related work
Branch hygiene
mainat7e0fb9f94c8ff16c1d6cbe0213a32a06e0778397feat/issue-106-spin-domains; not stacked and has no prerequisite PRsrc/solution.jland/orsrc/solver.jl; they should reconcile their backend-specific solution/Ising APIs after this PR landsdocs/src/examples.mdandtest/runtests.jl, but its current hunks are non-adjacentCloses #106