braintrace 0.2.3__tar.gz → 0.2.5__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 (184) hide show
  1. {braintrace-0.2.3 → braintrace-0.2.5}/PKG-INFO +45 -3
  2. {braintrace-0.2.3 → braintrace-0.2.5}/README.md +42 -1
  3. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/__init__.py +41 -11
  4. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/__init___test.py +60 -30
  5. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/__init__.py +21 -10
  6. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/_common.py +99 -141
  7. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/_common_test.py +0 -25
  8. braintrace-0.2.5/braintrace/_algorithm/axes.py +663 -0
  9. braintrace-0.2.5/braintrace/_algorithm/axes_test.py +497 -0
  10. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/base.py +88 -13
  11. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/base_test.py +2 -2
  12. braintrace-0.2.5/braintrace/_algorithm/d_rtrl.py +107 -0
  13. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/d_rtrl_test.py +1 -1
  14. braintrace-0.2.5/braintrace/_algorithm/dni.py +668 -0
  15. braintrace-0.2.5/braintrace/_algorithm/dni_test.py +1004 -0
  16. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/e_prop.py +76 -95
  17. braintrace-0.2.5/braintrace/_algorithm/e_prop_test.py +445 -0
  18. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/graph_executor.py +39 -8
  19. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/graph_executor_test.py +22 -1
  20. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/io_dim_vjp.py +388 -147
  21. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/io_dim_vjp_test.py +92 -4
  22. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/ostl.py +82 -16
  23. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/ostl_test.py +115 -0
  24. braintrace-0.2.5/braintrace/_algorithm/param_dim_vjp.py +1496 -0
  25. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/param_dim_vjp_test.py +412 -3
  26. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/pp_prop.py +34 -4
  27. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/pp_prop_test.py +9 -4
  28. braintrace-0.2.5/braintrace/_algorithm/random_projection_vjp.py +701 -0
  29. braintrace-0.2.5/braintrace/_algorithm/random_projection_vjp_test.py +412 -0
  30. braintrace-0.2.5/braintrace/_algorithm/sequence.py +575 -0
  31. braintrace-0.2.5/braintrace/_algorithm/sequence_test.py +1534 -0
  32. braintrace-0.2.5/braintrace/_algorithm/snap_n.py +221 -0
  33. braintrace-0.2.5/braintrace/_algorithm/snap_n_test.py +1289 -0
  34. braintrace-0.2.5/braintrace/_algorithm/tests/approx_correctness_test.py +308 -0
  35. braintrace-0.2.5/braintrace/_algorithm/tests/axis_acceptance_test.py +520 -0
  36. braintrace-0.2.5/braintrace/_algorithm/tests/axis_discrimination_test.py +111 -0
  37. braintrace-0.2.5/braintrace/_algorithm/tests/axis_golden_test.py +337 -0
  38. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/tests/conv_vmap_correctness_test.py +11 -0
  39. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/tests/diagnostic_exploration_test.py +2 -2
  40. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/tests/exact_correctness_test.py +75 -71
  41. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/tests/public_api_test.py +17 -3
  42. braintrace-0.2.5/braintrace/_algorithm/tests/scan_descent_support_test.py +353 -0
  43. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/tests/scan_fusion_test.py +2 -2
  44. braintrace-0.2.5/braintrace/_algorithm/tests/snn_model_correctness_test.py +136 -0
  45. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/tests/transform_correctness_test.py +3 -82
  46. braintrace-0.2.5/braintrace/_algorithm/tests/while_support_test.py +256 -0
  47. braintrace-0.2.5/braintrace/_algorithm/three_factor.py +200 -0
  48. braintrace-0.2.5/braintrace/_algorithm/three_factor_test.py +651 -0
  49. braintrace-0.2.5/braintrace/_algorithm/uoro.py +181 -0
  50. braintrace-0.2.5/braintrace/_algorithm/uoro_test.py +912 -0
  51. braintrace-0.2.5/braintrace/_algorithm/vjp_base.py +1908 -0
  52. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/vjp_base_test.py +493 -28
  53. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/vjp_graph_executor.py +190 -21
  54. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/vjp_graph_executor_test.py +57 -0
  55. braintrace-0.2.5/braintrace/_compatible_imports.py +148 -0
  56. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compatible_imports_test.py +60 -1
  57. braintrace-0.2.5/braintrace/_compile.py +396 -0
  58. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compile_test.py +37 -9
  59. braintrace-0.2.5/braintrace/_compiler/__init__.py +133 -0
  60. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/base.py +105 -17
  61. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/base_test.py +178 -3
  62. braintrace-0.2.5/braintrace/_compiler/canonicalize.py +1266 -0
  63. braintrace-0.2.5/braintrace/_compiler/canonicalize_test.py +1701 -0
  64. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/diagnostics.py +52 -0
  65. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/diagnostics_test.py +10 -0
  66. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/graph.py +225 -27
  67. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/graph_test.py +157 -1
  68. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/hid_param_op.py +225 -96
  69. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/hid_param_op_test.py +1 -1
  70. braintrace-0.2.5/braintrace/_compiler/hidden_group.py +2285 -0
  71. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/hidden_group_test.py +872 -2
  72. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/hidden_pertubation.py +262 -74
  73. braintrace-0.2.5/braintrace/_compiler/hidden_pertubation_test.py +508 -0
  74. braintrace-0.2.5/braintrace/_compiler/jaxpr_graph.py +319 -0
  75. braintrace-0.2.5/braintrace/_compiler/jaxpr_graph_test.py +320 -0
  76. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/module_info.py +119 -32
  77. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/module_info_test.py +30 -1
  78. braintrace-0.2.5/braintrace/_compiler/position_graph.py +636 -0
  79. braintrace-0.2.5/braintrace/_compiler/position_graph_test.py +604 -0
  80. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/report.py +2 -2
  81. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/report_test.py +1 -1
  82. braintrace-0.2.5/braintrace/_compiler/scan_descent.py +597 -0
  83. braintrace-0.2.5/braintrace/_compiler/scan_descent_test.py +485 -0
  84. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/tests/compiler_oracle_test.py +1 -1
  85. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/tests/compiler_property_test.py +1 -1
  86. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_grad_exponential.py +0 -5
  87. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_input_data.py +69 -39
  88. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_legacy/_ops.py +35 -35
  89. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_legacy/_params.py +28 -21
  90. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_misc.py +57 -4
  91. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_misc_test.py +53 -0
  92. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/__init__.py +42 -3
  93. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/_primitive.py +91 -13
  94. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/_primitive_test.py +160 -17
  95. braintrace-0.2.5/braintrace/_op/_registries.py +496 -0
  96. braintrace-0.2.5/braintrace/_op/_registries_test.py +342 -0
  97. braintrace-0.2.5/braintrace/_op/conv.py +927 -0
  98. braintrace-0.2.5/braintrace/_op/conv_test.py +1042 -0
  99. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/dense.py +177 -15
  100. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/dense_test.py +227 -32
  101. braintrace-0.2.5/braintrace/_op/einsum.py +371 -0
  102. braintrace-0.2.5/braintrace/_op/einsum_test.py +496 -0
  103. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/elemwise.py +129 -27
  104. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/elemwise_test.py +98 -7
  105. braintrace-0.2.5/braintrace/_op/embedding.py +292 -0
  106. braintrace-0.2.5/braintrace/_op/embedding_test.py +379 -0
  107. braintrace-0.2.5/braintrace/_op/grouped.py +464 -0
  108. braintrace-0.2.5/braintrace/_op/grouped_test.py +496 -0
  109. braintrace-0.2.5/braintrace/_op/lora.py +696 -0
  110. braintrace-0.2.5/braintrace/_op/lora_test.py +749 -0
  111. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/op_rule_oracle_test.py +15 -9
  112. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/sparse.py +188 -27
  113. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/sparse_test.py +294 -26
  114. braintrace-0.2.3/braintrace/_state_managment.py → braintrace-0.2.5/braintrace/_state_management.py +2 -10
  115. braintrace-0.2.3/braintrace/_state_managment_test.py → braintrace-0.2.5/braintrace/_state_management_test.py +1 -1
  116. braintrace-0.2.5/braintrace/_testing/__init__.py +50 -0
  117. braintrace-0.2.5/braintrace/_testing/oracle.py +779 -0
  118. braintrace-0.2.5/braintrace/_testing/oracle_models.py +1227 -0
  119. braintrace-0.2.5/braintrace/_testing/oracle_models_test.py +348 -0
  120. braintrace-0.2.5/braintrace/_testing/oracle_test.py +807 -0
  121. {braintrace-0.2.3/braintrace/_compiler → braintrace-0.2.5/braintrace/_testing}/scenario_catalog.py +326 -3
  122. {braintrace-0.2.3/braintrace/_compiler → braintrace-0.2.5/braintrace/_testing}/scenario_catalog_test.py +462 -11
  123. braintrace-0.2.5/braintrace/_typing_test.py +295 -0
  124. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_version.py +1 -1
  125. braintrace-0.2.5/braintrace/_version_test.py +170 -0
  126. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/__init__.py +55 -29
  127. braintrace-0.2.5/braintrace/nn/__init___test.py +248 -0
  128. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/_conv.py +41 -3
  129. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/_conv_test.py +67 -0
  130. braintrace-0.2.5/braintrace/nn/_embedding.py +288 -0
  131. braintrace-0.2.5/braintrace/nn/_embedding_test.py +186 -0
  132. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/_linear.py +148 -7
  133. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/_linear_test.py +48 -4
  134. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/_readout.py +3 -1
  135. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/_rnn.py +6 -1
  136. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/_rnn_test.py +57 -0
  137. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace.egg-info/PKG-INFO +45 -3
  138. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace.egg-info/SOURCES.txt +51 -16
  139. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace.egg-info/requires.txt +2 -1
  140. {braintrace-0.2.3 → braintrace-0.2.5}/pyproject.toml +99 -11
  141. braintrace-0.2.5/setup.py +136 -0
  142. braintrace-0.2.3/braintrace/_algorithm/d_rtrl.py +0 -58
  143. braintrace-0.2.3/braintrace/_algorithm/e_prop_test.py +0 -218
  144. braintrace-0.2.3/braintrace/_algorithm/oracle.py +0 -222
  145. braintrace-0.2.3/braintrace/_algorithm/oracle_models.py +0 -195
  146. braintrace-0.2.3/braintrace/_algorithm/oracle_test.py +0 -175
  147. braintrace-0.2.3/braintrace/_algorithm/osttp.py +0 -208
  148. braintrace-0.2.3/braintrace/_algorithm/osttp_test.py +0 -200
  149. braintrace-0.2.3/braintrace/_algorithm/otpe.py +0 -386
  150. braintrace-0.2.3/braintrace/_algorithm/otpe_test.py +0 -215
  151. braintrace-0.2.3/braintrace/_algorithm/ottt.py +0 -262
  152. braintrace-0.2.3/braintrace/_algorithm/ottt_test.py +0 -209
  153. braintrace-0.2.3/braintrace/_algorithm/param_dim_vjp.py +0 -892
  154. braintrace-0.2.3/braintrace/_algorithm/tests/approx_correctness_test.py +0 -323
  155. braintrace-0.2.3/braintrace/_algorithm/vjp_base.py +0 -789
  156. braintrace-0.2.3/braintrace/_compatible_imports.py +0 -58
  157. braintrace-0.2.3/braintrace/_compile.py +0 -302
  158. braintrace-0.2.3/braintrace/_compiler/__init__.py +0 -56
  159. braintrace-0.2.3/braintrace/_compiler/hidden_group.py +0 -1335
  160. braintrace-0.2.3/braintrace/_compiler/hidden_pertubation_test.py +0 -126
  161. braintrace-0.2.3/braintrace/_docs_examples_test.py +0 -247
  162. braintrace-0.2.3/braintrace/_op/_registries.py +0 -206
  163. braintrace-0.2.3/braintrace/_op/_registries_test.py +0 -177
  164. braintrace-0.2.3/braintrace/_op/conv.py +0 -607
  165. braintrace-0.2.3/braintrace/_op/conv_test.py +0 -571
  166. braintrace-0.2.3/braintrace/_op/lora.py +0 -475
  167. braintrace-0.2.3/braintrace/_op/lora_test.py +0 -442
  168. {braintrace-0.2.3 → braintrace-0.2.5}/LICENSE +0 -0
  169. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/tests/cross_check_test.py +0 -0
  170. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/tests/cell_relation_guardrail_test.py +0 -0
  171. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_grad_exponential_test.py +0 -0
  172. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_input_data_test.py +0 -0
  173. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_legacy/__init__.py +0 -0
  174. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_legacy/_ops_test.py +0 -0
  175. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_legacy/_params_test.py +0 -0
  176. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/op_rule_oracle.py +0 -0
  177. /braintrace-0.2.3/braintrace/_compiler/model4test.py → /braintrace-0.2.5/braintrace/_testing/compiler_models.py +0 -0
  178. /braintrace-0.2.3/braintrace/_etrace_model_test.py → /braintrace-0.2.5/braintrace/_testing/models.py +0 -0
  179. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_typing.py +0 -0
  180. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/_readout_test.py +0 -0
  181. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/py.typed +0 -0
  182. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace.egg-info/dependency_links.txt +0 -0
  183. {braintrace-0.2.3 → braintrace-0.2.5}/braintrace.egg-info/top_level.txt +0 -0
  184. {braintrace-0.2.3 → braintrace-0.2.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: braintrace
3
- Version: 0.2.3
3
+ Version: 0.2.5
4
4
  Summary: Enabling Scalable Online Learning for Brain Dynamics.
5
5
  Author-email: BrainTrace Developers <chao.brain@qq.com>
6
6
  License: Apache-2.0 license
@@ -26,9 +26,10 @@ Classifier: Topic :: Software Development :: Libraries
26
26
  Requires-Python: >=3.11
27
27
  Description-Content-Type: text/markdown
28
28
  License-File: LICENSE
29
+ Requires-Dist: jax>=0.8.0
29
30
  Requires-Dist: brainstate>=0.5.2
30
31
  Requires-Dist: brainunit
31
- Requires-Dist: brainevent
32
+ Requires-Dist: brainevent>=0.1.2
32
33
  Requires-Dist: brainpy.state
33
34
  Requires-Dist: braintools
34
35
  Provides-Extra: cpu
@@ -74,7 +75,7 @@ It has been integrated into our establishing [brain modeling ecosystem](https://
74
75
 
75
76
  ## Installation
76
77
 
77
- ``braintrace`` can run on Python 3.10+ installed on Linux, MacOS, and Windows. You can install ``braintrace`` via pip:
78
+ ``braintrace`` requires Python 3.11 or newer and supports Linux, macOS, and Windows. You can install ``braintrace`` via pip:
78
79
 
79
80
  ```bash
80
81
  pip install braintrace --upgrade
@@ -86,6 +87,47 @@ Alternatively, you can install `BrainX`, which bundles `braintrace` with other c
86
87
  pip install BrainX -U
87
88
  ```
88
89
 
90
+ ## Quickstart
91
+
92
+ Mark the trainable operations with an ETP primitive (here, via `braintrace.nn`
93
+ layers, which use them internally), then compile the model into a learner and
94
+ drive a sequence. There is no scan to write and no special parameter class —
95
+ weights stay plain `brainstate.ParamState`.
96
+
97
+ ```python
98
+ import brainstate
99
+ import jax.numpy as jnp
100
+ import braintrace
101
+
102
+ class GRUNet(brainstate.nn.Module):
103
+ def __init__(self, n_in, n_rec, n_out):
104
+ super().__init__()
105
+ self.rnn = braintrace.nn.GRUCell(n_in, n_rec)
106
+ self.out = braintrace.nn.Linear(n_rec, n_out)
107
+
108
+ def update(self, x):
109
+ return self.out(self.rnn(x))
110
+
111
+ model = GRUNet(3, 8, 1)
112
+
113
+ # One call: initialise states, compile the eligibility-trace graph,
114
+ # return a ready learner.
115
+ learner = braintrace.compile(model, braintrace.D_RTRL, jnp.zeros((1, 3)), batch_size=1)
116
+
117
+ def step_loss(x, y):
118
+ return jnp.mean((learner(x) - y) ** 2)
119
+
120
+ xs = brainstate.random.randn(100, 1, 3) # (time, batch, features)
121
+ ys = brainstate.random.randn(100, 1, 1)
122
+
123
+ # Drives the sequence and accumulates online gradients -- O(1) memory in T.
124
+ grads, losses = learner.etrace_grad(xs, ys, step_fn=step_loss, return_value=True)
125
+ ```
126
+
127
+ Swap `braintrace.D_RTRL` for `pp_prop`, `SnAp`, `UORO`, `ThreeFactor`, `DNI`,
128
+ `EProp`, the OSTL variants, or an explicit `braintrace.ETraceConfig` to change
129
+ the learning rule; nothing else in the snippet changes.
130
+
89
131
  ## Documentation
90
132
 
91
133
  The official documentation is hosted on Read the Docs: [https://brainx.chaobrain.com/braintrace](https://brainx.chaobrain.com/braintrace)
@@ -19,7 +19,7 @@ It has been integrated into our establishing [brain modeling ecosystem](https://
19
19
 
20
20
  ## Installation
21
21
 
22
- ``braintrace`` can run on Python 3.10+ installed on Linux, MacOS, and Windows. You can install ``braintrace`` via pip:
22
+ ``braintrace`` requires Python 3.11 or newer and supports Linux, macOS, and Windows. You can install ``braintrace`` via pip:
23
23
 
24
24
  ```bash
25
25
  pip install braintrace --upgrade
@@ -31,6 +31,47 @@ Alternatively, you can install `BrainX`, which bundles `braintrace` with other c
31
31
  pip install BrainX -U
32
32
  ```
33
33
 
34
+ ## Quickstart
35
+
36
+ Mark the trainable operations with an ETP primitive (here, via `braintrace.nn`
37
+ layers, which use them internally), then compile the model into a learner and
38
+ drive a sequence. There is no scan to write and no special parameter class —
39
+ weights stay plain `brainstate.ParamState`.
40
+
41
+ ```python
42
+ import brainstate
43
+ import jax.numpy as jnp
44
+ import braintrace
45
+
46
+ class GRUNet(brainstate.nn.Module):
47
+ def __init__(self, n_in, n_rec, n_out):
48
+ super().__init__()
49
+ self.rnn = braintrace.nn.GRUCell(n_in, n_rec)
50
+ self.out = braintrace.nn.Linear(n_rec, n_out)
51
+
52
+ def update(self, x):
53
+ return self.out(self.rnn(x))
54
+
55
+ model = GRUNet(3, 8, 1)
56
+
57
+ # One call: initialise states, compile the eligibility-trace graph,
58
+ # return a ready learner.
59
+ learner = braintrace.compile(model, braintrace.D_RTRL, jnp.zeros((1, 3)), batch_size=1)
60
+
61
+ def step_loss(x, y):
62
+ return jnp.mean((learner(x) - y) ** 2)
63
+
64
+ xs = brainstate.random.randn(100, 1, 3) # (time, batch, features)
65
+ ys = brainstate.random.randn(100, 1, 1)
66
+
67
+ # Drives the sequence and accumulates online gradients -- O(1) memory in T.
68
+ grads, losses = learner.etrace_grad(xs, ys, step_fn=step_loss, return_value=True)
69
+ ```
70
+
71
+ Swap `braintrace.D_RTRL` for `pp_prop`, `SnAp`, `UORO`, `ThreeFactor`, `DNI`,
72
+ `EProp`, the OSTL variants, or an explicit `braintrace.ETraceConfig` to change
73
+ the learning rule; nothing else in the snippet changes.
74
+
34
75
  ## Documentation
35
76
 
36
77
  The official documentation is hosted on Read the Docs: [https://brainx.chaobrain.com/braintrace](https://brainx.chaobrain.com/braintrace)
@@ -41,8 +41,10 @@ downward:
41
41
  hidden->weight / hidden->hidden Jacobian computations.
42
42
  4. **Algorithms** — online-learning orchestrators: the exact algorithms
43
43
  :class:`D_RTRL` / :func:`pp_prop` / :class:`ES_D_RTRL`, and the SNN family
44
- :class:`EProp`, :class:`OSTLRecurrent`, :class:`OSTLFeedforward`,
45
- :class:`OTPE`, :class:`OTTT`, :class:`OSTTP`.
44
+ :class:`EProp`, :class:`OSTLRecurrent`, :class:`OSTLFeedforward`. Every one
45
+ of them carries the two sequence drivers of
46
+ :class:`SequenceDriverMixin` — ``etrace_grad`` and ``etrace_evolve`` — so a
47
+ caller never writes the per-step gradient-accumulation loop by hand.
46
48
 
47
49
  The :mod:`braintrace.nn` subpackage provides ready-made ETP-wired layers
48
50
  (linear maps, convolutions, recurrent cells, read-outs).
@@ -50,7 +52,13 @@ The :mod:`braintrace.nn` subpackage provides ready-made ETP-wired layers
50
52
  Notes
51
53
  -----
52
54
  The convenience entry point :func:`compile` wraps a model together with an
53
- algorithm into a single trainable object and is the recommended starting point.
55
+ algorithm into a single trainable object and is the recommended starting point:
56
+ one call replaces ``init_all_states`` + algorithm construction +
57
+ ``compile_graph`` (+ the vmap wrapper, with ``vmap=True``). The object it
58
+ returns drives a sequence with :meth:`~SequenceDriverMixin.etrace_grad`
59
+ (accumulate online gradients under a loss) or
60
+ :meth:`~SequenceDriverMixin.etrace_evolve` (advance hidden state and the
61
+ eligibility trace with no loss).
54
62
  The ``braintrace.MatMulOp`` / ``ETraceParam`` style names from the v0.1.x API
55
63
  are deprecated shims served lazily with a :class:`DeprecationWarning`; new code
56
64
  should mark parameters by routing them through ETP ops instead.
@@ -73,9 +81,12 @@ from typing import TYPE_CHECKING, Any
73
81
  from . import nn
74
82
  from ._compile import compile
75
83
  from ._algorithm import (
84
+ ETraceConfig,
76
85
  ETraceAlgorithm,
77
86
  EligibilityTrace,
78
87
  ETraceGraphExecutor,
88
+ ETraceVmap,
89
+ SequenceDriverMixin,
79
90
  ETraceVjpAlgorithm,
80
91
  ETraceVjpGraphExecutor,
81
92
  ParamDimVjpAlgorithm,
@@ -83,17 +94,21 @@ from ._algorithm import (
83
94
  pp_prop,
84
95
  ES_D_RTRL,
85
96
  IODimVjpAlgorithm,
97
+ SnAp,
98
+ RandomProjectionVjpAlgorithm,
99
+ UORO,
100
+ ThreeFactor,
101
+ DNI,
102
+ SyntheticGradient,
103
+ train_synthetic_gradient,
86
104
  EProp,
87
105
  OSTLRecurrent,
88
106
  OSTLFeedforward,
89
- OTPE,
90
- OTTT,
91
- OSTTP,
92
107
  FixedRandomFeedback,
93
108
  KappaFilter,
94
- PresynapticTrace,
95
109
  )
96
110
  from ._compiler import (
111
+ ControlFlowPolicy,
97
112
  ETraceGraph,
98
113
  compile_etrace_graph,
99
114
  HiddenParamOpRelation,
@@ -115,6 +130,9 @@ from ._compiler import (
115
130
  from ._op import (
116
131
  ETPPrimitive,
117
132
  matmul,
133
+ grouped_matmul,
134
+ embedding,
135
+ einsum,
118
136
  element_wise,
119
137
  conv,
120
138
  sparse_matmul,
@@ -152,9 +170,14 @@ __all__ = [
152
170
  '__version__',
153
171
  '__version_info__',
154
172
 
173
+ # learning-rule axes
174
+ 'ETraceConfig',
175
+
155
176
  # algorithms
156
177
  'ETraceAlgorithm',
157
178
  'EligibilityTrace',
179
+ 'ETraceVmap',
180
+ 'SequenceDriverMixin',
158
181
  'ETraceVjpAlgorithm',
159
182
  'ETraceVjpGraphExecutor',
160
183
  'ParamDimVjpAlgorithm',
@@ -162,12 +185,22 @@ __all__ = [
162
185
  'pp_prop',
163
186
  'ES_D_RTRL',
164
187
  'IODimVjpAlgorithm',
188
+ 'SnAp',
189
+ 'RandomProjectionVjpAlgorithm',
190
+ 'UORO',
191
+ 'ThreeFactor',
192
+ 'DNI',
193
+ 'SyntheticGradient',
194
+ 'train_synthetic_gradient',
165
195
 
166
196
  # one-call entry point
167
197
  'compile',
168
198
 
169
199
  # ETP primitives (user API)
170
200
  'matmul',
201
+ 'grouped_matmul',
202
+ 'embedding',
203
+ 'einsum',
171
204
  'element_wise',
172
205
  'conv',
173
206
  'sparse_matmul',
@@ -185,6 +218,7 @@ __all__ = [
185
218
  'ETraceGraphExecutor',
186
219
 
187
220
  # compiler
221
+ 'ControlFlowPolicy',
188
222
  'ETraceGraph',
189
223
  'compile_etrace_graph',
190
224
  'HiddenGroup',
@@ -212,12 +246,8 @@ __all__ = [
212
246
  'EProp',
213
247
  'OSTLRecurrent',
214
248
  'OSTLFeedforward',
215
- 'OTPE',
216
- 'OTTT',
217
- 'OSTTP',
218
249
  'FixedRandomFeedback',
219
250
  'KappaFilter',
220
- 'PresynapticTrace',
221
251
 
222
252
  # errors
223
253
  'NotSupportedError',
@@ -33,7 +33,7 @@ import pytest
33
33
 
34
34
  import braintrace
35
35
  import braintrace._legacy as legacy
36
- from braintrace._algorithm.oracle_models import tanh_rnn
36
+ from braintrace._testing.oracle_models import tanh_rnn
37
37
 
38
38
 
39
39
  # ===========================================================================
@@ -71,6 +71,10 @@ def _algo_constructors():
71
71
  'EProp': lambda m: braintrace.EProp(m),
72
72
  'OSTLRecurrent': lambda m: braintrace.OSTLRecurrent(m),
73
73
  'OSTLFeedforward': lambda m: braintrace.OSTLFeedforward(m, decay_or_rank=0.9),
74
+ 'SnAp': lambda m: braintrace.SnAp(m, n=1),
75
+ 'UORO': lambda m: braintrace.UORO(m),
76
+ # `modulatory` has no fallback: a standing modulator is required.
77
+ 'ThreeFactor': lambda m: braintrace.ThreeFactor(m, modulator=0.5),
74
78
  }
75
79
 
76
80
 
@@ -87,33 +91,30 @@ def test_algorithm_is_usable_end_to_end(name):
87
91
  assert bool(jnp.all(jnp.isfinite(y)))
88
92
 
89
93
 
90
- # --- Task 3: SNN algos requiring leak + OSTTP B_list contract ----------------
91
-
92
- def test_ottt_otpe_require_explicit_leak():
93
- model = tanh_rnn(seed=0).factory()
94
+ def test_dni_is_usable_end_to_end():
95
+ # DNI is the one preset whose second collaborator is sized from the compiled
96
+ # graph, so it cannot join the shared map above: build, compile, then attach.
97
+ model = tanh_rnn(n_in=3, n_rec=4, seed=0).factory()
94
98
  brainstate.nn.init_all_states(model, batch_size=1)
95
- with pytest.raises(TypeError):
96
- braintrace.OTTT(model) # leak is keyword-only & required
97
- with pytest.raises(TypeError):
98
- braintrace.OTPE(model)
99
-
100
-
101
- def test_ottt_otpe_construct_with_leak():
102
- for ctor in (lambda m: braintrace.OTTT(m, leak=0.9),
103
- lambda m: braintrace.OTPE(m, leak=0.9)):
104
- model = tanh_rnn(seed=0).factory()
105
- brainstate.nn.init_all_states(model, batch_size=1)
106
- algo = ctor(model)
107
- assert algo is not None
99
+ algo = braintrace.DNI(model)
100
+ x0 = jnp.ones((3,), dtype='float32')
101
+ algo.compile_graph(x0)
102
+ algo.init_etrace_state()
103
+ algo.attach_synthesizer(
104
+ braintrace.SyntheticGradient(algo.group_signal_shapes()))
105
+ y = algo(x0)
106
+ assert y.shape == (1, 4)
107
+ assert bool(jnp.all(jnp.isfinite(y)))
108
108
 
109
109
 
110
- def test_osttp_constructs_with_B_list():
111
- model = tanh_rnn(n_in=3, n_rec=4, seed=0).factory()
112
- brainstate.nn.init_all_states(model, batch_size=1)
113
- # OSTTP needs one random-feedback matrix per HiddenGroup; B.shape[1] == n_l (=4).
114
- B_list = [jnp.eye(4, dtype='float32')]
115
- algo = braintrace.OSTTP(model, B_list)
116
- assert algo is not None
110
+ @pytest.mark.parametrize('name', ['UORO', 'ThreeFactor', 'DNI',
111
+ 'SyntheticGradient', 'train_synthetic_gradient',
112
+ 'RandomProjectionVjpAlgorithm'])
113
+ def test_p4_symbols_are_exported_from_both_all_lists(name):
114
+ from braintrace import _algorithm
115
+ assert name in braintrace.__all__, f'{name} missing from braintrace.__all__'
116
+ assert name in _algorithm.__all__, f'{name} missing from _algorithm.__all__'
117
+ assert getattr(braintrace, name) is getattr(_algorithm, name)
117
118
 
118
119
 
119
120
  # --- Task 4: dynamic weight assignment raises NotSupportedError --------------
@@ -148,7 +149,14 @@ def test_weight_used_inside_scan_raises_not_implemented():
148
149
  within a control-flow op. Previously (F-SCAN-WEIGHT) the message construction
149
150
  indexed the hidden-path map with the weight var and a KeyError escaped instead;
150
151
  the message now renders the weight variable directly, so the intended
151
- NotImplementedError surfaces."""
152
+ NotImplementedError surfaces.
153
+
154
+ Since Phase 2 canonicalization, statically short scans are unrolled at
155
+ extraction time instead of erroring, so this uses a length above
156
+ ``ControlFlowPolicy.scan_unroll_limit`` to reach the unsupported-op path
157
+ (after a SCAN_UNROLL_SKIPPED warning). Since Phase 4, structured scan
158
+ descent handles over-limit ETP scans by default, so this pins the
159
+ opt-out path via ``ControlFlowPolicy(scan_descent='off')``."""
152
160
 
153
161
  class ScanModel(brainstate.nn.Module):
154
162
  def __init__(self):
@@ -160,15 +168,17 @@ def test_weight_used_inside_scan_raises_not_implemented():
160
168
  def update(self, x):
161
169
  def body(carry, _):
162
170
  return braintrace.matmul(carry, self.w.value), None # weight inside scan
163
- out, _ = jax.lax.scan(body, self.h.value, xs=None, length=2)
171
+ out, _ = jax.lax.scan(body, self.h.value, xs=None, length=64)
164
172
  self.h.value = jax.nn.tanh(out)
165
173
  return self.h.value
166
174
 
167
175
  model = ScanModel()
168
176
  brainstate.nn.init_all_states(model, batch_size=1)
169
- algo = braintrace.D_RTRL(model)
177
+ algo = braintrace.D_RTRL(
178
+ model, control_flow=braintrace.ControlFlowPolicy(scan_descent='off'))
170
179
  with pytest.raises(NotImplementedError):
171
- algo.compile_graph(jnp.ones((1, 4), dtype='float32'))
180
+ with pytest.warns(UserWarning, match='NOT unrolled'):
181
+ algo.compile_graph(jnp.ones((1, 4), dtype='float32'))
172
182
 
173
183
 
174
184
  # --- Task 6: legacy + nn deprecations emit DeprecationWarning ----------------
@@ -191,6 +201,14 @@ def test_nn_forwarded_name_warns():
191
201
  _ = nn.LayerNorm
192
202
 
193
203
 
204
+ def test_nn_forwarded_state_name_warns_and_resolves():
205
+ import brainpy.state
206
+ import braintrace.nn as nn
207
+ with pytest.warns(DeprecationWarning):
208
+ forwarded = nn.LIF
209
+ assert forwarded is brainpy.state.LIF
210
+
211
+
194
212
  def test_nn_unknown_name_raises_attribute_error():
195
213
  import braintrace.nn as nn
196
214
  with pytest.raises(AttributeError):
@@ -217,8 +235,20 @@ def test_iodim_lives_in_io_dim_vjp_module():
217
235
  def test_expected_rnn_cells_exist():
218
236
  import braintrace.nn as nn
219
237
  for cell in ('ValinaRNNCell', 'GRUCell', 'MGUCell', 'LSTMCell', 'URLSTMCell',
220
- 'MinimalRNNCell', 'MiniGRU', 'MiniLSTM', 'LRUCell'):
238
+ 'MinimalRNNCell', 'MiniGRU', 'MiniLSTM', 'LRUCell', 'CFNCell'):
221
239
  assert hasattr(nn, cell), f"missing cell: {cell}"
240
+ assert cell in nn.__all__, f"cell not in __all__: {cell}"
241
+
242
+
243
+ def test_nn_dir_advertises_deprecated_forwards():
244
+ # ``braintrace.nn.__getattr__`` forwards ~50 names to brainstate.nn /
245
+ # brainpy.state. Without ``__dir__`` none of them is discoverable, so the
246
+ # forwarding is invisible to tab-completion and to ``dir()``-based tooling.
247
+ import braintrace.nn as nn
248
+ names = dir(nn)
249
+ assert 'ReLU' in names # forwarded to brainstate.nn
250
+ assert 'LIF' in names # forwarded to brainpy.state
251
+ assert set(nn.__all__).issubset(names)
222
252
 
223
253
 
224
254
  # ===========================================================================
@@ -17,32 +17,40 @@
17
17
 
18
18
  Groups the core ETrace infrastructure (``ETraceAlgorithm``, ``EligibilityTrace``,
19
19
  ``ETraceGraphExecutor``), VJP-based algorithms (D-RTRL, pp_prop / ES-D-RTRL),
20
- and paper-faithful SNN algorithms (EProp, OSTLRecurrent, OSTLFeedforward, OTPE,
21
- OTTT, OSTTP).
20
+ and paper-faithful SNN algorithms (EProp, OSTLRecurrent, OSTLFeedforward).
22
21
  """
23
22
 
24
23
  from __future__ import annotations
25
24
 
26
- from ._common import FixedRandomFeedback, KappaFilter, PresynapticTrace
25
+ from ._common import FixedRandomFeedback, KappaFilter
26
+ from .axes import ETraceConfig
27
27
  from .base import ETraceAlgorithm, EligibilityTrace
28
28
  from .d_rtrl import D_RTRL
29
29
  from .e_prop import EProp
30
30
  from .graph_executor import ETraceGraphExecutor
31
31
  from .ostl import OSTLFeedforward, OSTLRecurrent
32
- from .osttp import OSTTP
33
- from .otpe import OTPE
34
- from .ottt import OTTT
35
32
  from .io_dim_vjp import IODimVjpAlgorithm
36
33
  from .param_dim_vjp import ParamDimVjpAlgorithm
34
+ from .random_projection_vjp import RandomProjectionVjpAlgorithm
37
35
  from .pp_prop import ES_D_RTRL, pp_prop # ES_D_RTRL: back-compat alias
36
+ from .sequence import ETraceVmap, SequenceDriverMixin
37
+ from .snap_n import SnAp
38
+ from .dni import DNI, SyntheticGradient, train_synthetic_gradient
39
+ from .three_factor import ThreeFactor
40
+ from .uoro import UORO
38
41
  from .vjp_base import ETraceVjpAlgorithm
39
42
  from .vjp_graph_executor import ETraceVjpGraphExecutor
40
43
 
41
44
  __all__ = [
45
+ # axes
46
+ 'ETraceConfig',
42
47
  # core
43
48
  'ETraceAlgorithm',
44
49
  'EligibilityTrace',
45
50
  'ETraceGraphExecutor',
51
+ # sequence drivers
52
+ 'ETraceVmap',
53
+ 'SequenceDriverMixin',
46
54
  # VJP
47
55
  'ETraceVjpAlgorithm',
48
56
  'ETraceVjpGraphExecutor',
@@ -51,14 +59,17 @@ __all__ = [
51
59
  'pp_prop',
52
60
  'ES_D_RTRL',
53
61
  'IODimVjpAlgorithm',
62
+ 'SnAp',
63
+ 'RandomProjectionVjpAlgorithm',
64
+ 'UORO',
65
+ 'ThreeFactor',
66
+ 'DNI',
67
+ 'SyntheticGradient',
68
+ 'train_synthetic_gradient',
54
69
  # SNN
55
70
  'EProp',
56
71
  'OSTLRecurrent',
57
72
  'OSTLFeedforward',
58
- 'OTPE',
59
- 'OTTT',
60
- 'OSTTP',
61
73
  'FixedRandomFeedback',
62
74
  'KappaFilter',
63
- 'PresynapticTrace',
64
75
  ]