Module gopy.matrix.matrix_class

Expand source code
# An OOP aproach to representing and manipulating matrices


class Matrix:
    """
    Matrix object generated from a 2D array where each element is an array representing a row.
    Rows can contain type int or float.
    Common operations and information available.
    >>> rows = [
    ...     [1, 2, 3],
    ...     [4, 5, 6],
    ...     [7, 8, 9]
    ... ]
    >>> matrix = Matrix(rows)
    >>> print(matrix)
    [[1. 2. 3.]
     [4. 5. 6.]
     [7. 8. 9.]]
    
    Matrix rows and columns are available as 2D arrays
    >>> print(matrix.rows)
    [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    >>> print(matrix.columns())
    [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
    
    Order is returned as a tuple
    >>> matrix.order
    (3, 3)

    Squareness and invertability are represented as bool
    >>> matrix.is_square
    True
    >>> matrix.is_invertable()
    False

    Identity, Minors, Cofactors and Adjugate are returned as Matrices.  Inverse can be a Matrix or Nonetype
    >>> print(matrix.identity())
    [[1. 0. 0.]
     [0. 1. 0.]
     [0. 0. 1.]]
    >>> print(matrix.minors())
    [[-3. -6. -3.]
     [-6. -12. -6.]
     [-3. -6. -3.]]
    >>> print(matrix.cofactors())
    [[-3. 6. -3.]
     [6. -12. 6.]
     [-3. 6. -3.]]
    >>> print(matrix.adjugate()) # won't be apparent due to the nature of the cofactor matrix
    [[-3. 6. -3.]
     [6. -12. 6.]
     [-3. 6. -3.]]
    >>> print(matrix.inverse())
    None

    Determinant is an int, float, or Nonetype
    >>> matrix.determinant()
    0

    Negation, scalar multiplication, addition, subtraction, multiplication and exponentiation are available and all return a Matrix
    >>> print(-matrix)
    [[-1. -2. -3.]
     [-4. -5. -6.]
     [-7. -8. -9.]]
    >>> matrix2 = matrix * 3
    >>> print(matrix2)
    [[3. 6. 9.]
     [12. 15. 18.]
     [21. 24. 27.]]
    >>> print(matrix + matrix2)
    [[4. 8. 12.]
     [16. 20. 24.]
     [28. 32. 36.]]
    >>> print(matrix - matrix2)
    [[-2. -4. -6.]
     [-8. -10. -12.]
     [-14. -16. -18.]]
    >>> print(matrix ** 3)
    [[468. 576. 684.]
     [1062. 1305. 1548.]
     [1656. 2034. 2412.]]

    Matrices can also be modified
    >>> matrix.add_row([10, 11, 12])
    >>> print(matrix)
    [[1. 2. 3.]
     [4. 5. 6.]
     [7. 8. 9.]
     [10. 11. 12.]]
    >>> matrix2.add_column([8, 16, 32])
    >>> print(matrix2)
    [[3. 6. 9. 8.]
     [12. 15. 18. 16.]
     [21. 24. 27. 32.]]
    >>> print(matrix *  matrix2)
    [[90. 108. 126. 136.]
     [198. 243. 288. 304.]
     [306. 378. 450. 472.]
     [414. 513. 612. 640.]]

    """

    def __init__(self, rows):
        error = TypeError(
            "Matrices must be formed from a list of zero or more lists containing at least "
            "one and the same number of values, each of which must be of type int or float."
        )
        if len(rows) != 0:
            cols = len(rows[0])
            if cols == 0:
                raise error
            for row in rows:
                if len(row) != cols:
                    raise error
                for value in row:
                    if not isinstance(value, (int, float)):
                        raise error
            self.rows = rows
        else:
            self.rows = []

    # MATRIX INFORMATION
    def columns(self):
        return [[row[i] for row in self.rows] for i in range(len(self.rows[0]))]

    @property
    def num_rows(self):
        return len(self.rows)

    @property
    def num_columns(self):
        return len(self.rows[0])

    @property
    def order(self):
        return (self.num_rows, self.num_columns)

    @property
    def is_square(self):
        return self.order[0] == self.order[1]

    def identity(self):
        values = [
            [0 if column_num != row_num else 1 for column_num in range(self.num_rows)]
            for row_num in range(self.num_rows)
        ]
        return Matrix(values)

    def determinant(self):
        if not self.is_square:
            return None
        if self.order == (0, 0):
            return 1
        if self.order == (1, 1):
            return self.rows[0][0]
        if self.order == (2, 2):
            return (self.rows[0][0] * self.rows[1][1]) - (
                self.rows[0][1] * self.rows[1][0]
            )
        else:
            return sum(
                [
                    self.rows[0][column] * self.cofactors().rows[0][column]
                    for column in range(self.num_columns)
                ]
            )

    def is_invertable(self):
        return bool(self.determinant())

    def get_minor(self, row, column):
        values = [
            [
                self.rows[other_row][other_column]
                for other_column in range(self.num_columns)
                if other_column != column
            ]
            for other_row in range(self.num_rows)
            if other_row != row
        ]
        return Matrix(values).determinant()

    def get_cofactor(self, row, column):
        if (row + column) % 2 == 0:
            return self.get_minor(row, column)
        return -1 * self.get_minor(row, column)

    def minors(self):
        return Matrix(
            [
                [self.get_minor(row, column) for column in range(self.num_columns)]
                for row in range(self.num_rows)
            ]
        )

    def cofactors(self):
        return Matrix(
            [
                [
                    self.minors().rows[row][column]
                    if (row + column) % 2 == 0
                    else self.minors().rows[row][column] * -1
                    for column in range(self.minors().num_columns)
                ]
                for row in range(self.minors().num_rows)
            ]
        )

    def adjugate(self):
        values = [
            [self.cofactors().rows[column][row] for column in range(self.num_columns)]
            for row in range(self.num_rows)
        ]
        return Matrix(values)

    def inverse(self):
        determinant = self.determinant()
        return None if not determinant else self.adjugate() * (1 / determinant)

    def __repr__(self):
        return str(self.rows)

    def __str__(self):
        if self.num_rows == 0:
            return "[]"
        if self.num_rows == 1:
            return "[[" + ". ".join(self.rows[0]) + "]]"
        return (
            "["
            + "\n ".join(
                [
                    "[" + ". ".join([str(value) for value in row]) + ".]"
                    for row in self.rows
                ]
            )
            + "]"
        )

    # MATRIX MANIPULATION
    def add_row(self, row, position=None):
        type_error = TypeError("Row must be a list containing all ints and/or floats")
        if not isinstance(row, list):
            raise type_error
        for value in row:
            if not isinstance(value, (int, float)):
                raise type_error
        if len(row) != self.num_columns:
            raise ValueError(
                "Row must be equal in length to the other rows in the matrix"
            )
        if position is None:
            self.rows.append(row)
        else:
            self.rows = self.rows[0:position] + [row] + self.rows[position:]

    def add_column(self, column, position=None):
        type_error = TypeError(
            "Column must be a list containing all ints and/or floats"
        )
        if not isinstance(column, list):
            raise type_error
        for value in column:
            if not isinstance(value, (int, float)):
                raise type_error
        if len(column) != self.num_rows:
            raise ValueError(
                "Column must be equal in length to the other columns in the matrix"
            )
        if position is None:
            self.rows = [self.rows[i] + [column[i]] for i in range(self.num_rows)]
        else:
            self.rows = [
                self.rows[i][0:position] + [column[i]] + self.rows[i][position:]
                for i in range(self.num_rows)
            ]

    # MATRIX OPERATIONS
    def __eq__(self, other):
        if not isinstance(other, Matrix):
            raise TypeError("A Matrix can only be compared with another Matrix")
        return self.rows == other.rows

    def __ne__(self, other):
        return not self == other

    def __neg__(self):
        return self * -1

    def __add__(self, other):
        if self.order != other.order:
            raise ValueError("Addition requires matrices of the same order")
        return Matrix(
            [
                [self.rows[i][j] + other.rows[i][j] for j in range(self.num_columns)]
                for i in range(self.num_rows)
            ]
        )

    def __sub__(self, other):
        if self.order != other.order:
            raise ValueError("Subtraction requires matrices of the same order")
        return Matrix(
            [
                [self.rows[i][j] - other.rows[i][j] for j in range(self.num_columns)]
                for i in range(self.num_rows)
            ]
        )

    def __mul__(self, other):
        if isinstance(other, (int, float)):
            return Matrix([[element * other for element in row] for row in self.rows])
        elif isinstance(other, Matrix):
            if self.num_columns != other.num_rows:
                raise ValueError(
                    "The number of columns in the first matrix must "
                    "be equal to the number of rows in the second"
                )
            return Matrix(
                [
                    [Matrix.dot_product(row, column) for column in other.columns()]
                    for row in self.rows
                ]
            )
        else:
            raise TypeError(
                "A Matrix can only be multiplied by an int, float, or another matrix"
            )

    def __pow__(self, other):
        if not isinstance(other, int):
            raise TypeError("A Matrix can only be raised to the power of an int")
        if not self.is_square:
            raise ValueError("Only square matrices can be raised to a power")
        if other == 0:
            return self.identity()
        if other < 0:
            if self.is_invertable:
                return self.inverse() ** (-other)
            raise ValueError(
                "Only invertable matrices can be raised to a negative power"
            )
        result = self
        for i in range(other - 1):
            result *= self
        return result

    @classmethod
    def dot_product(cls, row, column):
        return sum([row[i] * column[i] for i in range(len(row))])


if __name__ == "__main__":
    import doctest

    doctest.testmod()

Classes

class Matrix (rows)

Matrix object generated from a 2D array where each element is an array representing a row. Rows can contain type int or float. Common operations and information available.

>>> rows = [
...     [1, 2, 3],
...     [4, 5, 6],
...     [7, 8, 9]
... ]
>>> matrix = Matrix(rows)
>>> print(matrix)
[[1. 2. 3.]

[4. 5. 6.] [7. 8. 9.]]

Matrix rows and columns are available as 2D arrays

>>> print(matrix.rows)
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> print(matrix.columns())
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Order is returned as a tuple

>>> matrix.order
(3, 3)

Squareness and invertability are represented as bool

>>> matrix.is_square
True
>>> matrix.is_invertable()
False

Identity, Minors, Cofactors and Adjugate are returned as Matrices. Inverse can be a Matrix or Nonetype

>>> print(matrix.identity())
[[1. 0. 0.]

[0. 1. 0.] [0. 0. 1.]]

>>> print(matrix.minors())
[[-3. -6. -3.]

[-6. -12. -6.] [-3. -6. -3.]]

>>> print(matrix.cofactors())
[[-3. 6. -3.]

[6. -12. 6.] [-3. 6. -3.]]

>>> print(matrix.adjugate()) # won't be apparent due to the nature of the cofactor matrix
[[-3. 6. -3.]

[6. -12. 6.] [-3. 6. -3.]]

>>> print(matrix.inverse())
None

Determinant is an int, float, or Nonetype

>>> matrix.determinant()
0

Negation, scalar multiplication, addition, subtraction, multiplication and exponentiation are available and all return a Matrix

>>> print(-matrix)
[[-1. -2. -3.]

[-4. -5. -6.] [-7. -8. -9.]]

>>> matrix2 = matrix * 3
>>> print(matrix2)
[[3. 6. 9.]

[12. 15. 18.] [21. 24. 27.]]

>>> print(matrix + matrix2)
[[4. 8. 12.]

[16. 20. 24.] [28. 32. 36.]]

>>> print(matrix - matrix2)
[[-2. -4. -6.]

[-8. -10. -12.] [-14. -16. -18.]]

>>> print(matrix ** 3)
[[468. 576. 684.]

[1062. 1305. 1548.] [1656. 2034. 2412.]]

Matrices can also be modified

>>> matrix.add_row([10, 11, 12])
>>> print(matrix)
[[1. 2. 3.]

[4. 5. 6.] [7. 8. 9.] [10. 11. 12.]]

>>> matrix2.add_column([8, 16, 32])
>>> print(matrix2)
[[3. 6. 9. 8.]

[12. 15. 18. 16.] [21. 24. 27. 32.]]

>>> print(matrix *  matrix2)
[[90. 108. 126. 136.]

[198. 243. 288. 304.] [306. 378. 450. 472.] [414. 513. 612. 640.]]

Expand source code
class Matrix:
    """
    Matrix object generated from a 2D array where each element is an array representing a row.
    Rows can contain type int or float.
    Common operations and information available.
    >>> rows = [
    ...     [1, 2, 3],
    ...     [4, 5, 6],
    ...     [7, 8, 9]
    ... ]
    >>> matrix = Matrix(rows)
    >>> print(matrix)
    [[1. 2. 3.]
     [4. 5. 6.]
     [7. 8. 9.]]
    
    Matrix rows and columns are available as 2D arrays
    >>> print(matrix.rows)
    [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    >>> print(matrix.columns())
    [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
    
    Order is returned as a tuple
    >>> matrix.order
    (3, 3)

    Squareness and invertability are represented as bool
    >>> matrix.is_square
    True
    >>> matrix.is_invertable()
    False

    Identity, Minors, Cofactors and Adjugate are returned as Matrices.  Inverse can be a Matrix or Nonetype
    >>> print(matrix.identity())
    [[1. 0. 0.]
     [0. 1. 0.]
     [0. 0. 1.]]
    >>> print(matrix.minors())
    [[-3. -6. -3.]
     [-6. -12. -6.]
     [-3. -6. -3.]]
    >>> print(matrix.cofactors())
    [[-3. 6. -3.]
     [6. -12. 6.]
     [-3. 6. -3.]]
    >>> print(matrix.adjugate()) # won't be apparent due to the nature of the cofactor matrix
    [[-3. 6. -3.]
     [6. -12. 6.]
     [-3. 6. -3.]]
    >>> print(matrix.inverse())
    None

    Determinant is an int, float, or Nonetype
    >>> matrix.determinant()
    0

    Negation, scalar multiplication, addition, subtraction, multiplication and exponentiation are available and all return a Matrix
    >>> print(-matrix)
    [[-1. -2. -3.]
     [-4. -5. -6.]
     [-7. -8. -9.]]
    >>> matrix2 = matrix * 3
    >>> print(matrix2)
    [[3. 6. 9.]
     [12. 15. 18.]
     [21. 24. 27.]]
    >>> print(matrix + matrix2)
    [[4. 8. 12.]
     [16. 20. 24.]
     [28. 32. 36.]]
    >>> print(matrix - matrix2)
    [[-2. -4. -6.]
     [-8. -10. -12.]
     [-14. -16. -18.]]
    >>> print(matrix ** 3)
    [[468. 576. 684.]
     [1062. 1305. 1548.]
     [1656. 2034. 2412.]]

    Matrices can also be modified
    >>> matrix.add_row([10, 11, 12])
    >>> print(matrix)
    [[1. 2. 3.]
     [4. 5. 6.]
     [7. 8. 9.]
     [10. 11. 12.]]
    >>> matrix2.add_column([8, 16, 32])
    >>> print(matrix2)
    [[3. 6. 9. 8.]
     [12. 15. 18. 16.]
     [21. 24. 27. 32.]]
    >>> print(matrix *  matrix2)
    [[90. 108. 126. 136.]
     [198. 243. 288. 304.]
     [306. 378. 450. 472.]
     [414. 513. 612. 640.]]

    """

    def __init__(self, rows):
        error = TypeError(
            "Matrices must be formed from a list of zero or more lists containing at least "
            "one and the same number of values, each of which must be of type int or float."
        )
        if len(rows) != 0:
            cols = len(rows[0])
            if cols == 0:
                raise error
            for row in rows:
                if len(row) != cols:
                    raise error
                for value in row:
                    if not isinstance(value, (int, float)):
                        raise error
            self.rows = rows
        else:
            self.rows = []

    # MATRIX INFORMATION
    def columns(self):
        return [[row[i] for row in self.rows] for i in range(len(self.rows[0]))]

    @property
    def num_rows(self):
        return len(self.rows)

    @property
    def num_columns(self):
        return len(self.rows[0])

    @property
    def order(self):
        return (self.num_rows, self.num_columns)

    @property
    def is_square(self):
        return self.order[0] == self.order[1]

    def identity(self):
        values = [
            [0 if column_num != row_num else 1 for column_num in range(self.num_rows)]
            for row_num in range(self.num_rows)
        ]
        return Matrix(values)

    def determinant(self):
        if not self.is_square:
            return None
        if self.order == (0, 0):
            return 1
        if self.order == (1, 1):
            return self.rows[0][0]
        if self.order == (2, 2):
            return (self.rows[0][0] * self.rows[1][1]) - (
                self.rows[0][1] * self.rows[1][0]
            )
        else:
            return sum(
                [
                    self.rows[0][column] * self.cofactors().rows[0][column]
                    for column in range(self.num_columns)
                ]
            )

    def is_invertable(self):
        return bool(self.determinant())

    def get_minor(self, row, column):
        values = [
            [
                self.rows[other_row][other_column]
                for other_column in range(self.num_columns)
                if other_column != column
            ]
            for other_row in range(self.num_rows)
            if other_row != row
        ]
        return Matrix(values).determinant()

    def get_cofactor(self, row, column):
        if (row + column) % 2 == 0:
            return self.get_minor(row, column)
        return -1 * self.get_minor(row, column)

    def minors(self):
        return Matrix(
            [
                [self.get_minor(row, column) for column in range(self.num_columns)]
                for row in range(self.num_rows)
            ]
        )

    def cofactors(self):
        return Matrix(
            [
                [
                    self.minors().rows[row][column]
                    if (row + column) % 2 == 0
                    else self.minors().rows[row][column] * -1
                    for column in range(self.minors().num_columns)
                ]
                for row in range(self.minors().num_rows)
            ]
        )

    def adjugate(self):
        values = [
            [self.cofactors().rows[column][row] for column in range(self.num_columns)]
            for row in range(self.num_rows)
        ]
        return Matrix(values)

    def inverse(self):
        determinant = self.determinant()
        return None if not determinant else self.adjugate() * (1 / determinant)

    def __repr__(self):
        return str(self.rows)

    def __str__(self):
        if self.num_rows == 0:
            return "[]"
        if self.num_rows == 1:
            return "[[" + ". ".join(self.rows[0]) + "]]"
        return (
            "["
            + "\n ".join(
                [
                    "[" + ". ".join([str(value) for value in row]) + ".]"
                    for row in self.rows
                ]
            )
            + "]"
        )

    # MATRIX MANIPULATION
    def add_row(self, row, position=None):
        type_error = TypeError("Row must be a list containing all ints and/or floats")
        if not isinstance(row, list):
            raise type_error
        for value in row:
            if not isinstance(value, (int, float)):
                raise type_error
        if len(row) != self.num_columns:
            raise ValueError(
                "Row must be equal in length to the other rows in the matrix"
            )
        if position is None:
            self.rows.append(row)
        else:
            self.rows = self.rows[0:position] + [row] + self.rows[position:]

    def add_column(self, column, position=None):
        type_error = TypeError(
            "Column must be a list containing all ints and/or floats"
        )
        if not isinstance(column, list):
            raise type_error
        for value in column:
            if not isinstance(value, (int, float)):
                raise type_error
        if len(column) != self.num_rows:
            raise ValueError(
                "Column must be equal in length to the other columns in the matrix"
            )
        if position is None:
            self.rows = [self.rows[i] + [column[i]] for i in range(self.num_rows)]
        else:
            self.rows = [
                self.rows[i][0:position] + [column[i]] + self.rows[i][position:]
                for i in range(self.num_rows)
            ]

    # MATRIX OPERATIONS
    def __eq__(self, other):
        if not isinstance(other, Matrix):
            raise TypeError("A Matrix can only be compared with another Matrix")
        return self.rows == other.rows

    def __ne__(self, other):
        return not self == other

    def __neg__(self):
        return self * -1

    def __add__(self, other):
        if self.order != other.order:
            raise ValueError("Addition requires matrices of the same order")
        return Matrix(
            [
                [self.rows[i][j] + other.rows[i][j] for j in range(self.num_columns)]
                for i in range(self.num_rows)
            ]
        )

    def __sub__(self, other):
        if self.order != other.order:
            raise ValueError("Subtraction requires matrices of the same order")
        return Matrix(
            [
                [self.rows[i][j] - other.rows[i][j] for j in range(self.num_columns)]
                for i in range(self.num_rows)
            ]
        )

    def __mul__(self, other):
        if isinstance(other, (int, float)):
            return Matrix([[element * other for element in row] for row in self.rows])
        elif isinstance(other, Matrix):
            if self.num_columns != other.num_rows:
                raise ValueError(
                    "The number of columns in the first matrix must "
                    "be equal to the number of rows in the second"
                )
            return Matrix(
                [
                    [Matrix.dot_product(row, column) for column in other.columns()]
                    for row in self.rows
                ]
            )
        else:
            raise TypeError(
                "A Matrix can only be multiplied by an int, float, or another matrix"
            )

    def __pow__(self, other):
        if not isinstance(other, int):
            raise TypeError("A Matrix can only be raised to the power of an int")
        if not self.is_square:
            raise ValueError("Only square matrices can be raised to a power")
        if other == 0:
            return self.identity()
        if other < 0:
            if self.is_invertable:
                return self.inverse() ** (-other)
            raise ValueError(
                "Only invertable matrices can be raised to a negative power"
            )
        result = self
        for i in range(other - 1):
            result *= self
        return result

    @classmethod
    def dot_product(cls, row, column):
        return sum([row[i] * column[i] for i in range(len(row))])

Static methods

def dot_product(row, column)
Expand source code
@classmethod
def dot_product(cls, row, column):
    return sum([row[i] * column[i] for i in range(len(row))])

Instance variables

var is_square
Expand source code
@property
def is_square(self):
    return self.order[0] == self.order[1]
var num_columns
Expand source code
@property
def num_columns(self):
    return len(self.rows[0])
var num_rows
Expand source code
@property
def num_rows(self):
    return len(self.rows)
var order
Expand source code
@property
def order(self):
    return (self.num_rows, self.num_columns)

Methods

def add_column(self, column, position=None)
Expand source code
def add_column(self, column, position=None):
    type_error = TypeError(
        "Column must be a list containing all ints and/or floats"
    )
    if not isinstance(column, list):
        raise type_error
    for value in column:
        if not isinstance(value, (int, float)):
            raise type_error
    if len(column) != self.num_rows:
        raise ValueError(
            "Column must be equal in length to the other columns in the matrix"
        )
    if position is None:
        self.rows = [self.rows[i] + [column[i]] for i in range(self.num_rows)]
    else:
        self.rows = [
            self.rows[i][0:position] + [column[i]] + self.rows[i][position:]
            for i in range(self.num_rows)
        ]
def add_row(self, row, position=None)
Expand source code
def add_row(self, row, position=None):
    type_error = TypeError("Row must be a list containing all ints and/or floats")
    if not isinstance(row, list):
        raise type_error
    for value in row:
        if not isinstance(value, (int, float)):
            raise type_error
    if len(row) != self.num_columns:
        raise ValueError(
            "Row must be equal in length to the other rows in the matrix"
        )
    if position is None:
        self.rows.append(row)
    else:
        self.rows = self.rows[0:position] + [row] + self.rows[position:]
def adjugate(self)
Expand source code
def adjugate(self):
    values = [
        [self.cofactors().rows[column][row] for column in range(self.num_columns)]
        for row in range(self.num_rows)
    ]
    return Matrix(values)
def cofactors(self)
Expand source code
def cofactors(self):
    return Matrix(
        [
            [
                self.minors().rows[row][column]
                if (row + column) % 2 == 0
                else self.minors().rows[row][column] * -1
                for column in range(self.minors().num_columns)
            ]
            for row in range(self.minors().num_rows)
        ]
    )
def columns(self)
Expand source code
def columns(self):
    return [[row[i] for row in self.rows] for i in range(len(self.rows[0]))]
def determinant(self)
Expand source code
def determinant(self):
    if not self.is_square:
        return None
    if self.order == (0, 0):
        return 1
    if self.order == (1, 1):
        return self.rows[0][0]
    if self.order == (2, 2):
        return (self.rows[0][0] * self.rows[1][1]) - (
            self.rows[0][1] * self.rows[1][0]
        )
    else:
        return sum(
            [
                self.rows[0][column] * self.cofactors().rows[0][column]
                for column in range(self.num_columns)
            ]
        )
def get_cofactor(self, row, column)
Expand source code
def get_cofactor(self, row, column):
    if (row + column) % 2 == 0:
        return self.get_minor(row, column)
    return -1 * self.get_minor(row, column)
def get_minor(self, row, column)
Expand source code
def get_minor(self, row, column):
    values = [
        [
            self.rows[other_row][other_column]
            for other_column in range(self.num_columns)
            if other_column != column
        ]
        for other_row in range(self.num_rows)
        if other_row != row
    ]
    return Matrix(values).determinant()
def identity(self)
Expand source code
def identity(self):
    values = [
        [0 if column_num != row_num else 1 for column_num in range(self.num_rows)]
        for row_num in range(self.num_rows)
    ]
    return Matrix(values)
def inverse(self)
Expand source code
def inverse(self):
    determinant = self.determinant()
    return None if not determinant else self.adjugate() * (1 / determinant)
def is_invertable(self)
Expand source code
def is_invertable(self):
    return bool(self.determinant())
def minors(self)
Expand source code
def minors(self):
    return Matrix(
        [
            [self.get_minor(row, column) for column in range(self.num_columns)]
            for row in range(self.num_rows)
        ]
    )