diff --git a/brainpy/state/_lif.py b/brainpy/state/_lif.py
index 713f4fe2..cc34e463 100644
--- a/brainpy/state/_lif.py
+++ b/brainpy/state/_lif.py
@@ -248,6 +248,7 @@ def __init__(
V_reset: ArrayLike = 0. * u.mV,
V_rest: ArrayLike = 0. * u.mV,
V_initializer: Callable = braintools.init.Constant(0. * u.mV),
+ noise: ArrayLike = None,
spk_fun: Callable = braintools.surrogate.ReluGrad(),
spk_reset: str = 'soft',
name: str = None,
@@ -279,8 +280,8 @@ def update(self, x=0. * u.mA):
V_th = self.V_th if self.spk_reset == 'soft' else jax.lax.stop_gradient(last_v)
V = last_v - (V_th - self.V_reset) * last_spk
# membrane potential
- dv = lambda v: (-v + self.V_rest + self.R * self.sum_current_inputs(x, v)) / self.tau
- V = brainstate.nn.exp_euler_step(dv, V)
+ dv = lambda v, t: (-v + self.V_rest + self.R * self.sum_current_inputs(x, v)) / self.tau
+ V = braintools.quad.ode_expeuler_step(dv, V, None)
V = self.sum_delta_inputs(V)
self.V.value = V
return self.get_spike(V)
diff --git a/docs/conf.py b/docs/conf.py
index 4ceca504..9d5d0858 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -28,6 +28,7 @@
print(f"Error deleting {item}: {e}")
build_version = os.environ.get('CURRENT_VERSION', 'v2')
+build_version = os.environ.get('CURRENT_VERSION', 'v3')
if build_version == 'v2':
shutil.copytree(
os.path.join(os.path.dirname(__file__), '../docs_classic'),
diff --git a/docs_state/README.md b/docs_state/README.md
deleted file mode 100644
index 8d50d48b..00000000
--- a/docs_state/README.md
+++ /dev/null
@@ -1,112 +0,0 @@
-# BrainPy Version 3 Documentation
-
-This directory contains documentation for BrainPy 3.x, the latest major version of BrainPy.
-
-## Overview
-
-BrainPy 3.x is a flexible, efficient, and extensible framework for computational neuroscience and brain-inspired computation. It has been completely rewritten based on [brainstate](https://github.com/chaobrain/brainstate) (since August 2025) and provides powerful capabilities for building, simulating, and training spiking neural networks.
-
-## Documentation Contents
-
-This directory contains tutorial notebooks and API documentation:
-
-### Tutorials (Bilingual: English & Chinese)
-
-#### SNN Simulation
-- **snn_simulation-en.ipynb** - Building and simulating spiking neural networks (English)
-- **snn_simulation-zh.ipynb** - 构建和模拟脉冲神经网络 (Chinese)
-
-#### SNN Training
-- **snn_training-en.ipynb** - Training spiking neural networks with surrogate gradients (English)
-- **snn_training-zh.ipynb** - 使用代理梯度训练脉冲神经网络 (Chinese)
-
-#### Checkpointing
-- **checkpointing-en.ipynb** - Saving and loading model states (English)
-- **checkpointing-zh.ipynb** - 保存和加载模型状态 (Chinese)
-
-### API Reference
-- **apis.rst** - Complete API documentation
-- **index.rst** - Main documentation entry point
-
-## Key Features in Version 3.x
-
-- Built on [brainstate](https://github.com/chaobrain/brainstate) for improved state management
-- Enhanced support for spiking neural networks
-- Streamlined API for building neural models
-- Improved performance and scalability
-- Better integration with JAX ecosystem
-- Support for GPU/TPU acceleration
-
-## Installation
-
-```bash
-# CPU version
-pip install -U brainpy[cpu]
-
-# GPU version (CUDA 12)
-pip install -U brainpy[cuda12]
-
-# GPU version (CUDA 13)
-pip install -U brainpy[cuda13]
-
-# TPU version
-pip install -U brainpy[tpu]
-
-# Full ecosystem
-pip install -U BrainX
-```
-
-## Quick Start
-
-```python
-import brainpy
-import brainstate
-import brainunit as u
-
-# Define a simple LIF neuron
-neuron = brainpy.LIF(100, V_rest=-60.*u.mV, V_th=-50.*u.mV)
-
-# Initialize and simulate
-brainstate.nn.init_all_states(neuron)
-spikes = neuron(1.*u.mA)
-```
-
-## Migration from Version 2.x
-
-If you're migrating from BrainPy 2.x, the API has changed significantly. See the migration guide in the main documentation for details.
-
-To use legacy 2.x APIs in version 3.x:
-
-```python
-import brainpy as bp
-import brainpy.math as bm
-```
-
-## Running Notebooks
-
-The tutorial notebooks can be run using Jupyter:
-
-```bash
-jupyter notebook snn_simulation-en.ipynb
-```
-
-Or with JupyterLab:
-
-```bash
-jupyter lab
-```
-
-## Building Documentation
-
-If you need to build the documentation locally, this directory is part of the larger documentation system. Please refer to the main documentation build instructions.
-
-## Learn More
-
-- [Main Documentation](https://brainpy.readthedocs.io)
-- [BrainPy GitHub](https://github.com/brainpy/BrainPy)
-- [BrainState GitHub](https://github.com/chaobrain/brainstate)
-- [BrainPy Ecosystem](https://brainmodeling.readthedocs.io)
-
-## Contributing
-
-Contributions to documentation are welcome! Please submit issues or pull requests to the [BrainPy repository](https://github.com/brainpy/BrainPy).
diff --git a/docs_state/api/index.rst b/docs_state/api/index.rst
index 32ab8814..93d31428 100644
--- a/docs_state/api/index.rst
+++ b/docs_state/api/index.rst
@@ -1,7 +1,7 @@
API Reference
=============
-Complete API reference for ``brainpy.state``
+Complete API reference for ``brainpy.state``.
.. note::
``brainpy.state`` is built on top of `brainstate `_,
@@ -49,10 +49,8 @@ The API is organized into the following categories:
Spike and current generators (PoissonSpike, SpikeTime)
-Quick Reference
----------------
-
-**Most commonly used classes:**
+Example Reference
+-----------------
Neurons
~~~~~~~
@@ -184,6 +182,7 @@ Readout Layers
brainpy.state.LeakySpikeReadout(in_size=100, tau=5*u.ms, V_th=1*u.mV)
.. toctree::
+ :hidden:
:maxdepth: 2
neurons
@@ -192,4 +191,4 @@ Readout Layers
synouts
stp
readouts
- inputs
\ No newline at end of file
+ inputs
diff --git a/docs_state/apis.rst b/docs_state/apis.rst
deleted file mode 100644
index 205eca94..00000000
--- a/docs_state/apis.rst
+++ /dev/null
@@ -1,115 +0,0 @@
-API Reference
-=============
-
-This page provides a comprehensive reference for all BrainPy APIs.
-
-.. currentmodule:: brainpy.state
-.. automodule:: brainpy.state
-
-
-
-Neuron Models
--------------
-
-.. autosummary::
- :toctree: generated/
- :nosignatures:
- :template: classtemplate.rst
-
- Neuron
- LIF
- LIFRef
- ALIF
- Izhikevich
- IF
- ExpIF
- AdExIF
-
-
-Synapse Models
---------------
-
-.. autosummary::
- :toctree: generated/
- :nosignatures:
- :template: classtemplate.rst
-
-
- Synapse
- Delta
- Exponential
- DualExponential
- Alpha
- NMDA
- AMPA
- GABAa
-
-
-Short-Term Plasticity
----------------------
-
-.. autosummary::
- :toctree: generated/
- :nosignatures:
- :template: classtemplate.rst
-
-
- STP
- STD
- STF
-
-
-Synaptic Output
----------------
-
-.. autosummary::
- :toctree: generated/
- :nosignatures:
- :template: classtemplate.rst
-
-
- CUBA
- COBA
- MgBlock
-
-
-Projection
-----------
-
-.. autosummary::
- :toctree: generated/
- :nosignatures:
- :template: classtemplate.rst
-
-
- Projection
- FullProjDelta
- FullProjAlignPostDelta
-
-
-Readout
--------
-
-.. autosummary::
- :toctree: generated/
- :nosignatures:
- :template: classtemplate.rst
-
-
- Readout
- Dense
- Linear
-
-
-Input Generators
-----------------
-
-.. autosummary::
- :toctree: generated/
- :nosignatures:
- :template: classtemplate.rst
-
-
- spike_input
- latency_input
-
diff --git a/docs_state/examples/gallery.rst b/docs_state/examples/gallery.rst
index f94f17df..fe05b821 100644
--- a/docs_state/examples/gallery.rst
+++ b/docs_state/examples/gallery.rst
@@ -142,9 +142,6 @@ Series of models exploring different gamma generation mechanisms:
- Excitatory-inhibitory interaction
-**Combined**: `Susin_Destexhe_2021_gamma_oscillation.py `_ - All mechanisms
-
-**Key Concepts**: Gamma mechanisms, network states, oscillation generation
Spiking Neural Network Training
--------------------------------
diff --git a/docs_state/index.rst b/docs_state/index.rst
index e84482a3..97e6865d 100644
--- a/docs_state/index.rst
+++ b/docs_state/index.rst
@@ -112,7 +112,7 @@ Learn more
.. card:: :material-regular:`data_exploration;2em` ``brainpy`` APIs
:class-card: sd-text-black sd-bg-light
- :link: https://brainpy.readthedocs.io/
+ :link: https://brainpy.readthedocs.io
----
@@ -131,7 +131,6 @@ See also the ecosystem
:caption: Tutorials
quickstart/index.rst
- tutorials/index.rst
examples/gallery.rst
diff --git a/docs_state/quickstart/core-concepts/architecture.ipynb b/docs_state/quickstart/core-concepts/architecture.ipynb
index 7404dc22..c890f957 100644
--- a/docs_state/quickstart/core-concepts/architecture.ipynb
+++ b/docs_state/quickstart/core-concepts/architecture.ipynb
@@ -4,7 +4,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "# Architecture Overview\n",
+ "# Overview\n",
"\n",
"``brainpy.state`` represents a complete architectural redesign built on top of the ``brainstate`` framework. This document explains the design principles and architectural components that make ``brainpy.state`` powerful and flexible."
]
@@ -96,16 +96,19 @@
"source": [
"## State Management System\n",
"\n",
- "### The Foundation: brainstate.State\n",
+ "### The Foundation: ``brainstate.State``\n",
"\n",
"Everything in ``brainpy.state`` revolves around **states**:"
]
},
{
"cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:08.201528Z",
+ "start_time": "2025-11-13T09:31:02.936126Z"
+ }
+ },
"source": [
"import brainpy\n",
"import brainstate\n",
@@ -116,7 +119,9 @@
"# Create a state\n",
"voltage = brainstate.State(0.0) # Single value\n",
"weights = brainstate.State([[0.1, 0.2], [0.3, 0.4]]) # Matrix"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 1
},
{
"cell_type": "markdown",
@@ -144,16 +149,21 @@
},
{
"cell_type": "code",
- "execution_count": 18,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:08.232382Z",
+ "start_time": "2025-11-13T09:31:08.227046Z"
+ }
+ },
"source": [
"class MyNeuron(brainstate.nn.Module):\n",
" def __init__(self):\n",
" super().__init__()\n",
" self.tau = brainstate.ParamState(10.0) # Trainable\n",
" self.weight = brainstate.ParamState([[0.1, 0.2]])"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 2
},
{
"cell_type": "markdown",
@@ -165,16 +175,21 @@
},
{
"cell_type": "code",
- "execution_count": 19,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:08.256361Z",
+ "start_time": "2025-11-13T09:31:08.248156Z"
+ }
+ },
"source": [
"class MyNeuron(brainstate.nn.Module):\n",
" def __init__(self, size):\n",
" super().__init__()\n",
" self.V = brainstate.ShortTermState(jnp.zeros(size)) # Dynamic\n",
" self.spike = brainstate.ShortTermState(jnp.zeros(size))"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 3
},
{
"cell_type": "markdown",
@@ -187,9 +202,12 @@
},
{
"cell_type": "code",
- "execution_count": 20,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:08.332155Z",
+ "start_time": "2025-11-13T09:31:08.288203Z"
+ }
+ },
"source": [
"# Define example size and shape\n",
"size = 100 # Number of neurons\n",
@@ -209,7 +227,9 @@
"weights = brainstate.ParamState(\n",
" braintools.init.Uniform(0.0, 1.0)(shape)\n",
")"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 4
},
{
"cell_type": "markdown",
@@ -224,9 +244,12 @@
},
{
"cell_type": "code",
- "execution_count": 21,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:08.344089Z",
+ "start_time": "2025-11-13T09:31:08.338163Z"
+ }
+ },
"source": [
"class MyComponent(brainstate.nn.Module):\n",
" def __init__(self, size):\n",
@@ -238,7 +261,9 @@
" def update(self, input):\n",
" # Define dynamics\n",
" pass"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 5
},
{
"cell_type": "markdown",
@@ -258,26 +283,23 @@
"source": [
"### Module Composition\n",
"\n",
- "Modules can contain other modules:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 22,
- "metadata": {},
- "outputs": [],
- "source": [
+ "Modules can contain other modules:\n",
+ "\n",
+ "```python\n",
+ "\n",
"class Network(brainstate.nn.Module):\n",
" def __init__(self):\n",
" super().__init__()\n",
" self.neurons = brainpy.state.LIF(100, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
" self.synapse = brainpy.state.Expon(100, tau=5*u.ms)\n",
- " # self.projection = brainpy.state.AlignPostProj(...) # Example - requires more setup\n",
+ " self.projection = brainpy.state.AlignPostProj(...) # Example - requires more setup\n",
"\n",
" def update(self, input):\n",
" # Compose behavior\n",
- " # self.projection(spikes) # Example\n",
- " self.neurons(input)"
+ " self.projection(spikes) # Example\n",
+ " self.neurons(input)\n",
+ "\n",
+ "```\n"
]
},
{
@@ -293,9 +315,12 @@
},
{
"cell_type": "code",
- "execution_count": 23,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:08.354960Z",
+ "start_time": "2025-11-13T09:31:08.350705Z"
+ }
+ },
"source": [
"class Neuron(brainstate.nn.Module):\n",
" def __init__(self, size, **kwargs):\n",
@@ -309,7 +334,9 @@
" # Update membrane potential\n",
" # Generate spikes\n",
" pass"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 6
},
{
"cell_type": "markdown",
@@ -334,9 +361,12 @@
},
{
"cell_type": "code",
- "execution_count": 24,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:08.365530Z",
+ "start_time": "2025-11-13T09:31:08.361447Z"
+ }
+ },
"source": [
"class Synapse(brainstate.nn.Module):\n",
" def __init__(self, size, tau, **kwargs):\n",
@@ -349,7 +379,9 @@
" # Update synaptic variable\n",
" # Return filtered output\n",
" pass"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 7
},
{
"cell_type": "markdown",
@@ -383,9 +415,12 @@
},
{
"cell_type": "code",
- "execution_count": 25,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:08.380053Z",
+ "start_time": "2025-11-13T09:31:08.371055Z"
+ }
+ },
"source": [
"# Define population sizes\n",
"pre_size = 100\n",
@@ -398,7 +433,9 @@
"comm = brainstate.nn.EventFixedProb(\n",
" pre_size, post_size, prob, weight\n",
")"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 8
},
{
"cell_type": "markdown",
@@ -410,14 +447,19 @@
},
{
"cell_type": "code",
- "execution_count": 26,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:08.390544Z",
+ "start_time": "2025-11-13T09:31:08.386339Z"
+ }
+ },
"source": [
"post_size = 50 # Postsynaptic population size\n",
"\n",
- "syn = brainpy.state.Expon.desc(post_size, tau=5*u.ms)"
- ]
+ "syn = brainpy.state.Expon(post_size, tau=5*u.ms)"
+ ],
+ "outputs": [],
+ "execution_count": 9
},
{
"cell_type": "markdown",
@@ -429,16 +471,21 @@
},
{
"cell_type": "code",
- "execution_count": 27,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:08.400227Z",
+ "start_time": "2025-11-13T09:31:08.397246Z"
+ }
+ },
"source": [
"# Current-based output\n",
- "out = brainpy.state.CUBA.desc() \n",
+ "out = brainpy.state.CUBA() \n",
"\n",
"# Or conductance-based output\n",
- "out = brainpy.state.COBA.desc(E=0*u.mV)"
- ]
+ "out = brainpy.state.COBA(E=0*u.mV)"
+ ],
+ "outputs": [],
+ "execution_count": 10
},
{
"cell_type": "markdown",
@@ -449,9 +496,12 @@
},
{
"cell_type": "code",
- "execution_count": 28,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:08.420603Z",
+ "start_time": "2025-11-13T09:31:08.405533Z"
+ }
+ },
"source": [
"# Define postsynaptic neurons\n",
"postsynaptic_neurons = brainpy.state.LIF(50, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
@@ -463,7 +513,9 @@
" out=out,\n",
" post=postsynaptic_neurons\n",
")"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 11
},
{
"cell_type": "markdown",
@@ -490,24 +542,12 @@
},
{
"cell_type": "code",
- "execution_count": 29,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "application/vnd.jupyter.widget-view+json": {
- "model_id": "21a5af1809d8460f8ff309173e9c3646",
- "version_major": 2,
- "version_minor": 0
- },
- "text/plain": [
- " 0%| | 0/10000 [00:00, ?it/s]"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:08.937334Z",
+ "start_time": "2025-11-13T09:31:08.430048Z"
}
- ],
+ },
"source": [
"# Example: create a simple network\n",
"class SimpleNetwork(brainstate.nn.Module):\n",
@@ -539,7 +579,27 @@
" indices,\n",
" pbar=brainstate.transform.ProgressBar(10)\n",
")"
- ]
+ ],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 0%| | 0/10000 [00:00, ?it/s]"
+ ],
+ "application/vnd.jupyter.widget-view+json": {
+ "version_major": 2,
+ "version_minor": 0,
+ "model_id": "53f4cd22f9f54b9494d7457134633d41"
+ }
+ },
+ "metadata": {},
+ "output_type": "display_data",
+ "jetTransient": {
+ "display_id": null
+ }
+ }
+ ],
+ "execution_count": 12
},
{
"cell_type": "markdown",
@@ -552,9 +612,12 @@
},
{
"cell_type": "code",
- "execution_count": 30,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:09.104741Z",
+ "start_time": "2025-11-13T09:31:08.980341Z"
+ }
+ },
"source": [
"# Create example input\n",
"input_example = jnp.ones(100) * 2.0 * u.nA\n",
@@ -569,7 +632,9 @@
"\n",
"# Subsequent calls: fast\n",
"result = simulate_step(0.1*u.ms, 1, input_example) # Fast (compiled)"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 13
},
{
"cell_type": "markdown",
@@ -594,17 +659,12 @@
},
{
"cell_type": "code",
- "execution_count": 31,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Loss (no trainable params): 0.0\n"
- ]
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:09.356118Z",
+ "start_time": "2025-11-13T09:31:09.113521Z"
}
- ],
+ },
"source": [
"# Example: Define mock functions for demonstration\n",
"def compute_loss(predictions, targets):\n",
@@ -630,6 +690,7 @@
"\n",
"# Compute gradients\n",
"if len(params) > 0:\n",
+ " optimizer = braintools.optim.Adam(lr=1e-3)\n",
" grads, loss = brainstate.transform.grad(\n",
" loss_fn,\n",
" grad_states=params,\n",
@@ -637,12 +698,22 @@
" )()\n",
" print(f\"Loss: {loss}\")\n",
" # Update parameters with optimizer (if defined)\n",
- " # optimizer.update(grads)\n",
+ " optimizer.update(grads)\n",
"else:\n",
" # If no trainable parameters, just compute loss\n",
" loss = loss_fn()\n",
" print(f\"Loss (no trainable params): {loss}\")"
- ]
+ ],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Loss (no trainable params): 0.0\n"
+ ]
+ }
+ ],
+ "execution_count": 14
},
{
"cell_type": "markdown",
@@ -657,9 +728,12 @@
},
{
"cell_type": "code",
- "execution_count": 32,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:09.386693Z",
+ "start_time": "2025-11-13T09:31:09.382194Z"
+ }
+ },
"source": [
"# Define with units\n",
"tau = 10 * u.ms\n",
@@ -668,7 +742,9 @@
"\n",
"# Units are checked automatically\n",
"neuron = brainpy.state.LIF(100, tau=tau, V_th=threshold)"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 15
},
{
"cell_type": "markdown",
@@ -691,9 +767,12 @@
},
{
"cell_type": "code",
- "execution_count": 33,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:09.432404Z",
+ "start_time": "2025-11-13T09:31:09.427692Z"
+ }
+ },
"source": [
"# Arithmetic with units\n",
"total_time = 100 * u.ms + 0.5 * u.second # → 600 ms\n",
@@ -705,7 +784,9 @@
"voltage = -65 * u.mV\n",
"current = 2 * u.nA\n",
"resistance = voltage / current # Automatically gives MΩ"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 16
},
{
"cell_type": "markdown",
@@ -722,9 +803,12 @@
},
{
"cell_type": "code",
- "execution_count": 34,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:09.471630Z",
+ "start_time": "2025-11-13T09:31:09.465919Z"
+ }
+ },
"source": [
"# Optimizers\n",
"optimizer = braintools.optim.Adam(lr=1e-3)\n",
@@ -739,7 +823,9 @@
"# pred = jnp.array([0.1, 0.9])\n",
"# target = jnp.array([0, 1])\n",
"# loss = braintools.metric.cross_entropy(pred, target)"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 17
},
{
"cell_type": "markdown",
@@ -752,15 +838,20 @@
},
{
"cell_type": "code",
- "execution_count": 35,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:09.496064Z",
+ "start_time": "2025-11-13T09:31:09.490951Z"
+ }
+ },
"source": [
"# All standard SI units\n",
"time = 10 * u.ms\n",
"voltage = -65 * u.mV\n",
"current = 2 * u.nA"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 18
},
{
"cell_type": "markdown",
@@ -773,9 +864,12 @@
},
{
"cell_type": "code",
- "execution_count": 37,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:31:09.518362Z",
+ "start_time": "2025-11-13T09:31:09.512404Z"
+ }
+ },
"source": [
"import brainstate\n",
"\n",
@@ -792,160 +886,9 @@
"\n",
"# Transformations\n",
"# result = brainstate.transform.for_loop(...)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Data Flow Example\n",
- "\n",
- "Here's how data flows through a typical ``brainpy.state`` simulation:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 38,
- "metadata": {},
+ ],
"outputs": [],
- "source": [
- "# 1. Define network\n",
- "class EINetwork(brainstate.nn.Module):\n",
- " def __init__(self):\n",
- " super().__init__()\n",
- " self.E = brainpy.state.LIF(800, V_rest=-65*u.mV, V_th=-50*u.mV, tau=15*u.ms)\n",
- " self.I = brainpy.state.LIF(200, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- " \n",
- " # Example projections (simplified - full setup requires more code)\n",
- " # self.E2E = brainpy.state.AlignPostProj(...)\n",
- " # self.E2I = brainpy.state.AlignPostProj(...)\n",
- " # self.I2E = brainpy.state.AlignPostProj(...)\n",
- " # self.I2I = brainpy.state.AlignPostProj(...)\n",
- "\n",
- " def update(self, input):\n",
- " # Get spikes from last time step\n",
- " e_spikes = self.E.get_spike()\n",
- " i_spikes = self.I.get_spike()\n",
- "\n",
- " # Update projections (spikes → synaptic currents)\n",
- " # self.E2E(e_spikes) # Updates E2E.syn.g\n",
- " # self.E2I(e_spikes)\n",
- " # self.I2E(i_spikes)\n",
- " # self.I2I(i_spikes)\n",
- "\n",
- " # Update neurons (currents → new V and spikes)\n",
- " self.E(input[:800] if len(input) >= 800 else input)\n",
- " self.I(input[800:] if len(input) > 800 else jnp.zeros(200) * u.nA)\n",
- "\n",
- " return e_spikes, i_spikes\n",
- "\n",
- "# 2. Initialize\n",
- "net = EINetwork()\n",
- "brainstate.nn.init_all_states(net)\n",
- "\n",
- "# 3. Compile\n",
- "@brainstate.transform.jit\n",
- "def step(input):\n",
- " return net.update(input)\n",
- "\n",
- "# 4. Simulate (commented out for quick execution)\n",
- "# times = u.math.arange(0*u.ms, 1000*u.ms, 0.1*u.ms)\n",
- "# results = brainstate.transform.for_loop(step, times)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "State Flow:\n",
- "\n",
- "```text\n",
- "Time t:\n",
- "┌──────────────────────────────────────────┐\n",
- "│ States at t-1: │\n",
- "│ E.V[t-1], E.spike[t-1] │\n",
- "│ I.V[t-1], I.spike[t-1] │\n",
- "│ E2E.syn.g[t-1], ... │\n",
- "└──────────────────────────────────────────┘\n",
- " ↓\n",
- "┌──────────────────────────────────────────┐\n",
- "│ Projection Updates: │\n",
- "│ E2E.syn.g[t] = f(g[t-1], E.spike[t-1])│\n",
- "│ ... (other projections) │\n",
- "└──────────────────────────────────────────┘\n",
- " ↓\n",
- "┌──────────────────────────────────────────┐\n",
- "│ Neuron Updates: │\n",
- "│ E.V[t] = f(V[t-1], Σ currents[t]) │\n",
- "│ E.spike[t] = E.V[t] >= V_th │\n",
- "│ ... (other neurons) │\n",
- "└──────────────────────────────────────────┘\n",
- " ↓\n",
- "Time t+1...\n",
- "```"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Performance Considerations\n",
- "\n",
- "### Memory Management\n",
- "\n",
- "- States are preallocated\n",
- "- In-place updates when possible\n",
- "- Efficient batching support\n",
- "- Automatic garbage collection\n",
- "\n",
- "### Compilation Strategy\n",
- "\n",
- "- Compile simulation loops\n",
- "- Batch operations when possible\n",
- "- Use ``for_loop`` for long sequences\n",
- "- Leverage JAX's XLA optimization\n",
- "\n",
- "### Hardware Acceleration\n",
- "\n",
- "- Automatic GPU dispatch for large arrays\n",
- "- TPU support for massive parallelism\n",
- "- Efficient CPU fallback for small problems"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Summary\n",
- "\n",
- "``brainpy.state`` 's architecture provides:\n",
- "\n",
- "✅ **Clear Abstractions**: Neurons, synapses, and projections with well-defined roles\n",
- "\n",
- "✅ **State Management**: Explicit, efficient handling of dynamical variables\n",
- "\n",
- "✅ **Modularity**: Compose complex models from simple components\n",
- "\n",
- "✅ **Performance**: JIT compilation and hardware acceleration\n",
- "\n",
- "✅ **Scientific Accuracy**: Integrated physical units\n",
- "\n",
- "✅ **Extensibility**: Easy to add custom components\n",
- "\n",
- "✅ **Modern Design**: Built on proven frameworks (JAX, brainstate)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Next Steps\n",
- "\n",
- "- Learn about specific components: [neurons](neurons.ipynb), [synapses](synapses.ipynb), [projections](projections.ipynb)\n",
- "- Understand state management in depth: [state-management](state-management.ipynb)\n",
- "- See practical examples in the [tutorials](../tutorials/basic/01-lif-neuron.ipynb)\n",
- "- Explore the ecosystem: [brainstate docs](https://brainstate.readthedocs.io/)"
- ]
+ "execution_count": 19
}
],
"metadata": {
diff --git a/docs_state/quickstart/core-concepts/index.rst b/docs_state/quickstart/core-concepts/index.rst
index 92e14c70..50bf2270 100644
--- a/docs_state/quickstart/core-concepts/index.rst
+++ b/docs_state/quickstart/core-concepts/index.rst
@@ -19,7 +19,6 @@ The core concepts of ``brainpy.state`` include:
- **Neurons**: Building blocks for neural computation, including different neuron models and their state representations
- **Synapses**: Connections between neurons that transmit signals and implement learning rules
- **Projections**: Network-level structures that organize and manage connections between populations of neurons
-- **State Management**: The powerful state handling system that enables efficient simulation and flexible model composition
Why these concepts matter
@@ -44,6 +43,5 @@ Each concept builds upon the previous ones, so we recommend reading them in orde
neurons.ipynb
synapses.ipynb
projections.ipynb
- state-management.ipynb
diff --git a/docs_state/quickstart/core-concepts/neurons.ipynb b/docs_state/quickstart/core-concepts/neurons.ipynb
index 74b6147d..d558803b 100644
--- a/docs_state/quickstart/core-concepts/neurons.ipynb
+++ b/docs_state/quickstart/core-concepts/neurons.ipynb
@@ -25,14 +25,46 @@
]
},
{
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:26.859882Z",
+ "start_time": "2025-11-13T09:26:26.856372Z"
+ }
+ },
"cell_type": "code",
- "execution_count": 20,
- "metadata": {},
- "outputs": [],
"source": [
+ "import numpy as np\n",
+ "\n",
"import brainpy\n",
+ "import brainstate\n",
+ "import braintools\n",
"import brainunit as u\n",
- "\n",
+ "import jax.numpy as jnp"
+ ],
+ "outputs": [],
+ "execution_count": 62
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:26.892571Z",
+ "start_time": "2025-11-13T09:26:26.882259Z"
+ }
+ },
+ "cell_type": "code",
+ "source": "brainstate.environ.set(dt=0.1 * u.ms)",
+ "outputs": [],
+ "execution_count": 63
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:26.904598Z",
+ "start_time": "2025-11-13T09:26:26.900474Z"
+ }
+ },
+ "source": [
"# Create a population of 100 LIF neurons\n",
"neurons = brainpy.state.LIF(\n",
" in_size=100,\n",
@@ -41,7 +73,9 @@
" V_reset=-65. * u.mV,\n",
" tau=10. * u.ms\n",
")"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 64
},
{
"cell_type": "markdown",
@@ -54,8 +88,19 @@
},
{
"cell_type": "code",
- "execution_count": 21,
- "metadata": {},
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:26.923422Z",
+ "start_time": "2025-11-13T09:26:26.913797Z"
+ }
+ },
+ "source": [
+ "# Initialize all states to default values\n",
+ "brainstate.nn.init_all_states(neurons)\n",
+ "\n",
+ "# Or with specific batch in_size\n",
+ "brainstate.nn.init_all_states(neurons, batch_size=32)"
+ ],
"outputs": [
{
"data": {
@@ -72,25 +117,17 @@
" V_reset=-65. * mvolt,\n",
" V_initializer=Constant(value=0.0 * mvolt),\n",
" V=HiddenState(\n",
- " value=~float32[100] * mvolt\n",
+ " value=~float32[32,100] * mvolt\n",
" )\n",
")"
]
},
- "execution_count": 21,
+ "execution_count": 65,
"metadata": {},
"output_type": "execute_result"
}
],
- "source": [
- "import brainstate\n",
- "\n",
- "# Initialize all states to default values\n",
- "brainstate.nn.init_all_states(neurons)\n",
- "\n",
- "# Or with specific batch in_in_size\n",
- "brainstate.nn.init_all_states(neurons, batch_in_in_size=32)"
- ]
+ "execution_count": 65
},
{
"cell_type": "markdown",
@@ -103,23 +140,15 @@
},
{
"cell_type": "code",
- "execution_count": 22,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Voltage shape: (100,)\n",
- "Spikes shape: (100,)\n"
- ]
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:26.957509Z",
+ "start_time": "2025-11-13T09:26:26.936911Z"
}
- ],
+ },
"source": [
- "import jax.numpy as jnp\n",
- "\n",
"# Single time step - provide input for all neurons\n",
- "# Create input current array matching neuron population in_in_size\n",
+ "# Create input current array matching neuron population in_size\n",
"input_current = jnp.ones(100) * 2.0 * u.nA # 100 neurons, each gets 2.0 nA\n",
"\n",
"# Access results\n",
@@ -128,7 +157,18 @@
"\n",
"print(f\"Voltage shape: {voltage.shape}\")\n",
"print(f\"Spikes shape: {spikes.shape}\")"
- ]
+ ],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Voltage shape: (32, 100)\n",
+ "Spikes shape: (32, 100)\n"
+ ]
+ }
+ ],
+ "execution_count": 66
},
{
"cell_type": "markdown",
@@ -136,6 +176,10 @@
"source": [
"## Available Neuron Models\n",
"\n",
+ "\n",
+ "For more neuron models, see the [API Reference](../../api/index.rst).\n",
+ "\n",
+ "\n",
"### IF (Integrate-and-Fire)\n",
"\n",
"The simplest spiking neuron model.\n",
@@ -153,8 +197,25 @@
},
{
"cell_type": "code",
- "execution_count": 23,
- "metadata": {},
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:26.977885Z",
+ "start_time": "2025-11-13T09:26:26.961663Z"
+ }
+ },
+ "source": [
+ "# IF neuron - simple parameters\n",
+ "neuron = brainpy.state.IF(\n",
+ " in_size=100,\n",
+ " V_th=1. * u.mV, # Spike threshold \n",
+ " tau=20. * u.ms, # Membrane time constant\n",
+ " R=1. * u.ohm # Input resistance\n",
+ ")\n",
+ "\n",
+ "# Initialize the neuron\n",
+ "import brainstate\n",
+ "brainstate.nn.init_all_states(neuron)"
+ ],
"outputs": [
{
"data": {
@@ -174,27 +235,12 @@
")"
]
},
- "execution_count": 23,
+ "execution_count": 67,
"metadata": {},
"output_type": "execute_result"
}
],
- "source": [
- "import brainpy\n",
- "import brainunit as u\n",
- "\n",
- "# IF neuron - simple parameters\n",
- "neuron = brainpy.state.IF(\n",
- " in_size=100,\n",
- " V_th=1. * u.mV, # Spike threshold \n",
- " tau=20. * u.ms, # Membrane time constant\n",
- " R=1. * u.ohm # Input resistance\n",
- ")\n",
- "\n",
- "# Initialize the neuron\n",
- "import brainstate\n",
- "brainstate.nn.init_all_states(neuron)"
- ]
+ "execution_count": 67
},
{
"cell_type": "markdown",
@@ -232,8 +278,26 @@
},
{
"cell_type": "code",
- "execution_count": 24,
- "metadata": {},
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.030431Z",
+ "start_time": "2025-11-13T09:26:27.017419Z"
+ }
+ },
+ "source": [
+ "neuron = brainpy.state.LIF(\n",
+ " in_size=100,\n",
+ " V_rest=-65. * u.mV,\n",
+ " V_th=-50. * u.mV,\n",
+ " V_reset=-65. * u.mV,\n",
+ " tau=10. * u.ms,\n",
+ " R=1. * u.ohm,\n",
+ " V_initializer=braintools.init.Normal(-65., 5., unit=u.mV)\n",
+ ")\n",
+ "\n",
+ "# Initialize the neuron\n",
+ "brainstate.nn.init_all_states(neuron)"
+ ],
"outputs": [
{
"data": {
@@ -255,30 +319,12 @@
")"
]
},
- "execution_count": 24,
+ "execution_count": 68,
"metadata": {},
"output_type": "execute_result"
}
],
- "source": [
- "import brainpy\n",
- "import brainstate\n",
- "import braintools\n",
- "import brainunit as u\n",
- "\n",
- "neuron = brainpy.state.LIF(\n",
- " in_size=100,\n",
- " V_rest=-65. * u.mV,\n",
- " V_th=-50. * u.mV,\n",
- " V_reset=-65. * u.mV,\n",
- " tau=10. * u.ms,\n",
- " R=1. * u.ohm,\n",
- " V_initializer=braintools.init.Normal(-65., 5., unit=u.mV)\n",
- ")\n",
- "\n",
- "# Initialize the neuron\n",
- "brainstate.nn.init_all_states(neuron)"
- ]
+ "execution_count": 68
},
{
"cell_type": "markdown",
@@ -319,8 +365,26 @@
},
{
"cell_type": "code",
- "execution_count": 25,
- "metadata": {},
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.083988Z",
+ "start_time": "2025-11-13T09:26:27.073064Z"
+ }
+ },
+ "source": [
+ "neuron = brainpy.state.LIFRef(\n",
+ " in_size=100,\n",
+ " V_rest=-65. * u.mV,\n",
+ " V_th=-50. * u.mV,\n",
+ " V_reset=-65. * u.mV,\n",
+ " tau=10. * u.ms,\n",
+ " tau_ref=2. * u.ms, # Refractory period\n",
+ " R=1. * u.ohm\n",
+ ")\n",
+ "\n",
+ "# Initialize the neuron\n",
+ "brainstate.nn.init_all_states(neuron)"
+ ],
"outputs": [
{
"data": {
@@ -346,29 +410,12 @@
")"
]
},
- "execution_count": 25,
+ "execution_count": 69,
"metadata": {},
"output_type": "execute_result"
}
],
- "source": [
- "import brainpy\n",
- "import brainstate\n",
- "import brainunit as u\n",
- "\n",
- "neuron = brainpy.state.LIFRef(\n",
- " in_size=100,\n",
- " V_rest=-65. * u.mV,\n",
- " V_th=-50. * u.mV,\n",
- " V_reset=-65. * u.mV,\n",
- " tau=10. * u.ms,\n",
- " tau_ref=2. * u.ms, # Refractory period\n",
- " R=1. * u.ohm\n",
- ")\n",
- "\n",
- "# Initialize the neuron\n",
- "brainstate.nn.init_all_states(neuron)"
- ]
+ "execution_count": 69
},
{
"cell_type": "markdown",
@@ -410,8 +457,27 @@
},
{
"cell_type": "code",
- "execution_count": 26,
- "metadata": {},
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.130935Z",
+ "start_time": "2025-11-13T09:26:27.119447Z"
+ }
+ },
+ "source": [
+ "neuron = brainpy.state.ALIF(\n",
+ " in_size=100,\n",
+ " V_rest=-65. * u.mV,\n",
+ " V_th=-50. * u.mV,\n",
+ " V_reset=-65. * u.mV,\n",
+ " tau=10. * u.ms,\n",
+ " tau_a=200. * u.ms, # Adaptation time constant\n",
+ " beta=0.1 * u.nA, # Spike-triggered adaptation\n",
+ " R=1. * u.ohm\n",
+ ")\n",
+ "\n",
+ "# Initialize the neuron\n",
+ "brainstate.nn.init_all_states(neuron)"
+ ],
"outputs": [
{
"data": {
@@ -439,30 +505,12 @@
")"
]
},
- "execution_count": 26,
+ "execution_count": 70,
"metadata": {},
"output_type": "execute_result"
}
],
- "source": [
- "import brainpy\n",
- "import brainstate\n",
- "import brainunit as u\n",
- "\n",
- "neuron = brainpy.state.ALIF(\n",
- " in_size=100,\n",
- " V_rest=-65. * u.mV,\n",
- " V_th=-50. * u.mV,\n",
- " V_reset=-65. * u.mV,\n",
- " tau=10. * u.ms,\n",
- " tau_a=200. * u.ms, # Adaptation time constant\n",
- " beta=0.1 * u.nA, # Spike-triggered adaptation\n",
- " R=1. * u.ohm\n",
- ")\n",
- "\n",
- "# Initialize the neuron\n",
- "brainstate.nn.init_all_states(neuron)"
- ]
+ "execution_count": 70
},
{
"cell_type": "markdown",
@@ -501,8 +549,24 @@
},
{
"cell_type": "code",
- "execution_count": 27,
- "metadata": {},
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.199145Z",
+ "start_time": "2025-11-13T09:26:27.188524Z"
+ }
+ },
+ "source": [
+ "neuron = brainpy.state.LIF(\n",
+ " in_size=100, \n",
+ " V_rest=-65. * u.mV,\n",
+ " V_th=-50. * u.mV,\n",
+ " V_reset=-65. * u.mV,\n",
+ " tau=10. * u.ms,\n",
+ " spk_reset='soft'\n",
+ ")\n",
+ "\n",
+ "brainstate.nn.init_all_states(neuron)"
+ ],
"outputs": [
{
"data": {
@@ -524,23 +588,12 @@
")"
]
},
- "execution_count": 27,
+ "execution_count": 71,
"metadata": {},
"output_type": "execute_result"
}
],
- "source": [
- "neuron = brainpy.state.LIF(\n",
- " in_size=100, \n",
- " V_rest=-65. * u.mV,\n",
- " V_th=-50. * u.mV,\n",
- " V_reset=-65. * u.mV,\n",
- " tau=10. * u.ms,\n",
- " spk_reset='soft'\n",
- ")\n",
- "\n",
- "brainstate.nn.init_all_states(neuron)"
- ]
+ "execution_count": 71
},
{
"cell_type": "markdown",
@@ -564,8 +617,24 @@
},
{
"cell_type": "code",
- "execution_count": 28,
- "metadata": {},
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.239190Z",
+ "start_time": "2025-11-13T09:26:27.229487Z"
+ }
+ },
+ "source": [
+ "neuron = brainpy.state.LIF(\n",
+ " in_size=100,\n",
+ " V_rest=-65. * u.mV,\n",
+ " V_th=-50. * u.mV,\n",
+ " V_reset=-65. * u.mV,\n",
+ " tau=10. * u.ms,\n",
+ " spk_reset='hard'\n",
+ ")\n",
+ "\n",
+ "brainstate.nn.init_all_states(neuron)"
+ ],
"outputs": [
{
"data": {
@@ -587,27 +656,16 @@
")"
]
},
- "execution_count": 28,
+ "execution_count": 72,
"metadata": {},
"output_type": "execute_result"
}
],
- "source": [
- "neuron = brainpy.state.LIF(\n",
- " in_size=100,\n",
- " V_rest=-65. * u.mV,\n",
- " V_th=-50. * u.mV,\n",
- " V_reset=-65. * u.mV,\n",
- " tau=10. * u.ms,\n",
- " spk_reset='hard'\n",
- ")\n",
- "\n",
- "brainstate.nn.init_all_states(neuron)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
+ "execution_count": 72
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
"source": [
"**Properties:**\n",
"\n",
@@ -627,8 +685,24 @@
},
{
"cell_type": "code",
- "execution_count": 29,
- "metadata": {},
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.277165Z",
+ "start_time": "2025-11-13T09:26:27.267358Z"
+ }
+ },
+ "source": [
+ "neuron = brainpy.state.LIF(\n",
+ " in_size=100,\n",
+ " V_rest=-65. * u.mV,\n",
+ " V_th=-50. * u.mV,\n",
+ " V_reset=-65. * u.mV,\n",
+ " tau=10. * u.ms,\n",
+ " spk_fun=braintools.surrogate.ReluGrad()\n",
+ ")\n",
+ "\n",
+ "brainstate.nn.init_all_states(neuron)"
+ ],
"outputs": [
{
"data": {
@@ -650,23 +724,12 @@
")"
]
},
- "execution_count": 29,
+ "execution_count": 73,
"metadata": {},
"output_type": "execute_result"
}
],
- "source": [
- "neuron = brainpy.state.LIF(\n",
- " in_size=100,\n",
- " V_rest=-65. * u.mV,\n",
- " V_th=-50. * u.mV,\n",
- " V_reset=-65. * u.mV,\n",
- " tau=10. * u.ms,\n",
- " spk_fun=braintools.surrogate.ReluGrad()\n",
- ")\n",
- "\n",
- "brainstate.nn.init_all_states(neuron)"
- ]
+ "execution_count": 73
},
{
"cell_type": "markdown",
@@ -690,34 +753,12 @@
},
{
"cell_type": "code",
- "execution_count": 30,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "LIF(\n",
- " in_size=(100,),\n",
- " out_size=(100,),\n",
- " spk_reset=soft,\n",
- " spk_fun=ReluGrad(alpha=0.3, width=1.0),\n",
- " R=1. * ohm,\n",
- " tau=10. * msecond,\n",
- " V_th=-50. * mvolt,\n",
- " V_rest=-65. * mvolt,\n",
- " V_reset=0. * mvolt,\n",
- " V_initializer=Uniform(low=-70.0, high=-60.0),\n",
- " V=HiddenState(\n",
- " value=float32[100] * mvolt\n",
- " )\n",
- ")"
- ]
- },
- "execution_count": 30,
- "metadata": {},
- "output_type": "execute_result"
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.319454Z",
+ "start_time": "2025-11-13T09:26:27.303637Z"
}
- ],
+ },
"source": [
"# Constant initialization\n",
"neuron1 = brainpy.state.LIF(\n",
@@ -748,7 +789,34 @@
" V_initializer=braintools.init.Uniform(-70., -60., unit=u.mV)\n",
")\n",
"brainstate.nn.init_all_states(neuron3)"
- ]
+ ],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "LIF(\n",
+ " in_size=(100,),\n",
+ " out_size=(100,),\n",
+ " spk_reset=soft,\n",
+ " spk_fun=ReluGrad(alpha=0.3, width=1.0),\n",
+ " R=1. * ohm,\n",
+ " tau=10. * msecond,\n",
+ " V_th=-50. * mvolt,\n",
+ " V_rest=-65. * mvolt,\n",
+ " V_reset=0. * mvolt,\n",
+ " V_initializer=Uniform(low=-70.0, high=-60.0),\n",
+ " V=HiddenState(\n",
+ " value=float32[100] * mvolt\n",
+ " )\n",
+ ")"
+ ]
+ },
+ "execution_count": 74,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 74
},
{
"cell_type": "markdown",
@@ -759,9 +827,12 @@
},
{
"cell_type": "code",
- "execution_count": 31,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.375509Z",
+ "start_time": "2025-11-13T09:26:27.350990Z"
+ }
+ },
"source": [
"# Membrane potential (with units)\n",
"voltage = neuron.V.value # Quantity with units\n",
@@ -771,7 +842,9 @@
"\n",
"# Access underlying array (without units)\n",
"voltage_array = neuron.V.value.to_decimal(u.mV)"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 75
},
{
"cell_type": "markdown",
@@ -784,14 +857,15 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.469688Z",
+ "start_time": "2025-11-13T09:26:27.386811Z"
+ }
+ },
"source": [
- "import jax.numpy as jnp\n",
- "\n",
"# Initialize with batch dimension\n",
- "brainstate.nn.init_all_states(neuron, batch_in_in_size=32)\n",
+ "brainstate.nn.init_all_states(neuron, batch_size=32)\n",
"\n",
"# Input shape: (batch_in_size, in_size)\n",
"# For 32 batches of 100 neurons each\n",
@@ -801,7 +875,17 @@
"# Output shape: (batch_in_size, in_size)\n",
"spikes = neuron.get_spike()\n",
"print(f\"Spikes shape: {spikes.shape}\") # Should be (32, 100)"
- ]
+ ],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Spikes shape: (32, 100)\n"
+ ]
+ }
+ ],
+ "execution_count": 76
},
{
"cell_type": "markdown",
@@ -814,25 +898,13 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/png": "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",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.702508Z",
+ "start_time": "2025-11-13T09:26:27.476680Z"
}
- ],
+ },
"source": [
- "import brainpy\n",
- "import brainstate\n",
- "import brainunit as u\n",
- "import jax.numpy as jnp\n",
"import matplotlib.pyplot as plt\n",
"\n",
"# Set time step\n",
@@ -857,25 +929,26 @@
"times = u.math.arange(0. * u.ms, duration, dt)\n",
"\n",
"# Input current (step input)\n",
- "def get_input(t):\n",
- " if t > 50*u.ms:\n",
- " return jnp.ones(1) * 20.0 * u.mA # Array of in_in_size 1\n",
- " else:\n",
- " return jnp.zeros(1) * u.mA # Array of in_in_size 1\n",
+ "def get_input():\n",
+ " t = brainstate.environ.get('t')\n",
+ " return u.math.where(\n",
+ " t > 50*u.ms,\n",
+ " jnp.ones(1) * 20.0 * u.mA, # Array of in_size 1\n",
+ " jnp.zeros(1) * u.mA, # Array of in_size 1\n",
+ " )\n",
+ "\n",
+ "def step_run(i, t):\n",
+ " with brainstate.environ.context(i=i, t=t):\n",
+ " neuron(get_input())\n",
+ " return neuron.V.value, neuron.get_spike()\n",
"\n",
"# Run simulation\n",
- "voltages = []\n",
- "spikes = []\n",
- "\n",
- "for t in times:\n",
- " neuron(get_input(t))\n",
- " voltages.append(neuron.V.value)\n",
- " spikes.append(neuron.get_spike())\n",
+ "voltages, spikes = brainstate.transform.for_loop(step_run, jnp.arange(times.size), times)\n",
"\n",
"# Plot results\n",
"voltages = u.math.asarray(voltages)\n",
"times_plot = times.to_decimal(u.ms)\n",
- "voltages_plot = voltages.to_decimal(u.mV).squeeze() # Remove in_in_size dimension\n",
+ "voltages_plot = voltages.to_decimal(u.mV).squeeze() # Remove in_size dimension\n",
"\n",
"plt.figure(figsize=(10, 4))\n",
"plt.plot(times_plot, voltages_plot)\n",
@@ -887,7 +960,23 @@
"plt.grid(True, alpha=0.3)\n",
"plt.tight_layout()\n",
"plt.show()"
- ]
+ ],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "image/png": "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dZhT0jmv14uamhrExsbCbud9E6th+VgXy8baWD7WxbKxNpaPtbF8rItlY22RUD5GzGjEkJ1h0B2gpqYGANC3b98wp4SIiIiIiIisrqamBsnJyZ2+b1NnC8s14/V6ceLECSQlJcFms4U7OUFVV1ejb9+++O677+ByucKdHArA8rEulo21sXysi2VjbSwfa2P5WBfLxtoioXyUUqipqUFOTk6Xo/Ec6Q5gt9uRm5sb7mR0i8vlsmwFJJaPlbFsrI3lY10sG2tj+Vgby8e6WDbWZvXy6WqE22DNyfFEREREREREAjDoJiIiIiIiIgoRBt0RyOl0Yvny5XA6neFOCgXB8rEulo21sXysi2VjbSwfa2P5WBfLxtoklQ8XUiMiIiIiIiIKEY50ExEREREREYUIg24iIiIiIiKiEGHQTURERERERBQiDLojzDPPPIP+/fsjNjYW+fn5+PLLL8OdJC2tWrUKl19+OZKSkpCZmYlrr70WRUVFfseMHz8eNpvN79/ChQvDlGK9rFixosPffsiQIb73GxsbUVBQgF69eiExMRHXX389Tp48GcYU66N///4dysZms6GgoAAA201P+/jjjzFt2jTk5OTAZrPhzTff9HtfKYVly5ahd+/eiIuLw8SJE3Hw4EG/YyoqKjBr1iy4XC6kpKRg3rx5qK2t7cFcyNRV2bjdbixZsgTDhw9HQkICcnJyMGfOHJw4ccLvdwRrb4899lgP50Sms7WduXPndvjbT5482e8Ytp3QOVv5BLsO2Ww2FBYW+o5h+wmN7vShu9NPKy4uxtSpUxEfH4/MzEzcf//9aGlp6cmsnBMG3RHk1VdfxX333Yfly5dj165dGDlyJK6++mqUl5eHO2na2bJlCwoKCvDFF19gw4YNcLvdmDRpEurq6vyOW7BgAUpLS33/nnjiiTClWD+XXHKJ39/+008/9b1377334t///jdee+01bNmyBSdOnMB1110XxtTqY/v27X7lsmHDBgDAjBkzfMew3fScuro6jBw5Es8880zQ95944gn88Y9/xLPPPott27YhISEBV199NRobG33HzJo1C1999RU2bNiAt99+Gx9//DFuu+22nsqCWF2VTX19PXbt2oWHHnoIu3btwvr161FUVIRrrrmmw7GPPPKIX3u66667eiL54p2t7QDA5MmT/f72r7zyit/7bDuhc7byMZdL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9OjRavDgwaqxsdH3O9h2Quds5zallKqqqlLx8fFqzZo1HX6e7Sd0ztaHVurs/bSWlhY1bNgwNWnSJLVnzx71/vvvq4yMDLV06dJwZKlbGHRHmKefflr169dPORwOdcUVV6gvvvgi3EnSEoCg/1588UWllFLFxcXqyiuvVGlpacrpdKoLLrhA3X///aqqqiq8CdfEjTfeqHr37q0cDofq06ePuvHGG9WhQ4d87zc0NKjf/OY3KjU1VcXHx6tf/OIXqrS0NIwp1ssHH3ygAKiioiK/19luet6mTZuCnstuvvlmpVTrtmEPPfSQysrKUk6nU1111VUdyu3MmTNq5syZKjExUblcLnXLLbeompqaMORGlq7K5siRI51ehzZt2qSUUmrnzp0qPz9fJScnq9jYWDV06FC1cuVKv6CP/nddlU99fb2aNGmSysjIUDExMSovL08tWLCgwyAJ207onO3cppRSf/nLX1RcXJyqrKzs8PNsP6Fztj60Ut3rpx09elRNmTJFxcXFqfT0dLV48WLldrt7ODfdZ1NKqRANohMRERERERFpjc90ExEREREREYUIg24iIiIiIiKiEGHQTURERERERBQiDLqJiIiIiIiIQoRBNxEREREREVGIMOgmIiIiIiIiChEG3UREREREREQhwqCbiIiIiIiIKEQYdBMREUWwuXPn4tprrw3b58+ePRsrV64M2e8/cOAAcnNzUVdXF7LPICIiCiWbUkqFOxFERETUkc1m6/L95cuX495774VSCikpKT2TKJP//Oc/mDBhAo4dO4bExMSQfc4vf/lLjBw5Eg899FDIPoOIiChUGHQTERFZVFlZme/rV199FcuWLUNRUZHvtcTExJAGu2czf/58REdH49lnnw3p57zzzjtYsGABiouLER0dHdLPIiIiOt84vZyIiMiisrOzff+Sk5Nhs9n8XktMTOwwvXz8+PG46667sGjRIqSmpiIrKwvPPfcc6urqcMsttyApKQkXXHAB3nvvPb/P2r9/P6ZMmYLExERkZWVh9uzZOH36dKdp83g8eP311zFt2jS/1/v3749HH30Uc+bMQWJiIvLy8vCvf/0Lp06dwvTp05GYmIgRI0Zgx44dvp85duwYpk2bhtTUVCQkJOCSSy7Bu+++63v/pz/9KSoqKrBly5Yf+BclIiLqeQy6iYiIhHnppZeQnp6OL7/8EnfddRfuuOMOzJgxAz/60Y+wa9cuTJo0CbNnz0Z9fT0AoLKyEhMmTMCoUaOwY8cOvP/++zh58iRuuOGGTj9j7969qKqqwmWXXdbhvaeeegrjxo3D7t27MXXqVMyePRtz5szBTTfdhF27dmHQoEGYM2cOjMl2BQUFaGpqwscff4x9+/bh8ccf9xvBdzgcuPTSS/HJJ5+c578UERFR6DHoJiIiEmbkyJH4/e9/j8GDB2Pp0qWIjY1Feno6FixYgMGDB2PZsmU4c+YM9u7dCwD405/+hFGjRmHlypUYMmQIRo0ahRdeeAGbNm3CN998E/Qzjh07hqioKGRmZnZ472c/+xluv/1232dVV1fj8ssvx4wZM3DhhRdiyZIl+Prrr3Hy5EkAQHFxMcaNG4fhw4dj4MCB+PnPf44rr7zS73fm5OTg2LFj5/kvRUREFHoMuomIiIQZMWKE7+uoqCj06tULw4cP972WlZUFACgvLwfQuiDapk2bfM+IJyYmYsiQIQCAw4cPB/2MhoYGOJ3OoIu9mT/f+KyuPv/uu+/Go48+inHjxmH58uW+mwFmcXFxvpF5IiKiSMKgm4iISJiYmBi/7202m99rRqDs9XoBALW1tZg2bRr27Nnj9+/gwYMdRpwN6enpqK+vR3Nzc5efb3xWV58/f/58fPvtt5g9ezb27duHyy67DE8//bTf76yoqEBGRkb3/gBEREQWwqCbiIhIc6NHj8ZXX32F/v3744ILLvD7l5CQEPRnLr30UgCt+2ifD3379sXChQuxfv16LF68GM8995zf+/v378eoUaPOy2cRERH1JAbdREREmisoKEBFRQVmzpyJ7du34/Dhw/jggw9wyy23wOPxBP2ZjIwMjB49Gp9++ukP/vxFixbhgw8+wJEjR7Br1y5s2rQJQ4cO9b1/9OhRlJSUYOLEiT/4s4iIiHoag24iIiLN5eTk4LPPPoPH48GkSZMwfPhwLFq0CCkpKbDbO+8qzJ8/Hy+//PIP/nyPx4OCggIMHToUkydPxoUXXog///nPvvdfeeUVTJo0CXl5eT/4s4iIiHqaTRn7dRARERGdg4aGBlx00UV49dVXMXbs2JB8RnNzMwYPHoy//e1vGDduXEg+g4iIKJQ40k1ERET/k7i4OPz1r3/F6dOnQ/YZxcXFeOCBBxhwExFRxOJINxEREREREVGIcKSbiIiIiIiIKEQYdBMRERERERGFCINuIiIiIiIiohBh0E1EREREREQUIgy6iYiIiIiIiEKEQTcRERERERFRiDDoJiIiIiIiIgoRBt1EREREREREIcKgm4iIiIiIiChEGHQTERERERERhcj/B8YTwbFYo4QQAAAAAElFTkSuQmCC"
+ },
+ "metadata": {},
+ "output_type": "display_data",
+ "jetTransient": {
+ "display_id": null
+ }
+ }
+ ],
+ "execution_count": 77
},
{
"cell_type": "markdown",
@@ -900,11 +989,13 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.715478Z",
+ "start_time": "2025-11-13T09:26:27.709840Z"
+ }
+ },
"source": [
- "import brainstate\n",
"from brainpy.state import Neuron\n",
"\n",
"class MyNeuron(Neuron):\n",
@@ -945,7 +1036,9 @@
"\n",
" def get_spike(self):\n",
" return self.spike.value"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 78
},
{
"cell_type": "markdown",
@@ -956,16 +1049,21 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.758920Z",
+ "start_time": "2025-11-13T09:26:27.752520Z"
+ }
+ },
"source": [
"neuron = MyNeuron(in_size=100, tau=10*u.ms, V_th=1*u.mV)\n",
"brainstate.nn.init_all_states(neuron)\n",
"\n",
"# Create appropriate input current\n",
"input_current = jnp.ones(100) * 0.5 * u.nA"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 79
},
{
"cell_type": "markdown",
@@ -978,15 +1076,20 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.814559Z",
+ "start_time": "2025-11-13T09:26:27.810192Z"
+ }
+ },
"source": [
"@brainstate.transform.jit\n",
"def simulate_step(input):\n",
" neuron(input)\n",
" return neuron.V.value"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 80
},
{
"cell_type": "markdown",
@@ -997,8 +1100,13 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.848829Z",
+ "start_time": "2025-11-13T09:26:27.840789Z"
+ }
+ },
+ "source": "brainstate.nn.init_all_states(neuron, batch_size=100)",
"outputs": [
{
"data": {
@@ -1019,14 +1127,12 @@
")"
]
},
- "execution_count": 87,
+ "execution_count": 81,
"metadata": {},
"output_type": "execute_result"
}
],
- "source": [
- "brainstate.nn.init_all_states(neuron, batch_in_in_size=100)"
- ]
+ "execution_count": 81
},
{
"cell_type": "markdown",
@@ -1037,138 +1143,127 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.879178Z",
+ "start_time": "2025-11-13T09:26:27.874662Z"
+ }
+ },
"source": [
"# Float32 is usually sufficient and faster\n",
- "brainstate.environ.set(dtype=jnp.float32)"
- ]
+ "brainstate.environ.set(precision=32)"
+ ],
+ "outputs": [],
+ "execution_count": 82
},
{
- "cell_type": "markdown",
"metadata": {},
- "source": [
- "4. **Preallocate arrays** when recording:"
- ]
+ "cell_type": "markdown",
+ "source": "4. Use soft reset for higher firing rates:"
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "n_steps = 2000 # Example: 2000 time steps\n",
- "neuron_in_in_size = 100 # Example: 100 neurons\n",
- "voltages = jnp.zeros((n_steps, neuron_in_in_size))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.912742Z",
+ "start_time": "2025-11-13T09:26:27.908977Z"
+ }
+ },
"source": [
- "import brainpy\n",
- "import brainstate\n",
- "import brainunit as u\n",
- "\n",
- "neuron = brainpy.state.LIF(\n",
- " in_in_size=100, \n",
- " V_rest=-65. * u.mV,\n",
- " V_th=-50. * u.mV,\n",
- " tau=10. * u.ms,\n",
- " spk_reset='soft'\n",
- ")\n",
"# Use soft reset for higher firing rates\n",
- "\n",
- "brainstate.nn.init_all_states(neuron)"
- ]
+ "neuron = brainpy.state.LIF(100, tau=10*u.ms, spk_reset='soft')"
+ ],
+ "outputs": [],
+ "execution_count": 83
},
{
- "cell_type": "code",
- "execution_count": null,
"metadata": {},
- "outputs": [],
- "source": [
- "neuron = brainpy.state.LIF(100, tau=10*u.ms, spk_reset='soft')\n",
- "# Use soft reset for higher firing rates"
- ]
+ "cell_type": "markdown",
+ "source": "5. Use hard reset for precise spike timing:"
},
{
- "cell_type": "markdown",
- "metadata": {},
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.923213Z",
+ "start_time": "2025-11-13T09:26:27.919965Z"
+ }
+ },
+ "cell_type": "code",
"source": [
- "import brainpy\n",
- "import brainstate\n",
- "import brainunit as u\n",
- "\n",
+ "# Use refractory period for precise timing\n",
"neuron = brainpy.state.LIFRef(\n",
- " in_in_size=100,\n",
+ " in_size=100,\n",
" V_rest=-65. * u.mV,\n",
" V_th=-50. * u.mV,\n",
" V_reset=-65. * u.mV,\n",
" tau=10. * u.ms,\n",
" tau_ref=2. * u.ms,\n",
" spk_reset='hard'\n",
- ")\n",
- "# Use refractory period for precise timing\n",
- "\n",
- "brainstate.nn.init_all_states(neuron)"
- ]
+ ")"
+ ],
+ "outputs": [],
+ "execution_count": 84
},
{
- "cell_type": "code",
- "execution_count": null,
"metadata": {},
- "outputs": [],
+ "cell_type": "markdown",
+ "source": "6. Use refractory period for precise timing"
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:26:27.959276Z",
+ "start_time": "2025-11-13T09:26:27.954296Z"
+ }
+ },
+ "cell_type": "code",
"source": [
"neuron = brainpy.state.LIFRef(\n",
" 100,\n",
" tau=10*u.ms,\n",
" tau_ref=2*u.ms,\n",
" spk_reset='hard'\n",
- ")\n",
- "# Use refractory period for precise timing"
- ]
+ ")"
+ ],
+ "outputs": [],
+ "execution_count": 85
},
{
- "cell_type": "markdown",
"metadata": {},
+ "cell_type": "markdown",
+ "source": "7. Adaptation creates bursting patterns"
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:27:20.880214Z",
+ "start_time": "2025-11-13T09:27:20.862053Z"
+ }
+ },
"source": [
- "import brainpy\n",
- "import brainstate\n",
- "import brainunit as u\n",
- "\n",
"neuron = brainpy.state.ALIF(\n",
- " in_in_size=100,\n",
+ " in_size=100,\n",
" V_rest=-65. * u.mV,\n",
" V_th=-50. * u.mV,\n",
" V_reset=-65. * u.mV,\n",
" tau=10. * u.ms,\n",
- " tau_w=200. * u.ms,\n",
- " a=0.01,\n",
- " b=0.1 * u.nA,\n",
+ " tau_a=200. * u.ms,\n",
" spk_reset='soft'\n",
")\n",
- "# Adaptation creates bursting patterns\n",
+ "brainstate.nn.init_all_states(neuron)\n",
"\n",
- "brainstate.nn.init_all_states(neuron)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
+ "# Adaptation creates bursting patterns\n",
"neuron = brainpy.state.ALIF(\n",
" 100,\n",
" tau=10*u.ms,\n",
" tau_a=200*u.ms,\n",
" beta=0.01,\n",
" spk_reset='soft'\n",
- ")\n",
- "# Adaptation creates bursting patterns"
- ]
+ ")"
+ ],
+ "outputs": [],
+ "execution_count": 89
},
{
"cell_type": "markdown",
diff --git a/docs_state/quickstart/core-concepts/projections.ipynb b/docs_state/quickstart/core-concepts/projections.ipynb
index db0067ee..c2ac6274 100644
--- a/docs_state/quickstart/core-concepts/projections.ipynb
+++ b/docs_state/quickstart/core-concepts/projections.ipynb
@@ -4,15 +4,15 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "# Projections: Connecting Neural Populations\n",
+ "# Projections\n",
"\n",
"Projections are `brainpy.state` 's mechanism for connecting neural populations.\n",
"They implement the **Communication-Synapse-Output (Comm-Syn-Out)** architecture,\n",
"which separates connectivity, synaptic dynamics, and output computation into modular components.\n",
"\n",
+ "\n",
"This guide provides a comprehensive understanding of projections in `brainpy.state`.\n",
"\n",
- "**Table of Contents**\n",
"\n",
"## Overview\n",
"\n",
@@ -24,6 +24,7 @@
"2. **Synapse (Syn)**: Temporal filtering and synaptic dynamics\n",
"3. **Output (Out)**: How synaptic currents affect postsynaptic neurons\n",
"\n",
+ "\n",
"**Key benefits:**\n",
"\n",
"- Modular design (swap components independently)\n",
@@ -31,33 +32,67 @@
"- Efficient (optimized sparse operations)\n",
"- Flexible (combine components in different ways)\n",
"\n",
+ "\n",
"### The Comm-Syn-Out Architecture"
]
},
{
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T11:46:03.343127Z",
+ "start_time": "2025-11-13T11:46:03.339748Z"
+ }
+ },
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
"source": [
- "Presynaptic Communication Synapse Output Postsynaptic\n",
- "Population ──► (Connectivity) ──► (Dynamics) ──► (Current) ──► Population\n",
+ "import brainstate\n",
+ "import braintools\n",
+ "import brainunit as u\n",
+ "import numpy as np\n",
"\n",
- "Spikes ──► Weight matrix ──► g(t) ──► I_syn ──► Neurons\n",
- " Sparse/Dense Expon/Alpha CUBA/COBA"
- ]
+ "import brainpy"
+ ],
+ "outputs": [],
+ "execution_count": 22
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T11:46:27.174926Z",
+ "start_time": "2025-11-13T11:46:27.170504Z"
+ }
+ },
+ "cell_type": "code",
+ "source": "brainstate.environ.set(dt=0.1 * u.ms)",
+ "outputs": [],
+ "execution_count": 24
},
{
- "cell_type": "markdown",
"metadata": {},
+ "cell_type": "markdown",
"source": [
+ "```text\n",
+ "Presynaptic Communication Synapse Output Postsynaptic\n",
+ "Population ──► (Connectivity) ──► (Dynamics) ──► (Current) ──► Population\n",
+ "\n",
+ "Spikes ──► Weight matrix ──► g(t) ──► I_syn ──► Neurons\n",
+ " Sparse/Dense Expon/Alpha CUBA/COBA\n",
+ "```\n",
+ "\n",
"**Flow:**\n",
"\n",
"1. Presynaptic spikes arrive\n",
"2. Communication: Spikes propagate through connectivity matrix\n",
"3. Synapse: Temporal dynamics filter the signal\n",
"4. Output: Convert to current/conductance\n",
- "5. Postsynaptic neurons receive input\n",
+ "5. Postsynaptic neurons receive input"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
"\n",
"### Types of Projections\n",
"\n",
@@ -92,17 +127,12 @@
"metadata": {},
"outputs": [],
"source": [
- "import brainpy\n",
- "import brainstate\n",
- "import brainunit as u\n",
- "import braintools\n",
- "\n",
"# Dense linear transformation\n",
"comm = brainstate.nn.Linear(\n",
- " 100, # in_size\n",
- " 50, # out_size\n",
+ " 100, # in_size\n",
+ " 50, # out_size\n",
" w_init=braintools.init.KaimingNormal(),\n",
- " b_init=None # No bias for synapses\n",
+ " b_init=None # No bias for synapses\n",
")"
]
},
@@ -135,10 +165,10 @@
"source": [
"# Sparse random connectivity (2% connection probability)\n",
"comm = brainstate.nn.EventFixedProb(\n",
- " 1000, # pre_size\n",
- " 800, # post_size\n",
- " conn_num=0.02, # 2% connectivity\n",
- " conn_weight=0.5 # Synaptic weight (unitless for event-based)\n",
+ " 1000, # pre_size\n",
+ " 800, # post_size\n",
+ " conn_num=0.02, # 2% connectivity\n",
+ " conn_weight=0.5 # Synaptic weight (unitless for event-based)\n",
")"
]
},
@@ -165,9 +195,9 @@
"source": [
"# All-to-all sparse (event-driven)\n",
"comm = brainstate.nn.AllToAll(\n",
- " 100, # pre_size\n",
- " 100, # post_size\n",
- " 0.3 # Unitless weight\n",
+ " 100, # pre_size\n",
+ " 100, # post_size\n",
+ " 0.3 # Unitless weight\n",
")"
]
},
@@ -186,8 +216,8 @@
"metadata": {},
"outputs": [],
"source": [
- "size=100\n",
- "weight=1.0\n",
+ "size = 100\n",
+ "weight = 1.0\n",
"\n",
"# One-to-one connections\n",
"comm = brainstate.nn.OneToOne(\n",
@@ -202,34 +232,6 @@
"source": [
"**Use case:** Feedforward pathways, identity mappings\n",
"\n",
- "### Comparison Table\n",
- "\n",
- "\n",
- " * - Type\n",
- " - Memory\n",
- " - Speed\n",
- " - Use Case\n",
- " - Example\n",
- " * - Linear (Dense)\n",
- " - High (O(n²))\n",
- " - Fast (optimized)\n",
- " - Small networks\n",
- " - Fully connected\n",
- " * - EventFixedProb\n",
- " - Low (O(n²p))\n",
- " - Very fast\n",
- " - Large networks\n",
- " - Cortical connectivity\n",
- " * - EventAll2All\n",
- " - Medium\n",
- " - Fast\n",
- " - Medium networks\n",
- " - Recurrent layers\n",
- " * - EventOne2One\n",
- " - Minimal (O(n))\n",
- " - Fastest\n",
- " - Feedforward\n",
- " - Sensory pathways\n",
"\n",
"## Synapse Layer\n",
"\n",
@@ -245,6 +247,7 @@
"$$\n",
"\\tau \\frac{dg}{dt} = -g + \\sum_k \\delta(t - t_k)\n",
"$$\n",
+ "\n",
"**Implementation:**"
]
},
@@ -255,9 +258,9 @@
"outputs": [],
"source": [
"# Exponential synapse with 5ms time constant\n",
- "syn = brainpy.state.Expon.desc(\n",
- " size=100, # Postsynaptic population size\n",
- " tau=5.0 * u.ms # Decay time constant\n",
+ "syn = brainpy.state.Expon(\n",
+ " in_size=100, # Postsynaptic population size\n",
+ " tau=5.0 * u.ms # Decay time constant\n",
")"
]
},
@@ -281,7 +284,7 @@
"\n",
"\n",
"$$\n",
- "\\tau \\frac{dg}{dt} = -g + h\n",
+ "\\tau \\frac{dg}{dt} = -g + h \\\\\n",
"\\tau \\frac{dh}{dt} = -h + \\sum_k \\delta(t - t_k)\n",
"$$\n",
"**Implementation:**"
@@ -294,9 +297,9 @@
"outputs": [],
"source": [
"# Alpha synapse\n",
- "syn = brainpy.state.Alpha.desc(\n",
- " size=100,\n",
- " tau=10.0 * u.ms # Characteristic time\n",
+ "syn = brainpy.state.Alpha(\n",
+ " in_size=100,\n",
+ " tau=10.0 * u.ms # Characteristic time\n",
")"
]
},
@@ -334,10 +337,10 @@
"# NMDA receptor\n",
"syn = brainpy.state.BioNMDA(\n",
" in_size=100,\n",
- " T_dur=100.0 * u.ms, # Slow decay\n",
- " T=2.0 * u.ms, # Fast rise\n",
- " alpha1=0.5 / u.mM, # Mg²⁺ sensitivity\n",
- " g_initializer=1.2 * u.mM # Mg²⁺ concentration\n",
+ " T_dur=100.0 * u.ms, # Slow decay\n",
+ " T=2.0 * u.ms, # Fast rise\n",
+ " alpha1=0.5 / u.mM, # Mg²⁺ sensitivity\n",
+ " g_initializer=1.2 * u.mM # Mg²⁺ concentration\n",
")"
]
},
@@ -360,16 +363,21 @@
},
{
"cell_type": "code",
- "execution_count": 239,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T11:42:57.610829Z",
+ "start_time": "2025-11-13T11:42:57.606831Z"
+ }
+ },
"source": [
"# AMPA receptor (fast excitation)\n",
- "syn = brainpy.state.AMPA.desc(\n",
- " size=100,\n",
- " tau=2.0 * u.ms # Fast decay (~2ms)\n",
+ "syn = brainpy.state.AMPA(\n",
+ " in_size=100,\n",
+ " beta=0.5 / u.ms, # Fast decay (~2ms)\n",
")"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 11
},
{
"cell_type": "markdown",
@@ -386,16 +394,21 @@
},
{
"cell_type": "code",
- "execution_count": 240,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T11:43:19.181623Z",
+ "start_time": "2025-11-13T11:43:19.177719Z"
+ }
+ },
"source": [
"# GABAa receptor (fast inhibition)\n",
- "syn = brainpy.state.GABAa.desc(\n",
- " size=100,\n",
- " tau=6.0 * u.ms # ~6ms decay\n",
+ "syn = brainpy.state.GABAa(\n",
+ " in_size=100,\n",
+ " beta=0.16 / u.ms, # ~6ms decay\n",
")"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 14
},
{
"cell_type": "markdown",
@@ -406,17 +419,22 @@
},
{
"cell_type": "code",
- "execution_count": 241,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T11:43:24.009249Z",
+ "start_time": "2025-11-13T11:43:24.005919Z"
+ }
+ },
"source": [
"# GABAb receptor (slow inhibition)\n",
"syn = brainpy.state.GABAa(\n",
" in_size=100,\n",
- " T_dur=150.0 * u.ms, # Very slow\n",
+ " T_dur=150.0 * u.ms, # Very slow\n",
" T=3.5 * u.ms\n",
")"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 15
},
{
"cell_type": "markdown",
@@ -433,16 +451,17 @@
},
{
"cell_type": "code",
- "execution_count": 242,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T11:43:26.083188Z",
+ "start_time": "2025-11-13T11:43:26.077812Z"
+ }
+ },
"source": [
- "import jax.numpy as jnp\n",
- "\n",
"class DoubleExpSynapse(brainpy.state.Synapse):\n",
" \"\"\"Custom synapse with two time constants.\"\"\"\n",
"\n",
- " def __init__(self, size, tau_fast=2*u.ms, tau_slow=10*u.ms, **kwargs):\n",
+ " def __init__(self, size, tau_fast=2 * u.ms, tau_slow=10 * u.ms, **kwargs):\n",
" super().__init__(size, **kwargs)\n",
" self.tau_fast = tau_fast\n",
" self.tau_slow = tau_slow\n",
@@ -452,7 +471,7 @@
" self.g_slow = brainstate.ShortTermState(jnp.zeros(size))\n",
"\n",
" def reset_state(self, batch_size=None):\n",
- " shape = self.size if batch_size is None else (batch_size, self.size)\n",
+ " shape = self.varshape if batch_size is None else (batch_size, *self.varshape)\n",
" self.g_fast.value = jnp.zeros(shape)\n",
" self.g_slow.value = jnp.zeros(shape)\n",
"\n",
@@ -468,7 +487,9 @@
" self.g_slow.value += dg_slow * dt.to_decimal(u.ms) + x * 0.3\n",
"\n",
" return self.g_fast.value + self.g_slow.value"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 16
},
{
"cell_type": "markdown",
@@ -493,9 +514,12 @@
},
{
"cell_type": "code",
- "execution_count": 243,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T11:43:28.874215Z",
+ "start_time": "2025-11-13T11:43:28.869215Z"
+ }
+ },
"source": [
"# Define population sizes\n",
"pre_size = 100\n",
@@ -508,7 +532,9 @@
"comm = brainstate.nn.EventFixedProb(\n",
" pre_size, post_size, conn_num, conn_weight\n",
")"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 17
},
{
"cell_type": "markdown",
@@ -540,16 +566,21 @@
},
{
"cell_type": "code",
- "execution_count": 244,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T11:43:29.757135Z",
+ "start_time": "2025-11-13T11:43:29.753741Z"
+ }
+ },
"source": [
"# Excitatory conductance-based\n",
- "out_exc = brainpy.state.COBA.desc(E=0.0 * u.mV)\n",
+ "out_exc = brainpy.state.COBA(E=0.0 * u.mV)\n",
"\n",
"# Inhibitory conductance-based\n",
- "out_inh = brainpy.state.COBA.desc(E=-80.0 * u.mV)"
- ]
+ "out_inh = brainpy.state.COBA(E=-80.0 * u.mV)"
+ ],
+ "outputs": [],
+ "execution_count": 18
},
{
"cell_type": "markdown",
@@ -573,18 +604,23 @@
},
{
"cell_type": "code",
- "execution_count": 245,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T11:43:31.336047Z",
+ "start_time": "2025-11-13T11:43:31.332070Z"
+ }
+ },
"source": [
"# NMDA with Mg²⁺ block\n",
- "out_nmda = brainpy.state.MgBlock.desc(\n",
+ "out_nmda = brainpy.state.MgBlock(\n",
" E=0.0 * u.mV,\n",
" cc_Mg=1.2 * u.mM,\n",
" alpha=0.062 / u.mV,\n",
" beta=3.57\n",
")"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 19
},
{
"cell_type": "markdown",
@@ -599,53 +635,85 @@
},
{
"cell_type": "code",
- "execution_count": 246,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T11:47:02.873592Z",
+ "start_time": "2025-11-13T11:47:02.423022Z"
+ }
+ },
"source": [
- "import brainpy as bp\n",
- "import brainstate\n",
- "import brainunit as u\n",
- "import jax.numpy as jnp\n",
- "\n",
"# Create populations\n",
- "pre = brainpy.state.LIF(100, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "post = brainpy.state.LIF(50, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
+ "pre = brainpy.state.LIF(100, V_rest=-65 * u.mV, V_th=-50 * u.mV, tau=10 * u.ms)\n",
+ "post = brainpy.state.LIF(50, V_rest=-65 * u.mV, V_th=-50 * u.mV, tau=10 * u.ms)\n",
"\n",
"# Create projection: 100 → 50 neurons\n",
"proj = brainpy.state.AlignPostProj(\n",
" comm=brainstate.nn.EventFixedProb(\n",
- " 100, # pre_size\n",
- " 50, # post_size\n",
- " conn_num=0.1, # 10% connectivity\n",
- " conn_weight=0.5 # Weight\n",
+ " 100, # pre_size\n",
+ " 50, # post_size\n",
+ " conn_num=0.1, # 10% connectivity\n",
+ " conn_weight=0.5 * u.mS # Weight\n",
" ),\n",
- " syn=brainpy.state.Expon.desc(\n",
- " in_size=50, # Postsynaptic size\n",
+ " syn=brainpy.state.Expon(\n",
+ " in_size=50, # Postsynaptic size\n",
" tau=5.0 * u.ms\n",
" ),\n",
- " out=brainpy.state.CUBA.desc(),\n",
- " post=post # Postsynaptic population\n",
+ " out=brainpy.state.CUBA(),\n",
+ " post=post # Postsynaptic population\n",
")\n",
"\n",
"# Initialize\n",
"brainstate.nn.init_all_states([pre, post, proj])\n",
"\n",
+ "\n",
"# Simulate\n",
"def step(t, i, inp):\n",
" with brainstate.environ.context(t=t, i=i):\n",
+ " # Update neurons\n",
+ " pre(inp)\n",
+ "\n",
" # Get presynaptic spikes\n",
" pre_spikes = pre.get_spike()\n",
"\n",
" # Update projection\n",
" proj(pre_spikes)\n",
"\n",
- " # Update neurons\n",
- " pre(inp)\n",
" post(0.0 * u.nA) # Projection provides input\n",
"\n",
- " return pre.get_spike(), post.get_spike()"
- ]
+ " return pre.get_spike(), post.get_spike()\n",
+ "\n",
+ "\n",
+ "indices = np.arange(1000)\n",
+ "times = indices * brainstate.environ.get_dt()\n",
+ "inputs = brainstate.random.uniform(30., 50., indices.shape) * u.nA\n",
+ "_ = brainstate.transform.for_loop(step, times, indices, inputs)"
+ ],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "(Array([[0., 0., 0., ..., 0., 0., 0.],\n",
+ " [0., 0., 0., ..., 0., 0., 0.],\n",
+ " [0., 0., 0., ..., 0., 0., 0.],\n",
+ " ...,\n",
+ " [0., 0., 0., ..., 0., 0., 0.],\n",
+ " [0., 0., 0., ..., 0., 0., 0.],\n",
+ " [0., 0., 0., ..., 0., 0., 0.]], dtype=float32),\n",
+ " Array([[0., 0., 0., ..., 0., 0., 0.],\n",
+ " [0., 0., 0., ..., 0., 0., 0.],\n",
+ " [0., 0., 0., ..., 0., 0., 0.],\n",
+ " ...,\n",
+ " [0., 0., 0., ..., 0., 0., 0.],\n",
+ " [0., 0., 0., ..., 0., 0., 0.],\n",
+ " [0., 0., 0., ..., 0., 0., 0.]], dtype=float32))"
+ ]
+ },
+ "execution_count": 27,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 27
},
{
"cell_type": "markdown",
@@ -656,51 +724,55 @@
},
{
"cell_type": "code",
- "execution_count": 247,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T11:51:00.592366Z",
+ "start_time": "2025-11-13T11:50:59.048927Z"
+ }
+ },
"source": [
"class EINetwork(brainstate.nn.Module):\n",
" def __init__(self, n_exc=800, n_inh=200):\n",
" super().__init__()\n",
"\n",
" # Populations\n",
- " self.E = brainpy.state.LIF(n_exc, V_rest=-65*u.mV, V_th=-50*u.mV, tau=15*u.ms)\n",
- " self.I = brainpy.state.LIF(n_inh, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
+ " self.E = brainpy.state.LIF(n_exc, V_rest=-65 * u.mV, V_th=-50 * u.mV, tau=15 * u.ms)\n",
+ " self.I = brainpy.state.LIF(n_inh, V_rest=-65 * u.mV, V_th=-50 * u.mV, tau=10 * u.ms)\n",
"\n",
" # E → E projection (AMPA, excitatory)\n",
" self.E2E = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(n_exc, n_exc, conn_num=0.02, conn_weight=0.6*u.mS),\n",
- " syn=brainpy.state.AMPA.desc(n_exc, tau=2.0*u.ms),\n",
- " out=brainpy.state.COBA.desc(E=0.0*u.mV),\n",
+ " comm=brainstate.nn.EventFixedProb(n_exc, n_exc, conn_num=0.02, conn_weight=0.6 * u.mS),\n",
+ " syn=brainpy.state.Expon(n_exc, tau=2. * u.ms),\n",
+ " out=brainpy.state.COBA(E=0.0 * u.mV),\n",
" post=self.E\n",
" )\n",
"\n",
" # E → I projection (AMPA, excitatory)\n",
" self.E2I = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(n_exc, n_inh, conn_num=0.02, conn_weight=0.6*u.mS),\n",
- " syn=brainpy.state.AMPA.desc(n_inh, tau=2.0*u.ms),\n",
- " out=brainpy.state.COBA.desc(E=0.0*u.mV),\n",
+ " comm=brainstate.nn.EventFixedProb(n_exc, n_inh, conn_num=0.02, conn_weight=0.6 * u.mS),\n",
+ " syn=brainpy.state.Expon(n_inh, tau=2. * u.ms),\n",
+ " out=brainpy.state.COBA(E=0.0 * u.mV),\n",
" post=self.I\n",
" )\n",
"\n",
" # I → E projection (GABAa, inhibitory)\n",
" self.I2E = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(n_inh, n_exc, conn_num=0.02, conn_weight=6.7*u.mS),\n",
- " syn=brainpy.state.GABAa.desc(n_exc, tau=6.0*u.ms),\n",
- " out=brainpy.state.COBA.desc(E=-80.0*u.mV),\n",
+ " comm=brainstate.nn.EventFixedProb(n_inh, n_exc, conn_num=0.02, conn_weight=6.7 * u.mS),\n",
+ " syn=brainpy.state.Expon(n_exc, tau=6. * u.ms),\n",
+ " out=brainpy.state.COBA(E=-80.0 * u.mV),\n",
" post=self.E\n",
" )\n",
"\n",
" # I → I projection (GABAa, inhibitory)\n",
" self.I2I = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(n_inh, n_inh, conn_num=0.02, conn_weight=6.7*u.mS),\n",
- " syn=brainpy.state.GABAa.desc(n_inh, tau=6.0*u.ms),\n",
- " out=brainpy.state.COBA.desc(E=-80.0*u.mV),\n",
+ " comm=brainstate.nn.EventFixedProb(n_inh, n_inh, conn_num=0.02, conn_weight=6.7 * u.mS),\n",
+ " syn=brainpy.state.Expon(n_inh, tau=6. * u.ms),\n",
+ " out=brainpy.state.COBA(E=-80.0 * u.mV),\n",
" post=self.I\n",
" )\n",
"\n",
- " def update(self, t, i, inp_e, inp_i):\n",
+ " def update(self, i, inp_e, inp_i):\n",
+ " t = brainstate.environ.get_dt() * i\n",
" with brainstate.environ.context(t=t, i=i):\n",
" # Get spikes BEFORE updating neurons\n",
" spk_e = self.E.get_spike()\n",
@@ -716,8 +788,15 @@
" self.E(inp_e)\n",
" self.I(inp_i)\n",
"\n",
- " return spk_e, spk_i"
- ]
+ " return spk_e, spk_i\n",
+ "\n",
+ "\n",
+ "net = EINetwork()\n",
+ "brainstate.nn.init_all_states(net)\n",
+ "_ = brainstate.transform.for_loop(net.update, indices, inputs, inputs)"
+ ],
+ "outputs": [],
+ "execution_count": 32
},
{
"cell_type": "markdown",
@@ -740,21 +819,21 @@
" def __init__(self, n_pre=100, n_post=100):\n",
" super().__init__()\n",
"\n",
- " self.post = brainpy.state.LIF(n_post, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
+ " self.post = brainpy.state.LIF(n_post, V_rest=-65 * u.mV, V_th=-50 * u.mV, tau=10 * u.ms)\n",
"\n",
" # Fast AMPA component\n",
" self.ampa_proj = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(n_pre, n_post, conn_num=0.1, conn_weight=0.3*u.mS),\n",
- " syn=brainpy.state.AMPA.desc(n_post, tau=2.0*u.ms),\n",
- " out=brainpy.state.COBA.desc(E=0.0*u.mV),\n",
+ " comm=brainstate.nn.EventFixedProb(n_pre, n_post, conn_num=0.1, conn_weight=0.3 * u.mS),\n",
+ " syn=brainpy.state.AMPA(n_post, tau=2.0 * u.ms),\n",
+ " out=brainpy.state.COBA(E=0.0 * u.mV),\n",
" post=self.post\n",
" )\n",
"\n",
" # Slow NMDA component\n",
" self.nmda_proj = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(n_pre, n_post, conn_num=0.1, conn_weight=0.3*u.mS),\n",
- " syn=brainpy.state.NMDA.desc(n_post, tau_decay=100.0*u.ms, tau_rise=2.0*u.ms),\n",
- " out=brainpy.state.MgBlock.desc(E=0.0*u.mV, cc_Mg=1.2*u.mM),\n",
+ " comm=brainstate.nn.EventFixedProb(n_pre, n_post, conn_num=0.1, conn_weight=0.3 * u.mS),\n",
+ " syn=brainpy.state.NMDA(n_post, tau_decay=100.0 * u.ms, tau_rise=2.0 * u.ms),\n",
+ " out=brainpy.state.MgBlock(E=0.0 * u.mV, cc_Mg=1.2 * u.mM),\n",
" post=self.post\n",
" )\n",
"\n",
@@ -774,554 +853,66 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "## Advanced Topics\n",
- "\n",
- "### Delay Projections\n",
+ "### Example 4: Delay Projections\n",
"\n",
"Add synaptic delays to projections."
]
},
{
"cell_type": "code",
- "execution_count": 249,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T11:57:15.058629Z",
+ "start_time": "2025-11-13T11:57:14.596654Z"
+ }
+ },
"source": [
- "import jax\n",
"\n",
- "# Define post_neurons for demonstration\n",
- "post_neurons = brainpy.state.LIF(100, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
"\n",
"# To implement delay, use a separate Delay module\n",
"delay_time = 5.0 * u.ms\n",
"\n",
+ "\n",
"# Create a network with delay\n",
"class DelayedProjection(brainstate.nn.Module):\n",
" def __init__(self, pre_size, post_size):\n",
" super().__init__()\n",
- " \n",
- " # Delay buffer for spikes\n",
- " self.delay = brainstate.nn.Delay(\n",
- " jax.ShapeDtypeStruct((pre_size,), bool), \n",
- " delay_time\n",
- " )\n",
- " \n",
+ "\n",
+ " # Define post_neurons for demonstration\n",
+ " self.post = brainpy.state.LIF(100, V_rest=-65 * u.mV, V_th=-50 * u.mV, tau=10 * u.ms)\n",
+ " self.delay = self.post.output_delay(delay_time)\n",
+ "\n",
" # Standard projection\n",
" self.proj = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(pre_size, post_size, conn_num=0.1, conn_weight=0.5),\n",
- " syn=brainpy.state.Expon.desc(post_size, tau=5.0*u.ms),\n",
- " out=brainpy.state.CUBA.desc(),\n",
- " post=post_neurons\n",
+ " comm=brainstate.nn.EventFixedProb(pre_size, post_size, conn_num=0.1, conn_weight=0.5 * u.mS),\n",
+ " syn=brainpy.state.Expon(post_size, tau=5.0 * u.ms),\n",
+ " out=brainpy.state.CUBA(),\n",
+ " post=self.post\n",
" )\n",
- " \n",
- " def update(self, pre_spikes):\n",
+ "\n",
+ " def update(self, inp=0. * u.nA):\n",
" # Retrieve delayed spikes\n",
- " delayed_spikes = self.delay.retrieve_at_step(\n",
- " u.math.asarray(delay_time / brainstate.environ.get_dt(), dtype=int)\n",
- " )\n",
+ " delayed_spikes = self.delay()\n",
" # Update projection with delayed spikes\n",
" self.proj(delayed_spikes)\n",
+ " self.post(inp)\n",
" # Store current spikes in delay buffer\n",
- " self.delay(pre_spikes)\n",
- "\n",
- "# Example usage:\n",
- "# delayed_proj = DelayedProjection(100, 100)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Use cases:**\n",
- "- Biologically realistic transmission delays\n",
- "- Axonal conduction delays\n",
- "- Synchronization studies\n",
- "\n",
- "### Heterogeneous Weights\n",
- "\n",
- "Different weights for different connections."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 250,
- "metadata": {},
- "outputs": [],
- "source": [
- "import jax.numpy as jnp\n",
- "\n",
- "# Custom weight matrix\n",
- "n_pre, n_post = 100, 50\n",
- "weights = jnp.abs(brainstate.random.randn(n_pre, n_post)) * 0.5\n",
- "\n",
- "# Note: EventJitFPHomoLinear may not support heterogeneous weights\n",
- "# For custom weights, consider using Linear or custom communication layer\n",
- "# comm = brainstate.nn.Linear(n_pre, n_post, w_init=lambda key, shape: weights)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Learning Synapses\n",
- "\n",
- "Combine with plasticity (see ../tutorials/advanced/06-synaptic-plasticity)."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 251,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Projection with learnable weights\n",
- "class PlasticProjection(brainstate.nn.Module):\n",
- " def __init__(self, n_pre, n_post):\n",
- " super().__init__()\n",
+ " self.delay(self.post.get_spike())\n",
"\n",
- " # Initialize weights as parameters\n",
- " self.weights = brainstate.ParamState(\n",
- " jnp.ones((n_pre, n_post)) * 0.5 * u.mS\n",
- " )\n",
- "\n",
- " self.proj = brainpy.state.AlignPostProj(\n",
- " comm=CustomComm(self.weights), # Use learnable weights\n",
- " syn=brainpy.state.Expon.desc(n_post, tau=5.0*u.ms),\n",
- " out=brainpy.state.CUBA.desc(),\n",
- " post=post_neurons\n",
- " )\n",
- "\n",
- " def update_weights(self, dw):\n",
- " \"\"\"Update weights based on learning rule.\"\"\"\n",
- " self.weights.value += dw"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Best Practices\n",
- "\n",
- "### Choosing Communication Type\n",
- "\n",
- "**Use EventFixedProb when:**\n",
- "- Large networks (>1000 neurons)\n",
- "- Sparse connectivity (<10%)\n",
- "- Biological models\n",
- "\n",
- "**Use Linear when:**\n",
- "- Small networks (<1000 neurons)\n",
- "- Fully connected layers\n",
- "- Training with gradients\n",
- "\n",
- "**Use EventOne2One when:**\n",
- "- Same-size populations\n",
- "- Feedforward pathways\n",
- "- Identity mappings\n",
- "\n",
- "### Choosing Synapse Type\n",
- "\n",
- "**Use Expon when:**\n",
- "- Default choice for most models\n",
- "- Fast computation needed\n",
- "- Simple dynamics sufficient\n",
- "\n",
- "**Use Alpha when:**\n",
- "- Rise time is important\n",
- "- More biological realism\n",
- "- Smoother responses\n",
- "\n",
- "**Use AMPA/NMDA/GABA when:**\n",
- "- Specific receptor types matter\n",
- "- Pharmacological studies\n",
- "- Detailed biological models\n",
- "\n",
- "### Choosing Output Type\n",
- "\n",
- "**Use CUBA when:**\n",
- "- Abstract models\n",
- "- Training with gradients\n",
- "- Speed is critical\n",
- "\n",
- "**Use COBA when:**\n",
- "- Biological realism needed\n",
- "- Voltage dependence matters\n",
- "- Shunting inhibition required\n",
- "\n",
- "### Performance Tips\n",
- "\n",
- "1. **Sparse over Dense:** Use sparse connectivity for large networks\n",
- "2. **Batch initialization:** Initialize all modules together\n",
- "3. **JIT compile:** Wrap simulation loop with `@brainstate.transform.jit`\n",
- "4. **Appropriate precision:** Use float32 unless high precision needed\n",
- "5. **Minimize communication:** Group projections with same connectivity\n",
- "\n",
- "### Common Patterns\n",
+ " def step_run(self, i, inp):\n",
+ " t = brainstate.environ.get_dt() * i\n",
+ " with brainstate.environ.context(t=t, i=i):\n",
+ " # Update post neurons\n",
+ " self.update(inp)\n",
+ " return self.post.get_spike()\n",
"\n",
- "**Pattern 1: Dale's Principle**\n",
"\n",
- "Neurons are either excitatory OR inhibitory (not both)."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 252,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[LIF(\n",
- " in_size=(800,),\n",
- " out_size=(800,),\n",
- " spk_reset=soft,\n",
- " spk_fun=ReluGrad(alpha=0.3, width=1.0),\n",
- " R=1. * ohm,\n",
- " tau=10 * msecond,\n",
- " V_th=-50 * mvolt,\n",
- " V_rest=-65 * mvolt,\n",
- " V_reset=0. * mvolt,\n",
- " V_initializer=Constant(value=0.0 * mvolt),\n",
- " V=HiddenState(\n",
- " value=~float32[800] * mvolt\n",
- " )\n",
- " ),\n",
- " LIF(\n",
- " in_size=(200,),\n",
- " out_size=(200,),\n",
- " spk_reset=soft,\n",
- " spk_fun=ReluGrad(alpha=0.3, width=1.0),\n",
- " R=1. * ohm,\n",
- " tau=10 * msecond,\n",
- " V_th=-50 * mvolt,\n",
- " V_rest=-65 * mvolt,\n",
- " V_reset=0. * mvolt,\n",
- " V_initializer=Constant(value=0.0 * mvolt),\n",
- " V=HiddenState(\n",
- " value=~float32[200] * mvolt\n",
- " )\n",
- " )]"
- ]
- },
- "execution_count": 252,
- "metadata": {},
- "output_type": "execute_result"
- }
+ "net = DelayedProjection(100, 100)\n",
+ "brainstate.nn.init_all_states(net)\n",
+ "_ = brainstate.transform.for_loop(net.step_run, indices, inputs)"
],
- "source": [
- "# Set simulation timestep if not already set\n",
- "brainstate.environ.set(dt=0.1 * u.ms)\n",
- "\n",
- "# Separate excitatory and inhibitory populations\n",
- "E = brainpy.state.LIF(800, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "I = brainpy.state.LIF(200, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "\n",
- "# Initialize states\n",
- "brainstate.nn.init_all_states([E, I])\n",
- "\n",
- "# E always excitatory (E=0mV)\n",
- "# I always inhibitory (E=-80mV)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Pattern 2: Balanced Networks**\n",
- "\n",
- "Excitation balanced by inhibition."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 253,
- "metadata": {},
"outputs": [],
- "source": [
- "# Strong inhibition to balance excitation\n",
- "w_exc = 0.6 * u.mS\n",
- "w_inh = 6.7 * u.mS # ~10× stronger\n",
- "\n",
- "# More E neurons than I (4:1 ratio)\n",
- "n_exc = 800\n",
- "n_inh = 200"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Pattern 3: Recurrent Loops**\n",
- "\n",
- "Self-connections for persistent activity."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 254,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "AlignPostProj(\n",
- " name=AlignPostProj30,\n",
- " modules=(),\n",
- " merging=True,\n",
- " comm=EventFixedNumConn(\n",
- " in_size=(800,),\n",
- " out_size=(800,),\n",
- " efferent_target=post,\n",
- " conn_num=16,\n",
- " seed=None,\n",
- " allow_multi_conn=True,\n",
- " weight=ParamState(\n",
- " value=~float32[] * msiemens\n",
- " ),\n",
- " conn=FixedPostNumConn(float32[800, 800], nse=12800)\n",
- " ),\n",
- " syn=Expon(\n",
- " in_size=(800,),\n",
- " out_size=(800,),\n",
- " tau=5 * msecond,\n",
- " g_initializer=Constant(value=0.0 * msiemens),\n",
- " g=HiddenState(\n",
- " value=~float32[800] * msiemens\n",
- " )\n",
- " ),\n",
- " out=COBA(\n",
- " E=0 * mvolt\n",
- " ),\n",
- " post=LIF(\n",
- " in_size=(800,),\n",
- " out_size=(800,),\n",
- " before_updates={\n",
- " \"(, (800,), {'tau': 5 * msecond}) // (, (), {'E': 0 * mvolt})\": _AlignPost(\n",
- " syn=Expon(...),\n",
- " out=COBA(...)\n",
- " )\n",
- " },\n",
- " current_inputs={\n",
- " 'AlignPostProj30': COBA(...)\n",
- " },\n",
- " spk_reset=soft,\n",
- " spk_fun=ReluGrad(alpha=0.3, width=1.0),\n",
- " R=1. * ohm,\n",
- " tau=10 * msecond,\n",
- " V_th=-50 * mvolt,\n",
- " V_rest=-65 * mvolt,\n",
- " V_reset=0. * mvolt,\n",
- " V_initializer=Constant(value=0.0 * mvolt),\n",
- " V=HiddenState(\n",
- " value=~float32[800] * mvolt\n",
- " )\n",
- " )\n",
- ")"
- ]
- },
- "execution_count": 254,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# Set simulation timestep if not already set\n",
- "brainstate.environ.set(dt=0.1 * u.ms)\n",
- "\n",
- "# Define E population for demonstration\n",
- "E = brainpy.state.LIF(800, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "n_exc = 800\n",
- "\n",
- "# Initialize states\n",
- "brainstate.nn.init_all_states(E)\n",
- "\n",
- "# Excitatory recurrence (working memory)\n",
- "E2E = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(n_exc, n_exc, conn_num=0.02, conn_weight=0.5*u.mS),\n",
- " syn=brainpy.state.Expon.desc(n_exc, tau=5*u.ms),\n",
- " out=brainpy.state.COBA.desc(E=0*u.mV),\n",
- " post=E\n",
- ")\n",
- "\n",
- "# Initialize projection states\n",
- "brainstate.nn.init_all_states(E2E)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Troubleshooting\n",
- "\n",
- "### Issue: Spikes not propagating\n",
- "\n",
- "**Symptoms:** Postsynaptic neurons don't receive input\n",
- "\n",
- "**Solutions:**\n",
- "\n",
- "1. Check spike timing: Call `get_spike()` BEFORE updating\n",
- "2. Verify connectivity: Check `prob` and `weight`\n",
- "3. Check update order: Projections before neurons"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 255,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Set simulation timestep\n",
- "brainstate.environ.set(dt=0.1 * u.ms)\n",
- "\n",
- "# Define neurons and projection for demonstration\n",
- "pre = brainpy.state.LIF(100, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "post = brainpy.state.LIF(50, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "proj = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(100, 50, conn_num=0.1, conn_weight=0.5),\n",
- " syn=brainpy.state.Expon.desc(50, tau=5.0*u.ms),\n",
- " out=brainpy.state.CUBA.desc(),\n",
- " post=post\n",
- ")\n",
- "\n",
- "# Initialize all states\n",
- "brainstate.nn.init_all_states([pre, post, proj])\n",
- "\n",
- "# Define input current\n",
- "inp = jnp.ones(100) * 5.0 * u.nA\n",
- "\n",
- "# CORRECT order - in update function context\n",
- "def correct_update(t, i):\n",
- " with brainstate.environ.context(t=t, i=i):\n",
- " spk = pre.get_spike() # Get spikes from previous step\n",
- " proj(spk) # Update projection\n",
- " pre(inp) # Update neurons\n",
- " return spk\n",
- "\n",
- "# Example: run one step\n",
- "result = correct_update(0.0*u.ms, 0)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Issue: Network silent or exploding\n",
- "\n",
- "**Symptoms:** No activity or runaway firing\n",
- "\n",
- "**Solutions:**\n",
- "\n",
- "1. Balance E/I weights (I should be ~10× stronger)\n",
- "2. Check reversal potentials (E=0mV, I=-80mV)\n",
- "3. Verify threshold and reset values\n",
- "4. Add external input"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 256,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Balanced weights\n",
- "w_exc = 0.5 * u.mS\n",
- "w_inh = 5.0 * u.mS # Strong inhibition\n",
- "\n",
- "# Proper reversal potentials\n",
- "out_exc = brainpy.state.COBA.desc(E=0.0 * u.mV)\n",
- "out_inh = brainpy.state.COBA.desc(E=-80.0 * u.mV)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Issue: Slow simulation\n",
- "\n",
- "**Solutions:**\n",
- "\n",
- "1. Use sparse connectivity (EventFixedProb)\n",
- "2. Use JIT compilation\n",
- "3. Use CUBA instead of COBA (if appropriate)\n",
- "4. Reduce connectivity or neurons"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 257,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Fast configuration\n",
- "@brainstate.transform.jit\n",
- "def simulate_step(net, t, i, inp):\n",
- " with brainstate.environ.context(t=t, i=i):\n",
- " return net.update(t, i, inp, inp)\n",
- "\n",
- "# Sparse connectivity\n",
- "comm = brainstate.nn.EventFixedProb(1000, 1000, conn_num=0.02, conn_weight=0.5)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Further Reading\n",
- "\n",
- "- ../tutorials/basic/03-network-connections - Network connections tutorial\n",
- "- architecture - Overall BrainPy architecture\n",
- "- synapses - Detailed synapse models\n",
- "- ../tutorials/advanced/06-synaptic-plasticity - Learning in projections\n",
- "- ../tutorials/advanced/07-large-scale-simulations - Scaling projections\n",
- "\n",
- "## Summary\n",
- "\n",
- "**Key takeaways:**\n",
- "\n",
- "✅ Projections use Comm-Syn-Out architecture\n",
- "\n",
- "✅ Communication: Dense (Linear) or Sparse (EventFixedProb)\n",
- "\n",
- "✅ Synapse: Temporal dynamics (Expon, Alpha, AMPA, GABA, NMDA)\n",
- "\n",
- "✅ Output: Current-based (CUBA) or Conductance-based (COBA)\n",
- "\n",
- "✅ Choose components based on scale, realism, and performance needs\n",
- "\n",
- "✅ Follow Dale's principle and balanced E/I patterns\n",
- "\n",
- "✅ Get spikes BEFORE updating for correct propagation\n",
- "\n",
- "**Quick reference:**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 258,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Define postsynaptic neurons for template\n",
- "post_neurons = brainpy.state.LIF(50, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "n_pre = 100\n",
- "n_post = 50\n",
- "\n",
- "# Standard projection template\n",
- "proj = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(n_pre, n_post, conn_num=0.1, conn_weight=0.5*u.mS),\n",
- " syn=brainpy.state.Expon.desc(n_post, tau=5.0*u.ms),\n",
- " out=brainpy.state.COBA.desc(E=0.0*u.mV),\n",
- " post=post_neurons\n",
- ")\n",
- "\n",
- "# Usage in network\n",
- "# def update(self, t, i):\n",
- "# with brainstate.environ.context(t=t, i=i):\n",
- "# spk = self.pre.get_spike() # Get spikes first\n",
- "# self.proj(spk) # Update projection\n",
- "# self.pre(inp) # Update neurons\n",
- "# self.post(0*u.nA)"
- ]
+ "execution_count": 36
}
],
"metadata": {
diff --git a/docs_state/quickstart/core-concepts/state-management.ipynb b/docs_state/quickstart/core-concepts/state-management.ipynb
deleted file mode 100644
index f017289c..00000000
--- a/docs_state/quickstart/core-concepts/state-management.ipynb
+++ /dev/null
@@ -1,1599 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# State Management: The Foundation of ``brainpy.state``\n",
- "\n",
- "State management is the core architectural change in `brainpy.state`. Understanding states is\n",
- "essential for using BrainPy effectively. This guide provides comprehensive coverage of the state\n",
- "system built on `brainstate`.\n",
- "\n",
- "**Table of Contents**\n",
- "\n",
- "## Overview\n",
- "\n",
- "### What is State?\n",
- "\n",
- "**State** is any variable that persists across function calls and can change over time. In neural simulations:\n",
- "\n",
- "- Membrane potentials\n",
- "- Synaptic conductances\n",
- "- Spike trains\n",
- "- Learnable weights\n",
- "- Temporary buffers\n",
- "\n",
- "**Key insight:** `brainpy.state` makes states **explicit** rather than implicit. Every stateful variable is declared and tracked.\n",
- "\n",
- "### Why Explicit State Management?\n",
- "\n",
- "**Problems with implicit state (BrainPy 2.x):**\n",
- "\n",
- "- Hard to track what changes when\n",
- "- Difficult to serialize/checkpoint\n",
- "- Unclear initialization procedures\n",
- "- Conflicts with JAX functional programming\n",
- "\n",
- "**Benefits of explicit state (`brainpy.state`):**\n",
- "\n",
- "✅ Clear variable lifecycle\n",
- "\n",
- "✅ Easy checkpointing and loading\n",
- "\n",
- "✅ Functional programming compatible\n",
- "\n",
- "✅ Better debugging and introspection\n",
- "\n",
- "✅ Automatic differentiation support\n",
- "\n",
- "✅ Type safety and validation\n",
- "\n",
- "### The State Hierarchy\n",
- "\n",
- "BrainPy uses different state types for different purposes:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "State (base class)\n",
- "│\n",
- "├── ParamState ← Learnable parameters (weights, biases)\n",
- "├── ShortTermState ← Temporary dynamics (V, g, spikes)\n",
- "└── LongTermState ← Persistent but non-learnable (statistics)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Each type has different semantics and handling:\n",
- "\n",
- "- **ParamState**: Updated by optimizers, saved in checkpoints\n",
- "- **ShortTermState**: Reset each trial, not saved\n",
- "- **LongTermState**: Saved but not trained\n",
- "\n",
- "## State Types\n",
- "\n",
- "### ParamState: Learnable Parameters\n",
- "\n",
- "**Use for:** Weights, biases, trainable parameters\n",
- "\n",
- "**Characteristics:**\n",
- "\n",
- "- Updated by gradient descent\n",
- "- Saved in model checkpoints\n",
- "- Persistent across trials\n",
- "- Registered with optimizers\n",
- "\n",
- "**Example:**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [],
- "source": [
- "import brainstate\n",
- "import jax.numpy as jnp\n",
- "\n",
- "class LinearLayer(brainstate.nn.Module):\n",
- " def __init__(self, in_size, out_size):\n",
- " super().__init__()\n",
- "\n",
- " # Learnable weight matrix\n",
- " self.W = brainstate.ParamState(\n",
- " brainstate.random.randn(in_size, out_size) * 0.01\n",
- " )\n",
- "\n",
- " # Learnable bias vector\n",
- " self.b = brainstate.ParamState(\n",
- " jnp.zeros(out_size)\n",
- " )\n",
- "\n",
- " def update(self, x):\n",
- " # Use parameters in computation\n",
- " return jnp.dot(x, self.W.value) + self.b.value\n",
- "\n",
- "# Access all parameters\n",
- "layer = LinearLayer(100, 50)\n",
- "params = layer.states(brainstate.ParamState)\n",
- "# Returns: {'W': ParamState(...), 'b': ParamState(...)}"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Common uses:**\n",
- "\n",
- "- Synaptic weights\n",
- "- Neural biases\n",
- "- Time constants (if learning them)\n",
- "- Connectivity matrices (if plastic)\n",
- "\n",
- "### ShortTermState: Temporary Dynamics\n",
- "\n",
- "**Use for:** Variables that reset each trial\n",
- "\n",
- "**Characteristics:**\n",
- "\n",
- "- Reset at trial start\n",
- "- Not saved in checkpoints\n",
- "- Represent current dynamics\n",
- "- Fastest state type\n",
- "\n",
- "**Example:**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [],
- "source": [
- "import brainpy as bp\n",
- "import brainunit as u\n",
- "\n",
- "class LIFNeuron(brainstate.nn.Module):\n",
- " def __init__(self, size):\n",
- " super().__init__()\n",
- "\n",
- " self.size = size\n",
- " self.V_rest = -65.0 * u.mV\n",
- " self.V_th = -50.0 * u.mV\n",
- "\n",
- " # Membrane potential (resets each trial)\n",
- " self.V = brainstate.ShortTermState(\n",
- " jnp.ones(size) * self.V_rest.to_decimal(u.mV)\n",
- " )\n",
- "\n",
- " # Spike indicator (resets each trial)\n",
- " self.spike = brainstate.ShortTermState(\n",
- " jnp.zeros(size)\n",
- " )\n",
- "\n",
- " def reset_state(self, batch_size=None):\n",
- " \"\"\"Called at trial start.\"\"\"\n",
- " if batch_size is None:\n",
- " self.V.value = jnp.ones(self.size) * self.V_rest.to_decimal(u.mV)\n",
- " self.spike.value = jnp.zeros(self.size)\n",
- " else:\n",
- " self.V.value = jnp.ones((batch_size, self.size)) * self.V_rest.to_decimal(u.mV)\n",
- " self.spike.value = jnp.zeros((batch_size, self.size))\n",
- "\n",
- " def update(self, I):\n",
- " # Update membrane potential (simplified example)\n",
- " new_V = self.V.value + I.to_decimal(u.mV) * 0.1\n",
- " new_spike = (new_V >= self.V_th.to_decimal(u.mV)).astype(float)\n",
- " \n",
- " self.V.value = new_V\n",
- " self.spike.value = new_spike"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Common uses:**\n",
- "\n",
- "- Membrane potentials\n",
- "- Synaptic conductances\n",
- "- Spike indicators\n",
- "- Refractory counters\n",
- "- Temporary buffers\n",
- "\n",
- "### LongTermState: Persistent Non-Learnable\n",
- "\n",
- "**Use for:** Statistics, counters, persistent metadata\n",
- "\n",
- "**Characteristics:**\n",
- "\n",
- "- Not reset each trial\n",
- "- Saved in checkpoints\n",
- "- Not updated by optimizers\n",
- "- Accumulates over time\n",
- "\n",
- "**Example:**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [],
- "source": [
- "class NeuronWithStatistics(brainstate.nn.Module):\n",
- " def __init__(self, size):\n",
- " super().__init__()\n",
- "\n",
- " self.V = brainstate.ShortTermState(jnp.zeros(size))\n",
- " self.spike = brainstate.ShortTermState(jnp.zeros(size))\n",
- "\n",
- " # Running spike count (persists across trials)\n",
- " self.total_spikes = brainstate.LongTermState(\n",
- " jnp.zeros(size, dtype=jnp.int32)\n",
- " )\n",
- "\n",
- " # Running average firing rate\n",
- " self.avg_rate = brainstate.LongTermState(\n",
- " jnp.zeros(size)\n",
- " )\n",
- "\n",
- " def update(self, I):\n",
- " # ... update dynamics ...\n",
- " # (Simplified example)\n",
- " self.spike.value = (self.V.value > 0).astype(float)\n",
- "\n",
- " # Accumulate statistics\n",
- " self.total_spikes.value += self.spike.value.astype(jnp.int32)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Common uses:**\n",
- "\n",
- "- Spike counters\n",
- "- Running averages\n",
- "- Homeostatic variables\n",
- "- Simulation metadata\n",
- "- Custom statistics\n",
- "\n",
- "## State Initialization\n",
- "\n",
- "### Automatic Initialization\n",
- "\n",
- "BrainPy provides `init_all_states()` for automatic initialization.\n",
- "\n",
- "**Basic usage:**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "MyNetwork(\n",
- " neuron=LIF(\n",
- " in_size=(100,),\n",
- " out_size=(100,),\n",
- " spk_reset=soft,\n",
- " spk_fun=ReluGrad(alpha=0.3, width=1.0),\n",
- " R=1. * ohm,\n",
- " tau=10 * msecond,\n",
- " V_th=-50 * mvolt,\n",
- " V_rest=-65 * mvolt,\n",
- " V_reset=0. * mvolt,\n",
- " V_initializer=Constant(value=0.0 * mvolt),\n",
- " V=HiddenState(\n",
- " value=~float32[32,100] * mvolt\n",
- " )\n",
- " )\n",
- ")"
- ]
- },
- "execution_count": 6,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "import brainstate\n",
- "import brainpy as bp\n",
- "import brainunit as u\n",
- "\n",
- "# Define a simple network for demonstration\n",
- "class MyNetwork(brainstate.nn.Module):\n",
- " def __init__(self):\n",
- " super().__init__()\n",
- " self.neuron = bp.state.LIF(100, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- " \n",
- " def update(self, inp):\n",
- " return self.neuron(inp)\n",
- "\n",
- "# Create network\n",
- "net = MyNetwork()\n",
- "\n",
- "# Initialize all states (single trial)\n",
- "brainstate.nn.init_all_states(net)\n",
- "\n",
- "# Initialize with batch dimension\n",
- "brainstate.nn.init_all_states(net, batch_size=32)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**What it does:**\n",
- "\n",
- "1. Finds all modules in the hierarchy\n",
- "2. Calls `reset_state()` on each module\n",
- "3. Handles nested structures automatically\n",
- "4. Sets up batch dimensions if requested\n",
- "\n",
- "**Example with network:**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "EINetwork(\n",
- " E=LIF(\n",
- " in_size=(800,),\n",
- " out_size=(800,),\n",
- " spk_reset=soft,\n",
- " spk_fun=ReluGrad(alpha=0.3, width=1.0),\n",
- " R=1. * ohm,\n",
- " tau=10 * msecond,\n",
- " V_th=-50 * mvolt,\n",
- " V_rest=-65 * mvolt,\n",
- " V_reset=0. * mvolt,\n",
- " V_initializer=Constant(value=0.0 * mvolt),\n",
- " V=HiddenState(\n",
- " value=~float32[10,800] * mvolt\n",
- " )\n",
- " ),\n",
- " I=LIF(\n",
- " in_size=(200,),\n",
- " out_size=(200,),\n",
- " spk_reset=soft,\n",
- " spk_fun=ReluGrad(alpha=0.3, width=1.0),\n",
- " R=1. * ohm,\n",
- " tau=10 * msecond,\n",
- " V_th=-50 * mvolt,\n",
- " V_rest=-65 * mvolt,\n",
- " V_reset=0. * mvolt,\n",
- " V_initializer=Constant(value=0.0 * mvolt),\n",
- " V=HiddenState(\n",
- " value=~float32[10,200] * mvolt\n",
- " )\n",
- " )\n",
- ")"
- ]
- },
- "execution_count": 7,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "class EINetwork(brainstate.nn.Module):\n",
- " def __init__(self):\n",
- " super().__init__()\n",
- " self.E = bp.state.LIF(800, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- " self.I = bp.state.LIF(200, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- " # ... projections ...\n",
- "\n",
- "net = EINetwork()\n",
- "\n",
- "# This initializes E, I, and all projections\n",
- "brainstate.nn.init_all_states(net, batch_size=10)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Manual Initialization\n",
- "\n",
- "For custom initialization, override `reset_state()`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [],
- "source": [
- "class CustomNeuron(brainstate.nn.Module):\n",
- " def __init__(self, size, V_init_range=(-70, -60)):\n",
- " super().__init__()\n",
- " self.size = size\n",
- " self.V_init_range = V_init_range\n",
- "\n",
- " self.V = brainstate.ShortTermState(jnp.zeros(size))\n",
- "\n",
- " def reset_state(self, batch_size=None):\n",
- " \"\"\"Custom initialization: random voltage in range.\"\"\"\n",
- "\n",
- " # Generate random initial voltages\n",
- " low, high = self.V_init_range\n",
- " if batch_size is None:\n",
- " init_V = brainstate.random.uniform(low, high, size=self.size)\n",
- " else:\n",
- " init_V = brainstate.random.uniform(low, high, size=(batch_size, self.size))\n",
- "\n",
- " self.V.value = init_V"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Best practices:**\n",
- "\n",
- "- Always check `batch_size` parameter\n",
- "- Handle both single and batched cases\n",
- "- Initialize all ShortTermStates\n",
- "- Don't initialize ParamStates (they're learnable)\n",
- "- Don't initialize LongTermStates (they persist)\n",
- "\n",
- "### Initializers for Parameters\n",
- "\n",
- "Use `braintools.init` for parameter initialization."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [],
- "source": [
- "import braintools.init as init\n",
- "\n",
- "class Network(brainstate.nn.Module):\n",
- " def __init__(self, in_size, out_size):\n",
- " super().__init__()\n",
- "\n",
- " # Xavier/Glorot initialization\n",
- " self.W1 = brainstate.ParamState(\n",
- " init.XavierNormal()(shape=(in_size, 100))\n",
- " )\n",
- "\n",
- " # Kaiming/He initialization (for ReLU)\n",
- " self.W2 = brainstate.ParamState(\n",
- " init.KaimingNormal()(shape=(100, out_size))\n",
- " )\n",
- "\n",
- " # Zero initialization\n",
- " self.b = brainstate.ParamState(\n",
- " init.Constant(0.0)(shape=(out_size,))\n",
- " )\n",
- "\n",
- " # Orthogonal initialization (for RNNs)\n",
- " self.W_rec = brainstate.ParamState(\n",
- " init.Orthogonal()(shape=(100, 100))\n",
- " )"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Available initializers:**\n",
- "\n",
- "- `Constant(value)` - Fill with constant\n",
- "- `Normal(mean, std)` - Gaussian distribution\n",
- "- `Uniform(low, high)` - Uniform distribution\n",
- "- `XavierNormal()` - Xavier/Glorot normal\n",
- "- `XavierUniform()` - Xavier/Glorot uniform\n",
- "- `KaimingNormal()` - He normal (for ReLU)\n",
- "- `KaimingUniform()` - He uniform\n",
- "- `Orthogonal()` - Orthogonal matrix (for RNNs)\n",
- "- `Identity()` - Identity matrix\n",
- "\n",
- "## State Access and Manipulation\n",
- "\n",
- "### Reading State Values\n",
- "\n",
- "Access the current value with `.value`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(100,)\n"
- ]
- }
- ],
- "source": [
- "neuron = bp.state.LIF(100, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "brainstate.nn.init_all_states(neuron)\n",
- "\n",
- "# Read current membrane potential\n",
- "current_V = neuron.V.value\n",
- "\n",
- "# Read shape\n",
- "print(current_V.shape) # (100,)\n",
- "\n",
- "# Read specific neurons\n",
- "V_neuron_0 = neuron.V.value[0]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Writing State Values\n",
- "\n",
- "Update state by assigning to `.value`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Set new value (entire array)\n",
- "neuron.V.value = jnp.ones(100) * -60.0\n",
- "\n",
- "# Update subset\n",
- "neuron.V.value = neuron.V.value.at[0:10].set(-55.0)\n",
- "\n",
- "# Increment\n",
- "neuron.V.value = neuron.V.value + 0.1"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Important:** Always assign to `.value`, not the state object itself!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example values\n",
- "new_V = jnp.ones(100) * -60.0\n",
- "\n",
- "# CORRECT\n",
- "neuron.V.value = new_V"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Collecting States\n",
- "\n",
- "Get all states of a specific type from a module."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example: Define a simple network\n",
- "example_net = MyNetwork()\n",
- "\n",
- "# Get all parameters\n",
- "params = example_net.states(brainstate.ParamState)\n",
- "# Returns: dict with parameter names as keys\n",
- "\n",
- "# Get all short-term states\n",
- "short_term = example_net.states(brainstate.ShortTermState)\n",
- "\n",
- "# Get all states (any type)\n",
- "all_states = example_net.states()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Example:**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [],
- "source": [
- "class SimpleNet(brainstate.nn.Module):\n",
- " def __init__(self):\n",
- " super().__init__()\n",
- " self.W = brainstate.ParamState(jnp.ones((10, 10)))\n",
- " self.V = brainstate.ShortTermState(jnp.zeros(10))\n",
- "\n",
- "net = SimpleNet()\n",
- "\n",
- "params = net.states(brainstate.ParamState)\n",
- "# {'W': ParamState(...)}\n",
- "\n",
- "states = net.states(brainstate.ShortTermState)\n",
- "# {'V': ShortTermState(...)}"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## State in Training\n",
- "\n",
- "### Gradient Computation\n",
- "\n",
- "Use `brainstate.transform.grad()` to compute gradients w.r.t. parameters."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example data for demonstration\n",
- "X = jnp.ones((10, 10)) # 10 samples, 10 features\n",
- "y = jnp.ones((10, 10)) # 10 targets\n",
- "\n",
- "def loss_fn(params, net, X, y):\n",
- " \"\"\"Loss function parameterized by params.\"\"\"\n",
- " # params is automatically used by net\n",
- " output = net(X)\n",
- " return jnp.mean((output - y) ** 2)\n",
- "\n",
- "# Get parameters\n",
- "params = net.states(brainstate.ParamState)\n",
- "\n",
- "# Compute gradients (if parameters exist)\n",
- "if len(params) > 0:\n",
- " grads = brainstate.transform.grad(loss_fn, params)(net, X, y)\n",
- " # grads has same structure as params\n",
- " # grads = {'W': gradient_for_W, 'b': gradient_for_b, ...}\n",
- "else:\n",
- " print(\"No trainable parameters in this network\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Key points:**\n",
- "\n",
- "- Gradients computed only for ParamState\n",
- "- ShortTermState treated as constants\n",
- "- Gradient structure matches parameter structure\n",
- "\n",
- "### Optimizer Updates\n",
- "\n",
- "Register parameters with optimizer and update."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import braintools\n",
- "\n",
- "# Create optimizer (use 'lr' not 'learning_rate')\n",
- "optimizer = braintools.optim.Adam(lr=1e-3)\n",
- "\n",
- "# Register trainable parameters\n",
- "params = net.states(brainstate.ParamState)\n",
- "if len(params) > 0:\n",
- " optimizer.register_trainable_weights(params)\n",
- "\n",
- "# Training loop (example structure)\n",
- "for epoch in range(num_epochs):\n",
- " for batch in data_loader:\n",
- " X, y = batch\n",
- "\n",
- " # Compute gradients\n",
- " grads = brainstate.transform.grad(\n",
- " loss_fn,\n",
- " params,\n",
- " return_value=False\n",
- " )(net, X, y)\n",
- "\n",
- " # Update parameters\n",
- " optimizer.update(grads)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**The optimizer automatically:**\n",
- "\n",
- "- Updates all registered parameters\n",
- "- Applies learning rate\n",
- "- Handles momentum/adaptive rates\n",
- "- Maintains optimizer state (momentum buffers, etc.)\n",
- "\n",
- "### State Persistence\n",
- "\n",
- "Training doesn't reset ShortTermState between batches (unless you do it manually)."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example: Training with state reset each example\n",
- "# (Pseudocode - demonstrates the pattern)\n",
- "\n",
- "import braintools\n",
- "\n",
- "# Prepare dummy data\n",
- "data_loader = [(jnp.ones(100) * u.nA, jnp.zeros(100)) for _ in range(5)]\n",
- "\n",
- "# Training loop with state reset each example\n",
- "for X, y in data_loader:\n",
- " # Reset dynamics for new example\n",
- " brainstate.nn.init_all_states(net)\n",
- "\n",
- " # Forward pass (dynamics evolve)\n",
- " output = net(X)\n",
- "\n",
- " # Backward pass\n",
- " params = net.states(brainstate.ParamState)\n",
- " if len(params) > 0:\n",
- " grads = brainstate.transform.grad(loss_fn, params)(net, X, y)\n",
- " optimizer.update(grads)\n",
- "\n",
- "# Training with persistent state (e.g., RNN)\n",
- "for X, y in data_loader:\n",
- " # Don't reset - state carries over\n",
- " output = net(X)\n",
- " params = net.states(brainstate.ParamState)\n",
- " if len(params) > 0:\n",
- " grads = brainstate.transform.grad(loss_fn, params)(net, X, y)\n",
- " optimizer.update(grads)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Batching\n",
- "\n",
- "### Batch Dimensions\n",
- "\n",
- "States can have a batch dimension for parallel trials.\n",
- "\n",
- "**Single trial:**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "LIF(\n",
- " in_size=(100,),\n",
- " out_size=(100,),\n",
- " spk_reset=soft,\n",
- " spk_fun=ReluGrad(alpha=0.3, width=1.0),\n",
- " R=1. * ohm,\n",
- " tau=10 * msecond,\n",
- " V_th=-50 * mvolt,\n",
- " V_rest=-65 * mvolt,\n",
- " V_reset=0. * mvolt,\n",
- " V_initializer=Constant(value=0.0 * mvolt),\n",
- " V=HiddenState(\n",
- " value=~float32[100] * mvolt\n",
- " )\n",
- ")"
- ]
- },
- "execution_count": 84,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "neuron = bp.state.LIF(100, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "brainstate.nn.init_all_states(neuron)\n",
- "# neuron.V.value.shape = (100,)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Batched trials:**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "LIF(\n",
- " in_size=(100,),\n",
- " out_size=(100,),\n",
- " spk_reset=soft,\n",
- " spk_fun=ReluGrad(alpha=0.3, width=1.0),\n",
- " R=1. * ohm,\n",
- " tau=10 * msecond,\n",
- " V_th=-50 * mvolt,\n",
- " V_rest=-65 * mvolt,\n",
- " V_reset=0. * mvolt,\n",
- " V_initializer=Constant(value=0.0 * mvolt),\n",
- " V=HiddenState(\n",
- " value=~float32[32,100] * mvolt\n",
- " )\n",
- ")"
- ]
- },
- "execution_count": 85,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "neuron = bp.state.LIF(100, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "brainstate.nn.init_all_states(neuron, batch_size=32)\n",
- "# neuron.V.value.shape = (32, 100)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Usage:**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Input also needs batch dimension\n",
- "inp = brainstate.random.rand(32, 100) * 2.0 * u.nA\n",
- "\n",
- "# Update operates on all batches in parallel\n",
- "neuron(inp)\n",
- "\n",
- "# Output has batch dimension\n",
- "spikes = neuron.get_spike() # shape: (32, 100)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Benefits of Batching\n",
- "\n",
- "**1. Parallelism:** GPU processes all batches simultaneously\n",
- "\n",
- "**2. Statistical averaging:** Reduce noise in gradients\n",
- "\n",
- "**3. Exploration:** Try different initial conditions\n",
- "\n",
- "**4. Efficiency:** Amortize compilation cost\n",
- "\n",
- "**Example: Parameter sweep with batching**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Test 10 different input currents in parallel\n",
- "batch_size = 10\n",
- "neuron_batched = bp.state.LIF(100, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "brainstate.nn.init_all_states(neuron_batched, batch_size=batch_size)\n",
- "\n",
- "# Different input for each batch\n",
- "currents = jnp.linspace(0, 5, batch_size).reshape(-1, 1) * u.nA\n",
- "inp_batched = jnp.broadcast_to(currents, (batch_size, 100))\n",
- "\n",
- "# Simulate (example - shortened for demonstration)\n",
- "# for _ in range(1000):\n",
- "# neuron_batched(inp_batched)\n",
- "\n",
- "# Analyze each trial separately\n",
- "# spike_counts = jnp.sum(neuron_batched.spike.value, axis=1) # (10,)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Checkpointing and Serialization\n",
- "\n",
- "### Saving Models\n",
- "\n",
- "Save model state to disk."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import pickle\n",
- "\n",
- "# Example: Saving checkpoint (pseudocode)\n",
- "current_epoch = 10 # Example epoch number\n",
- "# \n",
- "# # Get all states to save\n",
- "state_dict = {\n",
- " 'params': net.states(brainstate.ParamState),\n",
- " 'long_term': net.states(brainstate.LongTermState),\n",
- " 'epoch': current_epoch,\n",
- " 'optimizer_state': optimizer.state_dict() # If applicable\n",
- "}\n",
- "# \n",
- "# Save to file\n",
- "with open('checkpoint.pkl', 'wb') as f:\n",
- " pickle.dump(state_dict, f)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Note:** Don't save ShortTermState (it resets each trial).\n",
- "\n",
- "### Loading Models\n",
- "\n",
- "Restore model state from disk."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example: Loading checkpoint\n",
- "with open('checkpoint.pkl', 'rb') as f:\n",
- " state_dict = pickle.load(f)\n",
- "\n",
- "# Create fresh model\n",
- "net = MyNetwork()\n",
- "brainstate.nn.init_all_states(net)\n",
- "\n",
- "# Restore parameters\n",
- "params = state_dict['params']\n",
- "for name, param_state in params.items():\n",
- " # Find corresponding parameter in net and copy value\n",
- " net_params = net.states(brainstate.ParamState)\n",
- " if name in net_params:\n",
- " net_params[name].value = param_state.value\n",
- "\n",
- "# Restore long-term states similarly\n",
- "\n",
- "# Restore optimizer if continuing training\n",
- "optimizer.load_state_dict(state_dict['optimizer_state'])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Best Practices for Checkpointing\n",
- "\n",
- "**1. Save regularly during training**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "epoch = 10\n",
- "save_interval = 5\n",
- "\n",
- "if epoch % save_interval == 0:\n",
- " save_checkpoint(net, optimizer, epoch, path)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**2. Keep multiple checkpoints**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "epoch = 10\n",
- "save_path = f'checkpoint_epoch_{epoch}.pkl'"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**3. Save best model separately**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "val_loss = 0.5\n",
- "best_val_loss = 1.0\n",
- "\n",
- "if val_loss < best_val_loss:\n",
- " best_val_loss = val_loss\n",
- " save_checkpoint(net, optimizer, epoch, 'best_model.pkl')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**4. Include metadata**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "from datetime import datetime\n",
- "\n",
- "state_dict = {\n",
- " 'params': net.states(brainstate.ParamState),\n",
- " 'epoch': 10,\n",
- " 'best_val_loss': 0.5,\n",
- " 'config': {'lr': 1e-3, 'batch_size': 32}, # Hyperparameters\n",
- " 'timestamp': datetime.now()\n",
- "}"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Common Patterns\n",
- "\n",
- "### Pattern 1: Resetting Between Trials"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example: Simulate multiple trials (pseudocode)\n",
- "num_trials = 10\n",
- "trial_length = 100\n",
- "\n",
- "def get_input(trial, t):\n",
- " \"\"\"Generate input for given trial and time.\"\"\"\n",
- " return jnp.ones(100) * 5.0 * u.nA\n",
- "\n",
- "def record(output):\n",
- " \"\"\"Record output for analysis.\"\"\"\n",
- " pass\n",
- "\n",
- "# Simulate multiple trials\n",
- "for trial in range(num_trials):\n",
- " # Reset dynamics\n",
- " brainstate.nn.init_all_states(net)\n",
- "\n",
- " # Run trial\n",
- " for t in range(trial_length):\n",
- " inp = get_input(trial, t)\n",
- " output = net(inp)\n",
- " record(output)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Pattern 2: Accumulating Statistics"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "class NeuronWithStats(brainstate.nn.Module):\n",
- " def __init__(self, size):\n",
- " super().__init__()\n",
- " self.V = brainstate.ShortTermState(jnp.zeros(size))\n",
- "\n",
- " # Accumulate across trials\n",
- " self.total_spikes = brainstate.LongTermState(\n",
- " jnp.zeros(size, dtype=jnp.int32)\n",
- " )\n",
- " self.n_steps = brainstate.LongTermState(0)\n",
- "\n",
- " def update(self, I):\n",
- " # ... dynamics ...\n",
- "\n",
- " # Accumulate\n",
- " self.total_spikes.value += self.spike.value.astype(jnp.int32)\n",
- " self.n_steps.value += 1\n",
- "\n",
- " def get_firing_rate(self):\n",
- " \"\"\"Average firing rate across all trials.\"\"\"\n",
- " dt = brainstate.environ.get_dt()\n",
- " total_time = self.n_steps.value * dt.to_decimal(u.second)\n",
- " return self.total_spikes.value / total_time"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Pattern 3: Conditional Updates"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "class AdaptiveNeuron(brainstate.nn.Module):\n",
- " def __init__(self, size):\n",
- " super().__init__()\n",
- " self.V = brainstate.ShortTermState(jnp.zeros(size))\n",
- " self.spike = brainstate.ShortTermState(jnp.zeros(size))\n",
- " self.threshold = brainstate.ParamState(jnp.ones(size) * (-50.0))\n",
- "\n",
- " def update(self, I):\n",
- " # Dynamics (simplified)\n",
- " self.spike.value = (self.V.value > self.threshold.value).astype(float)\n",
- "\n",
- " # Homeostatic threshold adaptation\n",
- " # Simplified spike rate computation\n",
- " spike_rate = jnp.mean(self.spike.value) * 1000.0 # Assume dt=1ms\n",
- "\n",
- " # Adjust threshold based on activity\n",
- " target_rate = 5.0 # Hz\n",
- " adjustment = 0.01 * (spike_rate - target_rate)\n",
- "\n",
- " # Update learnable threshold\n",
- " self.threshold.value -= adjustment"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Pattern 4: Hierarchical States"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "class MyLayer(brainstate.nn.Module):\n",
- " def __init__(self, in_size, out_size):\n",
- " super().__init__()\n",
- " self.W = brainstate.ParamState(jnp.ones((in_size, out_size)) * 0.01)\n",
- " \n",
- " def update(self, x):\n",
- " return jnp.dot(x, self.W.value)\n",
- "\n",
- "class HierarchicalNetwork(brainstate.nn.Module):\n",
- " def __init__(self):\n",
- " super().__init__()\n",
- " # Submodules have their own states\n",
- " self.layer1 = MyLayer(100, 50)\n",
- " self.layer2 = MyLayer(50, 10)\n",
- "\n",
- " def update(self, x):\n",
- " # Each layer manages its own states\n",
- " h1 = self.layer1(x)\n",
- " h2 = self.layer2(h1)\n",
- " return h2\n",
- "\n",
- "net = HierarchicalNetwork()\n",
- "\n",
- "# Collect ALL states from hierarchy\n",
- "all_params = net.states(brainstate.ParamState)\n",
- "# Includes params from layer1 AND layer2\n",
- "\n",
- "# Initialize ALL states in hierarchy\n",
- "brainstate.nn.init_all_states(net)\n",
- "# Calls reset_state() on net, layer1, and layer2"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Advanced Topics\n",
- "\n",
- "### Custom State Types\n",
- "\n",
- "Create custom state types for specialized needs."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "class RandomState(brainstate.State):\n",
- " \"\"\"State that re-randomizes on reset.\"\"\"\n",
- "\n",
- " def __init__(self, shape, low=0.0, high=1.0):\n",
- " super().__init__(jnp.zeros(shape))\n",
- " self.shape = shape\n",
- " self.low = low\n",
- " self.high = high\n",
- "\n",
- " def reset(self):\n",
- " \"\"\"Re-randomize on reset.\"\"\"\n",
- " self.value = brainstate.random.uniform(\n",
- " self.low, self.high, size=self.shape\n",
- " )"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### State Sharing\n",
- "\n",
- "Share state between modules (use with caution)."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "class ModuleA(brainstate.nn.Module):\n",
- " def __init__(self, shared_W):\n",
- " super().__init__()\n",
- " self.W = shared_W\n",
- "\n",
- "class ModuleB(brainstate.nn.Module):\n",
- " def __init__(self, shared_W):\n",
- " super().__init__()\n",
- " self.W = shared_W\n",
- "\n",
- "class SharedState(brainstate.nn.Module):\n",
- " def __init__(self):\n",
- " super().__init__()\n",
- " # Shared weight matrix\n",
- " shared_W = brainstate.ParamState(jnp.ones((100, 100)))\n",
- " self.module1 = ModuleA(shared_W)\n",
- " self.module2 = ModuleB(shared_W)\n",
- " # module1 and module2 both modify the same weights"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**When to use:** Siamese networks, weight tying, parameter sharing\n",
- "\n",
- "**Caution:** Makes dependencies implicit, harder to debug\n",
- "\n",
- "### State Inspection\n",
- "\n",
- "Debug by inspecting state values."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Print all parameter shapes\n",
- "params = net.states(brainstate.ParamState)\n",
- "for name, state in params.items():\n",
- " print(f\"{name}: {state.value.shape}\")\n",
- "\n",
- "# Check for NaN values\n",
- "for name, state in params.items():\n",
- " if jnp.any(jnp.isnan(state.value)):\n",
- " print(f\"NaN detected in {name}!\")\n",
- "\n",
- "# Compute statistics\n",
- "V_values = neuron.V.value\n",
- "print(f\"V range: [{V_values.min():.2f}, {V_values.max():.2f}]\")\n",
- "print(f\"V mean: {V_values.mean():.2f}\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Troubleshooting\n",
- "\n",
- "### Issue: States not updating\n",
- "\n",
- "**Symptoms:** Values stay constant\n",
- "\n",
- "**Solutions:**\n",
- "\n",
- "1. Assign to `.value`, not the state itself\n",
- "2. Check you're updating the right variable\n",
- "3. Verify update function is called"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example of correct vs wrong state assignment\n",
- "example_V = jnp.ones(100) * -60.0\n",
- "\n",
- "# WRONG - Creates new object, doesn't update state!\n",
- "self.V = example_V\n",
- "\n",
- "# CORRECT - Updates state value\n",
- "self.V.value = example_V"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Issue: Batch dimension errors\n",
- "\n",
- "**Symptoms:** Shape mismatch errors\n",
- "\n",
- "**Solutions:**\n",
- "\n",
- "1. Initialize with `batch_size` parameter\n",
- "2. Ensure inputs have batch dimension\n",
- "3. Check `reset_state()` handles batching"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Initialize with batching\n",
- "brainstate.nn.init_all_states(net, batch_size=32)\n",
- "\n",
- "# Input needs batch dimension\n",
- "inp = jnp.zeros((32, 100)) # (batch, neurons)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Issue: Gradients are None\n",
- "\n",
- "**Symptoms:** No gradients for parameters\n",
- "\n",
- "**Solutions:**\n",
- "\n",
- "1. Ensure parameters are `ParamState`\n",
- "2. Check parameters are used in loss computation\n",
- "3. Verify gradient function call"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example: Ensure parameters are ParamState\n",
- "init_W = jnp.ones((100, 50)) * 0.01\n",
- "\n",
- "# Parameters must be ParamState\n",
- "self.W = brainstate.ParamState(init_W) # Correct\n",
- "\n",
- "# Compute gradients for parameters only\n",
- "params = net.states(brainstate.ParamState)\n",
- "grads = brainstate.transform.grad(loss_fn, params)(...)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Issue: Memory leak during training\n",
- "\n",
- "**Symptoms:** Memory grows over time\n",
- "\n",
- "**Solutions:**\n",
- "\n",
- "1. Don't accumulate history in Python lists\n",
- "2. Clear unnecessary references\n",
- "3. Use `jnp.array` operations (not Python append)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example: Avoid memory leaks\n",
- "inp = jnp.ones(100) * 5.0 * u.nA\n",
- "\n",
- "# BAD - accumulates in Python memory\n",
- "history = []\n",
- "for t in range(10000):\n",
- " output = net(inp)\n",
- " history.append(output) # Memory leak!\n",
- "\n",
- "# GOOD - use fixed-size buffer or don't store\n",
- "for t in range(10000):\n",
- " output = net(inp)\n",
- "# # Process immediately, don't store"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Further Reading\n",
- "\n",
- "- architecture - Overall BrainPy architecture\n",
- "- neurons - Neuron models and their states\n",
- "- synapses - Synapse models and their states\n",
- "- ../tutorials/advanced/05-snn-training - Training with states\n",
- "- BrainState documentation: https://brainstate.readthedocs.io/\n",
- "\n",
- "## Summary\n",
- "\n",
- "**Key takeaways:**\n",
- "\n",
- "✅ **Three state types:**\n",
- " - `ParamState`: Learnable parameters\n",
- " - `ShortTermState`: Temporary dynamics\n",
- " - `LongTermState`: Persistent statistics\n",
- "\n",
- "✅ **Initialization:**\n",
- " - Use `brainstate.nn.init_all_states(module)`\n",
- " - Implement `reset_state()` for custom logic\n",
- " - Handle batch dimensions\n",
- "\n",
- "✅ **Access:**\n",
- " - Read/write with `.value`\n",
- " - Collect with `.states(StateType)`\n",
- " - Never assign to state object directly\n",
- "\n",
- "✅ **Training:**\n",
- " - Gradients computed for `ParamState`\n",
- " - Register with optimizer\n",
- " - Update with `optimizer.update(grads)`\n",
- "\n",
- "✅ **Checkpointing:**\n",
- " - Save `ParamState` and `LongTermState`\n",
- " - Don't save `ShortTermState`\n",
- " - Include metadata and optimizer state\n",
- "\n",
- "**Quick reference:**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Quick reference example (pseudocode)\n",
- "\n",
- "# Define example initializers\n",
- "init_W = jnp.ones((100, 50)) * 0.01\n",
- "init_V = jnp.zeros(100)\n",
- "init_c = jnp.zeros(100, dtype=jnp.int32)\n",
- "\n",
- "# Define states\n",
- "class MyModule(brainstate.nn.Module):\n",
- " def __init__(self, size=100):\n",
- " super().__init__()\n",
- " self.size = size\n",
- " self.W = brainstate.ParamState(init_W) # Learnable\n",
- " self.V = brainstate.ShortTermState(init_V) # Resets\n",
- " self.count = brainstate.LongTermState(init_c) # Persists\n",
- "\n",
- " def reset_state(self, batch_size=None):\n",
- " \"\"\"Initialize ShortTermState.\"\"\"\n",
- " shape = self.size if batch_size is None else (batch_size, self.size)\n",
- " self.V.value = jnp.zeros(shape)\n",
- "\n",
- "# Initialize\n",
- "module = MyModule()\n",
- "brainstate.nn.init_all_states(module, batch_size=32)\n",
- "\n",
- "# Access\n",
- "params = module.states(brainstate.ParamState)\n",
- "new_V = jnp.ones(100) * -60.0\n",
- "module.V.value = new_V\n",
- "\n",
- "# Train\n",
- "def loss(params, module, X, y):\n",
- " return jnp.mean((module.update(X) - y) ** 2)\n",
- "grads = brainstate.transform.grad(loss, params)(module, X, y)\n",
- "# optimizer.update(grads)"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Ecosystem-py",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.11.13"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/docs_state/quickstart/core-concepts/synapses.ipynb b/docs_state/quickstart/core-concepts/synapses.ipynb
index 4a77ef5e..134f32fd 100644
--- a/docs_state/quickstart/core-concepts/synapses.ipynb
+++ b/docs_state/quickstart/core-concepts/synapses.ipynb
@@ -21,14 +21,14 @@
]
},
{
- "cell_type": "code",
- "execution_count": null,
"metadata": {},
- "outputs": [],
+ "cell_type": "markdown",
"source": [
+ "```text\n",
"Spikes → [Connectivity] → [Synapse] → [Output] → Neurons\n",
" ↑\n",
- " Temporal filtering"
+ " Temporal filtering\n",
+ "```\n"
]
},
{
@@ -43,33 +43,53 @@
]
},
{
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:44:12.956284Z",
+ "start_time": "2025-11-13T09:44:07.906351Z"
+ }
+ },
"cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [],
"source": [
- "import brainpy\n",
- "import braintools\n",
"import brainstate\n",
+ "import braintools\n",
"import brainunit as u\n",
+ "import jax.numpy as jnp\n",
+ "import matplotlib.pyplot as plt\n",
"\n",
+ "import brainpy"
+ ],
+ "outputs": [],
+ "execution_count": 1
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:44:12.985015Z",
+ "start_time": "2025-11-13T09:44:12.956284Z"
+ }
+ },
+ "source": [
"# Create neurons for demonstration\n",
- "neurons = brainpy.state.LIF(50, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
+ "neurons = brainpy.state.LIF(50, V_rest=-65 * u.mV, V_th=-50 * u.mV, tau=10 * u.ms)\n",
"\n",
"# Create synapse descriptor\n",
- "syn = brainpy.state.Expon.desc(\n",
- " in_size=100, # Number of synapses\n",
- " tau=5. * u.ms # Time constant\n",
+ "syn = brainpy.state.Expon(\n",
+ " in_size=100, # Number of synapses\n",
+ " tau=5. * u.ms # Time constant\n",
")\n",
"\n",
"# Use in projection\n",
"projection = brainpy.state.AlignPostProj(\n",
" comm=brainstate.nn.EventFixedProb(100, 50, 0.1, 0.5),\n",
- " syn=syn, # Synapse here\n",
- " out=brainpy.state.CUBA.desc(),\n",
+ " syn=syn, # Synapse here\n",
+ " out=brainpy.state.CUBA(),\n",
" post=neurons\n",
")"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 2
},
{
"cell_type": "markdown",
@@ -77,7 +97,7 @@
"source": [
"### Synapse Lifecycle\n",
"\n",
- "1. **Creation**: Define synapse with `.desc()` method\n",
+ "1. **Creation**: Define synapse with `()` method\n",
"2. **Integration**: Include in projection\n",
"3. **Update**: Called automatically by projection\n",
"4. **Access**: Read synaptic variables as needed"
@@ -85,28 +105,32 @@
},
{
"cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:56:55.823289Z",
+ "start_time": "2025-11-13T09:56:55.338315Z"
+ }
+ },
"source": [
- "import jax.numpy as jnp\n",
- "\n",
"# Example presynaptic spikes\n",
"presynaptic_spikes = jnp.zeros(100) # 100 presynaptic neurons\n",
"\n",
"projection = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.AllToAll(100, 100, 0.1,0.5),\n",
- " syn=brainpy.state.Expon.desc(100, tau=5.0),\n",
- " out=brainpy.state.COBA.desc(E=0),\n",
+ " comm=brainstate.nn.AllToAll(100, 100, braintools.init.KaimingNormal(unit=u.mS)),\n",
+ " syn=brainpy.state.Expon(100, tau=5.0),\n",
+ " out=brainpy.state.COBA(E=0),\n",
" post=neurons,\n",
")\n",
+ "brainstate.nn.init_all_states(projection)\n",
+ "\n",
"# During simulation\n",
"projection(presynaptic_spikes) # Updates synapse internally\n",
"\n",
- "\n",
"# Access synaptic variable\n",
"synaptic_current = projection.syn"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 5
},
{
"cell_type": "markdown",
@@ -114,6 +138,8 @@
"source": [
"## Available Synapse Models\n",
"\n",
+ "For more synapse models, see the [API reference](../../api/index.rst).\n",
+ "\n",
"### Expon (Single Exponential)\n",
"\n",
"The simplest and most commonly used synapse model.\n",
@@ -138,16 +164,21 @@
},
{
"cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:57:06.489948Z",
+ "start_time": "2025-11-13T09:57:06.486122Z"
+ }
+ },
"source": [
- "syn = brainpy.state.Expon.desc(\n",
- " size=100,\n",
+ "syn = brainpy.state.Expon(\n",
+ " in_size=100,\n",
" tau=5. * u.ms,\n",
" g_initializer=braintools.init.Constant(0. * u.mS)\n",
")"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 7
},
{
"cell_type": "markdown",
@@ -198,7 +229,7 @@
"\n",
"$$\n",
"\\begin{aligned}\n",
- "\\tau \\frac{dh}{dt} &= -h\n",
+ "\\tau \\frac{dh}{dt} &= -h \\\\\n",
"\\tau \\frac{dg}{dt} &= -g + h\n",
"\\end{aligned}\n",
"$$\n",
@@ -206,7 +237,6 @@
"\n",
"**Impulse Response:**\n",
"\n",
- "\n",
"$$\n",
"g(t) = \\frac{t}{\\tau}\\exp(-t/\\tau)\n",
"$$\n",
@@ -215,16 +245,21 @@
},
{
"cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:57:12.935057Z",
+ "start_time": "2025-11-13T09:57:12.929863Z"
+ }
+ },
"source": [
- "syn = brainpy.state.Alpha.desc(\n",
- " size=100,\n",
+ "syn = brainpy.state.Alpha(\n",
+ " in_size=100,\n",
" tau=5. * u.ms,\n",
" g_initializer=braintools.init.Constant(0. * u.mS)\n",
")"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 8
},
{
"cell_type": "markdown",
@@ -232,7 +267,7 @@
"source": [
"**Parameters:**\n",
"\n",
- "Same as Expon, but produces alpha-shaped response.\n",
+ "Same as ``Expon``, but produces alpha-shaped response.\n",
"\n",
"**Key Features:**\n",
"\n",
@@ -264,86 +299,6 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### AMPA (Excitatory)\n",
- "\n",
- "Models AMPA receptor dynamics for excitatory synapses.\n",
- "\n",
- "**Mathematical Model:**\n",
- "\n",
- "Similar to Alpha, but with parameters tuned for AMPA receptors.\n",
- "\n",
- "**Example:**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [],
- "source": [
- "syn = brainpy.state.AMPA.desc(\n",
- " size=100,\n",
- " tau=2. * u.ms, # Fast AMPA kinetics\n",
- " g_initializer=braintools.init.Constant(0. * u.mS)\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Key Features:**\n",
- "\n",
- "- Fast kinetics (τ ≈ 2 ms)\n",
- "- Excitatory receptor\n",
- "- Biologically parameterized\n",
- "\n",
- "**Use cases:**\n",
- "\n",
- "- Excitatory synapses\n",
- "- Cortical pyramidal neurons\n",
- "- Biological realism\n",
- "\n",
- "### GABAa (Inhibitory)\n",
- "\n",
- "Models GABAa receptor dynamics for inhibitory synapses.\n",
- "\n",
- "**Mathematical Model:**\n",
- "\n",
- "Similar to Alpha, but with parameters tuned for GABAa receptors.\n",
- "\n",
- "**Example:**"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [],
- "source": [
- "syn = brainpy.state.GABAa.desc(\n",
- " size=100,\n",
- " tau=10. * u.ms, # Slower GABAa kinetics\n",
- " g_initializer=braintools.init.Constant(0. * u.mS)\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Key Features:**\n",
- "\n",
- "- Slower kinetics (τ ≈ 10 ms)\n",
- "- Inhibitory receptor\n",
- "- Biologically parameterized\n",
- "\n",
- "**Use cases:**\n",
- "\n",
- "- Inhibitory synapses\n",
- "- GABAergic interneurons\n",
- "- Biological realism\n",
- "\n",
"## Synaptic Variables\n",
"\n",
"### The Descriptor Pattern\n",
@@ -353,58 +308,54 @@
},
{
"cell_type": "code",
- "execution_count": 18,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:58:19.442492Z",
+ "start_time": "2025-11-13T09:58:19.435903Z"
+ }
+ },
"source": [
- "# Example: Descriptor pattern\n",
- "\n",
- "# Create descriptor (not yet instantiated)\n",
- "syn_desc = brainpy.state.Expon.desc(in_size=100, tau=5*u.ms)\n",
- "\n",
"# Define neurons for example\n",
- "example_neurons = brainpy.state.LIF(100, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
+ "example_neurons = brainpy.state.LIF(100, V_rest=-65 * u.mV, V_th=-50 * u.mV, tau=10 * u.ms)\n",
"\n",
"# Instantiated within projection\n",
"example_projection = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(100, 100, 0.1, 0.5),\n",
- " syn=syn_desc,\n",
- " out=brainpy.state.CUBA.desc(),\n",
+ " comm=brainstate.nn.EventFixedProb(100, 100, 0.1, 0.5 * u.mS),\n",
+ " syn=brainpy.state.Expon(in_size=100, tau=5 * u.ms),\n",
+ " out=brainpy.state.CUBA(),\n",
" post=example_neurons\n",
")\n",
+ "brainstate.nn.init_all_states(example_projection)\n",
"\n",
"# Access instantiated synapse\n",
"actual_synapse = example_projection.syn\n",
"g_value = actual_synapse"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 9
},
{
"cell_type": "markdown",
"metadata": {},
- "source": [
- "### Why Descriptors?\n",
- "\n",
- "- **Deferred instantiation**: Created when needed\n",
- "- **Reusability**: Same descriptor for multiple projections\n",
- "- **Flexibility**: Configure before instantiation\n",
- "\n",
- "### Accessing Synaptic State"
- ]
+ "source": "### Accessing Synaptic State"
},
{
"cell_type": "code",
- "execution_count": 19,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T09:58:32.435703Z",
+ "start_time": "2025-11-13T09:58:32.429353Z"
+ }
+ },
"source": [
"# Define neurons for this example\n",
- "demo_neurons = brainpy.state.LIF(100, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
+ "demo_neurons = brainpy.state.LIF(100, V_rest=-65 * u.mV, V_th=-50 * u.mV, tau=10 * u.ms)\n",
"\n",
"# Within projection\n",
"demo_projection = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(100, 100, conn_num=10, conn_weight=0.5),\n",
- " syn=brainpy.state.Expon.desc(in_size=100, tau=5*u.ms),\n",
- " out=brainpy.state.CUBA.desc(),\n",
+ " comm=brainstate.nn.EventFixedProb(100, 100, conn_num=10, conn_weight=0.5 * u.mS),\n",
+ " syn=brainpy.state.Expon(in_size=100, tau=5 * u.ms),\n",
+ " out=brainpy.state.CUBA(),\n",
" post=demo_neurons\n",
")\n",
"\n",
@@ -416,48 +367,43 @@
"\n",
"# Convert to array for plotting\n",
"g_array = u.get_magnitude(synaptic_var)"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 10
},
{
"cell_type": "markdown",
"metadata": {},
- "source": [
- "## Synaptic Dynamics Visualization\n",
- "\n",
- "### Comparing Different Models"
- ]
+ "source": "## Synaptic Dynamics Visualization\n"
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-11-13T10:06:26.322483Z",
+ "start_time": "2025-11-13T10:06:25.930516Z"
+ }
+ },
"source": [
- "import brainpy as bp\n",
- "import brainstate\n",
- "import brainunit as u\n",
- "import matplotlib.pyplot as plt\n",
- "import jax.numpy as jnp\n",
- "\n",
"# Set simulation timestep\n",
"brainstate.environ.set(dt=0.1 * u.ms)\n",
"\n",
"# Create different synapses (without unit initializers to avoid mismatch)\n",
- "expon = brainpy.state.Expon(100, tau=5*u.ms)\n",
- "alpha = brainpy.state.Alpha(100, tau=5*u.ms)\n",
- "ampa = brainpy.state.AMPA(100, T=2*u.ms)\n",
- "gaba = brainpy.state.GABAa(100, T=10*u.ms)\n",
+ "expon = brainpy.state.Expon(1, tau=5 * u.ms)\n",
+ "alpha = brainpy.state.Alpha(1, tau=5 * u.ms)\n",
+ "ampa = brainpy.state.AMPA(1, T=2 * u.mM)\n",
+ "gaba = brainpy.state.GABAa(1, T=1. * u.mM)\n",
"\n",
"# Initialize\n",
"for syn in [expon, alpha, ampa, gaba]:\n",
" brainstate.nn.init_all_states(syn)\n",
"\n",
"# Single spike at t=0 (dimensionless spike count)\n",
- "spike_input = jnp.zeros(100)\n",
- "spike_input = spike_input.at[0].set(1.0)\n",
+ "spike_input = jnp.zeros(100) * u.mS\n",
+ "spike_input = spike_input.at[0].set(1.0 * u.mS)\n",
"\n",
"# Simulate\n",
- "times = u.math.arange(0*u.ms, 50*u.ms, 0.1*u.ms)\n",
+ "times = u.math.arange(0 * u.ms, 50 * u.ms, 0.1 * u.ms)\n",
"responses = {\n",
" 'Expon': [],\n",
" 'Alpha': [],\n",
@@ -465,30 +411,40 @@
" 'GABAa': []\n",
"}\n",
"\n",
- "for syn, name in zip([expon, alpha, ampa, gaba],\n",
- " ['Expon', 'Alpha', 'AMPA', 'GABAa']):\n",
- " # Re-initialize for clean start\n",
+ "for syn, name in zip([expon, alpha], ['Expon', 'Alpha']):\n",
" brainstate.nn.init_all_states(syn)\n",
- " for i, t in enumerate(times):\n",
+ "\n",
+ "\n",
+ " def step_run(i, t):\n",
" with brainstate.environ.context(t=t, i=i):\n",
- " if i == 0:\n",
- " syn(spike_input)\n",
- " else:\n",
- " syn(jnp.zeros(100))\n",
- " # Get the value (may have units or not)\n",
- " g_val = syn.g.value[0]\n",
- " if hasattr(g_val, 'magnitude'):\n",
- " responses[name].append(float(u.get_magnitude(g_val)))\n",
- " else:\n",
- " responses[name].append(float(g_val))\n",
+ " inp = u.math.where(i == 0, 1.0 * u.mS, 0.0 * u.mS)\n",
+ " g_val = syn(inp)\n",
+ " return g_val\n",
+ "\n",
+ "\n",
+ " responses[name] = brainstate.transform.for_loop(\n",
+ " step_run, u.math.arange(times.size), times,\n",
+ " )\n",
+ "\n",
+ "for syn, name in zip([ampa, gaba], ['AMPA', 'GABAa']):\n",
+ " brainstate.nn.init_all_states(syn)\n",
+ "\n",
+ "\n",
+ " def step_run(i, t):\n",
+ " with brainstate.environ.context(t=t, i=i):\n",
+ " inp = u.math.where(i == 0, 1.0, 0.0)\n",
+ " g_val = syn(inp)\n",
+ " return g_val\n",
+ "\n",
+ "\n",
+ " responses[name] = brainstate.transform.for_loop(\n",
+ " step_run, u.math.arange(times.size), times,\n",
+ " )\n",
"\n",
"# Plot\n",
"plt.figure(figsize=(10, 6))\n",
"for name, response in responses.items():\n",
- " response_array = jnp.array(response)\n",
- " plt.plot(u.get_magnitude(times),\n",
- " response_array,\n",
- " label=name, linewidth=2)\n",
+ " plt.plot(times, response, label=name, linewidth=2)\n",
"\n",
"plt.xlabel('Time (ms)')\n",
"plt.ylabel('Synaptic Variable (normalized)')\n",
@@ -496,422 +452,23 @@
"plt.legend()\n",
"plt.grid(True, alpha=0.3)\n",
"plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Integration with Projections\n",
- "\n",
- "### Complete Example"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import brainpy \n",
- "import brainstate\n",
- "import brainunit as u\n",
- "\n",
- "# Set simulation timestep\n",
- "brainstate.environ.set(dt=0.1 * u.ms)\n",
- "\n",
- "# Create neurons\n",
- "pre_neurons = brainpy.state.LIF(80, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "post_neurons = brainpy.state.LIF(100, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "\n",
- "# Create projection with exponential synapse\n",
- "projection = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(\n",
- " 80, 100, 0.1, 0.5\n",
- " ),\n",
- " syn=brainpy.state.Expon.desc(100, tau=5*u.ms),\n",
- " out=brainpy.state.CUBA.desc(),\n",
- " post=post_neurons\n",
- ")\n",
- "\n",
- "# Initialize all states\n",
- "brainstate.nn.init_all_states([pre_neurons, post_neurons, projection])\n",
- "\n",
- "# Simulation function\n",
- "def update(t, i, input_current):\n",
- " with brainstate.environ.context(t=t, i=i):\n",
- " # Update presynaptic neurons\n",
- " pre_neurons(input_current)\n",
- "\n",
- " # Get spikes and propagate through projection\n",
- " spikes = pre_neurons.get_spike()\n",
- " projection(spikes)\n",
- "\n",
- " # Update postsynaptic neurons\n",
- " post_neurons(0 * u.nA)\n",
- "\n",
- " return post_neurons.get_spike()\n",
- "\n",
- "# Run simulation\n",
- "times = u.math.arange(0*u.ms, 100*u.ms, 0.1*u.ms)\n",
- "indices = u.math.arange(times.size)\n",
- "\n",
- "# Create input current for all timesteps\n",
- "input_currents = jnp.ones(80) * 2*u.nA\n",
- "\n",
- "results = brainstate.transform.for_loop(\n",
- " lambda t, i: update(t, i, input_currents),\n",
- " times,\n",
- " indices\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Short-Term Plasticity\n",
- "\n",
- "Synapses can be combined with short-term plasticity (STP):"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Short-term plasticity (STP) can be combined with synapses\n",
- "Note: STP is typically implemented as part of custom synapse models\n",
- "or as a separate plasticity mechanism in the projection\n",
- "\n",
- "Example conceptual usage (not directly supported in current API):\n",
- "The idea is to modulate synaptic efficacy based on recent activity\n",
- "- Facilitation: increases with repeated activation\n",
- "- Depression: decreases with repeated activation\n",
- "\n",
- "For implementing STP, you would typically:\n",
- "1. Create a custom synapse class that includes STP dynamics\n",
- "2. Or use a separate plasticity module that modulates connection weights\n",
- "\n",
- "See the plasticity documentation for more details on implementing\n",
- "short-term plasticity mechanisms"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "See plasticity for more details on STP.\n",
- "\n",
- "## Custom Synapses\n",
- "\n",
- "### Creating Custom Synapse Models\n",
- "\n",
- "You can create custom synapse models by inheriting from `Synapse`:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import brainstate\n",
- "import braintools\n",
- "from brainpy.state import AlignPost\n",
- "\n",
- "class MyCustomSynapse(AlignPost):\n",
- " \"\"\"Custom synapse with double exponential dynamics.\"\"\"\n",
- " \n",
- " def __init__(self, size, tau1, tau2, g_initializer=None, **kwargs):\n",
- " super().__init__(size, **kwargs)\n",
- "\n",
- " self.tau1 = tau1\n",
- " self.tau2 = tau2\n",
- "\n",
- " # Synaptic variable - initialize without units for compatibility\n",
- " if g_initializer is None:\n",
- " g_initializer = braintools.init.Constant(0.)\n",
- " self.g = brainstate.ShortTermState(g_initializer(size))\n",
- "\n",
- " def update(self, x):\n",
- " # Get time step\n",
- " dt = brainstate.environ.get_dt()\n",
- "\n",
- " # Custom dynamics: simple decay\n",
- " # dg/dt = -g/tau1\n",
- " decay = -self.g.value / self.tau1\n",
- " self.g.value = self.g.value + decay * dt\n",
- " \n",
- " # Add spike input if provided\n",
- " if x is not None:\n",
- " self.g.value = self.g.value + x / self.tau2\n",
- "\n",
- " return self.g.value"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Usage:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Define neurons for custom synapse example\n",
- "custom_neurons = brainpy.state.LIF(100, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "\n",
- "# Create custom synapse descriptor using .desc() method\n",
- "syn_desc = MyCustomSynapse.desc(\n",
- " size=100,\n",
- " tau1=5*u.ms,\n",
- " tau2=10*u.ms\n",
- ")\n",
- "\n",
- "# Use in projection\n",
- "custom_projection = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(100, 100, 0.1, 0.5),\n",
- " syn=syn_desc,\n",
- " out=brainpy.state.CUBA.desc(),\n",
- " post=custom_neurons\n",
- ")\n",
- "\n",
- "print(\"Custom synapse projection created successfully!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Choosing the Right Synapse\n",
- "\n",
- "### Decision Guide\n",
- "\n",
- "\n",
- " * - Model\n",
- " - When to Use\n",
- " - Pros\n",
- " - Cons\n",
- " * - Expon\n",
- " - General purpose, speed\n",
- " - Fast, simple\n",
- " - Unrealistic rise\n",
- " * - Alpha\n",
- " - Biological realism\n",
- " - Realistic kinetics\n",
- " - Slower computation\n",
- " * - AMPA\n",
- " - Excitatory, fast\n",
- " - Biologically accurate\n",
- " - Specific use case\n",
- " * - GABAa\n",
- " - Inhibitory, slow\n",
- " - Biologically accurate\n",
- " - Specific use case\n",
- "\n",
- "### Recommendations\n",
- "\n",
- "**For machine learning / SNNs:**\n",
- " Use `Expon` for speed and simplicity.\n",
- "\n",
- "**For biological modeling:**\n",
- " Use `Alpha`, `AMPA`, or `GABAa` for realism.\n",
- "\n",
- "**For cortical networks:**\n",
- " - Excitatory: `AMPA` (τ ≈ 2 ms)\n",
- " - Inhibitory: `GABAa` (τ ≈ 10 ms)\n",
- "\n",
- "**For custom dynamics:**\n",
- " Implement custom synapse class.\n",
- "\n",
- "## Performance Considerations\n",
- "\n",
- "### Computational Cost\n",
- "\n",
- "\n",
- " * - Model\n",
- " - Relative Cost\n",
- " - Notes\n",
- " * - Expon\n",
- " - 1x (baseline)\n",
- " - Single state variable\n",
- " * - Alpha\n",
- " - 2x\n",
- " - Two state variables\n",
- " * - AMPA/GABAa\n",
- " - 2x\n",
- " - Similar to Alpha\n",
- "\n",
- "### Optimization Tips\n",
- "\n",
- "1. **Use Expon when possible**: Fastest option\n",
- "\n",
- "2. **Batch operations**: Multiple synapses together"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Define neurons for batch optimization example\n",
- "batch_neurons = brainpy.state.LIF(1000, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "\n",
- "# Good: Single projection with 1000 synapses\n",
- "good_proj = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(1000, 1000, 0.1, 0.5),\n",
- " syn=brainpy.state.Expon.desc(1000, tau=5*u.ms),\n",
- " out=brainpy.state.CUBA.desc(),\n",
- " post=batch_neurons\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "3. **JIT compilation**: Always use for simulations"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 84,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Define neurons and projection for JIT example\n",
- "jit_neurons = brainpy.state.LIF(100, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "jit_projection = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(100, 100, 0.1, 0.5),\n",
- " syn=brainpy.state.Expon.desc(100, tau=5*u.ms),\n",
- " out=brainpy.state.CUBA.desc(),\n",
- " post=jit_neurons\n",
- ")\n",
- "\n",
- "# Initialize\n",
- "brainstate.nn.init_all_states([jit_neurons, jit_projection])\n",
- "\n",
- "# Example spikes\n",
- "spikes = jnp.zeros(100)\n",
- "\n",
- "@brainstate.transform.jit\n",
- "def step():\n",
- " jit_projection(spikes)\n",
- " jit_neurons(0*u.nA)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Common Patterns\n",
- "\n",
- "### Excitatory-Inhibitory Balance"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 85,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Define neurons and sizes for E-I balance example\n",
- "post_size = 100\n",
- "ei_neurons = brainpy.state.LIF(post_size, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "\n",
- "# Excitatory projection (fast)\n",
- "E_proj = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(80, post_size, 0.1, 0.5),\n",
- " syn=brainpy.state.Expon.desc(post_size, tau=2*u.ms),\n",
- " out=brainpy.state.CUBA.desc(),\n",
- " post=ei_neurons\n",
- ")\n",
- "\n",
- "# Inhibitory projection (slow)\n",
- "I_proj = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(20, post_size, 0.1, 0.5),\n",
- " syn=brainpy.state.Expon.desc(post_size, tau=10*u.ms),\n",
- " out=brainpy.state.CUBA.desc(),\n",
- " post=ei_neurons\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Multiple Receptor Types"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Define neurons and size for multiple receptor example\n",
- "receptor_size = 100\n",
- "receptor_neurons = brainpy.state.LIF(receptor_size, V_rest=-65*u.mV, V_th=-50*u.mV, tau=10*u.ms)\n",
- "\n",
- "# Fast excitatory (AMPA-like) - using Expon with fast time constant\n",
- "ampa_proj = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(80, receptor_size, 0.1, 0.3),\n",
- " syn=brainpy.state.Expon.desc(receptor_size, tau=2*u.ms), # Fast AMPA kinetics\n",
- " out=brainpy.state.COBA.desc(E=0*u.mV),\n",
- " post=receptor_neurons\n",
- ")\n",
- "\n",
- "# Slow excitatory (NMDA-like) - using Expon with slow time constant\n",
- "nmda_proj = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(80, receptor_size, 0.1, 0.3),\n",
- " syn=brainpy.state.Expon.desc(receptor_size, tau=100*u.ms), # Slow NMDA kinetics\n",
- " out=brainpy.state.COBA.desc(E=0*u.mV),\n",
- " post=receptor_neurons\n",
- ")\n",
- "\n",
- "# Fast inhibitory (GABAa-like) - using Expon with medium time constant\n",
- "gaba_proj = brainpy.state.AlignPostProj(\n",
- " comm=brainstate.nn.EventFixedProb(20, receptor_size, 0.1, 0.5),\n",
- " syn=brainpy.state.Expon.desc(receptor_size, tau=10*u.ms), # GABAa kinetics\n",
- " out=brainpy.state.COBA.desc(E=-80*u.mV),\n",
- " post=receptor_neurons\n",
- ")\n",
- "\n",
- "print(\"Multiple receptor type projections created successfully!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Summary\n",
- "\n",
- "Synapses in `brainpy.state`:\n",
- "\n",
- "✅ **Multiple models**: Expon, Alpha, AMPA, GABAa\n",
- "\n",
- "✅ **Temporal filtering**: Convert spikes to continuous signals\n",
- "\n",
- "✅ **Descriptor pattern**: Flexible, reusable configuration\n",
- "\n",
- "✅ **Integration ready**: Seamless use in projections\n",
- "\n",
- "✅ **Extensible**: Easy custom synapse models\n",
- "\n",
- "✅ **Physical units**: Proper unit handling throughout\n",
- "\n",
- "## Next Steps\n",
- "\n",
- "- Learn about [projections](projections) for complete connectivity\n",
- "- Explore [plasticity](state-management) for learning rules\n",
- "- Follow [tutorials](../tutorials/index) for practice\n",
- "- See [examples](../examples/gallery) for network examples"
- ]
+ ],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "image/png": "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zLQef//99w3AmDFjhvXY2LFjDcDms8nL9OnTDcDw8vIybr75ZuPFF180/vrrL5s2DMMwdu/ebQDGhx9+aHO8d+/eRnR0tGE2mw3DMIw//vjDAIyaNWsaqamp1vPeeecdAzC2bt1qPXbl98swDGPixImGyWSy6Rf57QPDhw83goKCjIyMjDzf7yuvvGL4+/sbe/bssTn+7LPPGu7u7sbhw4fzvNYwDKN9+/ZG7dq1DcMwjCZNmhgPPPCAYRiGce7cOcPLy8uYNWuW9TP4+uuvrdf16dPH8PLyMvbv3289dvz4cSMwMNBo166d9diIESMMwFizZo312OnTp41SpUoZgBEbG2sYhmEkJSUZwcHBxtChQ23iO3nypFGqVCmb41n9IcuUKVPy3T+yS09PN0wmk/HUU0/leC2//cgwcv6MZcV3//3325x3++23G2XLlrU+X79+vQEYI0aMsDlv8ODBOe756aefFvjzys22bdsMX19fAzAaNGhgDB8+3Pjhhx+Mixcv5jg369+8b7/91nosISHBiIiIMBo2bGg9ltVPsv97l71/ffvtt4anp6cxdOhQm8+xY8eORt26dY2UlBTrMbPZbLRq1cqoVq1ajngmTJhgAMapU6eu+h5F5Oo04iQiACQmJgLke/HwL7/8ApDjL/RPPfUUQI4Rnlq1atGyZUvr8+bNmwNwyy23ULFixRzHDxw4kKPNxx9/3Po4a6pdWloaixcvth739fW1Pj537hwJCQm0bds2x7Q6gPbt21OrVq1rvFPLOqE1a9Zw/PjxXF9ft24dp0+f5rHHHrNZr9CjRw9q1KiR62jXI488YvO8bdu2ub7n7BYvXkxaWhojRozAze3yP99Dhw4lKCiowOvP7r//fhYuXEiHDh1YsWIFr7zyCm3btqVatWo2f6W+6aabaN68uU0J6vj4eH799VfuvffeHOWuhwwZYjNtq23btoDt9zb79+vixYucOXOGVq1aYRhGjimbcO0+EBwczMWLF6/6V/2vv/6atm3bUrp0ac6cOWP96tSpE5mZmSxfvvyan1mW/v37891335GWlsY333yDu7u7dbQvu8zMTH777Tf69OlDlSpVrMcjIiLo378/K1assP4M/vLLL7Ro0cJm7VRoaGiO0brff/+d8+fP069fP5v34e7uTvPmzfnjjz/yjDtr7dv8+fPtmp4YHx+PYRiULl06x2v57UdXk9vPxdmzZ62fTdZ02scee8zmvCeeeOKa976ezwugdu3abNq0iQEDBnDw4EHeeecd+vTpQ3h4OJ988kmO8yMjI236QlBQEAMHDmTjxo2cPHnymvHOnTuXu+++m4cffpiPPvrI+jMfHx/P0qVLraNzWe/j7NmzdOnShb179+aYIpz1/Tpz5sw12xWRvClxEhHA8j91sKznyY9Dhw7h5uaWo2JbuXLlCA4O5tChQzbHsydHAKVKlQIgKioq1+Pnzp2zOe7m5mbzCydYfpEHbKbYLFiwgBYtWuDj40OZMmUIDQ3lww8/JCEhIcd7qFy58rXeJmBZ+7Vt2zaioqJo1qwZL7/8ss0v/1nvtXr16jmurVGjRo7PwsfHh9DQUJtjpUuXzvGer5RXO15eXlSpUiVHO/bo0qULixYt4vz58yxfvpxhw4Zx6NAhevbsabPwfeDAgaxcudLa1tdff016ejr33Xdfjnte+T3P+uUt+/s8fPgwgwcPpkyZMtb1Xu3btwfI8T3LTx947LHHuOmmm+jWrRsVKlSw/jKf3d69e1m4cCGhoaE2X506dQLsW+h/zz33kJCQwK+//sqcOXPo2bNnrn98iIuL49KlS7n2kZo1a2I2mzly5Ahg+T7nVur8ymv37t0LWP74cOV7+e233676Pu6++25at27Ngw8+SHh4OPfccw9fffVVvpMo44p1ZVny24/ycq0+k/XvzpU/u9eqHAnX93lluemmm5g9ezZnzpxhy5Yt1unADz30kM0fcLJiuvKPCbn9m5Wb2NhYBgwYQN++fXnvvfds7rNv3z4Mw+DFF1/M8T6ypq1e+V6yvl+O3MtLpCRSVT0RASyJU2RkJNu2bbPruvz+jzh72eL8HM/rF7Or+euvv+jduzft2rVj6tSpRERE4OnpyaeffprrPjLZRzuu5q677qJt27Z8//33/Pbbb7zxxhtMmjSJ7777jm7dutkdZ17vuSjw8/Ojbdu2tG3blpCQEMaNG8evv/7KoEGDAEuiMHLkSObMmcNzzz3H559/TpMmTXJNCK71vc3MzOTWW28lPj6eZ555hho1auDv78+xY8cYPHiwXSMhWcLCwti0aROLFi3i119/5ddff+XTTz9l4MCBzJo1C7BUULz11lt5+umnc71H1i+3+REREUGHDh146623WLlyZaFW0sv6fGbPnk25cuVyvH61ct++vr4sX76cP/74g59//pmFCxcyb948brnlFn777bc8v3dlypTBZDJdM8m/Vj/KiyP/PbjS9XxeV3J3d6du3brUrVuXli1bcvPNNzNnzhxr8n29IiIiiIiI4JdffmHdunU0adLE+lrW+xg9ejRdunTJ9forE8ms71dISIhD4hMpqZQ4iYhVz549+fjjj1m9erXNtLrcVKpUCbPZzN69e6lZs6b1+KlTpzh//nyulaeuh9ls5sCBAza/1O7ZswfAWtTh22+/xcfHh0WLFuHt7W0979NPP73u9iMiInjsscd47LHHOH36NI0aNeK1116jW7du1ve6e/dubrnlFpvrdu/e7bDPIns72Ude0tLSiI2NddgvbVmyflk7ceKE9ViZMmXo0aMHc+bM4d5772XlypW8/fbbBbr/1q1b2bNnD7NmzbIpBpHXNLv89AGwjMD16tWLXr16YTabeeyxx/joo4948cUXqVq1KjExMVy4cMFhn1f//v158MEHCQ4Opnv37rmeExoaip+fH7t3787x2q5du3Bzc7OOvlaqVMk6OpLdlddmVbULCwsr0Htxc3OjY8eOdOzYkcmTJzNhwgSef/55/vjjjzzv5+HhQUxMDLGxsfluJ7d+VFBZ/+7ExsbajMpdWa0xN9f7eeUlr/eXNTKU/Y9LufXX3Pj4+LBgwQJuueUWunbtyp9//knt2rUBrD/7np6e+X4fsbGxhISE5BjpFhH7aKqeiFg9/fTT+Pv78+CDD3Lq1Kkcr+/fv99a2SvrF8Qrf2mePHkyQL6rXNnj/ffftz42DIP3338fT09POnbsCFj+CmwymWzKeh88eJAffvihwG1mZmbmmDIWFhZGZGSktex6kyZNCAsLY9q0aTal2H/99Vd27tzpsM+iU6dOeHl58e6779r8BX769OkkJCQUuJ0lS5bkejxrHduVo0n33XcfO3bs4P/+7/9wd3fPtYpifmSNLmR/L4Zh5Fo9Lsu1+sDZs2dtzndzc6NevXoA1u/NXXfdxerVq1m0aFGO+58/f95a7jm//vOf/zB27FimTp2a50am7u7udO7cmfnz59tM0zp16hRffPEFbdq0sU6X7d69O3///Tdr1661nhcXF2eztgws0+KCgoKYMGGCtaJidnFxcXnGfGVlRIAGDRoA5NhO4EotW7Zk3bp1OY7b248KImuEZerU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jZPZbOb48eMEBgZedaM8ERERERG5sRmGQVJSEpGRkbi5XX1MqcQlTsePH1fVHRERERERsTpy5AgVKlS46jklLnEKDAwELB9OUFCQi6OxjIDFxcURGhp6zSxXBNRnxH7qM2Iv9Rmxl/qM2Kuo9JnExESioqKsOcLVlLjEKWt6XlBQUJFJnFJSUggKCtI/NJIv6jNiL/UZsZf6jNhLfUbsVdT6TH6W8Lg+ShERERERkSJOiZOIiIiIiMg1KHESERERERG5hhK3xklEREREpDAZhkFGRgaZmZmuDqXIMJvNpKenk5KS4vQ1Tp6enri7u1/3fZQ4iYiIiIg4SVpaGidOnODSpUuuDqVIMQwDs9lMUlKS0/dWNZlMVKhQgYCAgOu6jxInEREREREnMJvNxMbG4u7uTmRkJF5eXk5PEoqLrFE4Dw8Pp34mhmEQFxfH0aNHqVat2nWNPClxEhERERFxgrS0NMxmM1FRUfj5+bk6nCKlsBIngNDQUA4ePEh6evp1JU4qDiEiIiIi4kRFYZ+iksxRiZm+iyIiIiIiItegxElEREREROQalDiJiIiIiIhcgxInERERERGxMXjwYEwmU46vrl27ujo0l1FVPRERERERyaFr1658+umnNse8vb1dFI3racRJRERERERy8Pb2ply5cjZfpUuXZtmyZXh5efHXX39Zz/3vf/9LWFgYp06dAqBDhw48/vjjPP7445QqVYqQkBBefPFFDMOwXnPu3DkGDRpE6dKl8fPzo1u3buzdu9f6+syZMwkODmbRokXUrFmTgIAAunbtyokTJwrvQ8jGpSNOy5cv54033mD9+vWcOHGC77//nj59+lz1mmXLljFq1Ci2b99OVFQUL7zwAoMHDy6UeEVERERErlev91YQl5Ra6O2GBnrz0xNtrvs+HTp0YMSIEdx3331s3ryZAwcO8OKLL/L1118THh5uPW/WrFk88MADrF27lnXr1vHQQw9RsWJFhg4dCsADDzzA/v37+fHHHwkKCuKZZ56he/fu7NixA09PTwAuXbrEm2++yezZs3Fzc2PAgAGMHj2aOXPmXPf7sJdLE6eLFy9Sv3597r//fu64445rnh8bG0uPHj145JFHmDNnDkuWLOHBBx8kIiKCLl26FELEIiIiIiLXJy4plZOJKa4O45oWLFhAQECAzbHnnnuO5557jldffZXff/+d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O08mkZ5pxtNdg4UiIiIixVHGmTNknDrl6jCuat++fRiGQfXq1W2Oh4SEWKfODRs2jEmTJpGYmMg333zD6tWrARgwYABt27blnXfeISAgwHptQkKC9XlycjKenp589NFHxMTEWM8xm83MnDmT9957D4B77rmHp556itjYWCpXrgxA+fLlGT16tPWaJ554gkWLFvHVV18pcRKoE1mKA3EXScsws+/0BWpGBF37IhEREREpcjxCQoptu2vXrsVsNnPvvfeSmpoKWAo5xMTEUL9+fQAaNGhApUqVmDdvHg888ID12sDAQDZs2ADAxYsX+e2333j00UcJCQmxTvv7/fffuXjxIt27dwcsidqtt97KjBkzeOWVVwDLaNWECRP46quvOHbsGGlpaaSmpuLn53fd7+9qlDgVE7Ujg/hx83HAshGuEicRERGR4im/0+VcqWrVqphMphyFG6pUqQKAr6+v9dj06dPZvn07Hh6XUwuz2cyMGTNsEic3NzeqVq0KgGEY1KpViyVLljBp0iRr4jR9+nTi4+Nt7m82m9myZQvjxo3Dzc2NN954g3feeYe3336bunXr4u/vz4gRI0hLS3P8B5GNEqdiInuBiO3HE7nThbGIiIiIyI2tbNmy3Hrrrbz//vs88cQTea5z2rp1K+vWrWPZsmWUKVPGejw+Pp4OHTqwa9cuatSokWc77u7uJCcnA5Z1VfPnz+fLL7+kdu3a1nMyMzNp06YNv/32G127dmXlypXcdtttDBgwALAkVnv27KFWrVqOeOt5UuJUTNSOzF6SXAUiRERERMS5pk6dSuvWrWnSpAkvv/wy9erVw83NjX/++Yddu3bRuHFjpk+fTrNmzWjXrl2O65s2bcr06dOt+zoZhsHJkycBuHTpEosWLWLRokW89NJLAMyePZuyZcty11132RSeAOjevTvTp0+na9euVKtWjW+++YZVq1ZRunRpJk+ezKlTp5Q4iUWwnxcVSvty9FwyO04kkmk2cHczXftCEREREZECiImJYePGjUyYMIExY8Zw9OhRvL29qVWrFqNHj+ahhx6iSpUqPPPMM7le37dvX9566y0mTJgAQGJiIhEREQB4e3tTsWJFxo0bx7PPPgtY9oG6/fbbcyRNWfe67777OHPmDC+88AIHDhygS5cu+Pn58dBDD9GnTx8SEpw7uGAyDMNwagtFTGJiIqVKlSIhIYGgINevEzKbzZw+fZqwsDDc3K5eKe+R2etZuN2SpS8e1Z6qYQFXPV9uTPb0GRFQnxH7qc+IvdRncpeSkmKtBufj4+PqcIoUwzDIyMjAw8Mj10TJka72fbAnN1DPLkbqlL/8zdyujXBFRERERAqNEqdipHa2AhFbjypxEhEREREpLEqcipG62RKnLSoQISIiIiJSaJQ4FSMhAd6UD7bUtN92LIFMc4laniYiIiIi4jJKnIqZehUso06X0jLZH3fBxdGIiIiIyLWUsFpsRY6jPn8lTsVMvQrB1sebj5x3WRwiIiIicnWenp6AZc8icZ20tDTAstnu9dA+TsVM/QrZ1jkdTeDOJlEujEZERERE8uLu7k5wcDCnT58GwM/Pz+mlt4uLwipHbjabiYuLw8/PDw+P60t9lDgVM3VsEqfzrgtERERERK6pXLlyANbkSSwMw8BsNuPm5ub0ZNLNzY2KFStedztKnIqZIB9PqoT6cyDuIjtPJJGWYcbLQzMuRURERIoik8lEREQEYWFhpKenuzqcIsNsNnP27FnKli3r9E2Tvby8HNKGEqdiqH6FYA7EXSQt08yuk4k2655EREREpOhxd3e/7jU2NxKz2Yynpyc+Pj5OT5wcpXhEKTbqZZuut1kb4YqIiIiIOJ0Sp2Io+wjTFlXWExERERFxOiVOxVDtyCA83CyL27ZoxElERERExOlcnjh98MEHREdH4+PjQ/PmzVm7du1Vz3/77bepXr06vr6+REVFMXLkSFJSUgop2qLBx9Od6uUCAdh7OomLqRkujkhERERE5Mbm0sRp3rx5jBo1irFjx7Jhwwbq169Ply5d8izX+MUXX/Dss88yduxYdu7cyfTp05k3bx7PPfdcIUfuelnT9cwGbDumUScREREREWdyaeI0efJkhg4dypAhQ6hVqxbTpk3Dz8+PGTNm5Hr+qlWraN26Nf379yc6OprOnTvTr1+/a45S3Yiu3AhXREREREScx2XlyNPS0li/fj1jxoyxHnNzc6NTp06sXr0612tatWrF559/ztq1a2nWrBkHDhzgl19+4b777suzndTUVFJTU63PExMTAUsJRLPZ7KB3U3Bms9m6AZg96pYPsj7efOR8kXgvUjgK2mek5FKfEXupz4i91GfEXkWlz9jTvssSpzNnzpCZmUl4eLjN8fDwcHbt2pXrNf379+fMmTO0adMGwzDIyMjgkUceuepUvYkTJzJu3Lgcx+Pi4orE2iiz2UxCQgKGYdhVw76UycDbw0RqhsHGw2e1G3UJUtA+IyWX+ozYS31G7KU+I/YqKn0mKSkp3+cWqw1wly1bxoQJE5g6dSrNmzdn3759DB8+nFdeeYUXX3wx12vGjBnDqFGjrM8TExOJiooiNDSUoKCgXK8pTGazGZPJRGhoqN2dpk5kKdYfPs+xhDQ8A4Ip7eflpCilKLmePiMlk/qM2Et9RuylPiP2Kip9xsfHJ9/nuixxCgkJwd3dnVOnTtkcP3XqFOXKlcv1mhdffJH77ruPBx98EIC6dety8eJFHnroIZ5//vlcP3Rvb2+8vb1zHHdzcysyP9gmk6lA8dSLCmb94fMAbDueRPubQp0QnRRFBe0zUnKpz4i91GfEXuozYq+i0GfsadtlUXp5edG4cWOWLFliPWY2m1myZAktW7bM9ZpLly7leHPu7u4AGIbhvGCLqPraCFdEREREpFC4dKreqFGjGDRoEE2aNKFZs2a8/fbbXLx4kSFDhgAwcOBAypcvz8SJEwHo1asXkydPpmHDhtapei+++CK9evWyJlAlSb1slfU2q7KeiIiIiIjTuDRxuvvuu4mLi+Oll17i5MmTNGjQgIULF1oLRhw+fNhmhOmFF17AZDLxwgsvcOzYMUJDQ+nVqxevvfaaq96CS0WX9SfIx4PElAw2HTmPYRiYTCZXhyUiIiIicsMxGSVsjltiYiKlSpUiISGhyBSHOH36NGFhYQWa33nf9DX8tfcMAH89fTNRZfwcHaIUMdfbZ6TkUZ8Re6nPiL3UZ8ReRaXP2JMbqGcXc40qlrY+3qh1TiIiIiIiTqHEqZhrWDHY+njj4XOuC0RERERE5AamxKmYaxh1ecRpw7+lyUVERERExLGUOBVzpfw8iQn1B2DH8QRS0jNdHJGIiIiIyI1HidMNoOG/65zSMw22H1dZchERERERR1PidAOwXed03mVxiIiIiIjcqJQ43QBsKuspcRIRERERcTglTjeAm8ID8fNyB2CDKuuJiIiIiDicEqcbgLubifoVggE4kZDCiYRk1wYkIiIiInKDUeJ0g2hUKdj6WNP1REREREQcS4nTDSL7fk7aCFdERERExLGUON0gGqiynoiIiIiI0yhxukGEBHhTqawfAFuOJZCWYXZxRCIiIiIiNw4lTjeQhlHBAKRlmNl5ItG1wYiIiIiI3EA87L0gNjaWv/76i0OHDnHp0iVCQ0Np2LAhLVu2xMfHxxkxSj41qlSaHzYdByxlyev/m0iJiIiIiMj1yXfiNGfOHN555x3WrVtHeHg4kZGR+Pr6Eh8fz/79+/Hx8eHee+/lmWeeoVKlSs6MWfJgWyDiPENauzAYEREREZEbSL4Sp4YNG+Ll5cXgwYP59ttviYqKsnk9NTWV1atX8+WXX9KkSROmTp3KnXfe6ZSAJW81IgLx8XQjJd3MxiOqrCciIiIi4ij5Spxef/11unTpkufr3t7edOjQgQ4dOvDaa69x8OBBR8UndvB0d6Ne+WDWHoznSHwyp5NSCAvU9EkRERERkeuVr+IQV0uarlS2bFkaN25c4IDk+jSqdHm63vqDGnUSEREREXGEfI04JSbmv0JbUFBQgYOR69c0ujTT/rQ8/ufgObrVjXBtQCIiIiIiN4B8JU7BwcGYTKZ83TAzM/O6ApLr0zjbiNO6Q/EujERERERE5MaRr8Tpjz/+sD4+ePAgzz77LIMHD6Zly5YArF69mlmzZjFx4kTnRCn5FuznxU3hAew5dYHtxxO5mJqBv7fdVedFRERERCSbfP1G3b59e+vj8ePHM3nyZPr162c91rt3b+rWrcvHH3/MoEGDHB+l2KVJdBn2nLpAptlg05HztK4a4uqQRERERESKtXwVh8hu9erVNGnSJMfxJk2asHbtWocEJdenaXS26XoqECEiIiIict3sTpyioqL45JNPchz/3//+l2N/J3GNJpXKWB9rnZOIiIiIyPWze/HLlClT6Nu3L7/++ivNmzcHYO3atezdu5dvv/3W4QGK/SqU9iU8yJtTialsOHSOjEwzHu5258giIiIiIvIvu3+b7t69O3v27KFXr17Ex8cTHx9Pr1692LNnD927d3dGjGInk8lEk2jLqNPFtEx2nUxycUQiIiIiIsVbgcqtRUVFMWHCBEfHIg7UtFJpft5yAoB/DsZTp3wpF0ckIiIiIlJ8FWj+1l9//cWAAQNo1aoVx44dA2D27NmsWLHCocFJwWWNOAGsO6QCESIiIiIi18PuxOnbb7+lS5cu+Pr6smHDBlJTUwFISEjQKFQRUqNcIAH/7t+07mA8hmG4OCIRERERkeLL7sTp1VdfZdq0aXzyySd4enpaj7du3ZoNGzY4NDgpOA93NxpWDAbgVGIqR88luzYgEREREZFizO7Eaffu3bRr1y7H8VKlSnH+/HlHxCQO0jTbdL1/DqosuYiIiIhIQdmdOJUrV459+/blOL5ixQqqVKnikKDEMZpUurwR7j/aCFdEREREpMDsTpyGDh3K8OHDWbNmDSaTiePHjzNnzhxGjx7No48+6owYpYAaVAzG3c0EWNY5iYiIiIhIwdhdjvzZZ5/FbDbTsWNHLl26RLt27fD29mb06NE88cQTzohRCsjPy4M6kUFsPprA3tMXOH8pjWA/L1eHJSIiIiJS7Ng94mQymXj++eeJj49n27Zt/P3338TFxfHKK684Iz65TjZlyTVdT0RERESkQOxOnD777DN27tyJl5cXtWrVolmzZgQEBJCSksJnn33mjBjlOjSrfDlxWhN71oWRiIiIiIgUX3YnToMHD6ZZs2Z8++23NscTEhIYMmSIwwITx2iWbcTp7wNa5yQiIiIiUhB2J04A48aN47777uPll192cDjiaKX9vahRLhCA7ccTSExJd3FEIiIiIiLFT4ESpwEDBrB06VI++ugj/vOf/5CcrM1Vi7IWVcoCYDZUXU9EREREpCAKVBwCoEWLFqxZs4Z9+/bRqlUrDh486OjYxEFaVNF0PRERERGR62F34mQYhvVxxYoVWbVqFdHR0dx6660ODUwcp1nlstbHaw6oQISIiIiIiL3sTpzGjh1LQECA9bmfnx/ff/89I0eOpF27dg4NThyjjL8X1cMt65y2HksgSeucRERERETsYvcGuGPHjs31+Lhx4647GHGe5lXKsPtUkmWd06Fz3Fw9zNUhiYiIiIgUG/lKnH788Ue6deuGp6cnP/74Y57nmUwmevXq5bDgxHFaVCnLZ6sPAfD3gbNKnERERERE7JCvxKlPnz6cPHmSsLAw+vTpk+d5JpOJzMxMR8UmDmSzEa4KRIiIiIiI2CVfiZPZbM71sRQfIQHeVAsLYO/pC2w9lsCF1AwCvO2eqSkiIiIiUiIVaB8nKZ6a/1uWPNNssP7QORdHIyIiIiJSfORryOHdd9/N9w2ffPLJAgcjztWiSlk+//swYFnn1P6mUBdHJCIiIiJSPOQrcZoyZUq+bmYymZQ4FWG265y0n5OIiIiISH7lK3GKjY11dhxSCMICfYgJ9Wd/3EW2HE3gUloGfl5a5yQiIiIici1a41TCNK9SFoAMrXMSEREREcm3Ag03HD16lB9//JHDhw+TlpZm89rkyZMdEpg4R4sqZflijWWd0+r9Z2lbTeucRERERESuxe7EacmSJfTu3ZsqVaqwa9cu6tSpw8GDBzEMg0aNGjkjRnGgFlUur3NauV/rnERERERE8sPuqXpjxoxh9OjRbN26FR8fH7799luOHDlC+/btufPOO50RozhQWKAPN4UHALD16HkSktNdHJGIiIiISNFnd+K0c+dOBg4cCICHhwfJyckEBAQwfvx4Jk2a5PAAxfFaVw0BwGxYypKLiIiIiMjV2Z04+fv7W9c1RUREsH//futrZ86ccVxk4jStY0Ksj1ft0/dMRERERORa7F7j1KJFC1asWEHNmjXp3r07Tz31FFu3buW7776jRYsWzohRHKx5lTK4u5nINBusUOIkIiIiInJNdidOkydP5sKFCwCMGzeOCxcuMG/ePKpVq6aKesVEoI8n9SuUYsPh8+yPu8jJhBTKlfJxdVgiIiIiIkWW3YlTlSpVrI/9/f2ZNm2aQwOSwtGmaggbDp8HYOW+M/RtXMG1AYmIiIiIFGHXtQHuhQsXSExMtPmS4qFV1cvrnFbu13Q9EREREZGrsTtxio2NpUePHvj7+1OqVClKly5N6dKlCQ4OpnTp0s6IUZygYcVgfD3dAcuIk2EYLo5IRERERKTosnuq3oABAzAMgxkzZhAeHo7JZHJGXOJk3h7uNK1chuV74jiVmMr+uItUDQtwdVgiIiIiIkWS3YnT5s2bWb9+PdWrV3dGPFKI2lQty/I9cYBl1EmJk4iIiIhI7uyeqte0aVOOHDnijFikkLXKtp/TSpUlFxERERHJk90jTv/73/945JFHOHbsGHXq1MHT09Pm9Xr16jksOHGuWhFBlPbz5NyldFYfOEum2cDdTVMvRURERESuZHfiFBcXx/79+xkyZIj1mMlkwjAMTCYTmZmZDg1QnMfNzUSrmBB+3nqCpJQMth5LoEFUsKvDEhEREREpcuxOnO6//34aNmzI3LlzVRziBtC6qiVxAst0PSVOIiIiIiI52Z04HTp0iB9//JGqVas6Ix4pZK2rlrU+XrH3DMNu1vdVRERERORKdheHuOWWW9i8ebMzYhEXqFjGj6gyvgCsOxTPxdQMF0ckIiIiIlL02D3i1KtXL0aOHMnWrVupW7dujuIQvXv3dlhw4nwmk4n2N4Xy+d+HSc80+PvAWTrWDHd1WCIiIiIiRYrdidMjjzwCwPjx43O8puIQxVO7apbECeDPPXFKnERERERErmB34mQ2m50Rh7hQq6oheLiZyDAb/PnvhrgiIiIiInKZXWuc0tPT8fDwYNu2bQ4L4IMPPiA6OhofHx+aN2/O2rVrr3r++fPnGTZsGBEREXh7e3PTTTfxyy+/OCyekijA24Mm0aUBOHT2EgfPXHRxRCIiIiIiRYtdiZOnpycVK1Z02HS8efPmMWrUKMaOHcuGDRuoX78+Xbp04fTp07men5aWxq233srBgwf55ptv2L17N5988gnly5d3SDxFRWxCLH+f+BvDMAqtzXY3hVofL9+rUScRERERkezsrqr3/PPP89xzzxEfH3/djU+ePJmhQ4cyZMgQatWqxbRp0/Dz82PGjBm5nj9jxgzi4+P54YcfaN26NdHR0bRv35769etfdyxFxdnks/T9sS9DfxvKD/t+KLR222dLnP7crcRJRERERCQ7u9c4vf/+++zbt4/IyEgqVaqEv7+/zesbNmzI133S0tJYv349Y8aMsR5zc3OjU6dOrF69OtdrfvzxR1q2bMmwYcOYP38+oaGh9O/fn2eeeQZ3d/dcr0lNTSU1NdX6PDExEbCs1SoK67XMZjOGYVhj2RO/h3RzOgDf7f2O22JuK5Q4aoQHEBroTVxSKqsPnCU5LR1vj9w/U3GtK/uMyLWoz4i91GfEXuozYq+i0mfsad/uxKlPnz72XpKrM2fOkJmZSXi4bQW38PBwdu3ales1Bw4cYOnSpdx777388ssv7Nu3j8cee4z09HTGjh2b6zUTJ05k3LhxOY7HxcWRkpJy/W/kOpnNZhISEjAMAzc3N06cPWF9bVPcJnYe2UlZ77JXuYPjNK3gzy87U7mUlsmSzbE0iQoqlHbFPlf2GZFrUZ8Re6nPiL3UZ8ReRaXPJCUl5ftcuxOnvBKUwmA2mwkLC+Pjjz/G3d2dxo0bc+zYMd5444084xozZgyjRo2yPk9MTCQqKorQ0FCCglyfGJjNZkwmE6Ghobi5ueF10cvm9a3JW7kr6q5CiaVzvQx+2WmZgrklLoPujcMKpV2xz5V9RuRa1GfEXuozYi/1GbFXUekzPj4++T7X7sQpy/r169m5cycAtWvXpmHDhnZdHxISgru7O6dOnbI5furUKcqVK5frNREREXh6etpMy6tZsyYnT54kLS0NLy+vHNd4e3vj7e2d47ibm1uR+cE2mUzWeJIzk21eW3p4KffUuKdQ4mh3UxgmExgGLN9zhue6F43PR3LK3mdE8kN9RuylPiP2Up8RexWFPmNP23ZHefr0aW655RaaNm3Kk08+yZNPPknjxo3p2LEjcXH5Lyrg5eVF48aNWbJkifWY2WxmyZIltGzZMtdrWrduzb59+2zmIu7Zs4eIiIhck6biKDndNnH65+Q/JKQmFErbZfy9qFe+FAC7TiZxKtH1UxlFRERERIoCuxOnJ554gqSkJLZv3058fDzx8fFs27aNxMREnnzySbvuNWrUKD755BNmzZrFzp07efTRR7l48SJDhgwBYODAgTbFIx599FHi4+MZPnw4e/bs4eeff2bChAkMGzbM3rdRZF3KuGTzPMPIYPnR5YXWfvbqesu1Ga6IiIiICFCAqXoLFy5k8eLF1KxZ03qsVq1afPDBB3Tu3Nmue919993ExcXx0ksvcfLkSRo0aMDChQutBSMOHz5sM3wWFRXFokWLGDlyJPXq1aN8+fIMHz6cZ555xt63UWQlZyTnOLb40GJ6xfQqlPbbVw/l3aX7APhzTxx3NokqlHZFRERERIoyuxMns9mMp6dnjuOenp4FKif4+OOP8/jjj+f62rJly3Ica9myJX///bfd7RQXl9Iv5Ti26vgqLqVfws/Tz+nt168QTKCPB0kpGfy19wyZZgN3N5PT2xURERERKcrsnqp3yy23MHz4cI4fP249duzYMUaOHEnHjh0dGlxJlH3EqVFYIwBSMlNYdXxVobTv4e5Gu2qW6XoJyelsPHyuUNoVERERESnK7E6c3n//fRITE4mOjiYmJoaYmBgqV65MYmIi7733njNiLFGyr3HKPj1v8eHFhRbDLTUulyFfsut0obUrIiIiIlJU2T1VLyoqig0bNrB48WLrRrU1a9akU6dODg+uJMo+4tQhqgOT100mKT2J5UeWk56Zjqd7zmmSjtaheqi1LPmSnad4pmsNp7cpIiIiIlKUFWgfJ5PJxK233sqtt97q6HhKvOxrnIK8gmgX1Y6fD/xMUnoSa0+upXX51k6PoWyANw2jgtlw+Dx7Tl3gSPwloso4f32ViIiIiEhRVaDEacmSJSxZsoTTp0/nKAgxY8YMhwRWUmWNOHmYPPB086RTxU78fOBnwDJdrzASJ4CONcPZcPg8AEt3nWZQq+hCaVdEREREpCiye43TuHHj6Ny5M0uWLOHMmTOcO3fO5kuuT1bi5Ovhi8lkolVkK3zcfQBYengpGeaMQolD65xERERERC6ze8Rp2rRpzJw5k/vuu88Z8ZR4WcUhfD19AfDz9KNthbb8fuh34lPiWXdqHS0iWjg9jhrlAoks5cPxhBT+3n+Wi6kZ+HsXaIBSRERERKTYs3vEKS0tjVatWjkjFgGS0y0jTn4el9cUdYnuYn286OCiQonDZDJxS03LqFNappkV+84USrsiIiIiIkWR3YnTgw8+yBdffOGMWEo8wzBspuplaVu+rfX54kOLC226Xsca4dbHS3dqup6IiIiIlFx2z71KSUnh448/ZvHixdSrVw9PT9vy2JMnT3ZYcCVNujmdDMOSFGVPnPw8/WhfoT0LDy7kfOp51p5YS6vyzh/1axlTFh9PN1LSzSzdfRqz2cDNzeT0dkVEREREihq7E6ctW7bQoEEDALZt22bzmsmkX6qvR/Y9nPw8bct/d4nuwsKDCwFYdGhRoSROPp7utKkawuKdp4lLSmXb8QTqVQh2ersiIiIiIkWN3YnTH3/84Yw4BNs9nLKPOAG0Kd8GXw9fkjOSWXxoMS+0eAFPN+dvhntLjXAW/ztNb8nO00qcRERERKREsnuNkziPzYiTh+2Ik4+HDx2iOgCQmJbImhNrCiWm7GXJl6osuYiIiIiUUPlKnB555BGOHj2arxvOmzePOXPmXFdQJVVWKXLIOeIErqmuV66UD3XKBwGw9VgCpxJTCqVdEREREZGiJF+JU2hoKLVr16Z79+58+OGH/PPPPxw7doyzZ8+yb98+fvzxR55++mkqVqzIlClTqFu3rrPjviFdbY0TWKbrZY1ELTm8hPTM9EKJ65Zs1fV+33GqUNoUERERESlK8pU4vfLKK+zZs4fWrVszdepUWrRoQcWKFQkLC6N69eoMHDiQAwcO8PHHH/P3339Tr149Z8d9Q7raGicAb3dvbq54MwBJaUmsPrG6UOLqXOty4rRo+8lCaVNEREREpCjJd3GI8PBwnn/+eZ5//nnOnTvH4cOHSU5OJiQkhJiYGFXUc4CrrXHK0jW6Kz8f+BmwTNdrV6Gd0+OqHRlE+WBfjp1PZvX+syQkp1PK1/mFKUREREREiooCFYcoXbo09evXp0WLFlStWlVJk4PYrHHyzDniBNAqshUBngEALD28lNTMVKfHZTKZ6FzbMuqUYTZYtltFIkRERESkZFFVvSIk+4hTblP1ALzcvbil4i0AXEi/wPKjywslti61y1kfa7qeiIiIiJQ0SpyKkOxrnPKaqgfQo3IP6+OsaXvO1qRSacr4ewGwbHccKemZhdKuiIiIiEhRoMSpCMnPiBNAs4hmlPUpC8Dyo8tJTEt0emwe7m50/HdPp0tpmazYe8bpbYqIiIiIFBVKnIqQ7GuccitHnsXDzYNulbsBkG5OZ/GhxU6PDWyn6/22Q9P1RERERKTkKFDilJGRweLFi/noo49ISkoC4Pjx41y4cMGhwZU0+R1xAuhRpfCn67WpFoKflzsAi3eeJiPTXCjtioiIiIi4mt2J06FDh6hbty633XYbw4YNIy4uDoBJkyYxevRohwdYkiSn5z9xql22NpWCKgHwz8l/OHXR+RvT+ni606F6KADxF9NYd+ic09sUERERESkK7E6chg8fTpMmTTh37hy+vpd/ub/99ttZsmSJQ4MraZIz8584mUwma5EIA4NfY391amxZOtdSdT0RERERKXnsTpz++usvXnjhBby8vGyOR0dHc+zYMYcFVhKlZlzek8nb3fua53ev0t36+OfYwpmud3ONMDzcLPt2/bb9FIZhFEq7IiIiIiKuZHfiZDabyczMWYr66NGjBAYGOiSokir7ZrY+Hj7XPL9SUCXqlK0DwK74Xew/v99psWUp5etJyxhLRb9j55PZftz5Ff1ERERERFzN7sSpc+fOvP3229bnJpOJCxcuMHbsWLp37573hXJNWcUh3E3ueLp55usaVxSJyF5db+E2TdcTERERkRuf3YnTW2+9xcqVK6lVqxYpKSn079/fOk1v0qRJzoixxMgaccrPNL0sXSt3xc1k+Tb+EvtLoUyd61w7HJNlth6/bD2h6XoiIiIicsOzO3GqUKECmzdv5rnnnmPkyJE0bNiQ119/nY0bNxIWFuaMGEuMrMQpP9P0soT4htAiogUAxy4cY+PpjU6JLbuwQB+aVy4DwIEzF9l5IsnpbYqIiIiIuJJHgS7y8GDAgAGOjqXES8lIAcDHPf+JE0DPKj1ZdXwVAD/u/5FG4Y0cHtuVetSN4O8D8QD8vPU4tSKDnN6miIiIiIir5Ctx+vHHH/N9w969exc4mJIuJdOSOHl75H+qHkDHih3x9/TnYvpFFh5cyDPNnrlmOfPr1aVOOcb+uB2zAb9sPcnoztUxZc3fExERERG5weQrcerTp0++bmYymXKtuCf5k1WO3N4RJz9PP7pEd+G7vd9xMf0iSw4voWeVns4I0coyXa8sqw+cJfbMRXacSKR2ZCmntikiIiIi4ir5WuNkNpvz9aWkqeAyzBlkGBmAfcUhstwWc5v18fx98x0W19X0qBdhffzzlhOF0qaIiIiIiCvYXRxCnMPePZyu1DCsIVGBUQCsObGGExecn8h0rVOOf/fC5WdV1xMRERGRG1iBEqclS5bQs2dPYmJiiImJoWfPnixevNjRsZUoWYUhwP6pemCZJpk16mRg8NOBnxwWW15CArxpUcWyGe6hs5e0Ga6IiIiI3LDsTpymTp1K165dCQwMZPjw4QwfPpygoCC6d+/OBx984IwYS4SswhBgf3GILL1jemPCMgQ0f9/8QhkByj5db4Gm64mIiIjIDcruxGnChAlMmTKFuXPn8uSTT/Lkk0/yxRdfMGXKFCZMmOCMGEuE7FP1CrLGCSAiIIJmEc0AOJx0mE1xmxwR2lV1rX15up42wxURERGRG5XdidP58+fp2rVrjuOdO3cmISHBIUGVRFkV9YDrKiVe2EUiygZ40zLGMl3vcPwlth3TdD0RERERufHYnTj17t2b77//Psfx+fPn07Onc0tg38iSM5Otjws64gSX93QCWHhwIckZyde44vr1qBtpfbxgy3GntyciIiIiUtjytY/Tu+++a31cq1YtXnvtNZYtW0bLli0B+Pvvv1m5ciVPPfWUc6IsAbKPOF1P4nTlnk6LDy2mV0wvR4SYpy61w3lx/jYyzQY/bT7OM11r4OamzXBFRERE5MaRr8RpypQpNs9Lly7Njh072LFjh/VYcHAwM2bM4IUXXnBshCXE9ZYjz+62mNv4bu93AHy39zunJ05lA7xpUzWEP/fEcTwhhX8OxtP832p7IiIiIiI3gnwlTrGxsc6Oo8TLXlWvIOXIs2sY1pDKpSoTmxDLulPrOJhwkOhS0dcZ4dXd3rA8f+6JA+CHTceVOImIiIjIDUUb4BYRNvs4XeeIk8lkom+1vtbnWaNPznRrrXB8Pd0BS3W9tAyz09sUERERESks+RpxutLRo0f58ccfOXz4MGlpaTavTZ482SGBlTSOKEeeXe+Y3ryz4R3SzenM3z+fJxo+gae753XfNy/+3h50rh3O/E3HSUhOZ9nu03SuXc5p7YmIiIiIFCa7E6clS5bQu3dvqlSpwq5du6hTpw4HDx7EMAwaNWrkjBhLBJupetc54gRQ2qc0HSt2ZOHBhcSnxLP0yFK6RHe57vteTZ8G5Zm/yVJVb/6m40qcREREROSGYfdUvTFjxjB69Gi2bt2Kj48P3377LUeOHKF9+/bceeedzoixRMheVe961zhl6XvT5el63+751iH3vJo21UIo4+8FwOKdp0hKSXd6myIiIiIihcHuxGnnzp0MHDgQAA8PD5KTkwkICGD8+PFMmjTJ4QGWFNlHnLw9rn+qHkCzcs2oEFABgNUnVnMk6YhD7psXT3c3etaLACA1w8zCbSed2p6IiIiISGGxO3Hy9/e3rmuKiIhg//791tfOnDnjuMhKGGeMOLmZ3GxGnb7fm3PjYke7rUF56+OsaXsiIiIiIsWd3YlTixYtWLFiBQDdu3fnqaee4rXXXuP++++nRYsWDg+wpHD0Gqcsfar2wcNkWcr2w74fyDBnOOzeuWlUMZiKZfwAWLX/DKcTU65xhYiIiIhI0Wd34jR58mSaN28OwLhx4+jYsSPz5s0jOjqa6dOnOzzAksLRVfWyhPiG0D6qPQBxyXEsP7rcYffOjclkok+DSADMBvy4WaNOIiIiIlL82Z04ValShXr16gGWaXvTpk1jy5YtfPvtt1SqVMnhAZYUNvs4OWiqXpbsezp9tecrh947N7c1vDxd74dNx5zenoiIiIiIs2kD3CLCGcUhsrSKbEWkv2UUaNWxVRxJdG6RiJjQAOqWLwXAtmOJ7D6Z5NT2REREREScLV+JU5kyZayFH0qXLk2ZMmXy/JKCyT5Vz9EjTu5u7txZ3VIq3sBg3u55Dr1/bv7TuIL18dfrnJuoiYiIiIg4W742wJ0yZQqBgYEAvP32286Mp8SySZwcWBwiyx3V7mDqpqmkm9P5ft/3DGs4DF8PX4e3k6V3/Uhe+3knaZlmfth0jGe61cDTXQOcIiIiIlI85StxGjRoEAAZGRmYTCa6dOlCeHi4UwMrabLWOHm6eeJmcnyCUcanDF2ju/LTgZ9ITEtkYexCbq92u8PbyVLa34tOtcL4ZetJzlxIY9nuOG6tpT4jIiIiIsWTXb+he3h48Mgjj5CSohLTjpa1xsnR0/Syu6fGPdbHc3fNxTAMp7UFcGfjKOtjTdcTERERkeLM7qGNZs2asXHjRmfEUqJlbYDrjGl6WeqG1KVW2VoA7IzfyZYzW5zWFkDbaiGEBVoKXSzddZozF1KvcYWIiIiISNFkd+L02GOP8dRTT/H++++zevVqtmzZYvMlBZO1xsmRezhdyWQycU/1y6NOX+760mltAXi4u3F7I0tp8gyzwfxN2tNJRERERIonuxOne+65h9jYWJ588klat25NgwYNaNiwofW/UjDJGcmAc0ecALpV7kYpb0up8EUHF3E2+axT27tyup6zpweKiIiIiDhDvopDZBcbG+uMOEo0wzAKZcQJLInZ7VVvZ+b2mdYKew/WfdBp7VUNC6BhxWA2Hj7PrpNJbD+eSJ1/93gSERERESku7E6cKlWq5Iw4SrR0Ix0Dy0iMs0ecAO6qfhezts+y7uk0uPZgPNzs7gr59p/GFdh4+DxgGXVS4iQiIiIixU2Bf1vesWMHhw8fJi0tzeZ47969rzuokiYt8/Jn6OwRJ4CowCjaVmjL8qPLOXnxJEsOL6FLdBentderfiTjf9pBaoaZ+ZuP81yPmnh7uDutPRERERERR7M7cTpw4AC33347W7duxWQyWdesmEwmADIzMx0bYQmQZi7cxAlgQM0BLD+6HIDZO2Y7NXEK8vGka51yzN90nPOX0lm0/RS960c6rT0REREREUezuzjE8OHDqVy5MqdPn8bPz4/t27ezfPlymjRpwrJly5wQ4o0v3Zxufezl7lUobbaIaEG10tUA2By3mS1xzq2IeHfTy0Ui5q457NS2REREREQcze7EafXq1YwfP56QkBDc3Nxwc3OjTZs2TJw4kSeffNIZMd7wXDHiZDKZuK/mfdbns3fMdmp7LauUpXKIPwCrD5zlQNwFp7YnIiIiIuJIdidOmZmZBAYGAhASEsLx45a9eSpVqsTu3bsdG10JkX3EydPNs9Da7V6lO2V8ygDw+6HfOXnxpNPaMplM9Gt2edTpy3+OOK0tERERERFHsztxqlOnDps3bwagefPm/Pe//2XlypWMHz+eKlWqODzAkqCwi0Nkb+uu6ncBkGlk8sWuL5za3n8aR+Hlbuly36w/SmqG1sOJiIiISPFgd+L0wgsvYDabARg/fjyxsbG0bduWX375hXfffdfhAZYE6Ubhr3HKcnf1u62jXN/s+YZL6Zec1lYZfy+61ikHQPzFNBZuc94Il4iIiIiII+U7cWrSpAnTpk2jZcuW3HHHHQBUrVqVXbt2cebMGU6fPs0tt9zitEBvZNlHnAo7cQrxDaF75e4AJKUlMX//fKe21795RevjuWtVJEJEREREiod8J07169fn6aefJiIigoEDB9pU0CtTpoy1HLnYz6aqnlvhJk4A99W6XCRizs45mA2z09pqXrkMVUItRSL+PhDPfhWJEBEREZFiIN+J0/Tp0zl58iQffPABhw8fpmPHjlStWpUJEyZw7NgxZ8Z4w3NFVb3sqpepTvNyzQE4lHiIP4784bS2TCYT/ZtdHnX6UqNOIiIiIlIM2LXGyc/Pj8GDB7Ns2TL27NnDPffcw0cffUR0dDQ9evTgu+++c1acNzSbqnruhVdVL7uBtQdaH8/YNsO6sbEz9G1UwaZIREq6ikSIiIiISNFmd3GILDExMbz66qscPHiQuXPn8vfff3PnnXcW6F4ffPAB0dHR+Pj40Lx5c9auXZuv67788ktMJhN9+vQpULtFhatHnADalm9r3RB3S9wW1p9a77S2Svt70a2upUjEuUvpKhIhIiIiIkVegRMngGXLljF48GAGDx5MZmYmQ4cOtfse8+bNY9SoUYwdO5YNGzZQv359unTpwunTp6963cGDBxk9ejRt27YtaPhFhs0ap0IuDpHFZDIxpPYQ6/MZ22Y4tb17m1eyPp61+qBT2xIRERERuV52J05Hjx7l1VdfpWrVqtxyyy0cPHiQqVOncuLECaZNm2Z3AJMnT2bo0KEMGTKEWrVqMW3aNPz8/JgxI+9f3DMzM7n33nsZN27cDbF3VPYRJ1clTgBdK3clwj8CgL+O/cXueOdtaNw0ujQ1ylk2Ut54+Dxbjp53WlsiIiIiItfLI78nfvXVV8yYMYMlS5YQFhbGoEGDuP/++6latWqBG09LS2P9+vWMGTPGeszNzY1OnTqxevXqPK8bP348YWFhPPDAA/z1119XbSM1NZXU1FTr88TERADMZrN1PypXMpvNNuXIPU2eLovLHXfuq3kf/133X8Ay6jSxzUSntTeoZSXGfL8NgJkrD/LmnfWc1taNxGw2YxhGkei/Ujyoz4i91GfEXuozYq+i0mfsaT/fidOAAQPo0aMH33//Pd27d8fN7bpm+QFw5swZMjMzCQ8PtzkeHh7Orl27cr1mxYoVTJ8+nU2bNuWrjYkTJzJu3Lgcx+Pi4khJSbE7Zkczm80kXUqyPr+UdOma0xSdqU2pNkzznEZieiILDy6kX1Q/yvmWc0pbLSM9CfJ2JzE1k5+2HOfBpmUp4+ea4hjFidlsJiEhAcMwHPJzKDc+9Rmxl/qM2Et9RuxVVPpMUlLStU/6V74Tp6NHjxIWFlaggBwlKSmJ++67j08++YSQkJB8XTNmzBhGjRplfZ6YmEhUVBShoaEEBQU5K9R8M5vNuO91tz4PKxPm8s/53pr38uGWDzEbZn459QvPNnvWaW3d0+w8H/8VS3qmwZLYZIbdXN5pbd0ozGYzJpOJ0NBQ/c9J8kV9RuylPiP2Up8RexWVPuPj45Pvc/OdODnjl/mQkBDc3d05deqUzfFTp05RrlzOUY79+/dz8OBBevXqZT2WNbzm4eHB7t27iYmJsbnG29sbb++clerc3NyKzA+2TVU9D2+Xx9W/Zn9m7phJckYy3+/7nkcbPEppn9JOaeu+ltH8b0UsZgPmrDnCIx2q4uleNL4vRZnJZCpSfViKPvUZsZf6jNhLfUbsVRT6jD1tu7Rne3l50bhxY5YsWWI9ZjabWbJkCS1btsxxfo0aNdi6dSubNm2yfvXu3Zubb76ZTZs2ERUVVZjhO0y6cbmqnqvKkWcX7BPMHdXuACAlM4XZO2Y7ra2oMn50rGmZqnkyMYXftp+6xhUiIiIiIoXP5X8SGDVqFJ988gmzZs1i586dPProo1y8eJEhQyylsQcOHGgtHuHj40OdOnVsvoKDgwkMDKROnTp4ebmuIt31yF4cwpVV9bIbVGsQHm6WAcm5u+aSkJrgtLYGt4q2Pp65KtZp7YiIiIiIFJTLE6e7776bN998k5deeokGDRqwadMmFi5caC0YcfjwYU6cOOHiKJ2rKOzjdKWIgAhui7kNgAvpF/hi5xdOa6tVTFmqhQUA8M/Bc2w/7rwkTURERESkIOxOnP755x/WrFmT4/iaNWtYt25dgYJ4/PHHOXToEKmpqaxZs4bmzZtbX1u2bBkzZ87M89qZM2fyww8/FKjdosJmHye3qydOhmFgGIazQwLggboP4G6yFK6YvXM2F9IuOKUdk8nEwOyjTisPOqUdEREREZGCsjtxGjZsGEeOHMlx/NixYwwbNswhQZU02UecrrbGycjM5PDgIexp1pyLf+dMXh0tKjCKnlV6ApCUlsTcXXOd1tYdDcsT6GOZGjh/03FOJ7q+VLyIiIiISBa7E6cdO3bQqFGjHMcbNmzIjh07HBJUSWMz4nSVqXopO3Zyac0azElJnBw/HiMz0+mxDa03FDeTpZvM2jGLi+kXndKOv7cH9zavBEBapplZqw86pR0RERERkYKwO3Hy9vbOUT4c4MSJE3h45Lu6uWST3zVO6ceOWh+nHThA4i+/ODUugEpBleheuTsACakJzNs9z2ltDW4Vjae7CYDP/z7MxdQMp7UlIiIiImIPuzOdzp07M2bMGObPn0+pUqUAOH/+PM899xy33nqrwwMsCbJGnNxMbtZKdrlJP3bM5vmZD6YS1K0bJicnrEPrDeXnAz9jYDBr+yz61eiHr4evY26edglOboX4A5SL38+c0O2cPnsWv4xUzn88Bf+wsuDpD/4hEFzR8hVyE5SpAiaTY2IQEREREbkGu3/jfvPNN2nXrh2VKlWiYcOGAGzatInw8HBmz3befj83sqwRp2vt4XRl4pR28CAJCxYQ3KePs0IDoEqpKnSJ7sLCgwuJT4nnq91fMaj2oILdzDDgxCbY+RMcXAHHNkC2EbdmAO7/Pjn771dufEpBRH2o1Bqq3AzlG4O7RjxFRERExDns/k2zfPnybNmyhTlz5rB582Z8fX0ZMmQI/fr1w9PT0xkx3vCyRpw83a7++aVdkTgBnPnwQ0r17On0UaeH6j3EwoMLAZixbQZ33nQnfp5++b/BxTOw/lPYPA/O7r3+gFISIHa55WvZRPAOgpu6QK0+ULUjeDpoRExEREREhAIkTgD+/v489NBDjo6lxLJ3xMnk7Y1v/fpcWruW9EOHSfjxJ4LvuN2pMVYrXY2u0V2to05f7PqCB+s+eO0LE47Bqvdg/UzISM75etmqULElhNWyTL8LjmLt8XQemrcLMyYaR/owo19NTBdOwfnDcC7WMrXv+Ca4cPLyfVITYevXli+vQKj7H2gyxDIqJSIiIiJynfKVOP34449069YNT09Pfvzxx6ue27t3b4cEVpJkJU5XKwxhGAbpxy0bAXtGRhL65BMcGnAfAGemTqVUr56YnDzi91iDx/jt0G+YDTMzts3grup3EeQVlPvJ6cmwYgqseBsyU21fq9QG6t0JN3WDwPAclzYNMyj3ZyK7Tibxx3FYdzGEppVvytnG+SNwYBkc+AP2LbaMQgGkJVlGt9Z/apnC13iIJZHSKJSIiIiIFFC+Eqc+ffpw8uRJwsLC6HOV9TQmk4nMQiiRfaPJmqp3tcQp8/x5jEuXAPAsXx6/Jk3wb9WSi6tWk370KAnz5xP8n/84Nc7KpSrTq0ov5u+fT1JaErO2z+KJhk/kPHHvYvjlKTh38PIxD19oPBhaPmYp8HAVJpOJh9pVYdRXmwH46M8DNI0uk/PE4ChodJ/lKyMNYv+E7T/A9u8hq2z6sfWWryXjoeUwaHI/+OSR7ImIiIiI5CFf5cjNZjNhYWHWx3l9KWkqmPTMf0ec3K5Sivzo5fVNnuXLAxDy+OWkJW7qVMxpaTmuc7RHGzxqrfz3+Y7PiU+Jv/xiRhr8+izM6Xs5aXLzgJaPw8ht0O31ayZNWXrWi6RckA8Ai3eeYvfJpKtf4OEF1W6FPh/AU7ugx2QoV/fy6xdPw+Kx8HYd+GMCXIrP+14iIiIiIlewex+nzz77jNTU1BzH09LS+OyzzxwSVEliGAbpxrXXOGWvqJeVOPk1aoh/u7YAZBw/wfm5c50YqUX5gPL0rdYXgEsZl5ixdYblhXMHYUYXWPPh5ZMrtYFHVkCX1yzlxO3g5eHGg20rW59PXbYv/xf7BEHTB+Dhv+DBJVD7duDf0uUpCfDnJHinAfw12TKlUERERETkGuxOnIYMGUJCQkKO40lJSQwZMsQhQZUkWdP0ADzd816jZJM4RUZaH4eNHGl9fGbaR2ReuODgCHN6qN5D1iTvy91fcnrfIvi4AxzfYDnB3Qu6vwmDF0BYzQK30795Rcr4W0bhftp8nINnLtp3A5MJKjSBO2fC4/9Ag3stI2AAqQmwZBy81xg2zgGzRktFREREJG92J06GYWDKZePRo0ePWjfElfxLy7ycOOV7xClb4uRTsyZBPXsCkHnuHPEzPnVClLbC/MK4p/o9AKRmpvLxwmGQfM7yYpkq8OBiaDb0ujeo9fPy4P7W0QCYDZj25/6C3yykGvSZCk9uhIb3genfrp94DOY/Bh+1g4MrryteEREREblx5TtxatiwIY0aNcJkMtGxY0caNWpk/apfvz5t27alU6dOzoz1hpQ9cbrqGqeTl0tve5aPtHkt9Mkn4N99nM7OnEnGmTMOjjKnB+o+gN+/8X4b4MMhDw+o3A4eWubQEuD3tYwm0Nvy3r7dcJQTCdc5tS64Itz2Pjy6ylLVL8upbTCzO3z3ECSdur42REREROSGk+/EqU+fPtx2220YhkGXLl247bbbrF/33HMPH330EZ9//rkzY70hZZ+qd7WqeuknLaXIcXfHI8R2vZBXxYqUvusuAIxLlzgz7SPHB3qF0nuXMPhsHAAZJhPvRNeGe78FH8eOOpby9WRgq0oApGcafLz8gGNuHFYT+n8Jg3+BiAaXj2+ZB+83gb8/hMwMx7QlIiIiIsVevjfAHTt2LADR0dHcfffd+Pj4OC2oksRmxOkqiVPGScsoiEdYGCZ39xyvhzz6COe//x4jOZlz8+ZRZtBAvKKiHB8wwK5f4LuHGISZeYEBnPVw5/fMc2w+t5P6oY7fcPb+1pWZseIgyemZzF17mGE3VyUk4OqbBedbdGsYuhQ2zILF4yDlvGUz3YXPwpav4LYPILyWY9oSERERkWLL7jVOgwYNwsfHh3Xr1jF79mxmz57N+vXrnRFbiZCfNU7m1FQy4y3lsz3Llcv1HI/QUMoMHmR5kp5O3LvvOTbQLLHL4evBYGTiZxg8FnQ5qZi8bjKGYTi8ybIB3vRrZiljnpJuZsaKWMc24OZu2d/piQ3QaODl48c3WNY+/flf+LdkvIiIiIiUTHYnTseOHaNt27Y0a9aM4cOHM3z4cJo2bUqbNm04evSoM2K8odlU1XPLvapeRrb1TR7lwvO8V9n778c9OBiAxJ9+InnbdscEmSX+AMy7DzL/LUdf907uuH0O0UHRAGw4vYE/jvzh2Db/9VC7Kni5W7rr7NWHSLjkhETGvyz0fg8e+B1CbrIcM6fDH6/BxzfD8U2Ob1NEREREigW7E6cHHniA9PR0du7cSXx8PPHx8ezcuROz2cyDDz7ojBhvaKmZl/fEymvEKf3k5WIFnuUi8ryXe2AgIY8+Yn1+etIkx40ApSbB3P6WqWwAVW+FPh/i4eHNyMaXS6JPWT+FDLPj1waVK+VD38YVAEhKzeB/Kxy01ik3Uc0se0C1fQpM/06LPLUVPrkFlrxi2ehXREREREoUuxOnP//8kw8//JDq1atbj1WvXp333nuP5cuXOzS4kiA92xSwvNY4ZWQVhgA8I3KfqpeldL9+eFayTGu79M8/XFiy5PqDNJvh+0cgbqflechN8J/p8O++UzdH3UyjsEYAHEw8yHd7v7v+NnMx7OYYPN0tJc5nrIgl/qITExhPH+j4EgxdAuF1LMeMTPjrTZh+K5zZ67y2RURERKTIsTtxioqKIj095zSpzMxMIiMjc7lCrib7iFNeiVP2ESeP8KsnTiYvL8L/7/+sz0+98QZG2nUmGCvfhl0LLI+9S8E9c22q55lMJkY1GWV9PnXTVC6m27lZbT5UKO3H3U0tBS8upmXy0fLr2NcpvyIbwtA/oMNzlzfPPbEJprWFf6aDE9Z0iYiIiEjRY3fi9MYbb/DEE0+wbt0667F169YxfPhw3nzzTYcGVxLkpxx5uh0jTgABHTvi17Sp5dpDhzk3d27BAzy2wbLGBwAT/GcGhFTNcVr90PrcWulWAM6mnOWTLZ8UvM2rGHZzVbw8LN32s1WHiEtKvcYVDuDhBR2esWzsW7aa5VhGMvw8Cub2gwtxzo9BRERERFzK7sRp8ODBbNq0iebNm+Pt7Y23tzfNmzdnw4YN3H///ZQpU8b6JdeWn6p6GSeyFYe4xogTWEaAwp59BkyWaW1xH0wl49y5AgR3Eb4bCllrltqMhGp5b3I8svFIa4GLz3Z8xpHEI/a3eQ0RpXzp/2+FveT0TKb9WQijTlkiG8LDyy0V+LLs+RU+bAl7FxdeHCIiIiJS6PK9j1OWt99+2wlhlFzZE6e8quqln/p3qp6HBx4hZfN1X9/atSnVpw8J33+POTGRM1M/pNzzz9kX3KLn4ew+y+OIBtBhzFVPjwqMYlDtQfxv6/9IN6fz5ro3eeeWd+xrMx8euzmGL/85TEq6mc//PsRD7aoQHlRI+4p5+UHPKVCtC8wfBpfOwMU4mNPXklje/AK42/1jJSIiIiJFnN2/4Q0aNMgZcZRY+RtxskzV88xj89u8hI4YTuLChZZNcefOpXS/e/CuUiV/F+9bDOs/tTz29IO+/7NMWbuGB+s+yPx984lLjmPpkaWsPr6alpEt8x1zfoQF+nBfi0p88lcsqRlmpv6xj3G31XFoG9dUvSs8ttqSPO39zXJsxRQ4/Df0nQ6lyhduPCIiIiLiVHZP1csuJSWFxMREmy+xz7XWOJmTk8k8fx4Ajzw2v82LZ3g4ZR94wPIkI4NTr76Wv/Lk6cnw81OXn3d5DUKq5atNf09/RjQeYX3+33/+65Ty5I+0j8HPy5JEzl17hGPnkx3exjUFhEH/r6Dzq5cLRxxeDdPawN7fCz8eEREREXEauxOnixcv8vjjjxMWFoa/vz+lS5e2+RL72FTVc8uZOGWcyr6Hk32JE0DZB+7H899qhxdXrSJpcT7W4ix/E84dtDyu1AYaD7GrzZ5VelI3pC4A+87v4+s9X9t1fX6UDfBmUKtoANIyzbz9+x6Ht5EvJhO0egKG/ApBln2mSI6HOf+BxS9DpuOTRhEREREpfHYnTk8//TRLly7lww8/xNvbm//973+MGzeOyMhIPvvsM2fEeENLN199H6f0k9kKQxQgcXLz9SVszLPW56cmTsScfJXRmbjdsPLfdUlunpb1PP8Wmch3myY3nmn2jPX5B5s+4HzWxrkO9HC7KgT5WEZ6vt1wlN0nkxzeRr5FNYNH/oKbul0+tmIKzOoJCcdcF5eIiIiIOITdidNPP/3E1KlT6du3Lx4eHrRt25YXXniBCRMmMGfOHGfEeEPLyDYi4emeszhEeraKegUZcQII7NQJ/9atLe0dP8HZT/IoFW4YsGAkZCVzbUZA6E0FarN+aH16VukJQEJqAu9ufLdA97maYD8vHrvZUhrdbMCkhbsc3oZd/MpAv7nQ+TXbqXsftYNYbQ4tIiIiUpzZnTjFx8dT5d8CA0FBQcTHxwPQpk0bli/XL4f2yj7ilFtVvYxT2Uac8rGHU25MJhPhzz8Pnpb7n/3fdNIOH8554o4f4NBKy+PSlaHtUznPscPIxiPx8/AD4Js937Albst13S83g1tFE1HKUlFv6a7T/H3grMPbsIvJBK0ehyELoZRls14unYHPboOV72rDXBEREZFiyu7EqUqVKsTGxgJQo0YNvvrqK8AyEhUcHOzQ4EqCayVOjhhxAvCuUpmygwYCYKSlcWri67YnZKTB4nGXn3ebBJ6+BW4PIMwvjGENhlnaxODVv18l05x5Xfe8ko+nOyNvvTwq9vqvu/JXAMPZoppa9nyK6Wh5bpjh9xfh68GQ6sIphSIiIiJSIHYnTkOGDGHz5s0APPvss3zwwQf4+PgwcuRI/u///s/hAd7orpk4nTxx+fXrSJwAyj7yKB5hYQBc+OMPkv744/KL62bAOUtCTHRbqNb5utrK0r9mf24qbUlsdsbvZN7ueQ65b3Z9G1WgenggAJuOnOfXbSevcUUh8SsD934N7bL9XOz4AT7pCGf2uiwsEREREbGf3YnTyJEjefLJJwHo1KkTu3bt4osvvmDjxo0MHz7c4QHe6K45Ve/kv1X1PD1xL5u/zW/z4h7gT9jTT1ufn3rlVcyXLkHyefhz0uUTO79id0GIvHi4efBCixesz9/b+B5nks845N5Z3N1MPNOtuvX5G4t2k55pdmgbBebmDre8APfMBe8gy7Ezu+Hjm2HHj66NTURERETy7br2cQKoVKkSd9xxB/Xq1XNEPCWOTeKUW3GIf6vqeYaFYXK77m8XQT2649eyheXex48T9977sPJtSwltgLp3QmTD624nu4ZhDbm96u0AXEi/wJvr3nTo/QFurh5Gs8plAIg9c5Ev1+ayhsuVanSHh5ZBWC3L87Qk+Oo++H2sSpaLiIiIFAMeBbloyZIlLFmyhNOnT2M22/5lf8aMGQ4JrKRIz8x7xMl86RLmhASg4IUhrmQymYgYO5YDvW/DSEsj/rPPKHXqHD5BgLsX3PKiQ9q50sjGI1l6ZCkJqQn8fOBnbq96O80jmjvs/iaTiTHdanD71FUATP59D73rl6eUX85k1GXKxsCDi+HHJ2HbN5ZjK9+G4xvhP5+C//WNKIqIiIiI89g9hDFu3Dg6d+7MkiVLOHPmDOfOnbP5Evtcbape+slsm9+GOyZxAvCKjibk0UcsTzIzOfG3D4YZaPIAlK7ksHayK+1TmhGNRlifj189npSMFIe20bBiaXrXt2z2e+5SOu8sKYLriLz8oe//oOvrYHK3HIv9Ez7pACe3uTQ0EREREcmb3YnTtGnTmDlzJmvWrOGHH37g+++/t/kS+1wtccrIXhjCQSNOWco+8ABelaMBSIn34tz+UtDauWvU7qh2Bw1CGwBwOOkwH27+0OFtPNutBj6elm792eqD7Dt9weFtXDeTCVo8CoMXgL+lWAfnD8P0W2G7foZEREREiiK7E6e0tDRatWrljFhKJJupeu55jzh5lItwaLsmLy8i+lS1Po/bFkT6JccUhMiLm8mNl1u9bE0QZ22fxY6zOxzaRmSwLw+3iwEgw2zw2s+Ovb9DVWplWfeUtaYs/ZKlXPmS8WAuIsUtRERERAQoQOL04IMP8sUXXzgjlhLpqiNOp7MlTmGhjm04+Tx+8T8QXOUiAObUTE6Of8XpeyDFBMcwtN5QADKNTF5e9TIZZscWR3ikfYx1U9w/dsfxx+7TDr2/Q5UqD0N+hXr3XD7211vwZT9ISXBdXCIiIiJiw+7EKSUlhcmTJ9O+fXueeOIJRo0aZfMl9smeOHm42dbqyIi7XLbbI9TBidOajyA1kbAGibgHeAFwYelSEhf87Nh2cvFgnQepGmwZ7doZv5PPdnzm0Pv7ernzbLca1uevLthRdMqT58bTF26fBl0mgOnfH8k9C7Xfk4iIiEgRYnfitGXLFho0aICbmxvbtm1j48aN1q9NmzY5IcQbW1bi5GHywM1k++3IiIuzPvYIDXNgo8mw9iMA3L3dKPfc5Q1aT736KhlnHLvP0pU83T15udXLmLBMDZy6aSqHEg85tI3e9SNpXKk0APvjLjJ7tWPv73AmE7QcBgO+A59gy7Gze+GTW2DPby4NTUREREQKkDj98ccfeX4tXbrUGTHe0KyJk1vOyvC2iVOI4xrd+jVcOmt5XLsPQXcMILBbVwAyExI4OW6806fs1Q+tz7017wUgNTOVsavGYjYcNypkMpl4qWct6/Mpv+/hdJJjq/g5RczNtvs9pSbCF3dZpu85+XsiIiIiInmzO3H69NNPSU5OdkYsJVJW4pTb5rdZiZNbqVK4eXs7pkHDgL+zVbNrMQyAci++iHtpywhN0u+/k7RwoWPau4onGj5BpL+lfPj6U+v5Yqdj187VjwrmzsYVAEhKzWDCzzsden+nKVMZHvgdavb+94BhKRjxzRBIu+jS0ERERERKKrsTp2effZbw8HAeeOABVq1a5YyYSpSsqnpXFoYwDMOaODl0tCl2OZz+t9JchWZQobGljTJlKPfS5c1vT45/hYz4eMe1mws/Tz/Gtx5vff72hreJTYh1aBvPdqtBKV/LZ/vDpuOs2u/caYgO4x0Ad86Cm1+4fGz79zC9i6V0uYiIiIgUKrsTp2PHjjFr1izOnDlDhw4dqFGjBpMmTeLkyZPOiO+GZx1xuiJxMiclYaSmAg4uDGEz2vSIzUuBXbsS2LkzAJnnzhVKlb3mEc3pX6M/YJmy98LKFxxaZa9sgLdNoYgXf9hGWkYRLhSRnZsbtP8/uGcueAVajp3aiumTm/E6tsa1sYmIiIiUMHYnTh4eHtx+++3Mnz+fI0eOMHToUObMmUPFihXp3bs38+fPx6w9aPItK0nIUYr8jBMq6p3db6nWBhBUPttUMAuTyUS5l17EPTgYgKSFC0lcsMAxbV/FiMYjqBRUCYAtcVuYuX2mQ+9/d5MoGkQFA5ZCEZ/8dcCh93e6Gt1h6BIoY9mfypQcT+kFQ2Dtx1r3JCIiIlJI7E6csgsPD6dNmza0bNkSNzc3tm7dyqBBg4iJiWHZsmUOCvHGlteIU8bpbIUhQhyUOK39BPj3F+1mQyGXdVUeISGUG/uS9fnJ8a+Qfvy4Y9rPg6+HL6+2ftVaVfCDTR+w59weh93fzc3Eq33q4Pbv/r7vLd3LkfhLDrt/oQitDkOXQtVOAJiMTNwWPgPzH4f0YlD0QkRERKSYK1DidOrUKd58801q165Nhw4dSExMZMGCBcTGxnLs2DHuuusuBg0a5OhYb0h5FYewrajngMQpPQU2z/33hj7QKO/vT1C3bgT16gVYpgwef3YMhpNHERuENWBw7cGAZRTuub+eIy0zzWH3r1O+FANbRgOQkm5m3E/bnT4N0eF8g6H/Vxithl8+tulzmNkdEp2b3IqIiIiUdHYnTr169SIqKoqZM2cydOhQjh07xty5c+nUyfKXcH9/f5566imOHDni8GBvRHmOODk6cdr5E6SctzyudRv4lbnq6eVefAGPiAgALq1dS/ynM68/hmsY1mCYdWPc3ed2897G9xx6/6c630RYoKU64eKdp/l1WzFcl+fmjtHpZc53moLh4Ws5dmw9fNQeDv/t2thEREREbmB2J05hYWH8+eefbNu2jREjRlCmTM5fwENDQ4mNdWx1tBtRpjnTuneR0xOnDbMuP2408JqnuwcFEfn665aNWYG4t98mZffu64/jKrzcvZjYdqL1s5i5fSarjjuucmOgjycv9bq8t9NL87dx/pLjRrUKU0rV7hj3L4LgipYDF0/DzJ6wboZrAxMRERG5QdmdOE2fPp2WLVte9RyTyUSlSpUKHFRJkTXaBE4uDnF2Pxz8y/K4TAxUap2vy/ybN6PMkCEAGOnpHB/9f5j/rfTnLDXK1GBEoxHW5y+seIFzKeccdv8edSO4tVY4AGcupPHKgmKyt1NuytWFocugcjvLc3M6LBgJPw2HjOKZEIqIiIgUVflOnFavXs2CKyqsffbZZ1SuXJmwsDAeeughUp38S/WNxiZxutoap7DrTJw2zr78uNFA6yhSfoSOGI539eoApO7dy+lJk64vlnwYUGsArSJbARCXHMdLq15y2Hokk8lSKCLQxwOAbzcc5c89cde4qgjzLwsDvrduZAzA+pkwqyckFcOpiCIiIiJFVL4Tp/Hjx7N9+3br861bt/LAAw/QqVMnnn32WX766ScmTpzolCBvVFcdcfo3cTL5+uLm71/wRjLTYdMXlsduHtCgv12Xu3l5EfnGfzF5W9YGnftiLomLfit4PPlp0+TGa21eo4yPZRrosiPL+Gr3Vw67f3iQD893r2l9/tx3W7mQ6ri9owqduwd0nQC3f2Qp/AFwZA183AGOrndpaCIiIiI3inwnTps2baJjx47W519++SXNmzfnk08+YdSoUbz77rt89ZXjfrktCdIzr504eYSEYLJjhCiHvb/BhVOWx9W7QUCY3bfwuekmwp97zvr8xAsvkHb0WMFjyocQ3xDGtxpvff7GujfYe26vw+5/d9MoWlYpC8Cx88m8uci567cKRf174P6FEFTB8jzpBHzaFTZ+7tq4RERERG4A+U6czp07R3h4uPX5n3/+Sbdu3azPmzZtqkp6dsprxMmckoI5MRFwwPqmzV9efnyVEuTXEnzXnQR26wr8W6L8qacw0tOvcdX1aR/Vnnuq3wNAamYqo5aN4lK6Y/ZfMplMvN63Lj6elh+BWasPsjY23iH3dqnIhvDQssvr2DLTYP4w+OX/LKOPIiIiIlIg+U6cwsPDrZXy0tLS2LBhAy1atLC+npSUhKdnzg1VJW95JU4OKwyRkgB7Flke+4dClZsLfCuTyUTE+PF4RkUBkLx5M3HvvFPw2PJpdNPR1ChTA4CDiQcZt3qcw9Y7VSrrz+jOlvVbhgFPfb2peE/ZyxIQCgPnQ9Ohl4+t/Rg+uw0uFOP1XCIiIiIulO/EqXv37jz77LP89ddfjBkzBj8/P9q2bWt9fcuWLcTExDglyBtVnomTo0qR7/gRMv8t2FH7DstamOvgHhhI+clvwb8J8tn/TefCn39e1z2vxdvdm7fav4W/p2Wd1y+xv/DN3m8cdv8hrSvTNLo0AEfik3nt5x0Ou7dLuXtCjzeh93vg7mU5dmilZd3T8Y0uDU1ERESkOMp34vTKK6/g4eFB+/bt+eSTT/jkk0/w8vKyvj5jxgw6d+7slCBvVNkTJ49sSY3DEqetX19+XO+ugt8nG9+6dQkbNcr6/NjTz5B29KhD7p2XikEVGddqnPX562teZ+dZx5QRd3cz8dadDfD3cgdg7tojLNl5yiH3LhIaDYTBv0BAOcvzxKMwoytsnufauERERESKmXwnTiEhISxfvpxz585x7tw5br/9dpvXv/76a8aOHevwAG9keRWHcEjilHgCYpdbHpeuDOUbF+w+uSgzeBAB/xYKMSckcOzJ4U7f36lLdBf617BUBEwzp/HUn0+RlJbkkHtXLOvHiz0vb4z7zLdbib94A+2DFNUUHv4TKjSzPM9Ige8fgkXPQ+YNMDVRREREpBDYvQFuqVKlcHd3z3G8TJkyNiNQcm1Onaq3/Tvg37VA9e6ya++mazGZTES+PhHPShUBSNmxg5OvvOKw++flqSZPUadsHQCOJB3huRXPYTbMDrn33U2juKWGpeLgmQupPP/9VoetpSoSAsvB4AW2BUJWvw+f3wEXz7ouLhEREZFiwu7ESRwnfyNOIQW7+ZZspeHr3lmwe1yFe2AgFd59D5OPZd+ghG++5fw3jlt7lBsvdy/eaP8GQV5BgGV/p4+2fOSQe2dV2SvtZ/k+/LrtJN9tcG7J9ULn4Q2934WeUyx7egHE/gkftdN+TyIiIiLXoMTJhZw24nRmH5zYZHkc0YD/b+++46Oo1sePf2Z7eq8khN57R+wgoIgVC1eBi10RC/d+r+VnuXrteu2KvV4pir2hiIigCAgiRTohoaX3snXm98ckm4TUhYTdwPN+vea1s2dmzpzgcbNPzpnnENv9CFvYNFvPHiT9p2atpawH/0Pl5i1NXHH0UsJSeOLUJ1DQR9Be3vAyy/e1ToKK+DAbD1/Y3/v+3s83k55X3ip1B5RhV8GMryCkak2vkv36ek9r39TTCwohhBBCiHokcPKjOoGTsYF05CYTxqgo3yv+67Oa/TYYbaotYvJkov6mP3ukOZ3sv/nmOunU28KYDmO4Zcgt3vd3rriT9OL0Vqn7nP5JXDJUX0C2wulh9vz1ONyeVqk7oKSNhut/htSqJQU8Tvh6Dnx2IzhbZ60sIYQQQojjiQROftTciJMpJgbFcAT/ibZ+WbPf57wjbl9LJdx5B0GDBgHgzspi/82zUZ1tm1zh6n5Xc1baWQCUucq4ddmtlDnLWqXuB87vS5c4Pf355gMlPLF4e6vUG3DCk/TnnkbdVFP253x48ywo2OO/dgkhhBBCBCAJnPyoocBJ83jw5BcARzhNryiz7jS9yI5H2crmKRYLKS88jylRT3lduWEDWff/u02TKyiKwkNjHqJbZDcA0ovTuWvlXXjUox8dCraYeGHqYCxG/X+PN1ems2xbzlHXG5CMZpj4KEx5C6rWyiJ7M7x6Omz/1q9NE0IIIYQIJBI4+VFDySHc+fmg6pnijihwqj3a1HvyUbXPF6a4OFJeerEmWcSnn1Lw7rttes9gczDPnfEcYZYwQE8W8dz651ql7r7JEdx9Ti/v+3989CfZJfZWqTsg9bsYrv0RYqqeh3MUw/zLYemD0ArBqBBCCCFEeyeBkx81NOJ01Ikh6gRObT9Nr7agvn1JfuRh7/ucJ56kbMXKNr1nx/COPHXaUxgVPUX+21ve5pOdn7RK3TNO6sS43gkAFJQ7uWX+H7g9rZP+PCDF99KDpz7n15St+G9VyvK2fW5NCCGEECLQSeDkR7UDJ1NVemhPQUFNWWyMbxWWZkPmb/p+bE+I63HUbfRV+DnnEHPjDfobVeXA7bdj37GjTe95UvJJ3D3ybu/7/6z6D2uz1h51vYqi8OSUASSG66Noq9MLePK74/R5p2q2cLjkXRj/MFQFo+z5SU9Znrnar00TQgghhPAnCZz8qKGseu78msVIjdE+Bk7bv8a76O0xnKZ3uLjZswkdNxYAtayMfdffgCu7bZ8RurTnpVzZ+0oA3Jqb25bdRkZJxlHXGxVi4aUrBmMy6OnPX/15D4s3HzrqegOaosBJN8OMLyFUH3Gj5AC8fTasfNY7lVQIIYQQ4kQigZMfNfSMU3ViCABTTLRvFfrp+abDKQYDHZ54Alu/fgC4Dx1i/403opa37ZpI/xz2T07ucDIAJc4SZi2dRaG98KjrHZoWzf+b1LvmPh9tZE9u62TwC2idxugpy9PG6O81D/xwP8y7FMrzm75WCCGEEOI4I4GTHzX0jJOnsCZwMkb5EDhVFkH6z/p+REdIGtgaTTxihuBgUue+jDk5GQD7X39xYM4/0NzuNrun0WDkyVOf9GbayyjJ4OalN1Pprjzquv9+UifOG6j/LGUONzf+bz0Vzrb7WQJGWCJM/wJO/T+oWnSYXUvglZMh41e/Nk0IIYQQ4liSwMmPagdOFqMFAPeRjjjtXgpq1Rf5XpP06VZ+ZoqLI/W1VzGE6VnvypYvJ/uRR9o0TXmoJZSXx75MXJCeWGNj3kb+9fO/cKtHF+QoisKjF/Wne3woANuzS7nz401t+rMEDKMJzrwHpn0CwbF6WelBeOdcPXmETN0TQgghxAlAAic/anDEqVZyCGO0D4HTziU1+z0mHHXbWou1WzdSXngezPrPVzhvPvmvvNKm90wKTWLuuLmEVK1L9NO+n3h49cNHHeSEWE28Mm0oIRY9acIXfx7k1Z9PoIViu54JN/4CnU7R32sePV35B1OgLLfpa4UQQggh2rmACJxeeuklOnXqhM1mY+TIkaxZs6bRc19//XVOOeUUoqKiiIqKYty4cU2eH8gaXMepOnBSFIyRkS2rSFVrAidzCKSd1IqtPHoho0aR9J8Hve9zn3uewvnz2/SePaN78uwZz3qzFS7asYjXNr521PV2jQvlv5cO8r5/fPE2lm7NPup6242wRJj+OZx2J96pe7uX6lP39rZt6nkhhBBCCH/ye+C0cOFC5syZw/3338/69esZOHAgEyZMICen4SxsP/30E1OnTmXZsmWsWrWK1NRUxo8fz4EDB45xy49eUyNOxshIFKOxZRUdXA8VVevsdD0DTNZWbWdriLzgAuL/9S/v+6wH/0Px11+36T1HJY3ioTEPed+/uOFFPtz+4VHXO7FfIreP01O9axrcumADO7JLj7redsNghDPugumfQUi8XlaWBe9OhuVPyIK5QgghhDgu+T1wevrpp7n22muZOXMmffr04ZVXXiE4OJi33nqrwfM/+OADbrrpJgYNGkSvXr144403UFWVpUuXHuOWH70GF8CtDpx8eb5p5/c1+93Ht0rb2kLMVTOJufZa/Y2mcfCOOylbsaJN7zmpyyTmDJ3jff/Qbw/x5e4vm7iiZW4Z241J/ZMAPVnENe/+TmG586jrbVe6nA43rITOp+nvNRWWPaw/+1S0z69NE0IIIYRobSZ/3tzpdLJu3Truuusub5nBYGDcuHGsWrWqRXVUVFTgcrmIbuR5IIfDgcPh8L4vKSkBQFVVVD8/1F57qp5RMeIuK0Or1DPAGaOiW9w+Zcd31ZOmULuNC+iH9WNuuxV3USHFHy0Ct5v9s28h9c03CBo8uM3uOb33dArthby95W00NO795V5sRhtjO449qnqfuLg/e/PL2XKwhMyCCm76YB1v/304FlPb/j1CVVU0TfN7/wUgJA6u+BhWPo2y/DEUTYXMX9HmnoR27jPQ9yJ/t1AQYH1GtAvSZ4SvpM8IXwVKn/Hl/n4NnPLy8vB4PCQkJNQpT0hIYNu2bS2q44477iA5OZlx48Y1ePzRRx/lgQceqFeem5uL3W73vdGtqKyyZi2g4oJiTMU1aw65Q4Ibna5Ym6E8h/hDGwBwxfQmv9IIlW272OzRUm64AXNOLq7ly9HsdvZdfwOhzz2LqWvXNrvn1A5TySvJ48t9X+LRPNzx8x08OORBhsUOO6p6Hzk7jZnzt1JQ4WbVngL+seB37jkrDaUNsxqqqkpxcTGapmEw+H3QWNdrBuaIvkQu/T+MZQdRHCUoH19N5aYvKTn5XjRLqL9beEILyD4jApr0GeEr6TPCV4HSZ0pLW/64hV8Dp6P12GOPsWDBAn766SdsNluD59x1113MmVMzVaukpITU1FTi4uIIDw8/Vk1tkMFc00kS4xMJKT1ESdX7kKQk4uPjm6/kj5ppeqbe57TsmgCgPvcsB268iYpVq9DKyqj41x2kvv0W1m7d2uyeD8Y/CL/Cl3u+xKW5eGDDA8wdN5ch8UOOuM74eHhtegh/e2MNTrfK13/l0y0pilvHdm/FltelqiqKohAXFxdYv5ziz4GeY9C++QfK5o8BCNrxGbbcDWgXvg4pRxekiiMXsH1GBCzpM8JX0meErwKlzzQWQzTEr4FTbGwsRqOR7Oy6Wcmys7NJTExs8tqnnnqKxx57jB9++IEBAwY0ep7VasVqrZ8swWAw+P1/7NprC1lNVtTCmhEnU0xsy9q3qyYNudJzIko7+bAy2GykvvgCGTOvwr5xI578fPbNvIq0d99ps+DJgIEHxzxIpbuSHzJ/wO6xM/vH2bwx/g36xvY94nqHdYrhucsGcdO89WgaPLd0FylRwVwyLLUVW1+XoigB0YfrCY6Ci9/Un7X7+p/gLEUp3Ivy9kQ4/S44ZY6eXEIccwHbZ0TAkj4jfCV9RvgqEPqML/f2a8+2WCwMHTq0TmKH6kQPo0ePbvS6J554gv/85z8sXryYYcPa71+xD08O4fF18VuPG/b8pO8HRUOHoa3cwrZlCAmh4+uvYeurBy2e/Hwy/j4Tx562WxvJZDDx+KmPM6bDGADKXGVcu+RatuRtOap6z+6fxP87p7f3/V2fbGLFzhN0bSNFgYGXww0rIGW4XqZ5YNlD8M4kKMzwb/uEEEIIIY6A3/8kMGfOHF5//XXeffddtm7dyo033kh5eTkzZ84EYPr06XWSRzz++OPce++9vPXWW3Tq1ImsrCyysrIoKytr7BYBq17gVFhr8duoFgROB9eDo2pyX5fT2+Vf8o0REXR8601sffoA4MnLI2PGDBx70tvsnhajhWdOf4ahCXqgWeos5drvr2Vj7sajqvfqkzvz95M6AeBWNW7833q2HCw+2ua2X9GdYeZiOO0OUKo+ajJXwdyTYN27ei53IYQQQoh2wu+B02WXXcZTTz3Ffffdx6BBg9iwYQOLFy/2JozIzMzk0KFD3vPnzp2L0+lkypQpJCUlebennnrKXz/CEavOqmfAgNFgxO3riFP1aBPo6ze1U9XBk7WPPmLjyc0jc8YMHOltFzwFmYJ4eezLNcGTq5TrllzHhpwNR1ynoijce24fxvfR+26Zw82Mt9aQnlfeGk1un4wmOONu+Ps3ENFRL3OWwZe3wLxLoeRQ09cLIYQQQgQIvwdOADfffDMZGRk4HA5Wr17NyJEjvcd++ukn3nnnHe/7vXv3omlave3f//73sW/4UXKq+ro/JoP+qFn14rcAxkbSq9dRO3DqcnortuzYM0ZGkvbWW1h768GTOzeXzBl/b9Npe8HmYF4e+zIjE/X+Vu4q5/ol17Mue90R12k0KDx3+WCGdIwEIK/MyZVvrOZQcWVrNLn9ShsNN66EwVfWlO38Hl4eBZsWyeiTEEIIIQJeQAROJ6rqqXrVgZPbl8DJUQb71uj70V0gsmObtPFYMkZG6iNPvXoB4M7JIePKadj/+qvN7hlsDuaFsS8wOkl/pq7CXcGNP9zI2qy1R1xnkMXI238fQa/EMAAOFFUy7c01FJxoC+QezhYB578EUxdCaNUSBPYi+Phq+OjvUJ7vz9YJIYQQQjRJAic/qp6qZ1bMQK0RJ6MRY0RE0xdnroLqZ6Ta+WhTbaaoKDq+XTPy5CkoIGP6DCrWHfkoUHOCTEG8MPYFb8KISnclN/1wE78c+OWI64wINvPeVSNIiwkGYFdOGTPfXkOZw93MlSeAnhPhpt/qLo7712fw8kjY9o3fmiWEEEII0RQJnPyosREnY1RU82nF60zTa7/PNzXEFBVF2rvvEDREX19JLSsj8+prKFuxos3uaTVaef6M5zkt5TQA7B47N/94M9/sOfIv8vHhNv539Ujiw/R0+H/uL+aqd9ZS4ZTgieBouORtmPIWBEXpZeW5sGAqfHojVBQ0fb0QQgghxDEmgZMfaejPdZgNZjRN8444maKimr/YGzgp0PmUtmmgHxnDw+n4xuuEjNFHgTS7nX03zaJk8eI2u2d1tr2z0s4C9HW27lxxJx9s/eCI60yNDuZ/14wkMlgfVVyTXsDV7/xOpdPTKm1u9/pdDDethh4Ta8r+nAcvjYQtn8mzT0IIIYQIGBI4+dHSS5ay4coNvHXyW2gVFWgOBwDGmJimLyzLgezN+n7y4Jq/2B9nDMHBpMx9mbDx4/UCl4sDc/5B0aJFbXZPs9HMk6c+yZQeUwA9uH1szWO88McLaEf4Jb5HQhjvXzWSMJs+srhqTz7XvLcWu0uCJwDCEmDqAjjvRbCG62XlOfDRDFh4pWTeE0IIIURAkMDJzxRFwWww10kMYYpuJhBK/7lm/zh6vqkhBouFDk//l4iLqp6HUVUO3XMvuS++dMSBTHOMBiP3jbqP6wZc5y17beNrPPjbg3jUIwt2+qdE8P7VIwmz6sHTL7vyufa93yV4qqYoMGQazFoNPc+pKd/2lT76JOs+CSGEEMLPJHAKEHVTkTcz4rRnWc3+cR44ASgmE0kP/YfoGTO8ZXkvvsihu/8fmrNtMtUpisLswbO5c8Sd3rJFOxbxz+X/xO62H1Gdg1IjeffqEYRWBU8rduZx7Xsyba+O8GS4fB5MeRtC4vQyR7G+7tO7kyF/t3/bJ4QQQogTlgROAcKTX5OK2djsiFNVkgSjFVJHNn3ucUIxGIi/8w7i//Uvb1nxp5+y74Yb8JSWttl9r+h9BY+d8hgmRQ92fsj8gau+u4q8yrwjqm9IxyjevWo4IRYjoAdPMyTbXl2KAv0ugllrYODUmvK9K2DuSfDLc+CRfy8hhBBCHFsSOAUId2Ghd9/U1IhT8X4oytD3U0eA2dbGLQsciqIQc9VMOjz7LIrFAkD5r6vI+NsVuA613XMwk7pM4oWxLxBs0lOLb8rbxN++/hs7C3ceUX1D06J596qakac16QVc8cZqiitcrdbm40JwNFz4Clz5MUSk6mVuOyy5D147DTJX+7d9QgghhDihSOAUIDz5tabqxTSx+G3Gqpr9tJPasEWBK3ziBDq+8zbGyEgAHDt3sveyy9t0odyTO5zMe2e/R0KwvnDrofJDTPt2GisPrDyi+oZ1imbetTXZ9v7cV8Tlr/9GXpmj1dp83Og2Tl/3aeQNgKKXZW+Gt8bDF7MldbkQQgghjgkJnAKEp7B2coimAqdai7KeoIETQPCQIXRaMB9zx44AuHNy2Pu3Kyj5pu0WUO0Z3ZP5k+bTJ6YPAOWucmYtncWCbQuOqL4BKZEsuG4UsaH6Ok9bD5Vw6aur2F9Y0WptPm5YQ+Hsx+HqJZDQv6Z8/XvwwlBY/z6oqv/aJ4QQQojjngROAcJde8SpJYGTwQQpw9u4VYHN0qkTnRbMJ2jQIEBf6+nAnH+Q8/QzaJ62SbgQFxzH2xPeZmzHsQComsrDqx/m4d8exuXxfapdr8RwPrx+FEkR+pTLPbnlXDz3V7ZllbRqu48bqcPhup9g4uNgCdPLKgvgi5vh7YmQtdmvzRNCCCHE8UsCpwDRohGnslzI26HvJw8GS8gxaFlgM0VH0/Hdd4i48EJvWf5rr7H/plltljQi2BzM06c/zcx+M71lC7Yv4JrvrzmipBFd4kL58PrRdInV/3tmlzi45JVV/LYnv5krT1BGE4y6AW5eqy+gW23fanj1VFh8NzjaLmGIEEIIIU5MEjgFCO8zTiYThvDwhk/K/LVm/wSepnc4g9VK0iMPk3D33WDUs9WVLV/O3ksvw7EnvW3uqRiYM3QOD570IGaD/pzS+pz1XPrlpWzI2eBzfanRwXx0w2gGpkYCUGp3M/3NNXyzSRZ/bVR4Ekx5C6Z9BjHd9DLNA7+9pE/f++MDmb4nhBBCiFYjgVOA8FRl1TNFRaEoSsMnZdQOnE4+Bq1qPxRFIXr6NDq+8TrGiAgAnOnp7L30UkqWLGmz+17Y/ULenfiuN2lEbmUuM7+bycJtC31eoDcm1Mr8a0dyek99/SKnR2XWvPW89vPuNlvs97jQ9Qy48Vc48x4wVWWZLMuGz2+CN86U7HtCCCGEaBUSOAUATdNwV63jZIxpIhW5NzGEAh1PjPWbfBUyejSdFn2EtUcPANSyMg7MvoXsRx9ts8Vy+8f1Z+G5CxmWMAwAt+rmodUPcd+v9/m8WG6wxcTr04cxZWgKAJoGj3yzjTs+3ojTLaMnjTJZ4dT/07Pv9Tq3pvzgH3r2vUVX66n8hRBCCCGOkAROgaC8HNz6gp6mxha/rSyqefA9sT/YIo5N29ohS2oqnebPI+zsid6ygnffY++0abgOHGiTe8YExfDa+NeY1meat+yzXZ8x9eup7C7a7VNdZqOBJ6cM4Nax3b1lH/6+n2lvrqawvG2Cv+NGdGe4/AOY/jnE96kp37wIXhgGyx4Fp2QtFEIIIYTvJHAKAGpJTQa16rWJ6tm3GqiarpU2ps3b1N4ZQkLo8PTTJNx3L4pZfwbJ/udG9lx0MaXLlrXJPc0GM/8a/i8eP+VxbEZ9ytiuol1c/tXlfLrzU5+m2ymKwu1n9eD5qYOxmPT/TVenF3DBy7+wO6esTdp/XOlyOly/Aib9F4Kqkq24K2H5Y/DiMNj4oTz/JIQQQgifSOAUALSWBE6yfpPPFEUh+m9/I23+fMwp+tQ3tbiY/TfeRPYTT6K20dS9c7qcw/xJ8+kWqScssHvs3Pfrfdy54k7KnL4FPecNTGZhrbWeMvIruOiVVazOkHTlzTKaYPg1cMt6GHWTnsIfoOQAfHItvH4G7PnJr00UQgghRPshgVMA0IpbMuK0pma/46i2bdBxJqhfXzp/8jFhZ43zlhW89RZ7L7scx65dbXLPblHdmDdpHlN6TPGWfZP+DZd+dSlb8rb4VNfgjlF8cfMYeifp2RZL7W5u/2wnL/20G1WVpBHNCoqCiY/Cjaug+/ia8kMb4L3z4f0L4dCffmueEEIIIdoHCZwCgFbaTODkduoPuQNEdYLQ+GPSruOJMTycDs8/T8Jdd0LV1D3H1q2kXzyFgvf/1yZZ64JMQdw/+n6ePO1JQs2hAOwr3ceV31zJq3++ilt1t7iu5MggFt0wmrP66Nn7VA3++/0Orn3vd4orfF9494QU1wOu+Aiu/BgS+tWU7/5RX//p42ugoG3S1wshhBCi/ZPAKQDUecYpooGkD9mboDo7W8qIY9Sq44+iKETPmEHnDxdi6dYVAM3hIPvhh9l37XW4snPa5L4TO03kw8kf0i9G/7Lu1ty8uOFFpn87nfTiln9RD7GaePXKodw+rjvVCeuXbsvh3BdXsPlAcRu0/DjVbZz+/NOFr0FEx5ryTR/Bi8Ph2zug3PeFjIUQQghxfJPAKQA0O1Vv39qa/VQJnI6WrXdvOi9aRNT0mgx45StXkn7eeZR8+22bjD6lhqXy3tnvcd2A6zAo+v92m/I2ccmXl/DB1g9QtZYlKjAYFGaf2Y1nL+xOVLA+cravoJKL5v7Kh2v3tXq7j1sGAwy8DGb/DhMerUkgobpg9Svw3CA9A19lkT9bKYQQQogAIoFTAGh2qt7+Ws83pQxv+wadAAw2G4l3303qG29gitMXnPUUF3Pg9jnsnz0bV07rjz6ZjWZmD57Ne2e/R1p4GgAOj4PH1jzGdd9fx4GylqdKH5kWzhc3j2FgaiQATrfKvz7eyJyFGyi1y9S9FjNZYfRNcOsGOOWfYArSy52lega+5wbA8ifALsk4hBBCiBOdBE4BQGtuql71iJM5uO6zGeKohZ48hs5ffE7YhAnesrIflrLn3MkUfeJbCvGWGhg3kI8mf8Tfev3NW7Y6azUXfn4h7//1Ph7V06J6OkQG8eH1o5g2Ks1b9skfB5j0/ErWZxa2eruPa7YIGHuvHkANuwoUo15uL4ZlD8Oz/eHnJ8FR6tdmCiGEEMJ/JHAKAGpTU/VKs6A4U99PHqKnWBatyhQVRcpzz9Lh2WcxxsQA+nNnh+6+W3/2qQ0WzQ0yBXHXyLt4ffzrJATrCR8q3ZU8sfYJrvzmSrYXbG9RPVaTkf9c0I/nLh9EqFXvG5kFFVzyyiqeX7oTj2Td801YIpz7DMxeB4OurBVAFcGPD+kB1Ir/SgAlhBBCnIAkcAoA3hEngwFDeHjdg7XTkKfKNL22FD5xAl2++pLw8yZ7y8pXrmT35PPIf+ttNFfrT4EblTSKT8//lMt6XuYt25y/mcu/upzn1j+HvTopSDPOH9SBb289hSEdIwHwqBpPL9nB5a+tYn9hRau3+7gX3RkueAluXgsD/wZVz6VRWQhLH4RnB8DKZ2QKnxBCCHECkcApAGil+l+vjeHhKIbD/pPUeb5JEkO0NVNUFB2eeILUV1/BlJgIgFZRQc4TT5B+0cVUrFvX6vcMs4Rxz6h7eHfiu3SO6Azomffe2PQGF39xMSsPrGxRPanRwXx4/WhuG9cdQ1XavbV7Czn72RUsXJvZJtMOj3sxXeHCuXDz7zDg8loBVAH88G94th8s/Q+U5fq1mUIIIYRoexI4BQCtWE8l3eTzTSCJIY6h0NNOo8uXXxD1t6mg6FGIY+dOMq64koN33Y07P7/V7zkkYQiLJi/ixoE3YjJUTbsrzeTGH27klh9vYX/p/mbrMBkN3DauBx/dMJqUKD3RQanDzR0fb2L6W2tk9OlIxXSFi16FWWug/yVQnRDeXgwrntKn8H3zf1CY4ddmCiGEEKLtSODkZ5rbjVZeDjTwfFOdhW87Q2jcsW3cCc4YFkbifffR6cOF2PrVJOUo/vRTdp99DgUffIDmbvkiti1hMVq4adBNLJq8iCHxQ7zly/Yt44LPL+DlDS+3aPre0LRovrn1FC4ekuItW7EzjwnP/Mz7v2WgyrNPRya2O1z8hh5ADboSqgJc3JWw5jV4fjB8cj3kbPVvO4UQQgjR6iRw8jNPSROJIbI2gceh78v6TX4T1L8/nRYuIPH++zCEhQF68ojs/zzEngsuoGzFila/Z9fIrrwz8R0eOfkRYoNiAT11+dw/53LhFxeyIntFs1Pvwm1m/nvpQN6eOZykCBsA5U4P9362mSveWE1Gfnmrt/uEEddDfwbq1j9h1Cw94yWA5oGNC+DlUTB/KmSsApkiKYQQQhwXJHDyM09RkXffGHnYVL39Mk0vUChGI1FTp9L122+IOP98b7lz1272XXsdmddeh2PXrta9p6IwuetkvrzgS2b0mYFJ0Uc3DpYf5MEND/L37/7OxtyNzdZzRs94vrv9VC4fnuotW7Unn/HP/MwLS3ficLcs/bloQEQKTHwEbt8Cp98FQVE1x7Z/A29PhNdOhz8X6iPIQgghhGi3JHDys7qBU2Tdg9XT9AA6DD0m7RFNM8XGkvz4Y3RaMJ+ggQO95eUrVrDn/As49MADuPPyWvWeoZZQ/jn8nyw6bxEjk0Z6yzfkbuCKb67gn8v/yb7SfU3WEW4z89jFA3j/6hF0iNSffXK4Vf67ZAcTn13Bip2S3OCoBEfD6XfqAdTExyC8Q82xQxvg0+v056CWPwnlrds/hBBCCHFsSODkZ2pVYghoKHBar78azJDQ99g1SjQraNAg0hbMJ/mppzAlJ+mFHg9F8xewa/wEcp57Dk9p66710zWyK6+f9TrPnv4sqSE1o0ff7f2O8z47jyfWPkGRvajJOk7pHsd3t5/KNSd3xliVei89r5xpb67h5nnryS5pWfpz0QhLCIy6EW7ZABe+Ckk1wTVlWbDsIXi6D3x+M2Rv8VszhRBCCOE7CZz8rPaIk6F2Vj17CeTt1PcT+oLJemwbJpqlKAoR506i6zffEHfbbRiC9edctIoK8ue+wu5xZ5H/5puo9tYLRhRF4YzUM3jtpNf4fyP+H9G2aADcqpv3/3qfiZ9M5MU/XqTE2fj6QqFWE/ec24evZp/MsLSaqWVfbTzE2P8uZ+5Pu7G7ZPreUTFZYODlcN1ymLkYep9Xk8rc44A/3oe5J8G7k+Gvz8HT+muECSGEEKJ1SeDkZ56imhEnU+0Rp6yNQNVD5R2GIAKXwWYj9obr6frdYqKuuALMZgA8xcXkPPkUu8dPoHD+fFRn6z3jYjKYuLTnpXx94ddc2/9abMaq5A+ucl7d+CoTP57Iaxtfo9zVeAKI3knhfHj9aJ6cMoDoEAsAZQ43jy/extj/LufLPw/K2k9HS1EgbTRc9r4+CjX6ZrDWWuQ6/Wf4cDo80xd+fAiKmp5yKYQQQgj/kcDJzzyNTdU7sL5mP3nwsWuQOGKmuDgS772nJoFE1fpP7pwcsh54kN3jJ1Dwvw9QHY5Wu2eoJZRbhtzCVxd+xWU9L/Ou/1TqLOWFP17g7I/P5u3NbzcaQBkMCpcMS+XHf5zGFSM7ehfOPVBUyez5f3DR3F9Zl1HYau09oUWlwYSHYc5fcPaTEN2l5lhZNvz8JDw3AOZdBju+A1VG/YQQQohAIoGTnzWaHKJ2YggJnNoVS0oKyY8/RpcvPid03FhvuTsri+yHHtKn8L3zDmplZavdMyEkgXtG3cOXF3zJBd0uwKgYASh0FPL0uqcZv2g8L214qdFnoCKDLTx8YX++ufUUTuke6y3/I7OIi+f+yqx569mTW9Zq7T2hWcNg5HVw8zqY9hn0ngxV/73QVNixGOZdCs8N1JNJlBzya3OFEEIIoVO0E2wuTklJCRERERQXFxMeHt78BW1s3y23Uvb99wB0W/oD5g5V2bieGwSF6WCywV0HwGjyXyPFUanctIm8ua9Q9uOPdcqN0dFEz5hB1OWXYYyIaOTq+lRVJScnh/j4eAyGhv/2sbd4L3P/nMu36d+iUfO/eJApiCk9pjCjzwwSQhIavFbTNH7akcsjX29lZ05NsGQ0KFw8pAO3jO1OSlRwi9srWqDkkP7c07p3oORA3WOKAbqeCYOugJ7ngNnmc/Ut6TNC1CZ9RvhK+ozwVaD0GV9iAwmc/CxjxgwqVq8BoOe63zGEhEBlITzeST8hZQRcs8R/DRStxr51K3lzX6G0KlCupgQHE3nRRUTPmI4lNbWRq2v48kGzp2gPb25+k6/3fI1Hq5n6ZTKYOL/r+czsN5O08LQGr3V7VBas3cczS3aQX17zfJbZqDB1REduPqMb8eG+f4kXTfC4YdcS+P0t2LkEOOzj2RYJ/afAoL9B8hDvdNDmBMovJ9F+SJ8RvpI+I3wVKH1GAqcmBFrgtOf8C3Bs345iNtNz458oigK7f4T3L9RPGHE9nPOEfxspWpV9xw7yX3mVksWLQVVrDhgMhI0fT8zMv9dZI+pwR/JBc7DsIO9seYdPdn6Cw1PzjJWCwmkpp3FFnysYmThS73+HKXe4efuXdF79eQ+ldre33GY2cMXINK47tQsJEkC1vsIM+ON/8OcCKM6sfzyutx5ADbgMwhoePawWKL+cRPshfUb4SvqM8FWg9BkJnJoQaIHTztPPwJ2VhTE2lh4rV+iFK/4LSx/U9y98VU9rLI47zsxMCt59j6JPPkE77HmnoKFDiZ4+nbCxZ6KY6k7TPJoPmrzKPD7Y+gELti2gzFX3maVukd24ovcVTOoyiSBTUL1riytcvL5iD2/9kk6Fs2b0ymI0MGVYCjec2pWOMTKFr9WpKuxdARvm6anL3Yc9G6cYoPOp0G+K/rxUUGQDVQTGLyfRfkifEb6SPiN8FSh9RgKnJgRa4LRt0GA0ux1Lt250/epLvXDhlbC1an/WGojr6b8GijbnLiykaOFCCv73AZ68vDrHTPHxRF56KZGXXII5IR5onQ+aUmcpC7cvZP62+eRU5NQ5FmGN4OLuFzO111QSQxLrXZtX5mDuT7v5328ZONw1I2ZGg8J5A5O58fSu9EgIO6J2iWbYS+Cvz/QgKnNV/eNGC3QfD/0uhh4TwaIHsoHyy0m0H9JnhK+kzwhfBUqfkcCpCYEUOKl2O9sH6RnzgoYNo9P/3tcPPN0XSvaDJRTuzASD0Y+tFMeK6nBQ8tVX5L/1Ns7du+seNBoJGzeOqKlTsQ0fRm5ubqt80LhUF0szl/LBXx+wIXdDnWMGxcCpHU5lSo8pjOkwxpvqvFpuqYM3V6bzv98yKHO46xw7o2ccV5/chTHdYhqc/idaQf5u+HM+bPoICvfWP24J1ZNJ9J+C2vk0cvKL/P7LSbQfgfKFRrQf0meErwKlz0jg1IRACpxc2dnsOu10AELHjSP1xRegLAee6q6fkHYyzPzafw0UfqGpKuW/rqJwwXzKflxW9zkowNKlC8azJ5I8dSqW2NhGavHdlrwt/G/r/1i8dzFutW4gFB8cz4XdLuSi7heRHJpc51hxhYt3V+3lrV/SKapw1TnWKzGMq07uzPmDkrGa5A8AbULT4MA62LQItnyirwl1+CnWcOwdT8c6+BIM3cZ5R6KEaEygfKER7Yf0GeGrQOkzEjg1IZACJ/v27aSffwEAERdfTPLDD+mZtD6Yop8w+mZ9wUxxwnIdOkThhx9S9NGietP4MJkIPf00Ii+6iNBTTkExm1vlnrkVuXy04yM+3vlxvWl8CgondTiJKd2ncFrKaZiNNfcsd7iZvyaTt3/Zy4Gius/hxIZauGJkGpePSCUpov7zU6KVqB7YuxI2L9Kfh7IX1z/HHAzdxkHv86DHeLC1PBW+OHEEyhca0X5InxG+CpQ+I4FTEwIpcCpfvYbMGTMAiL76KhL+7//qJoa46HUYcKkfWygCheZ0Urp0KYXz5lOxdm2948aYGCImTybiogux9ejRKvd0q25+OfALi3Yu4uf9P6NqdUe+IqwRTOw0kXO7nMvAuIHeKXluj8riLVm8uTKdPzKL6lxjUODMXglcMaojp3aPw2iQaXxtxu2E3Uth8ydoOxajOErqn2O0QJfTodck6D4BwpOOeTNFYAqULzSi/ZA+I3wVKH1GAqcmBFLgVPLd9xy49VYAYv8xh7hrr4WP/g5bPtVPuOk3iO/tvwaKgFS5axeHPpiH+4cf8OTm1jtu7dObiEmTCD/7bMzJyQ3U4Lvs8mw+2/UZn+z8hIPlB+sdTwlN4dyu53Jul3PrrAu1PrOQN1em8+2mQ6iHfdJ0iAxi6ohULh2WKutBtTHVZafojy+IylqJsu1rqMhr+MSkQXpSiR4T9H358nPCCpQvNKL9kD4jfBUofUYCpyYEUuBUuPBDsu6/H4CEBx8g+tJL4YWhkL8LjFa4+yAYTc3UIk401R80cdHRVP72G0WffErZ0qVoLle9c4MGDyZ80iTCJ07A1ArPQ6mayqqDq/hi9xf8mPkjdo+93jkDYgcwvtN4xqeNJylUH8E4WFTJwrX7WLA2k+wSR53zTQaFsb3juXhICqf3jMdikl+4ra3OLyc0PSPf1i/1reRAwxeFxOtT+XpM1EelrJIp8UQSKF9oRPshfUb4KlD6jAROTQikwCnv1dfIfeYZAJKff46I006CR1MADZIHw3U/+bV9IjA19EHjKSqi+OuvKf7sc+ybNtW/yGAgeOQIwieeTdjYM1sliCp3lbM0cylf7v6S1YdWo1H/o2RA7ADOSjuLszqdRYfQDrg9Kj9uy2HemkyW78jl8E+fqGAzkwcmc9GQFAamREhGvlbS6C8nTYOD62H7YtixGLI2NlyB0QKpI6HrmdD1DEgcKKNRx7lA+UIj2g/pM8JXgdJnJHBqQiAFTtlPPEnBW28BkPreu4QmAW+epR8cMh3Oe8F/jRMBq7kPGmdmJiXffEPJ19/g2LmzfgWKQtDgwYSNG0fYuLFYOnY86jZll2fzbfq3fLnnS3YU7mjwnL4xfRnfaTynp55O5/DO7C+sZMHaTD78fT+5pY5653eJC+GiwR04f1AHUqMlC9zRaPEvp5KDsOM7fdvzU/3FdqsFReujUF3PgC5nQGRqWzRb+FGgfKER7Yf0GeGrQOkzEjg1IZACp4N3/z+KP/kEgE6ff05Qyc/w9T/0g+c8BSOu9WPrRKDy5YPGvmOHHkR98y2uzMwGz7H26EHYuHGEjj0TW+/eKEf54bWneA9L9i7h+4zvGw2iOoZ15LTU0zgt5TQGxA7itz3FfLL+AN9vyaqzqG61gamRTOqfyNn9kiSIOgJH9MvJVQnpK/SRqJ1LoLjh/gNATPea0aiOoyEoslXaLfwnUL7QiPZD+ozwVaD0GQmcmhBIgdO+m2ZR9uOPAHRd/hOWNY/Aunf0g1d9Dx1H+q9xImAdyQeNpmnYN2+hdOkPlP7wA85duxs8zxgbS+jJJxN66imEjBmDMeLoUlXvLd7Lkgw9iNpWsK3Bc8LMYYzpMIZTU05lUOwoVu2w8/H6/axOL2jw/AEpEZzTP4lJ/SWIaqmj/uWkaVCwB3b/qI9Epf8MDWXpA0CBxP7Q6WRIOwnSxkBw9NE0X/hBoHyhEe2H9Bnhq0DpMxI4NSGQAqe9V1xJ5bp1APTY8AfG987WnzdAgbv2ycPYokGt8UHjSE+n9IcfKPthKZV//tnwSQYDQQMHEnraqYSccspRj0ZllmSybN8yftr3E3/k/IFH89S/pWJgQOwARiePpkvoYLZnRLJ4cx5bDzX8Jb1fh3DG9kpgXO8E+iaHY5D05g1q9V9OHre+6O6eZbB7GexfCw389/SK76MHUJ3G6K+h8UffBtGmAuULjWg/pM8IXwVKn5HAqQmBFDjtnnQuzt27ISiInmt/w/BYKrjtEN0Vblnv17aJwNXaHzSu7BzKlv1I2fKfKf/tN7TKhp9rMcbGEjJyJMGjRhIyciTm1NQjTt5Q7CjmlwO/sHz/clYeWEmJs+HAKMQcwvCE4XQPH0JJYWd+3Wbgr4OlDZ4bH2ZlbO94zuyVwMndYgmyGI+obcejNv/lZC/WF95N/xn2/gLZm6GBZCFeMd31ZBOpwyFlBMT1BIP89wokgfKFRrQf0meErwKlz0jg1IRACpx2jDkZT34+hoQEun/4Moa5o/UDfS6AS9/1a9tE4GrLDxrV6aRi7VrKf15B2YoVOPfsafRcU3ISISNHETxyBCGjRmFOTDyie7pVN3/k/MHP+39m+f7lpBenN3puYkgi/aKGoVZ2YfveWLbtNwP1gzerycBJXWM4uXscp3SPpXt86Amdoe+Y/3KqLISMVZDxi74d+hO0+s+ueVnDocMQPYhKHQEpwyAoqu3bKRoVKF9oRPshfUb4KlD6jAROTQikwCnnqadw5eXhMJrodGl/DJ9epx8481449Z9+bZsIXMfyg8a5fz/lK1boo1Fr1qBVVDR6riUtjeARwwkaPITgIYMxp6UdUbCSVZ7FqoOrWHVoFasPrabA3vCzTgCxtnjiLb0pL+7Irsw47BWxQP1/k/gwKyd3i+Xk7rGc3C32hFtw1++/nOwlsG+1PiqV8Qsc3ABq/XXH6ojtAR2G6UszJA+GxH5gDjomzRUB0GdEuyN9RvgqUPqMBE5NCKTACWo6TcKfL6Ksqko//reP9IUnhWiAvz5oNJeLys2bqVi9mvLfVlP5xx9ojvppxKsZY2IIGjyI4MFDCBoyGFvfvhgsFp/uqWoqOwp38NvB31h1aBXrstfh8DR+zxBTOKH0oCA/ieLCZDz2DqDVv2ePhFBO7hbHqC7RDO8UTVSIb+1qbwLll5OXq1Ifhdq3BvavgX1roSyr6WsUI8T1qgqkBumvCX0lmGojAddnRMCTPiN8FSh9RgKnJgRs4PT9DSh7lumFc7ZBeJJ/GyYCVqB80KgOB5Ub/tQDqdWr9SQTbnej5ysWC7b+/Qnq16/qta/Po1IOj4NNuZtYl72Oddnr2JC7gcrG1hoCFAzYtBTKS5JxlKeiVqaiOuuPSnWPD2VYp2hGdI5ieKdoUqKOr2x9gdJnGqVpULy/JojavwYObWx+VEox6oknkgbqQVRCX0joByExx6bdx7GA7zMi4EifEb4KlD4jgVMTAjJwys4m4f2TUSryIDgW/m8XnMDPY4imBcoHzeHUykoqN26i8o/1VKxfT+WGP1FLGktZrTOEh2Pr24egfv2x9etHUP9+mJKSWhxMuVQX2wu2sy57Hb9n/8767PWNJprw3lMLxlXRAXdlMqpdH5XSXNHUDqaSI2wM7xzNsLQoBqVG0TMxDIspcP6tfRWofaZJLrueZOLgH/rUvkMbIGdr09n7qoUm1g2kEvrqU/9Mx/fIYmtql31G+JX0GeGrQOkzEjg1IRADp7z0zcS/f4pe0OUMmP6ZX9skAlugfNA0R1NVHLt2Ubn+j6pg6g9c+/Y1e50xOhpbv77YevbC2rMntp49sHTqhGI2N3utqqnsLtrNprxNbMzdyMa8jewq3IXWVIY3QPNY8TiSqgIpPaBSHQmAnunNYjLQNzmcgSmRDEqNZGBqJJ1igttNwon20mea5aqErKpg6tAG/TV3W9OJJ6oZTBDbExL66Fn8YnvqwVR0FwmoGnDc9BlxzEifEb4KlD4jgVMTAjFwKlr3CdFfX60XjL4ZJjzs30aJgBYoHzRHwl1QgH3zZio3b8a+aTOVmzfhyc1r9jrFbMbSrRu2nj29wZS1Z09MMc1PySp3lbMlbwsb8zbqwVTuRvLt+c1ep6lGVGcCqj0B1ZGIp2pfc0cCChFBZgakRNA3OYI+yeH0SQqjc2woxgBcS6o995lmOSsgdytkb6m1bdYz+7WEwQRRnauCqR76Flf1egKvpXdc9xnRJqTPCF8FSp/xJTYwHaM2iSaYCnbWvInv47+GCNHGTNHRhJ56KqGnnuotc2Vn1wmm7Js34ykqqnOd5nLh2LoVx9atdcqNMTFYu3TB0qUL1q5dsHTpirVrF0yJid7RoBBzCCOSRjAiaYRel6aRXZHNtoJtbC3Yytb8rWwr2Mah8kN16lYMHoy2gxhtB+u2xWNBdSZgdyTwW34Cvx5MRHXEo7nDsZmN9EwIo3dSOH2Sw+mdFE6vxDDCbM2PlokjZAmGDkP1rZqmQemhmiCqOqDK2wHqYc/hqW7I36lvhwvvoI9I1ds6gyWkbX8uIYQQAUcCpwBgKthR8ya+t/8aIoQfmBMSMCckEDZ2LKAHNu6sLOzbt+PYvgPH9m3Yt+/AmZ4Oat0pWZ78fCry86lYu7ZOuRIcjLVzZyxdu2Dt0hVL585Y0jpiSU3FEBJCYkgiiSGJnJ56uveaInsR2wq3sTV/qzegyizNRD1sGphidGIM2ocxqO60Q001ozpj2e6MZeveWBbtiEV1xKE6Y+kYqa8l1S0+lK7xod59CajaiKJAeLK+dT+rptztgPxdkLtdD6Jyt0NeVdDkttevp+SAvu1dUf9YaGLdQKr2vi2i7X42IYQQfiOBUwAwewMnRU+3K8QJTFEUzElJmJOSCDv9dG+5arfj2L27KpjargdWu3bhyas/1U+rqMC+ZQv2LVvqHTPGxmJJTcXSsSPmjqlYOqZhSetIaGoqIxNHMipplPdch8dBenE6Owt3srtoN7uKdrGraBcHyg7Ub7fBhdF2CKPtUL1j+e5g8ipj+WVnLOqWWFRXNKorilhrIt1ik+gRH07X+FC6xoXQOTaEhDAbhgCc8tfumaw1SSNqUz1QlFkrmNoOuTv09/aihusqy9K3zF/rH7NFQERHiEyFyI4QkVprvyMER0sCICGEaIckcPI3TcVUuEvfj+6sTzsRQtRjsNkI6tuXoL51v/R6iotx7NmDc88eHLurXvfswbV/f70RKgBPXh6VeXlU/vFH/XuEh2NJScHcIRlzsr4lJyWRltyFszuPwRgVhaIoVLgq2FO8xxtQ7S3ZS0ZJBvtL9+PW6qdkN5gqwJSJMTizTnklsFE1syErCm1fFKpTD6iMnhgSg5PpFJlCl+g4OsWGkBYTQlp0MB2igjAb5fmBVmUwVo0adYYeE+oeqyiAwnQoSIeCPXW38tyG67MXg30TZG9q+Lg5uCqYqgquwjtUbUkQlqy/nsDPVwkhRKCSwMnfCjNQqqeIyPNNQvjMGBFB8ODBBA8eXKdcdThw7t2Lc/dunJmZODMyce7LxJWRiTu34S+8akkJ9r/+wv7XXw0eV4KCvKNhMcnJJCYncWZyd0yJp2LqEgex0WRpRWSUZJBenE5GSQYZJRnsLdlLTkVOw3UaXBitOWCtezy/avs914J6KALNFYnmDgd3JBGWOBJDEkgJS6RLVAqdomLoEBVMh8ggEiNsEli1puBofav9DFU1R2n9gKpwrz56VXKg/vNU1VwV+qhW3vbG72sJqwqkkvQph3VeqwKs0Hg96BNCCHFMSODkbzm1vqDJ801CtBqD1YqtZ09sPXvWO6ZWVODctx9nZgauzEycmfv0/YxMXFlZDY5UAWiVlTirRrcavW9ICB3i40mLj8cUH48pvhfm+FPxREeQF6py0GZnn6WM/a4cDpQdILNkP4fKD+JSnQ3WpxidGI25YK0J9iqAPcCeCvi5ArR9FlRXBJo7As0dTrAhighLNHHBcSSHxZIankCsMZj+DjNJkcHEhloluGoN1jBIGqBvh1M9UJqlB1HF+/RX7/4+/bWh56qqOUshr1SfLtgYxQDBMRASD6FxVa/xEBIHoQl1y4JjwSi/8oUQ4mjIp6i/5dTKEiYjTkIcE4bgYGw9e2Dr2aPeMc3lwpWdg/vQQVwHq7dD+ush/VWzN/6FVy0vx5meriezaEBy1TY6NBRjTDSm6BiM0aNxRwRTFmqiMFglz+rkoKWC3RSRrhSSacjDpTQcWAEoBidGa01w5QLygDwPbC0Ciqp+tt1GNE8omjsMMxEEGSIJs0QRbY0hPjiWxLBYUsJjSIuMp0t0PAnhwVhNMqJxRAxGiOigb4yuf1zT9Kl+1aNTJYeg9GDV6yEoOai/uioav4em6nWU50LDA5q1KPrIWXWQFRStB13BMVWjajFVZVWbLUpvoxBCCC8JnPxMya094iSBkxD+ppjNWFI6YEnp0OBxTdPwFBXhOnAQ16GDuA8e1AOtnJrNlZODVtHEF15ALStDLSvDlVHz3JMJiKvaegNjvY1SMERGokaG4QyzURlspNiikWd2kWtykGOuJM9cRkmQizKbQlkQlAaB00SdJASKwYNiKAZzMSr7KQfKgSwn/OXEG2B5f1aPFUUNxUgoViWMYFMYoaYIIqxRxARFERccRUJoDClhsXSIjKVjRDQRtvazMLBfKYo+EhQaDwxr+BxN05+Xqh1I1Q6wyrKgLBfKc8DTeGBdVRlU5Otb7tZmzgUDkGAwHxZYRVW9RoItUk+CUb0dXmaUjJFCiOOPBE7+VjXipBnMKDFd/dwYIURzFEXBFBWFKSqKoH59Gz3PU1ZeE0zl1g2q3Dm5ePLzcRcUoJaUNH9TTUMtLITCQiyABYgAOjZzmcdsxB5kpjzIQIkVSq0aZVY3ZRY3FTaNCqtCpRUqqrZKq+Ldr7CC3WJHMzrwkE8F+hTBPDfgRo+4GmyqEYMahJFgzEowVkMINmMoIeZQQs1hRFjDibRGEB0UTlxIFHEhkSSGRpIUFkWELQyb0SaBVzVF0QOSoMimp3JXB1jluVCWDWU5Vfs5elBVHVyVVR33OFp2e9VVkz3QV+aQBgKrWu+tYWAJ1V+9+6H6s13WMH3fHCzZB4UQAUUCJ3+qXlME9JXq5S90Qhw3jKEhGEM7Y+3SucnzNKcTd2GhHkjlF+ApqHotLNBfqwIs/Xg+mqNlX3oBjC4PIa5KQkogvuG7N3m9CtgtUGGDCktNcGW3gN2sH3OYwW5RsJvBYQG7WcVucWE3l+jlVedmmyHDAm4jTX8Z1hQUzYoRG0YlCLNiw2oIwmoMxmYMItgcQog5hFBLMGGWEMKtoUTawoi2hREdrG9RtjBsJhs2k40gYxAmg+n4DsZqB1ix3Zs+V9PAWaZnC6zI118ra+1X5ENlAVp5Pu7SHEzOEpSK/BYHW16ucn0rPdj8uY1RDHpA5Q2wau0fXmYJAXOQHmyZg2v2LYe9NwfraemP5/4ghGgzEjj5U/4ulOqsS3GSGEKIE5FisXgXAW4J1W7HU1yMp6gYT3FR1X4RanFxrfLDtqIitMpKn9tmAIKd+lajoWCr5c/CuA3VwZYeUDnM+pRCp1nBZaraN7lxmsur9sFpUmr2q84vMUFe1XU159Ucd5rAbQJNUUAzYMCCAQtGxYpJsWBSrJgNViwGG1ajFauxJtAKNtsIMgcRbA4izBxEiCWIUEswwWYrIRYbQWYroZYgbCYLVqMVi9Hi3axGK2aDGYMSoMk3FKVmlCcqrdHTNFUlPyeH+Ph4Peh0VdRM9bMX190qi+qX2WuVNfWcVlM0FRwl+lZ6ZFU0SDHUD6bMQbWCryB9xMxkBZOtBa9NHbPor0YrGAK0TwghWiwgAqeXXnqJJ598kqysLAYOHMgLL7zAiBEjGj3/o48+4t5772Xv3r10796dxx9/nHPOOecYtriVZNc836TF90b+/iWEaI7BZsNgs7U40AJQVZXsffuJsVnRyitQy0rxlJailpXX7JeW6ftlZTX7pWWopaV4yvWyppJitJRJBZMDQuoNYDQVfB15kgKPAi4TuI1O3EZwGanz6jZWHTcouE00eE6hEXKqznGZal1nBI9B3/cYam1G8ChGVIMJzWhEM5jRjCY0oxmMJhSTBcVo1l9NVowmMwazFcVkwWgyYzZZMBnMWIxmzAYTZqMZi8GMxaSXWYxmrNWbyYLFaMJmsuib2YzVaMFmMmMxWjAZTJgNZkwGU719k2LCaDA2H+Qpih5UWEL0tad85XYeFlQVgqNMH/lylOkZBB2lLSgr42j6gpem6nU5y46+Ll8YLXWDKqNZL/O+Vu0bGin3vjZQbmikvPb5BrOetMRgqrXVem801y8zmPRAU0bohAACIHBauHAhc+bM4ZVXXmHkyJE8++yzTJgwge3btxMfX39yya+//srUqVN59NFHOffcc5k3bx4XXHAB69evp1+/fn74CY5CnVTkkhhCCNF2FKsFU1wchoQj/6u35nTiKS9Hq6xEraio2mrtV1agNVheiVpRjlpRgVa7vKIC1W4HdyPrHbUCowZGF3qqwaZ/uhbU5suXdrUlN234SkUfmVMbCspqbapBP1dV9PelChQbQFWUOse06v1aZephZR6Dol+nKGjV+wYFTTGgKQqawVDz3mBAM+hl1e+pfjUYUBT9FYNBD8oUI4r3mFFPdmIwohiM3vNrrjGhGGJQlDgUg4JiMKAEG1FCDSiKggENo+LBoHkw4sGouTFqHgx4MOLWyzV3neMGzYVRc2FU9VdFdWHyuDCoToyqE4PqwOBxYkRDUcCggUHRMAAGTUNBw6Dg/eOmUrUZqs6vW1a1r2g1ZVr1tR4UdzmKuxwDGmg119VsVdc1eKzqeKPH2lBjwVat94rBTIyqoVhsjZxvBMVY9ar3mZr9w8q9x4yHnXfYNQ0eO8prUPRAUan6V60OHBVDM+8bO7+xa/Gh7urzW3pu7Z9BtCZF0/ybb3TkyJEMHz6cF198EdD/Mpqamsrs2bO58847651/2WWXUV5ezldffeUtGzVqFIMGDeKVV15p9n4lJSVERERQXFxMeHh46/0gR2Le5bDjWwDUW/7EEN3Jv+0R7YKqquRUTaExyNQP0QKB3mc0txvV7kBz2NHsdlSHA83hQLXba16rjqu1X+12VId+rPq19jHN5UJzOtFcLlSnE9XlQnXo73E60VxOFI/H3z++OI6pAIoecmu1vsNqVWU+H6v13nteA+cefg1K/VfvsdrnH1ZnnToaKD9cvS+UjZxb074GvoK2tP6mH5VsmabOa+DnVw57X7+Ow36eWhdoSuO3a2l7mzqv+phSvxUNUBrcbfb+La3Th3rtwwdw0f3z/fq7yZfYwK8jTk6nk3Xr1nHXXXd5ywwGA+PGjWPVqlUNXrNq1SrmzJlTp2zChAl89tlnDZ7vcDhw1HqYuqQqg5WqqqiNLHJ5rCg5W1AA1RyMGpbc6KKbQtSmqiqapvm9/4r2I+D7jMGAEhyEEhwEwLFcOUpTVT3AqhVk1Xn17h92jqvqmNsNLjea243mcYPbjeb24HG58DhduF0uPE43HpcTj8uN6nLjcTr1cpcD1e1Cc7v0690u8Hj0ETiPG8XjqbMZVFV/9aj6vqahqBoGTd9E4DFArejEjw0JWMfbiMjx9vO0vfWd8vz+u8mX+/s1cMrLy8Pj8ZBw2Fz9hIQEtm3b1uA1WVlZDZ6fldVwutRHH32UBx54oF55bm4u9laYr3/E3Hbiy/NQAHt4F4py8wLyL8Ei8KiqSnFxMZqmSZ8RLSJ9xgeKAlarvh1NNei/YI/VL1lN0/Q/vlVvHhVUD9ph71FVvaz2e4/He47q8aB5PLhdbkpLSrBZbWiqhurx6JtbRVP11+oyj9uN6nHjUT14PB7UWq+qx4Oq6fuaqla9etA0vR2aqoLmQVM1bxma3mZNAzSPnglQVUHTz0HTUKre639wrDmOpgeUmqahVB1XNK3qWFVZ1TkASq3jiv4PCVXT4bSq16qxHO++4g2A6pcpmnbYsZqyBq+vql6pd95hddSu2zv1r2banl5W3e5aU/dqldeuu86xOm2o37cOL1NqR4DVN6t6rX1uvRCiiWMN3behY00N7sgnW/vk0RRycnL8+ruptLTl2Wf8/oxTW7vrrrvqjFCVlJSQmppKXFyc/6fq3bkPd0EG5dmZATuFRgQeVVVRFIW4uDjpM6JFpM8IX6mqSm5urvQZ0WKB0meqn0CpPQiress07wFviKtqta6tGnnwHtRq79ach6YH/lUBNprmvYdaFdxXV1NdQ027ao1uqLWjP+3wm9Q9TP12ep+28d5P4/C4tk6ddX+CBg/VxO1avfoPP1FDOzx+rWlH9Z52eFntEzWGq/j9O7DNZmvxuX4NnGJjYzEajWRnZ9cpz87OJjExscFrEhMTfTrfarVibeAvhwaDIQB+GRggpjMeT0iAtEe0F4qiSJ8RPpE+I3wlfUb4SvqM8EX187f+7jO+3NuvPdtisTB06FCWLl3qLVNVlaVLlzJ69OgGrxk9enSd8wGWLFnS6PlCCCGEEEIIcbT8PlVvzpw5zJgxg2HDhjFixAieffZZysvLmTlzJgDTp0+nQ4cOPProowDceuutnHbaafz3v/9l0qRJLFiwgN9//53XXnvNnz+GEEIIIYQQ4jjm98DpsssuIzc3l/vuu4+srCwGDRrE4sWLvQkgMjMz6wyhnXTSScybN4977rmHu+++m+7du/PZZ5+1vzWchBBCCCGEEO2G39dxOtYCah0nAn99FRF4pM8IX0mfEb6SPiN8JX1G+CpQ+owvsYH0bCGEEEIIIYRohgROQgghhBBCCNEMCZyEEEIIIYQQohkSOAkhhBBCCCFEMyRwEkIIIYQQQohmSOAkhBBCCCGEEM2QwEkIIYQQQgghmiGBkxBCCCGEEEI0QwInIYQQQgghhGiGBE5CCCGEEEII0QwJnIQQQgghhBCiGRI4CSGEEEIIIUQzJHASQgghhBBCiGaY/N2AY03TNABKSkr83BKdqqqUlpZis9kwGCSOFc2TPiN8JX1G+Er6jPCV9Bnhq0DpM9UxQXWM0JQTLnAqLS0FIDU11c8tEUIIIYQQQgSC0tJSIiIimjxH0VoSXh1HVFXl4MGDhIWFoSiKv5tDSUkJqamp7Nu3j/DwcH83R7QD0meEr6TPCF9JnxG+kj4jfBUofUbTNEpLS0lOTm525OuEG3EyGAykpKT4uxn1hIeHyweN8In0GeEr6TPCV9JnhK+kzwhfBUKfaW6kqZpMQhVCCCGEEEKIZkjgJIQQQgghhBDNkMDJz6xWK/fffz9Wq9XfTRHthPQZ4SvpM8JX0meEr6TPCF+1xz5zwiWHEEIIIYQQQghfyYiTEEIIIYQQQjRDAichhBBCCCGEaIYETkIIIYQQQgjRDAmchBBCCCGEEKIZEjj50UsvvUSnTp2w2WyMHDmSNWvW+LtJIkD8/PPPTJ48meTkZBRF4bPPPqtzXNM07rvvPpKSkggKCmLcuHHs3LnTP40VAeHRRx9l+PDhhIWFER8fzwUXXMD27dvrnGO325k1axYxMTGEhoZy8cUXk52d7acWC3+bO3cuAwYM8C4+OXr0aL799lvvcekvojmPPfYYiqJw2223ecuk34jD/fvf/0ZRlDpbr169vMfbU5+RwMlPFi5cyJw5c7j//vtZv349AwcOZMKECeTk5Pi7aSIAlJeXM3DgQF566aUGjz/xxBM8//zzvPLKK6xevZqQkBAmTJiA3W4/xi0VgWL58uXMmjWL3377jSVLluByuRg/fjzl5eXec26//Xa+/PJLPvroI5YvX87Bgwe56KKL/Nhq4U8pKSk89thjrFu3jt9//50zzzyT888/ny1btgDSX0TT1q5dy6uvvsqAAQPqlEu/EQ3p27cvhw4d8m4rV670HmtXfUYTfjFixAht1qxZ3vcej0dLTk7WHn30UT+2SgQiQPv000+971VV1RITE7Unn3zSW1ZUVKRZrVZt/vz5fmihCEQ5OTkaoC1fvlzTNL2PmM1m7aOPPvKes3XrVg3QVq1a5a9migATFRWlvfHGG9JfRJNKS0u17t27a0uWLNFOO+007dZbb9U0TT5nRMPuv/9+beDAgQ0ea299Rkac/MDpdLJu3TrGjRvnLTMYDIwbN45Vq1b5sWWiPUhPTycrK6tO/4mIiGDkyJHSf4RXcXExANHR0QCsW7cOl8tVp9/06tWLjh07Sr8ReDweFixYQHl5OaNHj5b+Ipo0a9YsJk2aVKd/gHzOiMbt3LmT5ORkunTpwhVXXEFmZibQ/vqMyd8NOBHl5eXh8XhISEioU56QkMC2bdv81CrRXmRlZQE02H+qj4kTm6qq3HbbbYwZM4Z+/foBer+xWCxERkbWOVf6zYlt06ZNjB49GrvdTmhoKJ9++il9+vRhw4YN0l9EgxYsWMD69etZu3ZtvWPyOSMaMnLkSN555x169uzJoUOHeOCBBzjllFPYvHlzu+szEjgJIcRxZtasWWzevLnOHHIhGtKzZ082bNhAcXExixYtYsaMGSxfvtzfzRIBat++fdx6660sWbIEm83m7+aIduLss8/27g8YMICRI0eSlpbGhx9+SFBQkB9b5juZqucHsbGxGI3GehlDsrOzSUxM9FOrRHtR3Uek/4iG3HzzzXz11VcsW7aMlJQUb3liYiJOp5OioqI650u/ObFZLBa6devG0KFDefTRRxk4cCDPPfec9BfRoHXr1pGTk8OQIUMwmUyYTCaWL1/O888/j8lkIiEhQfqNaFZkZCQ9evRg165d7e6zRgInP7BYLAwdOpSlS5d6y1RVZenSpYwePdqPLRPtQefOnUlMTKzTf0pKSli9erX0nxOYpmncfPPNfPrpp/z444907ty5zvGhQ4diNpvr9Jvt27eTmZkp/UZ4qaqKw+GQ/iIaNHbsWDZt2sSGDRu827Bhw7jiiiu8+9JvRHPKysrYvXs3SUlJ7e6zRqbq+cmcOXOYMWMGw4YNY8SIETz77LOUl5czc+ZMfzdNBICysjJ27drlfZ+ens6GDRuIjo6mY8eO3HbbbTz00EN0796dzp07c++995KcnMwFF1zgv0YLv5o1axbz5s3j888/JywszDs3PCIigqCgICIiIrj66quZM2cO0dHRhIeHM3v2bEaPHs2oUaP83HrhD3fddRdnn302HTt2pLS0lHnz5vHTTz/x3XffSX8RDQoLC/M+N1ktJCSEmJgYb7n0G3G4f/7zn0yePJm0tDQOHjzI/fffj9FoZOrUqe3vs8bfaf1OZC+88ILWsWNHzWKxaCNGjNB+++03fzdJBIhly5ZpQL1txowZmqbpKcnvvfdeLSEhQbNardrYsWO17du3+7fRwq8a6i+A9vbbb3vPqays1G666SYtKipKCw4O1i688ELt0KFD/mu08KurrrpKS0tL0ywWixYXF6eNHTtW+/77773Hpb+IlqidjlzTpN+I+i677DItKSlJs1gsWocOHbTLLrtM27Vrl/d4e+oziqZpmp9iNiGEEEIIIYRoF+QZJyGEEEIIIYRohgROQgghhBBCCNEMCZyEEEIIIYQQohkSOAkhhBBCCCFEMyRwEkIIIYQQQohmSOAkhBBCCCGEEM2QwEkIIYQQQgghmiGBkxBCCCGEEEI0QwInIYQQAefvf/87F1xwgd/uP23aNB555JE2q/+vv/4iJSWF8vLyNruHEEKI1qVomqb5uxFCCCFOHIqiNHn8/vvv5/bbb0fTNCIjI49No2r5888/OfPMM8nIyCA0NLTN7jNlyhQGDhzIvffe22b3EEII0XokcBJCCHFMZWVlefcXLlzIfffdx/bt271loaGhbRqwNOeaa67BZDLxyiuvtOl9vv76a6699loyMzMxmUxtei8hhBBHT6bqCSGEOKYSExO9W0REBIqi1CkLDQ2tN1Xv9NNPZ/bs2dx2221ERUWRkJDA66+/Tnl5OTNnziQsLIxu3brx7bff1rnX5s2bOfvsswkNDSUhIYFp06aRl5fXaNs8Hg+LFi1i8uTJdco7derEQw89xPTp0wkNDSUtLY0vvviC3Nxczj//fEJDQxkwYAC///6795qMjAwmT55MVFQUISEh9O3bl2+++cZ7/KyzzqKgoIDly5cf5b+oEEKIY0ECJyGEEO3Cu+++S2xsLGvWrGH27NnceOONXHLJJZx00kmsX7+e8ePHM23aNCoqKgAoKirizDPPZPDgwfz+++8sXryY7OxsLr300kbvsXHjRoqLixk2bFi9Y8888wxjxozhjz/+YNKkSUybNo3p06dz5ZVXsn79erp27cr06dOpnsgxa9YsHA4HP//8M5s2beLxxx+vM5JmsVgYNGgQK1asaOV/KSGEEG1BAichhBDtwsCBA7nnnnvo3r07d911FzabjdjYWK699lq6d+/OfffdR35+Phs3bgTgxRdfZPDgwTzyyCP06tWLwYMH89Zbb7Fs2TJ27NjR4D0yMjIwGo3Ex8fXO3bOOedw/fXXe+9VUlLC8OHDueSSS+jRowd33HEHW7duJTs7G4DMzEzGjBlD//796dKlC+eeey6nnnpqnTqTk5PJyMho5X8pIYQQbUECJyGEEO3CgAEDvPtGo5GYmBj69+/vLUtISAAgJycH0JM8LFu2zPvMVGhoKL169QJg9+7dDd6jsrISq9XaYAKL2vevvldT97/lllt46KGHGDNmDPfff783oKstKCjIO0ImhBAisEngJIQQol0wm8113iuKUqesOthRVRWAsrIyJk+ezIYNG+psO3furDfyUy02NpaKigqcTmeT96++V1P3v+aaa9izZw/Tpk1j06ZNDBs2jBdeeKFOnQUFBcTFxbXsH0AIIYRfSeAkhBDiuDRkyBC2bNlCp06d6NatW50tJCSkwWsGDRoE6OsstYbU1FRuuOEGPvnkE/7xj3/w+uuv1zm+efNmBg8e3Cr3EkII0bYkcBJCCHFcmjVrFgUFBUydOpW1a9eye/duvvvuO2bOnInH42nwmri4OIYMGcLKlSuP+v633XYb3333Henp6axfv55ly5bRu3dv7/G9e/dy4MABxo0bd9T3EkII0fYkcBJCCHFcSk5O5pdffsHj8TB+/Hj69+/PbbfdRmRkJAZD47/+rrnmGj744IOjvr/H42HWrFn07t2biRMn0qNHD15++WXv8fnz5zN+/HjS0tKO+l5CCCHaniyAK4QQQtRSWVlJz549WbhwIaNHj26TezidTrp37868efMYM2ZMm9xDCCFE65IRJyGEEKKWoKAg3nvvvSYXyj1amZmZ3H333RI0CSFEOyIjTkIIIYQQQgjRDBlxEkIIIYQQQohmSOAkhBBCCCGEEM2QwEkIIYQQQgghmiGBkxBCCCGEEEI0QwInIYQQQgghhGiGBE5CCCGEEEII0QwJnIQQQgghhBCiGRI4CSGEEEIIIUQzJHASQgghhBBCiGb8f9jNULSfGkbHAAAAAElFTkSuQmCC"
+ },
+ "metadata": {},
+ "output_type": "display_data",
+ "jetTransient": {
+ "display_id": null
+ }
+ }
+ ],
+ "execution_count": 18
}
],
"metadata": {
diff --git a/docs_state/quickstart/index.rst b/docs_state/quickstart/index.rst
index 7177bc3a..c3b53d9f 100644
--- a/docs_state/quickstart/index.rst
+++ b/docs_state/quickstart/index.rst
@@ -36,4 +36,5 @@ For experienced users, you can jump directly to the concepts overview or explore
installation.rst
5min-tutorial.ipynb
- core-concepts/index
\ No newline at end of file
+ core-concepts/index
+
diff --git a/docs_state/quickstart/installation.rst b/docs_state/quickstart/installation.rst
index 04fa6fe5..693bafb1 100644
--- a/docs_state/quickstart/installation.rst
+++ b/docs_state/quickstart/installation.rst
@@ -161,14 +161,3 @@ Now that you have BrainPy installed, you can:
- Follow the :doc:`5-minute tutorial <5min-tutorial>` for a quick introduction
- Read about :doc:`core concepts ` to understand BrainPy's architecture
- Explore the :doc:`tutorials <../tutorials/index>` for detailed guides
-
-Using BrainPy with Binder
---------------------------
-
-If you want to try BrainPy without installing it locally, you can use our Binder environment:
-
-.. image:: https://mybinder.org/badge_logo.svg
- :target: https://mybinder.org/v2/gh/brainpy/BrainPy-binder/main
- :alt: Binder
-
-This provides a pre-configured Jupyter notebook environment in your browser.