Berechnen Sie die Kronecker-Summe zweier Matrizen

9

In den nachfolgenden Beispielen sind, Aund Bwird 2-mal-2 - Matrix sein, und die Matrizen sind eint indexiert.

Ein Kronecker- Produkt hat folgende Eigenschaften:

A⊗B =  A(1,1)*B   A(1,2)*B
        A(2,1)*B   A(2,2)*B

     =  A(1,1)*B(1,1)   A(1,1)*B(1,2)   A(1,2)*B(1,1)   A(1,2)*B(1,2)
        A(1,1)*B(2,1)   A(1,1)*B(2,2)   A(1,2)*B(2,1)   A(1,2)*B(2,2)
        A(2,1)*B(1,1)   A(2,1)*B(1,2)   A(2,2)*B(1,1)   A(2,2)*B(1,2)
        A(2,2)*B(2,1)   A(2,2)*B(1,2)   A(2,2)*B(2,1)   A(2,2)*B(2,2)

Eine Kronecker-Summe hat folgende Eigenschaften:

A⊕B = A⊗Ib + Ia⊗B

Iaund Ibsind die Identitäts - Matrizen mit den Abmessungen Aund Bjeweils. Aund Bsind quadratische Matrizen. Beachten Sie, dass Aund Bvon unterschiedlicher Größe sein können.

A⊕B =  A(1,1)+B(1,1)  B(1,2)         A(1,2)         0
        B(2,1)         A(1,1)+B(2,2)  0              A(1,2)
        A(2,1)         0              A(2,2)+B(1,1)  B(1,2)
        0              A(2,1)         B(2,1)         A(2,2)+B(2,2)

Berechnen Sie bei zwei quadratischen Matrizen Aund Bdie Kronecker-Summe der beiden Matrizen.

  • Die Größe der Matrizen wird mindestens sein 2-by-2. Die maximale Größe ist die Größe, die Ihr Computer / Ihre Sprache standardmäßig verarbeiten kann, jedoch die minimale 5-by-5Eingabe (5 MB Ausgabe).
  • Alle Eingabewerte sind nicht negative Ganzzahlen
  • Eingebaute Funktionen, die die Kronecker-Summe oder Kronecker-Produkte berechnen, sind nicht zulässig
  • Im Allgemeinen: Standardregeln für E / A-Format, Programm und Funktionen, Lücken usw.

Testfälle:

A =
     1     2
     3     4
B =
     5    10
     7     9

A⊕B =
     6    10     2     0
     7    10     0     2
     3     0     9    10
     0     3     7    13

----

A =
    28    83    96
     5    70     4
    10    32    44
B =
    39    19    65
    77    49    71
    80    45    76

A⊕B =
    67    19    65    83     0     0    96     0     0
    77    77    71     0    83     0     0    96     0
    80    45   104     0     0    83     0     0    96
     5     0     0   109    19    65     4     0     0
     0     5     0    77   119    71     0     4     0
     0     0     5    80    45   146     0     0     4
    10     0     0    32     0     0    83    19    65
     0    10     0     0    32     0    77    93    71
     0     0    10     0     0    32    80    45   120

----

A =
    76    57    54
    76     8    78
    39     6    94
B =
    59    92
    55    29

A⊕B =
   135    92    57     0    54     0
    55   105     0    57     0    54
    76     0    67    92    78     0
     0    76    55    37     0    78
    39     0     6     0   153    92
     0    39     0     6    55   123
Stewie Griffin
quelle

Antworten:

2

Gelee , 26 21 20 19 Bytes

æ*9Bs2¤×€€/€S;"/€;/

Die Eingabe ist eine Liste von zwei 2D-Listen, die Ausgabe ist eine einzelne 2D-Liste. Probieren Sie es online aus! oder überprüfen Sie alle Testfälle .

Wie es funktioniert

æ*9Bs2¤×€€/€S;"/€;/  Main link.
                     Argument: [A, B] (matrices of dimensions n×n and m×m)

      ¤              Evaluate the four links to the left as a niladic chain.
  9B                 Convert 9 to base 2, yielding [1, 0, 0, 1].
    s2               Split into sublists of length 2, yielding [[1, 0], [0, 1]].
æ*                   Vectorized matrix power.
                     This yields [[A¹, B⁰], [A⁰, B¹]], where B⁰ and A⁰ are the
                     identity matrices of dimensions m×m and n×n.
          /€         Reduce each pair by the following:
        €€             For each entry of the first matrix:
       ×                 Multiply the second matrix by that entry.
            S        Sum the two results, element by element.
                     This yields the Kronecker sum, in form of a n×n matrix of
                     m×m matrices.
               /€    Reduce each row of the outer matrix...
             ;"        by zipwith-concatenation.
                     This concatenates the columns of the matrices in each row,
                     yielding a list of length n of n×nm matrices.
                 ;/  Concatenate the lists, yielding a single nm×nm matrix.
Dennis
quelle
So viele Euro ... Ihr Programm ist reichhaltig!
Luis Mendo
5

CJam, 40 39 38 Bytes

9Yb2/q~f{.{_,,_ff=?}:ffff*::.+:~}:..+p

Das Eingabeformat ist eine Liste mit Aund Bals 2D-Listen, z

[[[1 2] [3 4]] [[5 10] [7 9]]]

Das Ausgabeformat ist eine einzelne 2D-Liste im CJam-Stil.

Testsuite. (Mit besser lesbarem Ausgabeformat.)

Erläuterung

Dieser Code ist eine Übung für zusammengesetzte (oder Infix-) Operatoren. Diese sind im Allgemeinen für die Array-Manipulation nützlich, aber diese Herausforderung hat die Notwendigkeit für sie verschärft. Hier ist eine kurze Übersicht:

  • ferwartet eine Liste und etwas anderes auf dem Stapel und ordnet den folgenden binären Operator der Liste zu, wobei das andere Element als zweites Argument übergeben wird. ZB [1 2 3] 2 f*und 2 [1 2 3] f*beide geben [2 4 6]. Wenn beide Elemente Listen sind, wird das erste zugeordnet und das zweite zum Curryen des Binäroperators verwendet.
  • :hat zwei Verwendungszwecke: Wenn der Operator, der ihm folgt, unär ist, ist dies eine einfache Karte. ZB [1 0 -1 4 -3] :zist [1 0 1 4 3], wo zbekommt der Modul einer Zahl. Wenn die Bediener es folgenden binär sind, wird dies klappt die Bediener statt. ZB [1 2 3 4] :+ist 10.
  • .vektorisiert einen binären Operator. Es erwartet zwei Listen als Argumente und wendet den Operator auf entsprechende Paare an. ZB [1 2 3] [5 7 11] .*gibt [5 14 33].

Beachten Sie, dass :selbst immer ein unärer Operator ist, während fund .selbst immer binäre Operatoren sind. Diese können beliebig verschachtelt werden (vorausgesetzt, sie haben die richtigen Aritäten). Und das werden wir tun ...

9Yb      e# Push the binary representation of 9, i.e. [1 0 0 1].
2/       e# Split into pairs, i.e. [[1 0] [0 1]]. We'll use these to indicate
         e# which of the two inputs we turn into an identity matrix.
q~       e# Read and evaluate input, [A B].
f{       e# This block is mapped over the [[1 0] [0 1]] list, also pushing
         e# [A B] onto the stack for each iteration.
  .{     e#   The stack has either [1 0] [A B] or [0 1] [A B]. We apply this
         e#   block to corresponding pairs, e.g. 1 A and 0 B.
    _,   e#     Duplicate the matrix and get its length/height N.
    ,_   e#     Turn into a range [0 1 ... N-1] and duplicate it.
    ff=  e#     Double f on two lists is an interesting idiom to compute an
         e#     outer product: the first f means that we map over the first list
         e#     with the second list as an additional parameter. That means for
         e#     the remaining operator the two arguments are a single integer
         e#     and a list. The second f then maps over the second list, passing
         e#     in the the number from the outer map as the first parameter.
         e#     That means the operator following ff is applied to every possible
         e#     pair of values in the two lists, neatly laid out in a 2D list.
         e#     The operator we're applying is an equality check, which is 1
         e#     only along the diagonal and 0 everywhere else. That is, we've
         e#     created an NxN identity matrix.
    ?    e#     Depending on whether the integer we've got along with the matrix
         e#     is 0 or 1, either pick the original matrix or the identity.
  }
         e#   At this point, the stack contains either [A Ib] or [Ia B]. 
         e#   Note that A, B, Ia and Ib are all 2D matrices.
         e#   We now want to compute the Kronecker product of this pair.
  :ffff* e#   The ffff* is the important step for the Kronecker product (but
         e#   not the whole story). It's an operator which takes two matrices
         e#   and replaces each cell of the first matrix with the second matrix
         e#   multiplied by that cell (so yeah, we'll end up with a 4D list of
         e#   matrices nested inside a matrix).
         e#   The leading : is a fold operation, but it's a bit of a degenerate
         e#   fold operation that is only used to apply the following binary operator
         e#   to the two elements of a list.
         e#   Now the ffff* works essentially the same as the ff= above, but
         e#   we have to deal with two more dimensions now. The first ff maps
         e#   over the cells of the first matrix, passing in the second matrix
         e#   as an additional argument. The second ff then maps over the second
         e#   matrix, passing in the cell from the outer map. We multiply them
         e#   with *.
         e#   Just to recap, we've essentially got the Kronecker product on the
         e#   stack now, but it's still a 4D list not a 2D list.
         e#   The four dimensions are:
         e#     1. Columns of the outer matrix.
         e#     2. Rows of the outer matrix.
         e#     3. Columns of the submatrices.
         e#     4. Rows of the submatrices.
         e#   We need to unravel that into a plain 2D matrix.
  ::.+   e#   This joins the rows of submatrices across columns of the outer matrix.
         e#   It might be easiest to read this from the right:
         e#     +    Takes two rows and concatenates them.
         e#     .+   Takes two matrices and concatenates corresponding rows.
         e#     :.+  Takes a list of matrices and folds .+ over them, thereby
         e#          concatenating the corresponding rows of all matrices.
         e#     ::.+ Maps this fold operation over the rows of the outer matrix.
         e#   We're almost done now, we just need to flatten the outer-most level
         e#   in order to get rid of the distinction of rows of the outer matrix.
  :~     e#   We do this by mapping ~ over those rows, which simply unwraps them.
}
         e# Phew: we've now got a list containing the two Kronecker products
         e# on the stack. The rest is easy, just perform pairwise addition.
:..+     e# Again, the : is a degenerate fold which is used to apply a binary
         e# operation to the two list elements. The ..+ then simply vectorises
         e# addition twice, such that we add corresponding cells of the 2D matrices.
p        e# All done, just pretty-print the matrix.
Martin Ender
quelle
fffffffffff was um alles in der Welt ... Ich hoffe, dass das Golfen überlebt, so dass Sie es schließlich erklären: P
FryAmTheEggman
@FryAmTheEggman ist :ffff*möglicherweise der längste (zusammengesetzte) Operator, den ich jemals in CJam verwendet habe ... Für ein weiteres Byte könnte man allerdings noch verrückter werden: 9Yb2/Q~f.{\{,,_ff=}&}::ffff*:::.+::~:..+p(und ja, ich werde eine Erklärung hinzufügen, wenn ich mit dem Golfen fertig bin).
Martin Ender
4

J - 38 33 31 Bytes

i=:=@i.@#
[:,./^:2(*/i)+(*/~i)~

Verwendungszweck

   f =: [:,./^:2(*/i)+(*/~i)~
   (2 2 $ 1 2 3 4) f (2 2 $ 5 10 7 9)
6 10 2  0
7 10 0  2
3  0 9 10
0  3 7 13
   (3 3 $ 28 83 96 5 70 4 10 32 44) f (3 3 $ 39 19 65 77 49 71 80 45 76)
67 19  65  83   0   0 96  0   0
77 77  71   0  83   0  0 96   0
80 45 104   0   0  83  0  0  96
 5  0   0 109  19  65  4  0   0
 0  5   0  77 119  71  0  4   0
 0  0   5  80  45 146  0  0   4
10  0   0  32   0   0 83 19  65
 0 10   0   0  32   0 77 93  71
 0  0  10   0   0  32 80 45 120
   (3 3 $ 76 57 54 76 8 78 39 6 94) f (2 2 $ 59 92 55 29)
135  92 57  0  54   0
 55 105  0 57   0  54
 76   0 67 92  78   0
  0  76 55 37   0  78
 39   0  6  0 153  92
  0  39  0  6  55 123
Meilen
quelle
Die Verwendung der Matrixteilung schlägt fehl, wenn eine der Matrizen singulär ist. (2 2 $ 1 2 3 4) f (2 2 $ 1 1 1 1)Wird beispielsweise einen Domänenfehler auslösen.
Dennis
@ Tennis guter Fang, ich habe nur gegen zufällige Werte getestet ? 4 4 $ 100. Ich bin mir nicht sicher, ob es eine Möglichkeit gibt, Dyad Compose x f&g y = (g x) f (g y)oder etwas anderes hier zu verwenden.
Meilen
2

Julia, 60 59 58 56 Bytes

A%B=hvcat(sum(A^0),sum(i->map(a->a*B^i,A'^-~-i),0:1)...)

Probieren Sie es online aus!

Wie es funktioniert

  • Für Matrizen A und B , map(a->a*B,A')berechnet das Kronecker - Produkt A⊗B .

    Das Ergebnis ist ein Vektor von Matrixblöcken mit den Abmessungen B .

    Wir müssen A (mit ') transponieren, da Matrizen in Spalten-Hauptreihenfolge gespeichert sind.

  • Da bitweise NICHT mit Zweierkomplement die Identität ~ n = - (n + 1) für alle ganzen Zahlen n erfüllt , haben wir - ~ -n = - (~ (-n)) = - ((- n) + 1) = 1 - n , also - ~ -0 = 1 und - ~ -1 = 0 .

    Auf diese Weise i->map(a->a*B^i,A'^-~-i)wendet die anonyme Funktion die obige Abbildung auf B⁰ (die Identitätsmatrix mit den Dimensionen von B ) und A¹ = A an, wenn i = 0 ist , und auf und A⁰, wenn i = 1 .

  • sum(i->map(a->a*B^i,A'^-~-i),0:1)summiert mit der obigen anonymen Funktion über {0,1} und berechnet die Kronecker-Summe A⊕B als A¹⊗B⁰ + A⁰⊗B¹ .

    Das Ergebnis ist ein Vektor von Matrixblöcken mit den Abmessungen B .

  • sum(A^0)berechnet die Summe aller Einträge der Identitätsmatrix der Dimensionen von A. Für eine n × n- Matrix A ergibt dies n .

  • Schließlich hvcat(sum(A^0),sum(i->map(a->a*B^i,A'^-~-i),0:1)...)verkettet die Matrixblöcke daß Form A B .

    Mit dem ersten Argument n werden n Matrixblöcke horizontal und die resultierenden (größeren) Blöcke vertikal hvcatverkettet .

Dennis
quelle
0

Ruby, 102

->a,b{r=0..-1+a.size*q=b.size
r.map{|i|r.map{|j|(i/q==j/q ?b[i%q][j%q]:0)+(i%q==j%q ?a[i/q][j/q]:0)}}}

Im Testprogramm

f=->a,b{r=0..-1+a.size*q=b.size
r.map{|i|r.map{|j|(i/q==j/q ?b[i%q][j%q]:0)+(i%q==j%q ?a[i/q][j/q]:0)}}}

aa =[[1,2],[3,4]]
bb =[[5,10],[7,9]]
f[aa,bb].each{|e|p e}
puts

aa =[[28,83,96],[5,70,4],[10,32,44]]
bb =[[39,19,65],[77,49,71],[80,45,76]]
f[aa,bb].each{|e|p e}
puts

aa =[[76,57,54],[76,8,78],[39,6,94]]
bb =[[59,92],[55,29]]
f[aa,bb].each{|e|p e}
puts

Benötigt zwei 2D-Arrays als Eingabe und gibt ein 2D-Array zurück.

Es gibt wahrscheinlich bessere Möglichkeiten, dies zu tun: Verwenden einer Funktion, um Wiederholungen zu vermeiden; Verwenden einer einzelnen Schleife und Drucken der Ausgabe. Werde sie später untersuchen.

Level River St.
quelle
0

JavaScript (ES6), 109

Aufbauend auf der Antwort auf die andere Herausforderung

(a,b)=>a.map((a,k)=>b.map((b,i)=>a.map((y,l)=>b.map((x,j)=>r.push(y*(i==j)+x*(k==l))),t.push(r=[]))),t=[])&&t

Prüfung

f=(a,b)=>a.map((a,k)=>b.map((b,i)=>a.map((y,l)=>b.map((x,j)=>r.push(y*(i==j)+x*(k==l))),t.push(r=[]))),t=[])&&t

console.log=x=>O.textContent+=x+'\n'

function show(label, mat)
{
  console.log(label)
  console.log(mat.join`\n`)
}

;[ 
  {a:[[1,2],[3,4]], b:[[5,10],[7,9]]},
  {a:[[28,83,96],[5,70,4],[10,32,44]], b:[[39,19,65],[77,49,71],[80,45,76]]},
  {a:[[76,57,54],[76,8,78],[39,6,94]], b:[[59,92],[55,29]]}
].forEach(t=>{
  show('A',t.a)  
  show('B',t.b)
  show('A⊕B',f(t.a,t.b))
  show('B⊕A',f(t.b,t.a))  
  console.log('-----------------')
})
<pre id=O></pre>

edc65
quelle