ADA-Python / algorithms /math_tools.py
ussu321's picture
Upload 50 files
bd86de0 verified
Raw
History Blame Contribute Delete
9.62 kB
"""
USSU Algorithm Analyzer v4.0 - Mathematical Tools Suite
Number theory, matrix ops, combinatorics, and complexity utilities.
"""
import math
import random
from typing import List, Tuple, Dict, Any
from utils.core import profile_algorithm, OperationCounter
class MathTools(OperationCounter):
"""Advanced mathematical calculations for algorithm analysis"""
def __init__(self):
super().__init__()
def reset(self):
self.reset_counters()
@profile_algorithm
def factorial(self, n: int) -> Dict:
self.reset()
if n < 0:
return {'algorithm': 'Factorial', 'result': None, 'error': 'Negative input'}
result = 1
for i in range(2, n + 1):
self.iterations += 1
result *= i
return {
'algorithm': 'Factorial',
'n': n,
'result': result,
'time_complexity': 'O(n)',
'space_complexity': 'O(1)',
'iterations': self.iterations,
}
@profile_algorithm
def fibonacci(self, n: int, method: str = "iterative") -> Dict:
self.reset()
if method == "recursive":
def fib(k):
self.recursions += 1
if k <= 1:
return k
return fib(k-1) + fib(k-2)
result = [fib(i) for i in range(n)]
return {
'algorithm': 'Fibonacci (Recursive)',
'sequence': result,
'time_complexity': 'O(2ⁿ)',
'space_complexity': 'O(n)',
'recursions': self.recursions,
}
elif method == "memoization":
memo = {}
def fib(k):
self.recursions += 1
if k in memo:
return memo[k]
if k <= 1:
return k
memo[k] = fib(k-1) + fib(k-2)
return memo[k]
result = [fib(i) for i in range(n)]
return {
'algorithm': 'Fibonacci (Memoization)',
'sequence': result,
'time_complexity': 'O(n)',
'space_complexity': 'O(n)',
'recursions': self.recursions,
}
else:
if n <= 0:
return {'algorithm': 'Fibonacci (Iterative)', 'sequence': [], 'time_complexity': 'O(n)', 'space_complexity': 'O(1)'}
fibs = [0, 1]
for i in range(2, n):
self.iterations += 1
fibs.append(fibs[-1] + fibs[-2])
return {
'algorithm': 'Fibonacci (Iterative)',
'sequence': fibs[:n],
'time_complexity': 'O(n)',
'space_complexity': 'O(1)',
'iterations': self.iterations,
}
@profile_algorithm
def gcd(self, a: int, b: int) -> Dict:
self.reset()
steps = 0
x, y = a, b
while y:
self.iterations += 1
x, y = y, x % y
steps += 1
return {
'algorithm': 'Euclidean GCD',
'gcd': x,
'steps': steps,
'time_complexity': 'O(log min(a,b))',
'space_complexity': 'O(1)',
'iterations': self.iterations,
}
@profile_algorithm
def extended_gcd(self, a: int, b: int) -> Dict:
self.reset()
if b == 0:
return {'algorithm': 'Extended GCD', 'gcd': a, 'x': 1, 'y': 0, 'time_complexity': 'O(log n)', 'space_complexity': 'O(log n)'}
x0, x1, y0, y1 = 1, 0, 0, 1
while b:
self.iterations += 1
q = a // b
a, b = b, a % b
x0, x1 = x1, x0 - q * x1
y0, y1 = y1, y0 - q * y1
return {
'algorithm': 'Extended GCD',
'gcd': a,
'x': x0,
'y': y0,
'time_complexity': 'O(log n)',
'space_complexity': 'O(log n)',
'iterations': self.iterations,
}
@profile_algorithm
def fast_exponentiation(self, base: float, exp: int) -> Dict:
self.reset()
result = 1
b = base
e = exp
while e > 0:
self.iterations += 1
if e % 2 == 1:
result *= b
b *= b
e //= 2
return {
'algorithm': 'Fast Exponentiation',
'result': result,
'time_complexity': 'O(log n)',
'space_complexity': 'O(1)',
'iterations': self.iterations,
}
@profile_algorithm
def is_prime(self, n: int) -> Dict:
self.reset()
if n < 2:
return {'algorithm': 'Primality Test', 'is_prime': False, 'checks': 0, 'time_complexity': 'O(√n)', 'space_complexity': 'O(1)'}
if n == 2:
return {'algorithm': 'Primality Test', 'is_prime': True, 'checks': 1, 'time_complexity': 'O(√n)', 'space_complexity': 'O(1)'}
if n % 2 == 0:
return {'algorithm': 'Primality Test', 'is_prime': False, 'checks': 1, 'time_complexity': 'O(√n)', 'space_complexity': 'O(1)'}
checks = 0
for i in range(3, int(math.sqrt(n)) + 1, 2):
self.iterations += 1
self.comparisons += 1
checks += 1
if n % i == 0:
return {'algorithm': 'Primality Test', 'is_prime': False, 'checks': checks, 'time_complexity': 'O(√n)', 'space_complexity': 'O(1)', 'iterations': self.iterations}
return {'algorithm': 'Primality Test', 'is_prime': True, 'checks': checks, 'time_complexity': 'O(√n)', 'space_complexity': 'O(1)', 'iterations': self.iterations, 'comparisons': self.comparisons}
@profile_algorithm
def sieve_eratosthenes(self, n: int) -> Dict:
self.reset()
if n < 2:
return {'algorithm': 'Sieve of Eratosthenes', 'primes': [], 'count': 0, 'time_complexity': 'O(n log log n)', 'space_complexity': 'O(n)'}
is_prime = [True] * (n + 1)
is_prime[0] = is_prime[1] = False
for i in range(2, int(math.sqrt(n)) + 1):
self.iterations += 1
if is_prime[i]:
for j in range(i*i, n + 1, i):
self.comparisons += 1
is_prime[j] = False
primes = [i for i in range(2, n + 1) if is_prime[i]]
return {
'algorithm': 'Sieve of Eratosthenes',
'primes': primes,
'count': len(primes),
'time_complexity': 'O(n log log n)',
'space_complexity': 'O(n)',
'iterations': self.iterations,
'comparisons': self.comparisons,
}
@profile_algorithm
def matrix_multiply(self, A: List[List[float]], B: List[List[float]]) -> Dict:
self.reset()
n = len(A)
m = len(B[0])
p = len(B)
result = [[0.0] * m for _ in range(n)]
for i in range(n):
for j in range(m):
for k in range(p):
self.iterations += 1
self.accesses += 2
result[i][j] += A[i][k] * B[k][j]
return {
'algorithm': 'Matrix Multiplication (Naive)',
'result': result,
'time_complexity': 'O(n³)',
'space_complexity': 'O(n²)',
'iterations': self.iterations,
'accesses': self.accesses,
}
@profile_algorithm
def modular_exponentiation(self, base: int, exp: int, mod: int) -> Dict:
self.reset()
result = 1
b = base % mod
e = exp
while e > 0:
self.iterations += 1
if e % 2 == 1:
result = (result * b) % mod
b = (b * b) % mod
e //= 2
return {
'algorithm': 'Modular Exponentiation',
'result': result,
'time_complexity': 'O(log exp)',
'space_complexity': 'O(1)',
'iterations': self.iterations,
}
@profile_algorithm
def tower_of_hanoi(self, n: int) -> Dict:
self.reset()
moves = []
def hanoi(disk, source, aux, target):
self.recursions += 1
if disk == 1:
moves.append(f"Move disk 1 from {source} to {target}")
return
hanoi(disk - 1, source, target, aux)
moves.append(f"Move disk {disk} from {source} to {target}")
hanoi(disk - 1, aux, source, target)
hanoi(n, 'A', 'B', 'C')
return {
'algorithm': 'Tower of Hanoi',
'moves': moves,
'total_moves': len(moves),
'time_complexity': 'O(2ⁿ)',
'space_complexity': 'O(n)',
'recursions': self.recursions,
}
@profile_algorithm
def generate_permutations(self, arr: List[Any]) -> Dict:
self.reset()
result = []
def permute(a, l, r):
self.recursions += 1
if l == r:
result.append(a[:])
else:
for i in range(l, r + 1):
self.iterations += 1
a[l], a[i] = a[i], a[l]
permute(a, l + 1, r)
a[l], a[i] = a[i], a[l]
permute(arr[:], 0, len(arr) - 1)
return {
'algorithm': 'Permutations (Backtracking)',
'permutations': result,
'count': len(result),
'time_complexity': 'O(n!)',
'space_complexity': 'O(n)',
'recursions': self.recursions,
'iterations': self.iterations,
}