有效的方法来决定一个n的决定因素! x n! Maple中的矩阵

时间:2013-02-21 23:13:50

标签: algorithm permutation maple determinants

我有一个大矩阵,n! x n !,我需要采取决定因素。对于n的每个排列,我关联

  • 长度为2n的向量(这很容易计算)
  • 2n个变量的多项式(在n上递归计算的线性因子的乘积)

矩阵是向量上多项式的评估矩阵(被认为是点)。因此矩阵的sigma,tau入口(由置换索引)是在tau的向量处评估的sigma的多项式。

示例 :对于n=3,如果i多项式为(x1 - 4)(x3 - 5)(x4 - 4)(x6 - 1)j点是(2,2,1,3,5,2),然后矩阵的(i,j)条目将为(2 - 4)(1 - 5)(3 - 4)(2 - 1) = -8。此处为n=3,因此点位于R^(3!) = R^6,多项式具有3!=6个变量。

我的目标是确定矩阵是否是非奇异的。


我现在的做法是:

  • 函数point采用排列并输出向量
  • 函数poly采用置换并输出多项式
  • 函数nextPerm以字典顺序给出下一个排列

我的代码的删节伪代码版本是这样的:

B := [];
P := [];
w := [1,2,...,n];
while w <> NULL do
  B := B append poly(w);
  P := P append point(w);
  w := nextPerm(w);
od;

// BUILD A MATRIX IN MAPLE
M := Matrix(n!, (i,j) -> eval(B[i],P[j]));

// COMPUTE DETERMINANT IN MAPLE
det := LinearAlgebra[Determinant]( M );

// TELL ME IF IT'S NONSINGULAR
if det = 0 then return false;
else return true; fi;

我使用内置函数LinearAlgebra[Determinant]在Maple中工作,但其他一切都是使用低级Maple函数的自定义构建函数(例如seqconvert和{{ 1}})。

我的问题是这需要太长时间,这意味着我可以耐心地前往cat,但获得n=7需要数天时间。理想情况下,我希望能够到达n=8

有没有人知道如何改善时间?我愿意用不同的语言工作,例如Matlab或C,但更愿意找到一种方法来加快Maple的速度。

我意识到如果没有所有的血腥细节,这可能很难回答,但每个功能的代码,例如n=10point已经过优化,所以这里真正的问题是,如果有更快的方法可以通过动态构建矩阵来获取行列式,或类似的东西。


更新:以下是我玩过的两个不起作用的想法:

  1. 我可以存储多项式(因为它们需要一段时间来计算,我不想重做,如果我可以帮助它)到长度为poly的向量中,并计算点上的苍蝇,并将这些值插入决定因素的排列公式:

    permutation determinant formula

    这里的问题是矩阵的大小为n!,因此对于我的情况,这将是O(N!)。当O((n!)!)n=10这是一个大甚至考虑做的方式。

  2. 使用LU分解计算行列式。幸运的是,我的矩阵的主对角线是非零的,所以这是可行的。由于这是矩阵大小的(n!)! = 3,628,800!,因此变为O(N^3)更接近可行。但问题是,它需要我存储整个矩阵,这会对内存造成严重压力,无需考虑运行时间。所以这也不起作用,至少不是没有更多的聪明。有什么想法吗?

2 个答案:

答案 0 :(得分:2)

我不清楚你的问题是空间还是时间。显然这两个交易来回。如果您只想知道行列式是否为正,那么您肯定应该使用LU分解。原因是如果A = LU L下三角形和U上三角形,那么

det(A) = det(L) det(U) = l_11 * ... * l_nn * u_11 * ... * u_nn

因此您只需要确定LU的任何主要对角线条目是否为0

为了进一步简化,请使用Doolittle的算法,l_ii = 1。如果算法在任何时候发生故障,矩阵都是单数的,所以你可以停下来。这是要点:

for k := 1, 2, ..., n do {
  for j := k, k+1, ..., n do {
    u_kj := a_kj - sum_{s=1...k-1} l_ks u_sj;
  }
  for i = k+1, k+2, ..., n do {
    l_ik := (a_ik - sum_{s=1...k-1} l_is u_sk)/u_kk;
  }
}

关键是你可以同时计算i的{​​{1}}行Ui L列,你只需要知道前一行/列向前移动。这样您就可以尽可能地并行处理并根据需要进行存储。由于您可以根据需要计算条目a_ij,因此您需要存储两个长度为n的向量,同时生成另外两个长度为n的向量(U行,列L)。该算法需要n^2时间。您可能会找到更多技巧,但这取决于您的空间/时间权衡。

答案 1 :(得分:-1)

不确定我是否已按照您的问题行事;是(或它是否减少)以下?

你有两个n个数字的向量,称它们为xc,然后矩阵元素是k (x_k+c_k)的产品,每个行/列对应一个xc的不同排序?

如果是这样,那么我相信只要xc中存在重复值,矩阵就会是奇异的,因为矩阵将具有重复的行/列。在较小的n上使用不同的值xc尝试一堆蒙特卡罗,以查看该案例是否通常是非单数的 - 如果6的情况确实如此,则很可能这对10来说是真的。

就蛮力而言,你的方法:

  1. 不是首发
  2. 工作速度会快得多(n=7应该是几秒钟),但是你可能不想使用LU来尝试SVD,这样可以让你更好地了解矩阵的表现。