Calculer la somme de Kronecker de deux matrices

9

Dans les exemples ci-dessous, Aet Bseront des matrices 2 par 2, et les matrices sont à un index.

Un produit Kronecker a les propriétés suivantes:

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)

Une somme Kronecker a les propriétés suivantes:

A⊕B = A⊗Ib + Ia⊗B

Iaet Ibsont les matrices d'identité avec les dimensions de Aet Brespectivement. Aet Bsont des matrices carrées. Notez que Aet Bpeuvent être de tailles différentes.

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)

Étant donné deux matrices carrées, Aet B, calculer la somme de Kronecker des deux matrices.

  • La taille des matrices sera au moins 2-by-2. La taille maximale sera ce que votre ordinateur / langage peut gérer par défaut, mais une 5-by-5entrée minimale (sortie de 5 Mo).
  • Toutes les valeurs d'entrée seront des entiers non négatifs
  • Les fonctions intégrées qui calculent la somme Kronecker ou les produits Kronecker ne sont pas autorisées
  • En général: règles standard concernant le format d'E / S, le programme et les fonctions, les failles, etc.

Cas de test:

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
la source

Réponses:

2

Gelée , 26 21 20 19 octets

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

L'entrée est une liste de deux listes 2D, la sortie est une seule liste 2D. Essayez-le en ligne! ou vérifiez tous les cas de test .

Comment ça fonctionne

æ*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
la source
Tant d'euros ... votre programme est riche!
Luis Mendo
5

CJam, 40 39 38 octets

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

Le format d'entrée est une liste contenant Aet Bsous forme de listes 2D, par exemple

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

Le format de sortie est une seule liste 2D de type CJam.

Suite de tests. (Avec un format de sortie plus lisible.)

Explication

Ce code est un exercice sur les opérateurs composés (ou infixés). Ceux-ci sont généralement utiles pour la manipulation de tableaux, mais ce défi a exacerbé leur besoin. Voici un bref aperçu:

  • fattend une liste et quelque chose d'autre sur la pile et mappe l' opérateur binaire suivant sur la liste, en passant l'autre élément comme deuxième argument. Par exemple, [1 2 3] 2 f*et les 2 [1 2 3] f*deux donnent [2 4 6]. Si les deux éléments sont des listes, le premier est mappé et le second est utilisé pour curry l'opérateur binaire.
  • :a deux utilisations: si l'opérateur qui le suit est unaire, il s'agit d'une simple carte. Par exemple , [1 0 -1 4 -3] :zest [1 0 1 4 3], où zobtient le module d'un nombre. Si l'opérateur qui le suit est binaire, cela repliera l'opérateur à la place. Par exemple , [1 2 3 4] :+est 10.
  • .vectorise un opérateur binaire. Il attend deux listes comme arguments et applique l'opérateur aux paires correspondantes. Par exemple, [1 2 3] [5 7 11] .*donne [5 14 33].

Notez que :lui - même est toujours un opérateur unaire, tandis que fet .eux-mêmes sont toujours des opérateurs binaires. Ceux-ci peuvent être imbriqués arbitrairement (à condition qu'ils aient les bonnes arités). Et c'est ce que nous ferons ...

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
la source
fffffffffff quoi sur terre ... J'espère que cela survit au golf pour que vous l'expliquiez finalement: P
FryAmTheEggman
@FryAmTheEggman :ffff*pourrait être l'opérateur le plus long (composé) que j'ai jamais utilisé dans CJam ... Pour un octet de plus, on pourrait devenir encore plus fou: 9Yb2/Q~f.{\{,,_ff=}&}::ffff*:::.+::~:..+p(et oui, ajoutera une explication lorsque j'aurai fini de jouer au golf).
Martin Ender
4

J - 38 33 31 octets

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

Usage

   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
miles
la source
L'utilisation de la division matricielle échouera si l'une des matrices est singulière. Par exemple, (2 2 $ 1 2 3 4) f (2 2 $ 1 1 1 1)générera une erreur de domaine.
Dennis
@Dennis bonne capture, je testais uniquement contre des valeurs aléatoires ? 4 4 $ 100. Je ne sais pas s'il y a un moyen d'utiliser la composition de dyade x f&g y = (g x) f (g y)ou autre chose ici.
miles
2

Julia, 60 59 58 56 octets

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

Essayez-le en ligne!

Comment ça fonctionne

  • Pour les matrices A et B , map(a->a*B,A')calcule le produit Kronecker A⊗B .

    Le résultat est un vecteur de blocs matriciels avec des dimensions de B .

    Nous devons transposer A (avec ') puisque les matrices sont stockées dans l'ordre des colonnes principales.

  • Puisque NOT au niveau du bit avec complément à deux satisfait l'identité ~ n = - (n + 1) pour tous les entiers n , nous avons que - ~ -n = - (~ (-n)) = - ((- n) + 1) = 1 - n , donc - ~ -0 = 1 et - ~ -1 = 0 .

    De cette façon, la fonction anonyme i->map(a->a*B^i,A'^-~-i)applique la carte ci-dessus à B⁰ (la matrice d'identité avec les dimensions de B ) et A¹ = A lorsque i = 0 , et à et A⁰ lorsque i = 1 .

  • sum(i->map(a->a*B^i,A'^-~-i),0:1)additionne {0,1} avec la fonction anonyme ci-dessus, calculant la somme de Kronecker A⊕B comme A¹⊗B⁰ + A⁰⊗B¹ .

    Le résultat est un vecteur de blocs matriciels avec des dimensions de B .

  • sum(A^0)calcule la somme de toutes les entrées de la matrice d'identité des dimensions de A. Pour une matrice n × n A , cela donne n .

  • Enfin, hvcat(sum(A^0),sum(i->map(a->a*B^i,A'^-~-i),0:1)...)concatène les blocs matriciels qui forment A⊕B .

    Avec le premier argument n , hvcatconcatène n blocs de matrice horizontalement et les blocs résultants (plus grands) verticalement.

Dennis
la source
0

Rubis, 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)}}}

En programme de test

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

Nécessite deux tableaux 2D en entrée et renvoie un tableau 2D.

Il existe probablement de meilleures façons de procéder: utiliser une fonction pour éviter les répétitions; en utilisant une seule boucle et en imprimant la sortie. Je les examinerai plus tard.

Level River St
la source
0

JavaScript (ES6), 109

Construit sur la réponse à l'autre défi

(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

Tester

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
la source