def test_hetero_neurons(Simulator, rng, seed):
    n_neurons = 100
    dt = 0.001
    T = 0.1
    dims_in = 2

    taus = nengo.dists.Uniform(0.001, 0.1).sample(n_neurons, rng=rng)
    synapses = [Lowpass(tau) for tau in taus]
    encoders = sphere.sample(n_neurons, dims_in, rng=rng)

    hs = HeteroSynapse(synapses, dt)

    def embed_encoders(x):
        # Reshapes the vectors to be the same dimensionality as the
        # encoders, and then takes the dot product row by row.
        # See http://stackoverflow.com/questions/26168363/ for a more
        # efficient solution.
        return np.sum(encoders * hs.from_vector(x), axis=1)

    with Network(seed=seed) as model:
        # Input stimulus
        stim = nengo.Node(size_in=dims_in)
        for i in range(dims_in):
            nengo.Connection(nengo.Node(
                output=nengo.processes.WhiteSignal(T, high=10, seed=seed)),
                             stim[i],
                             synapse=None)

        # HeteroSynapse node
        syn = nengo.Node(size_in=dims_in, output=hs)

        # For comparing results
        x = [
            nengo.Ensemble(n_neurons, dims_in, seed=0, encoders=encoders)
            for _ in range(2)
        ]  # expected, actual

        # Expected
        for i, synapse in enumerate(synapses):
            t = np.zeros_like(encoders)
            t[i, :] = encoders[i, :]
            nengo.Connection(stim, x[0].neurons, transform=t, synapse=synapse)

        # Actual
        nengo.Connection(stim, syn, synapse=None)
        nengo.Connection(syn,
                         x[1].neurons,
                         function=embed_encoders,
                         synapse=None)

        # Probes
        p_exp = nengo.Probe(x[0].neurons, synapse=None)
        p_act = nengo.Probe(x[1].neurons, synapse=None)

    # Check correctness
    with Simulator(model, dt=dt) as sim:
        sim.run(T)

    assert np.allclose(sim.data[p_act], sim.data[p_exp])
Beispiel #2
0
def delayed_synapse():
    a = 0.1  # desired delay
    b = 0.01  # synapse delay
    tau = 0.01  # recurrent tau
    hz = 15  # input frequency
    t = 1.0  # simulation time
    dt = 0.00001  # simulation timestep
    order = 6  # order of pade approximation
    tau_probe = 0.02

    dexp_synapse = DoubleExp(tau, tau / 5)

    sys_lambert = lambert_delay(a, b, tau, order - 1, order)
    synapse = (cont2discrete(Lowpass(tau), dt=dt) *
               DiscreteDelay(int(b / dt)))

    n_neurons = 2000
    neuron_type = PerfectLIF()

    A, B, C, D = sys_lambert.observable.transform(5*np.eye(order)).ss

    sys_normal = PadeDelay(a, order)
    assert len(sys_normal) == order

    with Network(seed=0) as model:
        stim = Node(output=WhiteSignal(t, high=hz, y0=0))

        x = EnsembleArray(n_neurons / order, len(A), neuron_type=neuron_type)
        output = Node(size_in=1)

        Connection(x.output, x.input, transform=A, synapse=synapse)
        Connection(stim, x.input, transform=B, synapse=synapse)
        Connection(x.output, output, transform=C, synapse=None)
        Connection(stim, output, transform=D, synapse=None)

        lowpass_delay = LinearNetwork(
            sys_normal, n_neurons_per_ensemble=n_neurons / order,
            synapse=tau, input_synapse=tau,
            dt=None, neuron_type=neuron_type, radii=1.0)
        Connection(stim, lowpass_delay.input, synapse=None)

        dexp_delay = LinearNetwork(
            sys_normal, n_neurons_per_ensemble=n_neurons / order,
            synapse=dexp_synapse, input_synapse=dexp_synapse,
            dt=None, neuron_type=neuron_type, radii=1.0)
        Connection(stim, dexp_delay.input, synapse=None)

        p_stim = Probe(stim, synapse=tau_probe)
        p_output_delayed = Probe(output, synapse=tau_probe)
        p_output_lowpass = Probe(lowpass_delay.output, synapse=tau_probe)
        p_output_dexp = Probe(dexp_delay.output, synapse=tau_probe)

    with Simulator(model, dt=dt, seed=0) as sim:
        sim.run(t)

    return (a, dt, sim.trange(), sim.data[p_stim],
            sim.data[p_output_delayed], sim.data[p_output_lowpass],
            sim.data[p_output_dexp])
Beispiel #3
0
def test_impulse():
    dt = 0.001
    tau = 0.005
    length = 500

    delta = np.zeros(length)  # TODO: turn into a little helper?
    delta[1] = 1. / dt  # starts at 1 to compensate for delay removed by nengo

    sys = Lowpass(tau)
    response = impulse(sys, dt, length)
    assert np.allclose(response[0], 0)

    # should give the same result as using filt
    assert np.allclose(response, sys.filt(delta, dt))

    # should also accept discrete systems
    dss = cont2discrete(sys, dt=dt)
    assert not dss.analog
    assert np.allclose(response, impulse(dss, dt=None, length=length) / dt)
def test_hetero_vector(Simulator, rng, seed):
    n_neurons = 20
    dt = 0.0005
    T = 0.1
    dims_in = 2
    synapses = [Alpha(0.1), Lowpass(0.005)]
    assert dims_in == len(synapses)

    encoders = sphere.sample(n_neurons, dims_in, rng=rng)

    with Network(seed=seed) as model:
        # Input stimulus
        stim = nengo.Node(size_in=dims_in)
        for i in range(dims_in):
            nengo.Connection(nengo.Node(
                output=nengo.processes.WhiteSignal(T, high=10, seed=seed)),
                             stim[i],
                             synapse=None)

        # HeteroSynapse Nodes
        syn_elemwise = nengo.Node(size_in=dims_in,
                                  output=HeteroSynapse(synapses,
                                                       dt,
                                                       elementwise=True))

        # For comparing results
        x = [
            nengo.Ensemble(n_neurons, dims_in, seed=0, encoders=encoders)
            for _ in range(2)
        ]  # expected, actual

        # Expected
        for j, synapse in enumerate(synapses):
            nengo.Connection(stim[j], x[0][j], synapse=synapse)

        # Actual
        nengo.Connection(stim, syn_elemwise, synapse=None)
        nengo.Connection(syn_elemwise, x[1], synapse=None)

        # Probes
        p_exp = nengo.Probe(x[0], synapse=None)
        p_act_elemwise = nengo.Probe(x[1], synapse=None)

    # Check correctness
    with Simulator(model, dt=dt) as sim:
        sim.run(T)

    assert np.allclose(sim.data[p_act_elemwise], sim.data[p_exp])
Beispiel #5
0
def test_invalid_discrete():
    dt = 0.001
    sys = cont2discrete(Lowpass(0.1), dt=dt)

    with pytest.raises(ValueError):
        discrete2cont(sys, dt=dt, method='gbt', alpha=1.1)

    with pytest.raises(ValueError):
        discrete2cont(sys, dt=0)

    with pytest.raises(ValueError):
        discrete2cont(sys, dt=dt, method=None)

    with pytest.raises(ValueError):
        discrete2cont(s, dt=dt)  # already continuous

    with pytest.raises(ValueError):
        cont2discrete(z, dt=dt)  # already discrete
def test_invalid_system():
    with pytest.raises(ValueError):
        HeteroSynapse(Lowpass(0.1))  # no dt provided
def test_hetero_multi_vector(Simulator, rng, seed):
    n_neurons = 20
    dt = 0.0005
    T = 0.1
    dims_in = 2
    synapses = [Alpha(0.1), Lowpass(0.005), Alpha(0.02)]

    dims_out = len(synapses) * dims_in
    encoders = sphere.sample(n_neurons, dims_out, rng=rng)

    with Network(seed=seed) as model:
        # Input stimulus
        stim = nengo.Node(size_in=dims_in)
        for i in range(dims_in):
            nengo.Connection(nengo.Node(
                output=nengo.processes.WhiteSignal(T, high=10, seed=seed)),
                             stim[i],
                             synapse=None)

        # HeteroSynapse Nodes
        syn_dot = nengo.Node(size_in=dims_in,
                             output=HeteroSynapse(synapses, dt))
        syn_elemwise = nengo.Node(size_in=dims_out,
                                  output=HeteroSynapse(np.repeat(
                                      synapses, dims_in),
                                                       dt,
                                                       elementwise=True))

        # For comparing results
        x = [
            nengo.Ensemble(n_neurons, dims_out, seed=0, encoders=encoders)
            for _ in range(3)
        ]  # expected, actual 1, actual 2

        # Expected
        for j, synapse in enumerate(synapses):
            nengo.Connection(stim,
                             x[0][j * dims_in:(j + 1) * dims_in],
                             synapse=synapse)

        # Actual (method #1 = matrix multiplies)
        nengo.Connection(stim, syn_dot, synapse=None)
        nengo.Connection(syn_dot, x[1], synapse=None)

        # Actual (method #2 = elementwise)
        for j in range(len(synapses)):
            nengo.Connection(stim,
                             syn_elemwise[j * dims_in:(j + 1) * dims_in],
                             synapse=None)
        nengo.Connection(syn_elemwise, x[2], synapse=None)

        # Probes
        p_exp = nengo.Probe(x[0], synapse=None)
        p_act_dot = nengo.Probe(x[1], synapse=None)
        p_act_elemwise = nengo.Probe(x[2], synapse=None)

    # Check correctness
    with Simulator(model, dt=dt) as sim:
        sim.run(T)

    assert np.allclose(sim.data[p_act_dot], sim.data[p_exp])
    assert np.allclose(sim.data[p_act_elemwise], sim.data[p_exp])
Beispiel #8
0
import pytest

from nengolib.signal.discrete import cont2discrete, discrete2cont
from nengolib.signal import s, z, ss_equal
from nengolib.synapses import Lowpass, Alpha, Highpass


@pytest.mark.parametrize(
    "sys", [Lowpass(0.1), Alpha(0.01), Highpass(0.01, order=4)])
def test_discrete(sys):
    dt = 0.001
    alpha = 0.6
    for method in ('gbt', 'bilinear', 'tustin', 'euler', 'forward_diff',
                   'backward_diff', 'zoh'):
        dsys = cont2discrete(sys, dt=dt, method=method, alpha=alpha)
        assert not dsys.analog
        rsys = discrete2cont(dsys, dt=dt, method=method, alpha=alpha)
        assert rsys.analog

        assert ss_equal(sys, rsys, atol=1e-07)


def test_invalid_discrete():
    dt = 0.001
    sys = cont2discrete(Lowpass(0.1), dt=dt)

    with pytest.raises(ValueError):
        discrete2cont(sys, dt=dt, method='gbt', alpha=1.1)

    with pytest.raises(ValueError):
        discrete2cont(sys, dt=0)
Beispiel #9
0
def figure_principle3(targets):
    theta = 0.1
    tau = 0.1 * theta
    lmbda = tau
    orders = range(6, 28)

    freqs = np.linspace(0.1 / theta, 16 / theta, 1000)
    s = 2.j * np.pi * freqs

    y = np.exp(-theta * s)
    Hinvs = (tau * s + 1) * np.exp(lmbda * s)

    cmap_lamb = sns.color_palette("GnBu_d", len(orders))[::-1]
    cmap_ignore = sns.color_palette("OrRd_d", len(orders))[::-1]

    data = np.empty((2, len(DISCRETE_DTS), DISCRETE_SEEDS))

    for seed in range(DISCRETE_SEEDS):
        for i, dt in enumerate(DISCRETE_DTS):
            npfile = np.load(DISCRETE_SIM % (seed, i))
            assert np.allclose(npfile['dt'], dt)
            delay = npfile['delay']
            # t = npfile['t']
            stim = npfile['stim']
            disc = npfile['disc']
            cont = npfile['cont']

            target = ideal_delay(stim, delay, dt)
            e_disc = nrmse(disc, target=target)
            e_cont = nrmse(cont, target=target)

            data[0, i, seed] = e_disc
            data[1, i, seed] = e_cont

    i = np.where(DISCRETE_DTS == 0.001)[0][0]
    assert np.allclose(DISCRETE_DTS[i], 0.001)
    e_disc = np.mean(data, axis=2)[0, i]
    e_cont = np.mean(data, axis=2)[1, i]
    improvement = (e_cont - e_disc) / e_cont * 100
    logging.info("Paper constant: Improvement at 1 ms: %s (%s -> %s)",
                 improvement, e_cont, e_disc)

    with sns.axes_style('ticks'):
        with sns.plotting_context('paper', font_scale=2.8):
            f, (ax1, ax2) = pylab.subplots(1, 2, figsize=(18, 5))

            ax1.set_title("Discrete Lowpass Improvement").set_y(1.05)

            for i, condition, cpal, marker in ((1, 'Principle 3',
                                                sns.color_palette("OrRd_d"),
                                                'X'),
                                               (0, 'Extension',
                                                sns.color_palette("GnBu_d"),
                                                'o')):
                sns.tsplot(data[i].T,
                           1000 * DISCRETE_DTS,
                           condition=condition,
                           color=cpal,
                           marker=marker,
                           markersize=15,
                           lw=3,
                           ci=95,
                           alpha=0.7,
                           ax=ax1)

            ax1.vlines([1.0],
                       np.min(data[0]),
                       2.0,
                       linestyle='--',
                       color='black',
                       lw=4,
                       alpha=0.7,
                       zorder=0)

            ax1.set_xlabel("Discrete Time-step [ms]", labelpad=20)
            ax1.set_ylabel("Absolute Error", labelpad=20)
            ax1.set_xlim(0, 1000 * DISCRETE_DTS[-1] + 0.1)

            ax2.set_title("Delayed Lowpass Improvement").set_y(1.05)

            for i, q in enumerate(orders):
                sys = PadeDelay(theta, order=q)
                mapped = ss2sim(sys, Lowpass(tau), dt=None)
                lambert = lambert_delay(theta, lmbda, tau, q - 1, q)

                y_lamb = lambert(Hinvs)
                y_ignore = mapped(Hinvs)

                ax2.semilogy(freqs * theta,
                             abs(y - y_ignore),
                             lw=2,
                             alpha=0.8,
                             zorder=len(orders) - i,
                             c=cmap_ignore[i])
                ax2.semilogy(freqs * theta,
                             abs(y - y_lamb),
                             lw=2,
                             alpha=0.8,
                             zorder=len(orders) - i,
                             c=cmap_lamb[i])

            lc_ignore = LineCollection(len(orders) * [[(0, 0)]],
                                       lw=10,
                                       colors=cmap_ignore)
            lc_lamb = LineCollection(len(orders) * [[(0, 0)]],
                                     lw=10,
                                     colors=cmap_lamb)
            ax2.legend([lc_ignore, lc_lamb], ['Principle 3', 'Extension'],
                       handlelength=2,
                       handler_map={LineCollection: HandlerDashedLines()})

            ax2.set_xlabel(r"Frequency $\times \, \theta$ [Hz $\times$ s]",
                           labelpad=20)

            sns.despine(offset=15)

            savefig(targets[0])
Beispiel #10
0
def figure_lambert(targets):
    npfile = np.load(LAMBERT_SIM)
    delay = npfile['delay']
    dt = npfile['dt']
    t = npfile['t']
    stim = npfile['stim']
    delayed = npfile['delayed']
    lowpass = npfile['lowpass']
    dexp = npfile['dexp']

    target = ideal_delay(stim, delay, dt)

    e_delayed = nrmse(delayed, target=target)
    e_lowpass = nrmse(lowpass, target=target)
    e_dexp = nrmse(dexp, target=target)

    improvement = (e_lowpass - e_delayed) / e_lowpass * 100
    logging.info("Paper constant: Lambert improvement: %s", improvement)
    logging.info("Paper constant: Delayed NRMSE: %s", e_delayed)
    logging.info("Paper constant: Lowpass NRMSE: %s", e_lowpass)
    logging.info("Paper constant: Double Exp NRMSE: %s", e_dexp)

    sample_rate = 100
    t = t[::sample_rate]
    stim = stim[::sample_rate]
    delayed = delayed[::sample_rate]
    lowpass = lowpass[::sample_rate]
    dexp = dexp[::sample_rate]
    target = target[::sample_rate]

    tau_over_theta = 0.1
    lambda_over_tau = 1.0
    max_freq_times_theta = 4.0
    theta = 0.1  # <-- the graph is still the same, no matter theta!
    tau = tau_over_theta * theta
    lmbda = lambda_over_tau * tau
    max_freq = max_freq_times_theta / theta
    tau2 = tau / 5  # TODO: parameters copied from delayed_synapse()
    q = 6
    assert np.allclose(tau, 0.01)
    assert np.allclose(lmbda, 0.01)

    freqs = np.linspace(0, max_freq, 200)
    s = 2.j * np.pi * freqs
    axis = freqs * theta  # scale-invariant axis

    lw = 3
    alpha = 0.8
    cmap = sns.color_palette(None, 4)

    F_lamb = lambert_delay(theta, lmbda, tau, q - 1, q)
    F_low = ss2sim(PadeDelay(theta, order=q), Lowpass(tau), dt=None)
    F_alpha = ss2sim(PadeDelay(theta, order=q), DoubleExp(tau, tau2), dt=None)

    y_low = F_low(tau * s + 1)
    y_lamb = F_lamb((tau * s + 1) * np.exp(lmbda * s))
    y_alpha = F_alpha((tau * s + 1) * (tau2 * s + 1))
    y = np.exp(-theta * s)

    # Compute where lmbda*s + lmbda/tau is within the principal branch
    tx = lmbda * 2 * np.pi * freqs
    st = (lmbda / tau > -(tx / np.tan(tx))) & (tx < np.pi) | (tx == 0)
    p = lmbda * s[st] + lmbda / tau
    assert np.allclose(lambertw(p * np.exp(p)), p)

    with sns.axes_style('ticks'):
        with sns.plotting_context('paper', font_scale=2.8):
            pylab.figure(figsize=(18, 5))
            gs = gridspec.GridSpec(1, 2, width_ratios=[1, 1.618])
            gs.update(wspace=0.3)
            ax1 = plt.subplot(gs[1])
            ax2 = plt.subplot(gs[0])

            ax1.set_title(r"$0.1\,$s Delay of $15\,$Hz White Noise").set_y(
                1.05)
            ax1.plot(t, target, lw=4, c=cmap[0], zorder=4, linestyle='--')
            ax1.plot(t, lowpass, alpha=alpha, c=cmap[1], zorder=2)
            ax1.plot(t, dexp, alpha=alpha, c=cmap[3], zorder=2)
            ax1.plot(t, delayed, alpha=alpha, c=cmap[2], zorder=3)
            ax1.set_ylim(-0.5, 0.5)
            ax1.set_xlabel("Time [s]", labelpad=20)
            ax1.set_ylabel("Output")

            ax2.set_title("Delay Accuracy").set_y(1.05)
            ax2.plot(axis,
                     np.zeros_like(freqs),
                     lw=lw,
                     c=cmap[0],
                     zorder=4,
                     linestyle='--',
                     label=r"Ideal")
            ax2.plot(axis,
                     abs(y - y_low),
                     lw=lw,
                     alpha=alpha,
                     c=cmap[1],
                     zorder=3,
                     label=r"Lowpass")
            ax2.plot(axis,
                     abs(y - y_alpha),
                     lw=lw,
                     alpha=alpha,
                     c=cmap[3],
                     zorder=3,
                     label=r"Double-exponential")
            ax2.plot(axis,
                     abs(y - y_lamb),
                     lw=lw,
                     alpha=alpha,
                     c=cmap[2],
                     zorder=3,
                     label=r"Delayed Lowpass")

            s = 0.8
            pts = np.asarray([[1.5, 0], [1.5 - s, -s], [1.5 + s, -s]])
            ax2.add_patch(Polygon(pts, closed=True, color='black'))

            ax2.set_xlabel(r"Frequency $\times \, \theta$ [Hz $\times$ s]",
                           labelpad=20)
            ax2.set_ylabel(r"Absolute Error", labelpad=20)

            ax2.legend(loc='upper left',
                       frameon=True).get_frame().set_alpha(0.8)

            sns.despine(offset=15)

            savefig(targets[0])