Awk Матрица умножения - PullRequest
       8

Awk Матрица умножения

0 голосов
/ 30 апреля 2018

Я пытаюсь написать команду AWK, которая позволяет мне выполнять матричное умножение между двумя файлами, разделенными табуляцией.

пример:

кошка м1

1 2 3 4
5 6 7 8

кошка м2

1 2
3 4
5 6
7 8

желаемый вывод:

 50  60
114 140

Ответы [ 2 ]

0 голосов
/ 01 мая 2018

Я бы предложил перейти с GNU Octave:

octave --eval 'load("m1"); load("m2"); m1*m2'

Выход:

ans =                              

    50    60
   114   140

Однако, при условии хорошо отформатированных файлов, вы можете сделать это следующим образом с GNU awk:

матрица-mult.awk

ARGIND == 1 {
  for(i=1; i<=NF; i++)
    m1[FNR][i] = $i
  m1_width  = NF
  m1_height = FNR
}

ARGIND == 2 {
  for(i=1; i<=NF; i++)
    m2[FNR][i] = $i
  m2_width  = NF
  m2_height = FNR
}

END {
  if(m1_width != m2_height) {
    print "Matrices are incompatible, unable to multiply!"
    exit 1
  }
  for(i=1; i<=m1_height; i++) {
    for(j=1; j<=m2_width; j++) {
      for(k=1; k<=m1_width; k++)
        sum += m1[i][k] * m2[k][j]
      printf sum OFS; sum=0
    }
    printf ORS
  }
}

Запустите его так:

awk -f matrix-mult.awk m1 m2

Выход:

50 60 
114 140
0 голосов
/ 30 апреля 2018

без проверки входных файлов для размеров.

будет проще разбить на два сценария: один для транспонирования второй матрицы и один для создания точечного произведения векторов. Также к простому awk коду вы можете прибегнуть к join.

$ awk '{m=NF/2; for(i=1;i<=m;i++) sum[NR] += $i*$(i+m)} 
   END {for(i=1;i<=NR;i++) 
          printf "%s", sum[i] (i==sqrt(NR)?ORS:OFS); 
        print ""}' <(join -j99 m1 <(transpose m2))

где transpose функция определяется как

$ function transpose() { awk '{for(j=1;j<=NF;j++) a[NR,j]=$j}
                          END {for(i=1;i<=NF;i++) 
                                 for(j=1;j<=NR;j++) 
                                   printf "%s",a[j,i] (j==NR?ORS:OFS)}' "$1"; }
...