diff --git a/CHANGES.rst b/CHANGES.rst index dcef43d69..c4a22dc23 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -42,6 +42,10 @@ Release History - ``SemanticPointer.translate`` and ``PointerSymbol.translate`` now use the ``keys`` argument; previously, this argument was mistakenly ignored. (`#248 `__) +- Fixed an issue where the names of iteratively generated semantic pointers + could grow exponentially in length, by truncating them at 1 KB. + (`#244 `__, + `#246 `__) 1.0.1 (December 14, 2019) diff --git a/LICENSE.rst b/LICENSE.rst index 902a18068..d550be43e 100644 --- a/LICENSE.rst +++ b/LICENSE.rst @@ -29,7 +29,7 @@ Licensed code Nengo SPA imports several open source libraries. * `NumPy `_ - Used under - `BSD license `__ + `BSD license `__ * `Sphinx `_ - Used under `BSD license `__ * `nbsphinx `_ - Used under diff --git a/docs/user-guide/spa-intro.rst b/docs/user-guide/spa-intro.rst index 2309159fb..6f82c7eaa 100644 --- a/docs/user-guide/spa-intro.rst +++ b/docs/user-guide/spa-intro.rst @@ -126,7 +126,7 @@ example of an SPA to date. nonlinear dynamical arm model). Central information manipulation depends on syntaictic structure for several tasks. Control is largely captured by the basal ganglia aciton selection elements. Memory and learning take place in - both basal ganglia and contex. The model itself consists of just under + both basal ganglia and cortex. The model itself consists of just under a million spiking neurons. Let us consider how the model would perform a single run of one of the cognitive diff --git a/nengo_spa/semantic_pointer.py b/nengo_spa/semantic_pointer.py index c28025e61..f0e64a978 100644 --- a/nengo_spa/semantic_pointer.py +++ b/nengo_spa/semantic_pointer.py @@ -42,6 +42,8 @@ class SemanticPointer(Fixed): Name of the Semantic Pointer. """ + MAX_NAME = 1024 + def __init__(self, data, vocab=None, algebra=None, name=None): super(SemanticPointer, self).__init__( TAnyVocab if vocab is None else TVocabulary(vocab) @@ -54,6 +56,9 @@ def __init__(self, data, vocab=None, algebra=None, name=None): self.v.setflags(write=False) self.vocab = vocab + + if name is not None and len(name) > self.MAX_NAME: + name = "%s..." % (name[: self.MAX_NAME - 3]) self.name = name def _get_algebra(cls, vocab, algebra): diff --git a/nengo_spa/tests/test_semantic_pointer.py b/nengo_spa/tests/test_semantic_pointer.py index c0a6e2425..7c7be75b5 100644 --- a/nengo_spa/tests/test_semantic_pointer.py +++ b/nengo_spa/tests/test_semantic_pointer.py @@ -324,6 +324,12 @@ def test_name(): assert (a + unnamed).name is None assert (a * unnamed).name is None + # check that names that blow up exponentially in length are truncated + for i in range(10): + a += a * b + assert len(a.name) == a.MAX_NAME + assert a.name.endswith("...") + def test_translate(rng): v1 = spa.Vocabulary(16, pointer_gen=rng)