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.

Recall that the TARGET, or ComparatorMechanism, of a learning sequence receives a TARGET, which is provided by the user at run time, and a SAMPLE, which is received from a projection sent by the last mechanism of the learning sequence. The TARGET and SAMPLE values for a particular TARGET Mechanism must have the same shape. See learning sequence for more details on how these components relate to each other.

The standard format for specifying targets is a Python dictionary where the keys are the last mechanism of each learning sequence, and the values are lists in which the i-th element represents the target value for that learning sequence on trial i. There must be the same number of keys in the target specification dictionary as there are TARGET Mechanisms in the system. Each target value must be compatible with the shape of the TARGET mechanism’s TARGET input state. This means that for a given key (which is always the last mechanism of the learning sequence) in the target specification dictionary, the value is usually a list of 1d lists/arrays.

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.

Trial # 1 2
Target value for the learning sequence containing Mechanism b [1.0, 1.0] [2.0, 2.0]
Target value for the learning sequence containing Mechanism c [1.0] [2.0]
>>> import psyneulink as pnl

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

>>> learning_sequence_1 = pnl.Process(name="learning-sequence-1",
...                                   pathway=[a, b],
...                                   learning=pnl.ENABLED)
>>> learning_sequence_2 = pnl.Process(name="learning-sequence-2",
...                                   pathway=[a, c],
...                                   learning=pnl.ENABLED)


>>> s = pnl.System(name="learning-system",
...                processes=[learning_sequence_1, learning_sequence_2])

>>> input_dictionary = {a: [[[0.1]], [[0.2]]]}

>>> target_dictionary = {b: [[1.0, 1.0], [2.0, 2.0]],
...                      c: [[1.0], [2.0]]}

>>> s.run(inputs=input_dictionary,
...       targets=target_dictionary)
Example of dictionary format of target specification

Alternatively, the value for a given key (last mechanism in the learning sequence) in the target specification dictionary may be a function. The output of that function must be compatible with the shape of the TARGET mechanism’s TARGET input state. The function will be executed at the start of the learning portion of each trial. This format allows targets to be constructed programmatically, in response to computations made during the run.

>>> a = TransferMechanism(name="a")
>>> b = TransferMechanism(name="b",
...                       default_variable=np.array([[0.0, 0.0]]))

>>> learning_sequence = Process(name="learning-sequence",
...                             pathway=[A, B],
...                             learning=ENABLED)

>>> s = System(name="learning-system",
...            processes=[LP])

>>> def target_function():
...     val_1 = NormalDist(mean=3.0).function()
...     val_2 = NormalDist(mean=3.0).function()
...     target_value = np.array([val_1, val_2])
...     return target_value

>>> s.run(inputs={A: [[[1.0]], [[2.0]], [[3.0]]]},
...       targets={B: target_function})

Note

Target specification dictionaries that provide values for multiple learning sequences may contain functions for some learning sequences and lists of values for others.

Finally, for convenience, if there is only one learning sequence in a system, the targets may be specified in a list, rather than a dictionary.

Trial # 1 2 3 4 5
Target corresponding to Mechanism b 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]]]}
>>> target_dictionary = {b: [[1.0], [2.0], [3.0], [4.0], [5.0]]}

>>> s.run(inputs=input_dictionary,
...       targets=target_dictionary)

Shorthand - specify the targets in a list because there is only one learning sequence:

>>> target_list = [[1.0], [2.0], [3.0], [4.0], [5.0]]

>>> s.run(inputs=input_dictionary,
...       targets=target_list)

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 (dict : default None) – the target values assigned to the ComparatorMechanism of each learning sequence on each TRIAL.
  • 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]