By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,257 Members | 1,167 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,257 IT Pros & Developers. It's quick & easy.

matrix class

P: n/a
Below is a module (matrix.py) with a class to implement some basic
matrix operations on a 2D list. Some things puzzle me about the best
way to do this (please don't refer to scipy, numpy and numeric because
this is a personal programming exercise for me in creating an
operational class in pure python for some *basic* matrix operations).

1. Please take a look at the __init__ function and comment on the
initialization of the list data with respect to unique memory
allocation.

2. In the operator overloading of __add__, __sub__, etc., the
statement isinstance(q, Matrix) raises exceptions every time. This
statement works fine outside of the class definition, but not during
the operator evaluation. What is going here?
## BEGIN MODULE FILE

class Matrix:
"""
Create and manipulate a matrix object

Matrix(data, dim)

data = list of lists (currently only 2D)
dim=(row,col) tuple of int

For example,

#data = [[0.0] * c for i in xrange(r)]
data = [[0.0,0.1],[1.0,1.1],[2.0,2.1]]
rowN =len(data)
colN =len(data[0])
m = Matrix(data)
m = Matrix(data,dim=(rowN, colN))

d1 = [[0.0, 0.1], [1.0, 1.1], [2.0, 2.1]] # 3x2 matrix
d2 = [[0.0, 0.1, 0.2], [1.0, 1.1, 1.2]] # 2x3 matrix
m1 = Matrix(d1)
m2 = Matrix(d2)
#m3 = m1 + m2 # dimension error
m3 = m1 + m2.transpose()
m3 = m1 - m2.transpose()
m3 = m1 * m2 # 3x3
m3 = m2 * m1 # 2x2

m1[2,:]
m1[:,2]
"""

def __init__(self, data=None, dim=None):
"""
create a matrix instance.

m = Matrix([data [, dim]])

<datais a 2D matrix comprised of a nested list of floats
<dimis a tuple of int values for the row and column size
(r,c)

eg:
data = [[0.0,0.1],[1.0,1.1],[2.0,2.1]]
dim = (3,2) # or (len(data),len(data[0]))
"""

if data != None:
self.data = data
r = len(data)
c = len(data[0])
# Are all the rows the same length?
rowLenCheck = sum([len(data[i]) != c for i in range(r)])
if rowLenCheck 0:
raise ValueError
else:
self.dim = (r,c)

if dim != None:
if (dim[0] == r) and (dim[1] == c):
self.dim = (r,c)
else:
# over-ride the dim input, do not reshape data!
# print a warning?
self.dim = (r,c)
else:
if dim != None:
if len(dim) == 2:
self.dim = tuple(dim)
r = dim[0]
c = dim[1]
else:
# maybe a new exception type?
arg = ("len(dim) != 2: ", dim)
raise ValueError, arg

# BEGIN ALT ----------------------------------------
# Does this give unique memory for each element?
# self.data = [[0.0] * c for i in xrange(r)]

# It seems that the initialization does not generate
# unique memory elements because all list elements
# refer to the same number object (0.0), but
# modification of any element creates a unique value,
# without changing any other values, eg:

##>>x = [[0.0] * 3 for i in xrange(2)]
##>>id(x)
# 3079625068L
# >>id(x[0][0])
# 136477300
# >>id(x[0][1])
# 136477300
# >>id(x[1][1])
# 136477300
# >>x[0][0] = 1.0
# >>x
# [[1.0, 0.0, 0.0], [0.0, 0.0, 0.0]]
# >>>
# END ALT ----------------------------------------

# create a zero row vector, with unique memory for
each element
self.data = [[x * 0.0 for x in range(c)]]
for i in range(1,r):
self.data.append([x * 0.0 for x in range(c)])
else:
self.data = []
self.dim = (0,0)
#print self.__doc__

def __getitem__(self, i):
"""
matrix[r,c] returns values from matrix.data, eg:
>>data = [[0.0,0.1],[1.0,1.1],[2.0,2.1]]
m = Matrix(data)
m[2,:]
[2.0, 2.1000000000000001]
"""
r = i[0]
c = i[1]
#print "index: (%s, %s)" % (r,c)
#print "value: ", self.data[r][c]
return self.data[r][c]

def reshape(self, newdim=None):
'reshape a matrix object: matrix.reshape(newdim)'
print "something to implement later"
pass

def transpose(self):
'transpose a matrix: m2 = m1.transpose()'
m = Matrix(dim=(self.dim[1],self.dim[0]))
for r in range(self.dim[0]):
for c in range(self.dim[1]):
m.data[c][r] = self.data[r][c]
return m

def __add__(self, q):
'matrix addition: m3 = m1 + m2'
# if isinstance(q, Matrix):
# arg = ("q is not a matrix instance", q)
# raise TypeError, arg
if self.dim != q.dim:
arg = ("p.dim != q.dim", self.dim, q.dim)
raise IndexError, arg
else:
# do the addition
m = Matrix(dim=self.dim)
for r in range(self.dim[0]): # rows of p and q
m.data[r] = map(lambda x, y: x + y, self.data[r],
q.data[r])
return m

def __sub__(self, q):
'matrix subtraction: matrix - matrix'
# if isinstance(q, Matrix):
# arg = ("q is not a matrix instance", q)
# raise TypeError, arg
if self.dim != q.dim:
arg = ("p.dim != q.dim", self.dim, q.dim)
raise IndexError, arg
else:
# do the subtraction
m = Matrix(dim=self.dim)
for r in range(self.dim[0]): # rows of p and q
m.data[r] = map(lambda x, y: x - y, self.data[r],
q.data[r])
return m

def __mul__(self, q):
"""
multiply two matrices:
m = p * q # p and q are matrix objects and p.dim[1] ==
q.dim[0]
"""
# if isinstance(q, Matrix):
# arg = ("q is not a matrix instance", q)
# raise TypeError, arg
if self.dim[1] != q.dim[0]:
arg = ("p.dim[1] != q.dim[0]", self.dim[1], q.dim[0])
raise IndexError, arg
else:
# do the multiplication
m = Matrix(dim=(self.dim[0], q.dim[1]))
for r in range(self.dim[0]): # rows of p
for c in range(q.dim[1]): # cols of q
# get the dot product of p(r,:) with q(:,c)
pVec = self.data[r]
qVec = [q.data[a][c] for a in xrange(q.dim[0])]
m.data[r][c] = sum(map(lambda x, y: x * y, pVec,
qVec))
return m

# let's not try to divide for now (leave the inverse stuff to c/c+
+)

def __len__(self):
return self.dim[0] * self.dim[1]

def __str__(self):
# print the matrix data
s = ""
for r in range(self.dim[0]):
for c in range(self.dim[1]):
s += "%f " % (self.data[r][c])
s += "\n"
return s

def printFormat(self, format):
"""
print the matrix data nicely formatted, eg:
matrix.printFormat("%8.4f")
"""
for r in range(self.dim[0]):
for c in range(self.dim[1]):
print format % (self.data[r][c]),
print

def __repr__(self):
# return something that will recreate the object
return "Matrix(%s, %s)" % (self.data, self.dim)


#
--------------------------------------------------------------------------------
# Explore the functionality - should be unit testing

# >>m = Matrix(dim=(2,2))
# >>type(m)
# <class '__main__.matrix'>
# >>m.dim
#(2, 2)
# >>m.len()
# 4
# >>m.data
# [[0.0, 0.0], [0.0, 0.0]]
# >>m.dim
# (2, 2)
# >>id(m.data[0][0])
# 136477668
# >>id(m.data[0][1])
# 136477380
# >>id(m.data[1][0])
# 136477668
# >>id(m.data[1][1])
# 136477380
# >>m.data[0][0] = 1.0
# >>m.data[1][0] = 2.0
# >>m.data
# [[1.0, 0.0], [2.0, 0.0]]

testing = 1
if testing:
d1 = [[0.0, 0.1], [1.0, 1.1], [2.0, 2.1]] # 3x2 matrix
d2 = [[0.0, 0.1, 0.2], [1.0, 1.1, 1.2]] # 2x3 matrix
m1 = Matrix(d1)
m2 = Matrix(d2)
#m3 = m1 + m2 # "dimension" error
m3 = m1 + m2.transpose()
m3 = m1 - m2.transpose()
m3 = m1 * m2 # 3x3
m3 = m2 * m1 # 2x2

## END MODULE FILE

Jun 13 '07 #1
Share this Question
Share on Google+
2 Replies


P: n/a
On Jun 12, 7:31 pm, DarrenWeber <Darren.We...@radiology.ucsf.edu>
wrote:
Below is a module (matrix.py) with a class to implement some basic
matrix operations on a 2D list. Some things puzzle me about the best
way to do this (please don't refer to scipy, numpy and numeric because
this is a personal programming exercise for me in creating an
operational class in pure python for some *basic* matrix operations).

1. Please take a look at the __init__ function and comment on the
initialization of the list data with respect to unique memory
allocation.

2. In the operator overloading of __add__, __sub__, etc., the
statement isinstance(q, Matrix) raises exceptions every time. This
statement works fine outside of the class definition, but not during
the operator evaluation. What is going here?
....
>
def __add__(self, q):
'matrix addition: m3 = m1 + m2'
# if isinstance(q, Matrix):
# arg = ("q is not a matrix instance", q)
# raise TypeError, arg
Wouldn't it make more sense to raise an exception if q is NOT an
instance of Matrix?

Jun 13 '07 #2

P: n/a
On Jun 12, 6:20 pm, Dan Bishop <danb...@yahoo.comwrote:
On Jun 12, 7:31 pm, DarrenWeber <Darren.We...@radiology.ucsf.edu>
wrote:
Below is a module (matrix.py) with a class to implement some basic
matrix operations on a 2D list. Some things puzzle me about the best
way to do this (please don't refer to scipy, numpy and numeric because
this is a personal programming exercise for me in creating an
operational class in pure python for some *basic* matrix operations).
1. Please take a look at the __init__ function and comment on the
initialization of the list data with respect to unique memory
allocation.
2. In the operator overloading of __add__, __sub__, etc., the
statement isinstance(q, Matrix) raises exceptions every time. This
statement works fine outside of the class definition, but not during
the operator evaluation. What is going here?
...
def __add__(self, q):
'matrix addition: m3 = m1 + m2'
# if isinstance(q, Matrix):
# arg = ("q is not a matrix instance", q)
# raise TypeError, arg

Wouldn't it make more sense to raise an exception if q is NOT an
instance of Matrix?

Duh, yea! I don't recommend programming and sleep deprivation ;-)

Jun 13 '07 #3

This discussion thread is closed

Replies have been disabled for this discussion.