# spapi
样条插值
函数库: TyCurveFitting
# 语法
spline = spapi(knots, x, y)
_ = spapi(k, x, y)
_ = spapi([knork1,...,knorkm],[x1,...,xm],y)
_ = spapi(..., "noderiv")
# 说明
spline = spapi(knots, x, y) 返回样条 f,此样条阶数为 k=length(knots) - length(x),节点满足对任意的 j,f(x[j]) = y[:,j]。若 x 含有相同的元素 x[j],则还有
_ = spapi(k, x, y),其中 k 为正整数,指定了样条的阶数为 k。这种情况下,spapi 将会为节点 x 调用 aptknt 函数来指定一个可接受的但不一定是最好的节点序列。换句话说,spapi(k, x, y) 与 spapi(aptknt(x,k), x, y) 具有相同的作用。
_ = spapi([knork1,...,knorkm],[x1,...,xm],y) 返回网格数据的张量积 B 样条插值。此处的 knorki 要么是节点序列,要么指定了用在第i个变元上的多项式的阶数的正整数,此时,spapi 函数将会为第 i 个变元提供对应的节点序列。
_ = spapi(..., "noderiv") 将向量形式或字符串形式的 noderiv 作为其第四个输入参数,其除了将有相同点的数据值分开表示以外与 spapi(..) 没有区别。当存在第四个输入参数的时候,重复点的数据值将被平均以匹配节点序列而不是以微分项相同进入匹配条件,这将会在下述的第一个例子中得到展示。
# 示例
二元样条插值
指令 spapi([0 0 0 0 1 2 2 2 2],[0 1 1 1 2],[2 0 1 2 -1]) 生成了在区间 [0,2] 上的仅在 1 处存在一个内部节点的唯一的三次样条 f,且满足以下五个条件
这包含了 在 1 相交的三个分支,即它们的函数值与前两阶导数值与所给值相同。
以下是使用五次样条在函数值 y 以及 x 处的导数 s 的一个切触插值的例子:
sp = spapi(augknt(x,6,2),[x;x;minimum(x);maximum(x)],[y;s;ddy0;ddy1])
其中 ddy0 与 ddy1 为边界点的二阶导数。
类似地,如果您想要在不同数据位点使用三次样条插值 sin(x) 函数并在位点子序列 x[s] 处匹配导数,则可以如下调用 spapi 函数:
sp = spapi(4,[x;x[s]],[sin.(x);cos.(x[s])])
augknt 可以提供一个合适的结点序列。如果你想要使用五次样条插值同样的数据,只需要把 4 改成 6 就可以。
此为二元样条插值的例子。
using TyCurveFitting
using TyBase
x = -2:0.5:2
y = -1:0.25:1
xx, yy = ndgrid(x, y)
z = exp.(-(xx .^ 2 + yy .^ 2))
knots = (3, 4)
x = (x, y)
y = z
pp = spapi(knots, x, y)
fnplt(pp)

网格数据的光滑插值
为了描述对于网格数据的光滑插值,下为双三次插值,其数据来源于双三次多项式
using TyCurveFitting
using TyBase
sites = ([0, 1], [0, 2])
coefs = zeros(4, 4)
coefs[1, 1] = 1
g = ppmak(sites, coefs)
dorder = [1, 1]
Dxg = fnval(fnder(g, [1, 0]), sites)
Dyg = fnval(fnder(g, [0, 1]), sites)
Dxyg = fnval(fnder(g, [1, 1]), sites)
f = spapi((4,4), ([0,1,0,1],[0,2,0,2]), [fnval(g, sites) Dyg;Dxg' Dxyg])
h = fnbrk(fn2fm(f, "pp"), "c")
if any(dropdims(h, dims = (findall(size(h) .== 1)...,)) - coefs .!= 0)
println("something went wrong")
end
没有任何东西被打出,这说明生成的插值 f 确为其本身。
# 输入参数
knots - 节点序列向量 | 数组元组
样条的节点序列,指定为非降向量。
数据类型: Int | Float
k - 样条的阶正整数
样条的阶,指定为标量。
数据类型: Int
x - 数据位点向量 | 数组元组
拟合数据值的数据位点,单变元时指定为向量,多变元时指定为数组元组。带节点的样条 f 满足对于每个数据位点 x 都有 f(x[j])=y[:,j] 对于 j 的所有取值。
对于多元、网格数据,可以指定 x 为在每个变元维度位点的数组元组,即 f(x1[i],x2[j],...,xn[k])=y[:,i,j,...,k]。
数据类型: Int | Float
y - 拟合数据值向量 | 矩阵 | 数组
在样条构造时需要拟合的数据值,指定为向量或矩阵。
数据类型: Int | Float
# 输出参数
spline - 样条结构体样条结构体
样条,以有以下元素的结构体形式返回。
Form - 样条的类型"B-"
样条的类型,返回为"B-",这意味着样条为 B 型。
数据类型: String
Knots - 样条节点的位置向量 | 数组元组
样条的节点位置,单变元时以向量,多变元时以向量元组形式返回。其中向量含有严格增的元素,分别表示定义多项式片段的定义区间的左右端点。
数据类型: Int | Float
Coefs - 多项式系数矩阵 | 数组
每个片段的多项式系数,单变元时以矩阵,多变元时以数组形式返回。
数据类型: Int | Float
Number - 多项式片段的数目标量 | 向量
描述样条的多项式片段的数目,单变元时以标量,多变元时以由各变元的多项式片段的数目组成的向量形式返回。
数据类型: Int
Order - 多项式阶数标量 | 向量
描述样条的分段多项式的阶数,单变元时以标量,多变元时以各变元阶数组成的向量形式返回。
数据类型: Int
Dim - 维数标量
目标函数的维数,以标量形式返回。
数据类型: Int
# 限制
给定的(单变元时)节点与位点为了使插值有定义必须满足Schöenberg-Whiter条件。如果位点序列非减,且
其中等号仅在 knots[1] 和 knots[end] 上取得。在多变元情形,这些条件必须对每个变量都满足。
# 算法
该函数使用 spcol 提供的几乎块对角配置矩阵
该函数以张量积形式匹配网格数据——利用单变元样条拟合与数据值线性相关的优势一次匹配一个变量。