Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connection functions with matrix outputs can sneak past validation #1657

Open
arvoelke opened this issue Dec 5, 2020 · 0 comments
Open

Connection functions with matrix outputs can sneak past validation #1657

arvoelke opened this issue Dec 5, 2020 · 0 comments

Comments

@arvoelke
Copy link
Contributor

arvoelke commented Dec 5, 2020

Describe the bug

It is possible to create a nengo.Connection(..., function=function) where function returns an array with more than one axes (e.g., a matrix), and it can make it past validation as long as the total size of the array matches the expected dimensionality. Rather than failing fast it will fail later during build with a less clear error.

To reproduce

import nengo

with nengo.Network() as model:
    x = nengo.Ensemble(100, 1)
    y = nengo.Ensemble(100, 9)
    nengo.Connection(x, y, function=lambda x: np.eye(3))

with nengo.Simulator(model) as sim:
    sim.step()

Expected behavior

Expected to see a validation error when the connection is created, similar to what you would see if for example function=lambda x: np.ones(8):

ValidationError: Connection.transform: Transform output size (8) not equal to connection output size (9)

Error message and logs

Instead of a validation error, a less clear exception occurs while building:

...
~/anaconda3/envs/nengo/lib/python3.7/site-packages/nengo/builder/connection.py in get_targets(conn, eval_points, dtype)
     86                     "None. Cannot solve for decoders." % (conn,)
     87                 )
---> 88             targets[i] = out
     89 
     90     return targets

ValueError: could not broadcast input array from shape (3,3) into shape (9)

Versions

  • OS: N/A
  • Python: N/A
  • Nengo: latest master
  • Other: N/A

Additional Context

It sneaks past validation because of this line:

return np.asarray(value).size

A solution could be to make sure that the array has at most one axis, as is done when checking the function on a node:

nengo/nengo/node.py

Lines 102 to 109 in 3ac49d6

if result is not None:
result = np.asarray(result)
if len(result.shape) > 1:
raise ValidationError(
"Node output must be a vector (got shape %s)" % (result.shape,),
attr=self.name,
obj=node,
)

By the way, superfluous axes seem to work as long as they are on the outermost dimensions (but not the innermost). That is, function=lambda x: np.ones(9)[None, :] works but function=lambda x: np.ones(9)[:, None] does not:

ValueError: could not broadcast input array from shape (9,1) into shape (9)

(And so there may be some models out there right now that work but accidentally rely on this being able to get past validation.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant