【问题标题】:Compute matrix power with integer entries用整数项计算矩阵幂
【发布时间】:2019-03-14 14:55:26
【问题描述】:

假设我有一个常数矩阵 A,我想计算 pow(A, n)。如in this question 所述,我可以计算它的特征值分解(或更一般地说,它的不变子空间和广义模态矩阵)以加快处理速度。

如果 A 是大小为 k 的方阵,则该算法通过平方取幂的复杂度为 O(k log n),准备成本(计算模态矩阵)为 O(k^3)。

我正在考虑的问题是精度损失。计算特征值等将我们带出整数域到浮点数。尽管最后我们知道 pow(A, n) 必须包含所有整数条目,但上面概述的算法只计算浮点数。

另一种方法是通过平方仅利用求幂,但这只会给我们一个 O(k^3 log n) 算法。

有没有办法准确地 - 无需转换为浮点数 - 快速计算 pow(A, n)?

【问题讨论】:

  • 如果这会导致有人可以在纸上执行但这是高度可选的算法,那就更好了
  • 即使您使用(固定大小)整数,由于溢出导致的信息丢失也是一个问题。所以通常你需要使用任意精度的整数。您也可以使用任意精度有理数来计算特征值,从而避免固定精度浮点的精度损失。
  • @ChrisDodd 考虑矩阵[1 1] 超过[1 0]。它的特征值为(1+sqrt(5))/2(1 - sqrt(5))/2。任意精确的理性不会拯救你。

标签: algorithm integer precision matrix-multiplication


【解决方案1】:

特征值分解也可以用于有限域上的矩阵,但前提是该域恰到好处。因此,不仅需要预处理来进行特征值分解,还需要找到(一些)有限域,甚至可以在这些域上进行。

寻找多个解有助于避免使用巨大的有限域,然后在一些小域中计算 pow(A, n) 并使用 CRT 计算出 ℤ 中的解。但这需要以某种方式有足够数量的足够大小的字段来使用,并且您不会事先真正知道什么是足够的(总是有一些 n 超过它停止工作),所以也许这一切都行不通在实践中。

举个小例子:

A = [[1, 1],
     [1, 0]]

特征 x² - x - 1,让我们猜测模 1009 会起作用(确实如此),然后有根 383 和 627,所以:

A = QDP mod 1009
Q = [[  1,   1],
     [382, 626]]
D = [[383,   0],
     [  0, 627]]
P = [[ 77, 153],
     [933, 856]]

例如

pow(A, 15) = Q [[928,   0], P = [[987, 610],
                [  0, 436]]      [610, 377]]

斐波那契数列符合预期,一切顺利。但是只有 1009 作为模数,指数超过 15 会使结果与 ℤ 中的结果不匹配,那么我们将需要更多/更大的字段。

【讨论】:

  • 如果你找到两个(或更多)这样的字段,你可以通过中国剩余定理计算出 Z 的结果,我是否理解正确?
  • @WorldSEnder 仅当字段大小的乘积足够大时,这是令人讨厌的部分
【解决方案2】:

使用Cayley-Hamilton theorem 我们可以更快。该定理指出,维度k 的每个矩阵幂都可以写成A 的第一个k 幂的和。

如果我们知道这一点,我们可以通过平方来使用幂运算,但我们不是在矩阵上工作,而是在A 上使用系数在ℤ 中的多项式。然后,我们可以在每一步之后将多项式减少特征多项式。

举个小例子:

A = [[1, 1],
     [1, 0]]
A^2 = A + 1 = writing poly. coefficients = {1, 1}

pow(A, 15) = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
           = {1, 0} * ({1, 0} * ({1, 0} * {1, 0}^2)^2)^2
           = {1, 0} * ({1, 0} * ({1, 0} * {1, 0, 0})^2)^2
           = {1, 0} * ({1, 0} * ({1, 0} * {1, 1})^2)^2
           = {1, 0} * ({1, 0} * ({1, 1, 0})^2)^2
           = {1, 0} * ({1, 0} * {2, 1}^2)^2
           = {1, 0} * ({1, 0} * {4, 4, 1})^2
           = {1, 0} * ({1, 0} * {8, 5})^2
           = {1, 0} * ({8, 5, 0})^2
           = {1, 0} * {13, 8}^2
           = {1, 0} * {169, 208, 64}
           = {1, 0} * {377, 233}
           = {377, 233, 0}
           = {610, 377}
           = [[987, 610],
              [610, 377]]

那么,运行时成本是多少?微不足道的O(k^2 * log n),因为在每个平方步骤中,我们需要计算两个多项式的平方并减少字符。多项式。在另一个答案中使用与@harold 类似的技巧,通过使用离散傅立叶多项式乘法得到O(k log k log n),因为我们可以找到原始根。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-05
    • 2021-05-09
    • 1970-01-01
    • 1970-01-01
    • 2017-03-11
    • 2018-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多