Nengo is designed so that models created with the Nengo frontend API work on a variety of different simulators, or “backends.” For example, backends have been created to take advantage of GPUs and neuromorphic hardware.
Nengo comes with a backend that is relatively fast,
and works on general purpose computers.
For most users, the only thing that you need to know
about this “reference” backend is how to
create and close a nengo.Simulator
instance.
nengo.
Simulator
(network, dt=0.001, seed=None, model=None, progress_bar=True, optimize=True)[source]¶Reference simulator for Nengo models.
The simulator takes a Network
and builds internal data structures to
run the model defined by that network. Run the simulator with the
run
method, and access probed data through the
data
attribute.
Building and running the simulation may allocate resources like files
and sockets. To properly free these resources, call the Simulator.close
method. Alternatively, Simulator.close
will automatically be called
if you use the with
syntax:
with nengo.Simulator(my_network) as sim:
sim.run(0.1)
print(sim.data[my_probe])
Note that the data
attribute is still accessible even when a simulator
has been closed. Running the simulator, however, will raise an error.
Parameters: |
|
---|---|
Attributes: |
|
dt
¶(float) The time step of the simulator.
n_steps
¶(int) The current time step of the simulator.
time
¶(float) The current time of the simulator.
close
()[source]¶Closes the simulator.
Any call to Simulator.run
, Simulator.run_steps
,
Simulator.step
, and Simulator.reset
on a closed simulator raises
a SimulatorClosed
exception.
reset
(seed=None)[source]¶Reset the simulator state.
Parameters: |
|
---|
run
(time_in_seconds, progress_bar=None)[source]¶Simulate for the given length of time.
If the given length of time is not a multiple of dt
,
it will be rounded to the nearest dt
. For example, if dt
is 0.001 and run
is called with time_in_seconds=0.0006
,
the simulator will advance one timestep, resulting in the actual
simulator time being 0.001.
The given length of time must be positive. The simulator cannot be run backwards.
Parameters: |
|
---|
run_steps
(steps, progress_bar=None)[source]¶Simulate for the given number of dt
steps.
Parameters: |
|
---|
trange
(dt=None)[source]¶Create a vector of times matching probed data.
Note that the range does not start at 0 as one might expect, but at
the first timestep (i.e., dt
).
Parameters: |
|
---|
The build process translates a Nengo model
to a set of data buffers (Signal
instances)
and computational operations (Operator
instances)
which implement the Nengo model
defined with the frontend API.
The build process is central to
how the reference simulator works,
and details how Nengo can be extended to include
new neuron types, learning rules, and other components.
Bekolay et al., 2014 provides a high-level description of the build process. For lower-level details and reference documentation, read on.
nengo.builder.
Signal
(initial_value, name=None, base=None, readonly=False, offset=0)[source]¶Represents data or views onto data within a Nengo simulation.
Signals are tightly coupled to NumPy arrays, which is how live data is represented in a Nengo simulation. Signals provide a view onto the important metadata of the live NumPy array, and maintain the original value of the array in order to reset the simulation to the initial state.
Parameters: |
|
---|
base
¶(Signal or None) The base signal, if this signal is a view.
Linking the two signals with the base
argument is necessary
to ensure that their live data is also linked.
dtype
¶(numpy.dtype) Data type of the signal (e.g., float64).
elemoffset
¶(int) Offset of data from base in elements.
elemstrides
¶(int) Strides of data in elements.
initial_value
¶(numpy.ndarray) Initial value of the signal.
Much of the metadata tracked by the Signal is based on this array as well (e.g., dtype).
is_view
¶(bool) True if this Signal is a view on another Signal.
itemsize
¶(int) Size of an array element in bytes.
name
¶(str) Name of the signal. Primarily used for debugging.
nbytes
¶(int) Number of bytes consumed by the signal.
ndim
¶(int) Number of array dimensions.
offset
¶(int) Offset of data from base in bytes.
For a signal view this gives the offset of the view from the base
initial_value
in bytes. This might differ from the offset
of the NumPy array view provided as initial_value
if the base
is a view already (in which case the signal base offset will be 0
because it starts where the view starts. That NumPy view can have
an offset of itself).
readonly
¶(bool) Whether associated live data can be changed.
shape
¶(tuple) Tuple of array dimensions.
size
¶(int) Total number of elements.
strides
¶(tuple) Strides of data in bytes.
Determine if two signals might overlap in memory.
This comparison is not exact and errs on the side of false positives.
See numpy.may_share_memory
for more details.
Parameters: |
|
---|
reshape
(*shape)[source]¶Return a view on this signal with a different shape.
Note that reshape
cannot change the overall size of the signal.
See numpy.reshape
for more details.
Any number of integers can be passed to this method, describing the desired shape of the returned signal.
nengo.builder.
Operator
(tag=None)[source]¶Base class for operator instances understood by Nengo.
During one simulator timestep, a Signal
can experience
in this specific order.
A set
defines the state of the signal at time \(t\), the start
of the simulation timestep. That state can then be modified by
increment
operations. A signal’s state will only be read
after
all increments are complete. The state is then finalized by an update
,
which denotes the state that the signal should be at time \(t + dt\).
Each operator must keep track of the signals that it manipulates, and which of these four types of manipulations is done to each signal so that the simulator can order all of the operators properly.
Note
There are intentionally no default values for the
reads
, sets
, incs
,
and updates
properties to ensure that subclasses
explicitly set these values.
Parameters: |
|
---|---|
Attributes: |
|
incs
¶Signals incremented by this operator.
Increments will be applied after sets (if it is set), and before reads.
reads
¶Signals that are read and not modified by this operator.
Reads occur after increments, and before updates.
sets
¶Signals set by this operator.
Sets occur first, before increments. A signal that is set here cannot be set or updated by any other operator.
updates
¶Signals updated by this operator.
Updates are the last operation to occur to a signal.
init_signals
(signals)[source]¶Initialize the signals associated with this operator.
The signals will be initialized into signals
.
Operator subclasses that use extra buffers should create them here.
Parameters: |
|
---|
make_step
(signals, dt, rng)[source]¶Returns a callable that performs the desired computation.
This method must be implemented by subclasses. To fully understand what
an operator does, look at its implementation of make_step
.
Parameters: |
|
---|
nengo.builder.operator.
Reset
(dst, value=0, tag=None)[source]¶Assign a constant value to a Signal.
Implements dst[...] = value
.
Parameters: |
|
---|
Notes
[dst]
[]
[]
[]
Attributes: |
|
---|
nengo.builder.operator.
Copy
(src, dst, src_slice=None, dst_slice=None, inc=False, tag=None)[source]¶Assign the value of one signal to another, with optional slicing.
Implements:
dst[:] = src
dst[dst_slice] = src[src_slice]
(when dst_slice
or src_slice
is not None)dst[dst_slice] += src[src_slice]
(when inc=True
)Parameters: |
|
---|
Notes
[] if inc else [dst]
[dst] if inc else []
[src]
[]
Attributes: |
|
---|
nengo.builder.operator.
ElementwiseInc
(A, X, Y, tag=None)[source]¶Increment signal Y
by A * X
(with broadcasting).
Implements Y[...] += A * X
.
Parameters: |
|
---|
Notes
[]
[Y]
[A, X]
[]
Attributes: |
|
---|
nengo.builder.operator.
DotInc
(A, X, Y, reshape=None, tag=None)[source]¶Increment signal Y
by dot(A, X)
.
Implements Y[...] += np.dot(A, X)
.
Note
Currently, this only supports matrix-vector multiplies for compatibility with Nengo OCL.
Parameters: |
|
---|
Notes
[]
[Y]
[A, X]
[]
Attributes: |
|
---|
nengo.builder.operator.
BsrDotInc
(A, X, Y, indices, indptr, reshape=None, tag=None)[source]¶Increment signal Y by dot(A, X) using block sparse row format.
Implements Y[...] += np.dot(A, X)
, where A
is an instance
of scipy.sparse.bsr_matrix
.
Note
Requires SciPy.
Note
Currently, this only supports matrix-vector multiplies for compatibility with Nengo OCL.
Parameters: |
|
---|
Notes
[]
[Y]
[A, X]
[]
Attributes: |
|
---|
nengo.builder.operator.
TimeUpdate
(step, time, tag=None)[source]¶Updates the simulation step and time.
Implements step[...] += 1
and time[...] = step * dt
.
A separate operator is used (rather than a combination of Copy
and
DotInc
) so that other backends can manage these important parts of the
simulation state separately from other signals.
Parameters: |
|
---|
Notes
[step, time]
[]
[]
[]
Attributes: |
|
---|
nengo.builder.operator.
SimPyFunc
(output, fn, t, x, tag=None)[source]¶Apply a Python function to a signal, with optional arguments.
Implements output[...] = fn(*args)
where args
can
include the current simulation time t
and an input signal x
.
Note that output
may also be None, in which case the function is
called but no output is captured.
Parameters: |
|
---|
Notes
[] if output is None else [output]
[]
([] if t is None else [t]) + ([] if x is None else [x])
[]
Attributes: |
|
---|
nengo.builder.neurons.
SimNeurons
(neurons, J, output, states=None, tag=None)[source]¶Set a neuron model output for the given input current.
Implements neurons.step_math(dt, J, output, *states)
.
Parameters: |
|
---|
Notes
[output] + states
[]
[J]
[]
Attributes: |
|
---|
nengo.builder.learning_rules.
SimBCM
(pre_filtered, post_filtered, theta, delta, learning_rate, tag=None)[source]¶Calculate connection weight change according to the BCM rule.
Implements the Bienenstock-Cooper-Munroe learning rule of the form
where
Parameters: |
|
---|
Notes
[]
[]
[pre_filtered, post_filtered, theta]
[delta]
Attributes: |
|
---|
nengo.builder.learning_rules.
SimOja
(pre_filtered, post_filtered, weights, delta, learning_rate, beta, tag=None)[source]¶Calculate connection weight change according to the Oja rule.
Implements the Oja learning rule of the form
where
Parameters: |
|
---|
Notes
[]
[]
[pre_filtered, post_filtered, weights]
[delta]
Attributes: |
|
---|
nengo.builder.learning_rules.
SimVoja
(pre_decoded, post_filtered, scaled_encoders, delta, scale, learning_signal, learning_rate, tag=None)[source]¶Simulates a simplified version of Oja’s rule in the vector space.
See Learning new associations for details.
Parameters: |
|
---|
Notes
[]
[]
[pre_decoded, post_filtered, scaled_encoders, learning_signal]
[delta]
Attributes: |
|
---|
nengo.builder.processes.
SimProcess
(process, input, output, t, mode='set', tag=None)[source]¶Simulate a process.
Parameters: |
|
---|
Notes
[output] if output is not None and mode=='set' else []
[output] if output is not None and mode=='inc' else []
[t, input] if input is not None else [t]
[output] if output is not None and mode=='update' else []
Attributes: |
|
---|
nengo.builder.
Builder
[source]¶Manages the build functions known to the Nengo build process.
Consists of two class methods to encapsulate the build function registry.
All build functions should use the Builder.register
method as a
decorator. For example:
@nengo.builder.Builder.register(MyRule)
def build_my_rule(model, my_rule, rule):
...
registers a build function for MyRule
objects.
Build functions should not be called directly, but instead called through
the Model.build
method. Model.build
uses the Builder.build
method
to ensure that the correct build function is called based on the type of
the object passed to it.
For example, to build the learning rule type my_rule
from above, do:
model.build(my_rule, connection.learning_rule)
This will call the build_my_rule
function from above with the arguments
model, my_rule, connection.learning_rule
.
Attributes: |
|
---|
build
(model, obj, *args, **kwargs)[source]¶Build obj
into model
.
This method looks up the appropriate build function for obj
and
calls it with the model and other arguments provided.
Note that if a build function is not specified for a particular type
(e.g., EnsembleArray
), the type’s method resolution order will be
examined to look for superclasses
with defined build functions (e.g., Network
in the case of
EnsembleArray
).
This indirection (calling Builder.build
instead of the build
function directly) enables users to augment the build process in their
own models, rather than having to modify Nengo itself.
In addition to the parameters listed below, further positional and keyword arguments will be passed unchanged into the build function.
Parameters: |
|
---|
nengo.builder.
Model
(dt=0.001, label=None, decoder_cache=None, builder=None)[source]¶Stores artifacts from the build process, which are used by Simulator
.
Parameters: |
|
---|---|
Attributes: |
|
add_op
(op)[source]¶Add an operator to the model.
In addition to adding the operator, this method performs additional
error checking by calling the operator’s make_step
function.
Calling make_step
catches errors early, such as when signals are
not properly initialized, which aids debugging. For that reason,
we recommend calling this method over directly accessing
the operators
attribute.
build
(obj, *args, **kwargs)[source]¶Build an object into this model.
See Builder.build
for more details.
Parameters: |
|
---|
has_built
(obj)[source]¶Returns true if the object has already been built in this model.
Note
Some objects (e.g. synapses) can be built multiple times,
and therefore will always result in this method returning
False
even though they have been built.
This check is implemented by checking if the object is in the
params
dictionary. Build function should therefore add themselves
to model.params
if they cannot be built multiple times.
Parameters: |
|
---|
nengo.builder.network.
build_network
(model, network, progress=None)[source]¶Builds a Network
object into a model.
The network builder does this by mapping each high-level object to its associated signals and operators one-by-one, in the following order:
Before calling any of the individual objects’ build functions, random number seeds are assigned to objects that did not have a seed explicitly set by the user. Whether the seed was assigned manually or automatically is tracked, and the decoder cache is only used when the seed is assigned manually.
Parameters: |
|
---|
Notes
Sets model.params[network]
to None
.
nengo.builder.ensemble.
build_ensemble
(model, ens)[source]¶Builds an Ensemble
object into a model.
A brief summary of what happens in the ensemble build process, in order:
Some of these steps may be altered or omitted depending on the parameters
of the ensemble, in particular the neuron type. For example, most steps are
omitted for the Direct
neuron type.
Parameters: |
|
---|
Notes
Sets model.params[ens]
to a BuiltEnsemble
instance.
nengo.builder.ensemble.
BuiltEnsemble
[source]¶Collects the parameters generated in build_ensemble
.
These are stored here because in the majority of cases the equivalent
attribute in the original ensemble is a Distribution
. The attributes
of a BuiltEnsemble are the full NumPy arrays used in the simulation.
See the Ensemble
documentation for more details on each parameter.
Parameters: |
|
---|
nengo.builder.node.
build_node
(model, node)[source]¶Builds a Node
object into a model.
The node build function is relatively simple. It involves creating input
and output signals, and connecting them with an Operator
that depends
on the type of node.output
.
Parameters: |
|
---|
Notes
Sets model.params[node]
to None
.
nengo.builder.connection.
build_connection
(model, conn)[source]¶Builds a Connection
object into a model.
A brief summary of what happens in the connection build process, in order:
Some of these steps may be altered or omitted depending on the parameters of the connection, in particular the pre and post types.
Parameters: |
|
---|
Notes
Sets model.params[conn]
to a BuiltConnection
instance.
nengo.builder.connection.
BuiltConnection
[source]¶Collects the parameters generated in build_connection
.
These are stored here because in the majority of cases the equivalent
attribute in the original connection is a Distribution
. The attributes
of a BuiltConnection are the full NumPy arrays used in the simulation.
See the Connection
documentation for more details on each parameter.
Note
The decoders
attribute is obsolete as of Nengo 2.1.0.
Use the weights
attribute instead.
Parameters: |
|
---|
nengo.builder.probe.
build_probe
(model, probe)[source]¶Builds a Probe
object into a model.
Under the hood, there are two types of probes: connection probes and signal probes.
Connection probes are those that are built by creating a new Connection
object from the probe’s target to the probe, and calling that connection’s
build function. Creating and building a connection ensure that the result
of probing the target’s attribute is the same as would result from that
target being connected to another object.
Signal probes are those that are built by finding the correct Signal
in the model and calling the build function corresponding to the probe’s
synapse.
Parameters: |
|
---|
Notes
Sets model.params[probe]
to a list.
Simulator
appends to that list when running a simulation.
nengo.builder.neurons.
build_neurons
(model, neurontype, neurons)[source]¶Builds a NeuronType
object into a model.
This build function works with any NeuronType
that does not require
extra state, like RectifiedLinear
and LIFRate
. This function adds a
SimNeurons
operator connecting the input current to the
neural output signals.
Parameters: |
|
---|
Notes
Does not modify model.params[]
and can therefore be called
more than once with the same NeuronType
instance.
nengo.builder.neurons.
build_lif
(model, lif, neurons)[source]¶Builds a LIF
object into a model.
In addition to adding a SimNeurons
operator, this build function sets up
signals to track the voltage and refractory times for each neuron.
Parameters: |
|
---|
Notes
Does not modify model.params[]
and can therefore be called
more than once with the same LIF
instance.
nengo.builder.neurons.
build_alifrate
(model, alifrate, neurons)[source]¶Builds an AdaptiveLIFRate
object into a model.
In addition to adding a SimNeurons
operator, this build function sets up
signals to track the adaptation term for each neuron.
Parameters: |
|
---|
Notes
Does not modify model.params[]
and can therefore be called
more than once with the same AdaptiveLIFRate
instance.
nengo.builder.neurons.
build_alif
(model, alif, neurons)[source]¶Builds an AdaptiveLIF
object into a model.
In addition to adding a SimNeurons
operator, this build function sets up
signals to track the voltage, refractory time, and adaptation term
for each neuron.
Parameters: |
|
---|
Notes
Does not modify model.params[]
and can therefore be called
more than once with the same AdaptiveLIF
instance.
nengo.builder.neurons.
build_izhikevich
(model, izhikevich, neurons)[source]¶Builds an Izhikevich
object into a model.
In addition to adding a SimNeurons
operator, this build function sets up
signals to track the voltage and recovery terms for each neuron.
Parameters: |
|
---|
Notes
Does not modify model.params[]
and can therefore be called
more than once with the same Izhikevich
instance.
nengo.builder.learning_rules.
build_learning_rule
(model, rule)[source]¶Builds a LearningRule
object into a model.
A brief summary of what happens in the learning rule build process, in order:
The learning rule system is designed to work with multiple learning rules
on the same connection. If only one learning rule was to be applied to the
connection, then we could directly modify the weights, rather than
calculating the delta here and applying it in build_connection
.
However, with multiple learning rules, we must isolate each delta signal
in case calculating the delta depends on the weights themselves,
making the calculation depend on the order of the learning rule
evaluations.
Parameters: |
|
---|
Notes
Sets model.params[rule]
to None
.
nengo.builder.learning_rules.
build_bcm
(model, bcm, rule)[source]¶Builds a BCM
object into a model.
Calls synapse build functions to filter the pre and post activities,
and adds a SimBCM
operator to the model to calculate the delta.
Parameters: |
|
---|
Notes
Does not modify model.params[]
and can therefore be called
more than once with the same BCM
instance.
nengo.builder.learning_rules.
build_oja
(model, oja, rule)[source]¶Builds a BCM
object into a model.
Calls synapse build functions to filter the pre and post activities,
and adds a SimOja
operator to the model to calculate the delta.
Parameters: |
|
---|
Notes
Does not modify model.params[]
and can therefore be called
more than once with the same Oja
instance.
nengo.builder.learning_rules.
build_voja
(model, voja, rule)[source]¶Builds a Voja
object into a model.
Calls synapse build functions to filter the post activities,
and adds a SimVoja
operator to the model to calculate the delta.
Parameters: |
|
---|
Notes
Does not modify model.params[]
and can therefore be called
more than once with the same Voja
instance.
nengo.builder.learning_rules.
build_pes
(model, pes, rule)[source]¶Builds a PES
object into a model.
Calls synapse build functions to filter the pre activities,
and adds several operators to implement the PES learning rule.
Unlike other learning rules, there is no corresponding Operator
subclass for the PES rule. Instead, the rule is implemented with
generic operators like ElementwiseInc
and DotInc
.
Generic operators are used because they are more likely to be
implemented on other backends like Nengo OCL.
Parameters: |
|
---|
Notes
Does not modify model.params[]
and can therefore be called
more than once with the same PES
instance.
nengo.builder.processes.
build_process
(model, process, sig_in=None, sig_out=None, inc=False)[source]¶Builds a Process
object into a model.
Parameters: |
|
---|
Notes
Does not modify model.params[]
and can therefore be called
more than once with the same Process
instance.
nengo.builder.processes.
build_synapse
(model, synapse, sig_in, sig_out=None)[source]¶Builds a Synapse
object into a model.
Parameters: |
|
---|
Notes
Does not modify model.params[]
and can therefore be called
more than once with the same Synapse
instance.
nengo.cache.
NoDecoderCache
[source]¶Provides the same interface as DecoderCache
without caching.
nengo.cache.
DecoderCache
(readonly=False, cache_dir=None)[source]¶Cache for decoders.
Hashes the arguments to the decoder solver and stores the result in a file which will be reused in later calls with the same arguments.
Be aware that decoders should not use any global state, but only values passed and attributes of the object instance. Otherwise the wrong solver results might get loaded from the cache.
Parameters: |
|
---|
nengo.cache.
Fingerprint
(obj)[source]¶Fingerprint of an object instance.
A finger print is equal for two instances if and only if they are of the same type and have the same attributes.
The fingerprint will be used as identification for caching.
Parameters: |
|
---|
Notes
Not all objects can be fingerprinted. In particular, custom classes are tricky to fingerprint as their implementation can change without changing its fingerprint, as the type and attributes may be the same.
In order to ensure that only safe object are fingerprinted, this class
maintains class attribute WHITELIST
that contains all types that can
be safely fingerprinted.
If you want your custom class to be fingerprinted, call the
whitelist
class method and pass in your class.
Attributes: |
|
---|
nengo.cache.
CacheIndex
(cache_dir)[source]¶Cache index mapping keys to (filename, start, end) tuples.
Once instantiated the cache index has to be used in a with
block to
allow access. The index will not be loaded before the with
block is
entered.
This class only provides read access to the cache index. For write
access use WriteableCacheIndex
.
Parameters: |
|
---|
Notes
Under the hood, the cache index is stored as a pickle file. The pickle file
contains two objects which are read sequentially: the version
tuple,
and the index
dictionary mapping keys to (filename, start, end) tuples.
Previously, these two objects were stored separately, with the version
tuple stored in a legacy.txt
file. These two objects were consolidated
in the pickle file in Nengo 2.3.0.
Examples
>>> cache_dir = "./my_cache"
>>> to_cache = ("gotta cache 'em all", 151)
>>> with CacheIndex(cache_dir) as index:
... filename, start, end = index[hash(to_cache)]
Attributes: |
|
---|
nengo.cache.
WriteableCacheIndex
(cache_dir)[source]¶Writable cache index mapping keys to files.
This class allows write access to the cache index.
The updated cache file will be written when the with
block is exited.
The initial read and the write on exit of the with
block are locked
against concurrent access with a file lock. The lock will be released
within the with
block.
Parameters: |
|
---|
Examples
>>> cache_dir = "./my_cache"
>>> to_cache = ("gotta cache 'em all", 151)
>>> key = hash(to_cache)
>>> with WriteableCacheIndex(cache_dir) as index:
... index[key] = ("file1", 0, 1) # set an item
... del index[key] # remove an item by key
... index.remove_file_entry("file1") # remove an item by filename
nengo.builder.optimizer.
optimize
(model, dg, max_passes=None)[source]¶Optimizes the operator graph by merging operators.
This reduces the number of iterators to iterate over in slow Python code (as opposed to fast C code). The resulting merged operators will also operate on larger chunks of sequential memory, making better use of CPU caching and prefetching.
The optimization algorithm has worst case complexity \(O(n^2 + e)\), where \(n\) is the number of operators and \(e\) is the number of edges in the dependency graph. In practice the run time will be much better because not all \(n^2\) pairwise combinations of operators will be evaluated. A grouping depending on the operator type and view bases is done with dictionaries. This grouping can be done in amortized linear time and reduces the actual worst-case runtime of the optimization algorithm to \(O(gm^2 + e)\), where \(g\) is the number of groups and \(m\) is the number of elements in a group. Moreover, information about memory alignment will be used to cut the inner loop short in many cases and gives a runtime much closer to linear in most cases.
Note that this function modifies both model
and dg
.
Parameters: |
|
---|