native python matrix class (2D list), without inverse

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • DarrenWeber

    #1

    native python matrix class (2D list), without inverse


    # Copyright (C) 2007 Darren Lee Weber
    #
    # This program is free software; you can redistribute it and/or modify
    # it under the terms of the GNU General Public License as published by
    # the Free Software Foundation; either version 2 of the License, or
    # (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful, but
    # WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    # General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program; if not, write to the Free Software
    # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
    # 02111-1307, USA.

    __version__ = "$Revision: 1.9 $" # $Date: 2007/06/14 00:24:57 $

    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:
    # check data for the cell types (ensure float)?
    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.appen d([x * 0.0 for x in range(c)])
    else:
    self.data = []
    self.dim = (0,0)
    #print self.__doc__

    def __getitem__(sel f, 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.1000000000000 001]
    """
    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=(sel f.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 = matrix1 + matrix2
    m3 = matrix1 + float
    m3 = matrix1 + int
    '''
    if isinstance(q, Matrix):
    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
    elif isinstance(q, float) or isinstance(q, int):
    # add a scalar value
    m = Matrix(dim=self .dim)
    for r in range(self.dim[0]): # rows
    m.data[r] = map(lambda x: x + q, self.data[r])
    return m
    else:
    arg = ("q is not a matrix, float or int", q)
    raise TypeError, arg

    def __sub__(self, q):
    '''
    matrix subtraction:
    m3 = matrix1 - matrix2
    m3 = matrix1 - float
    m3 = matrix1 - int
    '''
    if isinstance(q, Matrix):
    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
    elif isinstance(q, float) or isinstance(q, int):
    # subtract a scalar value
    m = Matrix(dim=self .dim)
    for r in range(self.dim[0]): # rows
    m.data[r] = map(lambda x: x - q, self.data[r])
    return m
    else:
    arg = ("q is not a matrix, float or int", q)
    raise TypeError, arg

    def __mul__(self, q):
    """
    multiply two matrices:
    m = p * q # p.dim[1] == q.dim[0]

    multiply a matrix with a scalar:
    m = p * q # where q is a float or int value
    """
    if isinstance(q, Matrix):
    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=(sel f.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)
    pRowVec = self.data[r]
    qColVec = [q.data[a][c] for a in
    xrange(q.dim[0])]
    m.data[r][c] = sum(map(lambda x, y: x * y,
    pRowVec, qColVec))
    return m
    elif isinstance(q, float) or isinstance(q, int):
    # subtract a scalar value
    m = Matrix(dim=self .dim)
    for r in range(self.dim[0]): # rows
    m.data[r] = map(lambda x: x * q, self.data[r])
    return m
    else:
    arg = ("q is not a matrix, float or int", q)
    raise TypeError, arg

    def __div__(self, q):
    """
    Divide a matrix with a scalar, eg:
    m = p / q # where q is a float or int value
    This operator will not return a matrix inverse
    """
    if isinstance(q, Matrix):
    # let's not do matrix divide in python, leave the inverse
    # to a c/c++ library
    arg = ("q is a matrix: will not calculate inverse", q)
    raise TypeError, arg
    elif isinstance(q, float) or isinstance(q, int):
    # divide a scalar value
    m = Matrix(dim=self .dim)
    for r in range(self.dim[0]): # rows
    m.data[r] = map(lambda x: x / q, self.data[r])
    return m
    else:
    arg = ("q is not a matrix, float or int", q)
    raise TypeError, arg

    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(sel f, format):
    """
    print the matrix data nicely formatted, eg:
    matrix.printFor mat("%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

    testing = 0
    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
    m3 += 10.0
    m3 -= 10.0
    m3 += 10
    m3 -= 10
    m3 /= 10.0
    m3 *= 10.0
    m3 /= 10
    m3 *= 10

Working...