Skip to content

Add optional SpinGlassPEPS backend#44

Open
bernalde wants to merge 3 commits into
feature/issue-37-backend-interfacefrom
feature/issue-38-spinglasspeps-backend
Open

Add optional SpinGlassPEPS backend#44
bernalde wants to merge 3 commits into
feature/issue-37-backend-interfacefrom
feature/issue-38-spinglasspeps-backend

Conversation

@bernalde
Copy link
Copy Markdown
Member

Summary

  • Adds core structured PEPS backend API: SquareGrid, KingGrid, PEPSBackend, solve_ising, and PEPSSolution.
  • Adds an optional TenSolverSpinGlassPEPSExt package extension that translates structured Ising/QUBO inputs into SpinGlassNetworks/SpinGlassEngine calls and decodes PEPS states back to TenSolver Boolean states.
  • Keeps DMRG as the default backend and preserves clear errors when the optional SpinGlass component stack is not available.
  • Documents the experimental dependency status and adds gated tests for the optional PEPS path.

Tests run

  • julia +1.12 --project=. -e 'using Test, Random, LinearAlgebra, TenSolver; include("test/utils.jl"); include("test/peps_backend.jl")'
    • Passed: PEPS backend core, 26 tests.
    • Skipped/broken as expected: optional SpinGlassPEPS extension test because the component packages are not available in the default environment.
  • git diff --check
    • Passed.
  • julia --project=docs/ docs/make.jl local
    • Passed.
  • julia +1.12 --project=. -e 'using Pkg; Pkg.test()'
    • Passed.
  • julia +1.12 --startup-file=no -e 'Meta.parse(read("ext/TenSolverSpinGlassPEPSExt.jl", String)); println("extension syntax parsed")'
    • Passed.
  • Temporary QUBOTools 0.11 load check:
    • julia +1.12 -e 'using Pkg; env = "/tmp/tensolver-qubotools011-check"; Pkg.activate(env); Pkg.develop(path="/home/bernalde/repos/TenSolver.jl"); Pkg.add(Pkg.PackageSpec(name="QUBOTools", version="0.11")); Pkg.instantiate(); Pkg.status(); using TenSolver; println("loaded with QUBOTools 0.11")'
    • Passed.

Notes about tests not run

  • The real SpinGlassPEPS CPU solve path could not be executed locally. A temporary environment with local clones of SpinGlassTensors, SpinGlassNetworks, SpinGlassEngine, and this branch failed to resolve against current registered compat bounds. After broadening TenSolver's QUBOTools compat to include 0.11, the remaining resolver conflict is SpinGlassNetworks 1.4 requiring CSV = "0.8"/old Parsers while TenSolver's ITensors/NDTensors stack requires InlineStrings with newer Parsers compatibility.
  • The extension code is therefore present as the optional/experimental source bridge requested by the issue, while CI keeps the SpinGlass component stack optional.

Closes #38

Copy link
Copy Markdown
Member Author

@bernalde bernalde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub rejected REQUEST_CHANGES because the authenticated account owns this pull request. The findings below are blocking from a maintainer review perspective. I would not merge this until the blocking issues above are addressed.

Comment thread src/solver.jl Outdated
_normalize_backend(backend::DMRGBackend) = backend
_normalize_backend(backend::PEPSBackend) = backend
_normalize_backend(backend::AbstractTenSolverBackend) = backend
function _normalize_backend(backend::Symbol)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: This reintroduces the hard-coded Symbol backend normalization that the current base just fixed. Because every symbol reaches this method, a package extension cannot add TenSolver._normalize_backend(::Val{:peps}) or another symbol-specific mapping; backend = :peps will always throw before extension-specific _minimize or _solve_ising methods can run. It also drops the fake-symbol regression test from test/backend.jl relative to the current base.

Please keep the current-base Val dispatch structure and layer PEPSBackend on top of it: _normalize_backend(backend::Symbol) = _normalize_backend(Val(backend)), _normalize_backend(::Val{:dmrg}) = default_backend, and a Val fallback that throws _backend_error(backend). Then keep/add a test proving a symbol-specific backend can be registered by an extension.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed by the restacked base and preserved here. The branch now inherits 009bcd1, which restores _normalize_backend(backend::Symbol) = _normalize_backend(Val(backend)), the Val{:dmrg} method, the Val fallback, and the fake-symbol regression test in test/backend.jl. No additional change was needed in e122868556e03840b5124333c6410b974e35a3db.

Comment thread docs/src/spinglasspeps_integration.md Outdated
SpinGlass component imports and calls. This keeps ordinary TenSolver installs
on the existing dependency footprint.

The extension is intentionally experimental while the upstream dependency stack
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: This documents that the registered SpinGlass component compat bounds do not resolve with TenSolver, and the tests skip the only extension exercise when those packages are absent. That means the PR exports and documents PEPSBackend as current public behavior, but users cannot activate it from registered packages and CI never runs the implementation in ext/TenSolverSpinGlassPEPSExt.jl. I confirmed the resolution failure in a fresh environment by developing this PR and adding SpinGlassNetworks, SpinGlassEngine, and SpinGlassTensors; Pkg reports no compatible Parsers version because SpinGlassNetworks 1.4 constrains CSV/Parsers while the TenSolver environment constrains InlineStrings/Parsers.

Please either keep this as non-public scaffolding until the optional stack resolves, or update the dependency/compat strategy so the optional packages install together with TenSolver and add a CI/test path that exercises the extension.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in e122868. PEPS backend/topology/result types are no longer exported or listed in public API docs, and docs/src/spinglasspeps_integration.md now describes the bridge as non-public scaffolding until the SpinGlass dependencies resolve and CI can cover the extension.

Comment thread src/solution.jl

sample(psi::Solution, n :: Integer) = [sample(psi) for _ in 1:n]

function sample(psi::PEPSSolution)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nonblocking: sample(::PEPSSolution) returns the most probable retained state deterministically rather than sampling according to probabilities, so sample(psi, n) repeats the same state. That is surprising next to sample(::Solution), which samples from the represented distribution, and next to the public probabilities field. Consider sampling from the cumulative probability distribution, or exposing deterministic best-state selection through a separate helper if that behavior is intentional.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in e122868. sample(::PEPSSolution) now draws from cumulative probability weights and validates length, nonnegative weights, and positive total weight. test/peps_backend.jl covers the weighted path and malformed probability vectors.

@bernalde bernalde force-pushed the feature/issue-37-backend-interface branch from f4a3769 to 009bcd1 Compare May 17, 2026 01:26
@bernalde bernalde force-pushed the feature/issue-38-spinglasspeps-backend branch from cb9598f to ca890fc Compare May 17, 2026 01:26
@bernalde
Copy link
Copy Markdown
Member Author

Pushed commit e122868556e03840b5124333c6410b974e35a3db.

Main changes:

  • Kept the PEPS bridge as non-public scaffolding while the registered SpinGlass component stack does not resolve with TenSolver and CI cannot exercise the extension.
  • Removed PEPS backend/topology/result exports and public API docs, while keeping internal qualified access for extension development.
  • Updated the integration note to describe the PEPS path as gated internal scaffolding rather than current public behavior.
  • Changed sample(::PEPSSolution) to sample by cumulative probability weights and added regression coverage for weighted sampling plus malformed probability vectors.
  • The outdated Symbol-dispatch thread is already addressed by the current Introduce solver backend interface #43 base: PR Add optional SpinGlassPEPS backend #44 now has the Val dispatch hook and fake-symbol backend test.

Tests run:

  • julia +1.12 --project=. -e 'using Test, Random, LinearAlgebra, TenSolver; include("test/utils.jl"); include("test/backend.jl"); include("test/peps_backend.jl")' - passed; backend interface 19 pass, PEPS backend core 34 pass, optional SpinGlassPEPS extension 1 expected broken.
  • julia +1.12 --project=. -e 'using Pkg; Pkg.test()' - passed.
  • julia +1.11.5 --project=docs/ docs/make.jl local - passed.
  • git diff --check - passed.

Notes on tests not cleanly runnable:

  • julia +1.12 --project=docs/ docs/make.jl local reaches doctests and document checks but fails during HTML rendering with could not find source path for package MbedTLS_jll from docs/Manifest.toml. The docs manifest was resolved with Julia 1.11.5, and the same docs command passes under +1.11.5.

Comments intentionally not addressed:

Remaining risks/follow-up:

Copy link
Copy Markdown
Member Author

@bernalde bernalde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fresh review of the current net diff: I did not find blocking issues. The PEPS scaffold is now kept out of exports/public API docs, and the restored Val backend dispatch preserves the extension hook. I left two nonblocking comments on test coverage and documentation wording.

Comment thread src/solver.jl
"""
function solve_ising end

function solve_ising(model::IsingModel; backend=default_backend, kwargs...)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nonblocking: solve_ising is now exported and listed in the API reference, but the PR only tests a one-spin field-only call through the IsingModel method. That does not exercise pair couplings, offset preservation, or the public solve_ising(J, h, offset) overload.

Please add a small exact 2- or 3-spin regression test that brute-forces the Ising objective and asserts both solve_ising(model; ...) and solve_ising(J, h, offset; ...) return the optimum and a Boolean sample whose converted spin state has matching Ising energy. That would make the new public API safer to maintain while the PEPS path remains internal.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in f3c4db1. test/backend.jl now brute-forces a two-spin Ising objective with pair coupling and offset, then checks both solve_ising(model; ...) and solve_ising(J, h, offset; ...) return the optimum and a sample whose spin energy matches it.

Comment thread docs/src/spinglasspeps_integration.md Outdated
behavior.

This stack step keeps the direct PEPS path as non-public scaffolding. The core
package contains internal backend, topology, `solve_ising`, and result
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nonblocking: This wording groups solve_ising into the non-public scaffolding, but solve_ising is exported and included in the public API reference. To keep the API boundary clear, please reword this to say the PEPS backend/topology/result types are internal scaffolding, while solve_ising is the public Ising boundary that optional structured backends may implement.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in f3c4db1. The integration note now says backend/topology/result boundaries are internal scaffolding, while exported solve_ising is the public Ising boundary optional structured backends may implement.

@bernalde
Copy link
Copy Markdown
Member Author

Pushed commit f3c4db10db4af978bb04f1ef9c804604f8b92c1a.

Main changes:

  • Added an exact two-spin solve_ising regression covering pair couplings, offset preservation, the IsingModel method, and the public solve_ising(J, h, offset) overload.
  • Clarified the SpinGlassPEPS integration note so PEPS backend/topology/result boundaries are internal scaffolding while exported solve_ising remains the public Ising boundary optional structured backends may implement.

Tests run:

  • julia +1.12 --project=. -e 'using Test, Random, LinearAlgebra, TenSolver; include("test/utils.jl"); include("test/backend.jl")' - passed; backend interface 25 pass.
  • julia +1.12 --project=. -e 'using Pkg; Pkg.test()' - passed.
  • julia +1.11.5 --project=docs/ docs/make.jl local - passed.
  • git diff --check - passed.

Comments intentionally not addressed:

  • None in the fresh review. Previously replied outdated threads remain addressed by 009bcd1584589592e135d6e7524d34cd3c03e712 and e122868556e03840b5124333c6410b974e35a3db.

Remaining risks/follow-up:

@codecov
Copy link
Copy Markdown

codecov Bot commented May 17, 2026

Codecov Report

❌ Patch coverage is 33.14917% with 121 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (feature/issue-37-backend-interface@009bcd1). Learn more about missing BASE report.

Files with missing lines Patch % Lines
ext/TenSolverSpinGlassPEPSExt.jl 0.00% 112 Missing ⚠️
src/solver.jl 82.50% 7 Missing ⚠️
src/solution.jl 93.10% 2 Missing ⚠️
Additional details and impacted files
@@                          Coverage Diff                          @@
##             feature/issue-37-backend-interface      #44   +/-   ##
=====================================================================
  Coverage                                      ?   72.84%           
=====================================================================
  Files                                         ?        6           
  Lines                                         ?      475           
  Branches                                      ?        0           
=====================================================================
  Hits                                          ?      346           
  Misses                                        ?      129           
  Partials                                      ?        0           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Member Author

@bernalde bernalde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the current net diff against feature/issue-37-backend-interface. No blocking or nonblocking inline issues found. The PEPS scaffolding remains internal, solve_ising is covered as public API, and the updated tests cover the newly public behavior and internal boundary sufficiently for this PR.

GitHub would not let me submit APPROVE because this account is the PR author: "Review Can not approve your own pull request".

Tests run locally:

  • git diff --check origin/feature/issue-37-backend-interface...HEAD
  • julia --project=. -e "using Pkg; Pkg.test()"
  • julia --project=. -e "using Test, Random, LinearAlgebra, TenSolver; include("test/utils.jl"); include("test/backend.jl"); include("test/peps_backend.jl")"
  • julia +1.12 --project=. -e "using Test, Random, LinearAlgebra, TenSolver; include("test/utils.jl"); include("test/backend.jl"); include("test/peps_backend.jl")"
  • julia --project=. targeted solve_ising exact-energy probe
  • julia --project=docs/ -e "using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()"
  • julia --project=docs/ docs/make.jl local

The optional SpinGlassPEPS extension path still cannot be exercised locally because SpinGlassNetworks/SpinGlassEngine/SpinGlassTensors cannot currently resolve with this package dependency stack; the PR documents that limitation and keeps the PEPS backend internal.

Merge recommendation: merge-ready from this review pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant