spacecore 0.3.1__tar.gz → 0.3.2__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.
Files changed (222) hide show
  1. {spacecore-0.3.1 → spacecore-0.3.2}/CHANGELOG.md +10 -1
  2. spacecore-0.3.2/CONTRIBUTING.md +55 -0
  3. {spacecore-0.3.1 → spacecore-0.3.2}/PKG-INFO +1 -1
  4. spacecore-0.3.2/docs/dev/adr/001_backend_layer.md +38 -0
  5. spacecore-0.3.2/docs/dev/adr/002_context_and_conversion.md +40 -0
  6. spacecore-0.3.2/docs/dev/adr/003_space_hierarchy.md +38 -0
  7. spacecore-0.3.2/docs/dev/adr/004_inner_product_and_geometry.md +38 -0
  8. spacecore-0.3.2/docs/dev/adr/005_space_subclasses_and_capabilities.md +38 -0
  9. spacecore-0.3.2/docs/dev/adr/006_current_batching_model.md +38 -0
  10. spacecore-0.3.2/docs/dev/adr/007_linop_contract.md +39 -0
  11. spacecore-0.3.2/docs/dev/adr/008_linop_subclasses.md +38 -0
  12. spacecore-0.3.2/docs/dev/adr/009_metric_adjoint.md +44 -0
  13. spacecore-0.3.2/docs/dev/adr/010_functional_contract.md +36 -0
  14. spacecore-0.3.2/docs/dev/adr/011_linalg_contract.md +38 -0
  15. spacecore-0.3.2/docs/dev/adr/012_jordan_spectrum.md +36 -0
  16. spacecore-0.3.2/docs/dev/adr/013_tree_structured_spaces.md +36 -0
  17. spacecore-0.3.2/docs/dev/adr/014_check_policy.md +43 -0
  18. spacecore-0.3.2/docs/dev/adr/015_dtype_default_vs_scalar_field.md +40 -0
  19. spacecore-0.3.2/docs/dev/adr/README.md +71 -0
  20. spacecore-0.3.2/docs/dev/contributing/architecture.md +94 -0
  21. spacecore-0.3.2/docs/dev/contributing/labels.md +53 -0
  22. spacecore-0.3.2/docs/dev/contributing/prerequisites.md +29 -0
  23. spacecore-0.3.2/docs/dev/contributing/process.md +78 -0
  24. spacecore-0.3.2/docs/dev/contributing/setup.md +49 -0
  25. spacecore-0.3.2/docs/dev/current.md +32 -0
  26. spacecore-0.3.2/docs/dev/vision.md +68 -0
  27. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/api/linops.rst +2 -1
  28. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/design/geometry.rst +21 -1
  29. spacecore-0.3.2/docs/source/dev/adr.rst +9 -0
  30. spacecore-0.3.2/docs/source/dev/contributing.rst +36 -0
  31. spacecore-0.3.2/docs/source/dev/index.rst +12 -0
  32. spacecore-0.3.2/docs/source/dev/vision.rst +9 -0
  33. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/index.rst +2 -0
  34. {spacecore-0.3.1 → spacecore-0.3.2}/pyproject.toml +1 -0
  35. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/__init__.py +2 -1
  36. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/_version.py +1 -1
  37. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linop/_algebra.py +64 -116
  38. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/base/__init__.py +2 -0
  39. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/checks/__init__.py +2 -0
  40. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/concrete/__init__.py +2 -0
  41. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore.egg-info/PKG-INFO +1 -1
  42. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore.egg-info/SOURCES.txt +28 -0
  43. {spacecore-0.3.1 → spacecore-0.3.2}/tests/backend/test_backend_ops_delegation.py +1 -0
  44. {spacecore-0.3.1 → spacecore-0.3.2}/tests/functional/test_metric_gradient.py +33 -13
  45. spacecore-0.3.2/tests/integration/test_github_labels.py +24 -0
  46. {spacecore-0.3.1 → spacecore-0.3.2}/tests/integration/test_public_api.py +1 -1
  47. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linops/test_adjoint_identity.py +179 -205
  48. {spacecore-0.3.1 → spacecore-0.3.2}/tests/spaces/test_product_structure.py +15 -9
  49. {spacecore-0.3.1 → spacecore-0.3.2}/tests/spaces/test_space_apply.py +4 -2
  50. {spacecore-0.3.1 → spacecore-0.3.2}/tests/spaces/test_stacked_space.py +23 -9
  51. spacecore-0.3.1/CONTRIBUTING.md +0 -13
  52. {spacecore-0.3.1 → spacecore-0.3.2}/LICENSE +0 -0
  53. {spacecore-0.3.1 → spacecore-0.3.2}/MANIFEST.in +0 -0
  54. {spacecore-0.3.1 → spacecore-0.3.2}/README.md +0 -0
  55. {spacecore-0.3.1 → spacecore-0.3.2}/docs/dev/0.3.1-docs-inventory.md +0 -0
  56. {spacecore-0.3.1 → spacecore-0.3.2}/docs/dev/0.3.1-docstring-audit.md +0 -0
  57. {spacecore-0.3.1 → spacecore-0.3.2}/docs/dev/docstring_style.md +0 -0
  58. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/_static/custom.css +0 -0
  59. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/api/backend.rst +0 -0
  60. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/api/context.rst +0 -0
  61. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/api/functionals.rst +0 -0
  62. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/api/index.rst +0 -0
  63. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/api/linalg.rst +0 -0
  64. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/api/spaces.rst +0 -0
  65. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/conf.py +0 -0
  66. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/design/backend_ops_array_api.rst +0 -0
  67. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/design/batching.rst +0 -0
  68. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/design/capability_dispatch.rst +0 -0
  69. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/design/checking_policy.rst +0 -0
  70. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/design/context_ownership.rst +0 -0
  71. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/design/conversion_policy.rst +0 -0
  72. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/design/dtype_policy.rst +0 -0
  73. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/design/index.rst +0 -0
  74. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/design/jax_integration.rst +0 -0
  75. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/design/performance.rst +0 -0
  76. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/release_notes.rst +0 -0
  77. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/tutorials/backend_ops.rst +0 -0
  78. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/tutorials/context.rst +0 -0
  79. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/tutorials/conversion_policy.rst +0 -0
  80. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/tutorials/index.rst +0 -0
  81. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/tutorials/linops.rst +0 -0
  82. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/tutorials/regularized_ot.rst +0 -0
  83. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/tutorials/spaces.rst +0 -0
  84. {spacecore-0.3.1 → spacecore-0.3.2}/docs/source/tutorials/weighted_tikhonov.rst +0 -0
  85. {spacecore-0.3.1 → spacecore-0.3.2}/examples/__init__.py +0 -0
  86. {spacecore-0.3.1 → spacecore-0.3.2}/examples/weighted_tikhonov.py +0 -0
  87. {spacecore-0.3.1 → spacecore-0.3.2}/setup.cfg +0 -0
  88. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/_batching.py +0 -0
  89. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/_checks.py +0 -0
  90. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/_contextual/__init__.py +0 -0
  91. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/_contextual/_bound.py +0 -0
  92. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/_contextual/_policies.py +0 -0
  93. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/_contextual/_state.py +0 -0
  94. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/_tree.py +0 -0
  95. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/backend/__init__.py +0 -0
  96. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/backend/_context.py +0 -0
  97. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/backend/_family.py +0 -0
  98. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/backend/_ops.py +0 -0
  99. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/backend/cupy/__init__.py +0 -0
  100. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/backend/cupy/_ops.py +0 -0
  101. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/backend/jax/__init__.py +0 -0
  102. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/backend/jax/_ops.py +0 -0
  103. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/backend/jax/_pytree.py +0 -0
  104. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/backend/numpy/__init__.py +0 -0
  105. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/backend/numpy/_ops.py +0 -0
  106. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/backend/torch/__init__.py +0 -0
  107. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/backend/torch/_ops.py +0 -0
  108. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/functional/__init__.py +0 -0
  109. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/functional/_base.py +0 -0
  110. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/functional/_composed.py +0 -0
  111. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/functional/_linear.py +0 -0
  112. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/functional/_quadratic.py +0 -0
  113. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linalg/__init__.py +0 -0
  114. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linalg/_cg.py +0 -0
  115. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linalg/_expm.py +0 -0
  116. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linalg/_lanczos.py +0 -0
  117. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linalg/_lsqr.py +0 -0
  118. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linalg/_power.py +0 -0
  119. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linalg/_utils.py +0 -0
  120. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linop/__init__.py +0 -0
  121. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linop/_base.py +0 -0
  122. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linop/_dense.py +0 -0
  123. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linop/_diagonal.py +0 -0
  124. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linop/_metric.py +0 -0
  125. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linop/_sparse.py +0 -0
  126. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linop/product/__init__.py +0 -0
  127. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linop/product/_base.py +0 -0
  128. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linop/product/_block.py +0 -0
  129. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linop/product/_from_single.py +0 -0
  130. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/linop/product/_to_single.py +0 -0
  131. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/__init__.py +0 -0
  132. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/_structure.py +0 -0
  133. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/base/_coordinate.py +0 -0
  134. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/base/_inner_product.py +0 -0
  135. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/base/_jordan.py +0 -0
  136. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/base/_space.py +0 -0
  137. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/base/_star.py +0 -0
  138. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/base/_vector.py +0 -0
  139. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/checks/_base.py +0 -0
  140. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/checks/_coordinate.py +0 -0
  141. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/checks/_product.py +0 -0
  142. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/concrete/_dense_coordinate.py +0 -0
  143. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/concrete/_dense_vector.py +0 -0
  144. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/concrete/_hermitian.py +0 -0
  145. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/concrete/_product.py +0 -0
  146. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/space/concrete/_stacked.py +0 -0
  147. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/types/__init__.py +0 -0
  148. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/types/_array.py +0 -0
  149. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/types/_dtype.py +0 -0
  150. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore/types/_misc.py +0 -0
  151. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore.egg-info/dependency_links.txt +0 -0
  152. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore.egg-info/requires.txt +0 -0
  153. {spacecore-0.3.1 → spacecore-0.3.2}/spacecore.egg-info/top_level.txt +0 -0
  154. {spacecore-0.3.1 → spacecore-0.3.2}/tests/__init__.py +0 -0
  155. {spacecore-0.3.1 → spacecore-0.3.2}/tests/_helpers.py +0 -0
  156. {spacecore-0.3.1 → spacecore-0.3.2}/tests/backend/__init__.py +0 -0
  157. {spacecore-0.3.1 → spacecore-0.3.2}/tests/backend/test_backend_consistency.py +0 -0
  158. {spacecore-0.3.1 → spacecore-0.3.2}/tests/backend/test_backend_loops.py +0 -0
  159. {spacecore-0.3.1 → spacecore-0.3.2}/tests/backend/test_backend_registry.py +0 -0
  160. {spacecore-0.3.1 → spacecore-0.3.2}/tests/backend/test_cupy_ops.py +0 -0
  161. {spacecore-0.3.1 → spacecore-0.3.2}/tests/backend/test_jax_ops.py +0 -0
  162. {spacecore-0.3.1 → spacecore-0.3.2}/tests/backend/test_numpy_ops.py +0 -0
  163. {spacecore-0.3.1 → spacecore-0.3.2}/tests/backend/test_torch_consistency.py +0 -0
  164. {spacecore-0.3.1 → spacecore-0.3.2}/tests/backend/test_torch_ops.py +0 -0
  165. {spacecore-0.3.1 → spacecore-0.3.2}/tests/conftest.py +0 -0
  166. {spacecore-0.3.1 → spacecore-0.3.2}/tests/context/__init__.py +0 -0
  167. {spacecore-0.3.1 → spacecore-0.3.2}/tests/context/test_checked_method.py +0 -0
  168. {spacecore-0.3.1 → spacecore-0.3.2}/tests/context/test_context.py +0 -0
  169. {spacecore-0.3.1 → spacecore-0.3.2}/tests/context/test_context_manager.py +0 -0
  170. {spacecore-0.3.1 → spacecore-0.3.2}/tests/context/test_context_resolution.py +0 -0
  171. {spacecore-0.3.1 → spacecore-0.3.2}/tests/context/test_enable_checks.py +0 -0
  172. {spacecore-0.3.1 → spacecore-0.3.2}/tests/context/test_errors.py +0 -0
  173. {spacecore-0.3.1 → spacecore-0.3.2}/tests/examples/__init__.py +0 -0
  174. {spacecore-0.3.1 → spacecore-0.3.2}/tests/examples/test_weighted_tikhonov.py +0 -0
  175. {spacecore-0.3.1 → spacecore-0.3.2}/tests/functional/test_functional.py +0 -0
  176. {spacecore-0.3.1 → spacecore-0.3.2}/tests/integration/__init__.py +0 -0
  177. {spacecore-0.3.1 → spacecore-0.3.2}/tests/integration/test_imports.py +0 -0
  178. {spacecore-0.3.1 → spacecore-0.3.2}/tests/integration/test_smoke_jax.py +0 -0
  179. {spacecore-0.3.1 → spacecore-0.3.2}/tests/integration/test_smoke_numpy.py +0 -0
  180. {spacecore-0.3.1 → spacecore-0.3.2}/tests/integration/test_smoke_torch.py +0 -0
  181. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linalg/__init__.py +0 -0
  182. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linalg/test_expm.py +0 -0
  183. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linalg/test_krylov.py +0 -0
  184. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linalg/test_metric_solvers.py +0 -0
  185. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linops/__init__.py +0 -0
  186. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linops/test_algebra.py +0 -0
  187. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linops/test_algebra_linop.py +0 -0
  188. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linops/test_batched_apply.py +0 -0
  189. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linops/test_batched_lifting.py +0 -0
  190. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linops/test_block_diagonal_linop.py +0 -0
  191. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linops/test_conversion_linops.py +0 -0
  192. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linops/test_dense_linop.py +0 -0
  193. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linops/test_diagonal_linop.py +0 -0
  194. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linops/test_linop_jit.py +0 -0
  195. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linops/test_product_linop_batching.py +0 -0
  196. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linops/test_product_structure.py +0 -0
  197. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linops/test_sparse_linop.py +0 -0
  198. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linops/test_stacked_linop.py +0 -0
  199. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linops/test_sum_to_single_linop.py +0 -0
  200. {spacecore-0.3.1 → spacecore-0.3.2}/tests/linops/test_to_dense.py +0 -0
  201. {spacecore-0.3.1 → spacecore-0.3.2}/tests/spaces/__init__.py +0 -0
  202. {spacecore-0.3.1 → spacecore-0.3.2}/tests/spaces/test_conversion_spaces.py +0 -0
  203. {spacecore-0.3.1 → spacecore-0.3.2}/tests/spaces/test_geometry.py +0 -0
  204. {spacecore-0.3.1 → spacecore-0.3.2}/tests/spaces/test_hermitian_space.py +0 -0
  205. {spacecore-0.3.1 → spacecore-0.3.2}/tests/spaces/test_product_space.py +0 -0
  206. {spacecore-0.3.1 → spacecore-0.3.2}/tests/spaces/test_space_checks.py +0 -0
  207. {spacecore-0.3.1 → spacecore-0.3.2}/tests/spaces/test_space_hierarchy.py +0 -0
  208. {spacecore-0.3.1 → spacecore-0.3.2}/tests/spaces/test_spectrum.py +0 -0
  209. {spacecore-0.3.1 → spacecore-0.3.2}/tests/spaces/test_vector_space.py +0 -0
  210. {spacecore-0.3.1 → spacecore-0.3.2}/tests/spaces/test_vectorized_checks.py +0 -0
  211. {spacecore-0.3.1 → spacecore-0.3.2}/tests/test_backend_ops_complex.py +0 -0
  212. {spacecore-0.3.1 → spacecore-0.3.2}/tutorials/1_BackendOps.ipynb +0 -0
  213. {spacecore-0.3.1 → spacecore-0.3.2}/tutorials/2_Context.ipynb +0 -0
  214. {spacecore-0.3.1 → spacecore-0.3.2}/tutorials/3_Space.ipynb +0 -0
  215. {spacecore-0.3.1 → spacecore-0.3.2}/tutorials/4_LinOp.ipynb +0 -0
  216. {spacecore-0.3.1 → spacecore-0.3.2}/tutorials/5_Conversion_Policy.ipynb +0 -0
  217. {spacecore-0.3.1 → spacecore-0.3.2}/tutorials/6_Regularized_Opt_Transport.ipynb +0 -0
  218. {spacecore-0.3.1 → spacecore-0.3.2}/tutorials/7_Quadratic_Program.ipynb +0 -0
  219. {spacecore-0.3.1 → spacecore-0.3.2}/tutorials/8_Linalg_MatrixFree.ipynb +0 -0
  220. {spacecore-0.3.1 → spacecore-0.3.2}/tutorials/9_Linalg_Comparison.ipynb +0 -0
  221. {spacecore-0.3.1 → spacecore-0.3.2}/tutorials/README.md +0 -0
  222. {spacecore-0.3.1 → spacecore-0.3.2}/tutorials/weighted_tikhonov.ipynb +0 -0
@@ -5,7 +5,15 @@ All notable changes to SpaceCore are documented in this file.
5
5
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and the project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
- ## [0.3.1]
8
+ ## [Unreleased]
9
+
10
+ ### Fixed
11
+
12
+ - Corrected the matrix-free adjoint contract so `MatrixFreeLinOp` and its
13
+ adjoint view use user-supplied forward and reverse callables directly, without
14
+ applying matrix-backed Riesz-map adjoint corrections.
15
+
16
+ ## [0.3.1] — 2026-06-10
9
17
 
10
18
  SpaceCore 0.3.1 is a release-candidate stabilization release for the `0.3.x`
11
19
  API. It focuses on documentation consistency, tutorial execution, release
@@ -302,5 +310,6 @@ iterative solvers and structured result types.
302
310
  - The CuPy backend is provided as a preview. Coverage of non-standard
303
311
  operations and sparse handling may evolve in a subsequent release.
304
312
 
313
+ [0.3.1]: https://github.com/Pavlo3P/SpaceCore/releases/tag/v0.3.1
305
314
  [0.3.0]: https://github.com/Pavlo3P/SpaceCore/releases/tag/v0.3.0
306
315
  [0.2.0]: https://github.com/Pavlo3P/SpaceCore/releases/tag/v0.2.0
@@ -0,0 +1,55 @@
1
+ # Contributing
2
+
3
+ SpaceCore is a mathematical software library for typed vector spaces, operators,
4
+ functionals, backend-independent array code, and geometry-aware algorithms. It
5
+ gives mathematical structure to objects; it does not hide problem-specific
6
+ mathematics from contributors.
7
+
8
+ ## Setup
9
+
10
+ Use [docs/dev/contributing/setup.md](docs/dev/contributing/setup.md) for the
11
+ full environment setup. The minimal contributor workflow is:
12
+
13
+ ```bash
14
+ pip install -e ".[dev]"
15
+ pytest --co -q
16
+ pytest tests/ -x -q
17
+ ruff check .
18
+ ```
19
+
20
+ Optional JAX, Torch, and CuPy backend instructions live in the detailed setup
21
+ guide.
22
+
23
+ ## Architecture
24
+
25
+ Read [docs/dev/contributing/architecture.md](docs/dev/contributing/architecture.md)
26
+ before changing core behavior. It explains the backend, context, space, LinOp,
27
+ functional, linalg, batching, and cross-cutting infrastructure layers.
28
+
29
+ ## Prerequisites
30
+
31
+ Read [docs/dev/contributing/prerequisites.md](docs/dev/contributing/prerequisites.md)
32
+ to judge the mathematical background needed for a change. Docstring and test
33
+ fixes may need little background; geometry, adjoint, spectral-method, and linalg
34
+ changes require mathematical review. Mathematical correctness is part of
35
+ contribution review even when tests pass.
36
+
37
+ ## Process
38
+
39
+ Follow [docs/dev/contributing/process.md](docs/dev/contributing/process.md) for
40
+ branch, PR, and review expectations. PRs should include tests, updated docs or
41
+ docstrings when relevant, a changelog entry under `[Unreleased]`, and a
42
+ mathematical invariant statement for changes touching geometry, adjoints,
43
+ spectral methods, fields, or batching.
44
+
45
+ ## Beginner-Safe Issues
46
+
47
+ Start with
48
+ [good-first-issue](https://github.com/Pavlo3P/SpaceCore/labels/good-first-issue).
49
+ That label is reserved for issues with a specific file to change, an example to
50
+ follow, and a concrete done condition.
51
+
52
+ ## Current Project State
53
+
54
+ Check [docs/dev/current.md](docs/dev/current.md) before opening design-heavy
55
+ PRs. Unsettled questions should not be implemented without maintainer agreement.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spacecore
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: Backend-agnostic vector spaces and linear operators.
5
5
  Author: Pavlo Pelikh
6
6
  License-Expression: Apache-2.0
@@ -0,0 +1,38 @@
1
+ # ADR-001: Backend layer
2
+
3
+ ## Status
4
+
5
+ Accepted
6
+
7
+ ## Context
8
+
9
+ SpaceCore supports multiple array ecosystems while exposing one contributor-facing numerical contract. The backend layer must hide routine namespace differences without pretending all libraries have identical sparse, dtype, device, mutation, or control-flow semantics.
10
+
11
+ ## Current design
12
+
13
+ `BackendOps` is the public backend contract. Concrete implementations currently cover NumPy/SciPy by default and optionally JAX, Torch, and CuPy when their packages are importable. A backend has a family name, dense and optional sparse array type predicates, dtype normalization, dense Array API style operations through `xp`, sparse conversion, control-flow primitives, vectorization, indexing mutation, and linear algebra helpers.
14
+
15
+ Backend detection is conservative. Context inference first uses `.ctx` on SpaceCore objects and then tests registered backend array predicates. Optional backend classes are registered only if import succeeds, and unknown names raise a typed backend error.
16
+
17
+ ## Decision
18
+
19
+ SpaceCore code should call `BackendOps` methods for portable behavior. Direct `ops.xp` or backend-specific handles are escape hatches, not the stable SpaceCore API. Behavior that depends on mathematical spaces, validation, conversion, batching, adjoints, or geometry belongs in SpaceCore. Backend libraries own raw array semantics such as broadcasting, device placement, autograd, memory layout, and low-level dtype promotion.
20
+
21
+ ## Rationale
22
+
23
+ One explicit contract keeps spaces, LinOps, functionals, and solvers backend-agnostic while still allowing each backend to implement sparse formats, tracing, and mutation idioms correctly.
24
+
25
+ ## Alternatives considered
26
+
27
+ Using array libraries directly throughout the code was rejected because it spreads backend conditionals across mathematical code. Requiring all optional backends at install time was rejected because NumPy/SciPy should remain the baseline dependency set. Treating `xp` as the public contract was rejected because sparse, loops, dtype sanitization, and indexing semantics are not fully covered by the Array API.
28
+
29
+ ## Consequences
30
+
31
+ New backend behavior must be added through `BackendOps` or an explicit backend-specific escape hatch. Tests for new backend methods must cover unavailable optional dependencies and avoid silently importing packages that are not installed. See [ADR-002](002_context_and_conversion.md) for context ownership and [ADR-011](011_linalg_contract.md) for solver delegation.
32
+
33
+ ## Contributor invariants
34
+
35
+ - `BackendOps` methods expose stable SpaceCore behavior without silently depending on unavailable optional packages.
36
+ - Optional backend imports must fail closed: unavailable packages should omit that backend, not break NumPy usage.
37
+ - Portable core code should prefer `ops.method(...)` over `ops.xp.method(...)`.
38
+ - Backend detection must remain conservative and reject ambiguous array ownership.
@@ -0,0 +1,40 @@
1
+ # ADR-002: Context and conversion
2
+
3
+ ## Status
4
+
5
+ Accepted
6
+
7
+ ## Context
8
+
9
+ Spaces, operators, and functionals need a common execution context for backend operations, default dtype, and validation behavior. Conversion must be predictable because hidden array movement or casting can change performance, autograd behavior, and numerical results.
10
+
11
+ ## Current design
12
+
13
+ `Context` stores `ops`, `dtype`, and `enable_checks`. It does not own arrays, devices, sparse storage, or gradient state. Context normalization accepts a concrete `Context`, backend family/name, or `None`. Concrete contexts are copied with sanitized dtype. Backend names create a new context through the registered backend. `None` resolves to the process default.
14
+
15
+ `Context.asarray` and `Context.assparse` convert explicit values into the context. `Context.convert` dispatches dense and sparse inputs through those constructors. `ContextBound.convert(new_ctx)` rebuilds a context-bound object in a target context through `_convert`; it returns `self` when the normalized context is equal. Constructors resolve explicit context first, then compatible inferred contexts from operands, then the default context.
16
+
17
+ The current design has no separate conversion policy object. Conversion policy lives in explicit `convert(...)`, `Context.asarray(...)`, `Context.assparse(...)`, and constructor resolution.
18
+
19
+ ## Decision
20
+
21
+ Conversion is explicit and target-context driven. User values passed to operations such as `apply`, `add`, or `inner` are validated when checks are enabled but are not silently converted. Object conversion rebuilds spaces, geometries, stored matrices, and algebraic operands in the requested context; matrix-free callables are preserved and must already be valid for the target backend.
22
+
23
+ ## Rationale
24
+
25
+ Explicit conversion avoids hidden device transfers, sparse format changes, dtype casts, and backend-specific callable failures. Keeping context small also makes equality and algebra compatibility checks straightforward.
26
+
27
+ ## Alternatives considered
28
+
29
+ Implicitly converting every operation input was rejected because it hides expensive transfers and can mask caller bugs. A separate conversion policy hierarchy was rejected for now because current behavior is simpler and has only one public mode: explicit target conversion.
30
+
31
+ ## Consequences
32
+
33
+ New context-bound classes must implement `_convert` when they store context-owned data. Conversions may fail when the target backend lacks sparse support, dtype support, or callable compatibility. Dtype defaults are representation defaults, not mathematical fields; see [ADR-015](015_dtype_default_vs_scalar_field.md).
34
+
35
+ ## Contributor invariants
36
+
37
+ - Context conversion must be explicit and predictable.
38
+ - `Context` owns backend, dtype default, and validation flag only.
39
+ - Constructors may convert their owned storage, but runtime operation arguments must not be silently converted.
40
+ - Conversion must preserve mathematical structure while rebuilding backend-owned representation.
@@ -0,0 +1,38 @@
1
+ # ADR-003: Space hierarchy
2
+
3
+ ## Status
4
+
5
+ Accepted
6
+
7
+ ## Context
8
+
9
+ SpaceCore represents mathematical spaces separately from raw array containers. Contributors need to know which layer owns linear operations, coordinates, membership, and element construction.
10
+
11
+ ## Current design
12
+
13
+ `Space` owns context and membership checks. `VectorSpace` adds abstract `zeros`, `add`, `scale`, and `axpy`. `CoordinateSpace` adds finite coordinate `shape`, `size`, `flatten`, `unflatten`, batch flattening, and `stacked`. `InnerProductSpace`, `StarSpace`, `JordanAlgebraSpace`, and `EuclideanJordanAlgebraSpace` add optional mathematical capabilities.
14
+
15
+ Concrete dense coordinate spaces construct zeros through their context, validate backend/shape/dtype, and flatten to a dense coordinate vector. `DenseVectorSpace` specializes one-dimensional dense coordinates. `ProductSpace` is a coordinate space whose elements are structured component containers, tuple by default or a registered pytree structure. `StackedSpace` represents a fixed leading-axis stack as one mathematical element.
16
+
17
+ ## Decision
18
+
19
+ A space defines valid elements and operations on those elements; it is not just an array shape. Coordinate representation is exposed through `flatten`/`unflatten` for operators and linalg, while mathematical operations use `zeros`, `add`, `scale`, and capability methods.
20
+
21
+ ## Rationale
22
+
23
+ Separating mathematical spaces from coordinate arrays lets product and pytree-structured elements participate in the same operator and solver contracts as dense vectors.
24
+
25
+ ## Alternatives considered
26
+
27
+ Using only array shapes was rejected because it cannot represent product structure, custom geometry, Hermitian membership, or future tree spaces. Making all spaces dense arrays was rejected because product and structured elements need non-array containers.
28
+
29
+ ## Consequences
30
+
31
+ New spaces must decide which capabilities they implement and must provide coordinate flattening if they are `CoordinateSpace`s. LinOps and solvers should depend on space methods, not on raw container assumptions. See [ADR-005](005_space_subclasses_and_capabilities.md) and [ADR-006](006_current_batching_model.md).
32
+
33
+ ## Contributor invariants
34
+
35
+ - `Space` membership is the source of truth for valid elements.
36
+ - `VectorSpace` linear operations must preserve membership.
37
+ - `CoordinateSpace.flatten` and `unflatten` must be inverse coordinate representations for one element.
38
+ - Product element structure must be handled through its `ProductStructure`, not by assuming tuples everywhere.
@@ -0,0 +1,38 @@
1
+ # ADR-004: Inner product and geometry
2
+
3
+ ## Status
4
+
5
+ Accepted
6
+
7
+ ## Context
8
+
9
+ Adjoints, gradients, norms, and solver correctness depend on the chosen inner product. Treating geometry as a hidden implementation detail would make non-Euclidean spaces incorrect.
10
+
11
+ ## Current design
12
+
13
+ `InnerProduct` is a separate geometry object with `inner`, `riesz`, `riesz_inverse`, `convert`, `validate_for`, and `is_euclidean`. `InnerProductSpace` delegates `inner`, `norm`, and Riesz maps to this geometry. Built-in geometries include Euclidean coordinate geometry and weighted diagonal geometry.
14
+
15
+ Spaces own a geometry instance. The same geometry type can be reused by different coordinate spaces and converted with the space context. Metric adjoints use Riesz maps, and linalg uses space inner products and norms. Euclidean spaces use identity Riesz maps; weighted spaces use multiplication/division by validated positive finite weights.
16
+
17
+ ## Decision
18
+
19
+ Geometry remains a separate object instead of only methods on `Space`. It is part of the mathematical contract of a space and must be validated, converted, and preserved by spaces and operators.
20
+
21
+ ## Rationale
22
+
23
+ A separate geometry object avoids duplicating inner-product implementations across space subclasses and makes metric changes explicit. It also lets matrix-backed operators implement the correct adjoint formula without guessing from concrete space types.
24
+
25
+ ## Alternatives considered
26
+
27
+ Putting all inner-product code directly on each space was rejected because it couples geometry to storage classes and makes reuse harder. Treating non-Euclidean geometry as a solver option was rejected because adjoints and gradients would already be wrong before the solver sees them.
28
+
29
+ ## Consequences
30
+
31
+ New geometries must provide Riesz maps if they are used with matrix-backed operators. Riesz maps should broadcast over leading batch axes for efficient batched adjoints. See [ADR-009](009_metric_adjoint.md) for adjoint details and [ADR-011](011_linalg_contract.md) for solver assumptions.
32
+
33
+ ## Contributor invariants
34
+
35
+ - Geometry is part of mathematical correctness, not just implementation detail.
36
+ - `InnerProduct.validate_for(space)` must reject incompatible geometry/storage pairs.
37
+ - Non-Euclidean geometry used by coordinate-backed LinOps must provide usable Riesz maps.
38
+ - `norm(x)` must be induced by `inner(x, x)` and return a real magnitude.
@@ -0,0 +1,38 @@
1
+ # ADR-005: Space subclasses and capabilities
2
+
3
+ ## Status
4
+
5
+ Accepted
6
+
7
+ ## Context
8
+
9
+ Concrete spaces expose different mathematical operations. Contributors need a stable way to reason about which operations are present and how conversion affects them.
10
+
11
+ ## Current design
12
+
13
+ Public concrete spaces include `DenseCoordinateSpace`, `DenseVectorSpace`, `ElementwiseJordanSpace`, `EuclideanElementwiseJordanSpace`, `HermitianSpace`, `ProductSpace`, and `StackedSpace`. Capability classes include `InnerProductSpace`, `StarSpace`, `JordanAlgebraSpace`, and `EuclideanJordanAlgebraSpace`.
14
+
15
+ `DenseCoordinateSpace` has inner-product geometry but no star operation. `DenseVectorSpace` adds elementwise conjugation. `ElementwiseJordanSpace` adds elementwise Jordan and spectral operations; when context and geometry are real Euclidean, construction dispatches to `EuclideanElementwiseJordanSpace`. `HermitianSpace` represents dense Hermitian matrices with Frobenius geometry and spectral calculus. `ProductSpace` and `StackedSpace` dynamically choose internal subclasses that preserve only capabilities shared by their components or base.
16
+
17
+ ## Decision
18
+
19
+ Capabilities are represented by Python class membership, not by flags. Geometry belongs to inner-product-capable spaces. Product and stacked conversion rebuilds converted components and then recomputes the capability-specific class.
20
+
21
+ ## Rationale
22
+
23
+ Class-based capabilities make missing operations fail naturally and keep capability composition explicit. Recomputing on conversion prevents stale capability promises after dtype or geometry changes.
24
+
25
+ ## Alternatives considered
26
+
27
+ Single concrete classes with runtime feature flags were rejected because they make unsupported operations harder to detect. Forcing every dense space to expose star or Jordan operations was rejected because those operations are not always mathematically valid.
28
+
29
+ ## Consequences
30
+
31
+ Code should test capabilities with `isinstance`, not with name checks or ad hoc attributes. New concrete spaces must be explicit about which capabilities they provide. Spectral operations belong only to Jordan-capable spaces; see [ADR-012](012_jordan_spectrum.md).
32
+
33
+ ## Contributor invariants
34
+
35
+ - Public capabilities must match actual implemented methods.
36
+ - `convert()` must recompute product and stacked capabilities in the target context.
37
+ - Geometry conversion must convert stored geometry arrays such as weights.
38
+ - Missing capabilities must remain absent rather than becoming no-op placeholders.
@@ -0,0 +1,38 @@
1
+ # ADR-006: Current batching model
2
+
3
+ ## Status
4
+
5
+ Accepted
6
+
7
+ ## Context
8
+
9
+ Batching is current SpaceCore behavior. It must be documented before 0.4.0 tests are generated so contributors do not accidentally remove or misstate it.
10
+
11
+ ## Current design
12
+
13
+ A space describes one mathematical element. Batched evaluation is represented by leading axes on values, not by changing `domain` or `codomain`. `_batching` contains shared helpers for batched membership checks and batched inner products. `checked_method(..., in_batched=True, out_batched=True)` validates trailing element shape while allowing leading dimensions.
14
+
15
+ `LinOp.vapply(xs)` applies `apply` over a leading batch axis. `LinOp.rvapply(ys)` applies the adjoint over a leading batch axis. The base implementation uses `ops.vmap`; dense, sparse, diagonal, algebraic, and product-structured operators provide specialized batched paths where useful. Functionals similarly expose `vvalue` and selected `vgrad` methods. `StackedSpace` is separate: it makes a fixed stack part of one element rather than a transient evaluation batch.
16
+
17
+ ## Decision
18
+
19
+ Batching stays as explicit vectorized methods (`vapply`, `rvapply`, `vvalue`, `vgrad`) and space batch helpers. `apply` and `rapply` remain single-element methods.
20
+
21
+ ## Rationale
22
+
23
+ This preserves the mathematical meaning of a space while supporting efficient backend vectorization and specialized dense/product fast paths.
24
+
25
+ ## Alternatives considered
26
+
27
+ Removing batching was rejected because current operators, tests, and materialization paths rely on it. Treating every leading axis as implicit batching in `apply` was rejected because it blurs single-element membership and makes product/pytree structure ambiguous.
28
+
29
+ ## Consequences
30
+
31
+ 0.4.0 tests must cover leading-axis validation, product-structured batches, backend fallback loops, native backend vectorization, metric `rvapply`, and consistency between single and batched methods. Known limitations include a leading-axis-only convention, backend-dependent performance, and fallback warnings where NumPy-style loops are used.
32
+
33
+ ## Contributor invariants
34
+
35
+ - `apply` and `rapply` are single-element contracts.
36
+ - `vapply` and `rvapply` own batched LinOp behavior.
37
+ - Batched validation must allow leading axes but still enforce trailing element shape, backend, dtype, and product component structure.
38
+ - Backend context conversion must preserve batched behavior and not bypass metric adjoints.
@@ -0,0 +1,39 @@
1
+ # ADR-007: LinOp contract
2
+
3
+ ## Status
4
+
5
+ Accepted
6
+
7
+ ## Context
8
+
9
+ Linear operators are the central abstraction connecting spaces, geometry, batching, and linalg.
10
+
11
+ ## Current design
12
+
13
+ `LinOp` owns a domain space, codomain space, and context. Construction resolves one context and converts both endpoint spaces to it. Subclasses implement `apply(x)` and `rapply(y)`. `rapply` is the Hermitian adjoint with respect to the declared space geometries. `.H` returns a cached adjoint view. Algebraic operations build lazy sums, scalar multiples, differences, and compositions. `to_dense` and `to_matrix` are explicit materialization helpers for small problems and tests.
14
+
15
+ Validation uses `checked_method` and endpoint membership checks when `ctx.enable_checks` is true. Conversion rebuilds spaces and owned data or operands in a target context.
16
+
17
+ ## Decision
18
+
19
+ The LinOp contract is mathematical: `A : X -> Y` with `apply : X -> Y` and `rapply : Y -> X` satisfying the inner-product adjoint identity. Algebra must preserve domain/codomain compatibility and context compatibility.
20
+
21
+ ## Rationale
22
+
23
+ Solvers and functionals can rely on `LinOp` without knowing whether the operator is dense, sparse, matrix-free, or structured.
24
+
25
+ ## Alternatives considered
26
+
27
+ A matrix-only operator API was rejected because matrix-free and structured operators are first-class. Returning raw transpose matrices for adjoints was rejected because non-Euclidean spaces require metric adjoints.
28
+
29
+ ## Consequences
30
+
31
+ New LinOp subclasses must implement true `rapply`, batching when they can improve on `ops.vmap`, conversion, and pytree flattening where applicable. See [ADR-009](009_metric_adjoint.md) for metric adjoints and [ADR-008](008_linop_subclasses.md) for implemented families.
32
+
33
+ ## Contributor invariants
34
+
35
+ - Domain and codomain spaces are part of operator identity.
36
+ - `rapply` must be the geometry-aware adjoint, not merely a coordinate transpose.
37
+ - `.H.apply(y)` must be equivalent to `rapply(y)`.
38
+ - Algebraic operators must preserve compatible contexts and spaces.
39
+ - Validation must check inputs and outputs against the declared endpoint spaces when enabled.
@@ -0,0 +1,38 @@
1
+ # ADR-008: LinOp subclasses
2
+
3
+ ## Status
4
+
5
+ Accepted
6
+
7
+ ## Context
8
+
9
+ SpaceCore implements several LinOp storage and composition families. Contributors need to know which subclasses own coordinates and which rely on user callables.
10
+
11
+ ## Current design
12
+
13
+ Matrix-backed operators include `DenseLinOp`, `SparseLinOp`, and `DiagonalLinOp`. They own dense tensors, sparse coordinate matrices, or diagonal arrays and implement coordinate forward actions plus metric-aware adjoints. `DenseLinOp` stores shape `cod.shape + dom.shape`; `SparseLinOp` stores a 2D sparse matrix and is limited to coordinate spaces; `DiagonalLinOp` stores one diagonal element per space coordinate.
14
+
15
+ Matrix-free operators include `MatrixFreeLinOp`, which trusts user-supplied callables. `IdentityLinOp` and `ZeroLinOp` are structural operators with no matrix storage. Lazy algebraic operators include `ComposedLinOp`, `SumLinOp`, and `ScaledLinOp`. Product-structured operators include `ProductLinOp`, `BlockDiagonalLinOp`, `StackedLinOp`, and `SumToSingleLinOp`.
16
+
17
+ ## Decision
18
+
19
+ Coordinate-backed operators own coordinate representations and may optimize dense, sparse, weighted, flat, and batched paths. Matrix-free operators trust supplied callables and only validate membership. Lazy and product operators delegate to their operands and preserve structure.
20
+
21
+ ## Rationale
22
+
23
+ This keeps high-performance coordinate cases efficient while preserving matrix-free and structured composition as first-class APIs.
24
+
25
+ ## Alternatives considered
26
+
27
+ Forcing every operator to expose a stored matrix was rejected because it breaks matrix-free and lazy use cases. Eagerly simplifying all algebra into dense matrices was rejected because it destroys sparsity, structure, and backend tracing.
28
+
29
+ ## Consequences
30
+
31
+ New structured operators should avoid materializing unless explicitly requested. Product operators must preserve `ProductSpace` structures, including pytree structures. Coordinate-backed operators must implement conversion for stored arrays. Matrix-free conversion cannot rewrite backend-specific Python callables.
32
+
33
+ ## Contributor invariants
34
+
35
+ - Matrix-backed subclasses own and validate their coordinate storage shape.
36
+ - Matrix-free `apply` and `rapply` callables are trusted as the mathematical contract.
37
+ - Lazy algebra must not reorder or densify operands unless a documented factory rule says so.
38
+ - Product operators must preserve domain and codomain product structures in `apply`, `rapply`, `vapply`, and `rvapply`.
@@ -0,0 +1,44 @@
1
+ # ADR-009: Metric adjoint
2
+
3
+ ## Status
4
+
5
+ Accepted
6
+
7
+ ## Context
8
+
9
+ Non-Euclidean inner products make the Euclidean coordinate adjoint insufficient. This ADR records the release-gating rule for correct adjoints.
10
+
11
+ ## Current design
12
+
13
+ Spaces expose Riesz maps through their `InnerProduct` geometry. Matrix-backed `DenseLinOp`, `SparseLinOp`, and `DiagonalLinOp` first compute the Euclidean coordinate adjoint and then adapt it to the declared domain and codomain geometry. The formula is:
14
+
15
+ ```text
16
+ A^sharp = R_X^{-1} A^dagger R_Y
17
+ ```
18
+
19
+ where `A : X -> Y`, `A^dagger` is the Euclidean conjugate coordinate adjoint, and `A^sharp` is the metric adjoint. Fast paths exist for Euclidean and weighted diagonal geometries. General metric paths require usable Riesz maps. `InnerProduct.validate_for(space)` validates geometry storage such as weighted metrics.
20
+
21
+ `MatrixFreeLinOp` is different: its direct `rapply` callable is already the metric adjoint and must not be Riesz-wrapped. `MatrixFreeLinOp.from_coordinate_adjoint(...)` exists for the case where the user has a Euclidean coordinate adjoint and wants SpaceCore to wrap it.
22
+
23
+ ## Decision
24
+
25
+ Matrix-backed operators are responsible for converting coordinate adjoints into metric adjoints. Matrix-free direct `rapply` is a true adjoint by contract. Type guards alone are not a correctness fix because the issue is geometry, not only class identity.
26
+
27
+ ## Rationale
28
+
29
+ The adjoint identity must hold for the declared spaces. Riesz maps are the architectural boundary between coordinate storage and mathematical geometry.
30
+
31
+ ## Alternatives considered
32
+
33
+ Using only type guards for Euclidean concrete spaces was rejected because custom spaces and weighted geometries need the same mathematical rule. Always Riesz-wrapping matrix-free `rapply` was rejected because it would double-wrap correct true adjoints and break user-supplied non-coordinate implementations.
34
+
35
+ ## Consequences
36
+
37
+ Coordinate-backed operators must reject non-Euclidean spaces without Riesz maps. Matrix-free docs and tests must distinguish true adjoints from coordinate adjoints. Batched metric adjoints should use batched Riesz maps when possible and may fall back to vectorized scalar adjoints with a warning. See [ADR-004](004_inner_product_and_geometry.md) and [ADR-007](007_linop_contract.md).
38
+
39
+ ## Contributor invariants
40
+
41
+ - Matrix-backed adjoints use `R_X^{-1} A^dagger R_Y`.
42
+ - `MatrixFreeLinOp(..., rapply=...)` receives a true metric adjoint and must not be automatically Riesz-wrapped.
43
+ - `from_coordinate_adjoint` is the explicit API for wrapping a Euclidean coordinate adjoint.
44
+ - `validate_for` and Riesz-map availability must be checked before accepting non-Euclidean coordinate-backed operators.
@@ -0,0 +1,36 @@
1
+ # ADR-010: Functional contract
2
+
3
+ ## Status
4
+
5
+ Accepted
6
+
7
+ ## Context
8
+
9
+ Functionals are scalar-valued maps on spaces. They share context and validation mechanics with LinOps but have different mathematical contracts.
10
+
11
+ ## Current design
12
+
13
+ `Functional` owns one domain space and a context. Subclasses implement `value(x)`. `vvalue(xs)` evaluates over a leading batch axis through backend `vmap` unless overridden. `LinearFunctional` adds a Riesz-gradient contract through `representer`, `grad`, and `vgrad`. `InnerProductFunctional` stores a representer and evaluates `<c, x>`. `MatrixFreeLinearFunctional` trusts user evaluation callables and has no stored representer. `QuadraticForm` defines optional `grad`, `vgrad`, and `hess_apply`; `LinOpQuadraticForm` stores a Hermitian operator, optional linear term, and scalar offset. Pull-backs are built by composing with a LinOp and have specializations for inner-product and quadratic functionals.
14
+
15
+ ## Decision
16
+
17
+ A functional is not a LinOp with a one-dimensional codomain. It owns a domain and scalar-valued evaluation, and gradients are space elements with respect to the domain geometry when implemented.
18
+
19
+ ## Rationale
20
+
21
+ Scalar-valued objectives need gradients, Hessian actions, and pull-backs that are clearer as a separate abstraction than as degenerate linear operators.
22
+
23
+ ## Alternatives considered
24
+
25
+ Representing all functionals as LinOps into a scalar space was rejected because it obscures Riesz gradients and quadratic objective structure. Requiring every functional to expose a gradient was rejected because matrix-free scalar maps may only support value evaluation.
26
+
27
+ ## Consequences
28
+
29
+ New functionals must validate domain inputs and scalar output shape when checks are enabled. Gradients must be Riesz gradients satisfying the domain inner-product convention. Pull-back specializations may use `A.H` and therefore depend on [ADR-009](009_metric_adjoint.md).
30
+
31
+ ## Contributor invariants
32
+
33
+ - `value` returns a scalar-like backend value, not an element of a codomain space.
34
+ - `grad` returns a domain element when implemented.
35
+ - Matrix-free functionals do not imply a stored representer.
36
+ - Functional composition requires `A.codomain == F.domain`.
@@ -0,0 +1,38 @@
1
+ # ADR-011: Linalg contract
2
+
3
+ ## Status
4
+
5
+ Accepted
6
+
7
+ ## Context
8
+
9
+ SpaceCore linalg routines must work for dense, sparse, matrix-free, structured, Euclidean, and non-Euclidean operators without materializing matrices by default.
10
+
11
+ ## Current design
12
+
13
+ Implemented iterative routines include `cg`, `lsqr`, `power_iteration`, `lanczos_smallest`, and `expm_multiply`. They operate on `LinOp` or, for power iteration, a quadratic-form Hessian action. They use `LinOp.apply`, `.H.apply`, space `add`, `scale`, `inner`, and `norm`. Backend loops, conditionals, indexing, eigendecompositions of small projected matrices, and array constructors are delegated to `BackendOps`.
14
+
15
+ Correctness assumptions are explicit. CG requires square Hermitian positive-definite operators in the domain geometry. LSQR uses the metric adjoint for normal-equation residuals. Power iteration, Lanczos, and exponential multiply require self-adjoint actions; known non-Hermitian structure is rejected, unknown matrix-free structure is trusted.
16
+
17
+ ## Decision
18
+
19
+ Linalg routines are operator-driven and geometry-aware. They must not require dense materialization of the input operator and must rely on backend primitives for loop and array behavior.
20
+
21
+ ## Rationale
22
+
23
+ This lets the same algorithms run on dense, sparse, lazy, product, and matrix-free operators while preserving non-Euclidean correctness.
24
+
25
+ ## Alternatives considered
26
+
27
+ Delegating all linalg to backend dense solvers was rejected because it would lose structure and matrix-free support. Reimplementing backend control flow ad hoc inside each solver was rejected because JAX/Torch/NumPy need different loop semantics.
28
+
29
+ ## Consequences
30
+
31
+ New solvers must state their mathematical assumptions in terms of spaces and geometry. They must use `A.H` for adjoint products and backend loop primitives for JIT-compatible backends. Solver workspaces should be driven by operand/operator dtype; see [ADR-015](015_dtype_default_vs_scalar_field.md).
32
+
33
+ ## Contributor invariants
34
+
35
+ - Solvers use space operations for vector arithmetic and geometry.
36
+ - Solvers do not materialize `A` unless the routine explicitly documents that choice.
37
+ - Hermitian, positive-definite, and residual assumptions are with respect to the declared space inner products.
38
+ - Backend-specific loop, indexing, and small dense linalg behavior goes through `BackendOps`.
@@ -0,0 +1,36 @@
1
+ # ADR-012: Jordan spectrum
2
+
3
+ ## Status
4
+
5
+ Accepted
6
+
7
+ ## Context
8
+
9
+ Spectral operations are mathematical capabilities of Jordan algebra spaces, not generic dense-array utilities.
10
+
11
+ ## Current design
12
+
13
+ `JordanAlgebraSpace` exposes `jordan`, `spectrum`, `spectral_decompose`, `from_spectrum`, and `spectral_apply`. Elementwise Jordan spaces return coordinates as their spectrum with `frame=None`. `HermitianSpace` uses backend `eigh` internally but exposes the result through the Jordan spectral API. Product Jordan spaces concatenate component spectra and return `ProductSpectralDecomposition` for structured component spectral data. Stacked Jordan spaces apply base spectral operations over the leading stack.
14
+
15
+ ## Decision
16
+
17
+ Public spectral behavior belongs to space capabilities (`spectrum` and `spectral_decompose`), not to callers reaching directly for backend `eigh` except inside the implementing space.
18
+
19
+ ## Rationale
20
+
21
+ Different Jordan spaces have different spectral meaning. A Hermitian matrix spectrum, an elementwise spectrum, and a product spectrum have different frames and reconstruction rules.
22
+
23
+ ## Alternatives considered
24
+
25
+ Exposing `eigh` as the universal space-level operation was rejected because it only applies to Hermitian matrix coordinates. Returning raw flattened eigenpairs for products was rejected because it loses component frames and structure.
26
+
27
+ ## Consequences
28
+
29
+ Only Jordan-capable spaces should expose spectral operations. Product spectral decompositions must remain structured objects. New spectral spaces must define reconstruction through `from_spectrum`. See [ADR-005](005_space_subclasses_and_capabilities.md).
30
+
31
+ ## Contributor invariants
32
+
33
+ - Do not call backend `eigh` as a generic replacement for `space.spectrum`.
34
+ - `spectral_decompose` must return enough data for `from_spectrum` to reconstruct an element.
35
+ - Product spectral data must preserve component boundaries.
36
+ - Capability dispatch controls whether spectral methods are present.
@@ -0,0 +1,36 @@
1
+ # ADR-013: Tree-structured spaces
2
+
3
+ ## Status
4
+
5
+ Proposed
6
+
7
+ ## Context
8
+
9
+ Current product spaces support tuple elements and registered pytree structures. Near-term design work should generalize this toward variable trees without losing SpaceCore-specific mathematical contracts.
10
+
11
+ ## Current design
12
+
13
+ `ProductSpace` is currently the structured space implementation. It can use `TupleStructure` or `PytreeStructure`. `PytreeStructure` delegates flattening and unflattening to JAX tree utilities and requires registered pytree/dataclass structures. Product components remain ordered coordinate spaces and capabilities are computed from shared component capabilities.
14
+
15
+ ## Decision
16
+
17
+ The planned direction is to model variables as pytrees and treat `ProductSpace` as a future special case of a more general `TreeSpace`. Generic tree traversal and structural definitions should be delegated to a tree library such as `optree`; SpaceCore should keep ownership of spaces, geometry, validation, context conversion, batching, and mathematical capabilities.
18
+
19
+ ## Rationale
20
+
21
+ Tree-shaped models are common in optimization and ML, but tree traversal is not SpaceCore's mathematical differentiator. Delegating generic tree mechanics avoids maintaining a parallel tree library.
22
+
23
+ ## Alternatives considered
24
+
25
+ Keeping only tuple product spaces was rejected as too limiting for real model variables. Reimplementing full pytree semantics inside SpaceCore was rejected because mature tree libraries already solve traversal, registration, and structure comparison.
26
+
27
+ ## Consequences
28
+
29
+ Do not treat current `ProductSpace` as the final tree abstraction. Future work must specify how tree leaves map to spaces, how context conversion rebuilds leaves, how batching interacts with tree leaves, and how capabilities compose across trees.
30
+
31
+ ## Contributor invariants
32
+
33
+ - This ADR is a planned direction, not an implementation claim.
34
+ - Generic tree flattening should be delegated; SpaceCore-specific math must stay in SpaceCore.
35
+ - Product-space behavior must remain stable until a `TreeSpace` decision supersedes it.
36
+ - Future tree spaces must preserve validation, geometry, batching, and conversion contracts from [ADR-003](003_space_hierarchy.md) and [ADR-006](006_current_batching_model.md).