Created
December 22, 2016 06:04
-
-
Save mcgrew/449651904574349a2d8450ed3715cc98 to your computer and use it in GitHub Desktop.
A matrix math implementation in python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
matrix.py | |
(c) 2007,2016 Thomas McGrew | |
""" | |
VERSION = "0.3-pre" | |
MATRIX_VALID_TYPES = (int, float, complex) | |
MATRIX_VALID_TYPENAMES = ('int', 'float', 'complex') | |
MATRIX_VALID_INTS = (int,) | |
MATRIX_VALID_COLLECTIONS = (list, tuple) | |
class Matrix(object): | |
""" | |
A class for matrix operations. All indices start at 0. | |
""" | |
def __init__(self, *rows): | |
""" | |
Accepts either a matrix, a 2-dimensional list of numbers, | |
a list with a matrix width ( int ), or a series of one-dimensional lists of numbers. | |
:Parameters: | |
rows : list | |
Arguments for creating a matrix. | |
""" | |
self._width = 0 | |
self._height = 0 | |
self._value = list() | |
if rows: | |
# if the value passed into the constructor is a matrix | |
if len(rows) == 1 and type(rows[0]) == type(self): | |
for row in rows[0].value: | |
newRow = list() | |
for item in row: # this should make a deep copy. | |
newRow.append(item) | |
self.addRow(*newRow) | |
# if the value passed into the constructor is a two-dimensional list | |
elif len(rows) == 1 and type(rows[0]) in MATRIX_VALID_COLLECTIONS and \ | |
type(rows[0][0]) in MATRIX_VALID_COLLECTIONS: | |
for row in rows[0]: | |
newRow = list() | |
for item in row: # this should make a deep copy. | |
newRow.append(item) | |
self.addRow(*newRow) | |
# if the value passed into the constructor is a list followed by a matrix width | |
elif ((len(rows) == 2) and (type(rows[0]) in MATRIX_VALID_COLLECTIONS) and ( | |
type(rows[1]) in MATRIX_VALID_INTS)): | |
if (len(rows[0]) % rows[1]): | |
raise ValueError( | |
'Invalid list length for matrix construction, must be a multiple of width argument') | |
newRow = list() | |
for i in range(len(rows[0])): | |
if (i and (not i % rows[1])): # i > 0 and a multiple of the given width. | |
self.addRow(*newRow) | |
newRow = list() | |
newRow.append(rows[0][i]) | |
# when we get here, there should still be one row left in the "buffer", so | |
self.addRow(*newRow) | |
# if the value passed into the constructor is several lists | |
else: | |
for row in rows: | |
if not (type(row) in MATRIX_VALID_COLLECTIONS): | |
raise TypeError("Constructor arguments must be of type 'list' or 'tuple'") # fix this! | |
self.addRow(*row) | |
def __abs__(self): | |
""" | |
Absolute value. | |
Call: abs( matrix ) | |
:rtype: matrix | |
:returns: a copy of the matrix with all values changed to their absolute value | |
""" | |
returnvalue = Matrix() | |
for row in self._value: | |
newRow = list() | |
for item in row: # this should make a deep copy. | |
newRow.append(abs(item)) | |
returnvalue.append(newRow) | |
return returnvalue | |
def __add__(self, obj): | |
""" | |
Addition. Requires matrices of the same size. | |
Call: mat1 + mat2 | |
:rtype: matrix | |
:returns: The result of adding mat1 and mat2 ( Linear Algebra ) | |
""" | |
if not (type(self) == type(obj)): | |
return NotImplemented | |
if not (self.size == obj.size): | |
raise ValueError("Matrices must be the same size for '+'") | |
returnvalue = Matrix() | |
for i in range(self._height): | |
currentRow = list() | |
for j in range(self._width): | |
currentRow.append(self._value[i][j] + obj.value[i][j]) | |
returnvalue.addRow(*currentRow) | |
return returnvalue | |
def __contains__(self, item): | |
""" | |
Contains. | |
Call: if x in matrix: | |
:Parameters: | |
item : number | |
The number to look for. | |
:rtype: boolean | |
:returns: True if a value is contained in the matrix. | |
""" | |
for row in self._value: | |
for i in row: | |
if i == item: | |
return True | |
return False | |
def __div__(self, obj): | |
""" | |
Division. | |
Call: matrix / x | |
:Parameters: | |
obj : number | |
The number to divide each item in the matrix by. | |
""" | |
if (type(obj) in MATRIX_VALID_TYPES): | |
returnvalue = Matrix() | |
for row in self._value: | |
newRow = list() | |
for item in row: | |
newItem = item / obj | |
# convert all of the round values to int. | |
if (type(newItem) is not complex) and (round(newItem, 4) == int(newItem)): | |
newItem = int(round(newItem)) | |
newRow.append(newItem) | |
returnvalue.addRow(*newRow) | |
return returnvalue | |
else: | |
return NotImplemented | |
def __divmod__(self, value): | |
""" | |
Division / Modulus | |
Call: divmod( matrix ) | |
:Parameters: | |
value : number | |
The value to mod/divide the matrix by. | |
:rtype: tuple | |
:returns: A 2 item tuple containing the matrix after division in item 0 \ | |
and the matrix after modulus in item 1. | |
""" | |
return tuple(self.__div__(value), self.__mod__(value)) | |
def __float__(self): | |
""" | |
Convert to Float | |
Call: float( matrix ) | |
:rtype: matrix | |
:returns: returns the determinant as a float value. | |
""" | |
return float(self.determinant()) | |
def __eq__(self, matrix): | |
""" | |
Equality | |
Call: mat1 == mat2 | |
:Parameters: | |
matrix : matrix | |
The matrix to compare this matrix to | |
:rtype: boolean | |
:returns: True if the matrices are identical | |
""" | |
if not (type(self) == type(matrix)): | |
return NotImplemented | |
if not (self.size == matrix.size): | |
return False | |
for i in range(self._height): | |
for j in range(self._width): | |
if not (self.value[i][j] == matrix.value[i][j]): | |
return False | |
return True | |
def __getattr__(self, name): | |
""" | |
Get attribute. | |
Call: mat.value; mat.width; mat.height; mat.size | |
:Parameters: | |
name : string | |
The object property to get | |
:rtype: int, list, or tuple | |
:returns: The value requested. | |
""" | |
# these should return copies, not the objects themselves. | |
if name == 'width': | |
return int(self._width) | |
if name == 'height': | |
return int(self._height) | |
if name == 'value': | |
return list(self._value) | |
if name == 'size': | |
return (int(self._width), int(self._height)) | |
def __getitem__(self, index): | |
""" | |
For getting parts of the matrix, mat[x] or mat[x][y]. The 'y' part will be | |
handled by the list item returned. | |
Call: matrix[x] or matrix[x][y] | |
:Parameters: | |
index : int | |
The row requested. | |
:rtype: list | |
:returns: The row requested, not a copy thereof, which means modifying the return \ | |
value will modify the matrix object, so be careful with this. | |
""" | |
if not (type(index) in MATRIX_VALID_INTS): | |
return NotImplemented | |
return self._value[index] | |
def __int__(self): | |
""" | |
Integer cast. | |
Call: int( matrix ); | |
:rtype: int | |
:returns: the determinant of the matrix | |
""" | |
return int(self.determinant()) | |
# not sure if this method is a good idea. | |
def __invert__(self): | |
""" | |
Usually used for binary inversion, here returns the inverse of the matrix. | |
Call: ~matrix | |
:rtype: matrix | |
:returns: The inverse of the matrix. | |
""" | |
return self.inverse() | |
def __iter__(self): | |
""" | |
Simple iterator method | |
Call: for x in mat:, list( mat ), etc. | |
:rtype: matrix | |
:returns: self | |
""" | |
self._iterpos = 0 | |
return self | |
def __mod__(self, mod): | |
""" | |
Modulus operator | |
Call: matrix % x | |
:Parameters: | |
mod : number | |
The number to mod each item in the matrix by. | |
:rtype: matrix | |
:returns: A matrix with all items modded | |
""" | |
if not (type(mod) in MATRIX_VALID_TYPES): | |
return NotImplemented | |
returnvalue = Matrix() | |
for i in range(self._height): | |
currentRow = list() | |
for j in range(self._width): | |
currentRow.append(self._value[i][j] % mod) | |
returnvalue.addRow(*currentRow) | |
return returnvalue | |
def __mul__(self, obj): | |
""" | |
Multiplication | |
Call: mat * mat, mat * x | |
:Parameters: | |
obj : number; matrix | |
The number or matrix to multiply this matrix by. | |
:rtype: matrix | |
:returns: The result of the multiplication ( Linear Algebra ) | |
""" | |
returnvalue = Matrix() | |
if (type(obj) in MATRIX_VALID_TYPES): | |
for row in self._value: | |
newRow = list() | |
for item in row: | |
newRow.append(item * obj) | |
returnvalue.addRow(*newRow) | |
return returnvalue | |
if (type(obj) == type(self)): | |
if not (self._width == obj.height): | |
raise ValueError("Matrices are the incorrect size for '*'") | |
else: | |
for i in range(self._height): | |
row = list() | |
for j in range(obj.width): | |
item = 0 | |
for k in range(self._width): | |
item += self._value[i][k] * obj.value[k][j] | |
row.append(item) | |
returnvalue.addRow(*row) | |
return returnvalue | |
return NotImplemented | |
def __ne__(self, matrix): | |
""" | |
Non-equality | |
Call: matrix1 != matrix2 | |
:Parameters: | |
matrix : matrix | |
The matrix to compare this matrix to. | |
:rtype: boolean | |
:returns: True if the matrices are NOT equal | |
""" | |
return not __eq__(matrix) | |
def __neg__(self): | |
""" | |
Negative of a matrix | |
:rtype: matrix | |
:returns: A matrix with the sign of each item changed. | |
""" | |
return self.__mul__(-1) | |
def __nonzero__(self): | |
""" | |
Nonzero. | |
Call: bool( matrix ) | |
:rtype: boolean | |
:returns: True if this is not a zero matrix | |
""" | |
for row in self._value: | |
for item in row: | |
if item: | |
return True | |
return False | |
def __pos__(self): | |
""" | |
Positive | |
Call: +matrix | |
:rtype: matrix | |
:returns: A copy of itself. | |
""" | |
return Matrix(self) | |
def __pow__(self, power): | |
""" | |
Power. This is only valid for square matrices | |
Call: mat ** x or pow( mat, x ) | |
:Parameters: | |
power : int | |
The power to raise this matrix to | |
:rtype: matrix | |
:returns: The result of the calculation ( Linear Algebra ) | |
""" | |
if type(power) is not int: | |
return NotImplemented | |
if not self.isSquare(): | |
raise ValueError("Power invalid for non-square matrices") | |
if power > 0: | |
p = power | |
returnvalue = Matrix(self) | |
elif power < 0: | |
p = -power | |
returnvalue = self.inverse() | |
elif power == 0: | |
return NotImplemented | |
for i in range(p - 1): | |
returnvalue *= returnvalue | |
return returnvalue | |
def __repr__(self): | |
""" | |
Representation. Formats the matrix for printing. | |
Call: repr( matrix ); str( matrix ) | |
:rtype: string | |
:returns: A formatted representation of this matrix. | |
""" | |
returnvalue = str() | |
itemwidth = self._maxValueLength() | |
for i in range(self._height): | |
if i: | |
returnvalue += '\n' | |
returnvalue += '[' | |
for j in range(self._width): | |
if type(self._value[i][j]) is float: | |
formatstring = " %%%d.3f " % itemwidth | |
else: | |
formatstring = " %%%ds " % itemwidth | |
returnvalue += (formatstring % self._value[i][j]) | |
returnvalue += ']' | |
return returnvalue | |
def __rmul__(self, obj): | |
""" | |
Right side multiplication | |
Call: x * mat | |
:Parameters: | |
obj : number | |
The number to multiply this matrix by. | |
:rtype: matrix | |
:returns: The same as mat * x | |
""" | |
if (type(obj) in MATRIX_VALID_TYPES): | |
return self.__mul__(obj) | |
return NotImplemented | |
__str__ = __repr__ | |
def __sub__(self, obj): | |
""" | |
Subtraction. Requires matrices of the same size. | |
Call: mat1 - mat2 | |
:Parameters: | |
obj : matrix | |
The matrix to subtract from this matrix | |
:rtype: matrix | |
:returns: The result of the calculation ( Linear Algebra ) | |
""" | |
if not (type(self) == type(obj)): | |
return NotImplemented | |
if not (self.size == obj.size): | |
raise ValueError("Matrices must be the same size for '+'") | |
returnvalue = Matrix() | |
for i in range(self._height): | |
currentRow = list() | |
for j in range(self._width): | |
currentRow.append(self._value[i][j] - obj.value[i][j]) | |
returnvalue.addRow(*currentRow) | |
return returnvalue | |
def _maxValueLength(self): | |
""" | |
Get the string length of the longest item in the matrix. | |
This is for formatting the output of __str__ and __repr__. | |
:rtype: int | |
:returns: The string length of the longest item in the matrix. | |
""" | |
returnvalue = 0 | |
for row in self._value: | |
for item in row: | |
if (type(item) == type(float())): | |
returnvalue = max(returnvalue, len('%.3f' % item)) | |
else: | |
returnvalue = max(returnvalue, len(str(item))) | |
return returnvalue | |
def addColumn(self, *column): | |
""" | |
Adds a column to the matrix. This must be the same height as the current columns, if there are any. | |
Call: matrix.addColumn( list ) or matrix.addColumn( item, item, item, ... ) | |
:Parameters: | |
column : list | |
The column to be inserted | |
""" | |
self.insertColumn(self._width, *column) | |
def addRow(self, *row): | |
""" | |
Adds a row to the matrix. This must be the same width as the current rows, if there are any. | |
Call: matrix.addRow( list ) or matrix.addRow( item, item, item, ... ) | |
:Parameters: | |
row : list | |
The row to be inserted | |
""" | |
self.insertRow(self._height, *row) | |
def adjoint(self): | |
""" | |
Adjoint of the matrix. | |
:rtype: matrix | |
:returns: The adjoint of this matrix. | |
""" | |
return self.cofactorMatrix().transpose() | |
# Aliases for adjoin t | |
adj = adjugate = adjoint | |
def cofactor(self, row, column): | |
""" | |
Cofactors. Only for square matrices | |
:Parameters: | |
row : int | |
The row number | |
column : int | |
The column number | |
:rtype: number | |
:returns: The cofactor of the item at row, column. | |
""" | |
if not self.isSquare(): | |
raise ValueError("Cofactor is not defined for a non-square matrix") | |
return ((-1) ** (row + column)) * self.minor(row, column) | |
def cofactorMatrix(self): | |
""" | |
The cofactor matrix. Only for square matrices. | |
:rtype: matrix | |
:returns: A matrix consisting of the cofactors of this matrix | |
""" | |
returnvalue = Matrix() | |
for i in range(self._height): | |
newRow = list() | |
for j in range(self._width): | |
newRow.append(self.cofactor(i, j)) | |
returnvalue.addRow(*newRow) | |
return returnvalue | |
def deleteColumn(self, column): | |
""" | |
Deletes a column from this matrix | |
:Parameters: | |
column : int | |
The column number to delete ( Starting at 0 ) | |
""" | |
if (column >= self._width or column <= -self._width): | |
raise IndexError('Invalid index, row %d does not exist' % column) | |
returnvalue = list() | |
self._width -= 1 | |
for row in self._value: | |
returnvalue.append(row.pop(column)) | |
return returnvalue | |
def deleteRow(self, row): | |
""" | |
Deletes a row from this matrix | |
:Parameters: | |
row : int | |
The row number to delete ( Starting at 0 ) | |
""" | |
if (row >= self._height or row <= -self.height): | |
raise IndexError('Invalid index, row %d does not exist' % row) | |
self._height -= 1 | |
return self._value.pop(row) | |
def determinant(self): | |
""" | |
Determinant. Only for square matrices. | |
:rtype: number | |
:returns: The determinant of this matrix | |
""" | |
if not self.isSquare(): | |
raise ValueError("Determinant is not defined for non-square matrix") | |
if (self._height == 1 and self._width == 1): | |
return self._value[0][0] | |
returnvalue = 0 | |
for i in range(self._width): | |
returnvalue += self._value[0][i] * self.cofactor(0, i) | |
return returnvalue | |
# An alias for determinant | |
det = determinant | |
def frobenius(self, value): | |
""" | |
Returns the Frobenius inner product of this matrix and the passed-in matrix | |
:Paramters: | |
value : matrix | |
The value of the matrix to combine this matrix with | |
:rtype: matrix | |
:returns: The Frobenius Inner Product of the two matrices | |
""" | |
return sum(self.hadamard(value)) | |
def getColumn(self, column): | |
""" | |
Get a column from this matrix | |
:Parameters: | |
column : int | |
The column to get. | |
:rtype: list | |
:returns: The column as a list | |
""" | |
returnvalue = list() | |
for row in self._value: | |
returnvalue.append(row[column]) | |
return returnvalue | |
def getRow(self, row): | |
""" | |
Get a row from this matrix | |
:Parameters: | |
row : int | |
The row to get. | |
:rtype: list | |
:returns: The row as a list | |
""" | |
returnvalue = list() | |
for item in self._value[row]: | |
returnvalue.append(item) | |
return returnvalue | |
def hadamard(self, value): | |
""" | |
Takes the Hadamard product of two matrices. | |
[ a b ] . [ e f ] = [ a*e c*f ] | |
[ c d ] [ g h ] [ c*g d*h ] | |
:Parameters: | |
value : matrix | |
The matrix to use in finding the Hadamard product | |
:rtype: matrix | |
:returns: The Hadamard product of this matrix and the passed-in matrix. | |
""" | |
if not (type(self) == type(value)): | |
raise TypeError("Inapproproate argument type for hadamard product") | |
if not (self.size == value.size): | |
raise ValueError("Matrices must be of the same size for hadamard product") | |
returnvalue = Matrix() | |
for i in range(self._height): | |
newRow = list() | |
for j in range(self._width): | |
newRow.append(self[i][j] * value[i][j]) | |
returnvalue.addRow(*newRow) | |
return returnvalue | |
def insertColumn(self, index, *column): | |
""" | |
Inserts a column into the matrix. This must be the same height as the current columns, if there are any. | |
Call: matrix.insertColumn( index, list ) or matrix.insertColumn( index, item, item, item, ... ) | |
:Parameters: | |
index : int | |
The column number to insert the new column before. | |
column : list | |
The column to be inserted | |
""" | |
if ((len(column) == 1) and (type(column[0]) in MATRIX_VALID_COLLECTIONS)): | |
column = column[0] | |
if self._height: | |
if not (len(column) == self._height): | |
raise ValueError('Improper length for new column: %d, should be %d' % (len(column), self._height)) | |
else: | |
self._height = len(column) | |
for i in range(self._height): | |
self._value.append(list()) | |
self._width += 1 | |
for i in range(self._height): | |
if not (type(column[i]) in MATRIX_VALID_TYPES): | |
message = "Values must be of type " | |
for t in range(len(MATRIX_VALID_TYPENAMES)): | |
if t: | |
message += ' or ' | |
message += "'%s'" % MATRIX_VALID_TYPENAMES[t] | |
raise TypeError(message) | |
self._value[i].insert(index, column[i]) | |
def insertRow(self, index, *row): | |
""" | |
Adds a row to the matrix. This must be the same width as the current rows, if there are any. | |
Call: matrix.insertRow( list ) or matrix.insertRow( item, item, item, ... ) | |
:Parameters: | |
index : int | |
The row number to insert the new row before. | |
row : list | |
The row to be inserted | |
""" | |
if ((len(row) == 1) and (type(row[0]) in MATRIX_VALID_COLLECTIONS)): | |
row = row[0] | |
if self._width: | |
if not (len(row) == self._width): | |
raise ValueError('Improper length for new row: %d, should be %d' % (len(row), self._width)) | |
else: | |
self._width = len(row) | |
self._height += 1 | |
# make a deep copy | |
newrow = list() | |
for item in row: | |
if not (type(item) in MATRIX_VALID_TYPES): | |
message = "Values must be of type " | |
for t in range(len(MATRIX_VALID_TYPENAMES)): | |
if t: | |
message += ' or ' | |
message += "'%s'" % MATRIX_VALID_TYPENAMES[t] | |
raise TypeError(message) | |
newrow.append(item) | |
self._value.insert(index, newrow) | |
def inverse(self): | |
""" | |
Inverse. | |
:rtype: matrix | |
:returns: The inverse of this matrx. | |
""" | |
if not self.isSquare(): | |
raise ValueError("Inverse is not defined for a non-square matrix") | |
if not self.determinant(): | |
raise ValueError('This matrix is not invertible') | |
# future division breaks the "/" operator, so we have to call the function directly. | |
return (self.adjoint().__div__(self.determinant())) | |
def isInvertible(self): | |
""" | |
Checks to see if this matrix is invertible | |
:rtype: boolean | |
:returns: True if the matrix can be inverted. | |
""" | |
return bool(self.isSquare() and self.determinant()) | |
def isSquare(self): | |
""" | |
Checks for a square matrix | |
:rtype: boolean | |
:returns: True if the matrix is square | |
""" | |
return self._width == self._height | |
def itemsToInt(self): | |
""" | |
Convert all items to int. | |
:rtype: matrix | |
:returns: A copy with all items in the matrix as an int. | |
""" | |
returnvalue = Matrix() | |
for row in self._value: | |
newRow = list() | |
for item in row: | |
# round the item to 3 decimal places before converting, | |
# so floats like 1.999999964 become 2, not 1 | |
newRow.append(int(round(item, 3))) | |
returnvalue.addRow(*newRow) | |
return returnvalue | |
def itemsToFloat(self): | |
""" | |
Convert all items to float. | |
:rtype: matrix | |
:returns: A copy with all items in the matrix as an float. | |
""" | |
returnvalue = Matrix() | |
for row in self._value: | |
newRow = list() | |
for item in row: | |
newRow.append(float(item)) | |
returnvalue.addRow(*newRow) | |
return returnvalue | |
def kronecker(self, value): | |
""" | |
Returns the Kronecker product of this matrix and the passed-in matrix | |
:Paramters: | |
value : matrix | |
The value of the matrix to combine this matrix with | |
:rtype: matrix | |
:returns: The Kronecker Product of the two matrices | |
""" | |
if not (type(self) == type(value)): | |
raise TypeError("Inappropriate argument type for kronecker product") | |
returnvalue = Matrix() | |
for i in range(self._height): | |
for j in range(value._height): | |
newRow = list() | |
for k in range(self._width): | |
for l in range(value._width): | |
newRow.append(self[i][k] * value[j][l]) | |
returnvalue.addRow(*newRow) | |
return returnvalue | |
def minor(self, i, j): | |
""" | |
The Minor of a matrix | |
:rtype: number | |
:returns: The minor of the item at column i, row j | |
""" | |
if not self.isSquare(): | |
raise ValueError("Minor is not defined for non-square matrix") | |
if (self._height == 1 and self._width == 1): | |
raise ValueError("Minor is not defined for 1x1 matrix") | |
m = Matrix(self) | |
m.deleteRow(i) | |
m.deleteColumn(j) | |
return m.determinant() | |
# next() method for the iterator; returns each item in the matrix, first row0, then row1, etc. | |
def next(self): | |
""" | |
Iterator method. | |
""" | |
if self._iterpos < (self._width * self._height): | |
x, y = divmod(self._iterpos, self._width) | |
v = self[x][y] | |
self._iterpos += 1 | |
return v | |
del self._iterpos | |
raise StopIteration() | |
def roundItems(self, digits=0): | |
""" | |
Round off the items in a matrix. | |
:Parameters: | |
digits : int | |
How many digits past the decimal point to round to. Can be negative. | |
:rtype: matrix | |
:returns: A matrix with all items rounded to 'digits' places. | |
""" | |
returnvalue = Matrix() | |
for row in self._value: | |
newRow = list() | |
for item in row: | |
item = round(item, digits) | |
if (digits <= 0): | |
item = int(item) | |
newRow.append(item) | |
returnvalue.addRow(*newRow) | |
return returnvalue | |
# An alias for roundItems | |
round = roundItems # alias | |
def swapColumns(self, i, j): | |
""" | |
Swaps columns i and j. | |
:Parameters: | |
i : int | |
The first of 2 columns to swap. | |
j : int | |
The second of 2 columns to swap. | |
""" | |
if not (type(i) in MATRIX_VALID_INTS and type( | |
j) in MATRIX_VALID_INTS): # this should be fixed to accomodate 'long' types | |
raise TypeError("Row indices must be of type 'int'") | |
columnA = self.deleteColumn(max(i, j)) | |
columnB = self.deleteColumn(min(i, j)) | |
self.insertColumn(min(i, j), *columnA) | |
self.insertColumn(max(i, j), *columnB) | |
def swapRows(self, i, j): | |
""" | |
Swaps rows i and j. | |
:Parameters: | |
i : int | |
The first of 2 rows to swap. | |
j : int | |
The second of 2 rows to swap. | |
""" | |
if not (type(i) in MATRIX_VALID_INTS and type( | |
j) in MATRIX_VALID_INTS): # this should be fixed to accomodate 'long' types | |
raise TypeError("Row indices must be of type 'int'") | |
rowA = self.deleteRow(max(i, j)) | |
rowB = self.deleteRow(min(i, j)) | |
self.insertRow(min(i, j), *rowA) | |
self.insertRow(max(i, j), *rowB) | |
def transpose(self): | |
""" | |
Transpose of a matrix. | |
:rtype: matrix | |
:returns: The transpose of this matrix. | |
""" | |
returnvalue = Matrix() | |
for i in range(self._width): | |
row = list() | |
for j in range(self._height): | |
row.append(self._value[j][i]) | |
returnvalue.addRow(*row) | |
return returnvalue | |
def identMatrix(size): | |
""" | |
Creates an identity matrix | |
:Parameters: | |
size : int | |
The width and height of the matrix to return. | |
:rtype: matrix | |
:returns: An identity matrix of the specified size. | |
""" | |
returnvalue = Matrix() | |
for i in range(size): | |
newrow = [0] * size | |
newrow[i] = 1 | |
returnvalue.addRow(*newrow) | |
return returnvalue | |
def zeroMatrix(width, height): | |
""" | |
Creates a zero matrix | |
:Parameters: | |
width : int | |
The width of the matrix to return | |
height : int | |
The height of the matrix to return | |
:rtype: matrix | |
:return: A zero matrix of the specified size. | |
""" | |
returnvalue = Matrix() | |
for i in range(width): | |
newrow = [0] * height | |
returnvalue.addRow(*newrow) | |
return returnvalue |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
cool