numpy 不使用积分计算分段常数函数的有符号面积

kzipqqlq  于 2023-06-23  发布在  其他
关注(0)|答案(1)|浏览(101)

我用下面的代码在Python中定义了一个step函数。该函数接受数组ax值,应用一些计算,并返回一个步进函数f。另外,我还定义了两个辅助函数rectpsi_j_n。我想计算step_functionpsi_j_n(x, -10, 0)的乘积的有符号面积,而不使用积分,因为它是一个矩形,这就是我要找的面积。
我最初的尝试:

signed_area = 0
for x_values in x:
    signed_area += step_function(x_values, a) * psi_j_n(x_values, -10, 0)

signed_area

是不正确的,因为我缺少矩形底边的长度。当我用手计算面积时,我应该得到0.012。

更新我用下面的代码定义了step函数:

import numpy as np
import matplotlib.pyplot as plt

# Define the step function
def step_function(x, a):
    def rect(x):
        return np.where((x >= 0) & (x < 1), 1, 0)
    
    f = np.sum([a[k-1] * rect(x - k) for k in range(1, len(a) + 1)], axis=0)
    return f

# Set the random seed for reproducibility
np.random.seed(42)

# Generate random values for a_k
N = 10
a = np.array([-0.25091976,  0.90142861,  0.46398788,  0.19731697, -0.68796272,
       -0.68801096, -0.88383278,  0.73235229,  0.20223002,  0.41614516])
#a = np.random.uniform(-1, 1, size=N)

# Define the x-values for plotting
x = np.arange(0, N + 1, 0.01)

# Evaluate the step function at x
y = step_function(x, a)

# Plot the step function
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('f(x)')
plt.title('Step Function Plot')
plt.grid(True)
plt.show()

它产生了图像

下面的代码定义了函数psi_j_n(x, j, n)

def psi(x):
    if 0 <= x < 0.5:
        return 1
    elif 0.5 <= x < 1:
        return -1
    else:
        return 0

def psi_j_n(x, j, n):
    return 2**(j/2) * psi(2**j * x - n)

然后,我想计算step_function(x, a)psi_j_n(x, j, n)的乘积。

lbsnaicq

lbsnaicq1#

正如您所说,代码中唯一缺少的是矩形的底部。你选择0.01,那么为什么不直接将结果乘以0.01呢?

signed_area = 0
for x_values in x:
    signed_area += 0.01*step_function(x_values, a) * psi_j_n(x_values, -10, 0)

signed_area

请注意,我可以将最终结果乘以0.01,这样效率会更高(但无论如何,代码根本没有效率;接下来看看如何使它这样)。但是把它放在那里可以使代码更容易适应每个矩形的面积不恒定的情况。

更高效的版本

您需要的是psi的矢量化版本。实际上,您只能使用标量值调用它,并且它返回标量值。

psi(0.1)
# 1
psi(0.6)
# -1
psi(2)
# 0

我们也希望能够调用

psi([0.1, 0.2, 2])
# array([1,-1,0])

有很多方法可以做到这一点。诀窍是不惜一切代价避免调用循环。一种方法可能是

def psi(x):
    return ((x>=0)&(x<1))*(2*(x<0.5)-1)

或者你也可以使用np.where,就像你已经为另一个函数所做的那样。
既然psi是“向量化的”,那么psi_j_n也是如此,你可以在代码中计算psi_j_n(x,-10,0)(现在有意义了,即使x是一个数组)和step_function(x,a)(又名y)的乘积。
如此简单

psi_j_n(x,-10,0)*y

然后计算它的积分(你说你不想要任何积分,但是因为你的尝试是计算积分,我认为你的意思是你不想在编码之前在一张纸上计算这个积分的公式)。
使用矩形方法的更简单的方法是

(psy_j_n(x,-10,0)*y).sum()*0.01)

实际上是0.012585459687500009

相关问题