hanspi42 / signalflowgrapher

This Python tool allows you to draw signal-flow graphs, calculate transfer functions (SymPy code is generated for further use in Jupyter notebooks), do graph manipulations (e.g., node elimination and graph transposition), and save a graph as TikZ for use in LaTeX documentation.
Artistic License 2.0
30 stars 6 forks source link

Branch weight 'N' causes crash #2

Closed hanspi42 closed 3 years ago

hanspi42 commented 4 years ago

If a branch has the weight 'N', the app crashes when trying to evaluate (e.g. Mason):

Traceback (most recent call last):
  File "C:\Users\hansp\Desktop\42\SVN\signalflowgrapher\src\signalflowgrapher\gui\conditional_actions\conditional_action.py", line 27, in <lambda>
    signal.connect(lambda *args: action(self._selection, *args))
  File "C:\Users\hansp\Desktop\42\SVN\signalflowgrapher\src\signalflowgrapher\gui\side_widget.py", line 180, in <lambda>
    self.__operation_controller.eliminate_node(sel[0])
  File "C:\Users\hansp\Desktop\42\SVN\signalflowgrapher\src\signalflowgrapher\controllers\operation_controller.py", line 92, in eliminate_node
    self_loops = operation.get_self_loops(node)
  File "C:\Users\hansp\Desktop\42\SVN\signalflowgrapher\src\signalflow_algorithms\algorithms\graph_operations.py", line 93, in get_self_loops
    weight = str(simplify(Mul(parse_expr(loop[0].weight),
  File "C:\Users\hansp\Anaconda3\envs\sfg\lib\site-packages\sympy\core\cache.py", line 94, in wrapper
    retval = cfunc(*args, **kwargs)
  File "C:\Users\hansp\Anaconda3\envs\sfg\lib\site-packages\sympy\core\operations.py", line 31, in __new__
    args = list(map(_sympify, args))
  File "C:\Users\hansp\Anaconda3\envs\sfg\lib\site-packages\sympy\core\sympify.py", line 439, in _sympify
    return sympify(a, strict=True)
  File "C:\Users\hansp\Anaconda3\envs\sfg\lib\site-packages\sympy\core\sympify.py", line 360, in sympify
    raise SympifyError(a)
sympy.core.sympify.SympifyError: SympifyError: <function N at 0x0000017823B83940>

Example: eliminate node 'y' in

e01.zip

hanspi42 commented 3 years ago

Observe: https://docs.sympy.org/dev/gotchas.html#symbols

Possible solutions: restrict allowed symbols; use try/except to prevent crashes

Doeme commented 3 years ago

I typically solve this by passing sympy.abc._clash to sp.sympify, i.e.:

import sympy as sp
from sympy.abc import _clash

expr = sp.sympify("1/I * N", locals = _clash)

Caveat: This removes the special meaning of the imaginary unit i

See also: https://docs.sympy.org/latest/modules/abc.html

hanspi42 commented 3 years ago

Thank you very much! We also use parse_expr(), and I just checked that

parse_expr("1/I * N", local_dict = _clash)

also works. It is a bit annoying that sympify uses local and parse_expr uses local_dict, but I guess that's how it is.

Removing the special meaning of i does not matter here.