Skip to article frontmatterSkip to article content

多项式除法与 Ruffini 法则

一元多项式除法与 Ruffini 法则

根据 Ruffini 法则,一元多项式除法和多项式求值之间具有紧密的关系。

如果我们利用多项式长除法来计算 f(X)/(Xd)f(X)/(X-d),那么我们可以得到一个商多项式 q(X)q(X) 和一个余数 rr,满足:

f(X)=(Xd)q(X)+rf(X) = (X-d)\cdot q(X) + r

这是大家熟知的多项式余数定理,即余数恰好等于 f(d)f(d)。所以当 f(X)f(X) 减去余数之后,就可以被 (Xd)(X-d) 整除。那么商多项式 q(X)q(X)f(d)f(d) 之间的是否也有一定的联系呢? 先上一个结论:商多项式 q(X)q(X) 恰好是 f(X)f(X)X=dX=d 处求值过程中,所产生的中间计算结果。

我们用系数形式来表示 f(X)f(X),那么

f(X)=a0+a1X+a2X2++anXnf(X) = a_0 + a_1X + a_2X^2 + \ldots + a_nX^n

变化下形式可得:

f(X)=a0+X(a1+X(a2++X(an1+Xan))f(X) = a_0 + X(a_1 + X(a_2 + \ldots + X(a_{n-1} + Xa_n)\ldots)

如果要计算「多项式求值」 f(d)f(d), 我们从左到右依次代入 X=dX=d 到上面等式,

qn1=d0+anqn2=dqn1+an1q1=dq2+a2q0=dq1+a1v=dq0+a0\begin{split} q_{n-1} &= d\cdot 0 + a_n\\ q_{n-2} &= d\cdot q_{n-1} + a_{n-1} \\ \vdots & \vdots \\ q_1 &= d\cdot q_2 + a_2 \\ q_0 &= d\cdot q_1 + a_1 \\ v &= d\cdot q_0 + a_0 \\ \end{split}

(q0,q1,,qn1)(q_0, q_1, \ldots, q_{n-1}) 正是商多项式 q(X)q(X) 的系数。换句话说,多项式的线性除法过程,其实正是多项式求值过程。

我们看一个简单例子,比如 f(X)=5+3X+2X2+X3f(X) = 5 + 3X + 2X^2 + X^3,我们要计算 f(2)f(-2),即等同于计算 f(X)/(X+2)f(X)/(X+2),计算过程如下:

q2=(2)0+1=1q1=(2)1+2=0q0=(2)0+3=3v=(2)3+5=1\begin{array}{lll} q_2 &= (-2)\cdot 0 + 1 &= 1\\ q_1 &= (-2)\cdot 1 + 2 &= 0\\ q_0 &= (-2)\cdot 0 + 3 &= 3\\ v & = (-2)\cdot 3 + 5 &= -1\\ \end{array}

我们于是得到最后一行的结果 f(2)=1f(-2) = -1,并且在计算过程中附带得到了商多项式 q(X)=3+X2q(X) = 3 + X^2

我们可以写一个简单的循环来实现这个计算过程:

fn div_poly(f: &[Scalar], d: Scalar) -> (Vec<Scalar>, Scalar) {
    let mut rem = Scalar::zero();
    let mut quo = Vec::new();

    for c in coeffs.iter().rev() {
        rem = rem * d + c;
        quo.insert(0, rem);
    }
    (quo, rem)
}

其实,Ruffini 法则不只针对线性多项式除法适用,也适用于除数多项式时任意次数的除法。这种一般化的算法被称为 Synthetic Division。

以上,我们一直在讨论一元多项式的除法,那么 MLE 的除法呢?幸运的是,Ruffini 法则同样适用于 MLE 多项式除法,MLE 多项式除法的计算过程等同于 MLE 多项式求值过程。

MLE 多项式除法

先热身一下,当我们用一个 MLE 除以一个一元线性多项式时,我们可以把 MLE 视为一个一元多项式,其它变元被看成是互相无法计算的常数。这样我们可以用一元多项式除法来快速得到商多项式(n1n-1 元 MLE)和余数。

比如

f~(X0,X1,X2)=2X0X2+3X1+4X0\tilde{f}(X_0, X_1, X_2) = 2\cdot X_0X_2 + 3\cdot X_1 + 4\cdot X_0

除法如下:

2X0X2+3X1+4X0(X2a)=(2X0)X2+(3X1+4X0)(X2a)=2X0,3X1+(4+2a)X0\frac{2\cdot X_0X_2 + 3\cdot X_1 + 4\cdot X_0}{(X_2-a)} = \frac{(2\cdot X_0)X_2 + (3\cdot X_1 + 4\cdot X_0)}{(X_2-a)} = 2\cdot X_0, 3X_1 + (4+ 2a)X_0

其中余数为 3X1+(4+2a)X03X_1 + (4+ 2a)X_0,商多项式也是一个 MLE 为 2X02\cdot X_0。那么接下来我们还可以对余数多项式继续做除法,这次我们除以 (X1b)(X_1-b)

3X1+(4+2a)X0(X1b)=3,(4+2a)X0+3b\frac{3X_1 + (4+ 2a)X_0}{(X_1-b)} = 3, (4+ 2a)X_0 + 3b

余数多项式为 (4+2a)X0+3b(4+ 2a)X_0 + 3b,商多项式为 3。最后,我们继续除法,除数多项式为 (X0c)(X_0-c)

(4+2a)X0+3b(X0c)=4+2a,3b+(4+2a)c\frac{(4+ 2a)X_0 + 3b}{(X_0-c)} = 4+2a, 3b + (4+2a)c

余数为 3b+(4+2a)c3b + (4+2a)c,商多项式为 4+2a4+2a

至此,我们计算了三次完整的 MLE 多项式除法,分别除以 (X2a)(X_2-a)(X1b)(X_1-b)(X0c)(X_0-c)。得到了三个商多项式,和最后的余数。现看看最后的余数,它恰好等于 f~(X)\tilde{f}(\vec{X})(c,b,a)(c,b,a) 处的取值。 这完美符合 Ruffini 法则。

r=3b+(4+2a)c=f~(c,b,a)r= 3b + (4+2a)c = \tilde{f}(c, b, a)

三个商多项式如下:

q2(X0,X1)=2X0q1(X0)=3q0=4+2a\begin{split} q_2(X_0,X_1) &= 2\cdot X_0\\ q_1(X_0) &= 3\\ q_0 &= 4+2a\\ \end{split}

不过计算多项式除法不是那么直观,那么接下来我们利用 Ruffini 法则来通过计算 MLE 求值,并且同时计算出商多项式,这个计算过程更加清晰。MLE 的计算过程可以看成是一个折叠的过程,对于每一个变元 Xk{Xn1,,X0}X_k\in\{X_{n-1},\ldots, X_0\},我们都可以把多项式看成一个一元线性多项式

f~(X,Xk)=A+BXk\tilde{f}(\vec{X},X_k)=A + B\cdot X_k

当我们把 Xk=αX_k = \alpha 代入后,可以得到:

f~(X,Xk)=A+αB\tilde{f}(\vec{X},X_k)=A + \alpha\cdot B

如果我们把 f~\tilde{f} 用系数向量来表示,那么这个过程可以看作是关于 α\alpha 因子的折叠。例如 f~(X0,X1,X2)=2X0X2+3X1+4X0\tilde{f}(X_0, X_1, X_2) = 2\cdot X_0X_2 + 3\cdot X_1 + 4\cdot X_0,那么它的系数向量为:

(0,4,3,0,0,2,0,0)1,X0,X1,X0X1,X2,X0X2,X1X2,X0X1X2\begin{array}{cccccccc} (&0, &4, &3, &0, &0, &2, &0, &0 &) \\ &1, &X_0, &X_1, &X_0X_1, &X_2, &X_0X_2, &X_1X_2, &X_0X_1X_2& \\ \end{array}

这些系数分别对应于第二排的单项式。接下来,假如要计算 f(c,b,a)f(c, b, a),我们可以用一个 split-and-fold 的思想来完成计算过程。

(0,4,3,0)+a(0,2,0,0)=(0,4+2a,3,0)(0,4+2a)+b(3,0)=(3b,4+2a)(3b)+c(4+2a)=3b+(4+2a)c\begin{split} (0,4,3,0) + a\cdot {\color{blue}(0,2,0,0)} & = (0, 4+2a, 3, 0)\\ (0, 4+2a) + b\cdot {\color{blue}(3, 0)} & = (3b, 4+2a)\\ (3b) + c\cdot {\color{blue}(4+2a)} & = 3b+ (4+2a)c\\ \end{split}

每一轮,我们都将向量对半拆成两半,把左边的一半加上右边一半乘以一个因子,这样递归三轮,我们会最终得到计算结果 3b+(4+2a)c3b+ (4+2a)c,这个结果也恰好等于前面的多项式除法计算的余数。我们前面提到过,根据 Ruffini 法则,商多项式应该是求值计算过程中的中间结果,那么这个折叠过程中,哪里能找到商多项式的踪迹呢?

商多项式是蓝色标记的向量作为「系数向量」的 MLE 多项式,也就是每一轮 split-and-fold 过程中,右边的半个向量。我们来验证一下,第一行的商多项式是 2X02\cdot X_0,它是单项式 (1,X0,X1,X0X1)(1,X_0,X_1,X_0X_1) 的系数,因此第一个商多项式为 2X02X_0;第二行商多项式是 (3,0)(3,0),这是一个常数多项式;第三行的商多项式是 (4+2a)(4+2a),也是一个常数多项式。这与我们前面手动做除法得到的结果一模一样。

TODO: q_k = f(... 1+u_k, ...) - f(... u_k, ...)

不过,在 ZeroMorph 协议中,MLE 是用「点值形式」来表示,如果我们要用上面的方法来计算除法,则需要先将 MLE 从点值形式转换为系数形式。这个转换过程(类似一元多项式的FFT)的一般化算法的时间复杂度为 O(Nlog2N)O(N\log^2N),即 O(2nn2)O(2^n\cdot n^2)。并且在计算得到商多项式之后,我们还要将 n1n-1个商多项式再通过逆向转换,从系数形式得到点值形式。这会引入不可忽略的转换开销。

其实,我们可以利用 split-and-fold 的思想,直接在 MLE 的「点值形式」上进行求值计算,并且同时计算出商多项式,完全避免「点值形式」和「系数形式」的来回转换。

我们看看 MLE 的点值形式上是如何计算求值的:

f~(X0,X1,,Xn2,Xn1)=i{0,1}nfieq~(i,X)\tilde{f}(X_0,X_1,\ldots, X_{n-2}, X_{n-1}) = \sum_{\vec{i}\in\{0,1\}^n} f_{\vec{i}} \cdot \tilde{eq}(\vec{i}, \vec{X})

假设 f~\tilde{f} 的点值形式为向量 (f000,f100,,f111)(f_{000}, f_{100}, \ldots, f_{111}),对应的 HyperCube 为 {0,1}3\{0,1\}^3

我们从右向左对 Xn1,,X0X_{n-1},\ldots, X_0 逐个代入对应的值,比如我们先代入 Xn1=un1X_{n-1}=u_{n-1},那么 f~(1)(X0,X1,,Xn2)\tilde{f}^{(1)}(X_0,X_1,\ldots, X_{n-2}) 的点值式为

(1un1)(f0,f1,,f2n21)+uk(f2n2,f2n2+1,,f2n11)(1-u_{n-1})\cdot(f_0, f_1, \ldots, f_{2^{n-2}-1}) + u_k\cdot(f_{2^{n-2}}, f_{2^{n-2}+1}, \ldots, f_{2^{n-1}-1})

这个计算过程也是一个 split-and-fold 的过程,可以一直递归下去,直到向量被折叠成一维。

我们再次用前面的 MLE 多项式,f~(X0,X1,X2)=2X0X2+3X1+4X0\tilde{f}(X_0, X_1, X_2) = 2\cdot X_0X_2 + 3\cdot X_1 + 4\cdot X_0,它的点值形式为:

(0,4,3,7,0,6,3,9)f000,f100,f010,f110,f001,f101,f011,f111\begin{array}{cccccccc} (&0, &4, &3, &7, &0, &6, &3, &9 &) \\ &f_{000}, &f_{100}, &f_{010}, &f_{110}, &f_{001}, &f_{101}, &f_{011}, &f_{111}& \\ \end{array}

比如,我们代入 (X0=1,X1=0,X2=1)(X_0=1,X_1=0,X_2=1),那么 f~(1,0,1)=2+4=6\tilde{f}(1, 0, 1)=2+4=6 正好对应点值向量的第 f101f_{101} 号元素。

下面,我们代入 (X0=c,X1=b,X2=a)(X_0=c,X_1=b,X_2=a),用 split-and-fold 的方式完成求值过程的计算:

(1a)(0,4,3,7)+a(0,6,3,9)=(0,4+2a,3,7+2a)(1b)(0,4+2a)+b(3,7+2a)=(3b,(1b)(4+2a)+b(7+2a))=(3b,4+2a+3b)(1c)(3b)+c(4+2a+3b)=3b3bc+4c+2ac+3bc=3b+(4+2a)c\begin{split} (1-a)\cdot(0,4,3,7) + a\cdot (0,6,3,9) & = (0, 4+2a, 3, 7+2a)\\ (1-b)\cdot(0, 4+2a) + b\cdot (3, 7+2a) & = (3b, (1-b)(4+2a)+b(7+2a)) = (3b, 4+2a+3b)\\ (1-c)\cdot(3b) + c\cdot (4+2a+3b) & = 3b - 3bc +4c+2ac + 3bc = 3b+ (4+2a)c\\ \end{split}

不出意料,最终的结果仍然是 3b+(4+2a)c3b+ (4+2a)c,不过这次我们不太容易在上面的计算过程中找到商多项式。

每一行的商多项式是右边向量减去左边向量,我们依次看看每一行:

q2(X0,X1):(0,6,3,9)(0,4,3,7)=(0,2,0,2)q1(X0):(3,7+2a)(0,4+2a)=(3,3)q0:(4+2a+3b)(3b)=4+2a\begin{split} q_2(X_0,X_1): & (0, 6, 3, 9) - (0, 4, 3, 7) = (0, 2, 0, 2)\\ q_1(X_0): & (3, 7+2a) - (0, 4+2a) = (3, 3)\\ q_0: & (4+2a+3b) - (3b) = 4+2a\\ \end{split}

记住,这是商多项式的点值形式,我们可以通过多项式插值,把它们转换成「系数形式」,并且和前面的商多项式做比较。

还有一种方法,是我们前面描述过的,将一个低维的 HyperCube 映射到一个高维的 HyperCube,实际上是低维 Cube 的重复, 因此我们看到 q2(X0,X1)q_2(X_0,X_1) 的点值形式是 (0,2,0,2)(0, 2, 0, 2),这正好是一个 2 维 HyperCube 的重复,表示 X1X_1 这个变元的相关系数均为零,所以我们可以快速得到 q2(X0,X1)=2X0q_2(X_0,X_1) = 2X_0。同样,q1(X0)q_1(X_0) 的点值形式是 (3,3)(3,3) 也是重复的模式,说明含有 X0X_0 变元的单项式系数均为零, 因此 q1(X0)=3q_1(X_0) = 3,最后加上 q0()=4+2aq_0() = 4+2a,它们和前面通过系数形式计算得到的商多项式是完全一致的。