Non-FGPA version of Adaptive Pendulum example

Following up on a suggestion from Terry at the 2018 Summer School, I’m trying to build adaptive PID controllers for quadcopter simulations. As usual, I’m trying to modify a simpler, working example to get started. The closest example I was able to find uses nengo-fpga. Although I’m interested in using FPGAs in my neumorphic computing course at some point, right now I don’t have access to one. Can anyone provide a code snippet to serve as a drop-in replacement for the FpgaPesEnsembleNetwork with ordinary Nengo?

Hi @simondlevy,

This page in the NengoFPGA documentation details how standard Nengo code can be converted into an equivalent FpgaPesEnsembleNetwork, so you can use it to reverse-engineer the FpgaPesEnsembleNetwork.

Generally, the FpgaPesEnsembleNetwork can be replaced with a standard Nengo ensemble, with care needed only when learning is enabled. Internally, when the learning rate is non-zero, the FpgaPesEnsembleNetwork creates an output connection with the PES learning rule applied to it, so if you want to replace the FpgaPesEnsembleNetwork with a Nengo ensemble, you’ll have to replicate that.

For the adaptive pendulum example in particular, it uses the PES learning rule, so one FpgaPesEnsembleNetwork can be replaced with this:

    with nengo.Network() as adapt_ens:
        n_neurons = 1000
        dimensions = 1
        learning_rate = 1e-5
        output_func = lambda x: [0]

        # Inputs and outputs from the `adapt_ens` network
        adapt_ens.input = nengo.Ensemble(n_neurons, dimensions)
        adapt_ens.error = nengo.Node(size_in=1)
        adapt_ens.output = nengo.Node(size_in=1)

        # Connection to output node (note, weights initialized to zero using the
        # function argument)
        conn = nengo.Connection(
            adapt_ens.input,
            adapt_ens.output,
            synapse=None,
            function=output_func,
        )

        # Add the learning rule on the output connection
        conn.learning_rule_type = nengo.PES(learning_rate=learning_rate)

        # Connect the error into the learning rule
        nengo.Connection(adapt_ens.error, conn.learning_rule)

Thanks, Xuan. I’m a seasoned Python programmer, but my Nengo skills are unfortunately so weak at this point that anything but a complete working example (the entire pendulum program with the fpga_net_equiv swapped in for the original FPGA-based network) is of no help to me. I’ve spent the past hour trying to incorporate your example code (and the original code to which you link), but no luck.

The code above is designed to be ploppable into any NengoFPGA code using a FpgaPesEnsembleNetwork network (all you will need to change the parameters the network is initialized with, and the object variable name).

As an example, in the adaptive pendulum code, you just replace this:

    adapt_ens = FpgaPesEnsembleNetwork(
        board,
        n_neurons=1000,
        dimensions=1,
        learning_rate=1e-5,
        function=lambda x: [0],
        label="pes ensemble",
    )

with this:

    with nengo.Network() as adapt_ens:
        n_neurons = 1000
        dimensions = 1
        learning_rate = 1e-5
        output_func = lambda x: [0]

        # Inputs and outputs from the `adapt_ens` network
        adapt_ens.input = nengo.Ensemble(n_neurons, dimensions)
        adapt_ens.error = nengo.Node(size_in=1)
        adapt_ens.output = nengo.Node(size_in=1)

        # Connection to output node (note, weights initialized to zero using the
        # function argument)
        conn = nengo.Connection(
            adapt_ens.input,
            adapt_ens.output,
            synapse=None,
            function=output_func,
        )

        # Add the learning rule on the output connection
        conn.learning_rule_type = nengo.PES(learning_rate=learning_rate)

        # Connect the error into the learning rule
        nengo.Connection(adapt_ens.error, conn.learning_rule)

Here’s the modified python file for you to run and compare with the original:
01-adaptive-pendulum2.py (7.2 KB)

Thanks, Xuan, that worked perfectly! I appreciate your help and patience.

That’s great to hear! :smiley: