How to put scalar multiplication in this code? - python

import random
import operator
import sys
import unittest
__version__ = "0.3"
class MatrixError(Exception):
""" An exception class for Matrix """
pass
class Matrix(object):
""" A simple Python matrix class with
basic operations and operator overloading """
def __init__(self, m, n, init=True):
if init:
self.rows = [[0]*n for x in range(m)]
else:
self.rows = []
self.m = m
self.n = n
def __getitem__(self, idx):
return self.rows[idx]
def __setitem__(self, idx, item):
self.rows[idx] = item
def __str__(self):
s='\n'.join([' '.join([str(item) for item in row]) for row in self.rows])
return s + '\n'
def __repr__(self):
s=str(self.rows)
rank = str(self.getRank())
rep="Matrix: \"%s\", rank: \"%s\"" % (s,rank)
return rep
def reset(self):
""" Reset the matrix data """
self.rows = [[] for x in range(self.m)]
def transpose(self):
""" Transpose the matrix. Changes the current matrix """
self.m, self.n = self.n, self.m
self.rows = [list(item) for item in zip(*self.rows)]
def getTranspose(self):
""" Return a transpose of the matrix without
modifying the matrix itself """
m, n = self.n, self.m
mat = Matrix(m, n)
mat.rows = [list(item) for item in zip(*self.rows)]
return mat
def getRank(self):
return (self.m, self.n)
def __eq__(self, mat):
""" Test equality """
return (mat.rows == self.rows)
def __add__(self, mat):
""" Add a matrix to this matrix and
return the new matrix. Doesn't modify
the current matrix """
if self.getRank() != mat.getRank():
raise MatrixError, "Trying to add matrixes of varying rank!"
ret = Matrix(self.m, self.n)
for x in range(self.m):
row = [sum(item) for item in zip(self.rows[x], mat[x])]
ret[x] = row
return ret
def __sub__(self, mat):
""" Subtract a matrix from this matrix and
return the new matrix. Doesn't modify
the current matrix """
if self.getRank() != mat.getRank():
raise MatrixError, "Trying to add matrixes of varying rank!"
ret = Matrix(self.m, self.n)
for x in range(self.m):
row = [item[0]-item[1] for item in zip(self.rows[x], mat[x])]
ret[x] = row
return ret
def __mul__(self, mat):
""" Multiple a matrix with this matrix and
return the new matrix. Doesn't modify
the current matrix """
matm, matn = mat.getRank()
if (self.n != matm):
raise MatrixError, "Matrices cannot be multipled!"
mat_t = mat.getTranspose()
mulmat = Matrix(self.m, matn) or Matrix(self.m, a)
for x in range(self.m):
for y in range(mat_t.m) or y==a:
mulmat[x][y] = sum([item[0]*item[1] for item in zip(self.rows[x], mat_t[y])])or a*x
return mulmat
def __iadd__(self, mat):
""" Add a matrix to this matrix.
This modifies the current matrix """
# Calls __add__
tempmat = self + mat
self.rows = tempmat.rows[:]
return self
def __isub__(self, mat):
""" Add a matrix to this matrix.
This modifies the current matrix """
# Calls __sub__
tempmat = self - mat
self.rows = tempmat.rows[:]
return self
def __imul__(self, mat):
""" Add a matrix to this matrix.
This modifies the current matrix """
# Possibly not a proper operation
# since this changes the current matrix
# rank as well...
# Calls __mul__
tempmat = self * mat
self.rows = tempmat.rows[:]
self.m, self.n = tempmat.getRank()
return self
def save(self, filename):
open(filename, 'w').write(str(self))
#classmethod
def _makeMatrix(cls, rows):
m = len(rows)
n = len(rows[0])
# Validity check
if any([len(row) != n for row in rows[1:]]):
raise MatrixError, "inconsistent row length"
mat = Matrix(m,n, init=False)
mat.rows = rows
return mat
#classmethod
def makeRandom(cls, m, n, low=0, high=10):
""" Make a random matrix with elements in range (low-high) """
obj = Matrix(m, n, init=False)
for x in range(m):
obj.rows.append([random.randrange(low, high) for i in range(obj.n)])
return obj
#classmethod
def makeZero(cls, m, n):
""" Make a zero-matrix of rank (mxn) """
rows = [[0]*n for x in range(m)]
return cls.fromList(rows)
#classmethod
def makeId(cls, m):
""" Make identity matrix of rank (mxm) """
rows = [[0]*m for x in range(m)]
idx = 0
for row in rows:
row[idx] = 1
idx += 1
return cls.fromList(rows)
#classmethod
def readStdin(cls):
""" Read a matrix from standard input """
print 'Enter matrix row by row. Type "q" to quit'
rows = []
while True:
line = sys.stdin.readline().strip()
if line=='q': break
row = [int(x) for x in line.split()]
rows.append(row)
return cls._makeMatrix(rows)
#classmethod
def readGrid(cls, fname):
""" Read a matrix from a file """
rows = []
for line in open(fname).readlines():
row = [int(x) for x in line.split()]
rows.append(row)
return cls._makeMatrix(rows)
#classmethod
def fromList(cls, listoflists):
""" Create a matrix by directly passing a list
of lists """
# E.g: Matrix.fromList([[1 2 3], [4,5,6], [7,8,9]])
rows = listoflists[:]
return cls._makeMatrix(rows)
I'm trying to put a scalar multiplication but it always fail.
For example,
a = [[2,2],[2,3]]
If I multiply it's like, 3*a = [[2,2],[2,3],[2,2],[2,3],[2,2],[2,3]]
How could I fix it?

For example, a = [[2,2],[2,3]] If I multiply it's like, 3*a = [[2,2],[2,3],[2,2],[2,3],[2,2],[2,3]]
Here, a is a list and not a Matrix. You can't overload the multiplication of a standard list by a scalar.

You can't multiply the whole list. The output you got is like a string multiplication.
a="hello"
b=a*3
print b
gives the output as
hellohellohello
That is what happens in your case. Multiply one by one
for i in range(len(a)):
for j in range(len(i)):
a[i][j]*=3

Related

How to use recursion inside a class function

I made a class function that deals with matrices or a list within a list. Sort of like a calculator that looks like this:
class RealMat:
def __init__(self, mat):
self.mat = mat
def __add__(self, other):
if len(self.mat) != len(other.mat) or len(self.mat[0]) != len(self.mat[0]):
return None
result = self.mat
for i in range(len(self.mat)):
for j in range(len(self.mat[0])):
result[i][j] = self.mat[i][j] + other.mat[i][j]
return RealMat(result)
def __sub__(self, other):
if len(self.mat) != len(other.mat) or len(self.mat[0]) != len(self.mat[0]):
return None
result = self.mat
for i in range(len(self.mat)):
for j in range(len(self.mat[0])):
result[i][j] = self.mat[i][j] - other.mat[i][j]
return RealMat(result)
def __mul__(self, other):
if isinstance(other, int):
for x in range(len(self.mat)):
for y in range(len(self.mat[0])):
self.mat[x][y] = self.mat[x][y] * other
return RealMat(self.mat)
if len(self.mat[0])!=len(other.mat):
return None
column=0
result=[[0]*len(self.mat) for i in range(len(other.mat[0]))]
for x in range(len(other.mat[0])):
row = 0
for x in range(len(self.mat)):
total = 0
i = 0
for x in range(len(self.mat[0])):
total += self.mat[row][i] * other.mat[i][column]
i += 1
result[row][column] = total
row += 1
column += 1
return RealMat(result)
def __rmul__(self, factor):
for x in range(len(self.mat)):
for y in range(len(self.mat[0])):
self.mat[x][y] = self.mat[x][y] * factor
return RealMat(self.mat)
def __pow__(self, n):
if len(self.mat) != len(self.mat[0]):
return None
if n == 0:
identity = [[1 if i == j else 0 for i in range(len(self.mat))] for j in range(len(self.mat))]
return RealMat(identity)
result = RealMat(self.mat)
for x in range(n-1):
result = result * RealMat(self.mat)
return result
def __eq__(self, other):
if len(self.mat) != len(other.mat) or len(self.mat[0]) != len(other.mat[0]):
return False
for x in range(len(self.mat)):
for y in range(len(self.mat[0])):
if self.mat[x][y] != other.mat[x][y]:
return False
return True
def getMatrixMinor(self,i,j):
return [row[:j] + row[j+1:] for row in (self.mat[:i]+self.mat[i+1:])]
def getMatrixDeternminant(self):
if len(self.mat) == 2:
return self.mat[0][0]*self.mat[1][1]-self.mat[0][1]*self.mat[1][0]
determinant = 0
for c in range(len(self.mat)):
determinant += ((-1)**c)*self.mat[0][c]*getMatrixDeternminant(getMatrixMinor(self.mat,0,c))
return determinant
All the other code works fine and I'm happy with it but I can't seem to make my determinant finder code to work
def getMatrixMinor(self,i,j):
return [row[:j] + row[j+1:] for row in (self.mat[:i]+self.mat[i+1:])]
This code gets me the minor matrix while this:
def getMatrixDeternminant(self):
if len(self.mat) == 2:
return self.mat[0][0]*self.mat[1][1]-self.mat[0][1]*self.mat[1][0]
determinant = 0
for c in range(len(self.mat)):
determinant += ((-1)**c)*self.mat[0][c]*getMatrixDeternminant(getMatrixMinor(self.mat,0,c))
return determinant
Solves the determinant of nxn matrix. However it keeps saying "getMatrixDeternminant is not defined" when I try to recurse it. Maybe because it is inside a class? I just got into OOP so I am not well versed in this. Can someone point out what I did wrong?
edit* I tried using the self.getMatrixDeternminant()
def getMatrixMinor(self,m,i,j):
return [row[:j] + row[j+1:] for row in (m[:i]+m[i+1:])]
def getMatrixDeternminant(self):
if len(self.mat) == 2:
return self.mat[0][0]*self.mat[1][1]-self.mat[0][1]*self.mat[1][0]
determinant = 0
for c in range(len(self.mat)):
determinant += ((-1)**c)*self.mat[0][c]*self.getMatrixDeternminant(self.getMatrixMinor(self.mat,0,c))
return determinant
it says:
TypeError: getMatrixDeternminant() takes 1 positional argument but 2 were given
Edit**: I actually got the code from somewhere and tried to implement it in my class. This is the original code:
def getMatrixMinor(m,i,j):
return [row[:j] + row[j+1:] for row in (m[:i]+m[i+1:])]
def getMatrixDeternminant(m):
#base case for 2x2 matrix
if len(m) == 2:
return m[0][0]*m[1][1]-m[0][1]*m[1][0]
determinant = 0
for c in range(len(m)):
determinant += ((-1)**c)*m[0][c]*getMatrixDeternminant(getMatrixMinor(m,0,c))
return determinant
Your getMatrixDeternminant [sic] calculates the determinant of the current object (self). However, your algorithm requires calculating the determinant of other matrices.
Therefore, first keep the algorithm as it was originally (usually you would make it a static method or keep it outside the class). Then, from your method, call that algorithm passing it your current matrix.

overwriting __add__(self, other) has same instances for self and other

I am trying to write a new add()-method for my class Matrix, which I am implementing without the usage of numpy.
The following problem occurs when I use my add method:
#classmethod
def __add__(self, other):
print(self._data)
print(other.data)
row = len(self._data)
column = len(self._data[0])
addition = [[0 for c in range(column)] for r in range(row)]
for i in range(row):
for j in range(column):
addition[i][j] += self._data[i][j] + other[i][j]
return Matrix(addition)
print yields the same value for self and for other although it shouldn't:
a = Matrix([[1, 2], [3, 4]])
b = Matrix.filled(2, 2, 1)
c = a + b
output for print, which clearly shows that c = b + b:
[[1, 1], [1, 1]]
[[1, 1], [1, 1]]
This is the rest of my code I implemented for my class:
class Matrix(object):
#initializes instance of Matrix
#classmethod
def __init__(self, iterable):
self._data = iterable
count = len(iterable[0])
for i in range(len(iterable)):
for j in range(len(iterable[i])):
assert count == len(iterable[i])
assert type(iterable[i][j]) == int or type(iterable[i][j]) == float
#get item at key - a[0,1] -> a[0][1]
#classmethod
def __getitem__(self, key):
if (isinstance(key,int)):
return self._data[key]
else:
return self._data[key[0]][key[1]]
#set value at key - a[1,0] = 42 -> a[1][0] = 42
#classmethod
def __setitem__(self, key, value):
if (isinstance(key,int)):
self._data[key] = value
else:
self._data[key[0]][key[1]] = value
#classmethod
def __str__(self):
k = "["
for i in self._data:
k = k + str(i)
k = k +"," + "\n" + " "
return k[:-3] + "]"
#builds matrix with dimensions row * column
#staticmethod
def filled(rows,cols, value):
matrix = [[value] * cols for i in range(rows)]
return Matrix(matrix)
#creates and returns copy of matrix
#property
def data(self):
matrix = copy.deepcopy(self._data)
return matrix
Thank you very much for your time and help

Issue with python __eq__ method in checking if 2 lists are equal

I have a python program in which I have a class called Vector and an empty list inside of that class which is being populated runtime.
Here is the init:
def __init__(self,n):
self.vector = [];
self.n = n;
for x in range(n):
self.vector.append(False);
And here is the eq:
def __eq__(self, other):
t = True
for x in range(self.n):
if self.vector[x] != other.vector[x]:
t = False;
return t
however, when I try to check if 2 objects of this type are equal, I always get true, even though I changed values inside of vector in Vector class.
Here is the code where I do the above:
vectors = []
n = tmp.size();
k = calculateCombinationCount(n,int(n/2))
for i in range(k):
for j in range(0,n-1):
if (tmp.vector[j] != tmp.vector[j+1]):
t = True
for x in vectors:
if x == tmp:
t = False;
if t:
vectors.append(tmp)
tmp.printVector();
tmp.swap(j,j+1);
I would appreciate any help that you can provide. Thank you :)
EDIT:
def swap(self,i,j):
tmp = self.vector[i]
self.vector[i] = self.vector[j]
self.vector[j] = tmp
def calculateCombinationCount(n,r):
k = factorial(n)/(factorial(int(r))*factorial(int(n-r)))
return int(k)
Right so I've updated your code to be much more pythonic (I can tell you come from another language, Java?).
from math import factorial
class Vector:
def __init__(self, size):
self.size = size
self.vector = [False] * size
def __eq__(self, other):
"""
Same if self.size == other.size
"""
assert self.size == other.size, (self.size, other.size)
return self.vector == other.vector
def print_vector(self):
print(self.vector)
def swap(self, i, j):
"""
More efficient and pythonic
"""
self.vector[i], self.vector[j] = self.vector[j], self.vector[i]
def calculate_combination_count(n, r):
"""
This is slow, I'd replace it with scipy.special.comb
https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.comb.html#scipy.special.comb
"""
return factorial(n) // (factorial(r) * factorial(n-r))
tmp = Vector(10)
vectors = []
n = tmp.size
k = calculate_combination_count(n, n // 2)
for i in range(k):
for j in range(0, n-1):
if tmp.vector[j] != tmp.vector[j + 1]:
if not any(vec == tmp for vec in vectors): # much more efficient
vectors.append(tmp)
tmp.print_vector()
tmp.swap(j, j + 1)
else: # Just to prove why it doesn't work
print('tmp.vector is all False: {}'.format(not all(tmp.vector)))
This prints out tmp.vector is all False: True repeatedly. I think this is your problem.
If you

Python Iterate 2D array __iter__

I am trying to create a 2D Array class and want to make the matrix iterable. Does anyone know how to go about doing this? I am a new to classes in python and still getting the hang of things. Also, how would str be implemented in my main? If i just use print(customMatrix) will that go and use the str method?
Heres what I'm working on. I know some of it isn't correct :)
class Array2D():
def __init__(self, height, width):
self._width = width
self._height = height
self.matrix = [[None]*height for _ in range(width)]
def width(self):
return self._width
def height(self):
return self._height
def set(self, row, col, element):
self.matrix[row][col] = element
def get(self, row, col):
return self.matrix[row][col]
def row(self, row_no):
rowList = []
for item in self.matrix[row_no][item]:
rowList.append(item)
def column(self, col_no):
colList = []
for item in self.matrix[item][col_no]:
colList.append(item)
def __str__(self):
#for row in self.matrix:
#print (row)
return (str(self.matrix))
def __iter__(self):
Actually there is a yield keyword which is handy in this case, It can be thought of as a return statement which saves the previous state while returning anything ,so when you call the method it first yields self.matrix[0][0] on the second call to this method it would yield self.matrix[0][1] and so on..
class Array2D():
def __init__(self, height, width):
self._width = width
self._height = height
self.matrix = [[None]*height for _ in range(width)]
def width(self):
return self._width
def height(self):
return self._height
def set(self, row, col, element):
self.matrix[row][col] = element
def get(self, row, col):
return self.matrix[row][col]
def row(self, row_no):
rowList = []
for item in self.matrix[row_no][item]:
rowList.append(item)
def column(self, col_no):
colList = []
for item in self.matrix[item][col_no]:
colList.append(item)
def __str__(self):
return_str = ""
for i in xrange(self._height):
for j in xrange(self._width):
return_str+=str(self.matrix[i][j])+" " #4 space between each element
return_str+="\n"
return return_str
def __iter__(self):
for i in xrange(self._height):
for j in xrange(self._width):
yield self.matrix[i][j]
def __iter__(self):
for x in xrange(self.width):
for y in xrange(self.height):
yield self.matrix[x][y]
Read up on generators and the yield keyword, they're fun to use!

how to create a between matrix calculations class in python?

I am trying to create a class that will be able to make all possible calculations between matrix. the input is a matrix (doesn't matter the size), and on that matrix the class should do any calculations - either multiply, combine or substract. The different functions are as follow:
I need to have in this class:
__init__(self, data)
get_width(self)
get_height(self)
add(self, m)
scalar_multiply(self, a)
subtract(self, m)
multiply(self, m)
compare(self, m)
Thanks alot, it also needs to be with simple actions.
This is my code till now:
class Matrix:
def __init__(self, data):
self.data = data
def get_width(self):
return len(self.data[0])
def get_height(self):
return len(self.data)
def add(self, m):
lines = []
for j in range(len(self.data)):
line = []
for i in range(len(self.data[j])):
line.append(self.data[j][i] + m[j][i])
lines.append(line)
return lines
def scalar_multiply(self, a):
res = []
for j in range(len(self.data)):
line = []
for i in range(len(self.data)):
line.append(self.data[j][i]*a)
res.append(line)
return res
def subtract(self, m):
lines = []
for j in range(len(self.data)):
line = []
for i in range(len(self.data)):
line.append(self.data[j][i] - m[j][i])
lines.append(line)
return lines
def multiply(self, m):
lines = []
for j in range(len(self.data-1)):
line = []
for i in range(len(m[0])-1):
schum = 0
for k in range(len(self.data[0]-1)):
schum = self.data[j][k]*m[k][i]
line.append(schum)
lines.append(line)
return lines
def compare(self, m):
for j in range(len(self.data)):
for i in range(len(self.data)[j]):
while self.data[j][i] == m[j][i]:
return True
else:
return False
Do you need to create this yourself? If not, there is already an excellent implementation of this in numpy

Categories

Resources