Spaces:
Paused
Paused
Download src/core/synapse_stochastic.py from ThomasHeisig/MHRN-Space: direct link, hf CLI and curl.
- Browser
- Download file 3.79 kB
-
https://huggingface.co/spaces/ThomasHeisig/MHRN-Space/resolve/main/src/core/synapse_stochastic.py
- Command line
-
hf download hf://spaces/ThomasHeisig/MHRN-Space/src/core/synapse_stochastic.py
-
curl -L -o synapse_stochastic.py https://huggingface.co/spaces/ThomasHeisig/MHRN-Space/resolve/main/src/core/synapse_stochastic.py
3.79 kB
| """Seeded quantal-release synapse variant built on one coherent STP model.""" | |
| from __future__ import annotations | |
| import random | |
| from dataclasses import asdict, dataclass, field | |
| from typing import Any | |
| from .biophysical_contracts import ModelProvenance, ModelTimescale | |
| class QuantalSynapseConfig: | |
| enabled: bool = False | |
| seed: int = 0 | |
| release_sites: int = 4 | |
| release_probability: float = 0.25 | |
| quantal_size: float = 0.05 | |
| facilitation_u: float = 0.2 | |
| tau_recovery_ticks: float = 800.0 | |
| tau_facilitation_ticks: float = 50.0 | |
| def __post_init__(self) -> None: | |
| if self.release_sites < 1: | |
| raise ValueError("release_sites must be >= 1") | |
| if not 0.0 <= self.release_probability <= 1.0: | |
| raise ValueError("release_probability must be in [0, 1]") | |
| if self.quantal_size < 0.0: | |
| raise ValueError("quantal_size must be >= 0") | |
| if self.tau_recovery_ticks <= 0.0 or self.tau_facilitation_ticks <= 0.0: | |
| raise ValueError("time constants must be > 0") | |
| class QuantalSTPSynapse: | |
| target_id: int | |
| weight: float | |
| delay: int | |
| config: QuantalSynapseConfig | |
| available_fraction: float = 1.0 | |
| facilitation: float = 0.0 | |
| last_tick: int = 0 | |
| release_count: int = 0 | |
| _rng: random.Random = field(init=False, repr=False) | |
| def __post_init__(self) -> None: | |
| if self.delay < 1: | |
| raise ValueError("delay must be >= 1") | |
| self._rng = random.Random(self.config.seed) | |
| def provenance_tag(self) -> ModelProvenance: | |
| return ModelProvenance( | |
| model_id="quantal-tsodyks-markram-v1", | |
| version="mhrn-experimental-1", | |
| timescale=ModelTimescale.TICK, | |
| enabled=self.config.enabled, | |
| parameters=asdict(self.config), | |
| seed=self.config.seed, | |
| ) | |
| def _recover(self, tick: int) -> None: | |
| elapsed = max(0, tick - self.last_tick) | |
| if elapsed == 0: | |
| return | |
| self.available_fraction += (1.0 - self.available_fraction) * min( | |
| 1.0, elapsed / self.config.tau_recovery_ticks | |
| ) | |
| self.facilitation *= max( | |
| 0.0, 1.0 - elapsed / self.config.tau_facilitation_ticks | |
| ) | |
| self.available_fraction = min(1.0, max(0.0, self.available_fraction)) | |
| self.facilitation = min(1.0, max(0.0, self.facilitation)) | |
| def release(self, tick: int) -> float: | |
| if not self.config.enabled: | |
| return 0.0 | |
| self._recover(tick) | |
| effective_p = min( | |
| 1.0, | |
| self.config.release_probability | |
| * (1.0 + self.facilitation) | |
| * self.available_fraction, | |
| ) | |
| quanta = sum( | |
| 1 | |
| for _ in range(self.config.release_sites) | |
| if self._rng.random() < effective_p | |
| ) | |
| used_fraction = quanta / self.config.release_sites | |
| self.available_fraction = max(0.0, self.available_fraction - used_fraction) | |
| self.facilitation = min(1.0, self.facilitation + self.config.facilitation_u) | |
| self.last_tick = tick | |
| self.release_count += quanta | |
| return self.weight * self.config.quantal_size * quanta | |
| def to_dict(self) -> dict[str, Any]: | |
| return { | |
| "schema_version": 1, | |
| "target_id": self.target_id, | |
| "weight": self.weight, | |
| "delay": self.delay, | |
| "available_fraction": self.available_fraction, | |
| "facilitation": self.facilitation, | |
| "last_tick": self.last_tick, | |
| "release_count": self.release_count, | |
| "provenance": self.provenance_tag.to_dict(), | |
| } | |
| __all__ = ["QuantalSTPSynapse", "QuantalSynapseConfig"] | |