J
Josh English
I am trying to whip up a quick matrix class that can handle multiplication.
Should be no problem, except when it fails.
--- Begin
#!/usr/bin/env python
# _*_ coding: utf-8
from operator import mul
class Matrix(object):
"""Matrix([data])
Data should be a list of equal sized lists.
Defaults to a 2d identity matrix
"""
def __init__(self, data=None):
if data is None:
data = [[1,0], [0,1]]
self.data = []
if isinstance(data, (list, tuple)):
ncols = len(data[0])
for row in data:
if len(row) != ncols:
raise ValueError("Rows are unequal lengths")
self.data.append(row)
self.size = (len(self.data), len(self.data[0]))
def get_row(self, idx):
if (0 <= idx < self.size[0]):
return self.data[idx]
else:
raise ValueError("Bad row")
def get_col(self, idx):
if (0 <= idx < self.size[1]):
return list(d[idx] for d in self.data)
else:
raise ValueError("Bad column index")
def __mul__(self, other):
if not isinstance(other, (Matrix,int, float)):
raise ValueError("Cannot multiply by given value")
if isinstance(other, (int, float)):
res = []
for row in self.data:
res.append([d*other for d in row])
return Matrix(res)
# left with a matrix
res = zero_matrix(self.size[0], other.size[1])
for i in range(res.size[0]):
for j in range(res.size[1]):
print i, j, self.get_row(i), other.get_col(j),
temp = map(mul, self.get_row(i), other.get_col(j))
print temp,
t = sum(temp)
print t
res.data[j] = t
print res.data
return res
def as_string(self):
# return a list of lines that look pretty
stringed =[]
for row in self.data:
stringed.append(map(str, row))
widths = []
for col in range(self.size[1]):
column = [s[col] for s in stringed]
widths.append(max(map(len, column)))
item_format = "{:>%s}"
format_items = [item_format % w for w in widths]
format_string = " ".join(format_items)
formatted = [format_string.format(*s) for s in stringed]
return formatted
def zero_matrix(rows, cols):
row = [0] * cols
data = []
for r in range(rows):
data.append(row)
return Matrix(data)
M = Matrix(([1, 0], [0, -1]))
N = M*4
print '\n'.join(M.as_string())
print '-'
print '\n'.join(N.as_string())
print '-'
S = N * M
print '\n'.join(S.as_string())
--- END
For some reason, my output from this is:
1 0
0 -1
-
4 0
0 -4
-
0 0 [4, 0] [1, 0] [4, 0] 4
[[4, 0], [4, 0]]
0 1 [4, 0] [0, -1] [0, 0] 0
[[4, 0], [4, 0]]
1 0 [0, -4] [1, 0] [0, 0] 0
[[0, 0], [0, 0]]
1 1 [0, -4] [0, -1] [0, 4] 4
[[0, 4], [0, 4]]
0 4
0 4
The print lines prove to me that the logic is working, but for some reason, assigning the sum to a particular item in a particular row is assigning the same row values to every row.
This should be one of those really simple Python things, but for the life of me I don't see it.
The first [[4, 0], [4, 0]] is clearly wrong. In each step, this algorithm is repeating the row.
Any ideas as to why this is happening?
Python 2.7.5, Windows 7, so nothing exotic.
Josh
Should be no problem, except when it fails.
--- Begin
#!/usr/bin/env python
# _*_ coding: utf-8
from operator import mul
class Matrix(object):
"""Matrix([data])
Data should be a list of equal sized lists.
Defaults to a 2d identity matrix
"""
def __init__(self, data=None):
if data is None:
data = [[1,0], [0,1]]
self.data = []
if isinstance(data, (list, tuple)):
ncols = len(data[0])
for row in data:
if len(row) != ncols:
raise ValueError("Rows are unequal lengths")
self.data.append(row)
self.size = (len(self.data), len(self.data[0]))
def get_row(self, idx):
if (0 <= idx < self.size[0]):
return self.data[idx]
else:
raise ValueError("Bad row")
def get_col(self, idx):
if (0 <= idx < self.size[1]):
return list(d[idx] for d in self.data)
else:
raise ValueError("Bad column index")
def __mul__(self, other):
if not isinstance(other, (Matrix,int, float)):
raise ValueError("Cannot multiply by given value")
if isinstance(other, (int, float)):
res = []
for row in self.data:
res.append([d*other for d in row])
return Matrix(res)
# left with a matrix
res = zero_matrix(self.size[0], other.size[1])
for i in range(res.size[0]):
for j in range(res.size[1]):
print i, j, self.get_row(i), other.get_col(j),
temp = map(mul, self.get_row(i), other.get_col(j))
print temp,
t = sum(temp)
print t
res.data[j] = t
print res.data
return res
def as_string(self):
# return a list of lines that look pretty
stringed =[]
for row in self.data:
stringed.append(map(str, row))
widths = []
for col in range(self.size[1]):
column = [s[col] for s in stringed]
widths.append(max(map(len, column)))
item_format = "{:>%s}"
format_items = [item_format % w for w in widths]
format_string = " ".join(format_items)
formatted = [format_string.format(*s) for s in stringed]
return formatted
def zero_matrix(rows, cols):
row = [0] * cols
data = []
for r in range(rows):
data.append(row)
return Matrix(data)
M = Matrix(([1, 0], [0, -1]))
N = M*4
print '\n'.join(M.as_string())
print '-'
print '\n'.join(N.as_string())
print '-'
S = N * M
print '\n'.join(S.as_string())
--- END
For some reason, my output from this is:
1 0
0 -1
-
4 0
0 -4
-
0 0 [4, 0] [1, 0] [4, 0] 4
[[4, 0], [4, 0]]
0 1 [4, 0] [0, -1] [0, 0] 0
[[4, 0], [4, 0]]
1 0 [0, -4] [1, 0] [0, 0] 0
[[0, 0], [0, 0]]
1 1 [0, -4] [0, -1] [0, 4] 4
[[0, 4], [0, 4]]
0 4
0 4
The print lines prove to me that the logic is working, but for some reason, assigning the sum to a particular item in a particular row is assigning the same row values to every row.
This should be one of those really simple Python things, but for the life of me I don't see it.
The first [[4, 0], [4, 0]] is clearly wrong. In each step, this algorithm is repeating the row.
Any ideas as to why this is happening?
Python 2.7.5, Windows 7, so nothing exotic.
Josh