Как выполнить умножение матрицы на вектор с помощью оператора * в Python? - PullRequest
0 голосов
/ 09 июня 2019

Я хочу перегрузить оператор умножения в Python. Что я точно хочу сделать, это умножить матрицу 4x4 на 4D вектор.

import math
class Vec4():
    def __init__(self, x = 0, y = 0, z = 0, w = 0):
        """Constructor for Vec4
        DO NOT MODIFY THIS METHOD"""
        self.values = [x,y,z,w]

    def __str__(self):
        """Returns the vector as a string representation
        DO NOT MODIFY THIS METHOD"""
        toReturn = ''
        if self is None: return '0.00 0.00 0.00 0.00'
        for c in range(0,4):
                toReturn += "%.2f" % self.values[c]
                if c != 3:
                    toReturn += ' '
        return toReturn

class Matrix4():
    def __init__(self, row1=None, row2=None, row3=None, row4=None):
        """Constructor for Matrix4
        DO NOT MODIFY THIS METHOD"""
        if row1 is None: row1 = Vec4()
        if row2 is None: row2 = Vec4()
        if row3 is None: row3 = Vec4()
        if row4 is None: row4 = Vec4()
        self.m_values = [row1,row2,row3,row4]

    def __str__(self):
        """Returns a string representation of the matrix
        DO NOT MODIFY THIS METHOD"""
        toReturn = ''
        if self is None: return '0.00 0.00 0.00 0.00\n0.00 0.00 0.00 0.00\n0.00 0.00 0.00 0.00\n0.00 0.00 0.00 0.00'
        for r in range(0,4):
            for c in range(0,4):
                toReturn += "%.2f" % self.m_values[r].values[c]
                if c != 3:
                    toReturn += ' '
            toReturn += '\n'
        return toReturn

    def __mul__(self, v):
        """Element wise multiplication of self by vector v
        Returns the result as a new vector"""
        x = self.m_values[0][0]*self.values[0]+self.m_values[0][1]*self.values[1]+self.m_values[0][2]*self.values[2]+self.m_values[0][3]*self.values[3]
        y = self.m_values[1][0]*self.values[0]+self.m_values[1][1]*self.values[1]+self.m_values[1][2]*self.values[2]+self.m_values[1][3]*self.values[3]
        z = self.m_values[2][0]*self.values[0]+self.m_values[2][1]*self.values[1]+self.m_values[2][2]*self.values[2]+self.m_values[3][3]*self.values[3]
        w = self.m_values[3][0]*self.values[0]+self.m_values[3][1]*self.values[1]+self.m_values[3][2]*self.values[2]+self.m_values[3][3]*self.values[3]
        return Vec4(x,y,z,w)

Как видите, я пытался это реализовать. Это не работает для меня. Результатом должен быть вектор.

A = Matrix4(Vec4(1, 0, 0, 0),
            Vec4(0, 1, 0, 0),
            Vec4(0, 0, 1, 0),
            Vec4(0, 0, 0, 1))
>>> V = Vec4(1,2,3,4)
>>> print(A*V)

Результат должен быть «1,00 2,00 3,00 4,00».

Но это вызывает ошибку:

Traceback (most recent call last):
  File "<pyshell#27>", line 1, in <module>
    print(A*V)
  File "C:\Users\xxx\Downloads\Download-Stuff\Gmail\TransformMatrix.py", line 45, in __mul__
    x = self.m_values[0].values[0]*self.values[0]+self.m_values[0].values[1]*self.values[1]+self.m_values[0].values[2]*self.values[2]+self.m_values[0].values[3]*self.values[3]
AttributeError: 'Matrix4' object has no attribute 'values'

Что мне делать? Что я делаю неправильно? Кто-то сказал мне использовать вложенные циклы, но я не знаком с этим.

Пожалуйста, помогите мне!

Заранее спасибо!

1 Ответ

1 голос
/ 10 июня 2019

У вас есть values в Vec4 и m_values в Matrix4.Когда вы ссылаетесь на self из класса Matrix4, это экземпляр Matrix4, на который вы ссылаетесь.Изнутри методов этого класса вам нужно либо обратиться к self.m_values, чтобы получить массив Vec4, либо self.m_values[i].values для доступа к содержимому Vec4.

. Возможно, вам будет проще, еслиВы переопределяете оператор индекса для обоих.например, для Vec4 включите в класс def:

def __getitem__(self, i):
    return self.values[i]
def __setitem__(self, i, v):
    self.values[i] = v

Когда вы приступите к деталям, как это сделать, я рекомендую проверить что-то вроде: https://mathoverflow.net/questions/34173/fast-matrix-multiplication

Обратите внимание, что numpy обеспечивает эффективное умножение матриц и может избавить вас от некоторых проблем.

...