# States¶

## Overview¶

A State provides an interface to one or more Projections, and receives the value(s) provided by them. The value of a State can be modulated by a ModulatoryProjection. There are three primary types of States (InputStates, ParameterStates and OutputStates) as well as one subtype (ModulatorySignal, used to send ModulatoryProjections), as summarized in the table below:

State Types and Associated Projection Types
State Type Owner Description Modulated by Specification
InputState Mechanism receives input from MappingProjection GatingSignal InputState constructor; Mechanism constructor or its add_states method
ParameterState Mechanism or Projection represents parameter value for a Component or its function LearningSignal and/or ControlSignal Implicitly whenever a parameter value is specified
OutputState Mechanism provides output to MappingProjection GatingSignal OutputState constructor; Mechanism constructor or its add_states method
ModulatorySignal AdaptiveMechanism provides value for ModulatoryProjection   AdaptiveMechanism constructor; tuple in State or parameter specification

## Creating a State¶

In general, States are created automatically by the objects to which they belong (their owner), or by specifying the State in the constructor for its owner. For example, unless otherwise specified, when a Mechanism is created it creates a default InputState and OutputState for itself, and whenever any Component is created, it automatically creates a ParameterState for each of its configurable parameters and those of its function. States are also created in response to explicit specifications. For example, InputStates and OutputStates can be specified in the constructor for a Mechanism (see Specifying States); and ParameterStates are specified in effect when the value of a parameter for any Component or its function is specified in the constructor for that Component or function. InputStates and OutputStates (but not ParameterStates) can also be created directly using their constructors, and then assigned to a Mechanism using the Mechanism’s add_states method; however, this should be done with caution as the State must be compatible with other attributes of its owner (such as its OutputStates) and its function (for example, see note regarding InputStates). Parameter States cannot on their own; they are always and only created when the Component to which a parameter belongs is created.

### Specifying a State¶

A State can be specified using any of the following:

• existing State object;
• name of a State subclass (InputState, ParameterState, or OutputState) – creates a default State of the specified type, using a default value for the State that is determined by the context in which it is specified.
• value – creates a default State using the specified value as its default value.
• State specification dictionary – can use the following: KEY:<value> entries, in addition to those specific to the State’s type (see documentation for each type):

• STATE_TYPE:<State type>
specifies type of State to create (necessary if it cannot be determined from the the context of the other entries or in which it is being created).
• NAME:<str>
the string is used as the name of the State.
• VALUE:<value>
the value is used as the default value of the State.

A State specification dictionary can also be used to specify one or more Projections used to modify the value of the State. The type of Projection(s) created depend on the type of State specified and context of the specification (see examples). This can be done using any of the following entries, each of which can contain any of the forms used to specify a Projection:

• MECHANISM:Mechanism
this can be used to specify one or more Projections to or from the specified Mechanism. If the entry appears without any accompanying State specification entries (see below), the Projection is assumed to be a MappingProjection to the Mechanism’s primary InputState or from its primary OutputState, depending upon the type of Mechanism and context of specification. It can also be accompanied by one or more State specification entries described below, to create one or more Projections to/from those specific States (see examples).
• <STATES_KEYWORD>:List[<str or State.name>,…]

this must accompany a MECHANISM entry (described above), and is used to specify its State(s) by name. Each entry must use one of the following keywords as its key, and there can be no more than one of each:

• INPUT_STATES
• OUTPUT_STATES
• PARAMETER_STATES
• LEARNING_SIGNAL
• CONTROL_SIGNAL
• GATING_SIGNAL.

Each entry must contain a list States of the specified type, all of which belong to the Mechanism specified in the MECHANISM entry; each item in the list must be the name of one the Mechanism’s States, or a ProjectionTuple the first item of which is the name of a State. The types of States that can be specified in this manner depends on the type of the Mechanism and context of the specification (see examples).

• State, Mechanism, or list of these – creates a default State with Projection(s) to/from the specified States; the type of State being created determines the type and directionality of the Projection(s) and, if Mechanism(s) are specified, which of their primary States are used (see State subclasses for specifics).

• Tuple specifications – these are convenience formats that can be used to compactly specify a State by specifying other Components with which it should be connected by Projection(s). Different States support different forms, but all support the following two forms:

• 2-item tuple: (<State name or list of State names>, <Mechanism>) – 1st item is the name of a State or list of them, and the 2nd item is the Mechanism to which they belong; a Projection is created to or from each of the States specified. The type of Projection depends on the type of State being created, and the type of States specified in the tuple (see Sender, Receiver and Attribute Assignments for Projection Types). For example, if the State being created is an InputState, and the States specified in the tuple are OutputStates, then MappingProjections are used; if ModulatorySignals are specified, then the corresponding type of ModulatoryProjections are created. See State subclasses for additional details and compatibility requirements.

• ProjectionTuple – a 4-item tuple that specifies one or more Projections to or from other State(s), along with a weight and/or exponent for each.

### Projections¶

When a State is created, it can be assigned one or more Projections, in either the projections argument of its constructor, or a PROJECTIONS entry of a State specification dictionary (or a dictionary assigned to the params argument of the State’s constructor). The following types of Projections can be specified for each type of State:

Specifiable Projections for State Types
State Type
PROJECTIONS specification
Assigned to Attribute
InputState
ParameterState
OutputState
Modulatory Signals

Projections must be specified in a list. Each entry must be either a specification for a projection, or for a sender or receiver of one, in which case the appropriate type of Projection is created. A sender or receiver can be specified as a State or a Mechanism. If a Mechanism is specified, its primary InputState or OutputState is used, as appropriate. When a sender or receiver is used to specify the Projection, the type of Projection created is inferred from the State and the type of sender or receiver specified, as illustrated in the examples below. Note that the State must be assigned to an owner in order to be functional, irrespective of whether any Projections have been assigned to it.

### Deferred Initialization¶

If a State is created on its own, and its owner Mechanism is specified, it is assigned to that Mechanism; if its owner not specified, then its initialization is deferred. Its initialization is completed automatically when it is assigned to an owner Mechanism using the owner’s add_states method. If the State is not assigned to an owner, it will not be functional (i.e., used during the execution of Mechanisms and/or Compositions, irrespective of whether it has any Projections assigned to it.

## Structure¶

### Owner¶

Every State has an owner. For InputStates and OutputStates, the owner must be a Mechanism. For ParameterStates it can be a Mechanism or a PathwayProjection. For ModulatorySignals, it must be an AdaptiveMechanism. When a State is created as part of another Component, its owner is assigned automatically to that Component. It is also assigned automatically when the State is assigned to a Mechanism using that Mechanism’s add_states method. Otherwise, it must be specified explicitly in the owner argument of the constructor for the State (in which case it is immediately assigned to the specified Mechanism). If the owner argument is not specified, the State’s initialization is deferred until it has been assigned to an owner using the owner’s add_states method.

### Projections¶

Every State has attributes that lists the Projections it sends and/or receives. These depend on the type of State, listed below (and shown in the table):

State Projection Attributes
Attribute Projection Type and State(s)
path_afferents MappingProjections to InputState
mod_afferents ModulatoryProjections to any State
efferents MappingProjections from OutputState

In addition to these attributes, all of the Projections sent and received by a State are listed in its projections attribute.

### Variable, Function and Value¶

In addition, like all PsyNeuLink Components, it also has the three following core attributes:

### Modulation¶

Every type of State has a mod_afferents attribute, that lists the ModulatoryProjections it receives. Each ModulatoryProjection comes from a ModulatorySignal that specifies how it should modulate the State’s value when the State is updated (see Modulation and ModulatorySignal_Anatomy_Figure). In most cases, a ModulatorySignal uses the State’s function to modulate its value. The function of every State assigns one of its parameters as its ADDITIVE_PARAM and another as its MULTIPLICATIVE_PARAM. The modulation attribute of a ModulatorySignal determines which of these to modify when the State uses it function to calculate its value. However, the ModulatorySignal can also be configured to override the State’s value (i.e., assign it directly), or to disable modulation, using one of the values of ModulationParam for its modulation attribute (see Modulation for a more detailed discussion).

## Execution¶

States cannot be executed. They are updated when the Component to which they belong is executed. InputStates and ParameterStates belonging to a Mechanism are updated before the Mechanism’s function is called. OutputStates are updated after the Mechanism’s function is called. When a State is updated, it executes any Projections that project to it (listed in its all_afferents attribute. It uses the values it receives from any PathWayProjections (listed in its path_afferents attribute) as the variable for its function. It then executes all of the ModulatoryProjections it receives. Different ModulatorySignals may call for different forms of modulation (see Modulation). Accordingly, it separately sums the values specified by any ModulatorySignals for the MULTIPLICATIVE_PARAM of its function, and similarly for the ADDITIVE_PARAM. It then applies the summed value for each to the corresponding parameter of its function. If any of the ModulatorySignals specifies OVERRIDE, then the value of that ModulatorySignal is used as the State’s value. Finally, the State calls its function to determine its value.

Note

The change in the value of a State does not occur until the Mechanism to which the State belongs is next executed; This conforms to a “lazy evaluation” protocol (see Lazy Evaluation for an explanation of “lazy” updating).

Examples

Usually, States are created automatically by the Mechanism to which they belong. For example, creating a TransferMechanism:

my_mech = pnl.TransferMechanism()


automatically creates an InputState, ParameterStates for its parameters, including the slope and intercept parameters of its Linear Function (its default function), and an OutputState (named RESULT):

print(my_mech.input_states)
> [(InputState InputState-0)]
print(my_mech.parameter_states)
> [(ParameterState intercept), (ParameterState slope), (ParameterState noise), (ParameterState integration_rate)]
print(my_mech.output_states)
> [(OutputState RESULT)]


Using the input_states argument of a Mechanism constructor.

When States are specified explicitly, it is usually in an argument of the constructor for the Mechanism to which they belong. For example, the following specifies that my_mech should have an InputState named ‘MY INPUT:

my_mech = pnl.TransferMechanism(input_states=['MY INPUT'])
print(my_mech.input_states)
> [(InputState 'MY INPUT')]


The InputState was specified by a string (for its name) in the input_states argument. It can also be specified in a variety of other ways, as described above and illustrated in the examples below. Note that when one or more States is specified in the argument of a Mechanism’s constructor, it replaces any defaults States created by the Mechanism when none are specified (see note.

For example, the following specifies the InputState by a value to use as its default_variable attribute:

my_mech = pnl.TransferMechanism(input_states=[[0,0])


The value is also used to format the InputState’s value, as well as the first (and, in this case, only) item of the Mechanism’s variable (i.e., the one to which the InputState is assigned), as show below:

print(my_mech.input_states[0].variable)
> [0 0]
print (my_mech.input_state.value)
> [ 0.  0.]
print (my_mech.variable)
> [[0 0]]


Note that in the first print state, the InputState was referenced as the first one in the input_states attribute of my_mech; the second print state references it directly, as the primary InputState of my_mech, using its input_state attribute (note the singular).

Multiple InputStates

The input_states argument can also be used to create more than one InputState:

my_mech = pnl.TransferMechanism(input_states=['MY FIRST INPUT', 'MY SECOND INPUT'])
print(my_mech.input_states)
> [(InputState MY FIRST INPUT), (InputState MY SECOND INPUT)]


Here, the print statement uses the input_states attribute, since there is now more than one InputState. OutputStates can be specified in a similar way, using the output_states argument.

Note

Although InputStates and OutputStates can be specified in a Mechanism’s constructor, ParameterStates cannot; those are created automatically when the Mechanism is created, for each of its user configurable parameters and those of its function. However, the value can be specified when the Mechanism is created, or its function is assigned, and can be accessed and subsequently modified, as described under ParameterState_Specification>.

OutputStates

The following example specifies two OutputStates for my_mech, using its Standard OutputStates:

my_mech = pnl.TransferMechanism(output_states=['RESULT', 'MEAN'])


As with InputStates, specification of OutputStates in the output_states argument suppresses the creation of any default OutPutStates that would have been created if no OutputStates were specified (see note above). For example, TransferMechanisms create a RESULT OutputState by default, that contains the result of their function. This default behavior is suppressed by any specifications in its output_states argument. Therefore, to retain a RESULTS OutputState, it must be included in the output_states argument along with any others that are specified, as in the example above. If the name of a specified OutputState matches the name of a Standard OutputState <OutputState_Standard> for the type of Mechanism, then that is used (as is the case for both of the OutputStates specified for the TransferMechanism in the example above); otherwise, a new OutputState is created.

State specification dictionary

States can be specified in greater detail using a State specification dictionary. In the example below, this is used to specify the variable and name of an InputState:

my_mech = pnl.TransferMechanism(input_states=[{STATE_TYPE: InputState,
NAME: 'MY INPUT',
VARIABLE: [0,0]})


The STATE_TYPE entry is included here for completeness, but is not actually needed when the State specification dicationary is used in input_states or output_states argument of a Mechanism, since the State’s type is clearly determined by the context of the specification; however, where that is not clear, then the STATE_TYPE entry must be included.

Projections

A State specification dictionary can also be used to specify projections to or from the State, also in a number of different ways. The most straightforward is to include them in a PROJECTIONS entry. For example, the following specifies that the InputState of my_mech receive two Projections, one from source_mech_1 and another from source_mech_2, and that its OutputState send one to destination_mech:

source_mech_1 = pnl.TransferMechanism(name='SOURCE_1')
source_mech_2 = pnl.TransferMechanism(name='SOURCE_2')
destination_mech = pnl.TransferMechanism(name='DEST')
my_mech = pnl.TransferMechanism(name='MY_MECH',
input_states=[{pnl.NAME: 'MY INPUT',
pnl.PROJECTIONS:[source_mech_1, source_mech_2]}],
output_states=[{pnl.NAME: 'RESULT',
pnl.PROJECTIONS:[destination_mech]}])

# Print names of the Projections:
for projection in my_mech.input_state.path_afferents:
print(projection.name)
> MappingProjection from SOURCE_1[RESULT] to MY_MECH[MY INPUT]
> MappingProjection from SOURCE_2[RESULT] to MY_MECH[MY INPUT]
for projection in my_mech.output_state.efferents:
print(projection.name)
> MappingProjection from MY_MECH[RESULT] to DEST[InputState]


A PROJECTIONS entry can contain any of the forms used to specify a Projection. Here, Mechanisms are used, which creates Projections from the primary InputState of source_mech, and to the primary OutputState of destination_mech. Note that MappingProjections are created, since the Projections specified are between InputStates and OutputStates. Modulatory Projections can also be specified in a similar way. The following creates a Gating Mechanism, and specifies that the InputState of my_mech should receive a GatingProjection from it:

my_gating_mech = pnl.GatingMechanism()
my_mech = pnl.TransferMechanism(name='MY_MECH',
input_states=[{pnl.NAME: 'MY INPUT',
pnl.PROJECTIONS:[my_gating_mech]}])


Conversely, ModulatoryProjections can also be specified from a Mechanism to one or more States that it modulates. In the following example, a Control Mechanism is created that sends ControlProjections to the drift_rate and threshold ParameterStates of a DDM Mechanism:

my_mech = pnl.DDM(name='MY DDM')
my_ctl_mech = pnl.ControlMechanism(control_signals=[{pnl.NAME: 'MY DDM DRIFT RATE AND THREHOLD CONTROL SIGNAL',
pnl.PROJECTIONS: [my_mech.parameter_states[pnl.DRIFT_RATE],
my_mech.parameter_states[pnl.THRESHOLD]]}])
# Print ControlSignals and their ControlProjections
for control_signal in my_ctl_mech.control_signals:
print(control_signal.name)
for control_projection in control_signal.efferents:
> MY DDM DRIFT RATE AND THREHOLD CONTROL SIGNAL
>     MY DDM: (ParameterState drift_rate)
>     MY DDM: (ParameterState threshold)


Note that a ControlMechanism uses a control_signals argument in place of an output_states argument (since it uses ControlSignal for its OutputStates. In the example above, both ControlProjections are assigned to a single ControlSignal. However, they could each be assigned to their own by specifying them in separate itesm of the control_signals argument:

my_mech = pnl.DDM(name='MY DDM')
my_ctl_mech = pnl.ControlMechanism(control_signals=[{pnl.NAME: 'DRIFT RATE CONTROL SIGNAL',
pnl.PROJECTIONS: [my_mech.parameter_states[pnl.DRIFT_RATE]]},
{pnl.NAME: 'THRESHOLD RATE CONTROL SIGNAL',
pnl.PROJECTIONS: [my_mech.parameter_states[pnl.THRESHOLD]]}])
# Print ControlSignals and their ControlProjections...
> DRIFT RATE CONTROL SIGNAL
>     MY DDM: (ParameterState drift_rate)
> THRESHOLD RATE CONTROL SIGNAL
>     MY DDM: (ParameterState threshold)


Specifying Projections in a State specification dictionary affords flexibility – for example, naming the State and/or specifying other attributes. However, if this is not necessary, the Projections can be used to specify States directly. For example, the following, which is much simpler, produces the same result as the previous example (sans the custom name; though as the printout below shows, the default names are usually pretty clear):

my_ctl_mech = pnl.ControlMechanism(control_signals=[my_mech.parameter_states[pnl.DRIFT_RATE],
my_mech.parameter_states[pnl.THRESHOLD]])
# Print ControlSignals and their ControlProjections...
> MY DDM drift_rate ControlSignal
>    MY DDM: (ParameterState drift_rate)
> MY DDM threshold ControlSignal
>    MY DDM: (ParameterState threshold)


Convenience formats

There are two convenience formats for specifying States and their Projections in a State specification dictionary. The first is to use the name of the State as the key for its entry, and then a list of , as in the following example:

source_mech_1 = pnl.TransferMechanism()
source_mech_2 = pnl.TransferMechanism()
destination_mech = pnl.TransferMechanism()
my_mech_C = pnl.TransferMechanism(input_states=[{'MY INPUT':[source_mech_1, source_mech_2]}],
output_states=[{'RESULT':[destination_mech]}])


This produces the same result as the first example under State specification dictionary above, but it is simpler and easier to read.

The second convenience format is used to specify one or more Projections to/from the States of a single Mechanism by their name. It uses the keyword MECHANISM to specify the Mechanism, coupled with a State-specific entry to specify Projections to its States. This can be useful when a Mechanism must send Projections to several States of another Mechanism, such as a ControlMechanism that sends ControlProjections to several parameters of a given Mechanism, as in the following example:

my_mech = pnl.DDM(name='MY DDM')
my_ctl_mech = pnl.ControlMechanism(control_signals=[{pnl.MECHANISM: my_mech,
pnl.PARAMETER_STATES: [pnl.DRIFT_RATE, pnl.THRESHOLD]}])


This produces the same result as the earlier example of ControlProjections, once again in a simpler and easier to read form. However, it be used only to specify Projections for a State to or from the States of a single Mechanism; Projections involving other Mechanisms must be assigned to other States.

Create and then assign a state

Finally, a State can be created directly using its constructor, and then assigned to a Mechanism. The following creates an InputState my_input_state with a MappingProjection to it from the primary OutputState of mech_A and assigns it to mech_B:

mech_A = pnl.TransferMechanism()
my_input_state = pnl.InputState(name='MY INPUT STATE',
projections=[mech_A])
mech_B = pnl.TransferMechanism(input_states=[my_input_state])
print(mech_B.input_states)
> [(InputState MY INPUT STATE)]


The InputState my_input_state could also have been assigned to mech_B in one of two other ways: by explicity adding it using mech_B’s add_states method:

mech_A = pnl.TransferMechanism()
my_input_state = pnl.InputState(name='MY INPUT STATE',
projections=[mech_A])
mech_B = pnl.TransferMechanism()


or by constructing it after mech_B and assigning mech_B as its owner:

mech_A = pnl.TransferMechanism()
mech_B = pnl.TransferMechanism()
my_input_state = pnl.InputState(name='MY INPUT STATE',
owner=mech_B,
projections=[mech_A])


Note that, in both cases, adding the InputState to mech_B does not replace its the default InputState generated when it was created, as shown by printing the input_states for mech_B:

print(mech_B.input_states)
> [(InputState InputState-0), (InputState MY INPUT STATE)]
> [(InputState InputState-0), (InputState MY INPUT STATE)]


As a consequence, my_input_state is not the primary InputState for mech_B (i.e., input_states[0]), but rather its second InputState (input_states[1]). This is differs from specifying the InputState as part of the constructor for the Mechanism, which suppresses generation of the default InputState, as in the first example above (see note).

## Class Reference¶

class psyneulink.components.states.state.State_Base(owner, variable=None, size=None, projections=None, params=None, name=None, prefs=None)

Base class for State.

Note

State is an abstract class and should NEVER be instantiated by a call to its constructor. It should be instantiated using the constructor for a subclass.

owner

Mechanism or Projection – object to which the State belongs (see Owner for additional details).

base_value

number, list or np.ndarray – value with which the State was initialized.

all_afferents

Optional[List[Projection]] – list of all Projections received by the State (i.e., for which it is a receiver.

path_afferents

Optional[List[Projection]] – list all PathwayProjections received by the State; note: only InputStates have path_afferents; the list is empty for other types of States.

mod_afferents

Optional[List[GatingProjection]] – list of all ModulatoryProjections received by the State.

projections

List[Projection] – list of all of the Projections sent or received by the State.

efferents

Optional[List[Projection]] – list of outgoing Projections from the State (i.e., for which is a sender; note: only OutputStates, and members of its ModulatoryProjection subclass (LearningProjection, ControlProjection and GatingProjection) have efferents; the list is empty for InputStates and ParameterStates.

function

TransferFunction : default determined by type – used to determine the State’s own value from the value of the Projection(s) it receives; the parameters that the TransferFunction identifies as ADDITIVE and MULTIPLICATIVE are subject to modulation by a ModulatoryProjection.

value

number, list or np.ndarray – current value of the State (updated by update method).

name

str – the name of the State. If the State’s initialization has been deferred, it is assigned a temporary name (indicating its deferred initialization status) until initialization is completed, at which time it is assigned its designated name. If that is the name of an existing State, it is appended with an indexed suffix, incremented for each State with the same base name (see Naming). If the name is not specified in the name argument of its constructor, a default name is assigned by the subclass (see subclass for details).

Note

Unlike other PsyNeuLink Components, States 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 State; 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).