From 4a0abbfe6f6a509da8f9a8c562b3de87f82d92dc Mon Sep 17 00:00:00 2001 From: suubersnake Date: Thu, 20 Mar 2014 19:11:58 -0700 Subject: [PATCH] Projects Complete: 28 Current Project: None Latest Project: Classes/Matrix.py --Implemented Family Tree generator (non-gui, will revisit gui) --Implemented Matrix.py as a helper for matrix math. --Cleaned up all the toString code to be properly pythonic --- Classes/FamilyTree/person.py | 55 ++++++++++-- Classes/{MatrixClass.py => Matrix.py} | 123 +++++++++++++++++--------- 2 files changed, 129 insertions(+), 49 deletions(-) rename Classes/{MatrixClass.py => Matrix.py} (64%) diff --git a/Classes/FamilyTree/person.py b/Classes/FamilyTree/person.py index 031eec394..6e9ec6842 100644 --- a/Classes/FamilyTree/person.py +++ b/Classes/FamilyTree/person.py @@ -1,10 +1,11 @@ +# Need to put a graphical back end on this at some point. but for class Person(object): """ Represents a node in a family tree. Members: name -- The name of the individual - Children -- Collection of Person objects that represent the descendents. + Children -- List of Person objects that represent the descendents. birthyear -- Self explainatory. deathyear -- Self explainatory. """ @@ -13,7 +14,7 @@ def __init__(self, name, children, birthyear, deathyear): Main constructor method. """ self.name = name - if len(children) > 0: + if children is not None: for child in children: if not(isinstance(child, Person) or child is None): raise TypeError("Not a Person or None") @@ -21,12 +22,48 @@ def __init__(self, name, children, birthyear, deathyear): self.birthyear = birthyear self.deathyear = deathyear - def traverse(self): + def traverseTree(self): """ - Traverses through all descendents of this individual by returning - all children until the most recent generation. + Traverses the person's generational tree and returns a list of + references to all descendents. """ - if len(self.children) == 0: - return None - for child in self.children: - print("----" + child.traverse()) + tree = [] + tree.append(self) + if self.children is not None: + for child in self.children: + tree.extend(child.traverseTree()) + return tree + + def __str__(self): + return self.name + + +def printTree(Person): + """ + Traverses through all descendents of this individual by returning + all children until the most recent generation. + """ + if not hasattr(printTree, "depth"): + printTree.depth = 0 # How many generations into the tree we are + else: + printTree.depth += 1 + print(str(Person) + " " + str(printTree.depth)) + # Format the tree + if Person.children is not None: + for child in Person.children: + print('\t' * printTree.depth + '|___', end="") + printTree(child) + printTree.depth -= 1 + + +if __name__ == '__main__': # Our test cases + bob = Person("Bob Lawrence", None, 2000, None) + cindy = Person("Cindy Lawrence", None, 2001, None) + katie = Person("Katie Lawrence", None, 2022, None) + martin = Person("Martin Lawrence", [katie], 2002, None) + loreli = Person("Loreli Lawrence", [bob, martin, cindy], 1975, None) + tree = loreli.traverseTree() + for entry in tree: + print(entry) + print() + printTree(loreli) diff --git a/Classes/MatrixClass.py b/Classes/Matrix.py similarity index 64% rename from Classes/MatrixClass.py rename to Classes/Matrix.py index c85b77fce..840616651 100644 --- a/Classes/MatrixClass.py +++ b/Classes/Matrix.py @@ -1,9 +1,14 @@ import copy + class Matrix2D(object): """ - This works with 2 dimensional matrixes. It takes a string representation to build it. + This works with 2 dimensional matrixes. It takes a string representation + to build it. """ + # + # Constructors + # def __init__(self, values): """ Constructor. Import values from a list of lists of integers @@ -29,10 +34,52 @@ def fromstring(cls, valueString): str.strip() # Remove whitespace in each string intlist = [] for str in strings: - intlist.append([int(i) for i in str.split()]) # Ensure they're integers + intlist.append([int(i) for i in str.split()]) # Cast as integers return cls(intlist) - def add(self, Matrix): + @classmethod + def empty(cls, rows, columns): + emptyList = [[0]*columns for x in range(0, rows)] + return cls(emptyList) + + # + # Public functions + # + def transpose(self): + """ + Returns a matrix that has been transposed according to matrix math. + """ + # Transposition is a reflection upon the main diagonal (0,0 to n,n) + old = self.matrix[:] + new = [] + for y in range(0, self.columns): + new.append([]) + for x in range(0, self.rows): + new[y].append(old[x][y]) + old = None + return Matrix2D(new) + + # + # Operator Overloads + # + def __add__(self, other): + return self.__add(other) + + def __sub__(self, other): + return self.__subtract(other) + + def __mul__(self, other): + return self.__multiply(other) + + def __str__(self): + string = "" + for row in self.matrix: + string = string + "\n" + str(row) + return string + # + # "Private" methods + # + def __add(self, Matrix): """ Returns a new matrix with the added value of self and Matrix """ @@ -47,7 +94,7 @@ def add(self, Matrix): return Matrix2D(result) - def subtract(self, Matrix): + def __subtract(self, Matrix): if not isinstance(Matrix, Matrix2D): raise TypeError("Not a valid type to use with matrix") if self.rows != Matrix.rows or self.columns != Matrix.columns: @@ -59,43 +106,39 @@ def subtract(self, Matrix): return Matrix2D(result) - def __scalar(self, multiplier): + def __scalarMul(self, multiplier): new = copy.deepcopy(self.matrix) for row in new: for entry in row: entry *= multiplier return Matrix2D(new) - def multiply(self, Matrix): + def __matrixMul(self, Matrix): + """ + Multiplies matrix with self. Assumes self as NxM and + Matrix as MxP + """ + if self.columns != Matrix.rows: + raise IndexError("Invalid matrix sizes") + new = Matrix2D.empty(self.rows, Matrix.columns) + # Use general matrix math form + for column in range(0, new.columns): + for row in range(0, new.rows): + for k in range(0, self.columns): + new.matrix[row][column] = new.matrix[row][column] + (self.matrix[row][k] * Matrix.matrix[k][column]) + return new + + def __multiply(self, Matrix): + """ + Performs scalar and matrix multiplication + on this matrix + """ if isinstance(Matrix, int): - return self.__scalar(Matrix) + return self.__scalarMul(Matrix) if not isinstance(Matrix, Matrix2D): raise TypeError("Not a valid type to use with matrix") # Do matrix math stuff - return None - - def transpose(self): - """ - Returns a matrix that has been transposed according to matrix math. - """ - # Transposition is a reflection upon the main diagonal (0,0 to n,n) - # This will work for any NxM matrix - old = self.matrix[:] - new = [] - # print(old) - # print(self.matrix) - for y in range(0, self.columns): - new.append([]) - for x in range(0, self.rows): - new[y].append(old[x][y]) - old = None - return Matrix2D(new) - - def toString(self): - string = "" - for row in self.matrix: - string = string + "\n" + str(row) - return string + return self.__matrixMul(Matrix) def main(): @@ -106,15 +149,15 @@ def main(): Matrix2D.fromstring("1 2 3;4 5 6;7 8 9"), Matrix2D.fromstring("1 2 3; 4 5 6; 7 8 9"), Matrix2D.fromstring("1 1 1; 1 1 1; 1 1 1")] - print(matrixs[0].transpose().toString()) - print(matrixs[1].transpose().toString()) - print(matrixs[3].transpose().toString()) - print(matrixs[1].add(matrixs[2]).toString()) - print(matrixs[4].add(matrixs[5]).toString()) - print(matrixs[1].toString()) - print(matrixs[4].toString()) - print(matrixs[1].subtract(matrixs[2]).toString()) - print(matrixs[4].subtract(matrixs[5]).toString()) + print(matrixs[0].transpose()) + print(matrixs[1].transpose()) + print(matrixs[3].transpose()) + print((matrixs[1] + matrixs[2])) + print((matrixs[4] + matrixs[5])) + print((matrixs[1] - matrixs[2])) + print((matrixs[4] - matrixs[5])) + print((matrixs[1] * matrixs[3])) + print((matrixs[4] * matrixs[5])) # for matrix in matrixs: # print(matrix.toString())