Skip to content

Commit

Permalink
Enable ruff ICN001 rule
Browse files Browse the repository at this point in the history
  • Loading branch information
MaximSmolskiy committed Mar 25, 2024
1 parent 102e9a3 commit a4e4b45
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 124 deletions.
38 changes: 19 additions & 19 deletions ciphers/hill_cipher.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

import string

import numpy
import numpy as np

from maths.greatest_common_divisor import greatest_common_divisor

Expand All @@ -49,11 +49,11 @@ class HillCipher:
# i.e. a total of 36 characters

# take x and return x % len(key_string)
modulus = numpy.vectorize(lambda x: x % 36)
modulus = np.vectorize(lambda x: x % 36)

to_int = numpy.vectorize(round)
to_int = np.vectorize(round)

def __init__(self, encrypt_key: numpy.ndarray) -> None:
def __init__(self, encrypt_key: np.ndarray) -> None:
"""
encrypt_key is an NxN numpy array
"""
Expand All @@ -63,7 +63,7 @@ def __init__(self, encrypt_key: numpy.ndarray) -> None:

def replace_letters(self, letter: str) -> int:
"""
>>> hill_cipher = HillCipher(numpy.array([[2, 5], [1, 6]]))
>>> hill_cipher = HillCipher(np.array([[2, 5], [1, 6]]))
>>> hill_cipher.replace_letters('T')
19
>>> hill_cipher.replace_letters('0')
Expand All @@ -73,7 +73,7 @@ def replace_letters(self, letter: str) -> int:

def replace_digits(self, num: int) -> str:
"""
>>> hill_cipher = HillCipher(numpy.array([[2, 5], [1, 6]]))
>>> hill_cipher = HillCipher(np.array([[2, 5], [1, 6]]))
>>> hill_cipher.replace_digits(19)
'T'
>>> hill_cipher.replace_digits(26)
Expand All @@ -83,10 +83,10 @@ def replace_digits(self, num: int) -> str:

def check_determinant(self) -> None:
"""
>>> hill_cipher = HillCipher(numpy.array([[2, 5], [1, 6]]))
>>> hill_cipher = HillCipher(np.array([[2, 5], [1, 6]]))
>>> hill_cipher.check_determinant()
"""
det = round(numpy.linalg.det(self.encrypt_key))
det = round(np.linalg.det(self.encrypt_key))

if det < 0:
det = det % len(self.key_string)
Expand All @@ -101,7 +101,7 @@ def check_determinant(self) -> None:

def process_text(self, text: str) -> str:
"""
>>> hill_cipher = HillCipher(numpy.array([[2, 5], [1, 6]]))
>>> hill_cipher = HillCipher(np.array([[2, 5], [1, 6]]))
>>> hill_cipher.process_text('Testing Hill Cipher')
'TESTINGHILLCIPHERR'
>>> hill_cipher.process_text('hello')
Expand All @@ -117,7 +117,7 @@ def process_text(self, text: str) -> str:

def encrypt(self, text: str) -> str:
"""
>>> hill_cipher = HillCipher(numpy.array([[2, 5], [1, 6]]))
>>> hill_cipher = HillCipher(np.array([[2, 5], [1, 6]]))
>>> hill_cipher.encrypt('testing hill cipher')
'WHXYJOLM9C6XT085LL'
>>> hill_cipher.encrypt('hello')
Expand All @@ -129,7 +129,7 @@ def encrypt(self, text: str) -> str:
for i in range(0, len(text) - self.break_key + 1, self.break_key):
batch = text[i : i + self.break_key]
vec = [self.replace_letters(char) for char in batch]
batch_vec = numpy.array([vec]).T
batch_vec = np.array([vec]).T
batch_encrypted = self.modulus(self.encrypt_key.dot(batch_vec)).T.tolist()[
0
]
Expand All @@ -140,14 +140,14 @@ def encrypt(self, text: str) -> str:

return encrypted

def make_decrypt_key(self) -> numpy.ndarray:
def make_decrypt_key(self) -> np.ndarray:
"""
>>> hill_cipher = HillCipher(numpy.array([[2, 5], [1, 6]]))
>>> hill_cipher = HillCipher(np.array([[2, 5], [1, 6]]))
>>> hill_cipher.make_decrypt_key()
array([[ 6, 25],
[ 5, 26]])
"""
det = round(numpy.linalg.det(self.encrypt_key))
det = round(np.linalg.det(self.encrypt_key))

if det < 0:
det = det % len(self.key_string)
Expand All @@ -159,15 +159,15 @@ def make_decrypt_key(self) -> numpy.ndarray:

inv_key = (
det_inv
* numpy.linalg.det(self.encrypt_key)
* numpy.linalg.inv(self.encrypt_key)
* np.linalg.det(self.encrypt_key)
* np.linalg.inv(self.encrypt_key)
)

return self.to_int(self.modulus(inv_key))

def decrypt(self, text: str) -> str:
"""
>>> hill_cipher = HillCipher(numpy.array([[2, 5], [1, 6]]))
>>> hill_cipher = HillCipher(np.array([[2, 5], [1, 6]]))
>>> hill_cipher.decrypt('WHXYJOLM9C6XT085LL')
'TESTINGHILLCIPHERR'
>>> hill_cipher.decrypt('85FF00')
Expand All @@ -180,7 +180,7 @@ def decrypt(self, text: str) -> str:
for i in range(0, len(text) - self.break_key + 1, self.break_key):
batch = text[i : i + self.break_key]
vec = [self.replace_letters(char) for char in batch]
batch_vec = numpy.array([vec]).T
batch_vec = np.array([vec]).T
batch_decrypted = self.modulus(decrypt_key.dot(batch_vec)).T.tolist()[0]
decrypted_batch = "".join(
self.replace_digits(num) for num in batch_decrypted
Expand All @@ -199,7 +199,7 @@ def main() -> None:
row = [int(x) for x in input().split()]
hill_matrix.append(row)

hc = HillCipher(numpy.array(hill_matrix))
hc = HillCipher(np.array(hill_matrix))

print("Would you like to encrypt or decrypt some text? (1 or 2)")
option = input("\n1. Encrypt\n2. Decrypt\n")
Expand Down
54 changes: 27 additions & 27 deletions fractals/julia_sets.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
from collections.abc import Callable
from typing import Any

import numpy
from matplotlib import pyplot
import matplotlib.pyplot as plt
import numpy as np

c_cauliflower = 0.25 + 0.0j
c_polynomial_1 = -0.4 + 0.6j
Expand All @@ -37,22 +37,22 @@
nb_pixels = 666


def eval_exponential(c_parameter: complex, z_values: numpy.ndarray) -> numpy.ndarray:
def eval_exponential(c_parameter: complex, z_values: np.ndarray) -> np.ndarray:
"""
Evaluate $e^z + c$.
>>> eval_exponential(0, 0)
1.0
>>> abs(eval_exponential(1, numpy.pi*1.j)) < 1e-15
>>> abs(eval_exponential(1, np.pi*1.j)) < 1e-15
True
>>> abs(eval_exponential(1.j, 0)-1-1.j) < 1e-15
True
"""
return numpy.exp(z_values) + c_parameter
return np.exp(z_values) + c_parameter


def eval_quadratic_polynomial(
c_parameter: complex, z_values: numpy.ndarray
) -> numpy.ndarray:
c_parameter: complex, z_values: np.ndarray
) -> np.ndarray:
"""
>>> eval_quadratic_polynomial(0, 2)
4
Expand All @@ -66,7 +66,7 @@ def eval_quadratic_polynomial(
return z_values * z_values + c_parameter


def prepare_grid(window_size: float, nb_pixels: int) -> numpy.ndarray:
def prepare_grid(window_size: float, nb_pixels: int) -> np.ndarray:
"""
Create a grid of complex values of size nb_pixels*nb_pixels with real and
imaginary parts ranging from -window_size to window_size (inclusive).
Expand All @@ -77,74 +77,74 @@ def prepare_grid(window_size: float, nb_pixels: int) -> numpy.ndarray:
[ 0.-1.j, 0.+0.j, 0.+1.j],
[ 1.-1.j, 1.+0.j, 1.+1.j]])
"""
x = numpy.linspace(-window_size, window_size, nb_pixels)
x = np.linspace(-window_size, window_size, nb_pixels)
x = x.reshape((nb_pixels, 1))
y = numpy.linspace(-window_size, window_size, nb_pixels)
y = np.linspace(-window_size, window_size, nb_pixels)
y = y.reshape((1, nb_pixels))
return x + 1.0j * y


def iterate_function(
eval_function: Callable[[Any, numpy.ndarray], numpy.ndarray],
eval_function: Callable[[Any, np.ndarray], np.ndarray],
function_params: Any,
nb_iterations: int,
z_0: numpy.ndarray,
z_0: np.ndarray,
infinity: float | None = None,
) -> numpy.ndarray:
) -> np.ndarray:
"""
Iterate the function "eval_function" exactly nb_iterations times.
The first argument of the function is a parameter which is contained in
function_params. The variable z_0 is an array that contains the initial
values to iterate from.
This function returns the final iterates.
>>> iterate_function(eval_quadratic_polynomial, 0, 3, numpy.array([0,1,2])).shape
>>> iterate_function(eval_quadratic_polynomial, 0, 3, np.array([0,1,2])).shape
(3,)
>>> numpy.round(iterate_function(eval_quadratic_polynomial,
>>> np.round(iterate_function(eval_quadratic_polynomial,
... 0,
... 3,
... numpy.array([0,1,2]))[0])
... np.array([0,1,2]))[0])
0j
>>> numpy.round(iterate_function(eval_quadratic_polynomial,
>>> np.round(iterate_function(eval_quadratic_polynomial,
... 0,
... 3,
... numpy.array([0,1,2]))[1])
... np.array([0,1,2]))[1])
(1+0j)
>>> numpy.round(iterate_function(eval_quadratic_polynomial,
>>> np.round(iterate_function(eval_quadratic_polynomial,
... 0,
... 3,
... numpy.array([0,1,2]))[2])
... np.array([0,1,2]))[2])
(256+0j)
"""

z_n = z_0.astype("complex64")
for _ in range(nb_iterations):
z_n = eval_function(function_params, z_n)
if infinity is not None:
numpy.nan_to_num(z_n, copy=False, nan=infinity)
z_n[abs(z_n) == numpy.inf] = infinity
np.nan_to_num(z_n, copy=False, nan=infinity)
z_n[abs(z_n) == np.inf] = infinity
return z_n


def show_results(
function_label: str,
function_params: Any,
escape_radius: float,
z_final: numpy.ndarray,
z_final: np.ndarray,
) -> None:
"""
Plots of whether the absolute value of z_final is greater than
the value of escape_radius. Adds the function_label and function_params to
the title.
>>> show_results('80', 0, 1, numpy.array([[0,1,.5],[.4,2,1.1],[.2,1,1.3]]))
>>> show_results('80', 0, 1, np.array([[0,1,.5],[.4,2,1.1],[.2,1,1.3]]))
"""

abs_z_final = (abs(z_final)).transpose()
abs_z_final[:, :] = abs_z_final[::-1, :]
pyplot.matshow(abs_z_final < escape_radius)
pyplot.title(f"Julia set of ${function_label}$, $c={function_params}$")
pyplot.show()
plt.matshow(abs_z_final < escape_radius)
plt.title(f"Julia set of ${function_label}$, $c={function_params}$")
plt.show()


def ignore_overflow_warnings() -> None:
Expand Down
34 changes: 17 additions & 17 deletions fractals/koch_snowflake.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,25 @@

from __future__ import annotations

import matplotlib.pyplot as plt # type: ignore
import numpy
import matplotlib.pyplot as plt
import numpy as np

# initial triangle of Koch snowflake
VECTOR_1 = numpy.array([0, 0])
VECTOR_2 = numpy.array([0.5, 0.8660254])
VECTOR_3 = numpy.array([1, 0])
VECTOR_1 = np.array([0, 0])
VECTOR_2 = np.array([0.5, 0.8660254])
VECTOR_3 = np.array([1, 0])
INITIAL_VECTORS = [VECTOR_1, VECTOR_2, VECTOR_3, VECTOR_1]

# uncomment for simple Koch curve instead of Koch snowflake
# INITIAL_VECTORS = [VECTOR_1, VECTOR_3]


def iterate(initial_vectors: list[numpy.ndarray], steps: int) -> list[numpy.ndarray]:
def iterate(initial_vectors: list[np.ndarray], steps: int) -> list[np.ndarray]:
"""
Go through the number of iterations determined by the argument "steps".
Be careful with high values (above 5) since the time to calculate increases
exponentially.
>>> iterate([numpy.array([0, 0]), numpy.array([1, 0])], 1)
>>> iterate([np.array([0, 0]), np.array([1, 0])], 1)
[array([0, 0]), array([0.33333333, 0. ]), array([0.5 , \
0.28867513]), array([0.66666667, 0. ]), array([1, 0])]
"""
Expand All @@ -50,13 +50,13 @@ def iterate(initial_vectors: list[numpy.ndarray], steps: int) -> list[numpy.ndar
return vectors


def iteration_step(vectors: list[numpy.ndarray]) -> list[numpy.ndarray]:
def iteration_step(vectors: list[np.ndarray]) -> list[np.ndarray]:
"""
Loops through each pair of adjacent vectors. Each line between two adjacent
vectors is divided into 4 segments by adding 3 additional vectors in-between
the original two vectors. The vector in the middle is constructed through a
60 degree rotation so it is bent outwards.
>>> iteration_step([numpy.array([0, 0]), numpy.array([1, 0])])
>>> iteration_step([np.array([0, 0]), np.array([1, 0])])
[array([0, 0]), array([0.33333333, 0. ]), array([0.5 , \
0.28867513]), array([0.66666667, 0. ]), array([1, 0])]
"""
Expand All @@ -74,22 +74,22 @@ def iteration_step(vectors: list[numpy.ndarray]) -> list[numpy.ndarray]:
return new_vectors


def rotate(vector: numpy.ndarray, angle_in_degrees: float) -> numpy.ndarray:
def rotate(vector: np.ndarray, angle_in_degrees: float) -> np.ndarray:
"""
Standard rotation of a 2D vector with a rotation matrix
(see https://en.wikipedia.org/wiki/Rotation_matrix )
>>> rotate(numpy.array([1, 0]), 60)
>>> rotate(np.array([1, 0]), 60)
array([0.5 , 0.8660254])
>>> rotate(numpy.array([1, 0]), 90)
>>> rotate(np.array([1, 0]), 90)
array([6.123234e-17, 1.000000e+00])
"""
theta = numpy.radians(angle_in_degrees)
c, s = numpy.cos(theta), numpy.sin(theta)
rotation_matrix = numpy.array(((c, -s), (s, c)))
return numpy.dot(rotation_matrix, vector)
theta = np.radians(angle_in_degrees)
c, s = np.cos(theta), np.sin(theta)
rotation_matrix = np.array(((c, -s), (s, c)))
return np.dot(rotation_matrix, vector)


def plot(vectors: list[numpy.ndarray]) -> None:
def plot(vectors: list[np.ndarray]) -> None:
"""
Utility function to plot the vectors using matplotlib.pyplot
No doctest was implemented since this function does not have a return value
Expand Down
2 changes: 1 addition & 1 deletion graphics/bezier_curve.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def plot_curve(self, step_size: float = 0.01):
step_size: defines the step(s) at which to evaluate the Bezier curve.
The smaller the step size, the finer the curve produced.
"""
from matplotlib import pyplot as plt # type: ignore
from matplotlib import pyplot as plt

to_plot_x: list[float] = [] # x coordinates of points to plot
to_plot_y: list[float] = [] # y coordinates of points to plot
Expand Down
4 changes: 2 additions & 2 deletions machine_learning/gradient_descent.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
function.
"""

import numpy
import numpy as np

# List of input, output pairs
train_data = (
Expand Down Expand Up @@ -116,7 +116,7 @@ def run_gradient_descent():
temp_parameter_vector[i] = (
parameter_vector[i] - LEARNING_RATE * cost_derivative
)
if numpy.allclose(
if np.allclose(
parameter_vector,
temp_parameter_vector,
atol=absolute_error_limit,
Expand Down
Loading

0 comments on commit a4e4b45

Please sign in to comment.