拉格朗日插值法

https://aaron67.cc/2020/10/29/lagrange-interpolate/

给定 ( t + 1 ) (t+1) (t+1) 个不同的点,过这些点且最高次不大于 t t t 的多项式,有且只有一条。

本文将介绍如何使用拉格朗日插值法,求解这样的多项式。

方法

已知点 ( x 0 , y 0 ) (x_0, y_0) (x0,y0) ( x 1 , y 1 ) (x_1, y_1) (x1,y1)、…、 ( x t , y t ) (x_t, y_t) (xt,yt),拉格朗日插值法的思路是寻找多项式 l j ( x ) l_j(x) lj(x),使其在 x = x j x = x_j x=xj 时的取值为 1,在其他点的取值都是 0。

这样的多项式很好构造。

l j ( x ) = ( x − x 0 ) . . . ( x − x j − 1 ) ( x − x j + 1 ) . . . ( x − x t ) ( x j − x 0 ) . . . ( x j − x j − 1 ) ( x j − x j + 1 ) . . . ( x j − x t ) l_j(x) = \frac{(x-x_0)...(x-x_{j-1})(x-x_{j+1})...(x-x_t)}{(x_j-x_0)...(x_j-x_{j-1})(x_j-x_{j+1})...(x_j-x_t)} lj(x)=(xjx0)...(xjxj1)(xjxj+1)...(xjxt)(xx0)...(xxj1)(xxj+1)...(xxt)

注意到,当 x = x j x=x_j x=xj 时, l j ( x j ) l_j(x_j) lj(xj) 的分子和分母相同,所以 l j ( x j ) = 1 l_j(x_j)=1 lj(xj)=1,当 x x x 取其他值时,其分子总是 0,所以结果为 0。

多项式 l j ( x ) l_j(x) lj(x) 就像开关一样,可以让 y j l j ( x ) y_jl_j(x) yjlj(x) 满足只有在 x = x j x = x_j x=xj 时的取值为 y j y_j yj,而在其他点的取值都是 0。

基于此,可以继续构造多项式

L ( x ) = y 0 l 0 ( x ) + y 1 l 1 ( x ) + . . . + y t l t ( x ) L(x) = y_0l_0(x) + y_1l_1(x) + ... + y_tl_t(x) L(x)=y0l0(x)+y1l1(x)+...+ytlt(x)

满足过已知的 ( t + 1 ) (t+1) (t+1) 个点。

给定点 ( x 0 , y 0 ) = ( 1 , 350 ) (x_0, y_0) = (1, 350) (x0,y0)=(1,350) ( x 1 , y 1 ) = ( 2 , 770 ) (x_1, y_1) = (2, 770) (x1,y1)=(2,770) ( x 2 , y 2 ) = ( 3 , 1350 ) (x_2, y_2) = (3, 1350) (x2,y2)=(3,1350),求过这三个点的多项式。

先构造 l j ( x ) l_j(x) lj(x),有

l 0 ( x ) = ( x − x 1 ) ( x − x 2 ) ( x 0 − x 1 ) ( x 0 − x 2 ) = ( x − 2 ) ( x − 3 ) ( 1 − 2 ) ( 1 − 3 ) = 1 2 x 2 − 5 2 x + 3 l_0(x) = \frac{(x - x_1)(x - x_2)}{(x_0 - x_1)(x_0 - x_2)} = \frac{(x-2)(x-3)}{(1-2)(1-3)} = \frac{1}{2}x^2 - \frac{5}{2}x + 3 l0(x)=(x0x1)(x0x2)(xx1)(xx2)=(12)(13)(x2)(x3)=21x225x+3

l 1 ( x ) = ( x − x 0 ) ( x − x 2 ) ( x 1 − x 0 ) ( x 1 − x 2 ) = ( x − 1 ) ( x − 3 ) ( 2 − 1 ) ( 2 − 3 ) = − x 2 + 4 x − 3 l_1(x) = \frac{(x-x_0)(x-x_2)}{(x_1-x_0)(x_1-x_2)} = \frac{(x-1)(x-3)}{(2-1)(2-3)} = -x^2 + 4x - 3 l1(x)=(x1x0)(x1x2)(xx0)(xx2)=(21)(23)(x1)(x3)=x2+4x3

l 2 ( x ) = ( x − x 0 ) ( x − x 1 ) ( x 2 − x 0 ) ( x 2 − x 1 ) = ( x − 1 ) ( x − 2 ) ( 3 − 1 ) ( 3 − 2 ) = 1 2 x 2 − 3 2 x + 1 l_2(x) = \frac{(x-x_0)(x-x_1)}{(x_2-x_0)(x_2-x_1)} = \frac{(x-1)(x-2)}{(3-1)(3-2)} = \frac{1}{2}x^2 - \frac{3}{2}x + 1 l2(x)=(x2x0)(x2x1)(xx0)(xx1)=(31)(32)(x1)(x2)=21x223x+1

再构造 L ( x ) L(x) L(x),有

L ( x ) = ∑ i = 0 2 y i l i ( x ) = 350 ( 1 2 x 2 − 5 2 x + 3 ) + 770 ( − x 2 + 4 x − 3 ) + 1350 ( 1 2 x 2 − 3 2 x + 1 ) = 80 x 2 + 180 x + 90 L(x) = \sum_{i=0}^{2}y_il_i(x) = 350(\frac{1}{2}x^2 - \frac{5}{2}x + 3) + 770(-x^2 + 4x - 3) + 1350(\frac{1}{2}x^2 - \frac{3}{2}x + 1) = 80x^2 + 180x + 90 L(x)=i=02yili(x)=350(21x225x+3)+770(x2+4x3)+1350(21x223x+1)=80x2+180x+90

求解完毕。

证明

存在性

显而易见,我们总能按公式构造出 l j ( x ) l_j(x) lj(x),从而构造出 L ( x ) L(x) L(x)

注意到, l j ( x ) l_j(x) lj(x) 的分子是 t t t 个 1 次多项式相乘,分母是一个整数,所以 l j ( x ) l_j(x) lj(x) 是一个最高次不大于 t t t 的多项式。

任意个最高次不大于 t t t 的多项式相加,结果多项式的最高次也不会大于 t t t,所以 L ( x ) L(x) L(x) 是一个最高次不大于 t t t 的多项式。

唯一性

假设这样的多项式不唯一,对任意两个最高次不大于 t t t 的拉格朗日多项式 L 1 L_1 L1 L 2 L_2 L2

因为 L 1 L_1 L1 L 2 L_2 L2 都过已知的 ( t + 1 ) (t+1) (t+1) 个点,所以两者的差 ( L 1 − L 2 ) (L_1 - L_2) (L1L2) 在这 ( t + 1 ) (t+1) (t+1) 个点的取值都是 0。

也就是说, ( L 1 − L 2 ) (L_1 - L_2) (L1L2) 一定是多项式 ( x − x 0 ) ( x − x 1 ) . . . ( x − x t ) (x-x_0)(x-x_1)...(x-x_t) (xx0)(xx1)...(xxt) 的倍数。

L 1 − L 2 ≠ 0 L_1 - L_2 \neq 0 L1L2=0,则其次数一定不小于 ( t + 1 ) (t+1) (t+1)

而任意个最高次不大于 t t t 的多项式相减,结果多项式的最高次也不会大于 t t t,所以 ( L 1 − L 2 ) (L_1 - L_2) (L1L2) 的最高次也不大于 t t t

矛盾。

所以 L 1 − L 2 = 0 L_1 - L_2 = 0 L1L2=0,即 L 1 = L 2 L_1 = L_2 L1=L2

完整代码

polynomial.py

Polynomial用来表示有限域 Secp256k1.n 上的多项式

y ≡ a 0 x 0 + a 1 x 1 + . . . a t x t ( m o d S e c p 256 k 1. n ) y \equiv a_0x^0 + a_1x^1 + ... a_tx^t \pmod{Secp256k1.n} ya0x0+a1x1+...atxt(modSecp256k1.n)

并实现了多项式加法、乘法和求值等基本运算。

对于方法interpolate_evaluate,我们的目标是计算插值得到的多项式在某点的取值,所以并不需要知道 L ( x ) L(x) L(x) 的具体形式,可以直接将参数 x x x 的值带入公式计算最终结果。方法的内层循环用来计算 l i ( x ) l_i(x) li(x) 的分子和分母的值,外层循环将每个 y i l i ( x ) y_il_i(x) yili(x)(分子和分母)的值保存到数组lagrange中,最后对所有的 y i l i ( x ) y_il_i(x) yili(x) 通分并求和,得到 L ( x ) L(x) L(x) 的值。

def interpolate_evaluate(points: list, x: int) -> int:
    """Lagrange interpolate with the giving points, then evaluate y at x"""
    if len(points) < 2:
        raise ValueError('Lagrange interpolation requires at least 2 points')
    # [(numerator, denominator) ...]
    lagrange = [(0, 0)] * len(points)
    # the product of all the denominator
    denominator_product = 1
    for i in range(len(points)):
        numerator, denominator = 1, 1
        for j in range(len(points)):
            if j != i:
                numerator *= (x - points[j][0])
                denominator *= (points[i][0] - points[j][0])
        lagrange[i] = (points[i][1] * numerator, denominator)
        denominator_product *= denominator
    numerator_sum = 0
    for (numerator, denominator) in lagrange:
        numerator_sum += numerator * denominator_product // denominator
    return (numerator_sum // denominator_product) % curve.n

参考

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值