【问题标题】:Trying to convert Matlab .m symbolic function file(s) to SymPy symbolic expression试图将 Matlab .m 符号函数文件转换为 SymPy 符号表达式
【发布时间】:2016-09-25 00:47:39
【问题描述】:

我有 Sapwin 4.0 输出的电路传递函数的计算机生成 .m 文件 http://cirlab.dinfo.unifi.it/Sapwin4/

对于我目前的兴趣而言,.m 文件的结构相当简单:

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;

我想将这些 .m 文件中的许多转换为 SymPy 符号表达式,以便进一步进行符号操作

使用 open、infile.read()、索引行、切片以获取 args 和 num 所需的字符串,所有工作

所以我只展示了简化的符号转换步骤,甚至将字符串变量替换为实际字符串:

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))
'''

三引号块显示了我已经尝试过的替代方案,结果相似,底线相同:

TypeError: *: 'function' and 'Symbol' 的操作数类型不受支持

在 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'

我最近在 IPython 和常规控制台上安装的 Anaconda3 Spyder 中看到了类似的错误

sympify 似乎在 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)

.m 文件 den 字符串破坏了它怎么办? 还是我做错了其他方式?

为了更有趣,如果为了安全起见,我在“=”之后更早地分割 .m den 字符串,它包括前导“+”,我得到:

TypeError:一元+的操作数类型错误:'function'

这是一个可以通过过滤解决的问题,但不允许这种单一使用“+”似乎是一个糟糕的假设 传递函数中的分子项很容易为正或负

【问题讨论】:

    标签: python sympy


    【解决方案1】:

    好吧,让我们试着找出最小的失败案例:

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

    这清楚地表明这里的问题是 E1,因为它是 existing function

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

    因此错误消息。解决此问题的一种方法是通过在 locals 参数中覆盖它来指定您不希望 E1 成为函数:

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

    (在您已经完成 var 在命名空间中创建 E1 之后),或者更一般地说,如果您想保护 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})
    

    【讨论】:

    • 我认为一元“+”是一个错误对于开发人员来说是一个问题
    • 一元“+”警告似乎是 sympify 错误的附属,并且当 sympify 输入根据解决方案受到保护时消失,因此 sympify 确实“正确”处理表达式字符串 arg 中的前导一元“+”没有出现在输出符号表达式中
    猜你喜欢
    • 1970-01-01
    • 2015-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多