# ModulatoryMechanism¶

## Overview¶

A ModulatoryMechanism is an AdaptiveMechanism that modulates the value(s) of one or more States of other Mechanisms in the Composition to which it belongs. It’s function calculates a modulatory_allocation: a list of values provided to each of its modulatory_signals. These can be ControlSignals, that modulate the value of a ParameterState of another Mechanism, and/or GatingSignals that modulate the value of an InputState or OutputState of another Mechanism. A ModulatoryMechanism can be configured to monitor the outputs of other Mechanisms in order to determine its modulatory_allocation, by assigning it an ObjectiveMechanism and/or specifying a list of OutputStates to monitor (see ObjectiveMechanism below). A ModulatoryMechanism can also be assigned as the controller of a Composition, which has a special relation to that Composition: it generally executes either before or after all of the other Mechanisms in that Composition (see Controller Execution).

## Creating a ModulatoryMechanism¶

A ModulatoryMechanism is created by calling its constructor. If neither its montior_for_control nor objective_mechanism arguments are specified, then only the ModulatoryMechanism is constructed, and its inputs must be specified in some other way. However, either of those arguments can be used to configure its inputs, as described below.

### ObjectiveMechanism¶

If an ObjectiveMechanism is specified in the objective_mechanism argument of a ModulatoryMechanism’s constructor or any OutputStates are specified in its monitor_for_modulation argument, then an ObjectiveMechanism is automatically created and assigned as the ModulatoryMechanism’s objective_mechanism attribute. If the objective_mechanism is specified simply as True, a default ObjectiveMechanism is created. This is used to monitor the OutputStates specified in either the monitor argument of the ObjectiveMechanism’s constructor and/or the monitor_for_modulation argument of the ModulatoryMechanism’s constructor. The values of these OutputStates are evaluted by the ObjectiveMechanism’s function, and the result is conveyed to the ModulatoryMechanism by way of a MappingProjection created from the OUTCOME Outputstate of the ObjectiveMechanism to the OUTCOME InputState of the ModulatoryMechanism, and used by it to determine its modulatory_allocation. The OutputStates monitored by the ModulatoryMechahism’s objective_mechanism are listed in its monitor_for_modulation attribute, and in the ObjectiveMechanism’s monitor attribute. These, along with the States modulated by the ModulatoryMechanism, can also be listed using its show method.

The ObjectiveMechanism and/or OutputStates it monitors can be specified using any of the following in the constructor for the ModualtoryMechanism:

• in the objective_mechanism argument:

• A constructor for an ObjectiveMechanism; its monitor argument can be used to specify the OutputStates to be monitored, and its function argument can be used to specify how those OutputStates are evaluated (see Examples).
• A list of OutputState specifications; a default ObjectiveMechanism is created, and the list of OutputState specifications are assigned to its monitor argument.
• in the monitor_for_modulation argument, a list of OutputState specifications; a default ObjectiveMechanism is created, and the list of OutputState specifications are assigned to its monitor argument.

If OutputStates to be monitored are specified in both the objective_mechanism argument (on their own, or within the constructor for an ObjectiveMechanism) and the monitor_for_modulation argument, both sets are used in creating the ObjectiveMechanism.

If an ObjectiveMechanism is specified using its constructor, any specifications in that constructor override any attributes specified for the default objective_mechanism of a ModulatoryMechanism, including those of its function (see note in EVCModulatoryMechanism for an example);

OutputStates to be monitored can also be added using either the ModulatoryMechanism’s add_to_monitor method, or the corresponding method of the ObjectiveMechanism.

### Specifying States to Modulate¶

A ModulatoryMechanism modulates the values of States using the ControlSignals and/or GatingSignals assigned to its modulatory_signals attribute, each of which is assigned, respectively, a ControlProjection or GatingProjection to the State it modulates (see Modulation for a description of how modulation operates). Modulation of a State can be specified either where the Component to which the State belongs is created (see specifying Specifying ControlSignals or Specifying GatingSignals), or in the modulatory_signals argument of the ModulatoryMechanism’s constructor. For the latter, the argument must be a specification for one or more ControlSignals and/or GatingSignals. States to be modulate can also be added to an existing ModulatoryMechanism by using its assign_params method to add a ControlSignal and/or GatingSignal for each additional State. All of a ModulatoryMechanism’s ModulatorySignals are listed in its modulatory_signals attribute. Any ControlSignals are also listed in the control_signals attribute, and GatingSignals in the gating_signals attribute. The projections from these to the States they modulate are listed in the modulatory_projections, control_projections, and gating_projections attributes, respectively.

### ModulatoryMechanisms and a Composition¶

A ModulatoryMechanism can be assigned to a Composition and executed just as any other Mechanism. It can also be assigned as the controller of a Composition, that has a special relation to the Composition: it is generally run either before or after all of the other Mechanisms in that Composition, including any other ModulatoryMechanisms that belong to it (see Controller). A ModulatoryMechanism can be the controller for only one Composition, and a Composition can have only one controller. A ModulatoryMechanism can be assigned as the controller for a Composition in any of the following ways, by specifying:

• the Composition in the composition argument of the ModulatoryMechanism’s constructor;
• the ModulatoryMechanism in the controller argument of the Composition’s constructor;
• the ModulatoryMechanism in the controller argument of the Composition’s add_controller method.

## Structure¶

### Input¶

A ModulatoryMechanism has a single InputState, named OUTCOME. If its objective_mechanism is implemented, then it receives a MappingProjection from that ObjectiveMechanism’s OUTCOME OutputState, the value of which is also stored in the ModulatoryMechanism’s outcome attribute. This is used as the input to the ModulatoryMechanism’s function, that determines its modulatory_allocation.

### Function¶

A ModulatoryMechanism’s function uses outcome (the value of its OUTCOME InputState) to generate a modulatory_allocation. By default, function is assigned the DefaultAllocationFunction, which takes a single value as its input, and assigns this as the value of each item of modulatory_allocation. Each of these items is assigned as the allocation for the corresponding ControlSignal or GatingSignal in modulatory_signals. Thus, by default, ModulatoryMechanism distributes its input as the allocation to each of its modulatory_signals, and/or by specifying that individual ControlSignals and/or GatingSignals reference different items in modulatory_allocation as their allocation (i.e., the value of their variable.

### Output¶

The OutputStates of a ModulatoryMechanism are ControlSignals and/or GatingSignals (listed in its modulatory_signals attribute) that send ControlProjection and/or GatingProjections to the corresponding States. The States modulated by a ModulatoryMechanism’s modulatory_signals can be displayed using its show method. By default, each item of the ModulatoryMechanism’s modulatory_allocation attribute is assigned to the variable of the corresponding ControlSignal or GatingSignal in its modulatory_signals attribute; however, subtypes of ModulatoryMechanism may assign values differently. The allocations to any ControlSignals are also listed in the control_signals attribute; and the allocations to any GatingSignals are listed in the gating_signals attribute.

Costs and Net Outcome

If a ModulatoryMechanism has any ControlSignals in its modulatory_signals, then it also computes the combined costs of those, and a net_outcome based on them (see below). This is used by some subclasses of ModulatoryMechanism (e.g., OptimizationControlMechanism) to compute the modulatory_allocation. These are computed using the ModulatoryMechanism’s default compute_reconfiguration_cost, combine_costs, and compute_net_outcome functions, but these can also be assigned custom functions (see links to attributes for details).

## Execution¶

The ModulatoryMechanism’s function takes as its input the value of its OUTCOME input_state (also contained in outcome). It uses that to determine its modulatory_allocation that specifies the value assigned to its modulatory_signals. Each of those uses the allocation it is assigned to calculate its ControlSignal intensity or GatingSignal intensity. These are used by their ControlProjection(s) or GatingProjection(s), respectively, to modulate the value of the States to which they project. Those values are then used in the subsequent TRIAL of execution. If a ModulatoryMechanism is a Composition’s controller, it is generally either the first or the last Mechanism to be executed in a TRIAL, although this can be customized (see Composition Controller).

Note

ParameterStates that receive ControlProjections, and InputStates and/or OutputStates that receive GatingProjections, do not update their values until their owner Mechanisms execute (see Lazy Evaluation for an explanation of “lazy” updating). This means that even if a ModulatoryMechanism has executed, the States that it modulates will not assume their new values until the Mechanisms to which they belong have executed.

Computation of Costs and Net_Outcome

When a ModulatoryMechanism updates the intensity of any ControlSignals in its modulatory_signals, each of those ControlSignals calculates a cost, based on its intensity. The ModulatoryMechanism computes a reconfiguration_cost based on these, using its compute_reconfiguration_cost function. It then combines this with the cost of its individual ControlSignals, using its combine_costs function, and assigns the result to its costs attribute. The ModulatoryMechanism uses this, together with its outcome attribute, to compute a net_outcome using its compute_net_outcome function. This is used by some subclasses of ModulatoryMechanism (e.g., OptimizationControlMechanism) to compute its modulatory_allocation.

Examples

The following example creates a ModulatoryMechanism by specifying its objective_mechanism using a constructor that specifies the OutputStates to be monitored by its objective_mechanism and the function used to evaluated these:

>>> import psyneulink as pnl
>>> my_transfer_mech_A = pnl.TransferMechanism(name="Transfer Mech A")
>>> my_DDM = pnl.DDM(name="My DDM")
>>> my_transfer_mech_B = pnl.TransferMechanism(function=pnl.Logistic,
...                                            name="Transfer Mech B")

>>> my_modulatory_mech = pnl.ModulatoryMechanism(
...                          objective_mechanism=pnl.ObjectiveMechanism(monitor=[(my_transfer_mech_A, 2, 1),
...                                                                                               my_DDM.output_states[pnl.RESPONSE_TIME]],
...                                                                     name="Objective Mechanism"),
...                          function=pnl.LinearCombination(operation=pnl.PRODUCT),
...                          modulatory_signals=[(pnl.THRESHOLD, my_DDM),
...                                              (pnl.GAIN, my_transfer_mech_B)],
...                          name="My Control Mech")


This creates an ObjectiveMechanism for the ModulatoryMechanism that monitors the primary OutputState of my_Transfer_mech_A and the RESPONSE_TIME OutputState of my_DDM; its function first multiplies the former by 2 before, then takes product of their values and passes the result as the input to the ModulatoryMechanism. The ModulatoryMechanism’s function uses this value to determine the allocation for its ControlSignals, that control the value of the threshold parameter of my_DDM and the gain parameter of the Logistic Function for my_transfer_mech_B.

The following example specifies the same set of OutputStates for the ObjectiveMechanism, by assigning them directly to the objective_mechanism argument:

>>> my_modulatory_mech = pnl.ModulatoryMechanism(
...                             objective_mechanism=[(my_transfer_mech_A, 2, 1),
...                                                  my_DDM.output_states[pnl.RESPONSE_TIME]],
...                             modulatory_signals=[(pnl.THRESHOLD, my_DDM),
...                                                 (pnl.GAIN, my_transfer_mech_B)])
...


Note that, while this form is more succinct, it precludes specifying the ObjectiveMechanism’s function. Therefore, the values of the monitored OutputStates will be added (the default) rather than multiplied.

The ObjectiveMechanism can also be created on its own, and then referenced in the constructor for the ModulatoryMechanism:

>>> my_obj_mech = pnl.ObjectiveMechanism(monitor=[(my_transfer_mech_A, 2, 1),
...                                                               my_DDM.output_states[pnl.RESPONSE_TIME]],
...                                      function=pnl.LinearCombination(operation=pnl.PRODUCT))

>>> my_modulatory_mech = pnl.ModulatoryMechanism(
...                        objective_mechanism=my_obj_mech,
...                        modulatory_signals=[(pnl.THRESHOLD, my_DDM),
...                                            (pnl.GAIN, my_transfer_mech_B)])


Here, as in the first example, the constructor for the ObjectiveMechanism can be used to specify its function, as well as the OutputState that it monitors.

See Specifying Control for a System for examples of how a ModulatoryMechanism, the OutputStates its objective_mechanism, and its control_signals can be specified for a System.

## Class Reference¶

class psyneulink.core.components.mechanisms.adaptive.modulatorymechanism.ModulatoryMechanism(system=None monitor_for_modulation=None, objective_mechanism=None, function=DefaultAllocationFunction, modulatory_signals=None, modulation=ModulationParam.MULTIPLICATIVE combine_costs=np.sum, compute_reconfiguration_cost=None, compute_net_outcome=lambda x, y:x-y, params=None, name=None, prefs=None)

Subclass of AdaptiveMechanism that modulates the parameter(s) of one or more Component(s).

Parameters: system (System or bool : default None) – specifies the System to which the ModulatoryMechanism should be assigned as its controller. monitor_for_modulation (List[OutputState or Mechanism] : default None) – specifies the OutputStates to be monitored by the ObjectiveMechanism specified in the objective_mechanism argument; for any Mechanisms specified, their primary OutputState are used. objective_mechanism (ObjectiveMechanism | List[OutputState specification] | bool : default None) – specifies either an ObjectiveMechanism to use for the ModulatoryMechanism, the list of OutputStates that one constructed automatically should use, or the construction of a default ObjectiveMechanism (for True); if a list of OutputState specifications is specified, the list is passed to as the monitor argument in the constructor for a default ObjectiveMechanism. function (TransferFunction : default Linear(slope=1, intercept=0)) – specifies function used to combine values of monitored OutputStates. modulatory_signals (ControlSignal specification or List[ControlSignal specification, ..]) – specifies the parameters to be controlled by the ModulatoryMechanism; a ControlSignal is created for each (see Specifying ControlSignals for details of specification). modulation (ModulationParam : ModulationParam.MULTIPLICATIVE) – specifies the default form of modulation used by the ModulatoryMechanism’s ControlSignals, unless they are individually specified. combine_costs (Function, function or method : default np.sum) – specifies function used to combine the cost of the ModulatoryMechanism’s control_signals; must take a list or 1d array of scalar values as its argument and return a list or array with a single scalar value. compute_reconfiguration_cost (Function, function or method : default None) – specifies function used to compute the ModulatoryMechanism’s reconfiguration_cost; must take a list or 2d array containing two lists or 1d arrays, both with the same shape as the ModulatoryMechanism’s control_allocation attribute, and return a scalar value. compute_net_outcome (Function, function or method : default lambda outcome, cost: outcome-cost) – function used to combine the values of its outcome and costs attributes; must take two 1d arrays (outcome and cost) with scalar values as its arguments and return an array with a single scalar value. params (Dict[param keyword: param value] : default None) – a parameter dictionary that can be used to specify the parameters for the Mechanism, parameters for its function, and/or a custom function and its parameters. Values specified for parameters in the dictionary override any assigned to those parameters in arguments of the constructor. name (str : default see name) – specifies the name of the ModulatoryMechanism. prefs (PreferenceSet or specification dict : default Mechanism.classPreferences) – specifies the PreferenceSet for the ModulatoryMechanism; see prefs for details.
system

System_Base – The System for which the ModulatoryMechanism is a controller. Note that this is distinct from a Mechanism’s systems attribute, which lists all of the Systems to which a Mechanisms belongs – a ModulatoryMechanism can belong to but not be the controller of a Composition.

objective_mechanism

ObjectiveMechanismObjectiveMechanism that monitors and evaluates the values specified in the ModulatoryMechanism’s objective_mechanism argument, and transmits the result to the ModulatoryMechanism’s OUTCOME input_state.

monitor_for_modulation

List[OutputState] – each item is an OutputState monitored by the ObjectiveMechanism listed in the ModulatoryMechanism’s objective_mechanism attribute; it is the same as that ObjectiveMechanism’s monitor attribute (see Monitor for specification). The value of the OutputStates in the list are used by the ObjectiveMechanism to generate the ModulatoryMechanism’s input.

monitored_output_states_weights_and_exponents

List[Tuple(float, float)] – each tuple in the list contains the weight and exponent associated with a corresponding OutputState specified in monitor_for_modulation; these are the same as those in the monitored_output_states_weights_and_exponents attribute of the objective_mechanism, and are used by the ObjectiveMechanism’s function to parametrize the contribution made to its output by each of the values that it monitors (see ObjectiveMechanism Function).

outcome

1d array – the value of the ModulatoryMechanism’s primary InputState, which receives its Projection from the OUTCOME OutputState of its objective_mechanism.

function

TransferFunction : default Linear(slope=1, intercept=0) – determines how the value s of the OutputStates specified in the monitor_for_modulation argument of the ModulatoryMechanism’s constructor are used to generate its modulatory_allocation.

modulatory_signals

ContentAddressableList[ModulatorySignal] – list of the ModulatoryMechanisms ControlSignals and GatingSignals, including any inherited from a system for which it is a controller. This is the same as the ModulatoryMechanism’s output_states attribute).

modulatory_allocation

2d array – contains allocations for all the ModulatoryMechanism’s modulatory_signals; each item is the value assigned as the allocation for a ControlSignal (listed in the control_signals attribute, or a GatingSignal (listed in the gating_signals attribute (these are also listed in the control_allocation and gating_allocation attributes, respectively. The modulatory_allocation is the same as the ModulatoryMechanism’s value attribute).

control_signals

ContentAddressableList[ControlSignal] – list of the ControlSignals for the ModulatoryMechanism, including any inherited from a system for which it is a controller.

control_allocation

2d array – each item is the value assigned as the allocation for the corresponding ControlSignal listed in the control_signals attribute.

gating_signals

ContentAddressableList[GatingSignal] – list of the GatingSignals for the ModulatoryMechanism, including any inherited from a system for which it is a controller.

gating_allocation

2d array – each item is the value assigned as the allocation for the corresponding GatingSignal listed in the gating_signals attribute <ModulatoryMechanism.gating_signals>.

compute_reconfiguration_cost

Function, function or method – function used to compute the ModulatoryMechanism’s reconfiguration_cost; result is a scalar value representing the difference — defined by the function — between the values of the ModulatoryMechanism’s current and last control_alloction, that can be accessed by reconfiguration_cost attribute.

costs

list – current costs for the ModulatoryMechanism’s control_signals, computed for each using its compute_costs method.

combine_costs

Function, function or method – function used to combine the cost of its control_signals; result is an array with a scalar value that can be accessed by combined_costs.

Note

This function is distinct from the combine_costs_function of a ControlSignal. The latter combines the different costs for an individual ControlSignal to yield its overall cost; the ModulatoryMechanism’s combine_costs function combines those costs for its control_signals.

combined_costs

1d array – result of the ModulatoryMechanism’s combine_costs function.

compute_net_outcome

Function, function or method – function used to combine the values of its outcome and costs attributes; result is an array with a scalar value that can be accessed by the the net_outcome attribute.

net_outcome

1d array – result of the ModulatoryMechanism’s compute_net_outcome function.

modulatory_projections

List[ControlProjection | GatingProjection] – list of ControlProjections and/or GatingProjections, one for each of the corresponding ControlSignals and/or GatingSignals in modulatory_signals.

control_projections

List[ControlProjection] – list of ControlProjections, one for each ControlSignal in control_signals.

gating_projections

List[GatingProjection] – list of GatingProjections, one for each GatingSignal in gating_signals.

modulation

ModulationParam – the default form of modulation used by the ModulatoryMechanism’s ControlSignals, unless they are individually specified.

name

str – the name of the ModulatoryMechanism; if it is not specified in the name argument of the constructor, a default is assigned by MechanismRegistry (see Naming for conventions used for default and duplicate names).

prefs

PreferenceSet or specification dict – the PreferenceSet for the ModulatoryMechanism; if it is not specified in the prefs argument of the constructor, a default is assigned using classPreferences defined in __init__.py (see PreferenceSet for details).

add_to_monitor(monitor_specs, context=None)

Instantiate OutputStates to be monitored by ModulatoryMechanism’s objective_mechanism.

monitored_output_states can be any of the following:

If any item is a Mechanism, its primary OutputState is used. OutputStates must belong to Mechanisms in the same System as the ModulatoryMechanism.

assign_as_controller(system: psyneulink.core.components.shellclasses.System_Base, context=<ContextFlags.COMMAND_LINE: 512>)

Assign ModulatoryMechanism as controller for a System.

system must be a System for which the ModulatoryMechanism should be assigned as the controller. If the specified System already has a controller, it will be replaced by the current one, and the current one will inherit any ControlSignals previously specified for the old controller or the System itself. If the current one is already the controller for another System, it will be disabled for that System.

show()

Display the OutputStates monitored by ModulatoryMechanism’s objective_mechanism and the parameters modulated by its control_signals`.