python-SymPy:带(3,n)-数组的lambdified dot()

我有一个lambdified的sympy函数,其中包含一个点积,例如

import numpy as np
import sympy


class dot(sympy.Function):
    pass


x = sympy.Symbol('x')
a = sympy.Matrix([1, 1, 1])
f = dot(x, a)

ff = sympy.lambdify((x), f, modules='numpy')

x = np.random.rand(3)
print(ff(x))  # okay

(奇怪的是,自定义点声明有效.不知道为什么会这样,但请不要介意.如果有更好的解决方案,请告诉我.)

我现在想一次用一堆向量调用ff,所以我去了

x = np.random.rand(3, 10)
print(ff(x))

不好!

ValueError: shapes (3,10) and (3,1) not aligned: 10 (dim 1) != 3 (dim 0)

好吧,所以我将不得不以某种方式转置dot的第一个参数.在sympy.Symbol(‘x’)上使用旧的.T是不合法的.

关于如何从lambdified sympy表达式中产生大量点积的任何提示?

解决方法:

您正在做很多奇怪的事情,但是我不能说这多少归因于MCVE的简化.

首先,对函数的定义更为优雅:

import sympy as sym    

x = sym.Symbol('x')
a = sym.Matrix([1, 1, 1])
dot = sym.Function('dot')
f = dot(x, a)

ff = sym.lambdify(x, f, modules='numpy')

之所以如此,是因为您最初要做的事情是因为您所要做的就是拥有一个说“点”的东西.一旦有了它,lambdify就会将np.dot替换为符号的该部分.

现在,为了完整起见,这是我应该做的事情:

import numpy as np

a = np.array([[1],[1],[1]])
ff = lambda x,a=a: np.dot(x,a)

我知道这可能不是您实际问题中的选择,但是我的经验是,如果可以在没有符号数学的情况下完成某些工作,那么这样做是值得的.

现在,为您的错误.错误很明显,数学也很清楚.您定义了一个函数,该函数对于任何输入x都会使用3d列向量a计算x * a.正如错误所暗示的,这在非常有限的情况下是有意义的.如果两个操作数都是3元素1d数组,则将是有意义的,在这种情况下,将返回标量积.但是,由于您的一个操作数固定为形状(3,1),因此np.dot仅执行矩阵乘法(对于矢量输入,将返回一个1元素的1d数组而不是标量).根据您的定义,它仅适用于可以从右边乘以a的矩阵,即形状(N,3)的矩阵.显然,您的输入并非如此.

您应该做的是将x放在数字侧:

x = np.random.rand(3,10)
print(ff(x.T))

这将在函数中输入形状(10,3)的数组,然后将其乘以形状(3,1)中的一个,得到形状为(10,1)的2d数组:列向量,每行包含如果给定输入向量带有a,则为标量积.

另一个选择是交换函数的定义:

f = dot(a.T,x)
ff = sym.lambdify(x, f, modules='numpy')
# or
a = np.array(1,1,1)  # transpose of previous a
ff = lambda x,a=a: np.dot(a,x)

两者都将创建一个函数,将右边的形状数组(1,3)与输入相乘.然后,您输入的形状为(3,10)的x是直接兼容的;输出将是10个标量积的一维数组.
在这个公式中

上一篇:python-Sympy:从数字上找到符号函数的根


下一篇:python-逐字渲染sympy表达式,不做任何简化