hndl 0.1.0__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 (244) hide show
  1. hndl-0.1.0/CONTRIBUTING.md +70 -0
  2. hndl-0.1.0/IMPLEMENTATION.md +204 -0
  3. hndl-0.1.0/LICENSE +21 -0
  4. hndl-0.1.0/MANIFEST.in +4 -0
  5. hndl-0.1.0/PKG-INFO +461 -0
  6. hndl-0.1.0/README.md +422 -0
  7. hndl-0.1.0/SPEC.md +793 -0
  8. hndl-0.1.0/docs/ADDING_OPERATORS.md +135 -0
  9. hndl-0.1.0/docs/networks.md +601 -0
  10. hndl-0.1.0/docs/operators/adaptive_avg_pool.md +136 -0
  11. hndl-0.1.0/docs/operators/adaptive_norm.md +91 -0
  12. hndl-0.1.0/docs/operators/add.md +53 -0
  13. hndl-0.1.0/docs/operators/attention.md +136 -0
  14. hndl-0.1.0/docs/operators/avg_pool.md +111 -0
  15. hndl-0.1.0/docs/operators/batch_norm.md +148 -0
  16. hndl-0.1.0/docs/operators/clamp.md +106 -0
  17. hndl-0.1.0/docs/operators/cls_token.md +112 -0
  18. hndl-0.1.0/docs/operators/concat.md +74 -0
  19. hndl-0.1.0/docs/operators/conv.md +127 -0
  20. hndl-0.1.0/docs/operators/conv1d.md +128 -0
  21. hndl-0.1.0/docs/operators/cross_attention.md +121 -0
  22. hndl-0.1.0/docs/operators/deconv.md +86 -0
  23. hndl-0.1.0/docs/operators/dropout.md +133 -0
  24. hndl-0.1.0/docs/operators/elu.md +105 -0
  25. hndl-0.1.0/docs/operators/embedding.md +117 -0
  26. hndl-0.1.0/docs/operators/feed_forward.md +138 -0
  27. hndl-0.1.0/docs/operators/flatten.md +47 -0
  28. hndl-0.1.0/docs/operators/gather_token.md +121 -0
  29. hndl-0.1.0/docs/operators/gelu.md +115 -0
  30. hndl-0.1.0/docs/operators/global_avg_pool.md +110 -0
  31. hndl-0.1.0/docs/operators/group_norm.md +54 -0
  32. hndl-0.1.0/docs/operators/hardswish.md +105 -0
  33. hndl-0.1.0/docs/operators/hopfield.md +169 -0
  34. hndl-0.1.0/docs/operators/identity.md +108 -0
  35. hndl-0.1.0/docs/operators/index.md +123 -0
  36. hndl-0.1.0/docs/operators/instance_norm.md +120 -0
  37. hndl-0.1.0/docs/operators/layer_norm.md +114 -0
  38. hndl-0.1.0/docs/operators/leaky_relu.md +46 -0
  39. hndl-0.1.0/docs/operators/linear.md +93 -0
  40. hndl-0.1.0/docs/operators/max_pool.md +107 -0
  41. hndl-0.1.0/docs/operators/mean.md +134 -0
  42. hndl-0.1.0/docs/operators/mish.md +105 -0
  43. hndl-0.1.0/docs/operators/moe.md +122 -0
  44. hndl-0.1.0/docs/operators/mul.md +97 -0
  45. hndl-0.1.0/docs/operators/pad.md +140 -0
  46. hndl-0.1.0/docs/operators/patch_embed.md +120 -0
  47. hndl-0.1.0/docs/operators/permute.md +126 -0
  48. hndl-0.1.0/docs/operators/pixel_shuffle.md +107 -0
  49. hndl-0.1.0/docs/operators/pool_tokens.md +139 -0
  50. hndl-0.1.0/docs/operators/pos_embed.md +90 -0
  51. hndl-0.1.0/docs/operators/pretrained.md +90 -0
  52. hndl-0.1.0/docs/operators/quick_gelu.md +103 -0
  53. hndl-0.1.0/docs/operators/relu.md +46 -0
  54. hndl-0.1.0/docs/operators/resblock.md +127 -0
  55. hndl-0.1.0/docs/operators/reshape.md +117 -0
  56. hndl-0.1.0/docs/operators/rms_norm.md +118 -0
  57. hndl-0.1.0/docs/operators/scale.md +104 -0
  58. hndl-0.1.0/docs/operators/sigmoid.md +100 -0
  59. hndl-0.1.0/docs/operators/silu.md +102 -0
  60. hndl-0.1.0/docs/operators/softmax.md +111 -0
  61. hndl-0.1.0/docs/operators/softplus.md +108 -0
  62. hndl-0.1.0/docs/operators/split.md +80 -0
  63. hndl-0.1.0/docs/operators/sub.md +98 -0
  64. hndl-0.1.0/docs/operators/sum.md +134 -0
  65. hndl-0.1.0/docs/operators/swiglu.md +111 -0
  66. hndl-0.1.0/docs/operators/tanh.md +46 -0
  67. hndl-0.1.0/docs/operators/transformer_block.md +167 -0
  68. hndl-0.1.0/docs/operators/transpose.md +107 -0
  69. hndl-0.1.0/docs/operators/upsample.md +135 -0
  70. hndl-0.1.0/docs/pretrained.md +97 -0
  71. hndl-0.1.0/examples/adaptive_normalization.py +58 -0
  72. hndl-0.1.0/examples/networks/README.md +8 -0
  73. hndl-0.1.0/examples/networks/autoencoder.hndl +18 -0
  74. hndl-0.1.0/examples/networks/autoencoder.json +8 -0
  75. hndl-0.1.0/examples/networks/dcgan_discriminator.hndl +25 -0
  76. hndl-0.1.0/examples/networks/dcgan_discriminator.json +8 -0
  77. hndl-0.1.0/examples/networks/dcgan_generator.hndl +26 -0
  78. hndl-0.1.0/examples/networks/dcgan_generator.json +8 -0
  79. hndl-0.1.0/examples/networks/gpt_tiny.hndl +17 -0
  80. hndl-0.1.0/examples/networks/gpt_tiny.json +9 -0
  81. hndl-0.1.0/examples/networks/hopfield_classifier.hndl +16 -0
  82. hndl-0.1.0/examples/networks/hopfield_classifier.json +8 -0
  83. hndl-0.1.0/examples/networks/lenet5.hndl +22 -0
  84. hndl-0.1.0/examples/networks/lenet5.json +8 -0
  85. hndl-0.1.0/examples/networks/mlp.hndl +8 -0
  86. hndl-0.1.0/examples/networks/mlp.json +8 -0
  87. hndl-0.1.0/examples/networks/moe_transformer.hndl +29 -0
  88. hndl-0.1.0/examples/networks/moe_transformer.json +9 -0
  89. hndl-0.1.0/examples/networks/resnet18.hndl +31 -0
  90. hndl-0.1.0/examples/networks/resnet18.json +8 -0
  91. hndl-0.1.0/examples/networks/unet_small.hndl +46 -0
  92. hndl-0.1.0/examples/networks/unet_small.json +8 -0
  93. hndl-0.1.0/examples/networks/vit_tiny.hndl +20 -0
  94. hndl-0.1.0/examples/networks/vit_tiny.json +8 -0
  95. hndl-0.1.0/pyproject.toml +55 -0
  96. hndl-0.1.0/setup.cfg +4 -0
  97. hndl-0.1.0/src/hndl/__init__.py +12 -0
  98. hndl-0.1.0/src/hndl/_parser_worker.py +213 -0
  99. hndl-0.1.0/src/hndl/_version.py +3 -0
  100. hndl-0.1.0/src/hndl/capture.py +238 -0
  101. hndl-0.1.0/src/hndl/config.py +248 -0
  102. hndl-0.1.0/src/hndl/docs.py +198 -0
  103. hndl-0.1.0/src/hndl/errors.py +18 -0
  104. hndl-0.1.0/src/hndl/operator.py +619 -0
  105. hndl-0.1.0/src/hndl/operators/__init__.py +31 -0
  106. hndl-0.1.0/src/hndl/operators/_pooling.py +57 -0
  107. hndl-0.1.0/src/hndl/operators/_relations.py +65 -0
  108. hndl-0.1.0/src/hndl/operators/adaptive_avg_pool.py +91 -0
  109. hndl-0.1.0/src/hndl/operators/adaptive_norm.py +49 -0
  110. hndl-0.1.0/src/hndl/operators/add.py +19 -0
  111. hndl-0.1.0/src/hndl/operators/attention.py +184 -0
  112. hndl-0.1.0/src/hndl/operators/avg_pool.py +65 -0
  113. hndl-0.1.0/src/hndl/operators/batch_norm.py +85 -0
  114. hndl-0.1.0/src/hndl/operators/clamp.py +65 -0
  115. hndl-0.1.0/src/hndl/operators/cls_token.py +67 -0
  116. hndl-0.1.0/src/hndl/operators/concat.py +62 -0
  117. hndl-0.1.0/src/hndl/operators/conv.py +96 -0
  118. hndl-0.1.0/src/hndl/operators/conv1d.py +104 -0
  119. hndl-0.1.0/src/hndl/operators/cross_attention.py +109 -0
  120. hndl-0.1.0/src/hndl/operators/deconv.py +52 -0
  121. hndl-0.1.0/src/hndl/operators/dropout.py +73 -0
  122. hndl-0.1.0/src/hndl/operators/elu.py +54 -0
  123. hndl-0.1.0/src/hndl/operators/embedding.py +69 -0
  124. hndl-0.1.0/src/hndl/operators/feed_forward.py +108 -0
  125. hndl-0.1.0/src/hndl/operators/flatten.py +24 -0
  126. hndl-0.1.0/src/hndl/operators/gather_token.py +98 -0
  127. hndl-0.1.0/src/hndl/operators/gelu.py +63 -0
  128. hndl-0.1.0/src/hndl/operators/global_avg_pool.py +49 -0
  129. hndl-0.1.0/src/hndl/operators/group_norm.py +36 -0
  130. hndl-0.1.0/src/hndl/operators/hardswish.py +51 -0
  131. hndl-0.1.0/src/hndl/operators/hopfield.py +135 -0
  132. hndl-0.1.0/src/hndl/operators/identity.py +45 -0
  133. hndl-0.1.0/src/hndl/operators/instance_norm.py +86 -0
  134. hndl-0.1.0/src/hndl/operators/layer_norm.py +63 -0
  135. hndl-0.1.0/src/hndl/operators/leaky_relu.py +18 -0
  136. hndl-0.1.0/src/hndl/operators/linear.py +41 -0
  137. hndl-0.1.0/src/hndl/operators/max_pool.py +58 -0
  138. hndl-0.1.0/src/hndl/operators/mean.py +105 -0
  139. hndl-0.1.0/src/hndl/operators/mish.py +51 -0
  140. hndl-0.1.0/src/hndl/operators/moe.py +137 -0
  141. hndl-0.1.0/src/hndl/operators/mul.py +30 -0
  142. hndl-0.1.0/src/hndl/operators/pad.py +148 -0
  143. hndl-0.1.0/src/hndl/operators/patch_embed.py +105 -0
  144. hndl-0.1.0/src/hndl/operators/permute.py +95 -0
  145. hndl-0.1.0/src/hndl/operators/pixel_shuffle.py +86 -0
  146. hndl-0.1.0/src/hndl/operators/pool_tokens.py +85 -0
  147. hndl-0.1.0/src/hndl/operators/pos_embed.py +70 -0
  148. hndl-0.1.0/src/hndl/operators/pretrained.py +117 -0
  149. hndl-0.1.0/src/hndl/operators/quick_gelu.py +49 -0
  150. hndl-0.1.0/src/hndl/operators/relu.py +17 -0
  151. hndl-0.1.0/src/hndl/operators/resblock.py +157 -0
  152. hndl-0.1.0/src/hndl/operators/reshape.py +69 -0
  153. hndl-0.1.0/src/hndl/operators/rms_norm.py +83 -0
  154. hndl-0.1.0/src/hndl/operators/scale.py +39 -0
  155. hndl-0.1.0/src/hndl/operators/sigmoid.py +40 -0
  156. hndl-0.1.0/src/hndl/operators/silu.py +41 -0
  157. hndl-0.1.0/src/hndl/operators/softmax.py +84 -0
  158. hndl-0.1.0/src/hndl/operators/softplus.py +59 -0
  159. hndl-0.1.0/src/hndl/operators/split.py +67 -0
  160. hndl-0.1.0/src/hndl/operators/sub.py +30 -0
  161. hndl-0.1.0/src/hndl/operators/sum.py +107 -0
  162. hndl-0.1.0/src/hndl/operators/swiglu.py +80 -0
  163. hndl-0.1.0/src/hndl/operators/tanh.py +15 -0
  164. hndl-0.1.0/src/hndl/operators/transformer_block.py +204 -0
  165. hndl-0.1.0/src/hndl/operators/transpose.py +91 -0
  166. hndl-0.1.0/src/hndl/operators/upsample.py +93 -0
  167. hndl-0.1.0/src/hndl/pretrained.py +290 -0
  168. hndl-0.1.0/src/hndl/py.typed +0 -0
  169. hndl-0.1.0/src/hndl/registry.py +126 -0
  170. hndl-0.1.0/src/hndl/resolver.py +410 -0
  171. hndl-0.1.0/src/hndl/settings.py +104 -0
  172. hndl-0.1.0/src/hndl/torch.py +488 -0
  173. hndl-0.1.0/src/hndl/types.py +222 -0
  174. hndl-0.1.0/src/hndl.egg-info/PKG-INFO +461 -0
  175. hndl-0.1.0/src/hndl.egg-info/SOURCES.txt +242 -0
  176. hndl-0.1.0/src/hndl.egg-info/dependency_links.txt +1 -0
  177. hndl-0.1.0/src/hndl.egg-info/requires.txt +16 -0
  178. hndl-0.1.0/src/hndl.egg-info/top_level.txt +1 -0
  179. hndl-0.1.0/tests/operators/__init__.py +0 -0
  180. hndl-0.1.0/tests/operators/conftest.py +45 -0
  181. hndl-0.1.0/tests/operators/test_adaptive_avg_pool.py +115 -0
  182. hndl-0.1.0/tests/operators/test_all_operators.py +150 -0
  183. hndl-0.1.0/tests/operators/test_attention.py +199 -0
  184. hndl-0.1.0/tests/operators/test_avg_pool.py +127 -0
  185. hndl-0.1.0/tests/operators/test_batch_norm.py +137 -0
  186. hndl-0.1.0/tests/operators/test_clamp.py +99 -0
  187. hndl-0.1.0/tests/operators/test_cls_token.py +84 -0
  188. hndl-0.1.0/tests/operators/test_conv1d.py +161 -0
  189. hndl-0.1.0/tests/operators/test_conv_down2.py +101 -0
  190. hndl-0.1.0/tests/operators/test_cross_attention.py +168 -0
  191. hndl-0.1.0/tests/operators/test_dropout.py +158 -0
  192. hndl-0.1.0/tests/operators/test_elu.py +57 -0
  193. hndl-0.1.0/tests/operators/test_embedding.py +102 -0
  194. hndl-0.1.0/tests/operators/test_feed_forward.py +123 -0
  195. hndl-0.1.0/tests/operators/test_gather_token.py +141 -0
  196. hndl-0.1.0/tests/operators/test_gelu.py +79 -0
  197. hndl-0.1.0/tests/operators/test_global_avg_pool.py +92 -0
  198. hndl-0.1.0/tests/operators/test_hardswish.py +57 -0
  199. hndl-0.1.0/tests/operators/test_hopfield.py +207 -0
  200. hndl-0.1.0/tests/operators/test_identity.py +58 -0
  201. hndl-0.1.0/tests/operators/test_instance_norm.py +114 -0
  202. hndl-0.1.0/tests/operators/test_layer_norm.py +94 -0
  203. hndl-0.1.0/tests/operators/test_max_pool.py +110 -0
  204. hndl-0.1.0/tests/operators/test_mean.py +104 -0
  205. hndl-0.1.0/tests/operators/test_mish.py +58 -0
  206. hndl-0.1.0/tests/operators/test_moe.py +165 -0
  207. hndl-0.1.0/tests/operators/test_mul.py +78 -0
  208. hndl-0.1.0/tests/operators/test_pad.py +150 -0
  209. hndl-0.1.0/tests/operators/test_patch_embed.py +113 -0
  210. hndl-0.1.0/tests/operators/test_permute.py +91 -0
  211. hndl-0.1.0/tests/operators/test_pixel_shuffle.py +108 -0
  212. hndl-0.1.0/tests/operators/test_pool_tokens.py +91 -0
  213. hndl-0.1.0/tests/operators/test_pos_embed.py +86 -0
  214. hndl-0.1.0/tests/operators/test_quick_gelu.py +67 -0
  215. hndl-0.1.0/tests/operators/test_resblock.py +190 -0
  216. hndl-0.1.0/tests/operators/test_rms_norm.py +120 -0
  217. hndl-0.1.0/tests/operators/test_scale.py +73 -0
  218. hndl-0.1.0/tests/operators/test_sigmoid.py +57 -0
  219. hndl-0.1.0/tests/operators/test_silu.py +58 -0
  220. hndl-0.1.0/tests/operators/test_softmax.py +104 -0
  221. hndl-0.1.0/tests/operators/test_softplus.py +65 -0
  222. hndl-0.1.0/tests/operators/test_sub.py +70 -0
  223. hndl-0.1.0/tests/operators/test_sum.py +104 -0
  224. hndl-0.1.0/tests/operators/test_swiglu.py +115 -0
  225. hndl-0.1.0/tests/operators/test_transformer_block.py +218 -0
  226. hndl-0.1.0/tests/operators/test_transpose.py +87 -0
  227. hndl-0.1.0/tests/operators/test_upsample.py +117 -0
  228. hndl-0.1.0/tests/test_adaptive_normalization.py +161 -0
  229. hndl-0.1.0/tests/test_capture.py +195 -0
  230. hndl-0.1.0/tests/test_config.py +219 -0
  231. hndl-0.1.0/tests/test_construction_settings.py +175 -0
  232. hndl-0.1.0/tests/test_custom_operator.py +656 -0
  233. hndl-0.1.0/tests/test_examples.py +86 -0
  234. hndl-0.1.0/tests/test_golden_plans.py +94 -0
  235. hndl-0.1.0/tests/test_network_examples.py +67 -0
  236. hndl-0.1.0/tests/test_package.py +16 -0
  237. hndl-0.1.0/tests/test_parameter_settings.py +282 -0
  238. hndl-0.1.0/tests/test_plans.py +168 -0
  239. hndl-0.1.0/tests/test_pretrained.py +224 -0
  240. hndl-0.1.0/tests/test_rank_dtype.py +135 -0
  241. hndl-0.1.0/tests/test_registry.py +108 -0
  242. hndl-0.1.0/tests/test_resolver.py +138 -0
  243. hndl-0.1.0/tests/test_settings_frontends.py +247 -0
  244. hndl-0.1.0/tests/test_torch.py +310 -0
@@ -0,0 +1,70 @@
1
+ # Developing HNDL
2
+
3
+ Use Python 3.11–3.14 on Linux. Create an environment and install the editable
4
+ package with its development tools:
5
+
6
+ ```sh
7
+ python -m venv .venv
8
+ . .venv/bin/activate
9
+ python -m pip install -e '.[dev]'
10
+ python -m pytest
11
+ ruff check src tests examples
12
+ python -m hndl.docs --check
13
+ ```
14
+
15
+ PyTorch is a dependency. CUDA tests run when a CUDA device is available; CPU
16
+ CI does not establish GPU correctness. Operator documentation under
17
+ `docs/operators` is generated from the `@operator` declarations; regenerate it
18
+ with `python -m hndl.docs` after changing one. See
19
+ [docs/ADDING_OPERATORS.md](docs/ADDING_OPERATORS.md) to add an operator.
20
+
21
+ Changes go through pull requests. CI tests the CPU backend on Python 3.11 and
22
+ 3.14, testing PyTorch 2.6 on Python 3.11 and the latest supported 2.x version
23
+ on Python 3.14. Keep the explicit activation and implicit
24
+ current-tensor behavior consistent between declarative configurations and
25
+ trusted Python callables. Configuration input must never be executed as Python.
26
+
27
+ Build release candidates with:
28
+
29
+ ```sh
30
+ python -m build
31
+ python -m twine check --strict dist/*
32
+ ```
33
+
34
+ The distribution version lives in `pyproject.toml` and
35
+ `src/hndl/_version.py`; update both together, and record the release in
36
+ `CHANGELOG.md`. Building a distribution does not publish it to PyPI.
37
+
38
+ ## Publishing
39
+
40
+ Releases are published by `.github/workflows/publish.yml` when a GitHub
41
+ release is published. The release tag must be `v<version>`, matching
42
+ `pyproject.toml`. The workflow checks the tag, builds the distributions, installs
43
+ the wheel in a clean environment with the CPU backend, runs the test suite and
44
+ the documentation check against it, and only then uploads. A failure at any
45
+ step prevents publishing. The wheel and source archive are retained as workflow
46
+ artifacts either way.
47
+
48
+ The upload authenticates in one of two ways; the first one that applies wins.
49
+
50
+ 1. **API token secret.** Create a PyPI API token and store it as the
51
+ repository secret `PYPI_API_TOKEN` (or as a secret on the GitHub `pypi`
52
+ environment). Until the project exists on PyPI the token must be
53
+ account-scoped; after the first upload it can be replaced with a token
54
+ scoped to `hndl`.
55
+ 2. **Trusted Publishing.** With no secret set, the workflow uses PyPI's
56
+ short-lived OIDC credentials. Register a [pending trusted publisher](https://docs.pypi.org/trusted-publishers/creating-a-project-through-oidc/)
57
+ for project `hndl`, owner `HyperGAN`, repository `HNDL`, workflow
58
+ `publish.yml`, environment `pypi`. This is PyPI account configuration, not
59
+ a repository secret.
60
+
61
+ The `pypi` GitHub environment is created on first use; add release reviewers
62
+ to it if publishing should require approval.
63
+
64
+ To rehearse without publishing, run the workflow manually from the Actions tab
65
+ (`workflow_dispatch`). The manual run builds and tests the distributions and
66
+ uploads them as artifacts; the publish job is skipped.
67
+
68
+ To release: update the version in `pyproject.toml` and `src/hndl/_version.py`,
69
+ record the release in `CHANGELOG.md`, merge, then create a GitHub release with
70
+ tag `v<version>` on `master`. Publishing the release triggers the workflow.
@@ -0,0 +1,204 @@
1
+ # Implementation notes: 0.1.0
2
+
3
+ This release implements the contract in [SPEC.md](SPEC.md). [README.md](README.md)
4
+ introduces the APIs with examples; the [operator catalog](docs/operators/index.md)
5
+ and the [authored networks](docs/networks.md) are generated from the code.
6
+
7
+ ## Available
8
+
9
+ - Declarative source and bounded UTF-8 file loading: `resolve`, `resolve_file`,
10
+ `network`, and `network_file`.
11
+ - Trusted Python authoring: `ops`, `resolve_callable`, and
12
+ `network_from_callable`, with one capture per construction.
13
+ - Implicit current tensor, explicit tensor arguments, assignments, comments,
14
+ names, split/remainder, branches, and explicit joins.
15
+ - Bidirectional inference for widths, reshape products, convolution and pooling
16
+ arithmetic, split/concat extents, sequence lengths, and the exact `up2` and
17
+ `down2` policies. Contradictions fail; the resolver does not choose arbitrary
18
+ missing sizes.
19
+ - One `@operator` declaration per operation, on the `nn.Module` that
20
+ implements it: alias and version, a shape relation written as
21
+ `x[B, C, H, W], params[B, 2*C] -> out[B, C, H, W]` (shared symbols, integer
22
+ scales, literals, `...` for shared middle axes, `x*` variadic inputs, port
23
+ dtypes) or a relation function over a bounded node view, scalar arguments
24
+ with help text, runnable examples, and hooks for positional rest arguments,
25
+ policies, validation, and finalization. Built-ins are discovered from
26
+ `hndl.operators`; custom operators use the same decorator on a `Registry`.
27
+ See [docs/ADDING_OPERATORS.md](docs/ADDING_OPERATORS.md).
28
+ - Fifty-nine operators across activation, arithmetic, shape, normalization,
29
+ convolution, spatial, sequence, vision, memory, regularization, and
30
+ pretrained categories, each with tests against PyTorch references.
31
+ - `pretrained(source)`: a generic loader for transformers and timm checkpoints
32
+ from local paths or `hf://` repositories. See [docs/pretrained.md](docs/pretrained.md).
33
+ - PyTorch modules, shape tables, name lookup, sequence indexing and shared
34
+ slices, ordinary autograd, state dictionaries, and CPU/CUDA construction in
35
+ float32, float16, or bfloat16.
36
+ - Persisted constant parameter initialization and trainability overrides,
37
+ shared by both frontends and applied when building or rebuilding a plan.
38
+ - Immutable resolved graph data, canonical JSON plan persistence, digests,
39
+ exact operator-version checks, and `build(plan)` without recapturing an
40
+ author function. JSON is a persistence format, not an authoring language.
41
+ - Generated documentation (`python -m hndl.docs`, checked in CI), MIT license,
42
+ wheel/source builds, CI, and a release publishing workflow.
43
+
44
+ ## Runtime and operation arguments
45
+
46
+ The supported platform is Linux, on Python 3.11–3.14. Config parsing uses a
47
+ Python 3.11 grammar with an explicit AST allowlist in an isolated Linux worker.
48
+ Unsupported platforms fail instead of falling back to in-process parsing.
49
+ Native authoring executes trusted Python; it is not sandboxed.
50
+
51
+ The backend requires PyTorch 2.6 or newer in the 2.x series. Tensors have
52
+ rank two `[B, F]`, rank three `[B, T, D]` (a sequence of `T` positions with
53
+ `D` features; `linear`, normalizations, and activations act on the last axis),
54
+ or rank four `[B, C, H, W]`. One-dimensional convolution and pooling use rank
55
+ three as `[B, C, L]`; `transpose(1, 2)` moves between the conventions. Only
56
+ the batch axis may be symbolic (`"B"`). Other dimensions and runtime batch
57
+ sizes must be positive integers. The device is always caller-selected.
58
+
59
+ Plans carry a compute `dtype` of `float32` (default), `float16`, or
60
+ `bfloat16`; parameters are constructed in that dtype and every floating tensor
61
+ port must match it at runtime. Operators can declare integer ports, such as
62
+ `embedding`'s `ids[B, T]:int64` input; pass `input_dtype="int64"` when the
63
+ graph input is integer. Edge dtypes are checked at resolution (`E_DTYPE`), so
64
+ an integer tensor cannot reach a floating-point port. Reduced precision is
65
+ qualified on CUDA.
66
+
67
+ Built-in unary operations take an optional leading tensor or `x=`. Custom
68
+ unary operations use their declared input-port keyword. Every operator's
69
+ arguments, defaults, bounds, shape relation, and examples are listed in
70
+ [docs/operators](docs/operators/index.md). Convolution spatial arguments
71
+ accept an integer or a pair of integers. Split/concat axes are positive,
72
+ non-batch indices; negative axes are rejected. `name=` sets a stable node ID
73
+ independently of Python variable names. Operator aliases are reserved names
74
+ in configurations.
75
+
76
+ `dropout` is stochastic in training mode using PyTorch's global RNG, the one
77
+ documented deviation from the rule that forward passes draw no hidden
78
+ randomness. `pretrained` reads its checkpoint's `config.json` (downloading it
79
+ for `hf://` sources) and traces the architecture on the meta device during
80
+ resolution, the one documented exception to allocation-free resolution.
81
+
82
+ ## Loading and allocation limits
83
+
84
+ Both string and file loading use the same parser worker. The fixed parser
85
+ limits are 64 KiB of UTF-8 source, 4,096 lines, 16,384 AST nodes, nesting depth
86
+ 96, 1,024 items per literal container, 16 KiB per string literal, and 256 bits
87
+ per integer literal. Worker address space is capped at 256 MiB and CPU time
88
+ at two seconds; the parent also enforces a wall-clock timeout. The worker
89
+ protocol is bounded at 2 MiB. Parsing never invokes `eval`, `exec`, or a
90
+ configuration-provided import or callback.
91
+
92
+ The resolver and builder additionally bound graph size, dimensions, element
93
+ counts, and registered parameter/buffer storage. Defaults are 4,096 nodes,
94
+ 16,384 input edges, 1,048,576 per dimension, 268,435,456 elements per
95
+ example, 1 GiB of registered state, and 256 solver iterations. Pass a
96
+ `limits` dictionary to resolution or construction to override these limits
97
+ explicitly; keys are `max_nodes`, `max_edges`, `max_dimension`,
98
+ `max_elements`, `max_state_bytes`, and `max_iterations`. Storage is measured
99
+ by constructing every module on PyTorch's allocation-free `meta` device before
100
+ real construction; `build_receipt["state_bytes"]` records the total. These
101
+ bounds do not estimate peak training memory or bound arbitrary native Python
102
+ authoring code.
103
+
104
+ ## Custom operation scope
105
+
106
+ `@operator` declarations are data: registration parses the shape string and
107
+ argument schema without constructing modules. Shared dimension names impose
108
+ equality within one node, `2*C` imposes an exact integer multiple in either
109
+ direction, literals fix an axis, and `...` shares a run of middle axes across
110
+ the ports that use it. Rules the string cannot express use a `relation`
111
+ function over a bounded node view; relations are trusted code. See
112
+ [docs/ADDING_OPERATORS.md](docs/ADDING_OPERATORS.md) and the
113
+ [technical contract](SPEC.md#8-custom-operators-and-minimal-graphs).
114
+
115
+ Each declaration permits at most 32 input ports, 32 output ports, 64 scalar
116
+ arguments, and 64 distinct dimension symbols. Port, argument, and dimension
117
+ names are limited to 64 characters. Dimension literals and scales are capped
118
+ at `2**31 - 1`; the usually lower runtime `max_dimension` still applies to
119
+ resolved extents. Integer scalar arguments are bounded by `abs(value) <=
120
+ 2**63 - 1`, and string arguments by 16,384 UTF-8 bytes. Float values must be
121
+ finite. Schemas may apply tighter numeric bounds. Omitted scalar arguments
122
+ need an explicit default unless marked `inferable`, in which case a shape
123
+ symbol or relation must determine them.
124
+
125
+ ## Saving a resolved plan
126
+
127
+ Use the plan alongside the model's ordinary PyTorch state dictionary:
128
+
129
+ ```python
130
+ from pathlib import Path
131
+ from hndl import ResolvedPlan
132
+ from hndl.torch import build
133
+
134
+ Path("architecture.json").write_text(model.plan.to_json(), encoding="utf-8")
135
+ plan = ResolvedPlan.from_json(
136
+ Path("architecture.json").read_text(encoding="utf-8")
137
+ )
138
+ restored = build(plan, device="cpu")
139
+ restored.load_state_dict(model.state_dict())
140
+ # build() returns the lower-level named-input/dictionary-output module:
141
+ result = restored(x=batch)["output"]
142
+ ```
143
+
144
+ Custom plans require the matching explicit registry at restore/build time.
145
+ Saved data cannot import its own implementations. Restoration verifies the
146
+ saved concrete equations, dimensions, and operator versions without executing
147
+ source or an author function. The ordinary PyTorch state dictionary does not
148
+ contain the architecture; keep both together. Plans that use `pretrained`
149
+ record the resolved checkpoint revision and fail to restore if the source has
150
+ changed.
151
+
152
+ Schema 1 uses sorted JSON object keys, compact separators, UTF-8 without ASCII
153
+ escaping, arrays for tuples, finite numbers, and SHA-256 digests. Node order,
154
+ identities, arguments, shapes, dtypes, initialization, and trainability
155
+ participate in the semantic digest. Source/frontend metadata and argument
156
+ provenance affect the artifact digest but not the semantic digest. Plan JSON
157
+ is limited to 16 MiB. Restoring arbitrary third-party artifacts is not the
158
+ same isolation boundary as loading declarative source.
159
+
160
+ ## Construction settings
161
+
162
+ `init={"weight": 0, "bias": 0}` selects constant parameter overrides after
163
+ normal module construction. `trainable=False` freezes all parameters in the
164
+ operation, while `trainable={"weight": False}` changes only named parameters.
165
+ Omitting either option preserves the constructor's values or `requires_grad`
166
+ flags. Empty mappings have the same meaning as omission. Explicit `None` is
167
+ not supported. Both options are reserved frontend metadata, alongside `name`
168
+ and `policy`, and are never passed as operator constructor arguments.
169
+
170
+ Targets are exact, relative parameter paths (including nested paths such as
171
+ `projection.weight`), with at most 256 entries per mapping and 256 characters
172
+ per path. Buffers and nonexistent targets are rejected at build time.
173
+ Constants must be numbers other than booleans and must round to finite
174
+ float32 values; the plan stores those rounded values and fills them into the
175
+ parameter's dtype. Trainability values must be booleans. Aliased parameters
176
+ cannot receive conflicting declarations. Constant targets cannot share storage
177
+ with a distinct parameter or a registered buffer.
178
+
179
+ Initialization overrides run under `no_grad` after parameters are materialized.
180
+ `initialization_seed=None` uses the caller's RNG; an explicit seed isolates
181
+ construction and restores the caller's RNG afterward. Freezing affects
182
+ parameter gradients, not input gradients or train/eval mode.
183
+
184
+ ## Limits of this release
185
+
186
+ - Custom shape relations beyond the DSL are trusted Python functions; there is
187
+ no declarative form for arithmetic relations, and inferable custom scalars
188
+ must be bound to a shape symbol or set by a relation.
189
+ - Weight tying between graph nodes is unsupported; `pretrained` loads tied
190
+ checkpoints correctly because the wrapped model ties them internally.
191
+ - Vision checkpoints load at their native resolution only.
192
+ - Full derivation chains for every inferred value, published machine-readable
193
+ plan schemas, and strict checkpoint-compatibility tooling beyond ordinary
194
+ PyTorch state loading remain future work.
195
+ - Training loops, metric optimization, optimizer state, and complete experiment
196
+ recovery remain owned by the application.
197
+
198
+ ## Development and publication
199
+
200
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for local checks and publishing setup.
201
+ CI tests the CPU backend on Python 3.11 and 3.14, checks that the generated
202
+ documentation is current, checks the built distributions, and exercises a
203
+ wheel installation outside the checkout. CUDA and network-dependent tests run
204
+ locally; CPU CI does not qualify CUDA execution or checkpoint downloads.
hndl-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 HNDL contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
hndl-0.1.0/MANIFEST.in ADDED
@@ -0,0 +1,4 @@
1
+ include LICENSE README.md SPEC.md IMPLEMENTATION.md CONTRIBUTING.md
2
+ recursive-include tests *.py
3
+ recursive-include examples *.py *.hndl *.json *.md
4
+ recursive-include docs *.md