SymPy:带有(3,n) - 阵列的lambdified dot()

时间:2016-07-08 14:36:38

标签: python numpy sympy

我有一个lambdify d sympy函数,其中包含dot个产品,例如,

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

(奇怪的是,自定义dot声明有效。不知道原因究竟是什么,但不要介意。如果有更好的解决方案,请告诉我。)

我现在想立即用一堆矢量打电话给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的第一个参数。使用.T上的旧版sympy.Symbol('x')并不合法。

有关如何使用lambdified sympy表达式制作大量点积的任何提示?

1 个答案:

答案 0 :(得分:3)

你做了很多奇怪的事情,但我不知道这有多少是由于过度简化的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')

这和你原来的kludge工作的原因是因为你要做的就是让某事说“dot”。完成后,lambdify会将np.dot替换为符号的该部分。

现在,为了完整起见,我的方法就是:

import numpy as np

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

我知道这可能不是你实际问题的一个选择,但我的经验是,如果没有符号数学可以完成某些事情,那么值得这样做。

现在,为您的错误。错误非常清楚,数学也是如此。您为任何输入x定义了一个函数,该函数使用3d列向量x*a计算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),则每行包含标量积。

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

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)的输入x可以直接兼容;输出将是10个标量积的1d阵列。 在这个表述中你的