Skip to content

Commit

Permalink
Feat/inputstate/combine (#766)
Browse files Browse the repository at this point in the history
* • Project
  ADD_STATES removed

* • InputState
  __init__: added combine arg that allows operation argument of
            LinearCombination (the default functon) to be specified

* • InputState
  __init__: added combine arg that allows operation argument of
            LinearCombination (the default functon) to be specified

* -
  • Loading branch information
jdcpni authored Apr 30, 2018
1 parent bd9917b commit 4f2ce2f
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ def _instantiate_attributes_after_function(self, context=None):
if GATING_PROJECTIONS in self.paramsCurrent:
if self.paramsCurrent[GATING_PROJECTIONS]:
for key, projection in self.paramsCurrent[GATING_PROJECTIONS].items():
self._instantiate_gating_projection(projection, context=self.name)
self._instantiate_gating_projection(projection, context=ContextFlags.METHOD)

def _assign_as_gating_mechanism(self, context=None):

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,6 @@
from psyneulink.components.states.inputstate import InputState
from psyneulink.components.states.modulatorysignals.learningsignal import LearningSignal
from psyneulink.components.states.parameterstate import ParameterState
from psyneulink.components.states.state import ADD_STATES
from psyneulink.globals.context import ContextFlags
from psyneulink.globals.keywords import ASSERT, CONTROL_PROJECTIONS, ENABLED, INPUT_STATES, \
LEARNED_PARAM, LEARNING, LEARNING_MECHANISM, LEARNING_PROJECTION, LEARNING_SIGNAL, LEARNING_SIGNALS, \
Expand Down Expand Up @@ -1143,8 +1142,6 @@ def add_states(self, states, context=None):
"""Add error_source and error_matrix for each InputState added"""

if context is None:
# context.source = ContextFlags.METHOD
# context.string = ADD_STATES
context = ContextFlags.COMMAND_LINE

states = super().add_states(states=states, context=context)
Expand Down
2 changes: 1 addition & 1 deletion psyneulink/components/mechanisms/mechanism.py
Original file line number Diff line number Diff line change
Expand Up @@ -867,7 +867,7 @@ class `UserList <https://docs.python.org/3.6/library/collections.html?highlight=
from psyneulink.components.states.modulatorysignals.modulatorysignal import _is_modulatory_spec
from psyneulink.components.states.outputstate import OutputState
from psyneulink.components.states.parameterstate import ParameterState
from psyneulink.components.states.state import ADD_STATES, REMOVE_STATES, _parse_state_spec
from psyneulink.components.states.state import REMOVE_STATES, _parse_state_spec
from psyneulink.globals.context import ContextFlags
from psyneulink.globals.keywords import \
CHANGED, COMMAND_LINE, EVC_SIMULATION, EXECUTING, EXECUTION_PHASE, FUNCTION, FUNCTION_PARAMS, \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,6 @@ def add_monitored_output_states(self, monitored_output_states_specs, context=Non

input_states = self._instantiate_input_states(monitored_output_states_specs=monitored_output_states_specs,
reference_value=reference_value,
# context='ADD_STATES')
context = ContextFlags.METHOD)

output_states = [[projection.sender for projection in state.path_afferents] for state in input_states]
Expand Down
58 changes: 55 additions & 3 deletions psyneulink/components/states/inputstate.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
<Process.pathway>`. InputStates can also be specified in the **input_states** argument of a Mechanism's
constructor (see `below <InputState_Specification>`).
The `variable <variable.InputState>` of an InputState can be specified using the **variable** or **size** arguments of
The `variable <InputState.variable>` of an InputState can be specified using the **variable** or **size** arguments of
its constructor. It can also be specified using the **projections** argument, if neither **variable** nor **size** is
specified. The **projections** argument is used to `specify Projections <State_Projections>` to the InputState. If
neither the **variable** nor **size** arguments is specified, then the value of the `Projections(s) <Projection>` or
Expand Down Expand Up @@ -460,11 +460,15 @@
import numpy as np
import typecheck as tc

from psyneulink.components.functions.function import Linear, LinearCombination, Reduce
from psyneulink.components.functions.function import Function, Linear, LinearCombination, Reduce
from psyneulink.components.states.outputstate import OutputState
from psyneulink.components.states.state import StateError, State_Base, _instantiate_state_list, state_type_keywords
from psyneulink.globals.context import ContextFlags
from psyneulink.globals.keywords import CLASS_DEFAULTS, COMMAND_LINE, EXPONENT, FUNCTION, GATING_SIGNAL, INPUT_STATE, INPUT_STATE_PARAMS, LEARNING_SIGNAL, MAPPING_PROJECTION, MATRIX, MECHANISM, OUTPUT_STATE, OUTPUT_STATES, PROCESS_INPUT_STATE, PROJECTIONS, PROJECTION_TYPE, REFERENCE_VALUE, SENDER, SUM, SYSTEM_INPUT_STATE, VARIABLE, WEIGHT
from psyneulink.globals.keywords import \
CLASS_DEFAULTS, COMBINE, COMMAND_LINE, EXPONENT, FUNCTION, GATING_SIGNAL, \
INPUT_STATE, INPUT_STATE_PARAMS, LEARNING_SIGNAL, MAPPING_PROJECTION, MATRIX, MECHANISM, OPERATION, \
OUTPUT_STATE, OUTPUT_STATES, PROCESS_INPUT_STATE, PRODUCT, PROJECTIONS, PROJECTION_TYPE, REFERENCE_VALUE, \
SENDER, SUM, SYSTEM_INPUT_STATE, VARIABLE, WEIGHT
from psyneulink.globals.preferences.componentpreferenceset import is_pref_set
from psyneulink.globals.preferences.preferenceset import PreferenceLevel
from psyneulink.globals.utilities import append_type_to_name, is_instance_or_subclass, is_numeric, iscompatible
Expand Down Expand Up @@ -507,6 +511,7 @@ class InputState(State_Base):
variable=None, \
size=None, \
function=LinearCombination(operation=SUM), \
combine=None, \
projections=None, \
weight=None, \
exponent=None, \
Expand Down Expand Up @@ -570,6 +575,13 @@ class InputState(State_Base):
by the InputState. It must produce a result that has the same format (number and type of elements) as the
item of its owner Mechanism's `variable <Mechanism_Base.variable>` to which the InputState has been assigned.
combine : SUM or PRODUCT : default None
specifies the **operation** argument used by the default `LinearCombination` function, wnich determines how the
`value <Projection.value>` of the InputState's `projections <InputState.projections>` are combined. This is a
convenience argument, that **operation** to be specified without having to specify the function's constructor;
accordingly, it assumes that LinearCombination (the default) is used as the InputState's function -- if it
conflicts with a specification of **function** an error is generated.
projections : list of Projection specifications
specifies the `MappingProjection(s) <MappingProjection>` and/or `GatingProjection(s) <GatingProjection>` to be
received by the InputState, and that are listed in its `path_afferents <InputState.path_afferents>` and
Expand Down Expand Up @@ -706,6 +718,7 @@ def __init__(self,
size=None,
function=None,
projections=None,
combine:tc.optional(tc.enum(SUM,PRODUCT))=None,
weight=None,
exponent=None,
params=None,
Expand All @@ -724,6 +737,45 @@ def __init__(self,
if variable is None and size is None and projections is not None:
variable = self._assign_variable_from_projection(variable, size, projections)

if combine:
# Make sure it doesn't conflict with any specification in **function**
# IMPLEMENTATION NOTE:
# Need to do validation & assignment here, since specification of **combine** influences value
# returned by function which is needed for validation of other attributes of InputState
if function:
owner_name = ""
if owner:
owner_name = " for InputState of {}".format(owner.name)
if isinstance(function, LinearCombination):
if function.operation != combine:
raise InputStateError("Specification of {} argument ({}) conflicts with "
"specification of {} ({}) for LinearCombination in {} "
"argument{}".
format(repr(COMBINE), combine.upper(),
repr(OPERATION),function.operation.upper(),
repr(FUNCTION), owner_name))
else:
# Leave function intact, as it may have other parameters specified by user
pass
elif isinstance(function, Function):
raise InputStateError("Specification of {} argument ({}) conflicts with "
"Function specified in {} argument ({}){}".
format(repr(COMBINE), combine.upper(),
repr(FUNCTION), function.name, owner_name))
elif isinstance(function, type):
if not issubclass(function, LinearCombination):
raise InputStateError("Specification of {} argument ({}) conflicts with "
"Function specified in {} argument ({}){}".
format(repr(COMBINE), combine.upper(),
repr(FUNCTION), function.__name__, owner_name))
else:
function = LinearCombination(operation=combine)
else:
raise InputStateError("PROGRAM ERROR: unrecognized specification for function argument ({}){} ".
format(function, owner_name))
else:
function=LinearCombination(operation=combine)

# Assign args to params and functionParams dicts (kwConstants must == arg names)
params = self._assign_args_to_param_dicts(function=function,
weight=weight,
Expand Down
2 changes: 1 addition & 1 deletion psyneulink/components/states/outputstate.py
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@
from psyneulink.components.component import Component
from psyneulink.components.functions.function import Function, OneHot, function_type, method_type
from psyneulink.components.shellclasses import Mechanism
from psyneulink.components.states.state import ADD_STATES, State_Base, _instantiate_state_list, state_type_keywords
from psyneulink.components.states.state import State_Base, _instantiate_state_list, state_type_keywords
from psyneulink.globals.context import ContextFlags
from psyneulink.globals.keywords import ALL, ASSIGN, CALCULATE, COMMAND_LINE, FUNCTION, GATING_SIGNAL, INDEX, INPUT_STATE, INPUT_STATES, MAPPING_PROJECTION, MAX_ABS_INDICATOR, MAX_ABS_VAL, MAX_INDICATOR, MAX_VAL, MEAN, MECHANISM_VALUE, MEDIAN, NAME, OUTPUT_STATE, OUTPUT_STATE_PARAMS, OWNER_VALUE, PARAMS, PARAMS_DICT, PROB, PROJECTION, PROJECTIONS, PROJECTION_TYPE, RECEIVER, REFERENCE_VALUE, RESULT, STANDARD_DEVIATION, STANDARD_OUTPUT_STATES, STATE, VALUE, VARIABLE, VARIANCE
from psyneulink.globals.preferences.componentpreferenceset import is_pref_set
Expand Down
1 change: 0 additions & 1 deletion psyneulink/components/states/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,6 @@ def test_multiple_modulatory_projections_with_mech_and_state_name_specs(self):

STANDARD_STATE_ARGS = {STATE_TYPE, OWNER, REFERENCE_VALUE, VARIABLE, NAME, PARAMS, PREFS_ARG}
STATE_SPEC = 'state_spec'
ADD_STATES = 'ADD_STATES'
REMOVE_STATES = 'REMOVE_STATES'

def _is_state_class(spec):
Expand Down
11 changes: 8 additions & 3 deletions psyneulink/globals/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,14 @@ def __init__(self, error_value):


class ContextFlags(IntEnum):
"""Used to identify the status of a `Component <Component>` when its value or one of its attributes is being
accessed. Also used to specify the context in which a value of the Component or its attribute is `logged
<Log_Conditions>`.
"""Used to identify the initialization and execution status of a `Component <Component>`.
Used when a Component's `value <Component.value>` or one of its attributes is being accessed.
Also used to specify the context in which a value of the Component or its attribute is `logged <Log_Conditions>`..
COMMENT:
Used to by **context** argument of all methods to specify type of caller.
COMMENT
"""

UNSET = 0
Expand Down
20 changes: 12 additions & 8 deletions psyneulink/globals/keywords.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,17 @@
'ADAPTIVE_MECHANISM', 'ALL', 'ALLOCATION_SAMPLES', 'ANGLE', 'ARGUMENT_THERAPY_FUNCTION', 'ASSIGN_VALUE','ASSERT',
'AUTO','AUTO_ASSIGN_MATRIX', 'AUTO_ASSOCIATIVE_PROJECTION', 'AUTO_DEPENDENT', 'AUTOASSOCIATIVE_LEARNING_MECHANISM',
'BACKPROPAGATION_FUNCTION', 'BETA', 'BIAS', 'ASSIGN', 'CHANGED', 'CLAMP_INPUT',
'COMBINATION_FUNCTION_TYPE', 'COMBINE_MEANS_FUNCTION', 'COMBINE_OUTCOME_AND_COST_FUNCTION', 'COMMAND_LINE',
'COMPARATOR_MECHANISM', 'COMPONENT_INIT', 'COMPOSITION_INTERFACE_MECHANISM', 'CONROLLER_PHASE_SPEC', 'CONSTANT',
'CONSTANT_INTEGRATOR_FUNCTION', 'CONTEXT', 'CONTROL', 'CONTROL_MECHANISM', 'CONTROL_PROJECTION',
'CONTROL_PROJECTION_PARAMS', 'CONTROL_PROJECTIONS', 'CONTROL_SIGNAL', 'CONTROL_SIGNAL_SPECS', 'CONTROL_SIGNALS',
'CONTROLLED_PARAMS', 'CONTROLLER', 'CORRELATION', 'COST_FUNCTION', 'CROSS_ENTROPY', 'CUSTOM_FUNCTION', 'CYCLE', 'DDM_MECHANISM', 'DECAY',
'DEFAULT', 'DEFAULT_CONTROL_MECHANISM', 'DEFAULT_MATRIX', 'DEFAULT_PROCESSING_MECHANISM', 'DEFAULT_SYSTEM',
'DEFERRED_ASSIGNMENT', 'DEFERRED_DEFAULT_NAME', 'DEFERRED_INITIALIZATION', 'DIFFERENCE', 'DIFFERENCE', 'DIFFUSION',
'DIST_FUNCTION_TYPE', 'DIST_MEAN', 'DIST_SHAPE', 'DISTANCE_FUNCTION', 'DISTANCE_METRICS', 'DISTRIBUTION_FUNCTION_TYPE',
'COMBINATION_FUNCTION_TYPE', 'COMBINE', 'COMBINE_MEANS_FUNCTION', 'COMBINE_OUTCOME_AND_COST_FUNCTION',
'COMMAND_LINE', 'COMPARATOR_MECHANISM', 'COMPONENT_INIT', 'COMPOSITION_INTERFACE_MECHANISM',
'CONROLLER_PHASE_SPEC', 'CONSTANT', 'CONSTANT_INTEGRATOR_FUNCTION', 'CONTEXT', 'CONTROL', 'CONTROL_MECHANISM',
'CONTROL_PROJECTION', 'CONTROL_PROJECTION_PARAMS', 'CONTROL_PROJECTIONS', 'CONTROL_SIGNAL',
'CONTROL_SIGNAL_SPECS', 'CONTROL_SIGNALS',
'CONTROLLED_PARAMS', 'CONTROLLER', 'CORRELATION', 'COST_FUNCTION', 'CROSS_ENTROPY', 'CUSTOM_FUNCTION', 'CYCLE',
'DDM_MECHANISM', 'DECAY', 'DEFAULT', 'DEFAULT_CONTROL_MECHANISM', 'DEFAULT_MATRIX',
'DEFAULT_PROCESSING_MECHANISM', 'DEFAULT_SYSTEM',
'DEFERRED_ASSIGNMENT', 'DEFERRED_DEFAULT_NAME', 'DEFERRED_INITIALIZATION',
'DIFFERENCE', 'DIFFERENCE', 'DIFFUSION', 'DIST_FUNCTION_TYPE', 'DIST_MEAN',
'DIST_SHAPE', 'DISTANCE_FUNCTION', 'DISTANCE_METRICS', 'DISTRIBUTION_FUNCTION_TYPE',
'DIVISION', 'DRIFT_DIFFUSION_INTEGRATOR_FUNCTION', 'DRIFT_RATE',
'ENABLE_CONTROLLER', 'ENABLED', 'ENERGY', 'ENTROPY', 'ERROR_DERIVATIVE_FUNCTION', 'EUCLIDEAN',
'EVC_MECHANISM', 'EVC_SIMULATION', 'EXAMPLE_FUNCTION_TYPE',
Expand Down Expand Up @@ -791,6 +794,7 @@ def _is_metric(metric):

FUNCTION_OUTPUT_TYPE = 'functionOutputType'

COMBINE = 'combine'
SUM = 'sum'
DIFFERENCE = DIFFERENCE # Defined above for DISTANCE_METRICS
PRODUCT = 'product'
Expand Down

0 comments on commit 4f2ce2f

Please sign in to comment.