Skip to content

Releases: 0xC000005/PyChebyshev

v0.21.1

27 Apr 18:47
758aa46

Choose a tag to compare

TT _dim_order cluster cleanup + open issues + perf + sobol parity

Closes the v0.20+v0.20.1 _dim_order cluster on ChebyshevTT (3 latent bugs surfaced by ultrareview), three open follow-up issues, two perf hoists, and adds ChebyshevTT.sobol_indices() parity.

Fixed (TT _dim_order cluster)

  • roots/minimize/maximize validate against user-frame domain (was storage-frame)
  • inner_product raises ValueError on mismatched _dim_order (was silently miscomputing)
  • get_evaluation_points returns user-frame columns (was storage-frame)

Open issues closed

  • #19eval_multi thread-safety: structural fix via _eval_storage_frame private helper
  • #20integrate error message references user-frame dim
  • #22_algebra._check_compatible uses np.allclose (handles tuple-vs-list domain syntax)

Added

  • ChebyshevTT.sobol_indices() — first-order + total-order Sobol indices via native TT contraction (O(d·n·r²)), no dense materialization. Cross-validated against ChebyshevApproximation.sobol_indices to ~1e-9.

Performance

  • _calculus._optimize_1d vectorized — used by all four classes' minimize/maximize
  • vectorized_eval_batch derivative-matrix hoist with moveaxis correction — speedup for batch derivative eval
  • Sobol total-order via cached L/R partials — O(d²·n·r²) → O(d·n·r²)

Tests

26 new tests across 7 test files. Total: 1141 passing on Python 3.10/3.11/3.12/3.13. Project coverage 93% (95% on core library).

PR: #23

v0.21.0

27 Apr 15:32
405386a

Choose a tag to compare

Slider/TT Calculus Parity

Closes the calculus parity gap promised since v0.17. After v0.21.0, all four public classes (ChebyshevApproximation, ChebyshevSpline, ChebyshevSlider, ChebyshevTT) support the full calculus surface: integrate, roots, minimize, maximize.

Added

  • ChebyshevSlider.roots(dim, fixed) — find all roots along dim with other dims fixed
  • ChebyshevSlider.minimize(dim, fixed) — global minimum along dim
  • ChebyshevSlider.maximize(dim, fixed) — global maximum along dim
  • ChebyshevTT.roots(dim, fixed) — same; user-frame dim/fixed, transparent under _dim_order (v0.20+)
  • ChebyshevTT.minimize(dim, fixed) — same
  • ChebyshevTT.maximize(dim, fixed) — same

Implementation

Pure delegation: each method validates via the existing _calculus._validate_calculus_args, reduces N-D to 1-D via self.slice(slice_params), constructs a 1-D ChebyshevApproximation via from_values(), and delegates to its roots()/minimize()/maximize() from v0.9. No new math.

Tests

57 new tests across 9 test classes in tests/test_calculus_completion.py (1112 total project tests pass on Python 3.10/3.11/3.12/3.13).

PR: #21

v0.20.1: TT _dim_order Full Threading + reorder()

27 Apr 13:51
e51211a

Choose a tag to compare

Patch release closing the v0.20 known limitations on ChebyshevTT.

What changed

v0.20 shipped with_auto_order() (heuristic dim reordering for rank reduction) but six methods raised NotImplementedError on non-identity _dim_order. v0.20.1 threads _dim_order through every public TT method and adds reorder() as the explicit alignment escape hatch for binary algebra between TTs of different orders.

Threaded methods (no longer guarded)

  • eval_multi(point, derivative_orders) — point + per-deriv axis labels translated user→storage
  • slice(dim_idx, value) — descending storage_pos processing, mutable live_dim_order
  • extrude(dim_idx, lo, hi, n_nodes) — identity branch preserves v0.18 behavior bit-for-bit
  • to_dense() — final transpose via inverse permutation
  • integrate(dims=, bounds=) partial — storage_for map keys quadrature/contraction/bounds by storage positions
  • Unary algebra (__neg__, __mul__ scalar, __truediv__ scalar) — propagates _dim_order

New public API

  • ChebyshevTT.reorder(new_order, *, max_rank=None, tolerance=None) — bubble-sort permutation alignment via TT-swap on coefficient cores. Use this to align two TTs of different _dim_orders before binary algebra:
    result = (tt1 + tt2.reorder(tt1.dim_order))

Binary algebra error message

__add__ / __sub__ on TTs of different _dim_order now raise ValueError (not NotImplementedError) with an actionable fix:

TT dim_order mismatch: [0, 1, 2] vs [2, 0, 1]. Call other = other.reorder(self.dim_order)
(or self = self.reorder(other.dim_order)) to align before adding/subtracting.

Tests

  • 1055 tests pass on Python 3.10/3.11/3.12/3.13
  • New tests/test_v0201_dim_threading.py (~63 tests, 9 classes) — TDD-driven per method
  • v0.20 guard tests flipped from _raises to _works
  • v0.18 TT parity (52 tests) untouched — identity-_dim_order paths unchanged

Compatibility

  • Fully backward-compatible. Canonical-order TTs (with_auto_order not called) take the same code path as v0.18-v0.20.
  • No new dependencies. No version bumps to existing deps.

See CHANGELOG.md for full details.

v0.20.0: Adaptive Refinement + Cross-Language Interop

27 Apr 03:42
5911925

Choose a tag to compare

Adaptive Refinement + Cross-Language Interop

Added

  • ChebyshevSpline.auto_knots(f, num_dim, domain, ...) classmethod — auto-place knots at function kinks via curvature-spike scan. Heuristic; tunable via threshold_factor, max_knots_per_dim, n_scan_points.
  • sobol_indices() instance method on ChebyshevApproximation and ChebyshevSpline — first-order and total-order Sobol sensitivity indices computed directly from spectral coefficients (no Monte Carlo, no extra function evaluations).
  • ChebyshevTT.with_auto_order(f, ...) classmethod — heuristic dimension reordering (greedy-swap or random) to minimize TT rank. New dim_order property; eval/save/load handle permutation transparently.
  • Reference .pcb readers in Rust and Juliareaders/rust/ (Cargo crate pcb_reader) and readers/julia/ (Pkg package PCBReader) ship as standalone projects within this repo. Delivers on the v0.14 cross-language portability promise.

Beyond MoCaX: auto-knot detection, Sobol indices, and TT dim reordering are PyChebyshev-unique adaptive features. The Rust + Julia readers parse v0.14 .pcb format independently of Python.

Known limitations (planned for v0.20.1)

ChebyshevTT.with_auto_order() threads the permuted _dim_order through eval() and full integrate(). Other methods (eval_multi(), slice(), extrude(), to_dense(), partial integrate(), algebra) raise NotImplementedError/ValueError on non-identity permutations to avoid silent wrong-results bugs. Full threading planned for v0.20.1.

Tests

  • 1041 tests passing across Python 3.10–3.13
  • 95% line coverage
  • 462-test cross-feature suite for v0.20 additions

See CHANGELOG.md for full details.

v0.19.0 — Build & Diagnostics

26 Apr 17:09
1d6be14

Choose a tag to compare

Three opt-in features for users with slow f or large grids. Strictly additive — no breaking changes. New optional dependency group pychebyshev[viz].

What's new

  • Parallel buildn_workers= ctor kwarg on ChebyshevApproximation and ChebyshevSpline evaluates f via concurrent.futures.ProcessPoolExecutor. None = sequential, -1 = os.cpu_count(), positive int = pool size.
  • Progress barsverbose=2 opt-in tqdm bars on ChebyshevSpline, ChebyshevSlider, and ChebyshevTT build paths.
  • plot_convergence(target_error, max_n) on ChebyshevApproximation — builds at increasing N, plots error decay on log-y axis.
  • plot_1d / plot_2d_surface / plot_2d_contour instance methods on all four classes. Use fixed= to constrain dimensions.

Plus optional pychebyshev[viz] (matplotlib + tqdm). Plot methods raise ImportError with install hint when used without the group.

See docs/user-guide/build-diagnostics.md for usage.

Stats

  • 997 tests passing (was 949 baseline; +48 new)
  • 12 commits across 10 implementation tasks + 2 review-fix commits
  • All v0.11–v0.18 functionality preserved

v0.18.0 — TT Feature Parity

26 Apr 12:38
42745d7

Choose a tag to compare

After v0.18, ChebyshevTT has full surface parity with ChebyshevApproximation for non-calculus features. Strictly additive — no breaking changes.

What's new

  • ChebyshevTT.nodes(num_dim, domain, n_nodes) static — Chebyshev grid generation matching ChebyshevApproximation.nodes().
  • ChebyshevTT.from_values(tensor_values, ...) classmethod — build TT directly from a precomputed full tensor via TT-SVD compression, skipping TT-Cross.
  • ChebyshevTT.extrude(params) — add a constant-function dimension; inserts a rank-preserving constant core.
  • ChebyshevTT.slice(params) — fix a dimension at a value via barycentric contraction (fast path at nodes).
  • TT algebra: +, -, * (scalar), __neg__, plus in-place variants. TT addition uses block-diagonal core stacking + TT-SVD rounding to max(self.max_rank, other.max_rank) to prevent rank explosion.
  • ChebyshevTT.to_dense() — materialize the TT chain into a full N-D tensor.

See CHANGELOG.md and docs/user-guide/tensor-train.md for usage.

Stats

  • 949 tests passing (was 897 baseline)
  • 96% line coverage
  • 10 commits across 10 implementation tasks
  • All v0.11–v0.17 functionality preserved

v0.17.0 — Integrate Everywhere

26 Apr 03:05
430cbeb

Choose a tag to compare

After v0.17, every PyChebyshev class supports integration. v0.9 had integrate() on ChebyshevApproximation and ChebyshevSpline; this release closes the gap on ChebyshevSlider and ChebyshevTT.

What's new

  • ChebyshevSlider.integrate(dims=None, bounds=None) — full and partial integration via the sliding-decomposition closed form. Returns scalar on full integration; a ChebyshevSlider over surviving dims on partial.
  • ChebyshevTT.integrate(dims=None, bounds=None) — full and partial integration via Fejér-1 quadrature contraction into each integrated core's node axis. Returns scalar on full integration; a ChebyshevTT over surviving dims on partial. Works on TT objects built via Cross, SVD, and ALS methods.

Both implementations support sub-interval bounds, dim-order invariance, and chain through partial integrations consistently.

Implementation notes

  • TT integration handles the DCT-II coefficient↔value-space distinction correctly: _coeff_core_to_value_core(...) is invoked only on integrated cores before applying quadrature weights; kept cores stay in coefficient space (rank-axis matrix absorption is value-space-agnostic).
  • Slider integration uses the unified rule new_tensor = vol_outside · source + (pv_new − pv · vol_T) for partial paths, equivalent to the spec's closed form across all classification cases.
  • 2 new private helpers in _calculus.py: _slider_partition_intersect(), _integrate_tt_along_dim().

Stats

  • 897 tests passing (from 853 baseline)
  • 95% line coverage; 97% on slider.py, 95% on tensor_train.py
  • 11 commits across 10 implementation tasks
  • Math empirically validated to ~1e-11–1e-15 across all paths

Beyond MoCaX

MoCaX 4.3.1 has no integrate() API on any class — PyChebyshev's spectral calculus toolkit is unique to this library.

See CHANGELOG.md and the Spectral Calculus user guide for details.

v0.16.0 — Polish Bundle

26 Apr 00:58
50a6ccd

Choose a tag to compare

The final cosmetic mirror of the MoCaX 4.3.1 surface. Strictly additive — no breaking changes.

What's new

11 v0.16 surface items across all four classes:

  • clone() deep copy on all four classes (function=None post-clone, like save/load)
  • Instance getters: get_max_derivative_order(), get_error_threshold(), get_special_points(), get_evaluation_points(), get_num_evaluation_points()
  • Static helpers: peek_format_version(filename), is_dimensionality_allowed(num_dim)
  • defer_build=True ctor flag + set_original_function_values(values) — in-place deferred construction (alt to the from_values() factory; bit-identical results)
  • Optional typed helpers Domain, Ns, SpecialPoints (frozen dataclasses; constructors accept both raw lists and these forms)

Plus: ChebyshevTT now accepts max_derivative_order keyword-only kwarg with __setstate__ backfill for legacy pickles.

See CHANGELOG.md for the full list and docs/user-guide/ergonomics.md for usage examples.

Stats

  • 853 tests passing (from 761 baseline)
  • 96% line coverage
  • 17 commits across 11 implementation tasks
  • All v0.11–v0.15 functionality preserved

v0.15.0 — Ergonomics Bundle

25 Apr 16:57
43a2e30

Choose a tag to compare

v0.15.0 — Ergonomics Bundle

Closes the remaining MoCaX 4.3.1 API-parity gaps with four small, additive features.

Added

  • additional_data= constructor kwarg on ChebyshevApproximation, ChebyshevSpline, ChebyshevSlider, and ChebyshevTT — threads user-supplied context through every f(point, data) call during build, eliminating closure boilerplate.
  • set_descriptor(s) / get_descriptor() on all four classes — free-form text labels.
  • get_derivative_id(orders) registry + eval(point, derivative_id=...) on ChebyshevApproximation, ChebyshevSpline, and ChebyshevSlider — stable session-local integer IDs over derivative-orders tuples (TT excluded since it has no derivative_order arg).
  • Introspection trio is_construction_finished() / get_constructor_type() / get_used_ns() on all four classes.

Changed

  • Breaking: ChebyshevApproximation.get_derivative_id was previously a no-op stub returning the input list. It now returns a stable session-local int per registered orders tuple.

Persistence semantics

  • Pickle preserves all v0.15 metadata (descriptor, additional_data, derivative-id registry).
  • Binary .pcb save raises NotImplementedError if additional_data is not None. Use format='pickle' for full persistence. Descriptor and derivative-id registry are silently dropped on .pcb save (reset to "" / empty on load).
  • Factory-derived interpolants (extrude, slice, partial integrate, algebra) reset all v0.15 metadata to defaults.

Tests + coverage

  • 761 tests pass (was 663 baseline; +98 new across test_ergonomics.py, test_binary_format.py, test_barycentric.py).
  • 96% line coverage across the package.

Docs

  • New user-guide page at docs/user-guide/ergonomics.md.
  • Binary-format docs extended with v0.15 metadata gap rows.
  • MoCaX side-by-side comparison script at compare_ergonomics.py (local-only, requires mocax_lib/).

🤖 Generated with Claude Code

v0.14.0 — Portable .pcb binary serialization

25 Apr 04:12
8282795

Choose a tag to compare

Adds an opt-in portable binary serialization format for ChebyshevApproximation and ChebyshevSpline. Cross-language consumers (C/Rust/Julia) can read PyChebyshev interpolants without Python.

Highlights

  • format='binary' kwarg on save() — opt-in; default stays 'pickle' (no breaking changes).
  • load() auto-detects via 4-byte magic header b"PCB\x00".
  • Stdlib struct + NumPy only — no new runtime dependencies.
  • C reference reader at examples/binary_reader/ (~240 lines, libm only).
  • Format spec at docs/user-guide/binary-format.md.

Restrictions

  • Binary format requires flat n_nodes for ChebyshevSpline. Nested-n_nodes splines raise NotImplementedError on binary save and fall back to pickle.
  • ChebyshevSlider and ChebyshevTT remain pickle-only in v0.14.

See CHANGELOG.md for full details.