Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions Population Growth.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,152 @@
"Using the above math plus your matrix library, calculate how many drakes of each age I will have in 20 2-year cycles."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from matrix_math import ShapeException, Vector, Matrix"
]
},
{
"cell_type": "code",
"execution_count": 77,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"leslie = Matrix([[0, 0.25, 0.6, 0.8, 0.15, 0], [0.7, 0, 0, 0, 0, 0], [0, 0.95, 0, 0, 0, 0], \\\n",
" [0, 0, 0.9, 0, 0, 0], [0, 0, 0, 0.9, 0, 0], [0, 0, 0, 0, 0.5, 0]])"
]
},
{
"cell_type": "code",
"execution_count": 78,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[[0, 0.25, 0.6, 0.8, 0.15, 0], [0.7, 0, 0, 0, 0, 0], [0, 0.95, 0, 0, 0, 0], [0, 0, 0.9, 0, 0, 0], [0, 0, 0, 0.9, 0, 0], [0, 0, 0, 0, 0.5, 0]]\n"
]
}
],
"source": [
"print(leslie.values)"
]
},
{
"cell_type": "code",
"execution_count": 79,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"dragons = Vector([10, 0, 0, 0, 0, 0])"
]
},
{
"cell_type": "code",
"execution_count": 80,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"for i in range(20):\n",
" dragons = leslie * dragons"
]
},
{
"cell_type": "code",
"execution_count": 81,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[6.149914942919132, 4.182186803339321, 3.8477209681295763, 3.283445777563774, 2.841646230444824, 1.4082839376892242]\n"
]
}
],
"source": [
"print(dragons.values)"
]
},
{
"cell_type": "code",
"execution_count": 82,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"test = Matrix([[.25, .5],[0, .95]])"
]
},
{
"cell_type": "code",
"execution_count": 83,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"leslie20 = leslie"
]
},
{
"cell_type": "code",
"execution_count": 84,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[[0.6407182838330322, 0.9533865528483813, 0.8694631478701617, 0.5726496552122178, 0.09224872414378701, 0.0], [0.4304940460043394, 0.6407182838330322, 0.589207447887139, 0.38925308434056616, 0.06273280205008984, 0.0], [0.3973077463172356, 0.5842419195773176, 0.5361636137495489, 0.35706936411382273, 0.05771581452194364, 0.0], [0.34629488713166195, 0.5108242452650171, 0.4623621114070214, 0.3053003556617743, 0.04925168666345661, 0.0], [0.2955101199807398, 0.445236283454994, 0.4061729376245585, 0.265355364753195, 0.042624693456672365, 0.0], [0.1420823115222412, 0.21107865712909984, 0.19694480404940706, 0.13093009099881617, 0.021124259065338366, 0.0]]\n"
]
}
],
"source": [
"for _ in range(20):\n",
" leslie20 *= leslie\n",
"print(leslie20.values)"
]
},
{
"cell_type": "code",
"execution_count": 89,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[6.407182838330322, 4.304940460043394, 3.973077463172356, 3.4629488713166197, 2.9551011998073977, 1.420823115222412]\n"
]
}
],
"source": [
"print((leslie20 * Vector([10,0,0,0,0,0])).values)"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down
177 changes: 177 additions & 0 deletions matrix_math.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import math


class ShapeException(Exception):
pass


class Vector:

def __init__(self, values):
self.values = self.is_vector(values)

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

@property
def shape(self):
return len(self.values),

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

def __eq__(self, other):
return self.values == other.values

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

def __add__(self, other):
if self.shape != other.shape:
raise ShapeException()
else:
return Vector([self.values[index] + other.values[index]
for index in range(len(self.values))])

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

def __sub__(self, other):
if self.shape != other.shape:
raise ShapeException()

else:
return Vector([self.values[index] - other.values[index]
for index in range(len(self.values))])

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

def __mul__(self, other):
if isinstance(other, Matrix):
return Vector([self.dot(Vector(row)) for row in other.values])
else:
return Vector([self.values[index] * other
for index in range(len(self.values))])

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

def dot(self, other):
"""takes the dot product of the vector and another vector"""
if self.shape != other.shape:
raise ShapeException()
else:
return sum([self.values[index] * other.values[index]
for index in range(len(self.values))])

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

def mag(self):
"""Returns the magnitude of the vector"""
return math.sqrt(sum([coefficient ** 2
for coefficient in self.values]))

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

def is_vector(self, a_list):
"""Checks to ensure the vector is initialized with a list of numbers"""
if type(a_list) != list:
raise ValueError(
"Must make Vector with numerical list")
else:
for item in a_list:
if not isinstance(item, (int, float)):
raise ValueError(
"Must make Vector with numerical list")
return a_list


###############################################################################


class Matrix:

def __init__(self, values):
self.values = self.is_matrix(values)

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

@property
def shape(self):
return len(self.values), len(self.values[0])

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

def __eq__(self, other):
return self.values == other.values

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

def __add__(self, other):
if self.shape != other.shape:
raise ShapeException()
else:
return Matrix([[self.values[row][index] + other.values[row][index]
for index in range(len(self.values[0]))]
for row in range(len(self.values))])

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

def __sub__(self, other):
if self.shape != other.shape:
raise ShapeException()
else:
return Matrix([[self.values[row][index] - other.values[row][index]
for index in range(len(self.values[0]))]
for row in range(len(self.values))])

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

def __mul__(self, other):
"""Checks if the matrix is being multiplied by a scalar, vector,
or other matrix and performs the corresponding operation."""
if isinstance(other, (int, float)):
return Matrix([[self.values[row][index] * other
for index in range(len(self.values[0]))]
for row in range(len(self.values))])

elif isinstance(other, Vector):
return Vector([other.dot(Vector(row)) for row in self.values])

elif isinstance(other, Matrix):
return Matrix([(other.transpose() * Vector(row)).values
for row in self.values])

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

def transpose(self):
"""Returns a matrix where the rows and columns of the current matrix
have been transposed"""
return Matrix([[row[index]
for row in self.values]
for index in range(len(self.values[0]))])

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

def is_matrix(self, a_list):
"""Checks to ensure the matrix is initialized with a list of
lists of numbers"""
if type(a_list) != list:
raise ValueError(
"Must make Matrix w/list of numerical lists")
else:
for index in range(len(a_list)):
if type(a_list[index]) != list or \
len(a_list[index]) != len(a_list[(index - 1)]):
raise ValueError(
"Must make Matrix w/list of numerical lists")
else:
for value in a_list[index]:
if not isinstance(value, (int, float)):
raise ValueError(
"Must make Matrix w/list of numerical lists")
return a_list

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

@classmethod
def from_function(cls, rows, columns, function):
"""Allows creation of a matrix from the number of rows, number of
columns, and an identity function."""
return cls([[function(x, y) for y in range(columns)]
for x in range(rows)])
Loading