Run

Overview

The run function is used for executing a Mechanism, Process or System. It can be called directly, however it is typically invoked by calling the run method of the Component to be run. It executes a Component by calling the Component’s execute method. While a Component’s execute method can be called directly, using its run method is easier because it:

  • allows multiple rounds of execution to be run in sequence, whereas the execute method of a Component runs only a single execution of the object;
  • automatically aggregates results across executions and stores them in the results attribute of the object.

Understanding a few basic concepts about how the run function operates will make it easier to use the execute and run methods of PsyNeuLink Components. These are discussed below.

Scope of Execution

When the run method of a Component is called, it executes that Component and all others within its scope of execution. For a Mechanism, the scope of execution is simply the Mechanism itself. For a Process, the scope of execution is all of the Mechanisms specified in its pathway attribute. For a System, the scope of execution is all of the Mechanisms in the Processes specified in the System’s processes attribute.

Timing

When run is called by a Component, it calls that Component’s execute method once for each input (or set of inputs) specified in the call to run, which constitutes a TRIAL of execution. For each TRIAL, the Component makes repeated calls to its Scheduler, executing the Components it specifies in each TIME_STEP, until every Component has been executed at least once or another termination condition is met. The Scheduler can be used in combination with Condition specifications for individual Components to execute different Components at different time scales.

Inputs

The run function presents the inputs for each TRIAL to the input_states of the relevant Mechanisms in the scope of execution. These are specified in the inputs argument of a Component’s execute or run method.

Inputs are specified in a Python dictionary where the keys are ORIGIN Mechanisms, and the values are lists in which the i-th element represents the input value to the mechanism on trial i. Each input value must be compatible with the shape of the mechanism’s variable. This means that the inputs to an origin mechanism are usually specified by a list of 2d lists/arrays, though some shorthand notations are allowed.

>>> import psyneulink as pnl

>>> a = pnl.TransferMechanism(name='a',
...                          default_variable=[[0.0, 0.0]])
>>> b = pnl.TransferMechanism(name='b',
...                          default_variable=[[0.0], [0.0]])
>>> c = pnl.TransferMechanism(name='c')

>>> p1 = pnl.Process(pathway=[a, c],
...                 name='p1')
>>> p2 = pnl.Process(pathway=[b, c],
...                 name='p2')

>>> s = pnl.System(processes=[p1, p2])

>>> input_dictionary = {a: [[[1.0, 1.0]], [[1.0, 1.0]]],
...                    b: [[[2.0], [3.0]], [[2.0], [3.0]]]}

>>> s.run(inputs=input_dictionary)
Example input specifications with variable

Note

Keep in mind that a mechanism’s variable is the concatenation of its input states. In other words, a fully specified mechanism variable is a 2d list/array in which the i-th element is the variable of the mechanism’s i-th input state. Because of this relationship between a mechanism's variable and its input states, it is also valid to think about the input specification for a given origin mechanism as a nested list of values for each input state on each trial.

Example input specifications with input states

The number of inputs specified must be the same for all origin mechanisms in the system. In other words, all of the values in the input dictionary must have the same length.

If num_trials is not in use, the number of inputs provided determines the number of trials in the run. For example, if five inputs are provided for each origin mechanism, and num_trials is not specified, the system will execute five times.

Trial # 1 2 3 4 5
Input to Mechanism a 1.0 2.0 3.0 4.0 5.0
>>> import psyneulink as pnl

>>> a = pnl.TransferMechanism(name='a')
>>> b = pnl.TransferMechanism(name='b')

>>> p1 = pnl.Process(pathway=[a, b])

>>> s = pnl.System(processes=[p1])

>>> input_dictionary = {a: [[[1.0]], [[2.0]], [[3.0]], [[4.0]], [[5.0]]]}

>>> s.run(inputs=input_dictionary)

If num_trials is in use, run will iterate over the inputs until num_trials is reached. For example, if five inputs are provided for each ORIGIN mechanism, and num_trials = 7, the system will execute seven times. The first two items in the list of inputs will be used on the 6th and 7th trials, respectively.

Trial # 1 2 3 4 5 6 7
Input to Mechanism a 1.0 2.0 3.0 4.0 5.0 1.0 2.0
import psyneulink as pnl

a = pnl.TransferMechanism(name='a')
b = pnl.TransferMechanism(name='b')

p1 = pnl.Process(pathway=[a, b])

s = pnl.System(processes=[p1])

input_dictionary = {a: [[[1.0]], [[2.0]], [[3.0]], [[4.0]], [[5.0]]]}

s.run(inputs=input_dictionary,
      num_trials=7)

For convenience, condensed versions of the input specification described above are also accepted in the following situations:

  • Case 1: Origin mechanism has only one input state
Trial # 1 2 3 4 5
Input to Mechanism a 1.0 2.0 3.0 4.0 5.0

Complete input specification:

import psyneulink as pnl

a = pnl.TransferMechanism(name='a')
b = pnl.TransferMechanism(name='b')

p1 = pnl.Process(pathway=[a, b])

s = pnl.System(processes=[p1])

input_dictionary = {a: [[[1.0]], [[2.0]], [[3.0]], [[4.0]], [[5.0]]]}

s.run(inputs=input_dictionary)

Shorthand - drop the outer list on each input because Mechanism a only has one input state:

input_dictionary = {a: [[1.0], [2.0], [3.0], [4.0], [5.0]]}

s.run(inputs=input_dictionary)

Shorthand - drop the remaining list on each input because Mechanism a’s variable is length 1:

input_dictionary = {a: [1.0, 2.0, 3.0, 4.0, 5.0]}

s.run(inputs=input_dictionary)
  • Case 2: Only one input is provided for the mechanism
Trial # 1
Input to Mechanism a [[1.0], [2.0]]

Complete input specification:

import psyneulink as pnl

a = pnl.TransferMechanism(name='a',
                          default_variable=[[0.0], [0.0]])
b = pnl.TransferMechanism(name='b')

p1 = pnl.Process(pathway=[a, b])

s = pnl.System(processes=[p1])

input_dictionary = {a: [[[1.0], [2.0]]]}

s.run(inputs=input_dictionary)

Shorthand - drop the outer list on Mechanism a’s input specification because there is only one trial:

input_dictionary = {a: [[1.0], [2.0]]}

s.run(inputs=input_dictionary)
  • Case 3: The same input is used on all trials
Trial # 1 2 3 4 5
Input to Mechanism a [[1.0], [2.0]] [[1.0], [2.0]] [[1.0], [2.0]] [[1.0], [2.0]] [[1.0], [2.0]]

Complete input specification:

import psyneulink as pnl

a = pnl.TransferMechanism(name='a',
                          default_variable=[[0.0], [0.0]])
b = pnl.TransferMechanism(name='b')

p1 = pnl.Process(pathway=[a, b])

s = pnl.System(processes=[p1])

input_dictionary = {a: [[[1.0], [2.0]], [[1.0], [2.0]], [[1.0], [2.0]], [[1.0], [2.0]], [[1.0], [2.0]]]}

s.run(inputs=input_dictionary)

Shorthand - drop the outer list on Mechanism a’s input specification and use num_trials to repeat the input value

input_dictionary = {a: [[1.0], [2.0]]}

s.run(inputs=input_dictionary,
      num_trials=5)
  • Case 4: There is only one origin mechanism
Trial # 1 2
Input to Mechanism a [1.0, 2.0, 3.0] [1.0, 2.0, 3.0]

Complete input specification:

import psyneulink as pnl

a = pnl.TransferMechanism(name='a',
                          default_variable=[[1.0, 2.0, 3.0]])
b = pnl.TransferMechanism(name='b')

p1 = pnl.Process(pathway=[a, b])

s = pnl.System(processes=[p1])

input_dictionary = input_dictionary = {a: [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]]}

s.run(inputs=input_dictionary)

Shorthand - specify Mechanism a’s inputs in a list because it is the only origin mechanism

input_list = [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]]

s.run(inputs=input_list)

Targets

If learning is specified for a Process or System, then target values for each TRIAL must be provided for each TARGET Mechanism in the Process or System being run. These are specified in the targets argument of the execute or run method, which can be in any of three formats. The two formats used for inputs (Sequence and Mechanism format) can also be used for targets. However, the format of the lists or ndarrays is simpler, since each TARGET Mechanism is assigned only a single target value, so there is never the need for the extra level of nesting (or dimension of ndarray) used for InputStates in the specification of inputs. Details concerning the use of the Sequence and Mechanism formats for targets is described below. Targets can also be specified as a function (for example, to allow the target to depend on the outcome of processing).

If either the Sequence or Mechanism format is used, then the number of targets specified for each Mechanism must equal the number specified for the inputs argument; as with inputs, if the number of TRIAL s specified is greater than the number of inputs (and targets), then the list will be cycled until the number of TRIAL s specified is completed. If a function is used for the targets, then it will be used to generate a target for each TRIAL.

The number of targets specified in the Sequence or Mechanism formats for each TRIAL, or generated using the function format, must equal the number of TARGET Mechanisms for the Process or System being run (see Process target_mechanisms or System targetMechanism respectively), and the value of each target must match (in number and type of elements) that of the target attribute of the TARGET Mechanism for which it is intended. Furthermore, if a range is specified for the output of the TERMINAL Mechanism with which the target is compared (that is, the Mechanism that provides the ComparatorMechanism's sample value, then the target must be within that range (for example, if the TERMINAL Mechanism is a TransferMechanism that uses a Logistic function, its range is [0,1], so the target must be within that range).

Sequence Format

(List[values] or ndarray): – there are at most three levels of nesting (or dimensions) required for targets: one for TRIAL s, one for Mechanisms, and one for the elements of each input. For a System with more than one TARGET Mechanism, the targets must be specified in the same order as they appear in the System’s target_mechanisms attribute. This should be the same order in which they are declared, and can be displayed using the System’s show method). All other requirements are the same as the Sequence format for inputs.

Mechanism Format

(Dict[Mechanism, List[values] or ndarray]): – there must be one entry in the dictionary for each of the TARGET Mechanisms in the Process or System being run, though the entries can be specified in any order (making this format easier to use. The value of each entry is a list or ndarray of the target values for that Mechanism, one for each TRIAL. There are at most two levels of nesting (or dimensions) required for each entry: one for the TRIAL, and the other for the elements of each input. In all other respects, the format is the same as the Mechanism format for inputs.

Function Format

[Function]: – the function must return an array with a number of items equal to the number of TARGET Mechanisms for the Process or System being run, each of which must match (in number and type of elements) the target attribute of the TARGET Mechanism for which it is intended. This format allows targets to be constructed programmatically, in response to computations made during the run.

Class Reference

environment.run(inputs, num_trials=None, initialize=False, intial_values=None, targets=None, learning=None, call_before_trial=None, call_after_trial=None, call_before_time_step=None, call_after_time_step=None)
Run a sequence of executions for a Process or System.
Parameters:
  • inputs (List[input] or ndarray(input) : default default_variable for a single TRIAL) – the input for each TRIAL in a sequence (see Inputs for detailed description of formatting requirements and options).
  • num_trials (int : default None) – the number of TRIAL s to run. If it is None (the default), then a number of TRIAL s run will be equal equal to the number of items specified in the inputs argument. If num_trials exceeds the number of inputs, then the inputs will be cycled until the number of TRIAL s specified have been run.
  • initialize (bool default False) – calls the initialize method of the System prior to the first TRIAL.
  • initial_values (Dict[Mechanism:List[input]], List[input] or np.ndarray(input) : default None) – the initial values assigned to Mechanisms designated as INITIALIZE_CYCLE.
  • targets (List[input] or np.ndarray(input) : default None) – the target values assigned to the ComparatorMechanism for each TRIAL (used for learning). The length must be equal to inputs.
  • learning (bool : default None) – enables or disables learning during execution for a Process or System. If it is not specified, the current state of learning is left intact. If it is True, learning is forced on; if it is False, learning is forced off.
  • call_before_trial (Function : default None) – called before each TRIAL in the sequence is run.
  • call_after_trial (Function : default None) – called after each TRIAL in the sequence is run.
  • call_before_time_step (Function : default ``None`) – called before each TIME_STEP is executed.
  • call_after_time_step (Function : default None) – called after each TIME_STEP is executed.
  • termination_processing (Dict[TimeScale: Condition]) – a dictionary containing Conditions that signal the end of the associated TimeScale within the processing phase of execution
  • termination_learning (Dict[TimeScale: Condition]) – a dictionary containing Conditions that signal the end of the associated TimeScale within the learning phase of execution
Returns:

<object>.results – list of the values, for each TRIAL, of the OutputStates for a Mechanism run directly, or of the OutputStates of the TERMINAL Mechanisms for the Process or System run.

Return type:

List[OutputState.value]