我的目标是用我自己定制的乘法和加法实现来计算一个基本的符号方程,比如ad(b + c)
。
我试图使用lambdify
来翻译两个核心SymPy函数(Add
和Mul
)与我自己的函数,但我不能让他们识别。
在这个阶段,我只是想让Add
工作。代码在下面。
from sympy import *
import numpy as np
x, y = symbols('x y')
A = [1,1]
B = [2,2]
def addVectors(inA, inB):
print("running addVectors")
return np.add(inA, inB)
# Test vector addition
print(addVectors(A,B))
# Now using lambdify
f = lambdify([x, y], x + y, {"add":addVectors})
print(f(A, B)) # <------- expect [3,3] and addVectors to be run a second time
# but I get the same as this
print(A + B)
从而产生
running addVectors
[3 3]
[1, 1, 2, 2]
[1, 1, 2, 2]
我期望使用自定义的addVectors
函数来计算表达式中的+
运算符。这意味着结果看起来像这样。
running addVectors
[3 3]
running addVectors
[3 3]
[1, 1, 2, 2]
我尝试了几种不同配置的lambdify
线,这些都给予了相同的原始结果。
f = lambdify([x, y], x + y, {"add":addVectors})
f = lambdify([x, y], x + y, {"Add":addVectors})
f = lambdify([x, y], x + y, {"+":addVectors})
f = lambdify([x, y], Add(x,y), {"Add":addVectors})
f = lambdify([x, y], x + y)
为了确认语法是否正确,我使用了一个更接近文档的示例,并将符号cos
函数替换为sin实现。
from sympy import *
import numpy as np
x = symbols('x')
def mysin(x):
print('taking the sin of', x)
return np.sin(x)
print(mysin(1))
f = lambdify(x, cos(x), {'cos': mysin})
f(1)
其如预期的那样工作并且产生
taking the sin of 1
0.8414709848078965
taking the sin of 1
0.8414709848078965
是否可以使用lambdify实现我自己的Add
和Mul
函数?
我怀疑我的问题是Add
(和Mul
)不是SymPy“函数”。文档将它们称为“表达式”,这意味着它们在lambdify
进程中不会被识别为替换。
我阅读过的一些链接:SymPy cosSymPy AddSymPy Lambdify
任何指针将不胜感激。谢谢你阅读到这里。
编辑:得到一个更一般的情况下工作
它使用lambdify
和replace
函数的组合来替换Add
和Mul
。然后,此示例计算ad(b + c)
的表达式,这就是目标。
from sympy import *
import numpy as np
w, x, y, z = symbols('w x y z')
A = [3,3]
B = [2,2]
C = [1,1]
D = [4,4]
def addVectors(*args):
result = args[0]
for arg in args[1:]:
result = np.add(result, arg)
return result
def mulVectors(*args):
result = args[0]
for arg in args[1:]:
result = np.multiply(result, arg)
return result
expr = w*z*(x + y)
print(expr)
expr = expr.replace(Add, lambda *args: lerchphi(*args))
expr = expr.replace(Mul, lambda *args: Max(*args))
print(expr)
f = lambdify([w, x, y, z], expr, {"lerchphi":addVectors, "Max":mulVectors})
print(f(A, B, C, D))
print(mulVectors(A,D,addVectors(B,C)))
从而产生
w*z*(x + y)
Max(w, z, lerchphi(x, y))
[36 36]
[36 36]
使用此解决方案需要注意的几点:
1.使用replace
函数,你可以用一个函数(type -> func)替换一个类型。参见文档。
1.我替换类型的函数必须接受多个输入,因为表达式中的每个类型可能有两个以上的参数(如上面示例中的multiply)。我只找到了3个接受*args
作为输入的函数。它们是Min
、Max
和lerchphi
。
- SymPy简化了
Min
和Max
的功能,因为Max(x, Min(x, y)) = x
。这意味着我不能同时使用Min
和Max
。所以我使用了lerchphi
和Max
。这些函数是任意的,因为我将在下一步中将它们的实现转换为自定义函数。这意味着我只能替换两个。
1.最后一步是将lerchphi
和Max
转换为自定义函数。
2条答案
按热度按时间icomxhvb1#
在sympy中,加法是一种运算。因此,我不确定是否可以通过传入自定义
modules
来实现您的目标…但是,
lambdify
的核心是打印模块。本质上,lambdify
使用某种打印机来生成要计算的表达式的字符串表示。如果你看一下lambdify
的签名,你会发现它可以传递一个自定义打印机。给定一个打印机类,与
+
的加法由_print_Add
方法执行。实现目标的一种方法是修改NumPyPrinter
的这个方法。请注意,我不知道这可能会产生什么影响。那是你自己去发现的。。
8zzbczxx2#
第一个
f
的帮助是:在mysin情况下它产生
sympy
+
生成一个Add
对象但我不知道这些信息是否可以在
lambdify
中使用。我从其他SO知道,lambdify
对sympy做了相当肤浅的词汇翻译。它没有显示出对目标模块(numpy
)有“深入”理解的迹象。lambdify
的文档相当长。我自己还没有全部读过,但我已经回答了一些关于它的问题:(