From dd768a0c3d8c3cf24c3aaf383ddabe67a9acb408 Mon Sep 17 00:00:00 2001 From: Marcel Stimberg Date: Thu, 27 Aug 2020 18:05:43 +0200 Subject: [PATCH] Exclude "constant over dt" subexpressions from cycle checking Fixes #1187 --- brian2/equations/equations.py | 14 +++++++++----- brian2/tests/test_equations.py | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/brian2/equations/equations.py b/brian2/equations/equations.py index d4b77c533..aa22af3f8 100644 --- a/brian2/equations/equations.py +++ b/brian2/equations/equations.py @@ -901,14 +901,18 @@ def _sort_subexpressions(self): static_deps = {} for eq in self._equations.values(): if eq.type == SUBEXPRESSION: - static_deps[eq.varname] = [dep for dep in eq.identifiers if - dep in self._equations and - self._equations[dep].type == SUBEXPRESSION] - + # "Constant over dt" subexpressions are implemented like parameters + # and can be considered as not depending on anything + if 'constant over dt' in eq.flags: + static_deps[eq.varname] = [] + else: + static_deps[eq.varname] = [dep for dep in eq.identifiers if + dep in self._equations and + self._equations[dep].type == SUBEXPRESSION] try: sorted_eqs = topsort(static_deps) except ValueError: - raise ValueError('Cannot resolve dependencies between static ' + raise ValueError('Cannot resolve dependencies between ' 'equations, dependencies contain a cycle.') # put the equations objects in the correct order diff --git a/brian2/tests/test_equations.py b/brian2/tests/test_equations.py index 0c614750c..eda780173 100644 --- a/brian2/tests/test_equations.py +++ b/brian2/tests/test_equations.py @@ -485,6 +485,20 @@ def test_extract_subexpressions(): assert constant['s2'].type == SUBEXPRESSION +@pytest.mark.codegen_independent +def test_cyclical_subexpressions(): + with pytest.raises(ValueError): + # dependency cycle + Equations('''dv/dt = (-v + s1)/ (10*ms) : 1 + s1 = 2 * s2 : 1 + s2 = s1/2 : 1''') + + # With constant over dt, the cycle disappears + Equations('''dv/dt = (-v + s1)/ (10*ms) : 1 + s1 = 2 * s2 : 1 + s2 = s1/2 : 1 (constant over dt)''') + + @pytest.mark.codegen_independent def test_repeated_construction(): eqs1 = Equations('dx/dt = x : 1')