我想将 Mathematica 中计算的分段函数输出转换为 Python。从 this 获取灵感Mathematica->Python 转换页面和 this编写分段函数的页面,我有
from numpy import linspace, vectorize, array
from numpy import arctan, log
import matplotlib.pyplot as plt
from sympy.parsing.mathematica import parse
def fun(x,a,b,c):
# string inside parse('') is my mathematica output
if a == 0:
out = parse('a (-I b + x) ArcTan[(b - a)/c]')
else:
out = parse('4 c a^2 Log[c^2 + (x - a)^2]')
return out
a = 0.17
b = 0.44
c = 0.29
x = linspace(0,50,int(1e3))
vfun = vectorize(fun)
y = vfun(x,a,b,c)
yp = 4*c*a**2*log(c**2 + (x - a)**2)
plt.figure()
plt.plot(x,y,'.-')
plt.title('mathematica -> python conversion')
plt.figure()
plt.plot(x,yp,'.-')
plt.title('expected')
plt.show()
情节如下:
而它应该是:
将 Mathematica 转换为 Python 时我是否做错了什么?或者给a
、b
、c
赋值的时候有问题吗? (请注意,这是一个 MWE,我想要转换的 Mathematica 代码比上面显示的要长得多且复杂。)
最佳答案
一个更简单的解决方案是使用eval
。现在我知道 eval
非常危险,但大多数时候它需要用户的输入,但这里的输入已经为我们定义了。
现在来看答案。< br/>
您没有获得预期的输出,因为您的矢量化数组不包含任何 float ,而仅包含mathematica解析器的输出,该解析器返回未评估的字符串,因此我们可以使用 .evalf()
作为@David给出的答案, lambdify()
内部使用 eval()
,或者我们可以直接使用 eval()
。
以下是所使用方法的文档:https://docs.sympy.org/latest/tutorial/basic_operations.html
from numpy import linspace, vectorize, array
from numpy import arctan, log
import matplotlib.pyplot as plt
from sympy.parsing.mathematica import MathematicaParser
def fun(x,a,b,c):
obj = MathematicaParser()
if a == 0:
out = obj.parse('a (-I b + x) ArcTan[(b - a)/c]')
else:
out = obj.parse('4 c a^2 Log[c^2 + (x - a)^2]')
return out
a = 0.17
b = 0.44
c = 0.29
x = linspace(0,50,int(1e3))
yp = 4*c*a**2*log(c**2 + (x - a)**2)
vfun = vectorize(fun)
y = vfun(x,a,b,c)
#Here y is a type <class 'numpy.ndarray'> containing 1000 <class 'numpy.str_'>
#['4*c*a**2*log(c**2+(x-a)**2)' '4*c*a**2*log(c**2+(x-a)**2)'
#'4*c*a**2*log(c**2+(x-a)**2)' '4*c*a**2*log(c**2+(x-a)**2)'
#'4*c*a**2*log(c**2+(x-a)**2)' '4*c*a**2*log(c**2+(x-a)**2)'
#'4*c*a**2*log(c**2+(x-a)**2)' '4*c*a**2*log(c**2+(x-a)**2)'
#....
y = eval(y[0]) #y[0] is '4*c*a**2*log(c**2+(x-a)**2)'
#When we evaluate y[0] we again get y as <class 'numpy.ndarray'> conatining 1000 <class 'numpy.float64'>
#Because x is <class 'numpy.ndarray'> it evaluates the first string over
#all the points in x.
#[-0.07309464 -0.07770262 -0.08110382 -0.0828403 -0.08263539 -0.08052339
#-0.07683235 -0.07203573 -0.06659307 -0.06086366 -0.05509179 -0.04942739
#-0.04395413 -0.03871304 -0.03371924 -0.0289728 -0.02446552 -0.02018495
#.....
plt.figure()
plt.plot(x, y,'.-')
plt.title('mathematica -> python conversion')
plt.figure()
plt.plot(x,yp,'.-')
plt.title('expected')
plt.show()
关于python - 用 Python 重写 Mathematica 输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56321120/