矩阵类和测试

马克

作为我学习的一部分,我创建了这个 Matrix 类。为了测试结果,我提供了一个“test.py”文件。

我现在的问题是测试文件总是给我这个错误:

> --------------------------------------------------------------------------- AttributeError                            Traceback (most recent call
> last) <ipython-input-7-daeb08264590> in <module>()
>       6 # and then selecting matrix.py
>       7 
> ----> 8 import test
> 
> /home/workspace/test.py in <module>()
>      76     return True
>      77 
> ---> 78 test()
> 
> /home/workspace/test.py in test()
>      57     assert equal(m2 * m1, m2_x_m1), "Error in your __mul__ function"
>      58     """
> ---> 59     assert equal(m1_x_m2.inverse(), m1_m2_inv), "Error in your inverse function for the 1 x 1 case"
>      60     assert equal(I2.inverse(), I2), "Error in your inverse function for the 2 x 2 case"
>      61     assert equal(top_ones.T(), left_ones), "Error in your T function (transpose)"
> 
> /home/workspace/test.py in equal(m1, m2)
>      68 
>      69 def equal(m1, m2):
> ---> 70     if len(m1.g) != len(m2.g): return False
>      71     if len(m1.g[0]) != len(m2.g[0]): return False
>      72     for r1, r2 in zip(m1.g, m2.g):
> 
> AttributeError: 'list' object has no attribute 'g'

但是,当自己测试案例时,它可以工作并显示相同的结果。

矩阵.py

import math
from math import sqrt
import numbers

def zeroes(height, width):
        """
        Creates a matrix of zeroes.
        """

        g = [[0.0 for _ in range(width)] for __ in range(height)]
        return Matrix(g)

def identity(n):
        """
        Creates a n x n identity matrix.
        """
        I = zeroes(n, n)
        for i in range(n):
            I.g[i][i] = 1.0
        return I

class Matrix(object):


    # Constructor
    def __init__(self, grid):
        self.g = grid
        self.h = len(grid)
        self.w = len(grid[0])

    #
    # Primary matrix math methods
    #############################

    def determinant(self):

        if not self.is_square():
            raise(ValueError, "Cannot calculate determinant of non-square matrix.")
        if self.h > 2:
            raise(NotImplementedError, "Calculating determinant not implemented for matrices largerer than 2x2.")


        if self.h == 1:
            return self.g[0][0]

        elif self.h == 2:
            return (self.g[0][0]*self.g[1][1]-self.g[0][1]*self.g[1][0])

    def trace(self):


        if not self.is_square():
            raise(ValueError, "Cannot calculate the trace of a non-square matrix.")


        sum_trace = 0

        for i in range(self.h):
            for j in range(self.w):
                if i == j:
                    sum_trace = sum_trace + self.g[i][j]

        return sum_trace

    def inverse(self):

        if not self.is_square():
            raise(ValueError, "Non-square Matrix does not have an inverse.")
        if self.h > 2:
            raise(NotImplementedError, "inversion not implemented for matrices larger than 2x2.")

        if self.h == 2:
            if self.g[0][0] * self.g[1][1] == self.g[0][1] * self.g[1][0]:
                return "ad = bc. Therefore Matrix does not have an inverse"
            else:      
                det_A = 1/(self.g[0][0]*self.g[1][1]-self.g[0][1]*self.g[1][0])
                inverse = [[det_A*self.g[1][1],det_A*-self.g[0][1]],[det_A*-self.g[1][0],det_A*self.g[0][0]]]
        elif self.h == 1:
            inverse = [[1/self.g[0][0]]]


    def T(self):

        matrix_transpose = []

        #Iterate through columns (e.g. j=0)
        for j in range(self.w):
            #Reset row for each itteration
            new_row = []
            #Iterate through rows (e.g. j = 0, i loops 0;1)
            for i in range(self.h):
                #i = 0, j = 0; i = 1, j = 0 > new row created out of matrix columns
                new_row.append(self.g[i][j])

            #new_row appended to matrix_transpose
            matrix_transpose.append(new_row)          

        return matrix_transpose

    def is_square(self):
        return self.h == self.w

    #
    # Begin Operator Overloading
    ############################
    def __getitem__(self,idx):

        return self.g[idx]

    def __repr__(self):

        s = ""
        for row in self.g:
            s += " ".join(["{} ".format(x) for x in row])
            s += "\n"
        return s

    def __add__(self,other):

        if self.h != other.h or self.w != other.w:
            raise(ValueError, "Matrices can only be added if the dimensions are the same") 

        matrix_addition = []
        for i in range(self.h):
            new_row = []
            for j in range(self.w):
                addition = self.g[i][j] + other.g[i][j]
                new_row.append(addition)

            matrix_addition.append(new_row)

        return Matrix(matrix_addition)


    def __neg__(self):

        for i in range(self.h):
            for j in range(self.w):
                self.g[i][j] *= -1   
        return Matrix(self.g)

    def __sub__(self, other):

        if self.h != other.h or self.w != other.w:
            raise(ValueError, "Matrices can only be substracted if the dimensions are the same")

        matrix_substraction = []
        for i in range(self.h):
            new_row = []
            for j in range(self.w):
                addition = self.g[i][j] - other.g[i][j]
                new_row.append(addition)

            matrix_substraction.append(new_row)

        return Matrix(matrix_substraction)

    def __mul__(self, other):

        #dot_product func
        def dot_product(vector_one, vector_two):
            dot_product = 0
            for i in range(len(vector_one)):
                dot_product += vector_one[i] * vector_two[i]

            return dot_product


        #get_row func
        def get_row(matrix, row):
            return matrix[row]

        #get_column func
        def get_column(matrix, column_number):
            column = []

            for i in range(len(matrix)): 
                column.append(matrix[i][column_number])

            return column

        result = []
        for i in range(self.h):
            row_result = []
            for j in range(self.w):
                vector_one = get_row(self.g, i)
                vector_two = get_column(other.g, j)
                calulated_dot_product = dot_product(vector_one, vector_two)
                row_result.append(calulated_dot_product)

            result.append(row_result)

        return Matrix(result)


    def __rmul__(self, other):

        if isinstance(other, numbers.Number):
            pass

            for i in range(self.h):
                for j in range(self.w):
                    self.g[i][j] = 2 * self.g[i][j]
            return Matrix(self.g)

测试文件

import matrix as m

def test():
    I2 = m.Matrix([
        [1, 0],
        [0, 1]
        ])
    I2_neg = m.Matrix([
        [-1, 0],
        [0, -1]
        ])

    zero = m.Matrix([
        [0,0],
        [0,0]
        ])

    m1 = m.Matrix([
        [1,2,3],
        [4,5,6]
        ])

    m2 = m.Matrix([
        [7,-2],
        [-3,-5],
        [4,1]
        ])

    m1_x_m2 = m.Matrix([
        [ 13,  -9],
        [ 37, -27]])

    m2_x_m1 = m.Matrix([
        [ -1,   4,   9],
        [-23, -31, -39],
        [  8,  13,  18]])

    m1_m2_inv = m.Matrix([
        [1.5, -0.5],
        [2.0555556, -0.722222222]
        ])

    top_ones = m.Matrix([
        [1,1],
        [0,0],
        ])

    left_ones = m.Matrix([
        [1,0],
        [1,0]
        ])

    assert equal(-I2, I2_neg), "Error in your __neg__ function"
    assert equal(I2 + I2_neg, zero), "Error in your __add__ function"
    assert equal(m1 * m2, m1_x_m2), "Error in your __mul__ function"
    assert equal(m2 * m1, m2_x_m1), "Error in your __mul__ function"
    assert equal(m1_x_m2.inverse(), m1_m2_inv), "Error in your inverse function for the 1 x 1 case"
    assert equal(I2.inverse(), I2), "Error in your inverse function for the 2 x 2 case"
    assert equal(top_ones.T(), left_ones), "Error in your T function (transpose)"
    assert equal(left_ones.T(), top_ones), "Error in your T function (transpose)"
    assert equal(top_ones - left_ones.T(), m.zeroes(2,2)), "Error in your __sub__ function"
    assert (4*m.identity(5))[0][0] == 4, "Error in your __rmul__ function"
    assert (4*m.identity(5)).trace() == 20 , "Error in your trace function"

    print("Congratulations! All tests pass. Your Matrix class is working as expected.")

def equal(m1, m2):
    if len(m1.g) != len(m2.g): return False
    if len(m1.g[0]) != len(m2.g[0]): return False
    for r1, r2 in zip(m1.g, m2.g):
        for v1, v2 in zip(r1, r2):
            if abs(v1 - v2) > 0.0001:
                return False
    return True

test()

Playground.py(测试并导入两个文件)

# Run this cell but don't modify it.

%load_ext autoreload
%autoreload 2
from matrix import Matrix, zeroes, identity

# Try running this code. You should get an assertion error. 
# You will continue to get assertion errors until all the 
# methods in matrix.py are correctly implemented.

# You can open matrix.py by selecting File > Open... 
# and then selecting matrix.py

import test

我试图分解问题,所以我可以减少我必须在这里与你分享的代码。但是无论我尝试更改什么,我都会从 test.py 中返回错误。我希望你们中的任何人都可以研究它,也许知道问题出在哪里。

/马克

施沃巴塞尔

在代码库的快速检查表明,这些方法inverseT该的Matrix类不返回Matrix的情况下,但裸露的网格(2D- lists); 当然,gequal测试中函数试图将它们与Matrix实例进行比较,这些网格没有属性将这两个方法的返回值包装成矩阵:

class Matrix(object):
    def inverse(self):
        # ....
        # not: return inverse
        return Matrix(inverse)

    def T(self):
        # ...
        # not: return matrix_transpose
        return Matrix(matrix_transpose)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章