Skip to content

Commit

Permalink
Refactor/keyword control to control (#2273)
Browse files Browse the repository at this point in the history
* -

* • controlmechanism.py, gatingmechanism.py:
  - CONTROL: 'CONTROL' -> 'control'
  - GATING: 'GATING' -> 'gating'

* • Project:
  - CONTROL: 'CONTROL' -> 'control'
  - del GATING
  - GATE = 'gate"

Co-authored-by: jdcpni <pniintel55>
  • Loading branch information
jdcpni authored Jan 3, 2022
1 parent 1fdb95d commit 491fede
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 42 deletions.
4 changes: 3 additions & 1 deletion Scripts/Examples/Gating-Mechanism. with UDF.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import functools

import numpy as np

import psyneulink as pnl
import psyneulink.core.components.functions.nonstateful.transferfunctions

Expand Down Expand Up @@ -51,7 +53,7 @@ def my_sinusoidal_fct(input,
# pnl.FUNCTION: my_sinusoidal_fct}
output_ports={pnl.NAME: 'RESULTS USING UDF',
# pnl.VARIABLE: (pnl.OWNER_VALUE, 0),
pnl.FUNCTION: psyneulink.core.components.functions.nonstateful.transferfunctions.Linear(slope=pnl.GATING)
pnl.FUNCTION: psyneulink.core.components.functions.nonstateful.transferfunctions.Linear(slope=pnl.GATE)
# pnl.FUNCTION: pnl.Logistic(gain=pnl.GATING)
# pnl.FUNCTION: my_linear_fct
# pnl.FUNCTION: my_exp_fct
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1206,8 +1206,8 @@ class Parameters(ModulatoryMechanism_Base.Parameters):
read_only=True,
structural=True,
parse_spec=True,
aliases=['control', 'control_signals'],
constructor_argument='control'
aliases=[CONTROL, CONTROL_SIGNALS],
constructor_argument=CONTROL
)

# MODIFIED 1/2/22 OLD: - MUCH OF THIS SEEMS TO BE COVERED ELSEWHERE; COMMENTING OUT ONLY CAUSES PROBLEMS WITH
Expand Down Expand Up @@ -1308,7 +1308,7 @@ def __init__(self,
# Only allow one of CONTROL, MODULATORY_SIGNALS OR CONTROL_SIGNALS to be specified
# These are synonyms, but allowing several to be specified and trying to combine the specifications
# can cause problems if different forms of specification are used to refer to the same Component(s)
control_specified = "'control'" if control else ''
control_specified = f"'{CONTROL}'" if control else ''
modulatory_signals_specified = ''
if MODULATORY_SIGNALS in kwargs:
args = kwargs.pop(MODULATORY_SIGNALS)
Expand Down Expand Up @@ -1412,14 +1412,18 @@ def _validate_params(self, request_set, target_set=None, context=None):

if CONTROL in target_set and target_set[CONTROL]:
control = target_set[CONTROL]
assert isinstance(control, list), \
f"PROGRAM ERROR: control arg {control} of {self.name} should have been converted to a list."
for ctl_spec in control:
ctl_spec = _parse_port_spec(port_type=ControlSignal, owner=self, port_spec=ctl_spec)
if not (isinstance(ctl_spec, ControlSignal)
or (isinstance(ctl_spec, dict) and ctl_spec[PORT_TYPE]==ControlSignal.__name__)):
raise ControlMechanismError(f"Invalid specification for '{CONTROL}' argument of {self.name}:"
f"({ctl_spec})")
self._validate_control_arg(control)

def _validate_control_arg(self, control):
"""Treat control arg separately so it can be overridden by subclassses (e.g., GatingMechanism)"""
assert isinstance(control, list), \
f"PROGRAM ERROR: control arg {control} of {self.name} should have been converted to a list."
for ctl_spec in control:
ctl_spec = _parse_port_spec(port_type=ControlSignal, owner=self, port_spec=ctl_spec)
if not (isinstance(ctl_spec, ControlSignal)
or (isinstance(ctl_spec, dict) and ctl_spec[PORT_TYPE] == ControlSignal)):
raise ControlMechanismError(f"Invalid specification for '{CONTROL}' argument of {self.name}:"
f"({ctl_spec})")

# IMPLEMENTATION NOTE: THIS SHOULD BE MOVED TO COMPOSITION ONCE THAT IS IMPLEMENTED
def _instantiate_objective_mechanism(self, input_ports=None, context=None):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,11 @@

from psyneulink.core.components.mechanisms.modulatory.control.controlmechanism import ControlMechanism
from psyneulink.core.components.ports.modulatorysignals.gatingsignal import GatingSignal
from psyneulink.core.components.ports.port import _parse_port_spec
from psyneulink.core.globals.defaults import defaultGatingAllocation
from psyneulink.core.globals.keywords import \
GATE, GATING, GATING_PROJECTION, GATING_SIGNAL, GATING_SIGNALS, \
INIT_EXECUTE_METHOD_ONLY, MONITOR_FOR_CONTROL, PROJECTION_TYPE
CONTROL, CONTROL_SIGNALS, GATE, GATING_PROJECTION, GATING_SIGNAL, GATING_SIGNALS, \
INIT_EXECUTE_METHOD_ONLY, MONITOR_FOR_CONTROL, PORT_TYPE, PROJECTION_TYPE
from psyneulink.core.globals.parameters import Parameter
from psyneulink.core.globals.preferences.basepreferenceset import is_pref_set
from psyneulink.core.globals.preferences.preferenceset import PreferenceLevel
Expand Down Expand Up @@ -217,7 +218,7 @@ def _is_gating_spec(spec):
GatingMechanism,
ControlMechanism)):
return True
elif isinstance(spec, str) and spec in {GATING, GATING_PROJECTION, GATING_SIGNAL}:
elif isinstance(spec, str) and spec in {GATE, GATING_PROJECTION, GATING_SIGNAL}:
return True
else:
return False
Expand Down Expand Up @@ -427,7 +428,7 @@ class Parameters(ControlMechanism.Parameters):
read_only=True,
structural=True,
parse_spec=True,
aliases=['control', 'control_signals', 'gate', 'gating_signal'],
aliases=[CONTROL, CONTROL_SIGNALS, 'gate', 'gating_signal'],
constructor_argument='gate'
)

Expand Down Expand Up @@ -526,6 +527,16 @@ def _register_control_signal_type(self, context=None):
registry=self._portRegistry,
)

def _validate_control_arg(self, gate):
"""Overrided to handle GatingMechanism-specific specifications"""
assert isinstance(gate, list), \
f"PROGRAM ERROR: 'gate' arg ({gate}) of {self.name} should have been converted to a list."
for spec in gate:
spec = _parse_port_spec(port_type=GatingSignal, owner=self, port_spec=spec)
if not (isinstance(spec, GatingSignal)
or (isinstance(spec, dict) and spec[PORT_TYPE] == GatingSignal)):
raise GatingMechanismError(f"Invalid specification for '{GATE}' argument of {self.name}: ({spec})")

def _instantiate_control_signal_type(self, gating_signal_spec, context):
"""Instantiate actual ControlSignal, or subclass if overridden"""
from psyneulink.core.components.ports.port import _instantiate_port
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -822,23 +822,23 @@ def __init__(self,
if MODULATES in kwargs:
# Don't allow **control** and **modulates** to both be specified
if control:
raise ControlSignalError(f"Both 'control' and '{MODULATES}' arguments are specified in the "
raise ControlSignalError(f"Both '{CONTROL}' and '{MODULATES}' arguments are specified in the "
f"constructor for '{name if name else self.__class__.__name__}; "
f"Should use just 'control'.")
f"Should use just '{CONTROL}'.")
# warnings.warn(f"The '{MODULATES}' argument (specified in the constructor for "
# f"'{name if name else self.__class__.__name__}') has been deprecated; "
# f"should use '{'control'}' going forward.")

if PROJECTIONS in kwargs:
raise ControlSignalError(f"Both '{MODULATES}' and '{PROJECTIONS}' arguments are specified "
f"in the constructor for '{name if name else self.__class__.__name__}; "
f"Should use just '{PROJECTIONS}' (or 'control') ")
f"Should use just '{PROJECTIONS}' (or '{CONTROL}') ")
control = kwargs.pop(MODULATES)

elif PROJECTIONS in kwargs:
# Don't allow **control** and **modulates** to both be specified
if control:
raise ControlSignalError(f"Both 'control' and '{PROJECTIONS}' arguments are specified "
raise ControlSignalError(f"Both '{CONTROL}' and '{PROJECTIONS}' arguments are specified "
f"in the constructor for '{name if name else self.__class__.__name__}; "
f"Must use just one or the other.")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
from psyneulink.core.components.shellclasses import Mechanism, Process_Base
from psyneulink.core.globals.context import ContextFlags
from psyneulink.core.globals.keywords import \
FUNCTION_OUTPUT_TYPE, GATING, GATING_MECHANISM, GATING_PROJECTION, GATING_SIGNAL, \
FUNCTION_OUTPUT_TYPE, GATE, GATING_MECHANISM, GATING_PROJECTION, GATING_SIGNAL, \
INPUT_PORT, OUTPUT_PORT
from psyneulink.core.globals.parameters import Parameter
from psyneulink.core.globals.preferences.basepreferenceset import is_pref_set
Expand All @@ -120,8 +120,8 @@
'GATING_SIGNAL_PARAMS', 'GatingProjection', 'GatingProjectionError',
]

parameter_keywords.update({GATING_PROJECTION, GATING})
projection_keywords.update({GATING_PROJECTION, GATING})
parameter_keywords.update({GATING_PROJECTION, GATE})
projection_keywords.update({GATING_PROJECTION, GATE})
GATING_SIGNAL_PARAMS = 'gating_signal_params'

class GatingProjectionError(Exception):
Expand Down
10 changes: 5 additions & 5 deletions psyneulink/core/components/projections/projection.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
as its the ControlProjection's `sender <ControlProjection.sender>`. See `ControlMechanism_ControlSignals` for
additional details.
* *GATING_PROJECTION* (or *GATING*) -- this can be used when specifying an `InputPort
* *GATING_PROJECTION* (or *GATE*) -- this can be used when specifying an `InputPort
<InputPort_Projection_Source_Specification>` or an `OutputPort <OutputPort_Projections>`, to create a
default `GatingProjection` to the `Port <Port>`. If the GatingProjection's `sender <GatingProjection.sender>`
cannot be inferred from the context in which this specification occurs, then its `initialization is deferred
Expand Down Expand Up @@ -402,14 +402,14 @@
import typecheck as tc

from psyneulink.core import llvm as pnlvm
from psyneulink.core.components.functions.nonstateful.transferfunctions import LinearMatrix
from psyneulink.core.components.functions.function import get_matrix
from psyneulink.core.components.shellclasses import Mechanism, Process_Base, Projection, Port
from psyneulink.core.components.functions.nonstateful.transferfunctions import LinearMatrix
from psyneulink.core.components.ports.modulatorysignals.modulatorysignal import _is_modulatory_spec
from psyneulink.core.components.ports.port import PortError
from psyneulink.core.components.shellclasses import Mechanism, Process_Base, Projection, Port
from psyneulink.core.globals.context import ContextFlags
from psyneulink.core.globals.keywords import \
CONTROL, CONTROL_PROJECTION, CONTROL_SIGNAL, EXPONENT, FUNCTION_PARAMS, GATING, GATING_PROJECTION, GATING_SIGNAL, \
CONTROL, CONTROL_PROJECTION, CONTROL_SIGNAL, EXPONENT, FUNCTION_PARAMS, GATE, GATING_PROJECTION, GATING_SIGNAL, \
INPUT_PORT, LEARNING, LEARNING_PROJECTION, LEARNING_SIGNAL, \
MAPPING_PROJECTION, MATRIX, MATRIX_KEYWORD_SET, MECHANISM, \
MODEL_SPEC_ID_RECEIVER_MECH, MODEL_SPEC_ID_RECEIVER_PORT, MODEL_SPEC_ID_SENDER_MECH, MODEL_SPEC_ID_SENDER_PORT, \
Expand Down Expand Up @@ -443,7 +443,7 @@
CONTROL: CONTROL_PROJECTION,
CONTROL_SIGNAL: CONTROL_PROJECTION,
CONTROL_PROJECTION: CONTROL_PROJECTION,
GATING: GATING_PROJECTION,
GATE: GATING_PROJECTION,
GATING_SIGNAL: GATING_PROJECTION,
GATING_PROJECTION: GATING_PROJECTION
}
Expand Down
10 changes: 5 additions & 5 deletions psyneulink/core/globals/keywords.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
'FEEDBACK', 'FITZHUGHNAGUMO_INTEGRATOR_FUNCTION', 'FINAL', 'FLAGS', 'FULL', 'FULL_CONNECTIVITY_MATRIX',
'FUNCTION', 'FUNCTIONS', 'FUNCTION_COMPONENT_CATEGORY','FUNCTION_CHECK_ARGS',
'FUNCTION_OUTPUT_TYPE', 'FUNCTION_OUTPUT_TYPE_CONVERSION', 'FUNCTION_PARAMS',
'GAIN', 'GAMMA_DIST_FUNCTION', 'GATE', 'GATING', 'GATING_MECHANISM', 'GATING_ALLOCATION', 'GATING_PROJECTION',
'GAIN', 'GAMMA_DIST_FUNCTION', 'GATE', 'GATING_MECHANISM', 'GATING_ALLOCATION', 'GATING_PROJECTION',
'GATING_PROJECTION_PARAMS', 'GATING_PROJECTIONS', 'GATING_SIGNAL', 'GATING_SIGNAL_SPECS', 'GATING_SIGNALS',
'GAUSSIAN', 'GAUSSIAN_FUNCTION', 'GILZENRAT_INTEGRATOR_FUNCTION',
'GREATER_THAN', 'GREATER_THAN_OR_EQUAL', 'GRADIENT_OPTIMIZATION_FUNCTION', 'GRID_SEARCH_FUNCTION',
Expand Down Expand Up @@ -660,8 +660,7 @@ def _is_metric(metric):
PULSE_CLAMP = "pulse_clamp"
NO_CLAMP = "no_clamp"
LEARNING_RATE = "learning_rate"
CONTROL = 'CONTROL'
GATING = 'gating'
# CONTROL = 'CONTROL'
PROCESS_DEFAULT_PROJECTION_FUNCTION = "Default Projection Function"
PROCESS_EXECUTE = "ProcessExecute"
MECHANISM_EXECUTED_LOG_ENTRY = "Mechanism Executed"
Expand Down Expand Up @@ -764,6 +763,7 @@ def _is_metric(metric):
PREDICTION_MECHANISM_OUTPUT = "PredictionMechanismOutput"

MODULATORY_SIGNALS = 'modulatory_signals'
CONTROL = 'control'
CONTROL_SIGNALS = 'control_signals'
CONTROL_SIGNAL_SPECS = 'CONTROL_SIGNAL_SPECS'
CONTROLLED_PARAMS = 'CONTROLLED_PARAMS'
Expand All @@ -778,16 +778,16 @@ def _is_metric(metric):
ALLOCATION_SAMPLES = "allocation_samples"

# GatingMechanism
GATE = 'gate'
GATING_SIGNALS = 'gating_signals'
GATING_SIGNAL_SPECS = 'GATING_SIGNAL_SPECS'
GATE = 'GATE'
GATED_PORTS = 'GATED_PORTS'
GATING_PROJECTIONS = 'GatingProjections'
GATING_ALLOCATION = 'gating_allocation'

MODULATORY_SPEC_KEYWORDS = {LEARNING, LEARNING_SIGNAL, LEARNING_PROJECTION, LEARNING_MECHANISM,
CONTROL, CONTROL_SIGNAL, CONTROL_PROJECTION, CONTROL_MECHANISM,
GATING, GATING_SIGNAL, GATING_PROJECTION, GATING_MECHANISM}
GATE, GATING_SIGNAL, GATING_PROJECTION, GATING_MECHANISM}

MODULATED_PARAMETER_PREFIX = 'mod_'

Expand Down
3 changes: 2 additions & 1 deletion tests/composition/test_gating.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import numpy as np
import pytest

import psyneulink as pnl


Expand All @@ -19,7 +20,7 @@ def test_gating(benchmark, comp_mode):
function=pnl.Linear(),
output_ports={
pnl.NAME: 'RESULTS USING UDF',
pnl.FUNCTION: pnl.Linear(slope=pnl.GATING)
pnl.FUNCTION: pnl.Linear(slope=pnl.GATE)
}
)

Expand Down
9 changes: 5 additions & 4 deletions tests/mechanisms/test_gating_mechanism.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import numpy as np

import psyneulink as pnl
import psyneulink.core.components.functions.nonstateful.transferfunctions

from psyneulink.core.components.functions.stateful.integratorfunctions import AccumulatorIntegrator
from psyneulink.core.components.functions.nonstateful.transferfunctions import Logistic
from psyneulink.core.components.functions.stateful.integratorfunctions import AccumulatorIntegrator
from psyneulink.core.components.mechanisms.modulatory.control.gating.gatingmechanism import GatingMechanism
from psyneulink.core.components.mechanisms.processing.transfermechanism import TransferMechanism
from psyneulink.core.components.projections.pathway.mappingprojection import MappingProjection
from psyneulink.core.compositions.composition import Composition
from psyneulink.core.globals.keywords import \
DEFAULT_VARIABLE, FUNCTION, FUNCTION_PARAMS, INITIALIZER, RATE, VALUE
from psyneulink.core.compositions.composition import Composition


def test_gating_with_composition():
"""Tests same configuration as control of InputPort in tests/mechansims/test_identicalness_of_control_and_gating
Expand Down Expand Up @@ -131,7 +132,7 @@ def my_sinusoidal_fct(
output_ports={
pnl.NAME: 'RESULTS USING UDF',
# pnl.VARIABLE: (pnl.OWNER_VALUE, 0),
pnl.FUNCTION: psyneulink.core.components.functions.nonstateful.transferfunctions.Linear(slope=pnl.GATING)
pnl.FUNCTION: psyneulink.core.components.functions.nonstateful.transferfunctions.Linear(slope=pnl.GATE)
}
)

Expand Down
10 changes: 6 additions & 4 deletions tests/projections/test_projection_specifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ def test_formats_for_control_specification_for_mechanism_and_function_params(sel
'ControlProjection for R-CONTROL[gain]'

gating_spec_list = [
pnl.GATING,
pnl.GATE,
pnl.CONTROL,
pnl.GATING_SIGNAL,
pnl.CONTROL_SIGNAL,
Expand All @@ -371,7 +371,7 @@ def test_formats_for_control_specification_for_mechanism_and_function_params(sel
pnl.ControlMechanism,
pnl.GatingMechanism(),
pnl.ControlMechanism(),
(0.3, pnl.GATING),
(0.3, pnl.GATE),
(0.3, pnl.CONTROL),
(0.3, pnl.GATING_SIGNAL),
(0.3, pnl.CONTROL_SIGNAL),
Expand Down Expand Up @@ -411,12 +411,14 @@ def test_formats_for_gating_specification_of_input_and_output_ports(self, input_
IN_NAME = G_IN[1]
else:
IN_NAME = G_IN
IN_CONTROL = pnl.CONTROL in repr(IN_NAME).split(".")[-1].upper()
# IN_CONTROL = pnl.CONTROL in repr(IN_NAME).split(".")[-1].upper()
IN_CONTROL = 'CONTROL' in repr(IN_NAME).split(".")[-1].upper()
if isinstance(G_OUT, tuple):
OUT_NAME = G_OUT[1]
else:
OUT_NAME = G_OUT
OUT_CONTROL = pnl.CONTROL in repr(OUT_NAME).split(".")[-1].upper()
# OUT_CONTROL = pnl.CONTROL in repr(OUT_NAME).split(".")[-1].upper()
OUT_CONTROL = 'CONTROL' in repr(OUT_NAME).split(".")[-1].upper()

T = pnl.TransferMechanism(
name='T-GATING',
Expand Down

0 comments on commit 491fede

Please sign in to comment.