Tiga pekerjaan muncul begitu komputasi matriks mulai bertumbuh: mengalikan banyak matriks sekaligus, memangkatkan satu matriks berkali-kali, dan menghitung determinan yang nilainya melampaui jangkauan float64. NumPy menyediakan satu fungsi khusus untuk masing-masing: np.linalg.multi_dot, np.linalg.matrix_power, dan np.linalg.slogdet.
Perkalian matriks bersifat asosiatif — (A @ B) @ C menghasilkan nilai yang sama dengan A @ (B @ C). Tetapi kesetaraan nilai tidak berarti kesetaraan biaya: urutan pengerjaan mengubah jumlah operasi skalar secara besar. Pada rantai transformasi bertahap atau perkalian matriks transisi berulang, memilih urutan yang salah membuat komputasi menjadi jauh lebih lambat.
Urutan Optimal dengan multi_dot #
np.linalg.multi_dot([A, B, C, D]) menerima daftar matriks dan mengalikannya dalam urutan yang dihitung paling murah — fungsi ini menilai terlebih dahulu susunan tanda kurung mana yang paling hemat operasi, alih-alih mengerjakan kiri-ke-kanan secara paksa:
import numpy as np
rng = np.random.default_rng(42)
A = rng.random((2, 50))
B = rng.random((50, 2))
C = rng.random((2, 50))
D = rng.random((50, 2))
print("bentuk:", A.shape, B.shape, C.shape, D.shape)
R = np.linalg.multi_dot([A, B, C, D])
print("hasil multi_dot :", R.shape)
print("sama dgn A@B@C@D:", np.allclose(R, A @ B @ C @ D))
print("sama dgn np.dot berantai:", np.allclose(R, np.dot(np.dot(np.dot(A, B), C), D)))Output yang Dihasilkan:
bentuk: (2, 50) (50, 2) (2, 50) (50, 2)
hasil multi_dot : (2, 2)
sama dgn A@B@C@D: True
sama dgn np.dot berantai: TrueBedah baris demi baris:
- Baris 3-6 (
rngdan empat matriks): empat matriks kecil berukuran berselang-seling lebar-sempit, dibuat dari generator ber-seed sehingga output pasti sama. - Baris 8 (
R = ...):multi_dotmengembalikan array(2, 2)— bentuk akhir yang sama seperti perkalian berantai biasa. - Baris 9-10 (
allclose): nilainya setara denganA @ B @ C @ Dmaupunnp.dotberantai dari bab Dot Product; yang berbeda hanya urutan pengerjaan di dalam fungsi.
Biaya tiap urutan (dihitung sebagai jumlah perkalian skalar) untuk bentuk di atas:
| Urutan pengerjaan | Rincian biaya | Total |
|---|---|---|
Kiri-ke-kanan: ((A@B)@C)@D | 200 + 200 + 200 | 600 |
(A@B)@(C@D) | 200 + 200 + 8 | 408 |
A@(B@C)@D | 5000 + 5000 + 200 | 10200 |
multi_dot memilih susunan termurah, 408: mengalikan (A @ B) dan (C @ D) lebih dulu agar hasil antara tetap kecil, lalu menggabungkannya. Penghematan terlihat kecil pada contoh 2x50 ini, tetapi skala dengan cepat pada matriks besar — dan multi_dot menghitung semuanya tanpa kita menyusun tanda kurung manual di atas operasi dasar bab Matrix Multiplication.
matrix_power: Menaikkan Matriks ke Pangkat #
np.linalg.matrix_power(A, n) menghasilkan A dikalikan dengan dirinya sendiri sebanyak n kali, dan menghitungnya lewat perkalian berulang yang hemat (pangkat dua berantai), bukan n kali perkalian sunyi:
import numpy as np
A = np.array([[1.0, 1.0],
[0.0, 1.0]])
print("pangkat 0:")
print(np.linalg.matrix_power(A, 0))
print("pangkat 3:")
print(np.linalg.matrix_power(A, 3))
print("pangkat -1:")
print(np.linalg.matrix_power(A, -1))Output yang Dihasilkan:
pangkat 0:
[[1. 0.]
[0. 1.]]
pangkat 3:
[[1. 3.]
[0. 1.]]
pangkat -1:
[[ 1. -1.]
[ 0. 1.]]- Baris 3-4 (
A): matriks segitiga atas sederhana yang mudah diperiksa dengan hitungan manual. - Baris 5-6 (
pangkat 0): A^0 didefinisikan sebagai matriks identitas I — konsisten dengan konvensi pangkat bilangan. - Baris 7-8 (
pangkat 3): hasilnya[[1, 3], [0, 1]], cocok dengan perkalian manualA @ A @ A: entri kanan atas bertambah satu setiap pangkat. - Baris 9-10 (
pangkat -1): pangkat negatif berarti inverse dipangkatkan;matrix_power(A, -1)setara dengannp.linalg.inv(A)dari bab Inverse Matriks, dan pangkat -2 setara denganinv(A) @ inv(A). Matriks singular akan memunculkanLinAlgErroruntuk pangkat negatif.
Matriks Transisi: Rute Dua Langkah #
Kasus nyata yang paling alami untuk pangkat matriks adalah graf. Bayangkan jaringan kurir dengan tiga kota — Jakarta, Bandung, Semarang — yang terhubung jalur langsung dua arah. Matriks ketetanggaan T berisi 1 bila ada jalur langsung antar dua kota, dan pangkat matriksnya menghitung banyaknya rute dua langkah:
import numpy as np
T = np.array([[0, 1, 1],
[1, 0, 1],
[1, 1, 0]])
T2 = np.linalg.matrix_power(T, 2)
print(T2)
print("jakarta -> jakarta (2 leg):", T2[0, 0])
print("jakarta -> bandung (2 leg):", T2[0, 1])Output yang Dihasilkan:
[[2 1 1]
[1 2 1]
[1 1 2]]
jakarta -> jakarta (2 leg): 2
jakarta -> bandung (2 leg): 1- Baris 7 (
T2 = ...): entri(i, j)dariT @ Tmenghitung banyak kota perantara yang menghubungkan i ke j;matrix_powermerapikan penulisannya. - Baris 9 (
T2[0, 0]): rute dua leg Jakarta ke Jakarta ada 2 — pulang lewat Bandung atau lewat Semarang. - Baris 10 (
T2[0, 1]): Jakarta ke Bandung dalam dua leg hanya lewat Semarang, sehingga bernilai 1.
Pola yang sama berlaku untuk matriks transisi probabilitas (random walk, peringkat halaman web): pangkat ke-n memproyeksikan sistem n langkah ke depan.
slogdet: Log-Determinan Aman Overflow #
Determinan matriks diagonal adalah perkalian entri diagonalnya (bab Determinant). Untuk matriks 400x400 dengan entri diagonal 1000, determinannya adalah 1000^400 = 10^1200 — jauh di atas batas float64 sekitar 1.8e308. Fungsi np.linalg.slogdet menghindari masalah ini dengan mengembalikan tanda dan logaritma determinan:
import numpy as np
A = np.diag([1000.0] * 400)
try:
with np.errstate(over="raise"):
d = np.linalg.det(A)
print("det :", d)
except FloatingPointError as e:
print("det -> FloatingPointError:", e)
sign, logabsdet = np.linalg.slogdet(A)
print("sign :", sign)
print("logabs :", logabsdet)
with np.errstate(over="ignore"):
print("det ulang (exp) :", sign * np.exp(logabsdet))Output yang Dihasilkan:
det -> FloatingPointError: overflow encountered in det
sign : 1.0
logabs : 2763.102111592873
det ulang (exp) : inf- Baris 3 (
A): matriks diagonal 400x400, seluruh entri diagonal 1000 — contoh determinan besar yang sepenuhnya deterministik. - Baris 5-10 (
detdalamerrstate):np.errstate(over="raise")mengubah pelaporan luapan menjadi exception, sehinggadetmelemparFloatingPointErroryang kita tangkap dan cetak. Tanpaerrstate, fungsi mengembalikaninfdisertaiRuntimeWarning. - Baris 11-13 (
slogdet): hasilnya pasangan(sign, logabsdet)— tanda determinan (1.0, positif) dan logaritma natural nilai mutlaknya, sekitar 2763.102. Angka sekecil ini aman tersimpan difloat64. - Baris 14-15 (
exp): mengembalikan nilai asli lewatsign * exp(logabsdet)menghasilkaninflagi. Ini bukan kegagalanslogdet, melainkan bukti bahwa determinan aslinya memang di luar jangkauanfloat64.
Nilai 10^1200 di atas adalah kasus ekstrem yang sengaja dibuat; kasus riil — matriks kovarians berdimensi besar, produk likelihood bertumpuk — meluap jauh lebih cepat dari yang kita duga, dan slogdet adalah jawaban standarnya.