我的目标是用我自己定制的乘法和加法实现来计算一个基本的符号等式,比如ad(b + c).

我试图用我自己的函数来使用lambdify来翻译两个核心的SymPy函数(AddMul),但是我无法识别它们.

在这个阶段,我只是想让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)

哪一种yield

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]

我try 了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)

为了确认语法是否正确,我使用了一个更接近文档的示例,并用SIN实现替换了符号cos函数.

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实现我自己的AddMul函数?

我怀疑我的问题是Add(和Mul)不是SymPy的‘函数’.文档中将它们称为"表达式",这意味着它们在lambdify过程中不会被识别为替换.

我一直在读的一些链接: SymPy cosSymPy Add 一百零二

如有任何建议,我们将不胜感激.感谢你读到这一步.

EDIT: Got a more general case working

它使用lambdifyreplace函数的组合来取代AddMul.然后,此示例计算格式为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)))

哪一种yield

w*z*(x + y)
Max(w, z, lerchphi(x, y))
[36 36]
[36 36]

关于此解决方案,有几点需要注意:

  1. 使用replace函数,您可以将类型替换为函数(type-gt;func).See the docs.
  2. 我用来替换类型的函数必须接受多个输入,因为表达式中的每个类型可能有两个以上的参数(如上例中的Multiply).我只找到了3个接受*args作为输入的函数.它们分别是MinMaxlerchphi.
  3. Max(x, Min(x, y)) = x开始,SymPy简化了MinMax个函数.这意味着我不能同时使用MinMax.所以我用了lerchphiMax.这些函数是任意的,因为我将在下一步将它们的实现转换为自定义函数.然而,这意味着我只能替换两个.
  4. 最后一步是将lerchphiMax转换为定制函数.

推荐答案

对于渐近,加法是一种运算.因此,我不确定是否可以通过传递自定义modules来实现您的目标...

然而,lambdify的核心是打印模块.本质上,lambdify使用一些打印机来生成要计算的表达式的字符串表示.如果你看lambdify‘S签名,你会发现它可以传递一个定制的打印机.

给定一个打印机类,通过_print_Add方法执行与+的加法.实现目标的一种方法是修改NumPyPrinter的这种方法.

from sympy.printing.lambdarepr import NumPyPrinter
import inspect

class MyNumPyPrinter(NumPyPrinter):
    def _print_Add(self, expr, **kwargs):
        str_args = [self.doprint(t) for t in expr.args]
        return "add(*[%s])" % ", ".join(str_args)

f = lambdify([x, y], x + y, printer=MyNumPyPrinter)
print(inspect.getsource(f))
# def _lambdifygenerated(x, y):
#    return add(*[x, y])

print(f(A, B))
# [3 3]

请注意,我不知道这可能会产生什么影响.这是你要找出的...

Python相关问答推荐

如何根据另一列值用字典中的值替换列值

如何在图片中找到这个化学测试条?OpenCV精明边缘检测不会绘制边界框

在内部列表上滚动窗口

Gekko:Spring-Mass系统的参数识别

海运图:调整行和列标签

如何列举Pandigital Prime Set

切片包括面具的第一个实例在内的眼镜的最佳方法是什么?

在Python中管理打开对话框

driver. find_element无法通过class_name找到元素'""

如何使Matplotlib标题以图形为中心,而图例框则以图形为中心

不允许访问非IPM文件夹

为什么np. exp(1000)给出溢出警告,而np. exp(—100000)没有给出下溢警告?

try 检索blob名称列表时出现错误填充错误""

将标签移动到matplotlib饼图中楔形块的开始处

如何删除重复的文字翻拍?

Python:从目录内的文件导入目录

如何在SQLAlchemy + Alembic中定义一个"Index()",在基表中的列上

Polars表达式无法访问中间列创建表达式

将索引表转换为Numy数组

Python:使用asyncio.StreamReader.readline()读取长行