SymPy:从对角矩阵创建一个numpy函数,该函数需要一个numpy数组作为输入。

11

在我找到的一个例子这里基础上,我正在尝试从使用sumpy.diag创建的对角矩阵中创建一个函数。

myM = Matrix([
[x1, 4, 4],
[4, x2, 4],
[4, 4, x3]])  

例如,这是使用此例程创建的:

import sympy as sp
import numpy as np

x1 = sp.Symbol('x1')
x2 = sp.Symbol('x2')
x3 = sp.Symbol('x3')
X = sp.Matrix([x1, x2, x3])

myM = 4 * sp.ones(3, 3)
sp.diag(*X) + myM - sp.diag(*np.diag(myM))

现在我想创建一个函数,使用lambdifyufuncify,它接受一个长度为3的numpy.array(例如np.array([0.1,0.2,0.3]))作为输入,并根据myM生成矩阵作为输出

myM = Matrix([
[0.1, 4, 4],
[4, 0.2, 4],
[4, 4, 0.3]])  
最终我需要使用这种方法符号地创建一个雅可比矩阵: Jacobian 由于计算过程中功能形式可能会发生变化,因此符号计算雅可比矩阵将非常有用。
2个回答

9
从一个数字向量创建一个3×3的矩阵并不是SymPy的功能,因为没有涉及到符号。考虑以下情况,其中参数d是一个包含对角线元素的数组。
def mat(d):
    return np.diag(d-4) + 4

上述函数返回一个二维NumPy数组。要返回一个SymPy矩阵,使用:
def mat(d):
    return sp.Matrix(np.diag(d-4) + 4)

当d的值非常小的时候,减法后再加上一个数可能会导致精度丢失,例如:(1e-20 - 4) + 4 的结果是零。更安全的方法是使用

def mat(d):
    diagmat = np.diag(d) 
    return diagmat + np.fromfunction(lambda i, j: (i != j)*4, diagmat.shape)

不完全是我想要的,但我会使用它,所以谢谢。 - Ohm

5

您可以使用 .subs() 方法将浮点数值替换为相应的符号:

import sympy as sp
import numpy as np

x1 = sp.Symbol('x1')
x2 = sp.Symbol('x2')
x3 = sp.Symbol('x3')
X = sp.Matrix([x1, x2, x3])

myM = 4 * sp.ones(3, 3)
smyM=sp.diag(*X) + myM - sp.diag(*np.diag(myM))

fcoefs = [(a, f) for a, f in (zip([x1, x2, x3], np.array([0.1,0.2,0.3])))]

fmyM = smyM.subs(fcoefs)

smyM
Out[105]: 
Matrix([
[x1,  4,  4],
[ 4, x2,  4],
[ 4,  4, x3]])

fmyM
Out[106]: 
Matrix([
[0.1,   4,   4],
[  4, 0.2,   4],
[  4,   4, 0.3]])

在进行以下操作之后,sympy.matrices.dense.MutableDenseMatrix 矩阵看起来很好:

fmyM @ myM
Out[107]: 
Matrix([
[32.4, 32.4, 32.4],
[32.8, 32.8, 32.8],
[33.2, 33.2, 33.2]])

可能需要将其转换为np.array以便与numpy完全使用

以下是我的一些代码,展示了我使用的模式:

def ysolv(coeffs):
    x,y,a,b,c,d,e = symbols('x y a b c d e')
    ellipse = a*y**2 + b*x*y + c*x + d*y + e - x**2
    y_sols = solve(ellipse, y)
    print(*y_sols, sep='\n')

    num_coefs = [(a, f) for a, f in (zip([a,b,c,d,e], coeffs))]
    y_solsf0 = y_sols[0].subs(num_coefs)
    y_solsf1 = y_sols[1].subs(num_coefs)

    f0 = lambdify([x], y_solsf0)
    f1 = lambdify([x], y_solsf1)
    return f0, f1

f0, f1 = ysolv(t[0])

y0 = [f0(x) for x in xs]
y1 = [f1(x) for x in xs]
...    

来源:https://stackoverflow.com/a/41232062/6876009(是的,我的“feeloutXrange”是一个如此糟糕的hack,以至于必须展示出来)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接