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 subsequent executions.

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, as well as in the specification of the parameter that the ControlSignal is intended to modulate (also see Modualory Specificadtion. Although a ControlSignal can also be created on its own 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(s) to be controlled must be specified. If other attributes of the ControlSignal need to be specified (e.g., one or more of its cost functions), then the Constructor for the ControlSignal can be used or a state specification dictionary, in which the parameter(s) to be controlled in the projections argument or PROJECTIONS entry, respectively, using any of the forms below. For convenience, the parameters can also be specified on their own in the control_signals argument of the ControlMechanism’s constructor, in which case a default ControlSignal will be created for each. In all cases, any of the following can be use to specify the parameter(s) to be controlled:

  • ParameterState (or list of them) – for the Mechanism(s) to which the parameter(s) belong;
  • 2-item tuple: (parameter name or list of them>, <Mechanism>) – the 1st item 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.

  • specification dictionary – this is an abbreviated form of state specification dictionary, in which the parameter(s) to be controlled can be specified in either of the two following ways:

    • 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 controlled;
      • 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).

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 (e.g., OptimizationControlMechanism); 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 contains the 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.

FIX: 8/30/19 – ADD DESCRIPTION OF function AS ACTUALLY IMPLEMENTED AS TransferWithCosts
AND MODIFY DOCUMENTATION OF COSTS AND COST FUNCTIONS BELOW, AND THEIR Attributes ENTRIES ACCORDINGLY: - cost functions can be specified, but attributes are pointers to function’s cost functions - cost attributes get value of corresponding attributes of cost function - ?handling of cost_options

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 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:

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 CostFunctions, each of which specifies a cost component. How the enabled components are combined is determined by the combine_costs_function. By default, the values of the enabled cost components are summed, however this can be modified by specifying the combine_costs_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.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 a control_allocation, 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:

>>> from psyneulink import *
>>> my_mech = TransferMechanism(function=Logistic(bias=(1.0, 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 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 bias 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 the 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 = TransferMechanism(function=Logistic(gain=(1.0, ControlSignal(modulation=ADDITIVE))))

Note that the ModulationParam specified for the ControlSignal refers to how the parameter of the Logistic Function (in this case, its gain parameter) is modified, and not directly to input Logistic function; 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., it would have replaced) the value of the Logistic Function’s gain parameter, rather than added to it.

Class Reference

class psyneulink.core.components.states.modulatorysignals.controlsignal.ControlSignal(owner, default_allocation=defaultControlAllocation, index=SEQUENTIAL, function=TransferWithCosts, costs_options=None, intensity_cost_function=Exponential, adjustment_cost_function=Linear, duration_cost_function=IntegratorFunction, combine_costs_function=Reduce(operation=SUM), allocation_samples=self.class_defaults.allocation_samples, modulation=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.
  • default_allocation (scalar, list or np.ndarray : defaultControlAllocation) – specifies the template and default value used for allocation; must match the shape of each item specified in allocation_samples.
  • index (int : default SEQUENTIAL) – specifies the item of the owner ControlMechanism’s control_allocation used as the ControlSignal’s value.
  • function (Function or method : default TransferWithCosts(transfer_fct=Linear(slope=1, intercept=0))) – specifies the function used to determine the intensity of the ControlSignal from its allocation; must be TransferWithCosts or a subclass of that, or one that meets the requirements described see above); see function for default behavior.
  • cost_options (CostFunctions or List[CostsFunctions] : None) – 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 IntegratorFunction) – specifies the function used to calculate the contribution of the ControlSignal’s duration to its cost.
  • combine_costs_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, 1d array, or SampleSpec : default SampleSpec(0.1, 1, 0.1)) – specifies the values used by the ControlSignal’s owner to determine its control_allocation (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.
  • modulates (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

scalar, list or np.ndarray – same as allocation.

allocation

float : default: defaultControlAllocation – value assigned by the ControlSignal’s owner, and used as the variable of its function to determine the ControlSignal’s ControlSignal.intensity.

last_allocation

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

allocation_samples

SampleIteratorSampleIterator created from allocation_samples specification and used to generate a set of values to sample by the ControlSignal’s owner when determining its control_allocation.

function

TransferWithCosts – converts allocation into the ControlSignal’s intensity. The default is the identity function, which assigns the ControlSignal’s allocation as its intensity, and does not calculate any costs. See ControlSignals_Function for additional details.

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 control_allocation used as the ControlSignal’s value.

control_signal

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

cost_options

CostFunctions or None – boolean combination of currently assigned CostFunctions. 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.

A ControlSignal’s adjustment_cost, and its adjustment_cost_function are distinct from the reconfiguration_cost and compute_reconfiguration_cost <ControlMechanism.compute_reconfiguration_cost function of the Control Mechanisms to which the ControlSignal belongs (see ControlMechanism Reconfiguration Cost for additional details).

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.

combine_costs_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).

compute_costs(intensity, context=None)

Compute costs based on self.value (intensity).