Closed at 2pm Monday 20th; I can't accept late submissions unfortunately.
For Assignment 7, due 2 pm Monday, beware not to overcomplicate things and avoid premature optimization.
def findPi(n_points):
rs = numpy.random.uniform(0, 1, size=(n_points,2))
return 4 * np.sum(np.linalg.norm(rs, axis = 1) < 1)/n_points
def integrate(n_points, dim):
rs = numpy.random.uniform(-1, 1, size=(n_points,dim))
return np.sum(np.linalg.norm(rs, axis = 1) < 1)/n_points * 2**dim]]
def integrate(n_points, dim, chunk_size=1000000):
# If less than 1,000,000 points operate in one go
if n_points <= chunk_size:
rs = np.random.uniform(-1, 1, size=(n_points, dim))
return np.sum(np.linalg.norm(rs, axis=1) < 1) / n_points * 2**dim
# Else do a for loop of 1,000,000 points at a time
total_sum = 0
num_chunks = int(np.ceil(n_points / chunk_size))
for i in range(num_chunks):
remaining_points = min(chunk_size, n_points - i * chunk_size)
rs = np.random.uniform(-1, 1, size=(remaining_points, dim))
# Add to the total sum here
total_sum += np.sum(np.linalg.norm(rs, axis=1) < 1)
return total_sum / n_points * 2**dim
Systems Modeling: OOP is beneficial for modeling complex systems with numerous interacting components, such as simulations of physical phenomena where entities can be modeled as objects.
Code Reusability and Extensibility: In projects where you'll be building upon existing models or simulations, OOP allows for easier extension and modification of code through inheritance and polymorphism.
Not better or worse but another approach / tool.
As is tradition, we'll use cats to explain OOP.
__init__
All python classess need the '__init__' constructor.
This constructor initializes a new cat instance with attributes like name, color, and age.
class Cat: def __init__(self, name, color, age): self.name = name self.color = color self.age = age newCat = Cat('larry', 'black', 3) print(newCat.name) # larry
Methods allow interaction with cat instances, such as making them meow or jump.
class Cat: # ... def meow(self): return "Meow!" def jump(self, height): return f"Jumps {height} feet high!" print(newCat.meow()) print(newCat.jump(3)) # Meow! # Jumps 3 feet high!
__str__
and __repr__
Explaining __str__
for user-friendly description and __repr__
for detailed developer view.
class Cat: # ... def __str__(self): return f"{self.name}, the {self.color} cat" def __repr__(self): return f"Cat('{self.name}', '{self.color}', {self.age})" print(newCat) print(repr(newCat)) # larry, the black cat # Cat('larry', 'black', 3)
Illustrating inheritance with different cat breeds. A base Cat
class and derived classes like Siamese
or Persian
.
class Siamese(Cat): def purr(self): return "Loud purring" class Persian(Cat): def fluff(self): return "Maximum fluffiness" sia = Siamese('Whiskers', 'grey', 4) print(sia.meow()) print(sia.purr()) # Meow! # Loud purring
The __del__
destructor method is called when an instance is about to be destroyed. Though not commonly used, it's helpful for clean-up activities.
Operator overloading, using methods like __add__
, allows custom behavior for Python's built-in operators. For example, adding two cat instances could combine their attributes.
class Cat: # ... def __del__(self): print(f"{self.name} says goodbye!") def __add__(self, other): return Cat(f"{self.name} & {other.name}", self.color, max(self.age, other.age)) cat1 = Cat('Luna', 'grey', 2) cat2 = Cat('Milo', 'brown', 4) newCat = cat1 + cat2 print(newCat) # Cat('Luna & Milo', 'grey', 4)
import numpy
points = [ [1, 2], [4,-2] ]
angle = numpy.pi/4
def rotate(points, angle):
cos = numpy.cos(angle)
sin = numpy.sin(angle)
rotated = []
for x,y in points:
newx = cos * x - sin * y
newy = sin * x + cos * y
rotated.append( [newx, newy] )
return rotated
rotate(points, angle)
[[-0.7071067811865474, 2.121320343559643], [4.242640687119286, 1.4142135623730947]]
Point
class definition¶class Point():
def __init__(self, x, y):
self.x = x
self.y = y
def rotate_by(self, angle):
cos = numpy.cos(angle)
sin = numpy.sin(angle)
newx = cos * self.x - sin * self.y
newy = sin * self.x + cos * self.y
self.x = newx
self.y = newy
def __str__(self):
return "({},{})".format(self.x, self.y)
def __repr__(self):
return "Point({},{})".format(self.x, self.y)
points = [ Point(1,2), Point(4,-2) ]
angle = numpy.pi/4
for p in points:
p.rotate_by(angle)
points
[Point(-0.7071067811865474,2.121320343559643), Point(4.242640687119286,1.4142135623730947)]