Repository navigation
Enrich the tests, fix the wrapper defects they expose, and document the conventions - #86
Merged
Merged
Conversation
tests/_helpers.py holds the closed forms of a single pole, a composite Gauss-Legendre rule, non-contiguous views and an error report that prints the max abs error and the relative norm error. conftest.py gains a session-scoped get_basis fixture that shares one SVE per (lambda, eps); test_dlr.py uses it and drops its print calls. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
u(tau) outside [-beta, beta], v(omega) outside [-wmax, wmax] and DLR poles outside the frequency window reached a Rust panic reported as an internal error (SpM-lab/sparse-ir-rs#266); a reduced Matsubara index of the wrong parity came back as status -5 and an empty point array as status -6. They are now rejected, or answered, before the call: ValueError naming the value, and an empty result of the right shape. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
TauSampling sorted user-supplied points silently, so evaluate() returned values in another order than the points were given; it now keeps the order and copies the array. Points outside [-beta, beta] (a Rust panic) and duplicated points (a rank-deficient matrix) raise ValueError, as do negative points with positive_only=True (SpM-lab/sparse-ir-rs#247). With positive_only=True, evaluate() rejects genuinely complex coefficients; fit() results stay accepted. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
wmax = 0, eps <= 0, a non-finite beta, wmax, eps or lambda_ and max_size = 0 now raise ValueError before the C library is called (it answered with status -6 or a panic). A kernel or precomputed SVE whose cutoff or kernel type does not match beta * wmax is rejected: the C library built a wrong basis from it without complaint. RegularizedBoseKernel with fermionic statistics raises ValueError, as in SparseIR.jl. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
AugmentedTauFunction.xmin/xmax, AugmentedMatsubaraFunction.zeta, the size, shape and slicing of augmented function sets and TauLinear.hat() at a scalar frequency raised AttributeError or TypeError, and aug.u[-1] returned the last augmentation instead of the last function. The function sets now carry size, xmin/xmax or zeta, and negative indices are resolved against the whole set. The new smoke test calls every export and every function set once. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
O1: a single pole against its closed forms in tau and Matsubara frequency (both statistics, beta = 10 and 1000). O2: uhat against the Fourier integral of u. O3: reflection, Re/Im parity and (anti)periodicity. O4: sign changes, orthonormality, default-point structure and the closed forms of the DLR functions. O5: round trips for Lambda = 0.1 .. 1e5 and eps down to 1e-15. None of the references comes from libsparseir. The asymptotic regime of uhat (|n| >= 40*Lambda) is wrong in the backend for l = 1, 2 (mod 4) (SpM-lab/sparse-ir-rs#265); it is pinned by strict xfails so that a backend fix makes them fail and get promoted. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Port of SparseIR.jl's integration test: random DLR coefficients with extra dimensions (2, 3, 4) are taken to IR, tau and Matsubara both through the IR basis and directly through the DLR, with the basis axis at every position, for both statistics, positive_only on and off, real and complex data. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Removes the try/except-pass blocks in test_core.py and test_kernel.py, restores the commented-out uhat and Matsubara-sampling checks, seeds the remaining global random draws, and turns shape-only and finite-only assertions into symmetry, round-trip and closed-form checks. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
AugmentedBasis.default_matsubara_sampling_points(positive_only=True) asked the C library for the positive-only variant with the buffer size as the point limit, which returned a truncated set padded with zeros ([0, 2, 4, 12, 0, 0, 0] for a bosonic basis with TauConst and TauLinear). MatsubaraSampling(AugmentedBasis(...), positive_only=True) therefore always failed: with a singular matrix or a parity error before this branch, with a duplicate-point error about points the caller never passed after it. The points are now the non-negative half of the full set, as for a plain basis. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- basis[:n] truncates a FiniteTempBasis to its n most significant singular values (it raised NotImplementedError, which also made AugmentedBasis slicing unusable; #84). Slices of augmented function sets keep their type. - Slices and lists of basis functions always give a set, also of one function (u[0:1] returned a single function), and a set evaluates to shape (size,) + shape(x). Empty selections raise ValueError before the call; the C library panics on them (SpM-lab/sparse-ir-rs#269). - Single functions have deriv, like the sets. - Augmented function sets reject index lists with TypeError (they failed with "too many values to unpack") and truncation to the augmentations alone with ValueError; MatsubaraConst.hat checks the parity. - MatsubaraSampling.cond with positive_only=True is the condition number of the real least-squares problem the fit solves; the C library reports that of the complex matrix, 55 instead of 2e7 for an augmented basis (SpM-lab/sparse-ir-rs#270). - SVEResult raises TypeError for a non-numeric eps; overlap checks its interval once instead of every quadrature point (0.011 s -> 0.007 s); the u docstrings state the [-beta, beta] domain. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The strict xfails cite the issue URL (spec 12.3). The sign-change grid no longer contains beta/2, where the odd functions vanish, and the O5 check of the truncated basis asserts its precondition instead of skipping. Checks that only asserted finite values now test the symmetric structure of the default tau points and continuity at the interval ends. The unused test_bases fixture, which built pylibsparseir objects, is removed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
DiscreteLehmannRepresentation(AugmentedBasis(...)) failed with "AttributeError: 'AugmentedBasis' object has no attribute '_ptr'"; the DLR is built on the C handle of an IR basis. It now raises TypeError naming the requirement, as SparseIR.jl throws ArgumentError. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…wrappers Two changes of the review fixes altered documented behavior that SparseIR.jl pins in its tests; they are reverted here so the wrappers stay in step: - A one-element selection of u or v gives a single function again (SparseIR.jl: basis.u[2:2] isa PiecewiseLegendrePoly). The defect it was meant to fix, aug.u[:naug + 1] failing, is fixed where it was: augmented function sets accept a single function as their basis part, and single functions report size 1. Selections of uhat, including lists, still give sets (a list used to give a single-function object holding several). - MatsubaraConst.hat accepts both parities again: its docstring says the statistics do not affect it, and SparseIR.jl tests the same. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A value such as 1e300 is integral as a float, so the integer check let it reach the int64 cast, which printed an overflow warning before the misleading "must be an integer" error. The range is now checked first. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The tutorial links pointed to the tutorial of sparse-ir v1, which is now marked deprecated, and the C library links to the archived C++ libsparseir repository. They now point to https://spm-lab.github.io/sparse-ir-tutorial-v2/ and to sparse-ir-rs, which builds the libsparseir C API. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
tutorials/ held jupytext copies imported from pysparseir. Eleven of the thirteen did `import pylibsparseir as sparse_ir` and could not run with the current package, and four were stubs. The maintained tutorial is https://spm-lab.github.io/sparse-ir-tutorial-v2/, which README.rst and doc/tutorial.rst link. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
TauLinear('F') was accepted, but its Matsubara values were those of the
bosonic function (for example -3.487i at n = 1 instead of the transform
-2.220) and its derivative had the wrong sign at negative tau, so the tau
and Matsubara columns of a fermionic augmented basis disagreed. Both
tau augmentations now raise ValueError for fermions, as TauConst did. Its
error message claimed that the fermionic transform vanishes at every odd
frequency, which is false (it is 2i sqrt(beta)/(pi n)); it now says that
the augmentation is defined for bosons only. The docstrings state the
functions and their transforms, and the derivatives return floats for
integer tau arrays (np.full_like kept the integer dtype and returned 0).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
rescale passed the accuracy of the basis (the first discarded singular value) as the new eps, so the rescaled set could keep one more function than a set built with the original eps (21 instead of 20 at beta = 10, wmax = 8, eps = 1e-6), contrary to its docstring and to FiniteTempBasis.rescale. It now passes the original eps. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
overlap probed f with a Python float, while the quadrature calls it with NumPy scalars, so functions written with array methods failed; the README's GF(2) example (np.sqrt(1 - w.clip(-1, 1)**2)) raised AttributeError. A function returning a Python float failed on f_res.dtype. The probe now uses a NumPy scalar and np.asarray, and the README example runs as written. The unused module-level _compute_overlap, which called _compute_overlap_internal with the wrong arguments, is removed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…#273) RegularizedBoseKernel now emits a DeprecationWarning; LogisticKernel is the default kernel for both statistics. Its docstring had the sign of the denominator wrong and called it fermionic; it now gives the kernel in dimensionless and physical units (irbasis paper, Chikano et al., CPC 240, 181 (2019), Eqs. (1)-(3)). For wmax != 1 libsparseir scales the singular values of a RegularizedBoseKernel basis by wmax**-1 instead of wmax**+1 (SpM-lab/sparse-ir-rs#273). test_o6 compares sum_l U_l S_l V_l with the physical kernel at wmax = 2 and is a strict xfail until the fix is released. The deprecation warning is filtered in the test configuration; test_kernel.py asserts it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
AugmentedBasis passed augmentation instances through unchecked, so a TauConst(5.0) augmented a beta = 10 basis (normalized for the wrong beta, and failing outside [-5, 5]) and a bosonic TauConst/TauLinear augmented a fermionic basis. Instances now need the basis's beta, and TauConst and TauLinear a bosonic basis; MatsubaraConst stays statistics-agnostic. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The kernel list now marks RegularizedBoseKernel as deprecated. The bosonic weight of LogisticKernel is 1/tanh(βω/2), not 1/tanh(ω/ωmax), as kernel.py already says: for a bosonic pole at ω0 = 0.1 (β = 10, ωmax = 8, eps = 1e-12), G_l = -s_l v_l(ω0) w(ω0) reproduces 1/(iν - ω0) to 1.5e-13 with the former and misses it by 3.6e2 with the latter. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The docstrings now state the conventions of the notation page (https://spm-lab.github.io/sparse-ir-doc/src/notation.html) as the code implements them; each statement was checked numerically (beta = 10, wmax = 8). - FiniteTempBasis: the example computed -G (gl = +s v); with gl = -s v(2.5) it reproduces 1/(iν - 2.5) to 5e-16. The class now gives K(τ, ω) in physical units, G(τ) = -<T c(τ) c†(0)>, G_l = -S_l ρ_l with ρ = A (F) or A/tanh(βω/2) (B), orthonormality on [0, β] and [-ωmax, ωmax], the gauge U_l(β⁻) > 0, the U, S, V shared by both statistics, truncation S_l/S_0 >= eps and S_l = sqrt(βωmax/2) s_l. The attribute is v (not V), the kernel is not inferred from the statistics, the omega points are real frequencies (the roots of V_L), unfolded τ points lie in (-β/2, β/2] symmetric about 0 and folded ones in [0, β), and finite_temp_bases builds two kernels. - u of all bases, TauSampling and the augmentations: τ in [-β, β], U(τ) = (-1)^ζ U(τ + β), +0.0 = 0⁺, beta = β⁻, -0.0 = 0⁻ and -beta = (-β)⁺. - Matsubara: iν with the reduced frequency n, ν = nπ/β, not an index; the Fourier transform and its inverse; positive_only means n >= 0 and G(-iν) = G(iν)*, and fit then returns complex128 with zero imaginary part. fit's claim that only a complex C entry point exists is dropped. - DLR: the poles are the roots of V_L, not extrema; u_p = -K(τ, ω_p); û_p = 1/(iν - ω_p) (F) and tanh(βω_p/2)/(iν - ω_p) (B); G_l = -S_l Σ_p V_l(ω_p) c_p. - SVEResult does not truncate at eps (len 60 for eps = 1e-2 to 1e-15), cutoff and n_sv have no effect, and only s is exposed; compute takes kernel, not K. - accuracy: the abstract default is significance[-1]; FiniteTempBasis returns S_L/S_0 and the DLR and augmented bases forward it. - LogisticKernel: physical form, and the bosonic identity without the undefined ρ′; RegularizedBoseKernel acts on A(ω)/ω. - poly: the [xmin, xmax] domain, period, default overlap ranges and the transform over [0, β]; _util: the reduced-frequency formula and the -0.0 rule of normalize_tau. - NumPy-style section headers lose their colon so napoleon renders them. Only docstrings changed: with docstrings stripped, the ASTs of all ten modules equal those at the parent commit, and the test suite still gives 345 passed, 5 xfailed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- README.rst and doc/index.rst link the notation page, and the README summarizes the main conventions. The GF(2) example uses iν names (siv, Sigmaiv, G0iv, Giv) and still converges in 11 iterations with Im Σ(iν) < 0. The cutoff advice is given in terms of wmax instead of lambda_ (the kernel depends only on Λ in the dimensionless variables), and U_l, S_l, V_l are named with their orthonormality intervals. - doc/kernels.rst: the "Custom kernels" section described an API that does not exist (callable kernels, hints(), FiniteTempBasis(K, 'F'), an undefined np). It now says that only the two kernels are supported and how to pass one. The introduction writes G(τ) = -∫ K w A with A = -Im G^R/π, gives both kernels in physical units and uses \tau and \omega inside math; the nonexistent __call__ members are no longer requested. - doc/conf.py: autoclass_content = "both", so that the constructor parameters (statistics, beta, wmax, eps, ...) are rendered; the kernel constructor docstrings, now rendered, name lambda_. - doc/otherbases.rst: fix the grammar and name the DLR poles. The Sphinx HTML build gives no warnings, as before. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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
This PR does three things:
spm-agent-rules/testing.md, including oracle tests whose reference values do not come from libsparseir.Behavior changes (user-visible)
Out-of-domain input:
u(τ),v(ω), DLR poles and TauSampling points outside their domain raiseValueErrorbefore the C call. Before, this was a Rust panic surfacing asRuntimeErrorwith status -7 (Out-of-domain τ/ω in spir_funcs_eval/spir_funcs_batch_eval and out-of-range points in spir_tau_sampling_new panic, collapsed to SPIR_INTERNAL_ERROR instead of SPIR_INVALID_ARGUMENT (core Rust + C ABI) sparse-ir-rs#266).Parity:
uhat(n)with the wrong parity raisesValueError(was status -5).Empty input: empty evaluation arrays return an empty result of the right shape (was status -6).
TauSampling order: user-supplied points keep the given order. They used to be sorted silently, so
evaluate()returned values in a different order from the points given.Sampling points: these raise
ValueError:positive_only=Trueevaluate()withpositive_only=TrueParameters: these raise
ValueError:wmax <= 0oreps <= 0beta,wmax,epsorlambda_max_size = 0beta * wmaxRegularizedBoseKernelwith fermionic statisticsStatistics: an invalid
statisticsstring withkernel=given used to be accepted silently and built a bosonic basis. It now raisesValueError.Augmented function sets: these now work:
AugmentedTauFunction.xmin/xmaxandAugmentedMatsubaraFunction.zetaTauLinear.hat(scalar)aug.u[-1]now returns the last function; it used to return an augmentation.Augmented positive_only sampling:
MatsubaraSampling(AugmentedBasis(...), positive_only=True)with the default points works now. It always failed before, because the positive-only default points of augmented bases were a truncated set padded with zeros. They are now the non-negative half of the full set, as for a plain basis.Basis truncation:
basis[:n]now truncates aFiniteTempBasisto its n most significant singular values. It raisedNotImplementedError, which also madeAugmentedBasisslicing unusable. Closes Basis truncation (basis[:n]) is unimplemented, which makes AugmentedBasis slicing unusable #84.Selections of basis functions:
ValueErrorbefore the call; the C library panics on them (fix(capi): spir_funcs_get_slice with nslice = 0 panics ("Cannot create empty PiecewiseLegendrePolyVector"), collapsed to SPIR_INTERNAL_ERROR sparse-ir-rs#269).uhatby list give a set; a list used to give a single-function object holding several functions.deriv.TypeError, and truncation to only the augmentations withValueError.MatsubaraSampling.condwithpositive_only=True: it is now the condition number of the real least-squares problem thatfitsolves. The C library reports that of the complex matrix, for example 55 instead of 2e7 for an augmented basis (fix(capi): spir_sampling_get_cond_num reports the condition number of the complex half matrix for positive-only Matsubara samplings, not of the real least-squares problem that fit solves sparse-ir-rs#270).Other checks:
FiniteTempBasisraisesTypeError; it used to be anAttributeError.SVEResultraisesTypeErrorfor a non-numericeps.ValueErrorwithout an overflow warning.overlap: it checks its interval once instead of at every quadrature point (0.011 s → 0.007 s). It probes the integrand with a NumPy scalar and accepts Python-float results, so the README's GF(2) example runs again; it failed withAttributeErroronw.clip.TauConst and TauLinear are bosonic-only:
statistics='F'raisesValueError.TauLinear.hatreturned the bosonic transform, so its τ and Matsubara columns disagreed.Augmentation instances: an instance passed to
AugmentedBasismust have the basis's β, and TauConst/TauLinear a bosonic basis. They were passed through unchecked, so e.g.TauConst(5.0)augmented a β = 10 basis.FiniteTempBasisSet.rescalekeepseps. It passed the basis accuracy, so eps shrank and the basis could grow (20 → 21 functions at eps = 1e-6).RegularizedBoseKernelis deprecated and emits aDeprecationWarning;LogisticKernelis the default for both statistics. Its docstring had the sign of the denominator wrong and called it fermionic.Documentation:
doc/tutorial.rstlink to the v2 tutorial and sparse-ir-rs.tutorials/are removed.doc/kernels.rstmarksRegularizedBoseKerneldeprecated and fixes the bosonic weight ofLogisticKernel(1/tanh(βω/2), not 1/tanh(ω/ωmax)).Documentation
The docstrings, README.rst and
doc/now state the conventions the code implements, with the notation of the new sparse-ir-doc page Notation and conventions (SpM-lab/sparse-ir-doc#5). Library code is unchanged: with docstrings removed, the syntax trees of the changed modules are identical.FiniteTempBasisexample computed −G (gl = +s·v);dlr.py's formula omitted the bosonic tanh factor;SVEResultdoes not truncate ateps;V, "kernel inferred from statistics", ω points called "imaginary time", the reduced-frequency formula in_util.pyand the −0.0 case ofnormalize_tau.doc/kernels.rst: the section on custom kernels described an API that does not exist; it now lists the two supported kernels and how to pass one.doc/conf.py:autoclass_content = "both", so constructor parameters render. TheParametersheaders are in NumPy style.FiniteTempBasisexample reproduces 1/(iν − 2.5) to 4.5e−16.Backend defects found
All were reported to SpM-lab/sparse-ir-rs. All but #273 are fixed on its main branch; the fixes reach this package with the next pylibsparseir release.
uhatis wrong for l ≡ 1, 2 (mod 4) at |n| ≥ 40Λ.tests/test_oracle.py. They turn into unexpected passes, to be removed, once a fixed pylibsparseir is used.spir_basis_get_default_matsus_extusedn_pointsboth as the basis size and as the output capacity, which gave the positive-only point sets above.spir_funcs_get_slicepanics. Fixed upstream by #281; the wrapper rejects empty selections first.condof positive-only samplings is understated. Fixed upstream by #280; the wrapper computes it itself.RegularizedBoseKernelbasis carries S_l ∝ ωmax⁻¹ instead of ωmax⁺¹ (irbasis paper, Eq. (25)).tests/test_oracle.py.Tests
test_oracle.pytest_boundary.pytest_public_surface.pytest_integration.py(a port of SparseIR.jl's integration test)_helpers.pyCompanion PRs: SpM-lab/SparseIR.jl#158 (Julia), SpM-lab/sparse-ir-doc#5 (notation page), SpM-lab/sparse-ir-rs#286 (#273 fix, merged).
🤖 Generated with Claude Code