Function inputs in Nengo

Hi everyone.

From what I learned so far, functions in Nengo can only have one argument. I have difficulty defining functions with two arguments especially when one of them is time. Could you please tell me how to define functions with two arguments?

Hi @smjh1371,

In Nengo, you are correct in the understanding that, generally, functions passed to connection objects can only contain 1 argument (x). To compute a function of more than one argument, what you’d want to do is to use a multi-dimensional input, and project some of the function arguments to a subset of the dimensions, and the other function arguments to the other subset of the dimensions. Then, when you compute the function, it will be a function of different dimensions of x.

The multiplication example how this process is used to build a network to compute the product y = a \times b. In that example, an ensemble (combined) is created to represent the vector [a, b].

combined = nengo.Ensemble(
    220, dimensions=2, radius=15
)  # This radius is ~sqrt(10^2+10^2)

Next a is projected onto the first element of the vector, and b is projected onto the second element of the vector:

nengo.Connection(A, combined[0])
nengo.Connection(B, combined[1])

Finally, the function that is passed to the connection to compute is y = x[0] * x[1]:

# Define a function that computes the multiplication of two inputs
def product(x):
    return x[0] * x[1]

# Connect the combined ensemble to the output ensemble D
nengo.Connection(combined, prod, function=product)

Thanks for your response. I have another question. Maybe I should start a new topic for that.
I have defined a dynamic model within an ensemble and simulate it with only initial conditions with no error. Inside the model there is a term which is the controller of the system. The calculation of the controller are done using the states of the system somewhere outside the main system’s ensemble. Now I’m not sure how to feedback this controller function into my model ensemble. Could you please help me with this? I mean without Nengo I know how to call a function and it worked but now I have no clue! I hope I made my question clear.

I believe I attempted to address your other question (about the dynamical model within Nengo) in this forum thread.

I’m not sure if I mentioned it in that other thread, but it would really help to have some example of how you have coded this dynamic system. You don’t have to provide the exact code you are using, a simple version of the controller (even a system that doesn’t do anything, but illustrates how the inputs and outputs are connected and used) will be helpful.

Let me ask it this way, then if it’s not clear I will share the code to make it clear. I want to call a function inside another function. But I get an error. I defined my model as one function and my controller as another function. I want to call the controller function inside the model function. Is that possible? My controller is a function of two variables.

My model is like this:

def model(x):
        
        dw = np.dot(np.linalg.inv(np.eye(3)), tau(k)) - np.dot(np.linalg.inv(np.eye(3)),(np.cross(w, np.dot(I_cm, w))))

        return dw

Inside the model I have the “tau” function which does some calculations and takes another ensemble as an input:

def tau(k):

        tau_temp = k

        q_a = np.array(k[0:3])
        w_a = np.array(k3:6])

        P_q = 20
        P_w = 4

        if q_a[0]< 0:

            ...

            tau = - P_q * ...

        else:

            tau = - P_q *...

        return tau

I don’t know how to feed this tau function into the model! I tried saving tau data in an ensemble but I still have no idea how to make a connection between my model and the tau !

I’m still a little uncertain as to what you are trying to accomplish… Perhaps a block diagram description of what connects to what would be better at explaining it.

As for your question, if you have a function call another function, you don’t necessarily need to do anything special to get them to work in Nengo, as long as you understand the Python contexts in which they are used. The least error prone way to get a function within a function to work in Nengo is to embed both functions into a class, like so:

class MyClass:
    def __init__(self):
        ...

    def tau(self, k):
        ...

    def model(self, x):
        # Has a function call that calls self.tau(k)
        ...

If you define such a class, you can then instantiate the class, and pass the relevant function to use in the Nengo network:

myclass = MyClass()

with nengo.Network() as model:
    my_node = nengo.Node(myclass.model)
    ...

In the code above, the my_node Nengo node is created to execute the myclass.model() function in every timestep of the Nengo simulation.

Can you clarify what you mean by this statement? Are you trying to modify the behaviour of the tau function based on the outputs of an Nengo ensemble? If you are, using the class approach I outlined above should allow you to do this. Simply use the tau function in another Nengo node, like so:

myclass = MyClass()

with nengo.Network() as model:
    my_node = nengo.Node(myclass.model)
    tau_node = nengo.Node(size_in=<dimension>, output=myclass.tau)
    ...
    nengo.Connection(..., tau_node)

Thanks. I should define all my functions before

with nengo.Network() as model:

is that correct?

And to answer your question:

Are you trying to modify the behaviour of the tau function based on the outputs of an Nengo ensemble?

yes I need a feedback from the system to update this term. This is the controller.

I have another question about this part

nengo.Connection(..., tau_node)

As you can see in the part of the code I shared tau is a term in the model.

def model(x):
        
        dw = np.dot(np.linalg.inv(np.eye(3)), tau(k)) - np.dot(np.linalg.inv(np.eye(3)),(np.cross(w, np.dot(I_cm, w))))

        return dw

In python regular code without nengo when I called tau it was ok. But I still don’t understand this connection you made

nengo.Connection(…, tau_node)

This is my main problem when using GUI. I don’t know if I want to make a connection between the tau and the system where should it go? Because before I was not worried about this!

And one more thing, so if I have my whole code in regular python programming, just by using the following format I can put it into Nengo? Is that correct?

class MyClass:
    def __init__(self):
        ...

    def tau(self, k):
        ...

    def model(self, x):

another issue is that I used “model” as the name for my system and also you used model in this line

with nengo.Network() as model:

I’m confused a little about it. the model in this line

my_node = nengo.Node(myclass.model)

is my system? correct ?

One very important question is Can I define the class inside the nengo.Network? I need an x ensemble to represent the states. If I define the class outside the nengo.Network, how can I use the x ensemble which should be in the nengo.Network?!!!

Nengo models are defined in a Python script, so as long as your functions / classes are defined before they need to be used (or called), then it should work. It doesn’t really matter if you define it inside or outside of the with nengo.Network() as model block.

This really depends on how you want to implement your model. Nengo will interpret Python code the same way as regular Python code. Especially if you put everything in a class (see my post above). If the tau function does not need to be modified by the outputs of a Nengo ensemble, then simply calling tau(k) in your dynamical system should work. One thing I did note is that you didn’t actually define k (nor w or I_cm) in your model(x) function. I assume that this means they are global constants of some kind? If they are, simply put them into the class like so:

class MyClass:
    def __init__(self):
        self.k = ...
        self.w = ...
        self.I_cm = ...

    def tau(self, k):
        ...

    def model(self, x):
        # Has a function call that calls self.tau(self.k)
        ...

If, however, these variables (k, I_cm, w) are meant to be the outputs of Nengo ensembles, then you’ll need to modify your class with additional “setter” functions to be able to grab data from the Nengo objects, and “save” them in the class. For example, if you add a set_k function like so:

class MyClass:
    def __init__(self):
        self.k = ...
        self.w = ...
        self.I_cm = ...

    def set_k(self, value):
        self.k = value

    def tau(self, k):
        ...

    def model(self, x):
        ...

You can then create a Nengo node with the set_k function, and connect to it to feed values to your class:

with nengo.Network() as model:
    ...
    set_k_node = nengo.Node(myclass.set_k, size_in=1)
    ens_k = nengo.Ensemble(...)
    nengo.Connection(ens_k, set_k_node)
    ...

In the Nengo code snippet above, the set_k_node runs the myclass.set_k function every Nengo timestep, and if you look in the MyClass.set_k function definition, you see that every time the function is run, it takes the value value and “saves” it to self.k. And since there is a nengo.Connection from ens_ktoset_k_node, what this achieves is to "save" the output of ens_kintomyclass.k` for every Nengo timestep. You should experiment with this feature (just by itself) to understand how it works.

Yes. This is fine. Nengo interprets this code like standard Python, and in that context, model is not the same as myclass.model (they are two different objects).

I believe I answered this above. See the example about set_k.

Based on your questions, it seems like you are still getting familiar with Nengo (and Python). I recommend you check out the Nengo summer school lectures to get a better understanding of Nengo, and neural networks built in Nengo.

Thanks for your comments. I have watched the Nengo summer school lectures several times. Those are about basic examples and unfortunately I could not benefit from those lectures.