Hi @bernd,
I’m not entirely sure what you are trying to accomplish. From your code, it seems like you have constructed a connection between an oscillator and an integrator with a specific function applied to the connection? And it looks like this function takes the 2D coordinate point of the oscillator, and turns it into a ramp signal, which is then used to determine what the output of the piecewise function should be?
So… in essence, what you are looking to do is to have something generate a customizable piecewise function that you can feed into the integrator? Are you looking to have this entirely in neurons?
If you are okay with using a nengo.Node
to make a customizable piecewise function, then something like this should suffice:
def custom_piecewise(t, x):
t1, t2, ampl = x
if t < t1 or t >= t2:
return 0
else:
return ampl
pw_node = nengo.Node(size_in=3, output=custom_piecewise)
nengo.Connection(val_t1, pw_node[0])
nengo.Connection(val_t2, pw_node[1])
nengo.Connection(ampl1, pw_node[2])
nengo.Connection(pw_node, BAP_syll01_conn1)
If, however, you want to implement it in neurons, there are a few ways to do it. I gave it some thought, and I think the most straightforward way is to leverage what you already have implemented in your network. Right now, you have the oscillator connected to the integrator with a connection function that turns the oscillator output into the piecewise signal:
oscillator --> connection function --> integrator
My thought is to introduce an intermediary ensemble to modify the output of the oscillator, like so:
val_t1 ------------+
val_t2 ----------+ |
ampl ----------+ | |
V V V
oscillator --> modulator --> connection function --> integrator
The goal of this “modulator” ensemble is to adjust the output of the oscillator based off the values of val_t1
, val_t2
, and ampl
. For example, let’s say the oscillator takes 1s to do one cycle. Let’s also say that in the connection function, you configure it so that the output is like this piecewise({0:[0], 0.5:[1.0], 1.0:[0]}
(so, default values are val_t1=0.5
, val_t2=1
, ampl=1
). Let’s also assume the oscillator starts at [0, 1] and cycles counter clockwise.
Now, let’s say you changed the output of the val
and ampl
ensembles to something different. Suppose you wanted val_t1=0.25
, val_t2=0.5
, ampl=1
. What the “modulator” ensemble should be tasked to compute is the mapping between the input oscillator values, and the output oscillator values. So, if the modulator ensemble maps an input of [1, 0] to an output of [0, -1], and an input of [0, -1] to an output of [0, 1], we should observe that as the oscillator cycles, it will produce the modified piecewise function that we wanted. Do I make any sense?
An alternate approach to this is to connect several ensembles (some with thresholds, some that are integrators, etc.) to form the piecewise function. The dynamics of these ensembles can then be controlled by the outputs of val_t1
, val_t2
, and ampl
. As an example, we could use the output of ampl
to get the amplitude of the piecewise function. Then, use a fast-decaying integrator (where the decay time is controlled by val_t1
, which should be doable if val_t1
determines the initial value in the integrator) to inhibit ampl
. This sets up the initial “0” value for the time until val_t1
. For val_t2
, we could have a regular integrator integrate to a specific threshold. Once it reaches this threshold, it triggers an inhibition on ampl
to then bring the function back to 0.
As to your question:
I’m not entirely sure what you are asking here… In Nengo, if you use “standard” connections (i.e., not connecting to the .neurons
object), the values being transmitted between ensembles is already decoded.