Determinante einer Ganzzahlmatrix


34

Geben Sie bei einer quadratischen Ganzzahlmatrix als Eingabe die Determinante der Matrix aus.

Regeln

  • Sie können davon ausgehen, dass alle Elemente in der Matrix, die Determinante der Matrix und die Gesamtzahl der Elemente in der Matrix innerhalb des für Ihre Sprache darstellbaren Bereichs von Ganzzahlen liegen.
  • Die Ausgabe eines Dezimal- / Gleitkommawerts mit einem Bruchteil von 0 ist zulässig (z . B. 42.0anstelle von 42).
  • Integrierte Funktionen sind zulässig, Sie werden jedoch aufgefordert, eine Lösung einzuschließen, die keine integrierten Funktionen verwendet.

Testfälle

[[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


Gibt es eine maximale Größe der Matrix, die unterstützt werden muss, oder ist sie willkürlich?
Taylor Scott

1
@ TaylorScott Erste Regel aufgeführt: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
Sie wissen, dass Sie eine interessante Herausforderung haben, wenn Sie 4 Jelly-Antworten hintereinander haben, die sich gegenseitig
herausfordern

Antworten:


25

Gelee , 15 Bytes

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

Probieren Sie es online!

Wie es funktioniert

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

Warum es funktioniert - Mathy-Version

Der Operator det nimmt eine Matrix und gibt einen Skalar zurück. Eine n- by- n- Matrix kann als Sammlung von n Vektoren der Länge n betrachtet werden. Det ist also eine Funktion, die n Vektoren von ℤ n nimmt und einen Skalar zurückgibt.

Daher schreibe ich det ( v 1 , v 2 , v 3 , ..., v n ) für det [ v 1 v 2 v 3 ... v n ].

Beachten Sie, dass det in jedem Argument linear ist, dh det ( v 1 + λ w 1 , v 2 , v 3 , ..., v n ) = det ( v 1 , v 2 , v 3 , ..., v n ) + λ det ( w 1 , v 2 , v 3 , ..., v n ). Daher ist es eine lineare Abbildung von (ℤ n ) n zu ℤ.

Es reicht aus, das Bild der Basis unter der linearen Karte zu bestimmen. Die Basis von (ℤ n ) n besteht aus n- fachen Tensorprodukten der Basiselemente von ℤ n , dh e 5 ⊗ e 3 ⊗ e 1 ⊗ e 5 ⊗ e 1 . Tensorprodukte, die identische Tensoren enthalten, müssen zu Null gesendet werden, da die Determinante einer Matrix, in der zwei Spalten identisch sind, Null ist. Es bleibt zu prüfen, wohin die Tensorprodukte verschiedener Basiselemente geschickt werden. Die Indizes der Vektoren im Tensorprodukt bilden eine Bijektion, dh eine Permutation, bei der gerade Permutationen zu 1 und ungerade Permutationen zu -1 gesendet werden.

Um zum Beispiel die Determinante von [[1, 2], [3, 4]] zu finden: Beachten Sie, dass die Spalten [1, 3] und [2, 4] sind. Wir zerlegen [1, 3] zu (1 e 1 + 3 e 2 ) und (2 e 1 + 4 e 2 ). Das entsprechende Element im Tensorprodukt ist (1 e 1 ⊗ 2 e 1 + 1 e 1 ⊗ 4 e 2 + 3 e 2 ⊗ 2 e 1 + 3 e 2 ⊗ 4 e 2 ), was wir zu (2 e 1 vereinfachen ⊗ e 1 + 4 e 1 ⊗ e 2 + 6 e 2 ⊗ e 1 + 12 e 2 ⊗ e 2). Deshalb:

det [[1, 2], [3, 4]]
= det (1 e 1 + 3 e 2 , 2 e 1 + 4 e 2 )
= det (2 e 1 ⊗ e 1 + 4 e 1 ⊗ e 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 ≤ e 2 )
= 2 det (e 1 ≤ e 1 ) + 4 det (e 1 ≤ e 2 ) + 6 det (e 2 ≤ e 1 ) + 12 det (e 2 ≤ e 2 )
= 2 (0) + 4 (1) + 6 (-1) + 12 (0)
= 4 - 6
= -2

Nun bleibt zu beweisen, dass die Formel zur Ermittlung der Parität der Permutation gültig ist. Mein Code ermittelt im Wesentlichen die Anzahl der Inversionen, dh die Stellen, an denen ein Element auf der linken Seite größer ist als ein Element auf der rechten Seite (nicht unbedingt nacheinander).

Beispielsweise gibt es in der Permutation 3614572 9 Inversionen (31, 32, 61, 64, 65, 62, 42, 52, 72), so dass die Permutation ungerade ist.

Die Begründung ist, dass jede Transposition (Vertauschen von zwei Elementen) entweder eine Inversion hinzufügt oder eine Inversion entfernt, wobei die Parität der Anzahl der Inversionen vertauscht wird, und die Parität der Permutation die Parität der Anzahl der Transpositionen ist, die zum Erreichen der Permutation erforderlich sind.

Abschließend lautet unsere Formel also:

Warum es funktioniert - Nicht-Mathy-Version

wobei σ eine Permutation von 𝕊 n ist, die Gruppe aller Permutationen auf n Buchstaben, und sgn das Vorzeichen der Permutation ist, AKA (-1) auf die Parität der Permutation angehoben ist und a ij der ( ij ) -te Eintrag in ist die Matrix ( i runter, j rüber).


17
Diese "nicht-mathematische Version" ist verdammt mathematisch.
MD XF

6
@MDXF Formeln und Symbole und Zahlen bilden kaum Mathematik. Mathematik ist die Abstraktion und Verallgemeinerung und die Logik hinter den formalen Manipulationen der Symbole.
Undichte Nonne

7
@JAB Jelly implementiert eine eigene benutzerdefinierte Codepage . (Eines Tages wird TIO einen Link zur Codepage enthalten ...)
totalhuman

1
@Mego Die "Summe der diagonalen Produkte" funktioniert nur für 1x1-, 2x2- und 3x3-Matrizen. Für größere Matrizen müssen Sie alle Permutationen und ihre Parität berücksichtigen.
Undichte Nonne

3
+1 für tatsächlich den Beweis in den Beitrag einschließen, anstatt zu sagen, "weil diese Formel auf der Seite abcxyz aufgeführt ist, muss es wahr sein".
User202729

11

R , 3 Bytes

Triviale Lösung

det

Probieren Sie es online!

R , 94 92 Bytes

neu implementierte Lösung

von Jarko Dubbeldam überfordert

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

Probieren Sie es online!

Verwendet rekursiv die Erweiterung durch Minderjährige in der ersten Spalte der Matrix.

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

Jelly , 16 15 12 10 Bytes

Ḣ×Zß-Ƥ$Ṛḅ-

Verwendet die Laplace-Erweiterung . Vielen Dank an @miles für das Abschlagen von 3 bis 5 Bytes!

Probieren Sie es online!

Wie es funktioniert

Ḣ×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 Language (Mathematica) , zwischen 14 und 42 Byte

Wir hatten eine 3-Byte- Lösung und eine 53-Byte-Lösung , die keine eingebauten Elemente enthält. Hier sind also einige seltsamere Lösungen, die irgendwo dazwischen liegen.

Die Wolfram-Sprache hat viele sehr intensive Funktionen zum Zerlegen von Matrizen in Produkte anderer Matrizen mit einfacherer Struktur. Eine der einfacheren ist die Jordan-Zersetzung. Jede Matrix ähnelt einer (möglicherweise komplexwertigen) oberen Dreiecksmatrix aus diagonalen Blöcken mit einer bestimmten Struktur, der Jordan-Zerlegung dieser Matrix. Ähnlichkeit bewahrt Determinanten, und die Determinante einer Dreiecksmatrix ist das Produkt der diagonalen Elemente, sodass wir die Determinante mit den folgenden 42 Bytes berechnen können :

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

Die Determinante ist auch gleich dem Produkt der Eigenwerte einer Matrix mit Multiplizität. Glücklicherweise verfolgt Wolframs Eigenwertfunktion die Multiplizität (auch für nicht diagonalisierbare Matrizen), sodass wir die folgende 20-Byte- Lösung erhalten:

1##&@@Eigenvalues@#&

Die nächste Lösung ist Betrug und ich bin mir nicht sicher, warum es funktioniert. Der Wronskian einer Liste von n Funktionen ist die Determinante der Matrix der ersten n- 1-Ableitungen der Funktionen. Wenn wir der WronskianFunktion eine Ganzzahlmatrix geben und sagen, dass die Differenzierungsvariable 1 ist, spuckt sie irgendwie die Determinante der Matrix aus. Es ist komisch, aber es beinhaltet nicht die Buchstaben " Det" und es sind nur 14 Bytes ...

#~Wronskian~1&

(Die Casoratian Determinante funktioniert auch, für 1 weitere Byte: #~Casoratian~1&)

Im Bereich der abstrakten Algebra, die Determinante eines n  x  n - Matrix (gedacht als die Karte k → k dh Multiplikation mit dem Faktor) ist die n - te äußerte Macht der Matrix (nach einem Isomorphismus Kommissionierung k → ⋀ n k n ). In der Wolfram-Sprache können wir dies mit den folgenden 26 Bytes tun :

HodgeDual[TensorWedge@@#]&

Und hier ist eine Lösung, die nur für positive Determinanten funktioniert. Wenn wir einen n- dimensionalen Einheitshyperwürfel nehmen und auf ihn eine lineare Transformation anwenden, ist das n- dimensionale "Volumen" der resultierenden Region der absolute Wert der Determinante der Transformation. Das Anwenden einer linearen Transformation auf einen Würfel ergibt ein Parallelepiped, und wir können sein Volumen mit den folgenden 39 Byte Code annehmen :

RegionMeasure@Parallelepiped[Last@#,#]&

1
Die Lösung, die ich in diese Richtung hatte, war Exp@*Tr@*MatrixLog, aber leider funktioniert dies nicht für einzelne Matrizen.
Mischa Lawrow

1
@ Mischa Lawrow Ooh, das ist klug! Ich denke, Sie können es mit beheben Check[E^Tr@MatrixLog@#,0]&.
Kein Baum

Das ist großartig! Ich hatte vorher nicht gewusst Check.
Mischa Lawrow

1
Ich habe vor einiger Zeit eine Herausforderung für Jordan Decomposition erstellt. Das könnte Sie auch interessieren. Was für eine großartige Antwort!
Mego

8

Haskell , 71 Bytes

-3 Bytes dank Lynn. Ein weiteres Mal ist es Craig Roy zu verdanken, dass es den Staub aufwirbelt.

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

Probieren Sie es online! Flag für Optimierungszwecke hinzugefügt -O. Es ist nicht notwendig.

Erklärung (veraltet)

f Implementiert rekursiv die Cofaktor-Erweiterung.

f[[x]]=x

Diese Linie deckt den Basisfall einer 1 × 1- Matrix ab, in welchem ​​Fall die Determinante ist mat[0, 0].

f(h:t)=

Dies verwendet Haskells Mustervergleich , um die Matrix in einen Kopf (die erste Reihe) und einen Schwanz (den Rest der Matrix) aufzuteilen.

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

Zählen Sie den Kopf der Matrix auf (indem Sie die unendliche Liste der ganzen Zahlen und den Kopf zippen) und iterieren Sie darüber.

           (-1)*i*v

Negieren Sie das Ergebnis basierend darauf, ob sein Index gerade ist, da die Berechnung der Determinante eine abwechselnde Addition und Subtraktion umfasst.

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

Dies entfernt im Wesentlichen die i-te Spalte des Schwanzes, indem i- Elemente genommen und mit der Zeile verkettet werden, in der für jede Zeile im Schwanz das erste (i + 1) -te Element abgelegt wird.

                   *f

Berechnen Sie die Determinante des obigen Ergebnisses und multiplizieren Sie sie mit dem Ergebnis von (-1)*i*v.

       sum

Summieren Sie das Ergebnis der obigen Liste und geben Sie es zurück.


2
Sie könnten 1 Byte sparen, wenn Sie das sum[(-1)^i*...durchfoldr(-)0[...
Craig Roy

6

Proton , 99 Bytes

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)

Probieren Sie es online!

-3 Bytes dank Mr. Xcoder
-3 Bytes dank Erik the Outgolfer

Expansion über die erste Reihe


Nur weil Proton keine Determinante eingebaut hat.
user202729

103 Bytes . ((~i%2)*2-1)->((-i%2)|1)
Mr. Xcoder

Auch 102 Bytes durch Ersetzen j!=imit j-ioder i-j.
Herr Xcoder


@EriktheOutgolfer Ah ja, danke!
HyperNeutrino

5

Oktave , 28 Bytes

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

Probieren Sie es online!

Dies verwendet die QR - Zerlegung einer Matrix X in eine orthgonal Matrix Q und eine obere Dreiecksmatrix R . Die Determinante X ist das Produkt von denen von Q und R . Eine orthogonale Matrix hat eine Einheitsdeterminante, und für eine dreieckige Matrix ist die Determinante das Produkt ihrer diagonalen Einträge. Octave - qrFunktion mit einem einzigen Ausgang genannt gibt R .

Das Ergebnis wird auf die nächste ganze Zahl gerundet. Bei großen Eingangsmatrizen können Gleitkommaungenauigkeiten einen Fehler von mehr als 0.5und damit ein falsches Ergebnis erzeugen.


1
Das ist eine interessante Möglichkeit, dem deteingebauten System auszuweichen . ;)
Tomsmeding

1
@tomsmeding :-) Außerdem wurde es bereits in Stewies Antwort
Luis Mendo


5

C,  176 bis  125 Bytes

Vielen Dank an @ceilingcat für das Golfen mit 42 Bytes und an @Lynn und @Jonathan Frech für das Speichern von jeweils einem Byte!

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;}

Berechnet die Determinante anhand der Laplace-Erweiterung in der ersten Zeile.

Probieren Sie es online!

Abgerollt:

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)speichert ein weiteres Byte.
Lynn

n+1+ckann sein n-~c.
Jonathan Frech

Schlagen Sie i=sstattdessenreturn s
ceilingcat 25.11.17

5

Jelly , 43 Bytes

Endlich habe ich meine nicht eingebaute Lösung in einer Golfsprache geschrieben!

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

Vielen Dank an HyperNeutrino für das Speichern eines Bytes!

Probieren Sie es online! (Der Klarheit halber mit einem Code versehen)

Der furchtbar lange Weg, n-te Elemente aus einer Liste zu entfernen, wird sich später verbessern


Diese Antwort war von den Antworten von HyperNeutrino, Dennis und Leaky Nun übertroffen worden. Jelly ist als Golfsprache sehr beliebt.

Schnelle Erklärung:

ÇḢḢ$Ṗ?    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

Gelee , 24 Bytes

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

Probieren Sie es online!

Erläuterung

œ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 Bytes dank der Lösung von user202729


4

MATL , 3 Bytes / 5 Bytes

Mit eingebauter Funktion

&0|

Probieren Sie es online!

Ohne eingebaut

Vielen Dank an Mischa Lawrow für den Hinweis auf einen jetzt korrigierten Fehler

YvpYo

Probieren Sie es online!

Dies berechnet die Determinante als Produkt der Eigenwerte, auf die nächste ganze Zahl gerundet, um Gleitkommaungenauigkeiten zu vermeiden.

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

Würde Ihnen das Produkt der singulären Werte nicht nur den absoluten Wert der Determinante mitteilen?
Mischa Lawrow

@ Mischa Lawrow Du hast vollkommen recht! Danke fürs bemerken. Ich habe es korrigiert, indem ich Eigenwerte anstelle von Singularwerten verwendet habe ... und das hat 4 Bytes gespart \ o /
Luis Mendo

4

R , 32 Bytes

function(m)Re(prod(eigen(m)$va))

Verwendet den Algorithmus von Not a Tree, bei dem die Eigenwerte der Matrix und der Realteil ihres Produkts genommen werden.

Probieren Sie es online!


Sehr elegant! +1.
Giuseppe

3

Oktave , 30 Bytes

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

Probieren Sie es online!

oder die langweilige 4-Byte-Lösung (6 Bytes gespart dank Luis Mendo (die Regeln bezüglich der eingebauten Funktionen wurden vergessen)):

@det

Erläuterung:

Komm auf! :)


3

TI-Basic, 2 Bytes

det(Ans

Ah, gut.

Bitte stimmen Sie nicht mit trivialen Antworten überein.

Als Gymnasiast (der gezwungen ist, einen dieser Taschenrechner zu besitzen) ist diese Funktion ...


8
Es ist immer noch hella nützlich in der Schule - lineare Algebra geht nicht weg
Taylor Scott

5
@ TaylorScott In der Tat kommt es mit einer Rache in Differentialgleichungen zurück.
Mego

@Mego - da hast du recht; obwohl aus irgendeinem Grund lassen sie mich alle calc und das vor linear nehmen: /
Taylor Scott

1
@TaylorScott Aufgrund eines Versehens der mathematischen Fakultät meiner Universität war Linalg keine Voraussetzung für verschiedene Prüfungen, als ich sie ablegte. Als mein Professor das bemerkte, gab er uns schnell einen dreitägigen Crashkurs in Linalg.
Mego

3

Haskell, 62 Bytes

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

Probieren Sie es online! (Fußzeile mit Testfällen aus der Lösung von @ totallyhuman.)

dberechnet die Determinante unter Verwendung einer Laplace-Erweiterung entlang der ersten Spalte. Benötigt drei Bytes mehr als die permanente .



3

Wolfram Language (Mathematica) , 53 52 Bytes

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

Probieren Sie es online!

Leider wird für die Berechnung der Determinante einer n × n- Matrix auf diese Weise der O ( n n ) -Speicher verwendet, wodurch große Testfälle außer Reichweite geraten.

Wie es funktioniert

Der erste Teil 1##&@@@(t=Tuples)@#berechnet alle möglichen Produkte eines Terms aus jeder Zeile der gegebenen Matrix. t[Range@Tr[1^#]&/@#]gibt eine Liste mit der gleichen Länge an, deren Elemente Dinge wie {3,2,1}oder {2,2,3}sagen, welchen Eintrag jeder Zeile wir für das entsprechende Produkt ausgewählt haben.

Wir wenden Signaturedie zweite Liste an, die gerade Permutationen 1, ungerade Permutationen -1und Nicht-Permutationen zuordnet 0. Dies ist genau der Koeffizient, mit dem das entsprechende Produkt in der Determinante erscheint.

Schließlich nehmen wir das Skalarprodukt der beiden Listen.


Wenn gerade Signaturezu viel von einem eingebauten ist, können wir bei 73 Bytes nehmen

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

Ersetzen durch 1##&@@Order@@@#~Subsets~{2}&. Dies berechnet Signatureeine mögliche Permutation, indem das Produkt von Orderauf alle Paare von Elementen der Permutation angewendet wird. Ordergibt an, 1ob das Paar in aufsteigender Reihenfolge ist, -1ob es in absteigender Reihenfolge ist und 0ob sie gleich sind.


-1 Byte danke an @ user202729


1
52 Bytes (falls Sie diesen Mathematica-
Golftipp

Ich habe es getan, aber irgendwie habe ich es hier vergessen. Vielen Dank!
Mischa Lawrow

3

Python 3 , 238 Bytes , 227 Bytes , 224 Bytes , 216 Bytes

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))))

Probieren Sie es online!

Meine Lösung verwendet die Definition einer Determinante für Berechnungen. Leider ist die Komplexität dieses Algorithmus n!und ich kann den Durchgang des letzten Tests nicht zeigen, aber theoretisch ist dies möglich.


3

CJam ( 50 45 Bytes)

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

Dies ist ein anonymer Block (Funktion), der ein 2D-Array auf dem Stapel aufnimmt und eine Ganzzahl auf dem Stapel hinterlässt.

Online-Testsuite

Präparation

Dies implementiert den Faddeev-LeVerrier-Algorithmus , und ich denke, es ist die erste Antwort, die diesen Ansatz wählt.

ckn×nEIN

p(λ)det(λichn-EIN)=k=0nckλk
cn=1c0=(-1)ndetEIN

M

M00cn=1(k=0)MkEINMk-1+cn-k+1ichcn-k=-1ktr(EINMk)k=1,,n .

cn-kMk(-1)kcn-k(-1)k+1EINMk

(-1)kcn-k=1ktr((-1)k+1EINMk)(-1)k+2EINMk+1=(-1)kcn-kEIN-EIN((-1)k+1EINMk)

{               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 , verschiedene

Hier sind eine Reihe von Methoden zur Berechnung der Determinante, die ich interessant fand, alle in SageMath programmiert. Sie können alle ausprobiert werden werden .

Eingebaut, 3 Bytes

det

Dieser ist nicht so interessant. Sage bietet Aliasnamen auf globaler Ebene für viele gängige Operationen, die normalerweise Objektmethoden sind. Dies ist also kürzer als lambda m:m.det().


Realteil des Produkts von Eigenwerten, 36 Bytes

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

Leider eigenvaluesist keiner dieser Aliase auf globaler Ebene. Zusammen mit der Tatsache, dass Sage keine gute Möglichkeit hat, Funktionen zu komponieren, bedeutet dies, dass wir mit hohen Kosten konfrontiert sind lambda. Diese Funktion symbolisiert Werte, die beim Drucken automatisch in numerische Werte konvertiert werden, sodass bei einigen Ausgaben möglicherweise eine gewisse Gleitkommaungenauigkeit vorliegt.


Produkt der Diagonale in Jordanischer Normalform, 60 Bytes

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

In der jordanischen Normalform wird eine NxN-Matrix als Blockmatrix mit N Blöcken auf der Diagonale dargestellt. Jeder Block besteht entweder aus einem einzelnen Eigenwert oder einer MxM-Matrix mit einem wiederholten Eigenwert auf der Diagonale und1 s in der (der Diagonale über und rechts von der "Haupt" -Diagonale). Dies führt zu einer Matrix mit allen Eigenwerten (mit Multiplizität) auf der Hauptdiagonale und einigen 1s auf der Superdiagonale, die wiederholten Eigenwerten entsprechen. Dies gibt das Produkt der Diagonale der jordanischen Normalform zurück, die das Produkt der Eigenwerte (mit Multiplikation) ist. Dies ist also ein umständlicherer Weg, die gleiche Berechnung wie bei der vorherigen Lösung durchzuführen.

Da Sage möchte, dass sich die jordanische Normalform über dem gleichen Ring befindet wie die ursprüngliche Matrix, funktioniert dies nur, wenn alle Eigenwerte rational sind. Komplexe Eigenwerte führen zu einem Fehler (es sei denn, die ursprüngliche Matrix befindet sich über dem Ring CDF(komplexe doppelte Gleitkommazahlen) oder SR). Dies bedeutet jedoch, dass im Vergleich zu der oben genannten Lösung keine Realteilnahme erforderlich ist.


Produkt von Diagonal in Smith Decomposition

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

Im Gegensatz zur jordanischen Normalform liegt die Smith-Normalform garantiert über dem gleichen Feld wie die ursprüngliche Matrix. Anstatt die Eigenwerte zu berechnen und sie mit einer Blockdiagonalmatrix darzustellen, berechnet die Smith-Zerlegung die Elementarteiler der Matrix (was für diesen Beitrag ein etwas zu kompliziertes Thema ist), fügt sie in eine Diagonalmatrix ein Dund berechnet zwei Matrizen mit Einheit Determinante Uund Vso, dass D = U*A*V(wo Aist die ursprüngliche Matrix). Da die Determinante des Matrizenprodukts gleich dem Produkt der Determinanten der Matrizen ( det(A*B*...) = det(A)*det(B)*...) ist und Uals VEinheitsdeterminanten definiert sind,det(D) = det(A) . Die Determinante einer Diagonalmatrix ist einfach das Produkt der Elemente auf der Diagonale.

Laplace-Erweiterung, 109 Byte

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]

Dadurch wird die Laplace-Erweiterung in der ersten Zeile mithilfe eines rekursiven Ansatzes ausgeführt. det([[a]]) = awird für den Basisfall verwendet. Es sollte kürzer sein, um es det([[]]) = 1für den Basisfall zu verwenden, aber mein Versuch , diese Implementierung durchzuführen, hatte einen Fehler, den ich noch nicht aufspüren konnte.


Leibnizsche Formel, 100 Bytes

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

Damit wird die Leibniz-Formel direkt umgesetzt. Für eine viel bessere Erklärung der Formel und warum es funktioniert, als ich möglicherweise schreiben könnte, sehen Sie diese ausgezeichnete Antwort .


Realteil von e^(Tr(ln(M)))48 Bytes

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

Diese Funktion gibt symbolische Ausdrücke zurück. Um eine numerische Annäherung zu erhalten, rufen Sie n(result)vor dem Drucken auf.

Dies ist ein Ansatz, den ich noch niemanden verwenden gesehen habe. Ich werde eine längere, detailliertere Erklärung für diese geben.

Sei Aeine quadratische Matrix über den Reals. Per Definition ist die Determinante von Agleich dem Produkt der Eigenwerte von A. Die Spur von Aist gleich der Summe der AEigenwerte von. Für reelle Zahlen r_1und r_2, exp(r_1) * exp(r_2) = exp(r_1 + r_2). Da die Matrixexponentialfunktion analog zur skalaren Exponentialfunktion definiert ist (insbesondere in der vorherigen Identität), kann die Matrixexponentialfunktion berechnet werden, indem die Matrix diagonalisiert und die skalare Exponentialfunktion auf die Eigenwerte auf der Diagonale angewendet wird det(exp(A)) = exp(trace(A))(Das Produkt von ist exp(λ)für jeden Eigenwert λvon Agleich der Summe der Eigenwerte von , die wir berechnen können .exp(A) ). Also, wenn wir eine Lsolche Matrix finden könnenexp(L) = Adet(A) = exp(trace(L))

Wir können eine solche Matrix Ldurch Rechnen finden log(A). Der Matrixlogarithmus kann auf die gleiche Weise berechnet werden wie das Matrixexponential: Bilden Sie eine quadratische Diagonalmatrix, indem Sie die skalare Logarithmusfunktion auf jeden Eigenwert von anwenden A(aus diesem Grund beschränken wir uns Aauf die Realwerte ). Da wir uns nur um die Spur von kümmern L, können wir die Konstruktion überspringen und die Exponentiale der Eigenwerte direkt summieren. Die Eigenwerte können komplex sein, auch wenn die Matrix nicht über dem komplexen Ring liegt. Wir nehmen also den Realteil der Summe.


1
Der letzte Teil ist eine faszinierende Idee, aber der Header und die Erklärung stimmen nicht mit dem Code überein, der keinen Matrixlogarithmus benötigt. Es ist nur real(prod(m.eigenvalues()))ungolfed.
Peter Taylor

2

Java 8, 266 261 259 258 Bytes

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;}

Schau Mama, keine Einbauten ... weil Java keine hat ...>.>

-7 Bytes dank @ceilingcat .

Erläuterung:

Probieren Sie es hier aus. (Nur der letzte Testfall ist zu groß, um in eine longGröße von 2 63 -1 zu passen .)

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

Rekursives Laplace

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)

Weniger golfen

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

Prüfung

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 Bytes mit dem gleichen Verhalten
Arnauld

Oder 85 Bytes zur Unterstützung der leeren Matrix (deren Determinante 1 sein sollte ).
Arnauld

(Ich habe die gleichen Optimierungen in dieser Antwort verwendet , die von Ihrer abgeleitet ist.)
Arnauld




1

Java (OpenJDK 8) , 195 192 177 Bytes

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;}

Probieren Sie es online!

Wie bei vielen anderen Antworten wird auch hier die Laplace-Formel verwendet. Eine etwas weniger golfene Version:

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;
}

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.