# TransferMechanism¶

## Overview¶

A TransferMechanism is a subclass of ProcessingMechanism that adds the ability to integrate its input.

As a ProcessingMechanism, it transforms its input using a simple mathematical function that maintains the shape of its input. The input can be a single scalar value, a simple list or array, or a multidimensional one (regular or ragged). The function used to carry out the transformation can be a TransferFunction or a custom one that can accept any of these forms of input and generate one of similar form. A TransferMechanism can also add noise to and/or clip the result of its function.

A TransferMechanism has two modes of operation: without integration and with integration enabled. Integration is disabled by default, so that the Mechanism’s function executes a full (“instantaneous”) transformation of its input on each execution (akin to the standard practice in feedforward neural networks). However, if integration is enabled, then it uses its integrator_function to integrate its input on each execution, before passing the result on to its function for transformation (akin to time-averaging the net input to a unit in a neural network before passing that to its activation function). When integration is enabled, using the integrator_mode Parameter, additional parameters can be used to configure the integration process, including how it is initialized and when it terminates.

## Creating a TransferMechanism¶

The primary arguments that determine the operation of a TransferMechanism are its function argument, that specifies the function used to transform its input; and, if integrator mode is set to True, then its integrator_function* argument and associated ones that specify how integration occurs (see Examples).

### Primary Function¶

By default, the primary function of a TransferMechanism is Linear, however the function argument can be used to specify any subclass or instance of TransferFunction. It can also be any python function or method, so long as it can take a scalar, or a list or array of numerical values as input and produce a result that is of the same shape; the function or method is “wrapped” as UserDefinedFunction, assigned as the TransferMechanism’s function attribute.

### Integator Function¶

By default, the integrator_function of a TransferMechanism is AdaptiveIntegrator, however the integrator_function argument of the Mechanism’s constructor can be used to specify any subclass of IntegratorFunction, so long as it can accept as input the TransferMechanism’s variable, and genereate a result of the same shape that is passed to the Mechanism’s function. In addition to specifying parameters in the constructor for an IntegratorFunction assigined to the integrator_function argument, the constructor for the TransferMechanism itself has arguments that can be used to confifure its integrator_function: initial_value, integration_rate, and noise. If any of these are specified in the TransferMechanism’s constructor, their value is used to specify the corresponding parameter of its integrator_function. Additonal parameters that govern how integration occurs are described under Execution With Integration.

## Structure¶

### InputPorts¶

By default, a TransferMechanism has a single InputPort; however, more than one can be specified using the default_variable or size arguments of its constructor (see Mechanism). The value of each InputPort is used as a separate item of the Mechanism’s variable, and transformed independently by its function.

### Functions¶

A TransferMechanism has two functions: its primary function that transforms its input, and an integrator_function that is used to integrate the input before passing it to the primary function when integrator_mode is set to True. The default function for a TransferMechanism is Linear, and the defult for its integrator_function is AdaptiveIntegrator, how custom functions can be assigned, as described under Creating a TransferMechanism.

### OutputPorts¶

By default, or if the output_ports argument is specified using the keyword RESULTS, a TransferMechanism generates one OutputPort for each item in the outer dimension (axis 0) of its value (each of which is the result of the Mechanism’s function (and possibly its integrator_function) applied to the value of the corresponding InputPort). If there is only one OutputPort (i.e., the case in which there is only one InputPort and therefore only one item in Mechanism’s value), the OutputPort is named RESULT. If there is more than one item in value, then an OuputPort is assigned for each; the name of the first is RESULT-0, and the names of the subsequent ones are suffixed with an integer that is incremented for each successive one (e.g., RESULT-1, RESULT-2, etc.). Additional OutputPorts can be assigned using the TransferMechanism’s standard_output_ports (see Standard OutputPorts) or by creating custom OutputPorts (but see note below).

Note

If any OutputPorts are specified in the output_ports argument of the TransferMechanism’s constructor, then, as with any Mechanism, its default OutputPorts are not automatically generated. Therefore, an OutputPort with the appropriate index must be explicitly specified for each and every item of the Mechanism’s value (corresponding to each InputPort) for which an OutputPort is needed.

## Execution¶

A TransferMechanism has two modes of execution, determined by its integrator_mode parameter. By default (integrator_mode = False) it executes without integration, directly transforming its input using its function, and possibly adding noise to and/or clipping the result. If integrator_mode = True, it executes with integration, by integrating its input before transforming it. Each of these is described in more detail below.

### Execution Without Integration¶

If integrator_mode is False (the default), the input received over input_ports (assigned as variable) is passed directly to function. If either the noise or clip Parameters have been specified, they are applied to the result of function. That is then assigned as the Mechanism’s value, and well as the values of its output_ports, each of which represents the transformed value of the corresponding input_ports (see examples).

### Execution With Integration¶

If integrator_mode is True, the TransferMechanism’s input (variable) is first passed to its integrator_function, the result of which is then passed to its primary function. The TransferMechanis has several Parameters that, in addition to those of its integrator_function, can be used to configure the integration process, as described in the following subsections (also see examples).

#### Initialization, Resetting and Resuming Integration¶

The staring point for integration can be initialized and reset, and also configured to resume in various ways, as described below (also examples).

Initializing integration – by default, the the starting point for integration is the Mechanism’s default_variable, and is usually an appropriately shaped array of 0’s. However, the starting point can be specified using the initializer argument of a TransferMechanism’s constructor.

Note

The value of initializer is passed to the integrator_function as its initializer Parameter. It can also be specified directly in the initializer argument of the constructor for an IntegratorFunction assigned to the integrator_function argument of a TransferMechanism’s constructor. If there is a disagreements between these (i.e., between the specifiation of initial_value for the TransferMechanism and initializer for its integrator_function, the value specified for the latter takes precedence, and that value is assigned as the one for the initial_value of the TransferMechanism.

Resetting integration – in some cases, it may be useful to reset the integration to the original starting point, or to a new one. This can be done using the Mechanism’s reset method. This first sets the integrator_function’s previous_value and value attributes to the specified value. That is then passed to the Mechanism’s function which is executed, and the result is assigned as the Mechanism current value and to its output_ports.

Note

The TransferMechanism’s reset method calls the reset method on its integrator_function, which can also be called directly. The key difference is that calling the Mechanism’s reset method also executes the Mechanism’s function and updates its output_ports. This is useful if the Mechanism’s value or that of any of its output_ports will be used or checked before the Mechanism is next executed. This may be true if, for example, the Mechanism is a RecurrentTransferMechanism, or if a Scheduler Condition depends on it.

Resuming integration – integration can be enabled and disabled between executions by setting integrator_mode to True and False, respectively. When re-enabling integration, the value used by the integrator_function for resuming integration can be configured using the TransferMechanism’s on_resume_integrator_mode Parameter; there are three options for this:

#### Integration¶

On each execution of the Mechanism, its variable is passed to the integrator_function, which integrates this with the function’s previous_value, using the Mechanism’s noise and integration_rate parameters.

Note

Like the TransferMechanism’s initial_value, its noise and integration_rate Parameters are used to specify the noise and initializer Parameters of its integrator_function, respectively. If there are any disagreements between these (e.g., any of these parameters is specified with conflicting values for the TransferMechanism and its integrator_function), the values specified for the integrator_function take precedence, and those value(s) are assigned as the ones for the corresponding Parameters of the TransferMechanism.

After the integrator_function executes, its result is passed to the Mechanism’s primary function, and its clip parameter is applied if specified, after which it is assigned to as the TransferMechanism’s value and that of its output_ports.

#### Termination¶

If integrator_mode is True then, for each execution of the TransferMechanism, it can be configured to conduct a single step of integration, or to continue to integrate during that execution until its termination condition is met. The latter is specified by the TransferMechanism’s execute_until_finished as well as its termination_threshold, termination_measure, and termination_comparison_op Parameters. These configurations are described below (also see examples).

Single step execution – If either execute_until_finished is set to False, or no termination_threshold is specified (i.e., it is None, the default), then only a signle step of integration is carried out each time the TransferMechanism is executed. In this case, the num_executions_before_finished attribute remains equal to 1, since the integrator_function is executed exactly once per call to the execute method (and the termination condition does not apply or has not been specified).

Execute to termination – if execute_until_finished is True and a value is specified for the termination_threshold then, during each execution of the TransferMechanism, it repeatedly calls its integrator_function and primary function, using the same input (variable) until its termination condition, or the number of executions reaches max_executions_before_finished. The numer of executions that have taken place since the last time the termination condition was met is contained in num_executions_before_finished, and is reset to 0 each time the termination condition is met.

Note

Even after its termination condition is met, a TransferMechanism will continue to execute if it is called again, carrying out one step of integration each time it is called. This can be useful in cases where the initial execution of the Mechanism is meant to bring it to some state (e.g., as an initial “settling process”), after which subsequent executions are meant to occur in step with the execution of other Mechanisms in a Composition (see example below).

By default, execute_until_finished is True, so that when integrator_mode is set to True a TransferMechanism will execute until it terminates, using a convergence criterion. However, the Mechanism’s method of termination can be configured using its termination_measure and termination_comparison_op Parameters can be used to congifure other termination conditions. There are two broad types of termination condition: convergence and boundary termination.

Convergence termination – execution terminates based on the difference between the TransferMechanism’s current value and its previous_value. This is implemented by specifying termination_measure with a function that accepts a 2d array with two items (1d arrays) as its argument, and returns a scalar (the default for a TransferMechanism is the Distance Function with MAX_ABS_DIFF as its metric). After each execution, the function is passed the Mechanism’s current value as well as its previous_value, and the scalar returned is compared to termination_threshold using the comparison operator specified by termination_comparison_op (which is LESS_THAN_OR_EQUAL by default). Execution continues until this returns True. A Distance Function with other metrics (e.g., ENERGY or ENTROPY) can be specified as the termination_measure, as can any other function that accepts a single argument that is a 2d array with two entries.

Boundary termination – Two types of boundaries can be specified: value or time.

Termination by value. This terminates execution when the Mechanism’s value reaches the the value specified by the termination_threshold Parameter. This is implemented by specifying termination_measure with a function that accepts a 2d array with a single entry as its argument and returns a scalar. The single entry is the TransferMechanism’s current value (that is, previous_value is ignored). After each execution, the function is passed the Mechanism’s current value, and the scalar returned is compared to termination_threshold using the comparison operator specified by termination_comparison_op. Execution continues until this returns True.

Termination by time. This terminates execution when the Mechanism has executed at least a number of times equal to termination_threshold at a particular TimeScale (e.g., within a RUN or a TRIAL). This is specified by assigning a TimeScale to termination_measure; execution terminates when the number of executions at that TimeScale equals the termination_threshold. Note that, in this case, termination_comparison_op is automatically set to GREATER_THAN_OR_EQUAL.

Examples

### Examples of Creating a TransferMechanism¶

Function Specification

The function of a TransferMechanism can be specified as the name of a Function class:

>>> import psyneulink as pnl
>>> my_linear_transfer_mechanism = pnl.TransferMechanism(function=pnl.Linear)


or using the constructor for a TransferFunction, in which case its Parameters can also be specified:

>>> my_logistic_tm = pnl.TransferMechanism(function=pnl.Logistic(gain=1.0, bias=-4))


Integrator Mode

The integrator_mode argument allows the TransferMechanism to operate in either an “instantaneous” or “time averaged” manner. By default, integrator_mode is set to False, meaning execution is instantaneous. In order to switch to time averaging, the integrator_mode argument of the constructor must be set to True.

>>> my_logistic_tm = pnl.TransferMechanism(function=pnl.Logistic(gain=1.0, bias=-4),
...                                                        integrator_mode=True)


When integrator_mode is True, the TransferMechanism uses its integrator_function to integrate its variable on each execution. The output of the integrator_function is then used as the input to function.

### Examples of Execution¶

#### Without Integration¶

If integrator_mode is False (the default), then the TransferMechanism updates its value and the value of its output_ports without using its integrator_function, as in the following example:

# >>> my_mech = pnl.TransferMechanism(size=2)
# >>> my_mech.execute([0.5, 1])
# array([[0.5, 1. ]])

>>> my_logistic_tm = pnl.TransferMechanism(function=pnl.Logistic,
...                                        size=3)
>>> my_logistic_tm.execute([-2.0, 0, 2.0])
array([[0.11920292, 0.5       , 0.88079708]])


Notice that the result is the full logistic transform of the input (i.e., no integration occured). Noise can also be added to the result. It can be specified as a float, and array, or function. If it is a float or list of floats, the value is simply added to the result, as shown in the example below, that uses the TransferMechanism’s default function, Linear:

>>> my_linear_tm = pnl.TransferMechanism(size=3,
...                                      noise=2.0)
>>> my_linear_tm.execute([1.0, 1.0, 1.0])
array([[3., 3., 3.]])
>>> my_linear_tm.execute([1.0, 1.0, 1.0])
array([[3., 3., 3.]])


Since by default Linear uses a slope of 1 and intercept <Linear.intercept of 0, the result is the same as the input, plus the value specified for noise. A list can also be used to specify noise (it must be the same length as the Mechanism’s variable), in which case each element is applied Hadamard (elementwise) to the result, as shown here:

>>> my_linear_tm.noise = [1.0,1.2,.9]
>>> my_linear_tm.execute([1.0, 1.0, 1.0])
array([[2. , 2.2, 1.9]])


While specifying noise as a constant (or a list of constantss) is not particularly useful, it can be replaced by any function that specifies a float, for example a DistributionFunction. As with numerical values, if a single function is specified, it is applied to all elements; however, on each execution, the function is executed indpendently for each element. This is shown below using the NormalDist function:

>>> my_linear_tm = pnl.TransferMechanism(size=3,
...                                      noise=pnl.NormalDist)
>>> my_linear_tm.execute([1.0, 1.0, 1.0])
array([[2.1576537 , 1.60782117, 0.75840058]])
>>> my_linear_tm.execute([1.0, 1.0, 1.0])
array([[2.20656132, 2.71995896, 0.57600537]])
>>> my_linear_tm.execute([1.0, 1.0, 1.0])
array([[1.03826716, 0.56148871, 0.8394907 ]])


Notice that each element was assigned a different random value for its noise, and that these also varied across executions. Notice that since only a single function was specified, it could be the name of a class. Functions can also be used in a list to specify noise, together with other functions or with numeric values; however, when used in a list, functions must be instances, as shown below:

>>> my_linear_tm = pnl.TransferMechanism(size=3,
...                                      noise=[pnl.NormalDist(), pnl.UniformDist(), 3.0])
>>> my_linear_tm.execute([1.0, 1.0, 1.0])
array([[-0.22503678,  1.36995517,  4.        ]])
>>> my_linear_tm.execute([1.0, 1.0, 1.0])
array([[2.08371805, 1.60392004, 4.        ]])


Notice that since noise is a modulable Parameter, assigning it a value after the TransferMechanism has been constructed must be done to its base value (see Modulation for additional information).

Finally, clipping can also be used to cap the result to within specified bounds:

>>> my_linear_tm.clip = (.5, 1.2)
>>> my_linear_tm.execute([1.0, 1.0, 1.0])
array([[1.2, 1.2, 1.2]])
>>> my_linear_tm.execute([1.0, 1.0, 1.0])
array([[1.2       , 1.06552886, 1.2       ]])
>>> my_linear_tm.execute([1.0, 1.0, 1.0])
array([[0.5       , 1.01316799, 1.2       ]])


Note that the bounds specified in clip apply to all elements of the result if it is an array.

#### With Integration¶

The following examples illustate the execution of a TransferMechanism with integrator_mode set to True. For convenience, a TransferMechanism has three Parameters that are used by most IntegratorFunctions, and that can be used to configure integration:initial_value, integration_rate, and noise. If any of these are specified in the TransferMechanism’s constructor, their value is used to specify the corresponding parameter of its integrator_function. In the following example, my_linear_tm is assigned Linear as its primary function, congifured to transform arrays of size 3, with an initial_value of [0.1, 0.5, 0.9] and an integration_rate of 0.5, that are passed as the values for the initializer and rate Parameters of its integrator_function Parameters, respectively. Since, its integrator_function is not specified, the default for a TransferMechanism is used, which is AdaptiveIntegrator. This integrates its input, returning results that begin close to its initializer and asymptotically approach the value of the current input, which in this example is [1.0, 1.0, 1,0] for each execution:

>>> my_linear_tm = pnl.TransferMechanism(size=3,
...                                      function=pnl.Linear,
...                                      integrator_mode=True,
...                                      initial_value=np.array([[0.1, 0.5, 0.9]]),
...                                      integration_rate=0.5)
>>> my_linear_tm.integrator_function.initializer
array([[0.1, 0.5, 0.9]])
>>> my_linear_tm.integrator_function.previous_value
array([[0.1, 0.5, 0.9]])
>>> my_linear_tm.execute([1.0, 1.0, 1.0])
array([[0.55, 0.75, 0.95]])
>>> my_linear_tm.execute([1.0, 1.0, 1.0])
array([[0.775, 0.875, 0.975]])
>>> my_linear_tm.execute([1.0, 1.0, 1.0])
array([[0.8875, 0.9375, 0.9875]])


Notice that specifying [[0.1, 0.5, 0.9]] as the initial_value for my_linear_tm assigns it both as the value of the integrator_function’s initializer Parameter, and also as its previous_value which is used in the first step of integration when my_linear_tm is executed. For an AdaptiveIntegrator, each step of integration returns a result that is its previous_value + (rate * previous_value - input), asymtotically approaching the input.

In the following example, both the TransferMechanism’s integration_rate and its integrator_function’s rate are specified:

>>> my_linear_tm = pnl.TransferMechanism(integrator_function=AdaptiveIntegrator(rate=0.3),
...                                      integration_rate=0.1)
>>> my_linear_tm.integration_rate
(TransferMechanism TransferMechanism-8):
integration_rate.base: 0.3
integration_rate.modulated: [0.3]


Notice that the value specified for the TransferMechanism integrator integrator_function (0.3) takes precendence, and is assigned as the value of the TransferMechanism’s integration_rate, overriding the specified value (0.1). The same applies for the specification of the TransferMechanism’s initial_value argument and the initializer for its integration_function. Notice also that two values are reported for the Mechanism’s integration_rate. This is because this is a modulable Parameter. The integration_rate.base is the one that is assigned; integration_rate.modulated reports the value that was actually used when the Mechanism was last executed; this is the same as the base value if the Parameter is not subject to modulation; if the Parameter is subject to modulation <ModulatorySignal_Modulation>, then the modulated value will be the base value modified by any modulatory signals that project to the Mechanism for that Parameter.

##### Initializing, Resetting and Resuming Integration¶

When integrator_mode is True, the state of integration can be initialized by specifying its initial_value using the initial_value argument in the constructor, as shown in the following example:

>>> my_linear_tm = pnl.TransferMechanism(function=pnl.Linear,
...                                      integrator_mode=True,
...                                      integration_rate=0.1,
...                                      initial_value=np.array([[0.2]]))
>>> my_linear_tm.integrator_function.previous_value
array([[0.2]])


It will then begin integration at that point. The result after each execution is the integrated value of the input and its integrator_function’s previous_value:

>>> my_linear_tm.execute(0.5)
array([[0.23]])
>>> my_linear_tm.execute(0.5)
array([[0.257]])
>>> my_linear_tm.execute(0.5)
array([[0.2813]])


The TransferMechanism’s reset method can be used to restart integration from its initial_value or some other one. For example, calling reset without an argument resets the starting point of integration for my_linear_tm back to 0.2, and if it is executed trials it produes the same results as the first 3 executions:

>>> my_linear_tm.integrator_function.reset()
[array([[0.2]])]
>>> my_linear_tm.execute(0.5)
array([[0.23]])
>>> my_linear_tm.execute(0.5)
array([[0.257]])
>>> my_linear_tm.execute(0.5)
array([[0.2813]])


The reset method can also be used to start integration at a specified value, by providing it as an argument to the method:

>>> my_linear_tm.integrator_function.reset([0.4])
[array([0.4])]
>>> my_linear_tm.execute(0.5)
array([[0.41]])
>>> my_linear_tm.execute(0.5)
array([[0.419]])


If integration is suspended (by changing integrator_mode from True to False), the value it uses to resume integration (if integrator_mode is reassigned as True) can be specified using the on_resume_integrator_mode option. If it is set to RESET, it will use initial_value to resume integration, just as if reset() had been called. If it is set to CURRENT_VALUE (the default), it will resume integration using the current value of the Mechanism, irrespective of the integrator_function’s previous_value at the point at which integration was last suspended, as shown below:

>>> my_linear_tm.integrator_mode = False
>>> my_linear_tm.execute(0.2)
array([[0.2]])
>>> my_linear_tm.execute(0.2)
array([[0.2]])
>>> my_linear_tm.on_resume_integrator_mode = pnl.CURRENT_VALUE
>>> my_linear_tm.integrator_mode = True
>>> my_linear_tm.execute(0.5)
array([[0.23]])
>>> my_linear_tm.execute(0.5)
array([[0.257]])


Notice that, with on_resume_integrator_mode set to CURRENT_VALUE, when integrator_mode is set back to True, integration proceeds from the most recent value of my_linear_tem. In contrast, if on_resume_integrator_mode is set to LAST_INTEGRATED_VALUE, integration resumes using the integrator_function’s previous_value IntegratorFunction.previous_value at the point at which integration was last suspended, irrespective of interverning executions:

>>> my_linear_tm.on_resume_integrator_mode = pnl.LAST_INTEGRATED_VALUE
>>> my_linear_tm.integrator_mode = False
>>> my_linear_tm.execute(1.0)
array([[1.]])
>>> my_linear_tm.integrator_mode = True
>>> my_linear_tm.execute(0.5)
array([[0.2813]])
>>> my_linear_tm.execute(0.5)
array([[0.30317]])


Notice in this case that, even though the most recent value of my_linear_tm is 1.0, when integrator_mode is set back to True, integration resumes from the most recent value when it was last True (in this case, where it left off in the preceding example, 0.257).

##### Terminating Integration¶

Termination by value. This terminates execution when the Mechanism’s value reaches the the value specified by the threshold argument. This is implemented by specifying termination_measure with a function that accepts a 2d array with a single entry as its argument and returns a scalar. The single entry is the TransferMechanism’s current value (that is, its previous_value is ignored). After each execution, the function is passed the Mechanism’s current value, and the scalar returned is compared to termination_threshold using the comparison operator specified by termination_comparison_op. Execution continues until this returns True, as in the following example:

>>> my_mech = pnl.TransferMechanism(size=2,
...                                 integrator_mode=True,
...                                 termination_measure=max,
...                                 termination_threshold=0.9,
...                                 termination_comparison_op=pnl.GREATER_THAN_OR_EQUAL)
>>> my_mech.execute([0.5, 1])
array([[0.46875, 0.9375 ]])
>>> my_mech.num_executions_before_finished
4


Here, my_mech continued to execute for 5 times, until the element of the Mechanism’s value with the greatest value exceeded 0.9. Note that GREATER_THAN_EQUAL is a keyword for the string “>=”, which is a key in the comparison_operators dict for the Python operator.ge; any of these can be used to specify termination_comparison_op).

Termination by time. This terminates execution when the Mechanism has executed at least a number of times equal to the threshold at a particular TimeScale (e.g., within a RUN or a TRIAL). This is specified by assigning a TimeScale to termination_measure; execution terminates when the number of executions at that TimeScale equals the termination_threshold. Note that, in this case, the termination_comparison_op argument is ignored (the termination_comparison_op is automatically set to GREATER_THAN_OR_EQUAL). For example, my_mech is configured below to execute at least twice per trial:

>>> my_mech = pnl.TransferMechanism(size=2,
...                                 integrator_mode=True,
...                                 termination_measure=TimeScale.TRIAL,
...                                 termination_threshold=2)
>>> my_mech.execute([0.5, 1])
array([[0.375, 0.75 ]])
>>> my_mech.num_executions_before_finished
2


As noted above, it will continue to execute if it is called again, but only once per call:

>>> my_mech.execute([0.5, 1])
array([[0.4375, 0.875 ]])
>>> my_mech.num_executions_before_finished
1
>>> my_mech.execute([0.5, 1])
array([[0.46875, 0.9375 ]])
>>> my_mech.num_executions_before_finished
1


In the following example, this behavior is exploited to allow a recurrent form of TransferMechanism (attention) to integrate for a fixed number of steps (e.g., to simulate the time taken to encode an instruction regarding the which feature of the stimulus should be attended) before a stimulus is presented, and then allowing that Mechanism to continue to integrate the instruction and impact stimulus processing once the stimulus is presented:

>>> stim_input = pnl.ProcessingMechanism(size=2)
>>> stim_percept = pnl.TransferMechanism(size=2, function=pnl.Logistic)
>>> decision = pnl.TransferMechanism(name='Decision', size=2,
...                                  integrator_mode=True,
...                                  execute_until_finished=False,
...                                  termination_threshold=0.65,
...                                  termination_measure=max,
...                                  termination_comparison_op=pnl.GREATER_THAN)
>>> instruction_input = pnl.ProcessingMechanism(size=2, function=pnl.Linear(slope=10))
>>> attention = pnl.LCAMechanism(name='Attention', size=2, function=pnl.Logistic,
...                              leak=8, competition=8, self_excitation=0, time_step_size=.1,
...                              termination_threshold=3,
...                              termination_measure = pnl.TimeScale.TRIAL)
>>> response = pnl.ProcessingMechanism(name='Response', size=2)
...
>>> comp = pnl.Composition()
>>> comp.add_linear_processing_pathway([stim_input, [[1,-1],[-1,1]], stim_percept, decision, response])
...
>>> stim_percept.set_log_conditions([pnl.RESULT])
>>> attention.set_log_conditions([pnl.RESULT])
>>> decision.set_log_conditions([pnl.RESULT])
>>> response.set_log_conditions(['OutputPort-0'])
...
>>> inputs = {stim_input:        [[1, 1], [1, 1]],
...           instruction_input: [[1, -1], [-1, 1]]}
>>> comp.run(inputs=inputs)


This example implements a simple model of attentional selection in perceptual decision making. In the model, stim_input represents the stimulus input, which is passed to stim_percept, which also receives input from the attention Mechanism. stim_percpt passes its output to decision, which integrates its input until one of the state_features of the input (the first or second) reaches the threshold of 0.65, at which point response executes (specified by the condition (reponse, WhenFinished(decision)). In addition to the stim_input, the model an instruction on each trial in instruction_input that specifies which feature of the stimulus (i.e., the first or second element) should be “attended”. This is passed to the attention Mechanism, which uses it to select which feature of stim_percept should be passed to decision, and thereby determine the response. Like the decision Mechanism, the attention Mechanism integrates its input. However, its threshold_measure is specified as TimeScale.TRIAL and its threshold as 3, so it carries out 3 steps of integration the first time it is executed in each trial. Thus, when the input is presented at the beginning of each trial, first stim_input and instruction_input execute. Then attention executes, but stim_percept does not yet do so, since it receives input from attention and thus must wait for that to execute first. When attention executes, it carries out its three steps of integration, (giving it a chance to “encode” the instruction before the stimulus is processed by stim_percept). Then stim_percept executes, followed by decision. However, the latter carries out only one step of integration, since its execute_until_finished is set to False. If its output does not meet its termination condition after that one step of integration, then response does not execute, since it has been assigned a condition that requires decision to terminate before it does so. As a result, since response has not executed, the trial continues. On the next pass, attention carries out only one step of integration, since its termination condition has already been met, as does decision since its termination condition has not yet been met. If it is met, then response executes and the trial ends (since all Mechanisms have now had an opportunity to execute). The value of the attention and decision Mechanisms after each execution are shown below:

>>> attention.log.print_entries(display=[pnl.TIME, pnl.VALUE])
Log for Attention:
Logged Item:   Time          Value
'RESULT'       0:0:0:1      [0.64565631 0.19781611]  # Trial 0
'RESULT'       0:0:0:1      [0.72347147 0.1422746 ]
'RESULT'       0:0:0:1      [0.74621565 0.1258587 ]
'RESULT'       0:0:1:1      [0.75306362 0.1208305 ]
'RESULT'       0:0:2:1      [0.75516272 0.11926922]
'RESULT'       0:0:3:1      [0.75581168 0.11878318]
'RESULT'       0:0:4:1      [0.75601306 0.11863188]
'RESULT'       0:1:0:1      [0.2955214  0.49852489]  # Trial 1
'RESULT'       0:1:0:1      [0.17185129 0.68187518]
'RESULT'       0:1:0:1      [0.13470156 0.73399742]
'RESULT'       0:1:1:1      [0.1235536  0.74936691]
'RESULT'       0:1:2:1      [0.12011584 0.75402671]

>>> decision.log.print_entries(display=[pnl.TIME, pnl.VALUE])
Log for Decision:
Logged Item:   Time          Value
'RESULT'       0:0:0:3      [0.33917677 0.2657116 ]  # Trial 0
'RESULT'       0:0:1:3      [0.50951133 0.39794126]
'RESULT'       0:0:2:3      [0.59490696 0.46386164]
'RESULT'       0:0:3:3      [0.63767534 0.49676128]
'RESULT'       0:0:4:3      [0.65908142 0.51319226]
'RESULT'       0:1:0:3      [0.59635299 0.59443706]  # Trial 1
'RESULT'       0:1:1:3      [0.56360108 0.6367389 ]
'RESULT'       0:1:2:3      [0.54679699 0.65839718]

>>> response.log.print_entries(display=[pnl.TIME, pnl.VALUE])
Log for Response:
Logged Item:   Time          Value
'OutputPort-0' 0:0:4:4      [0.65908142 0.51319226]  # Trial 0
'OutputPort-0' 0:1:2:4      [0.54679699 0.65839718]  # Trial 1


The Time signatures are run:trial:pass:time_step. Note that attention always executes in time_step 1 (after stim_input and instruction_input which execute in time_step 0). In trial 0, attention executes three times in pass 0 (to reach its specified threshold), and then again in passes 1, 2 and 3 and 4 along with decision (which executes in time_step 3, after stim_percept in time_step 2), as the trial continues and decision executes until reaching its threshold. Note that response executed only executed in pass 4, since it depends on the termination of decision. Note also that in trial 1 attention executes 3 times in pass 0 as it did in trial 0; however, decision executes only 3 times since it begins closer to its threshold in that trial.

## Class Reference¶

exception psyneulink.core.components.mechanisms.processing.transfermechanism.TransferError(error_value)
class psyneulink.core.components.mechanisms.processing.transfermechanism.TransferMechanism(noise=0.0, clip=(float:min, float:max), integrator_mode=False, integrator_function=AdaptiveIntegrator, initial_value=None, integration_rate=0.5, on_resume_integrator_mode=CURRENT_VALUE, termination_measure=Distance(metric=MAX_ABS_DIFF), termination_threshold=None, termination_comparison_op=LESS_THAN_OR_EQUAL, output_ports=RESULTS)

Subclass of ProcessingMechanism that performs a simple transform of its input. See Mechanism for additional arguments and attributes.

Parameters
noise

value is applied to the result of integrator_function if integrator_mode is False; otherwise it is passed as the noise Parameter to integrator_function. If noise is a float or function, it is added to all elements of the array being transformed; if it is a function, it is executed independently for each element each time the TransferMechanism is executed. If noise is an array, it is applied Hadamard (elementwise) to the array being transformed; again, each function is executed independently for each corresponding element of the array each time the Mechanism is executed.

Note

If noise is specified as a float or function in the constructor for the TransferMechanism, the noise Parameter cannot later be specified as a list or array, and vice versa.

Hint

To generate random noise that varies for every execution and across all elements of an array, a DistributionFunction should be used, that generates a new value on each execution. If noise is specified as a float, a function with a fixed output, or an array of either of these, then noise is simply an offset that is the same across all elements and executions.

Type

float, function or an array containing either or both

clip

determines the allowable range for all elements of the result of function. The 1st item (index 0) determines the minimum allowable value of the result, and the 2nd item (index 1) determines the maximum allowable value; any element of the result that exceeds the specified minimum or maximum value is set to the value of clip that it exceeds.

Type

tuple(float, float)

integrator_mode

determines whether the TransferMechanism uses its integrator_function to integrate its variable when it executes (see TransferMechanism_Execution for additional details).

Type

bool

integrator_function

the IntegratorFunction used when integrator_mode is set to True (see Integration for details).

Type

IntegratorFunction

initial_value

determines the starting value for the integrator_function when integrator_mode is True (see Initialization, Resetting and Resuming Integration for additional details).

Type

value, list or np.ndarray

integration_rate

determines the rate at which the TransferMechanism’s variable is integrated when it is executed with integrator_mode set to True; a higher value specifies a faster rate (see Integration for additional details).

Type

float

on_resume_integrator_mode

determines value used by the integrator_function when integration is resumed, and must be one of the following keywords: CURRENT_VALUE, LAST_INTEGRATED_VALUE, or RESET (see resuming integration for additional details).

Type

CURRENT_VALUE, LAST_INTEGRATED_VALUE, or RESET

termination_measure

used to determine when execution of the TransferMechanism is complete (i.e., is_finished is True), if execute_until_finished is True. If it is a TimeScale, then execution terminates when the value of the Mechanism’s num_executions at that TimeScale is is equal to termination_threshold. If it is a function, it is passed the value and previous_value of the TransferMechanism; its result (termination_measure_value) is compared with termination_threshold using TransferMechanism.termination_comparison_op, the result of which is used as the value of is_finished.

Note

A Mechanism’s previous value is distinct from the previous_value attribute of its integrator_function.

Type

function or TimeScale

termination_measure_value

value returned by termination_measure; used to determine when is_finished is True.

Type

array or scalar

termination_threshold

value with which termination_measure_value is compared to determine when execution of TransferMechanism is complete if execute_until_finished is True.

Type

None or float

termination_comparison_op

used to compare termination_measure_value with termination_threshold to determine when execution of TransferMechanism is complete if execute_until_finished is True.

Type

Comparator

standard_output_ports

list of Standard OutputPort that includes the following in addition to the standard_output_ports of a ProcessingMechanism:

COMBINE1d array

Element-wise (Hadamard) sum of all items of the TransferMechanism’s value (requires that they all have the same dimensionality).

Type

list[dict]

Returns

instance of TransferMechanism

Return type

TransferMechanism

_validate_params(request_set, target_set=None, context=None)

Validate FUNCTION and Mechanism params

_instantiate_parameter_ports(function=None, context=None)

Call Port._instantiate_parameter_ports to instantiate a ParameterPort for each parameter with modulable=True

This is a stub, implemented to allow Mechanism subclasses to override _instantiate_parameter_ports

or process InputPorts before and/or after call to _instantiate_parameter_ports :param function:

_instantiate_output_ports(context=None)

Call Port._instantiate_output_ports to instantiate orderedDict of OutputPort(s)

This is a stub, implemented to allow Mechanism subclasses to override _instantiate_output_ports

or process InputPorts before and/or after call to _instantiate_output_ports

_execute(variable=None, context=None, runtime_params=None)

Execute TransferMechanism function and return transform of input

reset(*args, force=False, context=None, **kwargs)

Reset value if Mechanisms is stateful.

If the mechanism’s function is an IntegratorFunction, or if the mechanism has and integrator_function (see TransferMechanism), this method effectively begins the function’s accumulation over again at the specified value, and updates related attributes on the mechanism. It also clears the value history, thus effectively setting the previous value to None.

If the mechanism’s function is an IntegratorFunction, its reset method:

1. Calls the function’s own reset method (see Note below for details)

2. Sets the mechanism’s value to the output of the function’s reset method

3. Updates its output ports based on its new value

If the mechanism has an integrator_function, its reset method:

(1) Calls the integrator_function's <TransferMechanism.integrator_function> own reset
<IntegratorFunction.reset> method (see Note below for details)

(2) Executes its function <Mechanism_Base.function> using the output of the integrator_function's
<TransferMechanism.integrator_function> reset <IntegratorFunction.reset> method as
the function's variable

(3) Sets the mechanism's value <Mechanism_Base.value> to the output of its function

(4) Updates its output ports <Mechanism_Base.output_port> based on its new value
<Mechanism_Base.value>


Note

The reset method of an IntegratorFunction Function typically resets the function’s previous_value (and any other stateful_attributes) and value to the quantity (or quantities) specified. If reset is called without arguments, the initializer value (or the values of each of the attributes in initializers) is used instead. The reset method may vary across different Integrators. See individual functions for details on their stateful_attributes, as well as other reinitialization steps that the reset method may carry out.

_parse_function_variable(variable, context=None)

Parses the variable passed in to a Component into a function_variable that can be used with the Function associated with this Component

_instantiate_attributes_after_function(context=None)

Determine numberr of items expected by termination_measure

_report_mechanism_execution(input, params=None, output=None, context=None)

Override super to report previous_input rather than input, and selected params

is_finished`(context=None)

Returns True when value of Mechanism reaches threhsold or if threshold is None.

Note: if threshold is None or Mechanism not in integartor_mode,

implements single update (cycle) per call to _execute method (equivalent to setting Component.execute_until_finished = False)