spacecore 0.3.2__tar.gz → 0.4.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- spacecore-0.4.1/CHANGELOG.md +637 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/MANIFEST.in +0 -1
- spacecore-0.4.1/PKG-INFO +342 -0
- spacecore-0.4.1/README.md +296 -0
- spacecore-0.4.1/docs/dev/0.4.1-bench-surface.md +159 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/adr/003_space_hierarchy.md +2 -2
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/adr/005_space_subclasses_and_capabilities.md +2 -2
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/adr/008_linop_subclasses.md +2 -2
- spacecore-0.4.1/docs/dev/adr/013_tree_structured_spaces.md +54 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/adr/014_check_policy.md +10 -2
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/adr/015_dtype_default_vs_scalar_field.md +5 -3
- spacecore-0.4.1/docs/dev/adr/016_kernel_layers.md +242 -0
- spacecore-0.4.1/docs/dev/adr/017_tensor_product_spaces.md +131 -0
- spacecore-0.4.1/docs/dev/adr/018_external_optimizer_adapters.md +111 -0
- spacecore-0.4.1/docs/dev/adr/019_everyday_toolbox.md +159 -0
- spacecore-0.4.1/docs/dev/adr/020_sets_and_projection.md +108 -0
- spacecore-0.4.1/docs/dev/adr/021_lazy_operator_algebra_and_simplification.md +131 -0
- spacecore-0.4.1/docs/dev/adr/022_caching.md +156 -0
- spacecore-0.4.1/docs/dev/adr/023_benchmark_framework.md +415 -0
- spacecore-0.4.1/docs/dev/adr/README.md +77 -0
- spacecore-0.4.1/docs/dev/adr/template.md +33 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/contributing/architecture.md +8 -10
- spacecore-0.4.1/docs/dev/contributing/linop_generators.md +47 -0
- spacecore-0.4.1/docs/dev/current.md +156 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/api/context.rst +3 -0
- spacecore-0.4.1/docs/source/api/functionals.rst +160 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/api/index.rst +1 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/api/linops.rst +21 -7
- spacecore-0.4.1/docs/source/api/optimize.rst +59 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/api/spaces.rst +17 -26
- spacecore-0.4.1/docs/source/design/backend_conformance.rst +452 -0
- spacecore-0.4.1/docs/source/design/backend_deviations.rst +138 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/design/batching.rst +6 -0
- spacecore-0.4.1/docs/source/design/batching_test_policy.rst +78 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/design/capability_dispatch.rst +2 -2
- spacecore-0.4.1/docs/source/design/checking_policy.rst +100 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/design/context_ownership.rst +14 -10
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/design/conversion_policy.rst +3 -3
- spacecore-0.4.1/docs/source/design/dtype_policy.rst +92 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/design/index.rst +5 -0
- spacecore-0.4.1/docs/source/design/kernels_policy.rst +218 -0
- spacecore-0.4.1/docs/source/design/tree_spaces.rst +192 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/dev/contributing.rst +6 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/index.rst +8 -4
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/release_notes.rst +154 -0
- spacecore-0.4.1/docs/source/tutorials/01_backend_and_context.rst +349 -0
- spacecore-0.4.1/docs/source/tutorials/02_linear_algebra.rst +289 -0
- spacecore-0.4.1/docs/source/tutorials/03_functionals.rst +270 -0
- spacecore-0.4.1/docs/source/tutorials/04_tree_spaces.rst +302 -0
- spacecore-0.4.1/docs/source/tutorials/05_weighted_tikhonov.rst +285 -0
- spacecore-0.4.1/docs/source/tutorials/06_optimal_transport.rst +263 -0
- spacecore-0.4.1/docs/source/tutorials/07_manifold_descent.rst +235 -0
- spacecore-0.4.1/docs/source/tutorials/08_pdhg_conic_program.rst +257 -0
- spacecore-0.4.1/docs/source/tutorials/09_kernels_and_fusion.rst +531 -0
- spacecore-0.4.1/docs/source/tutorials/index.rst +42 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/pyproject.toml +20 -1
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/__init__.py +49 -17
- spacecore-0.4.1/spacecore/_batching.py +59 -0
- spacecore-0.4.1/spacecore/_check_policy.py +88 -0
- spacecore-0.4.1/spacecore/_checks.py +137 -0
- spacecore-0.4.1/spacecore/_contextual/_bound.py +173 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/_contextual/_state.py +84 -27
- spacecore-0.4.1/spacecore/_repr.py +150 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/_version.py +1 -1
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/backend/__init__.py +3 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/backend/_context.py +59 -21
- spacecore-0.4.1/spacecore/backend/_eager.py +178 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/backend/_ops.py +227 -11
- spacecore-0.4.1/spacecore/backend/cupy/_ops.py +154 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/backend/jax/_ops.py +31 -19
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/backend/jax/_pytree.py +1 -1
- spacecore-0.4.1/spacecore/backend/numpy/_ops.py +298 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/backend/torch/_ops.py +33 -205
- spacecore-0.4.1/spacecore/functional/__init__.py +52 -0
- spacecore-0.4.1/spacecore/functional/_base.py +161 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/functional/_composed.py +11 -6
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/functional/_linear.py +48 -54
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/functional/_quadratic.py +16 -34
- spacecore-0.4.1/spacecore/functional/tools/__init__.py +29 -0
- spacecore-0.4.1/spacecore/functional/tools/_coordinate.py +72 -0
- spacecore-0.4.1/spacecore/functional/tools/_entropy.py +148 -0
- spacecore-0.4.1/spacecore/functional/tools/_huber.py +79 -0
- spacecore-0.4.1/spacecore/functional/tools/_least_squares.py +114 -0
- spacecore-0.4.1/spacecore/functional/tools/_norms.py +157 -0
- spacecore-0.4.1/spacecore/functional/tools/_proximal.py +226 -0
- spacecore-0.4.1/spacecore/functional/tools/_spectral.py +126 -0
- spacecore-0.4.1/spacecore/kernels/__init__.py +81 -0
- spacecore-0.4.1/spacecore/kernels/core/__init__.py +36 -0
- spacecore-0.4.1/spacecore/kernels/core/_rules.py +154 -0
- spacecore-0.4.1/spacecore/kernels/core/algebra.py +245 -0
- spacecore-0.4.1/spacecore/kernels/core/dense.py +114 -0
- spacecore-0.4.1/spacecore/kernels/core/diagonal.py +114 -0
- spacecore-0.4.1/spacecore/kernels/core/functional.py +153 -0
- spacecore-0.4.1/spacecore/kernels/core/sparse.py +123 -0
- spacecore-0.4.1/spacecore/kernels/specs/__init__.py +66 -0
- spacecore-0.4.1/spacecore/kernels/specs/_batched.py +234 -0
- spacecore-0.4.1/spacecore/kernels/specs/_dispatch.py +289 -0
- spacecore-0.4.1/spacecore/kernels/specs/_policy.py +209 -0
- spacecore-0.4.1/spacecore/kernels/specs/_registry.py +117 -0
- spacecore-0.4.1/spacecore/kernels/specs/block_batched.py +358 -0
- spacecore-0.4.1/spacecore/kernels/specs/block_diagonal.py +91 -0
- spacecore-0.4.1/spacecore/kernels/specs/composed.py +90 -0
- spacecore-0.4.1/spacecore/kernels/specs/composed_simplify.py +140 -0
- spacecore-0.4.1/spacecore/kernels/specs/stacked_batched.py +167 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/linalg/_cg.py +46 -16
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/linalg/_lanczos.py +10 -8
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/linalg/_lsqr.py +27 -20
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/linalg/_power.py +19 -15
- spacecore-0.4.1/spacecore/linalg/_utils.py +211 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/linop/__init__.py +3 -2
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/linop/_algebra.py +316 -161
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/linop/_base.py +80 -13
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/linop/_dense.py +24 -103
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/linop/_diagonal.py +18 -102
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/linop/_metric.py +3 -3
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/linop/_sparse.py +53 -110
- spacecore-0.4.1/spacecore/linop/tree/__init__.py +14 -0
- {spacecore-0.3.2/spacecore/linop/product → spacecore-0.4.1/spacecore/linop/tree}/_base.py +27 -18
- spacecore-0.4.1/spacecore/linop/tree/_block.py +482 -0
- {spacecore-0.3.2/spacecore/linop/product → spacecore-0.4.1/spacecore/linop/tree}/_from_single.py +52 -23
- {spacecore-0.3.2/spacecore/linop/product → spacecore-0.4.1/spacecore/linop/tree}/_to_single.py +51 -22
- spacecore-0.4.1/spacecore/optimize/__init__.py +20 -0
- spacecore-0.4.1/spacecore/optimize/_common.py +71 -0
- spacecore-0.4.1/spacecore/optimize/_optax.py +154 -0
- spacecore-0.4.1/spacecore/optimize/_scipy.py +260 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/space/__init__.py +8 -12
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/space/base/_coordinate.py +12 -4
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/space/base/_inner_product.py +18 -1
- spacecore-0.4.1/spacecore/space/base/_space.py +137 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/space/checks/__init__.py +2 -4
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/space/checks/_base.py +39 -81
- spacecore-0.4.1/spacecore/space/checks/_coordinate.py +10 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/space/concrete/__init__.py +4 -3
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/space/concrete/_dense_coordinate.py +51 -17
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/space/concrete/_dense_vector.py +23 -22
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/space/concrete/_hermitian.py +22 -19
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/space/concrete/_stacked.py +79 -38
- spacecore-0.4.1/spacecore/space/concrete/_tree_space.py +930 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/types/_array.py +2 -0
- spacecore-0.4.1/spacecore.egg-info/PKG-INFO +342 -0
- spacecore-0.4.1/spacecore.egg-info/SOURCES.txt +346 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore.egg-info/requires.txt +7 -1
- spacecore-0.4.1/tests/_conformance.py +318 -0
- spacecore-0.4.1/tests/backend/_conformance.py +41 -0
- spacecore-0.4.1/tests/backend/_references.py +731 -0
- spacecore-0.4.1/tests/backend/conftest.py +80 -0
- spacecore-0.4.1/tests/backend/test_backend_family.py +79 -0
- spacecore-0.4.1/tests/backend/test_context.py +435 -0
- spacecore-0.4.1/tests/backend/test_cupy_ops.py +153 -0
- spacecore-0.4.1/tests/backend/test_jax_ops.py +299 -0
- spacecore-0.4.1/tests/backend/test_jax_pytree_class.py +165 -0
- spacecore-0.4.1/tests/backend/test_lazy_namespace.py +59 -0
- spacecore-0.4.1/tests/backend/test_numpy_ops.py +191 -0
- spacecore-0.4.1/tests/backend/test_operations.py +1388 -0
- spacecore-0.4.1/tests/backend/test_torch_ops.py +223 -0
- spacecore-0.4.1/tests/backend/test_types_protocols.py +251 -0
- spacecore-0.4.1/tests/bench/test_bare_baseline.py +49 -0
- spacecore-0.4.1/tests/bench/test_bench_smoke.py +581 -0
- spacecore-0.4.1/tests/bench/test_macro_aggregate.py +140 -0
- spacecore-0.4.1/tests/bench/test_macro_dashboard.py +200 -0
- spacecore-0.4.1/tests/bench/test_macro_runner_smoke.py +220 -0
- spacecore-0.4.1/tests/bench/test_macro_schema.py +162 -0
- spacecore-0.4.1/tests/bench/test_regimes.py +131 -0
- spacecore-0.4.1/tests/context/conftest.py +26 -0
- spacecore-0.4.1/tests/context/test_check_policy.py +187 -0
- spacecore-0.4.1/tests/context/test_check_policy_helpers.py +147 -0
- spacecore-0.4.1/tests/context/test_checked_method.py +256 -0
- spacecore-0.4.1/tests/context/test_compatibility.py +254 -0
- spacecore-0.4.1/tests/context/test_context_bound.py +209 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/tests/context/test_enable_checks.py +10 -8
- spacecore-0.4.1/tests/context/test_policies_errors.py +183 -0
- spacecore-0.4.1/tests/context/test_state_free_functions.py +331 -0
- spacecore-0.4.1/tests/functional/conftest.py +46 -0
- spacecore-0.4.1/tests/functional/test_composed_functional.py +222 -0
- spacecore-0.4.1/tests/functional/test_functional_base.py +254 -0
- spacecore-0.4.1/tests/functional/test_generated_functionals.py +266 -0
- spacecore-0.4.1/tests/functional/test_inner_product_functional.py +182 -0
- spacecore-0.4.1/tests/functional/test_linear_functional.py +82 -0
- spacecore-0.4.1/tests/functional/test_linop_quadratic_form.py +190 -0
- spacecore-0.4.1/tests/functional/test_matrix_free_linear_functional.py +170 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/tests/functional/test_metric_gradient.py +7 -21
- spacecore-0.4.1/tests/functional/test_quadratic_form.py +117 -0
- spacecore-0.4.1/tests/functional/tools/test_battery_functionals.py +271 -0
- spacecore-0.4.1/tests/functional/tools/test_least_squares.py +107 -0
- spacecore-0.4.1/tests/functional/tools/test_proximal.py +269 -0
- spacecore-0.4.1/tests/functional/tools/test_spectral.py +137 -0
- spacecore-0.4.1/tests/generators/__init__.py +82 -0
- spacecore-0.4.1/tests/generators/_arrays.py +108 -0
- spacecore-0.4.1/tests/generators/_contexts.py +102 -0
- spacecore-0.4.1/tests/generators/_hermitian.py +77 -0
- spacecore-0.4.1/tests/generators/_metrics.py +79 -0
- spacecore-0.4.1/tests/generators/_params.py +60 -0
- spacecore-0.4.1/tests/generators/_protocol.py +18 -0
- spacecore-0.4.1/tests/generators/_seed.py +28 -0
- spacecore-0.4.1/tests/generators/_trees.py +108 -0
- spacecore-0.4.1/tests/generators/functionals.py +444 -0
- spacecore-0.4.1/tests/generators/linops.py +552 -0
- spacecore-0.4.1/tests/generators/spaces.py +590 -0
- spacecore-0.4.1/tests/generators/test_registry_completeness.py +155 -0
- spacecore-0.4.1/tests/generators/test_smoke.py +89 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/tests/integration/test_imports.py +1 -1
- {spacecore-0.3.2 → spacecore-0.4.1}/tests/integration/test_public_api.py +36 -10
- {spacecore-0.3.2 → spacecore-0.4.1}/tests/integration/test_smoke_numpy.py +1 -1
- spacecore-0.4.1/tests/integration/test_smoke_torch.py +63 -0
- spacecore-0.4.1/tests/kernels/conftest.py +22 -0
- spacecore-0.4.1/tests/kernels/test_core_kernel_dispatch.py +251 -0
- spacecore-0.4.1/tests/kernels/test_kernel_dispatch.py +574 -0
- spacecore-0.4.1/tests/kernels/test_kernel_registry.py +143 -0
- spacecore-0.4.1/tests/kernels/test_kernel_spec.py +109 -0
- spacecore-0.4.1/tests/kernels/test_kernels_match_generic.py +506 -0
- spacecore-0.4.1/tests/kernels/test_materialized_cache.py +266 -0
- spacecore-0.4.1/tests/linalg/_helpers.py +74 -0
- spacecore-0.4.1/tests/linalg/conftest.py +19 -0
- spacecore-0.4.1/tests/linalg/test_cg.py +282 -0
- spacecore-0.4.1/tests/linalg/test_core_resolution.py +110 -0
- spacecore-0.4.1/tests/linalg/test_expm_multiply.py +193 -0
- spacecore-0.4.1/tests/linalg/test_generated_solver_matrix.py +129 -0
- spacecore-0.4.1/tests/linalg/test_lanczos.py +260 -0
- spacecore-0.4.1/tests/linalg/test_lsqr.py +236 -0
- spacecore-0.4.1/tests/linalg/test_power_iteration.py +377 -0
- spacecore-0.4.1/tests/linalg/test_result_types.py +117 -0
- spacecore-0.4.1/tests/linalg/test_solver_contracts.py +114 -0
- spacecore-0.4.1/tests/linalg/test_utils.py +186 -0
- spacecore-0.4.1/tests/linops/conftest.py +35 -0
- spacecore-0.4.1/tests/linops/test_algebra_factories.py +354 -0
- spacecore-0.4.1/tests/linops/test_algebra_linops.py +986 -0
- spacecore-0.4.1/tests/linops/test_block_diagonal_linop.py +378 -0
- spacecore-0.4.1/tests/linops/test_block_matrix_linop.py +156 -0
- spacecore-0.4.1/tests/linops/test_dense_linop.py +516 -0
- spacecore-0.4.1/tests/linops/test_diagonal_linop.py +327 -0
- spacecore-0.4.1/tests/linops/test_fuse.py +323 -0
- spacecore-0.4.1/tests/linops/test_fused_algebra_overhead.py +224 -0
- spacecore-0.4.1/tests/linops/test_generated_linop_laws.py +149 -0
- spacecore-0.4.1/tests/linops/test_linop_base.py +386 -0
- spacecore-0.4.1/tests/linops/test_linop_jit.py +201 -0
- spacecore-0.4.1/tests/linops/test_metric_helpers.py +255 -0
- spacecore-0.4.1/tests/linops/test_sparse_linop.py +359 -0
- spacecore-0.4.1/tests/linops/test_stacked_linop.py +289 -0
- spacecore-0.4.1/tests/linops/test_sum_to_single_linop.py +290 -0
- spacecore-0.4.1/tests/linops/test_tree_helpers.py +100 -0
- spacecore-0.4.1/tests/linops/test_tree_linop_base.py +85 -0
- spacecore-0.4.1/tests/optim/test_cached_member_checks.py +157 -0
- spacecore-0.4.1/tests/optimize/__init__.py +0 -0
- spacecore-0.4.1/tests/optimize/_helpers.py +54 -0
- spacecore-0.4.1/tests/optimize/test_contracts.py +126 -0
- spacecore-0.4.1/tests/optimize/test_line_search_scipy.py +89 -0
- spacecore-0.4.1/tests/optimize/test_metric_handoff.py +63 -0
- spacecore-0.4.1/tests/optimize/test_minimize_optax.py +113 -0
- spacecore-0.4.1/tests/optimize/test_minimize_scipy.py +133 -0
- spacecore-0.4.1/tests/spaces/__init__.py +0 -0
- spacecore-0.4.1/tests/spaces/_generated_helpers.py +52 -0
- spacecore-0.4.1/tests/spaces/conftest.py +40 -0
- spacecore-0.4.1/tests/spaces/test_check_batched.py +181 -0
- spacecore-0.4.1/tests/spaces/test_coordinate_space_base.py +113 -0
- spacecore-0.4.1/tests/spaces/test_dense_coordinate_space.py +189 -0
- spacecore-0.4.1/tests/spaces/test_dense_vector_space.py +70 -0
- spacecore-0.4.1/tests/spaces/test_elementwise_jordan_spaces.py +135 -0
- spacecore-0.4.1/tests/spaces/test_generated_dense_coordinate.py +132 -0
- spacecore-0.4.1/tests/spaces/test_generated_dense_vector.py +60 -0
- spacecore-0.4.1/tests/spaces/test_generated_inner_product.py +96 -0
- spacecore-0.4.1/tests/spaces/test_generated_jordan_space.py +111 -0
- spacecore-0.4.1/tests/spaces/test_generated_space_laws.py +34 -0
- spacecore-0.4.1/tests/spaces/test_generated_tree_space.py +105 -0
- spacecore-0.4.1/tests/spaces/test_hermitian_space.py +192 -0
- spacecore-0.4.1/tests/spaces/test_inner_product.py +164 -0
- spacecore-0.4.1/tests/spaces/test_inner_product_space_base.py +114 -0
- spacecore-0.4.1/tests/spaces/test_jordan_algebra_spaces.py +182 -0
- spacecore-0.4.1/tests/spaces/test_space_base.py +149 -0
- spacecore-0.4.1/tests/spaces/test_space_checks.py +392 -0
- spacecore-0.4.1/tests/spaces/test_stacked_space.py +335 -0
- spacecore-0.4.1/tests/spaces/test_star_space_base.py +80 -0
- spacecore-0.4.1/tests/spaces/test_tree_space.py +488 -0
- spacecore-0.4.1/tests/spaces/test_tree_spectral_decomposition.py +79 -0
- spacecore-0.4.1/tests/spaces/test_vector_space_base.py +82 -0
- spacecore-0.4.1/tests/test_repr.py +433 -0
- spacecore-0.4.1/tests/test_weighted_tikhonov.py +80 -0
- spacecore-0.4.1/tutorials/01_backend_and_context.ipynb +564 -0
- spacecore-0.4.1/tutorials/02_linear_algebra.ipynb +502 -0
- spacecore-0.4.1/tutorials/03_functionals.ipynb +426 -0
- spacecore-0.4.1/tutorials/04_tree_spaces.ipynb +501 -0
- spacecore-0.4.1/tutorials/05_weighted_tikhonov.ipynb +476 -0
- spacecore-0.4.1/tutorials/06_optimal_transport.ipynb +445 -0
- spacecore-0.4.1/tutorials/07_manifold_descent.ipynb +354 -0
- spacecore-0.4.1/tutorials/08_pdhg_conic_program.ipynb +416 -0
- spacecore-0.4.1/tutorials/09_kernels_and_fusion.ipynb +810 -0
- spacecore-0.4.1/tutorials/README.md +50 -0
- spacecore-0.3.2/CHANGELOG.md +0 -315
- spacecore-0.3.2/PKG-INFO +0 -206
- spacecore-0.3.2/README.md +0 -165
- spacecore-0.3.2/docs/dev/adr/013_tree_structured_spaces.md +0 -36
- spacecore-0.3.2/docs/dev/adr/README.md +0 -71
- spacecore-0.3.2/docs/dev/current.md +0 -32
- spacecore-0.3.2/docs/source/api/functionals.rst +0 -80
- spacecore-0.3.2/docs/source/design/checking_policy.rst +0 -69
- spacecore-0.3.2/docs/source/design/dtype_policy.rst +0 -62
- spacecore-0.3.2/docs/source/tutorials/backend_ops.rst +0 -104
- spacecore-0.3.2/docs/source/tutorials/context.rst +0 -103
- spacecore-0.3.2/docs/source/tutorials/conversion_policy.rst +0 -102
- spacecore-0.3.2/docs/source/tutorials/index.rst +0 -88
- spacecore-0.3.2/docs/source/tutorials/linops.rst +0 -139
- spacecore-0.3.2/docs/source/tutorials/regularized_ot.rst +0 -662
- spacecore-0.3.2/docs/source/tutorials/spaces.rst +0 -124
- spacecore-0.3.2/docs/source/tutorials/weighted_tikhonov.rst +0 -194
- spacecore-0.3.2/examples/weighted_tikhonov.py +0 -267
- spacecore-0.3.2/spacecore/_batching.py +0 -18
- spacecore-0.3.2/spacecore/_checks.py +0 -95
- spacecore-0.3.2/spacecore/_contextual/_bound.py +0 -57
- spacecore-0.3.2/spacecore/_tree.py +0 -26
- spacecore-0.3.2/spacecore/backend/cupy/_ops.py +0 -290
- spacecore-0.3.2/spacecore/backend/numpy/_ops.py +0 -514
- spacecore-0.3.2/spacecore/functional/__init__.py +0 -17
- spacecore-0.3.2/spacecore/functional/_base.py +0 -138
- spacecore-0.3.2/spacecore/linalg/_utils.py +0 -122
- spacecore-0.3.2/spacecore/linop/product/__init__.py +0 -13
- spacecore-0.3.2/spacecore/linop/product/_block.py +0 -125
- spacecore-0.3.2/spacecore/space/_structure.py +0 -117
- spacecore-0.3.2/spacecore/space/base/_space.py +0 -49
- spacecore-0.3.2/spacecore/space/checks/_coordinate.py +0 -3
- spacecore-0.3.2/spacecore/space/checks/_product.py +0 -3
- spacecore-0.3.2/spacecore/space/concrete/_product.py +0 -686
- spacecore-0.3.2/spacecore.egg-info/PKG-INFO +0 -206
- spacecore-0.3.2/spacecore.egg-info/SOURCES.txt +0 -219
- spacecore-0.3.2/tests/backend/test_backend_consistency.py +0 -142
- spacecore-0.3.2/tests/backend/test_backend_loops.py +0 -119
- spacecore-0.3.2/tests/backend/test_backend_ops_delegation.py +0 -257
- spacecore-0.3.2/tests/backend/test_backend_registry.py +0 -102
- spacecore-0.3.2/tests/backend/test_cupy_ops.py +0 -66
- spacecore-0.3.2/tests/backend/test_jax_ops.py +0 -43
- spacecore-0.3.2/tests/backend/test_numpy_ops.py +0 -39
- spacecore-0.3.2/tests/backend/test_torch_consistency.py +0 -51
- spacecore-0.3.2/tests/backend/test_torch_ops.py +0 -108
- spacecore-0.3.2/tests/context/test_checked_method.py +0 -133
- spacecore-0.3.2/tests/context/test_context.py +0 -34
- spacecore-0.3.2/tests/context/test_context_manager.py +0 -46
- spacecore-0.3.2/tests/context/test_context_resolution.py +0 -115
- spacecore-0.3.2/tests/context/test_errors.py +0 -46
- spacecore-0.3.2/tests/examples/test_weighted_tikhonov.py +0 -109
- spacecore-0.3.2/tests/functional/test_functional.py +0 -243
- spacecore-0.3.2/tests/integration/test_smoke_torch.py +0 -34
- spacecore-0.3.2/tests/linalg/test_expm.py +0 -255
- spacecore-0.3.2/tests/linalg/test_krylov.py +0 -939
- spacecore-0.3.2/tests/linalg/test_metric_solvers.py +0 -68
- spacecore-0.3.2/tests/linops/test_adjoint_identity.py +0 -844
- spacecore-0.3.2/tests/linops/test_algebra.py +0 -533
- spacecore-0.3.2/tests/linops/test_algebra_linop.py +0 -242
- spacecore-0.3.2/tests/linops/test_batched_apply.py +0 -79
- spacecore-0.3.2/tests/linops/test_batched_lifting.py +0 -181
- spacecore-0.3.2/tests/linops/test_block_diagonal_linop.py +0 -27
- spacecore-0.3.2/tests/linops/test_conversion_linops.py +0 -62
- spacecore-0.3.2/tests/linops/test_dense_linop.py +0 -322
- spacecore-0.3.2/tests/linops/test_diagonal_linop.py +0 -162
- spacecore-0.3.2/tests/linops/test_linop_jit.py +0 -166
- spacecore-0.3.2/tests/linops/test_product_linop_batching.py +0 -201
- spacecore-0.3.2/tests/linops/test_product_structure.py +0 -231
- spacecore-0.3.2/tests/linops/test_sparse_linop.py +0 -345
- spacecore-0.3.2/tests/linops/test_stacked_linop.py +0 -18
- spacecore-0.3.2/tests/linops/test_sum_to_single_linop.py +0 -18
- spacecore-0.3.2/tests/linops/test_to_dense.py +0 -277
- spacecore-0.3.2/tests/spaces/test_conversion_spaces.py +0 -45
- spacecore-0.3.2/tests/spaces/test_geometry.py +0 -243
- spacecore-0.3.2/tests/spaces/test_hermitian_space.py +0 -54
- spacecore-0.3.2/tests/spaces/test_product_space.py +0 -68
- spacecore-0.3.2/tests/spaces/test_product_structure.py +0 -268
- spacecore-0.3.2/tests/spaces/test_space_apply.py +0 -159
- spacecore-0.3.2/tests/spaces/test_space_checks.py +0 -164
- spacecore-0.3.2/tests/spaces/test_space_hierarchy.py +0 -654
- spacecore-0.3.2/tests/spaces/test_spectrum.py +0 -237
- spacecore-0.3.2/tests/spaces/test_stacked_space.py +0 -156
- spacecore-0.3.2/tests/spaces/test_vector_space.py +0 -55
- spacecore-0.3.2/tests/spaces/test_vectorized_checks.py +0 -145
- spacecore-0.3.2/tests/test_backend_ops_complex.py +0 -41
- spacecore-0.3.2/tutorials/1_BackendOps.ipynb +0 -628
- spacecore-0.3.2/tutorials/2_Context.ipynb +0 -602
- spacecore-0.3.2/tutorials/3_Space.ipynb +0 -821
- spacecore-0.3.2/tutorials/4_LinOp.ipynb +0 -951
- spacecore-0.3.2/tutorials/5_Conversion_Policy.ipynb +0 -208
- spacecore-0.3.2/tutorials/6_Regularized_Opt_Transport.ipynb +0 -789
- spacecore-0.3.2/tutorials/7_Quadratic_Program.ipynb +0 -320
- spacecore-0.3.2/tutorials/8_Linalg_MatrixFree.ipynb +0 -560
- spacecore-0.3.2/tutorials/9_Linalg_Comparison.ipynb +0 -558
- spacecore-0.3.2/tutorials/README.md +0 -33
- spacecore-0.3.2/tutorials/weighted_tikhonov.ipynb +0 -539
- {spacecore-0.3.2 → spacecore-0.4.1}/CONTRIBUTING.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/LICENSE +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/0.3.1-docs-inventory.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/0.3.1-docstring-audit.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/adr/001_backend_layer.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/adr/002_context_and_conversion.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/adr/004_inner_product_and_geometry.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/adr/006_current_batching_model.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/adr/007_linop_contract.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/adr/009_metric_adjoint.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/adr/010_functional_contract.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/adr/011_linalg_contract.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/adr/012_jordan_spectrum.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/contributing/labels.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/contributing/prerequisites.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/contributing/process.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/contributing/setup.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/docstring_style.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/dev/vision.md +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/_static/custom.css +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/api/backend.rst +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/api/linalg.rst +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/conf.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/design/backend_ops_array_api.rst +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/design/geometry.rst +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/design/jax_integration.rst +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/design/performance.rst +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/dev/adr.rst +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/dev/index.rst +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/docs/source/dev/vision.rst +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/setup.cfg +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/_contextual/__init__.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/_contextual/_policies.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/backend/_family.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/backend/cupy/__init__.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/backend/jax/__init__.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/backend/numpy/__init__.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/backend/torch/__init__.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/linalg/__init__.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/linalg/_expm.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/space/base/__init__.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/space/base/_jordan.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/space/base/_star.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/space/base/_vector.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/types/__init__.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/types/_dtype.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore/types/_misc.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore.egg-info/dependency_links.txt +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/spacecore.egg-info/top_level.txt +0 -0
- {spacecore-0.3.2/examples → spacecore-0.4.1/tests}/__init__.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/tests/_helpers.py +0 -0
- {spacecore-0.3.2/tests → spacecore-0.4.1/tests/backend}/__init__.py +0 -0
- {spacecore-0.3.2/tests/backend → spacecore-0.4.1/tests/bench}/__init__.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/tests/conftest.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/tests/context/__init__.py +0 -0
- {spacecore-0.3.2/tests/examples → spacecore-0.4.1/tests/integration}/__init__.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/tests/integration/test_github_labels.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/tests/integration/test_smoke_jax.py +0 -0
- {spacecore-0.3.2/tests/integration → spacecore-0.4.1/tests/kernels}/__init__.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/tests/linalg/__init__.py +0 -0
- {spacecore-0.3.2 → spacecore-0.4.1}/tests/linops/__init__.py +0 -0
- {spacecore-0.3.2/tests/spaces → spacecore-0.4.1/tests/optim}/__init__.py +0 -0
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to SpaceCore are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and the project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.4.1] — 2026-06-28
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- The **`bench` benchmark submodule** is brought under version control and
|
|
15
|
+
aligned to the agreed 0.4.1 micro-surface (ADR-023,
|
|
16
|
+
`docs/dev/0.4.1-bench-surface.md`): probes measure per-call SpaceCore overhead
|
|
17
|
+
against a hand-optimal pure-array-library bare, across `space` / `linop` /
|
|
18
|
+
`functional` only (linalg, the synthetic kernel-comparison probes,
|
|
19
|
+
`check_member`, tree-space, and generated-linop probes removed). New
|
|
20
|
+
**configuration-regime axis** (`baseline` / `dispatch` / `dispatch_cache` /
|
|
21
|
+
`verify`) times the same probe under the ADR-016 dispatch and ADR-022 caching
|
|
22
|
+
toggles, recording a within-run `regime_speedup`; block operators are measured
|
|
23
|
+
uniform **and** ragged. The interactive HTML dashboard gains a problem-size
|
|
24
|
+
range slider, a backend/family/status/size/check/search/speedup filter set
|
|
25
|
+
that drives a fully **filter-reactive** summary and diagnosis section, a
|
|
26
|
+
bottom-of-page tag legend, and zero-count-status hiding. Every backend runs in
|
|
27
|
+
float64 for a fair comparison against the NumPy reference (JAX via
|
|
28
|
+
`enable_jax_x64`, Torch via `enable_torch_x64`); the sole exception is Apple
|
|
29
|
+
MPS (float32-only hardware), where the device probe builds a float32 case and
|
|
30
|
+
the correctness gate widens accordingly. The float64-aware tolerance is shared
|
|
31
|
+
by the verdict and diagnosis layers. **JAX is benchmarked only at
|
|
32
|
+
`check_level="none"`** and **jits both the SpaceCore call and the bare
|
|
33
|
+
reference**, comparing their post-compile steady state (the warmup absorbs
|
|
34
|
+
compilation, so the speedup is jitted-vs-jitted with compilation excluded);
|
|
35
|
+
each side's compile latency is recorded and reported separately (two
|
|
36
|
+
`sc compile` / `bare compile` columns). The pair is resolved **symmetrically** —
|
|
37
|
+
if either side is not jittable, both are timed eagerly, so a comparison is never
|
|
38
|
+
eager-vs-jitted. Tooling only — `spacecore` never imports `bench`.
|
|
39
|
+
- ADR-016 optimized-kernel **dispatch** is accepted and implemented (off by
|
|
40
|
+
default). `KernelSpec` gains `dispatch_key`, `priority`, and an optional
|
|
41
|
+
shape-only `cost` estimator (`KernelCost`); a spec that names a `dispatch_key`
|
|
42
|
+
with `rtol == atol == 0` is *dispatch-eligible*. `KernelRegistry` indexes the
|
|
43
|
+
eligible specs by key (descending `priority`) and rejects two eligible specs
|
|
44
|
+
that share a key at equal priority (`DispatchAmbiguityError`). A single
|
|
45
|
+
`spacecore.kernels.dispatch(key, *args, generic=…, ctx=…)` entry point selects
|
|
46
|
+
the first applicable, affordable spec or runs the inline `generic` fallback.
|
|
47
|
+
`dispatch_mode` (`off`/`on`/`verify`) is settable process-globally
|
|
48
|
+
(`set_dispatch_mode`) and per-scope (`dispatch_mode(...)` context manager);
|
|
49
|
+
`check_level="strict"` implies `verify`. A materializing fast path is gated by
|
|
50
|
+
a memory budget computed from `BackendOps.free_memory_bytes()` and
|
|
51
|
+
`set_memory_budget_fraction` — no estimate or no budget means no fuse. The
|
|
52
|
+
composed apply chain (`linop.composed.apply`) and block-diagonal apply
|
|
53
|
+
(`linop.block_diagonal.apply`) call sites are wired through `dispatch`; with
|
|
54
|
+
dispatch off they are result-identical to the prior inline paths. The two
|
|
55
|
+
`0.4.0` catalog specs stay explicit-entry (no `dispatch_key`); activating a
|
|
56
|
+
routed spec under either key is a benchmark-gated follow-up.
|
|
57
|
+
- Three dispatch-eligible algebraic-optimization kernels (exact, `rtol=atol=0`):
|
|
58
|
+
`composed-zero-annihilation` (a chain containing a zero map collapses to
|
|
59
|
+
`codomain.zeros()`) and `composed-identity-elision` (skip identity leaves)
|
|
60
|
+
under `linop.composed.apply`, and `block-diagonal-uniform-dense-batched`
|
|
61
|
+
(uniform flat-dense blocks fold into one batched `matmul`) under
|
|
62
|
+
`linop.block_diagonal.apply`. The block kernel is *materializing*: it carries a
|
|
63
|
+
shape-only `KernelCost` and the dispatcher gates it on the memory budget. All
|
|
64
|
+
three route only under `dispatch_mode("on"/"verify")`; dispatch stays off by
|
|
65
|
+
default. Each has a correctness reference and a `python -m bench` probe.
|
|
66
|
+
- `NumpyOps.free_memory_bytes()` reports available system RAM via `psutil` (now a
|
|
67
|
+
required core dependency), so the dispatcher's memory gate can size
|
|
68
|
+
materializing fast paths on the CPU backend.
|
|
69
|
+
- Five more dispatch-eligible batched-matmul kernels (exact, `rtol=atol=0`,
|
|
70
|
+
NumPy-only until cross-backend bit-exactness is verified) extend the catalog to
|
|
71
|
+
the adjoint and batched directions, each wired through `dispatch` at its own new
|
|
72
|
+
key with a shape-only `KernelCost` and a `Class::method` correctness reference:
|
|
73
|
+
`block-diagonal-uniform-dense-batched-rapply` / `-vapply` / `-rvapply` (under
|
|
74
|
+
`linop.block_diagonal.rapply` / `.vapply` / `.rvapply`) and the broadcast-no-sum
|
|
75
|
+
folds `stacked-uniform-dense-batched-apply` /
|
|
76
|
+
`sum-to-single-uniform-dense-batched-rapply` (under `linop.stacked.apply` /
|
|
77
|
+
`linop.sum_to_single.rapply`). The adjoint folds exploit the Euclidean-flat
|
|
78
|
+
adjoint and so guard on `EUCLIDEAN_FLAT`; the batched folds use the dense core's
|
|
79
|
+
transpose-on-right orientation. All five reuse one shared
|
|
80
|
+
`spacecore.kernels.specs._batched` helper (stack uniform flat-dense matrices into
|
|
81
|
+
a single batched `matmul`) instead of duplicating the fold. The
|
|
82
|
+
`BlockDiagonalLinOp` (`rapply`/`vapply`/`rvapply`), `StackedLinOp` (`apply`) and
|
|
83
|
+
`SumToSingleLinOp` (`rapply`) call sites are wired through `dispatch`;
|
|
84
|
+
dispatch-off is result-identical to the prior inline paths. Off by default.
|
|
85
|
+
- `SparseLinOp` is confirmed to need no dispatch spec: every direction is already a
|
|
86
|
+
single optimal backend call — one SpMV for `apply`/`rapply` and one batched SpMV
|
|
87
|
+
over the stacked right-hand side for `vapply`/`rvapply` — so the reserved
|
|
88
|
+
`linop.matvec.sparse` key stays inert (a spec would add only dispatch overhead).
|
|
89
|
+
- ADR-021 **lazy-operator-algebra `fuse()`** (Tier-2 explicit simplification):
|
|
90
|
+
`LinOp.fuse(*, materialize=False)` collapses each maximal subtree of dense
|
|
91
|
+
operators into a single materialized `DenseLinOp` — a composition becomes the
|
|
92
|
+
matrix product `M_A @ M_B`, a scalar folds into the matrix, a sum of dense terms
|
|
93
|
+
is added into one matrix, an adjoint fuses its operand, and block/tree operators
|
|
94
|
+
fuse each component (so a composed-dense block becomes foldable by the
|
|
95
|
+
block-diagonal dispatch spec). It is mathematically equal to the original up to
|
|
96
|
+
floating-point rounding (fusion reassociates the arithmetic) and is
|
|
97
|
+
adjoint-consistent on any geometry — the shared middle-space Riesz maps cancel,
|
|
98
|
+
so fusion is not restricted to Euclidean spaces. A matrix-free operand is
|
|
99
|
+
**never** densified by the default `fuse()`; `fuse(materialize=True)` is the
|
|
100
|
+
explicit opt-in that densifies it (via the `to_dense` basis probe) so an
|
|
101
|
+
enclosing expression can collapse. Lives in `spacecore.linop`, separate from the
|
|
102
|
+
ADR-016 dispatch layer.
|
|
103
|
+
- ADR-022 **materialized-form cache** for the uniform batched folds: the
|
|
104
|
+
input-independent stacked block-matrix array `ops.stack([matrix(p) for p in
|
|
105
|
+
parts])` is now built once and reused across applies instead of re-stacked every
|
|
106
|
+
call. `BlockDiagonalLinOp`, `StackedLinOp`, and `SumToSingleLinOp` carry their
|
|
107
|
+
`parts` in a `spacecore.kernels.CachedStackParts` tuple that memoizes the stack
|
|
108
|
+
per matrix accessor (`_A2` apply, `_A2H` adjoint, `_A2T`/`_A2H.T` batched), so a
|
|
109
|
+
routed fold pays one `matmul` with no re-stack. The memo is built lazily on first
|
|
110
|
+
optimized use (NumPy-only, and only while dispatch is `on`/`verify`), so the
|
|
111
|
+
default `off` path is untouched. It is a derived value: excluded from operator
|
|
112
|
+
identity (`__eq__`/`__hash__`) and from the pytree (`tree_flatten` re-normalizes
|
|
113
|
+
`parts` to a plain tuple, so a round-trip rebuilds an empty cache), and a
|
|
114
|
+
matrix-free operand is never cache-materialized (the fold is inapplicable). The
|
|
115
|
+
dispatcher stays stateless. Dispatch-decision caching remains out of scope
|
|
116
|
+
(ADR-022 §"Decision caching").
|
|
117
|
+
|
|
118
|
+
### Fixed
|
|
119
|
+
|
|
120
|
+
- Corrected stale `correctness_ref` node ids on two shipped `KernelSpec`s
|
|
121
|
+
(`composed-chain-apply`, `block-diagonal-dense-apply`) that named non-existent
|
|
122
|
+
module-level test nodes instead of the real `Class::method` ids (ADR-016
|
|
123
|
+
requires the reference pin an existing test).
|
|
124
|
+
|
|
125
|
+
## [0.4.0] — 2026-06-24
|
|
126
|
+
|
|
127
|
+
SpaceCore 0.4.0 stabilizes the typed linear-algebra core as a validated
|
|
128
|
+
algebra of structured mathematical objects. It ships a public check-policy,
|
|
129
|
+
ADR-015 Stage 1 dtype/field contract, the `TreeSpace` finite direct-product
|
|
130
|
+
abstraction, block-structured LinOps on tree domains, an everyday functional
|
|
131
|
+
and proximal toolbox, external optimizer adapters, reusable test generators,
|
|
132
|
+
and a full backend conformance matrix with deviation catalog.
|
|
133
|
+
|
|
134
|
+
### Added
|
|
135
|
+
|
|
136
|
+
- ADR-018 **external optimizer adapters** in the new `spacecore.optimize`
|
|
137
|
+
subpackage: `minimize_scipy(F, x0, *, method="L-BFGS-B", jac=True, **kw)` and
|
|
138
|
+
`line_search_scipy(F, x, d, **kw)` drive `scipy.optimize`, and
|
|
139
|
+
`minimize_optax(F, x0, optimizer, *, steps, callback=None)` runs the canonical
|
|
140
|
+
optax update loop with pytree pass-through. Each adapter evaluates the
|
|
141
|
+
objective through `F.value` and converts the metric (Riesz) gradient `F.grad`
|
|
142
|
+
to the coordinate gradient external optimizers expect with
|
|
143
|
+
`X.riesz(F.grad(x))` — the identity on a Euclidean space and mandatory on a
|
|
144
|
+
weighted one, defusing the study's silent metric-gradient trap once and
|
|
145
|
+
centrally. The external optimizer owns iteration, line search, and
|
|
146
|
+
convergence; the SciPy adapters reject complex domains and document the
|
|
147
|
+
structure/geometry/field lost at the boundary. `minimize_scipy` returns the
|
|
148
|
+
SciPy `OptimizeResult` with an added `x_element` field (the minimizer
|
|
149
|
+
unflattened into `F.domain`); `minimize_optax` requires a JAX-backed domain and
|
|
150
|
+
the optional `optax` extra (`pip install spacecore[optax]`). Per ADR-018,
|
|
151
|
+
jaxopt/BlackJAX/pymanopt seams stay as tutorials, not shipped adapters.
|
|
152
|
+
- ADR-019 everyday functional and proximal toolbox in the new
|
|
153
|
+
`spacecore.functional.tools` subpackage (re-exported from
|
|
154
|
+
`spacecore.functional` and the top-level `spacecore` namespace): named
|
|
155
|
+
constructors over the existing `Functional` machinery, with no new core type
|
|
156
|
+
hierarchy. `least_squares(A, b, *, weights=None, scale=0.5)` returns a
|
|
157
|
+
`LinOpQuadraticForm` for `scale·‖Ax−b‖²` (default `½‖Ax−b‖²`, with optional
|
|
158
|
+
diagonal residual weights). New battery functionals `SquaredL2NormFunctional`,
|
|
159
|
+
`LpNormFunctional`, `L1NormFunctional`, `NegativeEntropyFunctional`,
|
|
160
|
+
`KLDivergenceFunctional`, and `HuberFunctional` are coordinate objectives whose
|
|
161
|
+
gradients are the metric (Riesz) gradient under the domain geometry.
|
|
162
|
+
`SpectralLpNormFunctional` (with the `NuclearNormFunctional` wrapper) is the
|
|
163
|
+
spectral analogue — the Schatten-`p` norm of a Jordan spectrum (`HermitianSpace`
|
|
164
|
+
eigenvalues), a spectral function whose gradient is reconstructed through the
|
|
165
|
+
ADR-012 `from_spectrum` API; on an elementwise Jordan space it coincides with
|
|
166
|
+
`LpNormFunctional`. A closed-form proximal primitive
|
|
167
|
+
`generalized_shrinkage(X, *, c, x0, eps, lam=0.0, nonneg=False)` solves the
|
|
168
|
+
separable forward–backward subproblem in the space metric (per-coordinate
|
|
169
|
+
threshold `τᵢ = λ/(2 ε wᵢ)` on a diagonal metric; it **raises** on a
|
|
170
|
+
non-diagonal metric rather than returning a wrong separable answer), with the
|
|
171
|
+
named wrappers `prox_l1`, `prox_l2sq`, and `project_nonneg`. The
|
|
172
|
+
`IndicatorFunctional`/`project_C` surface reserved by ADR-019 is deferred to
|
|
173
|
+
ADR-020 (`Set`).
|
|
174
|
+
- `HermitianSpace.eig_to_dense` (and therefore `from_spectrum`, `psd_proj`, and
|
|
175
|
+
`spectral_apply`) now symmetrizes the `U diag(·) U^*` reconstruction before the
|
|
176
|
+
membership check, so a zero-tolerance Hermitian space no longer rejects its own
|
|
177
|
+
spectral reconstruction over a few-ULP floating-point skew.
|
|
178
|
+
- Public `check_level` policy literal (`"none"`, `"cheap"`, `"standard"`,
|
|
179
|
+
`"strict"`) with `CHECK_LEVELS` ordering and `_checks_at_least` dispatch
|
|
180
|
+
across spaces, LinOps, functionals, and solver preconditions.
|
|
181
|
+
- `Space.field` exposing a `Literal["real", "complex"]` mathematical
|
|
182
|
+
contract derived from the context dtype; capability guards now consult
|
|
183
|
+
`Space.field` instead of inspecting precision-bearing dtypes.
|
|
184
|
+
- `TreeSpace` finite direct-product space organized by an `optree`
|
|
185
|
+
definition; `TreeElement` ordered-leaf binding; `TreeSpace.from_leaf_spaces`
|
|
186
|
+
flat-tuple shortcut.
|
|
187
|
+
- `BlockDiagonalLinOp` and `BlockMatrixLinOp` over `TreeSpace` domains
|
|
188
|
+
including metric-adjoint behavior; `TreeLinOp` base class for tree-shaped
|
|
189
|
+
operators.
|
|
190
|
+
- Reusable test generators under `tests/generators/` for spaces, LinOps,
|
|
191
|
+
functionals, and linalg references; contributor guide at
|
|
192
|
+
`docs/dev/contributing/linop_generators.md`.
|
|
193
|
+
- `spacecore.kernels` subpackage with the optimized-kernel registration
|
|
194
|
+
policy. Two demonstration kernels ship in 0.4.0: `composed-chain-apply`
|
|
195
|
+
(skips the per-link `@checked_method` wrapper for a flat chain of LinOps)
|
|
196
|
+
and `block-diagonal-dense-apply` (tight ``ops.matmul`` loop over dense
|
|
197
|
+
block leaves). Both have correctness references and bench cases. No
|
|
198
|
+
dispatch or fusion is wired in 0.4.0: the ADR-016 dispatch mechanism is
|
|
199
|
+
implemented but ships **off by default** and dormant, with no production
|
|
200
|
+
routing (see Unreleased).
|
|
201
|
+
- Unified benchmark framework at `python -m bench` (subcommands `run`,
|
|
202
|
+
`compare`, `plot`, `summary`, `list`) with generator-driven probes in
|
|
203
|
+
`bench/_operations.py`, peak-memory recording in
|
|
204
|
+
`bench/harness.py:measure_peak_memory`, fixed seeds `(0, 1, 2, 3)`, and
|
|
205
|
+
a self-contained interactive Plotly dashboard at `bench/_dashboard.py`.
|
|
206
|
+
- Kernel policy doc at `docs/source/design/kernels_policy.rst`.
|
|
207
|
+
- Backend conformance matrix at `docs/source/design/backend_conformance.rst`
|
|
208
|
+
with per-op tolerance harness in `tests/backend/_conformance.py`,
|
|
209
|
+
systematic NumpyOps reference (`tests/backend/test_conformance_numpy.py`),
|
|
210
|
+
cross-backend parity (`tests/backend/test_conformance_cross_backend.py`),
|
|
211
|
+
and dedicated modules for optional args, conversion, dtype promotion,
|
|
212
|
+
field consistency, vmap, and JIT.
|
|
213
|
+
- Operator apply cores are organized as a *core-kernel* layer in the
|
|
214
|
+
`spacecore.kernels` subpackage instead of inline in each operator class. The
|
|
215
|
+
check-free cores of `apply`/`rapply`/`vapply`/`rvapply` for **every** operator
|
|
216
|
+
with a fast path — the composite algebra (`ComposedLinOp`, `ScaledLinOp`,
|
|
217
|
+
`SumLinOp`, the adjoint view, `IdentityLinOp`, `ZeroLinOp`, `MatrixFreeLinOp`)
|
|
218
|
+
and the concrete leaves (`DenseLinOp`, `DiagonalLinOp`, `SparseLinOp`) — now
|
|
219
|
+
live as concrete functions in the kernels subpackage (`kernels/algebra.py`,
|
|
220
|
+
`kernels/dense.py`, `kernels/diagonal.py`, `kernels/sparse.py`). Operators
|
|
221
|
+
bind them by declaring the `@core_kernels("...")` class decorator (rules in
|
|
222
|
+
`spacecore/kernels/_core.py`); the base `LinOp` cores remain the generic
|
|
223
|
+
fallback for operators without a registered kernel. Binding is static
|
|
224
|
+
(class-definition time), so routing through the kernel registry costs nothing
|
|
225
|
+
per call — leaf-operator apply latency is unchanged. The lazy-algebra cores
|
|
226
|
+
additionally validate membership only once at the boundary instead of
|
|
227
|
+
re-validating every intermediate link, and `ComposedLinOp` caches a flattened
|
|
228
|
+
`_apply_chain` at construction so a deep `A @ B @ C @ ...` runs one loop rather
|
|
229
|
+
than re-walking the binary tree (a depth-16 composition applies ~9x faster than
|
|
230
|
+
the per-link-checked path and scales flat with depth). All results are
|
|
231
|
+
numerically identical. Public API: `core_kernels`, `CoreKernelSet`,
|
|
232
|
+
`register_core_kernels`, `get_core_kernels`, `core_kernel_names` from
|
|
233
|
+
`spacecore.kernels`.
|
|
234
|
+
- Iterative linalg solvers (`cg`, `lanczos_smallest`, `lsqr`, `power_iteration`)
|
|
235
|
+
consume the check-free operator/space cores in their hot loops. They validate
|
|
236
|
+
the operator and right-hand side once, at entry, then run the iteration through
|
|
237
|
+
the resolved cores — eliminating the per-iteration membership validation that
|
|
238
|
+
dominated eager-backend runtime (CG at `check_level="standard"` is ~3.4x faster
|
|
239
|
+
on NumPy and now matches `check_level="none"`). Resolution is safe: a core is
|
|
240
|
+
used only when it is consistent with the public method (`linalg/_utils.py`
|
|
241
|
+
`resolve_core`/`SpaceCoreOps`), so a user space that overrides `inner` with a
|
|
242
|
+
custom geometry without overriding `_inner_core` keeps its override. Results are
|
|
243
|
+
numerically identical.
|
|
244
|
+
- The `spacecore.kernels` subpackage is reorganized into two subpackages by kind:
|
|
245
|
+
`spacecore.kernels.core` (the check-free apply/eval cores + the `core_kernels`
|
|
246
|
+
binding rules) and `spacecore.kernels.specs` (the benchmarked `KernelSpec`
|
|
247
|
+
layer). Public names are re-exported from `spacecore.kernels`, so
|
|
248
|
+
`spacecore.kernels.core_kernels`, `spacecore.kernels.CoreKernelSet`, and
|
|
249
|
+
`spacecore.kernels.KernelSpec`/`registry` resolve unchanged.
|
|
250
|
+
- The same core-kernel organization now covers the `spacecore.functional`
|
|
251
|
+
submodule. The check-free `value`/`grad`/`vvalue`/`vgrad` cores for
|
|
252
|
+
`InnerProductFunctional`, `MatrixFreeLinearFunctional`, `LinearFunctional`,
|
|
253
|
+
`LinOpQuadraticForm`, and `ComposedFunctional` live in
|
|
254
|
+
`spacecore/kernels/functional.py`; the functionals bind them via
|
|
255
|
+
`@core_kernels("...")`. `CoreKernelSet` gained `value`/`grad`/`vvalue`/`vgrad`
|
|
256
|
+
fields alongside the LinOp `apply`/`rapply`/`vapply`/`rvapply` ones, and the
|
|
257
|
+
base `Functional` carries the generic core fallbacks. Composite functionals now
|
|
258
|
+
reach their operands' cores instead of re-validating intermediates — e.g.
|
|
259
|
+
`LinOpQuadraticForm.value` validates its input once rather than once per
|
|
260
|
+
sub-term (`Q.apply` + `linear.value`), and `ComposedFunctional` evaluates
|
|
261
|
+
`F._value_core(A._apply_core(x))`. Results are numerically identical.
|
|
262
|
+
- `BackendOps.hstack`, `vstack`, `dstack`, and `column_stack` array-stacking
|
|
263
|
+
helpers delegating to the backend's native routines, alongside the existing
|
|
264
|
+
`stack`.
|
|
265
|
+
- `BackendOps.vectorize` for elementwise vectorization of a scalar Python
|
|
266
|
+
function over array arguments. Delegates to the backend's native
|
|
267
|
+
`vectorize` (NumPy, JAX, CuPy) and uses a portable Python-loop fallback on
|
|
268
|
+
backends without one (Torch). Closes the previously unimplemented
|
|
269
|
+
`ops.vectorize` fallback used by `spectral_apply`.
|
|
270
|
+
- Backend deviation catalog at `docs/source/design/backend_deviations.rst`.
|
|
271
|
+
- Batching test policy at `docs/source/design/batching_test_policy.rst`.
|
|
272
|
+
|
|
273
|
+
### Changed
|
|
274
|
+
|
|
275
|
+
- Spaces, LinOps, and functionals dispatch optional checks via
|
|
276
|
+
`_checks_at_least`; `cheap` covers shape/dtype/backend/tree-structure,
|
|
277
|
+
`standard` adds membership and Hermitian checks, `strict` adds bounded
|
|
278
|
+
expensive probes (matrix-free adjoint identity, CG positive-curvature
|
|
279
|
+
probe).
|
|
280
|
+
- `Context.dtype` is documented as the representation default; `Space.field`
|
|
281
|
+
is the mathematical contract derived from it.
|
|
282
|
+
|
|
283
|
+
### Removed
|
|
284
|
+
|
|
285
|
+
- `ProductSpace` was removed in favor of `TreeSpace`. Tuple-style products
|
|
286
|
+
use `TreeSpace.from_leaf_spaces((X1, X2, ...))`; nested / dict /
|
|
287
|
+
namedtuple structures use `TreeSpace(template, leaf_spaces)` or
|
|
288
|
+
`TreeSpace.from_template`.
|
|
289
|
+
- `ProductLinOp` was renamed to `TreeLinOp`. `ProductStructure`,
|
|
290
|
+
`TupleStructure`, `PytreeStructure`, `ProductStructureCheck`, and
|
|
291
|
+
`ProductComponentCheck` were removed; tree-structure handling and leaf
|
|
292
|
+
validation are owned by `TreeSpace`.
|
|
293
|
+
- Conversion (`ctx.asarray` and construction helpers) refuses silent
|
|
294
|
+
complex-to-real narrowing per ADR-015 Stage 1.
|
|
295
|
+
|
|
296
|
+
### Deprecated
|
|
297
|
+
|
|
298
|
+
- `enable_checks=True/False` is deprecated in favor of `check_level`:
|
|
299
|
+
`True` maps to `"standard"`, `False` maps to `"none"`. Passing both
|
|
300
|
+
raises `TypeError`. `enable_checks` continues to work in 0.4.0 but will
|
|
301
|
+
be removed in a future release.
|
|
302
|
+
|
|
303
|
+
### Fixed
|
|
304
|
+
|
|
305
|
+
- Corrected the matrix-free adjoint contract so `MatrixFreeLinOp` and its
|
|
306
|
+
adjoint view use user-supplied forward and reverse callables directly,
|
|
307
|
+
without applying matrix-backed Riesz-map adjoint corrections.
|
|
308
|
+
- `ComposedLinOp`, `ScaledLinOp`, and `SumLinOp` now implement structural
|
|
309
|
+
`is_hermitian()` inference. A Gram product `R.H @ R` (or `L @ L.H`) reports
|
|
310
|
+
`True` in any geometry, a real-scaled operator propagates its operand's
|
|
311
|
+
verdict, and a sum of provably-Hermitian terms reports `True`. The checks
|
|
312
|
+
are cheap, conservative, and never assert `False`, so the normal operator
|
|
313
|
+
`A.H @ A + lam * Identity` is now correctly recognized as self-adjoint
|
|
314
|
+
instead of reporting `None`.
|
|
315
|
+
- `cg` now rejects an operator that is *provably* non-self-adjoint in its
|
|
316
|
+
geometry (`A.is_hermitian() is False`) at entry with a clear `ValueError`,
|
|
317
|
+
matching the guard already used by `power_iteration`, `lanczos_smallest`,
|
|
318
|
+
and `expm_multiply`. Previously, at the default check level, `cg` would
|
|
319
|
+
silently accept (for example) a symmetric matrix on a weighted
|
|
320
|
+
inner-product space — which is not self-adjoint under the weighted inner
|
|
321
|
+
product — and return a confusing `converged=False` result. Operators with
|
|
322
|
+
unknown Hermiticity (`is_hermitian() is None`, e.g. matrix-free) are still
|
|
323
|
+
accepted unchecked.
|
|
324
|
+
|
|
325
|
+
### Known limitations
|
|
326
|
+
|
|
327
|
+
- Iterative solvers (`cg`, `lsqr`, `lanczos_smallest`, `power_iteration`,
|
|
328
|
+
`expm_multiply`) remain unbatched. Batched-input invocations raise a
|
|
329
|
+
clear shape error; explicit batched solver entry points are deferred to
|
|
330
|
+
0.5.0.
|
|
331
|
+
- ADR-015 Stage 2 (operand-dtype-preserving `Context.asarray`, opt-in
|
|
332
|
+
exact dtype membership, operand-dtype solver workspaces) is deferred to
|
|
333
|
+
0.5.0.
|
|
334
|
+
- Strict check level currently inherits the standard space-membership
|
|
335
|
+
semantics; additional spectral / metric probes at the space layer are
|
|
336
|
+
deferred to 0.5.0.
|
|
337
|
+
|
|
338
|
+
## [0.3.1] — 2026-06-10
|
|
339
|
+
|
|
340
|
+
SpaceCore 0.3.1 is a release-candidate stabilization release for the `0.3.x`
|
|
341
|
+
API. It focuses on documentation consistency, tutorial execution, release
|
|
342
|
+
artifact checks, and public API audit cleanup. It does not add new solver
|
|
343
|
+
families or SDPLab-specific downstream integration.
|
|
344
|
+
|
|
345
|
+
### Documentation
|
|
346
|
+
|
|
347
|
+
- Reworked API reference landing pages for backend, context, spaces, linear
|
|
348
|
+
operators, functionals, and linalg.
|
|
349
|
+
- Added design notes for context ownership, batching, and capability dispatch.
|
|
350
|
+
- Clarified conversion and dtype policy documentation for explicit target
|
|
351
|
+
contexts.
|
|
352
|
+
- Clarified adjoint documentation to distinguish coordinate transpose,
|
|
353
|
+
Euclidean adjoint, and metric/Riesz-represented adjoint behavior.
|
|
354
|
+
|
|
355
|
+
### Examples and Tutorials
|
|
356
|
+
|
|
357
|
+
- Added a SpaceCore-only weighted Tikhonov worked example demonstrating
|
|
358
|
+
weighted spaces, metric adjoints, lazy operator algebra, CG, and an
|
|
359
|
+
independent dense NumPy reference solve.
|
|
360
|
+
- Integrated the weighted Tikhonov example into tests and documentation.
|
|
361
|
+
|
|
362
|
+
### Testing and CI
|
|
363
|
+
|
|
364
|
+
- Documentation CI now builds Sphinx with warnings as errors.
|
|
365
|
+
- Release-candidate checks include full tests, strict docs build, public API
|
|
366
|
+
audit, artifact build, `twine check`, clean wheel installation, and smoke
|
|
367
|
+
testing.
|
|
368
|
+
|
|
369
|
+
### Known limitations
|
|
370
|
+
|
|
371
|
+
- Optional backend behavior depends on installed optional dependencies. CuPy is
|
|
372
|
+
not required for the core release-candidate gate.
|
|
373
|
+
- The advanced regularized OT tutorial is an illustrative SpaceCore/JAX/Optax
|
|
374
|
+
example, not a claim that SpaceCore ships a production OT solver.
|
|
375
|
+
|
|
376
|
+
## [0.3.0]
|
|
377
|
+
|
|
378
|
+
SpaceCore 0.3.0 is a breaking release for the unstable `0.x` series. Space
|
|
379
|
+
capabilities are now derived from actual structure, dtype, and inner product,
|
|
380
|
+
and conversions rebuild spaces through public factories so stale capabilities
|
|
381
|
+
are not retained.
|
|
382
|
+
|
|
383
|
+
### Migration
|
|
384
|
+
|
|
385
|
+
| 0.2.x | 0.3.0 |
|
|
386
|
+
| --- | --- |
|
|
387
|
+
| `space.eigh(x)` | `space.spectral_decompose(x)` for eigenvalues and frame |
|
|
388
|
+
| `space.eigh(x)` | `space.spectrum(x)` for eigenvalues only |
|
|
389
|
+
| `sc.VectorSpace((n,))` | `sc.DenseVectorSpace((n,))` |
|
|
390
|
+
| `sc.VectorSpace((d, d))` | `sc.DenseCoordinateSpace((d, d))` |
|
|
391
|
+
| `ProductInnerProductSpace(...)` | `ProductSpace(...)` |
|
|
392
|
+
| `ProductStarSpace(...)` | `ProductSpace(...)` |
|
|
393
|
+
| `ProductJordanAlgebraSpace(...)` | `ProductSpace(...)` |
|
|
394
|
+
| `ProductEuclideanJordanAlgebraSpace(...)` | `ProductSpace(...)` |
|
|
395
|
+
| `StackedInnerProductSpace(...)` | `StackedSpace(...)` |
|
|
396
|
+
| `StackedStarSpace(...)` | `StackedSpace(...)` |
|
|
397
|
+
| `StackedJordanAlgebraSpace(...)` | `StackedSpace(...)` |
|
|
398
|
+
| `StackedEuclideanJordanAlgebraSpace(...)` | `StackedSpace(...)` |
|
|
399
|
+
| `BatchSpace` and `space.batch(...)` | leading-axis batched arrays with `vapply(...)` / `rvapply(...)` |
|
|
400
|
+
| `op.vapply(xs, batch_space=...)` | `op.vapply(xs)` |
|
|
401
|
+
| global context conversion policies | explicit `Context` construction and `obj.convert(ctx)` |
|
|
402
|
+
| global dtype preservation policies | target-context dtype during explicit conversion |
|
|
403
|
+
|
|
404
|
+
Prominent `eigh` replacement:
|
|
405
|
+
|
|
406
|
+
```python
|
|
407
|
+
space.eigh(x)
|
|
408
|
+
# -> space.spectral_decompose(x) # eigenvalues and frame
|
|
409
|
+
# -> space.spectrum(x) # eigenvalues only
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Added
|
|
413
|
+
|
|
414
|
+
- `spectrum`, `spectral_decompose`, and `from_spectrum` as the public spectral
|
|
415
|
+
contract for Jordan spaces.
|
|
416
|
+
- `ElementwiseJordanSpace` for real or complex elementwise Jordan algebras.
|
|
417
|
+
- `EuclideanElementwiseJordanSpace` for real Euclidean elementwise Jordan
|
|
418
|
+
algebras.
|
|
419
|
+
- Jordan capability hierarchy separating `JordanAlgebraSpace` from
|
|
420
|
+
`EuclideanJordanAlgebraSpace`.
|
|
421
|
+
- `ProductStructure`, `TupleStructure`, `PytreeStructure`, and
|
|
422
|
+
`ProductSpace.from_template` for structured product elements.
|
|
423
|
+
- `ProductSpectralDecomposition` for product spectral data independent of
|
|
424
|
+
product element structure.
|
|
425
|
+
- `StackedSpace` for leading-axis repeated leaf spaces.
|
|
426
|
+
- Vectorizable axis-aware validation checks.
|
|
427
|
+
- `InnerProduct.validate_for(space)` and construction-time validation for
|
|
428
|
+
`WeightedInnerProduct`.
|
|
429
|
+
- `scripts/api_audit.py` for repository and downstream migration audits.
|
|
430
|
+
|
|
431
|
+
### Changed
|
|
432
|
+
|
|
433
|
+
- `VectorSpace` is an abstract linear-capability base.
|
|
434
|
+
- Previous concrete `VectorSpace` use cases moved to `DenseVectorSpace` for
|
|
435
|
+
one-dimensional dense vectors and `DenseCoordinateSpace` for generic dense
|
|
436
|
+
coordinate arrays.
|
|
437
|
+
- `DenseVectorSpace` is now a plain one-dimensional vector space with star and
|
|
438
|
+
no Jordan capability by default.
|
|
439
|
+
- Elementwise Euclidean-Jordan capability is selected only for real dtype with
|
|
440
|
+
`EuclideanInnerProduct`.
|
|
441
|
+
- `ProductSpace(...)` and `StackedSpace(...)` are the only public product and
|
|
442
|
+
stacked constructors; they auto-dispatch to private implementation classes.
|
|
443
|
+
- `convert()` for elementwise, product, and stacked spaces recomputes
|
|
444
|
+
capabilities through public factories.
|
|
445
|
+
- `ProductSpace.spectral_decompose` returns explicit product spectral data
|
|
446
|
+
rather than routing decompositions through element structure adapters.
|
|
447
|
+
|
|
448
|
+
### Removed
|
|
449
|
+
|
|
450
|
+
- Removed `eigh` from spaces. Use `spectral_decompose` when both eigenvalues
|
|
451
|
+
and a reconstruction frame are needed, or `spectrum` for eigenvalues only.
|
|
452
|
+
- Removed public specialized product and stacked constructors from the public
|
|
453
|
+
API.
|
|
454
|
+
- Removed `BatchSpace`, `Space.batch`, and `batch_space=` arguments from public
|
|
455
|
+
batching APIs. Use leading-axis vectorization through `vapply` and `rvapply`.
|
|
456
|
+
- Removed global context-policy and dtype-policy APIs. Conversion now follows
|
|
457
|
+
the requested target `Context` directly.
|
|
458
|
+
|
|
459
|
+
## [0.2.0]
|
|
460
|
+
|
|
461
|
+
SpaceCore 0.2.0 is a major API expansion. The backend layer now sits on the
|
|
462
|
+
Array API standard. Operators gained a lazy algebra with adjoint views,
|
|
463
|
+
composition, sums, and scaling. A new `Functional` hierarchy provides
|
|
464
|
+
scalar-valued maps with gradients and pull-backs. A new `spacecore.linalg`
|
|
465
|
+
module ships four JIT-compatible iterative solvers. Spaces, operators, and
|
|
466
|
+
functionals share a single validation pattern via `checked_method`, and the
|
|
467
|
+
public API is documented to numpydoc standard with doctest coverage.
|
|
468
|
+
|
|
469
|
+
This release introduces breaking changes; see [Migration](#migration-from-01x).
|
|
470
|
+
|
|
471
|
+
### Added
|
|
472
|
+
|
|
473
|
+
#### Backend
|
|
474
|
+
|
|
475
|
+
- Migrated `BackendOps` to the Array API standard via `array-api-compat`.
|
|
476
|
+
- `CuPyOps` and the `cupy` backend family as an optional install
|
|
477
|
+
(`pip install 'spacecore[cupy]'`).
|
|
478
|
+
- `BackendOps.is_complex_dtype` for backend-aware complex detection.
|
|
479
|
+
- `BackendOps.real_dtype` for extracting the real dtype matching a complex one.
|
|
480
|
+
- Broadened backend coverage for array creation, dtype conversion, sparse
|
|
481
|
+
conversion, indexing, reductions, linear algebra, loop primitives
|
|
482
|
+
(`fori_loop`, `while_loop`, `cond`), tree helpers, and vectorized mapping.
|
|
483
|
+
- JAX pytree registration for operator, space, and functional types so they
|
|
484
|
+
pass through `jax.jit`, `jax.vmap`, and `jax.grad` boundaries.
|
|
485
|
+
|
|
486
|
+
#### Context and checking
|
|
487
|
+
|
|
488
|
+
- Public free-function API in `spacecore._contextual`: `set_context`,
|
|
489
|
+
`get_context`, `resolve_context_priority`, `register_ops`, and the
|
|
490
|
+
resolution-policy accessors.
|
|
491
|
+
- Extended `checked_method` to support validation against `self` and multiple
|
|
492
|
+
input argument positions.
|
|
493
|
+
- Reusable space-validation checks: backend, dtype, shape, Hermitian,
|
|
494
|
+
square-matrix, product-structure, and product-component checks. Documented
|
|
495
|
+
at `docs/source/design/checking_policy.rst`.
|
|
496
|
+
|
|
497
|
+
#### Spaces
|
|
498
|
+
|
|
499
|
+
- `BatchSpace` for batched elements with explicit batch shape and batch-axis
|
|
500
|
+
metadata.
|
|
501
|
+
|
|
502
|
+
#### Linear operators
|
|
503
|
+
|
|
504
|
+
- Lazy operator algebra:
|
|
505
|
+
- `A @ B` composes operators.
|
|
506
|
+
- `A + B` sums operators.
|
|
507
|
+
- `alpha * A` scales an operator.
|
|
508
|
+
- `A.H` returns a cached adjoint view satisfying `A.H.H is A`.
|
|
509
|
+
- Algebraic simplification eliminates `I`, `Zero`, `alpha = 0`, `alpha = 1`,
|
|
510
|
+
and flattens nested sums.
|
|
511
|
+
- New operator types: `IdentityLinOp`, `ZeroLinOp`, `MatrixFreeLinOp`,
|
|
512
|
+
`DiagonalLinOp`.
|
|
513
|
+
- Structural `LinOp.is_hermitian()` reporting `True`, `False`, or `None`
|
|
514
|
+
(unknown) without applying incorrect Euclidean assumptions for custom space
|
|
515
|
+
geometries.
|
|
516
|
+
- `LinOp.to_dense()` for materializing operators as backend arrays.
|
|
517
|
+
- Product-structured operators and batched lifting:
|
|
518
|
+
- `ProductLinOp`
|
|
519
|
+
- `BlockDiagonalLinOp`
|
|
520
|
+
- `StackedLinOp`
|
|
521
|
+
- `SumToSingleLinOp`
|
|
522
|
+
- `vapply` / `rvapply` paths for batched operator application.
|
|
523
|
+
|
|
524
|
+
#### Functionals
|
|
525
|
+
|
|
526
|
+
- `Functional` as an abstract base for scalar-valued maps on spaces, with
|
|
527
|
+
`value`, `grad`, `hess_apply`, and batched counterparts.
|
|
528
|
+
- Linear functionals: `LinearFunctional`, `InnerProductFunctional`,
|
|
529
|
+
`MatrixFreeLinearFunctional`.
|
|
530
|
+
- Quadratic forms: `QuadraticForm`, `LinOpQuadraticForm`.
|
|
531
|
+
- `Functional.compose` and `ComposedFunctional` for pull-backs along linear
|
|
532
|
+
operators, with specializations that preserve the concrete functional type
|
|
533
|
+
when possible.
|
|
534
|
+
|
|
535
|
+
#### Linear algebra
|
|
536
|
+
|
|
537
|
+
The `spacecore.linalg` module is new in 0.2.0. It provides JIT-compatible
|
|
538
|
+
iterative solvers and structured result types.
|
|
539
|
+
|
|
540
|
+
- Iterative solvers:
|
|
541
|
+
- `cg` for Hermitian positive-definite systems.
|
|
542
|
+
- `lsqr` for rectangular least-squares problems.
|
|
543
|
+
- `power_iteration` for dominant-eigenpair estimates of a `LinOp` or
|
|
544
|
+
`QuadraticForm`.
|
|
545
|
+
- `lanczos_smallest` for smallest-Ritz-eigenpair estimates of Hermitian
|
|
546
|
+
operators.
|
|
547
|
+
- `expm_multiply` for Krylov matrix-exponential actions `exp(t A) v` on
|
|
548
|
+
Hermitian operators, with complex `t` supported for Schrodinger-type
|
|
549
|
+
evolution.
|
|
550
|
+
- Structured result types `CGResult`, `LSQRResult`, `PowerIterationResult`,
|
|
551
|
+
`LanczosResult`, and `ExpmMultiplyResult`, each carrying convergence
|
|
552
|
+
diagnostics and a compact `__repr__`.
|
|
553
|
+
- Solvers are geometry-aware: norms, inner products, and the default initial
|
|
554
|
+
vector use `Space.inner` and `Space.norm` rather than assuming Euclidean
|
|
555
|
+
geometry. This makes the solvers correct on custom inner products such as
|
|
556
|
+
RKHS or weighted spaces.
|
|
557
|
+
|
|
558
|
+
#### Documentation
|
|
559
|
+
|
|
560
|
+
- Numpydoc-standard public docstrings with runnable doctests for solvers,
|
|
561
|
+
spaces, operators, functionals, backends, and contextual helpers.
|
|
562
|
+
- API reference pages for backend ops, spaces, linear operators, functionals,
|
|
563
|
+
and linear algebra.
|
|
564
|
+
- JAX integration design note at `docs/source/design/jax_integration.rst`
|
|
565
|
+
covering trace-time operator algebra and recommended JIT usage.
|
|
566
|
+
- Tutorials for backend operations, linear operators, and matrix-free linalg
|
|
567
|
+
workflows.
|
|
568
|
+
|
|
569
|
+
#### Tooling
|
|
570
|
+
|
|
571
|
+
- Optional dependency groups: `[jax]`, `[torch]`, `[cupy]`, `[examples]`,
|
|
572
|
+
`[docs]`, `[dev]`.
|
|
573
|
+
- Explicit `__all__` at the top level covering new backends, operators,
|
|
574
|
+
functionals, solvers, result types, validation checks, and contextual
|
|
575
|
+
helpers.
|
|
576
|
+
- CI runs a JIT-traceability audit in `--check` mode and enforces a 70%
|
|
577
|
+
coverage floor via `pytest-cov`.
|
|
578
|
+
- Cross-backend tests covering NumPy, JAX, Torch, and optional CuPy.
|
|
579
|
+
|
|
580
|
+
### Changed
|
|
581
|
+
|
|
582
|
+
- Restructured `_contextual` to hide implementation details while preserving
|
|
583
|
+
the public API via free functions.
|
|
584
|
+
- Replaced manual `if self._enable_checks` guards with `checked_method` across
|
|
585
|
+
`Space`, `LinOp`, and `Functional`. Inline guards are now reserved for
|
|
586
|
+
non-membership checks such as dense-array assertions and custom output-shape
|
|
587
|
+
checks.
|
|
588
|
+
- Improved `VectorSpace`, `HermitianSpace`, and `ProductSpace` conversion
|
|
589
|
+
behavior, validation, batching support, and docstrings.
|
|
590
|
+
- Improved linear-operator equality, representation, conversion, and JAX
|
|
591
|
+
pytree behavior.
|
|
592
|
+
- `spacecore.__version__` now resolves from package metadata via
|
|
593
|
+
`importlib.metadata` instead of a hand-maintained constant.
|
|
594
|
+
- Bumped the package version to `0.2.0`.
|
|
595
|
+
|
|
596
|
+
### Fixed
|
|
597
|
+
|
|
598
|
+
- `LinOp.__eq__` returns `NotImplemented` instead of raising
|
|
599
|
+
`NotImplementedError` on the base class, so `op == None` and
|
|
600
|
+
`op in some_list` no longer raise.
|
|
601
|
+
- `DenseLinOp.is_hermitian` and `SparseLinOp.is_hermitian` return `None` for
|
|
602
|
+
custom space geometries instead of applying an incorrect Euclidean
|
|
603
|
+
matrix-symmetry test.
|
|
604
|
+
|
|
605
|
+
### Migration from 0.1.x
|
|
606
|
+
|
|
607
|
+
- `BackendOps.eps` is now a method `eps(dtype)` rather than a property.
|
|
608
|
+
Callers must pass a dtype, typically `ctx.dtype`.
|
|
609
|
+
- The implementation attribute `DenseLinOp.A` is now a `cached_property`
|
|
610
|
+
backed by `_A`. The public attribute access `op.A` is unchanged.
|
|
611
|
+
- `LinOp.__eq__` returns `NotImplemented` rather than raising; downstream code
|
|
612
|
+
relying on the exception should be updated to handle the new behavior.
|
|
613
|
+
- Several module-internal helpers in `spacecore._contextual` moved to private
|
|
614
|
+
modules. Use the public functions re-exported from `spacecore._contextual`
|
|
615
|
+
(`set_context`, `get_context`, `resolve_context_priority`, `register_ops`,
|
|
616
|
+
`set_resolution_policy`, and the dtype-policy accessors) rather than
|
|
617
|
+
importing from internal modules.
|
|
618
|
+
|
|
619
|
+
### Known limitations
|
|
620
|
+
|
|
621
|
+
- `cg`, `lsqr`, and `power_iteration` do not structurally validate operator
|
|
622
|
+
properties (positive-definiteness, full Hermiticity) and may silently
|
|
623
|
+
produce incorrect results on inputs that violate their preconditions. See
|
|
624
|
+
each function's `Notes` section for details.
|
|
625
|
+
- Operator algebra runs Python-level simplification at construction time. For
|
|
626
|
+
maximum JIT efficiency, assemble operator expressions outside the
|
|
627
|
+
`jax.jit` boundary; see the JAX integration design note.
|
|
628
|
+
- `MatrixFreeLinOp` stores its callables in pytree auxiliary data.
|
|
629
|
+
Constructing one inside a JIT-traced function with a new lambda each call
|
|
630
|
+
triggers retracing. Construct outside the traced region with a stable
|
|
631
|
+
callable reference.
|
|
632
|
+
- The CuPy backend is provided as a preview. Coverage of non-standard
|
|
633
|
+
operations and sparse handling may evolve in a subsequent release.
|
|
634
|
+
|
|
635
|
+
[0.3.1]: https://github.com/Pavlo3P/SpaceCore/releases/tag/v0.3.1
|
|
636
|
+
[0.3.0]: https://github.com/Pavlo3P/SpaceCore/releases/tag/v0.3.0
|
|
637
|
+
[0.2.0]: https://github.com/Pavlo3P/SpaceCore/releases/tag/v0.2.0
|