PerfectIntegratorNeuron

July 25, 2026 · View on GitHub

Module: sc_neurocore.neurons.models.perfect_integrator Reference: Lapicque 1907 (no-leak variant) Family: Integrate-and-fire (non-leaky) State variables: v (voltage)

Equations

CmdVdt=IC_m \frac{dV}{dt} = I

Discrete: V(t+1)=V(t)+ICmdtV(t+1) = V(t) + \frac{I}{C_m} \cdot dt

Spike when VVθV \geq V_\theta, then VVresetV \leftarrow V_{\text{reset}}.

Parameters

ParameterDefaultDescription
v0.0Membrane voltage
c_m1.0Membrane capacitance
v_threshold1.0Spike threshold
v_reset0.0Reset potential
dt0.1Time step

Validation contract

The implementation rejects invalid state before mutation:

  • v, v_threshold, v_reset, c_m, dt, and input current must be finite;
  • c_m and dt must be positive;
  • v_threshold must be greater than v_reset;
  • initial v must be below v_threshold;
  • each voltage increment and candidate voltage must remain finite before assignment.
  • runtime v, c_m, dt, v_threshold, and v_reset are revalidated before the I / C_m division so corrupted objects fail closed without mutating voltage.

These guards preserve the analytical positive-excursion ISI contract and prevent overflowing currents or capacitance scales from poisoning the state. Julia, Go, and Mojo transport the complete numeric contract through executable native paths. Go and Mojo validate a complete run before writing the caller's trace, so rejection cannot leave partial output. The Rust engine path is executable at factory defaults and rejects non-default instances explicitly.

The schema-level reference corpus pins the spike-bearing constant-current protocol perfect_integrator_constant_current_sawtooth. Its features are re-derived independently from the analytic reset sawtooth in tests/test_reference_perfect_integrator.py.

Behaviour

  • No leak: zero-input steps leave voltage unchanged; unlike LIF, there is no drift toward a resting potential.
  • Candidate-first threshold: the Euler candidate is computed and checked before an inclusive threshold comparison and hard reset.
  • Linear f–I relation: below the one-event-per-step ceiling, firing rate is proportional to current and inversely proportional to capacitance and the threshold excursion.
  • Deterministic: identical state and inputs produce bit-identical traces.
  • Floating-point boundary: decimal increments need not reach a decimal threshold on the algebraically expected step. The tests retain this IEEE 754 behaviour instead of replacing it with an epsilon threshold.

Analytical predictions

PropertyFormula
ISI (steps)(θVreset)/(Idt/Cm)\lceil (\theta - V_{\text{reset}}) / (I \cdot dt / C_m) \rceil
RateI/(Cm(θVreset))I / (C_m \cdot (\theta - V_{\text{reset}})) before the discrete ceiling
Linearityf(2I)=2f(I)f(2I) = 2 f(I) away from quantisation boundaries
Capacitance scalingf1/Cmf \propto 1/C_m
Threshold scalingf1/(θVreset)f \propto 1/(\theta - V_{\text{reset}})

Execution and silicon pipeline

PerfectIntegratorNeuron
├── step(current) → int {0,1}
├── simulate(..., backend="auto|python|rust|julia|go|mojo")
├── measured auto order: Mojo → Julia → Go → compatible Rust → Python
├── paired TOML/JSON schema: Euler + inclusive candidate threshold
├── generated Q8.8 RTL: 66-event parity at I=0.7 over 1,000 steps
└── catalogue formal job: SymbiYosys/Z3 bounded proof, depth 20

Verification evidence

SurfaceEvidenceContract
Python modeltests/test_model_perfect_integrator.pydynamics, f–I/ISI laws, reset, validation, analysis, and network use
Public native dispatchtests/test_perfect_integrator_backend_parity.py, tests/test_perfect_integrator_backend_auto_dispatch.py, tests/test_perfect_integrator_backend_validation.py, tests/test_perfect_integrator_backend_c_abi.py, tests/test_perfect_integrator_backend_unavailability.pyexecutable Rust/Julia/Go/Mojo paths, bit-exact parity, full numeric contract, and mutation-free rejection
Native loadingtests/test_perfect_integrator_backend_loading.pyfail-closed optional-runtime and C-symbol boundaries
Analytic referencetests/test_reference_perfect_integrator.pyindependent reset-sawtooth feature re-derivation
Python-to-Verilogtests/test_cosim_perfect_integrator.pyhand/schema/Q8.8 parity plus an explicit fractional-current boundary
Benchmarktests/test_bench_perfect_integrator.pypublic-path measurement, source hashes, environment metadata, and fail-closed parity exits

The acceleration goldens cover 1,000 steps at I=0/0.333/0.7/2/3/5/20, producing 0/32/66/200/250/500/1,000 events. Every Rust, Julia, Go, and Mojo trace is bit-identical to Python. At I=0.7, hand Python, schema Python, and Q8.8 RTL all produce 66 events over 1,000 steps. At I=0.333, fixed-point quantisation produces 31 RTL events versus 32 in both floating-point paths; that one-event boundary is a declared exclusion, not a failed parity claim.

Measured performance (2026-07-13)

The committed run was pinned to logical CPU 10, but that CPU was not reserved and the kernel isolated-CPU set was empty. The powersave-governor host load was 30.28 at the start and 30.76 at the end. These are local regression timings, not production throughput claims.

MetricValue
Evidence classLocal regression, non-isolated workstation
Benchmark artefactbenchmarks/results/local_python_2026-07-13_perfect_integrator_euler.json
Workload100,000 steps, 7 repeats, I=5.0
Polyglot contractFive public dispatch paths; 50,000 events and bit-exact voltage traces in every lane
BackendMedian ms/callSpeedup vs PythonMaximum voltage differenceEvents
Mojo0.965152.42×050,000
Julia1.63390.10×050,000
Go2.64455.64×050,000
Rust engine60.2682.44×050,000
Python147.1371.00×050,000

Pipeline verification

  1. Construction, scalar stepping, reset, population use, and long-run state stability pass through the maintained Python model suite.
  2. Rust, Julia, Go, and Mojo execute the same candidate-first recurrence. Julia, Go, and Mojo carry non-default state and parameters; Rust retains its stated factory-default boundary.
  3. Hand/schema/Q8.8 RTL preserve the enrolled 66-event operating point, and the I=0.333 quantisation boundary remains explicit.
  4. The generated inclusive-threshold RTL passes the depth-20 SymbiYosys/Z3 bounded proof.