ControlSignal

Overview

A ControlSignal is a type of ModulatorySignal that is specialized for use with a ControlMechanism and one or more ControlProjections, to modify the parameter(s) of one or more Components. A ControlSignal receives an allocation value from the ControlMechanism to which it belongs, and uses that to compute an intensity (also referred to as a control_signal) that is assigned as the value of its ControlProjections. Each ControlProjection conveys its value to the ParameterState for the parameter it controls, which uses that value to modulate the value of the parameter. A ControlSignal also calculates a cost, based on its intensity and/or its time course, that may be used by the ControlMechanism to adapt the ControlSignal’s allocation in the future.

Creating a ControlSignal

A ControlSignal is created automatically whenever the parameter of a Mechanism or of its function is specified for control. ControlSignals can also be specified in the control_signals argument of the constructor for a ControlMechanism or a System. Although a ControlSignal can be created directly using its constructor (or any of the other ways for creating an OutputState), this is usually not necessary nor is it advisable, as a ControlSignal has dedicated components and requirements for configuration that must be met for it to function properly.

Specifying ControlSignals

When a ControlSignal is specified in the control_signals argument of the constructor for a ControlMechanism, the parameter to be controlled must be specified. This can take any of the following forms:

  • ParameterState – of the Mechanism to which the parameter belongs;
  • specification dictionary – can take either of the following two forms:

    • for controlling a single parameter, the dictionary can have the following two entries:

      • NAME: str
        the string must be the name of the parameter to be gated;
      • MECHANISM: Mechanism
        the Mechanism must be the one to the which the parameter to be controlled belongs.
    • for controlling multiple parameters, the dictionary can have the following entry:

      • <str>:list
        the string used as the key specifies the name to be used for the ControlSignal, and each item of the list must be a specification of a parameter to be controlled by the ControlSignal (and that will receive a ControlProjection from it).
  • 2-item tuple – the 1st time must be the name of the parameter (or list of parameter names), and the 2nd item the Mechanism to which it (they) belong(s); this is a convenience format, that is simpler to use than a specification dictionary (see above), but precludes specification of any parameters for the ControlSignal.

Structure

A ControlSignal is owned by an ControlMechanism, and controls the parameters of one or more Components by modulating the function of the ParameterState that determines the value of each of the parameters that it control. Its operation is governed by several attributes of the ControlSignal, that are described below.

Projections

When a ControlSignal is created, it can be assigned one or more ControlProjections, using either the projections argument of its constructor, or in an entry of a dictionary assigned to the params argument with the key PROJECTIONS. These will be assigned to its efferents attribute. See State Projections for additional details concerning the specification of Projections when creating a State.

Note

Although a ControlSignal can be assigned more than one ControlProjection, all of those Projections will receive the same value (based on the intensity of that ControlSignal), and use the same form of modulation. Thus, for them to be meaningful, they should project to ParameterStates for parameters that are meaningfully related to one another (for example, the threshold parameter of multiple DDM Mechanisms).

Modulation

A ControlSignal has a modulation attribute that determines how its ControlSignal’s value is used by the States to which it projects to modify their value s (see Modulation for an explanation of how the modulation attribute is specified and used to modulate the value of a State). The modulation attribute can be specified in the modulation argument of the constructor for a ControlSignal, or in a specification dictionary as described above. The value must be a value of ModulationParam; if it is not specified, its default is the value of the modulation attribute of the ControlMechanism to which the ControlSignal belongs (which is the same for all of the ControlSignals belonging to that ControlMechanism). The value of the modulation attribute of a ControlSignal is used by all of the ControlProjections that project from that ControlSignal.

Allocation, Function and Intensity

Allocation (variable). A ControlSignal is assigned an allocation by the ControlMechanism to which it belongs. Some ControlMechanisms sample different allocation values for their ControlSignals to determine which to use (such as the EVCControlMechanism); in those cases, they use each ControlSignal’s allocation_samples attribute (specified in the allocation_samples argument of the ControlSignal’s constructor) to determine the allocation values to sample for that ControlSignal. A ControlSignal’s allocation attribute reflects value assigned to it by the ControlMechanism at the end of the previous TRIAL (i.e., when the ControlMechanism last executed – see ControlMechanism Execution); its value from the previous TRIAL is assigned to the last_intensity attribute.

Function. A ControlSignal’s allocation serves as its`variable <ControlSignal.variable>`, and is used by its function to generate an intensity. The default function for a ControlSignal is an identity function (Linear with slope =1 and intercept=0), that simply assigns the allocation as the ControlSignal’s intensity. However, another TransferFunction can be assigned (e.g., Exponential), or any other function that takes and returns a scalar value or 1d array.

Intensity (value). The result of the function is assigned as the value of the ControlSignal’s intensity attribute, which serves as the ControlSignal’s value (also referred to as control_signal). The intensity is used by its ControlProjection(s) to modulate the parameter(s) for which the ControlSignal is responsible. The ControlSignal’s intensity attribute reflects its value for the current TRIAL; its value from the previous TRIAL is assigned to the last_intensity attribute.

Costs and Cost Functions

A ControlSignal has a cost attribute that may be used by the ControlMechanism to which it belongs to determine its future allocation. The value of the cost is computed from the ControlSignal’s intensity using one or more of three cost functions, each of which computes a different component of the cost, and a function that combines them, as listed below:

  • duration_cost - calculated by the `duration_cost_function based on an integral of the the ControlSignal’s cost;

The components used to determine the ControlSignal’s cost can be specified in the costs_options argument of its constructor, or using its enable_costs, disable_costs and assign_costs methods. All of these take one or more values of ControlSignalCosts, each of which specifies a cost component. How the enabled components are combined is determined by the cost_combination_function. By default, the values of the enabled cost components are summed, however this can be modified by specifying the cost_combination_function.

Note

The index and assign attributes of a ControlSignal are automatically assigned and should not be modified.

Execution

A ControlSignal cannot be executed directly. It is executed whenever the ControlMechanism to which it belongs is executed. When this occurs, the ControlMechanism provides the ControlSignal with an allocation, that is used by its function to compute its intensity for that TRIAL. The intensity is used by the ControlSignal’s ControlProjections to set the value (s) of the ParameterState(s) to which the ControlSignal projects.

Recall that the ParameterState value is referenced anywhere that the controlled parameter is used in computation, and that it does not update until the component to which the ParameterState belongs executes. If the distinction between the base value stored in the parameter attribute (i.e. MyTransferMech.function_object.gain) and the value of the ParameterState is unfamiliar, see Parameter State documentation for more details, or see Modulation for a detailed description of how modulation operates.

The ControlSignal’s intensity is also used by its cost functions to compute its cost attribute. That is used by some ControlMechanisms, along with the ControlSignal’s allocation_samples attribute, to evaluate an allocation_policy, and adjust the ControlSignal’s allocation for the next TRIAL.

Note

The changes in a parameter in response to the execution of a ControlMechanism are not applied until the Mechanism with the parameter being controlled is next executed; see Lazy Evaluation for an explanation of “lazy” updating).

Examples

Modulate the parameter of a Mechanism’s function. The following example assigns a ControlSignal to the bias parameter of the Logistic Function used by a TransferMechanism:

>>> import psyneulink as pnl
>>> my_mech = pnl.TransferMechanism(function=pnl.Logistic(bias=(1.0, pnl.ControlSignal)))

Note that the ControlSignal is specified by it class. This will create a default ControlSignal, with a ControlProjection that projects to the TransferMechanism’s ParameterState for the bias parameter of its Logistic Function. The default value of a ControlSignal’s modulation attribute is Modulation.MULTIPLICATIVE, so that it will multiply the value of the bias parameter. When the TransferMechanism executes, the Logistic Function will use the value of the ControlSignal as its gain parameter.

Specify attributes of a ControlSignal. Ordinarily, ControlSignals modify the MULTIPLICATIVE_PARAM of a ParameterState’s function to modulate the parameter’s value. In the example below, this is changed by specifying the modulation attribute of a ControlSignal for the Logistic Function of a TransferMechanism. It is changed so that the value of the ControlSignal adds to, rather than multiplies, the value of the gain parameter of the Logistic function:

>>> my_mech = pnl.TransferMechanism(function=pnl.Logistic(gain=(1.0,
...                                                             pnl.ControlSignal(modulation=pnl.ModulationParam.ADDITIVE))))

Note that the ModulationParam specified for the ControlSignal pertains to the function of a ParameterState for the Logistic Function (in this case, its gain parameter), and not the Logistic function itself – that is, in this example, the value of the ControlSignal is added to the gain parameter of the Logistic function, not its variable). If the value of the ControlSignal’s modulation argument had been ModulationParam.OVERRIDE, then the ControlSignal’s value would have been used as (i.e., replaced) the value of the Logistic Function’s gain parameter, rather than added to it.

Modulate the parameters of several Mechanisms in a System. The following example assigns ControlSignals to modulate the gain parameter of the Logistic function for My_Mech_A and the intercept parameter of the Linear function for My_Mech_B:

>>> my_mech_a = pnl.TransferMechanism(function=pnl.Logistic)
>>> my_mech_b = pnl.TransferMechanism(function=pnl.Linear,
...                                   output_states=[pnl.RESULT, pnl.MEAN])

>>> process_a = pnl.Process(pathway=[my_mech_a])
>>> process_b = pnl.Process(pathway=[my_mech_b])

>>> my_system = pnl.System(processes=[process_a, process_b],
...                        monitor_for_control=[my_mech_a.output_states[pnl.RESULTS],
...                                             my_mech_b.output_states[pnl.MEAN]],
...                        control_signals=[(pnl.GAIN, my_mech_a),
...                                         {pnl.NAME: pnl.INTERCEPT,
...                                          pnl.MECHANISM: my_mech_b,
...                                          pnl.MODULATION: pnl.ModulationParam.ADDITIVE}],
...                        name='My Test System')

Class Reference

class psyneulink.components.states.modulatorysignals.controlsignal.ControlSignalCosts

Options for selecting cost functions to be used by a ControlSignal.

These can be used alone or in combination with one another, by enabling or disabling each using the ControlSignal’s toggle_cost_function method.

NONE

ControlSignal’s cost is not computed.

INTENSITY_COST

intensity_cost_function is used to calculate a contribution to the ControlSignal’s cost based its current intensity value.

ADJUSTMENT_COST

adjustment_cost_function is used to calculate a contribution to the cost based on the change in its intensity from its last value.

DURATION_COST

duration_cost_function is used to calculate a contribitution to the cost based on an integral of the ControlSignal’s cost (i.e., it accumulated value over multiple executions).

ALL

all of the cost functions.

DEFAULTS

assign default set of cost functions (currently set to INTENSITY_COST).

class psyneulink.components.states.modulatorysignals.controlsignal.ControlSignal(owner, index=SEQUENTIAL, function=Linear(), costs_options=ControlSignalCosts.DEFAULTS, intensity_cost_function=Exponential, adjustment_cost_function=Linear, duration_cost_function=Integrator, cost_combination_function=Reduce(operation=SUM), allocation_samples=self.ClassDefaults.allocation_samples, modulation=ModulationParam.MULTIPLICATIVE projections=None params=None, name=None, prefs=None)

A subclass of ModulatorySignal used by a ControlMechanism to modulate the parameter(s) of one or more other Mechanisms.

Parameters:
  • owner (ControlMechanism) – specifies the ControlMechanism to which to assign the ControlSignal.
  • index (int : default SEQUENTIAL) – specifies the item of the owner ControlMechanism’s allocation_policy used as the ControlSignal’s value.
  • function (Function or method : default Linear) – specifies the function used to determine the intensity of the ControlSignal from its allocation.
  • cost_options (ControlSignalCosts or List[ControlSignalCosts] : ControlSignalsCosts.DEFAULTS) – specifies the cost components to include in the computation of the ControlSignal’s cost.
  • intensity_cost_function (Optional[TransferFunction] : default Exponential) – specifies the function used to calculate the contribution of the ControlSignal’s intensity to its cost.
  • adjustment_cost_function (Optional[TransferFunction] : default Linear) – specifies the function used to calculate the contribution of the change in the ControlSignal’s intensity (from its last_intensity value) to its cost.
  • duration_cost_function (IntegratorFunction : default Integrator) – specifies the function used to calculate the contribution of the ControlSignal’s duration to its cost.
  • cost_combination_function (function : default Reduce(operation=SUM)) – specifies the function used to combine the results of any cost functions that are enabled, the result of which is assigned as the ControlSignal’s cost attribute.
  • allocation_samples (list : default range(0.1, 1, 0.1)) – specifies the values used by ControlSignal's `ControlSignal.owner to determine its allocation_policy (see Execution).
  • modulation (ModulationParam : default ModulationParam.MULTIPLICATIVE) – specifies the way in which the value the ControlSignal is used to modify the value of the parameter(s) that it controls.
  • projections (list of Projection specifications) – specifies the ControlProjection(s) to be assigned to the ControlSignal, and that will be listed in its efferents attribute (see Projections for additional details).
  • params (Dict[param keyword: param value] : default None) – a parameter dictionary that can be used to specify the parameters for the ControlSignal 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 ModulatorySignal name) – specifies the name of the ControlSignal; see ControlSignal name for additional details.
  • prefs (PreferenceSet or specification dict : default State.classPreferences) – specifies the PreferenceSet for the ControlSignal; see prefs for details.
owner

ControlMechanism – the ControlMechanism to which the ControlSignal belongs.

variable

number, list or np.ndarray – same as allocation; used by function to compute the ControlSignal’s intensity.

allocation

float : default: defaultControlAllocation – value used as variable for the ControlSignal’s function to determine its intensity.

last_allocation

float – value of allocation in the previous execution of ControlSignal’s owner.

allocation_samples

list : DEFAULT_SAMPLE_VALUES – set of values to sample by the ControlSignal’s owner to determine its allocation_policy.

function

TransferFunction : default Linear(slope=1, intercept=0) – converts allocation into the ControlSignal’s intensity. The default is the identity function, which assigns the ControlSignal’s allocation as its intensity.

value

float – result of the ControlSignal’s function; same as intensity and control_signal.

intensity

float – result of the ControlSignal’s function; assigned as the value of the ControlSignal’s ControlProjection, and used to modify the value of the parameter to which the ControlSignal is assigned; same as control_signal.

last_intensity

float – the intensity of the ControlSignal on the previous execution of its owner.

index

int – the item of the owner ControlMechanism’s allocation_policy used as the ControlSignal’s value.

control_signal

float – result of the ControlSignal’s function; same as intensity.

cost_options

int – boolean combination of currently assigned ControlSignalCosts. Specified initially in costs argument of ControlSignal’s constructor; can be modified using the assign_cost_options method.

intensity_cost_function

TransferFunction : default default Exponential – calculates intensity_cost from the current value of intensity. It can be any TransferFunction, or any other function that takes and returns a scalar value. The default is Exponential. It can be disabled permanently for the ControlSignal by assigning None.

intensity_cost

float – cost associated with the current intensity.

adjustment_cost_function

TransferFunction : default Linear – calculates adjustment_cost based on the change in intensity from last_intensity. It can be any TransferFunction, or any other function that takes and returns a scalar value. It can be disabled permanently for the ControlSignal by assigning None.

adjustment_cost

float – cost associated with last change to intensity.

duration_cost_function

IntegratorFunction : default Linear – calculates an integral of the ControlSignal’s cost. It can be any IntegratorFunction, or any other function that takes a list or array of two values and returns a scalar value. It can be disabled permanently for the ControlSignal by assigning None.

duration_cost

float – intregral of cost.

cost_combination_function

function : default Reduce(operation=SUM) – combines the results of all cost functions that are enabled, and assigns the result to cost. It can be any function that takes an array and returns a scalar value.

cost

float – combined result of all cost functions that are enabled.

modulation

ModulationParam – specifies the way in which the value the ControlSignal is used to modify the value of the parameter(s) that it controls.

efferents

[List[ControlProjection]] – a list of the ControlProjections assigned to (i.e., that project from) the ControlSignal.

name

str – name of the ControlSignal; if it is not specified in the name argument of its constructor, a default name is assigned (see name).

Note

Unlike other PsyNeuLink components, State names are “scoped” within a Mechanism, meaning that States with the same name are permitted in different Mechanisms. However, they are not permitted in the same Mechanism: States within a Mechanism with the same base name are appended an index in the order of their creation.

prefs

PreferenceSet or specification dict – the PreferenceSet for the ControlSignal; 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).

assign_costs(costs)

Assigns specified costs; all others are disabled.

Parameters:costs (ControlSignalCost or List[ControlSignalCosts]) – cost or list of costs to be used; all other will be disabled.
Returns:cost_options – current value of cost_options.
Return type:boolean combination of ControlSignalCosts
enable_costs(costs)

Enables specified costs; settings for all other costs are left intact.

Parameters:costs (ControlSignalCost or List[ControlSignalCosts]) – cost or list of costs to be enabled, in addition to any that are already enabled.
Returns:cost_options – current value of cost_options.
Return type:boolean combination of ControlSignalCosts
disable_costs(costs)

Disables specified costs; settings for all other costs are left intact.

Parameters:costs (ControlSignalCost or List[ControlSignalCosts]) – cost or list of costs to be disabled.
Returns:cost_options – current value of cost_options.
Return type:boolean combination of ControlSignalCosts
toggle_cost_function(cost_function_name, assignment=True)

Enables/disables use of a cost function.

cost_function_name should be a keyword (list under Structure).

get_costs()

Return three-element list with the values of intensity_cost, adjustment_cost and duration_cost