Python 3: умножьте вектор на матрицу без NumPy

Я довольно новыми для Python и пытаюсь создать функцию для умножения вектора на матрицу (любого размера столбца). например:

multiply([1,0,0,1,0,0], [[0,1],[1,1],[1,0],[1,0],[1,1],[0,1]])

[1, 1]

вот мой код:

def multiply(v, G):
    result = []
    total = 0
    for i in range(len(G)):
        r = G[i]
        for j in range(len(v)):
            total += r[j] * v[j]
        result.append(total)
    return result  

проблема в том, что когда я пытаюсь выбрать первую строку каждого столбца в матрице (r[j]), отображается ошибка "индекс списка вне диапазона". Есть ли другой способ завершить умножение без использования NumPy?

5 ответов


Нумпитонный подход: (используя numpy.dot чтобы получить точечное произведение двух матриц)

In [1]: import numpy as np

In [3]: np.dot([1,0,0,1,0,0], [[0,1],[1,1],[1,0],[1,0],[1,1],[0,1]])
Out[3]: array([1, 1])

в подходящие для Python подход:

длина вашего второго for цикл len(v) и вы пытаетесь индексировать v основываясь на этом, вы получили ошибку индекса . Как более pythonic способ вы можете использовать zip функция для получения столбцов списка затем используйте starmap и mul в пределах понимания списка:

In [13]: first,second=[1,0,0,1,0,0], [[0,1],[1,1],[1,0],[1,0],[1,1],[0,1]]

In [14]: from itertools import starmap

In [15]: from operator import mul

In [16]: [sum(starmap(mul, zip(first, col))) for col in zip(*second)]
Out[16]: [1, 1]

Я думаю, что проблема с вашим кодом заключалась в том, что вы перебираете строки матрицы, а не столбцы. Также вы не сбрасываете свою переменную "total" после каждого вычисления столбца матрицы vector*. Это то, что вы хотите:

def multiply(v, G):
    result = []
    for i in range(len(G[0])): #this loops through columns of the matrix
        total = 0
        for j in range(len(v)): #this loops through vector coordinates & rows of matrix
            total += v[j] * G[j][i]
        result.append(total)
    return result

r является элемент G таким образом, это строка, которая имеет только два элемента. Это означает, что вы не можете использовать индекс j чтобы получить значение от r, потому что j идет от 0 до длины v, что составляет 6 в вашем примере.


мне нужно решение, где первая Матрица может быть 2-мерным. Расширение решения от @Kasramvd для принятия двумерного first матрица. Опубликовано здесь для справки:

>>> first,second=[[1,0,0,1,0,0],[0,1,1,1,0,0]], [[0,1],[1,1],[1,0],[1,0],[1,1],[0,1]]
>>> from itertools import starmap
>>> from operator import mul
>>> [[sum(starmap(mul, zip(row, col))) for col in zip(*second)] for row in first]
[[1, 1], [3, 1]]

Я приложил код для умножения матрицы, следуйте примеру формата для одномерного умножения (списки списка)

def MM(a,b):
c = []
for i in range(0,len(a)):
    temp=[]
    for j in range(0,len(b[0])):
        s = 0
        for k in range(0,len(a[0])):
            s += a[i][k]*b[k][j]
        temp.append(s)
    c.append(temp)

return c
a=[[1,2]]
b=[[1],[2]]
print(MM(a,b))

результат [[5]]