Calcular o produto Kronecker

11

Relacionado , mas muito diferente.


Nos exemplos abaixo, Ae Bserão matrizes 2 por 2, e as matrizes são indexadas um.

Um produto Kronecker possui as seguintes propriedades:

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)

Desafio: Dadas duas matrizes Ae B, retorne A⊗B.

  • O tamanho das matrizes será pelo menos 1-by-1. O tamanho máximo será o que o seu computador / idioma puder manipular por padrão, mas com 5-by-5entrada mínima .
  • Todos os valores de entrada serão números inteiros não negativos
  • Funções internas que calculam produtos Kronecker ou produtos tensor / externo não são permitidas
  • Em geral: Regras padrão em relação ao formato de E / S, programa e funções, brechas etc.

Casos de teste:

A =   
     1     2
     3     4    
B =    
     5     6
     7     8    
A⊗B =    
     5     6    10    12
     7     8    14    16
    15    18    20    24
    21    24    28    32

B⊗A =    
     5    10     6    12
    15    20    18    24
     7    14     8    16
    21    28    24    32
------------------------
A =    
     1
     2
B =    
     1     2

A⊗B =    
     1     2
     2     4
------------------------
A =    
    16     2     3    13
     5    11    10     8
     9     7     6    12
     4    14    15     1

B =    
     1     1
     0     1

A⊗B  =    
    16    16     2     2     3     3    13    13
     0    16     0     2     0     3     0    13
     5     5    11    11    10    10     8     8
     0     5     0    11     0    10     0     8
     9     9     7     7     6     6    12    12
     0     9     0     7     0     6     0    12
     4     4    14    14    15    15     1     1
     0     4     0    14     0    15     0     1

B⊗A =    
    16     2     3    13    16     2     3    13
     5    11    10     8     5    11    10     8
     9     7     6    12     9     7     6    12
     4    14    15     1     4    14    15     1
     0     0     0     0    16     2     3    13
     0     0     0     0     5    11    10     8
     0     0     0     0     9     7     6    12
     0     0     0     0     4    14    15     1
------------------------

A = 2
B = 5
A⊗B = 10
Stewie Griffin
fonte

Respostas:

1

Geléia, 10 9 bytes

×€€;"/€;/

Usa o algoritmo de Büttner ( üpronunciado ao tentar emitir um eesom [como se encontra] na forma de boca de um oosom [como na bota]).

O ;"/€;/é inspirado por Dennis Mitchell . Era originalmente Z€F€€;/(que custa mais um byte).

Freira Furada
fonte
1
Ou, no IPA, / y /
Luis Mendo
Nem toda pessoa conhece IPA.
Leaky Nun
4
Obrigado pela explicação de como pronunciar o sobrenome de Martin. É super relevante. : P
Alex A.
Bem, é como eu mostrar respeito ...
Leaky Nun
;/pode ser agora. (recurso desafio de
datas anteriores
6

CJam, 13 bytes

{ffff*::.+:~}

Este é um bloco sem nome que espera duas matrizes no topo da pilha e deixa seu produto Kronecker em seu lugar.

Suíte de teste.

Explicação

Esta é apenas a parte do produto Kronecker da resposta anterior , portanto, estou aqui apenas reproduzindo as partes relevantes da explicação anterior:

Aqui está uma rápida visão geral dos operadores de infix do CJam para manipulação de lista:

  • fespera uma lista e mais alguma coisa na pilha e mapeia o seguinte operador binário sobre a lista, passando o outro elemento como o segundo argumento. Por exemplo, [1 2 3] 2 f*e 2 [1 2 3] f*ambos dão [2 4 6]. Se ambos os elementos são listas, o primeiro é mapeado e o segundo é usado para curry o operador binário.
  • :tem dois usos: se o operador a seguir é unário, este é um mapa simples. Por exemplo, [1 0 -1 4 -3] :zé [1 0 1 4 3], onde zfica o módulo de um número. Se o operador a seguir for binário, isso fará com que o operador seja dobrado . Por exemplo, [1 2 3 4] :+é 10.
  • .vetoriza um operador binário. Ele espera duas listas como argumentos e aplica o operador aos pares correspondentes. Por exemplo, [1 2 3] [5 7 11] .*[5 14 33].
ffff*  e# This 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# Now the ffff* is essentially a 4D version of the standard ff* idiom
       e# for outer products. For an explanation of ff*, see the answer to
       e# to the Kronecker sum challenge.
       e# The first ff maps over the cells of the first matrix, passing in the 
       e# second matrix as an additional argument. The second ff then maps over 
       e# the second matrix, passing in the cell from the outer map. We 
       e# multiply them 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.
Martin Ender
fonte
3
Seu código quase se parece com um endereço IPv6
Digital Trauma
4

MATLAB / Oitava, 83 42 bytes

Economizou 41 bytes, graças a FryAmTheEggman!

@(A,B)cell2mat(arrayfun(@(n)n*B,A,'un',0))

Teste aqui!

Demolir

arrayfuné um loop for disfarçado que se multiplica n*B, para uma variável ndefinida pelo segundo argumento. Isso funciona porque o loop através de uma matriz 2D é o mesmo que o loop através de um vetor. Ou seja, for x = Aé o mesmo que for x = A(:).

'un',0é equivalente ao mais detalhado 'UniformOutput', Falsee especifica que a saída contém células em vez de escalares.

cell2mat é usado para converter as células novamente em uma matriz numérica, que é então gerada.

Stewie Griffin
fonte
Você deve esclarecer que os arrayfunlaços linearmente como você diz, como se a matriz fosse um vetor, mas forfaz não (ele faz um loop sobre colunas da matriz)
Luis Mendo
1

Julia, 40 39 37 bytes

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

Experimente online!

Como funciona

  • Para as matrizes A e B , map(a->a*B,A')calcula o produto Kronecker A⊗B .

    O resultado é um vector de blocos da matriz com as dimensões de B .

    Temos que transpor A (com '), pois as matrizes são armazenadas na ordem principal da coluna.

  • sum(A^0)calcula a soma de todas as entradas da matriz de identidade das dimensões de A. Para uma matriz n × n A , isso gera n .

  • Com o primeiro argumento n , hvcatconcatena n blocos de matriz horizontalmente e os blocos (maiores) resultantes verticalmente.

Dennis
fonte
0

J, 10 bytes

Esta é uma implementação possível.

[:,./^:2*/

J, 13 bytes

Essa é uma implementação semelhante, mas usa a capacidade de J para definir classificações. Aplica-se *entre cada elemento no LHS com todo o RHS.

[:,./^:2*"0 _

Uso

   f =: <either definition>
    (2 2 $ 1 2 3 4) f (2 2 $ 5 6 7 8)
 5  6 10 12
 7  8 14 16
15 18 20 24
21 24 28 32
   (2 1 $ 1 2) f (1 2 $ 1 2)
1 2
2 4
   2 f 5
10
milhas
fonte
0

JavaScript (ES6), 79

Implementação direta com loop aninhado

(a,b)=>a.map(a=>b.map(b=>a.map(y=>b.map(x=>r.push(y*x)),t.push(r=[]))),t=[])&&t

Teste

f=(a,b)=>a.map(a=>b.map(b=>a.map(y=>b.map(x=>r.push(y*x)),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,6],[7,8]] },
  {a:[[1],[2]],b:[[1,2]]},
  {a:[[16,2,3,13],[5,11,10,8],[9,7,6,12],[4,14,15,1]],b:[[1,1],[0,1]]},
  {a:[[2]],b:[[5]]}
].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
fonte