There are a number of ways to organize the data for the Matrix ADT, but the most obvious is with the use of a two-dimensional array or rectangular grid. Having defined and implemented the Array2D abstract data type in the previous section, we can utilize it to implement the Matrix ADT.
The Constructor
A Matrix
object only requires one data field for storing the 2-D array. After creating the array, its elements must be set to zero as specified by the definition of the Matrix ADT. The constructor is provided below:
class Matrix :
def __init__(self, numRows, numCols) :
self._theGrid = Array2D(numRows, numCols)
self._theGrid.clear(0)
Matrix Size
The numRows
and numCols
methods are straightforward. They need only return the length of the corresponding dimension of the 2-D array.
def numRows(self) :
return self._theGrid.numRows()
def numCols(self) :
return self._theGrid.numCols()
Element Access
The element access methods are also rather simple as they need only call the corresponding method from the Array2D
class.
def __getitem__(self, ndxTuple) :
return self._theGrid[ ndxTuple[0], ndxTuple[1] ]
def __setitem__(self, ndxTuple, scalar) :
self._theGrid[ ndxTuple[0], ndxTuple[1] ] = scalar
Note that we do not check for valid indices in these methods even though it is a precondition as defined by the Matrix ADT. The validation of the precondition is omitted here since we know the corresponding methods of the Array2D
class have the same preconditions and they are verified by that class. If this were not the case, we would have to validate the indices and raise an exception directly within the methods of the Matrix
class.
Arithmetic Operations
The scaling matrix operation involves multiplying each element in the matrix by the given scalar value. The Matrix ADT calls for this operation to modify the matrix on which it is applied instead of creating a new matrix resulting from the multiplication. The scaleBy
method is provided below:
def scaleBy(self, scalar) :
for r in range( self.numRows() ) :
for c in range( self.numCols() ) :
self[r, c] *= scalar
The matrix add operation, on the other hand, creates and returns a new Matrix
object that is the result of adding the two given matrices.
def __add__(self, rhsMatrix) :
assert (rhsMatrix.numRows() == self.numRows() and
rhsMatrix.numCols() == self.numCols()), \
"Matrix sizes not compatible for the add operation."
newMatrix = Matrix(self.numRows(), self.numCols())
for r in range(self.numRows()) :
for c in range(self.numCols()) :
newMatrix[r, c] = self[r, c] + rhsMatrix[r, c]
return newMatrix
The first step is to ensure the two matrices are the same size as required by the rules of matrix addition. After verifying the sizes, a new Matrix
object is created and its elements set by iterating over and summing the corresponding elements from the two sources. The new matrix resulting from this operation is then returned. The implementation of the remaining methods, which are left as an exercise, can be done in a similar fashion.
The implementation of the Matrix
class is provided in listing below:
Program Listing
# Implementation of the Matrix ADT using a 2-D array.
from ezarrays import Array2D
class Matrix :
# Creates a matrix of size numRows x numCols initialized to 0.
def __init__(self, numRows, numCols) :
self._theGrid = Array2D(numRows, numCols)
self._theGrid.clear(0)
# Returns the number of rows in the matrix.
def numRows(self) :
return self._theGrid.numRows()
# Returns the number of columns in the matrix.
def numCols(self) :
return self._theGrid.numCols()
# Returns the value of element (i, j): x[i,j]
def __getitem__(self, ndxTuple) :
return self._theGrid[ ndxTuple[0], ndxTuple[1] ]
# Sets the value of element (i,j) to the value s: x[i,j] = s
def __setitem__(self, ndxTuple, scalar) :
self._theGrid[ ndxTuple[0], ndxTuple[1] ] = scalar
# Scales the matrix by the given scalar.
def scaleBy(self, scalar) :
for r in range( self.numRows() ) :
for c in range( self.numCols() ) :
self[ r, c ] *= scalar
# Creates and returns a new matrix that results from matrix addition.
def __add__(self, rhsMatrix) :
assert (rhsMatrix.numRows() == self.numRows() and
rhsMatrix.numCols() == self.numCols()), \
"Matrix sizes not compatible for the add operation."
# Create the new matrix.
newMatrix = Matrix(self.numRows(), self.numCols())
# Add the corresponding elements in the two matrices.
for r in range(self.numRows()) :
for c in range(self.numCols()) :
newMatrix[ r, c ] = self[ r, c ] + rhsMatrix[ r, c ]
return newMatrix
# --- The remaining methods go here. ---
|