💀

[Python]行列の積

2023/12/02に公開

行列の積

文字とかと演算できるやつ欲しくて作ったけどSymPyでいいじゃんってなって結局使わなかったコード

R.I.P.

AB = C
c_{ij} = \sum_{k}a_{ik}b_{kj}

コード

# 添え字付き文字列を格納したXの行列を作成する
def makeCharMat(row, col, char='X'):
  res = []
  for r in range(row):
    res.append([])
    for c in range(col):
      v = f'{char}{r+1}{c+1}'
      res[r].append(v)
    
  return res

# ndarrayではなく通常のリストを受け取る
def matrix_multiply(mat1, mat2):
  result = []
  row1 = len(mat1)
  col1 = len(mat1[0])
  row2 = len(mat2)
  col2 = len(mat2[0])

  if col1 != row2:
    raise ValueError("行列のサイズが不適切です")

  for i in range(row1):
    result.append([])
    for j in range(col2):
      if type(mat1[i][0]) == str and type(mat2[0][j]) != str: # [文字][数字]
        v = ''
        for k in range(col1 - 1):
          if mat2[k][j] == 0:
            continue
          elif mat2[k][j] == 1:
            v += f'{mat1[i][k]}'
            v += '+'
          else:
            v += f'{mat2[k][j]}{mat1[i][k]}'
            v += '+'
        # last
        if mat2[-1][j] == 0:
          v = v.rstrip('+')
        elif mat2[-1][j] == 1:
          v += f'{mat1[i][-1]}'
        else:
          v += f'{mat2[-1][j]}{mat1[i][-1]}'
        # result
        if len(v) == 0:
          result[i].append(0)
        else:
          result[i].append(v)
      elif type(mat1[i][0]) != str and type(mat2[0][j]) == str: # [数字][文字]
        v = ''
        for k in range(col1 - 1):
          if mat1[i][k] == 0:
            continue
          elif mat1[i][k] == 1:
            v += f'{mat2[k][j]}'
            v += '+'
          else:
            v += f'{mat1[i][k]}{mat2[k][j]}'
            v += '+'
        # last 
        if mat1[i][-1] == 0:
          v = v.rstrip('+')
        elif mat1[i][-1] == 1:
          v += f'{mat2[-1][j]}'
        else:
          v += f'{mat1[i][-1]}{mat2[-1][j]}'
        # result 
        if len(v) == 0:
          result[i].append(0)
        else:
          result[i].append(v)
      elif type(mat1[i][0]) == str and type(mat2[0][j]) == str: # [文字][文字]
        v = ''
        for k in range(col1 - 1):
          v += f'{mat1[i][k]}{mat2[k][j]}'
          v += '+'
        # last 
        v += f'{mat1[i][-1]}{mat2[-1][j]}'
        result[i].append(v)
      else: # [数字][数字]
        v = 0
        for k in range(col1):
          v += mat1[i][k] * mat2[k][j]
        result[i].append(v)
  return result

def show_mat(mat):
  for row in mat:
    print("[", end=" ")
    for ele in row:
      print(f'{ele}\t', end=" ")
    print("]")

実行例

X = makeCharMat(2, 2)
Y = makeCharMat(2, 2, char='Y')
N1 = [[1, 2, 3],
      [4, 5, 6]]
N2 = [[1, 2],
      [3, 4],
      [5, 6]]

res1 = matrix_multiply(X, Y) # [文字][文字]
res2 = matrix_multiply(X, N1) # [文字][数字]
res3 = matrix_multiply(N2, X) # [数字][文字]
res4 = matrix_multiply(N1, N2) #[数字][数字]
show_mat(res1)
show_mat(res2)
show_mat(res3)
show_mat(res4)
[ X11Y11+X12Y21	 X11Y12+X12Y22	 ]
[ X21Y11+X22Y21	 X21Y12+X22Y22	 ]
[ X11+4X12	 2X11+5X12	 3X11+6X12	 ]
[ X21+4X22	 2X21+5X22	 3X21+6X22	 ]
[ X11+2X21	 X12+2X22	 ]
[ 3X11+4X21	 3X12+4X22	 ]
[ 5X11+6X21	 5X12+6X22	 ]
[ 22	 28	 ]
[ 49	 64	 ]

Discussion