【问题标题】:Sympy lambdify array with shape (n,)形状为 (n,) 的 Sympy lambdify 数组
【发布时间】:2018-07-04 05:56:01
【问题描述】:

我目前对 sympy 有以下“问题”:

我有一个像M = matrix([pi*a, sin(1)*b]) 这样的符号表达式,我想将它传递给lambdify 并传递给数值优化器。问题是优化器需要函数来输入/输出形状为(n,) 的numpy 数组,特别是不是(n,1)

现在我已经能够使用以下代码 (MWE) 实现这一点:

import numpy as np
import sympy as sp
a, b = sp.symbols('a, b')
M = sp.Matrix([2*a, b])
f_tmp = sp.lambdify([[a,b]], M, 'numpy')
fun   = lambda x: np.reshape( f_tmp(x), (2,))

现在,这当然非常难看,因为每次评估 fun 时都需要应用重塑(可能很多次)。有没有办法避免这个问题? Matrix 类根据定义始终是二维的。我尝试使用sympyMutableDenseNDimArray-class,但它们不能与lambdify 一起使用。 (符号变量无法识别)

【问题讨论】:

    标签: sympy


    【解决方案1】:

    一种方法是将矩阵转换为嵌套列表并取第一行:

    fun = sp.lambdify([[a, b]], M.T.tolist()[0], 'numpy')
    

    现在fun([2, 3])[4, 3]。这是一个 Python 列表,而不是 NumPy 数组,但优化器(至少是 SciPy 中的那些)应该可以接受。

    一个也可以

    fun = sp.lambdify([[a, b]], np.squeeze(M), 'numpy')
    

    它还返回一个列表。

    在我的测试中,上面的速度同样快,而且比带有包装功能的版本(np.squeezenp.reshape)快:大约 6 µs 对 9 µs。似乎好处在于消除了一个函数调用。

    【讨论】:

    • 这真的很有帮助! (1,1) 情况似乎只有一个错误:如果我将 np.squeeze(M, axis=1) 用于 (1,1) 矩阵,则结果具有形状 () 而不是预期的 (1 ,)。
    • 第二个选项似乎也返回列表,而不是 np.array。 (使用 sympy 1.1.1 和 numpy 1.14.3)
    • 在这两个方面都是正确的。 (1, 1) 的边缘情况可以用 np.squeeze(np.array(M), axis=1) 修复,但我们没有得到 NumPy 数组的事实表明第一个版本无论如何都更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多