1 1 ```import numpy as np ``` 2 3 1 ```from nengo import LIF ``` 4 1 ```from nengo.builder.builder import Builder ``` 5 1 ```from nengo.builder.neurons import SimNeurons ``` 6 1 ```from nengo.neurons import NeuronType ``` 7 8 1 ```__all__ = ['Unit', 'Tanh', 'init_lif'] ``` 9 10 11 1 ```def _sample_lif_state(sim, ens, x0, rng): ``` 12 ``` """Sample the LIF's voltage/refractory assuming uniform within ISI. ``` 13 ``` """ ``` 14 1 ``` lif = ens.neuron_type ``` 15 1 ``` params = sim.model.params ``` 16 17 1 ``` eval_points = x0[None, :] ``` 18 1 ``` x = np.dot(eval_points, params[ens].encoders.T / ens.radius)[0] ``` 19 1 ``` a = ens.neuron_type.rates(x, params[ens].gain, params[ens].bias) ``` 20 1 ``` J = params[ens].gain * x + params[ens].bias ``` 21 22 ``` # fast-forward to a random time within the ISI for any active neurons ``` 23 1 ``` is_active = a > 0 ``` 24 1 ``` t_isi = np.zeros_like(a) ``` 25 1 ``` t_isi[is_active] = rng.rand(np.count_nonzero(is_active)) / a[is_active] ``` 26 27 ``` # work backwards through the LIF solution to find the corresponding voltage ``` 28 ``` # since the refractory period is at the beginning of the ISI, we must ``` 29 ``` # set that first, then subtract and use the remaining delta ``` 30 1 ``` refractory_time = np.where( ``` 31 ``` is_active & (t_isi < lif.tau_ref), ``` 32 ``` sim.dt + (lif.tau_ref - t_isi), 0) # dt immediately subtracted ``` 33 1 ``` delta_t = (t_isi - lif.tau_ref).clip(0) ``` 34 1 ``` voltage = -J * np.expm1(-delta_t / lif.tau_rc) ``` 35 36 ``` # fast-forward to the steady-state for any subthreshold neurons ``` 37 1 ``` subthreshold = ~is_active ``` 38 1 ``` voltage[subthreshold] = J[subthreshold].clip(0) ``` 39 40 1 ``` return voltage, refractory_time ``` 41 42 43 1 ```def init_lif(sim, ens, x0=None, rng=None): ``` 44 ``` """Initialize an ensemble of LIF Neurons to represent ``x0``. ``` 45 46 ``` Must be called from within a simulator context block, and before ``` 47 ``` the simulation (see example below). ``` 48 49 ``` Parameters ``` 50 ``` ---------- ``` 51 ``` sim : :class:`nengo.Simulator` ``` 52 ``` The created simulator, from whose context the call is within. ``` 53 ``` ens : :class:`nengo.Ensemble` ``` 54 ``` The ensemble of LIF neurons to be initialized. ``` 55 ``` x0 : ``(d,) array_like``, optional ``` 56 ``` A ``d``-dimensional state-vector that the ``` 57 ``` ensemble should be initialized to represent, where ``` 58 ``` ``d = ens.dimensions``. Defaults to the zero vector. ``` 59 ``` rng : :class:`numpy.random.RandomState` or ``None``, optional ``` 60 ``` Random number generator state. ``` 61 62 ``` Returns ``` 63 ``` ------- ``` 64 ``` v : ``(n,) np.array`` ``` 65 ``` Array of initialized voltages, where ``n = ens.n_neurons``. ``` 66 ``` r : ``(n,) np.array`` ``` 67 ``` Array of initialized refractory times, where ``n = ens.n_neurons``. ``` 68 69 ``` Notes ``` 70 ``` ----- ``` 71 ``` This will not initialize the synapses. ``` 72 73 ``` Examples ``` 74 ``` -------- ``` 75 ``` >>> import nengo ``` 76 ``` >>> from nengolib import Network ``` 77 ``` >>> from nengolib.neurons import init_lif ``` 78 ``` >>> ``` 79 ``` >>> with Network() as model: ``` 80 ``` >>> u = nengo.Node(0) ``` 81 ``` >>> x = nengo.Ensemble(100, 1) ``` 82 ``` >>> nengo.Connection(u, x) ``` 83 ``` >>> p_v = nengo.Probe(x.neurons, 'voltage') ``` 84 ``` >>> ``` 85 ``` >>> with nengo.Simulator(model, dt=1e-4) as sim: ``` 86 ``` >>> init_lif(sim, x) ``` 87 ``` >>> sim.run(0.01) ``` 88 ``` >>> ``` 89 ``` >>> import matplotlib.pyplot as plt ``` 90 ``` >>> plt.title("Initialized LIF Voltage Traces") ``` 91 ``` >>> plt.plot(1e3 * sim.trange(), sim.data[p_v]) ``` 92 ``` >>> plt.xlabel("Time (ms)") ``` 93 ``` >>> plt.ylabel("Voltage (Unitless)") ``` 94 ``` >>> plt.show() ``` 95 ``` """ ``` 96 97 1 ``` if rng is None: ``` 98 1 ``` rng = sim.rng ``` 99 100 1 ``` if x0 is None: ``` 101 1 ``` x0 = np.zeros(ens.dimensions) ``` 102 ``` else: ``` 103 1 ``` x0 = np.atleast_1d(x0) ``` 104 1 ``` if x0.shape != (ens.dimensions,): ``` 105 1 ``` raise ValueError( ``` 106 ``` "x0 must be an array of length %d" % ens.dimensions) ``` 107 108 1 ``` if not isinstance(ens.neuron_type, LIF): ``` 109 1 ``` raise ValueError("ens.neuron_type=%r must be an instance of " ``` 110 ``` "nengo.LIF" % ens.neuron_type) ``` 111 112 1 ``` vr = _sample_lif_state(sim, ens, x0, rng) ``` 113 114 ``` # https://github.com/nengo/nengo/issues/1415 ``` 115 1 ``` signal = sim.model.sig[ens.neurons] ``` 116 1 ``` sim.signals[signal['voltage']], sim.signals[signal['refractory_time']] = vr ``` 117 1 ``` return vr ``` 118 119 120 1 ```class Unit(NeuronType): ``` 121 ``` """A neuron model with gain=1 and bias=0 on its input.""" ``` 122 123 1 ``` def rates(self, x, gain, bias): ``` 124 ``` raise NotImplementedError("unit does not support decoding") ``` 125 126 1 ``` def gain_bias(self, max_rates, intercepts): ``` 127 1 ``` return np.ones_like(max_rates), np.zeros_like(max_rates) ``` 128 129 130 1 ```class Tanh(Unit): ``` 131 ``` """Common hyperbolic tangent neural nonlinearity.""" ``` 132 133 1 ``` def step_math(self, dt, J, output): ``` 134 1 ``` output[...] = np.tanh(J) ``` 135 136 137 1 ```@Builder.register(Unit) ``` 138 ```def build_unit(model, unit, neurons): ``` 139 ``` """Adds all unit neuron types to the nengo reference backend.""" ``` 140 1 ``` model.add_op(SimNeurons(neurons=unit, ``` 141 ``` J=model.sig[neurons]['in'], ``` 142 ``` output=model.sig[neurons]['out'])) ```

Read our documentation on viewing source code .