Oblicz sumę Kroneckera dwóch macierzy

9

W poniższych przykładach Ai Bnie większy niż 2-by-2 matryc oraz matryc są jednym indeksowane.

Kronecker produkt ma następujące właściwości:

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)

Suma Kronecker ma następujące właściwości:

A⊕B = A⊗Ib + Ia⊗B

Iai Ibmacierzami tożsamości o wymiarach odpowiednio Ai B. Ai Bsą macierzami kwadratowymi. Pamiętaj, że Ai Bmogą mieć różne rozmiary.

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)

Biorąc pod uwagę dwie macierze kwadratowe Ai Bobliczyć sumę Kroneckera dwóch macierzy.

  • Rozmiar matryc będzie co najmniej 2-by-2. Maksymalny rozmiar będzie taki, jaki domyślnie obsługuje Twój komputer / język, ale minimalna ilość 5-by-5danych wejściowych (5 MB na wyjściu).
  • Wszystkie wartości wejściowe będą liczbami całkowitymi nieujemnymi
  • Wbudowane funkcje obliczające sumę Kronecker lub produkty Kronecker są niedozwolone
  • Ogólnie: Standardowe zasady dotyczące formatu I / O, programu i funkcji, luk itp.

Przypadki testowe:

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
źródło

Odpowiedzi:

2

Galaretka , 26 21 20 19 bajtów

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

Dane wejściowe to lista dwóch list 2D, dane wyjściowe to pojedyncza lista 2D. Wypróbuj online! lub zweryfikuj wszystkie przypadki testowe .

Jak to działa

æ*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
źródło
Tyle euro ... Twój program jest bogaty!
Luis Mendo
5

CJam, 40 39 38 bajtów

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

Format wejściowy to lista zawierająca Ai Bjako listy 2D, np

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

Format wyjściowy to pojedyncza lista 2D w stylu CJam.

Zestaw testowy. (Z bardziej czytelnym formatem wyjściowym.)

Wyjaśnienie

Ten kod jest ćwiczeniem złożonym (lub niepoprawnym) operatorów. Są one ogólnie przydatne do manipulacji tablicami, ale wyzwanie to zaostrzyło ich potrzebę. Oto krótki przegląd:

  • foczekuje listy i czegoś innego na stosie i mapuje następujący operator binarny na liście, przekazując drugi element jako drugi argument. Np. [1 2 3] 2 f*I 2 [1 2 3] f*oba dają [2 4 6]. Jeśli oba elementy są listami, pierwszy jest mapowany, a drugi służy do curry operatora binarnego.
  • :ma dwa zastosowania: jeśli podążający za nim operator jest jednoargumentowy, jest to prosta mapa. Np. [1 0 -1 4 -3] :zJest [1 0 1 4 3], gdzie zdostaje moduł liczby. Jeśli podążający za nim operator jest binarny, spowoduje to jego spasowanie . Np . [1 2 3 4] :+Jest 10.
  • .wektoryzuje operator binarny. Oczekuje dwóch list jako argumentów i stosuje operator do odpowiednich par. Np . [1 2 3] [5 7 11] .*Daje [5 14 33].

Zauważ, że :sam jest zawsze operatorem jednoargumentowym, fa .sam jest zawsze operatorem binarnym. Można je dowolnie zagnieżdżać (pod warunkiem, że mają odpowiednie arie). I to właśnie zrobimy ...

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
źródło
fffffffffff co do licha ... Mam nadzieję, że przetrwa gra w golfa, więc w końcu to wyjaśnisz: P
FryAmTheEggman
@FryAmTheEggman :ffff*może być najdłuższy (związek) operator jaki kiedykolwiek używane w CJam ... Na jeden więcej jeden bajt może pójść nawet bardziej szalony jednak: 9Yb2/Q~f.{\{,,_ff=}&}::ffff*:::.+::~:..+p(i tak, doda wyjaśnienie gdy skończę grać w golfa).
Martin Ender
4

J - 38 33 31 bajtów

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

Stosowanie

   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
mile
źródło
Użycie podziału macierzy zakończy się niepowodzeniem, jeśli jedna z macierzy jest pojedyncza. Na przykład (2 2 $ 1 2 3 4) f (2 2 $ 1 1 1 1)podniesie błąd domeny.
Dennis
@ Dennis dobry połów, testowałem tylko z przypadkowymi wartościami ? 4 4 $ 100. Nie jestem pewien, czy istnieje sposób na wykorzystanie komponowania diada x f&g y = (g x) f (g y)lub czegoś innego.
mile
2

Julia, 60 59 58 56 bajtów

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

Wypróbuj online!

Jak to działa

  • Dla macierzy A i B , map(a->a*B,A')oblicza produktów Kronecker A⊗B .

    Wynikiem jest wektor bloków matrycy o wymiarach B .

    Musimy transponować A (z '), ponieważ macierze są przechowywane w porządku głównym kolumny.

  • Ponieważ bitowe NIE z dopełnieniem dwóch spełnia tożsamość ~ n = - (n + 1) dla wszystkich liczb całkowitych n , mamy to - ~ -n = - (~ (-n)) = - ((- n) + 1) = 1 - n , więc - ~ -0 = 1 i - ~ -1 = 0 .

    W ten sposób anonimowa funkcja i->map(a->a*B^i,A'^-~-i)stosuje powyższą mapę do B⁰ (macierz tożsamości z wymiarami B ) i A¹ = A, gdy i = 0 , oraz do i A⁰, gdy i = 1 .

  • sum(i->map(a->a*B^i,A'^-~-i),0:1)sumuje ponad {0,1} z powyższą anonimową funkcją, obliczając sumę Aron Kroneckera jako A¹⊗B⁰ + A⁰⊗B¹ .

    Wynikiem jest wektor bloków matrycy o wymiarach B .

  • sum(A^0)oblicza sumę wszystkich wpisów macierzy tożsamości wymiarów A. Dla n x n macierzy A , Daje n .

  • Na koniec hvcat(sum(A^0),sum(i->map(a->a*B^i,A'^-~-i),0:1)...)konkatenuje bloki macierzy, które tworzą A⊕B .

    Z pierwszego argumentu n , hvcatskleja n bloków matrycy w poziomie, i wynikające z bloków (większych) w pionie.

Dennis
źródło
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)}}}

W programie testowym

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

Wymaga dwóch tablic 2D jako danych wejściowych i zwraca tablicę 2D.

Prawdopodobnie są na to lepsze sposoby: użycie funkcji w celu uniknięcia powtórzeń; używając pojedynczej pętli i wypisując wynik. Zajmę się nimi później.

Level River St
źródło
0

JavaScript (ES6), 109

Oparty na odpowiedzi na inne wyzwanie

(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

Test

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
źródło