Big-O/Ω/Θ mendefinisikan efisiensi algoritma secara formal; recurrence relation dan master theorem menjelaskan kompleksitas rekursif — sementara tahun 2026, linear algebra & calculus menjadi fondasi daily-work dari transformers, attention mechanisms, dan optimasi model di era AI.

Setelah di episode 25 kita mempelajari differential equations dan simulasi numerik — Euler method dan RK4 untuk sistem dinamis — pada episode ini kita menghubungkan kembali semua konsep matematika yang telah dipelajari ke dunia programming: analisis kompleksitas dan tren matematika 2026. Ini adalah episode "big picture" yang menunjukkan bagaimana matematika bukan lagi teori, melainkan daily-work setiap engineer di era AI.
Mengapa analisis kompleksitas penting? Karena mengetahui seberapa cepat algoritma kalian bukan sekadar hal akademis — ia menentukan apakah sistem kalian bisa menangani 1 juta data atau hanya 1000. Dan di tahun 2026, linear algebra dan calculus bukan lagi hanya untuk data scientist — mereka menjadi keterampilan dasar untuk setiap engineer yang bekerja dengan LLM, fine-tuning, dan AI-augmented development.
import math
def f_is_O_of_g(f, g, n_values):
"""Cek apakah f(n) = O(g(n)) menggunakan limit ratio."""
ratios = [f(n) / g(n) for n in n_values if g(n) > 0]
if not ratios:
return True
return max(ratios) < float('inf')
# Contoh: 3n² + 5n + 2 = O(n²)
f = lambda n: 3*n**2 + 5*n + 2
g = lambda n: n**2
n_values = [10, 100, 1000, 10000, 100000]
ratios = [f(n) / g(n) for n in n_values]
print("3n² + 5n + 2 = O(n²)?")
print(f" f(n)/g(n) ratios: {[f'{r:.4f}' for r in ratios]}")
print(f" Ratio converges to: {ratios[-1]:.4f} (should be < ∞)")
print(f" Conclusion: 3n² + 5n + 2 = O(n²) ✓")
# Big-Omega: f(n) = Ω(g(n)) jika f(n) ≥ c×g(n) untuk some c > 0
print(f"\n3n² + 5n + 2 = Ω(n²)?")
print(f" min ratio: {min(ratios):.4f} > 0 → Ω(n²) ✓")
# Big-Theta: f(n) = Θ(g(n)) jika f = O(g) dan f = Ω(g)
print(f" → 3n² + 5n + 2 = Θ(n²) ✓")import time
def constant_time(n):
"""O(1) — akses array."""
return n
def logarithmic_time(n):
"""O(log n) — binary search."""
count = 0
x = n
while x > 1:
x //= 2
count += 1
return count
def linear_time(n):
"""O(n) — single loop."""
return sum(range(n))
def nlogn_time(n):
"""O(n log n) — merge sort."""
if n <= 1:
return 0
return n * logarithmic_time(n)
def quadratic_time(n):
"""O(n²) — nested loop."""
count = 0
for i in range(min(n, 10000)): # limit untuk demo
for j in range(min(n, 10000)):
count += 1
return count
# Bandingkan waktu
for n in [1000, 10000]:
print(f"\nn={n}:")
start = time.perf_counter()
constant_time(n)
print(f" O(1): {time.perf_counter()-start:.6f}s")
start = time.perf_counter()
logarithmic_time(n)
print(f" O(log n): {time.perf_counter()-start:.6f}s")
start = time.perf_counter()
linear_time(n)
print(f" O(n): {time.perf_counter()-start:.6f}s")Banyak algoritma rekursif punya kompleksitas yang didefinisikan oleh recurrence relation:
import math
# Merge sort: T(n) = 2T(n/2) + n, T(1) = 0
# Solution: T(n) = O(n log n)
def merge_sort_steps(n):
"""Hitung jumlah operasi merge sort."""
if n <= 1:
return 0
return 2 * merge_sort_steps(n // 2) + n
# Bandingkan dengan O(n log n) prediction
print("Merge sort — actual vs predicted:")
for n in [8, 16, 32, 64, 128]:
actual = merge_sort_steps(n)
predicted = n * math.log2(n)
ratio = actual / predicted if predicted > 0 else 0
print(f" n={n}: actual={actual}, n×log₂n={predicted:.1f}, ratio={ratio:.2f}")Untuk rekurensi T(n) = aT(n/b) + O(n^d):
import math
def master_theorem(a, b, d):
"""Prediksi Big-O dari Master Theorem."""
log_b_a = math.log(a) / math.log(b)
if d < log_b_a:
return f"O(n^({log_b_a:.2f}))"
elif d == log_b_a:
return f"O(n^({log_b_a:.2f}) × log n)"
else:
return f"O(n^{d})"
# Binary search: T(n) = T(n/2) + O(1)
print(f"Binary search: a=1, b=2, d=0 → {master_theorem(1, 2, 0)}")
# Merge sort: T(n) = 2T(n/2) + O(n)
print(f"Merge sort: a=2, b=2, d=1 → {master_theorem(2, 2, 1)}")
# Strassen: T(n) = 7T(n/2) + O(n²)
print(f"Strassen: a=7, b=2, d=2 → {master_theorem(7, 2, 2)}")Attention mechanism pada dasarnya adalah dot product antara query, key, dan value — operasi matriks:
import numpy as np
def scaled_dot_product_attention(Q, K, V):
"""Attention(Q,K,V) = softmax(QK^T / √d_k) × V"""
d_k = Q.shape[1]
scores = Q @ K.T / np.sqrt(d_k)
attention_weights = np.exp(scores) / np.exp(scores).sum(axis=-1, keepdims=True)
return attention_weights @ V
# Q, K, V: (seq_len × d_model)
np.random.seed(42)
seq_len, d_model = 4, 8
Q = np.random.randn(seq_len, d_model)
K = np.random.randn(seq_len, d_model)
V = np.random.randn(seq_len, d_model)
output = scaled_dot_product_attention(Q, K, V)
print(f"Attention output shape: {output.shape}")
print(f"Attention weights sum per row (should be 1):")
scores = Q @ K.T / np.sqrt(d_model)
weights = np.exp(scores) / np.exp(scores).sum(axis=-1, keepdims=True)
print(f" {weights.sum(axis=-1)}")import numpy as np
def positional_encoding(max_len, d_model):
"""Sinusoidal positional encoding — angle dari posisi."""
PE = np.zeros((max_len, d_model))
position = np.arange(max_len).reshape(-1, 1)
div_term = np.exp(np.arange(0, d_model, 2) * -(np.log(10000) / d_model))
PE[:, 0::2] = np.sin(position * div_term)
PE[:, 1::2] = np.cos(position * div_term)
return PE
pe = positional_encoding(10, 16)
print(f"Positional encoding shape: {pe.shape}")
print(f"Position 0 (first 8 dims): {pe[0, :8].round(3)}")
print(f"Position 1 (first 8 dims): {pe[1, :8].round(3)}")
print(f"Orthogonality: pos0·pos1 = {np.dot(pe[0], pe[1]):.4f} (should be ≈0)")import numpy as np
def sgd_step(grad, params, lr):
"""Stochastic Gradient Descent update."""
return params - lr * grad
def momentum_step(grad, params, velocity, lr, beta=0.9):
"""SGD with momentum."""
velocity = beta * velocity + grad
return params - lr * velocity, velocity
def adam_step(grad, params, m, v, t, lr=0.001, beta1=0.9, beta2=0.999):
"""Adam optimizer."""
m = beta1 * m + (1 - beta1) * grad
v = beta2 * v + (1 - beta2) * grad**2
m_hat = m / (1 - beta1**t)
v_hat = v / (1 - beta2**t)
params = params - lr * m_hat / (np.sqrt(v_hat) + 1e-8)
return params, m, v
# Demo: minimize f(x) = x²
np.random.seed(42)
x = 10.0
m, v = 0.0, 0.0
print("Adam optimizer: minimize f(x) = x²")
for t in range(1, 11):
grad = 2 * x
x, m, v = adam_step(grad, x, m, v, t)
print(f" Step {t}: x = {x:.6f}, f(x) = {x**2:.6f}")Tip
Di tahun 2026, setiap engineer yang bekerja dengan AI perlu memahami: linear algebra (attention, embeddings), calculus (backpropagation, gradients), dan probability (loss functions, uncertainty). Matematika bukan lagi "nice to have" — ia adalah daily-work skill.
Inti yang harus dibawa pulang:
Di episode 27 selanjutnya (episode terakhir!) kita akan membahas roadmap belajar lanjutan dan refleksi akhir — rekap semua episode, checklist pemahaman, dan langkah selanjutnya ke series lanjutan. Selamat, kalian sudah menyelesaikan perjalanan Belajar Math dari nol hingga applied reasoning!