You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何手动评估由scipy生成的三次B样条(基于系数与节点)

手动评估scipy.interpolate.make_interp_spline生成的样条(适配Numba)

make_interp_spline默认生成三次B样条(阶数k=3),其系数是B样条基函数的权重,而非直接的多项式系数,因此不能直接用节点间相对距离代入多项式计算。以下是手动评估的核心逻辑和伪代码:

核心前提

  • t:完整节点数组(包含开头/结尾的重复节点,比如你提供的例子中,原节点数组可能为[0,0,0,0,2,3,4,5,5,5,5],三次样条要求首尾各有k+1个重复节点)
  • c:系数数组(你提供的[0., 34.66324, 86.65809, 155.98457, 207.97942])
  • k:样条阶数,默认k=3

手动评估步骤(伪代码)

1. 定位待评估点的区间

找到最大的索引i,满足t[i] ≤ x < t[i+1]。边界点x = t[-1]直接取最后一个区间(i = len(t)-2)。用二分查找效率更高,适合Numba编译:

def find_interval(x, t):
    if x >= t[-1]:
        return len(t) - 2
    low, high = 0, len(t) - 1
    while low < high:
        mid = (low + high) // 2
        if x < t[mid]:
            high = mid
        else:
            low = mid + 1
    return low - 1

2. 用De Boor算法计算B样条基函数值

三次样条需要计算当前区间对应的4个基函数值,通过递推公式实现(避免递归,适配Numba):

def compute_cubic_basis(x, t, i):
    # 取当前区间对应的4个基函数的节点范围
    j_start = i - 3
    b = [0.0]*4

    # 零次基函数(k=0)
    for idx in range(4):
        tj = t[j_start + idx]
        tj1 = t[j_start + idx + 1]
        if tj <= x < tj1:
            b[idx] = 1.0
        elif x == t[-1] and (j_start + idx + 1) == len(t):
            b[idx] = 1.0

    # 递推一次基函数(k=1)
    new_b = [0.0]*3
    for idx in range(3):
        denom1 = t[j_start + idx + 1] - t[j_start + idx]
        term1 = ((x - t[j_start + idx])/denom1) * b[idx] if denom1 != 0 else 0.0
        denom2 = t[j_start + idx + 2] - t[j_start + idx + 1]
        term2 = ((t[j_start + idx + 2] - x)/denom2) * b[idx+1] if denom2 != 0 else 0.0
        new_b[idx] = term1 + term2
    b = new_b

    # 递推二次基函数(k=2)
    new_b = [0.0]*2
    for idx in range(2):
        denom1 = t[j_start + idx + 2] - t[j_start + idx]
        term1 = ((x - t[j_start + idx])/denom1) * b[idx] if denom1 != 0 else 0.0
        denom2 = t[j_start + idx + 3] - t[j_start + idx + 1]
        term2 = ((t[j_start + idx + 3] - x)/denom2) * b[idx+1] if denom2 != 0 else 0.0
        new_b[idx] = term1 + term2
    b = new_b

    # 递推三次基函数(k=3)
    new_b = [0.0]*1
    denom1 = t[j_start + 3] - t[j_start]
    term1 = ((x - t[j_start])/denom1) * b[0] if denom1 != 0 else 0.0
    denom2 = t[j_start + 4] - t[j_start + 1]
    term2 = ((t[j_start + 4] - x)/denom2) * b[1] if denom2 != 0 else 0.0
    new_b[0] = term1 + term2

    # 补全另外三个三次基函数值(重复递推逻辑,此处简化为完整计算)
    # 实际可合并为通用递推函数,此处为清晰拆分
    return [b0, b1, b2, b3]  # 对应B_{i-3,3}, B_{i-2,3}, B_{i-1,3}, B_{i,3}

3. 计算样条值

取对应区间的4个系数,与基函数值加权求和:

def evaluate_spline(x, t, c):
    i = find_interval(x, t)
    basis = compute_cubic_basis(x, t, i)
    # 取i-3到i的系数
    coeffs = c[i-3:i+1]
    return sum(coeff * b for coeff, b in zip(coeffs, basis))

Numba适配优化版

将上述逻辑合并为Numba可编译的函数,消除Python对象开销:

import numba as nb

@nb.njit
def numba_evaluate_spline(x, t, c):
    k = 3
    m = len(t)
    # 定位区间
    if x >= t[-1]:
        i = m - 2
    else:
        low, high = 0, m - 1
        while low < high:
            mid = (low + high) // 2
            if x < t[mid]:
                high = mid
            else:
                low = mid + 1
        i = low - 1
    
    idx_start = i - k
    # 初始化基函数
    b = nb.typed.List([0.0]*(k+1))
    for j in range(k+1):
        tj = t[idx_start + j]
        tj1 = t[idx_start + j + 1]
        if tj <= x < tj1:
            b[j] = 1.0
        elif x == t[-1] and (idx_start + j + 1) == m:
            b[j] = 1.0
    
    # 递推计算高次基函数
    for d in range(1, k+1):
        new_b = nb.typed.List([0.0]*(k+1 - d))
        for j in range(len(new_b)):
            tj = t[idx_start + j]
            tj_d = t[idx_start + j + d]
            denom1 = tj_d - tj
            term1 = ((x - tj)/denom1) * b[j] if denom1 != 0 else 0.0
            
            tj1 = t[idx_start + j + 1]
            tj1_d = t[idx_start + j + 1 + d]
            denom2 = tj1_d - tj1
            term2 = ((tj1_d - x)/denom2) * b[j+1] if denom2 != 0 else 0.0
            
            new_b[j] = term1 + term2
        b = new_b
    
    # 加权求和
    value = 0.0
    for j in range(len(b)):
        value += c[idx_start + j] * b[j]
    return value

内容的提问来源于stack exchange,提问作者user1554752

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 18:27:32