scipy 中连续函数卷积的优化方法

mspsb9vt  于 2022-11-10  发布在  其他
关注(0)|答案(1)|浏览(147)

我尝试用python数值计算以下形式的积分

为了达到这个目的,我首先定义了两组离散的x和t值,假设

x_samples = np.linspace(-10, 10, 100)
t_samples = np.linspace(0, 1, 100)
dx = x_samples[1]-x_samples[0]
dt = t_samples[1]-t_samples[0]

符号化地声明函数g(x,t)等于0,如果t〈0,并且离散化两个函数以积分为

discretG = g(x_samples[None, :], t_samples[:, None])
discretH = h(x_samples[None, :], t_samples[:, None])

然后我试着逃跑

discretF = signal.fftconvolve(discretG, discretH, mode='full') * dx * dt

然而,在基本的测试功能上,例如

g(x,t) = lambda x,t: np.exp(-np.abs(x))+t
h(x,t) = lambda x,t: np.exp(-np.abs(x))-t

我没有找到一个协议之间的数值积分和卷积使用scipy和我想有一个相当快的方式计算这些积分,特别是当我只能访问离散表示的函数,而不是他们的符号之一。

xfyts7mz

xfyts7mz1#

根据你的代码,我假设你想对两个函数gh进行卷积,这两个函数只对[a, b]*[m,n]不为零。
当然,你可以用signal.fftconvolve来计算卷积。关键是不要忘记discretF中的索引与真实的坐标之间的转换。这里我使用插值来计算任意(x,t)

import numpy as np
from scipy import signal, interpolate

a = -1
b = 2
m = -10
n = 15

samples_num = 1000
x_eval_index = 200
t_eval_index = 300

x_samples = np.linspace(a, b, samples_num)
t_samples = np.linspace(m, n, samples_num)
dx = x_samples[1]-x_samples[0]
dt = t_samples[1]-t_samples[0]

g = lambda x,t: np.exp(-np.abs(x))+t
h = lambda x,t: np.exp(-np.abs(x))-t

discretG = g(x_samples[None, :], t_samples[:, None])
discretH = h(x_samples[None, :], t_samples[:, None])

discretF = signal.fftconvolve(discretG, discretH, mode='full')

def compute_f(x, t):
    if x < 2*a or x > 2*b or t < 2*m or t > 2*n:
        return 0
    # use interpolation t get data on new point
    x_samples_for_conv = np.linspace(2*a, 2*b, 2*samples_num-1)
    t_samples_for_conv = np.linspace(2*m, 2*n, 2*samples_num-1)
    f = interpolate.RectBivariateSpline(x_samples_for_conv, t_samples_for_conv, discretF.T)
    return f(x, t)[0, 0] * dx * dt

注意:你可以扩展我的代码,在xy定义的网格上计算卷积,其中xy是一维数组。(在我的代码中,xy现在是浮点数)
您可以使用以下代码来探究“数值积分”和“使用scipy进行卷积”之间的“一致性”(以及上述compute_f函数的正确性):


# how the convolve work

# for 1D f[i]=sigma_{j} g[j]h[i-j]

sum = 0
for y_idx, y in enumerate(x_samples[0:]):
    for s_idx, s in enumerate(t_samples[0:]):
        if x_eval_index - y_idx < 0 or t_eval_index - s_idx < 0:
            continue
        if t_eval_index - s_idx >= len(x_samples[0:]) or x_eval_index - y_idx >= len(t_samples[0:]):
            continue
        sum += discretG[t_eval_index - s_idx, x_eval_index - y_idx] * discretH[s_idx, y_idx] * dx * dt
print("Do discrete convolution manually, I get: %f" % sum)
print("Do discrete convolution using scipy, I get: %f" % (discretF[t_eval_index, x_eval_index] * dx * dt))

# numerical integral

# the x_val and t_val

# take 1D convolution as example, function defined on [a, b], and index of your samples range from [0, samples_num-1]

# after convolution, function defined on [2a, 2b], index of your samples range from [0, 2*samples_num-2]

dx_prime = (b-a) / (samples_num-1)
dt_prime = (n-m) / (samples_num-1)
x_eval = 2*a + x_eval_index * dx_prime
t_eval = 2*m + t_eval_index * dt_prime

sum = 0
for y in x_samples[:]:
    for s in t_samples[:]:
        if x_eval - y < a or x_eval - y > b:
            continue
        if t_eval - s < m or t_eval - s > n:
            continue
        if y < a or y >= b:
            continue
        if s < m or s >= n:
            continue
        sum += g(x_eval - y, t_eval - s) * h(y, s) * dx * dt
print("Do numerical integration, I get: %f" % sum)
print("The convolution result of 'compute_f' is: %f" % compute_f(x_eval, t_eval))

其给出:

Do discrete convolution manually, I get: -154.771369
Do discrete convolution using scipy, I get: -154.771369
Do numerical integration, I get: -154.771369
The convolution result of 'compute_f' is: -154.771369

相关问题