Repository: PrincetonUniversity/PsyNeuLink

Issue:
Inconsistent shape of instance_defaults.value between MappingProjection and its function_object
```
>>> import psyneulink as pnl
>>> A = pnl.components.mechanisms.TransferMechanism(default_variable=[0,0,0])
>>> B = pnl.components.mechanisms.TransferMechanism(default_variable=[0,0])
>>> P = pnl.components.projections.MappingProjection(sender=A, reciever=B)
>>> print(P.instance_defaults.value)
[ 0.  0.]
>>> print(P.function_object.instance_defaults.value)
[ 0.  0.  0.]
```

Comments:

Patch:
diff --git a/psyneulink/components/component.py b/psyneulink/components/component.py
index 6fe282529e..2a9f3a19bd 100644
--- a/psyneulink/components/component.py
+++ b/psyneulink/components/component.py
@@ -2649,9 +2649,8 @@ class Component(object):
             kwargs_to_instantiate = function.ClassDefaults.values().copy()
             if function_params is not None:
                 kwargs_to_instantiate.update(**function_params)
-                # matrix is unexpected at this point
                 # default_variable should not be in any function_params but sometimes it is
-                kwargs_to_remove = [MATRIX, 'default_variable']
+                kwargs_to_remove = ['default_variable']
 
                 for arg in kwargs_to_remove:
                     try:
@@ -2659,6 +2658,14 @@ class Component(object):
                     except KeyError:
                         pass
 
+                # matrix is determined from parameter state based on string value in function_params
+                # update it here if needed
+                if MATRIX in kwargs_to_instantiate:
+                    try:
+                        kwargs_to_instantiate[MATRIX] = self.parameter_states[MATRIX].instance_defaults.value
+                    except (AttributeError, KeyError, TypeError):
+                        pass
+
             _, kwargs = prune_unused_args(function.__init__, args=[], kwargs=kwargs_to_instantiate)
             self.function_object = function(default_variable=function_variable, **kwargs)
         else:
diff --git a/psyneulink/components/functions/function.py b/psyneulink/components/functions/function.py
index a3822272a7..e83a9d60fd 100644
--- a/psyneulink/components/functions/function.py
+++ b/psyneulink/components/functions/function.py
@@ -4004,7 +4004,7 @@ class LinearMatrix(TransferFunction):  # ---------------------------------------
     @tc.typecheck
     def __init__(self,
                  default_variable=None,
-                 matrix:tc.optional(is_matrix) = None,
+                 matrix=None,
                  params=None,
                  owner=None,
                  prefs: is_pref_set = None):


Test patch:
diff --git a/tests/projections/test_projections.py b/tests/projections/test_projections.py
new file mode 100644
index 0000000000..482a6ab589
--- /dev/null
+++ b/tests/projections/test_projections.py
@@ -0,0 +1,18 @@
+import numpy as np
+import psyneulink as pnl
+import pytest
+
+
+@pytest.mark.parametrize(
+    'projection_type, sender_variable, receiver_variable, projection_value, function_value',
+    [
+        (pnl.MappingProjection, [0, 0, 0], [0, 0], np.array([0, 0]), np.array([0, 0]))
+    ]
+)
+def test_value_shapes_with_matrix(projection_type, sender_variable, receiver_variable, projection_value, function_value):
+    A = pnl.TransferMechanism(default_variable=sender_variable)
+    B = pnl.TransferMechanism(default_variable=receiver_variable)
+    P = projection_type(sender=A, receiver=B)
+
+    assert P.instance_defaults.value.shape == projection_value.shape
+    assert P.function_object.instance_defaults.value.shape == function_value.shape