braintrace 0.2.1__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {braintrace-0.2.1 → braintrace-0.2.3}/PKG-INFO +7 -4
- {braintrace-0.2.1 → braintrace-0.2.3}/README.md +1 -0
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/__init__.py +10 -6
- braintrace-0.2.1/braintrace/api_contract_test.py → braintrace-0.2.3/braintrace/__init___test.py +65 -19
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/__init__.py +2 -0
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/_common.py +21 -19
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/_common_test.py +2 -2
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/base.py +64 -11
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/base_test.py +25 -2
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/d_rtrl.py +2 -0
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/d_rtrl_test.py +182 -236
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/e_prop.py +14 -14
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/e_prop_test.py +32 -6
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/graph_executor.py +24 -64
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/graph_executor_test.py +1 -1
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/io_dim_vjp.py +44 -24
- braintrace-0.2.3/braintrace/_algorithm/io_dim_vjp_test.py +423 -0
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/oracle_test.py +29 -13
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/ostl.py +15 -10
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/ostl_test.py +44 -8
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/osttp.py +18 -11
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/osttp_test.py +33 -5
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/otpe.py +23 -21
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/otpe_test.py +30 -4
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/ottt.py +21 -19
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/ottt_test.py +30 -4
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/param_dim_vjp.py +124 -201
- braintrace-0.2.3/braintrace/_algorithm/param_dim_vjp_test.py +459 -0
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/pp_prop.py +4 -3
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/pp_prop_test.py +31 -5
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm/tests}/approx_correctness_test.py +2 -2
- braintrace-0.2.3/braintrace/_algorithm/tests/conv_vmap_correctness_test.py +327 -0
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm/tests}/cross_check_test.py +3 -3
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm/tests}/diagnostic_exploration_test.py +2 -5
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm/tests}/exact_correctness_test.py +2 -2
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm/tests}/public_api_test.py +1 -1
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm/tests}/scan_fusion_test.py +2 -2
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm/tests}/transform_correctness_test.py +3 -3
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/vjp_base.py +24 -10
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/vjp_base_test.py +5 -5
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/vjp_graph_executor.py +69 -64
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/vjp_graph_executor_test.py +1 -1
- braintrace-0.2.3/braintrace/_compile.py +302 -0
- braintrace-0.2.3/braintrace/_compile_test.py +435 -0
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/__init__.py +10 -7
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/base.py +2 -2
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/base_test.py +13 -9
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/diagnostics_test.py +1 -1
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/graph.py +15 -1
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/graph_test.py +1 -1
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/hid_param_op.py +2 -1
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/hid_param_op_test.py +4 -4
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/hidden_group.py +272 -13
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/hidden_group_test.py +268 -4
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/hidden_pertubation.py +3 -2
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/hidden_pertubation_test.py +2 -2
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/model4test.py +1 -1
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/module_info.py +1 -1
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/module_info_test.py +1 -1
- braintrace-0.2.3/braintrace/_compiler/report.py +231 -0
- braintrace-0.2.3/braintrace/_compiler/report_test.py +53 -0
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/scenario_catalog_test.py +46 -4
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler/tests}/cell_relation_guardrail_test.py +1 -1
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler/tests}/compiler_oracle_test.py +1 -1
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler/tests}/compiler_property_test.py +2 -2
- braintrace-0.2.3/braintrace/_docs_examples_test.py +247 -0
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/_etrace_model_test.py +1 -1
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/_grad_exponential.py +7 -5
- braintrace-0.2.3/braintrace/_grad_exponential_test.py +82 -0
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/_input_data.py +10 -8
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/_legacy/_ops.py +6 -6
- braintrace-0.2.3/braintrace/_legacy/_ops_test.py +185 -0
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/_legacy/_params.py +7 -7
- braintrace-0.2.1/braintrace/_legacy/_legacy_test.py → braintrace-0.2.3/braintrace/_legacy/_params_test.py +6 -134
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/_misc.py +14 -12
- braintrace-0.2.3/braintrace/_misc_test.py +163 -0
- {braintrace-0.2.1/braintrace/_etrace_op → braintrace-0.2.3/braintrace/_op}/__init__.py +10 -2
- {braintrace-0.2.1/braintrace/_etrace_op → braintrace-0.2.3/braintrace/_op}/_primitive.py +34 -21
- {braintrace-0.2.1/braintrace/_etrace_op → braintrace-0.2.3/braintrace/_op}/_primitive_test.py +1 -1
- {braintrace-0.2.1/braintrace/_etrace_op → braintrace-0.2.3/braintrace/_op}/_registries.py +71 -1
- {braintrace-0.2.1/braintrace/_etrace_op → braintrace-0.2.3/braintrace/_op}/_registries_test.py +16 -4
- {braintrace-0.2.1/braintrace/_etrace_op → braintrace-0.2.3/braintrace/_op}/conv.py +107 -28
- {braintrace-0.2.1/braintrace/_etrace_op → braintrace-0.2.3/braintrace/_op}/conv_test.py +50 -5
- {braintrace-0.2.1/braintrace/_etrace_op → braintrace-0.2.3/braintrace/_op}/dense.py +274 -43
- {braintrace-0.2.1/braintrace/_etrace_op → braintrace-0.2.3/braintrace/_op}/dense_test.py +215 -8
- braintrace-0.2.3/braintrace/_op/elemwise.py +421 -0
- braintrace-0.2.3/braintrace/_op/elemwise_test.py +394 -0
- {braintrace-0.2.1/braintrace/_etrace_op → braintrace-0.2.3/braintrace/_op}/lora.py +112 -26
- {braintrace-0.2.1/braintrace/_etrace_op → braintrace-0.2.3/braintrace/_op}/lora_test.py +39 -4
- {braintrace-0.2.1/braintrace/_etrace_op → braintrace-0.2.3/braintrace/_op}/op_rule_oracle_test.py +8 -8
- {braintrace-0.2.1/braintrace/_etrace_op → braintrace-0.2.3/braintrace/_op}/sparse.py +123 -33
- {braintrace-0.2.1/braintrace/_etrace_op → braintrace-0.2.3/braintrace/_op}/sparse_test.py +185 -21
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/_state_managment.py +0 -1
- braintrace-0.2.3/braintrace/_state_managment_test.py +108 -0
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/_typing.py +7 -1
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/_version.py +1 -1
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/nn/__init__.py +8 -4
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/nn/_conv.py +7 -2
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/nn/_conv_test.py +1 -1
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/nn/_linear.py +88 -24
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/nn/_linear_test.py +344 -14
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/nn/_readout.py +11 -9
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/nn/_readout_test.py +1 -1
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/nn/_rnn.py +60 -58
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/nn/_rnn_test.py +2 -2
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace.egg-info/PKG-INFO +7 -4
- braintrace-0.2.3/braintrace.egg-info/SOURCES.txt +121 -0
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace.egg-info/requires.txt +5 -3
- {braintrace-0.2.1 → braintrace-0.2.3}/pyproject.toml +92 -7
- braintrace-0.2.1/braintrace/_compile.py +0 -153
- braintrace-0.2.1/braintrace/_compile_test.py +0 -125
- braintrace-0.2.1/braintrace/_etrace_op/elemwise.py +0 -239
- braintrace-0.2.1/braintrace/_etrace_op/elemwise_test.py +0 -244
- braintrace-0.2.1/braintrace/legacy_deprecation_test.py +0 -53
- braintrace-0.2.1/braintrace.egg-info/SOURCES.txt +0 -112
- {braintrace-0.2.1 → braintrace-0.2.3}/LICENSE +0 -0
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/oracle.py +0 -0
- {braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/oracle_models.py +0 -0
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/_compatible_imports.py +0 -0
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/_compatible_imports_test.py +0 -0
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/diagnostics.py +0 -0
- {braintrace-0.2.1/braintrace/_etrace_compiler → braintrace-0.2.3/braintrace/_compiler}/scenario_catalog.py +0 -0
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/_input_data_test.py +0 -0
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/_legacy/__init__.py +0 -0
- {braintrace-0.2.1/braintrace/_etrace_op → braintrace-0.2.3/braintrace/_op}/op_rule_oracle.py +0 -0
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace/py.typed +0 -0
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace.egg-info/dependency_links.txt +0 -0
- {braintrace-0.2.1 → braintrace-0.2.3}/braintrace.egg-info/top_level.txt +0 -0
- {braintrace-0.2.1 → braintrace-0.2.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: braintrace
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
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,10 +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: brainstate>=0.
|
|
29
|
+
Requires-Dist: brainstate>=0.5.2
|
|
30
30
|
Requires-Dist: brainunit
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
Requires-Dist: brainpy
|
|
31
|
+
Requires-Dist: brainevent
|
|
32
|
+
Requires-Dist: brainpy.state
|
|
33
33
|
Requires-Dist: braintools
|
|
34
34
|
Provides-Extra: cpu
|
|
35
35
|
Requires-Dist: jax[cpu]; extra == "cpu"
|
|
@@ -41,10 +41,12 @@ Provides-Extra: tpu
|
|
|
41
41
|
Requires-Dist: jax[tpu]; extra == "tpu"
|
|
42
42
|
Provides-Extra: testing
|
|
43
43
|
Requires-Dist: pytest; extra == "testing"
|
|
44
|
+
Requires-Dist: pytest-cov; extra == "testing"
|
|
44
45
|
Requires-Dist: jax[cpu]; extra == "testing"
|
|
45
46
|
Requires-Dist: hypothesis; extra == "testing"
|
|
46
47
|
Provides-Extra: dev
|
|
47
48
|
Requires-Dist: pytest; extra == "dev"
|
|
49
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
48
50
|
Requires-Dist: jax[cpu]; extra == "dev"
|
|
49
51
|
Requires-Dist: hypothesis; extra == "dev"
|
|
50
52
|
Requires-Dist: mypy>=1.8; extra == "dev"
|
|
@@ -64,6 +66,7 @@ Dynamic: license-file
|
|
|
64
66
|
<a href="https://brainx.chaobrain.com/braintrace/"><img alt="Documentation" src="https://readthedocs.org/projects/braintrace/badge/?version=latest"></a>
|
|
65
67
|
<a href="https://badge.fury.io/py/braintrace"><img alt="PyPI version" src="https://badge.fury.io/py/braintrace.svg"></a>
|
|
66
68
|
<a href="https://github.com/chaobrain/braintrace/actions/workflows/CI.yml"><img alt="Continuous Integration" src="https://github.com/chaobrain/braintrace/actions/workflows/CI.yml/badge.svg"></a>
|
|
69
|
+
<a href="https://codecov.io/gh/chaobrain/braintrace"><img alt="Code Coverage" src="https://codecov.io/gh/chaobrain/braintrace/branch/main/graph/badge.svg"></a>
|
|
67
70
|
</p>
|
|
68
71
|
|
|
69
72
|
[``braintrace``](https://github.com/chaobrain/braintrace) provides online learning algorithms for biological neural networks.
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
<a href="https://brainx.chaobrain.com/braintrace/"><img alt="Documentation" src="https://readthedocs.org/projects/braintrace/badge/?version=latest"></a>
|
|
12
12
|
<a href="https://badge.fury.io/py/braintrace"><img alt="PyPI version" src="https://badge.fury.io/py/braintrace.svg"></a>
|
|
13
13
|
<a href="https://github.com/chaobrain/braintrace/actions/workflows/CI.yml"><img alt="Continuous Integration" src="https://github.com/chaobrain/braintrace/actions/workflows/CI.yml/badge.svg"></a>
|
|
14
|
+
<a href="https://codecov.io/gh/chaobrain/braintrace"><img alt="Code Coverage" src="https://codecov.io/gh/chaobrain/braintrace/branch/main/graph/badge.svg"></a>
|
|
14
15
|
</p>
|
|
15
16
|
|
|
16
17
|
[``braintrace``](https://github.com/chaobrain/braintrace) provides online learning algorithms for biological neural networks.
|
|
@@ -66,11 +66,13 @@ Examples
|
|
|
66
66
|
"""
|
|
67
67
|
|
|
68
68
|
|
|
69
|
-
from
|
|
69
|
+
from __future__ import annotations
|
|
70
|
+
|
|
71
|
+
from typing import TYPE_CHECKING, Any
|
|
70
72
|
|
|
71
73
|
from . import nn
|
|
72
74
|
from ._compile import compile
|
|
73
|
-
from .
|
|
75
|
+
from ._algorithm import (
|
|
74
76
|
ETraceAlgorithm,
|
|
75
77
|
EligibilityTrace,
|
|
76
78
|
ETraceGraphExecutor,
|
|
@@ -91,7 +93,7 @@ from ._etrace_algorithms import (
|
|
|
91
93
|
KappaFilter,
|
|
92
94
|
PresynapticTrace,
|
|
93
95
|
)
|
|
94
|
-
from .
|
|
96
|
+
from ._compiler import (
|
|
95
97
|
ETraceGraph,
|
|
96
98
|
compile_etrace_graph,
|
|
97
99
|
HiddenParamOpRelation,
|
|
@@ -106,10 +108,11 @@ from ._etrace_compiler import (
|
|
|
106
108
|
ModuleInfo,
|
|
107
109
|
extract_module_info,
|
|
108
110
|
CompilationRecord,
|
|
111
|
+
CompilationReport,
|
|
109
112
|
DiagnosticKind,
|
|
110
113
|
DiagnosticLevel,
|
|
111
114
|
)
|
|
112
|
-
from .
|
|
115
|
+
from ._op import (
|
|
113
116
|
ETPPrimitive,
|
|
114
117
|
matmul,
|
|
115
118
|
element_wise,
|
|
@@ -198,6 +201,7 @@ __all__ = [
|
|
|
198
201
|
|
|
199
202
|
# compiler diagnostics
|
|
200
203
|
'CompilationRecord',
|
|
204
|
+
'CompilationReport',
|
|
201
205
|
'DiagnosticKind',
|
|
202
206
|
'DiagnosticLevel',
|
|
203
207
|
|
|
@@ -242,7 +246,7 @@ _DEPRECATED_LEGACY = {
|
|
|
242
246
|
}
|
|
243
247
|
|
|
244
248
|
|
|
245
|
-
def __getattr__(name):
|
|
249
|
+
def __getattr__(name: str) -> Any:
|
|
246
250
|
if name in _DEPRECATED_LEGACY:
|
|
247
251
|
import warnings
|
|
248
252
|
warnings.warn(
|
|
@@ -256,5 +260,5 @@ def __getattr__(name):
|
|
|
256
260
|
raise AttributeError(f'module {__name__!r} has no attribute {name!r}')
|
|
257
261
|
|
|
258
262
|
|
|
259
|
-
def __dir__():
|
|
263
|
+
def __dir__() -> list[str]:
|
|
260
264
|
return sorted(list(__all__) + list(_DEPRECATED_LEGACY))
|
braintrace-0.2.1/braintrace/api_contract_test.py → braintrace-0.2.3/braintrace/__init___test.py
RENAMED
|
@@ -13,10 +13,18 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
# ==============================================================================
|
|
15
15
|
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
"""Tests for the ``braintrace`` package root (``braintrace/__init__.py``).
|
|
17
|
+
|
|
18
|
+
Two concerns, both owned by the package root:
|
|
19
|
+
|
|
20
|
+
* **Public-API contract** — every ``braintrace.__all__`` symbol resolves to a
|
|
21
|
+
usable object; public algorithms run a minimal end-to-end step; documented
|
|
22
|
+
error paths fire on their real triggers; legacy/nn deprecations warn; and the
|
|
23
|
+
implementation facts that drifted from CLAUDE.md (F-17) stay pinned.
|
|
24
|
+
* **Legacy deprecation forwarding** — the v0.1.x shims served lazily by
|
|
25
|
+
``__getattr__`` warn on access, stay out of ``__all__``, and appear in
|
|
26
|
+
``__dir__``.
|
|
27
|
+
"""
|
|
20
28
|
|
|
21
29
|
import brainstate
|
|
22
30
|
import jax
|
|
@@ -24,8 +32,13 @@ import jax.numpy as jnp
|
|
|
24
32
|
import pytest
|
|
25
33
|
|
|
26
34
|
import braintrace
|
|
27
|
-
|
|
35
|
+
import braintrace._legacy as legacy
|
|
36
|
+
from braintrace._algorithm.oracle_models import tanh_rnn
|
|
37
|
+
|
|
28
38
|
|
|
39
|
+
# ===========================================================================
|
|
40
|
+
# Public-API contract
|
|
41
|
+
# ===========================================================================
|
|
29
42
|
|
|
30
43
|
# --- Task 1: every __all__ symbol resolves to a non-None object --------------
|
|
31
44
|
|
|
@@ -130,18 +143,12 @@ def test_dynamic_weight_assignment_raises_not_supported():
|
|
|
130
143
|
|
|
131
144
|
# --- Task 5: weight inside control flow raises NotImplementedError -----------
|
|
132
145
|
|
|
133
|
-
@pytest.mark.xfail(
|
|
134
|
-
strict=True,
|
|
135
|
-
reason="F-SCAN-WEIGHT: the weight-in-control-flow guard intends to raise "
|
|
136
|
-
"NotImplementedError, but its error-message construction at "
|
|
137
|
-
"base.py:133 indexes invar_to_hidden_path with the *weight* var "
|
|
138
|
-
"(absent from that hidden-path map), so a KeyError escapes instead. "
|
|
139
|
-
"The guard fires, but the wrong exception type surfaces.",
|
|
140
|
-
)
|
|
141
146
|
def test_weight_used_inside_scan_raises_not_implemented():
|
|
142
|
-
"""check_unsupported_op
|
|
143
|
-
|
|
144
|
-
|
|
147
|
+
"""check_unsupported_op raises NotImplementedError when a weight var is used
|
|
148
|
+
within a control-flow op. Previously (F-SCAN-WEIGHT) the message construction
|
|
149
|
+
indexed the hidden-path map with the weight var and a KeyError escaped instead;
|
|
150
|
+
the message now renders the weight variable directly, so the intended
|
|
151
|
+
NotImplementedError surfaces."""
|
|
145
152
|
|
|
146
153
|
class ScanModel(brainstate.nn.Module):
|
|
147
154
|
def __init__(self):
|
|
@@ -193,8 +200,8 @@ def test_nn_unknown_name_raises_attribute_error():
|
|
|
193
200
|
# --- Task 7: lock the drifted implementation facts (F-17) --------------------
|
|
194
201
|
|
|
195
202
|
def test_ostl_is_two_classes_not_a_factory():
|
|
196
|
-
from braintrace.
|
|
197
|
-
from braintrace.
|
|
203
|
+
from braintrace._algorithm.param_dim_vjp import ParamDimVjpAlgorithm
|
|
204
|
+
from braintrace._algorithm.io_dim_vjp import IODimVjpAlgorithm
|
|
198
205
|
assert isinstance(braintrace.OSTLRecurrent, type)
|
|
199
206
|
assert isinstance(braintrace.OSTLFeedforward, type)
|
|
200
207
|
assert issubclass(braintrace.OSTLRecurrent, ParamDimVjpAlgorithm)
|
|
@@ -202,7 +209,7 @@ def test_ostl_is_two_classes_not_a_factory():
|
|
|
202
209
|
|
|
203
210
|
|
|
204
211
|
def test_iodim_lives_in_io_dim_vjp_module():
|
|
205
|
-
from braintrace.
|
|
212
|
+
from braintrace._algorithm.io_dim_vjp import IODimVjpAlgorithm
|
|
206
213
|
assert braintrace.IODimVjpAlgorithm is IODimVjpAlgorithm
|
|
207
214
|
assert braintrace.pp_prop is braintrace.ES_D_RTRL # aliases
|
|
208
215
|
|
|
@@ -212,3 +219,42 @@ def test_expected_rnn_cells_exist():
|
|
|
212
219
|
for cell in ('ValinaRNNCell', 'GRUCell', 'MGUCell', 'LSTMCell', 'URLSTMCell',
|
|
213
220
|
'MinimalRNNCell', 'MiniGRU', 'MiniLSTM', 'LRUCell'):
|
|
214
221
|
assert hasattr(nn, cell), f"missing cell: {cell}"
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
# ===========================================================================
|
|
225
|
+
# Legacy v0.1.x deprecation forwarding
|
|
226
|
+
# ===========================================================================
|
|
227
|
+
|
|
228
|
+
_LEGACY_NAMES = [
|
|
229
|
+
'ETraceOp', 'MatMulOp', 'ElemWiseOp', 'ConvOp', 'SpMatMulOp', 'LoraOp',
|
|
230
|
+
'ETraceParam', 'ElemWiseParam', 'NonTempParam',
|
|
231
|
+
'FakeETraceParam', 'FakeElemWiseParam',
|
|
232
|
+
]
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
@pytest.mark.parametrize('name', _LEGACY_NAMES)
|
|
236
|
+
def test_legacy_access_warns_and_returns_class(name):
|
|
237
|
+
with pytest.warns(DeprecationWarning):
|
|
238
|
+
obj = getattr(braintrace, name)
|
|
239
|
+
assert obj is getattr(legacy, name)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
@pytest.mark.parametrize('name', _LEGACY_NAMES)
|
|
243
|
+
def test_legacy_names_not_in_all(name):
|
|
244
|
+
assert name not in braintrace.__all__
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def test_from_import_warns():
|
|
248
|
+
with pytest.warns(DeprecationWarning):
|
|
249
|
+
from braintrace import MatMulOp # noqa: F401
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def test_unknown_attribute_raises_attribute_error():
|
|
253
|
+
with pytest.raises(AttributeError):
|
|
254
|
+
_ = braintrace.ThisNameDoesNotExist
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def test_legacy_names_in_dir():
|
|
258
|
+
d = dir(braintrace)
|
|
259
|
+
for name in _LEGACY_NAMES:
|
|
260
|
+
assert name in d
|
|
@@ -21,6 +21,8 @@ and paper-faithful SNN algorithms (EProp, OSTLRecurrent, OSTLFeedforward, OTPE,
|
|
|
21
21
|
OTTT, OSTTP).
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
24
26
|
from ._common import FixedRandomFeedback, KappaFilter, PresynapticTrace
|
|
25
27
|
from .base import ETraceAlgorithm, EligibilityTrace
|
|
26
28
|
from .d_rtrl import D_RTRL
|
{braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/_common.py
RENAMED
|
@@ -15,15 +15,17 @@
|
|
|
15
15
|
|
|
16
16
|
"""Shared helpers for the SNN online-learning algorithms."""
|
|
17
17
|
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
18
20
|
from functools import partial
|
|
19
21
|
from typing import Any, Dict, Optional
|
|
20
22
|
|
|
21
23
|
import brainstate
|
|
22
24
|
import jax
|
|
23
25
|
import jax.numpy as jnp
|
|
24
|
-
import
|
|
26
|
+
import brainunit as u
|
|
25
27
|
|
|
26
|
-
from braintrace._typing import PyTree
|
|
28
|
+
from braintrace._typing import ArrayLike, PyTree
|
|
27
29
|
|
|
28
30
|
__all__ = [
|
|
29
31
|
'PresynapticTrace',
|
|
@@ -42,12 +44,12 @@ class _ZeroResetState(brainstate.ShortTermState):
|
|
|
42
44
|
for ``batch_size`` (or prepended for scalar-shaped states).
|
|
43
45
|
"""
|
|
44
46
|
|
|
45
|
-
def __init__(self, init_value):
|
|
47
|
+
def __init__(self, init_value: Any) -> None:
|
|
46
48
|
super().__init__(init_value)
|
|
47
49
|
self._init_shape = jnp.shape(init_value)
|
|
48
50
|
self._init_dtype = init_value.dtype
|
|
49
51
|
|
|
50
|
-
def reset_state(self, batch_size: Optional[int] = None, **kwargs):
|
|
52
|
+
def reset_state(self, batch_size: Optional[int] = None, **kwargs: Any) -> None:
|
|
51
53
|
"""Re-zero the state at its original shape.
|
|
52
54
|
|
|
53
55
|
Parameters
|
|
@@ -105,13 +107,13 @@ class PresynapticTrace(_ZeroResetState):
|
|
|
105
107
|
|
|
106
108
|
__module__ = 'braintrace'
|
|
107
109
|
|
|
108
|
-
def __init__(self, init_value, leak: float):
|
|
110
|
+
def __init__(self, init_value: Any, leak: float) -> None:
|
|
109
111
|
super().__init__(init_value)
|
|
110
112
|
if not (0.0 < leak < 1.0):
|
|
111
113
|
raise ValueError(f'leak must be in (0, 1); got {leak}')
|
|
112
114
|
self.leak = float(leak)
|
|
113
115
|
|
|
114
|
-
def update(self, x):
|
|
116
|
+
def update(self, x: ArrayLike) -> Any:
|
|
115
117
|
r"""Apply one accumulation step :math:`\hat{a} \leftarrow \lambda \cdot \hat{a} + x`.
|
|
116
118
|
|
|
117
119
|
Parameters
|
|
@@ -163,13 +165,13 @@ class KappaFilter(_ZeroResetState):
|
|
|
163
165
|
|
|
164
166
|
__module__ = 'braintrace'
|
|
165
167
|
|
|
166
|
-
def __init__(self, init_value, kappa: float):
|
|
168
|
+
def __init__(self, init_value: Any, kappa: float) -> None:
|
|
167
169
|
super().__init__(init_value)
|
|
168
170
|
if not (0.0 <= kappa < 1.0):
|
|
169
171
|
raise ValueError(f'kappa must be in [0, 1); got {kappa}')
|
|
170
172
|
self.kappa = float(kappa)
|
|
171
173
|
|
|
172
|
-
def update(self, x):
|
|
174
|
+
def update(self, x: ArrayLike) -> Any:
|
|
173
175
|
r"""Apply one low-pass step :math:`x_{\mathrm{filt}} \leftarrow (1-\kappa) x + \kappa\, x_{\mathrm{filt}}`.
|
|
174
176
|
|
|
175
177
|
Parameters
|
|
@@ -230,14 +232,14 @@ class FixedRandomFeedback:
|
|
|
230
232
|
|
|
231
233
|
__module__ = 'braintrace'
|
|
232
234
|
|
|
233
|
-
def __init__(self, n_target: int, n_layer: int, key, init_scale: float = 0.1):
|
|
235
|
+
def __init__(self, n_target: int, n_layer: int, key: Any, init_scale: float = 0.1) -> None:
|
|
234
236
|
self.B = jax.lax.stop_gradient(
|
|
235
237
|
init_scale * jax.random.normal(key, (n_target, n_layer))
|
|
236
238
|
)
|
|
237
239
|
self.n_target = int(n_target)
|
|
238
240
|
self.n_layer = int(n_layer)
|
|
239
241
|
|
|
240
|
-
def project(self, y_target):
|
|
242
|
+
def project(self, y_target: Any) -> Any:
|
|
241
243
|
"""Project the target onto the frozen feedback matrix.
|
|
242
244
|
|
|
243
245
|
Parameters
|
|
@@ -267,7 +269,7 @@ def extract_y_target(args: tuple, *, index: int = -1) -> Optional[jax.Array]:
|
|
|
267
269
|
def _reset_state_in_a_dict(
|
|
268
270
|
state_dict: Dict[Any, brainstate.State],
|
|
269
271
|
batch_size: Optional[int],
|
|
270
|
-
):
|
|
272
|
+
) -> None:
|
|
271
273
|
"""
|
|
272
274
|
Reset the values in a dictionary of states to zero.
|
|
273
275
|
|
|
@@ -293,7 +295,7 @@ def _reset_state_in_a_dict(
|
|
|
293
295
|
def _zeros_like_batch_or_not(
|
|
294
296
|
batch_size: Optional[int],
|
|
295
297
|
x: jax.Array
|
|
296
|
-
):
|
|
298
|
+
) -> Any:
|
|
297
299
|
"""
|
|
298
300
|
Create a zeros array with the same shape and type as the input array,
|
|
299
301
|
optionally including a batch dimension.
|
|
@@ -325,7 +327,7 @@ def _batched_zeros_like(
|
|
|
325
327
|
batch_size: Optional[int],
|
|
326
328
|
num_state: int, # the number of hidden states
|
|
327
329
|
x: jax.Array # the input array
|
|
328
|
-
):
|
|
330
|
+
) -> Any:
|
|
329
331
|
"""
|
|
330
332
|
Create a batched zeros array with the same shape as the input array,
|
|
331
333
|
extended by the number of hidden states.
|
|
@@ -354,7 +356,7 @@ def _batched_zeros_like(
|
|
|
354
356
|
return u.math.zeros((batch_size, *x.shape, num_state), x.dtype)
|
|
355
357
|
|
|
356
358
|
|
|
357
|
-
def _sum_dim(xs: jax.Array, axis: int = -1):
|
|
359
|
+
def _sum_dim(xs: jax.Array, axis: int = -1) -> Any:
|
|
358
360
|
"""
|
|
359
361
|
Sums the elements along the last dimension of each array in a PyTree.
|
|
360
362
|
|
|
@@ -373,7 +375,7 @@ def _sum_dim(xs: jax.Array, axis: int = -1):
|
|
|
373
375
|
return jax.tree.map(lambda x: u.math.sum(x, axis=axis), xs)
|
|
374
376
|
|
|
375
377
|
|
|
376
|
-
def _unit_safe_add(a, b):
|
|
378
|
+
def _unit_safe_add(a: Any, b: Any) -> Any:
|
|
377
379
|
"""Add two leaves, stripping units only when one side has units and the other does not.
|
|
378
380
|
|
|
379
381
|
Gradient contributions for the same weight may come from paths that
|
|
@@ -390,7 +392,7 @@ def _unit_safe_add(a, b):
|
|
|
390
392
|
return u.math.add(a, b)
|
|
391
393
|
|
|
392
394
|
|
|
393
|
-
def _extract_leaf(pytree_val: PyTree, leaf_idx: int):
|
|
395
|
+
def _extract_leaf(pytree_val: PyTree, leaf_idx: int) -> Any:
|
|
394
396
|
"""Return the leaf at ``leaf_idx`` in ``jax.tree.leaves(pytree_val)``.
|
|
395
397
|
|
|
396
398
|
Bare arrays (treedef with a single leaf) return the array unchanged.
|
|
@@ -409,7 +411,7 @@ def _extract_leaf(pytree_val: PyTree, leaf_idx: int):
|
|
|
409
411
|
def _wrap_leaves_as_pytree(
|
|
410
412
|
reference_pytree: PyTree,
|
|
411
413
|
leaf_grads: Dict[int, jax.Array],
|
|
412
|
-
):
|
|
414
|
+
) -> Any:
|
|
413
415
|
"""Build a pytree matching ``reference_pytree`` with ``leaf_grads``
|
|
414
416
|
inserted at the given leaf indices; any other leaf is zero-filled.
|
|
415
417
|
|
|
@@ -441,7 +443,7 @@ def _wrap_leaves_as_pytree(
|
|
|
441
443
|
|
|
442
444
|
|
|
443
445
|
def _route_grads_by_path(
|
|
444
|
-
relation,
|
|
446
|
+
relation: Any,
|
|
445
447
|
per_key_grads: Dict[str, jax.Array],
|
|
446
448
|
weight_vals: Dict[Any, PyTree],
|
|
447
449
|
target_dict: Dict[Any, PyTree],
|
|
@@ -478,7 +480,7 @@ def _update_dict(
|
|
|
478
480
|
key: Any,
|
|
479
481
|
value: PyTree,
|
|
480
482
|
error_when_no_key: Optional[bool] = False
|
|
481
|
-
):
|
|
483
|
+
) -> None:
|
|
482
484
|
"""Update the dictionary.
|
|
483
485
|
|
|
484
486
|
If the key exists, then add the value to the existing value.
|
|
@@ -20,9 +20,9 @@ import jax
|
|
|
20
20
|
import jax.numpy as jnp
|
|
21
21
|
import numpy.testing as npt
|
|
22
22
|
import pytest
|
|
23
|
-
import
|
|
23
|
+
import brainunit as u
|
|
24
24
|
|
|
25
|
-
from braintrace.
|
|
25
|
+
from braintrace._algorithm._common import (
|
|
26
26
|
FixedRandomFeedback,
|
|
27
27
|
KappaFilter,
|
|
28
28
|
PresynapticTrace,
|
{braintrace-0.2.1/braintrace/_etrace_algorithms → braintrace-0.2.3/braintrace/_algorithm}/base.py
RENAMED
|
@@ -19,11 +19,13 @@
|
|
|
19
19
|
|
|
20
20
|
# -*- coding: utf-8 -*-
|
|
21
21
|
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
22
24
|
from typing import Dict, Any, Optional
|
|
23
25
|
|
|
24
26
|
import brainstate
|
|
25
27
|
|
|
26
|
-
from braintrace.
|
|
28
|
+
from braintrace._compiler import ETraceGraph, CompilationReport
|
|
27
29
|
from .graph_executor import ETraceGraphExecutor
|
|
28
30
|
from .._typing import Path
|
|
29
31
|
|
|
@@ -89,7 +91,7 @@ class ETraceAlgorithm(brainstate.nn.Module):
|
|
|
89
91
|
model: brainstate.nn.Module,
|
|
90
92
|
graph_executor: ETraceGraphExecutor,
|
|
91
93
|
name: Optional[str] = None,
|
|
92
|
-
):
|
|
94
|
+
) -> None:
|
|
93
95
|
super().__init__(name=name) # type: ignore[call-arg] # brainstate hides Module.__init__ from type checkers
|
|
94
96
|
|
|
95
97
|
# the model
|
|
@@ -131,6 +133,28 @@ class ETraceAlgorithm(brainstate.nn.Module):
|
|
|
131
133
|
"""
|
|
132
134
|
return self.graph_executor.graph
|
|
133
135
|
|
|
136
|
+
@property
|
|
137
|
+
def report(self) -> CompilationReport:
|
|
138
|
+
"""Structured, read-only report of the compiled eligibility-trace graph.
|
|
139
|
+
|
|
140
|
+
Returns
|
|
141
|
+
-------
|
|
142
|
+
CompilationReport
|
|
143
|
+
A view over :attr:`graph`.
|
|
144
|
+
|
|
145
|
+
Raises
|
|
146
|
+
------
|
|
147
|
+
RuntimeError
|
|
148
|
+
If accessed before the graph has been compiled.
|
|
149
|
+
"""
|
|
150
|
+
if not self.is_compiled:
|
|
151
|
+
raise RuntimeError(
|
|
152
|
+
'The eligibility-trace graph is not compiled yet. Build the '
|
|
153
|
+
'learner with braintrace.compile(...) (or call .compile_graph(...)) '
|
|
154
|
+
'before accessing .report.'
|
|
155
|
+
)
|
|
156
|
+
return CompilationReport(self.graph)
|
|
157
|
+
|
|
134
158
|
@property
|
|
135
159
|
def executor(self) -> ETraceGraphExecutor:
|
|
136
160
|
"""
|
|
@@ -188,7 +212,7 @@ class ETraceAlgorithm(brainstate.nn.Module):
|
|
|
188
212
|
assert self._other_states is not None
|
|
189
213
|
return self._other_states
|
|
190
214
|
|
|
191
|
-
def _split_state(self):
|
|
215
|
+
def _split_state(self) -> None:
|
|
192
216
|
# --- the state separation --- #
|
|
193
217
|
#
|
|
194
218
|
# [NOTE]
|
|
@@ -206,7 +230,7 @@ class ETraceAlgorithm(brainstate.nn.Module):
|
|
|
206
230
|
self._other_states
|
|
207
231
|
) = self.graph.module_info.retrieved_model_states.split(brainstate.ParamState, brainstate.HiddenState, ...)
|
|
208
232
|
|
|
209
|
-
def compile_graph(self, *args) -> None:
|
|
233
|
+
def compile_graph(self, *args: Any) -> None:
|
|
210
234
|
r"""
|
|
211
235
|
Compile the eligibility trace graph of the relationship between etrace weights, states and operators.
|
|
212
236
|
|
|
@@ -222,6 +246,18 @@ class ETraceAlgorithm(brainstate.nn.Module):
|
|
|
222
246
|
The input arguments.
|
|
223
247
|
"""
|
|
224
248
|
|
|
249
|
+
# ``vmap_new_states`` / ``vmap2_new_states`` run an eager *discovery
|
|
250
|
+
# probe* that executes the surrounding ``init`` (including this call)
|
|
251
|
+
# once against throwaway, un-batched states before the real mapped
|
|
252
|
+
# pass. Compiling there would bind the executor to those probe states
|
|
253
|
+
# (which are discarded and left untagged), so the subsequent
|
|
254
|
+
# ``brainstate.nn.Vmap(..., vmap_states='new')`` would not cover them
|
|
255
|
+
# and writing a batched value raises ``BatchAxisError``. Defer to the
|
|
256
|
+
# real mapped pass, which creates the 'new'-tagged batched states.
|
|
257
|
+
_in_probe = getattr(brainstate.transform, 'in_new_state_probe', None)
|
|
258
|
+
if _in_probe is not None and _in_probe():
|
|
259
|
+
return
|
|
260
|
+
|
|
225
261
|
if not self.is_compiled:
|
|
226
262
|
# --- invalidate cached state splits --- #
|
|
227
263
|
self._param_states = None
|
|
@@ -261,13 +297,30 @@ class ETraceAlgorithm(brainstate.nn.Module):
|
|
|
261
297
|
"""
|
|
262
298
|
return self.graph_executor.state_id_to_path
|
|
263
299
|
|
|
264
|
-
def show_graph(
|
|
265
|
-
|
|
266
|
-
|
|
300
|
+
def show_graph(
|
|
301
|
+
self,
|
|
302
|
+
verbose: bool = True,
|
|
303
|
+
return_msg: bool = False,
|
|
304
|
+
) -> None | str:
|
|
305
|
+
"""Display the eligibility-trace graph.
|
|
306
|
+
|
|
307
|
+
Delegates to :meth:`ETraceGraphExecutor.show_graph`.
|
|
308
|
+
|
|
309
|
+
Parameters
|
|
310
|
+
----------
|
|
311
|
+
verbose : bool, optional
|
|
312
|
+
If True (default), print the summary to stdout.
|
|
313
|
+
return_msg : bool, optional
|
|
314
|
+
If True, return the summary string. Default False.
|
|
315
|
+
|
|
316
|
+
Returns
|
|
317
|
+
-------
|
|
318
|
+
None or str
|
|
319
|
+
The summary string if ``return_msg`` is True, else None.
|
|
267
320
|
"""
|
|
268
|
-
self.graph_executor.show_graph()
|
|
321
|
+
return self.graph_executor.show_graph(verbose=verbose, return_msg=return_msg)
|
|
269
322
|
|
|
270
|
-
def __call__(self, *args) -> Any:
|
|
323
|
+
def __call__(self, *args: Any) -> Any:
|
|
271
324
|
"""
|
|
272
325
|
Update the model and the eligibility trace states.
|
|
273
326
|
|
|
@@ -283,7 +336,7 @@ class ETraceAlgorithm(brainstate.nn.Module):
|
|
|
283
336
|
"""
|
|
284
337
|
return self.update(*args)
|
|
285
338
|
|
|
286
|
-
def update(self, *args) -> Any:
|
|
339
|
+
def update(self, *args: Any) -> Any:
|
|
287
340
|
"""
|
|
288
341
|
Update the model and the eligibility trace states.
|
|
289
342
|
|
|
@@ -304,7 +357,7 @@ class ETraceAlgorithm(brainstate.nn.Module):
|
|
|
304
357
|
"""
|
|
305
358
|
raise NotImplementedError
|
|
306
359
|
|
|
307
|
-
def init_etrace_state(self, *args, **kwargs) -> None:
|
|
360
|
+
def init_etrace_state(self, *args: Any, **kwargs: Any) -> None:
|
|
308
361
|
"""
|
|
309
362
|
Initialize the eligibility trace states of the etrace algorithm.
|
|
310
363
|
|
|
@@ -21,8 +21,8 @@ import brainstate
|
|
|
21
21
|
import jax.numpy as jnp
|
|
22
22
|
|
|
23
23
|
import braintrace
|
|
24
|
-
from braintrace.
|
|
25
|
-
from braintrace.
|
|
24
|
+
from braintrace._algorithm import ETraceAlgorithm, EligibilityTrace
|
|
25
|
+
from braintrace._algorithm.graph_executor import ETraceGraphExecutor
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
# ---------------------------------------------------------------------------
|
|
@@ -580,5 +580,28 @@ class TestETraceAlgorithmTwoLayerIntegration(unittest.TestCase):
|
|
|
580
580
|
self.assertGreaterEqual(len(algo.hidden_states), 2)
|
|
581
581
|
|
|
582
582
|
|
|
583
|
+
def test_report_before_compile_raises():
|
|
584
|
+
import brainstate, pytest, braintrace
|
|
585
|
+
from braintrace._algorithm.oracle_models import tanh_rnn
|
|
586
|
+
model = tanh_rnn(n_in=3, n_rec=4, seed=0).factory()
|
|
587
|
+
brainstate.nn.init_all_states(model, batch_size=1)
|
|
588
|
+
algo = braintrace.D_RTRL(model)
|
|
589
|
+
with pytest.raises(RuntimeError):
|
|
590
|
+
_ = algo.report
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
def test_report_after_compile_matches_show_graph():
|
|
594
|
+
import brainstate, jax.numpy as jnp, braintrace
|
|
595
|
+
from braintrace import CompilationReport
|
|
596
|
+
from braintrace._algorithm.oracle_models import tanh_rnn
|
|
597
|
+
model = tanh_rnn(n_in=3, n_rec=4, seed=0).factory()
|
|
598
|
+
brainstate.nn.init_all_states(model, batch_size=1)
|
|
599
|
+
algo = braintrace.D_RTRL(model)
|
|
600
|
+
algo.compile_graph(jnp.ones((3,), 'float32'))
|
|
601
|
+
assert isinstance(algo.report, CompilationReport)
|
|
602
|
+
# show_graph(return_msg=True) is exactly report.to_str(1)
|
|
603
|
+
assert algo.show_graph(verbose=False, return_msg=True) == algo.report.to_str(1)
|
|
604
|
+
|
|
605
|
+
|
|
583
606
|
if __name__ == '__main__':
|
|
584
607
|
unittest.main()
|