Condition

Overview

Conditions are used to specify when Components are allowed to execute. Conditions can be used to specify a variety of required conditions for execution, including the state of the Component itself (e.g., how many times it has already executed, or the value of one of its attributes), the state of the Composition (e.g., how many TIME_STEP s have occurred in the current TRIAL), or the state of other Components in a Composition (e.g., whether or how many times they have executed). PsyNeuLink provides a number of pre-specified Conditions that can be parametrized (e.g., how many times a Component should be executed). Custom conditions can also be created, by assigning a function to a Condition that can reference any Component or its attributes in PsyNeuLink, thus providing considerable flexibility for scheduling.

Note

Any Component that is part of a collection specified to a Scheduler for execution can be associated with a Condition. Most commonly, these are Mechanisms. However, in some circumstances Projections can be included in the specification to a Scheduler (e.g., for learning) in which case these can also be assigned Conditions.

Creating Conditions

Pre-specified Conditions

Pre-specified Conditions can be instantiated and added to a Scheduler at any time, and take effect immediately for the execution of that Scheduler. Most pre-specified Conditions have one or more arguments that must be specified to achieve the desired behavior. Many Conditions are also associated with an owner attribute (a Components to which the Condition belongs). Schedulers maintain the data used to test for satisfaction of Condition, independent in different execution_id contexts. The Scheduler is generally responsible for ensuring that Conditions have access to the necessary data. When pre-specified Conditions are instantiated within a call to the add method of a Scheduler or ConditionSet, the Condition’s owner is determined through context and assigned automatically, as in the following example:

my_scheduler.add_condition(A, EveryNPasses(1))
my_scheduler.add_condition(B, EveryNCalls(A, 2))
my_scheduler.add_condition(C, EveryNCalls(B, 2))

Here, EveryNCalls(A, 2) for example, is assigned the owner B.

Custom Conditions

Custom Conditions can be created by calling the constructor for the base class (Condition()) or one of the generic classes, and assigning a function to the func argument and any arguments it requires to the args and/or kwargs arguments (for formal or keyword arguments, respectively). The function is called with args and kwargs by the Scheduler on each PASS through its consideration_queue, and the result is used to determine whether the associated Component is allowed to execute on that PASS. Custom Conditions allow arbitrary schedules to be created, in which the execution of each Component can depend on one or more attributes of any other Components in the Composition.

For example, the following script fragment creates a custom Condition in which mech_A is scheduled to wait to execute until a RecurrentTransferMechanism mech_B has “converged” (that is, settled to the point that none of its elements has changed in value more than a specified amount since the previous TIME_STEP):

def converge(mech, thresh):
    for val in mech.delta:
        if abs(val) >= thresh:
            return False
    return True
epsilon = 0.01
my_scheduler.add_condition(mech_A, NWhen(Condition(converge, mech_B, epsilon), 1))

In the example, a function converge is defined that references the delta attribute of a TransferMechanism (which reports the change in its value). The function is assigned to the standard Condition() with mech_A and epsilon as its arguments, and composite Condition NWhen (which is satisfied the first N times after its condition becomes true), The Condition is assigned to mech_B, thus scheduling it to execute one time when all of the elements of mech_A have changed by less than epsilon.

Structure

The Scheduler associates every Component with a Condition. If a Component has not been explicitly assigned a Condition, it is assigned the Condition Always that causes it to be executed whenever it is under consideration. Condition subclasses (listed below) provide a standard set of Conditions that can be implemented simply by specifying their parameter(s). There are five types:

List of Pre-specified Conditions

Note

The optional TimeScale argument in many Conditions specifies the unit of time over which the Condition operates; the default value is TRIAL for all Conditions except those with “Trial” in their name, for which it is RUN.

Generic Conditions (used to construct custom Conditions):

  • While (func, *args, **kwargs) satisfied whenever the specified function (or callable) called with args and/or kwargs evaluates to True. Equivalent to Condition(func, *args, **kwargs)
  • WhileNot (func, *args, **kwargs) satisfied whenever the specified function (or callable) called with args and/or kwargs evaluates to False. Equivalent to Not(Condition(func, *args, **kwargs))

Static Conditions (independent of other Conditions, Components or time):

Composite Conditions (based on one or more other Conditions):

  • All (*Conditions) satisfied whenever all of the specified Conditions are satisfied.
  • Any (*Conditions) satisfied whenever any of the specified Conditions are satisfied.
  • Not (Condition) satisfied whenever the specified Condition is not satisfied.
  • NWhen (Condition, int) satisfied the first specified number of times the specified Condition is satisfied.

Time-Based Conditions (based on the count of units of time at a specified TimeScale):

  • BeforeTimeStep (int[, TimeScale]) satisfied any time before the specified TIME_STEP occurs.
  • AtTimeStep (int[, TimeScale]) satisfied only during the specified TIME_STEP.
  • AfterTimeStep (int[, TimeScale]) satisfied any time after the specified TIME_STEP has occurred.
  • AfterNTimeSteps (int[, TimeScale]) satisfied when or any time after the specified number of TIME_STEPs has occurred.
  • BeforePass (int[, TimeScale]) satisfied any time before the specified PASS occurs.
  • AtPass (int[, TimeScale]) satisfied only during the specified PASS.
  • AfterPass (int[, TimeScale]) satisfied any time after the specified PASS has occurred.
  • AfterNPasses (int[, TimeScale]) satisfied when or any time after the specified number of PASSes has occurred.
  • EveryNPasses (int[, TimeScale]) satisfied every time the specified number of PASSes occurs.
  • BeforeTrial (int[, TimeScale]) satisfied any time before the specified TRIAL occurs.
  • AtTrial (int[, TimeScale]) satisfied any time during the specified TRIAL.
  • AfterTrial (int[, TimeScale]) satisfied any time after the specified TRIAL occurs.
  • AfterNTrials (int[, TimeScale]) satisfied any time after the specified number of TRIALs has occurred.

Component-Based Conditions (based on the execution or state of other Components):

  • BeforeNCalls (Component, int[, TimeScale]) satisfied any time before the specified Component has executed the specified number of times.
  • AtNCalls (Component, int[, TimeScale]) satisfied when the specified Component has executed the specified number of times.
  • AfterCall (Component, int[, TimeScale]) satisfied any time after the Component has executed the specified number of times.
  • AfterNCalls (Component, int[, TimeScale]) satisfied when or any time after the Component has executed the specified number of times.
  • AfterNCallsCombined (*Components, int[, TimeScale]) satisfied when or any time after the specified Components have executed the specified number of times among themselves, in total.
  • EveryNCalls (Component, int[, TimeScale]) satisfied when the specified Component has executed the specified number of times since the last time owner has run.
  • JustRan (Component) satisfied if the specified Component was assigned to run in the previous TIME_STEP.
  • AllHaveRun (*Components) satisfied when all of the specified Components have executed at least once.
  • WhenFinished (Component) satisfied when the specified Component has set its is_finished attribute to True.
  • WhenFinishedAny (*Components) satisfied when any of the specified Components has set their is_finished attribute to True.
  • WhenFinishedAll (*Components) satisfied when all of the specified Components have set their is_finished attributes to True.

Execution

When the Scheduler runs, it makes a sequential PASS through its consideration_queue, evaluating each consideration_set in the queue to determine which Components should be assigned to execute. It evaluates the Components in each set by calling the is_satisfied method of the Condition associated with each of those Components. If it returns True, then the Component is assigned to the execution set for the TIME_STEP of execution generated by that PASS. Otherwise, the Component is not executed.

Class Reference

class psyneulink.scheduling.condition.ConditionSet(conditions=None)

Used in conjunction with a Scheduler to store the Conditions associated with a Components.

Parameters:conditions (Dict[Component: Condition]) – specifies an iterable collection of Components and the Conditions associated with each.
conditions

Dict[Component: Condition] – the key of each entry is a Component, and its value is the Condition associated with that Component. Conditions can be added to the ConditionSet using the ConditionSet’s add_condition method.

add_condition(owner, condition)

Adds a Condition to the ConditionSet. If owner already has a Condition, it is overwritten with the new one. If you want to add multiple conditions to a single owner, use the composite Conditions to accurately specify the desired behavior.

Parameters:
  • owner (Component) – specifies the Component with which the condition should be associated. condition will govern the execution behavior of owner
  • condition (Condition) – specifies the Condition, associated with the owner to be added to the ConditionSet.
add_condition_set(conditions)

Adds a set of Conditions (in the form of a dict or another ConditionSet) to the ConditionSet. Any Condition added here will overwrite an existing Condition for a given owner. If you want to add multiple conditions to a single owner, add a single Composite Condition to accurately specify the desired behavior.

Parameters:conditions (dict[Component: Condition], ConditionSet) –

specifies collection of Conditions to be added to this ConditionSet,

if a dict is provided:
each entry should map an owner Components (the Components whose execution behavior will be governed) to a Condition
class psyneulink.scheduling.condition.Condition(func, *args, **kwargs)

Used in conjunction with a Scheduler to specify the condition under which a Components should be allowed to execute.

Parameters:
  • func (callable) – specifies function to be called when the Condition is evaluated, to determine whether it is currently satisfied.
  • args (*args) – specifies formal arguments to pass to func when the Condition is evaluated.
  • kwargs (**kwargs) – specifies keyword arguments to pass to func when the Condition is evaluated.
owner(Component)

the Components with which the Condition is associated, and the execution of which it determines.

is_satisfied(*args, **kwargs)

the function called to determine satisfaction of this Condition.

Parameters:
  • args (*args) – specifies additional formal arguments to pass to func when the Condition is evaluated. these are appended to the args specified at instantiation of this Condition
  • kwargs (**kwargs) – specifies additional keyword arguments to pass to func when the Condition is evaluated. these are added to the kwargs specified at instantiation of this Condition
Returns:

  • True - if the Condition is satisfied
  • False - if the Condition is not satisfied

psyneulink.scheduling.condition.While

alias of Condition

class psyneulink.scheduling.condition.WhileNot(func, *args, **kwargs)
Parameters:
  • func – callable specifies function to be called when the Condition is evaluated, to determine whether it is currently satisfied.
  • args*args specifies formal arguments to pass to func when the Condition is evaluated.
  • kwargs**kwargs specifies keyword arguments to pass to func when the Condition is evaluated.

Satisfied when:

  • func is False
class psyneulink.scheduling.condition.Always
Parameters:none

Satisfied when:

  • always satisfied.
class psyneulink.scheduling.condition.Never
Parameters:none

Satisfied when:

  • never satisfied.
class psyneulink.scheduling.condition.All(*args)
Parameters:args – one or more Conditions

Satisfied when:

  • all of the Conditions in args are satisfied.

Notes

  • To initialize with a list (for example):

    conditions = [AfterNCalls(mechanism, 5) for mechanism in mechanism_list]
    

    unpack the list to supply its members as args:

    composite_condition = All(*conditions)
    
class psyneulink.scheduling.condition.Any(*args)
Parameters:args – one or more Conditions

Satisfied when:

  • one or more of the Conditions in args is satisfied.

Notes

  • To initialize with a list (for example):

    conditions = [AfterNCalls(mechanism, 5) for mechanism in mechanism_list]
    

    unpack the list to supply its members as args:

    composite_condition = All(*conditions)
    
class psyneulink.scheduling.condition.Not(condition)
Parameters:condition (Condition) – a Condition

Satisfied when:

  • condition is not satisfied.
class psyneulink.scheduling.condition.NWhen(condition, n=1)
Parameters:
  • condition (Condition) – a Condition
  • n (int) – the maximum number of times this condition will be satisfied

Satisfied when:

  • the first n times condition is satisfied upon evaluation
class psyneulink.scheduling.condition.BeforeTimeStep(n, time_scale=<TimeScale.TRIAL: 2>)
Parameters:
  • n (int) – the ‘TIME_STEP’ before which the Condition is satisfied
  • time_scale (TimeScale) – the TimeScale used as basis for counting TIME_STEPs (default: TimeScale.TRIAL)

Satisfied when:

  • at most n-1 TIME_STEPs have occurred within one unit of time at the TimeScale specified by time_scale.

Notes

class psyneulink.scheduling.condition.AtTimeStep(n, time_scale=<TimeScale.TRIAL: 2>)
Parameters:
  • n (int) – the TIME_STEP at which the Condition is satisfied
  • time_scale (TimeScale) – the TimeScale used as basis for counting TIME_STEPs (default: TimeScale.TRIAL)

Satisfied when:

  • exactly n TIME_STEPs have occurred within one unit of time at the TimeScale specified by time_scale.

Notes

  • Counts of TimeScales are zero-indexed (that is, the first ‘TIME_STEP’ is pass 0, the second ‘TIME_STEP’ is 1, etc.); so, AtTimeStep(1) is satisfied when a single TIME_STEP (TIME_STEP 0) has occurred, and AtTimeStep(2) is satisfied when two TIME_STEPs have occurred (TIME_STEP 0 and TIME_STEP 1), etc..
class psyneulink.scheduling.condition.AfterTimeStep(n, time_scale=<TimeScale.TRIAL: 2>)
Parameters:
  • n (int) – the TIME_STEP after which the Condition is satisfied
  • time_scale (TimeScale) – the TimeScale used as basis for counting TIME_STEPs (default: TimeScale.TRIAL)

Satisfied when:

  • at least n+1 TIME_STEPs have occurred within one unit of time at the TimeScale specified by time_scale.

Notes

  • Counts of TimeScals are zero-indexed (that is, the first TIME_STEP is 0, the second TIME_STEP is 1, etc.); so, AfterTimeStep(1) is satisfied after TIME_STEP 1 has occurred and thereafter (i.e., in TIME_STEPs 2, 3, 4, etc.).
class psyneulink.scheduling.condition.AfterNTimeSteps(n, time_scale=<TimeScale.TRIAL: 2>)
Parameters:
  • n (int) – the number of TIME_STEPs after which the Condition is satisfied
  • time_scale (TimeScale) – the TimeScale used as basis for counting TIME_STEPs (default: TimeScale.TRIAL)

Satisfied when:

  • at least n TIME_STEPs have occurred within one unit of time at the TimeScale specified by time_scale.
class psyneulink.scheduling.condition.BeforePass(n, time_scale=<TimeScale.TRIAL: 2>)
Parameters:
  • n (int) – the ‘PASS’ before which the Condition is satisfied
  • time_scale (TimeScale) – the TimeScale used as basis for counting PASSes (default: TimeScale.TRIAL)

Satisfied when:

  • at most n-1 PASSes have occurred within one unit of time at the TimeScale specified by time_scale.

Notes

  • Counts of TimeScales are zero-indexed (that is, the first PASS is 0, the second PASS is 1, etc.); so, BeforePass(2) is satisfied at PASS 0 and PASS 1.
class psyneulink.scheduling.condition.AtPass(n, time_scale=<TimeScale.TRIAL: 2>)
Parameters:
  • n (int) – the PASS at which the Condition is satisfied
  • time_scale (TimeScale) – the TimeScale used as basis for counting PASSes (default: TimeScale.TRIAL)

Satisfied when:

  • exactly n PASSes have occurred within one unit of time at the TimeScale specified by time_scale.

Notes

  • Counts of TimeScales are zero-indexed (that is, the first ‘PASS’ is pass 0, the second ‘PASS’ is 1, etc.); so, AtPass(1) is satisfied when a single PASS (PASS 0) has occurred, and AtPass(2) is satisfied when two PASSes have occurred (PASS 0 and PASS 1), etc..
class psyneulink.scheduling.condition.AfterPass(n, time_scale=<TimeScale.TRIAL: 2>)
Parameters:
  • n (int) – the PASS after which the Condition is satisfied
  • time_scale (TimeScale) – the TimeScale used as basis for counting PASSes (default: TimeScale.TRIAL)

Satisfied when:

  • at least n+1 PASSes have occurred within one unit of time at the TimeScale specified by time_scale.

Notes

  • Counts of TimeScales are zero-indexed (that is, the first PASS is 0, the second PASS is 1, etc.); so, AfterPass(1) is satisfied after PASS 1 has occurred and thereafter (i.e., in PASSes 2, 3, 4, etc.).
class psyneulink.scheduling.condition.AfterNPasses(n, time_scale=<TimeScale.TRIAL: 2>)
Parameters:
  • n (int) – the number of PASSes after which the Condition is satisfied
  • time_scale (TimeScale) – the TimeScale used as basis for counting PASSes (default: TimeScale.TRIAL)

Satisfied when:

  • at least n PASSes have occurred within one unit of time at the TimeScale specified by time_scale.
class psyneulink.scheduling.condition.EveryNPasses(n, time_scale=<TimeScale.TRIAL: 2>)
Parameters:
  • n (int) – the frequency of passes with which this condition is satisfied
  • time_scale (TimeScale) – the TimeScale used as basis for counting PASSes (default: TimeScale.TRIAL)

Satisfied when:

  • PASS 0
  • the specified number of PASSes that has occurred within a unit of time (at the TimeScale specified by time_scale) is evenly divisible by n.
class psyneulink.scheduling.condition.BeforeTrial(n, time_scale=<TimeScale.RUN: 3>)
Parameters:
  • n (int) – the TRIAL before which the Condition is satisfied
  • time_scale (TimeScale) – the TimeScale used as basis for counting TRIALs (default: TimeScale.RUN)

Satisfied when:

  • at most n-1 TRIALs have occurred within one unit of time at the TimeScale specified by time_scale.

Notes

  • Counts of TimeScales are zero-indexed (that is, the first TRIAL is 0, the second TRIAL is 1, etc.); so, BeforeTrial(2) is satisfied at TRIAL 0 and TRIAL 1.
class psyneulink.scheduling.condition.AtTrial(n, time_scale=<TimeScale.RUN: 3>)
Parameters:
  • n (int) – the TRIAL at which the Condition is satisfied
  • time_scale (TimeScale) – the TimeScale used as basis for counting TRIALs (default: TimeScale.RUN)

Satisfied when:

  • exactly n TRIALs have occurred within one unit of time at the TimeScale specified by time_scale.

Notes

  • Counts of TimeScales are zero-indexed (that is, the first TRIAL is 0, the second TRIAL is 1, etc.); so, AtTrial(1) is satisfied when one TRIAL (TRIAL 0) has already occurred.
class psyneulink.scheduling.condition.AfterTrial(n, time_scale=<TimeScale.RUN: 3>)
Parameters:
  • n (int) – the TRIAL after which the Condition is satisfied
  • time_scale (TimeScale) – the TimeScale used as basis for counting TRIALs. (default: TimeScale.RUN)

Satisfied when:

  • at least n+1 TRIALs have occurred within one unit of time at the TimeScale specified by time_scale.

Notes

  • Counts of TimeScales are zero-indexed (that is, the first TRIAL is 0, the second TRIAL is 1, etc.); so, AfterPass(1) is satisfied after TRIAL 1 has occurred and thereafter (i.e., in TRIALs 2, 3, 4, etc.).
class psyneulink.scheduling.condition.AfterNTrials(n, time_scale=<TimeScale.RUN: 3>)
Parameters:
  • n (int) – the number of TRIALs after which the Condition is satisfied
  • time_scale (TimeScale) – the TimeScale used as basis for counting TRIALs (default: TimeScale.RUN)

Satisfied when:

  • at least n TRIALs have occured within one unit of time at the TimeScale specified by time_scale.
class psyneulink.scheduling.condition.BeforeNCalls(dependency, n, time_scale=<TimeScale.TRIAL: 2>)
Parameters:
  • component (Component) – the Component on which the Condition depends
  • n (int) – the number of executions of component before which the Condition is satisfied
  • time_scale (TimeScale) – the TimeScale used as basis for counting executions of component
  • (default – TimeScale.TRIAL)

Satisfied when:

  • the Component specified in component has executed at most n-1 times within one unit of time at the TimeScale specified by time_scale.
class psyneulink.scheduling.condition.AtNCalls(dependency, n, time_scale=<TimeScale.TRIAL: 2>)
Parameters:
  • component (Component) – the Component on which the Condition depends
  • n (int) – the number of executions of component at which the Condition is satisfied
  • time_scale (TimeScale) – the TimeScale used as basis for counting executions of component
  • (default – TimeScale.TRIAL)

Satisfied when:

  • the Component specified in component has executed exactly n times within one unit of time at the TimeScale specified by time_scale.
class psyneulink.scheduling.condition.AfterCall(dependency, n, time_scale=<TimeScale.TRIAL: 2>)
Parameters:
  • component (Component) – the Component on which the Condition depends
  • n (int) – the number of executions of component after which the Condition is satisfied
  • time_scale (TimeScale) – the TimeScale used as basis for counting executions of component
  • (default – TimeScale.TRIAL)

Satisfied when:

  • the Component specified in component has executed at least n+1 times within one unit of time at the TimeScale specified by time_scale.
class psyneulink.scheduling.condition.AfterNCalls(dependency, n, time_scale=<TimeScale.TRIAL: 2>)
Parameters:
  • component (Component) – the Component on which the Condition depends
  • n (int) – the number of executions of component after which the Condition is satisfied
  • time_scale (TimeScale) – the TimeScale used as basis for counting executions of component
  • (default – TimeScale.TRIAL)

Satisfied when:

  • the Component specified in component has executed at least n times within one unit of time at the TimeScale specified by time_scale.
class psyneulink.scheduling.condition.AfterNCallsCombined(*dependencies, n=None, time_scale=<TimeScale.TRIAL: 2>)
Parameters:
  • *components (Components) – one or more Components on which the Condition depends
  • n (int) – the number of combined executions of all Components specified in components after which the
  • is satisfied (default (Condition) – None)
  • time_scale (TimeScale) – the TimeScale used as basis for counting executions of component
  • (default – TimeScale.TRIAL)

Satisfied when:

  • there have been at least n+1 executions among all of the Components specified in components within one unit of time at the TimeScale specified by time_scale.
class psyneulink.scheduling.condition.EveryNCalls(dependency, n)
Parameters:
  • component (Component) – the Component on which the Condition depends
  • n (int) – the frequency of executions of component at which the Condition is satisfied

Satisfied when:

  • the Component specified in component has executed at least n times since the last time the Condition’s owner executed.

Notes

  • scheduler’s count of each other Component that is “useable” by the Component is reset to 0 when the Component runs
class psyneulink.scheduling.condition.JustRan(dependency)
Parameters:component (Component) – the Component on which the Condition depends

Satisfied when:

  • the Component specified in component executed in the previous TIME_STEP.

Notes

  • This Condition can transcend divisions between TimeScales. For example, if A runs in the final TIME_STEP of a TRIAL, JustRan(A) is satisfied at the beginning of the next TRIAL.
class psyneulink.scheduling.condition.AllHaveRun(*dependencies, time_scale=<TimeScale.TRIAL: 2>)
Parameters:
  • *components (Components) – an iterable of Components on which the Condition depends
  • time_scale (TimeScale) – the TimeScale used as basis for counting executions of component
  • (default – TimeScale.TRIAL)

Satisfied when:

  • all of the Components specified in components have executed at least once within one unit of time at the TimeScale specified by time_scale.
class psyneulink.scheduling.condition.WhenFinished(dependency)
Parameters:component (Component) – the Component on which the Condition depends

Satisfied when:

  • the Component specified in component has set its is_finished attribute to True.

Notes

  • This is a dynamic Condition: Each Component is responsible for assigning its is_finished attribute on it own, which can occur independently of the execution of other Components. Therefore the satisfaction of this Condition) can vary arbitrarily in time.
class psyneulink.scheduling.condition.WhenFinishedAny(*dependencies)
Parameters:*components (Components) – zero or more Components on which the Condition depends

Satisfied when:

  • any of the Components specified in components have set their is_finished attribute to True.

Notes

  • This is a convenience class; WhenFinishedAny(A, B, C) is equivalent to Any(WhenFinished(A), WhenFinished(B), WhenFinished(C)). If no components are specified, the condition will default to checking all of scheduler’s Components.
  • This is a dynamic Condition: Each Component is responsible for assigning its is_finished attribute on it own, which can occur independently of the execution of other Components. Therefore the satisfaction of this Condition) can vary arbitrarily in time.
class psyneulink.scheduling.condition.WhenFinishedAll(*dependencies)
Parameters:*components (Components) – zero or more Components on which the Condition depends

Satisfied when:

  • all of the Components specified in components have set their is_finished attributes to True.

Notes

  • This is a convenience class; WhenFinishedAny(A, B, C) is equivalent to All(WhenFinished(A), WhenFinished(B), WhenFinished(C)). If no components are specified, the condition will default to checking all of scheduler’s Components.
  • This is a dynamic Condition: Each Component is responsible for assigning its is_finished attribute on it own, which can occur independently of the execution of other Components. Therefore the satisfaction of this Condition) can vary arbitrarily in time.