转置原理

如果一个算法的输入是一个向量 \(\bm a\),输出是另一个向量 \(\bm b\),且这个算法是一个线性变换,那么可以写成如下形式:

\[M\bm a=\bm b \]

其中 \(M\) 为这个算法的线性变换所代表的矩阵。

由于 \((AB)^T=B^TA^T\),所以上式可以变形为:

\[\bm a^TM^T=\bm b^T \]

这个式子的意义是,考虑另外一个算法,其输入是一个向量 \(\bm a^T\),输出是另一个向量 \(\bm b^T\),且这个算法的线性变换所代表的矩阵为 \(M^T\)。称这个算法为原算法的转置算法。不难看出,一个算法的转置的转置是他本身。

那么如果有一个运行时间为 \(O(T(n))\) 的算法,就存在一个运行时间与原算法同样的转置算法,反之依然。

为什么呢?考虑这个算法的每一步操作都相当于一个线性变换,假如这个算法运行 \(t\) 步,第 \(i\) 步所代表的线性变换为 \(M_i\),那么有:

\[M=\prod_{i=1}^t M_i \]

要算 \(M^T\),根据公式,只需要将每个 \(M_i\) 转置后翻转整个序列,即:

\[M^T=\prod_{i=t}^1 M_i^T \]

这样,如果能原操作耗费同样时间进行所有操作的转置操作,那么就能与原算法耗费同样的时间完成其转置算法。

这里为了证明,考虑将 \(M\) 分解为三种初等矩阵的乘积,即对换、倍乘、倍加。而且向量乘初等矩阵复杂度是 \(O(1)\) 的,如果能证明初等矩阵的转置操作复杂度仍然是 \(O(1)\),就证明了上述命题。显然,初等矩阵的转置还是初等矩阵,所以上述命题得证。

那么具体地该如何求出一个算法的转置算法呢?还是考虑分解成初等矩阵的乘积,然后讨论这三种初等矩阵的转置是什么:

  • 对于对换操作,如果是交换了 \(a_i\)\(a_j\),有 \(\begin{bmatrix}0&1\\1&0\end{bmatrix}\times\begin{bmatrix}a_i\\a_j\end{bmatrix}=\begin{bmatrix}a_j\\ a_i\end{bmatrix}\),转置后矩阵不变,含义还是交换元素。
  • 对于倍乘操作,分析与上面相似,含义不变。
  • 对于倍加操作,如果是给 \(a_i\) 倍加上 \(a_j\)\(c\) 倍,有 \(\begin{bmatrix}1&c\\0&1\end{bmatrix}\times\begin{bmatrix}a_i\\a_j\end{bmatrix}=\begin{bmatrix}a_i+ca_j\\ a_j\end{bmatrix}\),转置后得到 \(\begin{bmatrix}1&0\\c&1\end{bmatrix}\times\begin{bmatrix}a_i\\a_j\end{bmatrix}=\begin{bmatrix}a_i\\ a_j+ca_i\end{bmatrix}\),含义是给 \(a_j\) 倍加上 \(a_i\)\(c\) 倍。

所以就可以求出一个算法的转置算法了。

转置原理优化加法卷积

(暂时默认下标从 \(0\) 开始)

考虑 FFT 这个算法是啥,输入是一个 \(n\) 维向量 \(\bm a\),输出的也是一个 \(n\) 维向量 \(\bm b\),进行的变换就是傅里叶矩阵:

\[\operatorname{FFT}= \begin{bmatrix} \omega_n^0&\omega_n^0&\omega_n^0&\cdots&\omega_n^0\\ \omega_n^0&\omega_n^1&\omega_n^2&\cdots&\omega_n^{n-1}\\ \vdots&\vdots&\vdots&\ddots&\vdots\\ \omega_n^0&\omega_n^i&\omega_n^{2i}&\cdots&\omega_n^{(n-1)i}\\ \vdots&\vdots&\vdots&\ddots&\vdots\\ \omega_n^0&\omega_n^{n-1}&\omega_n^{2(n-1)}&\cdots&\omega_n^{(n-1)(n-1)} \end{bmatrix} \]

简要地说,\(\operatorname{FFT}_{i,j}=\omega_n^{i,j}\)

不难观察到 \(\operatorname{FFT}=\operatorname{FFT}^T\),所以说 FFT 的转置算法还是 FFT。

考虑 FFT 算法是如何实现的。对于一个输入向量,我们先对其交换位反转的位置对,然后进行一个线性变换 \(P\),可以写成如下形式:

\[\operatorname{FFT}=\operatorname{bitrev}\times P \]

对于 IFFT,交换操作是同样的,线性变换不同,设为 \(Q\),于是有:

\[\operatorname{IFFT}=\operatorname{bitrev}\times Q \]

假如说要求 \(\bm a\)\(\bm b\) 的加法卷积,那么就是要求:

\[[(\bm a\times\operatorname{FFT})\cdot(\bm b\times\operatorname{FFT})]\times\operatorname{IFFT} \]

其中点号代表逐项相乘。

因为 \(\operatorname{FFT}=\operatorname{FFT}^T\),所以:

\[\begin{aligned} &\quad[(\bm a\times\operatorname{FFT})\cdot(\bm b\times\operatorname{FFT})]\times\operatorname{IFFT}\\ &=[(\bm a\times\operatorname{FFT}^T)\cdot(\bm b\times\operatorname{FFT}^T)]\times\operatorname{IFFT}\\ &=[(\bm a\times P^T\times\operatorname{bitrev}^T)\cdot(\bm b\times P^T\times \operatorname{bitrev}^T)]\times \operatorname{bitrev}\times Q \end{aligned}\]

注意这个式子,相当于是我们先求出 \(\bm a\times P^T\)\(\bm b\times P^T\),然后将其分别 bitrev,乘起来,再 bitrev 回去,最后乘上 \(Q\)。那这个 bitrev 其实可以扔掉,仍然能达到相同的效果。于是要求即为:

\[[(\bm a\times P^T)\cdot(\bm b\times P^T)]\times Q \]

现在只需要算 \(P^T\) 就好了。还记得上面讲的求一个算法的转置吗?那么就完成了。现在不需要预处理位反转了。这只是一个常数优化但是不失为一个例子。

posted @ 2025-05-02 21:29  Linge_Zzzz  阅读(89)  评论(0)    收藏  举报