spacecore 0.4.2__tar.gz → 0.4.3__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.2 → spacecore-0.4.3}/CHANGELOG.md +196 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/PKG-INFO +21 -12
- {spacecore-0.4.2 → spacecore-0.4.3}/README.md +20 -11
- spacecore-0.4.3/docs/source/api/context.rst +61 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/api/functionals.rst +86 -4
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/design/checking_policy.rst +30 -22
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/release_notes.rst +91 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/pyproject.toml +7 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/__init__.py +47 -24
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/_batching.py +8 -2
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/_checks.py +39 -0
- spacecore-0.4.3/spacecore/_errors.py +29 -0
- spacecore-0.4.3/spacecore/_lazy_algebra.py +181 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/_version.py +1 -1
- spacecore-0.4.3/spacecore/backend/__init__.py +42 -0
- spacecore-0.4.3/spacecore/backend/_container.py +215 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/backend/_ops.py +247 -43
- spacecore-0.4.3/spacecore/backend/_optional.py +215 -0
- spacecore-0.4.3/spacecore/backend/_registry.py +193 -0
- spacecore-0.4.3/spacecore/backend/jax/__init__.py +19 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/backend/jax/_ops.py +15 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/backend/torch/_ops.py +51 -2
- {spacecore-0.4.2/spacecore/_contextual → spacecore-0.4.3/spacecore/contextual}/__init__.py +21 -1
- {spacecore-0.4.2/spacecore/_contextual → spacecore-0.4.3/spacecore/contextual}/_bound.py +75 -34
- {spacecore-0.4.2/spacecore/backend → spacecore-0.4.3/spacecore/contextual}/_context.py +89 -49
- spacecore-0.4.3/spacecore/contextual/_contextual.py +260 -0
- spacecore-0.4.3/spacecore/contextual/_state.py +263 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/functional/__init__.py +17 -2
- spacecore-0.4.3/spacecore/functional/_algebra.py +762 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/functional/_base.py +58 -31
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/functional/_composed.py +69 -6
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/functional/_linear.py +29 -19
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/functional/_quadratic.py +15 -11
- spacecore-0.4.3/spacecore/functional/_realified.py +240 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/functional/tools/__init__.py +9 -2
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/functional/tools/_coordinate.py +15 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/functional/tools/_entropy.py +40 -9
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/functional/tools/_huber.py +33 -6
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/functional/tools/_norms.py +32 -11
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/functional/tools/_proximal.py +49 -4
- spacecore-0.4.3/spacecore/functional/tools/_spectral.py +292 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/core/algebra.py +7 -12
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/core/functional.py +15 -2
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/specs/_dispatch.py +12 -3
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linalg/_power.py +1 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linop/_algebra.py +233 -133
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linop/_base.py +58 -18
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linop/_dense.py +42 -6
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linop/_diagonal.py +11 -5
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linop/_metric.py +13 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linop/_sparse.py +11 -5
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linop/tree/_base.py +14 -5
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linop/tree/_block.py +27 -16
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linop/tree/_from_single.py +10 -5
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linop/tree/_to_single.py +10 -5
- spacecore-0.4.3/spacecore/opfamily.py +329 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/optimize/_optax.py +2 -2
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/space/base/_coordinate.py +24 -5
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/space/base/_inner_product.py +3 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/space/base/_jordan.py +6 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/space/base/_space.py +63 -7
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/space/base/_star.py +3 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/space/base/_vector.py +3 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/space/concrete/_dense_coordinate.py +9 -2
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/space/concrete/_dense_vector.py +29 -9
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/space/concrete/_hermitian.py +38 -2
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/space/concrete/_stacked.py +36 -24
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/space/concrete/_tree_space.py +18 -21
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore.egg-info/PKG-INFO +21 -12
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore.egg-info/SOURCES.txt +20 -7
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/backend/_references.py +187 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/backend/test_context.py +33 -48
- spacecore-0.4.3/tests/backend/test_optional_guard.py +188 -0
- spacecore-0.4.3/tests/backend/test_pytree_registry.py +429 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/bench/test_bench_smoke.py +9 -7
- spacecore-0.4.3/tests/conftest.py +25 -0
- spacecore-0.4.3/tests/context/_contracts.py +101 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/context/conftest.py +5 -0
- spacecore-0.4.3/tests/context/test_ambient_scoping.py +216 -0
- spacecore-0.4.3/tests/context/test_check_policy.py +204 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/context/test_check_policy_helpers.py +8 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/context/test_checked_method.py +11 -3
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/context/test_compatibility.py +47 -68
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/context/test_context_bound.py +57 -19
- spacecore-0.4.3/tests/context/test_context_contracts.py +133 -0
- spacecore-0.4.3/tests/context/test_context_resolution_policy.py +102 -0
- spacecore-0.4.3/tests/context/test_enable_checks.py +164 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/context/test_policies_errors.py +24 -12
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/context/test_state_free_functions.py +38 -34
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/functional/test_algebra.py +184 -5
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/functional/test_composed_functional.py +167 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/functional/test_functional_base.py +103 -2
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/functional/test_generated_functionals.py +32 -23
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/functional/test_inner_product_functional.py +1 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/functional/test_linear_functional.py +1 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/functional/test_linop_quadratic_form.py +7 -6
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/functional/test_matrix_free_linear_functional.py +10 -8
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/functional/test_metric_gradient.py +75 -67
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/functional/test_quadratic_form.py +1 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/functional/tools/test_proximal.py +139 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/functional/tools/test_spectral.py +24 -14
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/generators/_arrays.py +1 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/generators/_contexts.py +7 -10
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/generators/_hermitian.py +1 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/generators/_metrics.py +1 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/generators/_trees.py +1 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/generators/functionals.py +114 -22
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/generators/linops.py +20 -16
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/generators/spaces.py +8 -4
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/generators/test_registry_completeness.py +1 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/integration/test_imports.py +1 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/integration/test_public_api.py +8 -4
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/integration/test_smoke_torch.py +24 -21
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/kernels/test_kernel_dispatch.py +49 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linalg/_helpers.py +10 -2
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linalg/test_core_resolution.py +2 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linalg/test_generated_solver_matrix.py +2 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linalg/test_solver_contracts.py +2 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linalg/test_utils.py +14 -8
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/test_algebra_factories.py +82 -33
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/test_algebra_linops.py +48 -29
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/test_block_diagonal_linop.py +8 -7
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/test_block_matrix_linop.py +1 -2
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/test_dense_linop.py +6 -5
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/test_fused_algebra_overhead.py +8 -5
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/test_linop_jit.py +8 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/test_metric_helpers.py +3 -3
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/test_sparse_linop.py +9 -7
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/test_stacked_linop.py +8 -6
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/test_sum_to_single_linop.py +6 -4
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/test_tree_helpers.py +6 -4
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/optim/test_cached_member_checks.py +16 -12
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_check_batched.py +4 -8
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_dense_coordinate_space.py +1 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_elementwise_jordan_spaces.py +3 -3
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_generated_dense_coordinate.py +2 -2
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_hermitian_space.py +65 -6
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_jordan_algebra_spaces.py +4 -4
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_jordan_invariants.py +6 -6
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_space_base.py +9 -9
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_space_checks.py +6 -4
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_stacked_space.py +3 -2
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_tree_space.py +14 -10
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_tree_spectral_decomposition.py +12 -11
- spacecore-0.4.3/tests/test_equality.py +310 -0
- spacecore-0.4.3/tests/test_opfamily.py +289 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/test_repr.py +1 -1
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/test_weighted_tikhonov.py +9 -8
- spacecore-0.4.2/docs/source/api/context.rst +0 -45
- spacecore-0.4.2/spacecore/_contextual/_policies.py +0 -17
- spacecore-0.4.2/spacecore/_contextual/_state.py +0 -446
- spacecore-0.4.2/spacecore/backend/__init__.py +0 -41
- spacecore-0.4.2/spacecore/backend/jax/__init__.py +0 -14
- spacecore-0.4.2/spacecore/backend/jax/_pytree.py +0 -32
- spacecore-0.4.2/spacecore/functional/_algebra.py +0 -440
- spacecore-0.4.2/spacecore/functional/tools/_spectral.py +0 -126
- spacecore-0.4.2/tests/backend/test_jax_pytree_class.py +0 -165
- spacecore-0.4.2/tests/conftest.py +0 -7
- spacecore-0.4.2/tests/context/test_check_policy.py +0 -187
- spacecore-0.4.2/tests/context/test_enable_checks.py +0 -128
- {spacecore-0.4.2 → spacecore-0.4.3}/CONTRIBUTING.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/LICENSE +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/MANIFEST.in +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/0.3.1-docs-inventory.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/0.3.1-docstring-audit.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/0.4.1-bench-surface.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/001_backend_layer.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/002_context_and_conversion.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/003_space_hierarchy.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/004_inner_product_and_geometry.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/005_space_subclasses_and_capabilities.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/006_current_batching_model.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/007_linop_contract.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/008_linop_subclasses.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/009_metric_adjoint.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/010_functional_contract.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/011_linalg_contract.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/012_jordan_spectrum.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/013_tree_structured_spaces.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/014_check_policy.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/015_dtype_default_vs_scalar_field.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/016_kernel_layers.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/017_tensor_product_spaces.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/018_external_optimizer_adapters.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/019_everyday_toolbox.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/020_sets_and_projection.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/021_lazy_operator_algebra_and_simplification.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/022_caching.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/023_benchmark_framework.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/README.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/adr/template.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/contributing/architecture.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/contributing/labels.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/contributing/linop_generators.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/contributing/prerequisites.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/contributing/process.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/contributing/setup.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/current.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/docstring_style.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/dev/vision.md +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/_static/custom.css +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/api/backend.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/api/index.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/api/linalg.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/api/linops.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/api/optimize.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/api/spaces.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/conf.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/design/backend_conformance.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/design/backend_deviations.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/design/backend_ops_array_api.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/design/batching.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/design/batching_test_policy.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/design/capability_dispatch.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/design/context_ownership.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/design/conversion_policy.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/design/dtype_policy.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/design/geometry.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/design/index.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/design/jax_integration.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/design/kernels_policy.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/design/performance.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/design/tree_spaces.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/dev/adr.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/dev/contributing.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/dev/index.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/dev/vision.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/index.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/tutorials/01_backend_and_context.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/tutorials/02_linear_algebra.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/tutorials/03_functionals.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/tutorials/04_tree_spaces.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/tutorials/05_weighted_tikhonov.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/tutorials/06_optimal_transport.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/tutorials/07_manifold_descent.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/tutorials/08_pdhg_conic_program.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/tutorials/09_kernels_and_fusion.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/docs/source/tutorials/index.rst +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/setup.cfg +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/_check_policy.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/_repr.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/backend/_eager.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/backend/_family.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/backend/cupy/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/backend/cupy/_ops.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/backend/numpy/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/backend/numpy/_ops.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/backend/torch/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/functional/tools/_least_squares.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/core/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/core/_rules.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/core/dense.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/core/diagonal.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/core/sparse.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/specs/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/specs/_batched.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/specs/_policy.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/specs/_registry.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/specs/block_batched.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/specs/block_diagonal.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/specs/composed.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/specs/composed_simplify.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/kernels/specs/stacked_batched.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linalg/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linalg/_cg.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linalg/_expm.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linalg/_lanczos.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linalg/_lsqr.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linalg/_utils.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linop/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/linop/tree/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/optimize/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/optimize/_common.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/optimize/_scipy.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/space/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/space/base/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/space/checks/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/space/checks/_base.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/space/checks/_coordinate.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/space/concrete/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/types/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/types/_array.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/types/_dtype.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore/types/_misc.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore.egg-info/dependency_links.txt +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore.egg-info/requires.txt +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/spacecore.egg-info/top_level.txt +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/_conformance.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/_helpers.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/backend/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/backend/_conformance.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/backend/conftest.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/backend/test_backend_family.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/backend/test_cupy_ops.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/backend/test_jax_ops.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/backend/test_lazy_namespace.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/backend/test_numpy_ops.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/backend/test_operations.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/backend/test_torch_ops.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/backend/test_types_protocols.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/bench/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/bench/test_bare_baseline.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/bench/test_macro_aggregate.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/bench/test_macro_dashboard.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/bench/test_macro_runner_smoke.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/bench/test_macro_schema.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/bench/test_regimes.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/context/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/functional/conftest.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/functional/tools/test_battery_functionals.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/functional/tools/test_least_squares.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/generators/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/generators/_params.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/generators/_protocol.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/generators/_seed.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/generators/test_smoke.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/integration/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/integration/test_github_labels.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/integration/test_smoke_jax.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/integration/test_smoke_numpy.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/kernels/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/kernels/conftest.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/kernels/test_core_kernel_dispatch.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/kernels/test_kernel_registry.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/kernels/test_kernel_spec.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/kernels/test_kernels_match_generic.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/kernels/test_materialized_cache.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linalg/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linalg/conftest.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linalg/test_cg.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linalg/test_expm_multiply.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linalg/test_lanczos.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linalg/test_lsqr.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linalg/test_power_iteration.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linalg/test_result_types.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/conftest.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/test_diagonal_linop.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/test_fuse.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/test_generated_linop_laws.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/test_linop_base.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/linops/test_tree_linop_base.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/optim/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/optimize/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/optimize/_helpers.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/optimize/test_contracts.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/optimize/test_line_search_scipy.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/optimize/test_metric_handoff.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/optimize/test_minimize_optax.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/optimize/test_minimize_scipy.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/__init__.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/_generated_helpers.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/conftest.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_coordinate_space_base.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_dense_vector_space.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_generated_dense_vector.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_generated_inner_product.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_generated_jordan_space.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_generated_space_laws.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_generated_tree_space.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_inner_product.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_inner_product_space_base.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_star_space_base.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tests/spaces/test_vector_space_base.py +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tutorials/01_backend_and_context.ipynb +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tutorials/02_linear_algebra.ipynb +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tutorials/03_functionals.ipynb +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tutorials/04_tree_spaces.ipynb +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tutorials/05_weighted_tikhonov.ipynb +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tutorials/06_optimal_transport.ipynb +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tutorials/07_manifold_descent.ipynb +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tutorials/08_pdhg_conic_program.ipynb +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tutorials/09_kernels_and_fusion.ipynb +0 -0
- {spacecore-0.4.2 → spacecore-0.4.3}/tutorials/README.md +0 -0
|
@@ -7,6 +7,202 @@ and the project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.4.3] — 2026-09-12
|
|
11
|
+
|
|
12
|
+
### Removed
|
|
13
|
+
|
|
14
|
+
- **`jax_pytree_class` is removed from the public API** (breaking). Pytree
|
|
15
|
+
registration is no longer a JAX-named decorator applied by hand, but a
|
|
16
|
+
backend-neutral registry: containers inherit `PyTreeNode` and each backend
|
|
17
|
+
installs its own tree protocol (see *Added*). No replacement decorator is
|
|
18
|
+
exported — a class becomes a pytree node by being a concrete `LinOp`,
|
|
19
|
+
`Functional`, or one of the three pytree `Space` types. Code that decorated its
|
|
20
|
+
own class should inherit `spacecore.backend.PyTreeNode` instead.
|
|
21
|
+
- **`SpectralLpNormFunctional` is removed** (breaking). A per-formula spectral
|
|
22
|
+
class duplicates the value, the gradient, the pytree methods and the validation
|
|
23
|
+
of its coordinate twin — it re-checked `p >= 1` that `LpNormFunctional` already
|
|
24
|
+
enforces. The Schatten `p`-norm is now the spectral *lift* of the coordinate
|
|
25
|
+
`p`-norm:
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
# before
|
|
29
|
+
f = sc.SpectralLpNormFunctional(X, p)
|
|
30
|
+
# after
|
|
31
|
+
f = sc.spectralize(X, lambda s: sc.LpNormFunctional(s, p))
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`NuclearNormFunctional(X)` is unchanged as a named constructor and now returns a
|
|
35
|
+
`SpectralFunctional` whose `base` is `LpNormFunctional(s, 1.0)`; code reading
|
|
36
|
+
`f.p` should read `f.base.p`.
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- **Backend-neutral pytree registration.** `PyTreeNode` (the capability mixin
|
|
41
|
+
owning the `tree_flatten` / `tree_unflatten` contract), `PyTreeRegistry`, and
|
|
42
|
+
`BackendOps.install_pytree_protocol()` — a plugin hook, no-op by default, that a
|
|
43
|
+
backend implements to teach its transform machinery to see inside SpaceCore
|
|
44
|
+
containers. The registry wires the class × backend cross-product with
|
|
45
|
+
back-fill in both directions, so registration no longer depends on import order.
|
|
46
|
+
`LinOp` and `Functional` now carry the capability on their bases, so every
|
|
47
|
+
concrete subclass — including user-defined ones — is registered automatically.
|
|
48
|
+
- **Torch is now a transform-capable backend.** `TorchOps.install_pytree_protocol`
|
|
49
|
+
registers containers with `torch.utils._pytree`, so a Torch-backed operator can
|
|
50
|
+
flow through `torch.compile` and `torch.func` as a traced argument rather than an
|
|
51
|
+
opaque leaf. One registration also covers `torch.utils._cxx_pytree`.
|
|
52
|
+
- **`SpectralFunctional`, `spectralize`, `eigenvalue_space`** — lift **any**
|
|
53
|
+
symmetric coordinate functional onto a Jordan spectrum (Lewis's theorem), instead
|
|
54
|
+
of hand-writing a class per formula. `spectralize(X, NegativeEntropyFunctional)`
|
|
55
|
+
is the von Neumann entropy; `SquaredL2NormFunctional` lifts to the squared
|
|
56
|
+
Frobenius norm, `HuberFunctional` to its spectral analogue. The base functional
|
|
57
|
+
must be symmetric — eigenvalues have no canonical order, so a non-symmetric `f`
|
|
58
|
+
makes `f(lambda(X))` ill-defined rather than merely mis-differentiated.
|
|
59
|
+
- **`RealifiedFunctional` and `realify`** — view a complex-domain functional over
|
|
60
|
+
stacked real coordinates `(Re v, Im v)`, for optimizers that assume a real vector
|
|
61
|
+
space. The real gradient is `(Re g_v, Im g_v)` with `g_v` the *coordinate*
|
|
62
|
+
gradient, so the metric correction stays where ADR-010 put it. `realify` is a
|
|
63
|
+
no-op on an already-real domain.
|
|
64
|
+
- **`OpsRegistry`** — the backend registry extracted out of `Contextual`, which now
|
|
65
|
+
holds ambient policy only. Instantiable, so registration is testable without the
|
|
66
|
+
process-wide singleton; `register_ops` still raises `ContextConflictError` on a
|
|
67
|
+
duplicate family.
|
|
68
|
+
- **`BackendOps.complex_dtype`** — the inverse of `real_dtype`. Deriving it at the
|
|
69
|
+
call site is not portable: NumPy promotes `float32` against a Python complex to
|
|
70
|
+
`complex128`, while JAX and Torch give `complex64`.
|
|
71
|
+
|
|
72
|
+
- **`ProductFunctional` and `make_functional_product`** — the functional algebra
|
|
73
|
+
becomes multiplicative. `F * G` is the pointwise product `F(x) * G(x)` on a
|
|
74
|
+
shared domain, with the product-rule Riesz gradient
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
grad(F·G)(x) = conj(G(x))·grad F(x) + conj(F(x))·grad G(x)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
combined through the domain's own `scale`/`add` (a domain element may be a
|
|
81
|
+
pytree), and a `value_and_grad` that evaluates each factor once. Deliberately
|
|
82
|
+
**binary**: the product rule is a two-factor law, and `(F*G)*H` expresses the
|
|
83
|
+
n-ary case at the same cost. The conjugations are identities for the usual
|
|
84
|
+
real-valued factors.
|
|
85
|
+
- **`ConstantFunctional` and `make_constant_functional`** — the constant map
|
|
86
|
+
`x -> c`, with zero gradient. This is the embedding of a scalar into the
|
|
87
|
+
functional algebra, previously unrepresentable: the algebra had a zero element
|
|
88
|
+
and an affine shift but no constant node. `make_constant_functional` collapses
|
|
89
|
+
`c = 0` to `ZeroFunctional` so the additive identity keeps one representation.
|
|
90
|
+
- **`spacecore.opfamily`: `OperatorFamily`, `FunctionalScaledOperator`,
|
|
91
|
+
`make_functional_scaled_operator`** — `F * A` for a `Functional` and a `LinOp`
|
|
92
|
+
is the functional-weighted map `m(x) = F(x) A x`. That map is **not linear**
|
|
93
|
+
(both the scale and the direction move with `x`), so it is deliberately *not* a
|
|
94
|
+
`LinOp`; it is a point-indexed *family* `x -> A_x`, of which a `LinOp` is the
|
|
95
|
+
constant case. Freezing the point recovers linearity, and each point carries
|
|
96
|
+
two different operators:
|
|
97
|
+
|
|
98
|
+
- `m.at(x)` — the frozen member `F(x) · A`, an ordinary `ScaledLinOp` that
|
|
99
|
+
composes, sums and has an adjoint;
|
|
100
|
+
- `m.linearize_at(x)` — the derivative `Dm(x)[h] = <grad F(x), h>·Ax + F(x)·A h`,
|
|
101
|
+
with metric adjoint `<Ax, w>_Y·grad F(x) + conj(F(x))·A^# w`, for Newton-type
|
|
102
|
+
steps.
|
|
103
|
+
|
|
104
|
+
They differ by exactly a rank-one term and coincide only when `F` is constant.
|
|
105
|
+
A `ConstantFunctional` weight collapses to a plain `ScaledLinOp`, so the linear
|
|
106
|
+
case is never forced through the non-linear type. The module is top-level
|
|
107
|
+
because it depends on both `linop` and `functional`, and neither depends on it.
|
|
108
|
+
- **`checked_method(out_scalar=True)` / `out_batched_scalar=True`** — the codomain
|
|
109
|
+
check for a `Functional`. `out_space=` names an attribute holding a `Space`, and
|
|
110
|
+
a functional's codomain is the scalar *field*, reported only as a string, so the
|
|
111
|
+
decorator that guards every `LinOp` output had nothing to bind to and the check
|
|
112
|
+
was hand-written per subclass. `out_scalar` asserts `shape == ()`;
|
|
113
|
+
`out_batched_scalar` asserts `(N,)` with `N` read from the input named by
|
|
114
|
+
`in_space`, which it therefore requires.
|
|
115
|
+
- **`Space.scalar_field`, `Space.declared_scalar_field`, `Space.check_scalar`** —
|
|
116
|
+
the field of scalars a space is closed under, *declared* rather than inferred
|
|
117
|
+
from the dtype. It defaults to `field`; `HermitianSpace` declares `"real"`,
|
|
118
|
+
because complex Hermitian matrices have complex entries but form a **real**
|
|
119
|
+
vector space (`i·H` is anti-Hermitian).
|
|
120
|
+
|
|
121
|
+
### Changed
|
|
122
|
+
|
|
123
|
+
- **`check_level` is a property of the bound object, not of `Context`** (breaking).
|
|
124
|
+
`Context(ops, dtype=..., check_level=...)` and the deprecated `enable_checks=`
|
|
125
|
+
argument are gone; `Context` is now exactly `(ops, dtype)`. Pass `check_level=`
|
|
126
|
+
to the space / operator / functional constructor, or set it ambiently with
|
|
127
|
+
`set_check_level` / `use_check_level`. Two contexts differing only in strictness
|
|
128
|
+
are now correctly the same context.
|
|
129
|
+
- **`spacecore._contextual` is now `spacecore.contextual`** (breaking), and
|
|
130
|
+
`Context` moved out of `spacecore.backend`. The top-level `spacecore.Context`
|
|
131
|
+
re-export is unchanged.
|
|
132
|
+
- **Ambient context and check level are scoped with `contextvars`.**
|
|
133
|
+
`use_context` / `use_check_level` install a `ContextVar` override unwound by
|
|
134
|
+
`Token`, so nesting is exact and concurrent threads or async tasks cannot clobber
|
|
135
|
+
one another. `set_context` / `set_check_level` still write the process-wide
|
|
136
|
+
baseline. The backend registry deliberately stays global — scoping it would make
|
|
137
|
+
a backend registered inside a `with` block vanish on exit.
|
|
138
|
+
- **`available_ops()` is memoized and returns a tuple** rather than a list.
|
|
139
|
+
Discovery attempts a real import per optional backend and scans entry-point
|
|
140
|
+
metadata; it ran three times per `import spacecore`. A tuple because the cached
|
|
141
|
+
value is shared.
|
|
142
|
+
|
|
143
|
+
- **`Functional.__mul__` / `__rmul__` now dispatch on the operand type.** A scalar
|
|
144
|
+
still gives `ScaledFunctional`; a `Functional` now gives the pointwise product
|
|
145
|
+
and a `LinOp` the functional-weighted family. Previously both returned
|
|
146
|
+
`NotImplemented`, so `F * G` and `F * A` raised `TypeError`. Operands that are
|
|
147
|
+
neither scalar-like nor `Functional` nor `LinOp` still defer to the reflected
|
|
148
|
+
operation.
|
|
149
|
+
- **Functional outputs are checked as scalars at `standard` and above.** 17
|
|
150
|
+
`value` and 3 `vvalue` implementations carry the new decorator flags, replacing
|
|
151
|
+
four hand-written `_checks_at_least("standard")` / `_check_scalar_shape` bodies
|
|
152
|
+
with one implementation. The level matches what those call sites already used —
|
|
153
|
+
`cheap` deliberately does not run it. Cost is ~0.5 µs per `value` call, and
|
|
154
|
+
nothing at `check_level="none"`, which still short-circuits before any check.
|
|
155
|
+
`MatrixFreeLinearFunctional.vvalue` keeps its own check: it permits several
|
|
156
|
+
leading batch axes, which is broader than the single-axis contract `vvalue`
|
|
157
|
+
documents. `RealifiedFunctional.value` is checked on its output only — its input
|
|
158
|
+
is validated against the *complex* domain by the inner functional.
|
|
159
|
+
- **`_check_scalar_shape` distinguishes single from batched output** in its error
|
|
160
|
+
message ("Expected scalar output" vs "Expected scalar batch output"). It said
|
|
161
|
+
"batch" unconditionally, which was harmless while it guarded four batched paths
|
|
162
|
+
and misleading now that it guards ~20 mostly single-element ones.
|
|
163
|
+
- **`HermitianSpace.scale` / `scale_batch` reject a non-real multiplier**
|
|
164
|
+
(breaking, at `standard` and above). `scale(1j, H)` returned a skew-Hermitian
|
|
165
|
+
array still typed as an element of `Herm(n)`; the error surfaced at some later
|
|
166
|
+
membership check, or never at `check_level="none"`. Only a *provably* non-real
|
|
167
|
+
multiplier is refused, so a traced scalar under `jax.jit` still passes. `field`
|
|
168
|
+
remains dtype-derived and still drives equality and repr: a real-dtype and a
|
|
169
|
+
complex-dtype `Herm(n)` are genuinely different spaces.
|
|
170
|
+
|
|
171
|
+
### Fixed
|
|
172
|
+
|
|
173
|
+
- **A present-but-broken optional backend no longer aborts `import spacecore`.**
|
|
174
|
+
`spacecore.backend` eagerly imported the JAX subpackage to reach
|
|
175
|
+
`jax_pytree_class`, so an installed-but-unimportable backend raising anything
|
|
176
|
+
other than `ModuleNotFoundError` — a shadowed `cupy`, a partially-installed
|
|
177
|
+
`jax` — propagated out of the import. Discovery is now the only path into a
|
|
178
|
+
backend package, and it warns and skips instead.
|
|
179
|
+
- **One broken backend now warns once, not once per discovery call.**
|
|
180
|
+
|
|
181
|
+
- **`ComposedFunctional` now has a gradient.** `F.compose(A).grad(x)` raised
|
|
182
|
+
`NotImplementedError`: the node implemented `value` but not the chain rule,
|
|
183
|
+
though `LinOp.rapply` already provides the metric adjoint it needs. Added
|
|
184
|
+
`grad`, a fused `value_and_grad`, and a batched `vgrad`, with cores registered
|
|
185
|
+
in the `composed-functional` kernel set:
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
grad(F o A)(x) = A^#(grad F(A x))
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
`rapply` **is** `A^#` (ADR-009), so no Riesz map is applied on top of it —
|
|
192
|
+
that would count the geometry twice — and no explicit conjugation appears,
|
|
193
|
+
because the adjoint identity absorbs it. `value_and_grad` applies `A` once and
|
|
194
|
+
shares the image, where the inherited default applied it twice. The typed
|
|
195
|
+
specializations in `make_functional_composed` (`InnerProductFunctional`,
|
|
196
|
+
`LinOpQuadraticForm`) were unaffected, and are used as a cross-check on the
|
|
197
|
+
generic node.
|
|
198
|
+
- **`scalar_eq` no longer swallows every exception.** It wrapped its comparison in
|
|
199
|
+
a bare `except Exception: return False`, so a raising `__eq__` was silently
|
|
200
|
+
reported as inequality. Narrowed to `TypeError` — the base class of JAX's
|
|
201
|
+
`TracerBoolConversionError` and of any "cannot reduce to a concrete bool"
|
|
202
|
+
failure — which keeps the intended verdict for an abstract scalar (undecidable,
|
|
203
|
+
so canonicalization is skipped and the expression tree stays unfolded but
|
|
204
|
+
correct) while letting a genuinely broken `__eq__` propagate.
|
|
205
|
+
|
|
10
206
|
## [0.4.2] — 2026-07-01
|
|
11
207
|
|
|
12
208
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: spacecore
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.3
|
|
4
4
|
Summary: Backend-agnostic vector spaces and linear operators.
|
|
5
5
|
Author: Pavlo Pelikh
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -226,7 +226,8 @@ level) adds named constructors over that machinery, with no new core types:
|
|
|
226
226
|
`least_squares` for `½‖Ax−b‖²`, coordinate norms (`SquaredL2NormFunctional`,
|
|
227
227
|
`LpNormFunctional`, `L1NormFunctional`), `NegativeEntropyFunctional`,
|
|
228
228
|
`KLDivergenceFunctional`, `HuberFunctional`, the spectral
|
|
229
|
-
`
|
|
229
|
+
`NuclearNormFunctional` (and `spectralize` / `SpectralFunctional` to lift any
|
|
230
|
+
coordinate functional to a spectral one), and the metric-aware
|
|
230
231
|
proximal primitive `generalized_shrinkage` with the wrappers `prox_l1`,
|
|
231
232
|
`prox_l2sq`, and `project_nonneg`. Each objective's gradient is the metric
|
|
232
233
|
(Riesz) gradient under the domain geometry, and the proximal step is taken in
|
|
@@ -260,21 +261,29 @@ and [deviation catalog](https://pavlo3p.github.io/SpaceCore/design/backend_devia
|
|
|
260
261
|
|
|
261
262
|
## Validation Policy
|
|
262
263
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
`
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
run strict.
|
|
264
|
+
Every context-bound object — space, operator, functional — carries a
|
|
265
|
+
`check_level` that determines how aggressively it validates its inputs, together
|
|
266
|
+
with solver preconditions. The ordered levels are
|
|
267
|
+
`CHECK_LEVELS = ("none", "cheap", "standard", "strict")`: `cheap` covers
|
|
268
|
+
shape/dtype/backend/tree-structure, `standard` adds membership and Hermitian
|
|
269
|
+
checks, and `strict` adds bounded expensive probes. Checks are opt-in per
|
|
270
|
+
object, so hot paths can run unvalidated while development and tests run strict.
|
|
271
|
+
|
|
272
|
+
The level is a property of the bound object rather than of the `Context`: a
|
|
273
|
+
context fixes backend ops and dtype, while two objects sharing that backend and
|
|
274
|
+
dtype may legitimately validate at different strictness. Pass `check_level=` to
|
|
275
|
+
a constructor, or move the ambient default with `sc.set_check_level(...)` /
|
|
276
|
+
`sc.use_check_level(...)`.
|
|
270
277
|
|
|
271
278
|
```python
|
|
272
279
|
import numpy as np
|
|
273
280
|
import spacecore as sc
|
|
274
281
|
|
|
275
|
-
ctx = sc.Context(sc.NumpyOps(), dtype=np.float64
|
|
276
|
-
X = sc.DenseCoordinateSpace((2,), ctx)
|
|
277
|
-
A = sc.DenseLinOp(
|
|
282
|
+
ctx = sc.Context(sc.NumpyOps(), dtype=np.float64)
|
|
283
|
+
X = sc.DenseCoordinateSpace((2,), ctx, check_level="standard")
|
|
284
|
+
A = sc.DenseLinOp(
|
|
285
|
+
ctx.asarray([[2.0, 0.0], [0.0, 3.0]]), X, X, ctx, check_level="standard"
|
|
286
|
+
)
|
|
278
287
|
|
|
279
288
|
try:
|
|
280
289
|
A.apply(ctx.asarray([1.0, 2.0, 3.0])) # wrong shape
|
|
@@ -180,7 +180,8 @@ level) adds named constructors over that machinery, with no new core types:
|
|
|
180
180
|
`least_squares` for `½‖Ax−b‖²`, coordinate norms (`SquaredL2NormFunctional`,
|
|
181
181
|
`LpNormFunctional`, `L1NormFunctional`), `NegativeEntropyFunctional`,
|
|
182
182
|
`KLDivergenceFunctional`, `HuberFunctional`, the spectral
|
|
183
|
-
`
|
|
183
|
+
`NuclearNormFunctional` (and `spectralize` / `SpectralFunctional` to lift any
|
|
184
|
+
coordinate functional to a spectral one), and the metric-aware
|
|
184
185
|
proximal primitive `generalized_shrinkage` with the wrappers `prox_l1`,
|
|
185
186
|
`prox_l2sq`, and `project_nonneg`. Each objective's gradient is the metric
|
|
186
187
|
(Riesz) gradient under the domain geometry, and the proximal step is taken in
|
|
@@ -214,21 +215,29 @@ and [deviation catalog](https://pavlo3p.github.io/SpaceCore/design/backend_devia
|
|
|
214
215
|
|
|
215
216
|
## Validation Policy
|
|
216
217
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
`
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
run strict.
|
|
218
|
+
Every context-bound object — space, operator, functional — carries a
|
|
219
|
+
`check_level` that determines how aggressively it validates its inputs, together
|
|
220
|
+
with solver preconditions. The ordered levels are
|
|
221
|
+
`CHECK_LEVELS = ("none", "cheap", "standard", "strict")`: `cheap` covers
|
|
222
|
+
shape/dtype/backend/tree-structure, `standard` adds membership and Hermitian
|
|
223
|
+
checks, and `strict` adds bounded expensive probes. Checks are opt-in per
|
|
224
|
+
object, so hot paths can run unvalidated while development and tests run strict.
|
|
225
|
+
|
|
226
|
+
The level is a property of the bound object rather than of the `Context`: a
|
|
227
|
+
context fixes backend ops and dtype, while two objects sharing that backend and
|
|
228
|
+
dtype may legitimately validate at different strictness. Pass `check_level=` to
|
|
229
|
+
a constructor, or move the ambient default with `sc.set_check_level(...)` /
|
|
230
|
+
`sc.use_check_level(...)`.
|
|
224
231
|
|
|
225
232
|
```python
|
|
226
233
|
import numpy as np
|
|
227
234
|
import spacecore as sc
|
|
228
235
|
|
|
229
|
-
ctx = sc.Context(sc.NumpyOps(), dtype=np.float64
|
|
230
|
-
X = sc.DenseCoordinateSpace((2,), ctx)
|
|
231
|
-
A = sc.DenseLinOp(
|
|
236
|
+
ctx = sc.Context(sc.NumpyOps(), dtype=np.float64)
|
|
237
|
+
X = sc.DenseCoordinateSpace((2,), ctx, check_level="standard")
|
|
238
|
+
A = sc.DenseLinOp(
|
|
239
|
+
ctx.asarray([[2.0, 0.0], [0.0, 3.0]]), X, X, ctx, check_level="standard"
|
|
240
|
+
)
|
|
232
241
|
|
|
233
242
|
try:
|
|
234
243
|
A.apply(ctx.asarray([1.0, 2.0, 3.0])) # wrong shape
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Context API
|
|
2
|
+
===========
|
|
3
|
+
|
|
4
|
+
``Context`` packages backend operations and the default dtype. Spaces,
|
|
5
|
+
operators, and functionals store a normalized context and use it for array
|
|
6
|
+
construction and conversion.
|
|
7
|
+
|
|
8
|
+
Validation policy is *not* part of a context: ``check_level`` belongs to the
|
|
9
|
+
bound object, so two objects on the same backend and dtype may validate at
|
|
10
|
+
different strictness. Use ``check_level="none"``, ``"cheap"``, ``"standard"``,
|
|
11
|
+
or ``"strict"`` on the object, or move the ambient default with
|
|
12
|
+
``set_check_level`` / ``use_check_level``. The exported ``spacecore.CheckLevel``
|
|
13
|
+
literal is available for annotations. See :doc:`../design/checking_policy`.
|
|
14
|
+
|
|
15
|
+
Context
|
|
16
|
+
-------
|
|
17
|
+
|
|
18
|
+
.. autosummary::
|
|
19
|
+
:nosignatures:
|
|
20
|
+
|
|
21
|
+
spacecore.Context
|
|
22
|
+
|
|
23
|
+
.. autoclass:: spacecore.Context
|
|
24
|
+
:members:
|
|
25
|
+
|
|
26
|
+
Context helpers
|
|
27
|
+
---------------
|
|
28
|
+
|
|
29
|
+
.. autosummary::
|
|
30
|
+
:nosignatures:
|
|
31
|
+
|
|
32
|
+
spacecore.get_context
|
|
33
|
+
spacecore.set_context
|
|
34
|
+
spacecore.use_context
|
|
35
|
+
spacecore.get_check_level
|
|
36
|
+
spacecore.set_check_level
|
|
37
|
+
spacecore.use_check_level
|
|
38
|
+
spacecore.normalize_context
|
|
39
|
+
spacecore.normalize_ops
|
|
40
|
+
spacecore.resolve_context_priority
|
|
41
|
+
spacecore.register_ops
|
|
42
|
+
|
|
43
|
+
* ``get_context`` and ``set_context`` manage the global default context, and
|
|
44
|
+
``use_context`` overrides it for a block, scoped to the current thread or
|
|
45
|
+
async task.
|
|
46
|
+
* ``get_check_level`` / ``set_check_level`` / ``use_check_level`` do the same for
|
|
47
|
+
the ambient validation level applied to newly constructed bound objects.
|
|
48
|
+
* ``normalize_context`` turns backend names, families, concrete contexts, or ``None`` into a context.
|
|
49
|
+
* ``resolve_context_priority`` chooses a common context for constructors.
|
|
50
|
+
* ``register_ops`` adds a custom backend implementation.
|
|
51
|
+
|
|
52
|
+
.. autofunction:: spacecore.get_context
|
|
53
|
+
.. autofunction:: spacecore.set_context
|
|
54
|
+
.. autofunction:: spacecore.use_context
|
|
55
|
+
.. autofunction:: spacecore.get_check_level
|
|
56
|
+
.. autofunction:: spacecore.set_check_level
|
|
57
|
+
.. autofunction:: spacecore.use_check_level
|
|
58
|
+
.. autofunction:: spacecore.normalize_context
|
|
59
|
+
.. autofunction:: spacecore.normalize_ops
|
|
60
|
+
.. autofunction:: spacecore.resolve_context_priority
|
|
61
|
+
.. autofunction:: spacecore.register_ops
|
|
@@ -20,6 +20,69 @@ Base and composition
|
|
|
20
20
|
* ``ComposedFunctional`` represents pullback ``f o A`` for a linear operator ``A``.
|
|
21
21
|
* ``make_functional_composed`` constructs the same pullback with simplifications.
|
|
22
22
|
|
|
23
|
+
Algebra
|
|
24
|
+
-------
|
|
25
|
+
|
|
26
|
+
Lazy nodes for combining functionals. The operator overloads on ``Functional``
|
|
27
|
+
(``a * F``, ``F + G``, ``F - G``, ``-F``, ``F * G``) delegate to the ``make_*``
|
|
28
|
+
factories, which apply local, *structural* canonicalization — they read node
|
|
29
|
+
types, never values.
|
|
30
|
+
|
|
31
|
+
.. autosummary::
|
|
32
|
+
:nosignatures:
|
|
33
|
+
|
|
34
|
+
spacecore.functional.ScaledFunctional
|
|
35
|
+
spacecore.functional.SumFunctional
|
|
36
|
+
spacecore.functional.ShiftedFunctional
|
|
37
|
+
spacecore.functional.ZeroFunctional
|
|
38
|
+
spacecore.functional.ConstantFunctional
|
|
39
|
+
spacecore.functional.ProductFunctional
|
|
40
|
+
spacecore.functional.make_scaled_functional
|
|
41
|
+
spacecore.functional.make_functional_sum
|
|
42
|
+
spacecore.functional.make_shifted_functional
|
|
43
|
+
spacecore.functional.make_constant_functional
|
|
44
|
+
spacecore.functional.make_functional_product
|
|
45
|
+
|
|
46
|
+
* ``ScaledFunctional`` is ``a * F``; the Riesz gradient scales by ``conj(a)``.
|
|
47
|
+
* ``SumFunctional`` is ``F_1 + ... + F_n`` on a shared domain.
|
|
48
|
+
* ``ShiftedFunctional`` is the affine shift ``F + c`` (gradient unchanged).
|
|
49
|
+
* ``ZeroFunctional`` is the additive identity, recognized by the canonicalizers.
|
|
50
|
+
* ``ConstantFunctional`` is ``x -> c``, the embedding of a scalar into the
|
|
51
|
+
algebra; ``make_constant_functional`` collapses ``c = 0`` to ``ZeroFunctional``.
|
|
52
|
+
* ``ProductFunctional`` is the pointwise product ``F(x) * G(x)``, with the
|
|
53
|
+
product-rule Riesz gradient
|
|
54
|
+
:math:`\overline{G(x)}\, \nabla F(x) + \overline{F(x)}\, \nabla G(x)`. Because
|
|
55
|
+
functionals are scalar-valued, scaling is the constant-factor case of a
|
|
56
|
+
product: ``make_functional_product`` folds a ``ConstantFunctional`` factor back
|
|
57
|
+
into a ``ScaledFunctional``, and a ``ZeroFunctional`` factor to zero.
|
|
58
|
+
|
|
59
|
+
Operator families (``F · A``)
|
|
60
|
+
-----------------------------
|
|
61
|
+
|
|
62
|
+
.. autosummary::
|
|
63
|
+
:nosignatures:
|
|
64
|
+
|
|
65
|
+
spacecore.OperatorFamily
|
|
66
|
+
spacecore.FunctionalScaledOperator
|
|
67
|
+
spacecore.make_functional_scaled_operator
|
|
68
|
+
|
|
69
|
+
``F * A`` for a ``Functional`` and a ``LinOp`` is the functional-weighted map
|
|
70
|
+
:math:`m(x) = F(x)\,Ax`. This is **not** linear — both the scale and the
|
|
71
|
+
direction move with ``x`` — so it is *not* a ``LinOp``; it is an
|
|
72
|
+
``OperatorFamily``, a point-indexed family :math:`x \mapsto A_x`.
|
|
73
|
+
|
|
74
|
+
Each point carries two different linear operators, and they are not the same:
|
|
75
|
+
|
|
76
|
+
* ``m.at(x)`` — the **frozen member** ``F(x) · A``, an ordinary ``LinOp`` that
|
|
77
|
+
composes, sums, and has an adjoint. Freezing the point is what recovers
|
|
78
|
+
linearity.
|
|
79
|
+
* ``m.linearize_at(x)`` — the **derivative** :math:`Dm(x)`, for Newton-type
|
|
80
|
+
steps. They coincide only when ``F`` is constant; otherwise they differ by a
|
|
81
|
+
rank-one term.
|
|
82
|
+
|
|
83
|
+
A ``ConstantFunctional`` weight collapses to an ordinary ``ScaledLinOp``, so the
|
|
84
|
+
linear case is never forced through the non-linear type.
|
|
85
|
+
|
|
23
86
|
Linear functionals
|
|
24
87
|
------------------
|
|
25
88
|
|
|
@@ -59,8 +122,12 @@ metric (Riesz) gradients under the domain geometry.
|
|
|
59
122
|
spacecore.functional.SquaredL2NormFunctional
|
|
60
123
|
spacecore.functional.LpNormFunctional
|
|
61
124
|
spacecore.functional.L1NormFunctional
|
|
62
|
-
spacecore.functional.
|
|
125
|
+
spacecore.functional.SpectralFunctional
|
|
126
|
+
spacecore.functional.spectralize
|
|
127
|
+
spacecore.functional.eigenvalue_space
|
|
63
128
|
spacecore.functional.NuclearNormFunctional
|
|
129
|
+
spacecore.functional.RealifiedFunctional
|
|
130
|
+
spacecore.functional.realify
|
|
64
131
|
spacecore.functional.NegativeEntropyFunctional
|
|
65
132
|
spacecore.functional.KLDivergenceFunctional
|
|
66
133
|
spacecore.functional.HuberFunctional
|
|
@@ -68,8 +135,14 @@ metric (Riesz) gradients under the domain geometry.
|
|
|
68
135
|
* ``least_squares`` builds the ``scale ||A x - b||^2`` objective as a ``LinOpQuadraticForm``.
|
|
69
136
|
* ``SquaredL2NormFunctional`` is ``1/2 ||x||_X^2`` (gradient ``x``, clean shrinkage prox).
|
|
70
137
|
* ``LpNormFunctional`` / ``L1NormFunctional`` are coordinate ``p``-norms.
|
|
71
|
-
* ``
|
|
72
|
-
|
|
138
|
+
* ``SpectralFunctional`` / ``spectralize`` lift **any** symmetric coordinate
|
|
139
|
+
functional onto a Jordan spectrum (Lewis): the Schatten ``p``-norm is
|
|
140
|
+
``spectralize(X, lambda s: LpNormFunctional(s, p))``, the von Neumann entropy
|
|
141
|
+
is ``spectralize(X, NegativeEntropyFunctional)``. ``eigenvalue_space`` builds
|
|
142
|
+
the real space the spectrum lives in.
|
|
143
|
+
* ``NuclearNormFunctional`` is the named Schatten-1 case.
|
|
144
|
+
* ``RealifiedFunctional`` / ``realify`` present a complex-domain functional over
|
|
145
|
+
stacked real coordinates, for real-only optimizers.
|
|
73
146
|
* ``NegativeEntropyFunctional`` and ``KLDivergenceFunctional`` are the entropy objectives.
|
|
74
147
|
* ``HuberFunctional`` is the separable Huber loss.
|
|
75
148
|
|
|
@@ -137,11 +210,20 @@ Autodoc
|
|
|
137
210
|
|
|
138
211
|
.. autofunction:: spacecore.functional.L1NormFunctional
|
|
139
212
|
|
|
140
|
-
.. autoclass:: spacecore.functional.
|
|
213
|
+
.. autoclass:: spacecore.functional.SpectralFunctional
|
|
141
214
|
:members:
|
|
142
215
|
|
|
216
|
+
.. autofunction:: spacecore.functional.spectralize
|
|
217
|
+
|
|
218
|
+
.. autofunction:: spacecore.functional.eigenvalue_space
|
|
219
|
+
|
|
143
220
|
.. autofunction:: spacecore.functional.NuclearNormFunctional
|
|
144
221
|
|
|
222
|
+
.. autoclass:: spacecore.functional.RealifiedFunctional
|
|
223
|
+
:members:
|
|
224
|
+
|
|
225
|
+
.. autofunction:: spacecore.functional.realify
|
|
226
|
+
|
|
145
227
|
.. autoclass:: spacecore.functional.NegativeEntropyFunctional
|
|
146
228
|
:members:
|
|
147
229
|
|
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
Checking policy
|
|
2
2
|
===============
|
|
3
3
|
|
|
4
|
-
SpaceCore uses ``
|
|
5
|
-
The public type is ``spacecore.CheckLevel``, a literal type with four
|
|
6
|
-
values: ``"none"``, ``"cheap"``, ``"standard"``, and ``"strict"``. A
|
|
7
|
-
keeps
|
|
4
|
+
SpaceCore uses ``ContextBound.check_level`` as its public runtime-validation
|
|
5
|
+
policy. The public type is ``spacecore.CheckLevel``, a literal type with four
|
|
6
|
+
ordered values: ``"none"``, ``"cheap"``, ``"standard"``, and ``"strict"``. A
|
|
7
|
+
literal keeps construction simple and makes invalid spellings visible to static
|
|
8
8
|
type checkers without introducing a separate policy object.
|
|
9
9
|
|
|
10
|
+
The level belongs to the *bound object* — space, operator, functional — and not
|
|
11
|
+
to the :class:`~spacecore.Context`. A context fixes backend ops and dtype; two
|
|
12
|
+
objects sharing both may still need different strictness, so the policy is set
|
|
13
|
+
per object, with an ambient default for objects that do not name one.
|
|
14
|
+
|
|
10
15
|
.. code-block:: python
|
|
11
16
|
|
|
12
17
|
import spacecore as sc
|
|
13
18
|
|
|
14
|
-
ctx = sc.Context(sc.NumpyOps(), dtype="float64"
|
|
15
|
-
X = sc.DenseCoordinateSpace((3,), ctx=ctx)
|
|
19
|
+
ctx = sc.Context(sc.NumpyOps(), dtype="float64")
|
|
20
|
+
X = sc.DenseCoordinateSpace((3,), ctx=ctx, check_level="standard")
|
|
16
21
|
|
|
17
22
|
x = X.ctx.asarray([1.0, 2.0, 3.0])
|
|
18
23
|
X.check_member(x)
|
|
@@ -53,9 +58,11 @@ Choosing a level
|
|
|
53
58
|
* Performance-sensitive trusted code: use ``"cheap"`` or ``"none"``.
|
|
54
59
|
* User-facing libraries: usually use ``"standard"``.
|
|
55
60
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
An object constructed without an explicit ``check_level`` takes the ambient
|
|
62
|
+
default, read with :func:`spacecore.get_check_level`. Move that default
|
|
63
|
+
process-wide with :func:`spacecore.set_check_level`, or for a block with
|
|
64
|
+
:func:`spacecore.use_check_level`, which is scoped to the current thread or
|
|
65
|
+
async task.
|
|
59
66
|
|
|
60
67
|
Where checks run
|
|
61
68
|
----------------
|
|
@@ -71,25 +78,26 @@ When a context is inferred from several source objects, SpaceCore selects the
|
|
|
71
78
|
least expensive source level. For example, combining ``"strict"`` and
|
|
72
79
|
``"cheap"`` contexts produces a ``"cheap"`` inferred policy.
|
|
73
80
|
|
|
74
|
-
Migration from
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
``enable_checks`` remains as a deprecated compatibility keyword:
|
|
81
|
+
Migration from context-carried levels
|
|
82
|
+
-------------------------------------
|
|
78
83
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
Before 0.4.3 the level rode on the ``Context``, and the long-deprecated
|
|
85
|
+
``enable_checks=`` Boolean was still accepted there. Both are gone: ``Context``
|
|
86
|
+
is now exactly ``(ops, dtype)``, and passing either keyword to it raises
|
|
87
|
+
``TypeError``.
|
|
82
88
|
|
|
83
89
|
.. code-block:: python
|
|
84
90
|
|
|
85
|
-
#
|
|
86
|
-
ctx = sc.Context(sc.NumpyOps()
|
|
91
|
+
# 0.4.3 and later: the level is set on the object
|
|
92
|
+
ctx = sc.Context(sc.NumpyOps())
|
|
93
|
+
X = sc.DenseCoordinateSpace((3,), ctx=ctx, check_level="standard")
|
|
87
94
|
|
|
88
|
-
#
|
|
89
|
-
|
|
95
|
+
# ...or moved for everything constructed in a block
|
|
96
|
+
with sc.use_check_level("strict"):
|
|
97
|
+
Y = sc.DenseCoordinateSpace((3,), ctx=ctx)
|
|
90
98
|
|
|
91
|
-
|
|
92
|
-
|
|
99
|
+
The level is always one of the four literals; the Boolean spelling is not
|
|
100
|
+
accepted in its place. Read an object's level back from ``obj.check_level``.
|
|
93
101
|
|
|
94
102
|
Implementation convention
|
|
95
103
|
-------------------------
|