f5r5e5d
f5r5e5d

Reputation: 3721

Trying to convert Matlab .m symbolic function file(s) to SymPy symbolic expression

I have computer generated .m files for electrical circuit transfer functions output by Sapwin 4.0 http://cirlab.dinfo.unifi.it/Sapwin4/

The .m files have fairly simple structure for my present interests:

function [out]=my003_v1(s,C1,C2,E1,R1,R2);
num = + ( E1 )+ ( E1*C1*R2 +E1*C2*R2 )*s;
den = + ( E1 +1 )+ ( E1*C1*R2 +C1*R2 +C1*R1 +E1*C2*R2 +C2*R2 )*s+ ( E1*C2*C1*R1*R2 +C2*C1*R1*R2 )*s^2;
out = num/den;

I want to convert many of these .m files into SymPy symbolic expressions for further symbolic manipulation

with open, infile.read(), indexing lines, slicing to get desired strings for args and num, den all work

So I just show cut down symbolic conversion steps with even the string variables replaced with the actual strings:

from sympy import symbols, var, sympify

var('s,C1,C2,E1,R1,R2')
'''

#awkward alternative to var:
exp_str='s,C1,C2,E1,R1,R2' + " = symbols('" + 's,C1,C2,E1,R1,R2' + "')"
exec(exp_str)
print(exp_str)
'''

a=sympify(' ( E1 )+ ( E1*C1*R2 +E1*C2*R2 )*s')
'''
# another alternative to sympify:
from sympy.parsing.sympy_parser import (parse_expr,
standard_transformations)

parse_expr(' ( E1 )+ ( E1*C1*R2 +E1*C2*R2 )*s', transformations=(standard_transformations))
'''

The triple quote blocks show alternatives I've already tried with similar results, same bottom line:

TypeError: unsupported operand type(s) for *: 'function' and 'Symbol'

The error report with code ran on SympyLive:

Traceback (most recent call last):
  File "<string>", line 12, in <module>
  File "/base/data/home/apps/s~sympy-live-hrd/46.393464279709602171/sympy/sympy/core/sympify.py", line 322, in sympify
    expr = parse_expr(a, local_dict=locals, transformations=transformations, evaluate=evaluate)
  File "/base/data/home/apps/s~sympy-live-hrd/46.393464279709602171/sympy/sympy/parsing/sympy_parser.py", line 894, in parse_expr
    return eval_expr(code, local_dict, global_dict)
  File "/base/data/home/apps/s~sympy-live-hrd/46.393464279709602171/sympy/sympy/parsing/sympy_parser.py", line 807, in eval_expr
    code, global_dict, local_dict)  # take local objects in preference
  File "<string>", line 1, in <module>
TypeError: unsupported operand type(s) for *: 'function' and 'Symbol'

I see similar error on my Anaconda3 recent install, Spyder, on IPython and regular console

sympify seems to work with similar expression structure in SymPy Live:

>>> sympify(x*y+(z**k+x*y*z)*t)
t(xyz+zk)+xy


... sympify('-(x**k+ y*z*t+ m)*z')
z(−m−tyz−xk)

What about the .m file den string is breaking it? or am I doing it wrong some other way?

for more fun, if I slice the .m den string earlier after the "=" to be safe, it includes the leading "+", and I get:

TypeError: bad operand type for unary +: 'function'

Which is a problem that can be worked around with the filtering but not allowing this unary use of "+" seems be a poor assumption The numerator term in a transfer function may easily be positive or negative

Upvotes: 2

Views: 580

Answers (1)

DSM
DSM

Reputation: 353329

Well, let's try to find the minimum failing case:

>>> a=sympify('E1*C2')
Traceback (most recent call last):
[...]
TypeError: unsupported operand type(s) for *: 'function' and 'Symbol'

which makes it clear it's the E1 which is the problem here, because it's an existing function:

>>> a=sympify('E1')
>>> a
<function E1 at 0x7fcb04c11510>

And thus the error message. One way to get around this would be to specify that you don't want E1 to be the function by overriding it in the locals argument:

>>> a = sympify(' ( E1 )+ ( E1*C1*R2 +E1*C2*R2 )*s', locals={'E1': E1})
>>> a
E1 + s*(C1*E1*R2 + C2*E1*R2)

(after you've already done your var to create E1 in the namespace), or more generally if you wanted to protect everything in your vv:

vv = sympy.var('s,C1,C2,E1,R1,R2')
a=sympify(' ( E1 )+ ( E1*C1*R2 +E1*C2*R2 )*s', locals={str(v):v for v in vv})

Upvotes: 1

Related Questions