CECS 229 Programming Assignment #4

Submission Instructions:

To receive credit for this assignment, you must submit to CodePost this file converted to a Python script named pa4.py

Objectives:

Apply vector operations to translate, scale, and rotate a set of points representing an image.

Perform various operations with or on vectors: addition, subtraction, dot product, norm.

Needed Import Statements

# MAKE SURE TO RUN THIS CELL BEFORE RUNNING ANY TESTER CELLS

“””

In order for the import statements below to work, you must download and save

the plotting.py and image.py files to the same folder where this file is located.

“””

import cmath # Mathematical functions to be used on complex numbers

import math

from plotting import plot

import image

Problem 1:

Create a function translate(S, z0) that translates the points in the input set S

by z0=a0+b0i

. The function should satisfy the following:

INPUT:

S – set S

z0 – complex number

OUTPUT:

a set consisting of points in S translated by z0

# Writing a function to translate a set of complex numbers in the form of z_0 = a_0 + b_0i

def translate(S, z0):

“””

translates the complex numbers of set S by z0

INPUT:

* S – set of complex numbers

* z0 – complex number

OUT:

* a set consisting of points in S translated by z0

“””

# Checks if the input ‘z0’ is a complex number

if type(z0) != complex:

raise TypeError(“the ‘z0’ input has to a complex number”)

else: # Runs the code below once the basic requirements are met

# Creating a list to store the translated complex numbers

complex_number_list = []

# Iterating through the set ‘S’

for i in S:

# “Translating” each complex number in the set ‘S’ by ‘z0′ thru addition

translation_sum = i + z0

# Appending the translated complex number to the list

complex_number_list.append(translation_sum)

# Converting the list to a set

translated_set = set(complex_number_list)

return translated_set # Returning the translated set

“””

TESTER CELL #1 FOR translate()

“””

”’

S = {2 + 2j, 3 + 2j , 1.75 + 1j, 2 + 1j, 2.25 + 1j, 2.5 + 1j, 2.75 + 1j, 3 + 1j, 3.25 + 1j}

print(“ORIGINAL VALUES:”, S)

plot([(S, ‘black’)], 10, title = “Original Values”) # original values will be plotted in black

T1 = translate(S, -3-2j) # values translated by -3-2i will be plotted in red

T2 = translate(S, 3-2j) # values translated by 3-2i will be plotted in green

T3 = translate(S, -3+2j) # values translated by -3+2i will be plotted in orange

T4 = translate(S, 3+2j) # values translated by 3+2i will be plotted in blue

print(“SHIFT LEFT 3, DOWN 2:”, T1)

print(“Expected: {0j, (-0.25-1j), (-1+0j), -1j, (-1-1j), (-1.25-1j), (-0.75-1j), (0.25-1j), (-0.5-1j)}\n”)

print(“\nSHIFT RIGHT 3, DOWN 2:”, T2)

print(“Expected: {(6-1j), (6.25-1j), (5+0j), (6+0j), (5-1j), (5.75-1j), (5.5-1j), (4.75-1j), (5.25-1j)}\n”)

print(“\nSHIFT LEFT 3, UP 2:”, T3)

print(“Expected: {(-1+3j), (-1.25+3j), (-0.75+3j), (-1+4j), (-0.5+3j), 4j, (-0.25+3j), 3j, (0.25+3j)}\n”)

print(“\nSHIFT RIGHT 3, UP 2:”, T4)

print(“Expected: {(4.75+3j), (5.5+3j), (5.25+3j), (5+3j), (5+4j), (6+4j), (5.75+3j), (6+3j), (6.25+3j)}\n”)

# plotting original values against translated values

plot([(S, ‘black’), (T1, ‘red’), (T2, ‘green’), (T3, ‘orange’), (T4, ‘blue’)], 10, title = “Original + Shifted Values”)

”’

“””

TESTER CELL #2 FOR translate()

“””

”’

img = image.file2image(‘img01.png’)

gray_img = image.color2gray(img)

complex_img = image.gray2complex(gray_img)

translated_img = translate(complex_img, -200 + 0j)

plot([(complex_img, ‘black’)], 200, title = “Original Image”)

plot([(translated_img, ‘black’)], 200, title = “Translated Image”)

”’

Problem 2:

Create a function scale(S, k) that scales the points in the input set S

by a factor of k

:

INPUT:

S – set S

k – positive float, raises ValueError if k ≤

0.

OUTPUT:

a set consisting of points in S scaled by k

.

# Writing a function to scale a set of complex numbers in the form of z_0 = a_0 + b_0i

def scale(S, k: float):

“””

scales the complex numbers of set S by k.

INPUT:

* S – set of complex numbers

* k – positive float, raises ValueError if k <= 0

OUT:

* T – set consisting of points in S scaled by k

“””

# Conditional statement to check if k is a positive float

if k <= 0:

raise ValueError(“K is less than or equal to 0; K has to be greater than 0”)

else: # Runs the following code once the basic requirements are met

# Creating a list to store the scaled complex numbers

complex_number_list = []

# Iterating through the set ‘S’

for i in S:

# “Scaling” each complex number in the set ‘S’ by ‘k’ thru multiplication

scaled_number = i * k

# Appending the scaled complex number to the list

complex_number_list.append(scaled_number)

# Converting the list to a set

scaled_set = set(complex_number_list)

return scaled_set # Returning the scaled set

“””

TESTER CELL #1 FOR scale()

“””

”’

S = {2 + 2j, 3 + 2j , 1.75 + 1j, 2 + 1j, 2.25 + 1j, 2.5 + 1j, 2.75 + 1j, 3 + 1j, 3.25 + 1j}

T1 = translate(S, -3-2j) # values translated by -3-2i will be plotted in red

T2 = translate(S, 3-2j) # values translated by 3-2i will be plotted in green

T3 = translate(S, -3+2j) # values translated by -3+2i will be plotted in orange

T4 = translate(S, 3+2j) # values translated by 3+2i will be plotted in blue

sets = [S, T1, T2, T3, T4]

scaled_sets = [scale(A, 2) for A in sets]

for i in range(len(scaled_sets)):

print(“Original Set:”, sets[i])

print(“After Scaling by 2:”, scaled_sets[i], “\n”)

plot([(S, ‘black’)], 10, title = “Original Values”)

plot_data = list(zip(scaled_sets, [‘black’, ‘red’, ‘green’, ‘orange’, ‘blue’]))

plot(plot_data, 10, title = “Scaled by 2″) #second parameter affects window size

”’

“””

TESTER CELL #2 FOR scale()

“””

”’

img = image.file2image(‘img01.png’)

gray_img = image.color2gray(img)

complex_img = image.gray2complex(gray_img)

scaled_img = scale(complex_img, 1.5)

plot([(complex_img, ‘black’)], 200, title = “Original Image”)

plot([(scaled_img, ‘black’)], 200, title = “Image Scaled 1.5x”)

”’

Problem 3:

Create a function rotate(S, theta) that rotates the points in the input set S

by θ

radians:

INPUT:

S – set S

theta – float. If negative, the rotation is clockwise. If positive the rotation is counterclockwise. If zero, no rotation.

OUT:

a set consisting of points in S rotated by θ

# Writing a function that rotates a set of complex numbers by ‘theta’ radians

def rotate(S, theta: float):

“””

rotates the complex numbers of set S by theta radians.

INPUT:

* S – set of complex numbers

* theta – float. If negative, the rotation is clockwise. If positive the rotation is counterclockwise. If zero, no rotation.

OUT:

* a set consisting of points in S rotated by theta radians

“””

# Creating a list to store the rotated complex numbers

complex_number_list = []

# Conditional statement to lead outcomes based on the value of ‘theta’

if theta < 0 or theta > 0: # if theta is negative/positive, the rotation is clockwise/counterclockwise

# Going through each complex number in the set ‘S’

for i in S:

# Finding the polar form of each complex number in the set ‘S’

i = abs(i) * cmath.exp((cmath.phase(i)) * 1j) # i = r * e^(θj), where r = abs(i) and θ = cmath.phase(i)

# Rotating each complex number in the set ‘S’ by ‘theta’ radians

rotated_complex_number = i * cmath.exp(theta * 1j) # rotated_number = i * e^(θj), where θ = theta(number of radians to rotate by)

# Rounding the real and imaginary parts of the rotated complex number to five decimal places

rotated_complex_number = round(rotated_complex_number.real, 5) + round(rotated_complex_number.imag, 5) * 1j

# Appending the rotated complex number to the list

complex_number_list.append(rotated_complex_number)

else: # If theta is zero, no rotation is done

# Going through each complex number in the set ‘S’

for i in S:

# Appending the complex number to the list as it is

complex_number_list.append(i)

# Converting the list to a set

rotated_set = set(complex_number_list)

return rotated_set # Returning the rotated set

“””

TESTER CELL #1 FOR rotate()

“””

”’

S = {2 + 2j, 3 + 2j , 1.75 + 1j, 2 + 1j, 2.25 + 1j, 2.5 + 1j, 2.75 + 1j, 3 + 1j, 3.25 + 1j}

T1 = translate(S, -3-2j) # values translated by -3-2i will be plotted in red

T2 = translate(S, 3-2j) # values translated by 3-2i will be plotted in green

T3 = translate(S, -3+2j) # values translated by -3+2i will be plotted in orange

T4 = translate(S, 3+2j) # values translated by 3+2i will be plotted in blue

sets = [S, T1, T2, T3, T4]

rotated_sets = [rotate(A, math.pi/2) for A in sets]

for i in range(len(rotated_sets)):

print(“Original Set:”, sets[i])

print(“After Scaling by 2:”, rotated_sets[i], “\n”)

plot_data_rot = list(zip(rotated_sets, [‘black’, ‘red’, ‘green’, ‘orange’, ‘blue’]))

plot(plot_data_rot, 10, title = “Rotated by 90 degrees”) #second parameter affects window size

rotated_sets_2 = [rotate(A, -1*math.pi/2) for A in sets]

for i in range(len(rotated_sets_2)):

print(“Original Set:”, sets[i])

print(“After Scaling by 2:”, rotated_sets_2[i], “\n”)

plot([(S, ‘black’), (T1, ‘red’), (T2, ‘green’), (T3, ‘orange’), (T4, ‘blue’)], 10, title = “Original Values”)

plot_data_rot_2 = list(zip(rotated_sets_2, [‘black’, ‘red’, ‘green’, ‘orange’, ‘blue’]))

plot(plot_data_rot_2, 10, title = “Rotated by -90 degrees”) #second parameter affects window size

”’

“””

TESTER CELL #2 FOR rotate()

“””

”’

img = image.file2image(‘img01.png’)

gray_img = image.color2gray(img)

complex_img = image.gray2complex(gray_img)

rotated_img = rotate(complex_img, -1 * math.pi/2)

plot([(complex_img, ‘black’)], 200, title = “Original Image”)

plot([(rotated_img, ‘black’)], 200, title = “Image Rotated by -90 degrees”)

”’

“””

Full image transformation = rotation + scaling + translation

“””

”’

img = image.file2image(‘img01.png’)

gray_img = image.color2gray(img)

complex_img = image.gray2complex(gray_img)

rotated_img = rotate(complex_img, -1*math.pi/2)

scaled_img = scale(rotated_img, 1.5)

translated_img = translate(scaled_img, -125 + 150j)

plot([(complex_img, ‘black’)], 200, title = “Original Image”)

plot([(translated_img, ‘black’)], 200, title = “Transformed Image”)

”’

Problem 4:

Finish the implementation of class Vec which instantiates row-vector objects with defined operations of addition, subtraction, scalar multiplication, and dot product. In addition, Vec class overloads the Python built-in function abs() so that when it is called on a Vec object, it returns the Euclidean norm of the vector.

class Vec:

def __init__(self, contents = []):

“””

Constructor defaults to empty vector

INPUT: list of elements to initialize a vector object, defaults to empty list

“””

self.elements = contents

return

def __abs__(self):

“””

Overloads the built-in function abs(v)

returns the Euclidean norm of vector v

“””

# Variable to store the magnitude of the vector

magnitude_vector = 0

# Variable to store the sum of the squares of the elements in the vector

vector_squares = []

# Running through all the elements in the vector

for element in self.elements:

# Squaring the elements of the vector

sum_of_squares = element ** 2

# Appending the sum of the squares to the list

vector_squares.append(sum_of_squares)

# Square root of the sum of the squares of the elements in the vector

magnitude_vector = math.sqrt(sum(vector_squares))

return magnitude_vector # Returning the magnitude of the vector

def __add__(self, other):

“””Overloads the + operator to support Vec + Vec

raises ValueError if vectors are not same length

“””

# Conditional Statement to check whether vectors are of same length

if len(self.elements) != len(other.elements):

raise ValueError(“Vectors must be same length”)

else: # Run the following code once the condition is satisfied

# Variable to store the sum of the vectors

vector_sum = []

# Running through all the elements in the vector

for element in range(len(self.elements)):

# Adding the elements of the vectors together

sum_result = self.elements[element] + other.elements[element]

# Appending the sum of the elements to the list

vector_sum.append(sum_result)

# Converting the list to a vector

vector_sum = Vec(vector_sum)

return vector_sum # Returning the sum of the vectors

def __sub__(self, other):

“””

Overloads the – operator to support Vec – Vec

Raises a ValueError if the lengths of both Vec objects are not the same

“””

# Conditional Statement to check whether vectors are of same length

if len(self.elements) != len(other.elements):

raise ValueError(“Vectors must be same length”)

else: # Run the following code once the condition is satisfied

# Variable to store the difference of the vectors

vector_difference = []

# Running through all the elements in the vector

for element in range(len(self.elements)):

# Subtracting the elements of the vectors together

difference_result = self.elements[element] – other.elements[element]

# Appending the difference of the elements to the list

vector_difference.append(difference_result)

# Converting the list to a vector

vector_difference = Vec(vector_difference)

return vector_difference # Returning the difference of the vectors

def __mul__(self, other):

“””Overloads the * operator to support

– Vec * Vec (dot product) raises ValueError if vectors are not same length in the case of dot product

– Vec * float (component-wise product)

– Vec * int (component-wise product)

“””

if type(other) == Vec: #define dot product

# Conditional Statement to check whether vectors are of same length

if len(self.elements) != len(other.elements):

raise ValueError(“Vectors must be same length”)

else: # Run the following code once the condition is satisfied

# Variable to store the dot product of the vectors

dot_product = 0

# Running through all the elements in the vector

for element in range(len(self.elements)):

# Multiplying the elements of the vectors each other

product_result = self.elements[element] * other.elements[element]

# Adding the product of the elements to the variable

dot_product += product_result

return dot_product # Returning the dot product

elif type(other) == float or type(other) == int: #scalar-vector multiplication

# Variable to store the result of scalar-vector multiplication

vector_product = []

# Running a loop through all the elements in the vector

for element in range(len(self.elements)):

# Multiplying the each elements in the vector to the scalar value

product_result = self.elements[element] * other

# Appending the product of the elements to the list

vector_product.append(product_result)

# Converting the list to a vector

vector_product = Vec(vector_product)

return vector_product # Returning the scalar-vector multiplication

def __rmul__(self, other):

“””

Overloads the * operation to support

– float * Vec

– int * Vec

“””

# Variable to store another version of scalar-vector multiplication

vector_product = []

# Running a loop through all the elements in the vector

for element in range(len(self.elements)):

# Multiplying the each elements in the vector to the scalar value

product_result = self.elements[element] * other

# Appending the product of the elements to the list

vector_product.append(product_result)

# Converting the list to a vector

vector_product = Vec(vector_product)

return vector_product # Returning the scalar-vector multiplication

def __str__(self):

“””returns string representation of this Vec object”””

return str(self.elements) # does NOT need further implementation

“””———————-TESTER CELL———————-“””

”’

u = Vec([1, 2, 3])

w = Vec([0, 1, -1])

v = Vec([0, -3])

print(“u = “, u)

print(“w = “, w)

print(“\nEuclidean norm of u:”, abs(u))

print(“Expected:”, math.sqrt(sum([ui**2 for ui in u.elements])))

print(“\nEuclidean norm of v:”, abs(v))

print(“Expected: 3.0”)

print(“\nu left scalar multiplication by 2:”, 2*u)

print(“Expected: [2, 4, 6]”)

print(“\nw right scalar multiplication by -1:”, w * -1)

print(“Expected: [0, -1, 1]”)

print(“\nVector addition:”, u + w)

print(“Expected: [1, 3, 2]”)

print(“\nVector addition:”, u – w)

print(“Expected: [1, 1, 4]”)

print(“\nDot product:”, w*u)

print(“Expected: -1″)

”’

”’

try:

print(“\nDot product:”, v*u)

print(“If this line prints, you forgot to raise a ValueError for taking the dot product of vectors of different lengths”)

except:

print(“If this line prints, an error was correctly raised.”)

”’

u = [1, 2, 3]

w = [0, 1, -1]

Euclidean norm of u: 3.7416573867739413

Expected: 3.7416573867739413

Euclidean norm of v: 3.0

Expected: 3.0

u left scalar multiplication by 2: None

Expected: [2, 4, 6]

w right scalar multiplication by -1: [0, -1, 1]

Expected: [0, -1, 1]

Vector addition: [1, 3, 2]

Expected: [1, 3, 2]

Vector addition: [1, 1, 4]

Expected: [1, 1, 4]

Dot product: -1

Expected: -1

‘\ntry:\n print(“\nDot product:”, v*u)\n print(“If this line prints, you forgot to raise a ValueError for taking the dot product of vectors of different lengths”)\nexcept:\n print(“If this line prints, an error was correctly raised.”)\n’