【问题标题】:SymPy: lambdify with 2-D inputsSymPy:使用二维输入进行lambdify
【发布时间】:2020-05-31 22:20:29
【问题描述】:

我正在计算一个方阵V,它的每个元素都是我用sympy 计算的积分。我只计算一个定积分V_nm,其结果是一个带有符号索引mn 的数值表达式。说V_nm看起来像这样:

>>> V_nm
sin(3*n)*cos(m)

现在我希望使用mn 作为数组的索引,从V_nm 中创建一个二维数字(不是符号!)矩阵。假设对于 2 x 2 矩阵,给定 V_nm 的结果将是:

[[sin(3)cos(1) sin(3)cos(2)]
 [sin(6)cos(1) sin(6)cos(2)]]

即,n 指定列,m 指定行。 (注意:我在 1 而不是 0 开始 mn,但这没关系)。

我该如何做到这一点?
我知道我可以在列表理解中使用V_nm.subs([(n, ...), (m, ...)]),然后使用evalf(),但这是一条漫长的道路。我希望使用lambdify 来实现这一点。我知道如何将lambdify 用于一维数组。你能告诉我如何为二维数组实现它吗?

【问题讨论】:

    标签: python numpy sympy


    【解决方案1】:

    有 sympy 的 FunctionMatrix 专门针对这种情况。请注意,它使用从零开始的索引:

    In [1]: m, n, i, j = symbols('m, n, i, j')                                                                                        
    
    In [2]: V_nm = FunctionMatrix(m, n, Lambda((i, j), 100*(i+1) + (j+1)))                                                            
    
    In [3]: V_nm                                                                                                                      
    Out[3]: [100⋅i + j + 101]
    
    In [4]: V_nm.subs({m:2, n:3}).as_explicit()                                                                                       
    Out[4]: 
    ⎡101  102  103⎤
    ⎢             ⎥
    ⎣201  202  203⎦
    
    In [5]: lambdify((m, n), V_nm)(2, 3)                                                                                              
    Out[5]: 
    array([[101., 102., 103.],
           [201., 202., 203.]])
    

    【讨论】:

    • 使用 sympy 1.5.1 我在尝试调用 lambdify 时收到关于 FunctionMatrix 未找到的错误。但升级到 sympy 1.6 后,它运行良好。
    【解决方案2】:

    您的要求看起来不像标准功能。但分两步就可以了。先lambdify这个表达式,然后创建一个函数,通过numpy的broadcasting生成想要的二维数组:

    from sympy import sin, cos, lambdify
    from sympy.abc import m, n
    import numpy as np
    
    V_mn = sin(3 * n) * cos(m)
    
    V_mn_np = lambdify((m, n), V_mn)
    # using list comprehension:
    # V_mn_np2D = lambda m, n: np.array([[V_mn_np(i, j) for j in range(n)] for i in range(m)])
    # using numpy's broadcasting (faster for large arrays):
    V_mn_np2D = lambda m, n: V_mn_np(np.arange(m)[:, None], np.arange(n))
    
    V_mn_np2D(2, 2)
    

    要让编号从 1 开始而不是 0,请使用 np.arange(1, m+1)np.arange(1, n+1)

    作为一项测试,100 * m + n 等函数可以轻松验证该方法是否按预期工作。

    W_mn = 100 * m + n
    
    W_mn_np = lambdify((m, n), W_mn)
    W_mn_np2D = lambda m, n: W_mn_np(np.arange(1, m+1)[:, None], np.arange(1, n+1))
    
    W_mn_np2D(2, 3)
    

    输出:

    array([[101, 102, 103],
           [201, 202, 203]])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多