整数矩阵的行列式


34

给定一个平方整数矩阵作为输入,输出矩阵的行列式。

规则

  • 您可以假设矩阵中的所有元素,矩阵的行列式以及矩阵中元素的总数在您的语言可表示的整数范围内。
  • 允许输出分数为0的十进制/浮点值(例如42.0代替42)。
  • 允许使用内置函数,但是建议您包括不使用内置函数的解决方案。

测试用例

[[42]] -> 42
[[2, 3], [1, 4]] -> 5
[[1, 2, 3], [4, 5, 6], [7, 8, 9]] -> 0
[[13, 17, 24], [19, 1, 3], [-5, 4, 0]] -> 1533
[[372, -152, 244], [-97, -191, 185], [-53, -397, -126]] -> 46548380
[[100, -200, 58, 4], [1, -90, -55, -165], [-67, -83, 239, 182], [238, -283, 384, 392]] -> 571026450
[[432, 45, 330, 284, 276], [-492, 497, 133, -289, -28], [-443, -400, 56, 150, -316], [-344, 316, 92, 205, 104], [277, 307, -464, 244, -422]] -> -51446016699154
[[416, 66, 340, 250, -436, -146], [-464, 68, 104, 471, -335, -442], [159, -407, 310, -489, -248, 370], [62, 277, 446, -325, 47, -193], [460, 460, -418, -28, 234, -374], [249, 375, 489, 172, -423, 125]] -> 39153009069988024
[[-246, -142, 378, -156, -373, 444], [186, 186, -23, 50, 349, -413], [216, 1, -418, 38, 47, -192], [109, 345, -356, -296, -47, -498], [-283, 91, 258, 66, -127, 79], [218, 465, -420, -326, -445, 19]] -> -925012040475554
[[-192, 141, -349, 447, -403, -21, 34], [260, -307, -333, -373, -324, 144, -190], [301, 277, 25, 8, -177, 180, 405], [-406, -9, -318, 337, -118, 44, -123], [-207, 33, -189, -229, -196, 58, -491], [-426, 48, -24, 72, -250, 160, 359], [-208, 120, -385, 251, 322, -349, -448]] -> -4248003140052269106
[[80, 159, 362, -30, -24, -493, 410, 249, -11, -109], [-110, -123, -461, -34, -266, 199, -437, 445, 498, 96], [175, -405, 432, -7, 157, 169, 336, -276, 337, -200], [-106, -379, -157, -199, 123, -172, 141, 329, 158, 309], [-316, -239, 327, -29, -482, 294, -86, -326, 490, -295], [64, -201, -155, 238, 131, 182, -487, -462, -312, 196], [-297, -75, -206, 471, -94, -46, -378, 334, 407, -97], [-140, -137, 297, -372, 228, 318, 251, -93, 117, 286], [-95, -300, -419, 41, -140, -205, 29, -481, -372, -49], [-140, -281, -88, -13, -128, -264, 165, 261, -469, -62]] -> 297434936630444226910432057


是否需要支持的最大矩阵尺寸是任意的?
泰勒·斯科特

1
@TaylorScott列出的第一条规则:You may assume that all elements in the matrix, the determinant of the matrix, and the total number of elements in the matrix are within the representable range of integers for your language.
Mego

4
您知道当您连续遇到4个果冻答案时,您会遇到一个有趣的挑战……
totallyhuman 2017年

Answers:


25

果冻,15 字节

LŒ!ðŒcIṠ;ị"Pð€S

在线尝试!

怎么运行的

LŒ!ðŒcIṠ;ị"Pð€S   input
L                 length
 Œ!               all_permutations
   ð        ð€    for each permutation:
    Œc                take all unordered pairs
      I               calculate the difference between
                      the two integers of each pair
       Ṡ              signum of each difference
                      (positive -> 1, negative -> -1)
        ;             append:
         ị"             the list of elements generated by taking
                        each row according to the index specified
                        by each entry of the permutation
           P          product of everything
              S   sum

工作原理-Mathy版本

运算符det取一个矩阵并返回一个标量。一个Ñ -by- Ñ矩阵可被认为是集合Ñ长度的矢量Ñ,所以DET是真的,需要一个功能Ñ矢量从ℤ Ñ并返回一个标量。

因此,我写DETv 1v 2v 3,...,v Ñ为)DET [ v 1 v 2 v 3 ... v Ñ ]。

注意,DET是线性的每个参数,即DETv 1瓦特1v 2v 3,...,v Ñ)= DETv 1v 2v 3,...,v Ñ)+ λdetw 1v 2v 3,...,v n)。因此,它是从(ℤ线性地图ÑÑ 到ℤ。

确定线性映射下的基础图像就足够了。(ℤ的基础ÑñÑ ℤ的基础元件的倍张量积Ñ,即例如È 5 ⊗ë 3 ⊗ë 1 ⊗Ë 5 ⊗ë 1。包含相同张量的张量积必须发送为零,因为两列相同的矩阵的行列式为零。剩下的工作是检查将不同基础元素的张量积发送给什么。张量积中向量的索引形成双射,即置换,其中偶数置换发送到1,奇数置换发送到-1。

例如,要查找[[1,2],[3,4]]的行列式:请注意,列为[​​1,3]和[2,4]。我们将[1,3]分解为(1 e 1 + 3 e 2)和(2 e 1 + 4 e 2)。在张量积的相应元件是(1E 1 ⊗2e的1 + 1 C 1 ⊗4 E 2 + 3e的2 ⊗2e的1 + 3e的2 ⊗4 E 2),我们简化到(图2e 1 ⊗ë 1个 + 4 E 1 ⊗ë 2 + 6e中2 ⊗ë 1 + 12e的2 ⊗ë 2)。因此:

DET [[1,2],[3,4]]
= DET(1E 1 + 3e的2,图2e 1和 + 4 E 2
= DET(图2e 1 ⊗ë 1 + 4 E 1 ⊗ë 2 + 6 e 2 e 1 + 12 e 2 e 2
= det(2 e 1 e 1)+ det(4 e 1 e 2)+ det(6 e 2 e 1)+ det(12 e2 ⊗ë 2
= 2 DET(E 1 ⊗ë 1)+ 4 DET(E 1 ⊗ë 2)+ 6 DET(E 2 ⊗ë 1)+ 12 DET(E 2 ⊗ë 2
= 2(0) + 4(1)+ 6(-1)+ 12(0)
= 4-6
= -2

现在,仍然需要证明用于查找置换的奇偶性的公式是有效的。我的代码所做的基本上是找到反转的次数,即,左侧元素大于右侧元素的位置(不一定是连续的)。

例如,在排列3614572中,存在9个反转(31、32、61、64、65、62、42、52、72),因此排列为奇数。

理由是每个置换(交换两个元素)要么添加一个反转,要么去除一个反转,交换反转次数的奇偶性,而置换的奇偶性就是实现置换所需的置换次数的奇偶性。

因此,总而言之,我们的公式由下式给出:

工作原理-非数学版本

其中σ是𝕊的置换Ñ的组上的所有排列的Ñ字母,SGN是置换的符号,AKA(-1)升高到置换的奇偶性,和一个IJ是(IJ在条目矩阵(i向下,j跨)。


17
那个“非数学版本”简直太数学了。
MD XF

6
@MDXF公式,符号和数字很难构成数学。数学是对符号进行形式操纵的抽象,概括和逻辑。
Leaky Nun

7
@JAB Jelly实现自己的自定义代码页。(这些天之一,TIO将包括指向代码页的链接...)
完全人类的,2017年

1
@Mego“对角乘积和”仅适用于1x1、2x2和3x3矩阵。对于更大的矩阵,您需要考虑所有排列及其奇偶性。
Leaky Nun

3
+1表示实际上在帖子中包含证明,而不是说“因为此公式在abcxyz页上列出,因此它必须为真”。
user202729

11

R,3个字节

平凡的解决方案

det

在线尝试!

R94 92字节

重新实施的解决方案

贾科·杜伯丹Jarko Dubbeldam)超越

d=function(m)"if"(x<-nrow(m),m[,1]%*%sapply(1:x,function(y)(-1)^(y-1)*d(m[-y,-1,drop=F])),1)

在线尝试!

在矩阵的第一列下递归使用未成年人的扩展。

f <- function(m){
 x <- nrow(m)                 # number of rows of the matrix
 if(sum(x) > 1){              # when the recursion reaches a 1x1, it has 0 rows
                              # b/c [] drops attributes
  minor <- function(y){
   m[y] * (-1)^(y-1) *
   d(m[-y,-1])                # recurse with the yth row and first column dropped
   }
  minors <- sapply(1:x,minor) # call on each row
  sum(minors)                 # return the sum
 } else {
  m                           # return the 1x1 matrix
 }
}



9

果冻16 15 12 10字节

Ḣ×Zß-Ƥ$Ṛḅ-

使用Laplace扩展感谢@miles打高尔夫球3 5个字节!

在线尝试!

怎么运行的

Ḣ×Zß-Ƥ$Ṛḅ-  Main link. Argument: M (matrix / 2D array)

Ḣ           Head; pop and yield the first row of M.
      $     Combine the two links to the left into a monadic chain.
  Z         Zip/transpose the matrix (M without its first row).
   ß-Ƥ      Recursively map the main link over all outfixes of length 1, i.e., over
            the transpose without each of its rows.
            This yields an empty array if M = [[x]].
 ×          Take the elementwise product of the first row and the result on the
            right hand. Due to Jelly's vectorizer, [x] × [] yields [x].
       Ṛ    Reverse the order of the products.
        ḅ-  Convert from base -1 to integer.
                [a]          -> (-1)**0*a
                [a, b]       -> (-1)**1*a + (-1)**0*b = b - a
                [a, b, c]    -> (-1)**2*a + (-1)**1*b + (-1)**0*c = c - b + a
                etc.

8

Wolfram语言(Mathematica),介于14到42个字节之间

我们有一个3字节的内置解决方案和一个53字节的解决方案,它完全避免了内置功能,因此这是介于两者之间的一些奇怪的解决方案。

Wolfram语言具有许多非常强大的功能,可以将矩阵分解为结构更简单的其他矩阵的乘积。Jordan分解是一种较简单的方法(意味着我以前已经听说过)。每个矩阵都类似于一个(可能是复数值)由具有特定结构的对角线块组成的上三角矩阵,称为该矩阵的约旦分解。相似度保留行列式,而三角形矩阵的行列式是对角元素的乘积,因此我们可以使用以下42个字节来计算行列式:

1##&@@Diagonal@Last@JordanDecomposition@#&

行列式也等于矩阵的特征值乘积的乘积。幸运的是,Wolfram的特征值函数可以跟踪多重性(即使对于非对角线矩阵也是如此),因此我们得到以下20字节解:

1##&@@Eigenvalues@#&

下一个解决方案是一种作弊方式,我不确定它为什么起作用。n个函数列表的Wronskian是该函数的前n -1个导数的矩阵的行列式。如果我们给该Wronskian函数一个整数矩阵,并说微分变量为1,则它将以某种方式吐出矩阵的行列式。很奇怪,但是它不包含字母“ Det”,并且只有14个字节

#~Wronskian~1&

(该Casoratian决定性的作品,以及,1个字节多:#~Casoratian~1&

在抽象代数的境界,一个行列式Ñ  X  Ñ是矩阵(作为图k→ķ由所述行列式相乘的思想)ñ基质的次外功率(采摘的同构后ķ→⋀ Ñ ķ n)。在Wolfram语言中,我们可以使用以下26个字节来实现

HodgeDual[TensorWedge@@#]&

这是仅适用于正行列式的解决方案。如果我们采用n维单位超立方体并对其进行线性变换,则所得区域的n维“体积”是该变换行列式的绝对值。将线性变换应用于多维数据集可以得到一个平行六面体,我们可以使用以下39个字节的代码来获取其体积:

RegionMeasure@Parallelepiped[Last@#,#]&

1
我遵循的思路是Exp@*Tr@*MatrixLog,但是不幸的是,这不适用于奇异矩阵。
米沙·拉夫罗夫

1
@MishaLavrov哦,这很聪明!我认为您可以使用进行修复Check[E^Tr@MatrixLog@#,0]&
不是一棵树

那很棒!我以前没有意识到Check
Misha Lavrov

1
不久前,我为Jordan分解提出了挑战。您可能也对此感兴趣。真是个好答案!
Mego

8

Haskell,71个字节

-3个字节,感谢Lynn。多亏了克雷格·罗伊(Craig Roy),才尘埃落定。

f[]=1
f(h:t)=foldr1(-)[v*f[take i l++drop(i+1)l|l<-t]|(i,v)<-zip[0..]h]

在线尝试! 添加了-O用于优化目的的标志。没有必要。

说明(过时)

f 递归地实现辅因子扩展。

f[[x]]=x

该行覆盖1 × 1矩阵的基本情况,在这种情况下,行列式为mat[0, 0]

f(h:t)=

这使用Haskell的模式匹配将矩阵分为(第一行)和(矩阵的其余部分)。

          [                                     |(i,v)<-zip[0..]h]

枚举矩阵的头部(通过压缩无限个整数列表和头部)并对其进行迭代。

           (-1)*i*v

由于行列式的计算涉及交替的加法和减法,因此根据其索引是否为偶数取反结果。

                     [take i l++drop(i+1)l|l<-t]

这实质上是通过采用i元素并将其与行连接而删除尾部的第ith列,并在尾部的每一行中删除第(i + 1)个元素。

                   *f

计算上述结果的行列式,然后将其乘以的结果(-1)*i*v

       sum

对以上列表的结果求和并返回。


2
如果替换为sum[(-1)^i*...,则可以节省1个字节foldr(-)0[...
Craig Roy

6

质子,99字节

f=m=>(l=len(m))==1?m[0][0]:sum((-1)**i*m[0][i]*f([[m[k][j]for k:1..l]for j:0..l if j-i])for i:0..l)

在线尝试!

Xcoder先生,
-3个字节;Outgolfer先生Erik,-3个字节

扩展第一行


只是因为Proton没有内置行列式。
user202729

103个字节((~i%2)*2-1)->((-i%2)|1)
Xcoder先生17年

也可以j!=ij-i或替换102个字节i-j
Xcoder先生17年


@EriktheOutgolfer啊,是的,谢谢!
HyperNeutrino

5

八度,28字节

@(x)round(prod(diag(qr(x))))

在线尝试!

这使用了QR分解的矩阵X到orthgonal矩阵Q和上三角矩阵[R X的行列式 是QR的乘积。正交矩阵具有单位行列式,而对于三角矩阵,行列式为其对角线项的乘积。八度音的qr功能调用单个输出给[R

结果四舍五入到最接近的整数。对于较大的输入矩阵,浮点错误可能会产生超过的误差0.5,从而导致错误的结果。


1
这是逃避det内建函数的有趣方式。;)
tomsmeding

1
@tomsmeding :-)而且,它已经在Stewie的答案中
Luis Mendo


5

C, 176 字节

感谢@ceilingcat打高尔夫球42个字节,也感谢@Lynn和@Jonathan Frech分别节省了一个字节!

d(M,n)int*M;{int i=n--,s=*M*!n,c,T[n*n];for(;i--;s+=M[i]*(1-i%2*2)*d(T,n))for(c=n*n;c--;T[c]=M[n-~c+c/n+(c%n>=i)]);return s;}

使用沿第一行的拉普拉斯展开式计算行列式。

在线尝试!

展开:

d(M, n)int*M;
{
    int i=n--, s=*M*!n, c, T[n*n];
    for (; i--; s+=M[i]*(1-i%2*2)*d(T,n))
        for (c=n*n; c--;)
            T[c] = M[n-~c+c/n+(c%n>=i)];
    return s;
}

(i%2*-2+1)→再(1-i%2*2)保存一个字节。
林恩

n+1+c可以n-~c
乔纳森·弗雷希

建议i=s而不是return s
ceilingcat '17

5

果冻,43个字节

最后,我用高尔夫球语言编写了非内置解决方案!

ḣ⁹’’¤;ṫḊ€Ç×⁸ị@⁹’¤¤ḷ/¤
çЀ⁸J‘¤µJ-*×NS
ÇḢḢ$Ṗ?

感谢HyperNeutrino节省了一个字节!

在线尝试!(为清楚起见,用空格隔开)

从列表中删除第n个元素的方法非常漫长,以后会有所改进


HyperNeutrino,Dennis和Leaky Nun的答案已经超出了这个答案。果冻是作为高尔夫语言非常受欢迎。

快速说明:

ÇḢḢ$Ṗ?    Main link.
     ?    If
    Ṗ     after remove the last element, the value is not empty (truthy)
Ç         then execute the last link
 ḢḢ$      else get the element at index [1, 1].

çЀ⁸J‘¤µJ-*×NS     Helper link 1, take input as a matrix.
çЀ                Apply the previous link, thread right argument to
   ⁸J‘¤            the range [2, 3, ..., n+1]
       µ           With the result,
        J-*        generate the range [-1, 1, -1, 1, ...] with that length
           ×N      Multiply by negative
             S     Sum

ḣ⁹’’¤;ṫḊ€Ç×⁸ị@⁹’¤¤ḷ/¤    Helper link 2, take left input as a matrix, right input as a number in range [2..n+1]
ḣ
 ⁹’’¤                    Take head ρ-2 of the matrix
     ;                   concatenate with 
      ṫ                  tail ρ (that is, remove item ρ-1)
       Ḋ€                Remove first column
         Ç               Calculate determinant of remaining matrix
          ×         ¤    multiply by
                  ḷ/     the first column,
            ị@           row #
              ⁹’¤        ρ-1 (just removed in determinant calculation routine) of
           ⁸     ¤       the matrix.

4

果冻,24字节

œcL’$ṚÑ€
J-*×Ḣ€×ÇSµḢḢ$Ṗ?

在线尝试!

说明

œcL’$ṚÑ€         Helper Link; get the next level of subdeterminants (for Laplace Expansion)
œc               Combinations without replacement of length:
  L’$            Length of input - 1 (this will get all submatrices, except it's reversed)
     Ṛ           Reverse the whole thing
      р         Get the determinant of each of these
J-*×Ḣ€×ÇSµḢḢ$Ṗ?  Main Link
              ?  If the next value is truthy
             Ṗ   Remove the last element (truthy if the matrix was at least size 2)
J-*×Ḣ€×ÇSµ       Then expand
          ḢḢ$    Otherwise, get the first element of the first element (m[0][0] in Python)
J                [1, 2, ..., len(z)]
 -*              (-1 ** z) for each z in the length range
   ×             Vectorizing multiply with
    Ḣ€           The first element of each (this gets the first column); modifies each row (makes it golfier yay)
      ×Ç         Vectorizing multiply with the subdeterminants
        S        Sum

-2个字节归功于user202729的解决方案


4

玛特,3个字节/ 5个字节

具有内置功能

&0|

在线尝试!

没有内置

感谢Misha Lavrov指出了一个错误,现已更正

YvpYo

在线尝试!

这将行列式计算为特征值的乘积,四舍五入到最接近的整数以避免浮点错误。

Yv       % Implicit input. Push vector containing the eigenvalues
p        % Product
Yo       % Round. Implicit display

奇异值的乘积不只能告诉您行列式的绝对值吗?
Misha Lavrov

@MishaLavrov你完全正确!感谢您的关注。我通过使用特征值而不是奇异值来更正了它……并节省了4个字节\ o /
Luis Mendo


3

八度,30字节

@(x)-prod(diag([~,l,~]=lu(x)))

在线尝试!

或者,无聊的4字节解决方案(由于Luis Mendo节省了6个字节(忘记了有关内置函数的规则)):

@det

说明:

接下来!:)


3

TI基本,2字节

det(Ans

呃,好吧。

请不要赞成琐碎的答案。

作为高中生(被迫拥有其中一个计算器),此功能非常有用,因此...


8
它仍然是有用的海拉大学-线性代数不会消失
泰勒·斯科特

5
@TaylorScott实际上,它以微分方程的形式复出。
Mego

@Mego-你是对的;尽管由于某些原因,他们让我接受了所有的calc和线性之前的内容:/
Taylor Scott Scott

1
@TaylorScott由于我大学的数学系的监督,linalg并不是我获得diffeq的先决条件。当我的教授意识到这一点时,他很快给了我们在利纳尔格为期3天的速成课程。
Mego

3

Haskell,62个字节

a#((b:c):r)=b*d(a++map tail r)-(a++[c])#r
_#_=0
d[]=1
d l=[]#l

在线尝试!(以@totallyhuman解决方案中的测试用例为基础)

d使用沿第一列的Laplace展开来计算行列式。需要比永久字节多三个字节。



3

Wolfram语言(Mathematica)53 52字节

1##&@@@(t=Tuples)@#.Signature/@t[Range@Tr[1^#]&/@#]&

在线尝试!

不幸的是,以这种方式计算n × n矩阵的行列式会使用O(n n)内存,这使大型测试用例无法触及。

怎么运行的

第一部分1##&@@@(t=Tuples)@#从给定矩阵的每一行中计算出一项的所有可能乘积。t[Range@Tr[1^#]&/@#]给出一个长度相同的列表,其元素类似于{3,2,1}{2,2,3}说我们为相应产品选择的每一行的哪个条目。

我们将其应用于Signature第二个列表,该列表将偶数排列映射到1,将奇数排列映射到,将-1非排列映射到0。这正是相应乘积出现在行列式中的系数。

最后,我们采用两个列表的点积。


如果甚至Signature太多内置,我们可以取73个字节

1##&@@@(t=Tuples)@#.(1##&@@Order@@@#~Subsets~{2}&/@t[Range@Tr[1^#]&/@#])&

替换为1##&@@Order@@@#~Subsets~{2}&。这Signature通过将Order应用乘积应用于置换的所有成对元素来计算可能的置换。Order将给出1该对是否按升序排列,-1是否按降序排列以及0相等。


-1个字节感谢@ user202729


1
52个字节(以防万一您不知道Mathematica高尔夫球技巧)
user202729

我做到了,但不知何故在这里忘记了。谢谢!
Misha Lavrov

3

Python 3中238个字节227个字节224个字节216个字节

from functools import*
from itertools import*
r=range;n=len;s=sum
f=lambda l:s(reduce(lambda p,m:p*m,[l[a][b]for a,b in zip(r(n(l)),j)])*(-1)**s(s(y<j[x]for y in j[x:])for x in r(n(l)))for j in permutations(r(n(l))))

在线尝试!

我的解决方案使用行列式的定义进行计算。不幸的是,这种算法的复杂度很高,n!我无法显示最后一次测试的通过,但是从理论上讲这是可能的。


3

CJam(50 45字节)

{:A_,{1$_,,.=1b\)/:CAff*A@zf{\f.*1fb}..-}/;C}

这是一个匿名块(函数),它在堆栈上采用2D数组,并在堆栈上保留整数。

在线测试套件

解剖

这实现了Faddeev-LeVerrier算法,我认为这是采用该方法的第一个答案。

Cķñ×ñ一种

pλtλ一世ñ-一种=ķ=0ñCķλķ
Cñ=1个C0=-1个ñt一种

中号

中号00Cñ=1个ķ=0中号ķ一种中号ķ-1个+Cñ-ķ+1个一世Cñ-ķ=-1个ķŤ[R一种中号ķķ=1个ñ 

Cñ-ķ中号ķ-1个ķCñ-ķ-1个ķ+1个一种中号ķ

-1个ķCñ-ķ=1个ķŤ[R-1个ķ+1个一种中号ķ-1个ķ+2一种中号ķ+1个=-1个ķCñ-ķ一种-一种-1个ķ+1个一种中号ķ

{               e# Define a block
  :A            e#   Store the input matrix in A
  _,            e#   Take the length of a copy
  {             e#     for i = 0 to n-1
                e#       Stack: (-1)^{i+2}AM_{i+1} i
    1$_,,.=1b   e#       Calculate tr((-1)^{i+2}AM_{i+1})
    \)/:C       e#       Divide by (i+1) and store in C
    Aff*        e#       Multiply by A
    A@          e#       Push a copy of A, bring (-1)^{i+2}AM_{i+1} to the top
    zf{\f.*1fb} e#       Matrix multiplication
    ..-         e#       Matrix subtraction
  }/
  ;             e#   Pop (-1)^{n+2}AM_{n+1} (which incidentally is 0)
  C             e#   Fetch the last stored value of C
}



2

SageMath,各种

这是一堆用于计算我发现有趣的行列式的方法,所有方法都在SageMath中编程。他们都可以在这里尝试。

内置3字节

det

这个不太有趣。Sage为通常是对象方法的许多常见操作提供了全局级别的别名,因此比短lambda m:m.det()


特征值乘积的实部,36字节

lambda m:real(prod(m.eigenvalues()))

不幸的是,eigenvalues不是这些全局级别的别名之一。结合Sage没有整齐的功能编写方法的事实,这意味着我们受制于昂贵的lambda。此功能的符号值在打印时会自动转换为数值,因此某些输出中可能会出现一些浮点数不准确的情况。


Jordan形式对角线的乘积,60字节

lambda m:prod(m.jordan_form()[x,x]for x in range(m.nrows()))

在约旦范式中,NxN矩阵表示为块矩阵,对角线上有N个块。每个块由单个特征值或MxM矩阵组成,该矩阵在对角线上具有重复的特征值,在对角线1上(“主”对角线上方和右侧的对角线)具有s。这样就产生了一个矩阵,其中所有特征值(具有多重性)在主对角线上,而1在超对角线上的一些s与重复的特征值相对应。这将返回约旦法线形式的对角线的乘积,该乘积是特征值(具有多重性)的乘积,因此这是执行与先前解决方案相同的计算的更round回的方式。

因为Sage希望Jordan范式与原始矩阵在同一环上,所以这仅在所有特征值都是有理值的情况下才有效。复杂的特征值会导致错误(除非原始矩阵在圆环上CDF(复杂的双浮点数)或SR)。但是,这意味着与上述解决方案相比,没有必要真正发挥作用。


Smith分解中对角线的乘积

lambda m:prod(m.smith_form()[0].diagonal())

与Jordan范式不同,Smith范式可以保证与原始矩阵在同一字段上。Smith分解不是计算特征值并用块对角矩阵表示它们,而是计算矩阵的基本除数(这对于本帖子来说有点太复杂了),将它们放入对角矩阵D,并用单位计算两个矩阵行列式UV使得D = U*A*V(其中A是原始矩阵)。由于矩阵乘积的行列式等于矩阵行列式的乘积(det(A*B*...) = det(A)*det(B)*...),U并且V被定义为具有单位行列式,因此det(D) = det(A)。对角矩阵的行列式只是对角线上元素的乘积。

拉普拉斯扩展,109字节

lambda m:m.nrows()>1and sum((-1)**j*m[0,j]*L(m[1:,:j].augment(m[1:,j+1:]))for j in range(m.ncols()))or m[0,0]

这将使用递归方法沿第一行执行Laplace扩展。det([[a]]) = a用于基本情况。det([[]]) = 1对于基本情况,它应该更短一些,但是在该实现中的尝试有一个我尚未能够找到的错误。


莱布尼兹公式,100字节

L2 = lambda m:sum(sgn(p)*prod(m[k,p[k]-1]for k in range(m.ncols()))for p in Permutations(m.ncols()))

这直接实现了莱布尼兹的公式。要获得比我可能写的更好的有关公式及其作用的解释,请参见此出色的答案


的实部e^(Tr(ln(M))),48个字节

lambda m:real(exp(sum(map(ln,m.eigenvalues()))))

此函数返回符号表达式。要获得数值近似值,请n(result)在打印前致电。

这是我尚未看到任何人使用的方法。我将对此进行更详细的解释。

A实数的平方矩阵。根据定义,的行列式A等于的特征值的乘积A。的踪迹A等于A特征值之和。对于实数r_1r_2exp(r_1) * exp(r_2) = exp(r_1 + r_2)。由于矩阵指数函数被定义为类似于标量指数函数(尤其是在以前的恒等式中),并且矩阵指数可以通过将矩阵对角线化并将标量指数函数应用于对角线上的特征值来计算。det(exp(A)) = exp(trace(A))(的产物exp(λ)为每个特征值λA等于的本征值的总和exp(A))。因此,如果我们能找到一个矩阵L,使得exp(L) = A,我们可以计算det(A) = exp(trace(L))

我们可以L通过计算找到这样的矩阵log(A)。可以采用与矩阵指数相同的方式来计算矩阵对数:通过将标量对数函数应用于的每个特征值来形成对角线正方形矩阵A(这就是我们限制A为实数的原因)。由于我们只关心的踪迹L,因此可以跳过结构,而直接将特征值的指数求和即可。即使矩阵不在复环上,特征值也可能是复数,因此我们将总和的实数作为实数。


1
最后一部分是一个引人入胜的想法,但是标题和解释与代码不匹配,该代码不采用矩阵对数。只是没有real(prod(m.eigenvalues()))高尔夫球。
彼得·泰勒

2

Java的8,266个 261 259 258字节

long d(int[][]m){long r=0;int i=0,j,k,l=m.length,t[][]=new int[l-1][l-1],q=m[0][0];if(l<3)return l<2?q:q*m[1][1]-m[0][1]*m[1][0];for(;i<l;r+=m[0][i]*(1-i++%2*2)*d(t))for(j=0;++j<l;)for(k=l;k-->0;){q=m[j][k];if(k<i)t[j-1][k]=q;if(k>i)t[j-1][k-1]=q;}return r;}

妈妈,没有内置插件。. 因为Java没有内置插件。

-7个字节,感谢@ceilingcat

说明:

在这里尝试。(只有最后一个测试用例太大,无法容纳long2 63 -1 的大小。)

long d(int[][]m){             // Method with integer-matrix parameter and long return-type
  long r=0;                   //  Return-long, starting at 0
  int i=0,j,k,                //  Index-integers
      l=m.length,             //  Dimensions of the square matrix
      t[][]=new int[l-1][l-1],//  Temp-matrix, one size smaller than `m`
      q=m[0][0];              //  The first value in the matrix (to reduce bytes)
  if(l<3)                     //  If the dimensions are 1 or 2:
    return l<2?               //   If the dimensions are 1:
      q                       //    Simply return the only item in it
     :                        //   Else (the dimensions are 2):
      q*m[1][1]-m[0][1]*m[1][0];
                              //    Calculate the determinant of the 2x2 matrix
                              //  If the dimensions are 3 or larger: 
  for(;i<l;                   //  Loop (1) from 0 to `l` (exclusive)
      r+=                     //    After every iteration: add the following to the result:
         m[0][i]              //     The item in the first row and `i`'th column,
         *(1-i++%2*2)         //     multiplied by 1 if `i` is even; -1 if odd,
         *d(t))               //     multiplied by a recursive call with the temp-matrix
    for(j=0;                  //   Reset index `j` to 0
        ++j<l;)               //   Inner loop (2) from 0 to `l` (exclusive)
      for(k=l;k-->0;){        //    Inner loop (3) from `l-1` to 0 (inclusive)
        q=m[j][k];            //     Set the integer at location `j,k` to reduce bytes
        if(k<i)               //     If `k` is smaller than `i`:
          t[j-1][k]=q;        //      Set this integer at location `j-1,k`
        if(k>i)               //     Else-if `k` is larger than `i`:
          t[j-1][k-1]=q;      //      Set this integer at location `j-1,k-1`
                              //     Else: `k` and `i` are equals: do nothing (implicit)
      }                       //    End of inner loop (3)
                              //   End of inner loop (2) (implicit / single-line body)
                              //  End of loop (1) (implicit / single-line body)
  return r;                   //  Return the result-long
}                             // End of method

2

JavaScript(ES6),91

递归拉普拉斯

q=(a,s=1)=>+a||a.reduce((v,[r],i)=>v-(s=-s)*r*q(a.map(r=>r.slice(1)).filter((r,j)=>j-i)),0)

少打高尔夫球

q = (a,s=1) => // s used as a local variable
  a[1] // check if a is a single element array 
       // if array, recursive call expanding along 1st column
  ? a.reduce((v,[r],i) => v-(s=-s)*r*q(a.map(r=>r.slice(1)).filter((r,j)=>j-i)),0) 
  : +a // single element, convert to number

测试

q=(a,s=1)=>+a||a.reduce((v,[r],i)=>v-(s=-s)*r*q(a.map(r=>r.slice(1)).filter((r,j)=>j-i)),0)

TestCases=`[[42]] -> 42
[[2, 3], [1, 4]] -> 5
[[1, 2, 3], [4, 5, 6], [7, 8, 9]] -> 0
[[13, 17, 24], [19, 1, 3], [-5, 4, 0]] -> 1533
[[372, -152, 244], [-97, -191, 185], [-53, -397, -126]] -> 46548380
[[100, -200, 58, 4], [1, -90, -55, -165], [-67, -83, 239, 182], [238, -283, 384, 392]] -> 571026450
[[432, 45, 330, 284, 276], [-492, 497, 133, -289, -28], [-443, -400, 56, 150, -316], [-344, 316, 92, 205, 104], [277, 307, -464, 244, -422]] -> -51446016699154`
.split('\n')

TestCases.forEach(r=>{
  [a,k] = r.split (' -> ')
  a = eval(a)
  d = q(a)
  console.log('Test '+(k==d ? 'OK':'KO')+
    '\nMatrix '+a.join('|')+
    '\nResult '+d+
    '\nCheck  '+k)
})


83个字节具有相同的行为
Arnauld

85个字节来支持空矩阵(其行列式应为1)。
Arnauld

(我在此答案中使用了相同的优化方法,优化方法是从您的答案中得出的。)
Arnauld




1

爪哇(OpenJDK的8) 195个192 177字节

long d(int[][]m){long D=0;for(int l=m.length-1,t[][]=new int[l][l],i=0,j,k;i<=l;D+=m[0][i]*(1-i++%2*2)*(l<1?1:d(t)))for(j=0;j<l*l;)t[j/l][k=j%l]=m[1+j++/l][k<i?k:k+1];return D;}

在线尝试!

像许多其他答案一样,它也使用拉普拉斯公式。略少打高尔夫球的版本:

long d(int[][]m){
  long D=0;
  int l=m.length-1,t[][]=new int[l][l],i=0,j,k;
  for(;i<=l;)
    for(j=0;j<l*l;)
      t[j/l][k=j%l]=m[1+j++/l][k<i?k:k+1];
    D+=m[0][i]*(1-i++%2*2)*(l<1?1:d(t));
  return D;
}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.