简体   繁体   English

SymPy - Kronecker Delta Function 评估

[英]SymPy - Kronecker Delta Function Evaluation

I am using SymPy for the numerical analysis of large sets of equations.我正在使用 SymPy 对大型方程组进行数值分析。 Part of my equation contains a Kronecker Delta function acting as an impulse such that when q = 0 -> dirac_delta = 1, otherwise dirac_delta = 0. I need to perform this for values of q = - 10 -> +10 in integer steps of 1.我的等式的一部分包含一个 Kronecker Delta function 作为脉冲,这样当 q = 0 -> dirac_delta = 1 时,否则 dirac_delta = 0。我需要在 integer 步中对 q = - 10 -> +10 的值执行此操作1.

A simplified example of my code is:我的代码的一个简化示例是:

import sympy as sp
import numpy as np

modules = ["numpy", "sympy"]

# Create symbols
q = sp.symbols('q', integer=True)

# Create P_q symbol as a function of q
P_q = sp.symbols('P_q', cls=sp.Function)
P_q = P_q(q)

# Define Equation
# Simplified example KroneckerDelta - when q = 0, P_q = 1, otherwise P_q = 0
P_q_eq = sp.Eq(P_q, sp.KroneckerDelta(0,q))
P_q = sp.KroneckerDelta(0,q)
display(P_q_eq)

# Create a lambda function for fast numerical calculation 
lam_P_q = sp.lambdify(q, P_q, modules)

# Define the values of q
num_points = 21
data = np.linspace(-10, 10, num_points, dtype=int)
#print(data)

ans = lam_P_q(data)
print(ans)

On run I receive an error:在运行时我收到一个错误:

ValueError Traceback (most recent call last) in 36 #print(data) 37 ---> 38 ans = lam_P_q(data) 39 print(ans) 36 #print(data) 37 ---> 38 ans = lam_P_q(data) 39 print(ans) 中的 ValueError Traceback(最近调用最后一次)

in _lambdifygenerated(q) 1 def _lambdifygenerated(q): ----> 2 return ((1 if 0 == q else 0))在 _lambdifygenerated(q) 1 def _lambdifygenerated(q): ----> 2 return ((1 if 0 == q else 0))

ValueError: The truth value of an array with more than one element is ambiguous. ValueError:具有多个元素的数组的真值不明确。 Use a.any() or a.all()使用 a.any() 或 a.all()

My understanding is that I need to add the.any() or.all() because the lambdify is comparing the array q, to a single value 0. So when I modify the input data with.any() or.all() it then returns a single value.我的理解是我需要添加 the.any() or.all() 因为 lambdify 正在将数组 q 与单个值 0 进行比较。所以当我使用 .any() or.all() 修改输入数据时然后它返回一个值。

However, I require a response of 0 or 1 for each value of q - such that it is an impulse response depending on the value of q.但是,我要求每个 q 值的响应为 0 或 1 - 这样它就是一个取决于 q 值的脉冲响应。

print(q)打印(q)

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

I have tried to provide the "0" comparison value as an array of zeroes with equal length to q, but this did not work.我试图将“0”比较值作为长度与 q 相等的零数组提供,但这没有用。

I know that this can be generated with the scipy signal function "signal.unit_impulse(21, 'mid')", but I am unsure how to implement this in the SymPy format for lambdify to output q as outlined just above.我知道这可以用 scipy 信号 function "signal.unit_impulse(21, 'mid')" 生成,但我不确定如何在 SymPy 格式中将其实现为 lambdify 到 output q,如上所述。 I have tried to create a custom module to replace the sp.KroneckerDelta function to perform this but couldn't get a working solution (likely due to a poor implementation):我试图创建一个自定义模块来替换 sp.KroneckerDelta function 来执行此操作,但无法获得有效的解决方案(可能是由于实施不当):

def impulse(num, p):
    val = signal.unit_impulse(num, 'mid')
    j = p + (num-1)/2
    kron_p = int(val[j])
        
    return kron_p

kronecker = {'KroneckerDelta': impulse(21,q)}
modules = [kronecker, "numpy", "sympy"]

Do I need to substitute the values of q into the lambdify function instead - if so, how do I specify a range of values to substitute?我是否需要将 q 的值替换为 lambdify function - 如果是这样,我如何指定要替换的值范围?

I feel like I am doing something fundamentally wrong in my approach and would appreciate help getting what I thought would be a relatively simple thing to do in SymPy to work.我觉得我在我的方法中做了一些根本错误的事情,并且很感激帮助让我认为在 SymPy 中做一件相对简单的事情来工作。 (I am quite new to SymPy and definitely still trying to get my head around it). (我对 SymPy 还很陌生,而且肯定还在努力了解它)。 Thanks.谢谢。

Ur created variable data is a list type looking like this:您创建的变量data是一个列表类型,如下所示:

data = [-10  -9  -8  -7  -6  ... 8   9  10]

lam_P_q(data) is not meant to take a variable with type list . lam_P_q(data)并不意味着采用类型为list的变量。 It is meant to take a single number.它的意思是取一个数字。 In your case for example: data = -10例如,在您的情况下: data = -10

To feed lam_P_q(data) with all single numbers from the data variable, a for loop can be used.要将data变量中的所有单个数字提供给lam_P_q(data) ,可以使用 for 循环。 Below is your modified example:以下是您修改后的示例:

import sympy as sp
import numpy as np
from IPython.display import display


modules = ["numpy", "sympy"]

# Create symbols
q = sp.symbols('q', integer=True)

# Create P_q symbol as a function of q
P_q = sp.symbols('P_q', cls=sp.Function)
P_q = P_q(q)
print(P_q)

# Define Equation
# Simplified example KroneckerDelta - when q = 0, P_q = 1, otherwise P_q = 0
P_q_eq = sp.Eq(P_q, sp.KroneckerDelta(0,q))
P_q = sp.KroneckerDelta(0,q)
display(P_q_eq)

# Create a lambda function for fast numerical calculation 
lam_P_q = sp.lambdify(q, P_q, modules)

# Define the values of q
num_points = 21
data = np.linspace(-10, 10, num_points, dtype=int)
print(data)
#feeding lam_P_q with numbers and saving answers into the list results
results=[]
for num in data:
    ans = lam_P_q(num)
    results.append(ans)

print(results)

This is a bug in lambdify.这是 lambdify 中的错误。 Please open a sympy issue:请打开一个同情问题:

https://github.com/sympy/sympy/issues https://github.com/sympy/sympy/issues

You can work around it by rewriting the KroneckerDelta to a Piecewise:您可以通过将 KroneckerDelta 重写为 Piecewise 来解决这个问题:

In [12]: P_q
Out[12]: 
δ   
 0,q

In [13]: P_q.rewrite(Piecewise)
Out[13]: 
⎧0  for q ≠ 0
⎨            
⎩1  otherwise

In [14]: f = lambdify(q, P_q.rewrite(Piecewise), modules)

In [15]: f(data)
Out[15]: 
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0.])

This is the generated code:这是生成的代码:

In [16]: import inspect

In [18]: print(inspect.getsource(f))
def _lambdifygenerated(q):
    return select([not_equal(q, 0),True], [0,1], default=nan)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM