diff --git a/.idea/runConfigurations/EVC_System_Laming_Validation_Test_Script__SPECIFY_ControlSignals__.xml b/.idea/runConfigurations/EVC_System_Laming_Validation_Test_Script__SPECIFY_ControlSignals__.xml
index 044a20175a6..001c85fccf0 100644
--- a/.idea/runConfigurations/EVC_System_Laming_Validation_Test_Script__SPECIFY_ControlSignals__.xml
+++ b/.idea/runConfigurations/EVC_System_Laming_Validation_Test_Script__SPECIFY_ControlSignals__.xml
@@ -6,13 +6,13 @@
-
+
-
+
diff --git a/.idea/runConfigurations/Multilayer_Learning_Test_Script__WITH_GATING_.xml b/.idea/runConfigurations/Multilayer_Learning_Test_Script__WITH_GATING_.xml
index 835474c0ba4..17a4d45d47c 100644
--- a/.idea/runConfigurations/Multilayer_Learning_Test_Script__WITH_GATING_.xml
+++ b/.idea/runConfigurations/Multilayer_Learning_Test_Script__WITH_GATING_.xml
@@ -6,13 +6,13 @@
-
+
-
+
-
-
+
+
diff --git a/.idea/runConfigurations/_EVC_System_Laming_Validation_Test_Script.xml b/.idea/runConfigurations/_EVC_System_Laming_Validation_Test_Script.xml
index 3d591cba49a..b91a9de1273 100644
--- a/.idea/runConfigurations/_EVC_System_Laming_Validation_Test_Script.xml
+++ b/.idea/runConfigurations/_EVC_System_Laming_Validation_Test_Script.xml
@@ -11,7 +11,7 @@
-
+
diff --git a/.idea/runConfigurations/_META_TEST.xml b/.idea/runConfigurations/_META_TEST.xml
index e31c4b4f241..45e56a57fbd 100644
--- a/.idea/runConfigurations/_META_TEST.xml
+++ b/.idea/runConfigurations/_META_TEST.xml
@@ -11,7 +11,7 @@
-
+
diff --git a/.idea/runConfigurations/_Multilayer_Learning_Test_Script.xml b/.idea/runConfigurations/_Multilayer_Learning_Test_Script.xml
index d3bbb98be1e..43638df8227 100644
--- a/.idea/runConfigurations/_Multilayer_Learning_Test_Script.xml
+++ b/.idea/runConfigurations/_Multilayer_Learning_Test_Script.xml
@@ -6,7 +6,7 @@
-
+
diff --git a/.idea/runConfigurations/_Reinforcement_Learning_Test_Script.xml b/.idea/runConfigurations/_Reinforcement_Learning_Test_Script.xml
index abd86930ca1..fc84bda3df6 100644
--- a/.idea/runConfigurations/_Reinforcement_Learning_Test_Script.xml
+++ b/.idea/runConfigurations/_Reinforcement_Learning_Test_Script.xml
@@ -10,7 +10,7 @@
-
+
diff --git a/.idea/runConfigurations/_Scratch_Pad.xml b/.idea/runConfigurations/_Scratch_Pad.xml
index d4abb3e0af1..297acc32aa5 100644
--- a/.idea/runConfigurations/_Scratch_Pad.xml
+++ b/.idea/runConfigurations/_Scratch_Pad.xml
@@ -5,12 +5,12 @@
-
+
-
+
-
+
diff --git a/PsyNeuLink Tutorial.ipynb b/PsyNeuLink Tutorial.ipynb
index f6fcad5e590..960fa6c017f 100644
--- a/PsyNeuLink Tutorial.ipynb
+++ b/PsyNeuLink Tutorial.ipynb
@@ -74,9 +74,7 @@
{
"cell_type": "code",
"execution_count": 1,
- "metadata": {
- "collapsed": false
- },
+ "metadata": {},
"outputs": [],
"source": [
"from PsyNeuLink.Components.System import system\n",
@@ -86,7 +84,7 @@
"from PsyNeuLink.Components.Mechanisms.ProcessingMechanisms.TransferMechanism import TransferMechanism\n",
"from PsyNeuLink.Components.Functions.Function import Linear, Logistic\n",
"\n",
- "from PsyNeuLink.Components.Projections.MappingProjection import MappingProjection"
+ "from PsyNeuLink.Components.Projections.TransmissiveProjections.MappingProjection import MappingProjection"
]
},
{
@@ -113,13 +111,14 @@
},
{
"cell_type": "code",
- "execution_count": 3,
+ "execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
- "linear_transfer_mechanism = TransferMechanism(function=Linear(slope = 1, intercept = 0))"
+ "linear_transfer_mechanism = TransferMechanism(\n",
+ " function=Linear(slope=1, intercept=0))"
]
},
{
@@ -131,24 +130,24 @@
},
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": 20,
"metadata": {
- "collapsed": false
+ "collapsed": true
},
"outputs": [
{
"data": {
"text/plain": [
- "[array([[ 1.]])]"
+ "array([[ 1.]])"
]
},
- "execution_count": 4,
+ "execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "linear_transfer_mechanism.run([1])"
+ "linear_transfer_mechanism.execute([1])"
]
},
{
@@ -173,7 +172,7 @@
},
{
"cell_type": "code",
- "execution_count": 5,
+ "execution_count": 23,
"metadata": {
"collapsed": false
},
@@ -191,41 +190,16 @@
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": 24,
"metadata": {
- "collapsed": false
+ "collapsed": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "\n",
- "\n",
- "****************************************\n",
- "\n",
- "\n",
- "''Process-1' component' executing with:\n",
- "- pathway: ['TransferMechanism-1']\n",
- "- input: 4\n",
- "\n",
- "'TransferMechanism-1' executed:\n",
- "- input: 4.0\n",
- "- params:\n",
- "\tfunction: Linear\n",
- "\t\tintercept: 0\n",
- "\t\tslope: 1\n",
- "\tinitial_value: None\n",
- "\tnoise: 0.0\n",
- "\ttime_scale: TimeScale.TRIAL\n",
- "- output: 4.0\n",
- "\n",
- "''Process-1' component' completed:\n",
- "- output: 4.0\n",
- "\n",
- "\n",
- "****************************************\n",
- "\n"
+ "\n\n****************************************\n\n\n'Process-1' executing with:\n- pathway: ['TransferMechanism-1']\n- input: [[4]]\n\n'TransferMechanism-1' executed:\n- input: 4.0\n- params:\n\tfunction: Linear\n\t\tintercept: 0\n\t\tslope: 1\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 4.0\n\n'Process-1' completed:\n- output: 4.0\n\n\n****************************************\n\n"
]
},
{
@@ -234,7 +208,7 @@
"array([ 4.])"
]
},
- "execution_count": 6,
+ "execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
@@ -254,7 +228,7 @@
"cell_type": "code",
"execution_count": 7,
"metadata": {
- "collapsed": false
+ "collapsed": true
},
"outputs": [
{
@@ -300,23 +274,149 @@
},
{
"cell_type": "code",
- "execution_count": 8,
+ "execution_count": 25,
"metadata": {
- "collapsed": false
+ "collapsed": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "---------------------------------------------------"
+ "\n'TransferMechanism-2' executed:\n- input: -3.0, -6.0\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0474 0.00247\n-\n'TransferMechanism-2' executed:\n- input: -2.88, -5.76\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0532 0.00314\n-\n'TransferMechanism-2' executed:\n- input: -2.76, -5.52\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0595 0.00399\n-\n'TransferMechanism-2' executed:\n- input: -2.64, -5.28\n- params:\n\tfunction: Logistic\n\t\tbias: 0"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0666 0.00507\n-\n'TransferMechanism-2' executed:\n- input: -2.52, -5.04\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0745 0.00643\n-\n'TransferMechanism-2' executed:\n- input: -2.4, -4.8\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0832 0.00816\n-\n'TransferMechanism-2' executed:\n- input: -2.28, -4.56\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0928 0.0104\n-\n'TransferMechanism-2' executed:\n- input: -2.16, -4.32\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.103 0.0131\n-\n'TransferMechanism-2' executed:\n- input: -2.04, -4.08"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.115 0.0166\n-\n'TransferMechanism-2' executed:\n- input: -1.92, -3.84\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.128 0.021\n-\n'TransferMechanism-2' executed:\n- input: -1.8, -3.6\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.142 0.0266\n-\n'TransferMechanism-2' executed:\n- input: -1.68, -3.36\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.157 0.0336\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-2' executed:\n- input: -1.56, -3.12\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.174 0.0423\n-\n'TransferMechanism-2' executed:\n- input: -1.44, -2.88\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.192 0.0532\n-\n'TransferMechanism-2' executed:\n- input: -1.32, -2.64\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.211 0.0666\n-\n'TransferMechanism-2' executed:\n- input: -1.2, -2.4\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.231 0.0832\n-\n'TransferMechanism-2' executed:\n- input: -1.08, -2.16\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.254 0.103\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-2' executed:\n- input: -0.96, -1.92\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.277 0.128\n-\n'TransferMechanism-2' executed:\n- input: -0.84, -1.68\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.302 0.157\n-\n'TransferMechanism-2' executed:\n- input: -0.72, -1.44\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.327 0.192\n-\n'TransferMechanism-2' executed:\n- input: -0.6, -1.2\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.354 0.231\n-\n'TransferMechanism-2' executed:\n- input: -0.48, -0.96\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.382 0.277\n-\n'TransferMechanism-2' executed:\n- input: -0.36, -0.72\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.411 0.327\n-\n'TransferMechanism-2' executed:\n- input: -0.24, -0.48\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.44 0.382\n-\n'TransferMechanism-2' executed:\n- input: -0.12, -0.24\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.47 0.44\n-\n'TransferMechanism-2' executed:\n- input: 0.0, 0.0\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.5 0.5\n-\n'TransferMechanism-2' executed:\n- input: 0.12, 0.24\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.53 0.56\n-\n'TransferMechanism-2' executed:\n- input: 0.24, 0.48\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.56 0.618\n-\n'TransferMechanism-2' executed:\n- input: 0.36, 0.72\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.589 0.673\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-2' executed:\n- input: 0.48, 0.96\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.618 0.723\n-\n'TransferMechanism-2' executed:\n- input: 0.6, 1.2\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.646 0.769\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-2' executed:\n- input: 0.72, 1.44\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.673 0.808\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-2' executed:\n- input: 0.84, 1.68\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.698 0.843\n-\n'TransferMechanism-2' executed:\n- input: 0.96, 1.92\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.723 0.872\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-2' executed:\n- input: 1.08, 2.16\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.746 0.897\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-2' executed:\n- input: 1.2, 2.4\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.769 0.917\n-\n'TransferMechanism-2' executed:\n- input: 1.32, 2.64\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n- output: 0.789 0.933\n-\n'TransferMechanism-2' executed:\n- input: 1.44, 2.88\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.808 0.947\n-\n'TransferMechanism-2' executed:\n- input: 1.56, 3.12\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.826 0.958\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-2' executed:\n- input: 1.68, 3.36\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.843 0.966\n-\n'TransferMechanism-2' executed:\n- input: 1.8, 3.6\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.858 0.973\n-\n'TransferMechanism-2' executed:\n- input: 1.92, 3.84\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.872 0.979\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-2' executed:\n- input: 2.04, 4.08\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.885 0.983\n-\n'TransferMechanism-2' executed:\n- input: 2.16, 4.32\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.897 0.987\n-\n'TransferMechanism-2' executed:\n- input: 2.28, 4.56\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.907 0.99\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-2' executed:\n- input: 2.4, 4.8\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.917 0.992\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-2' executed:\n- input: 2.52, 5.04\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.926 0.994\n-\n'TransferMechanism-2' executed:\n- input: 2.64, 5.28\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.933 0.995\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-2' executed:\n- input: 2.76, 5.52\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.94 0.996\n-\n'TransferMechanism-2' executed:\n- input: 2.88, 5.76\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.947 0.997\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-2' executed:\n- input: 3.0, 6.0\n- params:\n\tfunction: Logistic\n\t\tbias: 0\n\t\tgain: 1\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.953 0.998\n-"
]
},
{
"data": {
- "image/png": "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\n",
+ "image/png": "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\n",
"text/plain": [
- ""
+ ""
]
},
"metadata": {},
@@ -325,17 +425,19 @@
],
"source": [
"# Create the mechanism\n",
- "logistic_transfer_mechanism = TransferMechanism(default_input_value = [0, 0], function=Logistic(gain = 1, bias = 0))\n",
+ "logistic_transfer_mechanism = TransferMechanism(default_input_value=[0, 0],\n",
+ " function=Logistic(gain=1,\n",
+ " bias=0))\n",
"\n",
"# Package into a process\n",
- "logistic_transfer_process = process(pathway = [logistic_transfer_mechanism])\n",
+ "logistic_transfer_process = process(pathway=[logistic_transfer_mechanism])\n",
"\n",
"# Iterate and plot\n",
"xVals = np.linspace(-3, 3, num=51)\n",
"y1Vals = np.zeros((51,))\n",
"y2Vals = np.zeros((51,))\n",
"for i in range(xVals.shape[0]):\n",
- " output = logistic_transfer_process.execute([xVals[i], xVals[i]*2])\n",
+ " output = logistic_transfer_process.execute([xVals[i], xVals[i] * 2])\n",
" y1Vals[i] = output[0]\n",
" y2Vals[i] = output[1]\n",
" # Progress bar\n",
@@ -363,189 +465,704 @@
},
{
"cell_type": "code",
- "execution_count": 9,
+ "execution_count": 26,
"metadata": {
- "collapsed": false
+ "collapsed": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "---------------------------------------------------"
+ "\n'TransferMechanism-3' executed:\n- input: -3.0\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -4.0\n\n'TransferMechanism-4' executed:\n- input: -4.0\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.018\n-\n'TransferMechanism-3' executed:\n- input: -2.88\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -3.76\n\n'TransferMechanism-4' executed:\n- input: -3.76\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0228\n-\n'TransferMechanism-3' executed:\n- input: -2.76\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -3.52\n\n'TransferMechanism-4' executed:\n- input: -3.52\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0287\n-"
]
},
{
- "data": {
- "image/png": "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\nwP8HzmYp/YovtV8AAAAASUVORK5CYII=\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "linear_input_unit = TransferMechanism(function = Linear(slope = 2, intercept = 2))\n",
- "logistic_output_unit = TransferMechanism(function = Logistic())\n",
- "mini_connected_network = process(pathway = [linear_input_unit, IDENTITY_MATRIX, logistic_output_unit])\n",
- "\n",
- "# Iterate and plot\n",
- "xVals = np.linspace(-3, 3, num=51)\n",
- "yVals = np.zeros((51,))\n",
- "for i in range(xVals.shape[0]):\n",
- " yVals[i] = mini_connected_network.execute([xVals[i]])[0]\n",
- " # Progress bar\n",
- " print(\"-\", end=\"\")\n",
- "plt.plot(xVals, yVals)\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "IDENTITY_MATRIX is a keyword that provides a projection from the unit preceding it to the unit following that creates a one-to-one output to input projection between the two. Other useful projection keywords are...\n",
- "\n",
- "Now let's make our projection definition a bit more explicit."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {
- "collapsed": false
- },
- "outputs": [
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-3' executed:\n- input: -2.64\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -3.28\n\n'TransferMechanism-4' executed:\n- input: -3.28\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0363\n-\n'TransferMechanism-3' executed:\n- input: -2.52\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -3.04\n\n'TransferMechanism-4' executed:\n- input: -3.04\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0457\n-"
+ ]
+ },
{
"name": "stdout",
"output_type": "stream",
"text": [
- "---------------------------------------------------"
+ "\n'TransferMechanism-3' executed:\n- input: -2.4\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -2.8\n\n'TransferMechanism-4' executed:\n- input: -2.8\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0573\n-\n'TransferMechanism-3' executed:\n- input: -2.28\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -2.56\n\n'TransferMechanism-4' executed:\n- input: -2.56\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0718\n-\n'TransferMechanism-3' executed:\n- input: -2.16"
]
},
{
- "data": {
- "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgQAAAFkCAYAAABfHiNRAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAAPYQAAD2EBqD+naQAAIABJREFUeJzt3XmcnfPd//HXR4TEFtWgtTyo2ltCpraqcnPXWltUGUu0\nlDulSixFqNj35UbFThLLEHvsJURsoSbE7YdqSm+iqbVNbiJI8v398Z00yZhJ5pzMzHXOnNfz8TiP\nM3PNdc155xhzfeZzfa/vN1JKSJKk2rZQ0QEkSVLxLAgkSZIFgSRJsiCQJElYEEiSJCwIJEkSFgSS\nJAkLAkmShAWBJEnCgkCSJFFGQRARW0TEyIh4LyJmRsQubThmq4hojIhpEfFmRBxQXlxJktQRyukQ\nLA68DBwGzHchhIhYFbgfGAX0AS4Bro2In5Tx2pIkqQPEgixuFBEzgd1SSiPnsc+5wA4ppfXn2NYA\n9Eop7Vj2i0uSpHbTGWMINgUea7btEWCzTnhtSZLUBgt3wmt8C3i/2bb3gaUiYtGU0hfND4iIbwLb\nAX8DpnV4QkmSuo4ewKrAIymlj9t6UGcUBC2JpufWrldsB9zcSVkkSeqK9gVuaevOnVEQ/ANYvtm2\n5YApKaUvWznmbwA33XQT66yzTgdG61oGDhzIxRdfXHSMquP7Vjrfs/JU0vs2fTpMnQqffdbyY+pU\n+PxzmDYtPzf/eNbnX3wBX36ZP/7yy/z5jBnl51poIVh4YejePT9PnTqQZZa5mO7doVu3vK1bt9kf\nz/l588dCC8393NK2iLmfF1po9iNi7s+bb4uY/fm8Pp7175q1vfkDvr5/a/s03zbn9lkfv/PO65xx\nxn7QdC5tq84oCJ4Ddmi2bdum7a2ZBrDOOuvQt2/fjsrV5fTq1cv3qwy+b6XzPStPe79vKeWT94cf\nwgcf5OdPPoF//nP2Y87PZ308ZUo+oc/LYovlx+KLz37M+ny55WZ/3rMn9OjR+nOPHrDoorMfiyzy\n9Y8XWSQ/unfPJ8U57bJLL0aO9GetFOPGwRlnACVeci+5IIiIxYHVmd32Xy0i+gCfpJTejYizgRVS\nSrPmGrgS+E3T3QbXA9sAPwO8w0CSWjB9OkyaBBMnwnvv5edJk2af9D/4YPajpRN7z57wjW/AMsvk\n5298A9ZYY/bHvXrBUkvlx5JLfv3jJZbIfy2rtpTTIfgB8AT5+n8CLmzaPgw4kDyIcOVZO6eU/hYR\nOwEXAb8FJgIHpZSa33kgSTXh//4P/vrX/HjrLXjnndkn/okT4f33YebM2fv37Anf/jYsvzwsuyz0\n6ZP/Sm/+6N07FwGLLlrcv03Vq+SCIKX0JPO4XTGl9MtWjqkr9bUkqVp98gm8/jpMmDD75P/UU/mE\n/tFHs/dbcklYZRVYcUVYf33Yccf88Uor5ceKK+a/6ue8Zix1hKLuMlAHqK+vLzpCVfJ9K53v2Wyf\nfQavvQavvjr34+9/n73PCivAaqvBeuvV85OfwHe/O/vxzW96sp8Xf9Y6zwLNVNhRIqIv0NjY2OjA\nJUkV4+OP4YUX4Pnn4aWX8on/rbfy1yLyCf7735/9WHfdvG2xxYrNrdoybtw46urqAOpSSuPaepwd\nAklqwZdfwvjx+eT//PMwdmxu/0P+q/4HP4B+/Waf/NdZxxO/qpsFgSSR77sfMwYeewyeeSZ3AL74\nIt8Ot8EGsMMOsMkmsOmmuf1vm19djQWBpJo0c2Y+6T/6KPzxj7kI+PLLPIjvxz+G+vpcAGywgaP2\nVRssCCTVjHfeySf/Rx+FUaPymIAlloCttoLzz4ef/ATWXtu//lWbLAgkdWl/+xvcfjuMGAEvvphn\nwtt4Yzj00FwAbLJJviwg1ToLAkldzjvvwB13wG235bsCevSAnXaCY46BbbfN9/VLmpsFgaQuYeLE\nXASMGAHPPZev+++4IzQ0wE9/mi8NSGqdBYGkqjVjBjzwAFx+eR4bsMgisP32cNNNsPPOeV5+SW1j\nQSCp6nz4IVx7LVx5Zb48sPHGcP31eV6AXr2KTidVJwsCSVUhpTxB0OWX58sCEfnWwMMOy5MESVow\nFgSSKtrnn+dxAJdfntd5/8538lrvBx6YZwyU1D4sCCRVpGnT4Oqr4ayz4IMP8tiA++/Pz926FZ1O\n6nosCCRVlC+/hBtuyF2Av/8dDjgABg2C1VcvOpnUtS1UdABJgnzHwPDheabAX/8attgiLyt8/fUW\nA1JnsCCQVKiZM/Mgwe9/P3cDNtggrzJ4yy2w1lpFp5NqhwWBpEKkBPfdBxtuCHvtlQcL/ulPcNdd\nsN56RaeTao8FgaRO9+67sOuusMsusMwy8PTT8OCD3j4oFcmCQFKnmTEDLrkE1lkHGhvhzjvh8cdh\n882LTibJgkBSp3j5Zdh0Uxg4EH7xizxgsF8/lxqWKoUFgaQO9dln8Lvf5csB06bBM8/AH/7gFMNS\npXEeAkkd5pFHYMAAmDQJTj89Lz/cvXvRqSS1xA6BpHb38cew7755VsHvfhdefRVOOMFiQKpkdggk\ntasXXoA994RPP4Vhw2D//R0nIFUDOwSS2kVKeQGiH/0IVlghDyLs399iQKoWFgSSFtinn8I++8Bv\nfgOHHgpPPgkrr1x0Kkml8JKBpAXy2muwxx4wcSLcdhv8/OdFJ5JUDjsEksp2yy2w0UZ5OeIXX7QY\nkKqZBYGkkn3xRb40sO++uTvw/PMuRCRVOy8ZSCrJ3/6W7yJ45RW46io4+GAHDkpdgQWBpDYbPx62\n2w569oRnn4W6uqITSWovXjKQ1CZPPQVbbgkrrpgvEVgMSF2LBYGk+br/fth2W+jbF554ApZbruhE\nktqbBYGkeRo+HHbbDXbYAR58EJZaquhEkjqCBYGkVl18MRxwQF6ueMQI6NGj6ESSOooFgaSvSQlO\nPBGOOgqOPx6uuQYWdgiy1KX5v7ikucyYkecYuPpquOACOProohNJ6gwWBJL+7Ysv8mRD99wDQ4fm\nywWSaoMFgSQApk2DnXeGp5+Gu+6CXXYpOpGkzmRBIInp06G+Hp55Bh56CLbaquhEkjqbBYFU41KC\nAQPgvvvg3nstBqRaZUEg1bgTToDrroMbb4Sddio6jaSieNuhVMMuvBDOPTfPN7DffkWnkVQkCwKp\nRg0bBsccA4MGwZFHFp1GUtEsCKQadN99cNBBcMghcMYZRaeRVAksCKQaM2YM/PzneX2CIUMgouhE\nkiqBBYFUQ15+Oc818MMfws03Q7duRSeSVCksCKQa8de/wvbbwxpr5JkIF1206ESSKokFgVQDPvgA\ntt0WevXKEw8tuWTRiSRVGuchkLq46dPzmIHPPoPnn4dlly06kaRKVFaHICIOi4i3I+LziBgbERvN\nZ/8jI+KNiJgaEe9ExEURYcNS6gTHHZenJL79dlhllaLTSKpUJRcEEbEXcCEwGNgQGA88EhG9W9l/\nH+Dspv3XBg4E9gLOLDOzpDa69Va46KI8AdEWWxSdRlIlK6dDMBC4KqU0PKX0BjAAmEo+0bdkM+Dp\nlNJtKaV3UkqPAQ3AxmUlltQmr76a5xrYd184/PCi00iqdCUVBBHRHagDRs3allJKwGPkE39LngXq\nZl1WiIjVgB2BB8oJLGn+/vUv2H13WH11uPpq5xqQNH+lDirsDXQD3m+2/X1grZYOSCk1NF1OeDoi\noun4K1NK55YaVtL8zZwJ/fvDRx/Biy/CYosVnUhSNWivuwwCSC1+IWIrYBD50sILwOrApRExKaU0\nz0lTBw4cSK9evebaVl9fT319fXtklrqkM8+E+++HBx6A73636DSSOlJDQwMNDQ1zbZs8eXJZ3yty\nx7+NO+dLBlOBPVJKI+fYPhTolVLavYVjxgDPpZSOm2PbvuRxCEu08jp9gcbGxkb69u3b5nxSrXvo\nobyE8SmnwMknF51GUhHGjRtHXV0dQF1KaVxbjytpDEFK6SugEdhm1ramywDbkMcKtGQxYGazbTOb\nDvXKptRO/vpX2GefXBCcdFLRaSRVm3IuGVwEDIuIRvIlgIHkk/5QgIgYDkxMKQ1q2v8+YGBEvAw8\nD6wBnAbcm0ppT0hq1dSp0K8f9O4NN94ICzkHqaQSlVwQpJRGNA0SPA1YHngZ2C6l9GHTLisB0+c4\n5HRyR+B0YEXgQ2Ak4N8wUjtIKS9jPGECjB0LSy9ddCJJ1aisQYUppSHAkFa+tnWzz2cVA6eX81qS\n5u2KK/LKhQ0NsN56RaeRVK1sLEpV7M9/hmOOgUMPhb33LjqNpGpmQSBVqenTYf/9YeWV4fzzi04j\nqdq52qFUpc4+G8aNywsXOfmQpAVlh0CqQo2NcNppMGgQbLJJ0WkkdQUWBFKV+fzzfKlg/fWdb0BS\n+/GSgVRlTjoJ3nordwkWWaToNJK6CgsCqYqMHg0XXwwXXADf+17RaSR1JV4ykKrElCnwi1/Aj38M\nRx5ZdBpJXY0dAqlKHHkkfPxx7hI4NbGk9mZBIFWBe++FG26A666DVVctOo2krsi/M6QK98EHcPDB\nsMsu8MtfFp1GUldlQSBVsJRgwID8fPXV4ILhkjqKlwykCnbjjXD33XDXXbD88kWnkdSV2SGQKtT7\n78MRR+RJiHbfveg0kro6CwKpQh1zDHTrlucdkKSO5iUDqQI98QTcdFO+q+Cb3yw6jaRaYIdAqjBf\nfgmHHgqbb54nIpKkzmCHQKowF1wAf/kLjBjhBESSOo+/bqQK8tZbcPrpcNRRsN56RaeRVEssCKQK\nkRIcfjgsuyycfHLRaSTVGi8ZSBXi7rvhwQfz8xJLFJ1GUq2xQyBVgE8/zXMO/PSnsOuuRaeRVIss\nCKQKcMopeSXDyy5zemJJxbAgkAr2yivw3/8Nv/+9KxlKKo4FgVSgmTPz4kVrrglHH110Gkm1zEGF\nUoGuvx6eey7PTLjIIkWnkVTL7BBIBfnoIzjuOOjfH7baqug0kmqdBYFUkN/9Ls89cP75RSeRJC8Z\nSIUYOxZuuAGuvBKWW67oNJJkh0DqdCnlqYn79IFf/aroNJKU2SGQOtntt+eBhI89Bt26FZ1GkjI7\nBFInmjYNjj8+z0i4zTZFp5Gk2ewQSJ3ossvgnXfymgWSVEnsEEid5MMP4Ywz8kREa69ddBpJmpsF\ngdRJTj01Pw8eXGwOSWqJlwykTvDGG/kWw7PPhmWXLTqNJH2dHQKpExx7LKy8Mhx+eNFJJKlldgik\nDjZqFNx/P9x2G/ToUXQaSWqZHQKpA82YkVcx3Gwz2HPPotNIUuvsEEgdaPhwGD8+T0QUUXQaSWqd\nHQKpg3z6KZx4Iuy1F2y6adFpJGneLAikDnLBBfDJJ3DOOUUnkaT5syCQOsB778F558ERR8Cqqxad\nRpLmz4JA6gAnnQSLLw6DBhWdRJLaxkGFUjt76SUYNgz+8Afo1avoNJLUNnYIpHZ2wgmw5ppw8MFF\nJ5GktrNDILWjJ5+ERx6B22+H7t2LTiNJbWeHQGonKeUxA337Qr9+RaeRpNLYIZDayYMPwrPPwsMP\nw0KW2pKqjL+2pHYwc2aehOjHP4Ztty06jSSVzg6B1A5GjMhTFD/9tFMUS6pOZXUIIuKwiHg7Ij6P\niLERsdF89u8VEZdHxN+bjnkjIrYvL7JUWb76Cn7/e9hpJ9h886LTSFJ5Su4QRMRewIXAIcALwEDg\nkYhYM6X0UQv7dwceA/4B9AP+DqwC/GsBcksVY+hQmDAB7rij6CSSVL5yLhkMBK5KKQ0HiIgBwE7A\ngcB5Lex/ELA0sGlKaUbTtnfKeF2p4kybBqeeCnvvDX36FJ1GkspX0iWDpr/264BRs7allBK5A7BZ\nK4ftDDwHDImIf0TE/0TECRHhgEZVvSFD4B//gNNOKzqJJC2YUjsEvYFuwPvNtr8PrNXKMasBWwM3\nATsAawBDmr7PGSW+vlQxpkyBs86CAw+ENdYoOo0kLZj2ussggNTK1xYiFwyHNHUTXoqIFYFjmE9B\nMHDgQHo1mwy+vr6e+vr6BU8sLaCLL4ZPP4WTTy46iaRa1dDQQENDw1zbJk+eXNb3inyObuPO+ZLB\nVGCPlNLIObYPBXqllHZv4ZjRwJcppW3n2LY98ACwaEppegvH9AUaGxsb6du3b9v/NVIn+egjWG21\nvF7BhRcWnUaSZhs3bhx1dXUAdSmlcW09rqTr+Cmlr4BGYJtZ2yIimj5/tpXDngFWb7ZtLWBSS8WA\nVA3OPTdPVXz88UUnkaT2Uc7AvouAQyKif0SsDVwJLAYMBYiI4RFx1hz7XwF8MyIuiYg1ImIn4ATg\nDwsWXSrGe+/lpY2PPhqWXbboNJLUPkoeQ5BSGhERvYHTgOWBl4HtUkofNu2yEjB9jv0nRsS2wMXA\neOC9po9bukVRqninnw6LLw5HHVV0EklqP2UNKkwpDSHfKdDS17ZuYdvzwA/LeS2pkkyYANddB+ec\nA0stVXQaSWo/zgUglWDwYFhuOTj00KKTSFL7cnEjqY1eew0aGuDyy6Fnz6LTSFL7skMgtdFpp8HK\nK8NBBxWdRJLanx0CqQ1efTUvcXzVVbDIIkWnkaT2Z4dAaoNTT4VVVoFf/KLoJJLUMewQSPPxyit5\naeNrr4Xu3YtOI0kdww6BNB+nnJKnKe7fv+gkktRx7BBI8/DSS3D33XDDDXYHJHVtdgikeTjlFFh9\nddhvv6KTSFLHskMgtaKxEUaOhOHDYWH/T5HUxdkhkFoxeDCstRbU1xedRJI6nn/3SC144QV44AG4\n+Wa7A5Jqgx0CqQWDB8M668BeexWdRJI6h3/7SM089xw8/DDceit061Z0GknqHHYIpGZOOQW+9z3Y\nc8+ik0hS57FDIM3hmWfgj3+E22+HhSyXJdUQf+VJcxg8GNZfH/r1KzqJJHUuOwRSkzFjYNQouOsu\nuwOSao+/9qQmgwfDBhvAbrsVnUSSOp8dAgkYPTo/7rkHIopOI0mdzw6BRL6zYMMNYZddik4iScWw\nQ6CaN3o0PPkk3Huv3QFJtcsOgWreKadA376w885FJ5Gk4tghUE174oncHRg50u6ApNpmh0A1K6XZ\n3YGf/rToNJJULDsEqlmjR+e5B+wOSJIdAtUouwOSNDc7BKpJTzxhd0CS5mSHQDVnVnegrs7ugCTN\nYodANeeJJ+Cpp+C+++wOSNIsdghUU+bsDuy0U9FpJKly2CFQTXn8cbsDktQSOwSqGbO6Az/4gd0B\nSWrODoFqxuOPw9NPw/332x2QpObsEKgmzNkd2HHHotNIUuWxQ6CaMGqU3QFJmhc7BOry7A5I0vzZ\nIVCXN2oUPPOM3QFJmhc7BOrSUoLf/x422sjugCTNix0CdWkPPQRjx8LDD9sdkKR5sUOgLislOPlk\n2Hxz2HbbotNIUmWzQ6Aua+RIaGzMYwjsDkjSvNkhUJc0cyYMHgxbbQVbb110GkmqfHYI1CXddReM\nHw9jxhSdRJKqgx0CdTkzZuTuwE9+AltsUXQaSaoOdgjU5YwYAa+9BtdfX3QSSaoedgjUpUyfnmcl\n3Gkn2GSTotNIUvWwQ6Au5eab4c034ZZbik4iSdXFDoG6jK++gtNOg912g7q6otNIUnWxQ6AuY9gw\neOstuPvuopNIUvWxQ6Au4Ysv4PTTYc89Yf31i04jSdWnrIIgIg6LiLcj4vOIGBsRG7XxuL0jYmZE\n3FXO60qtuf56ePfdPKBQklS6kguCiNgLuBAYDGwIjAceiYje8zluFeB8wKli1K6mTYMzz4R99oF1\n1y06jSRVp3I6BAOBq1JKw1NKbwADgKnAga0dEBELATcBJwNvlxNUas3VV8OkSXkhI0lSeUoqCCKi\nO1AHjJq1LaWUgMeAzeZx6GDgg5TSDeWElFozdSqcdRb07w9rrll0GkmqXqXeZdAb6Aa832z7+8Ba\nLR0QEZsDvwT6lJxOmo8hQ+Djj+0OSNKCaq/bDgNIX9sYsQRwI3BwSumfpX7TgQMH0qtXr7m21dfX\nU19fX25OdSGTJ8PZZ8OBB8J3vlN0GknqfA0NDTQ0NMy1bfLkyWV9r8gd/zbunC8ZTAX2SCmNnGP7\nUKBXSmn3Zvv3AcYBM8hFA8y+TDEDWCul9LUxBRHRF2hsbGykb9++bf/XqKaceCJcfDFMmAArrFB0\nGkmqDOPGjaMuz85Wl1Ia19bjShpDkFL6CmgEtpm1LSKi6fNnWzjkdWA9YAPyJYM+wEjg8aaP3y3l\n9aVZJk3KxcARR1gMSFJ7KOeSwUXAsIhoBF4g33WwGDAUICKGAxNTSoNSSl8Cr815cET8izwW8fUF\nCa7advrp0KMHHHdc0UkkqWsouSBIKY1omnPgNGB54GVgu5TSh027rARMb7+I0twmTIBrrsl3Fyy9\ndNFpJKlrKGtQYUppCDCkla9tPZ9jf1nOa0qznHQSfOtb8JvfFJ1EkroOFzdSVWlshNtug2uvhZ49\ni04jSV2HixupqpxwAqy9NhxwQNFJJKlrsUOgqjFqFDz6KNx1FyzsT64ktSs7BKoKKcHxx8Omm8Ju\nuxWdRpK6Hv/OUlW44w548UUYPRoi5ru7JKlEdghU8b76Ks9KuMMOsOWWRaeRpK7JDoEq3vXX57kH\nbr+96CSS1HXZIVBFmzoVTj0V9tkH+rhepiR1GAsCVbRLLoGPPspTFUuSOo4FgSrWJ5/AuefCgAEu\nbyxJHc2CQBXr7LNhxow8VbEkqWNZEKgivf02XHYZHH00LLdc0WkkqeuzIFBFOvZY6N07P0uSOp63\nHarijB4Nd94JN90Eiy9edBpJqg12CFRRZsyAI4/MUxTvs0/RaSSpdtghUEW57joYPx6ef94piiWp\nM9khUMX417/yFMX9+8PGGxedRpJqiwWBKsbpp8Pnn+fbDSVJncuCQBXhz3+GSy+FQYNghRWKTiNJ\ntceCQBXh6KNhpZXgqKOKTiJJtclBhSrcww/DAw/AHXdAjx5Fp5Gk2mSHQIX66isYOBC22gr69Ss6\njSTVLjsEKtSQIfDmm3Drrd5mKElFskOgwnz0EZxyChx8MPTpU3QaSaptFgQqzMknQ0r5dkNJUrG8\nZKBC/M//wFVXwQUXwLLLFp1GkmSHQJ0upbxeweqrw2GHFZ1GkgR2CFSAO+6Axx+H+++HRRYpOo0k\nCewQqJP9859w+OGw++6w005Fp5EkzWJBoE513HF5vYI//KHoJJKkOXnJQJ3mySfhmmvgiitcr0CS\nKo0dAnWKadPgkENg883zsySpstghUKc480x4+224+25YyDJUkiqOv5rV4V59Fc45Jy9tvO66RaeR\nJLXEgkAdasaMPDXxGmvACScUnUaS1BovGahDXXkljB0LTz0Fiy5adBpJUmvsEKjDTJyYuwIDBsCP\nflR0GknSvFgQqEOklKclXmKJPH5AklTZvGSgDnHnnTByZH7u1avoNJKk+bFDoHY3a3ri3XaDfv2K\nTiNJagsLArW744+HqVOdnliSqomXDNSuxoyBq6+GIUNgxRWLTiNJais7BGo3kydD//75joL/+q+i\n00iSSmGHQO0iJfj1r/P4gdGjnZ5YkqqNBYHaxU03QUNDfqy6atFpJEml8u84LbC//hUOPRQOOAD2\n3rvoNJKkclgQaIF89RXssw8svzxcdlnRaSRJ5fKSgRbIKafAuHHwzDOw5JJFp5EklcuCQGUbPRrO\nPhvOOgs23rjoNJKkBeElA5Xlk09gv/1gyy3h2GOLTiNJWlAWBCpZSnDwwXk2whtvhG7dik4kSVpQ\nZRUEEXFYRLwdEZ9HxNiI2Gge+/4qIsZExCdNj0fntb8q37XXwl135eeVVio6jSSpPZRcEETEXsCF\nwGBgQ2A88EhE9G7lkC2BW4CtgE2Bd4E/RsS3ywmsYr3xBhxxBBxyiAsXSVJXUk6HYCBwVUppeErp\nDWAAMBU4sKWdU0r7p5SuTCm9klJ6E/hV0+tuU25oFeOLL6C+HlZZBS66qOg0kqT2VNJdBhHRHagD\nzpq1LaWUIuIxYLM2fpvFge7AJ6W8top3wgnw2mswdiwsvnjRaSRJ7anUDkFvoBvwfrPt7wPfauP3\nOBd4D3isxNdWgW66CS6+GM47DzbcsOg0kqT21l7zEASQ5rtTxPHAz4EtU0pfzm//gQMH0qtXr7m2\n1dfXU19fX25OleH55+FXv4Jf/AJ++9ui00iSZmloaKChoWGubZMnTy7re0VK8z2Pz945XzKYCuyR\nUho5x/ahQK+U0u7zOPYYYBCwTUrppfm8Tl+gsbGxkb59+7Y5n9rfxImw0Uaw2mrw+OOw6KJFJ5Ik\nzcu4ceOoq6sDqEspjWvrcSVdMkgpfQU0MseAwIiIps+fbe24iDgWOBHYbn7FgCrH1Kmw667QvXu+\nzdBiQJK6rnIuGVwEDIuIRuAF8l0HiwFDASJiODAxpTSo6fPfAacB9cA7EbF80/f5NKX02YLFV0dJ\nKV8ieOONvE7B8svP9xBJUhUruSBIKY1omnPgNGB54GXyX/4fNu2yEjB9jkN+Tb6r4I5m3+rUpu+h\nCnT66XD77XDnnbDBBkWnkSR1tLIGFaaUhgBDWvna1s0+/045r6Hi3HknDB6ciwInH5Kk2uBaBprL\nSy9B//6w995w4olFp5EkdRYLAv3bP/6RBxGuuy5cfz1EFJ1IktRZLAgEwLRpsPvuMH063HMP9OxZ\ndCJJUmdqr4mJVMVSgv/6r3y5YMwYWHHFohNJkjqbBUGNSwl+9zsYPhxuvhk23rjoRJKkInjJoMYN\nHgwXXACXXAL77FN0GklSUSwIatiZZ+ZbC887zzUKJKnWWRDUqAsugJNOygXBsccWnUaSVDQLghp0\n2WW5CDjxxFwUSJJkQVBjrr46Xx44+ujcHZAkCSwIasqwYTBgABx2GJx/vhMPSZJmsyCoEbfeCgce\nCAcdBJdeajEgSZqbBUENuOsu2G8/2HdfuOoqWMj/6pKkZjw1dHF33pkXKvrZz/L6BBYDkqSWeHro\nolKCiy+GPffMSxjfeCMs7LyUkqRWWBB0QdOnw+GHw1FH5WmJb7kFuncvOpUkqZL5N2MX8+mnUF8P\nDz2UxwscckjRiSRJ1cCCoAuZNAl++lN48024/37YfvuiE0mSqoUFQRfx6quw444wcyY8/TT06VN0\nIklSNXHh6Xd5AAAJwklEQVQMQRfw2GOw+ebwjW/A2LEWA5Kk0lkQVLkbboAddoAf/hCeegpWWqno\nRJKkamRBUKW++gqOPz7PPnjggXDffbDUUkWnkiRVK8cQVKG33sqzDv7pT3lNgqOPdipiSdKCsSCo\nMjffDL/+NfTunQcPbrpp0YkkSV2BlwyqxJQpsP/+eU2CXXeFl1+2GJAktR87BFVg7FjYZx/46KM8\nBfF++xWdSJLU1dghqGAzZsBZZ8GPfgTLLZe7AhYDkqSOYEFQod59F7bZBk46CU44Id9SuNpqRaeS\nJHVVXjKoMNOnw5VXwu9/D0ssAU88AVtuWXQqSVJXZ4eggowZA3V18Nvfws9+BuPHWwxIkjqHBUEF\neO+9PGhwyy2hZ0944QW45hpYZpmik0mSaoUFQYG++ALOOQfWWgtGjcrTED/7LPzgB0UnkyTVGscQ\nFOTBB+HII/Osg7/9LQweDL16FZ1KklSr7BB0sldfhV12gZ12gpVXzuMELrrIYkCSVCwLgk7y4ouw\n++6w3nrwyitw++152eLvfa/oZJIkWRB0uDFjYLvtYKON4P/9P7juOnjzzXwXgQsSSZIqhQVBB0gJ\nHn4Yttgi3zkwaRI0NMDrr+elihdZpOiEkiTNzYKgHc2cCXffnbsBO+yQ7yK499485fDee0O3bkUn\nlCSpZd5l0A4mTYKhQ+H662HChNwV+OMf4T//08sCkqTqYEFQpunT4aGH4Npr4YEHoHv3PC5g2DD4\n4Q+LTidJUmksCEo0YULuBAwdmjsDffvCpZfmmQaXXrrodJIklceCoA3++U+47748k+Do0XnOgP32\ng4MOgg03LDqdJEkLzoKgFRMn5gGB99yTi4Dp02GrreDGG2GPPfKaA5IkdRUWBE1SgtdeywXAPffk\niYQWXhi23jpfEthlF1hxxaJTSpLUMWq6IPj007yY0KOP5iJgwgRYYol8y+DAgbDjjo4LkCTVhpoq\nCGYVAKNH58ef/pQvBXzrW7DzznDJJbkj0KNH0UklSepcXbogmDIFnn8ennhi7gJg+eXzeID+/fPz\nWms5X4AkqbZ1mYJgyhQYNw4aG2c/3nwzf2255fKJf//94T/+wwJAkqTmqq4gSCnf///663lK4OYn\n/549862A220HgwbBxhvD2mtbAEiSNC8VXRD87//m2/9efz0/3ngjP0+Zkr++2GKwwQazT/51dfnk\nv3BF/6skSao8Fb24Ub9+sOuucOaZuRBYe+184r/nnlwcTJkCzzyTbws84AD4/vdruxhoaGgoOkJV\n8n0rne9ZeXzfSud71nnKKggi4rCIeDsiPo+IsRGx0Xz23zMiXm/af3xE7NCW17niCnjvPZg8OQ8O\nHDoUjjsuFwlrreXqgc35P055fN9K53tWHt+30vmedZ6SC4KI2Au4EBgMbAiMBx6JiN6t7L8ZcAtw\nDbABcA9wT0SsO7/X2nhjWGEFr/9LktTRyukQDASuSikNTym9AQwApgIHtrL/EcBDKaWLUkp/TikN\nBsYBvykrsSRJanclFQQR0R2oA0bN2pZSSsBjwGatHLZZ09fn9Mg89pckSZ2s1CF4vYFuwPvNtr8P\nrNXKMd9qZf9vzeN1egC8/vrrJcarbZMnT2bcuHFFx6g6vm+l8z0rj+9b6XzPSjfHubOkeXfba0x+\nAKkd918VYL/99luASLWprq6u6AhVyfetdL5n5fF9K53vWdlWBZ5t686lFgQfATOA5ZttX46vdwFm\n+UeJ+0O+pLAv8DdgWokZJUmqZT3IxcAjpRwUeQhACQdEjAWeTykd0fR5AO8Al6aUzm9h/1uBniml\nXefY9gwwPqV0aEkvLkmSOkQ5lwwuAoZFRCPwAvmug8WAoQARMRyYmFIa1LT/JcCTEXEU8ABQTx6Y\nePCCRZckSe2l5IIgpTSiac6B08iXAl4Gtkspfdi0y0rA9Dn2fy4i6oEzmx5/AXZNKb22oOElSVL7\nKPmSgSRJ6noqei0DSZLUOSwIJElS5RcEEXFvRPxv08JIf4+I4RHx7aJzVaqIWCUiro2ItyJiakT8\nJSJOaZplUvMQEYMi4pmI+CwiPik6T6UqdXGzWhcRW0TEyIh4LyJmRsQuRWeqdBFxQkS8EBFTIuL9\niLg7ItYsOlcli4gBTYsHTm56PBsR25fyPSq+IAAeB/YE1gT6Ad8Fbi80UWVbmzzx08HAuuS7QAaQ\nB3Rq3roDI4Arig5SqUpd3EwALE4efH0YpU3gVsu2AC4DNgH+k/z/5h8jomehqSrbu8Bx5Lv46sjn\nznsjYp22foOqG1QYETsDdwOLppRmFJ2nGkTEMcCAlNLqRWepBhFxAHBxSmmZorNUmlbmIXmXPA/J\neYWGqwIRMRPYLaU0sugs1aSp4PwA+HFK6emi81SLiPgYOCaldENb9q+GDsG/RcQy5BkMn7EYKMnS\ngC1wLZAyFzeT2sPS5O6Kv8faICIWioi9yXMEPdfW46qiIIiIcyLiU/LUySsDuxUcqWpExOrkpaav\nLDqLqt68Fjeb12JlUtmaulD/DTzt/DXzFhHfj4j/A74AhgC7p5TeaOvxhRQEEXF20+Ca1h4zmg0g\nOQ/YAPgJeS2FG4vIXaQy3jMiYkXgIeC2lNL1xSQvVjnvm0pW6uJmUimGkMdD7V10kCrwBtCHPPbi\nCmB4RKzd1oMLGUMQEd8Evjmf3d5KKU1vvrHpJPcusFlK6fmOyFeJSn3PImIF4Ang2ZTSLzs6X6Uq\n52fNMQQta7pkMBXYY85r4BExFOiVUtq9qGzVwjEEpYmIPwA7A1uklN4pOk+1iYhHgQkppV+3Zf/2\nWv64JCmlj4GPyzy8W9Pzou0UpyqU8p41FU2PA38CDuzIXJVuAX/WNIeU0ldNa5hsA4yEf7dztwEu\nLTKbup6mYmBXYEuLgbItRAnnykIKgrZqur95Y+Bp4J/A6uQ1FP5CCQMlaknTHA2jyUtH/w5YLv/O\nhpTSvJacrnkRsTKwDLAK0C0i+jR9aUJK6bPiklWUeS5upq+LiMXJv7uiadNqTT9bn6SU3i0uWeWK\niCHkhfB2AT6LiOWbvjQ5pTStuGSVKyLOJF8ifhdYkjwAf0tg2zZ/j0q+7TAivk9eLXF98r28k8j/\n4DNTSpOKzFapmtrdzccLBHlAeLcWDlGTiLgB6N/Cl/4jpTSms/NUqog4lFxszlrc7PCU0ovFpqpc\nEbEl+fJd81+2w1JKNd3Ba03TpZWWTk6/TCkN7+w81SAirgW2Br4NTAZeAc5JKT3e5u9RyQWBJEnq\nHFVx26EkSepYFgSSJMmCQJIkWRBIkiQsCCRJEhYEkiQJCwJJkoQFgSRJwoJAkiRhQSBJkrAgkCRJ\nwP8HzmYp/YovtV8AAAAASUVORK5CYII=\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "linear_input_unit = TransferMechanism(function = Linear(slope = 2, intercept = 2))\n",
- "logistic_output_unit = TransferMechanism(function = Logistic())\n",
- "\n",
- "mapping_matrix = np.asarray([[1]])\n",
- "unit_mapping_projection = MappingProjection(sender = linear_input_unit, receiver = logistic_output_unit, matrix = mapping_matrix)\n",
- "mini_connected_network = process(pathway = [linear_input_unit, unit_mapping_projection, logistic_output_unit])\n",
- "\n",
- "# Iterate and plot\n",
- "xVals = np.linspace(-3, 3, num=51)\n",
- "yVals = np.zeros((51,))\n",
- "for i in range(xVals.shape[0]):\n",
- " yVals[i] = mini_connected_network.execute([xVals[i]])[0]\n",
- " # Progress bar\n",
- " print(\"-\", end=\"\")\n",
- "plt.plot(xVals, yVals)\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This time we specified our mapping matrix (which is a 2-D numpy array) then explicitly initialized a *[MappingProjection](https://princetonuniversity.github.io/PsyNeuLink/MappingProjection.html)* with that matrix as well as its input and output mechanisms. Note: because we specified the input and output mechanisms in the projection itself, we didn't need to include it in the process pathway as it will infer its position from those parameters. Ultimately, however, this does the exact same thing as our keyword method above which is far less verbose for this common use case."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Systems\n",
- "\n",
- "The highest level at which models are considered in PsyNeuLink is that of the *[System](https://princetonuniversity.github.io/PsyNeuLink/System.html)*. A system is composed of one or more processes which can then run in unison. This allows system graphs to be more complex than the strictly linear ones of processes. Our first system will consist of two input nodes that converge on a single output mechanism. We will be modelling competition between color naming and word reading in the stroop task."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "colors = TransferMechanism(default_input_value=[0,0], function=Linear, name=\"Colors\")\n",
- "words = TransferMechanism(default_input_value=[0,0], function=Linear(slope = 1.5), name=\"Words\")\n",
- "response = TransferMechanism(default_input_value=[0,0], function=Logistic, name=\"Response\")\n",
- "\n",
- "color_naming_process = process(pathway = [colors, IDENTITY_MATRIX, response], name = \"Color Naming\")\n",
- "word_reading_process = process(pathway = [words, IDENTITY_MATRIX, response], name = \"Word Reading\")\n",
- "\n",
- "mini_stroop = system(processes=[color_naming_process, word_reading_process], name='Stroop Model')\n",
- "\n",
- "# Note: Once again, make sure you do not run this cell multiple times. This would create multiple\n",
- "# processes and systems that share the same variable name in the PsyNeuLink registry causing\n",
- "# unexpected behavior."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The order of processes in the system initialization is important here as it is the order we will feed inputs to the system."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {
- "collapsed": false
- },
- "outputs": [
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -2.32\n\n'TransferMechanism-4' executed:\n- input: -2.32\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0895\n-\n'TransferMechanism-3' executed:\n- input: -2.04\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -2.08\n"
+ ]
+ },
{
- "data": {
- "text/plain": [
- "[array([ 0.73105858, 0.81757448]),\n",
- " array(0.7743165274118242),\n",
- " array(0.0018712501328105086)]"
- ]
- },
- "execution_count": 12,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "mini_stroop.execute([[1, 0], [0, 1]])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {
- "collapsed": false
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-4' executed:\n- input: -2.08\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.111\n-\n'TransferMechanism-3' executed:\n- input: -1.92\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -1.84\n\n'TransferMechanism-4' executed:\n- input: -1.84\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.137\n-\n'TransferMechanism-3' executed:\n- input: -1.8\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -1.6\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-4' executed:\n- input: -1.6\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.168\n-\n'TransferMechanism-3' executed:\n- input: -1.68\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -1.36\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-4' executed:\n- input: -1.36\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.204\n-\n'TransferMechanism-3' executed:\n- input: -1.56\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -1.12\n\n'TransferMechanism-4' executed:\n- input: -1.12\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.246\n-\n'TransferMechanism-3' executed:\n- input: -1.44\n- params:\n\tfunction: Linear\n\t\tintercept: 2"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -0.88\n\n'TransferMechanism-4' executed:\n- input: -0.88\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.293\n-\n'TransferMechanism-3' executed:\n- input: -1.32\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -0.64\n\n'TransferMechanism-4' executed:\n- input: -0.64\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.345\n-\n'TransferMechanism-3' executed:\n- input: -1.2\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -0.4\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-4' executed:\n- input: -0.4\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.401\n-\n'TransferMechanism-3' executed:\n- input: -1.08\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -0.16\n\n'TransferMechanism-4' executed:\n- input: -0.16\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.46\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-3' executed:\n- input: -0.96\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.08\n\n'TransferMechanism-4' executed:\n- input: 0.08\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.52\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-3' executed:\n- input: -0.84\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.32\n\n'TransferMechanism-4' executed:\n- input: 0.32\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.579\n-\n'TransferMechanism-3' executed:\n- input: -0.72\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.56\n\n'TransferMechanism-4' executed:\n- input: 0.56\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.636\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-3' executed:\n- input: -0.6\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.8\n\n'TransferMechanism-4' executed:\n- input: 0.8\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n- output: 0.69\n-\n'TransferMechanism-3' executed:\n- input: -0.48\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 1.04\n\n'TransferMechanism-4' executed:\n- input: 1.04\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.739\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-3' executed:\n- input: -0.36\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 1.28\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-4' executed:\n- input: 1.28\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.782\n-\n'TransferMechanism-3' executed:\n- input: -0.24\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 1.52\n\n'TransferMechanism-4' executed:\n- input: 1.52\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.821\n-\n'TransferMechanism-3' executed:\n- input: -0.12\n- params:\n\tfunction: Linear"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 1.76\n\n'TransferMechanism-4' executed:\n- input: 1.76\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.853\n-\n'TransferMechanism-3' executed:\n- input: 0.0\n- params:\n\tfunction: Linear"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 2.0\n\n'TransferMechanism-4' executed:\n- input: 2.0\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.881\n-\n'TransferMechanism-3' executed:\n- input: 0.12\n- params:\n\tfunction: Linear"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 2.24\n\n'TransferMechanism-4' executed:\n- input: 2.24\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.904\n-\n'TransferMechanism-3' executed:\n- input: 0.24\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 2.48\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-4' executed:\n- input: 2.48\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.923\n-\n'TransferMechanism-3' executed:\n- input: 0.36\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 2.72\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-4' executed:\n- input: 2.72\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.938\n-\n'TransferMechanism-3' executed:\n- input: 0.48\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 2.96\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-4' executed:\n- input: 2.96\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.951\n-\n'TransferMechanism-3' executed:\n- input: 0.6\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 3.2\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-4' executed:\n- input: 3.2\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.961\n-\n'TransferMechanism-3' executed:\n- input: 0.72\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 3.44\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-4' executed:\n- input: 3.44\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.969\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-3' executed:\n- input: 0.84\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 3.68\n\n'TransferMechanism-4' executed:\n- input: 3.68\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.975\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-3' executed:\n- input: 0.96\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 3.92\n\n'TransferMechanism-4' executed:\n- input: 3.92\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.981\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-3' executed:\n- input: 1.08\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 4.16\n\n'TransferMechanism-4' executed:\n- input: 4.16\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.985\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "-\n'TransferMechanism-3' executed:\n- input: 1.2\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 4.4\n\n'TransferMechanism-4' executed:\n- input: 4.4\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "- output: 0.988\n-\n'TransferMechanism-3' executed:\n- input: 1.32\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 4.64\n\n'TransferMechanism-4' executed:\n- input: 4.64\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.99\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "-\n'TransferMechanism-3' executed:\n- input: 1.44\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 4.88\n\n'TransferMechanism-4' executed:\n- input: 4.88\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.992\n-\n'TransferMechanism-3' executed:\n- input: 1.56\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 5.12\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-4' executed:\n- input: 5.12\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.994\n-\n'TransferMechanism-3' executed:\n- input: 1.68\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 5.36"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n\n'TransferMechanism-4' executed:\n- input: 5.36\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.995\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-3' executed:\n- input: 1.8\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 5.6\n\n'TransferMechanism-4' executed:\n- input: 5.6\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.996\n-\n'TransferMechanism-3' executed:\n- input: 1.92\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 5.84\n\n'TransferMechanism-4' executed:\n- input: 5.84\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n- output: 0.997\n-\n'TransferMechanism-3' executed:\n- input: 2.04\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 6.08\n\n'TransferMechanism-4' executed:\n- input: 6.08\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.998\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-3' executed:\n- input: 2.16\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 6.32\n\n'TransferMechanism-4' executed:\n- input: 6.32\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.998\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "-\n'TransferMechanism-3' executed:\n- input: 2.28\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 6.56\n\n'TransferMechanism-4' executed:\n- input: 6.56\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.999\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-3' executed:\n- input: 2.4\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 6.8\n\n'TransferMechanism-4' executed:\n- input: 6.8\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.999\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-3' executed:\n- input: 2.52\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 7.04\n\n'TransferMechanism-4' executed:\n- input: 7.04\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.999\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-3' executed:\n- input: 2.64\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 7.28\n\n'TransferMechanism-4' executed:\n- input: 7.28\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.999\n-\n'TransferMechanism-3' executed:\n- input: 2.76\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 7.52\n\n'TransferMechanism-4' executed:\n- input: 7.52\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.999\n-\n'TransferMechanism-3' executed:\n- input: 2.88\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 7.76\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-4' executed:\n- input: 7.76\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 1.0\n-\n'TransferMechanism-3' executed:\n- input: 3.0\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 8.0\n\n'TransferMechanism-4' executed:\n- input: 8.0\n- params:\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 1.0\n-"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "linear_input_unit = TransferMechanism(function=Linear(slope=2, intercept=2))\n",
+ "logistic_output_unit = TransferMechanism(function=Logistic())\n",
+ "mini_connected_network = process(\n",
+ " pathway=[linear_input_unit, IDENTITY_MATRIX, logistic_output_unit])\n",
+ "\n",
+ "# Iterate and plot\n",
+ "xVals = np.linspace(-3, 3, num=51)\n",
+ "yVals = np.zeros((51,))\n",
+ "for i in range(xVals.shape[0]):\n",
+ " yVals[i] = mini_connected_network.execute([xVals[i]])[0]\n",
+ " # Progress bar\n",
+ " print(\"-\", end=\"\")\n",
+ "plt.plot(xVals, yVals)\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "IDENTITY_MATRIX is a keyword that provides a projection from the unit preceding it to the unit following that creates a one-to-one output to input projection between the two. Other useful projection keywords are...\n",
+ "\n",
+ "Now let's make our projection definition a bit more explicit."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 29,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-7' executed:\n- input: -3.0\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -4.0\n\n'TransferMechanism-8' executed:\n- input: -4.0\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.018\n-\n'TransferMechanism-7' executed:\n- input: -2.88\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -3.76\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-8' executed:\n- input: -3.76\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0228\n-\n'TransferMechanism-7' executed:\n- input: -2.76\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -3.52\n\n'TransferMechanism-8' executed:\n- input: -3.52\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0287\n-\n'TransferMechanism-7' executed:\n- input: -2.64\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\ttime_scale: TimeScale.TRIAL\n- output: -3.28\n\n'TransferMechanism-8' executed:\n- input: -3.28\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0363\n-\n'TransferMechanism-7' executed:\n- input: -2.52\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -3.04\n\n'TransferMechanism-8' executed:\n- input: -3.04\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0457\n-\n'TransferMechanism-7' executed:\n- input: -2.4\n- params:\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -2.8\n\n'TransferMechanism-8' executed:\n- input: -2.8\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0573\n-\n'TransferMechanism-7' executed:\n- input: -2.28\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -2.56\n\n'TransferMechanism-8' executed:\n- input: -2.56\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0718\n-\n'TransferMechanism-7' executed:\n- input: -2.16\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -2.32\n\n'TransferMechanism-8' executed:\n- input: -2.32\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0895\n-\n'TransferMechanism-7' executed:\n- input: -2.04\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -2.08\n\n'TransferMechanism-8' executed:\n- input: -2.08\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.111\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-7' executed:\n- input: -1.92\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -1.84\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-8' executed:\n- input: -1.84\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.137\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-7' executed:\n- input: -1.8\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -1.6\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-8' executed:\n- input: -1.6\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.168\n-\n'TransferMechanism-7' executed:\n- input: -1.68"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -1.36\n\n'TransferMechanism-8' executed:\n- input: -1.36\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.204\n-\n'TransferMechanism-7' executed:\n- input: -1.56\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -1.12\n\n'TransferMechanism-8' executed:\n- input: -1.12\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.246\n-\n'TransferMechanism-7' executed:\n- input: -1.44\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -0.88\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-8' executed:\n- input: -0.88\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.293\n-\n'TransferMechanism-7' executed:\n- input: -1.32\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -0.64\n\n'TransferMechanism-8' executed:\n- input: -0.64\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.345\n-\n'TransferMechanism-7' executed:\n- input: -1.2\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -0.4\n\n'TransferMechanism-8' executed:\n- input: -0.4\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.401\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-7' executed:\n- input: -1.08\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: -0.16\n\n'TransferMechanism-8' executed:\n- input: -0.16\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.46\n-\n'TransferMechanism-7' executed:\n- input: -0.96\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.08\n\n'TransferMechanism-8' executed:\n- input: 0.08\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.52\n-\n'TransferMechanism-7' executed:\n- input: -0.84\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.32\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-8' executed:\n- input: 0.32\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.579\n-\n'TransferMechanism-7' executed:\n- input: -0.72\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.56\n\n'TransferMechanism-8' executed:\n- input: 0.56\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.636\n-\n'TransferMechanism-7' executed:\n- input: -0.6\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.8\n\n'TransferMechanism-8' executed:\n- input: 0.8\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.69\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-7' executed:\n- input: -0.48\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 1.04\n\n'TransferMechanism-8' executed:\n- input: 1.04\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.739\n-\n'TransferMechanism-7' executed:\n- input: -0.36\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 1.28\n\n'TransferMechanism-8' executed:\n- input: 1.28\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.782\n-\n'TransferMechanism-7' executed:\n- input: -0.24\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 1.52\n\n'TransferMechanism-8' executed:\n- input: 1.52\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.821\n-\n'TransferMechanism-7' executed:\n- input: -0.12\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 1.76\n\n'TransferMechanism-8' executed:\n- input: 1.76\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.853\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-7' executed:\n- input: 0.0\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 2.0\n\n'TransferMechanism-8' executed:\n- input: 2.0\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.881\n-\n'TransferMechanism-7' executed:\n- input: 0.12\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 2.24\n\n'TransferMechanism-8' executed:\n- input: 2.24\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.904\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-7' executed:\n- input: 0.24\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 2.48\n\n'TransferMechanism-8' executed:\n- input: 2.48\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.923\n-\n'TransferMechanism-7' executed:\n- input: 0.36\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 2.72\n\n'TransferMechanism-8' executed:\n- input: 2.72\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.938\n-\n'TransferMechanism-7' executed:\n- input: 0.48\n- params:\n\tfunction: Linear\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 2.96\n\n'TransferMechanism-8' executed:\n- input: 2.96\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.951\n-\n'TransferMechanism-7' executed:\n- input: 0.6\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 3.2\n\n'TransferMechanism-8' executed:\n- input: 3.2\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.961\n-\n'TransferMechanism-7' executed:\n- input: 0.72\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 3.44\n\n'TransferMechanism-8' executed:\n- input: 3.44\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.969\n-\n'TransferMechanism-7' executed:\n- input: 0.84\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 3.68\n\n'TransferMechanism-8' executed:\n- input: 3.68\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.975\n-\n'TransferMechanism-7' executed:\n- input: 0.96\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 3.92\n\n'TransferMechanism-8' executed:\n- input: 3.92\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.981\n-\n'TransferMechanism-7' executed:\n- input: 1.08\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 4.16\n\n'TransferMechanism-8' executed:\n- input: 4.16\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.985\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-7' executed:\n- input: 1.2\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 4.4\n\n'TransferMechanism-8' executed:\n- input: 4.4\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.988\n-\n'TransferMechanism-7' executed:\n- input: 1.32\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 4.64\n\n'TransferMechanism-8' executed:\n- input: 4.64\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.99\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-7' executed:\n- input: 1.44\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 4.88\n\n'TransferMechanism-8' executed:\n- input: 4.88\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.992\n-\n'TransferMechanism-7' executed:\n- input: 1.56\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 5.12\n\n'TransferMechanism-8' executed:\n- input: 5.12"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.994\n-\n'TransferMechanism-7' executed:\n- input: 1.68\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 5.36\n\n'TransferMechanism-8' executed:\n- input: 5.36\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.995\n-\n'TransferMechanism-7' executed:\n- input: 1.8\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 5.6\n\n'TransferMechanism-8' executed:\n- input: 5.6\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.996\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-7' executed:\n- input: 1.92\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 5.84\n\n'TransferMechanism-8' executed:\n- input: 5.84\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.997\n-\n'TransferMechanism-7' executed:\n- input: 2.04\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 6.08\n\n'TransferMechanism-8' executed:\n- input: 6.08\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.998\n-"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n'TransferMechanism-7' executed:\n- input: 2.16\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 6.32\n\n'TransferMechanism-8' executed:\n- input: 6.32\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.998\n-\n'TransferMechanism-7' executed:\n- input: 2.28\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 6.56\n\n'TransferMechanism-8' executed:\n- input: 6.56\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.999\n-\n'TransferMechanism-7' executed:\n- input: 2.4\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 6.8\n\n'TransferMechanism-8' executed:\n- input: 6.8\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.999\n-\n'TransferMechanism-7' executed:\n- input: 2.52\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 7.04\n\n'TransferMechanism-8' executed:\n- input: 7.04\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.999\n-\n'TransferMechanism-7' executed:\n- input: 2.64\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 7.28\n\n'TransferMechanism-8' executed:\n- input: 7.28"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.999\n-\n'TransferMechanism-7' executed:\n- input: 2.76\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 7.52\n\n'TransferMechanism-8' executed:\n- input: 7.52\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.999\n-\n'TransferMechanism-7' executed:\n- input: 2.88\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 7.76\n\n'TransferMechanism-8' executed:\n- input: 7.76\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 1.0\n-\n'TransferMechanism-7' executed:\n- input: 3.0\n- params:\n\tfunction: Linear\n\t\tintercept: 2\n\t\tslope: 2\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 8.0\n\n'TransferMechanism-8' executed:\n- input: 8.0\n- params:\n\tfunction: Logistic\n\t\tbias: 0.0\n\t\tgain: 1.0\n\tinitial_value: 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 1.0\n-"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXcAAAD8CAYAAACMwORRAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAH2ZJREFUeJzt3Xl8VPW9//HXJxshJIQlAZGETcKmoEJcKm4VsKCtdrOV\nahe1Wntrq9X21lp/6LXto7X91d622lZ78bpVLda20oqCtmi1FQQUhYQtbAnBQFiyQpbJfO4fCRgR\nyRAmOTOT9/PxyGPmnPmGeR+SeXM4c+Z8zd0REZHEkhR0ABERiT6Vu4hIAlK5i4gkIJW7iEgCUrmL\niCQglbuISAJSuYuIJCCVu4hIAlK5i4gkoJSgnjgnJ8dHjBgR1NOLiMSlFStW7HL33I7GBVbuI0aM\nYPny5UE9vYhIXDKzrZGM02EZEZEEpHIXEUlAKncRkQSkchcRSUAqdxGRBNRhuZvZg2a208xWf8Dj\nZma/NLMSM3vbzCZHP6aIiByNSPbcHwJmHuHxWUBB29d1wG+OPZaIiByLDs9zd/d/mtmIIwy5FHjE\nW+frW2Jm/cxsiLu/E6WMItIDhcNOczhMqMUJtbTeb25pXW4JO6Hwgdvwe5Zbwk74wLK33g87reu9\n9asl7LjTttx66+3uhx1wx9tyOBB2cG/9PufA9797H9o/zsFxHLzPgUFMGz+Yk/P7denfXzQ+xDQU\nKGu3vK1t3fvK3cyuo3XvnmHDhkXhqUWku4XDTl1TiLqGEPWNIeravuobQ9Q2hNjf3MK+ptavhuYW\n9jWF2NfUQmNzmMZQC42hMA3NrbcH1jW3OI2h1vJuarsNhRN3fudBfdPjotwj5u4PAA8AFBYWJu5P\nTiSO1DWG2FnTwO76JnbXNbbdtt7fs6+Zqn1N1Oxvpmp/M9X7m6nZ30ykvZuemkRGWgq9U5NJT02i\nV8q7t336pNArpfV+anISaSlJ9EpJIjXZSE1OOrguJclISW5dn5LUdptsJCe1PpacZKQkGUltt8n2\n7v2ktuXkJMMMktuWzYyktuUka30syd69bwZG65gDYw3DksA4ZJ21bqu1Wz4wxtrW07bcnaJR7uVA\nfrvlvLZ1IhKwlrBTUdNA6e59lO6pZ9ve/VRUN1BR09B6W91AbWPosN/bNz2FAX3S6JfR+jV8YB+y\ne6fSLyOVvumpZKWn0KdXCpnpKWT2everd1oyGWnJpKckk5TUvYUm74pGuc8HbjCzJ4EzgGodbxfp\nXnWNITbsqGX9jlrW76hjY2Udpbv3sW3vfppawgfHJRkMykpncHY6J+RmMnV0DsdlpzO4by9yMnsx\noE8aOZm96J+RRlqKzpSOZx2Wu5k9AZwP5JjZNuAOIBXA3X8LLAAuAkqAfcBVXRVWRGBXXSMrS6t4\na1sVRdtrWFdRS3nV/oOPp6cmMSonk7HHZTHjxMEMG5DB8AF9GD4wgyHZ6aQkq7R7gkjOlpndweMO\nfC1qiUTkoJaws6q8muVb9vBmWRUrS6sOFnlykjE6N5Mpw/sz+/R8xgzOYuxxWeT1zyBZh0N6vMAu\n+Ssi7+fubNm9j1dLdvHqhkpe27ibmobWY+JD+/XmlPx+fOmsEZwyrB8nHZ9N77TkgBNLrFK5iwQs\n1BJm6eY9LFj1Di+tqzy4Zz60X29mnTSEswtyOGPUAAZlpQecVOKJyl0kAC1hZ+mm3Ty76h2eX13B\n7vomeqcmc05BDtefN4qzC3IZMTCj20+fk8ShchfpRusqanl86VaeXfUOu+paC33a+EFcPHEI548d\npMMsEjUqd5Eu1hQKs6i4gkde28rrm/eQlpLEjPGDuXjSED6sQpcuonIX6SLvVO/niaWlPLGsjMra\nRoYNyOC2i8Zx2ZR8+vdJCzqeJDiVu0iUba/az72LS5i3rIwWd6aNG8SVZw7n3IJcfWJTuo3KXSRK\ndtY08OuXNvL40lIcZ/bpw7ju3FHkD8gIOpr0QCp3kWO0u66R3768kUde20oo7Fw2JY8bLhhNXn+V\nugRH5S7SSS1h5+F/b+Fni9axv7mFj586lBunFTB8YJ+go4mo3EU6Y3V5Nd/90ypWlVdz3phc/t9H\nJzB6UGbQsUQOUrmLHIX6xhD3vLCe//3XZgb06cW9nzuViycO0YeNJOao3EUi9GLxDuY8s5rt1Q1c\nccYw/nPmOLJ7pwYdS+SwVO4iHWhobuEHzxbz2JJSxgzO5OnPfYgpwwcEHUvkiFTuIkdQunsf//H4\nClaX1/CVc0dxy4VjNYmFxAWVu8gHWFhUwbeeegsDfveFQmZMGBx0JJGIqdxFDtHcEuYnz6/ld69s\nZlJeNvd9brI+iCRxR+Uu0k5lbSPXP7aCFVv38oUPDed7F4+nV4ou7CXxR+Uu0mbr7no+P/d1Kmsb\n+dXsU/nYyccHHUmk01TuIkDR9mq++OAyQuEwj197BqcO6x90JJFjonKXHm/Jpt1c+/BystJTePK6\nDzF6UFbQkUSOmcpderSFRRV8/Yk3GTYgg0euPp3j+/UOOpJIVKjcpcd68vVSbvvzKk7O78eDXzxN\nE2hIQlG5S4/0yGtbmPNMEeeNyeU3V04mI00vBUks+o2WHueZleXMeaaIGRMG8+srJpOarE+cSuLR\nb7X0KIvX7uSWeW9x5qgB/Gr2qSp2SVj6zZYeY9mWPVz/2ArGD+nL775QSHqqPpwkiUvlLj1C8fYa\nrn5oGUP79+ahq04jK12X6pXEpnKXhLdlVz1fePB1Mnul8Og1ZzAws1fQkUS6nMpdEtqOmgaunLuU\nsDuPXnMGQ3Ueu/QQKndJWI2hFr7y6Ar21Dfx0FWnaY5T6VEiKnczm2lm68ysxMxuPczjw8xssZm9\naWZvm9lF0Y8qcnTunF/EyrIq7vnMyUzK6xd0HJFu1WG5m1kycB8wC5gAzDazCYcMux2Y5+6nApcD\nv452UJGj8fjSUp54vYz/OP8EZp40JOg4It0ukj3304ESd9/k7k3Ak8Clh4xxoG/b/Wxge/Qiihyd\nN0r3csf81Zw7JpdbLhwbdByRQERS7kOBsnbL29rWtXcncKWZbQMWAF8/3B9kZteZ2XIzW15ZWdmJ\nuCJHtrO2ga8+toLjstP55eWnkJxkQUcSCUS03lCdDTzk7nnARcCjZva+P9vdH3D3QncvzM3NjdJT\ni7RqCoX52u/foHp/M/dfWUi/DF0ITHquSMq9HMhvt5zXtq69a4B5AO7+GpAO5EQjoEikfvhsMcu2\n7OXuT01iwvF9O/4GkQQWSbkvAwrMbKSZpdH6hun8Q8aUAtMAzGw8reWu4y7Sbf7yZjkPv7aVa84e\nyaWnHHrUUKTn6bDc3T0E3AAsBNbQelZMkZndZWaXtA27BbjWzN4CngC+5O7eVaFF2tu2dx+3/2U1\np43oz3dnjQs6jkhMiOiSv+6+gNY3Stuvm9PufjEwNbrRRDoWDju3zHsLd+eez5xCiq7yKALoE6oS\n5+a+upmlm/dwxyUnkj8gI+g4IjFD5S5xa11FLT9duI4ZEwZz2ZS8oOOIxBSVu8SlxlALN/1hJX17\np/CjT07ETOezi7SnafYkLv33ixtY804N//OFQnJ0CV+R99Geu8SdZVv2cP/LG7n8tHymTxgcdByR\nmKRyl7hS1xji5nkrGdq/N7d/9NDr14nIATosI3HlRwvWUL53P/O+8iEye+nXV+SDaM9d4saKrXv5\n/dJSrp46ksIRA4KOIxLTVO4SF5pbwnzvz6sYkp3ON2eMCTqOSMzT/2slLjz0ry2srajl/s9PoY8O\nx4h0SHvuEvPKq/ZzzwvrmT5+EBfq7BiRiKjcJebdOb+o9faSE/VhJZEIqdwlpi0qquCF4h3cNL2A\nvP66doxIpFTuErPqG0PcOb+IccdlcfXZI4OOIxJXVO4Ss37x9w1sr27gh584iVRdylfkqOgVIzFp\nzTs1zH11M7NPz2fKcJ3TLnK0VO4Sc9ydOc+spl/vVL4zUzMriXSGyl1izoJVFSzbspdvf2Qs/TLS\ngo4jEpdU7hJTGppb+PHzaxh3XBaXFeYHHUckbqncJaY89O8tlO3Zz+0XTyA5See0i3SWyl1ixq66\nRu79RwnTxg3i7IKcoOOIxDWVu8SMn7+wnobmFm67eHzQUUTinspdYsK6ilqeeL2UK88czgm5mUHH\nEYl7KncJnLvzg2eLyUpP5cZpBUHHEUkIKncJ3EvrK3llwy6+Ma2A/n106qNINKjcJVDNLWF++Owa\nRub04fNnDg86jkjCULlLoJ54vZSSnXV8d9Y40lL06ygSLXo1SWDqGkP84sUNnDlqADM0CYdIVGm+\nMgnM3Fc2s7u+ibmzxmsSDpEo0567BGJPfRO/e2UTHzlxMKfk9ws6jkjCUblLIH69uIR9TSG+deHY\noKOIJKSIyt3MZprZOjMrMbNbP2DMZ8ys2MyKzOzx6MaURLK9aj+PLNnKJyfnUTA4K+g4Igmpw2Pu\nZpYM3AfMALYBy8xsvrsXtxtTAHwXmOrue81sUFcFlvj3ixc3gMNN0/WBJZGuEsme++lAibtvcvcm\n4Eng0kPGXAvc5+57Adx9Z3RjSqIo2VnHUyvKuOLMYZrwWqQLRVLuQ4Gydsvb2ta1NwYYY2b/MrMl\nZjYzWgElsdzzwjp6pybztQ+PDjqKSEKL1qmQKUABcD6QB/zTzCa6e1X7QWZ2HXAdwLBhw6L01BIv\n3t5WxYJVFXxjWgE5mb2CjiOS0CLZcy8H2k+Jk9e2rr1twHx3b3b3zcB6Wsv+Pdz9AXcvdPfC3Nzc\nzmaWOPXThevon5HKteeMDDqKSMKLpNyXAQVmNtLM0oDLgfmHjPkLrXvtmFkOrYdpNkUxp8S5f2/c\nxSsbdvG1D48mKz016DgiCa/Dcnf3EHADsBBYA8xz9yIzu8vMLmkbthDYbWbFwGLg2+6+u6tCS3xx\nd37y/DqGZKdzpS4OJtItIjrm7u4LgAWHrJvT7r4DN7d9ibzH4nU7WVlWxY8+OZH01OSg44j0CPqE\nqnQpd+eeF9aTP6A3n56SF3QckR5D5S5dalHxDlaX1/CNCwpITdavm0h30atNukw47Pz8hfWMzOnD\nJ0499KMRItKVVO7SZZ5bXcHailpunFZAivbaRbqVXnHSJVrCzn+/uJ7RgzL52MnHBx1HpMdRuUuX\n+Nvb29mws46bpheQnKSJOES6m8pdoi7UEuYXL25g3HFZXHTSkKDjiPRIKneJumdWbmfTrnpumj6G\nJO21iwRC5S5R1dwS5hd/38CJx/flIydq0muRoKjcJar+9MY2Svfs4+YZYzTptUiAVO4SNU2hML/8\newkn5/fjgnGajEskSCp3iZqnVpRRXrWfb04v0F67SMBU7hIVjaEW7vtHCZOH9eO8MbpWv0jQVO4S\nFfOWlbG9uoFv6li7SExQucsxa2hu4b7FGykc3p+zR+cEHUdEULlLFPxhWRkVNdprF4klKnc5Jg3N\nLfz6pRJOHzGAs04YGHQcEWmjcpdj8vjSUnbUNHLTDJ0hIxJLVO7SaQ3NLfzm5Y2cOWoAZ52gY+0i\nsUTlLp322JKtVNY28s3pY4KOIiKHULlLp+xrCvHblzdy1gkDOWOUjrWLxBqVu3TKY0u2squuiW/O\n0F67SCxSuctRq28Mcf/Lmzh7dA6njRgQdBwROQyVuxy1h1/bwu76Jr45oyDoKCLyAVTuclRqGpq5\n/+VNfHhsLlOGa69dJFap3OWoPPjqZqr3N3PzjLFBRxGRI1C5S8T21jcx95XNfOTEwUzMyw46jogc\ngcpdIvbAK5uoawrpDBmROKByl4hU1jby0L+28LFJxzPuuL5BxxGRDqjcJSK/fXkjjaEWbpquM2RE\n4oHKXTpUUd3Ao0u28snJeYzKzQw6johEIKJyN7OZZrbOzErM7NYjjPuUmbmZFUYvogTt3sUbCIed\nG6dpr10kXnRY7maWDNwHzAImALPNbMJhxmUBNwJLox1SglO2Zx9/WFbGZ0/LJ39ARtBxRCRCkey5\nnw6UuPsmd28CngQuPcy47wN3Aw1RzCcB+9U/NmBm3HDB6KCjiMhRiKTchwJl7Za3ta07yMwmA/nu\n/mwUs0nANlXW8fQb5VxxxjCGZPcOOo6IHIVjfkPVzJKAe4BbIhh7nZktN7PllZWVx/rU0sX+/6J1\npKck8R/na69dJN5EUu7lQH675by2dQdkAScBL5nZFuBMYP7h3lR19wfcvdDdC3NzczufWrrcm6V7\nWbCqgmvPHUVuVq+g44jIUYqk3JcBBWY20szSgMuB+QcedPdqd89x9xHuPgJYAlzi7su7JLF0OXfn\nx8+tJSczjS+fMyroOCLSCR2Wu7uHgBuAhcAaYJ67F5nZXWZ2SVcHlO730vpKlm7ewzemFZDZKyXo\nOCLSCRG9ct19AbDgkHVzPmDs+cceS4LSEnbufm4twwdmcPlpw4KOIyKdpE+oyns8s7KctRW1fOvC\nsaSl6NdDJF7p1SsHNTS38LNF65k4NJuLJw4JOo6IHAOVuxz02JKtlFft59ZZ40hKsqDjiMgxULkL\n0Dp93r2LSzinIIepo3OCjiMix0jlLgDc//JGqvY1852Z44KOIiJRoHIXKqobmPvqZi495XhOGqrp\n80QSgcpduPv5tYQdbtGk1yIJQ+Xew63Yupc/v1nOteeMZNhAXdJXJFGo3HuwcNi5669FDO7bSxcH\nE0kwKvce7Ok3tvHWtmpunTWOPrrMgEhCUbn3ULUNzdz9/DomD+vHx08Z2vE3iEhc0e5aD3Xv4hJ2\n1TUy94uFmOkDSyKJRnvuPdDmXfU8+OpmLpuSx8n5/YKOIyJdQOXeA/3gb8X0Sknm2zN16qNIolK5\n9zAvrdvJ39fu5OsXjGZQVnrQcUSki6jce5DmljDf/1sxI3P6cNXUkUHHEZEupHLvQea+upmNlfXc\nfvF4XatdJMHpFd5DbNlVz89fWM/ME49j2vjBQccRkS6mcu8B3J3v/mkVaSlJ/NelJwYdR0S6gcq9\nB5i3vIzXNu3mtovGM7iv3kQV6QlU7gluZ00DP3x2DWeMHMBnC/ODjiMi3UTlnuDu/GsRDaEwP/rk\nRE2dJ9KDqNwT2MKiChasquDGaQWMys0MOo6IdCOVe4KqaWhmzjOrGXdcFtedOyroOCLSzXThsAT1\n4+fWUlnbyAOfLyQ1Wf+Gi/Q0etUnoNc27ubxpaVcPXWkLgwm0kOp3BNM1b4mbp63khEDM7j5wjFB\nxxGRgOiwTAJxd259ehW76hp5+qtnkZGmH69IT6U99wTyxOtlPF9UwbcuHMukPB2OEenJVO4JYsOO\nWu76WxHnFORw7Tk6O0akp1O5J4CG5ha+/sSb9ElL4WefOVkfVhIRHXNPBD9+bi1rK2r53y+dpgk4\nRASIcM/dzGaa2TozKzGzWw/z+M1mVmxmb5vZ381sePSjyuH8fc0OHvr3Fq6eOpIPjxsUdBwRiREd\nlruZJQP3AbOACcBsM5twyLA3gUJ3nwT8EfhJtIPK++2saeDbf3ybCUP68p1Zmg9VRN4VyZ776UCJ\nu29y9ybgSeDS9gPcfbG772tbXALkRTemHKqhuYXrH1vB/qYWfjn7VHqlJAcdSURiSCTlPhQoa7e8\nrW3dB7kGeO5wD5jZdWa23MyWV1ZWRp5S3sPdue1Pq3ijtIp7PnMyowfpomAi8l5RPVvGzK4ECoGf\nHu5xd3/A3QvdvTA3NzeaT92j/PblTfzpzXJumTGGWROHBB1HRGJQJGfLlAPtZ3nIa1v3HmY2Hfge\ncJ67N0YnnhxqUVEFP1m4lktOPp4bLhgddBwRiVGR7LkvAwrMbKSZpQGXA/PbDzCzU4H7gUvcfWf0\nYwpA8fYabvrDSibl9eMnn56Emc5nF5HD67Dc3T0E3AAsBNYA89y9yMzuMrNL2ob9FMgEnjKzlWY2\n/wP+OOmkytpGvvzwMrJ7p/K7z08hPVVvoIrIB4voQ0zuvgBYcMi6Oe3uT49yLmmnobmFrzy6nD37\nmvjj9WcxSJNci0gH9AnVGBdqCXPLvLd4o7SK31wxmZOGZgcdSUTigK4tE8Naws4tT73Fs6ve4faL\nx+vMGBGJmMo9RoXDzn/+8W2eWbmd78wcx5d1pUcROQoq9xgUDju3/XkVT7+xjZtnjOGr558QdCQR\niTMq9xjj7syZv5onl5Xx9QtG841pBUFHEpE4pHKPIe7OXX8r5rElpXzlvFHcPENzoIpI5+hsmRjR\nEna+/7fig5fvvXXmOH1ISUQ6TeUeA/Y1hbjxyZW8ULyDa84eye0Xj1exi8gxUbkHbGdtA19+eDmr\ny6u542MTuGrqyKAjiUgCULkHaF1FLVc/tIw99U088PlCpk8YHHQkEUkQKveA/HN9JV/7/Rv0Tkvm\nqes/pE+eikhUqdy7mbvz2JKt3PnXYgoGZfLgl07j+H69g44lIglG5d6N9tQ3cevTb7OoeAcfHpvL\nL2efSlZ6atCxRCQBqdy7yasbdnHzvJVU7Wvm9ovHc/XUkSQl6YwYEekaKvcu1hhq4WeL1vPAPzcx\nelAm/3vVaZx4vI6vi0jXUrl3oZKdtdz45EqKttdw5ZnD+N5FE+idpkk2RKTrqdy7QH1jiHsXlzD3\nlc1kpqfwuy8UMkOnOYpIN1K5R5G788zK7fzouTXsqGnkU5Pz+M6ssQzK0sxJItK9VO5Rsrq8mjvm\nF7Fi614m5WXzmyunMHlY/6BjiUgPpXI/RqW793Hf4hLmrShjQEYaP/nUJD49JU9nwohIoFTunbSu\nopbfvFTCX99+h2QzrjprJDdOLyC7t85bF5HgqdyP0ltlVdy3uIRFxTvISEvm6qkj+PI5oxjcV8fV\nRSR2qNwj0BhqYVHRDp54vZR/b9xNdu9UbpxWwJfOGkH/PmlBxxMReR+V+xGseaeGPywr4y8ry6na\n18zQfr357qxxXHHmcDJ76a9ORGKXGuoQO2saWFhUwVMrtvH2tmrSkpOYceJgPluYz9TROSTrjVIR\niQMqd6BkZx2Liit4oXgHb5ZWATDuuCzmfHQCnzh1qA69iEjc6ZHlXtcYYvmWPby2cTcvFO9g0656\nACblZXPLjDHMOHEwYwdnaao7EYlbPaLc6xpDLNuyh6Wb9rBk025WlVfTEnZSk40zRw3kqqkjmD5h\nMEOydV11EUkMCVfu9Y0h1rxTw6ryalaVV7O6vJqSnXWEHVKTjZPz+vHV807gjFEDmDK8PxlpCfdX\nICISv+W+rynEpsp6NlbWsXFnHRsr61m3o5aNlXW4t47JzerFxKHZzDxpCGeMHMDkYf11VUYR6RHi\nrtyffL2UX/2jhPKq/QfXJRkMH9iHE3L7cPHEIUwcms3EvGx9sEhEeqyIyt3MZgK/AJKB/3H3Hx/y\neC/gEWAKsBv4rLtviW7UVrlZvThtRH8uz81n9KBMThiUyfCBGfRK0R65iMgBHZa7mSUD9wEzgG3A\nMjOb7+7F7YZdA+x199FmdjlwN/DZrgg8bfxgpo3XtdFFRI4kKYIxpwMl7r7J3ZuAJ4FLDxlzKfBw\n2/0/AtNM5xGKiAQmknIfCpS1W97Wtu6wY9w9BFQDA6MRUEREjl4k5R41ZnadmS03s+WVlZXd+dQi\nIj1KJOVeDuS3W85rW3fYMWaWAmTT+sbqe7j7A+5e6O6Fubm5nUssIiIdiqTclwEFZjbSzNKAy4H5\nh4yZD3yx7f6ngX+4HzjbXEREuluHZ8u4e8jMbgAW0noq5IPuXmRmdwHL3X0+MBd41MxKgD20/gMg\nIiIBieg8d3dfACw4ZN2cdvcbgMuiG01ERDqrW99QFRGR7mFBHRo3s0pgaye/PQfYFcU4QdK2xJ5E\n2Q7QtsSqY9mW4e7e4RkpgZX7sTCz5e5eGHSOaNC2xJ5E2Q7QtsSq7tgWHZYREUlAKncRkQQUr+X+\nQNABokjbEnsSZTtA2xKrunxb4vKYu4iIHFm87rmLiMgRxG25m9n3zextM1tpZovM7PigM3WWmf3U\nzNa2bc+fzaxf0Jk6w8wuM7MiMwubWVye1WBmM81snZmVmNmtQefpLDN70Mx2mtnqoLMcCzPLN7PF\nZlbc9rt1Y9CZOsvM0s3sdTN7q21b/qtLny9eD8uYWV93r2m7/w1ggrtfH3CsTjGzC2m9Hk/IzO4G\ncPfvBBzrqJnZeCAM3A98y92XBxzpqLRNTLOedhPTALMPmZgmLpjZuUAd8Ii7nxR0ns4ysyHAEHd/\nw8yygBXAx+P0Z2JAH3evM7NU4FXgRndf0hXPF7d77geKvU0fID7/lQLcfVHbdfABltB65c244+5r\n3H1d0DmOQSQT08QFd/8nrdd5imvu/o67v9F2vxZYw/vnk4gL3qqubTG17avLeituyx3AzH5oZmXA\nFcCcjsbHiauB54IO0UNFMjGNBMTMRgCnAkuDTdJ5ZpZsZiuBncAL7t5l2xLT5W5mL5rZ6sN8XQrg\n7t9z93zg98ANwaY9so62pW3M94AQrdsTkyLZDpFoM7NM4GngpkP+1x5X3L3F3U+h9X/np5tZlx0y\ni+iqkEFx9+kRDv09rVetvKML4xyTjrbFzL4EfBSYFsvXwj+Kn0k8imRiGulmbcennwZ+7+5/CjpP\nNLh7lZktBmYCXfKmd0zvuR+JmRW0W7wUWBtUlmNlZjOB/wQucfd9QefpwSKZmEa6UdubkHOBNe5+\nT9B5joWZ5R44E87MetP6xn2X9VY8ny3zNDCW1rMztgLXu3tc7mW1TXLSi3enJlwSj2f+mNkngF8B\nuUAVsNLdPxJsqqNjZhcB/827E9P8MOBInWJmTwDn03r1wR3AHe4+N9BQnWBmZwOvAKtofa0D3NY2\nx0RcMbNJwMO0/m4lAfPc/a4ue754LXcREflgcXtYRkREPpjKXUQkAancRUQSkMpdRCQBqdxFRBKQ\nyl1EJAGp3EVEEpDKXUQkAf0fgjtDHUYfk3kAAAAASUVORK5CYII=\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "linear_input_unit = TransferMechanism(function=Linear(slope=2, intercept=2))\n",
+ "logistic_output_unit = TransferMechanism(function=Logistic())\n",
+ "\n",
+ "mapping_matrix = np.asarray([[1]])\n",
+ "unit_mapping_projection = MappingProjection(sender=linear_input_unit,\n",
+ " receiver=logistic_output_unit,\n",
+ " matrix=mapping_matrix)\n",
+ "mini_connected_network = process(\n",
+ " pathway=[linear_input_unit, unit_mapping_projection, logistic_output_unit])\n",
+ "\n",
+ "# Iterate and plot\n",
+ "xVals = np.linspace(-3, 3, num=51)\n",
+ "yVals = np.zeros((51,))\n",
+ "for i in range(xVals.shape[0]):\n",
+ " yVals[i] = mini_connected_network.execute([xVals[i]])[0]\n",
+ " # Progress bar\n",
+ " print(\"-\", end=\"\")\n",
+ "plt.plot(xVals, yVals)\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This time we specified our mapping matrix (which is a 2-D numpy array) then explicitly initialized a *[MappingProjection](https://princetonuniversity.github.io/PsyNeuLink/MappingProjection.html)* with that matrix as well as its input and output mechanisms. Note: because we specified the input and output mechanisms in the projection itself, we didn't need to include it in the process pathway as it will infer its position from those parameters. Ultimately, however, this does the exact same thing as our keyword method above which is far less verbose for this common use case."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Systems\n",
+ "\n",
+ "The highest level at which models are considered in PsyNeuLink is that of the *[System](https://princetonuniversity.github.io/PsyNeuLink/System.html)*. A system is composed of one or more processes which can then run in unison. This allows system graphs to be more complex than the strictly linear ones of processes. Our first system will consist of two input nodes that converge on a single output mechanism. We will be modelling competition between color naming and word reading in the stroop task."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "colors = TransferMechanism(default_input_value=[0, 0], function=Linear,\n",
+ " name=\"Colors\")\n",
+ "words = TransferMechanism(default_input_value=[0, 0],\n",
+ " function=Linear(slope=1.5), name=\"Words\")\n",
+ "response = TransferMechanism(default_input_value=[0, 0], function=Logistic,\n",
+ " name=\"Response\")\n",
+ "\n",
+ "color_naming_process = process(pathway=[colors, IDENTITY_MATRIX, response],\n",
+ " name=\"Color Naming\")\n",
+ "word_reading_process = process(pathway=[words, IDENTITY_MATRIX, response],\n",
+ " name=\"Word Reading\")\n",
+ "\n",
+ "# Should pass in scheduler or have system create new scheduler if scheduler=None\n",
+ "mini_stroop = system(processes=[color_naming_process, word_reading_process],\n",
+ " name='Stroop Model')\n",
+ "\n",
+ "# Note: Once again, make sure you do not run this cell multiple times. This would create multiple\n",
+ "# processes and systems that share the same variable name in the PsyNeuLink registry causing\n",
+ "# unexpected behavior."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The order of processes in the system initialization is important here as it is the order we will feed inputs to the system."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[[array([ 0.73105858, 0.81757448])], [array([ 0.73105858, 0.81757448])]]"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "input = {colors: [1, 0], \n",
+ " words: [0, 1]}\n",
+ "mini_stroop.run(input)3"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {
+ "collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
- "[array([ 0.5 , 0.92414182]),\n",
- " array(0.7120709099893783),\n",
- " array(0.04497407086372298)]"
+ "[[array([ 0.73105858, 0.81757448])],\n [array([ 0.73105858, 0.81757448])],\n [array([ 0.5 , 0.92414182])]]"
]
},
- "execution_count": 13,
+ "execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "mini_stroop.execute([[0, 1], [0, 1]])"
+ "input_dict = {colors: [0, 1],\n",
+ " words: [0, 1]}\n",
+ "mini_stroop.run(input_dict)"
]
},
{
@@ -566,34 +1183,41 @@
},
{
"cell_type": "code",
- "execution_count": 14,
+ "execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
- "ink_color = TransferMechanism(default_input_value = [0, 0], function = Linear())\n",
- "word = TransferMechanism(default_input_value = [0, 0], function = Linear())\n",
- "task_demand = TransferMechanism(default_input_value = [0, 0], function = Linear())\n",
+ "ink_color = TransferMechanism(default_input_value=[0, 0], function=Linear())\n",
+ "word = TransferMechanism(default_input_value=[0, 0], function=Linear())\n",
+ "task_demand = TransferMechanism(default_input_value=[0, 0], function=Linear())\n",
"\n",
- "hidden_layer = TransferMechanism(default_input_value = [0, 0, 0, 0], function = Logistic(bias = -4))\n",
+ "hidden_layer = TransferMechanism(default_input_value=[0, 0, 0, 0],\n",
+ " function=Logistic(bias=-4))\n",
"\n",
- "output_layer = TransferMechanism(default_input_value = [0, 0], function = Linear())\n",
+ "output_layer = TransferMechanism(default_input_value=[0, 0], function=Linear())\n",
"\n",
"color_mapping_matrix = np.asarray([[2.2, -2.2, 0, 0], [-2.2, 2.2, 0, 0]])\n",
- "color_projection = MappingProjection(sender = ink_color, receiver = hidden_layer, matrix = color_mapping_matrix)\n",
+ "color_projection = MappingProjection(sender=ink_color, receiver=hidden_layer,\n",
+ " matrix=color_mapping_matrix)\n",
"word_mapping_matrix = np.asarray([[0, 0, 2.6, -2.6], [0, 0, -2.6, 2.6]])\n",
- "word_projection = MappingProjection(sender = word, receiver = hidden_layer, matrix = word_mapping_matrix)\n",
+ "word_projection = MappingProjection(sender=word, receiver=hidden_layer,\n",
+ " matrix=word_mapping_matrix)\n",
"task_mapping_matrix = np.asarray([[4, 4, 0, 0], [0, 0, 4, 4]])\n",
- "task_projection = MappingProjection(sender = task_demand, receiver = hidden_layer, matrix = task_mapping_matrix)\n",
- "output_mapping_matrix = np.asarray([[1.3, -1.3], [-1.3, 1.3], [2.5, -2.5], [-2.5, 2.5]])\n",
- "MappingProjection(sender = hidden_layer, receiver = output_layer, matrix = output_mapping_matrix)\n",
+ "task_projection = MappingProjection(sender=task_demand, receiver=hidden_layer,\n",
+ " matrix=task_mapping_matrix)\n",
+ "output_mapping_matrix = np.asarray(\n",
+ " [[1.3, -1.3], [-1.3, 1.3], [2.5, -2.5], [-2.5, 2.5]])\n",
+ "MappingProjection(sender=hidden_layer, receiver=output_layer,\n",
+ " matrix=output_mapping_matrix)\n",
"\n",
- "color_naming_process = process(pathway = [ink_color, hidden_layer, output_layer])\n",
- "word_reading_process = process(pathway = [word, hidden_layer, output_layer])\n",
- "task_process = process(pathway = [task_demand, hidden_layer, output_layer])\n",
+ "color_naming_process = process(pathway=[ink_color, hidden_layer, output_layer])\n",
+ "word_reading_process = process(pathway=[word, hidden_layer, output_layer])\n",
+ "task_process = process(pathway=[task_demand, hidden_layer, output_layer])\n",
"\n",
- "stroop_model = system(processes = [color_naming_process, word_reading_process, task_process])\n",
+ "stroop_model = system(\n",
+ " processes=[color_naming_process, word_reading_process, task_process])\n",
"\n",
"ink_color.reportOutputPref = True\n",
"word.reportOutputPref = True\n",
@@ -607,7 +1231,7 @@
},
{
"cell_type": "code",
- "execution_count": 15,
+ "execution_count": 17,
"metadata": {
"collapsed": false
},
@@ -616,65 +1240,25 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "\n",
- "'TransferMechanism-7' executed:\n",
- "- input: 1.0, 0.0\n",
- "- params:\n",
- "\tfunction: Linear\n",
- "\t\tintercept: 0.0\n",
- "\t\tslope: 1.0\n",
- "\tinitial_value: None\n",
- "\tnoise: 0.0\n",
- "\ttime_scale: TimeScale.TRIAL\n",
- "- output: 1.0 0.0\n",
- "\n",
- "'TransferMechanism-8' executed:\n",
- "- input: 1.0, 0.0\n",
- "- params:\n",
- "\tfunction: Linear\n",
- "\t\tintercept: 0.0\n",
- "\t\tslope: 1.0\n",
- "\tinitial_value: None\n",
- "\tnoise: 0.0\n",
- "\ttime_scale: TimeScale.TRIAL\n",
- "- output: 1.0 0.0\n",
- "\n",
- "'TransferMechanism-9' executed:\n",
- "- input: 0.0, 1.0\n",
- "- params:\n",
- "\tfunction: Linear\n",
- "\t\tintercept: 0.0\n",
- "\t\tslope: 1.0\n",
- "\tinitial_value: None\n",
- "\tnoise: 0.0\n",
- "\ttime_scale: TimeScale.TRIAL\n",
- "- output: 0.0 1.0\n",
- "\n",
- "'TransferMechanism-10' executed:\n",
- "- input: 2.2, -2.2, 6.6, 1.4\n",
- "- params:\n",
- "\tfunction: Logistic\n",
- "\t\tbias: -4\n",
- "\t\tgain: 1.0\n",
- "\tinitial_value: None\n",
- "\tnoise: 0.0\n",
- "\ttime_scale: TimeScale.TRIAL\n",
- "- output: 0.9979746796109501 0.8581489350995123 0.9999750846110607 0.9955037268390589\n"
+ "\n'TransferMechanism-1' executed:\n- input: 1.0, 0.0\n- params:\n\tfunction: Linear\n\t\tintercept: 0.0\n\t\tslope: 1.0\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 1.0 0.0\n\n'TransferMechanism-3' executed:\n- input: 0.0, 1.0\n- params:\n\tfunction: Linear\n\t\tintercept: 0.0\n\t\tslope: 1.0\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.0 1.0\n\n'TransferMechanism-2' executed:\n- input: 1.0, 0.0\n- params:\n\tfunction: Linear\n\t\tintercept: 0.0\n\t\tslope: 1.0\n\tinitial_value: 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 1.0 0.0\n\n'TransferMechanism-4' executed:\n- input: 2.2, -2.2, 6.6, 1.4\n- params:\n\tfunction: Logistic\n\t\tbias: -4\n\t\tgain: 1.0\n\tinitial_value: 0 0 0 0\n\tnoise: 0.0\n\ttime_scale: TimeScale.TRIAL\n- output: 0.998 0.858 1.0 0.996\n"
]
},
{
"data": {
"text/plain": [
- "[array([ 0.19295186, -0.19295186]), array(0.0), array(0.037230421163059885)]"
+ "[[array([ 0.19295186, -0.19295186])]]"
]
},
- "execution_count": 15,
+ "execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "stroop_model.execute([[1, 0], [1, 0], [0, 1]])"
+ "input_dict = {ink_color: [1, 0],\n",
+ " word: [1, 0],\n",
+ " task_demand: [0, 1]}\n",
+ "stroop_model.run(input_dict)"
]
},
{
@@ -707,4 +1291,4 @@
},
"nbformat": 4,
"nbformat_minor": 0
-}
\ No newline at end of file
+}
diff --git a/PsyNeuLink/Components/Component.py b/PsyNeuLink/Components/Component.py
index 3208bd80290..235d0bf84fe 100644
--- a/PsyNeuLink/Components/Component.py
+++ b/PsyNeuLink/Components/Component.py
@@ -16,8 +16,8 @@
Overview
--------
-Component is the base class for all of the objects used to create compositions (`processes ` or
-`systems `) in PsyNeuLink. It defines a common set of attributes possessed, and methods used by all
+Component is the base class for all of the objects used to create compositions (`processes ` or
+`systems `) in PsyNeuLink. It defines a common set of attributes possessed, and methods used by all
component objects.
.. _Component_Creation:
@@ -26,7 +26,7 @@
--------------------
A Component is never created directly. However, its __init__() method is always called when a subclass is instantiated;
-that, in turn, calls a standard set of methods (listed `below `) as part of the initialization
+that, in turn, calls a standard set of methods (listed `below `) as part of the initialization
procedure.
.. _Component_Structure:
@@ -43,125 +43,125 @@
.. _Component_Variable:
-* **variable** - the value of the `variable ` attribute is used as the input to its
- `function `. Specification of the variable in the constructor for a component determines both
- its format (e.g., whether it's value is numeric, its dimensionality and shape if it is an array, etc.) as well as
- its default value (the value used when the component is executed and no input is provided).
+* **variable** - the value of the `variable ` attribute is used as the input to its
+ `function `. Specification of the variable in the constructor for a component determines both
+ its format (e.g., whether it's value is numeric, its dimensionality and shape if it is an array, etc.) as well as
+ its default value (the value used when the component is executed and no input is provided).
.. _Component_Function:
-* **function** - the `function ` attribute determines the computation that a component carries out.
+* **function** - the `function ` attribute determines the computation that a component carries out.
It is always a PsyNeuLink `Function ` object (itself a PsyNeuLink component).
-
+
.. note::
The `function ` of a component can be assigned either a `Function ` object or any
- other callable object in python. If the latter is assigned, it will be "wrapped" in a `UserDefinedFunction`.
-
- All components have a default `function ` (with a default set of parameters), that is used if it
- is not otherwise specified. The `function ` can be specified in the
- function argument of the constructor for the component, using one of the following:
+ other callable object in python. If the latter is assigned, it will be "wrapped" in a `UserDefinedFunction`.
+
+ All components have a default `function ` (with a default set of parameters), that is used if it
+ is not otherwise specified. The `function ` can be specified in the
+ function argument of the constructor for the component, using one of the following:
- * **class** - this must be a subclass of `Function `, as in the following example::
+ * **class** - this must be a subclass of `Function `, as in the following example::
my_component = SomeComponent(function=SomeFunction)
-
- This will create a default instance of the specified subclass, using default values for its parameters.
+
+ This will create a default instance of the specified subclass, using default values for its parameters.
|
* **Function** - this can be either an existing `Function ` object or the constructor for one, as in the
following examples:
-
+
my_component = SomeComponent(function=SomeFunction)
-
+
or
-
+
some_function = SomeFunction(some_param=1)
my_component = SomeComponent(some_function)
-
- The specified Function will be used as a template to create a new Function object that is assigned to the
- `function_object` attribute of the component, the `function ` of which will be assigned as
+
+ The specified Function will be used as a template to create a new Function object that is assigned to the
+ `function_object` attribute of the component, the `function ` of which will be assigned as
the 'function ` attribute of the component.
-
+
.. note::
-
- In the current implementation of PsyNeuLink, if a `Function ` object (or the constructor for one) is
- used to specify the `function ` attribute of a component, the Function object specified (or
- created) is used to determine attributes of the Function object created for and assigned to the component, but
- is not *itself* assigned to the component. This is so that `Functions ` can be used as templates for
+
+ In the current implementation of PsyNeuLink, if a `Function ` object (or the constructor for one) is
+ used to specify the `function ` attribute of a component, the Function object specified (or
+ created) is used to determine attributes of the Function object created for and assigned to the component, but
+ is not *itself* assigned to the component. This is so that `Functions ` can be used as templates for
more than one component, without being assigned simultaneously to multiple components.
- A `function ` can also be specified in an entry of a
- `parameter specification dictionary ` assigned to the
- **params** argument of the constructor for the component, with the keyword FUNCTION as its key, and one of the
- specifications above as its value, as in the following example::
+ A `function ` can also be specified in an entry of a
+ `parameter specification dictionary ` assigned to the
+ **params** argument of the constructor for the component, with the keyword FUNCTION as its key, and one of the
+ specifications above as its value, as in the following example::
my_component = SomeComponent(params={FUNCTION:SomeFunction(some_param=1)})
-* **function_params** - the `function_params ` attribute contains a dictionary of the parameters
+* **function_params** - the `function_params ` attribute contains a dictionary of the parameters
for the component's `function ` and their values. Each entry is the name of a parameter, and
- its value the value of that parameter. This dictionary is read-only. Changes to the value of the function's
- parameters must be made by assigning a value to the corresponding attribute of the component's
- `function_object ` attribute (e.g., myMechanism.function_object.my_parameter),
- or in a FUNCTION_PARAMS dict using its `assign_params` method. The parameters for the function can be specified
+ its value the value of that parameter. This dictionary is read-only. Changes to the value of the function's
+ parameters must be made by assigning a value to the corresponding attribute of the component's
+ `function_object ` attribute (e.g., myMechanism.function_object.my_parameter),
+ or in a FUNCTION_PARAMS dict using its `assign_params` method. The parameters for the function can be specified
when the component is created in one of the following ways:
-
+
* in the **constructor** for a Function -- if that is used to specify the `function ` argument,
as in the following example::
my_component = SomeComponent(function=SomeFunction(some_param=1, some_param=2)
* in an argument of the **component's constructor** -- if all of the allowable functions for a component's
- `function ` share some or all of their parameters in common, the shared paramters may appear
+ `function ` share some or all of their parameters in common, the shared paramters may appear
as arguments in the constructor of the component itself, which can be used to set their values.
- * in an entry of a `parameter specification dictionary ` assigned to the
- **params** argument of the constructor for the component. The entry must use the keyword
+ * in an entry of a `parameter specification dictionary ` assigned to the
+ **params** argument of the constructor for the component. The entry must use the keyword
FUNCTION_PARAMS as its key, and its value must be a dictionary containing the parameters and their values.
- The key for each entry in the FUNCTION_PARAMS dictionary must be the name of a parameter, and its value the
+ The key for each entry in the FUNCTION_PARAMS dictionary must be the name of a parameter, and its value the
parameter's value, as in the example below::
-
+
my_component = SomeComponent(function=SomeFunction
params={FUNCTION_PARAMS:{SOME_PARAM=1, SOME_OTHER_PARAM=2}})
-
+
See `ParameterState_Specifying_Parameters` for details concerning different ways in which the value of a parameter
can be specified.
.. _Component_Function_Object:
-* **function_object** - the `function_object` attribute refers to the `Function ` assigned to the component;
- The Function's `function ` is assigned to the `function ` attribute of the
- component. The parameters of the Function can be modified by assigning values to the attributes corresponding to
+* **function_object** - the `function_object` attribute refers to the `Function ` assigned to the component;
+ The Function's `function ` is assigned to the `function ` attribute of the
+ component. The parameters of the Function can be modified by assigning values to the attributes corresponding to
those parameters (see `function_params ` above).
.. _Component_User_Params:
* **user_params** - the `user_params` attribute contains a dictionary of all of the user-modifiable attributes for the
- the component. This dictionary is read-only. Changes to the value of an attribute must be made by assigning a
+ the component. This dictionary is read-only. Changes to the value of an attribute must be made by assigning a
value to the attribute directly, or using the component's `assign_params` method.
-..
+..
COMMENT:
INCLUDE IN DEVELOPERS' MANUAL
* **paramClassDefaults**
-
+
* **paramInstanceDefaults**
COMMENT
-* **value** - the `value ` attribute contains the result (return value) of the component's
- `function ` after the function is called.
+* **value** - the `value ` attribute contains the result (return value) of the component's
+ `function ` after the function is called.
..
-* **name** - the `name ` attribute contains the name assigned to the component when it was created.
- If it was not specified, a default is assigned by the registry for subclass (see :doc:`Registry ` for
+* **name** - the `name ` attribute contains the name assigned to the component when it was created.
+ If it was not specified, a default is assigned by the registry for subclass (see :doc:`Registry ` for
conventions used in assigning default names and handling of duplicate names).
..
* **prefs** - the `prefs ` attribute contains the `PreferenceSet` assigned to the component when
it was created. If it was not specified, a default is assigned using `classPreferences` defined in __init__.py
Each individual preference is accessible as an attribute of the component, the name of which is the name of the
- preference (see `PreferenceSet ` for details).
+ preference (see `PreferenceSet ` for details).
COMMENT:
* **log**
COMMENT
-
+
.. _Component_Methods:
Component Methods
@@ -169,69 +169,69 @@
COMMENT:
INCLUDE IN DEVELOPERS' MANUAL
-
- There are two sets of methods that belong to every component: one set that is called when it is initialized; and
- another set that can be called to perform various operations common to all components. Each of these is described
- briefly below. All of these methods can be overridden by subclasses to implement customized operations, however
- it is strongly recommended that the method be called on super() at some point, so that the standard operations are
- carried out. Whether customization operations should be performed before or after the call to super is discussed in
- the descriptions below where relevant.
-
+
+ There are two sets of methods that belong to every component: one set that is called when it is initialized; and
+ another set that can be called to perform various operations common to all components. Each of these is described
+ briefly below. All of these methods can be overridden by subclasses to implement customized operations, however
+ it is strongly recommended that the method be called on super() at some point, so that the standard operations are
+ carried out. Whether customization operations should be performed before or after the call to super is discussed in
+ the descriptions below where relevant.
+
.. _Component_Initialization_Methods:
-
+
Initialization Methods
^^^^^^^^^^^^^^^^^^^^^^
-
+
These methods can be overridden by the subclass to customize the initialization process, but should always call the
corresponding method of the Component base class (using ``super``) to insure full initialization. There are two
- categories of initializion methods: validation and instantiation.
-
-
+ categories of initializion methods: validation and instantiation.
+
+
.. _Component_Validation_Methods:
-
- * **Validation methods** perform a strictly *syntactic* check, to determine if a value being validated conforms
- to the format expected for it by the component (i.e., the type of the value and, if it is iterable, the type its
- elements and/or its length). The value itself is not checked in any other way (e.g., whether it equals a particular
- value or falls in a specified range). If the validation fails, and exception is raised. Validation methods never
+
+ * **Validation methods** perform a strictly *syntactic* check, to determine if a value being validated conforms
+ to the format expected for it by the component (i.e., the type of the value and, if it is iterable, the type its
+ elements and/or its length). The value itself is not checked in any other way (e.g., whether it equals a particular
+ value or falls in a specified range). If the validation fails, and exception is raised. Validation methods never
make changes the actual value of an attribute, but they may change its format (e.g., from a list to an ndarray) to
comply with requirements of the component.
-
- * `_validate_variable ` validates the value provided to the keyword:`variable`
- argument in the constructor for the component. If it is overridden, customized validation should generally
- performed *prior* to the call to super(), to allow final processing by the Component base class.
-
- * `_validate_params ` validates the value of any parameters specified in the
- constructor for the component (whether they are made directly in the argument for a parameter, or in a
- `parameter specification dictionary `. If it is overridden by a subclass,
+
+ * `_validate_variable ` validates the value provided to the keyword:`variable`
+ argument in the constructor for the component. If it is overridden, customized validation should generally
+ performed *prior* to the call to super(), to allow final processing by the Component base class.
+
+ * `_validate_params ` validates the value of any parameters specified in the
+ constructor for the component (whether they are made directly in the argument for a parameter, or in a
+ `parameter specification dictionary `. If it is overridden by a subclass,
customized validation should generally be performed *after* the call to super().
-
- * **Instantiation methods** create, assign, and/or perform *semantic* checks on the values of component attributes.
- Semantic checks may include value and/or range checks, as well as checks of formatting and/or value
+
+ * **Instantiation methods** create, assign, and/or perform *semantic* checks on the values of component attributes.
+ Semantic checks may include value and/or range checks, as well as checks of formatting and/or value
compatibility with other attributes of the component and/or the attributes of other components (for example, the
- _instantiate_function method checks that the input of the component's `function ` is compatible
+ _instantiate_function method checks that the input of the component's `function ` is compatible
with its `variable `).
-
- * `_instantiate_defaults ` first calls the validation methods, and then
+
+ * `_instantiate_defaults ` first calls the validation methods, and then
assigns the default values for all of the attributes of the instance of the component being created.
-
+
_instantiate_attributes_before_function
_instantiate_function
_instantiate_attributes_after_function
-
+
.. _Component_Callable_Methods:
-
+
Callable Methods
^^^^^^^^^^^^^^^^
-
+
initialize
COMMENT
.. _Component_Assign_Params:
-* **assign_params** - the `assign_params` method is used to assign the value of one or more parameters of a
- component. Each parameter is specified as an entry in a dict in the **request_set** argument;
- parameters for the component's function are specified as entries in a FUNCTION_PARAMS dict within
- **request_set** dict.
+* **assign_params** - the `assign_params` method is used to assign the value of one or more parameters of a
+ component. Each parameter is specified as an entry in a dict in the **request_set** argument;
+ parameters for the component's function are specified as entries in a FUNCTION_PARAMS dict within
+ **request_set** dict.
* **reset_params** - the `reset_params` method is used to reset the value of all user_params to their default
(paramClass
@@ -248,7 +248,7 @@
COMMENT:
INCLUDE IN DEVELOPERS' MANUAL
.. _Component_Class_Reference:
-
+
Class Reference
---------------
COMMENT
@@ -275,10 +275,12 @@
"""
-from collections import OrderedDict
+from collections import OrderedDict, Iterable
from PsyNeuLink.Globals.Utilities import *
from PsyNeuLink.Globals.Preferences.ComponentPreferenceSet import *
+component_keywords = {NAME, VARIABLE, VALUE, FUNCTION, FUNCTION_PARAMS, PARAMS, PREFS_ARG, CONTEXT}
+
class ResetMode(Enum):
CURRENT_TO_INSTANCE_DEFAULTS = 0
INSTANCE_TO_CLASS = 1
@@ -296,17 +298,17 @@ class ResetMode(Enum):
from collections import UserDict
class ParamsDict(UserDict):
"""Create, set and get attribute of owner for each key in dict
-
+
Creates and maintains an interface to attributes of a component via a dict:
- any assignment to an entry of the dict creates or updates the value of the attribute with the name of the key
- any query retrieves the value of the attribute with the name of the key
Dict itself is maintained in self.data
-
- Notes:
- * This provides functionality similar to the __dict__ attribute of a python object,
+
+ Notes:
+ * This provides functionality similar to the __dict__ attribute of a python object,
but is restricted to the attributes relevant to its role as a PsyNeuLink component.
* It insures that any instantiation of a function_params attribute is a ReadOnlyOrderedDict
-
+
"""
def __init__(self, owner, dict=None):
@@ -399,7 +401,7 @@ class Component(object):
it can be referenced either as self.function, self.params[FUNCTION] or self.paramsCurrent[FUNCTION]
- function_object (Function): the object to which function belongs (and that defines it's parameters)
- output (value: self.value)
- - outputValue (return from self.execute: concatenated set of values of outputStates)
+ - output_values (return from self.execute: concatenated set of values of outputStates)
- class and instance variable defaults
- class and instance param defaults
The components's execute method (.execute is the component's primary method
@@ -466,8 +468,13 @@ class Component(object):
+ componentCategory - category of Component (i.e., process, mechanism, projection, learning, function)
+ componentType - type of component within a category
(e.g., TransferMechanism, MappingProjection, ControlProjection, etc.)
- + requiredParamClassDefaultTypes - dict of param names and types that all subclasses of Component must
- implement;
+ + requiredParamClassDefaultTypes - dict of param names & types that all subclasses of Component must implement;
+ + prev_context - str (primarily used to track and prevent recursive calls to assign_params from setters)
+
+ # Prevent recursive calls from setters
+ if self.prev_context == context:
+ return
+
Class methods:
- _validate_variable(variable)
@@ -502,7 +509,7 @@ class Component(object):
+ function (implementation is optional; aliased to params[FUNCTION] by default)
"""
- #region CLASS ATTRIBUTES
+ #CLASS ATTRIBUTES
className = "COMPONENT"
suffix = " " + className
# IMPLEMENTATION NOTE: *** CHECK THAT THIS DOES NOT CAUSE ANY CHANGES AT SUBORDNIATE LEVELS TO PROPOGATE EVERYWHERE
@@ -528,8 +535,18 @@ class Component(object):
# * kwComponentCategory (below) is used as placemarker for Component.Function class; replaced in __init__ below
# (can't reference own class directly class block)
requiredParamClassDefaultTypes = {}
+
paramClassDefaults = {}
- #endregion
+
+ # IMPLEMENTATION NOTE: This is needed so that the State class can be used with ContentAddressableList,
+ # which requires that the attribute used for addressing is on the class;
+ # it is also declared as a property, so that any assignments are validated to be strings,
+ # insuring that assignment by one instance will not affect the value of others.
+ name = None
+
+
+ # IMPLEMENTATION NOTE: Primarily used to track and prevent recursive calls to assign_params from setters.
+ prev_context = None
def __init__(self,
variable_default,
@@ -544,11 +561,6 @@ def __init__(self,
- params_default (dict): assigned as paramInstanceDefaults
Note: if parameter_validation is off, validation is suppressed (for efficiency) (Component class default = on)
- :param variable_default: (anything but a dict) - value to assign as variableInstanceDefault
- :param param_defaults: (dict) - params to be assigned to paramInstanceDefaults
- :param log: (ComponentLog enum) - log entry types set in self.componentLog
- :param name: (string) - optional, overrides assignment of default (componentName of subclass)
- :return:
"""
# # MODIFIED 8/14/16 NEW:
@@ -578,18 +590,16 @@ def __init__(self,
self.componentName = self.componentName or self.componentType
except AttributeError:
self.componentName = self.componentType
- #endregion
- #region ENFORCE REGISRY
+ # ENFORCE REGISRY
if self.__class__.__bases__[0].__bases__[0].__bases__[0].__name__ is 'ShellClass':
try:
self.__class__.__bases__[0].registry
except AttributeError:
raise ComponentError("{0} is a category class and so must implement a registry".
format(self.__class__.__bases__[0].__name__))
- #endregion
- #region ASSIGN PREFS
+ # ASSIGN PREFS
# If a PreferenceSet was provided, assign to instance
if isinstance(prefs, PreferenceSet):
@@ -598,45 +608,16 @@ def __init__(self,
# Otherwise, if prefs is a specification dict instantiate it, or if it is None assign defaults
else:
self.prefs = ComponentPreferenceSet(owner=self, prefs=prefs, context=context)
- #endregion
-
- # MODIFIED 9/11/16 NEW:
- # IMPLEMENTATION NOTE: This is nice and all, but:
- # - property version only works for getter, and for class (can't access instance values)
- # - attribute version works for getter, but setter sets the attribute and not the pref
- # So, for now, hard coding property setters and getters for each preference (see below)
- # Assign prefs to attributes on object
- # for pref in self.prefs.prefsList:
- # # Generate attribute for each pref that returns value of the pref
- # PROBLEM: MAKING AN ASSIGNMENT TO THE ATTRIBUTE WILL NOT AFFECT THE PREFERENCE, JUST THIS ATTRIBUTE
- # setattr(self,
- # underscore_to_camelCase(pref),
- # getattr(getattr(self, 'prefs'), underscore_to_camelCase(pref)))
- # PROBLEM: THIS REQUIRES THAT THE PROPERTY IS PUT ON THE CLASS, WHICH GENERATES UNDESIRABLE BEHAVIORS
- # ALSO, SETTER WON'T WORK PROPERLY HERE EITHER
- # # IMPLEMENT: WITHOUT SETTER:
- # setattr(type(self),
- # underscore_to_camelCase(pref),
- # property(lambda self: getattr(getattr(self, 'prefs'), underscore_to_camelCase(pref))))
- # # IMPLEMENT: WITH SETTER:
- # pref_name = underscore_to_camelCase(pref)
- # setattr(type(self),
- # pref_name,
- # property(lambda self: getattr(getattr(self, 'prefs'), pref_name),
- # lambda self, value: setattr(getattr(getattr(self, 'prefs'), pref_name),
- # pref_name,
- # value)))
- # MODIFIED 9/11/16 END
-
- #region ASSIGN LOG
+
+ # ASSIGN LOG
+
self.log = Log(owner=self)
self.recording = False
# Used by run to store return value of execute
self.results = []
- #endregion
- #region ENFORCE REQUIRED CLASS DEFAULTS
+ # ENFORCE REQUIRED CLASS DEFAULTS
# All subclasses must implement variableClassDefault
# Do this here, as _validate_variable might be overridden by subclass
@@ -647,9 +628,8 @@ def __init__(self,
except AttributeError:
raise ComponentError("variableClassDefault must be defined for {} or its base class".
format(self.componentName))
- #endregion
- #region CHECK FOR REQUIRED PARAMS
+ # CHECK FOR REQUIRED PARAMS
# All subclasses must implement, in their paramClassDefaults, params of types specified in
# requiredClassParams (either above or in subclass defintion)
@@ -665,7 +645,7 @@ def __init__(self,
type(PsyNeuLink.Components.Functions.Function.Function_Base)
if required_param not in self.paramClassDefaults.keys():
- raise ComponentError("Param {} must be in paramClassDefaults for {}".
+ raise ComponentError("Param \'{}\' must be in paramClassDefaults for {}".
format(required_param, self.name))
# If the param does not match any of the types specified for it in type_requirements
@@ -683,9 +663,10 @@ def __init__(self,
format(required_param_value.__name__, required_param, self.name, type_names))
except TypeError:
pass
- #endregion
- #region ASSIGN DEFAULTS
+
+ # VALIDATE VARIABLE AND PARAMS, AND ASSIGN DEFAULTS
+
# Validate the set passed in and assign to paramInstanceDefaults
# By calling with assign_missing, this also populates any missing params with ones from paramClassDefaults
self._instantiate_defaults(variable=variable_default,
@@ -694,9 +675,9 @@ def __init__(self,
target_set=self.paramInstanceDefaults, # destination set to which params are being assigned
default_set=self.paramClassDefaults, # source set from which missing params are assigned
context=context)
- #endregion
- #region SET CURRENT VALUES OF VARIABLE AND PARAMS
+ # SET CURRENT VALUES OF VARIABLE AND PARAMS
+
self.variable = self.variableInstanceDefault
# self.variable = self.variableInstanceDefault.copy()
@@ -704,29 +685,28 @@ def __init__(self,
self.paramsCurrent = self.paramInstanceDefaults.copy()
self.runtime_params_in_use = False
- #endregion
- #region VALIDATE FUNCTION (self.function and/or self.params[function, FUNCTION_PARAMS])
+ # VALIDATE FUNCTION (self.function and/or self.params[function, FUNCTION_PARAMS])
self._validate_function(context=context)
- #endregion
- #region INSTANTIATE ATTRIBUTES BEFORE FUNCTION
+ # INSTANTIATE ATTRIBUTES BEFORE FUNCTION
# Stub for methods that need to be executed before instantiating function
# (e.g., _instantiate_sender and _instantiate_receiver in Projection)
self._instantiate_attributes_before_function(context=context)
- #endregion
- #region INSTANTIATE FUNCTION and assign output (by way of self.execute) to self.value
+ # INSTANTIATE FUNCTION
+ # - assign initial function parameter values from ParameterStates,
+ # - assign function's output to self.value (based on call of self.execute)
self._instantiate_function(context=context)
- #endregion
- #region INSTANTIATE ATTRIBUTES AFTER FUNCTION
+ # INSTANTIATE ATTRIBUTES AFTER FUNCTION
# Stub for methods that need to be executed after instantiating function
# (e.g., instantiate_output_state in Mechanism)
self._instantiate_attributes_after_function(context=context)
- #endregion
-#endregion
+ def __repr__(self):
+ return '({0} {1})'.format(type(self).__name__, self.name)
+ #return '{1}'.format(type(self).__name__, self.name)
def _deferred_init(self, context=None):
"""Use in subclasses that require deferred initialization
@@ -761,8 +741,9 @@ def _deferred_init(self, context=None):
# If name is None, mark as deferred so that name can be customized
# using info that has become available at time of deferred init
- self.init_args['name'] = self.init_args['name'] or ('deferred_init_' + self.className) or \
- DEFERRED_DEFAULT_NAME
+ self.init_args['name'] = (self.init_args['name'] or
+ ('deferred_init_' + self.className) or
+ DEFERRED_DEFAULT_NAME)
# Complete initialization
super(self.__class__,self).__init__(**self.init_args)
@@ -790,6 +771,34 @@ def parse_arg(arg):
name = arg
return name
+ def _convert_function_to_class(function, source):
+ from PsyNeuLink.Components.Functions.Function import Function
+ from inspect import isfunction
+ fct_cls = None
+ fct_params = None
+ # It is a PsyNeuLink Function class
+ if inspect.isclass(function) and issubclass(function, Function):
+ fct_cls = function
+ # It is an instantiateed PsyNeuLink Function class
+ elif isinstance(function, Function):
+ # Set it to the class (for compatibility with current implementation of _instantiate_function()
+ # and put its params in FUNCTION_PARAMS
+ fct_cls = function.__class__
+ fct_params = function.user_params.copy()
+ # It is a generic function
+ elif isfunction(function):
+ # Assign to paramClassDefaults as is (i.e., don't convert to class), since class is generic
+ # (_instantiate_function also tests for this and leaves it as is)
+ fct_cls = function
+ else:
+ if hasattr(self, 'name'):
+ name = self.name
+ else:
+ name = self.__class__.__name__
+ raise ComponentError("Unrecognized object ({}) specified in {} for {}".
+ format(function, source, name))
+ return (fct_cls, fct_params)
+
# ASSIGN DEFAULTS TO paramClassDefaults
# Check if defaults have been assigned to paramClassDefaults, and if not do so
for arg in kwargs:
@@ -797,8 +806,8 @@ def parse_arg(arg):
arg_name = parse_arg(arg)
- # The params arg (nor anything in it) is never a default
- if arg_name is kwParams:
+ # The params arg is never a default (nor is anything in it)
+ if arg_name is PARAMS:
continue
# Check if param exists in paramClassDefaults
@@ -809,28 +818,11 @@ def parse_arg(arg):
except:
# If arg is FUNCTION and it's default is an instance (i.e., not a class)
if arg_name is FUNCTION and not inspect.isclass(default(arg)):
-
# FIX: REFACTOR Component._instantiate_function TO USE COPY OF INSTANTIATED function
-
- function = default(arg)
- from PsyNeuLink.Components.Functions.Function import Function
- from inspect import isfunction
-
- # It is a PsyNeuLink Function
- if isinstance(function, Function):
- # Set it to the class (for compatibility with current implementation of _instantiate_function()
- # and put its params in FUNCTION_PARAMS
- self.paramClassDefaults[arg] = default(arg).__class__
- self.paramClassDefaults[FUNCTION_PARAMS] = default(arg).user_params.copy()
-
- # It is a generic function
- elif isfunction(function):
- # Assign to paramClassDefaults as is (i.e., don't convert to class), since class is generic
- # (_instantiate_function also tests for this and leaves it as is)
- self.paramClassDefaults[arg] = function
- else:
- raise ComponentError("Unrecognized object ({}) specified as function for {}".
- format(function, self.name))
+ fct_cls, fct_params = _convert_function_to_class(default(arg), 'function arg')
+ self.paramClassDefaults[arg] = fct_cls
+ if fct_params:
+ self.paramClassDefaults[FUNCTION_PARAMS] = fct_params
# Get defaults values for args listed in FUNCTION_PARAMS
# Note: is not an arg, but rather used to package args that belong to a non-instantiated function
@@ -839,11 +831,12 @@ def parse_arg(arg):
for item in kwargs[arg]:
self.paramClassDefaults[FUNCTION_PARAMS][item] = default(item)
else:
- if inspect.isclass(default(arg)) and issubclass(default(arg),inspect._empty):
+ default_arg = default(arg)
+ if inspect.isclass(default_arg) and issubclass(default_arg,inspect._empty):
raise ComponentError("PROGRAM ERROR: \'{}\' parameter of {} must be assigned a default value "
"in its constructor or in paramClassDefaults (it can be \'None\')".
format(arg, self.__class__.__name__))
- self.paramClassDefaults[arg] = default(arg)
+ self.paramClassDefaults[arg] = default_arg
# param corresponding to arg IS already in paramClassDefaults, so ignore
else:
@@ -861,7 +854,7 @@ def parse_arg(arg):
for arg in sorted(list(kwargs.keys())):
# Put any values (presumably in a dict) passed in the "params" arg in params_arg
- if arg is kwParams:
+ if arg is PARAMS:
params_arg = kwargs[arg]
continue
@@ -918,10 +911,9 @@ def parse_arg(arg):
# Assign as is (i.e., don't convert to class), since class is generic
# (_instantiate_function also tests for this and leaves it as is)
params[FUNCTION] = function
- # FIX: UNCOMMENT WHEN EVC IS GIVEN A PREF SET
- # if self.verbosePref:
- # warnings.warn("{} is not a PsyNeuLink Function, "
- # "therefore runtime_params cannot be used".format(default(arg).__name__))
+ if self.verbosePref:
+ warnings.warn("{} is not a PsyNeuLink Function, "
+ "therefore runtime_params cannot be used".format(default(arg).__name__))
else:
raise ComponentError("Unrecognized object ({}) specified as function for {}".
format(function, self.name))
@@ -933,23 +925,49 @@ def parse_arg(arg):
# If function was instantiated object, FUNCTION_PARAMS came from it, so ignore additional specification
if ignore_FUNCTION_PARAMS:
continue
- # # MODIFIED 4/9/17 OLD:
- # params[FUNCTION_PARAMS] = kwargs[arg]
- # MODIFIED 4/9/17 NEW:
params[FUNCTION_PARAMS] = ReadOnlyOrderedDict(name=FUNCTION_PARAMS)
for param_name in sorted(list(kwargs[arg].keys())):
params[FUNCTION_PARAMS].__additem__(param_name,kwargs[arg][param_name])
- # MODIFIED 4/9/17 END
- # For standard params, assign arg and its default value to paramClassDefaults
+ # If no input_states or output_states are specified, ignore
+ # (ones in paramClassDefaults will be assigned to paramsCurrent below (in params_class_defaults_only)
+ elif arg in {INPUT_STATES, OUTPUT_STATES} and kwargs[arg] is None:
+ continue
+
+ # For all other params, assign arg and its default value to paramClassDefaults
else:
params[arg] = kwargs[arg]
- # Add or override arg values with any specified in params dict (including FUNCTION_PARAMS)
+ # Add or override arg values with any specified in params dict (including FUNCTION and FUNCTION_PARAMS)
if params_arg:
+ # If function was specified in the function arg of the constructor
+ # and also in the FUNCTION entry of a params dict in params arg of constructor:
+ if params and FUNCTION in params and FUNCTION in params_arg:
+ # Check if it is the same as the default or the one assigned in the function arg of the constructor
+ if not is_same_function_spec(params[FUNCTION], params_arg[FUNCTION]):
+ fct_cls, fct_params = _convert_function_to_class(params_arg[FUNCTION],
+ '{} entry of params dict'.format(FUNCTION))
+ params_arg[FUNCTION] = fct_cls
+ if fct_params:
+ params_arg[FUNCTION_PARAMS] = fct_params
+ # If it is not the same, delete any function params that have already been assigned
+ # in params[] for the function specified in the function arg of the constructor
+ if FUNCTION_PARAMS in params:
+ for param in list(params[FUNCTION_PARAMS].keys()):
+ params[FUNCTION_PARAMS].__deleteitem__(param)
try:
- # Update params[FUNCTION_PARAMS] with any from param_arg[FUNCTION_PARAMS] (specified in the constructor)
+ # Replace any parameters for function specified in function arg of constructor
+ # with those specified either in FUNCTION_PARAMS entry of params dict
+ # or for an instantiated function specified in FUNCTION entry of params dict
+
+ # First, if the function is instantiated, get the parameters from its user_params dict
+ from PsyNeuLink.Components.Functions.Function import Function
+ if FUNCTION in params_arg and isinstance(params_arg[FUNCTION], Function):
+ for param_name in params_arg[FUNCTION].user_params:
+ params[FUNCTION_PARAMS].__additem__(param_name, params_arg[FUNCTION].user_params[param_name])
+ # Then get any specified in FUNCTION_PARAMS entry of the params dict
+ # (these will override any specified in the constructor for the function)
for param_name in params_arg[FUNCTION_PARAMS].keys():
params[FUNCTION_PARAMS].__additem__(param_name, params_arg[FUNCTION_PARAMS][param_name])
# Convert params_arg[FUNCTION_PARAMS] to ReadOnlyOrderedDict and update it with params[FUNCTION_PARAMS];
@@ -985,7 +1003,6 @@ def parse_arg(arg):
# • therefore, assignments of paramInstance defaults to paramsCurrent in __init__ overwrites the
# the user-specified vaules (from the constructor args) in user_params
self.user_params_for_instantiation = OrderedDict()
- from collections import Iterable
for param_name in sorted(list(self.user_params.keys())):
param_value = self.user_params[param_name]
if isinstance(param_value, (str, np.ndarray, tuple)):
@@ -996,8 +1013,8 @@ def parse_arg(arg):
if isinstance(param_value, dict):
for k, v in param_value.items():
self.user_params_for_instantiation[param_name][k] = v
- elif isinstance(param_value, ReadOnlyOrderedDict):
- for k in sorted(list(param_value.keys())):
+ elif isinstance(param_value, (ReadOnlyOrderedDict, ContentAddressableList)):
+ for k in sorted(list(param_value)):
self.user_params_for_instantiation[param_name].__additem__(k,param_value[k])
# SET
elif isinstance(param_value, set):
@@ -1010,12 +1027,15 @@ def parse_arg(arg):
else:
self.user_params_for_instantiation[param_name] = param_value
+ # FIX: 6/1/17 - MAKE SURE FUNCTIONS DON'T GET ASSIGNED AS PROPERTIES, SINCE THEY DON'T HAVE ParameterStates
+ # AND SO CAN'T RETURN A ParameterState.value AS THEIR VALUE
+
# Provide opportunity for subclasses to filter final set of params in class-specific way
# Note: this is done here to preserve identity of user-specified params assigned to user_params above
self._filter_params(params)
# Create property on self for each parameter in user_params:
- # these will be validated whenever they are assigned a new value
+ # these WILL be validated whenever they are assigned a new value
self._create_attributes_for_params(make_as_properties=True, **self.user_params)
# Create attribute on self for each parameter in paramClassDefaults not in user_params:
@@ -1044,12 +1064,11 @@ def _filter_params(self, params):
def _create_attributes_for_params(self, make_as_properties=False, **kwargs):
"""Create property on parent class of object for all attributes passed in kwargs dict.
-
+
If attribute or property already exists, do nothing.
- Create backing field for attribute with "_" prefixed to attribute name,
- and assign value provided in kwargs as its default value.
+ Create backing field for attribute with "_" prefixed to attribute name,
+ and assign value provided in kwargs as its default value.
"""
-
if make_as_properties:
for arg_name, arg_value in kwargs.items():
if not any(hasattr(parent_class, arg_name) for parent_class in self.__class__.mro()):
@@ -1079,6 +1098,7 @@ def _check_args(self, variable, params=None, target_set=None, context=None):
:target_set: (dict) - set to which params should be assigned (default: self.paramsCurrent)
:return:
"""
+ # VARIABLE ------------------------------------------------------------
# If function is called without any arguments, get default for variable
if variable is None:
@@ -1098,6 +1118,8 @@ def _check_args(self, variable, params=None, target_set=None, context=None):
else:
self.variable = variable
+ # PARAMS ------------------------------------------------------------
+
# If target_set is not specified, use paramsCurrent
if target_set is None:
target_set = self.paramsCurrent
@@ -1114,11 +1136,13 @@ def _check_args(self, variable, params=None, target_set=None, context=None):
runtime_params = params
if runtime_params and runtime_params is not None:
for param_name in self.user_params:
- # IMPLEMENTATION NOTE: FUNCTION_RUNTIME_PARAM_NOT_SUPPORTED
- # At present, assignment of ``function`` as runtime param is not supported
+ # Ignore input_states and output_states -- they should not be modified during run
+ # IMPLEMENTATION NOTE:
+ # FUNCTION_RUNTIME_PARAM_NOT_SUPPORTED:
+ # At present, assignment of ``function`` as runtime param is not supported
# (this is because paramInstanceDefaults[FUNCTION] could be a class rather than an bound method;
# i.e., not yet instantiated; could be rectified by assignment in _instantiate_function)
- if param_name is FUNCTION:
+ if param_name in {FUNCTION, INPUT_STATES, OUTPUT_STATES}:
continue
# If param is specified in runtime_params, then assign it
if param_name in runtime_params:
@@ -1217,28 +1241,45 @@ def _instantiate_defaults(self,
if not isinstance(default_set, dict):
raise ComponentError("default parameter set must be a dictionary")
- # IMPLEMENTATION NOTE: REMOVE
- # # Enforce implementation of variableEncodingDim and valueEncodingDim:
- # try:
- # self.variableEncodingDim
- # except AttributeError:
- # raise ComponentError("{0} or its base class must implement variableEncodingDim".
- # format(self.__class__.__name__))
- # try:
- # self.valueEncodingDim
- # except AttributeError:
- # raise ComponentError("{0} or its base class must implement valueEncodingDim".
- # format(self.__class__.__name__))
+ # # GET VARIABLE FROM PARAM DICT IF SPECIFIED
+ # # (give precedence to that over variable arg specificadtion)
+ # if VARIABLE in request_set and request_set[VARIABLE] is not None:
+ # variable = request_set[VARIABLE]
+
+ # ASSIGN SIZE OR SHAPE TO VARIABLE if specified
+
+ # If size has been specified, make sure it doesn't conflict with variable arg or param specification
+ if hasattr(self, 'size') and self.size is not None:
+ # Both variable and size are specified
+ if variable is not None:
+ # If they confict, raise exception, otherwise use variable (it specifies both size and content).
+ if self.size != len(variable):
+ raise ComponentError("The size arg of {} ({}) conflicts with the length of its variable arg ({})".
+ format(self.name, self.size, len(variable)))
+ # Variable is not specified, so set to array of zero with length = size
+ else:
+ variable = np.zeros(self.size)
+
+ elif hasattr(self, 'shape') and self.shape is not None:
+ # Both variable and shape are specified
+ if variable is not None:
+ # If they conflict, raise exception, otherwise use variable (it specifies both shape and content)
+ if self.shape != np.array(variable).shape:
+ raise ComponentError("The shape arg of {} ({}) conflicts the shape of its variable arg ({})".
+ format(self.name, self.size, np.array(variable).shape))
+ # Variable is not specified, so set to array of zeros with specified shape
+ else:
+ variable = np.zeros(self.shape)
# VALIDATE VARIABLE (if not called from assign_params)
- if not any(context_string in context for context_string in {COMMAND_LINE, 'ATTRIBUTE_SETTER'}):
+
+ if not any(context_string in context for context_string in {COMMAND_LINE, SET_ATTRIBUTE}):
# if variable has been passed then validate and, if OK, assign as variableInstanceDefault
self._validate_variable(variable, context=context)
if variable is None:
self.variableInstanceDefault = self.variableClassDefault
else:
- # MODIFIED 6/9/16 (CONVERT TO np.ndarray)
self.variableInstanceDefault = self.variable
# If no params were passed, then done
@@ -1254,7 +1295,7 @@ def _instantiate_defaults(self,
raise ComponentError("Altering paramClassDefaults not permitted")
if default_set is None:
- if any(context_string in context for context_string in {COMMAND_LINE, 'ATTRIBUTE_SETTER'}):
+ if any(context_string in context for context_string in {COMMAND_LINE, SET_ATTRIBUTE}):
default_set = {}
for param_name in request_set:
default_set[param_name] = self.paramInstanceDefaults[param_name]
@@ -1310,33 +1351,21 @@ def _instantiate_defaults(self,
self.assign_default_FUNCTION_PARAMS = True
- try:
- # # MODIFIED 11/30/16 OLD:
- # function = request_set[FUNCTION]
- # MODIFIED 11/30/16 NEW:
- # Copy to keep record of request_set function for comparison below, after request_set has been updated
- import copy
- function = copy.deepcopy(request_set[FUNCTION])
- # MODIFIED 11/30/16 END
- except KeyError:
- # If there is no function specified, then allow functionParams
- # Note: this occurs for objects that have "hard-coded" functions
- self.assign_default_FUNCTION_PARAMS = True
- else:
+ if FUNCTION in request_set:
# Get function class:
+ function = request_set[FUNCTION]
if inspect.isclass(function):
function_class = function
else:
function_class = function.__class__
# Get default function (from ParamClassDefaults)
- try:
- default_function = default_set[FUNCTION]
- except KeyError:
+ if not FUNCTION in default_set:
# This occurs if a function has been specified as an arg in the call to __init__()
# but there is no function spec in paramClassDefaults;
# This will be caught, and an exception raised, in _validate_params()
pass
else:
+ default_function = default_set[FUNCTION]
# Get default function class
if inspect.isclass(function):
default_function_class = default_function
@@ -1392,15 +1421,14 @@ def _instantiate_defaults(self,
# if request_set has been passed or created then validate and, if OK, assign params to target_set
if request_set:
# MODIFIED 4/18/17 NEW:
- # For params that are a ParamValueProjection or 2-item tuple, extract the value
+ # For params that are a 2-item tuple, extract the value
# both for validation and assignment (tuples are left intact in user_params_for_instantiation dict
- # which is used it instantiate the specified projections)
+ # which is used it instantiate the specified components in the 2nd item of the tuple)
# IMPLEMENTATION NOTE: Do this here rather than in _validate_params, as it needs to be done before
# any override of _validate_params, which (should not, but) may process params
# before calling super()._validate_params
- from PsyNeuLink.Components.ShellClasses import ParamValueProjection
for param_name, param_value in request_set.items():
- if isinstance(param_value, (ParamValueProjection, tuple)):
+ if isinstance(param_value, tuple):
param_value = self._get_param_value_from_tuple(param_value)
request_set[param_name] = param_value
# MODIFIED 4/18/17 END NEW
@@ -1424,6 +1452,21 @@ def _assign_params(self, request_set:tc.optional(dict)=None, context=None):
from PsyNeuLink.Components.Functions.Function import Function
+ # FIX: Hack to prevent recursion in calls to setter and assign_params
+ # MODIFIED 5/6/17 NEW:
+ # Prevent recursive calls from setters
+ if self.prev_context == context:
+ return
+ self.prev_context = context
+ # MODIFIED 5/6/17 END
+ # import uuid
+ # try:
+ # if self.prev_id == self.curr_id:
+ # return
+ # except AttributeError:
+ # pass
+ # self.curr_id = uuid.uuid4()
+
if not request_set:
if self.verbosePref:
warnings.warn("No params specified")
@@ -1449,17 +1492,13 @@ def _assign_params(self, request_set:tc.optional(dict)=None, context=None):
pref_buffer = self.prefs._param_validation_pref
self.paramValidationPref = PreferenceEntry(False, PreferenceLevel.INSTANCE)
- # pref_buffer = self.prefs
- # self.prefs = suppress_validation_preference_set
- # self.prefs = ComponentPreferenceSet(prefs = {
- # kpParamValidationPref: PreferenceEntry(False,PreferenceLevel.INSTANCE),
- # kpVerbosePref: PreferenceEntry(False,PreferenceLevel.INSTANCE),
- # kpReportOutputPref: PreferenceEntry(False,PreferenceLevel.INSTANCE)})
-
self.paramsCurrent.update(validated_set)
-
+ # The following is so that:
+ # if the component is a function and it is passed as an argument to a component,
+ # then the parameters are available in self.user_params_for_instantiation
+ # (which is needed when the function is recreated from its class in _assign_args_to_params_dicts)
+ self.user_params_for_instantiation.update(self.user_params)
self.paramValidationPref = pref_buffer
- # self.prefs = pref_buffer
# FIX: THIS NEEDS TO BE HANDLED BETTER:
# FIX: DEAL WITH INPUT_STATES AND PARAMETER_STATES DIRECTLY (RATHER THAN VIA instantiate_attributes_before...)
@@ -1471,8 +1510,13 @@ def _assign_params(self, request_set:tc.optional(dict)=None, context=None):
validated_set_param_names = list(validated_set.keys())
- if INPUT_STATES in validated_set_param_names:
- self._instantiate_attributes_before_function()
+ # If an input_state is being added from the command line,
+ # must _instantiate_attributes_before_function to parse input_states specification
+ # Otherwise, should not be run,
+ # as it induces an unecessary call to _instantatiate_parameter_states (during instantiate_input_states),
+ # that causes name-repetition problems when it is called as part of the standard init procedure
+ if INPUT_STATES in validated_set_param_names and COMMAND_LINE in context:
+ self._instantiate_attributes_before_function(context=COMMAND_LINE)
# Give owner a chance to instantiate function and/or function params
# (e.g., wrap in UserDefineFunction, as per EVCMechanism)
@@ -1481,32 +1525,17 @@ def _assign_params(self, request_set:tc.optional(dict)=None, context=None):
for param_value in validated_set.values()):
self._instantiate_attributes_before_function()
- # MODIFIED 4/17/17 OLD:
- # # If object is a Mechanism or MappingProjection, instantiate ParameterState for param if required
- # # (States don't have ParameterStates)
- # from PsyNeuLink.Components.Mechanisms.Mechanism import Mechanism
- # from PsyNeuLink.Components.Projections.MappingProjection import MappingProjection
- # if isinstance(self, (Mechanism, MappingProjection)):
- # # NEED TO DO THIS NO MATTER WHAT, SINCE NEED PARAMETER STATES FOR ALL NEW PARAMS
- # # AS IT IS NOW, _instantiate_parameter_states ignores existing parameterStates
- # # but this may cause it to ignore FUNCTION_PARAMS when FUNCTION has changed
- # from PsyNeuLink.Components.States.ParameterState import _instantiate_parameter_state
- # for param_name in validated_set_param_names:
- # if not param_name in self.user_params_for_instantiation:
- # _instantiate_parameter_state(owner=self,
- # param_name=param_name,
- # param_value=validated_set[param_name],
- # context=context)
- # MODIFIED 4/17/17 END
-
# If the object's function is being assigned, and it is a class, instantiate it as a Function object
if FUNCTION in validated_set and inspect.isclass(self.function):
self._instantiate_function(context=COMMAND_LINE)
- if OUTPUT_STATES in validated_set:
- self._instantiate_attributes_after_function()
-
-
+ # FIX: WHY SHOULD IT BE CALLED DURING STANDRD INIT PROCEDURE?
+ # # MODIFIED 5/5/17 OLD:
+ # if OUTPUT_STATES in validated_set:
+ # MODIFIED 5/5/17 NEW: [THIS FAILS WITH A SPECIFICATION IN output_states ARG OF CONSTRUCTOR]
+ if OUTPUT_STATES in validated_set and COMMAND_LINE in context:
+ # MODIFIED 5/5/17 END
+ self._instantiate_attributes_after_function(context=COMMAND_LINE)
def reset_params(self, mode=ResetMode.INSTANCE_TO_CLASS):
"""Reset current and/or instance defaults
@@ -1589,11 +1618,6 @@ def _validate_variable(self, variable, context=None):
# Otherwise, do some checking on variable before converting to np.ndarray
- # If variable is a ParamValueProjection tuple, get value:
- from PsyNeuLink.Components.Mechanisms.Mechanism import ParamValueProjection
- if isinstance(variable, ParamValueProjection):
- variable = variable.value
-
# If variable is callable (function or object reference), call it and assign return to value to variable
# Note: check for list is necessary since function references must be passed wrapped in a list so that they are
# not called before being passed
@@ -1644,14 +1668,13 @@ def _validate_params(self, request_set, target_set=None, context=None):
for param_name, param_value in request_set.items():
# Check that param is in paramClassDefaults (if not, it is assumed to be invalid for this object)
- try:
- self.paramClassDefaults[param_name]
- except KeyError:
- # MODIFIED 11/30/16 NEW:
+ if not param_name in self.paramClassDefaults:
+ # these are always allowable since they are attribs of every component
+ if param_name in {VARIABLE, NAME, VALUE, PARAMS}:
+ continue
# function is a class, so function_params has not yet been implemented
if param_name is FUNCTION_PARAMS and inspect.isclass(self.function):
continue
- # MODIFIED 11/30/16 END
raise ComponentError("{0} is not a valid parameter for {1}".format(param_name, self.__class__.__name__))
# The value of the param is None in paramClassDefaults: suppress type checking
@@ -1694,8 +1717,8 @@ def _validate_params(self, request_set, target_set=None, context=None):
# then simply assign value to paramClassDefault (implication of not specifying it explicitly);
# this also allows it to pass the test below and function execution to occur for initialization;
from PsyNeuLink.Components.Projections.Projection import Projection, ProjectionRegistry
- # from PsyNeuLink.Components.Projections.ControlProjection import ControlProjection
- # from PsyNeuLink.Components.Projections.LearningProjection import LearningProjection
+ # from PsyNeuLink.Components.Projections.ModulatoryProjections.ControlProjection import ControlProjection
+ # from PsyNeuLink.Components.Projections.ModulatoryProjections.LearningProjection import LearningProjection
if (((isinstance(param_value, str) and
param_value in {CONTROL_PROJECTION, LEARNING_PROJECTION, LEARNING}) or
isinstance(param_value, Projection) or # These should be just ControlProjection or LearningProjection
@@ -1705,7 +1728,6 @@ def _validate_params(self, request_set, target_set=None, context=None):
# If self is a Function and param is a class ref for function, instantiate it as the function
from PsyNeuLink.Components.Functions.Function import Function_Base
- from PsyNeuLink.Components.ShellClasses import ParamValueProjection
if (isinstance(self, Function_Base) and
inspect.isclass(param_value) and
issubclass(param_value, self.paramClassDefaults[param_name])):
@@ -1714,12 +1736,6 @@ def _validate_params(self, request_set, target_set=None, context=None):
target_set[param_name] = param_value()
continue
- # # MODIFIED 4/18/17 OLD:
- # # Value is a ParamValueProjection or 2-item tuple extract its value for validation below
- # if isinstance(param_value, (ParamValueProjection, tuple)):
- # param_value = self._get_param_value_from_tuple(param_value)
- # MODIFIED 4/18/17 END
-
# Check if param value is of same type as one with the same name in paramClassDefaults;
# don't worry about length
@@ -1796,13 +1812,11 @@ def _validate_params(self, request_set, target_set=None, context=None):
target_set[param_name] = param_value
else:
target_set[param_name] = param_value.copy()
- # MODIFIED 4/3/17 KM adding list/array parameter for noise
-
- # If param is a function_type, allow any other function_type
+ # If param is a function_type (or it has a function attribute that is one), allow any other function_type
elif callable(param_value):
target_set[param_name] = param_value
- elif callable(param_value.function):
+ elif hasattr(param_value, FUNCTION) and callable(param_value.function):
target_set[param_name] = param_value
# Parameter is not a valid type
@@ -1810,27 +1824,33 @@ def _validate_params(self, request_set, target_set=None, context=None):
if type(self.paramClassDefaults[param_name]) is type:
type_name = 'the name of a subclass of ' + self.paramClassDefaults[param_name].__base__.__name__
else:
- type_name = 'an instance of ' + self.paramClassDefaults[param_name].__name__
- raise ComponentError("Value of {0} param ({1}) must be {2} ".
- format(param_name, param_value, type_name))
+ type_name = self.paramClassDefaults[param_name].__class__.__name__
+ raise ComponentError("Value of {} param for {} ({}) must be a {}".
+ format(param_name, self.name, param_value, type_name))
def _get_param_value_from_tuple(self, param_spec):
- """Returns param value (first item) of either a ParamValueProjection or an unnamed (value, projection) tuple
+ """Returns param value (first item) of a (value, projection) tuple
"""
- from PsyNeuLink.Components.Mechanisms.Mechanism import ParamValueProjection
from PsyNeuLink.Components.Projections.Projection import Projection
- # from PsyNeuLink.Components.Projections.ControlProjection import ControlProjection
- # from PsyNeuLink.Components.Projections.LearningProjection import LearningProjection
-
- if isinstance(param_spec, ParamValueProjection):
- value = param_spec.value
+ # from PsyNeuLink.Components.Projections.Modulatory.ControlProjection import ControlProjection
+ # from PsyNeuLink.Components.Projections.Modulatory.LearningProjection import LearningProjection
+ from PsyNeuLink.Components.Projections.ModulatoryProjections.ModulatoryProjection import ModulatoryProjection_Base
+ from PsyNeuLink.Components.States.ModulatorySignals.ModulatorySignal import ModulatorySignal
+ ALLOWABLE_TUPLE_SPEC_KEYWORDS = {CONTROL_PROJECTION, LEARNING_PROJECTION, CONTROL, LEARNING}
+ ALLOWABLE_TUPLE_SPEC_CLASSES = (ModulatoryProjection_Base, ModulatorySignal)
# If the 2nd item is a CONTROL or LEARNING SPEC, return the first item as the value
- elif (isinstance(param_spec, tuple) and len(param_spec) is 2 and
- (param_spec[1] in {CONTROL_PROJECTION, LEARNING_PROJECTION, CONTROL, LEARNING} or
- isinstance(param_spec[1], Projection) or
- (inspect.isclass(param_spec[1]) and issubclass(param_spec[1], Projection)))
- ):
+ if (isinstance(param_spec, tuple) and len(param_spec) is 2 and
+ # # MODIFIED 6/19/17 OLD:
+ # (param_spec[1] in {CONTROL_PROJECTION, LEARNING_PROJECTION, CONTROL, LEARNING} or
+ # isinstance(param_spec[1], Projection) or
+ # (inspect.isclass(param_spec[1]) and issubclass(param_spec[1], Projection)))
+ # MODIFIED 6/19/17 NEW:
+ (param_spec[1] in ALLOWABLE_TUPLE_SPEC_KEYWORDS or
+ isinstance(param_spec[1], ALLOWABLE_TUPLE_SPEC_CLASSES) or
+ (inspect.isclass(param_spec[1]) and issubclass(param_spec[1], ALLOWABLE_TUPLE_SPEC_CLASSES)))
+ # MODIFIED 6/19/17 END
+ ):
value = param_spec[0]
# Otherwise, just return the tuple
@@ -2006,15 +2026,11 @@ def _instantiate_function(self, context=None):
:return:
"""
try:
-
- function = self.paramsCurrent[FUNCTION]
-
- # params[FUNCTION] is NOT implemented
+ function = self.function
+ # self.function is NOT implemented
except KeyError:
-
function = None
-
- # params[FUNCTION] IS implemented
+ # self.function IS implemented
else:
# If FUNCTION is an already instantiated method:
if isinstance(function, method_type):
@@ -2027,7 +2043,7 @@ def _instantiate_function(self, context=None):
if self.prefs.verbosePref:
warnings.warn("{0} ({1}) is not a subclass of Function".
format(FUNCTION,
- self.paramsCurrent[FUNCTION].__class__.__name__,
+ self.function.__class__.__name__,
self.name))
function = None
@@ -2045,7 +2061,7 @@ def _instantiate_function(self, context=None):
elif inspect.isclass(function) and issubclass(function, COMPONENT_BASE_CLASS):
# Check if params[FUNCTION_PARAMS] is specified
try:
- function_param_specs = self.paramsCurrent[FUNCTION_PARAMS].copy()
+ function_param_specs = self.function_params.copy()
except (KeyError, AttributeError):
# FUNCTION_PARAMS not specified, so nullify
function_param_specs = {}
@@ -2060,13 +2076,10 @@ def _instantiate_function(self, context=None):
format(FUNCTION_PARAMS, self.name, function_param_specs))
# parse entries of FUNCTION_PARAMS dict
else:
- # Get param value from any params specified as ParamValueProjection or (param, projection) tuple
+ # Get param value from any params specified in a tuple or a dict
from PsyNeuLink.Components.Projections.Projection import Projection
- from PsyNeuLink.Components.Mechanisms.Mechanism import ParamValueProjection
for param_name, param_spec in function_param_specs.items():
- if isinstance(param_spec, ParamValueProjection):
- from PsyNeuLink.Components.States.ParameterState import ParameterState
- function_param_specs[param_name] = param_spec.value
+ # Get param value from (param, projection) tuple
if (isinstance(param_spec, tuple) and len(param_spec) is 2 and
(param_spec[1] in {MAPPING_PROJECTION, CONTROL_PROJECTION, LEARNING_PROJECTION} or
isinstance(param_spec[1], Projection) or
@@ -2074,6 +2087,9 @@ def _instantiate_function(self, context=None):
):
from PsyNeuLink.Components.States.ParameterState import ParameterState
function_param_specs[param_name] = param_spec[0]
+ # Get param value from VALUE entry of a parameter specification dictionary
+ elif isinstance(param_spec, dict) and VALUE in param_spec:
+ function_param_specs[param_name] = param_spec[VALUE]
# Instantiate function from class specification
function_instance = function(variable_default=self.variable,
@@ -2084,7 +2100,7 @@ def _instantiate_function(self, context=None):
# and would require every function to have the owner arg in its __init__
owner=self,
context=context)
- self.paramsCurrent[FUNCTION] = function_instance.function
+ self.function = function_instance.function
# If in VERBOSE mode, report assignment
if self.prefs.verbosePref:
@@ -2096,16 +2112,16 @@ def _instantiate_function(self, context=None):
except AttributeError:
pass
warnings.warn("{0} assigned as function for {1}".
- format(self.paramsCurrent[FUNCTION].__self__.componentName,
+ format(self.function.__self__.componentName,
object_name))
# FUNCTION is a generic function (presumably user-defined), so "wrap" it in UserDefinedFunction:
# Note: calling UserDefinedFunction.function will call FUNCTION
elif inspect.isfunction(function):
-
+
from PsyNeuLink.Components.Functions.Function import UserDefinedFunction
- self.paramsCurrent[FUNCTION] = UserDefinedFunction(function=function, context=context).function
+ self.function = UserDefinedFunction(function=function, context=context).function
# If FUNCTION is NOT a Function class reference:
# - issue warning if in VERBOSE mode
@@ -2114,7 +2130,7 @@ def _instantiate_function(self, context=None):
if self.prefs.verbosePref:
warnings.warn("{0} ({1}) is not a subclass of Function".
format(FUNCTION,
- self.paramsCurrent[FUNCTION].__class__.__name__,
+ self.function.__class__.__name__,
self.name))
function = None
@@ -2122,13 +2138,13 @@ def _instantiate_function(self, context=None):
if not function:
# Try to assign to self.function
try:
- self.paramsCurrent[FUNCTION] = self.function
+ self.function = self.function
# If self.function is also not implemented, raise exception
# Note: this is a "sanity check," as this should have been checked in _validate_function (above)
except AttributeError:
raise ComponentError("{0} ({1}) is not a Function object or class, "
"and {2}.function is not implemented".
- format(FUNCTION, self.paramsCurrent[FUNCTION],
+ format(FUNCTION, self.function,
self.__class__.__name__))
# If self.function is implemented, warn if in VERBOSE mode
else:
@@ -2136,27 +2152,18 @@ def _instantiate_function(self, context=None):
warnings.warn("{0} ({1}) is not a Function object or a specification for one; "
"{1}.function ({}) will be used instead".
format(FUNCTION,
- self.paramsCurrent[FUNCTION].__self__.componentName,
+ self.function.__self__.componentName,
self.name,
self.function.__self__.name))
- # Now that function has been instantiated, call self.function
- # to assign its output (and type of output) to self.value
- if not context:
- context = "DIRECT CALL"
- # MODIFIED 8/29/16: QUESTION:
- # FIX: ?? SHOULD THIS CALL self.execute SO THAT function IS EVALUATED IN CONTEXT,
- # FIX: AS WELL AS HOW IT HANDLES RETURN VALUES (RE: outputStates AND self.value??
- # ANSWER: MUST BE self.execute AS THE VALUE OF AN OBJECT IS THE OUTPUT OF ITS EXECUTE METHOD, NOT ITS FUNCTION
- # self.value = self.function(context=context+kwSeparator+COMPONENT_INIT)
- self.value = self.execute(context=context)
- if self.value is None:
- raise ComponentError("PROGRAM ERROR: Execute method for {} must return a value".format(self.name))
- self._value_template = self.value
+ # MAKE ASSIGNMENTS
+ # Now that function has been instantiated:
+ # - assign to paramInstanceDefaults
self.paramInstanceDefaults[FUNCTION] = self.function
- # For all components other than a Function itself, assign function_object and function_params
+ # - for all components other than a Function itself,
+ # assign function_object, function_params dict, and function's parameters from any ParameterStates
from PsyNeuLink.Components.Functions.Function import Function
if not isinstance(self, Function):
self.function_object = self.function.__self__
@@ -2165,12 +2172,30 @@ def _instantiate_function(self, context=None):
elif self.function_object.owner != self:
raise ComponentError("Function being assigned to {} ({}) belongs to another component: {}".
format(self.name, self.function_object.name, self.function_object.owner.name))
-
+ # sort to maintain alphabetical order of function_params
for param_name in sorted(list(self.function_object.user_params_for_instantiation.keys())):
+ # assign to param to function_params dict
self.function_params.__additem__(param_name,
self.function_object.user_params_for_instantiation[param_name])
+ # # assign values from any ParameterStates the Component may (which it should) have
+ # try:
+ # value_type = type(getattr(self.function_object, '_'+param_name))
+ # param_value = type_match(self._parameter_states[param_name].value, value_type)
+ # except:
+ # pass
+ # else:
+ # setattr(self.function_object, '_'+param_name, param_value)
self.paramInstanceDefaults[FUNCTION_PARAMS] = self.function_params
+ # - call self.execute to get value, since the value of a Component is defined as what is returned by its
+ # execute method, not its function
+ if not context:
+ context = "DIRECT CALL"
+ self.value = self.execute(context=context)
+ if self.value is None:
+ raise ComponentError("PROGRAM ERROR: Execute method for {} must return a value".format(self.name))
+ self._value_template = self.value
+
def _instantiate_attributes_after_function(self, context=None):
pass
@@ -2193,6 +2218,21 @@ def _update_value(self, context=None):
# def variable(self, value):
# self._variable = value
+ def _change_function(self, to_function):
+ pass
+
+ @property
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, value):
+ if not isinstance(value, str):
+ raise ComponentError("Name assigned to {} ({}) must be a string constant".
+ format(self.__class__.__name__, value))
+
+ self._name = value
+
@property
def prefs(self):
# Whenever pref is accessed, use current owner as context (for level checking)
@@ -2330,57 +2370,57 @@ def auto_dependent(self, value):
COMPONENT_BASE_CLASS = Component
-# Autoprop
-# per Bryn Keller
-
-docs = {'foo': 'Foo controls the fooness, as modulated by the the bar',
- 'bar': 'Bar none, the most important property'}
-
def make_property(name, default_value):
backing_field = '_' + name
def getter(self):
- return getattr(self, backing_field)
+ try:
+ # Get value of function param from ParameterState.value of owner
+ # case: request is for the value of a Function parameter for which the owner has a ParameterState
+ # example: slope or intercept parameter of a Linear Function)
+ # rationale: most common and therefore requires the greatest efficiency
+ # note: use backing_field[1:] to get name of parameter as index into _parameter_states)
+ return self.owner._parameter_states[backing_field[1:]].value
+ except (AttributeError, TypeError):
+ try:
+ # Get value of param from component's own ParameterState.value
+ # case: request is for the value of a parameter of a Mechanism or Project that has a ParameterState
+ # example: matrix parameter of a MappingProjection)
+ # rationale: next most common case
+ # note: use backing_field[1:] to get name of parameter as index into _parameter_states)
+ return self._parameter_states[backing_field[1:]].value
+ except (AttributeError, TypeError):
+ # Get value of param from component's attribute
+ # case: request is for the value of an attribute for which the component has no ParameterState
+ # rationale: least common case
+ # example: parameter of a Function belonging to a state (which don't themselves have ParameterStates)
+ # note: use backing_field since referencing property rather than item in _parameter_states)
+ return getattr(self, backing_field)
def setter(self, val):
- # if self.paramValidationPref and hasattr(self, backing_field):
if self.paramValidationPref and hasattr(self, PARAMS_CURRENT):
- self._assign_params(request_set={backing_field[1:]:val},
- context='ATTRIBUTE_SETTER')
+ val_str = val.__class__.__name__
+ curr_context = SET_ATTRIBUTE + ': ' + val_str + ' for ' + backing_field[1:] + ' of ' + self.name
+ self._assign_params(request_set={backing_field[1:]:val}, context=curr_context)
else:
setattr(self, backing_field, val)
- # setattr(self, backing_field, val)
-
# Update user_params dict with new value
self.user_params.__additem__(name, val)
- # # MODIFIED 4/20/17 NEW:
- # # Update parameterState.value if there is one
- # try:
- # if name in self.parameterStates:
- # self.parameterStates[name].baseValue = val
- # # self.parameterStates[name].value = val
- # except AttributeError:
- # pass
- # # MODIFIED 4/20/17 END
-
# If component is a Function and has an owner, update function_params dict for owner
+ # also, get parameter_state_owner if one exists
from PsyNeuLink.Components.Functions.Function import Function_Base
if isinstance(self, Function_Base) and self.owner:
+ param_state_owner = self.owner
self.owner.function_params.__additem__(name, val)
+ else:
+ param_state_owner = self
- # # MODIFIED 4/20/17 NEW:
- # # Update value of owner's parameterState
- # try:
- # if name in self.owner.parameterStates:
- # self.owner.parameterStates[name].baseValue = val
- # # self.owner.parameterStates[name].value = val
- # except AttributeError:
- # pass
- # # MODIFIED 4/20/17 END
-
+ # If the parameter is associated with a ParameterState, assign the value to the ParameterState's variable
+ if hasattr(param_state_owner, '_parameter_states') and name in param_state_owner._parameter_states:
+ param_state_owner._parameter_states[name].variable = val
# Create the property
prop = property(getter).setter(setter)
diff --git a/PsyNeuLink/Components/Functions/Function.py b/PsyNeuLink/Components/Functions/Function.py
index 46cb8fc7a96..ad23a370546 100644
--- a/PsyNeuLink/Components/Functions/Function.py
+++ b/PsyNeuLink/Components/Functions/Function.py
@@ -36,6 +36,10 @@
* `GammaDist`
* `WaldDist`
+Objective Functions:
+ * `Stability`
+ * `Distance`
+
Learning Functions:
* `Reinforcement`
* `BackPropagation`
@@ -46,25 +50,25 @@
--------
A Function is a `component ` that "packages" a function (in its `function ` method)
-for use by other PsyNeuLink components. Every `component ` in PsyNeuLink is assigned a Function; when thata
+for use by other PsyNeuLink components. Every `component ` in PsyNeuLink is assigned a Function; when thata
component is executed, its Function's `function ` is executed. The
`function ` can be any callable operation, although most commonly it is a mathematical operation
-(and, for those, almost always uses a call to one or more numpy functions). There are two reasons PsyNeuLink
+(and, for those, almost always uses a call to one or more numpy functions). There are two reasons PsyNeuLink
packages functions in a Function component: to *manage parameters*, and for *modularity*.
**Manage parameters**. Parameters are attributes of a function that either remain stable over multiple calls to the
-function (e.g., the `gain ` or `bias ` of a `Logistic` function, or the learning rate
+function (e.g., the `gain ` or `bias ` of a `Logistic` function, or the learning rate
of a learning function); or, if they change, they do so less frequently or under the control of different factors
-than the function's variable (i.e., its input). As a consequence, it is useful to manage these separately from the
-function's variable, and not have to provide them every time the function is called. To address this, every
-PsyNeuLink Function has a set of attributes corresponding to the parameters of the function, that can be specified at
-the time the Function is created (in arguments to its constructor), and can be modified independently
-of a call to its :keyword:`function`. Modifications can be directly (e.g., in a script), or by the operation of other
-PsyNeuLink components (e.g., `AdaptiveMechanisms`) by way of `ControlProjections `.
+than the function's variable (i.e., its input). As a consequence, it is useful to manage these separately from the
+function's variable, and not have to provide them every time the function is called. To address this, every
+PsyNeuLink Function has a set of attributes corresponding to the parameters of the function, that can be specified at
+the time the Function is created (in arguments to its constructor), and can be modified independently
+of a call to its :keyword:`function`. Modifications can be directly (e.g., in a script), or by the operation of other
+PsyNeuLink components (e.g., `AdaptiveMechanisms`) by way of `ControlProjections `.
-**Modularity**. By providing a standard interface, any Function assigned to a components in PsyNeuLink can be replaced
-with other PsyNeuLink Functions, or with user-written custom functions so long as they adhere to certain standards
-(the PsyNeuLink :ref:`Function API `).
+**Modularity**. By providing a standard interface, any Function assigned to a components in PsyNeuLink can be replaced
+with other PsyNeuLink Functions, or with user-written custom functions so long as they adhere to certain standards
+(the PsyNeuLink :ref:`Function API `).
.. _Function_Creation:
@@ -86,15 +90,15 @@
Every Function has a `variable ` that provides the input to its
`function ` method. It's core attribute is its `function ` attribute,
-that determines the computation that it carries out. Ths must be a callable object (that is, a python function or
-method of some kind). Unlike other PsyNeuLink `Components`, it *cannot* be (another) Function object (it can't be
+that determines the computation that it carries out. Ths must be a callable object (that is, a python function or
+method of some kind). Unlike other PsyNeuLink `Components`, it *cannot* be (another) Function object (it can't be
"turtles" all the way down!). A Function also has an attribute for each of the parameters of its `function
`. If a Function has been assigned to another component, then it also has an `owner
` attribute that refers to that component. The Function itself is assigned as the component's
`function_object ` attribute. Each of the Function's attributes is also assigned
as an attribute of the `owner `, and those are each associated with with a
`parameterState ` of the `owner `. Projections to those parameterStates can be
-used by `ControlProjections ` to modify the Function's parameters.
+used by `ControlProjections ` to modify the Function's parameters.
COMMENT:
.. _Function_Output_Type_Conversion:
@@ -106,7 +110,7 @@
* FunctionOutputType.NP_1D_ARRAY: return 1d np.array
* FunctionOutputType.NP_2D_ARRAY: return 2d np.array.
-To implement FunctionOutputTypeConversion, the Function's kwFunctionOutputTypeConversion parameter must set to True,
+To implement FunctionOutputTypeConversion, the Function's FUNCTION_OUTPUT_TYPE_CONVERSION parameter must set to True,
and function type conversion must be implemented by its `function ` method
(see `Linear` for an example).
COMMENT
@@ -119,8 +123,8 @@
Functions are not executable objects, but their `function ` can be called. This can be done
directly. More commonly, however, they are called when their `owner ` is executed. The parameters
of the `function ` can be modified when it is executed, by assigning a
-`parameter specification dictionary ` to the **params** argument in the
-call to the `function `. For `mechanisms `, this can also be done by specifying
+`parameter specification dictionary ` to the **params** argument in the
+call to the `function `. For `mechanisms `, this can also be done by specifying
`runtime_params ` for the mechanism when it is `executed `.
Class Reference
@@ -141,6 +145,8 @@
# 'UniformDist`',
# 'GammaDist',
# 'WaldDist',
+# 'Stability`,
+# 'Distance`,
# 'Reinforcement',
# 'BackPropagation',
# 'FunctionError',
@@ -149,18 +155,19 @@
from functools import reduce
from operator import *
from random import randint
-from numpy import sqrt, abs, tanh, exp
-import numpy as np
-import typecheck as tc
+from numpy import abs, tanh, exp
from PsyNeuLink.Components.ShellClasses import *
-from PsyNeuLink.Globals.Registry import register_category
from PsyNeuLink.Globals.Keywords import *
-from PsyNeuLink.Globals.Utilities import random_matrix
+from PsyNeuLink.Globals.Registry import register_category
+from PsyNeuLink.Globals.Utilities import is_matrix
+
+EPSILON = np.finfo(float).eps
FunctionRegistry = {}
+function_keywords = {FUNCTION_OUTPUT_TYPE, FUNCTION_OUTPUT_TYPE_CONVERSION}
class FunctionError(Exception):
def __init__(self, error_value):
@@ -201,6 +208,114 @@ def is_function_type(x):
return False
+# Modulatory Parameters ************************************************************************************************
+
+ADDITIVE_PARAM = 'additive_param'
+MULTIPLICATIVE_PARAM = 'multiplicative_param'
+OVERRIDE_PARAM = 'OVERRIDE'
+DISABLE_PARAM = 'DISABLE'
+
+
+class MultiplicativeParam():
+ attrib_name = MULTIPLICATIVE_PARAM
+ name = 'MULTIPLICATIVE'
+ init_val = 1
+ reduce = lambda x : np.product(np.array(x), axis=0)
+
+
+class AdditiveParam():
+ attrib_name = ADDITIVE_PARAM
+ name = 'ADDITIVE_PARAM'
+ init_val = 0
+ reduce = lambda x : np.sum(np.array(x), axis=0)
+
+# IMPLEMENTATION NOTE: USING A namedtuple DOESN'T WORK, AS CAN'T COPY PARAM IN Component._validate_param
+# ModulationType = namedtuple('ModulationType', 'attrib_name, name, init_val, reduce')
+
+
+class ModulationParam():
+ """Specify parameter of a `Function ` for `modulation ` by a ModulatorySignal
+
+ COMMENT:
+ Each term specifies a different type of modulation used by a `ModulatorySignal`. The first two refer to classes
+ that define the following terms:
+ * attrib_name (*ADDITIVE_PARAM* or *MULTIPLICATIVE_PARAM*): specifies which meta-parameter of the function
+ to use for modulation;
+ * name (str): name of the meta-parameter
+ * init_val (int or float): value with which to initialize the parameter being modulated if it is not otherwise
+ specified
+ * reduce (function): the manner by which to aggregate multiple ModulatorySignals of that type, if the
+ `ParameterState` receives more than one `ModulatoryProjection` of that type.
+ COMMENT
+
+ Attributes
+ ----------
+
+ MULTIPLICATIVE
+ assign the `value ` of the ModulatorySignal to the *MULTIPLICATIVE_PARAM*
+ of the State's `function `;
+
+ ADDITIVE
+ assign the `value ` of the ModulatorySignal to the *ADDITIVE_PARAM*
+ of the State's `function `;
+
+ OVERRIDE
+ assign the `value ` of the ModulatorySignal directly to the State's
+ `value ` (ignoring its `variable ` and `function `);
+
+ DISABLE
+ ignore the ModulatorySignal when calculating the State's `value `.
+ """
+ MULTIPLICATIVE = MultiplicativeParam
+ # MULTIPLICATIVE = ModulationType(MULTIPLICATIVE_PARAM,
+ # 'MULTIPLICATIVE',
+ # 1,
+ # lambda x : np.product(np.array(x), axis=0))
+ ADDITIVE = AdditiveParam
+ # ADDITIVE = ModulationType(ADDITIVE_PARAM,
+ # 'ADDITIVE_PARAM',
+ # 0,
+ # lambda x : np.sum(np.array(x), axis=0))
+ OVERRIDE = OVERRIDE_PARAM
+ DISABLE = DISABLE_PARAM
+
+MULTIPLICATIVE = ModulationParam.MULTIPLICATIVE
+ADDITIVE = ModulationParam.ADDITIVE
+OVERRIDE = ModulationParam.OVERRIDE
+DISABLE = ModulationParam.DISABLE
+
+
+def _is_modulation_param(val):
+ if val in ModulationParam.__dict__.values():
+ return True
+ else:
+ return False
+
+ModulatedParam = namedtuple('ModulatedParam', 'meta_param, function_param, function_param_val')
+
+from PsyNeuLink.Components.Projections.ModulatoryProjections.ModulatoryProjection import ModulatoryProjection_Base
+@tc.typecheck
+def _get_modulated_param(owner, mod_proj:ModulatoryProjection_Base):
+ """Return ModulationParam object, function param name and value of param modulated by ModulatoryProjection
+ """
+
+ # Get function "meta-parameter" object specified in the projection sender's modulation attribute
+ function_mod_meta_param_obj = mod_proj.sender.modulation
+
+ # Get the actual parameter of owner.function_object to be modulated
+ function_param_name = owner.function_object.params[function_mod_meta_param_obj.attrib_name]
+
+ # Get the function parameter's value
+ function_param_value = owner.function_object.params[function_param_name]
+ # MODIFIED 6/9/17 OLD:
+ # if function_param_value is None:
+ # function_param_value = function_mod_meta_param_obj.init_val
+ # MODIFIED 6/9/17 END
+
+ # Return the meta_parameter object, function_param name, and function_param_value
+ return ModulatedParam(function_mod_meta_param_obj, function_param_name, function_param_value)
+
+
# ******************************* get_param_value_for_keyword ********************************************************
def get_param_value_for_keyword(owner, keyword):
@@ -258,7 +373,7 @@ class Function_Base(Function):
Functions are used to "wrap" functions used used by other components;
They are defined here (on top of standard libraries) to provide a uniform interface for managing parameters
(including defaults)
- NOTE: the Function category definition serves primarily as a shell, and as an interface to the Function
+ NOTE: the Function category definition serves primarily as a shell, and as an interface to the Function
class, to maintain consistency of structure with the other function categories;
it also insures implementation of .function for all Function Components
(as distinct from other Function subclasses, which can use a FUNCTION param
@@ -285,7 +400,7 @@ class Function_Base(Function):
FunctionOutputType.RAW_NUMBER, return value is "exposed" as a number
FunctionOutputType.NP_1D_ARRAY, return value is 1d np.array
FunctionOutputType.NP_2D_ARRAY, return value is 2d np.array
- - it must be enabled for a subclass by setting params[kwFunctionOutputTypeConversion] = True
+ - it must be enabled for a subclass by setting params[FUNCTION_OUTPUT_TYPE_CONVERSION] = True
- it must be implemented in the execute method of the subclass
- see Linear for an example
@@ -303,7 +418,7 @@ class Function_Base(Function):
+ registry (dict): FunctionRegistry
+ classPreference (PreferenceSet): ComponentPreferenceSet, instantiated in __init__()
+ classPreferenceLevel (PreferenceLevel): PreferenceLevel.CATEGORY
- + paramClassDefaults (dict): {kwFunctionOutputTypeConversion: :keyword:`False`}
+ + paramClassDefaults (dict): {FUNCTION_OUTPUT_TYPE_CONVERSION: :keyword:`False`}
Class methods:
none
@@ -369,7 +484,7 @@ class Function_Base(Function):
`component ` to which the Function has been assigned.
prefs : PreferenceSet or specification dict : Projection.classPreferences
- the `PreferenceSet` for function. Specified in the `prefs` argument of the constructor for the function;
+ the `PreferenceSet` for function. Specified in the **prefs** argument of the constructor for the function;
if it is not specified, a default is assigned using `classPreferences` defined in __init__.py
(see :doc:`PreferenceSet ` for details).
@@ -390,7 +505,10 @@ class Function_Base(Function):
variableEncodingDim = 1
paramClassDefaults = Component.paramClassDefaults.copy()
- paramClassDefaults.update({kwFunctionOutputTypeConversion: False}) # Enable/disable output type conversion
+ paramClassDefaults.update({
+ FUNCTION_OUTPUT_TYPE_CONVERSION: False, # Enable/disable output type conversion
+ FUNCTION_OUTPUT_TYPE:None # Default is to not convert
+ })
def __init__(self,
variable_default,
@@ -438,19 +556,32 @@ def execute(self, variable=None, params=None, context=None):
@property
def functionOutputType(self):
- if self.paramsCurrent[kwFunctionOutputTypeConversion]:
+ # # MODIFIED 6/11/17 OLD:
+ # if self.paramsCurrent[FUNCTION_OUTPUT_TYPE_CONVERSION]:
+ # MODIFIED 6/11/17 NEW:
+ if hasattr(self, FUNCTION_OUTPUT_TYPE_CONVERSION):
+ # MODIFIED 6/11/17 END
return self._functionOutputType
return None
@functionOutputType.setter
def functionOutputType(self, value):
- if not value and not self.paramsCurrent[kwFunctionOutputTypeConversion]:
+ # Initialize backing field if it has not yet been set
+ # ??or if FunctionOutputTypeConversion is False?? <- FIX: WHY?? [IS THAT A SIDE EFFECT OR PREVIOUSLY USING
+ # FIX: self.paramsCurrent[FUNCTION_OUTPUT_TYPE_CONVERSION]
+ # FIX: TO DECIDE IF ATTRIBUTE EXISTS?
+ # # MODIFIED 6/11/17 OLD:
+ # if not value and not self.paramsCurrent[FUNCTION_OUTPUT_TYPE_CONVERSION]:
+ # MODIFIED 6/11/17 NEW:
+ if value is None and (not hasattr(self, FUNCTION_OUTPUT_TYPE_CONVERSION)
+ or not self.FunctionOutputTypeConversion):
+ # MODIFIED 6/11/17 END
self._functionOutputType = value
return
# Attempt to set outputType but conversion not enabled
- if value and not self.paramsCurrent[kwFunctionOutputTypeConversion]:
+ if value and not self.paramsCurrent[FUNCTION_OUTPUT_TYPE_CONVERSION]:
raise FunctionError("output conversion is not enabled for {0}".format(self.__class__.__name__))
# Bad outputType specification
@@ -530,7 +661,7 @@ class ArgumentTherapy(Function_Base):
`component ` to which the Function has been assigned.
prefs : PreferenceSet or specification dict : Projection.classPreferences
- the `PreferenceSet` for function. Specified in the `prefs` argument of the constructor for the function;
+ the `PreferenceSet` for function. Specified in the **prefs** argument of the constructor for the function;
if it is not specified, a default is assigned using `classPreferences` defined in __init__.py
(see :doc:`PreferenceSet ` for details).
@@ -561,7 +692,7 @@ class Manner(Enum):
# in the initialization call or later (using either _instantiate_defaults or during a function call)
paramClassDefaults = Function_Base.paramClassDefaults.copy()
- paramClassDefaults.update({kwFunctionOutputTypeConversion: True,
+ paramClassDefaults.update({FUNCTION_OUTPUT_TYPE_CONVERSION: True,
PARAMETER_STATE_PARAMS: None
# PROPENSITY: Manner.CONTRARIAN,
# PERTINACITY: 10
@@ -781,7 +912,7 @@ class UserDefinedFunction(Function_Base):
`component ` to which the Function has been assigned.
prefs : PreferenceSet or specification dict : Projection.classPreferences
- the `PreferenceSet` for function. Specified in the `prefs` argument of the constructor for the function;
+ the `PreferenceSet` for function. Specified in the **prefs** argument of the constructor for the function;
if it is not specified, a default is assigned using `classPreferences` defined in __init__.py
(see :doc:`PreferenceSet ` for details).
@@ -793,7 +924,7 @@ class UserDefinedFunction(Function_Base):
paramClassDefaults = Function_Base.paramClassDefaults.copy()
paramClassDefaults.update({
- kwFunctionOutputTypeConversion: False,
+ FUNCTION_OUTPUT_TYPE_CONVERSION: False,
PARAMETER_STATE_PARAMS: None
})
@@ -829,8 +960,53 @@ def function(self,
class CombinationFunction(Function_Base):
+ """Function that combines multiple items, yielding a result with the same shape as its operands
+
+ All CombinationFunctions must have two attributes - multiplicative_param and additive_param -
+ each of which is assigned the name of one of the function's parameters;
+ this is for use by ModulatoryProjections (and, in particular, GatingProjections,
+ when the CombinationFunction is used as the function of an InputState or OutputState).
+
+ """
componentType = COMBINATION_FUNCTION_TYPE
+ # IMPLEMENTATION NOTE: THESE SHOULD SHOULD BE REPLACED WITH ABC WHEN IMPLEMENTED
+ def __init__(self, variable_default,
+ params,
+ owner,
+ prefs,
+ context):
+
+ if not hasattr(self, MULTIPLICATIVE_PARAM):
+ raise FunctionError("PROGRAM ERROR: {} must implement a {} attribute".
+ format(self.__class__.__name__, MULTIPLICATIVE_PARAM))
+
+ if not hasattr(self, ADDITIVE_PARAM):
+ raise FunctionError("PROGRAM ERROR: {} must implement an {} attribute".
+ format(self.__class__.__name__, ADDITIVE_PARAM))
+
+ super().__init__(variable_default=variable_default,
+ params=params,
+ owner=owner,
+ prefs=prefs,
+ context=context)
+
+ @property
+ def multiplicative(self):
+ return getattr(self, self.multiplicative_param)
+
+ @multiplicative.setter
+ def multiplicative(self, val):
+ setattr(self, self.multiplicative_param, val)
+
+ @property
+ def additive(self):
+ return getattr(self, self.additive_param)
+
+ @additive.setter
+ def additive(self, val):
+ setattr(self, self.additive_param, val)
+
class Reduce(CombinationFunction): # ------------------------------------------------------------------------
# FIX: CONFIRM THAT 1D KWEIGHTS USES EACH ELEMENT TO SCALE CORRESPONDING VECTOR IN VARIABLE
@@ -840,6 +1016,8 @@ class Reduce(CombinationFunction): # ------------------------------------------
Reduce( \
variable_default=variableClassDefault, \
operation=SUM, \
+ scale=1.0, \
+ offset=0.0, \
params=None, \
owner=None, \
prefs=None, \
@@ -848,6 +1026,8 @@ class Reduce(CombinationFunction): # ------------------------------------------
.. _Reduce:
Combine values in each of one or more arrays into a single value for each array.
+ Use optional SCALE and OFFSET parameters to linearly transform the resulting value for each array.
+ Returns a scalar value for each array of the input.
COMMENT:
IMPLEMENTATION NOTE: EXTEND TO MULTIDIMENSIONAL ARRAY ALONG ARBITRARY AXIS
@@ -863,6 +1043,14 @@ class Reduce(CombinationFunction): # ------------------------------------------
specifies whether to sum or multiply the elements in `variable ` of
`function `.
+ scale : float
+ specifies a value by which to multiply each element of the output of `function `
+ (see `scale ` for details)
+
+ offset : float
+ specifies a value to add to each element of the output of `function `
+ (see `offset ` for details)
+
params : Optional[Dict[param keyword, param value]]
a `parameter dictionary ` that specifies the parameters for the
function. Values specified for parameters in the dictionary override any assigned to those parameters in
@@ -886,17 +1074,29 @@ class Reduce(CombinationFunction): # ------------------------------------------
determines whether elements of each array in `variable ` of
`function ` are summmed or multiplied.
+ scale : float
+ value is applied multiplicatively to each element of the array after applying the `operation `
+ (see `scale ` for details); this done before applying the `offset `
+ (if it is specified).
+
+ offset : float
+ value is added to each element of the array after applying the `operation `
+ and `scale ` (if it is specified).
+
owner : Mechanism
`component ` to which the Function has been assigned.
prefs : PreferenceSet or specification dict : Projection.classPreferences
- the `PreferenceSet` for function. Specified in the `prefs` argument of the constructor for the function;
+ the `PreferenceSet` for function. Specified in the **prefs** argument of the constructor for the function;
if it is not specified, a default is assigned using `classPreferences` defined in __init__.py
(see :doc:`PreferenceSet ` for details).
"""
componentName = REDUCE_FUNCTION
+ multiplicative_param = SCALE
+ additive_param = OFFSET
+
variableClassDefault = [0, 0]
# variableClassDefault_locked = True
@@ -906,6 +1106,8 @@ class Reduce(CombinationFunction): # ------------------------------------------
def __init__(self,
variable_default=variableClassDefault,
operation: tc.enum(SUM, PRODUCT) = SUM,
+ scale: parameter_spec = 1.0,
+ offset: parameter_spec = 0.0,
params=None,
owner=None,
prefs: is_pref_set = None,
@@ -913,6 +1115,8 @@ def __init__(self,
# Assign args to params and functionParams dicts (kwConstants must == arg names)
params = self._assign_args_to_param_dicts(operation=operation,
+ scale=scale,
+ offset=offset,
params=params)
super().__init__(variable_default=variable_default,
@@ -939,8 +1143,8 @@ def function(self,
time_scale=TimeScale.TRIAL,
context=None):
"""
- Returns a scalar value for each array in `variable ` that is either the sum or
- product of the elements in that array.
+ Calculate sum or product of the elements for each array in `variable `,
+ apply `scale ` and/or `offset `, and return array of resulting values.
Arguments
---------
@@ -969,12 +1173,14 @@ def function(self,
self._check_args(variable=variable, params=params, context=context)
operation = self.paramsCurrent[OPERATION]
+ scale = self.paramsCurrent[SCALE]
+ offset = self.paramsCurrent[OFFSET]
# Calculate using relevant aggregation operation and return
if (operation is SUM):
- result = np.sum(self.variable)
+ result = np.sum(self.variable) * scale + offset
elif operation is PRODUCT:
- result = np.product(self.variable)
+ result = np.product(self.variable) * scale + offset
else:
raise FunctionError("Unrecognized operator ({0}) for Reduce function".
format(self.paramsCurrent[OPERATION].self.Operation.SUM))
@@ -991,9 +1197,9 @@ class LinearCombination(
variable_default, \
weights=None, \
exponents=None, \
- scale=1.0, \
- offset=0.0, \
operation=SUM, \
+ scale=None, \
+ offset=None, \
params=None, \
owner=None, \
name=None, \
@@ -1047,32 +1253,32 @@ class LinearCombination(
variable : 1d or 2d np.array : default variableClassDefault
specifies a template for the arrays to be combined. If it is 2d, all items must have the same length.
- weights : 1d or 2d np.array
+ weights : 1d or 2d np.array : default None
specifies values used to multiply the elements of each array in `variable `.
If it is 1d, its length must equal the number of items in `variable `;
if it is 2d, the length of each item must be the same as those in `variable `,
and there must be the same number of items as there are in `variable `
(see `weights ` for details)
- exponents : 1d or 2d np.array
+ exponents : 1d or 2d np.array : default None
specifies values used to exponentiate the elements of each array in `variable `.
If it is 1d, its length must equal the number of items in `variable `;
if it is 2d, the length of each item must be the same as those in `variable `,
and there must be the same number of items as there are in `variable `
(see `exponents ` for details)
- scale : float
+ operation : SUM or PRODUCT
+ specifies whether the `function ` takes the elementwise (Hadamarad)
+ sum or product of the arrays in `variable `.
+
+ scale : float or np.ndarray : default None
specifies a value by which to multiply each element of the output of `function `
(see `scale ` for details)
- offset : float
+ offset : float or np.ndarray : default None
specifies a value to add to each element of the output of `function `
(see `offset ` for details)
- operation : SUM or PRODUCT
- specifies whether the `function ` takes the elementwise (Hadamarad)
- sum or product of the arrays in `variable `.
-
params : Optional[Dict[param keyword, param value]]
a `parameter dictionary ` that specifies the parameters for the
function. Values specified for parameters in the dictionary override any assigned to those parameters in
@@ -1109,19 +1315,19 @@ class LinearCombination(
In either case, exponentiating is applied after application of the `weights `
(if any are specified).
- scale : float
- value is multiplied by each element of the array after applying the `operation `
- (see `scale ` for details); this done before applying the
- `offset ` (if it is specified).
-
- offset : float
- value is added to each element of the array after applying the `operation `
- and `scale ` (if it is specified).
-
operation : SUM or PRODUCT
determines whether the `function ` takes the elementwise (Hadamard) sum or
product of the arrays in `variable `.
+ scale : float or np.ndarray
+ value is applied multiplicatively to each element of the array after applying the
+ `operation ` (see `scale ` for details);
+ this done before applying the `offset ` (if it is specified).
+
+ offset : float or np.ndarray
+ value is added to each element of the array after applying the `operation `
+ and `scale ` (if it is specified).
+
COMMENT:
function : function
applies the `weights ` and/or `exponents ` to the
@@ -1142,7 +1348,7 @@ class LinearCombination(
`component ` to which the Function has been assigned.
prefs : PreferenceSet or specification dict : Projection.classPreferences
- the `PreferenceSet` for function. Specified in the `prefs` argument of the constructor for the function;
+ the `PreferenceSet` for function. Specified in the **prefs** argument of the constructor for the function;
if it is not specified, a default is assigned using `classPreferences` defined in __init__.py
(see :doc:`PreferenceSet ` for details).
@@ -1156,6 +1362,9 @@ class LinearCombination(
kpRuntimeParamStickyAssignmentPref: PreferenceEntry(False, PreferenceLevel.INSTANCE)
}
+ multiplicative_param = SCALE
+ additive_param = OFFSET
+
variableClassDefault = [2, 2]
# variableClassDefault_locked = True
@@ -1170,24 +1379,30 @@ def __init__(self,
# MODIFIED 2/10/17 OLD: [CAUSING CRASHING FOR SOME REASON]
# # weights:is_numeric_or_none=None,
# # exponents:is_numeric_or_none=None,
- # MODIFIED 2/10/17 NEW:
- weights=None,
- exponents=None,
- scale: parameter_spec = 1.0,
- offset: parameter_spec = 0.0,
- # MODIFIED 2/10/17 END
- operation: tc.enum(SUM, PRODUCT) = SUM,
+ # weights=None,
+ # exponents=None,
+ weights:tc.optional(parameter_spec)=None,
+ exponents:tc.optional(parameter_spec)=None,
+ operation: tc.enum(SUM, PRODUCT)=SUM,
+ # scale=1.0,
+ # offset=0.0,
+ # scale:tc.optional(parameter_spec)=1.0,
+ # offset:tc.optional(parameter_spec)=0.0,
+ # scale:is_numeric_or_none=None,
+ # offset:is_numeric_or_none=None,
+ scale=None,
+ offset=None,
params=None,
owner=None,
prefs: is_pref_set = None,
context=componentName + INITIALIZING):
# Assign args to params and functionParams dicts (kwConstants must == arg names)
- params = self._assign_args_to_param_dicts(scale=scale,
- offset=offset,
- weights=weights,
+ params = self._assign_args_to_param_dicts(weights=weights,
exponents=exponents,
operation=operation,
+ scale=scale,
+ offset=offset,
params=params)
super().__init__(variable_default=variable_default,
@@ -1213,6 +1428,8 @@ def _validate_variable(self, variable, context=None):
# FIX: THEN TEST THAT SHAPES OF EVERY ELEMENT ALONG AXIS 0 ARE THE SAME
# FIX; PUT THIS IN DOCUMENTATION
if isinstance(variable, (list, np.ndarray)):
+ if isinstance(variable, np.ndarray) and not variable.ndim:
+ return
length = 0
for i in range(len(variable)):
if i == 0:
@@ -1230,15 +1447,14 @@ def _validate_variable(self, variable, context=None):
format(variable, self.__class__.__name__))
def _validate_params(self, request_set, target_set=None, context=None):
- """Insure that WEIGHTS and EXPONENTS are lists or np.arrays of numbers with length equal to variable
-
- Args:
- request_set:
- target_set:
- context:
-
- Returns:
-
+ """Validate weghts, exponents, scale and offset parameters
+
+ Check that WEIGHTS and EXPONENTS are lists or np.arrays of numbers with length equal to variable
+ Check that SCALE and OFFSET are either scalars or np.arrays of numbers with length and shape equal to variable
+
+ Note: the checks of compatiability with variable are only performed for validation calls during execution
+ (i.e., from check_args(), since during initialization or COMMAND_LINE assignment,
+ a parameter may be re-assigned before variable assigned during is known
"""
# FIX: MAKE SURE THAT IF OPERATION IS SUBTRACT OR DIVIDE, THERE ARE ONLY TWO VECTORS
@@ -1249,8 +1465,53 @@ def _validate_params(self, request_set, target_set=None, context=None):
if WEIGHTS in target_set and target_set[WEIGHTS] is not None:
target_set[WEIGHTS] = np.atleast_2d(target_set[WEIGHTS]).reshape(-1, 1)
+ if EXECUTING in context:
+ if len(target_set[WEIGHTS]) != len(self.variable):
+ raise FunctionError("Number of weights ({0}) is not equal to number of items in variable ({1})".
+ format(len(target_set[WEIGHTS]), len(self.variable.shape)))
+
if EXPONENTS in target_set and target_set[EXPONENTS] is not None:
target_set[EXPONENTS] = np.atleast_2d(target_set[EXPONENTS]).reshape(-1, 1)
+ if EXECUTING in context:
+ if len(target_set[EXPONENTS]) != len(self.variable):
+ raise FunctionError("Number of exponents ({0}) does not equal number of items in variable ({1})".
+ format(len(target_set[EXPONENTS]), len(self.variable.shape)))
+
+ if SCALE in target_set and target_set[SCALE] is not None:
+ scale = target_set[SCALE]
+ if isinstance(scale, numbers.Number):
+ pass
+ elif isinstance(scale, np.ndarray):
+ target_set[SCALE] = np.array(scale)
+ else:
+ raise FunctionError("{} param of {} ({}) must be a scalar or an np.ndarray".
+ format(SCALE, self.name, scale))
+ if EXECUTING in context:
+ if (isinstance(scale, np.ndarray) and
+ (scale.size != self.variable.size or
+ scale.shape != self.variable.shape)):
+ raise FunctionError("Scale is using Hadamard modulation "
+ "but its shape and/or size (shape: {}, size:{}) "
+ "do not match the variable being modulated (shape: {}, size: {})".
+ format(scale.shape, scale.size, self.variable.shape, self.variable.size))
+
+ if OFFSET in target_set and target_set[OFFSET] is not None:
+ offset = target_set[OFFSET]
+ if isinstance(offset, numbers.Number):
+ pass
+ elif isinstance(offset, np.ndarray):
+ target_set[OFFSET] = np.array(offset)
+ else:
+ raise FunctionError("{} param of {} ({}) must be a scalar or an np.ndarray".
+ format(OFFSET, self.name, offset))
+ if EXECUTING in context:
+ if (isinstance(offset, np.ndarray) and
+ (offset.size != self.variable.size or
+ offset.shape != self.variable.shape)):
+ raise FunctionError("Offset is using Hadamard modulation "
+ "but its shape and/or size (shape: {}, size:{}) "
+ "do not match the variable being modulated (shape: {}, size: {})".
+ format(offset.shape, offset.size, self.variable.shape, self.variable.size))
# if not operation:
# raise FunctionError("Operation param missing")
@@ -1258,6 +1519,7 @@ def _validate_params(self, request_set, target_set=None, context=None):
# raise FunctionError("Operation param ({0}) must be Operation.SUM or Operation.PRODUCT".
# format(operation))
+
def function(self,
variable=None,
params=None,
@@ -1299,11 +1561,22 @@ def function(self,
# Validate variable and assign to self.variable, and validate params
self._check_args(variable=variable, params=params, context=context)
- exponents = self.paramsCurrent[EXPONENTS]
- weights = self.paramsCurrent[WEIGHTS]
- operation = self.paramsCurrent[OPERATION]
- offset = self.paramsCurrent[OFFSET]
- scale = self.paramsCurrent[SCALE]
+ exponents = self.exponents
+ weights = self.weights
+ operation = self.operation
+ # QUESTION: WHICH IS LESS EFFICIENT:
+ # A) UNECESSARY ARITHMETIC OPERATIONS IF SCALE AND/OR OFFSET ARE 1.0 AND 0, RESPECTIVELY?
+ # (DOES THE COMPILER KNOW NOT TO BOTHER WITH MULT BY 1 AND/OR ADD 0?)
+ # B) EVALUATION OF IF STATEMENTS TO DETERMINE THE ABOVE?
+ # IMPLEMENTATION NOTE: FOR NOW, ASSUME B) ABOVE, AND ASSIGN DEFAULT "NULL" VALUES TO offset AND scale
+ if self.offset is None:
+ offset = 0.0
+ else:
+ offset = self.offset
+ if self.scale is None:
+ scale = 1.0
+ else:
+ scale = self.scale
# IMPLEMENTATION NOTE: CONFIRM: SHOULD NEVER OCCUR, AS _validate_variable NOW ENFORCES 2D np.ndarray
# If variable is 0D or 1D:
@@ -1313,9 +1586,6 @@ def function(self,
# FIX FOR EFFICIENCY: CHANGE THIS AND WEIGHTS TO TRY/EXCEPT // OR IS IT EVEN NECESSARY, GIVEN VALIDATION ABOVE??
# Apply exponents if they were specified
if exponents is not None:
- if len(exponents) != len(self.variable):
- raise FunctionError("Number of exponents ({0}) does not equal number of items in variable ({1})".
- format(len(exponents), len(self.variable.shape)))
# Avoid divide by zero warning:
# make sure there are no zeros for an element that is assigned a negative exponent
if INITIALIZING in context and any(not any(i) and j < 0 for i, j in zip(self.variable, exponents)):
@@ -1325,33 +1595,140 @@ def function(self,
# Apply weights if they were specified
if weights is not None:
- if len(weights) != len(self.variable):
- raise FunctionError("Number of weights ({0}) is not equal to number of items in variable ({1})".
- format(len(weights), len(self.variable.shape)))
- else:
- self.variable = self.variable * weights
+ self.variable = self.variable * weights
+
+ # CALCULATE RESULT USING RELEVANT COMBINATION OPERATION AND MODULATION
- # Calculate using relevant aggregation operation and return
if (operation is SUM):
- result = sum(self.variable) * scale + offset
- elif operation is PRODUCT:
- result = reduce(mul, self.variable, 1)
+ if isinstance(scale, numbers.Number):
+ # Scalar scale and offset
+ if isinstance(offset, numbers.Number):
+ result = np.sum(self.variable, axis=0) * scale + offset
+ # Scalar scale and Hadamard offset
+ else:
+ result = np.sum(np.append([self.variable * scale], [offset], axis=0), axis=0)
+ else:
+ # Hadamard scale, scalar offset
+ if isinstance(offset, numbers.Number):
+ result = np.product([np.sum([self.variable], axis=0), scale], axis=0)
+ # Hadamard scale and offset
+ else:
+ hadamard_product = np.product([np.sum([self.variable], axis=0), scale], axis=0)
+ result = np.sum(np.append([hadamard_product], [offset], axis=0), axis=0)
+
+ elif (operation is PRODUCT):
+ product = np.product(self.variable, axis=0)
+ if isinstance(scale, numbers.Number):
+ # Scalar scale and offset
+ if isinstance(offset, numbers.Number):
+ result = product * scale + offset
+ # Scalar scale and Hadamard offset
+ else:
+ result = np.sum(np.append([product], [offset], axis=0), axis=0) + offset
+ else:
+ # Hadamard scale, scalar offset
+ if isinstance(offset, numbers.Number):
+ result = np.product(np.append([product], [scale], axis=0), axis=0) + offset
+ # Hadamard scale and offset
+ else:
+ hadamard_product = np.product(np.append([product], [scale], axis=0), axis=0)
+ result = np.sum(np.append([hadamard_product], [offset], axis=0), axis=0)
+
+ # elif operation is PRODUCT:
+ # result = reduce(mul, self.variable, 1)
+
else:
raise FunctionError("Unrecognized operator ({0}) for LinearCombination function".
format(self.paramsCurrent[OPERATION].self.Operation.SUM))
- # FIX: CONFIRM THAT RETURNS LIST IF GIVEN A LIST
return result
+ @property
+ def offset(self):
+ if not hasattr(self, '_offset'):
+ return None
+ else:
+ return self._offset
+
+ @offset.setter
+ def offset(self, val):
+ self._offset = val
+
+ @property
+ def scale(self):
+ if not hasattr(self, '_scale'):
+ return None
+ else:
+ return self._scale
+
+ @scale.setter
+ def scale(self, val):
+ self._scale = val
+
+
# region *********************************** TRANSFER FUNCTIONS ***********************************************
# endregion
+BOUNDS = 'bounds'
+
class TransferFunction(Function_Base):
- componentType = TRANFER_FUNCTION_TYPE
+ """Function that transforms variable but maintains its shape
+
+ All TransferFunctions must have the attribute `bounds` that specifies the lower and upper limits of the result;
+ if there are none, the attribute is set to `None`; if it has at least one bound, the attribute is set to a
+ tuple specifying the lower and upper bounds, respectively, with `None` as the entry for no bound.
+
+ All TransferFunctions must also have two attributes - multiplicative_param and additive_param -
+ each of which is assigned the name of one of the function's parameters;
+ this is for use by ModulatoryProjections (and, in particular, GatingProjections,
+ when the TransferFunction is used as the function of an InputState or OutputState).
+
+ """
+ componentType = TRANSFER_FUNCTION_TYPE
+
+ # IMPLEMENTATION NOTE: THESE SHOULD SHOULD BE REPLACED WITH ABC WHEN IMPLEMENTED
+ def __init__(self, variable_default,
+ params,
+ owner,
+ prefs,
+ context):
+
+ if not hasattr(self, BOUNDS):
+ raise FunctionError("PROGRAM ERROR: {} must implement a {} attribute".
+ format(self.__class__.__name__, BOUNDS))
+
+ if not hasattr(self, MULTIPLICATIVE_PARAM):
+ raise FunctionError("PROGRAM ERROR: {} must implement a {} attribute".
+ format(self.__class__.__name__, MULTIPLICATIVE_PARAM))
+
+ if not hasattr(self, ADDITIVE_PARAM):
+ raise FunctionError("PROGRAM ERROR: {} must implement an {} attribute".
+ format(self.__class__.__name__, ADDITIVE_PARAM))
+
+ super().__init__(variable_default=variable_default,
+ params=params,
+ owner=owner,
+ prefs=prefs,
+ context=context)
+
+ @property
+ def multiplicative(self):
+ return getattr(self, self.multiplicative_param)
+
+ @multiplicative.setter
+ def multiplicative(self, val):
+ setattr(self, self.multiplicative_param, val)
+
+ @property
+ def additive(self):
+ return getattr(self, self.additive_param)
+ @additive.setter
+ def additive(self, val):
+ setattr(self, self.additive_param, val)
-class Linear(
- TransferFunction): # --------------------------------------------------------------------------------------
+
+class Linear(TransferFunction): # -------------------------------------------------------------------------------------
"""
Linear( \
variable_default, \
@@ -1408,11 +1785,13 @@ class Linear(
value added to each element of `variable ` after applying the `slope `
(if it is specified).
+ bounds : None
+
owner : Mechanism
`component ` to which the Function has been assigned.
prefs : PreferenceSet or specification dict : Projection.classPreferences
- the `PreferenceSet` for function. Specified in the `prefs` argument of the constructor for the function;
+ the `PreferenceSet` for function. Specified in the **prefs** argument of the constructor for the function;
if it is not specified, a default is assigned using `classPreferences` defined in __init__.py
(see :doc:`PreferenceSet ` for details).
@@ -1420,6 +1799,10 @@ class Linear(
componentName = LINEAR_FUNCTION
+ bounds = None
+ multiplicative_param = SLOPE
+ additive_param = INTERCEPT
+
classPreferences = {
kwPreferenceSetName: 'LinearClassPreferences',
kpReportOutputPref: PreferenceEntry(False, PreferenceLevel.INSTANCE),
@@ -1430,7 +1813,7 @@ class Linear(
paramClassDefaults = Function_Base.paramClassDefaults.copy()
paramClassDefaults.update({
- kwFunctionOutputTypeConversion: True,
+ FUNCTION_OUTPUT_TYPE_CONVERSION: True,
PARAMETER_STATE_PARAMS: None
})
@@ -1455,7 +1838,7 @@ def __init__(self,
prefs=prefs,
context=context)
- self.functionOutputType = None
+ # self.functionOutputType = None
def function(self,
variable=None,
@@ -1557,8 +1940,7 @@ def derivative(self, input=None, output=None):
return self.slope
-class Exponential(
- TransferFunction): # ---------------------------------------------------------------------------------
+class Exponential(TransferFunction): # --------------------------------------------------------------------------------
"""
Exponential( \
variable_default, \
@@ -1609,13 +1991,15 @@ class Exponential(
value by which `variable ` is multiplied before exponentiation.
scale : float
- value by which the exponentiated value is multipled.
+ value by which the exponentiated value is multiplied.
+
+ bounds : (0, None)
owner : Mechanism
`component ` to which the Function has been assigned.
prefs : PreferenceSet or specification dict : Projection.classPreferences
- the `PreferenceSet` for function. Specified in the `prefs` argument of the constructor for the function;
+ the `PreferenceSet` for function. Specified in the **prefs** argument of the constructor for the function;
if it is not specified, a default is assigned using `classPreferences` defined in __init__.py
(see :doc:`PreferenceSet ` for details).
@@ -1623,6 +2007,11 @@ class Exponential(
componentName = EXPONENTIAL_FUNCTION
+ bounds = (0, None)
+ multiplicative_param = RATE
+ additive_param = SCALE
+
+
variableClassDefault = 0
paramClassDefaults = Function_Base.paramClassDefaults.copy()
@@ -1757,11 +2146,13 @@ class Logistic(
value added to each element of `variable ` after applying the `gain `
(if it is specified).
+ bounds : (0,1)
+
owner : Mechanism
`component ` to which the Function has been assigned.
prefs : PreferenceSet or specification dict : Projection.classPreferences
- the `PreferenceSet` for function. Specified in the `prefs` argument of the constructor for the function;
+ the `PreferenceSet` for function. Specified in the **prefs** argument of the constructor for the function;
if it is not specified, a default is assigned using `classPreferences` defined in __init__.py
(see :doc:`PreferenceSet ` for details).
@@ -1770,6 +2161,10 @@ class Logistic(
componentName = LOGISTIC_FUNCTION
parameter_keywords.update({GAIN, BIAS})
+ bounds = (0,1)
+ multiplicative_param = GAIN
+ additive_param = BIAS
+
variableClassDefault = 0
paramClassDefaults = Function_Base.paramClassDefaults.copy()
@@ -1860,7 +2255,7 @@ class SoftMax(
.. _SoftMax:
- SoftMax transform of variable (see `The Softmax function and its derivative
+ SoftMax transform of variable (see `The Softmax function and its derivative
`_ for a nice discussion).
Arguments
@@ -1908,11 +2303,14 @@ class SoftMax(
* **PROB**: probabilistically chosen element based on softmax-transformed values after normalizing sum of
values to 1, 0 for all others.
+ bounds : None if `output `==MAX_VAL, else (0,1) : default (0,1)
+
+
owner : Mechanism
`component ` to which the Function has been assigned.
prefs : PreferenceSet or specification dict : Projection.classPreferences
- the `PreferenceSet` for function. Specified in the `prefs` argument of the constructor for the function;
+ the `PreferenceSet` for function. Specified in the **prefs** argument of the constructor for the function;
if it is not specified, a default is assigned using `classPreferences` defined in __init__.py
(see :doc:`PreferenceSet ` for details).
@@ -1920,6 +2318,10 @@ class SoftMax(
componentName = SOFTMAX_FUNCTION
+ bounds = (0,1)
+ multiplicative_param = GAIN
+ additive_param = None
+
variableClassDefault = 0
paramClassDefaults = Function_Base.paramClassDefaults.copy()
@@ -1938,6 +2340,8 @@ def __init__(self,
params = self._assign_args_to_param_dicts(gain=gain,
output=output,
params=params)
+ if output is MAX_VAL:
+ bounds = None
super().__init__(variable_default=variable_default,
params=params,
@@ -1954,7 +2358,7 @@ def function(self,
Return: e**(`gain ` * `variable `) /
sum(e**(`gain ` * `variable `)),
filtered by `ouptput ` specification.
-
+
Arguments
---------
@@ -2017,14 +2421,14 @@ def derivative(self, output, input=None):
"""
derivative(output)
- Calculate the derivative of `function `. If OUTPUT_TYPE for the SoftMax Function is ALL,
+ Calculate the derivative of `function `. If OUTPUT_TYPE for the SoftMax Function is ALL,
return Jacobian matrix (derivative for each element of the output array with respect to each of the others):
COMMENT:
D[j]/S[i] = S[i](d[i,j] - S[j]) where d[i,j]=1 if i==j; d[i,j]=0 if i!=j.
COMMENT
- D\ :sub:`j`\ S\ :sub:`i` = S\ :sub:`i`\ (𝜹\ :sub:`i,j` - S\ :sub:`j`),
- where 𝜹\ :sub:`i,j`\ =1 if i=j and 𝜹\ :sub:`i,j`\ =0 if i≠j.
- If OUTPUT_TYPE is MAX_VAL or MAX_INDICATOR, return 1d array of the derivatives of the maximum
+ D\\ :sub:`j`\\ S\\ :sub:`i` = S\\ :sub:`i`\\ (𝜹\\ :sub:`i,j` - S\\ :sub:`j`),
+ where 𝜹\\ :sub:`i,j`\\ =1 if i=j and 𝜹\\ :sub:`i,j`\\ =0 if i≠j.
+ If OUTPUT_TYPE is MAX_VAL or MAX_INDICATOR, return 1d array of the derivatives of the maximum
value with respect to the others (calculated as above). If OUTPUT_TYPE is PROB, raise an exception
(since it is ambiguous as to which element would have been chosen by the SoftMax function)
@@ -2091,13 +2495,13 @@ class LinearMatrix(TransferFunction): # ---------------------------------------
COMMENT: [CONVERT TO FIGURE]
----------------------------------------------------------------------------------------------------------
- MATRIX FORMAT
+ MATRIX FORMAT
INDICES:
Output elements:
- 0 1 2 3
- 0 [0,0] [0,1] [0,2] [0,3]
- Input elements: 1 [1,0] [1,1] [1,2] [1,3]
- 2 [2,0] [2,1] [2,2] [2,3]
+ 0 1 2 3 4
+ 0 [0,0] [0,1] [0,2] [0,3] [0,4]
+ Input elements: 1 [1,0] [1,1] [1,2] [1,3] [1,4]
+ 2 [2,0] [2,1] [2,2] [2,3] [2,4]
matrix.shape => (input/rows, output/cols)
@@ -2125,6 +2529,8 @@ class LinearMatrix(TransferFunction): # ---------------------------------------
specifies matrix used to transform `variable `
(see `matrix ` for specification details).
+ bounds : None
+
params : Optional[Dict[param keyword, param value]]
a `parameter dictionary ` that specifies the parameters for the
function. Values specified for parameters in the dictionary override any assigned to those parameters in
@@ -2157,7 +2563,7 @@ class LinearMatrix(TransferFunction): # ---------------------------------------
`component ` to which the Function has been assigned.
prefs : PreferenceSet or specification dict : Projection.classPreferences
- the `PreferenceSet` for function. Specified in the `prefs` argument of the constructor for the function;
+ the `PreferenceSet` for function. Specified in the **prefs** argument of the constructor for the function;
if it is not specified, a default is assigned using `classPreferences` defined in __init__.py
(see :doc:`PreferenceSet ` for details).
@@ -2165,25 +2571,29 @@ class LinearMatrix(TransferFunction): # ---------------------------------------
componentName = LINEAR_MATRIX_FUNCTION
+ bounds = None
+ multiplicative_param = None
+ additive_param = None
+
DEFAULT_FILLER_VALUE = 0
variableClassDefault = [DEFAULT_FILLER_VALUE] # Sender vector
paramClassDefaults = Function_Base.paramClassDefaults.copy()
- def matrix_spec(m):
- if m is None:
- return True
- if m in MATRIX_KEYWORD_VALUES:
- return True
- if isinstance(m, (list, np.ndarray, np.matrix, function_type)):
- return True
- return False
+ # def is_matrix_spec(m):
+ # if m is None:
+ # return True
+ # if m in MATRIX_KEYWORD_VALUES:
+ # return True
+ # if isinstance(m, (list, np.ndarray, np.matrix, function_type)):
+ # return True
+ # return False
@tc.typecheck
def __init__(self,
variable_default=variableClassDefault,
- matrix: matrix_spec = None,
+ matrix:tc.optional(is_matrix) = None,
params=None,
owner=None,
prefs: is_pref_set = None,
@@ -2202,29 +2612,26 @@ def __init__(self,
prefs=prefs,
context=context)
- self.matrix = self.instantiate_matrix(self.paramsCurrent[MATRIX])
+ self._matrix = self.instantiate_matrix(self.paramsCurrent[MATRIX])
def _validate_variable(self, variable, context=None):
- """Insure that variable passed to LinearMatrix is a 1D np.array
+ """Insure that variable passed to LinearMatrix is a max 2D np.array
- :param variable: (1D np.array)
+ :param variable: (max 2D np.array)
:param context:
:return:
"""
super()._validate_variable(variable, context)
- # Check that self.variable == 1D
+ # Check that self.variable <= 2D
try:
- is_not_1D = not self.variable.ndim is 1
-
+ if not self.variable.ndim <= 2:
+ raise FunctionError("variable ({0}) for {1} must be a numpy.ndarray of dimension at most 2".format(self.variable, self.__class__.__name__))
except AttributeError:
- raise FunctionError("PROGRAM ERROR: variable ({0}) for {1} should be an np.ndarray".
- format(self.variable, self.__class__.__name__))
- else:
- if is_not_1D:
- raise FunctionError("variable ({0}) for {1} must be a 1D np.ndarray".
+ raise FunctionError("PROGRAM ERROR: variable ({0}) for {1} should be a numpy.ndarray".
format(self.variable, self.__class__.__name__))
+
def _validate_params(self, request_set, target_set=None, context=None):
"""Validate params and assign to targets
@@ -2256,8 +2663,8 @@ def _validate_params(self, request_set, target_set=None, context=None):
# MODIFIED 3/26/17 OLD:
# Check for and validate kwReceiver first, since it may be needed to validate and/or construct the matrix
# First try to get receiver from specification in params
- if kwReceiver in param_set:
- self.receiver = param_set[kwReceiver]
+ if RECEIVER in param_set:
+ self.receiver = param_set[RECEIVER]
# Check that specification is a list of numbers or an np.array
if ((isinstance(self.receiver, list) and all(isinstance(elem, numbers.Number) for elem in self.receiver)) or
isinstance(self.receiver, np.ndarray)):
@@ -2270,7 +2677,7 @@ def _validate_params(self, request_set, target_set=None, context=None):
if (self.owner and self.owner.prefs.verbosePref) or self.prefs.verbosePref:
print("Identity matrix requested but kwReceiver not specified; sender length ({0}) will be used".
format(sender_len))
- self.receiver = param_set[kwReceiver] = sender
+ self.receiver = param_set[RECEIVER] = sender
# # MODIFIED 3/26/17 NEW:
# self.receiver = param_set[kwReceiver] = sender
# MODIFIED 3/26/17 END
@@ -2282,11 +2689,11 @@ def _validate_params(self, request_set, target_set=None, context=None):
for param_name, param_value in param_set.items():
# Receiver param already checked above
- if param_name is kwReceiver:
+ if param_name is RECEIVER:
continue
# Not currently used here
- if param_name is kwFunctionOutputTypeConversion:
+ if param_name in function_keywords:
continue
if param_name is AUTO_DEPENDENT:
@@ -2300,7 +2707,7 @@ def _validate_params(self, request_set, target_set=None, context=None):
continue
# np.matrix or np.ndarray provided, so validate that it is numeric and check dimensions
- elif isinstance(param_value, (np.ndarray, np.matrix)):
+ elif isinstance(param_value, (list, np.ndarray, np.matrix)):
# get dimensions specified by:
# variable (sender): width/cols/outer index
# kwReceiver param: height/rows/inner index
@@ -2330,7 +2737,7 @@ def _validate_params(self, request_set, target_set=None, context=None):
continue
# Identity matrix requested (using keyword), so check send_len == receiver_len
- elif param_value in {IDENTITY_MATRIX, OFF_DIAGNOAL_MATRIX}:
+ elif param_value in {IDENTITY_MATRIX, HOLLOW_MATRIX}:
# Receiver length doesn't equal sender length
if not (self.receiver.shape == sender.shape and self.receiver.size == sender.size):
# if self.owner.prefs.verbosePref:
@@ -2385,7 +2792,7 @@ def _validate_params(self, request_set, target_set=None, context=None):
MATRIX_KEYWORD_NAMES))
else:
message += "Unrecognized param ({}) specified for the {} function of {}".format(param_name,
- self.name,
+ self.componentName,
self.owner.name)
continue
@@ -2393,7 +2800,7 @@ def _validate_params(self, request_set, target_set=None, context=None):
raise FunctionError(message)
def _instantiate_attributes_before_function(self, context=None):
- self.matrix = self.instantiate_matrix(self.matrix)
+ self._matrix = self.instantiate_matrix(self.matrix)
def instantiate_matrix(self, specification, context=None):
"""Implements matrix indicated by specification
@@ -2469,7 +2876,7 @@ def function(self,
def keyword(self, keyword):
- from PsyNeuLink.Components.Projections.MappingProjection import MappingProjection
+ from PsyNeuLink.Components.Projections.PathwayProjections.MappingProjection import MappingProjection
rows = None
cols = None
if isinstance(self, MappingProjection):
@@ -2489,6 +2896,16 @@ def param_function(owner, function):
return function(sender_len, receiver_len)
+# def is_matrix_spec(m):
+# if m is None:
+# return True
+# if isinstance(m, (list, np.ndarray, np.matrix, function_type)):
+# return True
+# if m in MATRIX_KEYWORD_VALUES:
+# return True
+# return False
+
+
def get_matrix(specification, rows=1, cols=1, context=None):
"""Returns matrix conforming to specification with dimensions = rows x cols or None
@@ -2499,7 +2916,7 @@ def get_matrix(specification, rows=1, cols=1, context=None):
+ matrix keyword:
+ AUTO_ASSIGN_MATRIX: IDENTITY_MATRIX if it is square, othwerwise FULL_CONNECTIVITY_MATRIX
+ IDENTITY_MATRIX: 1's on diagonal, 0's elsewhere (must be square matrix), otherwise generates error
- + OFF_DIAGONAL_MATRIX: 0's on diagonal, 1's elsewhere (must be square matrix), otherwise generates error
+ + HOLLOW_MATRIX: 0's on diagonal, 1's elsewhere (must be square matrix), otherwise generates error
+ FULL_CONNECTIVITY_MATRIX: all 1's
+ RANDOM_CONNECTIVITY_MATRIX (random floats uniformly distributed between 0 and 1)
+ 2D list or np.ndarray of numbers
@@ -2507,6 +2924,10 @@ def get_matrix(specification, rows=1, cols=1, context=None):
Returns 2D np.array with length=rows in dim 0 and length=cols in dim 1, or none if specification is not recognized
"""
+
+ if isinstance(specification, list):
+ specification = np.array(specification)
+
# Matrix provided (and validated in _validate_params); convert to np.array
if isinstance(specification, np.matrix):
return np.array(specification)
@@ -2536,7 +2957,7 @@ def get_matrix(specification, rows=1, cols=1, context=None):
format(rows, cols, specification))
return np.identity(rows)
- if specification is OFF_DIAGNOAL_MATRIX:
+ if specification is HOLLOW_MATRIX:
if rows != cols:
raise FunctionError("Sender length ({0}) must equal receiver length ({1}) to use {}".
format(rows, cols, specification))
@@ -2562,165 +2983,130 @@ def get_matrix(specification, rows=1, cols=1, context=None):
class IntegratorFunction(Function_Base):
componentType = INTEGRATOR_FUNCTION_TYPE
-
-# FIX: IF RATE HAS TO BE BETWEEN 0 AND 1, VALIDATE_VARIABLE ACCORDINGLY
-# SEARCH & REPLACE: previous_value -> previous_value
-
# • why does integrator return a 2d array?
-# • does rate have to be between 0 and 1 (if so, validate_variable)
-# • does rate = 0 and rate = 1 have the same meaning for all integration_types?
-# • should we change "integration_type" to "type"??
# • are rate and noise converted to 1d np.array? If not, correct docstring
# • can noise and initializer be an array? If so, validated in validate_param?
-# • time_step_size?? (vs rate??)
-# • can noise be a function now?
-
class Integrator(
IntegratorFunction): # --------------------------------------------------------------------------------
- """
- Integrator( \
- variable_default=None, \
- rate=1.0, \
- integration_type=CONSTANT, \
- noise=0.0, \
- time_step_size=1.0, \
- initializer, \
- params=None, \
- owner=None, \
- prefs=None, \
- )
-
- .. _Integrator:
-
- Integrate current value of `variable ` with its prior value.
-
- Arguments
- ---------
-
- variable_default : number, list or np.array : default variableClassDefault
- specifies a template for the value to be integrated; if it is a list or array, each element is independently
- integrated.
-
- rate : float, list or 1d np.array : default 1.0
- specifies the rate of integration. If it is a list or array, it must be the same length as
- `variable ` (see `rate ` for details).
-
- integration_type : CONSTANT, SIMPLE, ADAPTIVE, DIFFUSION : default CONSTANT
- specifies type of integration (see `integration_type ` for details).
-
- noise : float, PsyNeuLink Function, list or 1d np.array : default 0.0
- specifies random value to be added in each call to `function `. (see
- `noise ` for details).
-
- time_step_size : float : default 0.0
- determines the timing precision of the integration process when `integration_type `
- is set to DIFFUSION (see `time_step_size ` for details.
-
- initializer float, list or 1d np.array : default 0.0
- specifies starting value for integration. If it is a list or array, it must be the same length as
- `variable_default ` (see `initializer ` for details).
-
- params : Optional[Dict[param keyword, param value]]
- a `parameter dictionary ` that specifies the parameters for the
- function. Values specified for parameters in the dictionary override any assigned to those parameters in
- arguments of the constructor.
-
- owner : Component
- `component ` to which to assign the Function.
-
- prefs : Optional[PreferenceSet or specification dict : Function.classPreferences]
- the `PreferenceSet` for the Function. If it is not specified, a default is assigned using `classPreferences`
- defined in __init__.py (see :doc:`PreferenceSet ` for details).
-
-
- Attributes
- ----------
-
- variable : number or np.array
- current input value some portion of which (determined by `rate `) that will be
- added to the prior value; if it is an array, each element is independently integrated.
-
- rate : float or 1d np.array
- determines the rate of integration based on current and prior values. If integration_type is set to ADAPTIVE,
- all elements must be between 0 and 1 (0 = no change; 1 = instantaneous change). If it has a single element, it
- applies to all elements of `variable `; if it has more than one element, each element
- applies to the corresponding element of `variable `.
-
- integration_type : CONSTANT, SIMPLE, ADAPTIVE, DIFFUSION
- specifies type of integration:
- * **CONSTANT**: `previous_value ` + `rate ` +
- `noise ` (ignores `variable `);
- * **SIMPLE**: `previous_value ` + `rate ` *
- `variable ` + `noise `;
- * **ADAPTIVE**: (1-`rate `) * `variable ` +
- (`rate ` * `previous_value `) + `noise `
- (`Weiner filter `_ or
- `Delta rule `_);
- * **DIFFUSION**: `previous_value ` +
- (`rate ` * `previous_value` * `time_step_size `) +
- √(`time_step_size ` * `noise ` * Gaussian(0,1))
- (`Drift Diffusion Model
- `_).
-
- noise : float, function, list, or 1d np.array
- specifies random value to be added in each call to `function `.
-
- If noise is a list or array, it must be the same length as `variable `. If noise is
- specified as a single float or function, while `variable ` is a list or array,
- noise will be applied to each variable element. In the case of a noise function, this means that the function
- will be executed separately for each variable element.
-
- Note that in the case of DIFFUSION, noise must be specified as a float (or list or array of floats) because this
- value will be used to construct the standard DDM probability distribution. For all other types of integration,
- in order to generate random noise, we recommend that you instead select a probability distribution function
- (see `Distribution Functions ` for details), which will generate a new noise value from
- its distribution on each execution. If noise is specified as a float or as a function with a fixed output (or a
- list or array of these), then the noise will simply be an offset that remains the same across all executions.
-
- time_step_size : float
- determines the timing precision of the integration process when `integration_type `
- is set to DIFFUSION (and used to scale the `noise ` parameter appropriately).
-
- initializer : 1d np.array or list
- determines the starting value for integration (i.e., the value to which
- `previous_value ` is set.
-
- If initializer is a list or array, it must be the same length as `variable `. If
- initializer is specified as a single float or function, while `variable ` is a list or
- array, initializer will be applied to each variable element. In the case of an initializer function, this means
- that the function will be executed separately for each variable element.
-
- previous_value : 1d np.array : default variableClassDefault
- stores previous value with which `variable ` is integrated.
-
- owner : Mechanism
- `component ` to which the Function has been assigned.
-
- prefs : PreferenceSet or specification dict : Projection.classPreferences
- the `PreferenceSet` for function. Specified in the `prefs` argument of the constructor for the function;
- if it is not specified, a default is assigned using `classPreferences` defined in __init__.py
- (see :doc:`PreferenceSet ` for details).
-
- """
+ # """
+ # Integrator( \
+ # variable_default=None, \
+ # rate=1.0, \
+ #
+ # noise=0.0, \
+ # time_step_size=1.0, \
+ # initializer, \
+ # params=None, \
+ # owner=None, \
+ # prefs=None, \
+ # )
+ #
+ # .. _Integrator:
+ #
+ # Integrate current value of `variable ` with its prior value.
+ #
+ # Arguments
+ # ---------
+ #
+ # variable_default : number, list or np.array : default variableClassDefault
+ # specifies a template for the value to be integrated; if it is a list or array, each element is independently
+ # integrated.
+ #
+ # rate : float, list or 1d np.array : default 1.0
+ # specifies the rate of integration. If it is a list or array, it must be the same length as
+ # `variable ` (see `rate ` for details).
+ #
+ # noise : float, PsyNeuLink Function, list or 1d np.array : default 0.0
+ # specifies random value to be added in each call to `function `. (see
+ # `noise ` for details).
+ #
+ # time_step_size : float : default 0.0
+ # determines the timing precision of the integration process when `integration_type