# linear_algebra_timeit.py
import timeit
def dot_loop(a, b):
result = 0
for i in range(len(a)):
result += a[i] * b[i]
return result
def dot_linalg(a, b):
return sum(x * y for x, y in zip(a, b))
def matrix_mult_loop(A, B):
rows_A, cols_A = len(A), len(A[0])
rows_B, cols_B = len(B), len(B[0])
result = [[0] * cols_B for _ in range(rows_A)]
for i in range(rows_A):
for j in range(cols_B):
for k in range(cols_A):
result[i][j] += A[i][k] * B[k][j]
return result
def matrix_mult_linalg(A, B):
return [[sum(a * b for a, b in zip(row, col)) for col in zip(*B)] for row in A]
def normalize_loop(v):
mag = 0
for x in v:
mag += x * x
mag = mag ** 0.5
result = []
for x in v:
result.append(x / mag)
return result
def normalize_linalg(v):
mag = sum(x * x for x in v) ** 0.5
return [x / mag for x in v]
def add_loop(a, b):
result = []
for i in range(len(a)):
result.append(a[i] + b[i])
return result
def add_linalg(a, b):
return [x + y for x, y in zip(a, b)]
def transpose_loop(M):
rows, cols = len(M), len(M[0])
result = []
for c in range(cols):
row = []
for r in range(rows):
row.append(M[r][c])
result.append(row)
return result
def transpose_linalg(M):
return list(map(list, zip(*M)))
def cross_product_loop(a, b):
return [
a[1] * b[2] - a[2] * b[1],
a[2] * b[0] - a[0] * b[2],
a[0] * b[1] - a[1] * b[0]
]
def cross_product_linalg(a, b):
return [a[1]*b[2]-a[2]*b[1], a[2]*b[0]-a[0]*b[2], a[0]*b[1]-a[1]*b[0]]
def run_benchmarks():
print("=" * 70)
print("LINEAR ALGEBRA VS LOOPS PERFORMANCE")
print("=" * 70)
sizes = [100, 500, 1000]
for n in sizes:
print(f"\n--- SIZE n={n} ---\n")
v1 = list(range(n))
v2 = list(range(n, 2*n))
print(f"DOT PRODUCT (n={n}):")
t1 = timeit.timeit(lambda: dot_loop(v1, v2), number=1000)
t2 = timeit.timeit(lambda: dot_linalg(v1, v2), number=1000)
print(f" Loop: {t1:.6f}s")
print(f" Comprehension: {t2:.6f}s")
print(f" Speedup: {t1/t2:.2f}x\n")
print(f"ELEMENT-WISE ADD (n={n}):")
t1 = timeit.timeit(lambda: add_loop(v1, v2), number=1000)
t2 = timeit.timeit(lambda: add_linalg(v1, v2), number=1000)
print(f" Loop: {t1:.6f}s")
print(f" Comprehension: {t2:.6f}s")
print(f" Speedup: {t1/t2:.2f}x\n")
print(f"NORMALIZE (n={n}):")
t1 = timeit.timeit(lambda: normalize_loop(v1), number=1000)
t2 = timeit.timeit(lambda: normalize_linalg(v1), number=1000)
print(f" Loop: {t1:.6f}s")
print(f" Comprehension: {t2:.6f}s")
print(f" Speedup: {t1/t2:.2f}x\n")
if n <= 100:
m = 50
M1 = [[i+j for j in range(m)] for i in range(m)]
M2 = [[i*j+1 for j in range(m)] for i in range(m)]
print(f"MATRIX MULTIPLY ({m}x{m}):")
t1 = timeit.timeit(lambda: matrix_mult_loop(M1, M2), number=10)
t2 = timeit.timeit(lambda: matrix_mult_linalg(M1, M2), number=10)
print(f" Nested loops: {t1:.6f}s")
print(f" Comprehension: {t2:.6f}s")
print(f" Speedup: {t1/t2:.2f}x\n")
print(f"MATRIX TRANSPOSE ({m}x{m}):")
t1 = timeit.timeit(lambda: transpose_loop(M1), number=1000)
t2 = timeit.timeit(lambda: transpose_linalg(M1), number=1000)
print(f" Loop: {t1:.6f}s")
print(f" zip(*M): {t2:.6f}s")
print(f" Speedup: {t1/t2:.2f}x\n")
if n == 100:
v3 = [1.0, 2.0, 3.0]
v4 = [4.0, 5.0, 6.0]
print(f"CROSS PRODUCT (3D):")
t1 = timeit.timeit(lambda: cross_product_loop(v3, v4), number=10000)
t2 = timeit.timeit(lambda: cross_product_linalg(v3, v4), number=10000)
print(f" Loop: {t1:.6f}s")
print(f" Inline: {t2:.6f}s")
print(f" Speedup: {t1/t2:.2f}x\n")
print("=" * 70)
print("SUMMARY: List comprehensions and built-in functions are faster")
print(" than explicit loops due to optimized C implementations")
print("=" * 70)
run_benchmarks()